QPlatformWindow: Add Window masks.
[profile/ivi/qtbase.git] / src / widgets / kernel / qwidget_qpa.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
5 **
6 ** This file is part of the QtGui module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
16 **
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
20 **
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
28 **
29 ** Other Usage
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "QtWidgets/qwidget.h"
43 #include "QtGui/qevent.h"
44 #include "QtWidgets/qapplication.h"
45 #include "private/qwidgetbackingstore_p.h"
46 #include "private/qwidget_p.h"
47 #include "private/qwidgetwindow_qpa_p.h"
48 #include "private/qapplication_p.h"
49 #include "QtWidgets/qdesktopwidget.h"
50 #include <qpa/qplatformwindow.h>
51 #include "QtGui/qsurfaceformat.h"
52 #include <qpa/qplatformopenglcontext.h>
53 #include <qpa/qplatformintegration.h>
54 #include "QtGui/private/qwindow_p.h"
55
56 #include <qpa/qplatformcursor.h>
57 #include <QtGui/QGuiApplication>
58 #include <QtGui/QScreen>
59 #include <QtCore/QMargins>
60
61 QT_BEGIN_NAMESPACE
62
63 void q_createNativeChildrenAndSetParent(const QWidget *parentWidget)
64 {
65     QObjectList children = parentWidget->children();
66     for (int i = 0; i < children.size(); i++) {
67         if (children.at(i)->isWidgetType()) {
68             const QWidget *childWidget = qobject_cast<const QWidget *>(children.at(i));
69             if (childWidget) { // should not be necessary
70                 if (childWidget->testAttribute(Qt::WA_NativeWindow)) {
71                     if (!childWidget->windowHandle())
72                         childWidget->winId();
73                     if (childWidget->windowHandle()) {
74                         QWindow *parentWindow = childWidget->nativeParentWidget()->windowHandle();
75                         if (childWidget->isWindow())
76                             childWidget->windowHandle()->setTransientParent(parentWindow);
77                         else
78                             childWidget->windowHandle()->setParent(parentWindow);
79                     }
80                 } else {
81                     q_createNativeChildrenAndSetParent(childWidget);
82                 }
83             }
84         }
85     }
86
87 }
88
89 void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyOldWindow)
90 {
91     Q_Q(QWidget);
92
93     Q_UNUSED(window);
94     Q_UNUSED(initializeWindow);
95     Q_UNUSED(destroyOldWindow);
96
97     Qt::WindowFlags flags = data.window_flags;
98
99     if (!q->testAttribute(Qt::WA_NativeWindow) && !q->isWindow())
100         return; // we only care about real toplevels
101
102     QWindow *win = topData()->window;
103     // topData() ensures the extra is created but does not ensure 'window' is non-null
104     // in case the extra was already valid.
105     if (!win) {
106         createTLSysExtra();
107         win = topData()->window;
108     }
109
110     win->setWindowFlags(data.window_flags);
111     fixPosIncludesFrame();
112     win->setGeometry(q->geometry());
113     win->setScreen(QGuiApplication::screens().value(topData()->screenIndex, 0));
114
115     if (q->testAttribute(Qt::WA_TranslucentBackground)) {
116         QSurfaceFormat format;
117         format.setAlphaBufferSize(8);
118         win->setFormat(format);
119     }
120
121     if (QWidget *nativeParent = q->nativeParentWidget()) {
122         if (nativeParent->windowHandle()) {
123             if (flags & Qt::Window) {
124                 win->setTransientParent(nativeParent->windowHandle());
125                 win->setParent(0);
126             } else {
127                 win->setTransientParent(0);
128                 win->setParent(nativeParent->windowHandle());
129             }
130         }
131     }
132
133     qt_window_private(win)->positionPolicy = topData()->posIncludesFrame ?
134         QWindowPrivate::WindowFrameInclusive : QWindowPrivate::WindowFrameExclusive;
135     win->create();
136
137     data.window_flags = win->windowFlags();
138
139     QBackingStore *store = q->backingStore();
140
141     if (!store) {
142         if (win && q->windowType() != Qt::Desktop)
143             q->setBackingStore(new QBackingStore(win));
144         else
145             q->setAttribute(Qt::WA_PaintOnScreen, true);
146     }
147
148     setWindowModified_helper();
149     setWinId(win->winId());
150
151     // Check children and create windows for them if necessary
152     q_createNativeChildrenAndSetParent(q);
153
154     // If widget is already shown, set window visible, too
155     if (q->isVisible())
156         win->setVisible(true);
157 }
158
159 void QWidget::destroy(bool destroyWindow, bool destroySubWindows)
160 {
161     Q_D(QWidget);
162
163     d->aboutToDestroy();
164     if (!isWindow() && parentWidget())
165         parentWidget()->d_func()->invalidateBuffer(d->effectiveRectFor(geometry()));
166     d->deactivateWidgetCleanup();
167
168     if ((windowType() == Qt::Popup))
169         qApp->d_func()->closePopup(this);
170
171     if (this == QApplicationPrivate::active_window)
172         QApplication::setActiveWindow(0);
173     if (QWidget::mouseGrabber() == this)
174         releaseMouse();
175     if (QWidget::keyboardGrabber() == this)
176         releaseKeyboard();
177
178     setAttribute(Qt::WA_WState_Created, false);
179
180     if (windowType() != Qt::Desktop) {
181         if (destroySubWindows) {
182             QObjectList childList(children());
183             for (int i = 0; i < childList.size(); i++) {
184                 QWidget *widget = qobject_cast<QWidget *>(childList.at(i));
185                 if (widget && widget->testAttribute(Qt::WA_NativeWindow)) {
186                     if (widget->windowHandle()) {
187                         widget->destroy();
188                     }
189                 }
190             }
191         }
192         if (destroyWindow) {
193             d->deleteTLSysExtra();
194         } else {
195             if (parentWidget() && parentWidget()->testAttribute(Qt::WA_WState_Created)) {
196                 d->hide_sys();
197             }
198         }
199
200         d->setWinId(0);
201     }
202 }
203
204 void QWidgetPrivate::setParent_sys(QWidget *newparent, Qt::WindowFlags f)
205 {
206     Q_Q(QWidget);
207
208     Qt::WindowFlags oldFlags = data.window_flags;
209     bool wasCreated = q->testAttribute(Qt::WA_WState_Created);
210
211     int targetScreen = -1;
212     // Handle a request to move the widget to a particular screen
213     if (newparent && newparent->windowType() == Qt::Desktop) {
214         // make sure the widget is created on the same screen as the
215         // programmer specified desktop widget
216
217         // get the desktop's screen number
218         targetScreen = newparent->window()->d_func()->topData()->screenIndex;
219         newparent = 0;
220     }
221
222     setWinId(0);
223
224     if (parent != newparent) {
225         QObjectPrivate::setParent_helper(newparent); //### why does this have to be done in the _sys function???
226         if (q->windowHandle()) {
227             q->windowHandle()->setWindowFlags(f);
228             QWidget *parentWithWindow =
229                 newparent ? (newparent->windowHandle() ? newparent : newparent->nativeParentWidget()) : 0;
230             if (parentWithWindow) {
231                 if (f & Qt::Window) {
232                     q->windowHandle()->setTransientParent(parentWithWindow->windowHandle());
233                     q->windowHandle()->setParent(0);
234                 } else {
235                     q->windowHandle()->setTransientParent(0);
236                     q->windowHandle()->setParent(parentWithWindow->windowHandle());
237                 }
238             } else {
239                 q->windowHandle()->setTransientParent(0);
240                 q->windowHandle()->setParent(0);
241             }
242         }
243     }
244
245     if (!newparent) {
246         f |= Qt::Window;
247         if (targetScreen == -1) {
248             if (parent)
249                 targetScreen = q->parentWidget()->window()->d_func()->topData()->screenIndex;
250         }
251     }
252
253     bool explicitlyHidden = q->testAttribute(Qt::WA_WState_Hidden) && q->testAttribute(Qt::WA_WState_ExplicitShowHide);
254
255     // Reparenting toplevel to child
256     if (!(f&Qt::Window) && (oldFlags&Qt::Window) && !q->testAttribute(Qt::WA_NativeWindow)) {
257         //qDebug() << "setParent_sys() change from toplevel";
258         q->destroy();
259     } else if (newparent && wasCreated) {
260         q->createWinId();
261     }
262
263     adjustFlags(f, q);
264     data.window_flags = f;
265     q->setAttribute(Qt::WA_WState_Created, false);
266     q->setAttribute(Qt::WA_WState_Visible, false);
267     q->setAttribute(Qt::WA_WState_Hidden, false);
268
269     if (q->isWindow() || (!newparent || newparent->isVisible()) || explicitlyHidden)
270         q->setAttribute(Qt::WA_WState_Hidden);
271     q->setAttribute(Qt::WA_WState_ExplicitShowHide, explicitlyHidden);
272
273     // move the window to the selected screen
274     if (!newparent && targetScreen != -1) {
275         if (maybeTopData())
276             maybeTopData()->screenIndex = targetScreen;
277         // only if it is already created
278         if (q->testAttribute(Qt::WA_WState_Created)) {
279             q->windowHandle()->setScreen(QGuiApplication::screens().value(targetScreen, 0));
280         }
281     }
282 }
283
284 QPoint QWidget::mapToGlobal(const QPoint &pos) const
285 {
286     int x = pos.x(), y = pos.y();
287     const QWidget *w = this;
288     while (w) {
289         x += w->data->crect.x();
290         y += w->data->crect.y();
291         w = w->isWindow() ? 0 : w->parentWidget();
292     }
293     return QPoint(x, y);
294 }
295
296 QPoint QWidget::mapFromGlobal(const QPoint &pos) const
297 {
298     int x = pos.x(), y = pos.y();
299     const QWidget *w = this;
300     while (w) {
301         x -= w->data->crect.x();
302         y -= w->data->crect.y();
303         w = w->isWindow() ? 0 : w->parentWidget();
304     }
305     return QPoint(x, y);
306 }
307
308 void QWidgetPrivate::updateSystemBackground() {}
309
310 #ifndef QT_NO_CURSOR
311 void QWidgetPrivate::setCursor_sys(const QCursor &cursor)
312 {
313     Q_UNUSED(cursor);
314     Q_Q(QWidget);
315     qt_qpa_set_cursor(q, false);
316 }
317
318 void QWidgetPrivate::unsetCursor_sys()
319 {
320     Q_Q(QWidget);
321     qt_qpa_set_cursor(q, false);
322 }
323
324 #endif //QT_NO_CURSOR
325
326 void QWidgetPrivate::setWindowTitle_sys(const QString &caption)
327 {
328     Q_Q(QWidget);
329     if (!q->isWindow())
330         return;
331
332     if (QWindow *window = q->windowHandle())
333         window->setWindowTitle(caption);
334
335 }
336
337 void QWidgetPrivate::setWindowIcon_sys()
338 {
339     Q_Q(QWidget);
340     if (QWindow *window = q->windowHandle())
341         window->setWindowIcon(q->windowIcon());
342 }
343
344 void QWidgetPrivate::setWindowIconText_sys(const QString &iconText)
345 {
346     Q_UNUSED(iconText);
347 }
348
349 QWidget *qt_pressGrab = 0;
350 QWidget *qt_mouseGrb = 0;
351 static QWidget *keyboardGrb = 0;
352
353 void QWidget::grabMouse()
354 {
355     if (qt_mouseGrb)
356         qt_mouseGrb->releaseMouse();
357
358     if (windowHandle())
359         windowHandle()->setMouseGrabEnabled(true);
360
361     qt_mouseGrb = this;
362     qt_pressGrab = 0;
363 }
364
365 #ifndef QT_NO_CURSOR
366 void QWidget::grabMouse(const QCursor &cursor)
367 {
368     Q_UNUSED(cursor);
369
370     if (qt_mouseGrb)
371         qt_mouseGrb->releaseMouse();
372
373     if (windowHandle())
374         windowHandle()->setMouseGrabEnabled(true);
375
376     qt_mouseGrb = this;
377     qt_pressGrab = 0;
378 }
379 #endif
380
381 bool QWidgetPrivate::stealMouseGrab(bool grab)
382 {
383     // This is like a combination of grab/releaseMouse() but with error checking
384     // and it has no effect on the result of mouseGrabber().
385     Q_Q(QWidget);
386     return q->windowHandle() ? q->windowHandle()->setMouseGrabEnabled(grab) : false;
387 }
388
389 void QWidget::releaseMouse()
390 {
391     if (qt_mouseGrb == this) {
392         if (windowHandle())
393             windowHandle()->setMouseGrabEnabled(false);
394         qt_mouseGrb = 0;
395     }
396 }
397
398 void QWidget::grabKeyboard()
399 {
400     if (keyboardGrb)
401         keyboardGrb->releaseKeyboard();
402     if (windowHandle())
403         windowHandle()->setKeyboardGrabEnabled(true);
404     keyboardGrb = this;
405 }
406
407 bool QWidgetPrivate::stealKeyboardGrab(bool grab)
408 {
409     // This is like a combination of grab/releaseKeyboard() but with error
410     // checking and it has no effect on the result of keyboardGrabber().
411     Q_Q(QWidget);
412     return q->windowHandle() ? q->windowHandle()->setKeyboardGrabEnabled(grab) : false;
413 }
414
415 void QWidget::releaseKeyboard()
416 {
417     if (keyboardGrb == this) {
418         if (windowHandle())
419             windowHandle()->setKeyboardGrabEnabled(false);
420         keyboardGrb = 0;
421     }
422 }
423
424 QWidget *QWidget::mouseGrabber()
425 {
426     if (qt_mouseGrb)
427         return qt_mouseGrb;
428     return qt_pressGrab;
429 }
430
431 QWidget *QWidget::keyboardGrabber()
432 {
433     return keyboardGrb;
434 }
435
436 void QWidget::activateWindow()
437 {
438     if (windowHandle())
439         windowHandle()->requestActivateWindow();
440 }
441
442 // Position top level windows at the center, avoid showing
443 // Windows at the default 0,0 position excluding the frame.
444 static inline QRect positionTopLevelWindow(QRect geometry, const QScreen *screen)
445 {
446     if (screen && geometry.x() == 0 && geometry.y() == 0) {
447        const QRect availableGeometry = screen->availableGeometry();
448         if (availableGeometry.width() > geometry.width()
449             && availableGeometry.height() > geometry.height())
450             geometry.moveCenter(availableGeometry.center());
451     }
452     return geometry;
453 }
454
455 // move() was invoked with Qt::WA_WState_Created not set (frame geometry
456 // unknown), that is, crect has a position including the frame.
457 // If we can determine the frame strut, fix that and clear the flag.
458 void QWidgetPrivate::fixPosIncludesFrame()
459 {
460     Q_Q(QWidget);
461     if (QTLWExtra *te = maybeTopData()) {
462         if (te->posIncludesFrame) {
463             // For Qt::WA_DontShowOnScreen, assume a frame of 0 (for
464             // example, in QGraphicsProxyWidget).
465             if (q->testAttribute(Qt::WA_DontShowOnScreen)) {
466                 te->posIncludesFrame = 0;
467             } else {
468                 if (q->windowHandle()) {
469                     updateFrameStrut();
470                     if (!q->data->fstrut_dirty) {
471                         data.crect.translate(te->frameStrut.x(), te->frameStrut.y());
472                         te->posIncludesFrame = 0;
473                     }
474                 } // windowHandle()
475             } // !WA_DontShowOnScreen
476         } // posIncludesFrame
477     } // QTLWExtra
478 }
479
480 void QWidgetPrivate::show_sys()
481 {
482     Q_Q(QWidget);
483
484     QWindow *window = q->windowHandle();
485
486     if (q->testAttribute(Qt::WA_DontShowOnScreen)) {
487         invalidateBuffer(q->rect());
488         q->setAttribute(Qt::WA_Mapped);
489         if (q->isWindow() && q->windowModality() != Qt::NonModal && window) {
490             // add our window to the modal window list
491             QGuiApplicationPrivate::showModalWindow(window);
492         }
493         return;
494     }
495
496     QApplication::postEvent(q, new QUpdateLaterEvent(q->rect()));
497
498     if (!q->isWindow() && !q->testAttribute(Qt::WA_NativeWindow))
499         return;
500
501     if (window) {
502         if (q->isWindow())
503             fixPosIncludesFrame();
504         QRect geomRect = q->geometry();
505         if (q->isWindow()) {
506             if (!q->testAttribute(Qt::WA_Moved))
507                 geomRect = positionTopLevelWindow(geomRect, window->screen());
508         } else {
509             QPoint topLeftOfWindow = q->mapTo(q->nativeParentWidget(),QPoint());
510             geomRect.moveTopLeft(topLeftOfWindow);
511         }
512         const QRect windowRect = window->geometry();
513         if (windowRect != geomRect) {
514             window->setGeometry(geomRect);
515         }
516
517         if (QBackingStore *store = q->backingStore()) {
518             if (store->size() != geomRect.size()) {
519                 store->resize(geomRect.size());
520             }
521         }
522
523         invalidateBuffer(q->rect());
524         window->setVisible(true);
525     }
526 }
527
528
529 void QWidgetPrivate::hide_sys()
530 {
531     Q_Q(QWidget);
532
533     QWindow *window = q->windowHandle();
534
535     if (q->testAttribute(Qt::WA_DontShowOnScreen)) {
536         q->setAttribute(Qt::WA_Mapped, false);
537         if (q->isWindow() && q->windowModality() != Qt::NonModal && window) {
538             // remove our window from the modal window list
539             QGuiApplicationPrivate::hideModalWindow(window);
540         }
541         // do not return here, if window non-zero, we must hide it
542     }
543
544     deactivateWidgetCleanup();
545
546     if (!q->isWindow()) {
547         QWidget *p = q->parentWidget();
548         if (p &&p->isVisible()) {
549             invalidateBuffer(q->rect());
550         }
551     } else {
552         invalidateBuffer(q->rect());
553     }
554
555     if (window)
556         window->setVisible(false);
557 }
558
559 void QWidgetPrivate::setMaxWindowState_helper()
560 {
561     Q_Q(QWidget);
562
563     const uint old_state = data.in_set_window_state;
564     data.in_set_window_state = 1;
565
566     const QRect desktop = qApp->desktop()->availableGeometry(qApp->desktop()->screenNumber(q));
567     q->setGeometry(desktop);
568
569     data.in_set_window_state = old_state;
570 }
571
572 void QWidgetPrivate::setFullScreenSize_helper()
573 {
574     Q_Q(QWidget);
575
576     const uint old_state = data.in_set_window_state;
577     data.in_set_window_state = 1;
578
579     const QRect screen = qApp->desktop()->screenGeometry(qApp->desktop()->screenNumber(q));
580     q->move(screen.topLeft());
581     q->resize(screen.size());
582
583     data.in_set_window_state = old_state;
584 }
585
586 Qt::WindowState effectiveState(Qt::WindowStates state)
587  {
588      if (state & Qt::WindowMinimized)
589          return Qt::WindowMinimized;
590      else if (state & Qt::WindowFullScreen)
591          return Qt::WindowFullScreen;
592      else if (state & Qt::WindowMaximized)
593          return Qt::WindowMaximized;
594      return Qt::WindowNoState;
595  }
596
597 void QWidget::setWindowState(Qt::WindowStates newstate)
598 {
599     Q_D(QWidget);
600     Qt::WindowStates oldstate = windowState();
601     if (oldstate == newstate)
602         return;
603     if (isWindow() && !testAttribute(Qt::WA_WState_Created))
604         create();
605
606     data->window_state = newstate;
607     data->in_set_window_state = 1;
608     bool needShow = false;
609     Qt::WindowState newEffectiveState = effectiveState(newstate);
610     Qt::WindowState oldEffectiveState = effectiveState(oldstate);
611     if (isWindow() && newEffectiveState != oldEffectiveState) {
612         d->createTLExtra();
613         if (oldEffectiveState == Qt::WindowNoState)
614             d->topData()->normalGeometry = geometry();
615
616         Q_ASSERT(windowHandle());
617         windowHandle()->setWindowState(newEffectiveState);
618         bool supported = windowHandle()->windowState() == newEffectiveState;
619
620         if (!supported) {
621             // undo the effects of the old emulated state
622             if (oldEffectiveState == Qt::WindowFullScreen) {
623                 setParent(0, d->topData()->savedFlags);
624                 needShow = true;
625             } else if (oldEffectiveState == Qt::WindowMinimized) {
626                 needShow = true;
627             }
628
629             // emulate the new window state
630             if (newEffectiveState == Qt::WindowMinimized) {
631                 //### not ideal...
632                 hide();
633                 needShow = false;
634             } else if (newEffectiveState == Qt::WindowFullScreen) {
635                 d->topData()->savedFlags = windowFlags();
636                 setParent(0, Qt::FramelessWindowHint | (windowFlags() & Qt::WindowStaysOnTopHint));
637                 d->setFullScreenSize_helper();
638                 raise();
639                 needShow = true;
640             } else if (newEffectiveState == Qt::WindowMaximized) {
641                 createWinId();
642                 d->setMaxWindowState_helper();
643             } else if (newEffectiveState == Qt::WindowNoState) {
644                 // reset old geometry
645                 QRect r = d->topData()->normalGeometry;
646                 if (r.width() >= 0) {
647                     d->topData()->normalGeometry = QRect(0,0,-1,-1);
648                     setGeometry(r);
649                 }
650             }
651         }
652     }
653     data->in_set_window_state = 0;
654
655     if (needShow)
656         show();
657
658     if (newstate & Qt::WindowActive)
659         activateWindow();
660
661     QWindowStateChangeEvent e(oldstate);
662     QApplication::sendEvent(this, &e);
663 }
664
665 void QWidgetPrivate::setFocus_sys()
666 {
667
668 }
669
670 void QWidgetPrivate::raise_sys()
671 {
672     Q_Q(QWidget);
673     if (q->isWindow()) {
674         q->windowHandle()->raise();
675     }
676 }
677
678 void QWidgetPrivate::lower_sys()
679 {
680     Q_Q(QWidget);
681     if (q->isWindow()) {
682         Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
683         q->windowHandle()->lower();
684     } else if (QWidget *p = q->parentWidget()) {
685         setDirtyOpaqueRegion();
686         p->d_func()->invalidateBuffer(effectiveRectFor(q->geometry()));
687     }
688 }
689
690 void QWidgetPrivate::stackUnder_sys(QWidget*)
691 {
692     Q_Q(QWidget);
693     if (QWidget *p = q->parentWidget()) {
694         setDirtyOpaqueRegion();
695         p->d_func()->invalidateBuffer(effectiveRectFor(q->geometry()));
696     }
697 }
698
699 void QWidgetPrivate::setGeometry_sys(int x, int y, int w, int h, bool isMove)
700 {
701     Q_Q(QWidget);
702     if (extra) {                                // any size restrictions?
703         w = qMin(w,extra->maxw);
704         h = qMin(h,extra->maxh);
705         w = qMax(w,extra->minw);
706         h = qMax(h,extra->minh);
707     }
708
709     QPoint oldp = q->geometry().topLeft();
710     QSize olds = q->size();
711     QRect r(x, y, w, h);
712
713     bool isResize = olds != r.size();
714     isMove = oldp != r.topLeft(); //### why do we have isMove as a parameter?
715
716
717     // We only care about stuff that changes the geometry, or may
718     // cause the window manager to change its state
719     if (r.size() == olds && oldp == r.topLeft())
720         return;
721
722     if (!data.in_set_window_state) {
723         q->data->window_state &= ~Qt::WindowMaximized;
724         q->data->window_state &= ~Qt::WindowFullScreen;
725         if (q->isWindow())
726             topData()->normalGeometry = QRect(0, 0, -1, -1);
727     }
728
729     QPoint oldPos = q->pos();
730     data.crect = r;
731
732     bool needsShow = false;
733
734     if (w == 0 || h == 0) {
735         q->setAttribute(Qt::WA_OutsideWSRange, true);
736         if (q->isVisible() && q->testAttribute(Qt::WA_Mapped))
737             hide_sys();
738         data.crect = QRect(x, y, w, h);
739     } else if (q->isVisible() && q->testAttribute(Qt::WA_OutsideWSRange)) {
740         q->setAttribute(Qt::WA_OutsideWSRange, false);
741         needsShow = true;
742     }
743
744     if (q->isVisible()) {
745         if (!q->testAttribute(Qt::WA_DontShowOnScreen) && !q->testAttribute(Qt::WA_OutsideWSRange)) {
746             if (q->windowHandle()) {
747                 if (q->isWindow()) {
748                     q->windowHandle()->setGeometry(q->geometry());
749                 } else {
750                     QPoint posInNativeParent =  q->mapTo(q->nativeParentWidget(),QPoint());
751                     q->windowHandle()->setGeometry(QRect(posInNativeParent,r.size()));
752                 }
753                 const QWidgetBackingStore *bs = maybeBackingStore();
754                 if (bs->store) {
755                     if (isResize)
756                         bs->store->resize(r.size());
757                 }
758
759                 if (needsShow)
760                     show_sys();
761             } else {
762                 if (isMove && !isResize)
763                     moveRect(QRect(oldPos, olds), x - oldPos.x(), y - oldPos.y());
764                 else
765                     invalidateBuffer_resizeHelper(oldPos, olds);
766             }
767         }
768
769         if (isMove) {
770             QMoveEvent e(q->pos(), oldPos);
771             QApplication::sendEvent(q, &e);
772         }
773         if (isResize) {
774             QResizeEvent e(r.size(), olds);
775             QApplication::sendEvent(q, &e);
776             if (q->windowHandle())
777                 q->update();
778         }
779     } else { // not visible
780         if (isMove && q->pos() != oldPos)
781             q->setAttribute(Qt::WA_PendingMoveEvent, true);
782         if (isResize)
783             q->setAttribute(Qt::WA_PendingResizeEvent, true);
784     }
785
786 }
787
788 void QWidgetPrivate::setConstraints_sys()
789 {
790     Q_Q(QWidget);
791     if (extra && q->windowHandle()) {
792         QWindow *win = q->windowHandle();
793         QWindowPrivate *winp = qt_window_private(win);
794
795         winp->minimumSize = QSize(extra->minw, extra->minh);
796         winp->maximumSize = QSize(extra->maxw, extra->maxh);
797
798         if (extra->topextra) {
799             winp->baseSize = QSize(extra->topextra->basew, extra->topextra->baseh);
800             winp->sizeIncrement = QSize(extra->topextra->incw, extra->topextra->inch);
801         }
802
803         if (winp->platformWindow) {
804             fixPosIncludesFrame();
805             winp->platformWindow->propagateSizeHints();
806         }
807     }
808 }
809
810 void QWidgetPrivate::scroll_sys(int dx, int dy)
811 {
812     Q_Q(QWidget);
813     scrollChildren(dx, dy);
814     scrollRect(q->rect(), dx, dy);
815 }
816
817 void QWidgetPrivate::scroll_sys(int dx, int dy, const QRect &r)
818 {
819     scrollRect(r, dx, dy);
820 }
821
822 int QWidget::metric(PaintDeviceMetric m) const
823 {
824     Q_D(const QWidget);
825
826     QScreen *screen = 0;
827     if (QWidget *topLevel = window())
828         if (QWindow *topLevelWindow = topLevel->windowHandle()) {
829             QPlatformScreen *platformScreen = QPlatformScreen::platformScreenForWindow(topLevelWindow);
830             if (platformScreen)
831                 screen = platformScreen->screen();
832         }
833     if (!screen && QGuiApplication::primaryScreen())
834         screen = QGuiApplication::primaryScreen();
835
836     if (!screen) {
837         if (m == PdmDpiX || m == PdmDpiY)
838               return 72;
839         return QPaintDevice::metric(m);
840     }
841     int val;
842     if (m == PdmWidth) {
843         val = data->crect.width();
844     } else if (m == PdmWidthMM) {
845         val = data->crect.width() * screen->physicalSize().width() / screen->geometry().width();
846     } else if (m == PdmHeight) {
847         val = data->crect.height();
848     } else if (m == PdmHeightMM) {
849         val = data->crect.height() * screen->physicalSize().height() / screen->geometry().height();
850     } else if (m == PdmDepth) {
851         return screen->depth();
852     } else if (m == PdmDpiX) {
853         if (d->extra && d->extra->customDpiX)
854             return d->extra->customDpiX;
855         else if (d->parent)
856             return static_cast<QWidget *>(d->parent)->metric(m);
857         return qRound(screen->logicalDotsPerInchX());
858     } else if (m == PdmDpiY) {
859         if (d->extra && d->extra->customDpiY)
860             return d->extra->customDpiY;
861         else if (d->parent)
862             return static_cast<QWidget *>(d->parent)->metric(m);
863         return qRound(screen->logicalDotsPerInchY());
864     } else if (m == PdmPhysicalDpiX) {
865         return qRound(screen->physicalDotsPerInchX());
866     } else if (m == PdmPhysicalDpiY) {
867         return qRound(screen->physicalDotsPerInchY());
868     } else {
869         val = QPaintDevice::metric(m);// XXX
870     }
871     return val;
872 }
873
874 /*!
875     \preliminary
876
877     Returns the QPlatformWindow this widget will be drawn into.
878 */
879 QWindow *QWidget::windowHandle() const
880 {
881     Q_D(const QWidget);
882     QTLWExtra *extra = d->maybeTopData();
883     if (extra)
884         return extra->window;
885
886     return 0;
887 }
888
889 void QWidgetPrivate::createSysExtra()
890 {
891 }
892
893 void QWidgetPrivate::deleteSysExtra()
894 {
895
896 }
897
898 void QWidgetPrivate::createTLSysExtra()
899 {
900     Q_Q(QWidget);
901     extra->topextra->screenIndex = 0;
902     extra->topextra->window = 0;
903     if (q->testAttribute(Qt::WA_NativeWindow) || q->isWindow())
904         extra->topextra->window = new QWidgetWindow(q);
905 }
906
907 void QWidgetPrivate::deleteTLSysExtra()
908 {
909     if (extra && extra->topextra) {
910         //the toplevel might have a context with a "qglcontext associated with it. We need to
911         //delete the qglcontext before we delete the qplatformopenglcontext.
912         //One unfortunate thing about this is that we potentially create a glContext just to
913         //delete it straight afterwards.
914         if (extra->topextra->window) {
915             extra->topextra->window->destroy();
916         }
917         setWinId(0);
918         delete extra->topextra->window;
919         extra->topextra->window = 0;
920
921         extra->topextra->backingStoreTracker.destroy();
922         delete extra->topextra->backingStore;
923         extra->topextra->backingStore = 0;
924
925     }
926 }
927
928 void QWidgetPrivate::registerDropSite(bool on)
929 {
930     Q_UNUSED(on);
931 }
932
933 void QWidgetPrivate::setMask_sys(const QRegion &regionIn)
934 {
935     if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowMasks)) {
936         qWarning("%s: Not supported on %s.", Q_FUNC_INFO, qPrintable(QGuiApplication::platformName()));
937         return;
938     }
939     Q_Q(QWidget);
940     QRegion region = regionIn;
941     QWindow *window = q->windowHandle();
942     if (!window) {
943         if (QWidget *nativeParent = q->nativeParentWidget()) {
944             window = nativeParent->windowHandle();
945             region.translate(q->mapTo(nativeParent, QPoint(0, 0)));
946         }
947     }
948     if (window)
949         if (QPlatformWindow *platformWindow = window->handle())
950             platformWindow->setMask(region);
951 }
952
953 void QWidgetPrivate::updateFrameStrut()
954 {
955     Q_Q(QWidget);
956     if (q->data->fstrut_dirty) {
957         if (QTLWExtra *te = maybeTopData()) {
958             if (te->window) {
959                 if (const QPlatformWindow *pw = te->window->handle()) {
960                     const QMargins margins = pw->frameMargins();
961                     if (!margins.isNull()) {
962                         te->frameStrut.setCoords(margins.left(), margins.top(), margins.right(), margins.bottom());
963                         q->data->fstrut_dirty = false;
964                     }
965                 }
966             }
967         }
968     }
969 }
970
971 void QWidgetPrivate::setWindowOpacity_sys(qreal level)
972 {
973     Q_Q(QWidget);
974     if (q->windowHandle())
975         q->windowHandle()->setOpacity(level);
976 }
977
978 void QWidgetPrivate::setWSGeometry(bool dontShow, const QRect &oldRect)
979 {
980     Q_UNUSED(dontShow);
981     Q_UNUSED(oldRect);
982     // XXX
983 }
984
985 QPaintEngine *QWidget::paintEngine() const
986 {
987     qWarning("QWidget::paintEngine: Should no longer be called");
988     return 0; //##### @@@
989 }
990
991 void QWidgetPrivate::setModal_sys()
992 {
993     Q_Q(QWidget);
994     if (q->windowHandle())
995         q->windowHandle()->setWindowModality(q->windowModality());
996 }
997
998 #ifndef QT_NO_CURSOR
999 static inline void applyCursor(QWidget *w, QCursor c)
1000 {
1001     if (QWindow *window = w->windowHandle())
1002         if (const QScreen *screen = window->screen())
1003             if (QPlatformCursor *cursor = screen->handle()->cursor())
1004                 cursor->changeCursor(&c, window);
1005 }
1006
1007 void qt_qpa_set_cursor(QWidget *w, bool force)
1008 {
1009     if (!w->testAttribute(Qt::WA_WState_Created))
1010         return;
1011
1012     static QPointer<QWidget> lastUnderMouse = 0;
1013     if (force) {
1014         lastUnderMouse = w;
1015     } else if (lastUnderMouse) {
1016         const WId lastWinId = lastUnderMouse->effectiveWinId();
1017         const WId winId = w->effectiveWinId();
1018         if (lastWinId && lastWinId == winId)
1019             w = lastUnderMouse;
1020     } else if (!w->internalWinId()) {
1021         return; // The mouse is not under this widget, and it's not native, so don't change it.
1022     }
1023
1024     while (!w->internalWinId() && w->parentWidget() && !w->isWindow()
1025            && !w->testAttribute(Qt::WA_SetCursor))
1026         w = w->parentWidget();
1027
1028     QWidget *nativeParent = w;
1029     if (!w->internalWinId())
1030         nativeParent = w->nativeParentWidget();
1031     if (!nativeParent || !nativeParent->internalWinId())
1032         return;
1033
1034     if (w->isWindow() || w->testAttribute(Qt::WA_SetCursor)) {
1035         QCursor *oc = QApplication::overrideCursor();
1036         if (oc)
1037             applyCursor(nativeParent, *oc);
1038         else if (w->isEnabled())
1039             applyCursor(nativeParent, w->cursor());
1040         else
1041             // Enforce the windows behavior of clearing the cursor on
1042             // disabled widgets.
1043             applyCursor(nativeParent, Qt::ArrowCursor);
1044     } else {
1045         applyCursor(nativeParent, Qt::ArrowCursor);
1046     }
1047 }
1048 #endif //QT_NO_CURSOR 
1049
1050 QT_END_NAMESPACE