26 |
26 |
27 #include <QGraphicsWidget> |
27 #include <QGraphicsWidget> |
28 #include <QGraphicsSceneMouseEvent> |
28 #include <QGraphicsSceneMouseEvent> |
29 #include <QStyleOptionGraphicsItem> |
29 #include <QStyleOptionGraphicsItem> |
30 #include <QInputContext> |
30 #include <QInputContext> |
|
31 #include <QPointer> |
31 |
32 |
32 #include "hbinputregioncollector_p.h" |
33 #include "hbinputregioncollector_p.h" |
33 #include "hbinstance.h" |
34 #include "hbinstance.h" |
34 #include "hbwidget.h" |
35 #include "hbwidget.h" |
35 #include "hbview.h" |
36 #include "hbview.h" |
36 #include "hbnamespace_p.h" |
|
37 #include "hbstackedlayout.h" |
37 #include "hbstackedlayout.h" |
|
38 #include "hbpopup.h" |
38 |
39 |
39 #if defined (Q_OS_SYMBIAN) |
40 #if defined (Q_OS_SYMBIAN) |
40 #include <coemain.h> |
41 #include <coemain.h> |
41 #include <coecntrl.h> |
42 #include <coecntrl.h> |
42 #include <e32cmn.h> |
43 #include <e32cmn.h> |
50 } |
51 } |
51 |
52 |
52 Q_DECLARE_TYPEINFO(TRect, Q_MOVABLE_TYPE); |
53 Q_DECLARE_TYPEINFO(TRect, Q_MOVABLE_TYPE); |
53 #endif |
54 #endif |
54 |
55 |
|
56 |
|
57 class HbProxyWindow: public QWidget |
|
58 { |
|
59 public: |
|
60 HbProxyWindow() |
|
61 { |
|
62 setGeometry(0,0,0,0); |
|
63 } |
|
64 void setWindow(QWidget* window) |
|
65 { |
|
66 this->window = window; |
|
67 if (window) { |
|
68 window->setParent(this); |
|
69 } |
|
70 } |
|
71 ~HbProxyWindow() |
|
72 { |
|
73 if (window) { |
|
74 window->setParent(0); |
|
75 } |
|
76 } |
|
77 private: |
|
78 QPointer<QWidget> window; |
|
79 }; |
|
80 |
|
81 |
55 class HbInputTransparentWindow : public HbWidget |
82 class HbInputTransparentWindow : public HbWidget |
56 { |
83 { |
57 public: |
84 public: |
58 |
85 |
59 HbInputTransparentWindow(QGraphicsItem *parent = 0); |
86 HbInputTransparentWindow(QGraphicsItem *parent = 0); |
88 painter->setCompositionMode(QPainter::CompositionMode_Source); |
115 painter->setCompositionMode(QPainter::CompositionMode_Source); |
89 painter->fillRect(option->exposedRect, QColor(0, 0, 0, 0)); |
116 painter->fillRect(option->exposedRect, QColor(0, 0, 0, 0)); |
90 painter->setCompositionMode(compositionMode); |
117 painter->setCompositionMode(compositionMode); |
91 } |
118 } |
92 |
119 |
|
120 class HbInputMainWindowPrivate |
|
121 { |
|
122 public: |
|
123 HbInputMainWindowPrivate(HbInputMainWindow *owner) |
|
124 :q_ptr(owner), mLastFocusedWidget(0), mSpellQueryLaunched(false), mProxyWindow(0), mIsInputWindowFocusLocked(false) |
|
125 { |
|
126 } |
|
127 ~HbInputMainWindowPrivate(); |
|
128 void dismissNonModalDialogs(); |
|
129 HbInputMainWindow *q_ptr; |
|
130 QPointer<QWidget> mLastFocusedWidget; |
|
131 QRegion mMask; |
|
132 bool mSpellQueryLaunched; |
|
133 QPointer<HbProxyWindow > mProxyWindow; |
|
134 bool mIsInputWindowFocusLocked; |
|
135 }; |
|
136 |
|
137 /* |
|
138 Dismisses all non-modal dialogs with tap-outside dismiss policy which are attached to the region collector. |
|
139 */ |
|
140 void HbInputMainWindowPrivate::dismissNonModalDialogs() |
|
141 { |
|
142 HbInputRegionCollectorPrivate *const regionColPrivate = HbInputRegionCollector::instance()->d_ptr; |
|
143 if (regionColPrivate->mEnabled && !regionColPrivate->mModalDialogs) { |
|
144 QList<HbWidgetFilterList> list = regionColPrivate->mInputWidgets; |
|
145 for (int i = 0; i < list.size(); ++i) { |
|
146 if (list.at(i).mIsVisible) { |
|
147 HbPopup *popup = qobject_cast<HbPopup *>(list.at(i).mWidget); |
|
148 // dismiss non-modal dialogs, which have tap-outside dismiss policy. |
|
149 if (popup && (popup->dismissPolicy() & HbPopup::TapOutside) && !popup->isModal()) { |
|
150 popup->close(); |
|
151 } |
|
152 } |
|
153 } |
|
154 } |
|
155 } |
|
156 |
|
157 HbInputMainWindowPrivate::~HbInputMainWindowPrivate() |
|
158 { |
|
159 delete mProxyWindow; |
|
160 } |
|
161 |
93 /* |
162 /* |
94 creates an instance of HbInputMainWindow. |
163 creates an instance of HbInputMainWindow. |
95 */ |
164 */ |
96 HbInputMainWindow *HbInputMainWindow::instance() |
165 HbInputMainWindow *HbInputMainWindow::instance() |
97 { |
166 { |
99 return mainWindow; |
168 return mainWindow; |
100 } |
169 } |
101 |
170 |
102 HbInputMainWindow::~HbInputMainWindow() |
171 HbInputMainWindow::~HbInputMainWindow() |
103 { |
172 { |
104 delete mProxyWindow; |
173 delete d_ptr; |
105 } |
174 } |
106 |
175 |
107 // constructor. |
176 // constructor. |
108 HbInputMainWindow::HbInputMainWindow() |
177 HbInputMainWindow::HbInputMainWindow() |
109 // HbMainWindow creates a background QGraphicsItem, which has the background image. we need to hide it that. |
178 // HbMainWindow creates a background QGraphicsItem, which has the background image. we need to hide it that. |
110 : HbMainWindow(0, Hb::WindowFlagTransparent), mLastFocusedWidget(0), mSpellQueryLaunched(false), mProxyWindow(0) |
179 : HbMainWindow(0, Hb::WindowFlagTransparent), d_ptr(new HbInputMainWindowPrivate(this)) |
111 { |
180 { |
112 // We need a window which is of type Qt::Window flag at the same time does not show |
181 // We need a window which is of type Qt::Window flag at the same time does not show |
113 // any decorators Qt::Tool seems to be the option, and we want this window to be always on top so Qt::WindowStaysOnTopHint. |
182 // any decorators Qt::Tool seems to be the option, and we want this window to be always on top so Qt::WindowStaysOnTopHint. |
114 // And since transparency requires to have a frameless window we are setting that too. |
183 // And since transparency requires to have a frameless window we are setting that too. |
115 setWindowFlags(Qt::WindowStaysOnTopHint | Qt::Tool | Qt::FramelessWindowHint); |
184 setWindowFlags(Qt::WindowStaysOnTopHint | Qt::Tool | Qt::FramelessWindowHint); |
155 } |
224 } |
156 |
225 |
157 |
226 |
158 void HbInputMainWindow::updateRegion(QRegion region) |
227 void HbInputMainWindow::updateRegion(QRegion region) |
159 { |
228 { |
160 mMask = region; |
229 d_ptr->mMask = region; |
161 #if defined (Q_OS_SYMBIAN) |
230 #if defined (Q_OS_SYMBIAN) |
162 RWindowBase *rwindow = effectiveWinId()->DrawableWindow(); |
231 RWindowBase *rwindow = effectiveWinId()->DrawableWindow(); |
163 if (region.isEmpty()) { |
232 if (region.isEmpty()) { |
164 TRegionFix<1> tregion(TRect(TPoint(0, 0), TSize(0, 0))); |
233 TRegionFix<1> tregion(TRect(TPoint(0, 0), TSize(0, 0))); |
165 rwindow->SetShape(tregion); |
234 rwindow->SetShape(tregion); |
166 } else { |
235 } else { |
167 // Using QVector assumes the memory layout is the same as RRegion |
236 // Using QVector assumes the memory layout is the same as RRegion |
168 QVector<QRect> rects = region.rects(); |
237 QVector<QRect> rects = region.rects(); |
169 QVector<TRect> trects(rects.count()); |
238 QVector<TRect> trects(rects.count()); |
|
239 RRegion rregion; |
170 for (int i = 0; i < trects.count(); ++i) { |
240 for (int i = 0; i < trects.count(); ++i) { |
171 trects[i] = qt_QRect2TRect(rects.at(i)); |
241 rregion.AddRect(qt_QRect2TRect(rects.at(i))); |
172 } |
242 } |
173 RRegion rregion(trects.count(), trects.data()); |
243 if (!rregion.CheckError()) |
174 if (!rregion.CheckError()) { |
244 rwindow->SetShape(rregion); |
175 rwindow->SetShape(rregion); |
245 } |
176 } |
|
177 } |
|
178 #else |
246 #else |
179 setMask(region); |
247 setMask(region); |
180 #endif |
248 #endif |
181 } |
249 } |
182 |
250 |
203 and blocks the events to the application window by launching a widget which sits exactly in between the applicaion |
271 and blocks the events to the application window by launching a widget which sits exactly in between the applicaion |
204 and HbInputMainWindow. |
272 and HbInputMainWindow. |
205 */ |
273 */ |
206 bool HbInputMainWindow::eventFilter(QObject *obj, QEvent *event) |
274 bool HbInputMainWindow::eventFilter(QObject *obj, QEvent *event) |
207 { |
275 { |
208 if (event->type() == QEvent::DynamicPropertyChange) { |
|
209 const QString p = static_cast<QDynamicPropertyChangeEvent *>(event)->propertyName(); |
|
210 if (p == "SpellQueryLaunched") { |
|
211 QVariant variant = obj->property("SpellQueryLaunched"); |
|
212 if (variant.isValid()) { |
|
213 mSpellQueryLaunched = variant.toBool(); |
|
214 if (mSpellQueryLaunched) { |
|
215 qApp->setActiveWindow(this); |
|
216 setFocus(Qt::OtherFocusReason); |
|
217 } else { |
|
218 if (mLastFocusedWidget) { |
|
219 qApp->setActiveWindow(mLastFocusedWidget); |
|
220 } |
|
221 } |
|
222 } |
|
223 // return true as we are interested party! |
|
224 return true; |
|
225 } |
|
226 } |
|
227 |
|
228 // we need to only check for spontaneous events. |
276 // we need to only check for spontaneous events. |
229 if (event->spontaneous() && (event->type() == QEvent::MouseButtonPress || event->type() == QEvent::MouseButtonRelease)) { |
277 if (event->spontaneous() && (event->type() == QEvent::MouseButtonPress)) { |
230 QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event); |
278 QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event); |
231 if (mouseEvent) { |
279 if (mouseEvent) { |
232 // get the top level widget at the point, and see if that widget is a HbMainWindow, |
280 // when we have only non-modal dialogs launched inside HbInputMainWindow, for instance exactword popup. |
233 // If it is a HbMainWindow then do not do any thing, as events will propagate |
281 // in that case HbInputMainWindow's window region is such that it only has exactword popup and the |
234 // correctly. But when it is clicked inside application window then send the event to |
282 // vkb. And clicking anywhere other than vkb and exactword popup will not be know to HbInputMainWindow. |
235 // viewport as we might want to close a popup. |
283 // With the help of this eventfilter we will come to know if there are any click events outside |
236 if (!mMask.contains(mouseEvent->globalPos())) { |
284 // of HbInputMainWindow's region and we should close all the non-modal with tapoutside dismiss policy. |
237 qApp->sendEvent(viewport(), event); |
285 if (!d_ptr->mMask.contains(mouseEvent->globalPos())) { |
|
286 d_ptr->dismissNonModalDialogs(); |
238 } |
287 } |
|
288 } |
|
289 } else if(event->spontaneous() && event->type() == QEvent::WindowActivate) { |
|
290 if(d_ptr->mIsInputWindowFocusLocked && (qApp->activeWindow()!= this)) { |
|
291 qApp->setActiveWindow(this); |
239 } |
292 } |
240 } |
293 } |
241 |
294 |
242 return HbMainWindow::eventFilter(obj, event); |
295 return HbMainWindow::eventFilter(obj, event); |
243 } |
296 } |
273 } |
326 } |
274 #endif |
327 #endif |
275 |
328 |
276 HbInputRegionCollector::instance()->setEnabled(true); |
329 HbInputRegionCollector::instance()->setEnabled(true); |
277 if (win && win->windowModality() != Qt::NonModal) { |
330 if (win && win->windowModality() != Qt::NonModal) { |
278 if (!mProxyWindow) { |
331 if (!d_ptr->mProxyWindow) { |
279 mProxyWindow = new HbProxyWindow(); |
332 d_ptr->mProxyWindow = new HbProxyWindow(); |
280 } |
333 } |
281 mProxyWindow->setWindow(this); |
334 d_ptr->mProxyWindow->setWindow(this); |
282 // since the focused widget is inside a modal dialog which blocks events to other_window. |
335 // since the focused widget is inside a modal dialog which blocks events to other_window. |
283 // and since hbinputmainwindow also comes under the other_window. It does will not get the |
336 // and since hbinputmainwindow also comes under the other_window. It does will not get the |
284 // mouse click events. |
337 // mouse click events. |
285 mProxyWindow->setParent(win); |
338 d_ptr->mProxyWindow->setParent(win); |
286 // setParent resets the window flags, so we have to set the flags once again before show() is called. |
339 // setParent resets the window flags, so we have to set the flags once again before show() is called. |
287 setWindowFlags(Qt::WindowStaysOnTopHint | Qt::Tool | Qt::FramelessWindowHint); |
340 setWindowFlags(Qt::WindowStaysOnTopHint | Qt::Tool | Qt::FramelessWindowHint); |
288 show(); |
341 show(); |
289 } else { |
342 } else { |
290 if (mProxyWindow && mProxyWindow->isAncestorOf(this)) { |
343 if (d_ptr->mProxyWindow && d_ptr->mProxyWindow->isAncestorOf(this)) { |
291 mProxyWindow->setWindow(0); |
344 d_ptr->mProxyWindow->setParent(0); |
|
345 d_ptr->mProxyWindow->setWindow(0); |
292 setParent(0); |
346 setParent(0); |
293 // setParent resets the window flags, so we have to set the flags once again before show is called. |
347 // setParent resets the window flags, so we have to set the flags once again before show is called. |
294 setWindowFlags(Qt::WindowStaysOnTopHint | Qt::Tool | Qt::FramelessWindowHint); |
348 setWindowFlags(Qt::WindowStaysOnTopHint | Qt::Tool | Qt::FramelessWindowHint); |
295 } |
349 } |
296 show(); |
350 show(); |
324 // installing event filter to the application.. this is needed to get |
378 // installing event filter to the application.. this is needed to get |
325 // the events happening in other vanilla windows. |
379 // the events happening in other vanilla windows. |
326 qApp->removeEventFilter(this); |
380 qApp->removeEventFilter(this); |
327 } |
381 } |
328 |
382 |
|
383 void HbInputMainWindow::lockFocus() |
|
384 { |
|
385 // lock only when HbinputMainWindow is active. |
|
386 if (!isVisible()) |
|
387 return; |
|
388 |
|
389 d_ptr->mIsInputWindowFocusLocked = true; |
|
390 setFocus(Qt::OtherFocusReason); |
|
391 qApp->setActiveWindow(this); |
|
392 #if defined(Q_OS_SYMBIAN) |
|
393 // this is done to come on top of all the controls in symbian OS, done to overlap soft keys as well. |
|
394 RWindow *rWindow = static_cast<RWindow *>(effectiveWinId()->DrawableWindow()); |
|
395 const int positionForeground(0); |
|
396 // Now window ordinal position works with latest symbian release. So giving back this window |
|
397 // a FEP priority. This will enable this window to come on top of any softkeys. |
|
398 rWindow->SetOrdinalPosition(positionForeground); |
|
399 #endif |
|
400 } |
|
401 |
|
402 void HbInputMainWindow::unlockFocus() |
|
403 { |
|
404 if (!isVisible()) |
|
405 return; |
|
406 |
|
407 d_ptr->mIsInputWindowFocusLocked = false; |
|
408 if (d_ptr->mLastFocusedWidget) { |
|
409 qApp->setActiveWindow(d_ptr->mLastFocusedWidget); |
|
410 } |
|
411 } |
|
412 |
329 //EOF |
413 //EOF |