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

Last change on this file since 846 was 846, checked in by Dmitry A. Kuminov, 14 years ago

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

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