source: trunk/src/gui/kernel/qwidget_s60.cpp@ 798

Last change on this file since 798 was 769, checked in by Dmitry A. Kuminov, 15 years ago

trunk: Merged in qt 4.6.3 sources from branches/vendor/nokia/qt.

  • Property svn:eol-style set to native
File size: 45.5 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation ([email protected])
6**
7** This file is part of the QtGui module of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
15**
16** GNU Lesser General Public License Usage
17** Alternatively, this file may be used under the terms of the GNU Lesser
18** General Public License version 2.1 as published by the Free Software
19** Foundation and appearing in the file LICENSE.LGPL included in the
20** packaging of this file. Please review the following information to
21** ensure the GNU Lesser General Public License version 2.1 requirements
22** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23**
24** In addition, as a special exception, Nokia gives you certain additional
25** rights. These rights are described in the Nokia Qt LGPL Exception
26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you have questions regarding the use of this file, please contact
37** Nokia at [email protected].
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "qwidget_p.h"
43#include "qdesktopwidget.h"
44#include "qapplication.h"
45#include "qapplication_p.h"
46#include "private/qbackingstore_p.h"
47#include "qevent.h"
48#include "qt_s60_p.h"
49
50#include "qbitmap.h"
51#include "private/qwindowsurface_s60_p.h"
52
53#include <qinputcontext.h>
54
55#ifdef Q_WS_S60
56#include <aknappui.h>
57#endif
58
59// This is necessary in order to be able to perform delayed invokation on slots
60// which take arguments of type WId. One example is
61// QWidgetPrivate::_q_delayedDestroy, which is used to delay destruction of
62// CCoeControl objects until after the CONE event handler has finished running.
63Q_DECLARE_METATYPE(WId)
64
65QT_BEGIN_NAMESPACE
66
67extern bool qt_nograb();
68
69QWidget *QWidgetPrivate::mouseGrabber = 0;
70QWidget *QWidgetPrivate::keyboardGrabber = 0;
71
72static bool isEqual(const QList<QAction*>& a, const QList<QAction*>& b)
73{
74 if ( a.count() != b.count())
75 return false;
76 int index=0;
77 while (index<a.count()) {
78 if (a.at(index)->softKeyRole() != b.at(index)->softKeyRole())
79 return false;
80 if (a.at(index)->text().compare(b.at(index)->text())!=0)
81 return false;
82 index++;
83 }
84 return true;
85}
86
87void QWidgetPrivate::setWSGeometry(bool dontShow, const QRect &)
88{
89 // Note: based on x11 implementation
90
91 static const int XCOORD_MAX = 16383;
92 static const int WRECT_MAX = 16383;
93
94 Q_Q(QWidget);
95
96 Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
97
98 /*
99 There are up to four different coordinate systems here:
100 Qt coordinate system for this widget.
101 Symbian coordinate system for this widget (relative to wrect).
102 Qt coordinate system for parent
103 Symbian coordinate system for parent (relative to parent's wrect).
104 */
105
106 QRect validRange(-XCOORD_MAX,-XCOORD_MAX, 2*XCOORD_MAX, 2*XCOORD_MAX);
107 QRect wrectRange(-WRECT_MAX,-WRECT_MAX, 2*WRECT_MAX, 2*WRECT_MAX);
108 QRect wrect;
109 //xrect is the Symbian geometry of my widget. (starts out in parent's Qt coord sys, and ends up in parent's Symbian coord sys)
110 QRect xrect = data.crect;
111
112 const QWidget *const parent = q->parentWidget();
113 QRect parentWRect = parent->data->wrect;
114
115 if (parentWRect.isValid()) {
116 // parent is clipped, and we have to clip to the same limit as parent
117 if (!parentWRect.contains(xrect)) {
118 xrect &= parentWRect;
119 wrect = xrect;
120 //translate from parent's to my Qt coord sys
121 wrect.translate(-data.crect.topLeft());
122 }
123 //translate from parent's Qt coords to parent's X coords
124 xrect.translate(-parentWRect.topLeft());
125
126 } else {
127 // parent is not clipped, we may or may not have to clip
128
129 if (data.wrect.isValid() && QRect(QPoint(),data.crect.size()).contains(data.wrect)) {
130 // This is where the main optimization is: we are already
131 // clipped, and if our clip is still valid, we can just
132 // move our window, and do not need to move or clip
133 // children
134
135 QRect vrect = xrect & parent->rect();
136 vrect.translate(-data.crect.topLeft()); //the part of me that's visible through parent, in my Qt coords
137 if (data.wrect.contains(vrect)) {
138 xrect = data.wrect;
139 xrect.translate(data.crect.topLeft());
140 if (data.winid)
141 data.winid->SetExtent(TPoint(xrect.x(), xrect.y()), TSize(xrect.width(), xrect.height()));
142 return;
143 }
144 }
145
146 if (!validRange.contains(xrect)) {
147 // we are too big, and must clip
148 xrect &=wrectRange;
149 wrect = xrect;
150 wrect.translate(-data.crect.topLeft());
151 //parent's X coord system is equal to parent's Qt coord
152 //sys, so we don't need to map xrect.
153 }
154 }
155
156 // unmap if we are outside the valid window system coord system
157 bool outsideRange = !xrect.isValid();
158 bool mapWindow = false;
159 if (q->testAttribute(Qt::WA_OutsideWSRange) != outsideRange) {
160 q->setAttribute(Qt::WA_OutsideWSRange, outsideRange);
161 if (outsideRange) {
162 if (data.winid)
163 data.winid->DrawableWindow()->SetVisible(EFalse);
164 q->setAttribute(Qt::WA_Mapped, false);
165 } else if (!q->isHidden()) {
166 mapWindow = true;
167 }
168 }
169
170 if (outsideRange)
171 return;
172
173 bool jump = (data.wrect != wrect);
174 data.wrect = wrect;
175
176 // and now recursively for all children...
177 for (int i = 0; i < children.size(); ++i) {
178 QObject *object = children.at(i);
179 if (object->isWidgetType()) {
180 QWidget *w = static_cast<QWidget *>(object);
181 if (!w->isWindow() && w->testAttribute(Qt::WA_WState_Created))
182 w->d_func()->setWSGeometry(jump);
183 }
184 }
185
186 if (data.winid) {
187 // move ourselves to the new position and map (if necessary) after
188 // the movement. Rationale: moving unmapped windows is much faster
189 // than moving mapped windows
190 if (!parent->internalWinId())
191 xrect.translate(parent->mapTo(q->nativeParentWidget(), QPoint(0, 0)));
192
193 data.winid->SetExtent(TPoint(xrect.x(), xrect.y()), TSize(xrect.width(), xrect.height()));
194 }
195
196 if (mapWindow and !dontShow) {
197 q->setAttribute(Qt::WA_Mapped);
198 if (q->internalWinId())
199 q->internalWinId()->DrawableWindow()->SetVisible(ETrue);
200 }
201
202 if (jump && data.winid) {
203 RWindow *const window = static_cast<RWindow *>(data.winid->DrawableWindow());
204 window->Invalidate(TRect(0, 0, wrect.width(), wrect.height()));
205 }
206}
207
208void QWidgetPrivate::setGeometry_sys(int x, int y, int w, int h, bool isMove)
209{
210 Q_Q(QWidget);
211
212 Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
213
214 if ((q->windowType() == Qt::Desktop))
215 return;
216
217 QPoint oldPos(q->pos());
218 QSize oldSize(q->size());
219 QRect oldGeom(data.crect);
220
221 // Lose maximized status if deliberate resize
222 if (w != oldSize.width() || h != oldSize.height())
223 data.window_state &= ~Qt::WindowMaximized;
224
225 if (extra) { // any size restrictions?
226 w = qMin(w,extra->maxw);
227 h = qMin(h,extra->maxh);
228 w = qMax(w,extra->minw);
229 h = qMax(h,extra->minh);
230 }
231
232 if (q->isWindow())
233 topData()->normalGeometry = QRect(0, 0, -1, -1);
234 else {
235 uint s = data.window_state;
236 s &= ~(Qt::WindowMaximized | Qt::WindowFullScreen);
237 data.window_state = s;
238 }
239
240 bool isResize = w != oldSize.width() || h != oldSize.height();
241 if (!isMove && !isResize)
242 return;
243
244 if (q->isWindow()) {
245 if (w == 0 || h == 0) {
246 q->setAttribute(Qt::WA_OutsideWSRange, true);
247 if (q->isVisible() && q->testAttribute(Qt::WA_Mapped))
248 hide_sys();
249 data.crect = QRect(x, y, w, h);
250 data.window_state &= ~Qt::WindowFullScreen;
251 } else if (q->isVisible() && q->testAttribute(Qt::WA_OutsideWSRange)) {
252 q->setAttribute(Qt::WA_OutsideWSRange, false);
253
254 // put the window in its place and show it
255 q->internalWinId()->SetRect(TRect(TPoint(x, y), TSize(w, h)));
256 data.crect.setRect(x, y, w, h);
257 show_sys();
258 } else {
259 QRect r = QRect(x, y, w, h);
260 data.crect = r;
261 q->internalWinId()->SetRect(TRect(TPoint(x, y), TSize(w, h)));
262 topData()->normalGeometry = data.crect;
263 }
264 } else {
265 data.crect.setRect(x, y, w, h);
266
267 QTLWExtra *tlwExtra = q->window()->d_func()->maybeTopData();
268 const bool inTopLevelResize = tlwExtra ? tlwExtra->inTopLevelResize : false;
269
270 if (q->isVisible() && (!inTopLevelResize || q->internalWinId())) {
271 // Top-level resize optimization does not work for native child widgets;
272 // disable it for this particular widget.
273 if (inTopLevelResize)
274 tlwExtra->inTopLevelResize = false;
275 if (!isResize && maybeBackingStore())
276 moveRect(QRect(oldPos, oldSize), x - oldPos.x(), y - oldPos.y());
277 else
278 invalidateBuffer_resizeHelper(oldPos, oldSize);
279
280 if (inTopLevelResize)
281 tlwExtra->inTopLevelResize = true;
282 }
283 if (q->testAttribute(Qt::WA_WState_Created))
284 setWSGeometry();
285 }
286
287 if (q->isVisible()) {
288 if (isMove && q->pos() != oldPos) {
289 QMoveEvent e(q->pos(), oldPos);
290 QApplication::sendEvent(q, &e);
291 }
292 if (isResize) {
293 bool slowResize = qgetenv("QT_SLOW_TOPLEVEL_RESIZE").toInt();
294 const bool setTopLevelResize = !slowResize && q->isWindow() && extra && extra->topextra
295 && !extra->topextra->inTopLevelResize;
296 if (setTopLevelResize)
297 extra->topextra->inTopLevelResize = true;
298 QResizeEvent e(q->size(), oldSize);
299 QApplication::sendEvent(q, &e);
300 if (!q->testAttribute(Qt::WA_StaticContents) && q->internalWinId())
301 q->internalWinId()->DrawDeferred();
302 if (setTopLevelResize)
303 extra->topextra->inTopLevelResize = false;
304 }
305 } else {
306 if (isMove && q->pos() != oldPos)
307 q->setAttribute(Qt::WA_PendingMoveEvent, true);
308 if (isResize)
309 q->setAttribute(Qt::WA_PendingResizeEvent, true);
310 }
311}
312
313void QWidgetPrivate::create_sys(WId window, bool /* initializeWindow */, bool destroyOldWindow)
314{
315 Q_Q(QWidget);
316
317 Qt::WindowType type = q->windowType();
318 Qt::WindowFlags &flags = data.window_flags;
319 QWidget *parentWidget = q->parentWidget();
320
321 bool topLevel = (flags & Qt::Window);
322 bool popup = (type == Qt::Popup);
323 bool dialog = (type == Qt::Dialog
324 || type == Qt::Sheet
325 || (flags & Qt::MSWindowsFixedSizeDialogHint));
326 bool desktop = (type == Qt::Desktop);
327 //bool tool = (type == Qt::Tool || type == Qt::Drawer);
328
329 if (popup)
330 flags |= Qt::WindowStaysOnTopHint; // a popup stays on top
331
332 TRect clientRect = static_cast<CEikAppUi*>(S60->appUi())->ClientRect();
333 int sw = clientRect.Width();
334 int sh = clientRect.Height();
335
336 if (desktop) {
337 TSize screenSize = S60->screenDevice()->SizeInPixels();
338 data.crect.setRect(0, 0, screenSize.iWidth, screenSize.iHeight);
339 q->setAttribute(Qt::WA_DontShowOnScreen);
340 } else if (topLevel && !q->testAttribute(Qt::WA_Resized)){
341 int width = sw;
342 int height = sh;
343 if (extra) {
344 width = qMax(qMin(width, extra->maxw), extra->minw);
345 height = qMax(qMin(height, extra->maxh), extra->minh);
346 }
347 data.crect.setSize(QSize(width, height));
348 }
349
350 CCoeControl *const destroyw = destroyOldWindow ? data.winid : 0;
351
352 createExtra();
353 if (window) {
354 setWinId(window);
355 TRect tr = window->Rect();
356 data.crect.setRect(tr.iTl.iX, tr.iTl.iY, tr.Width(), tr.Height());
357
358 } else if (topLevel) {
359 if (!q->testAttribute(Qt::WA_Moved) && !q->testAttribute(Qt::WA_DontShowOnScreen))
360 data.crect.moveTopLeft(QPoint(clientRect.iTl.iX, clientRect.iTl.iY));
361
362 QScopedPointer<QSymbianControl> control( q_check_ptr(new QSymbianControl(q)) );
363 QT_TRAP_THROWING(control->ConstructL(true, desktop));
364 control->SetMopParent(static_cast<CEikAppUi*>(S60->appUi()));
365
366 // Symbian windows are always created in an inactive state
367 // We perform this assignment for the case where the window is being re-created
368 // as aa result of a call to setParent_sys, on either this widget or one of its
369 // ancestors.
370 extra->activated = 0;
371
372 if (!desktop) {
373 TInt stackingFlags;
374 if ((q->windowType() & Qt::Popup) == Qt::Popup) {
375 stackingFlags = ECoeStackFlagRefusesAllKeys | ECoeStackFlagRefusesFocus;
376 } else {
377 stackingFlags = ECoeStackFlagStandard;
378 }
379 control->MakeVisible(false);
380 QT_TRAP_THROWING(control->ControlEnv()->AppUi()->AddToStackL(control.data(), ECoeStackPriorityDefault, stackingFlags));
381 // Avoid keyboard focus to a hidden window.
382 control->setFocusSafely(false);
383
384 RDrawableWindow *const drawableWindow = control->DrawableWindow();
385 // Request mouse move events.
386 drawableWindow->PointerFilter(EPointerFilterEnterExit
387 | EPointerFilterMove | EPointerFilterDrag, 0);
388 drawableWindow->EnableVisibilityChangeEvents();
389
390 }
391
392 q->setAttribute(Qt::WA_WState_Created);
393
394 int x, y, w, h;
395 data.crect.getRect(&x, &y, &w, &h);
396 control->SetRect(TRect(TPoint(x, y), TSize(w, h)));
397
398 // We wait until the control is fully constructed before calling setWinId, because
399 // this generates a WinIdChanged event.
400 setWinId(control.take());
401
402 if (!desktop)
403 s60UpdateIsOpaque(); // must be called after setWinId()
404
405 } else if (q->testAttribute(Qt::WA_NativeWindow) || paintOnScreen()) { // create native child widget
406
407 QScopedPointer<QSymbianControl> control( q_check_ptr(new QSymbianControl(q)) );
408 QT_TRAP_THROWING(control->ConstructL(!parentWidget));
409
410 // Symbian windows are always created in an inactive state
411 // We perform this assignment for the case where the window is being re-created
412 // as aa result of a call to setParent_sys, on either this widget or one of its
413 // ancestors.
414 extra->activated = 0;
415
416 TInt stackingFlags;
417 if ((q->windowType() & Qt::Popup) == Qt::Popup) {
418 stackingFlags = ECoeStackFlagRefusesAllKeys | ECoeStackFlagRefusesFocus;
419 } else {
420 stackingFlags = ECoeStackFlagStandard;
421 }
422 control->MakeVisible(false);
423 QT_TRAP_THROWING(control->ControlEnv()->AppUi()->AddToStackL(control.data(), ECoeStackPriorityDefault, stackingFlags));
424 // Avoid keyboard focus to a hidden window.
425 control->setFocusSafely(false);
426
427 q->setAttribute(Qt::WA_WState_Created);
428 int x, y, w, h;
429 data.crect.getRect(&x, &y, &w, &h);
430 control->SetRect(TRect(TPoint(x, y), TSize(w, h)));
431
432 RDrawableWindow *const drawableWindow = control->DrawableWindow();
433 // Request mouse move events.
434 drawableWindow->PointerFilter(EPointerFilterEnterExit
435 | EPointerFilterMove | EPointerFilterDrag, 0);
436
437 if (q->isVisible() && q->testAttribute(Qt::WA_Mapped)) {
438 activateSymbianWindow(control.data());
439 control->MakeVisible(true);
440 }
441
442 // We wait until the control is fully constructed before calling setWinId, because
443 // this generates a WinIdChanged event.
444 setWinId(control.take());
445 }
446
447 if (destroyw) {
448 destroyw->ControlEnv()->AppUi()->RemoveFromStack(destroyw);
449
450 // Delay deletion of the control in case this function is called in the
451 // context of a CONE event handler such as
452 // CCoeControl::ProcessPointerEventL
453 QMetaObject::invokeMethod(q, "_q_delayedDestroy",
454 Qt::QueuedConnection, Q_ARG(WId, destroyw));
455 }
456
457 if (q->testAttribute(Qt::WA_AcceptTouchEvents))
458 registerTouchWindow();
459}
460
461
462void QWidgetPrivate::show_sys()
463{
464 Q_Q(QWidget);
465
466 if (q->testAttribute(Qt::WA_OutsideWSRange))
467 return;
468
469 Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
470
471 q->setAttribute(Qt::WA_Mapped);
472
473 if (q->testAttribute(Qt::WA_DontShowOnScreen)) {
474 invalidateBuffer(q->rect());
475 return;
476 }
477
478 if (q->internalWinId()) {
479 if (!extra->activated)
480 activateSymbianWindow();
481
482 QSymbianControl *id = static_cast<QSymbianControl *>(q->internalWinId());
483
484#ifdef Q_WS_S60
485 // Lazily initialize the S60 screen furniture when the first window is shown.
486 if (!QApplication::testAttribute(Qt::AA_S60DontConstructApplicationPanes)
487 && !S60->buttonGroupContainer() && !S60->statusPane()) {
488
489 bool isFullscreen = q->windowState() & Qt::WindowFullScreen;
490
491 if (!q->testAttribute(Qt::WA_DontShowOnScreen)) {
492
493 // Create the status pane and CBA here
494 CEikAppUi *ui = static_cast<CEikAppUi *>(S60->appUi());
495 MEikAppUiFactory *factory = CEikonEnv::Static()->AppUiFactory();
496 TRAP_IGNORE(factory->ReadAppInfoResourceL(0, ui));
497 if (S60->buttonGroupContainer())
498 S60->buttonGroupContainer()->SetCommandSetL(R_AVKON_SOFTKEYS_EMPTY_WITH_IDS);
499
500 if (S60->statusPane()) {
501 // Use QDesktopWidget as the status pane observer to proxy for the AppUi.
502 // Can't use AppUi directly because it privately inherits from MEikStatusPaneObserver.
503 QSymbianControl *desktopControl = static_cast<QSymbianControl *>(QApplication::desktop()->winId());
504 S60->statusPane()->SetObserver(desktopControl);
505
506 // Hide the status pane if fullscreen OR
507 // Fill client area if maximized OR
508 // Put window below status pane unless the window has an explicit position.
509 if (isFullscreen) {
510 S60->statusPane()->MakeVisible(false);
511 } else if (q->windowState() & Qt::WindowMaximized) {
512 TRect r = static_cast<CEikAppUi*>(S60->appUi())->ClientRect();
513 id->SetExtent(r.iTl, r.Size());
514 } else if (!q->testAttribute(Qt::WA_Moved)) {
515 id->SetPosition(static_cast<CEikAppUi*>(S60->appUi())->ClientRect().iTl);
516 }
517 }
518 }
519 }
520#endif
521
522 id->MakeVisible(true);
523
524 if(q->isWindow())
525 id->setFocusSafely(true);
526 }
527
528 invalidateBuffer(q->rect());
529}
530
531void QWidgetPrivate::activateSymbianWindow(WId wid)
532{
533 Q_Q(QWidget);
534
535 Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
536 Q_ASSERT(q->testAttribute(Qt::WA_Mapped));
537 Q_ASSERT(!extra->activated);
538
539 if(!wid)
540 wid = q->internalWinId();
541
542 Q_ASSERT(wid);
543
544 QT_TRAP_THROWING(wid->ActivateL());
545 extra->activated = 1;
546}
547
548void QWidgetPrivate::hide_sys()
549{
550 Q_Q(QWidget);
551
552 Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
553 deactivateWidgetCleanup();
554 QSymbianControl *id = static_cast<QSymbianControl *>(q->internalWinId());
555
556 if (id) {
557 //Incorrect optimisation - for popup windows, Qt's focus is moved before
558 //hide_sys is called, resulting in the popup window keeping its elevated
559 //position in the CONE control stack.
560 //This can result in keyboard focus being in an invisible widget in some
561 //conditions - e.g. QTBUG-4733
562 //if(id->IsFocused()) // Avoid unnecessary calls to FocusChanged()
563 id->setFocusSafely(false);
564 id->MakeVisible(false);
565 if (QWidgetBackingStore *bs = maybeBackingStore())
566 bs->releaseBuffer();
567 } else {
568 invalidateBuffer(q->rect());
569 }
570
571 q->setAttribute(Qt::WA_Mapped, false);
572}
573
574void QWidgetPrivate::setFocus_sys()
575{
576 Q_Q(QWidget);
577 if (q->testAttribute(Qt::WA_WState_Created) && q->window()->windowType() != Qt::Popup)
578 if (!q->effectiveWinId()->IsFocused()) // Avoid unnecessry calls to FocusChanged()
579 static_cast<QSymbianControl *>(q->effectiveWinId())->setFocusSafely(true);
580}
581
582void QWidgetPrivate::raise_sys()
583{
584 Q_Q(QWidget);
585
586 Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
587 if (q->internalWinId()) {
588 q->internalWinId()->DrawableWindow()->SetOrdinalPosition(0);
589
590 // If toplevel widget, raise app to foreground
591 if (q->isWindow())
592 S60->wsSession().SetWindowGroupOrdinalPosition(S60->windowGroup().Identifier(), 0);
593 }
594}
595
596void QWidgetPrivate::lower_sys()
597{
598 Q_Q(QWidget);
599
600 Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
601 if (q->internalWinId()) {
602 // If toplevel widget, lower app to background
603 if (q->isWindow())
604 S60->wsSession().SetWindowGroupOrdinalPosition(S60->windowGroup().Identifier(), -1);
605 else
606 q->internalWinId()->DrawableWindow()->SetOrdinalPosition(-1);
607 }
608
609 if (!q->isWindow())
610 invalidateBuffer(q->rect());
611}
612
613void QWidgetPrivate::setModal_sys()
614{
615
616}
617
618void QWidgetPrivate::stackUnder_sys(QWidget* w)
619{
620 Q_Q(QWidget);
621 Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
622
623 if (q->internalWinId() && w->internalWinId()) {
624 RDrawableWindow *const thisWindow = q->internalWinId()->DrawableWindow();
625 RDrawableWindow *const otherWindow = w->internalWinId()->DrawableWindow();
626 thisWindow->SetOrdinalPosition(otherWindow->OrdinalPosition() + 1);
627 }
628
629 if (!q->isWindow() || !w->internalWinId())
630 invalidateBuffer(q->rect());
631}
632
633void QWidgetPrivate::reparentChildren()
634{
635 Q_Q(QWidget);
636
637 QObjectList chlist = q->children();
638 for (int i = 0; i < chlist.size(); ++i) { // reparent children
639 QObject *obj = chlist.at(i);
640 if (obj->isWidgetType()) {
641 QWidget *w = (QWidget *)obj;
642 if (!w->testAttribute(Qt::WA_WState_Created))
643 continue;
644 if (!w->isWindow()) {
645 w->d_func()->invalidateBuffer(w->rect());
646 WId parent = q->effectiveWinId();
647 WId child = w->effectiveWinId();
648 if (parent != child) {
649 // Child widget is native. Because Symbian windows cannot be
650 // re-parented, we must re-create the window.
651 const WId window = 0;
652 const bool initializeWindow = false;
653 const bool destroyOldWindow = true;
654 w->d_func()->create_sys(window, initializeWindow, destroyOldWindow);
655 }
656 // ### TODO: We probably also need to update the component array here
657 w->d_func()->reparentChildren();
658 } else {
659 bool showIt = w->isVisible();
660 QPoint old_pos = w->pos();
661 w->setParent(q, w->windowFlags());
662 w->move(old_pos);
663 if (showIt)
664 w->show();
665 }
666 }
667 }
668}
669
670void QWidgetPrivate::setParent_sys(QWidget *parent, Qt::WindowFlags f)
671{
672 Q_Q(QWidget);
673
674 bool wasCreated = q->testAttribute(Qt::WA_WState_Created);
675
676 if (q->isVisible() && q->parentWidget() && parent != q->parentWidget())
677 q->parentWidget()->d_func()->invalidateBuffer(q->geometry());
678
679 if (q->testAttribute(Qt::WA_DropSiteRegistered))
680 q->setAttribute(Qt::WA_DropSiteRegistered, false);
681
682 QSymbianControl *old_winid = static_cast<QSymbianControl *>(wasCreated ? data.winid : 0);
683 if ((q->windowType() == Qt::Desktop))
684 old_winid = 0;
685 setWinId(0);
686
687 // hide and reparent our own window away. Otherwise we might get
688 // destroyed when emitting the child remove event below. See QWorkspace.
689 if (wasCreated && old_winid) {
690 old_winid->MakeVisible(false);
691 if (old_winid->IsFocused()) // Avoid unnecessary calls to FocusChanged()
692 old_winid->setFocusSafely(false);
693 old_winid->SetParent(0);
694 }
695
696 QObjectPrivate::setParent_helper(parent);
697 bool explicitlyHidden = q->testAttribute(Qt::WA_WState_Hidden) && q->testAttribute(Qt::WA_WState_ExplicitShowHide);
698
699 data.window_flags = f;
700 data.fstrut_dirty = true;
701 q->setAttribute(Qt::WA_WState_Created, false);
702 q->setAttribute(Qt::WA_WState_Visible, false);
703 q->setAttribute(Qt::WA_WState_Hidden, false);
704 adjustFlags(data.window_flags, q);
705 // keep compatibility with previous versions, we need to preserve the created state
706 // (but we recreate the winId for the widget being reparented, again for compatibility)
707 if (wasCreated || (!q->isWindow() && parent->testAttribute(Qt::WA_WState_Created)))
708 createWinId();
709 if (q->isWindow() || (!parent || parent->isVisible()) || explicitlyHidden)
710 q->setAttribute(Qt::WA_WState_Hidden);
711 q->setAttribute(Qt::WA_WState_ExplicitShowHide, explicitlyHidden);
712
713 if (wasCreated)
714 reparentChildren();
715
716 if (old_winid) {
717 CBase::Delete(old_winid);
718 }
719
720 if (q->testAttribute(Qt::WA_AcceptDrops)
721 || (!q->isWindow() && q->parentWidget() && q->parentWidget()->testAttribute(Qt::WA_DropSiteRegistered)))
722 q->setAttribute(Qt::WA_DropSiteRegistered, true);
723
724 invalidateBuffer(q->rect());
725}
726
727void QWidgetPrivate::setConstraints_sys()
728{
729
730}
731
732
733void QWidgetPrivate::s60UpdateIsOpaque()
734{
735 Q_Q(QWidget);
736
737 if (!q->testAttribute(Qt::WA_WState_Created) || !q->testAttribute(Qt::WA_TranslucentBackground))
738 return;
739
740 if ((data.window_flags & Qt::FramelessWindowHint) == 0)
741 return;
742
743 RWindow *const window = static_cast<RWindow *>(q->effectiveWinId()->DrawableWindow());
744
745#ifdef Q_SYMBIAN_SEMITRANSPARENT_BG_SURFACE
746 window->SetSurfaceTransparency(!isOpaque);
747#else
748 if (!isOpaque) {
749 const TDisplayMode displayMode = static_cast<TDisplayMode>(window->SetRequiredDisplayMode(EColor16MA));
750 if (window->SetTransparencyAlphaChannel() == KErrNone)
751 window->SetBackgroundColor(TRgb(255, 255, 255, 0));
752 } else
753 window->SetTransparentRegion(TRegionFix<1>());
754#endif
755}
756
757void QWidgetPrivate::setWindowIcon_sys(bool forceReset)
758{
759#ifdef Q_WS_S60
760 Q_Q(QWidget);
761
762 if (!q->testAttribute(Qt::WA_WState_Created) || !q->isWindow() )
763 return;
764
765 QTLWExtra* topData = this->topData();
766 if (topData->iconPixmap && !forceReset)
767 // already been set
768 return;
769
770 TRect cPaneRect;
771 TBool found = AknLayoutUtils::LayoutMetricsRect( AknLayoutUtils::EContextPane, cPaneRect );
772 CAknContextPane* contextPane = S60->contextPane();
773 if (found && contextPane) { // We have context pane with valid metrics
774 QIcon icon = q->windowIcon();
775 if (!icon.isNull()) {
776 // Valid icon -> set it as an context pane picture
777 QSize size = icon.actualSize(QSize(cPaneRect.Size().iWidth, cPaneRect.Size().iHeight));
778 QPixmap pm = icon.pixmap(size);
779 QBitmap mask = pm.mask();
780 if (mask.isNull()) {
781 mask = QBitmap(pm.size());
782 mask.fill(Qt::color1);
783 }
784
785 CFbsBitmap* nBitmap = pm.toSymbianCFbsBitmap();
786 CFbsBitmap* nMask = mask.toSymbianCFbsBitmap();
787 contextPane->SetPicture(nBitmap,nMask);
788 } else {
789 // Icon set to null -> set context pane picture to default
790 QT_TRAP_THROWING(contextPane->SetPictureToDefaultL());
791 }
792 } else {
793 // Context pane does not exist, try setting small icon to title pane
794 TRect titlePaneRect;
795 TBool found = AknLayoutUtils::LayoutMetricsRect( AknLayoutUtils::ETitlePane, titlePaneRect );
796 CAknTitlePane* titlePane = S60->titlePane();
797 if (found && titlePane) { // We have title pane with valid metrics
798 // The API to get title_pane graphics size is not public -> assume square space based
799 // on titlebar font height. CAknBitmap would be optimum, wihtout setting the size, since
800 // then title pane would automatically scale the bitmap. Unfortunately it is not public API
801 // Also this function is leaving, although it is not named as such.
802 const CFont * font;
803 QT_TRAP_THROWING(font = AknLayoutUtils::FontFromId(EAknLogicalFontTitleFont));
804 TSize iconSize(font->HeightInPixels(), font->HeightInPixels());
805
806 QIcon icon = q->windowIcon();
807 if (!icon.isNull()) {
808 // Valid icon -> set it as an title pane small picture
809 QSize size = icon.actualSize(QSize(iconSize.iWidth, iconSize.iHeight));
810 QPixmap pm = icon.pixmap(size);
811 QBitmap mask = pm.mask();
812 if (mask.isNull()) {
813 mask = QBitmap(pm.size());
814 mask.fill(Qt::color1);
815 }
816
817 CFbsBitmap* nBitmap = pm.toSymbianCFbsBitmap();
818 CFbsBitmap* nMask = mask.toSymbianCFbsBitmap();
819 titlePane->SetSmallPicture( nBitmap, nMask, ETrue );
820 } else {
821 // Icon set to null -> set context pane picture to default
822 titlePane->SetSmallPicture( NULL, NULL, EFalse );
823 }
824 }
825 }
826
827#else
828 Q_UNUSED(forceReset)
829#endif
830}
831
832void QWidgetPrivate::setWindowTitle_sys(const QString &caption)
833{
834#ifdef Q_WS_S60
835 Q_Q(QWidget);
836 if (q->isWindow()) {
837 Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
838 CAknTitlePane* titlePane = S60->titlePane();
839 if (titlePane) {
840 if (caption.isEmpty()) {
841 QT_TRAP_THROWING(titlePane->SetTextToDefaultL());
842 } else {
843 QT_TRAP_THROWING(titlePane->SetTextL(qt_QString2TPtrC(caption)));
844 }
845 }
846 }
847#else
848 Q_UNUSED(caption)
849#endif
850}
851
852void QWidgetPrivate::setWindowIconText_sys(const QString & /*iconText */)
853{
854
855}
856
857void QWidgetPrivate::scroll_sys(int dx, int dy)
858{
859 Q_Q(QWidget);
860
861 scrollChildren(dx, dy);
862 if (!paintOnScreen() || !q->internalWinId() || !q->internalWinId()->OwnsWindow()) {
863 scrollRect(q->rect(), dx, dy);
864 } else {
865 Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
866 RDrawableWindow *const window = q->internalWinId()->DrawableWindow();
867 window->Scroll(TPoint(dx, dy));
868 }
869}
870
871void QWidgetPrivate::scroll_sys(int dx, int dy, const QRect &r)
872{
873 Q_Q(QWidget);
874
875 if (!paintOnScreen() || !q->internalWinId() || !q->internalWinId()->OwnsWindow()) {
876 scrollRect(r, dx, dy);
877 } else {
878 Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
879 RDrawableWindow *const window = q->internalWinId()->DrawableWindow();
880 window->Scroll(TPoint(dx, dy), qt_QRect2TRect(r));
881 }
882}
883
884/*!
885 For this function to work in the emulator, you must add:
886 TRANSPARENCY
887 To a line in the wsini.ini file.
888*/
889void QWidgetPrivate::setWindowOpacity_sys(qreal)
890{
891 // ### TODO: Implement uniform window transparency
892}
893
894void QWidgetPrivate::updateFrameStrut()
895{
896
897}
898
899void QWidgetPrivate::updateSystemBackground()
900{
901
902}
903
904void QWidgetPrivate::registerDropSite(bool /* on */)
905{
906
907}
908
909void QWidgetPrivate::createTLSysExtra()
910{
911 extra->topextra->backingStore = 0;
912 extra->topextra->inExpose = 0;
913}
914
915void QWidgetPrivate::deleteTLSysExtra()
916{
917 delete extra->topextra->backingStore;
918 extra->topextra->backingStore = 0;
919}
920
921void QWidgetPrivate::createSysExtra()
922{
923 extra->activated = 0;
924 extra->nativePaintMode = QWExtra::Default;
925 extra->receiveNativePaintEvents = 0;
926}
927
928void QWidgetPrivate::deleteSysExtra()
929{
930 // this should only be non-zero if destroy() has not run due to constructor fail
931 if (data.winid) {
932 data.winid->ControlEnv()->AppUi()->RemoveFromStack(data.winid);
933 delete data.winid;
934 data.winid = 0;
935 }
936}
937
938QWindowSurface *QWidgetPrivate::createDefaultWindowSurface_sys()
939{
940 return new QS60WindowSurface(q_func());
941}
942
943void QWidgetPrivate::setMask_sys(const QRegion& /* region */)
944{
945
946}
947
948void QWidgetPrivate::registerTouchWindow()
949{
950#ifdef QT_SYMBIAN_SUPPORTS_ADVANCED_POINTER
951 Q_Q(QWidget);
952 if (q->testAttribute(Qt::WA_WState_Created) && q->windowType() != Qt::Desktop) {
953 RWindow *rwindow = static_cast<RWindow *>(q->effectiveWinId()->DrawableWindow());
954 rwindow->EnableAdvancedPointers();
955 }
956#endif
957}
958
959int QWidget::metric(PaintDeviceMetric m) const
960{
961 Q_D(const QWidget);
962 int val;
963 if (m == PdmWidth) {
964 val = data->crect.width();
965 } else if (m == PdmHeight) {
966 val = data->crect.height();
967 } else {
968 CWsScreenDevice *scr = S60->screenDevice();
969 switch(m) {
970 case PdmDpiX:
971 case PdmPhysicalDpiX:
972 if (d->extra && d->extra->customDpiX) {
973 val = d->extra->customDpiX;
974 } else {
975 const QWidgetPrivate *p = d;
976 while (p->parent) {
977 p = static_cast<const QWidget *>(p->parent)->d_func();
978 if (p->extra && p->extra->customDpiX) {
979 val = p->extra->customDpiX;
980 break;
981 }
982 }
983 if (p == d || !(p->extra && p->extra->customDpiX))
984 val = S60->defaultDpiX;
985 }
986 break;
987 case PdmDpiY:
988 case PdmPhysicalDpiY:
989 if (d->extra && d->extra->customDpiY) {
990 val = d->extra->customDpiY;
991 } else {
992 const QWidgetPrivate *p = d;
993 while (p->parent) {
994 p = static_cast<const QWidget *>(p->parent)->d_func();
995 if (p->extra && p->extra->customDpiY) {
996 val = p->extra->customDpiY;
997 break;
998 }
999 }
1000 if (p == d || !(p->extra && p->extra->customDpiY))
1001 val = S60->defaultDpiY;
1002 }
1003 break;
1004 case PdmWidthMM:
1005 {
1006 TInt twips = scr->HorizontalPixelsToTwips(data->crect.width());
1007 val = (int)(twips * (25.4/KTwipsPerInch));
1008 break;
1009 }
1010 case PdmHeightMM:
1011 {
1012 TInt twips = scr->VerticalPixelsToTwips(data->crect.height());
1013 val = (int)(twips * (25.4/KTwipsPerInch));
1014 break;
1015 }
1016 case PdmNumColors:
1017 val = TDisplayModeUtils::NumDisplayModeColors(scr->DisplayMode());
1018 break;
1019 case PdmDepth:
1020 val = TDisplayModeUtils::NumDisplayModeBitsPerPixel(scr->DisplayMode());
1021 break;
1022 default:
1023 val = 0;
1024 qWarning("QWidget::metric: Invalid metric command");
1025 }
1026 }
1027 return val;
1028}
1029
1030QPaintEngine *QWidget::paintEngine() const
1031{
1032 return 0;
1033}
1034
1035QPoint QWidget::mapToGlobal(const QPoint &pos) const
1036{
1037 Q_D(const QWidget);
1038 if (!testAttribute(Qt::WA_WState_Created) || !internalWinId()) {
1039
1040 QPoint p = pos + data->crect.topLeft();
1041 return (isWindow() || !parentWidget()) ? p : parentWidget()->mapToGlobal(p);
1042
1043 } else if ((d->data.window_flags & Qt::Window) && internalWinId()) { //toplevel
1044 QPoint tp = geometry().topLeft();
1045 return pos + tp;
1046 }
1047
1048 // Native window case
1049 const TPoint widgetScreenOffset = internalWinId()->PositionRelativeToScreen();
1050 const QPoint globalPos = QPoint(widgetScreenOffset.iX, widgetScreenOffset.iY) + pos;
1051 return globalPos;
1052}
1053
1054QPoint QWidget::mapFromGlobal(const QPoint &pos) const
1055{
1056 Q_D(const QWidget);
1057 if (!testAttribute(Qt::WA_WState_Created) || !internalWinId()) {
1058 QPoint p = (isWindow() || !parentWidget()) ? pos : parentWidget()->mapFromGlobal(pos);
1059 return p - data->crect.topLeft();
1060 } else if ((d->data.window_flags & Qt::Window) && internalWinId()) { //toplevel
1061 QPoint tp = geometry().topLeft();
1062 return pos - tp;
1063 }
1064
1065 // Native window case
1066 const TPoint widgetScreenOffset = internalWinId()->PositionRelativeToScreen();
1067 const QPoint widgetPos = pos - QPoint(widgetScreenOffset.iX, widgetScreenOffset.iY);
1068 return widgetPos;
1069}
1070
1071static Qt::WindowStates effectiveState(Qt::WindowStates state)
1072{
1073 if (state & Qt::WindowMinimized)
1074 return Qt::WindowMinimized;
1075 else if (state & Qt::WindowFullScreen)
1076 return Qt::WindowFullScreen;
1077 else if (state & Qt::WindowMaximized)
1078 return Qt::WindowMaximized;
1079 return Qt::WindowNoState;
1080}
1081
1082void QWidget::setWindowState(Qt::WindowStates newstate)
1083{
1084 Q_D(QWidget);
1085
1086 Qt::WindowStates oldstate = windowState();
1087
1088 const TBool isFullscreen = newstate & Qt::WindowFullScreen;
1089 const TBool cbaRequested = windowFlags() & Qt::WindowSoftkeysVisibleHint;
1090 const TBool cbaVisible = CEikButtonGroupContainer::Current() ? true : false;
1091 const TBool softkeyVisibilityChange = isFullscreen && (cbaRequested != cbaVisible);
1092
1093 if (oldstate == newstate && !softkeyVisibilityChange)
1094 return;
1095
1096 if (isWindow()) {
1097 createWinId();
1098 Q_ASSERT(testAttribute(Qt::WA_WState_Created));
1099
1100 const bool wasResized = testAttribute(Qt::WA_Resized);
1101 const bool wasMoved = testAttribute(Qt::WA_Moved);
1102
1103 QSymbianControl *window = static_cast<QSymbianControl *>(effectiveWinId());
1104 if (window && newstate & Qt::WindowMinimized) {
1105 window->setFocusSafely(false);
1106 window->MakeVisible(false);
1107 } else if (window && oldstate & Qt::WindowMinimized) {
1108 window->setFocusSafely(true);
1109 window->MakeVisible(true);
1110 }
1111
1112#ifdef Q_WS_S60
1113 // Hide window decoration when switching to fullsccreen / minimized otherwise show decoration.
1114 // The window decoration visibility has to be changed before doing actual window state
1115 // change since in that order the availableGeometry will return directly the right size and
1116 // we will avoid unnecessarty redraws
1117 CEikStatusPane *statusPane = S60->statusPane();
1118 CEikButtonGroupContainer *buttonGroup = S60->buttonGroupContainer();
1119 TBool visible = !(newstate & (Qt::WindowFullScreen | Qt::WindowMinimized));
1120 if (statusPane)
1121 statusPane->MakeVisible(visible);
1122 if (buttonGroup) {
1123 // Visibility
1124 buttonGroup->MakeVisible(visible || (isFullscreen && cbaRequested));
1125 }
1126#endif // Q_WS_S60
1127
1128 // Ensure the initial size is valid, since we store it as normalGeometry below.
1129 if (!wasResized && !isVisible())
1130 adjustSize();
1131
1132 QTLWExtra *top = d->topData();
1133 QRect normalGeometry = (top->normalGeometry.width() < 0) ? geometry() : top->normalGeometry;
1134
1135 const bool cbaVisibilityHint = windowFlags() & Qt::WindowSoftkeysVisibleHint;
1136 if (newstate & Qt::WindowFullScreen && !cbaVisibilityHint) {
1137 window->SetExtentToWholeScreen();
1138 } else if (newstate & Qt::WindowMaximized || ((newstate & Qt::WindowFullScreen) && cbaVisibilityHint)) {
1139 TRect maxExtent = qt_QRect2TRect(qApp->desktop()->availableGeometry(this));
1140 window->SetExtent(maxExtent.iTl, maxExtent.Size());
1141 } else {
1142#ifdef Q_WS_S60
1143 // With delayed creation of S60 app panes, the normalGeometry calculated above is not
1144 // accurate because it did not consider the status pane. This means that when returning
1145 // normal mode after showing the status pane, the geometry would overlap so we should
1146 // move it if it never had an explicit position.
1147 if (!wasMoved && statusPane && visible) {
1148 TPoint tl = static_cast<CEikAppUi*>(S60->appUi())->ClientRect().iTl;
1149 normalGeometry.setTopLeft(QPoint(tl.iX, tl.iY));
1150 }
1151#endif
1152 setGeometry(normalGeometry);
1153 }
1154
1155 //restore normal geometry
1156 top->normalGeometry = normalGeometry;
1157
1158 // FixMe QTBUG-8977
1159 // In some platforms, WA_Resized and WA_Moved are also not set when application window state is
1160 // anything else than normal. In Symbian we can restore them only for normal window state since
1161 // restoring for other modes, will make fluidlauncher to be launched in wrong size (200x100)
1162 if (effectiveState(newstate) == Qt::WindowNoState) {
1163 setAttribute(Qt::WA_Resized, wasResized);
1164 setAttribute(Qt::WA_Moved, wasMoved);
1165 }
1166 }
1167
1168 data->window_state = newstate;
1169
1170 if (newstate & Qt::WindowActive)
1171 activateWindow();
1172
1173 QWindowStateChangeEvent e(oldstate);
1174 QApplication::sendEvent(this, &e);
1175}
1176
1177
1178void QWidget::destroy(bool destroyWindow, bool destroySubWindows)
1179{
1180 Q_D(QWidget);
1181 if (!isWindow() && parentWidget())
1182 parentWidget()->d_func()->invalidateBuffer(geometry());
1183 d->deactivateWidgetCleanup();
1184 QSymbianControl *id = static_cast<QSymbianControl *>(internalWinId());
1185 if (testAttribute(Qt::WA_WState_Created)) {
1186
1187#ifndef QT_NO_IM
1188 if (d->ic) {
1189 delete d->ic;
1190 } else {
1191 QInputContext *ic = QApplicationPrivate::inputContext;
1192 if (ic) {
1193 ic->widgetDestroyed(this);
1194 }
1195 }
1196#endif
1197
1198 if (QWidgetPrivate::mouseGrabber == this)
1199 releaseMouse();
1200 if (QWidgetPrivate::keyboardGrabber == this)
1201 releaseKeyboard();
1202 setAttribute(Qt::WA_WState_Created, false);
1203 QObjectList childList = children();
1204 for (int i = 0; i < childList.size(); ++i) { // destroy all widget children
1205 register QObject *obj = childList.at(i);
1206 if (obj->isWidgetType())
1207 static_cast<QWidget*>(obj)->destroy(destroySubWindows,
1208 destroySubWindows);
1209 }
1210 if (destroyWindow && !(windowType() == Qt::Desktop) && id) {
1211 if (id->IsFocused()) // Avoid unnecessry calls to FocusChanged()
1212 id->setFocusSafely(false);
1213 id->ControlEnv()->AppUi()->RemoveFromStack(id);
1214 }
1215 }
1216
1217 QT_TRY {
1218 d->setWinId(0);
1219 } QT_CATCH (const std::bad_alloc &) {
1220 // swallow - destructors must not throw
1221 }
1222
1223 if (destroyWindow) {
1224 delete id;
1225 // At this point the backing store should already be destroyed
1226 // so we flush the command buffer to ensure that the freeing of
1227 // those resources and deleting the window can happen "atomically"
1228 S60->wsSession().Flush();
1229 }
1230}
1231
1232QWidget *QWidget::mouseGrabber()
1233{
1234 return QWidgetPrivate::mouseGrabber;
1235}
1236
1237QWidget *QWidget::keyboardGrabber()
1238{
1239 return QWidgetPrivate::keyboardGrabber;
1240}
1241
1242void QWidget::grabKeyboard()
1243{
1244 if (!qt_nograb()) {
1245 if (QWidgetPrivate::keyboardGrabber && QWidgetPrivate::keyboardGrabber != this)
1246 QWidgetPrivate::keyboardGrabber->releaseKeyboard();
1247
1248 // ### TODO: Native keyboard grab
1249
1250 QWidgetPrivate::keyboardGrabber = this;
1251 }
1252}
1253
1254void QWidget::releaseKeyboard()
1255{
1256 if (!qt_nograb() && QWidgetPrivate::keyboardGrabber == this) {
1257 // ### TODO: Native keyboard release
1258 QWidgetPrivate::keyboardGrabber = 0;
1259 }
1260}
1261
1262void QWidget::grabMouse()
1263{
1264 if (isVisible() && !qt_nograb()) {
1265 if (QWidgetPrivate::mouseGrabber && QWidgetPrivate::mouseGrabber != this)
1266 QWidgetPrivate::mouseGrabber->releaseMouse();
1267 Q_ASSERT(testAttribute(Qt::WA_WState_Created));
1268 WId id = effectiveWinId();
1269 id->SetPointerCapture(true);
1270 QWidgetPrivate::mouseGrabber = this;
1271
1272#ifndef QT_NO_CURSOR
1273 QApplication::setOverrideCursor(cursor());
1274#endif
1275 }
1276}
1277
1278#ifndef QT_NO_CURSOR
1279void QWidget::grabMouse(const QCursor &cursor)
1280{
1281 if (isVisible() && !qt_nograb()) {
1282 if (QWidgetPrivate::mouseGrabber && QWidgetPrivate::mouseGrabber != this)
1283 QWidgetPrivate::mouseGrabber->releaseMouse();
1284 Q_ASSERT(testAttribute(Qt::WA_WState_Created));
1285 WId id = effectiveWinId();
1286 id->SetPointerCapture(true);
1287 QWidgetPrivate::mouseGrabber = this;
1288
1289 QApplication::setOverrideCursor(cursor);
1290 }
1291}
1292#endif
1293
1294void QWidget::releaseMouse()
1295{
1296 if (!qt_nograb() && QWidgetPrivate::mouseGrabber == this) {
1297 Q_ASSERT(testAttribute(Qt::WA_WState_Created));
1298 if(!window()->isModal()) {
1299 WId id = effectiveWinId();
1300 id->SetPointerCapture(false);
1301 }
1302 QWidgetPrivate::mouseGrabber = 0;
1303#ifndef QT_NO_CURSOR
1304 QApplication::restoreOverrideCursor();
1305#endif
1306 }
1307}
1308
1309void QWidget::activateWindow()
1310{
1311 Q_D(QWidget);
1312
1313 QWidget *tlw = window();
1314 if (tlw->isVisible()) {
1315 window()->createWinId();
1316 QSymbianControl *id = static_cast<QSymbianControl *>(tlw->internalWinId());
1317 id->setFocusSafely(true);
1318 }
1319}
1320
1321#ifndef QT_NO_CURSOR
1322
1323void QWidgetPrivate::setCursor_sys(const QCursor &cursor)
1324{
1325 Q_UNUSED(cursor);
1326 Q_Q(QWidget);
1327 qt_symbian_set_cursor(q, false);
1328}
1329
1330void QWidgetPrivate::unsetCursor_sys()
1331{
1332 Q_Q(QWidget);
1333 qt_symbian_set_cursor(q, false);
1334}
1335#endif
1336
1337QT_END_NAMESPACE
Note: See TracBrowser for help on using the repository browser.