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

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

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

  • Property svn:eol-style set to native
File size: 50.4 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation (qt-info@nokia.com)
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 qt-info@nokia.com.
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 // Hide window decoration when switching to fullscreen / minimized otherwise show decoration.
1188 // The window decoration visibility has to be changed before doing actual window state
1189 // change since in that order the availableGeometry will return directly the right size and
1190 // we will avoid unnecessary redraws
1191 Qt::WindowStates comparisonState = newstate;
1192 QWidget *parentWindow = parentWidget();
1193 if (parentWindow) {
1194 while (parentWindow->parentWidget())
1195 parentWindow = parentWindow->parentWidget();
1196 comparisonState = parentWindow->windowState();
1197 } else {
1198 parentWindow = this;
1199 }
1200
1201 const bool decorationsVisible = !(comparisonState & (Qt::WindowFullScreen | Qt::WindowMinimized));
1202 const bool parentIsFullscreen = comparisonState & Qt::WindowFullScreen;
1203 const bool parentCbaVisibilityHint = parentWindow->windowFlags() & Qt::WindowSoftkeysVisibleHint;
1204 bool buttonGroupVisibility = (decorationsVisible || (parentIsFullscreen && parentCbaVisibilityHint));
1205
1206 // For non-toplevel normal and maximized windows, show cba if window has softkey
1207 // actions even if topmost parent is not showing cba. Do the same for fullscreen
1208 // windows that request it.
1209 if (!buttonGroupVisibility
1210 && parentWidget()
1211 && !(newstate & Qt::WindowMinimized)
1212 && ((windowFlags() & Qt::WindowSoftkeysVisibleHint) || !(newstate & Qt::WindowFullScreen))) {
1213 for (int i = 0; i < actions().size(); ++i) {
1214 if (actions().at(i)->softKeyRole() != QAction::NoSoftKey) {
1215 buttonGroupVisibility = true;
1216 break;
1217 }
1218 }
1219 }
1220 S60->setStatusPaneAndButtonGroupVisibility(decorationsVisible, buttonGroupVisibility);
1221
1222#endif // Q_WS_S60
1223
1224 // Ensure the initial size is valid, since we store it as normalGeometry below.
1225 if (!wasResized && !isVisible())
1226 adjustSize();
1227
1228 QTLWExtra *top = d->topData();
1229 QRect normalGeometry = (top->normalGeometry.width() < 0) ? geometry() : top->normalGeometry;
1230
1231 const bool cbaVisibilityHint = windowFlags() & Qt::WindowSoftkeysVisibleHint;
1232 if (newstate & Qt::WindowFullScreen && !cbaVisibilityHint) {
1233 setAttribute(Qt::WA_OutsideWSRange, false);
1234 window->SetExtentToWholeScreen();
1235 } else if (newstate & Qt::WindowMaximized || ((newstate & Qt::WindowFullScreen) && cbaVisibilityHint)) {
1236 setAttribute(Qt::WA_OutsideWSRange, false);
1237 TRect maxExtent = qt_QRect2TRect(qApp->desktop()->availableGeometry(this));
1238 window->SetExtent(maxExtent.iTl, maxExtent.Size());
1239 } else {
1240#ifdef Q_WS_S60
1241 // With delayed creation of S60 app panes, the normalGeometry calculated above is not
1242 // accurate because it did not consider the status pane. This means that when returning
1243 // normal mode after showing the status pane, the geometry would overlap so we should
1244 // move it if it never had an explicit position.
1245 if (!wasMoved && S60->statusPane() && decorationsVisible) {
1246 TPoint tl = static_cast<CEikAppUi*>(S60->appUi())->ClientRect().iTl;
1247 normalGeometry.setTopLeft(QPoint(tl.iX, tl.iY));
1248 }
1249#endif
1250 setGeometry(normalGeometry);
1251 }
1252
1253 //restore normal geometry
1254 top->normalGeometry = normalGeometry;
1255
1256 // FixMe QTBUG-8977
1257 // In some platforms, WA_Resized and WA_Moved are also not set when application window state is
1258 // anything else than normal. In Symbian we can restore them only for normal window state since
1259 // restoring for other modes, will make fluidlauncher to be launched in wrong size (200x100)
1260 if (effectiveState(newstate) == Qt::WindowNoState) {
1261 setAttribute(Qt::WA_Resized, wasResized);
1262 setAttribute(Qt::WA_Moved, wasMoved);
1263 }
1264 }
1265
1266 data->window_state = newstate;
1267
1268 if (newstate & Qt::WindowActive)
1269 activateWindow();
1270
1271 QWindowStateChangeEvent e(oldstate);
1272 QApplication::sendEvent(this, &e);
1273}
1274
1275
1276void QWidget::destroy(bool destroyWindow, bool destroySubWindows)
1277{
1278 Q_D(QWidget);
1279 d->aboutToDestroy();
1280 if (!isWindow() && parentWidget())
1281 parentWidget()->d_func()->invalidateBuffer(geometry());
1282 d->deactivateWidgetCleanup();
1283 QSymbianControl *id = static_cast<QSymbianControl *>(internalWinId());
1284 if (testAttribute(Qt::WA_WState_Created)) {
1285
1286#ifndef QT_NO_IM
1287 if (d->ic) {
1288 delete d->ic;
1289 } else {
1290 QInputContext *ic = QApplicationPrivate::inputContext;
1291 if (ic) {
1292 ic->widgetDestroyed(this);
1293 }
1294 }
1295#endif
1296
1297 if (QWidgetPrivate::mouseGrabber == this)
1298 releaseMouse();
1299 if (QWidgetPrivate::keyboardGrabber == this)
1300 releaseKeyboard();
1301 setAttribute(Qt::WA_WState_Created, false);
1302 QObjectList childList = children();
1303 for (int i = 0; i < childList.size(); ++i) { // destroy all widget children
1304 register QObject *obj = childList.at(i);
1305 if (obj->isWidgetType())
1306 static_cast<QWidget*>(obj)->destroy(destroySubWindows,
1307 destroySubWindows);
1308 }
1309 if (destroyWindow && !(windowType() == Qt::Desktop) && id) {
1310 if (id->IsFocused()) // Avoid unnecessry calls to FocusChanged()
1311 id->setFocusSafely(false);
1312 id->ControlEnv()->AppUi()->RemoveFromStack(id);
1313 }
1314 }
1315
1316 QT_TRY {
1317 d->setWinId(0);
1318 } QT_CATCH (const std::bad_alloc &) {
1319 // swallow - destructors must not throw
1320 }
1321
1322 if (destroyWindow) {
1323 delete id;
1324 // At this point the backing store should already be destroyed
1325 // so we flush the command buffer to ensure that the freeing of
1326 // those resources and deleting the window can happen "atomically"
1327 if (qApp)
1328 S60->wsSession().Flush();
1329 }
1330}
1331
1332QWidget *QWidget::mouseGrabber()
1333{
1334 return QWidgetPrivate::mouseGrabber;
1335}
1336
1337QWidget *QWidget::keyboardGrabber()
1338{
1339 return QWidgetPrivate::keyboardGrabber;
1340}
1341
1342void QWidget::grabKeyboard()
1343{
1344 if (!qt_nograb()) {
1345 if (QWidgetPrivate::keyboardGrabber && QWidgetPrivate::keyboardGrabber != this)
1346 QWidgetPrivate::keyboardGrabber->releaseKeyboard();
1347
1348 // ### TODO: Native keyboard grab
1349
1350 QWidgetPrivate::keyboardGrabber = this;
1351 }
1352}
1353
1354void QWidget::releaseKeyboard()
1355{
1356 if (!qt_nograb() && QWidgetPrivate::keyboardGrabber == this) {
1357 // ### TODO: Native keyboard release
1358 QWidgetPrivate::keyboardGrabber = 0;
1359 }
1360}
1361
1362void QWidget::grabMouse()
1363{
1364 if (isVisible() && !qt_nograb()) {
1365 if (QWidgetPrivate::mouseGrabber && QWidgetPrivate::mouseGrabber != this)
1366 QWidgetPrivate::mouseGrabber->releaseMouse();
1367 Q_ASSERT(testAttribute(Qt::WA_WState_Created));
1368 WId id = effectiveWinId();
1369 id->SetPointerCapture(true);
1370 QWidgetPrivate::mouseGrabber = this;
1371
1372#ifndef QT_NO_CURSOR
1373 QApplication::setOverrideCursor(cursor());
1374#endif
1375 }
1376}
1377
1378#ifndef QT_NO_CURSOR
1379void QWidget::grabMouse(const QCursor &cursor)
1380{
1381 if (isVisible() && !qt_nograb()) {
1382 if (QWidgetPrivate::mouseGrabber && QWidgetPrivate::mouseGrabber != this)
1383 QWidgetPrivate::mouseGrabber->releaseMouse();
1384 Q_ASSERT(testAttribute(Qt::WA_WState_Created));
1385 WId id = effectiveWinId();
1386 id->SetPointerCapture(true);
1387 QWidgetPrivate::mouseGrabber = this;
1388
1389 QApplication::setOverrideCursor(cursor);
1390 }
1391}
1392#endif
1393
1394void QWidget::releaseMouse()
1395{
1396 if (!qt_nograb() && QWidgetPrivate::mouseGrabber == this) {
1397 Q_ASSERT(testAttribute(Qt::WA_WState_Created));
1398 if(!window()->isModal()) {
1399 WId id = effectiveWinId();
1400 id->SetPointerCapture(false);
1401 }
1402 QWidgetPrivate::mouseGrabber = 0;
1403#ifndef QT_NO_CURSOR
1404 QApplication::restoreOverrideCursor();
1405#endif
1406 }
1407}
1408
1409void QWidget::activateWindow()
1410{
1411 Q_D(QWidget);
1412
1413 QWidget *tlw = window();
1414 if (tlw->isVisible()) {
1415 window()->createWinId();
1416 QSymbianControl *id = static_cast<QSymbianControl *>(tlw->internalWinId());
1417 id->setFocusSafely(true);
1418 }
1419}
1420
1421#ifndef QT_NO_CURSOR
1422
1423void QWidgetPrivate::setCursor_sys(const QCursor &cursor)
1424{
1425 Q_UNUSED(cursor);
1426 Q_Q(QWidget);
1427 qt_symbian_set_cursor(q, false);
1428}
1429
1430void QWidgetPrivate::unsetCursor_sys()
1431{
1432 Q_Q(QWidget);
1433 qt_symbian_set_cursor(q, false);
1434}
1435#endif
1436
1437QT_END_NAMESPACE
Note: See TracBrowser for help on using the repository browser.