Update spec to build Qt 5.0
[profile/ivi/qtbase.git] / tests / auto / widgets / kernel / qwidget / tst_qwidget.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the test suite of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia.  For licensing terms and
14 ** conditions see http://qt.digia.com/licensing.  For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file.  Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights.  These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file.  Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42
43 #include <qboxlayout.h>
44 #include <qapplication.h>
45 #include <qbitmap.h>
46 #include <qdebug.h>
47 #include <qeventloop.h>
48 #include <qlabel.h>
49 #include <qlayout.h>
50 #include <qlineedit.h>
51 #include <qlistview.h>
52 #include <qmessagebox.h>
53 #include <qpainter.h>
54 #include <qpoint.h>
55 #include <qpushbutton.h>
56 #include <qstyle.h>
57 #include <qwidget.h>
58 #include <qstylefactory.h>
59 #include <qdesktopwidget.h>
60 #include <private/qwidget_p.h>
61 #include <private/qapplication_p.h>
62 #include <qcalendarwidget.h>
63 #include <qmainwindow.h>
64 #include <qdockwidget.h>
65 #include <qtoolbar.h>
66 #include <QtGui/qpaintengine.h>
67 #include <QtGui/qbackingstore.h>
68 #include <QtGui/qguiapplication.h>
69 #include <QtGui/qscreen.h>
70 #include <qmenubar.h>
71 #include <qcompleter.h>
72 #include <qtableview.h>
73 #include <qtreewidget.h>
74 #include <qabstractnativeeventfilter.h>
75 #include <qproxystyle.h>
76 #include <QtWidgets/QGraphicsView>
77 #include <QtWidgets/QGraphicsProxyWidget>
78
79 #include "../../../qtest-config.h"
80
81 #if defined(Q_OS_MAC)
82 #include "tst_qwidget_mac_helpers.h"  // Abstract the ObjC stuff out so not everyone must run an ObjC++ compile.
83 #endif
84
85 #include <QtTest/QtTest>
86
87 #ifdef Q_OS_WIN
88 #  include <QtCore/qt_windows.h>
89 #  include <QtGui/private/qguiapplication_p.h>
90 #include <qpa/qplatformnativeinterface.h>
91 #include <qpa/qplatformintegration.h>
92
93 static HWND winHandleOf(const QWidget *w)
94 {
95     static QPlatformNativeInterface *nativeInterface
96             = QGuiApplicationPrivate::instance()->platformIntegration()->nativeInterface();
97     if (void *handle = nativeInterface->nativeResourceForWindow("handle", w->window()->windowHandle()))
98         return reinterpret_cast<HWND>(handle);
99     qWarning() << "Cannot obtain native handle for " << w;
100     return 0;
101 }
102
103 #  ifdef Q_OS_WINCE
104 #    define Q_CHECK_PAINTEVENTS
105 #    ifdef Q_OS_WINCE_WM
106 #      include <qguifunctions_wince.h>
107 // taken from qguifunctions_wce.cpp
108 #      define SPI_GETPLATFORMTYPE 257
109 static bool qt_wince_is_platform(const QString &platformString) {
110     wchar_t tszPlatform[64];
111     if (SystemParametersInfo(SPI_GETPLATFORMTYPE,
112                              sizeof(tszPlatform)/sizeof(*tszPlatform),tszPlatform,0))
113       if (0 == _tcsicmp(reinterpret_cast<const wchar_t *> (platformString.utf16()), tszPlatform))
114             return true;
115     return false;
116 }
117 static inline bool qt_wince_is_smartphone() { return qt_wince_is_platform(QString::fromLatin1("Smartphone")); }
118 #    endif // Q_OS_WINCE_WM
119 #  else //  Q_OS_WINCE
120 #    define Q_CHECK_PAINTEVENTS \
121     if (::SwitchDesktop(::GetThreadDesktop(::GetCurrentThreadId())) == 0) \
122         QSKIP("desktop is not visible, this test would fail");
123 #  endif //  !Q_OS_WINCE
124 #else // Q_OS_WIN
125 #  define Q_CHECK_PAINTEVENTS
126 #endif // else Q_OS_WIN
127
128
129 #if defined(Q_OS_WINCE_WM)
130 #include <qguifunctions_wince.h>
131 // taken from qguifunctions_wce.cpp
132 #define SPI_GETPLATFORMTYPE 257
133 bool qt_wince_is_platform(const QString &platformString) {
134     wchar_t tszPlatform[64];
135     if (SystemParametersInfo(SPI_GETPLATFORMTYPE,
136                              sizeof(tszPlatform)/sizeof(*tszPlatform),tszPlatform,0))
137       if (0 == _tcsicmp(reinterpret_cast<const wchar_t *> (platformString.utf16()), tszPlatform))
138             return true;
139     return false;
140 }
141 bool qt_wince_is_smartphone() {
142        return qt_wince_is_platform(QString::fromLatin1("Smartphone"));
143 }
144 #endif
145
146 #ifdef Q_OS_MAC
147 #include <Security/AuthSession.h>
148 bool macHasAccessToWindowsServer()
149 {
150     SecuritySessionId mySession;
151     SessionAttributeBits sessionInfo;
152     SessionGetInfo(callerSecuritySession, &mySession, &sessionInfo);
153     return (sessionInfo & sessionHasGraphicAccess);
154 }
155 #endif
156
157 class tst_QWidget : public QObject
158 {
159     Q_OBJECT
160
161 public:
162     tst_QWidget();
163     virtual ~tst_QWidget();
164
165 public slots:
166     void initTestCase();
167     void cleanupTestCase();
168     void init();
169     void cleanup();
170 private slots:
171     void getSetCheck();
172     void fontPropagation();
173     void fontPropagation2();
174     void palettePropagation();
175     void palettePropagation2();
176     void enabledPropagation();
177     void ignoreKeyEventsWhenDisabled_QTBUG27417();
178     void properTabHandlingWhenDisabled_QTBUG27417();
179     void popupEnterLeave();
180 #ifndef QT_NO_DRAGANDDROP
181     void acceptDropsPropagation();
182 #endif
183     void isEnabledTo();
184     void visible();
185     void visible_setWindowOpacity();
186     void isVisibleTo();
187     void isHidden();
188     void fonts();
189     void mapFromAndTo_data();
190     void mapFromAndTo();
191     void focusChainOnHide();
192     void focusChainOnReparent();
193     void setTabOrder();
194 #ifdef Q_OS_WIN
195     void activation();
196 #endif
197     void reparent();
198     void windowState();
199     void showMaximized();
200     void showFullScreen();
201     void showMinimized();
202     void showMinimizedKeepsFocus();
203     void icon();
204     void hideWhenFocusWidgetIsChild();
205     void normalGeometry();
206     void setGeometry();
207 #ifndef Q_OS_WINCE
208     void windowOpacity();
209 #endif
210     void raise();
211     void lower();
212 #ifndef QT_MAC_USE_COCOA
213     void stackUnder();
214 #endif
215     void testContentsPropagation();
216     void saveRestoreGeometry();
217     void restoreVersion1Geometry_data();
218     void restoreVersion1Geometry();
219
220     void widgetAt();
221 #ifdef Q_OS_MAC
222     void sheetOpacity();
223     void setMask();
224 #endif
225     void optimizedResizeMove();
226     void optimizedResize_topLevel();
227     void resizeEvent();
228     void task110173();
229
230     void testDeletionInEventHandlers();
231
232     void childDeletesItsSibling();
233
234     void setMinimumSize();
235     void setMaximumSize();
236     void setFixedSize();
237
238     void ensureCreated();
239     void winIdChangeEvent();
240     void persistentWinId();
241     void showNativeChild();
242     void qobject_castInDestroyedSlot();
243
244     void showHideEvent_data();
245     void showHideEvent();
246
247     void lostUpdatesOnHide();
248
249     void update();
250     void isOpaque();
251
252 #ifndef Q_OS_MAC
253     void scroll();
254 #endif
255
256     // tests QWidget::setGeometry()
257     void setWindowGeometry_data();
258     void setWindowGeometry();
259
260     // tests QWidget::move() and resize()
261     void windowMoveResize_data();
262     void windowMoveResize();
263
264     void moveChild_data();
265     void moveChild();
266     void showAndMoveChild();
267
268 #ifndef QT_MAC_USE_COCOA
269     void subtractOpaqueSiblings();
270 #endif
271
272 #if defined (Q_OS_WIN) && !defined(Q_OS_WINCE)
273     void setGeometry_win();
274 #endif
275
276     void setLocale();
277     void deleteStyle();
278     void multipleToplevelFocusCheck();
279     void setFocus();
280 #ifndef QTEST_NO_CURSOR
281     void setCursor();
282 #endif
283     void setToolTip();
284     void testWindowIconChangeEventPropagation();
285
286     void minAndMaxSizeWithX11BypassWindowManagerHint();
287     void showHideShowX11();
288     void clean_qt_x11_enforce_cursor();
289
290     void childEvents();
291     void render();
292     void renderInvisible();
293     void renderWithPainter();
294     void render_task188133();
295     void render_task211796();
296     void render_task217815();
297 #ifndef Q_OS_WINCE
298     void render_windowOpacity();
299 #endif
300     void render_systemClip();
301     void render_systemClip2_data();
302     void render_systemClip2();
303     void render_systemClip3_data();
304     void render_systemClip3();
305     void render_task252837();
306     void render_worldTransform();
307
308     void setContentsMargins();
309
310     void moveWindowInShowEvent_data();
311     void moveWindowInShowEvent();
312
313     void repaintWhenChildDeleted();
314     void hideOpaqueChildWhileHidden();
315 #if !defined(Q_OS_WINCE)
316     void updateWhileMinimized();
317 #endif
318     void alienWidgets();
319     void adjustSize();
320     void adjustSize_data();
321     void updateGeometry();
322     void updateGeometry_data();
323     void sendUpdateRequestImmediately();
324     void doubleRepaint();
325     void resizeInPaintEvent();
326     void opaqueChildren();
327
328     void setMaskInResizeEvent();
329     void moveInResizeEvent();
330
331     void immediateRepaintAfterShow();
332     void immediateRepaintAfterInvalidateBuffer();
333
334     void effectiveWinId();
335     void effectiveWinId2();
336     void customDpi();
337     void customDpiProperty();
338
339     void quitOnCloseAttribute();
340     void moveRect();
341
342 #if defined (Q_OS_WIN)
343     void gdiPainting();
344     void paintOnScreenPossible();
345 #endif
346     void reparentStaticWidget();
347     void QTBUG6883_reparentStaticWidget2();
348
349     void translucentWidget();
350
351     void setClearAndResizeMask();
352     void maskedUpdate();
353 #ifndef QTEST_NO_CURSOR
354     void syntheticEnterLeave();
355     void taskQTBUG_4055_sendSyntheticEnterLeave();
356     void underMouse();
357     void taskQTBUG_27643_enterEvents();
358 #endif
359     void windowFlags();
360     void initialPosForDontShowOnScreenWidgets();
361     void updateOnDestroyedSignal();
362     void toplevelLineEditFocus();
363
364     void focusWidget_task254563();
365 #ifndef Q_OS_WINCE_WM
366     void rectOutsideCoordinatesLimit_task144779();
367 #endif
368     void setGraphicsEffect();
369
370 #ifdef QT_BUILD_INTERNAL
371     void destroyBackingStore();
372 #endif
373
374     void activateWindow();
375
376     void openModal_taskQTBUG_5804();
377
378     void focusProxyAndInputMethods();
379 #ifdef QT_BUILD_INTERNAL
380     void scrollWithoutBackingStore();
381 #endif
382
383     void taskQTBUG_7532_tabOrderWithFocusProxy();
384     void movedAndResizedAttributes();
385     void childAt();
386 #ifdef Q_OS_MAC
387     void childAt_unifiedToolBar();
388     void taskQTBUG_11373();
389 #endif
390     void taskQTBUG_17333_ResizeInfiniteRecursion();
391
392     void nativeChildFocus();
393     void grab();
394     void grabMouse();
395     void grabKeyboard();
396
397     void touchEventSynthesizedMouseEvent();
398
399     void styleSheetPropagation();
400
401     void destroyedSignal();
402 private:
403     bool ensureScreenSize(int width, int height);
404     QWidget *testWidget;
405
406     const QString m_platform;
407 };
408
409 bool tst_QWidget::ensureScreenSize(int width, int height)
410 {
411     QSize available;
412     available = QDesktopWidget().availableGeometry().size();
413     return (available.width() >= width && available.height() >= height);
414 }
415
416 // Testing get/set functions
417 void tst_QWidget::getSetCheck()
418 {
419     QWidget obj1;
420     QWidget child1(&obj1);
421     // QStyle * QWidget::style()
422     // void QWidget::setStyle(QStyle *)
423     QScopedPointer<QStyle> var1(QStyleFactory::create(QLatin1String("Windows")));
424     obj1.setStyle(var1.data());
425     QCOMPARE(static_cast<QStyle *>(var1.data()), obj1.style());
426     obj1.setStyle((QStyle *)0);
427     QVERIFY(var1.data() != obj1.style());
428     QVERIFY(0 != obj1.style()); // style can never be 0 for a widget
429
430     // int QWidget::minimumWidth()
431     // void QWidget::setMinimumWidth(int)
432     obj1.setMinimumWidth(0);
433     QCOMPARE(obj1.minimumWidth(), 0);
434     obj1.setMinimumWidth(INT_MIN);
435     QCOMPARE(obj1.minimumWidth(), 0); // A widgets width can never be less than 0
436     obj1.setMinimumWidth(INT_MAX);
437
438     child1.setMinimumWidth(0);
439     QCOMPARE(child1.minimumWidth(), 0);
440     child1.setMinimumWidth(INT_MIN);
441     QCOMPARE(child1.minimumWidth(), 0); // A widgets width can never be less than 0
442     child1.setMinimumWidth(INT_MAX);
443     QCOMPARE(child1.minimumWidth(), QWIDGETSIZE_MAX); // The largest minimum size should only be as big as the maximium
444
445     // int QWidget::minimumHeight()
446     // void QWidget::setMinimumHeight(int)
447     obj1.setMinimumHeight(0);
448     QCOMPARE(obj1.minimumHeight(), 0);
449     obj1.setMinimumHeight(INT_MIN);
450     QCOMPARE(obj1.minimumHeight(), 0); // A widgets height can never be less than 0
451     obj1.setMinimumHeight(INT_MAX);
452
453     child1.setMinimumHeight(0);
454     QCOMPARE(child1.minimumHeight(), 0);
455     child1.setMinimumHeight(INT_MIN);
456     QCOMPARE(child1.minimumHeight(), 0); // A widgets height can never be less than 0
457     child1.setMinimumHeight(INT_MAX);
458     QCOMPARE(child1.minimumHeight(), QWIDGETSIZE_MAX); // The largest minimum size should only be as big as the maximium
459
460     // int QWidget::maximumWidth()
461     // void QWidget::setMaximumWidth(int)
462     obj1.setMaximumWidth(0);
463     QCOMPARE(obj1.maximumWidth(), 0);
464     obj1.setMaximumWidth(INT_MIN);
465     QCOMPARE(obj1.maximumWidth(), 0); // A widgets width can never be less than 0
466     obj1.setMaximumWidth(INT_MAX);
467     QCOMPARE(obj1.maximumWidth(), QWIDGETSIZE_MAX); // QWIDGETSIZE_MAX is the abs max, not INT_MAX
468
469     // int QWidget::maximumHeight()
470     // void QWidget::setMaximumHeight(int)
471     obj1.setMaximumHeight(0);
472     QCOMPARE(obj1.maximumHeight(), 0);
473     obj1.setMaximumHeight(INT_MIN);
474     QCOMPARE(obj1.maximumHeight(), 0); // A widgets height can never be less than 0
475     obj1.setMaximumHeight(INT_MAX);
476     QCOMPARE(obj1.maximumHeight(), QWIDGETSIZE_MAX); // QWIDGETSIZE_MAX is the abs max, not INT_MAX
477
478     // back to normal
479     obj1.setMinimumWidth(0);
480     obj1.setMinimumHeight(0);
481     obj1.setMaximumWidth(QWIDGETSIZE_MAX);
482     obj1.setMaximumHeight(QWIDGETSIZE_MAX);
483
484     // const QPalette & QWidget::palette()
485     // void QWidget::setPalette(const QPalette &)
486     QPalette var6;
487     obj1.setPalette(var6);
488     QCOMPARE(var6, obj1.palette());
489     obj1.setPalette(QPalette());
490     QCOMPARE(QPalette(), obj1.palette());
491
492     // const QFont & QWidget::font()
493     // void QWidget::setFont(const QFont &)
494     QFont var7;
495     obj1.setFont(var7);
496     QCOMPARE(var7, obj1.font());
497     obj1.setFont(QFont());
498     QCOMPARE(QFont(), obj1.font());
499
500     // qreal QWidget::windowOpacity()
501     // void QWidget::setWindowOpacity(qreal)
502     obj1.setWindowOpacity(0.0);
503     QCOMPARE(0.0, obj1.windowOpacity());
504     obj1.setWindowOpacity(1.1f);
505     QCOMPARE(1.0, obj1.windowOpacity()); // 1.0 is the fullest opacity possible
506
507     // QWidget * QWidget::focusProxy()
508     // void QWidget::setFocusProxy(QWidget *)
509     {
510         QScopedPointer<QWidget> var9(new QWidget());
511         obj1.setFocusProxy(var9.data());
512         QCOMPARE(var9.data(), obj1.focusProxy());
513         obj1.setFocusProxy((QWidget *)0);
514         QCOMPARE((QWidget *)0, obj1.focusProxy());
515     }
516
517     // const QRect & QWidget::geometry()
518     // void QWidget::setGeometry(const QRect &)
519     qApp->processEvents();
520     QRect var10(10, 10, 100, 100);
521     obj1.setGeometry(var10);
522     qApp->processEvents();
523     qDebug() << obj1.geometry();
524     QCOMPARE(var10, obj1.geometry());
525     obj1.setGeometry(QRect(0,0,0,0));
526     qDebug() << obj1.geometry();
527     QCOMPARE(QRect(0,0,0,0), obj1.geometry());
528
529     // QLayout * QWidget::layout()
530     // void QWidget::setLayout(QLayout *)
531     QBoxLayout *var11 = new QBoxLayout(QBoxLayout::LeftToRight);
532     obj1.setLayout(var11);
533     QCOMPARE(static_cast<QLayout *>(var11), obj1.layout());
534     obj1.setLayout((QLayout *)0);
535     QCOMPARE(static_cast<QLayout *>(var11), obj1.layout()); // You cannot set a 0-pointer layout, that keeps the current
536     delete var11; // This will remove the layout from the widget
537     QCOMPARE((QLayout *)0, obj1.layout());
538
539     // bool QWidget::acceptDrops()
540     // void QWidget::setAcceptDrops(bool)
541     obj1.setAcceptDrops(false);
542     QCOMPARE(false, obj1.acceptDrops());
543     obj1.setAcceptDrops(true);
544     QCOMPARE(true, obj1.acceptDrops());
545
546     // bool QWidget::autoFillBackground()
547     // void QWidget::setAutoFillBackground(bool)
548     obj1.setAutoFillBackground(false);
549     QCOMPARE(false, obj1.autoFillBackground());
550     obj1.setAutoFillBackground(true);
551     QCOMPARE(true, obj1.autoFillBackground());
552
553     var1.reset();
554 #if defined (Q_OS_WIN) && !defined(Q_OS_WINCE)
555     obj1.setWindowFlags(Qt::FramelessWindowHint | Qt::WindowSystemMenuHint);
556     const HWND handle = reinterpret_cast<HWND>(obj1.winId());   // explicitly create window handle
557     QVERIFY(GetWindowLong(handle, GWL_STYLE) & WS_POPUP);
558 #endif
559 }
560
561 tst_QWidget::tst_QWidget() : m_platform(qApp->platformName().toLower())
562 {
563     QFont font;
564     font.setBold(true);
565     font.setPointSize(42);
566     qApp->setFont(font, "QPropagationTestWidget");
567
568     QPalette palette;
569     palette.setColor(QPalette::ToolTipBase, QColor(12, 13, 14));
570     palette.setColor(QPalette::Text, QColor(21, 22, 23));
571     qApp->setPalette(palette, "QPropagationTestWidget");
572
573     testWidget = 0;
574 }
575
576 tst_QWidget::~tst_QWidget()
577 {
578 }
579
580 class BezierViewer : public QWidget {
581 public:
582     explicit BezierViewer(QWidget* parent = 0);
583     void paintEvent( QPaintEvent* );
584     void setPoints( const QPolygonF& poly );
585 private:
586     QPolygonF points;
587
588 };
589
590 void tst_QWidget::initTestCase()
591 {
592 #ifdef Q_OS_WINCE //disable magic for WindowsCE
593     qApp->setAutoMaximizeThreshold(-1);
594 #endif
595   // Create the test class
596     testWidget = new BezierViewer;
597     testWidget->resize(200,200);
598     testWidget->show();
599     QVERIFY(QTest::qWaitForWindowExposed(testWidget));
600 }
601
602 void tst_QWidget::cleanupTestCase()
603 {
604     delete testWidget;
605     testWidget = 0;
606 }
607
608 void tst_QWidget::init()
609 {
610 // TODO: Add initialization code here.
611 // This will be executed immediately before each test is run.
612     testWidget->setFont(QFont());
613     testWidget->setPalette(QPalette());
614 }
615
616 void tst_QWidget::cleanup()
617 {
618 }
619
620 // Helper class...
621
622 BezierViewer::BezierViewer( QWidget* parent)
623         : QWidget( parent )
624 {
625     setObjectName(QLatin1String("TestWidget"));
626     setWindowTitle(objectName());
627     QPalette pal;
628     pal.setColor(backgroundRole(), Qt::white);
629     setPalette(pal);
630 }
631
632
633 void BezierViewer::setPoints( const QPolygonF& a )
634 {
635     points = a;
636 }
637
638 #include "private/qbezier_p.h"
639 void BezierViewer::paintEvent( QPaintEvent* )
640 {
641     if ( points.size() != 4 ) {
642 #if defined(QT_CHECK_RANGE)
643         qWarning( "QPolygon::bezier: The array must have 4 control points" );
644 #endif
645         return;
646     }
647
648     /* Calculate Bezier curve */
649     QPolygonF bezier = QBezier::fromPoints(points.at(0),points.at(1),points.at(2),points.at(3)).toPolygon();
650
651     QPainter painter( this );
652
653     /* Calculate scale to fit in window */
654     QRectF br = bezier.boundingRect() | points.boundingRect();
655     QRectF pr = rect();
656     int scl = qMax( qMin(pr.width()/br.width(), pr.height()/br.height()), qreal(1.) );
657     int border = scl-1;
658
659     /* Scale Bezier curve vertices */
660     for ( QPolygonF::Iterator it = bezier.begin(); it != bezier.end(); ++it ) {
661         it->setX( (it->x()-br.x()) * scl + border );
662         it->setY( (it->y()-br.y()) * scl + border );
663     }
664
665     /* Draw grid */
666     painter.setPen( Qt::lightGray );
667         int i;
668         for ( i = border; i <= pr.width(); i += scl ) {
669                 painter.drawLine( i, 0, i, pr.height() );
670     }
671     for ( int j = border; j <= pr.height(); j += scl ) {
672         painter.drawLine( 0, j, pr.width(), j );
673     }
674
675     /* Write number of vertices */
676     painter.setPen( Qt::red );
677     painter.setFont( QFont("Helvetica", 14, QFont::DemiBold, true ) );
678     QString caption;
679     caption.setNum( bezier.size() );
680     caption += QString::fromLatin1( " vertices" );
681     painter.drawText( 10, pr.height()-10, caption );
682
683     /* Draw Bezier curve */
684     painter.setPen( Qt::black );
685     painter.drawPolyline( bezier );
686
687     /* Scale and draw control points */
688     painter.setPen( Qt::darkGreen );
689     for ( QPolygonF::Iterator p1 = points.begin(); p1 != points.end(); ++p1 ) {
690         int x = (p1->x()-br.x()) * scl + border;
691         int y = (p1->y()-br.y()) * scl + border;
692         painter.drawLine( x-4, y-4, x+4, y+4 );
693         painter.drawLine( x+4, y-4, x-4, y+4 );
694     }
695
696     /* Draw vertices */
697     painter.setPen( Qt::red );
698     painter.setBrush( Qt::red );
699     for ( QPolygonF::Iterator p2 = bezier.begin(); p2 != bezier.end(); ++p2 )
700         painter.drawEllipse( p2->x()-1, p2->y()-1, 3, 3 );
701 }
702
703 void tst_QWidget::fontPropagation()
704 {
705     QFont font = testWidget->font();
706     QWidget* childWidget = new QWidget( testWidget );
707     childWidget->show();
708     QCOMPARE( font, childWidget->font() );
709
710     font.setBold( true );
711     testWidget->setFont( font );
712     QCOMPARE( font, testWidget->font() );
713     QCOMPARE( font, childWidget->font() );
714
715     QFont newFont = font;
716     newFont.setItalic( true );
717     childWidget->setFont( newFont );
718     QWidget* grandChildWidget = new QWidget( childWidget );
719     QCOMPARE( font, testWidget->font() );
720     QCOMPARE( newFont, grandChildWidget->font() );
721
722     font.setUnderline( true );
723     testWidget->setFont( font );
724
725     // the child and grand child should now have merged bold and
726     // underline
727     newFont.setUnderline( true );
728
729     QCOMPARE( newFont, childWidget->font() );
730     QCOMPARE( newFont, grandChildWidget->font() );
731
732     // make sure font propagation continues working after reparenting
733     font = testWidget->font();
734     font.setPointSize(font.pointSize() + 2);
735     testWidget->setFont(font);
736
737     QWidget *one   = new QWidget(testWidget);
738     QWidget *two   = new QWidget(one);
739     QWidget *three = new QWidget(two);
740     QWidget *four  = new QWidget(two);
741
742     four->setParent(three);
743     four->move(QPoint(0,0));
744
745     font.setPointSize(font.pointSize() + 2);
746     testWidget->setFont(font);
747
748     QCOMPARE(testWidget->font(), one->font());
749     QCOMPARE(one->font(), two->font());
750     QCOMPARE(two->font(), three->font());
751     QCOMPARE(three->font(), four->font());
752
753     QVERIFY(testWidget->testAttribute(Qt::WA_SetFont));
754     QVERIFY(! one->testAttribute(Qt::WA_SetFont));
755     QVERIFY(! two->testAttribute(Qt::WA_SetFont));
756     QVERIFY(! three->testAttribute(Qt::WA_SetFont));
757     QVERIFY(! four->testAttribute(Qt::WA_SetFont));
758
759     font.setPointSize(font.pointSize() + 2);
760     one->setFont(font);
761
762     QCOMPARE(one->font(), two->font());
763     QCOMPARE(two->font(), three->font());
764     QCOMPARE(three->font(), four->font());
765
766     QVERIFY(one->testAttribute(Qt::WA_SetFont));
767     QVERIFY(! two->testAttribute(Qt::WA_SetFont));
768     QVERIFY(! three->testAttribute(Qt::WA_SetFont));
769     QVERIFY(! four->testAttribute(Qt::WA_SetFont));
770
771     font.setPointSize(font.pointSize() + 2);
772     two->setFont(font);
773
774     QCOMPARE(two->font(), three->font());
775     QCOMPARE(three->font(), four->font());
776
777     QVERIFY(two->testAttribute(Qt::WA_SetFont));
778     QVERIFY(! three->testAttribute(Qt::WA_SetFont));
779     QVERIFY(! four->testAttribute(Qt::WA_SetFont));
780
781     font.setPointSize(font.pointSize() + 2);
782     three->setFont(font);
783
784     QCOMPARE(three->font(), four->font());
785
786     QVERIFY(three->testAttribute(Qt::WA_SetFont));
787     QVERIFY(! four->testAttribute(Qt::WA_SetFont));
788
789     font.setPointSize(font.pointSize() + 2);
790     four->setFont(font);
791
792     QVERIFY(four->testAttribute(Qt::WA_SetFont));
793 }
794
795 class QPropagationTestWidget : public QWidget
796 {
797     Q_OBJECT
798 public:
799     QPropagationTestWidget(QWidget *parent = 0)
800         : QWidget(parent)
801     { }
802 };
803
804 void tst_QWidget::fontPropagation2()
805 {
806     // ! Note, the code below is executed in tst_QWidget's constructor.
807     // QFont font;
808     // font.setBold(true);
809     // font.setPointSize(42);
810     // qApp->setFont(font, "QPropagationTestWidget");
811
812     QScopedPointer<QWidget> root(new QWidget);
813     root->setObjectName(QLatin1String("fontPropagation2"));
814     root->setWindowTitle(root->objectName());
815     root->resize(200, 200);
816
817     QWidget *child0 = new QWidget(root.data());
818     QWidget *child1 = new QWidget(child0);
819     QWidget *child2 = new QPropagationTestWidget(child1);
820     QWidget *child3 = new QWidget(child2);
821     QWidget *child4 = new QWidget(child3);
822     QWidget *child5 = new QWidget(child4);
823     root->show();
824
825     // Check that only the application fonts apply.
826     QCOMPARE(root->font(), QApplication::font());
827     QCOMPARE(child0->font(), QApplication::font());
828     QCOMPARE(child1->font(), QApplication::font());
829     QCOMPARE(child2->font().pointSize(), 42);
830     QVERIFY(child2->font().bold());
831     QCOMPARE(child3->font().pointSize(), 42);
832     QVERIFY(child3->font().bold());
833     QCOMPARE(child4->font().pointSize(), 42);
834     QVERIFY(child4->font().bold());
835     QCOMPARE(child5->font().pointSize(), 42);
836     QVERIFY(child5->font().bold());
837
838     // Set child0's font size to 15, and remove bold on child4.
839     QFont font;
840     font.setPointSize(15);
841     child0->setFont(font);
842     QFont unboldFont;
843     unboldFont.setBold(false);
844     child4->setFont(unboldFont);
845
846     // Check that the above settings propagate correctly.
847     QCOMPARE(root->font(), QApplication::font());
848     QCOMPARE(child0->font().pointSize(), 15);
849     QVERIFY(!child0->font().bold());
850     QCOMPARE(child1->font().pointSize(), 15);
851     QVERIFY(!child1->font().bold());
852     QCOMPARE(child2->font().pointSize(), 15);
853     QVERIFY(child2->font().bold());
854     QCOMPARE(child3->font().pointSize(), 15);
855     QVERIFY(child3->font().bold());
856     QCOMPARE(child4->font().pointSize(), 15);
857     QVERIFY(!child4->font().bold());
858     QCOMPARE(child5->font().pointSize(), 15);
859     QVERIFY(!child5->font().bold());
860
861     // Replace the app font for child2. Italic should propagate
862     // but the size should still be ignored. The previous bold
863     // setting is gone.
864     QFont italicSizeFont;
865     italicSizeFont.setItalic(true);
866     italicSizeFont.setPointSize(33);
867     qApp->setFont(italicSizeFont, "QPropagationTestWidget");
868
869     // Check that this propagates correctly.
870     QCOMPARE(root->font(), QApplication::font());
871     QCOMPARE(child0->font().pointSize(), 15);
872     QVERIFY(!child0->font().bold());
873     QVERIFY(!child0->font().italic());
874     QCOMPARE(child1->font().pointSize(), 15);
875     QVERIFY(!child1->font().bold());
876     QVERIFY(!child1->font().italic());
877     QCOMPARE(child2->font().pointSize(), 15);
878     QVERIFY(!child2->font().bold());
879     QVERIFY(child2->font().italic());
880     QCOMPARE(child3->font().pointSize(), 15);
881     QVERIFY(!child3->font().bold());
882     QVERIFY(child3->font().italic());
883     QCOMPARE(child4->font().pointSize(), 15);
884     QVERIFY(!child4->font().bold());
885     QVERIFY(child4->font().italic());
886     QCOMPARE(child5->font().pointSize(), 15);
887     QVERIFY(!child5->font().bold());
888     QVERIFY(child5->font().italic());
889 }
890
891 void tst_QWidget::palettePropagation()
892 {
893     QPalette palette = testWidget->palette();
894     QWidget* childWidget = new QWidget( testWidget );
895     childWidget->show();
896     QCOMPARE( palette, childWidget->palette() );
897
898     palette.setColor( QPalette::Base, Qt::red );
899     testWidget->setPalette( palette );
900     QCOMPARE( palette, testWidget->palette() );
901     QCOMPARE( palette, childWidget->palette() );
902
903     QPalette newPalette = palette;
904     newPalette.setColor( QPalette::Highlight, Qt::green );
905     childWidget->setPalette( newPalette );
906     QWidget* grandChildWidget = new QWidget( childWidget );
907     QCOMPARE( palette, testWidget->palette() );
908     QCOMPARE( newPalette, grandChildWidget->palette() );
909
910     palette.setColor( QPalette::Text, Qt::blue );
911     testWidget->setPalette( palette );
912
913     // the child and grand child should now have merged green
914     // highlight and blue text
915     newPalette.setColor( QPalette::Text, Qt::blue);
916
917     QCOMPARE( newPalette, childWidget->palette() );
918     QCOMPARE( newPalette, grandChildWidget->palette() );
919 }
920
921 void tst_QWidget::palettePropagation2()
922 {
923     // ! Note, the code below is executed in tst_QWidget's constructor.
924     // QPalette palette;
925     // font.setColor(QPalette::ToolTipBase, QColor(12, 13, 14));
926     // font.setColor(QPalette::Text, QColor(21, 22, 23));
927     // qApp->setPalette(palette, "QPropagationTestWidget");
928
929     QScopedPointer<QWidget> root(new QWidget);
930     root->setObjectName(QLatin1String("palettePropagation2"));
931     root->setWindowTitle(root->objectName());
932     root->resize(200, 200);
933     QWidget *child0 = new QWidget(root.data());
934     QWidget *child1 = new QWidget(child0);
935     QWidget *child2 = new QPropagationTestWidget(child1);
936     QWidget *child3 = new QWidget(child2);
937     QWidget *child4 = new QWidget(child3);
938     QWidget *child5 = new QWidget(child4);
939     root->show();
940     QVERIFY(QTest::qWaitForWindowExposed(root.data()));
941
942     // These colors are unlikely to be imposed on the default palette of
943     // QWidget ;-).
944     QColor sysPalText(21, 22, 23);
945     QColor sysPalToolTipBase(12, 13, 14);
946     QColor overridePalText(42, 43, 44);
947     QColor overridePalToolTipBase(45, 46, 47);
948     QColor sysPalButton(99, 98, 97);
949
950     // Check that only the application fonts apply.
951     QPalette appPal = QApplication::palette();
952     QCOMPARE(root->palette(), appPal);
953     QCOMPARE(child0->palette(), appPal);
954     QCOMPARE(child1->palette(), appPal);
955     QCOMPARE(child2->palette().color(QPalette::ToolTipBase), sysPalToolTipBase);
956     QCOMPARE(child2->palette().color(QPalette::Text), sysPalText);
957     QCOMPARE(child2->palette().color(QPalette::ToolTipText), appPal.color(QPalette::ToolTipText));
958     QCOMPARE(child3->palette().color(QPalette::ToolTipBase), sysPalToolTipBase);
959     QCOMPARE(child3->palette().color(QPalette::Text), sysPalText);
960     QCOMPARE(child3->palette().color(QPalette::ToolTipText), appPal.color(QPalette::ToolTipText));
961     QCOMPARE(child4->palette().color(QPalette::ToolTipBase), sysPalToolTipBase);
962     QCOMPARE(child4->palette().color(QPalette::Text), sysPalText);
963     QCOMPARE(child4->palette().color(QPalette::ToolTipText), appPal.color(QPalette::ToolTipText));
964     QCOMPARE(child5->palette().color(QPalette::ToolTipBase), sysPalToolTipBase);
965     QCOMPARE(child5->palette().color(QPalette::Text), sysPalText);
966     QCOMPARE(child5->palette().color(QPalette::ToolTipText), appPal.color(QPalette::ToolTipText));
967
968     // Set child0's Text, and set ToolTipBase on child4.
969     QPalette textPalette;
970     textPalette.setColor(QPalette::Text, overridePalText);
971     child0->setPalette(textPalette);
972     QPalette toolTipPalette;
973     toolTipPalette.setColor(QPalette::ToolTipBase, overridePalToolTipBase);
974     child4->setPalette(toolTipPalette);
975
976     // Check that the above settings propagate correctly.
977     QCOMPARE(root->palette(), appPal);
978     QCOMPARE(child0->palette().color(QPalette::Text), overridePalText);
979     QCOMPARE(child0->palette().color(QPalette::ToolTipBase), appPal.color(QPalette::ToolTipBase));
980     QCOMPARE(child0->palette().color(QPalette::ToolTipText), appPal.color(QPalette::ToolTipText));
981     QCOMPARE(child1->palette().color(QPalette::Text), overridePalText);
982     QCOMPARE(child1->palette().color(QPalette::ToolTipBase), appPal.color(QPalette::ToolTipBase));
983     QCOMPARE(child1->palette().color(QPalette::ToolTipText), appPal.color(QPalette::ToolTipText));
984     QCOMPARE(child2->palette().color(QPalette::Text), overridePalText);
985     QCOMPARE(child2->palette().color(QPalette::ToolTipBase), sysPalToolTipBase);
986     QCOMPARE(child2->palette().color(QPalette::ToolTipText), appPal.color(QPalette::ToolTipText));
987     QCOMPARE(child3->palette().color(QPalette::Text), overridePalText);
988     QCOMPARE(child3->palette().color(QPalette::ToolTipBase), sysPalToolTipBase);
989     QCOMPARE(child3->palette().color(QPalette::ToolTipText), appPal.color(QPalette::ToolTipText));
990     QCOMPARE(child4->palette().color(QPalette::Text), overridePalText);
991     QCOMPARE(child4->palette().color(QPalette::ToolTipBase), overridePalToolTipBase);
992     QCOMPARE(child4->palette().color(QPalette::ToolTipText), appPal.color(QPalette::ToolTipText));
993     QCOMPARE(child5->palette().color(QPalette::Text), overridePalText);
994     QCOMPARE(child5->palette().color(QPalette::ToolTipBase), overridePalToolTipBase);
995     QCOMPARE(child5->palette().color(QPalette::ToolTipText), appPal.color(QPalette::ToolTipText));
996
997     // Replace the app palette for child2. Button should propagate but Text
998     // should still be ignored. The previous ToolTipBase setting is gone.
999     QPalette buttonPalette;
1000     buttonPalette.setColor(QPalette::ToolTipText, sysPalButton);
1001     qApp->setPalette(buttonPalette, "QPropagationTestWidget");
1002
1003     // Check that the above settings propagate correctly.
1004     QCOMPARE(root->palette(), appPal);
1005     QCOMPARE(child0->palette().color(QPalette::Text), overridePalText);
1006     QCOMPARE(child0->palette().color(QPalette::ToolTipBase), appPal.color(QPalette::ToolTipBase));
1007     QCOMPARE(child0->palette().color(QPalette::ToolTipText), appPal.color(QPalette::ToolTipText));
1008     QCOMPARE(child1->palette().color(QPalette::Text), overridePalText);
1009     QCOMPARE(child1->palette().color(QPalette::ToolTipBase), appPal.color(QPalette::ToolTipBase));
1010     QCOMPARE(child1->palette().color(QPalette::ToolTipText), appPal.color(QPalette::ToolTipText));
1011     QCOMPARE(child2->palette().color(QPalette::Text), overridePalText);
1012     QCOMPARE(child2->palette().color(QPalette::ToolTipBase), appPal.color(QPalette::ToolTipBase));
1013     QCOMPARE(child2->palette().color(QPalette::ToolTipText), sysPalButton);
1014     QCOMPARE(child3->palette().color(QPalette::Text), overridePalText);
1015     QCOMPARE(child3->palette().color(QPalette::ToolTipBase), appPal.color(QPalette::ToolTipBase));
1016     QCOMPARE(child3->palette().color(QPalette::ToolTipText), sysPalButton);
1017     QCOMPARE(child4->palette().color(QPalette::Text), overridePalText);
1018     QCOMPARE(child4->palette().color(QPalette::ToolTipBase), overridePalToolTipBase);
1019     QCOMPARE(child4->palette().color(QPalette::ToolTipText), sysPalButton);
1020     QCOMPARE(child5->palette().color(QPalette::Text), overridePalText);
1021     QCOMPARE(child5->palette().color(QPalette::ToolTipBase), overridePalToolTipBase);
1022     QCOMPARE(child5->palette().color(QPalette::ToolTipText), sysPalButton);
1023 }
1024
1025 void tst_QWidget::enabledPropagation()
1026 {
1027     QWidget* childWidget = new QWidget( testWidget );
1028     childWidget->show();
1029     QVERIFY( testWidget->isEnabled() );
1030     QVERIFY( childWidget->isEnabled() );
1031
1032     testWidget->setEnabled( false );
1033     QVERIFY( !testWidget->isEnabled() );
1034     QVERIFY( !childWidget->isEnabled() );
1035
1036     testWidget->setDisabled( false );
1037     QVERIFY( testWidget->isEnabled() );
1038     QVERIFY( childWidget->isEnabled() );
1039
1040     QWidget* grandChildWidget = new QWidget( childWidget );
1041     QVERIFY( grandChildWidget->isEnabled() );
1042
1043     testWidget->setDisabled( true );
1044     QVERIFY( !testWidget->isEnabled() );
1045     QVERIFY( !childWidget->isEnabled() );
1046     QVERIFY( !grandChildWidget->isEnabled() );
1047
1048     grandChildWidget->setEnabled( false );
1049     testWidget->setEnabled( true );
1050     QVERIFY( testWidget->isEnabled() );
1051     QVERIFY( childWidget->isEnabled() );
1052     QVERIFY( !grandChildWidget->isEnabled() );
1053
1054     grandChildWidget->setEnabled( true );
1055     testWidget->setEnabled( false );
1056     childWidget->setDisabled( true );
1057     testWidget->setEnabled( true );
1058     QVERIFY( testWidget->isEnabled() );
1059     QVERIFY( !childWidget->isEnabled() );
1060     QVERIFY( !grandChildWidget->isEnabled() );
1061 }
1062
1063 void tst_QWidget::ignoreKeyEventsWhenDisabled_QTBUG27417()
1064 {
1065     QLineEdit lineEdit;
1066     lineEdit.setDisabled(true);
1067     lineEdit.show();
1068     QTest::keyClick(&lineEdit, Qt::Key_A);
1069     QTRY_VERIFY(lineEdit.text().isEmpty());
1070 }
1071
1072 void tst_QWidget::properTabHandlingWhenDisabled_QTBUG27417()
1073 {
1074     QWidget widget;
1075     QVBoxLayout *layout = new QVBoxLayout();
1076     QLineEdit *lineEdit = new QLineEdit();
1077     layout->addWidget(lineEdit);
1078     QLineEdit *lineEdit2 = new QLineEdit();
1079     layout->addWidget(lineEdit2);
1080     QLineEdit *lineEdit3 = new QLineEdit();
1081     layout->addWidget(lineEdit3);
1082     widget.setLayout(layout);
1083     widget.show();
1084
1085     lineEdit->setFocus();
1086     QTRY_VERIFY(lineEdit->hasFocus());
1087     QTest::keyClick(&widget, Qt::Key_Tab);
1088     QTRY_VERIFY(lineEdit2->hasFocus());
1089     QTest::keyClick(&widget, Qt::Key_Tab);
1090     QTRY_VERIFY(lineEdit3->hasFocus());
1091
1092     lineEdit2->setDisabled(true);
1093     lineEdit->setFocus();
1094     QTRY_VERIFY(lineEdit->hasFocus());
1095     QTest::keyClick(&widget, Qt::Key_Tab);
1096     QTRY_VERIFY(!lineEdit2->hasFocus());
1097     QVERIFY(lineEdit3->hasFocus());
1098 }
1099
1100 // Drag'n drop disabled in this build.
1101 #ifndef QT_NO_DRAGANDDROP
1102 void tst_QWidget::acceptDropsPropagation()
1103 {
1104     QWidget *childWidget = new QWidget(testWidget);
1105     childWidget->show();
1106     QVERIFY(!testWidget->acceptDrops());
1107     QVERIFY(!childWidget->acceptDrops());
1108
1109     testWidget->setAcceptDrops(true);
1110     QVERIFY(testWidget->acceptDrops());
1111     QVERIFY(!childWidget->acceptDrops());
1112     QVERIFY(childWidget->testAttribute(Qt::WA_DropSiteRegistered));
1113
1114     testWidget->setAcceptDrops(false);
1115     QVERIFY(!testWidget->acceptDrops());
1116     QVERIFY(!childWidget->acceptDrops());
1117     QVERIFY(!childWidget->testAttribute(Qt::WA_DropSiteRegistered));
1118
1119     QWidget *grandChildWidget = new QWidget(childWidget);
1120     QVERIFY(!grandChildWidget->acceptDrops());
1121     QVERIFY(!grandChildWidget->testAttribute(Qt::WA_DropSiteRegistered));
1122
1123     testWidget->setAcceptDrops(true);
1124     QVERIFY(testWidget->acceptDrops());
1125     QVERIFY(!childWidget->acceptDrops());
1126     QVERIFY(childWidget->testAttribute(Qt::WA_DropSiteRegistered));
1127     QVERIFY(!grandChildWidget->acceptDrops());
1128     QVERIFY(grandChildWidget->testAttribute(Qt::WA_DropSiteRegistered));
1129
1130     grandChildWidget->setAcceptDrops(true);
1131     testWidget->setAcceptDrops(false);
1132     QVERIFY(!testWidget->acceptDrops());
1133     QVERIFY(!childWidget->acceptDrops());
1134     QVERIFY(grandChildWidget->acceptDrops());
1135     QVERIFY(grandChildWidget->testAttribute(Qt::WA_DropSiteRegistered));
1136
1137     grandChildWidget->setAcceptDrops(false);
1138     QVERIFY(!grandChildWidget->testAttribute(Qt::WA_DropSiteRegistered));
1139     testWidget->setAcceptDrops(true);
1140     childWidget->setAcceptDrops(true);
1141     testWidget->setAcceptDrops(false);
1142     QVERIFY(!testWidget->acceptDrops());
1143     QVERIFY(childWidget->acceptDrops());
1144     QVERIFY(!grandChildWidget->acceptDrops());
1145     QVERIFY(grandChildWidget->testAttribute(Qt::WA_DropSiteRegistered));
1146 }
1147 #endif
1148
1149 void tst_QWidget::isEnabledTo()
1150 {
1151     QWidget* childWidget = new QWidget( testWidget );
1152     QWidget* grandChildWidget = new QWidget( childWidget );
1153
1154     QVERIFY( childWidget->isEnabledTo( testWidget ) );
1155     QVERIFY( grandChildWidget->isEnabledTo( testWidget ) );
1156
1157     childWidget->setEnabled( false );
1158     QVERIFY( !childWidget->isEnabledTo( testWidget ) );
1159     QVERIFY( grandChildWidget->isEnabledTo( childWidget ) );
1160     QVERIFY( !grandChildWidget->isEnabledTo( testWidget ) );
1161 }
1162
1163 void tst_QWidget::visible()
1164 {
1165     // Ensure that the testWidget is hidden for this test at the
1166     // start
1167
1168     testWidget->hide();
1169     QVERIFY( !testWidget->isVisible() );
1170     QWidget* childWidget = new QWidget( testWidget );
1171     QVERIFY( !childWidget->isVisible() );
1172
1173     testWidget->show();
1174     QVERIFY( testWidget->isVisible() );
1175     QVERIFY( childWidget->isVisible() );
1176
1177     QWidget* grandChildWidget = new QWidget( childWidget );
1178     QVERIFY( !grandChildWidget->isVisible() );
1179     grandChildWidget->show();
1180     QVERIFY( grandChildWidget->isVisible() );
1181
1182     grandChildWidget->hide();
1183     testWidget->hide();
1184     testWidget->show();
1185     QVERIFY( !grandChildWidget->isVisible() );
1186     QVERIFY( testWidget->isVisible() );
1187     QVERIFY( childWidget->isVisible() );
1188
1189     grandChildWidget->show();
1190     childWidget->hide();
1191     testWidget->hide();
1192     testWidget->show();
1193     QVERIFY( testWidget->isVisible() );
1194     QVERIFY( !childWidget->isVisible() );
1195     QVERIFY( !grandChildWidget->isVisible() );
1196
1197     grandChildWidget->show();
1198     QVERIFY( !grandChildWidget->isVisible() );
1199 }
1200
1201 void tst_QWidget::setLocale()
1202 {
1203     QWidget w;
1204     QCOMPARE(w.locale(), QLocale());
1205
1206     w.setLocale(QLocale::Italian);
1207     QCOMPARE(w.locale(), QLocale(QLocale::Italian));
1208
1209     QWidget child1(&w);
1210     QCOMPARE(child1.locale(), QLocale(QLocale::Italian));
1211
1212     w.unsetLocale();
1213     QCOMPARE(w.locale(), QLocale());
1214     QCOMPARE(child1.locale(), QLocale());
1215
1216     w.setLocale(QLocale::French);
1217     QCOMPARE(w.locale(), QLocale(QLocale::French));
1218     QCOMPARE(child1.locale(), QLocale(QLocale::French));
1219
1220     child1.setLocale(QLocale::Italian);
1221     QCOMPARE(w.locale(), QLocale(QLocale::French));
1222     QCOMPARE(child1.locale(), QLocale(QLocale::Italian));
1223
1224     child1.unsetLocale();
1225     QCOMPARE(w.locale(), QLocale(QLocale::French));
1226     QCOMPARE(child1.locale(), QLocale(QLocale::French));
1227
1228     QWidget child2;
1229     QCOMPARE(child2.locale(), QLocale());
1230     child2.setParent(&w);
1231     QCOMPARE(child2.locale(), QLocale(QLocale::French));
1232 }
1233
1234 void tst_QWidget::visible_setWindowOpacity()
1235 {
1236     testWidget->hide();
1237     QVERIFY( !testWidget->isVisible() );
1238     testWidget->setWindowOpacity(0.5);
1239 #ifdef Q_OS_WIN
1240     QVERIFY(!::IsWindowVisible(winHandleOf(testWidget)));
1241 #endif
1242     testWidget->setWindowOpacity(1.0);
1243 }
1244
1245 void tst_QWidget::isVisibleTo()
1246 {
1247     // Ensure that the testWidget is hidden for this test at the
1248     // start
1249
1250     testWidget->hide();
1251     QWidget* childWidget = new QWidget( testWidget );
1252     QVERIFY( childWidget->isVisibleTo( testWidget ) );
1253     childWidget->hide();
1254     QVERIFY( !childWidget->isVisibleTo( testWidget ) );
1255
1256     QWidget* grandChildWidget = new QWidget( childWidget );
1257     QVERIFY( !grandChildWidget->isVisibleTo( testWidget ) );
1258     QVERIFY( grandChildWidget->isVisibleTo( childWidget ) );
1259
1260     testWidget->show();
1261     childWidget->show();
1262
1263     QVERIFY( childWidget->isVisibleTo( testWidget ) );
1264     grandChildWidget->hide();
1265     QVERIFY( !grandChildWidget->isVisibleTo( childWidget ) );
1266     QVERIFY( !grandChildWidget->isVisibleTo( testWidget ) );
1267
1268 }
1269
1270 void tst_QWidget::isHidden()
1271 {
1272     // Ensure that the testWidget is hidden for this test at the
1273     // start
1274
1275     testWidget->hide();
1276     QVERIFY( testWidget->isHidden() );
1277     QWidget* childWidget = new QWidget( testWidget );
1278     QVERIFY( !childWidget->isHidden() );
1279
1280     testWidget->show();
1281     QVERIFY( !testWidget->isHidden() );
1282     QVERIFY( !childWidget->isHidden() );
1283
1284     QWidget* grandChildWidget = new QWidget( childWidget );
1285     QVERIFY( grandChildWidget->isHidden() );
1286     grandChildWidget->show();
1287     QVERIFY( !grandChildWidget->isHidden() );
1288
1289     grandChildWidget->hide();
1290     testWidget->hide();
1291     testWidget->show();
1292     QVERIFY( grandChildWidget->isHidden() );
1293     QVERIFY( !testWidget->isHidden() );
1294     QVERIFY( !childWidget->isHidden() );
1295
1296     grandChildWidget->show();
1297     childWidget->hide();
1298     testWidget->hide();
1299     testWidget->show();
1300     QVERIFY( !testWidget->isHidden() );
1301     QVERIFY( childWidget->isHidden() );
1302     QVERIFY( !grandChildWidget->isHidden() );
1303
1304     grandChildWidget->show();
1305     QVERIFY( !grandChildWidget->isHidden() );
1306 }
1307
1308 void tst_QWidget::fonts()
1309 {
1310     // Tests setFont(), ownFont() and unsetFont()
1311     QWidget* cleanTestWidget = new QWidget( testWidget );
1312     QFont originalFont = cleanTestWidget->font();
1313
1314     QVERIFY( !cleanTestWidget->testAttribute(Qt::WA_SetFont) );
1315     cleanTestWidget->setFont(QFont());
1316     QVERIFY( !cleanTestWidget->testAttribute(Qt::WA_SetFont) );
1317
1318     QFont newFont( "times", 18 );
1319     cleanTestWidget->setFont( newFont );
1320     newFont = newFont.resolve( testWidget->font() );
1321
1322     QVERIFY( cleanTestWidget->testAttribute(Qt::WA_SetFont) );
1323     QVERIFY( cleanTestWidget->font() == newFont );
1324
1325     cleanTestWidget->setFont(QFont());
1326     QVERIFY( !cleanTestWidget->testAttribute(Qt::WA_SetFont) );
1327     QVERIFY( cleanTestWidget->font() == originalFont );
1328 }
1329
1330 void tst_QWidget::mapFromAndTo_data()
1331 {
1332     QTest::addColumn<bool>("windowHidden");
1333     QTest::addColumn<bool>("subWindow1Hidden");
1334     QTest::addColumn<bool>("subWindow2Hidden");
1335     QTest::addColumn<bool>("subSubWindowHidden");
1336     QTest::addColumn<bool>("windowMinimized");
1337     QTest::addColumn<bool>("subWindow1Minimized");
1338
1339     QTest::newRow("window 1 sub1 1 sub2 1 subsub 1") << false << false << false << false << false << false;
1340     QTest::newRow("window 0 sub1 1 sub2 1 subsub 1") << true << false << false << false << false << false;
1341     QTest::newRow("window 1 sub1 0 sub2 1 subsub 1") << false << true << false << false << false << false;
1342     QTest::newRow("window 0 sub1 0 sub2 1 subsub 1") << true << true << false << false << false << false;
1343     QTest::newRow("window 1 sub1 1 sub2 0 subsub 1") << false << false << true << false << false << false;
1344     QTest::newRow("window 0 sub1 1 sub2 0 subsub 1") << true << false << true << false << false << false;
1345     QTest::newRow("window 1 sub1 0 sub2 0 subsub 1") << false << true << true << false << false << false;
1346     QTest::newRow("window 0 sub1 0 sub2 0 subsub 1") << true << true << true << false << false << false;
1347     QTest::newRow("window 1 sub1 1 sub2 1 subsub 0") << false << false << false << true << false << false;
1348     QTest::newRow("window 0 sub1 1 sub2 1 subsub 0") << true << false << false << true << false << false;
1349     QTest::newRow("window 1 sub1 0 sub2 1 subsub 0") << false << true << false << true << false << false;
1350     QTest::newRow("window 0 sub1 0 sub2 1 subsub 0") << true << true << false << true << false << false;
1351     QTest::newRow("window 1 sub1 1 sub2 0 subsub 0") << false << false << true << true << false << false;
1352     QTest::newRow("window 0 sub1 1 sub2 0 subsub 0") << true << false << true << true << false << false;
1353     QTest::newRow("window 1 sub1 0 sub2 0 subsub 0") << false << true << true << true << false << false;
1354     QTest::newRow("window 0 sub1 0 sub2 0 subsub 0") << true << true << true << true << false << false;
1355     QTest::newRow("window 1 sub1 1 sub2 1 subsub 1 windowMinimized") << false << false << false << false << true << false;
1356     QTest::newRow("window 0 sub1 1 sub2 1 subsub 1 windowMinimized") << true << false << false << false << true << false;
1357     QTest::newRow("window 1 sub1 0 sub2 1 subsub 1 windowMinimized") << false << true << false << false << true << false;
1358     QTest::newRow("window 0 sub1 0 sub2 1 subsub 1 windowMinimized") << true << true << false << false << true << false;
1359     QTest::newRow("window 1 sub1 1 sub2 0 subsub 1 windowMinimized") << false << false << true << false << true << false;
1360     QTest::newRow("window 0 sub1 1 sub2 0 subsub 1 windowMinimized") << true << false << true << false << true << false;
1361     QTest::newRow("window 1 sub1 0 sub2 0 subsub 1 windowMinimized") << false << true << true << false << true << false;
1362     QTest::newRow("window 0 sub1 0 sub2 0 subsub 1 windowMinimized") << true << true << true << false << true << false;
1363     QTest::newRow("window 1 sub1 1 sub2 1 subsub 0 windowMinimized") << false << false << false << true << true << false;
1364     QTest::newRow("window 0 sub1 1 sub2 1 subsub 0 windowMinimized") << true << false << false << true << true << false;
1365     QTest::newRow("window 1 sub1 0 sub2 1 subsub 0 windowMinimized") << false << true << false << true << true << false;
1366     QTest::newRow("window 0 sub1 0 sub2 1 subsub 0 windowMinimized") << true << true << false << true << true << false;
1367     QTest::newRow("window 1 sub1 1 sub2 0 subsub 0 windowMinimized") << false << false << true << true << true << false;
1368     QTest::newRow("window 0 sub1 1 sub2 0 subsub 0 windowMinimized") << true << false << true << true << true << false;
1369     QTest::newRow("window 1 sub1 0 sub2 0 subsub 0 windowMinimized") << false << true << true << true << true << false;
1370     QTest::newRow("window 0 sub1 0 sub2 0 subsub 0 windowMinimized") << true << true << true << true << true << false;
1371     QTest::newRow("window 1 sub1 1 sub2 1 subsub 1 subWindow1Minimized") << false << false << false << false << false << true;
1372     QTest::newRow("window 0 sub1 1 sub2 1 subsub 1 subWindow1Minimized") << true << false << false << false << false << true;
1373     QTest::newRow("window 1 sub1 0 sub2 1 subsub 1 subWindow1Minimized") << false << true << false << false << false << true;
1374     QTest::newRow("window 0 sub1 0 sub2 1 subsub 1 subWindow1Minimized") << true << true << false << false << false << true;
1375     QTest::newRow("window 1 sub1 1 sub2 0 subsub 1 subWindow1Minimized") << false << false << true << false << false << true;
1376     QTest::newRow("window 0 sub1 1 sub2 0 subsub 1 subWindow1Minimized") << true << false << true << false << false << true;
1377     QTest::newRow("window 1 sub1 0 sub2 0 subsub 1 subWindow1Minimized") << false << true << true << false << false << true;
1378     QTest::newRow("window 0 sub1 0 sub2 0 subsub 1 subWindow1Minimized") << true << true << true << false << false << true;
1379     QTest::newRow("window 1 sub1 1 sub2 1 subsub 0 subWindow1Minimized") << false << false << false << true << false << true;
1380     QTest::newRow("window 0 sub1 1 sub2 1 subsub 0 subWindow1Minimized") << true << false << false << true << false << true;
1381     QTest::newRow("window 1 sub1 0 sub2 1 subsub 0 subWindow1Minimized") << false << true << false << true << false << true;
1382     QTest::newRow("window 0 sub1 0 sub2 1 subsub 0 subWindow1Minimized") << true << true << false << true << false << true;
1383     QTest::newRow("window 1 sub1 1 sub2 0 subsub 0 subWindow1Minimized") << false << false << true << true << false << true;
1384     QTest::newRow("window 0 sub1 1 sub2 0 subsub 0 subWindow1Minimized") << true << false << true << true << false << true;
1385     QTest::newRow("window 1 sub1 0 sub2 0 subsub 0 subWindow1Minimized") << false << true << true << true << false << true;
1386     QTest::newRow("window 0 sub1 0 sub2 0 subsub 0 subWindow1Minimized") << true << true << true << true << false << true;
1387
1388
1389 }
1390
1391 void tst_QWidget::mapFromAndTo()
1392 {
1393     QFETCH(bool, windowHidden);
1394     QFETCH(bool, subWindow1Hidden);
1395     QFETCH(bool, subWindow2Hidden);
1396     QFETCH(bool, subSubWindowHidden);
1397     QFETCH(bool, windowMinimized);
1398     QFETCH(bool, subWindow1Minimized);
1399
1400     // create a toplevel and two overlapping siblings
1401     QWidget window;
1402     window.setObjectName(QStringLiteral("mapFromAndTo"));
1403     window.setWindowTitle(window.objectName());
1404     window.setWindowFlags(window.windowFlags() | Qt::X11BypassWindowManagerHint);
1405     QWidget *subWindow1 = new QWidget(&window);
1406     QWidget *subWindow2 = new QWidget(&window);
1407     QWidget *subSubWindow = new QWidget(subWindow1);
1408
1409     // set their geometries
1410     window.setGeometry(100, 100, 100, 100);
1411     subWindow1->setGeometry(50, 50, 100, 100);
1412     subWindow2->setGeometry(75, 75, 100, 100);
1413     subSubWindow->setGeometry(10, 10, 10, 10);
1414
1415 #if !defined (Q_OS_WINCE) //still no proper minimizing
1416     //update visibility
1417     if (windowMinimized) {
1418         if (!windowHidden) {
1419             window.showMinimized();
1420             QVERIFY(window.isMinimized());
1421         }
1422     } else {
1423         window.setVisible(!windowHidden);
1424     }
1425     if (subWindow1Minimized) {
1426         subWindow1->hide();
1427         subWindow1->showMinimized();
1428         QVERIFY(subWindow1->isMinimized());
1429     } else {
1430         subWindow1->setVisible(!subWindow1Hidden);
1431     }
1432 #else
1433     Q_UNUSED(windowHidden);
1434     Q_UNUSED(subWindow1Hidden);
1435     Q_UNUSED(windowMinimized);
1436     Q_UNUSED(subWindow1Minimized);
1437 #endif
1438
1439     subWindow2->setVisible(!subWindow2Hidden);
1440     subSubWindow->setVisible(!subSubWindowHidden);
1441
1442     // window
1443     QCOMPARE(window.mapToGlobal(QPoint(0, 0)), QPoint(100, 100));
1444     QCOMPARE(window.mapToGlobal(QPoint(10, 0)), QPoint(110, 100));
1445     QCOMPARE(window.mapToGlobal(QPoint(0, 10)), QPoint(100, 110));
1446     QCOMPARE(window.mapToGlobal(QPoint(-10, 0)), QPoint(90, 100));
1447     QCOMPARE(window.mapToGlobal(QPoint(0, -10)), QPoint(100, 90));
1448     QCOMPARE(window.mapToGlobal(QPoint(100, 100)), QPoint(200, 200));
1449     QCOMPARE(window.mapToGlobal(QPoint(110, 100)), QPoint(210, 200));
1450     QCOMPARE(window.mapToGlobal(QPoint(100, 110)), QPoint(200, 210));
1451     QCOMPARE(window.mapFromGlobal(QPoint(100, 100)), QPoint(0, 0));
1452     QCOMPARE(window.mapFromGlobal(QPoint(110, 100)), QPoint(10, 0));
1453     QCOMPARE(window.mapFromGlobal(QPoint(100, 110)), QPoint(0, 10));
1454     QCOMPARE(window.mapFromGlobal(QPoint(90, 100)), QPoint(-10, 0));
1455     QCOMPARE(window.mapFromGlobal(QPoint(100, 90)), QPoint(0, -10));
1456     QCOMPARE(window.mapFromGlobal(QPoint(200, 200)), QPoint(100, 100));
1457     QCOMPARE(window.mapFromGlobal(QPoint(210, 200)), QPoint(110, 100));
1458     QCOMPARE(window.mapFromGlobal(QPoint(200, 210)), QPoint(100, 110));
1459     QCOMPARE(window.mapToParent(QPoint(0, 0)), QPoint(100, 100));
1460     QCOMPARE(window.mapToParent(QPoint(10, 0)), QPoint(110, 100));
1461     QCOMPARE(window.mapToParent(QPoint(0, 10)), QPoint(100, 110));
1462     QCOMPARE(window.mapToParent(QPoint(-10, 0)), QPoint(90, 100));
1463     QCOMPARE(window.mapToParent(QPoint(0, -10)), QPoint(100, 90));
1464     QCOMPARE(window.mapToParent(QPoint(100, 100)), QPoint(200, 200));
1465     QCOMPARE(window.mapToParent(QPoint(110, 100)), QPoint(210, 200));
1466     QCOMPARE(window.mapToParent(QPoint(100, 110)), QPoint(200, 210));
1467     QCOMPARE(window.mapFromParent(QPoint(100, 100)), QPoint(0, 0));
1468     QCOMPARE(window.mapFromParent(QPoint(110, 100)), QPoint(10, 0));
1469     QCOMPARE(window.mapFromParent(QPoint(100, 110)), QPoint(0, 10));
1470     QCOMPARE(window.mapFromParent(QPoint(90, 100)), QPoint(-10, 0));
1471     QCOMPARE(window.mapFromParent(QPoint(100, 90)), QPoint(0, -10));
1472     QCOMPARE(window.mapFromParent(QPoint(200, 200)), QPoint(100, 100));
1473     QCOMPARE(window.mapFromParent(QPoint(210, 200)), QPoint(110, 100));
1474     QCOMPARE(window.mapFromParent(QPoint(200, 210)), QPoint(100, 110));
1475
1476     // first subwindow
1477     QCOMPARE(subWindow1->mapToGlobal(QPoint(0, 0)), QPoint(150, 150));
1478     QCOMPARE(subWindow1->mapToGlobal(QPoint(10, 0)), QPoint(160, 150));
1479     QCOMPARE(subWindow1->mapToGlobal(QPoint(0, 10)), QPoint(150, 160));
1480     QCOMPARE(subWindow1->mapToGlobal(QPoint(-10, 0)), QPoint(140, 150));
1481     QCOMPARE(subWindow1->mapToGlobal(QPoint(0, -10)), QPoint(150, 140));
1482     QCOMPARE(subWindow1->mapToGlobal(QPoint(100, 100)), QPoint(250, 250));
1483     QCOMPARE(subWindow1->mapToGlobal(QPoint(110, 100)), QPoint(260, 250));
1484     QCOMPARE(subWindow1->mapToGlobal(QPoint(100, 110)), QPoint(250, 260));
1485     QCOMPARE(subWindow1->mapFromGlobal(QPoint(150, 150)), QPoint(0, 0));
1486     QCOMPARE(subWindow1->mapFromGlobal(QPoint(160, 150)), QPoint(10, 0));
1487     QCOMPARE(subWindow1->mapFromGlobal(QPoint(150, 160)), QPoint(0, 10));
1488     QCOMPARE(subWindow1->mapFromGlobal(QPoint(140, 150)), QPoint(-10, 0));
1489     QCOMPARE(subWindow1->mapFromGlobal(QPoint(150, 140)), QPoint(0, -10));
1490     QCOMPARE(subWindow1->mapFromGlobal(QPoint(250, 250)), QPoint(100, 100));
1491     QCOMPARE(subWindow1->mapFromGlobal(QPoint(260, 250)), QPoint(110, 100));
1492     QCOMPARE(subWindow1->mapFromGlobal(QPoint(250, 260)), QPoint(100, 110));
1493     QCOMPARE(subWindow1->mapToParent(QPoint(0, 0)), QPoint(50, 50));
1494     QCOMPARE(subWindow1->mapToParent(QPoint(10, 0)), QPoint(60, 50));
1495     QCOMPARE(subWindow1->mapToParent(QPoint(0, 10)), QPoint(50, 60));
1496     QCOMPARE(subWindow1->mapToParent(QPoint(-10, 0)), QPoint(40, 50));
1497     QCOMPARE(subWindow1->mapToParent(QPoint(0, -10)), QPoint(50, 40));
1498     QCOMPARE(subWindow1->mapToParent(QPoint(100, 100)), QPoint(150, 150));
1499     QCOMPARE(subWindow1->mapToParent(QPoint(110, 100)), QPoint(160, 150));
1500     QCOMPARE(subWindow1->mapToParent(QPoint(100, 110)), QPoint(150, 160));
1501     QCOMPARE(subWindow1->mapFromParent(QPoint(50, 50)), QPoint(0, 0));
1502     QCOMPARE(subWindow1->mapFromParent(QPoint(60, 50)), QPoint(10, 0));
1503     QCOMPARE(subWindow1->mapFromParent(QPoint(50, 60)), QPoint(0, 10));
1504     QCOMPARE(subWindow1->mapFromParent(QPoint(40, 50)), QPoint(-10, 0));
1505     QCOMPARE(subWindow1->mapFromParent(QPoint(50, 40)), QPoint(0, -10));
1506     QCOMPARE(subWindow1->mapFromParent(QPoint(150, 150)), QPoint(100, 100));
1507     QCOMPARE(subWindow1->mapFromParent(QPoint(160, 150)), QPoint(110, 100));
1508     QCOMPARE(subWindow1->mapFromParent(QPoint(150, 160)), QPoint(100, 110));
1509
1510     // subsubwindow
1511     QCOMPARE(subSubWindow->mapToGlobal(QPoint(0, 0)), QPoint(160, 160));
1512     QCOMPARE(subSubWindow->mapToGlobal(QPoint(10, 0)), QPoint(170, 160));
1513     QCOMPARE(subSubWindow->mapToGlobal(QPoint(0, 10)), QPoint(160, 170));
1514     QCOMPARE(subSubWindow->mapToGlobal(QPoint(-10, 0)), QPoint(150, 160));
1515     QCOMPARE(subSubWindow->mapToGlobal(QPoint(0, -10)), QPoint(160, 150));
1516     QCOMPARE(subSubWindow->mapToGlobal(QPoint(100, 100)), QPoint(260, 260));
1517     QCOMPARE(subSubWindow->mapToGlobal(QPoint(110, 100)), QPoint(270, 260));
1518     QCOMPARE(subSubWindow->mapToGlobal(QPoint(100, 110)), QPoint(260, 270));
1519     QCOMPARE(subSubWindow->mapFromGlobal(QPoint(160, 160)), QPoint(0, 0));
1520     QCOMPARE(subSubWindow->mapFromGlobal(QPoint(170, 160)), QPoint(10, 0));
1521     QCOMPARE(subSubWindow->mapFromGlobal(QPoint(160, 170)), QPoint(0, 10));
1522     QCOMPARE(subSubWindow->mapFromGlobal(QPoint(150, 160)), QPoint(-10, 0));
1523     QCOMPARE(subSubWindow->mapFromGlobal(QPoint(160, 150)), QPoint(0, -10));
1524     QCOMPARE(subSubWindow->mapFromGlobal(QPoint(260, 260)), QPoint(100, 100));
1525     QCOMPARE(subSubWindow->mapFromGlobal(QPoint(270, 260)), QPoint(110, 100));
1526     QCOMPARE(subSubWindow->mapFromGlobal(QPoint(260, 270)), QPoint(100, 110));
1527     QCOMPARE(subSubWindow->mapToParent(QPoint(0, 0)), QPoint(10, 10));
1528     QCOMPARE(subSubWindow->mapToParent(QPoint(10, 0)), QPoint(20, 10));
1529     QCOMPARE(subSubWindow->mapToParent(QPoint(0, 10)), QPoint(10, 20));
1530     QCOMPARE(subSubWindow->mapToParent(QPoint(-10, 0)), QPoint(0, 10));
1531     QCOMPARE(subSubWindow->mapToParent(QPoint(0, -10)), QPoint(10, 0));
1532     QCOMPARE(subSubWindow->mapToParent(QPoint(100, 100)), QPoint(110, 110));
1533     QCOMPARE(subSubWindow->mapToParent(QPoint(110, 100)), QPoint(120, 110));
1534     QCOMPARE(subSubWindow->mapToParent(QPoint(100, 110)), QPoint(110, 120));
1535     QCOMPARE(subSubWindow->mapFromParent(QPoint(10, 10)), QPoint(0, 0));
1536     QCOMPARE(subSubWindow->mapFromParent(QPoint(20, 10)), QPoint(10, 0));
1537     QCOMPARE(subSubWindow->mapFromParent(QPoint(10, 20)), QPoint(0, 10));
1538     QCOMPARE(subSubWindow->mapFromParent(QPoint(0, 10)), QPoint(-10, 0));
1539     QCOMPARE(subSubWindow->mapFromParent(QPoint(10, 0)), QPoint(0, -10));
1540     QCOMPARE(subSubWindow->mapFromParent(QPoint(110, 110)), QPoint(100, 100));
1541     QCOMPARE(subSubWindow->mapFromParent(QPoint(120, 110)), QPoint(110, 100));
1542     QCOMPARE(subSubWindow->mapFromParent(QPoint(110, 120)), QPoint(100, 110));
1543 }
1544
1545 void tst_QWidget::focusChainOnReparent()
1546 {
1547     QWidget window;
1548     QWidget *child1 = new QWidget(&window);
1549     QWidget *child2 = new QWidget(&window);
1550     QWidget *child3 = new QWidget(&window);
1551     QWidget *child21 = new QWidget(child2);
1552     QWidget *child22 = new QWidget(child2);
1553     QWidget *child4 = new QWidget(&window);
1554
1555     QWidget *expectedOriginalChain[8] = {&window, child1,  child2,  child3,  child21, child22, child4, &window};
1556     QWidget *w = &window;
1557     for (int i = 0; i <8; ++i) {
1558         QCOMPARE(w, expectedOriginalChain[i]);
1559         w = w->nextInFocusChain();
1560     }
1561     for (int i = 7; i >= 0; --i) {
1562         w = w->previousInFocusChain();
1563         QCOMPARE(w, expectedOriginalChain[i]);
1564     }
1565
1566     QWidget window2;
1567     child2->setParent(&window2);
1568
1569     QWidget *expectedNewChain[5] = {&window2, child2,  child21, child22, &window2};
1570     w = &window2;
1571     for (int i = 0; i <5; ++i) {
1572         QCOMPARE(w, expectedNewChain[i]);
1573         w = w->nextInFocusChain();
1574     }
1575     for (int i = 4; i >= 0; --i) {
1576         w = w->previousInFocusChain();
1577         QCOMPARE(w, expectedNewChain[i]);
1578     }
1579
1580     QWidget *expectedOldChain[5] = {&window, child1,  child3, child4, &window};
1581     w = &window;
1582     for (int i = 0; i <5; ++i) {
1583         QCOMPARE(w, expectedOldChain[i]);
1584         w = w->nextInFocusChain();
1585     }
1586     for (int i = 4; i >= 0; --i) {
1587         w = w->previousInFocusChain();
1588         QCOMPARE(w, expectedOldChain[i]);
1589     }
1590 }
1591
1592
1593 void tst_QWidget::focusChainOnHide()
1594 {
1595     testWidget->hide(); // We do not want to get disturbed by other widgets
1596     // focus should move to the next widget in the focus chain when we hide it.
1597     QScopedPointer<QWidget> parent(new QWidget());
1598     parent->setObjectName(QLatin1String("focusChainOnHide"));
1599     parent->resize(200, 200);
1600     parent->setWindowTitle(parent->objectName());
1601     parent->setFocusPolicy(Qt::StrongFocus);
1602     QWidget *child = new QWidget(parent.data());
1603     child->setObjectName(QLatin1String("child"));
1604     child->setFocusPolicy(Qt::StrongFocus);
1605     QWidget::setTabOrder(child, parent.data());
1606
1607     parent->show();
1608     qApp->setActiveWindow(parent->window());
1609     child->activateWindow();
1610     child->setFocus();
1611     qApp->processEvents();
1612
1613     QTRY_COMPARE(child->hasFocus(), true);
1614     child->hide();
1615     qApp->processEvents();
1616
1617     QTRY_COMPARE(parent->hasFocus(), true);
1618     QCOMPARE(parent.data(), qApp->focusWidget());
1619
1620     testWidget->show(); //don't disturb later tests
1621 }
1622
1623 class Container : public QWidget
1624 {
1625 public:
1626     QVBoxLayout* box;
1627
1628     Container()
1629     {
1630         box = new QVBoxLayout(this);
1631         //(new QVBoxLayout(this))->setAutoAdd(true);
1632     }
1633
1634     void tab()
1635     {
1636         focusNextPrevChild(true);
1637     }
1638
1639     void backTab()
1640     {
1641         focusNextPrevChild(false);
1642     }
1643 };
1644
1645 class Composite : public QFrame
1646 {
1647 public:
1648     Composite(QWidget* parent = 0, const char* name = 0)
1649         : QFrame(parent)
1650     {
1651         setObjectName(name);
1652         //QHBoxLayout* hbox = new QHBoxLayout(this, 2, 0);
1653         //hbox->setAutoAdd(true);
1654         QHBoxLayout* hbox = new QHBoxLayout(this);
1655
1656         lineEdit = new QLineEdit(this);
1657         hbox->addWidget(lineEdit);
1658
1659         button = new QPushButton(this);
1660         hbox->addWidget(button);
1661         button->setFocusPolicy( Qt::NoFocus );
1662
1663         setFocusProxy( lineEdit );
1664         setFocusPolicy( Qt::StrongFocus );
1665
1666         setTabOrder(lineEdit, button);
1667     }
1668
1669 private:
1670     QLineEdit* lineEdit;
1671     QPushButton* button;
1672 };
1673
1674 #define NUM_WIDGETS 4
1675
1676 void tst_QWidget::setTabOrder()
1677 {
1678     QTest::qWait(100);
1679
1680     Container container;
1681     container.setObjectName("setTabOrder");
1682     container.setWindowTitle(container.objectName());
1683
1684     Composite* comp[NUM_WIDGETS];
1685
1686     QLineEdit *firstEdit = new QLineEdit(&container);
1687     container.box->addWidget(firstEdit);
1688
1689     int i = 0;
1690     for(i = 0; i < NUM_WIDGETS; i++) {
1691         comp[i] = new Composite(&container);
1692         container.box->addWidget(comp[i]);
1693     }
1694
1695     QLineEdit *lastEdit = new QLineEdit(&container);
1696     container.box->addWidget(lastEdit);
1697
1698     container.setTabOrder(lastEdit, comp[NUM_WIDGETS-1]);
1699     for(i = NUM_WIDGETS-1; i > 0; i--) {
1700         container.setTabOrder(comp[i], comp[i-1]);
1701     }
1702     container.setTabOrder(comp[0], firstEdit);
1703
1704     int current = NUM_WIDGETS-1;
1705     lastEdit->setFocus();
1706
1707     container.show();
1708     container.activateWindow();
1709     qApp->setActiveWindow(&container);
1710     QVERIFY(QTest::qWaitForWindowActive(&container));
1711
1712     QTRY_VERIFY(lastEdit->hasFocus());
1713     container.tab();
1714     do {
1715         QVERIFY(comp[current]->focusProxy()->hasFocus());
1716         container.tab();
1717         current--;
1718     } while (current >= 0);
1719
1720     QVERIFY(firstEdit->hasFocus());
1721 }
1722
1723 #ifdef Q_OS_WIN
1724 void tst_QWidget::activation()
1725 {
1726     Q_CHECK_PAINTEVENTS
1727
1728 #if defined(Q_OS_WINCE)
1729     int waitTime = 1000;
1730 #else
1731     int waitTime = 100;
1732 #endif
1733
1734 #ifdef Q_OS_WINCE
1735     qApp->processEvents();
1736 #endif
1737     QWidget widget1;
1738     widget1.setObjectName("activation-Widget1");
1739     widget1.setWindowTitle(widget1.objectName());
1740
1741     QWidget widget2;
1742     widget1.setObjectName("activation-Widget2");
1743     widget1.setWindowTitle(widget2.objectName());
1744
1745     widget1.show();
1746     widget2.show();
1747
1748     QTest::qWait(waitTime);
1749     QVERIFY(qApp->activeWindow() == &widget2);
1750     widget2.showMinimized();
1751     QTest::qWait(waitTime);
1752
1753     QVERIFY(qApp->activeWindow() == &widget1);
1754     widget2.showMaximized();
1755     QTest::qWait(waitTime);
1756     QVERIFY(qApp->activeWindow() == &widget2);
1757     widget2.showMinimized();
1758     QTest::qWait(waitTime);
1759     QVERIFY(qApp->activeWindow() == &widget1);
1760     widget2.showNormal();
1761     QTest::qWait(waitTime);
1762 #ifndef Q_OS_WINCE
1763     if (QSysInfo::WindowsVersion >= QSysInfo::WV_VISTA)
1764         QEXPECT_FAIL("", "MS introduced new behavior after XP", Continue);
1765 #endif
1766     QTest::qWait(waitTime);
1767     QVERIFY(qApp->activeWindow() == &widget2);
1768     widget2.hide();
1769     QTest::qWait(waitTime);
1770     QVERIFY(qApp->activeWindow() == &widget1);
1771 }
1772 #endif // Q_OS_WIN
1773
1774 void tst_QWidget::windowState()
1775 {
1776     if (m_platform == QStringLiteral("xcb"))
1777         QSKIP("X11: Many window managers do not support window state properly, which causes this test to fail.");
1778 #ifdef Q_OS_WINCE_WM
1779     QPoint pos(500, 500);
1780     QSize size(200, 200);
1781     if (qt_wince_is_smartphone()) { //small screen
1782         pos = QPoint(10,10);
1783         size = QSize(100,100);
1784     }
1785 #else
1786     const QPoint pos(500, 500);
1787     const QSize size(200, 200);
1788 #endif
1789
1790     QWidget widget1;
1791     widget1.move(pos);
1792     widget1.resize(size);
1793     QCOMPARE(widget1.pos(), pos);
1794     QCOMPARE(widget1.size(), size);
1795     QTest::qWait(100);
1796     widget1.setObjectName(QStringLiteral("windowState-Widget1"));
1797     widget1.setWindowTitle(widget1.objectName());
1798     QCOMPARE(widget1.pos(), pos);
1799     QCOMPARE(widget1.size(), size);
1800
1801 #define VERIFY_STATE(s) QCOMPARE(int(widget1.windowState() & stateMask), int(s))
1802
1803     const int stateMask = Qt::WindowMaximized|Qt::WindowMinimized|Qt::WindowFullScreen;
1804
1805     widget1.setWindowState(Qt::WindowMaximized);
1806     QTest::qWait(100);
1807     VERIFY_STATE(Qt::WindowMaximized);
1808     QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowMaximized);
1809
1810     widget1.show();
1811     QTest::qWait(100);
1812     VERIFY_STATE(Qt::WindowMaximized);
1813     QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowMaximized);
1814
1815     widget1.setWindowState(widget1.windowState() ^ Qt::WindowMaximized);
1816     QTest::qWait(100);
1817     QVERIFY(!(widget1.windowState() & Qt::WindowMaximized));
1818     QTRY_COMPARE(widget1.pos(), pos);
1819     QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowNoState);
1820
1821     widget1.setWindowState(Qt::WindowMinimized);
1822     QTest::qWait(100);
1823     VERIFY_STATE(Qt::WindowMinimized);
1824     QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowMinimized);
1825
1826     widget1.setWindowState(widget1.windowState() | Qt::WindowMaximized);
1827     QTest::qWait(100);
1828     VERIFY_STATE((Qt::WindowMinimized|Qt::WindowMaximized));
1829     QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowMinimized);
1830
1831     widget1.setWindowState(widget1.windowState() ^ Qt::WindowMinimized);
1832     QTest::qWait(100);
1833     VERIFY_STATE(Qt::WindowMaximized);
1834     QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowMaximized);
1835
1836     widget1.setWindowState(widget1.windowState() ^ Qt::WindowMaximized);
1837     QTest::qWait(100);
1838     QVERIFY(!(widget1.windowState() & (Qt::WindowMinimized|Qt::WindowMaximized)));
1839     QTRY_COMPARE(widget1.pos(), pos);
1840     QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowNoState);
1841
1842     widget1.setWindowState(Qt::WindowFullScreen);
1843     QTest::qWait(100);
1844     VERIFY_STATE(Qt::WindowFullScreen);
1845     QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowFullScreen);
1846
1847     widget1.setWindowState(widget1.windowState() ^ Qt::WindowMinimized);
1848     QTest::qWait(100);
1849     VERIFY_STATE((Qt::WindowFullScreen|Qt::WindowMinimized));
1850     QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowMinimized);
1851
1852     widget1.setWindowState(widget1.windowState() ^ Qt::WindowMinimized);
1853     QTest::qWait(100);
1854     VERIFY_STATE(Qt::WindowFullScreen);
1855     QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowFullScreen);
1856
1857     widget1.setWindowState(Qt::WindowNoState);
1858     QTest::qWait(100);
1859     VERIFY_STATE(Qt::WindowNoState);
1860     QTRY_COMPARE(widget1.pos(), pos);
1861     QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowNoState);
1862
1863     widget1.setWindowState(Qt::WindowFullScreen);
1864     QTest::qWait(100);
1865     VERIFY_STATE(Qt::WindowFullScreen);
1866     QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowFullScreen);
1867
1868     widget1.setWindowState(widget1.windowState() ^ Qt::WindowMaximized);
1869     QTest::qWait(100);
1870     VERIFY_STATE((Qt::WindowFullScreen|Qt::WindowMaximized));
1871     QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowFullScreen);
1872
1873     widget1.setWindowState(widget1.windowState() ^ Qt::WindowMinimized);
1874     QTest::qWait(100);
1875     VERIFY_STATE((Qt::WindowFullScreen|Qt::WindowMaximized|Qt::WindowMinimized));
1876     QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowMinimized);
1877
1878     widget1.setWindowState(widget1.windowState() ^ Qt::WindowMinimized);
1879     QTest::qWait(100);
1880     VERIFY_STATE((Qt::WindowFullScreen|Qt::WindowMaximized));
1881     QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowFullScreen);
1882
1883     widget1.setWindowState(widget1.windowState() ^ Qt::WindowFullScreen);
1884     QTest::qWait(100);
1885     VERIFY_STATE(Qt::WindowMaximized);
1886     QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowMaximized);
1887
1888     widget1.setWindowState(widget1.windowState() ^ Qt::WindowMaximized);
1889     QTest::qWait(100);
1890     QVERIFY(!(widget1.windowState() & stateMask));
1891     QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowNoState);
1892
1893     QTRY_COMPARE(widget1.pos(), pos);
1894     QTRY_COMPARE(widget1.size(), size);
1895 }
1896
1897 void tst_QWidget::showMaximized()
1898 {
1899     QWidget plain;
1900     QHBoxLayout *layout;
1901     layout = new QHBoxLayout;
1902     QWidget layouted;
1903     QLineEdit le;
1904     QLineEdit le2;
1905     QLineEdit le3;
1906
1907     layout->addWidget(&le);
1908     layout->addWidget(&le2);
1909     layout->addWidget(&le3);
1910
1911     layouted.setLayout(layout);
1912
1913     plain.showMaximized();
1914     QVERIFY(plain.windowState() & Qt::WindowMaximized);
1915
1916     plain.showNormal();
1917     QVERIFY(!(plain.windowState() & Qt::WindowMaximized));
1918
1919     layouted.showMaximized();
1920     QVERIFY(layouted.windowState() & Qt::WindowMaximized);
1921
1922     layouted.showNormal();
1923     QVERIFY(!(layouted.windowState() & Qt::WindowMaximized));
1924
1925     // ### fixme: embedded may choose a different size to fit on the screen.
1926     if (layouted.size() != layouted.sizeHint())
1927         QEXPECT_FAIL("", "QTBUG-22326", Continue);
1928     QCOMPARE(layouted.size(), layouted.sizeHint());
1929
1930     layouted.showMaximized();
1931     QVERIFY(layouted.isMaximized());
1932     QVERIFY(layouted.isVisible());
1933
1934     layouted.hide();
1935     QVERIFY(layouted.isMaximized());
1936     QVERIFY(!layouted.isVisible());
1937
1938     layouted.showMaximized();
1939     QVERIFY(layouted.isMaximized());
1940     QVERIFY(layouted.isVisible());
1941
1942     layouted.showMinimized();
1943     QVERIFY(layouted.isMinimized());
1944     QVERIFY(layouted.isMaximized());
1945
1946     layouted.showMaximized();
1947     QVERIFY(!layouted.isMinimized());
1948     QVERIFY(layouted.isMaximized());
1949     QVERIFY(layouted.isVisible());
1950
1951     layouted.showMinimized();
1952     QVERIFY(layouted.isMinimized());
1953     QVERIFY(layouted.isMaximized());
1954
1955     layouted.showMaximized();
1956     QVERIFY(!layouted.isMinimized());
1957     QVERIFY(layouted.isMaximized());
1958     QVERIFY(layouted.isVisible());
1959
1960     {
1961         QWidget frame;
1962         QWidget widget(&frame);
1963         widget.showMaximized();
1964         QVERIFY(widget.isMaximized());
1965     }
1966
1967     {
1968         QWidget widget;
1969         widget.setGeometry(0, 0, 10, 10);
1970         widget.showMaximized();
1971         QTRY_VERIFY(widget.size().width() > 20 && widget.size().height() > 20);
1972     }
1973 }
1974
1975 void tst_QWidget::showFullScreen()
1976 {
1977     QWidget plain;
1978     QHBoxLayout *layout;
1979     QWidget layouted;
1980     QLineEdit le;
1981     QLineEdit le2;
1982     QLineEdit le3;
1983     layout = new QHBoxLayout;
1984
1985     layout->addWidget(&le);
1986     layout->addWidget(&le2);
1987     layout->addWidget(&le3);
1988
1989     layouted.setLayout(layout);
1990
1991     plain.showFullScreen();
1992     QVERIFY(plain.windowState() & Qt::WindowFullScreen);
1993     QVERIFY(plain.windowHandle());
1994     QVERIFY(plain.windowHandle()->screen());
1995     const QRect expectedFullScreenGeometry = plain.windowHandle()->screen()->geometry();
1996     QTRY_COMPARE(plain.geometry(), expectedFullScreenGeometry);
1997
1998     plain.showNormal();
1999     QVERIFY(!(plain.windowState() & Qt::WindowFullScreen));
2000
2001     layouted.showFullScreen();
2002     QVERIFY(layouted.windowState() & Qt::WindowFullScreen);
2003     QTRY_COMPARE(layouted.geometry(), expectedFullScreenGeometry);
2004
2005     layouted.showNormal();
2006     QVERIFY(!(layouted.windowState() & Qt::WindowFullScreen));
2007
2008     // ### fixme: embedded may choose a different size to fit on the screen.
2009     if (layouted.size() != layouted.sizeHint())
2010         QEXPECT_FAIL("", "QTBUG-22326", Continue);
2011     QCOMPARE(layouted.size(), layouted.sizeHint());
2012
2013     layouted.showFullScreen();
2014     QVERIFY(layouted.isFullScreen());
2015     QVERIFY(layouted.isVisible());
2016     QTRY_COMPARE(layouted.geometry(), expectedFullScreenGeometry);
2017
2018     layouted.hide();
2019     QVERIFY(layouted.isFullScreen());
2020     QVERIFY(!layouted.isVisible());
2021
2022     layouted.showFullScreen();
2023     QVERIFY(layouted.isFullScreen());
2024     QVERIFY(layouted.isVisible());
2025     QTRY_COMPARE(layouted.geometry(), expectedFullScreenGeometry);
2026
2027     layouted.showMinimized();
2028     QVERIFY(layouted.isMinimized());
2029     QVERIFY(layouted.isFullScreen());
2030
2031     layouted.showFullScreen();
2032     if (m_platform == QStringLiteral("windows"))
2033         QEXPECT_FAIL("", "QTBUG-26424", Continue);
2034     QVERIFY(!layouted.isMinimized());
2035     QVERIFY(layouted.isFullScreen());
2036     QVERIFY(layouted.isVisible());
2037     QTRY_COMPARE(layouted.geometry(), expectedFullScreenGeometry);
2038
2039     layouted.showMinimized();
2040     QVERIFY(layouted.isMinimized());
2041     QVERIFY(layouted.isFullScreen());
2042
2043     layouted.showFullScreen();
2044     QVERIFY(!layouted.isMinimized());
2045     QVERIFY(layouted.isFullScreen());
2046     QVERIFY(layouted.isVisible());
2047     QTRY_COMPARE(layouted.geometry(), expectedFullScreenGeometry);
2048
2049     {
2050         QWidget frame;
2051         QWidget widget(&frame);
2052         widget.showFullScreen();
2053         QVERIFY(widget.isFullScreen());
2054         QTRY_COMPARE(layouted.geometry(), expectedFullScreenGeometry);
2055     }
2056 }
2057
2058 class ResizeWidget : public QWidget {
2059 public:
2060     ResizeWidget(QWidget *p = 0) : QWidget(p)
2061     {
2062         setObjectName(QLatin1String("ResizeWidget"));
2063         setWindowTitle(objectName());
2064         m_resizeEventCount = 0;
2065     }
2066 protected:
2067     void resizeEvent(QResizeEvent *e){
2068         QCOMPARE(size(), e->size());
2069         ++m_resizeEventCount;
2070     }
2071
2072 public:
2073     int m_resizeEventCount;
2074 };
2075
2076 void tst_QWidget::resizeEvent()
2077 {
2078     {
2079         QWidget wParent;
2080         ResizeWidget wChild(&wParent);
2081         wParent.show();
2082         QCOMPARE (wChild.m_resizeEventCount, 1); // initial resize event before paint
2083         wParent.hide();
2084         QSize safeSize(640,480);
2085         if (wChild.size() == safeSize)
2086             safeSize.setWidth(639);
2087         wChild.resize(safeSize);
2088         QCOMPARE (wChild.m_resizeEventCount, 1);
2089         wParent.show();
2090         QCOMPARE (wChild.m_resizeEventCount, 2);
2091     }
2092
2093     {
2094         ResizeWidget wTopLevel;
2095         wTopLevel.show();
2096         QCOMPARE (wTopLevel.m_resizeEventCount, 1); // initial resize event before paint for toplevels
2097         wTopLevel.hide();
2098         QSize safeSize(640,480);
2099         if (wTopLevel.size() == safeSize)
2100             safeSize.setWidth(639);
2101         wTopLevel.resize(safeSize);
2102         QCOMPARE (wTopLevel.m_resizeEventCount, 1);
2103         wTopLevel.show();
2104         QCOMPARE (wTopLevel.m_resizeEventCount, 2);
2105     }
2106 }
2107
2108 void tst_QWidget::showMinimized()
2109 {
2110     QWidget plain;
2111     plain.move(100, 100);
2112     plain.resize(200, 200);
2113     QPoint pos = plain.pos();
2114
2115     plain.showMinimized();
2116     QVERIFY(plain.isMinimized());
2117     QVERIFY(plain.isVisible());
2118     QCOMPARE(plain.pos(), pos);
2119
2120     plain.showNormal();
2121     QVERIFY(!plain.isMinimized());
2122     QVERIFY(plain.isVisible());
2123     QCOMPARE(plain.pos(), pos);
2124
2125     plain.showMinimized();
2126     QVERIFY(plain.isMinimized());
2127     QVERIFY(plain.isVisible());
2128     QCOMPARE(plain.pos(), pos);
2129
2130     plain.hide();
2131     QVERIFY(plain.isMinimized());
2132     QVERIFY(!plain.isVisible());
2133
2134     plain.showMinimized();
2135     QVERIFY(plain.isMinimized());
2136     QVERIFY(plain.isVisible());
2137
2138     plain.setGeometry(200, 200, 300, 300);
2139     plain.showNormal();
2140     QCOMPARE(plain.geometry(), QRect(200, 200, 300, 300));
2141
2142     {
2143         QWidget frame;
2144         QWidget widget(&frame);
2145         widget.showMinimized();
2146         QVERIFY(widget.isMinimized());
2147     }
2148 }
2149
2150 void tst_QWidget::showMinimizedKeepsFocus()
2151 {
2152     if (m_platform == QStringLiteral("xcb"))
2153         QSKIP("QTBUG-26424");
2154
2155     //here we test that minimizing a widget and restoring it doesn't change the focus inside of it
2156     {
2157         QWidget window;
2158         window.resize(200, 200);
2159         QWidget child1(&window), child2(&window);
2160         child1.setFocusPolicy(Qt::StrongFocus);
2161         child2.setFocusPolicy(Qt::StrongFocus);
2162         window.show();
2163         qApp->setActiveWindow(&window);
2164         QVERIFY(QTest::qWaitForWindowActive(&window));
2165         child2.setFocus();
2166
2167         QTRY_COMPARE(window.focusWidget(), &child2);
2168         QTRY_COMPARE(qApp->focusWidget(), &child2);
2169
2170         window.showMinimized();
2171         QTRY_VERIFY(window.isMinimized());
2172         QTRY_COMPARE(window.focusWidget(), &child2);
2173
2174         window.showNormal();
2175         QTest::qWait(10);
2176         QTRY_COMPARE(window.focusWidget(), &child2);
2177     }
2178
2179     //testing deletion of the focusWidget
2180     {
2181         QWidget window;
2182         QWidget *child = new QWidget(&window);
2183         child->setFocusPolicy(Qt::StrongFocus);
2184         window.show();
2185         qApp->setActiveWindow(&window);
2186         QVERIFY(QTest::qWaitForWindowActive(&window));
2187         child->setFocus();
2188         QTRY_COMPARE(window.focusWidget(), child);
2189         QTRY_COMPARE(qApp->focusWidget(), child);
2190
2191         delete child;
2192         QCOMPARE(window.focusWidget(), static_cast<QWidget*>(0));
2193         QCOMPARE(qApp->focusWidget(), static_cast<QWidget*>(0));
2194     }
2195
2196     //testing reparenting the focus widget
2197     {
2198         QWidget window;
2199         QWidget *child = new QWidget(&window);
2200         child->setFocusPolicy(Qt::StrongFocus);
2201         window.show();
2202         qApp->setActiveWindow(&window);
2203         QVERIFY(QTest::qWaitForWindowActive(&window));
2204         child->setFocus();
2205         QTRY_COMPARE(window.focusWidget(), child);
2206         QTRY_COMPARE(qApp->focusWidget(), child);
2207
2208         child->setParent(0);
2209         QCOMPARE(window.focusWidget(), static_cast<QWidget*>(0));
2210         QCOMPARE(qApp->focusWidget(), static_cast<QWidget*>(0));
2211     }
2212
2213     //testing setEnabled(false)
2214     {
2215         QWidget window;
2216         QWidget *child = new QWidget(&window);
2217         child->setFocusPolicy(Qt::StrongFocus);
2218         window.show();
2219         qApp->setActiveWindow(&window);
2220         QVERIFY(QTest::qWaitForWindowActive(&window));
2221         child->setFocus();
2222         QTRY_COMPARE(window.focusWidget(), child);
2223         QTRY_COMPARE(qApp->focusWidget(), child);
2224
2225         child->setEnabled(false);
2226         QCOMPARE(window.focusWidget(), static_cast<QWidget*>(0));
2227         QCOMPARE(qApp->focusWidget(), static_cast<QWidget*>(0));
2228     }
2229
2230     //testing clearFocus
2231     {
2232         QWidget window;
2233         QWidget *firstchild = new QWidget(&window);
2234         firstchild->setFocusPolicy(Qt::StrongFocus);
2235         QWidget *child = new QWidget(&window);
2236         child->setFocusPolicy(Qt::StrongFocus);
2237         window.show();
2238         qApp->setActiveWindow(&window);
2239         QVERIFY(QTest::qWaitForWindowActive(&window));
2240         child->setFocus();
2241         QTRY_COMPARE(window.focusWidget(), child);
2242         QTRY_COMPARE(qApp->focusWidget(), child);
2243
2244         child->clearFocus();
2245         QCOMPARE(window.focusWidget(), static_cast<QWidget*>(0));
2246         QCOMPARE(qApp->focusWidget(), static_cast<QWidget*>(0));
2247
2248         window.showMinimized();
2249         QTest::qWait(30);
2250         QTRY_VERIFY(window.isMinimized());
2251         QCOMPARE(window.focusWidget(), static_cast<QWidget*>(0));
2252         QTRY_COMPARE(qApp->focusWidget(), static_cast<QWidget*>(0));
2253
2254         window.showNormal();
2255         qApp->setActiveWindow(&window);
2256         QVERIFY(QTest::qWaitForWindowActive(&window));
2257 #ifdef Q_OS_MAC
2258         if (!macHasAccessToWindowsServer())
2259             QEXPECT_FAIL("", "When not having WindowServer access, we lose focus.", Continue);
2260 #endif
2261         QTRY_COMPARE(window.focusWidget(), firstchild);
2262 #ifdef Q_OS_MAC
2263         if (!macHasAccessToWindowsServer())
2264             QEXPECT_FAIL("", "When not having WindowServer access, we lose focus.", Continue);
2265 #endif
2266         QTRY_COMPARE(qApp->focusWidget(), firstchild);
2267     }
2268 }
2269
2270
2271 void tst_QWidget::reparent()
2272 {
2273     QWidget parent;
2274     parent.setWindowTitle("Toplevel");
2275     parent.setGeometry(300, 300, 200, 150);
2276
2277     QWidget child(0);
2278     child.setObjectName("child");
2279     child.setGeometry(10, 10, 180, 130);
2280     QPalette pal1;
2281     pal1.setColor(child.backgroundRole(), Qt::white);
2282     child.setPalette(pal1);
2283
2284     QWidget childTLW(&child, Qt::Window);
2285     childTLW.setObjectName("childTLW");
2286     childTLW.setGeometry(100, 100, 50, 50);
2287     QPalette pal2;
2288     pal2.setColor(childTLW.backgroundRole(), Qt::yellow);
2289     childTLW.setPalette(pal2);
2290
2291     parent.show();
2292     childTLW.show();
2293     QVERIFY(QTest::qWaitForWindowExposed(&parent));
2294
2295 #ifdef Q_OS_WINCE
2296     parent.move(50, 50);
2297 #else
2298     parent.move(300, 300);
2299 #endif
2300
2301     QPoint childPos = parent.mapToGlobal(child.pos());
2302     QPoint tlwPos = childTLW.pos();
2303
2304     child.setParent(0, child.windowFlags() & ~Qt::WindowType_Mask);
2305     child.setGeometry(childPos.x(), childPos.y(), child.width(), child.height());
2306     child.show();
2307
2308 #if 0   // QTBUG-26424
2309     if (m_platform == QStringLiteral("xcb"))
2310         QEXPECT_FAIL("", "On X11, the window manager will apply NorthWestGravity rules to 'child', which"
2311                          " means the top-left corner of the window frame will be placed at 'childPos'"
2312                          " causing this test to fail.", Continue);
2313 #endif
2314
2315     QCOMPARE(child.geometry().topLeft(), childPos);
2316     QTRY_COMPARE(childTLW.pos(), tlwPos);
2317 }
2318
2319 // Qt/Embedded does it differently.
2320 void tst_QWidget::icon()
2321 {
2322     QPixmap p(20,20);
2323     p.fill(Qt::red);
2324     testWidget->setWindowIcon(p);
2325
2326     QVERIFY(!testWidget->windowIcon().isNull());
2327     testWidget->show();
2328     QVERIFY(!testWidget->windowIcon().isNull());
2329     testWidget->showFullScreen();
2330     QVERIFY(!testWidget->windowIcon().isNull());
2331     testWidget->showNormal();
2332     QVERIFY(!testWidget->windowIcon().isNull());
2333 }
2334
2335 void tst_QWidget::hideWhenFocusWidgetIsChild()
2336 {
2337     testWidget->activateWindow();
2338     QScopedPointer<QWidget> parentWidget(new QWidget(testWidget));
2339     parentWidget->setObjectName("parentWidget");
2340     parentWidget->setGeometry(0, 0, 100, 100);
2341     QLineEdit *edit = new QLineEdit(parentWidget.data());
2342     edit->setObjectName("edit1");
2343     QLineEdit *edit3 = new QLineEdit(parentWidget.data());
2344     edit3->setObjectName("edit3");
2345     edit3->move(0,50);
2346     parentWidget->show();
2347     QLineEdit *edit2 = new QLineEdit(testWidget);
2348     edit2->setObjectName("edit2");
2349     edit2->show();
2350     edit2->move(110, 100);
2351     edit->setFocus();
2352     qApp->processEvents();
2353     QString actualFocusWidget, expectedFocusWidget;
2354     if (!qApp->focusWidget() && m_platform == QStringLiteral("xcb"))
2355         QSKIP("X11: Your window manager is too broken for this test");
2356
2357     QVERIFY(qApp->focusWidget());
2358     actualFocusWidget.sprintf("%p %s %s", qApp->focusWidget(), qApp->focusWidget()->objectName().toLatin1().constData(), qApp->focusWidget()->metaObject()->className());
2359     expectedFocusWidget.sprintf("%p %s %s", edit, edit->objectName().toLatin1().constData(), edit->metaObject()->className());
2360     QCOMPARE(actualFocusWidget, expectedFocusWidget);
2361
2362     parentWidget->hide();
2363     qApp->processEvents();
2364     actualFocusWidget.sprintf("%p %s %s", qApp->focusWidget(), qApp->focusWidget()->objectName().toLatin1().constData(), qApp->focusWidget()->metaObject()->className());
2365     expectedFocusWidget.sprintf("%p %s %s", edit2, edit2->objectName().toLatin1().constData(), edit2->metaObject()->className());
2366     QCOMPARE(actualFocusWidget, expectedFocusWidget);
2367 }
2368
2369 void tst_QWidget::normalGeometry()
2370 {
2371     QWidget parent;
2372     parent.setWindowTitle("NormalGeometry parent");
2373     QWidget *child = new QWidget(&parent);
2374
2375     QCOMPARE(parent.normalGeometry(), parent.geometry());
2376     QCOMPARE(child->normalGeometry(), QRect());
2377
2378     parent.setGeometry(100, 100, 200, 200);
2379     parent.show();
2380     QVERIFY(QTest::qWaitForWindowExposed(&parent));
2381     QApplication::processEvents();
2382
2383     QRect geom = parent.geometry();
2384     // ### the window manager places the top-left corner at
2385     // ### 100,100... making geom something like 102,124 (offset by
2386     // ### the frame/frame)... this indicates a rather large different
2387     // ### between how X11 and Windows works
2388     // QCOMPARE(geom, QRect(100, 100, 200, 200));
2389     QCOMPARE(parent.normalGeometry(), geom);
2390
2391     parent.setWindowState(parent.windowState() ^ Qt::WindowMaximized);
2392     QTest::qWait(10);
2393     QTRY_VERIFY(parent.windowState() & Qt::WindowMaximized);
2394     QTRY_VERIFY(parent.geometry() != geom);
2395     QTRY_COMPARE(parent.normalGeometry(), geom);
2396
2397     parent.setWindowState(parent.windowState() ^ Qt::WindowMaximized);
2398     QTest::qWait(10);
2399     QTRY_VERIFY(!(parent.windowState() & Qt::WindowMaximized));
2400     QTRY_COMPARE(parent.geometry(), geom);
2401     QTRY_COMPARE(parent.normalGeometry(), geom);
2402
2403     parent.showMaximized();
2404     QTest::qWait(10);
2405     QTRY_VERIFY(parent.windowState() & Qt::WindowMaximized);
2406     QTRY_VERIFY(parent.geometry() != geom);
2407     QCOMPARE(parent.normalGeometry(), geom);
2408
2409     parent.showNormal();
2410     QTest::qWait(10);
2411     QTRY_VERIFY(!(parent.windowState() & Qt::WindowMaximized));
2412     QTRY_COMPARE(parent.geometry(), geom);
2413     QCOMPARE(parent.normalGeometry(), geom);
2414
2415     parent.setWindowState(parent.windowState() ^ Qt::WindowMinimized);
2416     QTest::qWait(10);
2417     parent.setWindowState(parent.windowState() ^ Qt::WindowMaximized);
2418     QTest::qWait(10);
2419     if (m_platform == QStringLiteral("xcb"))
2420         QSKIP("QTBUG-26424");
2421     QTRY_VERIFY(parent.windowState() & (Qt::WindowMinimized|Qt::WindowMaximized));
2422     // ### when minimized and maximized at the same time, the geometry
2423     // ### does *NOT* have to be the normal geometry, it could be the
2424     // ### maximized geometry.
2425     // QCOMPARE(parent.geometry(), geom);
2426     QTRY_COMPARE(parent.normalGeometry(), geom);
2427
2428     parent.setWindowState(parent.windowState() ^ Qt::WindowMinimized);
2429     QTest::qWait(10);
2430     QTRY_VERIFY(!(parent.windowState() & Qt::WindowMinimized));
2431     QTRY_VERIFY(parent.windowState() & Qt::WindowMaximized);
2432     QTRY_VERIFY(parent.geometry() != geom);
2433     QTRY_COMPARE(parent.normalGeometry(), geom);
2434
2435     parent.setWindowState(parent.windowState() ^ Qt::WindowMaximized);
2436     QTest::qWait(10);
2437     QTRY_VERIFY(!(parent.windowState() & Qt::WindowMaximized));
2438     QTRY_COMPARE(parent.geometry(), geom);
2439     QTRY_COMPARE(parent.normalGeometry(), geom);
2440
2441     parent.setWindowState(parent.windowState() ^ Qt::WindowFullScreen);
2442     QTest::qWait(10);
2443     QTRY_VERIFY(parent.windowState() & Qt::WindowFullScreen);
2444     QTRY_VERIFY(parent.geometry() != geom);
2445     QTRY_COMPARE(parent.normalGeometry(), geom);
2446
2447     parent.setWindowState(parent.windowState() ^ Qt::WindowFullScreen);
2448     QTest::qWait(10);
2449     QVERIFY(!(parent.windowState() & Qt::WindowFullScreen));
2450     QTRY_COMPARE(parent.geometry(), geom);
2451     QTRY_COMPARE(parent.normalGeometry(), geom);
2452
2453     parent.showFullScreen();
2454     QTest::qWait(10);
2455     QTRY_VERIFY(parent.windowState() & Qt::WindowFullScreen);
2456     QTRY_VERIFY(parent.geometry() != geom);
2457     QTRY_COMPARE(parent.normalGeometry(), geom);
2458
2459     parent.showNormal();
2460     QTest::qWait(10);
2461     QTRY_VERIFY(!(parent.windowState() & Qt::WindowFullScreen));
2462     QTRY_COMPARE(parent.geometry(), geom);
2463     QTRY_COMPARE(parent.normalGeometry(), geom);
2464
2465     parent.showNormal();
2466     parent.setWindowState(Qt:: WindowFullScreen | Qt::WindowMaximized);
2467     parent.setWindowState(Qt::WindowMinimized | Qt:: WindowFullScreen | Qt::WindowMaximized);
2468     parent.setWindowState(Qt:: WindowFullScreen | Qt::WindowMaximized);
2469     QTest::qWait(10);
2470     QTRY_COMPARE(parent.normalGeometry(), geom);
2471 }
2472
2473 void tst_QWidget::setGeometry()
2474 {
2475     QWidget tlw;
2476     QWidget child(&tlw);
2477
2478     QRect tr(100,100,200,200);
2479     QRect cr(50,50,50,50);
2480     tlw.setGeometry(tr);
2481     child.setGeometry(cr);
2482     tlw.show();
2483     QTest::qWait(50);
2484     QCOMPARE(tlw.geometry().size(), tr.size());
2485     QCOMPARE(child.geometry(), cr);
2486
2487     tlw.setParent(0, Qt::Window|Qt::FramelessWindowHint);
2488     tr = QRect(0,0,100,100);
2489     tr.moveTopLeft(QApplication::desktop()->availableGeometry().topLeft());
2490     tlw.setGeometry(tr);
2491     QCOMPARE(tlw.geometry(), tr);
2492     tlw.show();
2493     QTest::qWait(50);
2494     if (tlw.frameGeometry() != tlw.geometry())
2495         QSKIP("Your window manager is too broken for this test");
2496     if (m_platform == QStringLiteral("xcb"))
2497         QSKIP("QTBUG-26424");
2498     QCOMPARE(tlw.geometry(), tr);
2499 }
2500
2501 // Windows CE does not support windowOpacity.
2502 #ifndef Q_OS_WINCE
2503 void tst_QWidget::windowOpacity()
2504 {
2505     QWidget widget;
2506     QWidget child(&widget);
2507
2508     // Initial value should be 1.0
2509     QCOMPARE(widget.windowOpacity(), 1.0);
2510     // children should always return 1.0
2511     QCOMPARE(child.windowOpacity(), 1.0);
2512
2513     widget.setWindowOpacity(0.0);
2514     QCOMPARE(widget.windowOpacity(), 0.0);
2515     child.setWindowOpacity(0.0);
2516     QCOMPARE(child.windowOpacity(), 1.0);
2517
2518     widget.setWindowOpacity(1.0);
2519     QCOMPARE(widget.windowOpacity(), 1.0);
2520     child.setWindowOpacity(1.0);
2521     QCOMPARE(child.windowOpacity(), 1.0);
2522
2523     widget.setWindowOpacity(2.0);
2524     QCOMPARE(widget.windowOpacity(), 1.0);
2525     child.setWindowOpacity(2.0);
2526     QCOMPARE(child.windowOpacity(), 1.0);
2527
2528     widget.setWindowOpacity(-1.0);
2529     QCOMPARE(widget.windowOpacity(), 0.0);
2530     child.setWindowOpacity(-1.0);
2531     QCOMPARE(child.windowOpacity(), 1.0);
2532 }
2533 #endif
2534
2535 class UpdateWidget : public QWidget
2536 {
2537 public:
2538     UpdateWidget(QWidget *parent = 0) : QWidget(parent) {
2539         setObjectName(QLatin1String("UpdateWidget"));
2540         setWindowTitle(objectName());
2541         reset();
2542     }
2543
2544     void paintEvent(QPaintEvent *e) {
2545         paintedRegion += e->region();
2546         ++numPaintEvents;
2547         if (resizeInPaintEvent) {
2548             resizeInPaintEvent = false;
2549             resize(size() + QSize(2, 2));
2550         }
2551     }
2552
2553     bool event(QEvent *event)
2554     {
2555         switch (event->type()) {
2556         case QEvent::ZOrderChange:
2557             ++numZOrderChangeEvents;
2558             break;
2559         case QEvent::UpdateRequest:
2560             ++numUpdateRequestEvents;
2561             break;
2562         case QEvent::ActivationChange:
2563         case QEvent::FocusIn:
2564         case QEvent::FocusOut:
2565         case QEvent::WindowActivate:
2566         case QEvent::WindowDeactivate:
2567             if (!updateOnActivationChangeAndFocusIn)
2568                 return true; // Filter out to avoid update() calls in QWidget.
2569             break;
2570         default:
2571             break;
2572         }
2573         return QWidget::event(event);
2574     }
2575
2576     void reset() {
2577         numPaintEvents = 0;
2578         numZOrderChangeEvents = 0;
2579         numUpdateRequestEvents = 0;
2580         updateOnActivationChangeAndFocusIn = false;
2581         resizeInPaintEvent = false;
2582         paintedRegion = QRegion();
2583     }
2584
2585     int numPaintEvents;
2586     int numZOrderChangeEvents;
2587     int numUpdateRequestEvents;
2588     bool updateOnActivationChangeAndFocusIn;
2589     bool resizeInPaintEvent;
2590     QRegion paintedRegion;
2591 };
2592
2593 void tst_QWidget::lostUpdatesOnHide()
2594 {
2595 #ifndef Q_OS_MAC
2596     UpdateWidget widget;
2597     widget.setAttribute(Qt::WA_DontShowOnScreen);
2598     widget.show();
2599     widget.hide();
2600     QTest::qWait(50);
2601     widget.show();
2602     QTest::qWait(50);
2603
2604     QCOMPARE(widget.numPaintEvents, 1);
2605 #endif
2606 }
2607
2608 void tst_QWidget::raise()
2609 {
2610     QTest::qWait(10);
2611     QScopedPointer<QWidget> parentPtr(new QWidget);
2612     parentPtr->resize(200, 200);
2613     parentPtr->setObjectName(QLatin1String("raise"));
2614     parentPtr->setWindowTitle(parentPtr->objectName());
2615     QList<UpdateWidget *> allChildren;
2616
2617     UpdateWidget *child1 = new UpdateWidget(parentPtr.data());
2618     child1->setAutoFillBackground(true);
2619     allChildren.append(child1);
2620
2621     UpdateWidget *child2 = new UpdateWidget(parentPtr.data());
2622     child2->setAutoFillBackground(true);
2623     allChildren.append(child2);
2624
2625     UpdateWidget *child3 = new UpdateWidget(parentPtr.data());
2626     child3->setAutoFillBackground(true);
2627     allChildren.append(child3);
2628
2629     UpdateWidget *child4 = new UpdateWidget(parentPtr.data());
2630     child4->setAutoFillBackground(true);
2631     allChildren.append(child4);
2632
2633     parentPtr->show();
2634     QVERIFY(QTest::qWaitForWindowExposed(parentPtr.data()));
2635     QTest::qWait(10);
2636
2637 #ifdef Q_OS_MAC
2638     if (child1->internalWinId()) {
2639         QSKIP("Cocoa has no Z-Order for views, we hack it, but it results in paint events.");
2640     }
2641 #endif
2642
2643     QList<QObject *> list1;
2644     list1 << child1 << child2 << child3 << child4;
2645     QVERIFY(parentPtr->children() == list1);
2646     QCOMPARE(allChildren.count(), list1.count());
2647
2648     foreach (UpdateWidget *child, allChildren) {
2649         int expectedPaintEvents = child == child4 ? 1 : 0;
2650         if (expectedPaintEvents == 0) {
2651             QVERIFY(child->numPaintEvents == 0);
2652         } else {
2653             // show() issues multiple paint events on some window managers
2654             QTRY_VERIFY(child->numPaintEvents >= expectedPaintEvents);
2655         }
2656         QCOMPARE(child->numZOrderChangeEvents, 0);
2657         child->reset();
2658     }
2659
2660     for (int i = 0; i < 5; ++i)
2661         child2->raise();
2662     QTest::qWait(50);
2663
2664     foreach (UpdateWidget *child, allChildren) {
2665         int expectedPaintEvents = child == child2 ? 1 : 0;
2666         int expectedZOrderChangeEvents = child == child2 ? 1 : 0;
2667         QTRY_COMPARE(child->numPaintEvents, expectedPaintEvents);
2668         QCOMPARE(child->numZOrderChangeEvents, expectedZOrderChangeEvents);
2669         child->reset();
2670     }
2671
2672     QList<QObject *> list2;
2673     list2 << child1 << child3 << child4 << child2;
2674     QVERIFY(parentPtr->children() == list2);
2675
2676     // Creates a widget on top of all the children and checks that raising one of
2677     // the children underneath doesn't trigger a repaint on the covering widget.
2678     QWidget topLevel;
2679     QWidget *parent = parentPtr.take();
2680     parent->setParent(&topLevel);
2681     topLevel.show();
2682     QVERIFY(QTest::qWaitForWindowExposed(&topLevel));
2683     QTest::qWait(50);
2684
2685     UpdateWidget *onTop = new UpdateWidget(&topLevel);
2686     onTop->reset();
2687     onTop->resize(topLevel.size());
2688     onTop->setAutoFillBackground(true);
2689     onTop->show();
2690     QTest::qWait(50);
2691     QTRY_VERIFY(onTop->numPaintEvents > 0);
2692     onTop->reset();
2693
2694     // Reset all the children.
2695     foreach (UpdateWidget *child, allChildren)
2696         child->reset();
2697
2698     for (int i = 0; i < 5; ++i)
2699         child3->raise();
2700     QTest::qWait(50);
2701
2702     QCOMPARE(onTop->numPaintEvents, 0);
2703     QCOMPARE(onTop->numZOrderChangeEvents, 0);
2704
2705     QList<QObject *> list3;
2706     list3 << child1 << child4 << child2 << child3;
2707     QVERIFY(parent->children() == list3);
2708
2709     foreach (UpdateWidget *child, allChildren) {
2710         int expectedPaintEvents = 0;
2711         int expectedZOrderChangeEvents = child == child3 ? 1 : 0;
2712         QTRY_COMPARE(child->numPaintEvents, expectedPaintEvents);
2713         QCOMPARE(child->numZOrderChangeEvents, expectedZOrderChangeEvents);
2714         child->reset();
2715     }
2716 }
2717
2718 // Cocoa has no Z-Order for views, we hack it, but it results in paint events.
2719 #ifndef QT_OS_MAC
2720 void tst_QWidget::lower()
2721 {
2722     QScopedPointer<QWidget> parent(new QWidget);
2723     parent->setObjectName(QLatin1String("lower"));
2724     parent->setWindowTitle(parent->objectName());
2725     parent->resize(200, 200);
2726     QList<UpdateWidget *> allChildren;
2727
2728     UpdateWidget *child1 = new UpdateWidget(parent.data());
2729     child1->setAutoFillBackground(true);
2730     allChildren.append(child1);
2731
2732     UpdateWidget *child2 = new UpdateWidget(parent.data());
2733     child2->setAutoFillBackground(true);
2734     allChildren.append(child2);
2735
2736     UpdateWidget *child3 = new UpdateWidget(parent.data());
2737     child3->setAutoFillBackground(true);
2738     allChildren.append(child3);
2739
2740     UpdateWidget *child4 = new UpdateWidget(parent.data());
2741     child4->setAutoFillBackground(true);
2742     allChildren.append(child4);
2743
2744     parent->show();
2745     QVERIFY(QTest::qWaitForWindowExposed(parent.data()));
2746
2747     QList<QObject *> list1;
2748     list1 << child1 << child2 << child3 << child4;
2749     QVERIFY(parent->children() == list1);
2750     QCOMPARE(allChildren.count(), list1.count());
2751
2752     foreach (UpdateWidget *child, allChildren) {
2753         int expectedPaintEvents = child == child4 ? 1 : 0;
2754         if (expectedPaintEvents == 0) {
2755             QVERIFY(child->numPaintEvents == 0);
2756         } else {
2757             // show() issues multiple paint events on some window managers
2758             QTRY_VERIFY(child->numPaintEvents >= expectedPaintEvents);
2759         }
2760         QCOMPARE(child->numZOrderChangeEvents, 0);
2761         child->reset();
2762     }
2763
2764     for (int i = 0; i < 5; ++i)
2765         child4->lower();
2766
2767     QTest::qWait(100);
2768
2769     foreach (UpdateWidget *child, allChildren) {
2770         int expectedPaintEvents = child == child3 ? 1 : 0;
2771         int expectedZOrderChangeEvents = child == child4 ? 1 : 0;
2772         QTRY_COMPARE(child->numZOrderChangeEvents, expectedZOrderChangeEvents);
2773         QTRY_COMPARE(child->numPaintEvents, expectedPaintEvents);
2774         child->reset();
2775     }
2776
2777     QList<QObject *> list2;
2778     list2 << child4 << child1 << child2 << child3;
2779     QVERIFY(parent->children() == list2);
2780 }
2781 #endif
2782
2783 // Cocoa has no Z-Order for views, we hack it, but it results in paint events.
2784 #ifndef QT_OS_MAC
2785 void tst_QWidget::stackUnder()
2786 {
2787     QScopedPointer<QWidget> parent(new QWidget);
2788     parent->setObjectName(QLatin1String("stackUnder"));
2789     parent->setWindowTitle(parent->objectName());
2790     parent->resize(200, 200);
2791     QList<UpdateWidget *> allChildren;
2792
2793     UpdateWidget *child1 = new UpdateWidget(parent.data());
2794     child1->setAutoFillBackground(true);
2795     allChildren.append(child1);
2796
2797     UpdateWidget *child2 = new UpdateWidget(parent.data());
2798     child2->setAutoFillBackground(true);
2799     allChildren.append(child2);
2800
2801     UpdateWidget *child3 = new UpdateWidget(parent.data());
2802     child3->setAutoFillBackground(true);
2803     allChildren.append(child3);
2804
2805     UpdateWidget *child4 = new UpdateWidget(parent.data());
2806     child4->setAutoFillBackground(true);
2807     allChildren.append(child4);
2808
2809     parent->show();
2810     QVERIFY(QTest::qWaitForWindowExposed(parent.data()));
2811     QList<QObject *> list1;
2812     list1 << child1 << child2 << child3 << child4;
2813     QVERIFY(parent->children() == list1);
2814
2815     foreach (UpdateWidget *child, allChildren) {
2816         int expectedPaintEvents = child == child4 ? 1 : 0;
2817 #if defined(Q_OS_WIN) || defined(Q_OS_MAC)
2818         if (expectedPaintEvents == 1 && child->numPaintEvents == 2)
2819             QEXPECT_FAIL(0, "Mac and Windows issues double repaints for Z-Order change", Continue);
2820 #endif
2821         QTRY_COMPARE(child->numPaintEvents, expectedPaintEvents);
2822         QCOMPARE(child->numZOrderChangeEvents, 0);
2823         child->reset();
2824     }
2825
2826     for (int i = 0; i < 5; ++i)
2827         child4->stackUnder(child2);
2828     QTest::qWait(10);
2829
2830     QList<QObject *> list2;
2831     list2 << child1 << child4 << child2 << child3;
2832     QVERIFY(parent->children() == list2);
2833
2834     foreach (UpdateWidget *child, allChildren) {
2835         int expectedPaintEvents = child == child3 ? 1 : 0;
2836         int expectedZOrderChangeEvents = child == child4 ? 1 : 0;
2837         QTRY_COMPARE(child->numPaintEvents, expectedPaintEvents);
2838         QTRY_COMPARE(child->numZOrderChangeEvents, expectedZOrderChangeEvents);
2839         child->reset();
2840     }
2841
2842     for (int i = 0; i < 5; ++i)
2843         child1->stackUnder(child3);
2844     QTest::qWait(10);
2845
2846     QList<QObject *> list3;
2847     list3 << child4 << child2 << child1 << child3;
2848     QVERIFY(parent->children() == list3);
2849
2850     foreach (UpdateWidget *child, allChildren) {
2851         int expectedZOrderChangeEvents = child == child1 ? 1 : 0;
2852         if (child == child3) {
2853 #ifdef Q_OS_WINCE
2854             qApp->processEvents();
2855 #endif
2856 #ifndef Q_OS_MAC
2857             QEXPECT_FAIL(0, "See QTBUG-493", Continue);
2858 #endif
2859             QCOMPARE(child->numPaintEvents, 0);
2860         } else {
2861             QCOMPARE(child->numPaintEvents, 0);
2862         }
2863         QTRY_COMPARE(child->numZOrderChangeEvents, expectedZOrderChangeEvents);
2864         child->reset();
2865     }
2866 }
2867 #endif
2868
2869 void drawPolygon(QPaintDevice *dev, int w, int h)
2870 {
2871     QPainter p(dev);
2872     p.fillRect(0, 0, w, h, Qt::white);
2873
2874     QPolygon a;
2875     a << QPoint(0, 0) << QPoint(w/2, h/2) << QPoint(w, 0)
2876       << QPoint(w/2, h) << QPoint(0, 0);
2877
2878     p.setPen(QPen(Qt::black, 1));
2879     p.setBrush(Qt::DiagCrossPattern);
2880     p.drawPolygon(a);
2881 }
2882
2883 class ContentsPropagationWidget : public QWidget
2884 {
2885     Q_OBJECT
2886 public:
2887     ContentsPropagationWidget(QWidget *parent = 0) : QWidget(parent)
2888     {
2889         setObjectName(QLatin1String("ContentsPropagationWidget"));
2890         setWindowTitle(objectName());
2891         QWidget *child = this;
2892         for (int i=0; i<32; ++i) {
2893             child = new QWidget(child);
2894             child->setGeometry(i, i, 400 - i*2, 400 - i*2);
2895         }
2896     }
2897
2898     void setContentsPropagation(bool enable) {
2899         foreach (QObject *child, children())
2900             qobject_cast<QWidget *>(child)->setAutoFillBackground(!enable);
2901     }
2902
2903 protected:
2904     void paintEvent(QPaintEvent *)
2905     {
2906         int w = width(), h = height();
2907         drawPolygon(this, w, h);
2908     }
2909
2910     QSize sizeHint() const { return QSize(500, 500); }
2911 };
2912
2913 void tst_QWidget::testContentsPropagation()
2914 {
2915     ContentsPropagationWidget widget;
2916     widget.setFixedSize(500, 500);
2917     widget.setContentsPropagation(false);
2918     QPixmap widgetSnapshot = widget.grab(QRect(QPoint(0, 0), QSize(-1, -1)));
2919
2920     QPixmap correct(500, 500);
2921     drawPolygon(&correct, 500, 500);
2922     //correct.save("correct.png", "PNG");
2923
2924     //widgetSnapshot.save("snap1.png", "PNG");
2925     QVERIFY(widgetSnapshot.toImage() != correct.toImage());
2926
2927     widget.setContentsPropagation(true);
2928     widgetSnapshot = widgetSnapshot = widget.grab(QRect(QPoint(0, 0), QSize(-1, -1)));
2929     //widgetSnapshot.save("snap2.png", "PNG");
2930
2931     QCOMPARE(widgetSnapshot, correct);
2932 }
2933
2934 /*
2935     Test that saving and restoring window geometry with
2936     saveGeometry() and restoreGeometry() works.
2937 */
2938
2939 void tst_QWidget::saveRestoreGeometry()
2940 {
2941     const QPoint position(100, 100);
2942     const QSize size(200, 200);
2943
2944     QByteArray savedGeometry;
2945
2946     {
2947         QWidget widget;
2948         widget.move(position);
2949         widget.resize(size);
2950         widget.show();
2951         QVERIFY(QTest::qWaitForWindowExposed(&widget));
2952         QApplication::processEvents();
2953
2954         QTRY_COMPARE(widget.pos(), position);
2955         QCOMPARE(widget.size(), size);
2956         savedGeometry = widget.saveGeometry();
2957     }
2958
2959     {
2960         QWidget widget;
2961
2962         const QByteArray empty;
2963         const QByteArray one("a");
2964         const QByteArray two("ab");
2965         const QByteArray three("abc");
2966         const QByteArray four("abca");
2967         const QByteArray garbage("abcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabc");
2968
2969         QVERIFY(widget.restoreGeometry(empty) == false);
2970         QVERIFY(widget.restoreGeometry(one) == false);
2971         QVERIFY(widget.restoreGeometry(two) == false);
2972         QVERIFY(widget.restoreGeometry(three) == false);
2973         QVERIFY(widget.restoreGeometry(four) == false);
2974         QVERIFY(widget.restoreGeometry(garbage) == false);
2975
2976         QVERIFY(widget.restoreGeometry(savedGeometry));
2977         widget.show();
2978         QVERIFY(QTest::qWaitForWindowExposed(&widget));
2979         QApplication::processEvents();
2980
2981         QTRY_COMPARE(widget.pos(), position);
2982         QCOMPARE(widget.size(), size);
2983         widget.show();
2984         QCOMPARE(widget.pos(), position);
2985         QCOMPARE(widget.size(), size);
2986     }
2987
2988     {
2989         QWidget widget;
2990         widget.move(position);
2991         widget.resize(size);
2992         widget.show();
2993         QVERIFY(QTest::qWaitForWindowExposed(&widget));
2994         QTRY_COMPARE(widget.geometry().size(), size);
2995
2996         QRect geom;
2997
2998         //Restore from Full screen
2999         savedGeometry = widget.saveGeometry();
3000         geom = widget.geometry();
3001         widget.setWindowState(widget.windowState() | Qt::WindowFullScreen);
3002         QTRY_VERIFY((widget.windowState() & Qt::WindowFullScreen));
3003         QTest::qWait(500);
3004         QVERIFY(widget.restoreGeometry(savedGeometry));
3005         QTest::qWait(120);
3006         QTRY_VERIFY(!(widget.windowState() & Qt::WindowFullScreen));
3007         QTRY_COMPARE(widget.geometry(), geom);
3008
3009         //Restore to full screen
3010         widget.setWindowState(widget.windowState() | Qt::WindowFullScreen);
3011         QTest::qWait(120);
3012         QTRY_VERIFY((widget.windowState() & Qt::WindowFullScreen));
3013         QTest::qWait(500);
3014         savedGeometry = widget.saveGeometry();
3015         geom = widget.geometry();
3016         widget.setWindowState(widget.windowState() ^ Qt::WindowFullScreen);
3017         QTest::qWait(120);
3018         QTRY_VERIFY(!(widget.windowState() & Qt::WindowFullScreen));
3019         QTest::qWait(400);
3020         QVERIFY(widget.restoreGeometry(savedGeometry));
3021         QTest::qWait(120);
3022         QTRY_VERIFY((widget.windowState() & Qt::WindowFullScreen));
3023         QTRY_COMPARE(widget.geometry(), geom);
3024         QVERIFY((widget.windowState() & Qt::WindowFullScreen));
3025         widget.setWindowState(widget.windowState() ^ Qt::WindowFullScreen);
3026         QTest::qWait(120);
3027         QTRY_VERIFY(!(widget.windowState() & Qt::WindowFullScreen));
3028         QTest::qWait(120);
3029
3030         //Restore from Maximised
3031         widget.move(position);
3032         widget.resize(size);
3033         QTest::qWait(10);
3034         QTRY_COMPARE(widget.size(), size);
3035         QTest::qWait(500);
3036         savedGeometry = widget.saveGeometry();
3037         geom = widget.geometry();
3038         widget.setWindowState(widget.windowState() | Qt::WindowMaximized);
3039         QTest::qWait(120);
3040         QTRY_VERIFY((widget.windowState() & Qt::WindowMaximized));
3041         QTRY_VERIFY(widget.geometry() != geom);
3042         QTest::qWait(500);
3043         QVERIFY(widget.restoreGeometry(savedGeometry));
3044         QTest::qWait(120);
3045         QTRY_COMPARE(widget.geometry(), geom);
3046
3047         QVERIFY(!(widget.windowState() & Qt::WindowMaximized));
3048
3049         //Restore to maximised
3050         widget.setWindowState(widget.windowState() | Qt::WindowMaximized);
3051         QTest::qWait(120);
3052         QTRY_VERIFY((widget.windowState() & Qt::WindowMaximized));
3053         QTest::qWait(500);
3054         geom = widget.geometry();
3055         savedGeometry = widget.saveGeometry();
3056         widget.setWindowState(widget.windowState() ^ Qt::WindowMaximized);
3057         QTest::qWait(120);
3058         QTRY_VERIFY(!(widget.windowState() & Qt::WindowMaximized));
3059         QTest::qWait(500);
3060         QVERIFY(widget.restoreGeometry(savedGeometry));
3061         QTest::qWait(120);
3062         QTRY_VERIFY((widget.windowState() & Qt::WindowMaximized));
3063         QTRY_COMPARE(widget.geometry(), geom);
3064     }
3065 }
3066
3067 void tst_QWidget::restoreVersion1Geometry_data()
3068 {
3069     QTest::addColumn<QString>("fileName");
3070     QTest::addColumn<uint>("expectedWindowState");
3071     QTest::addColumn<QPoint>("expectedPosition");
3072     QTest::addColumn<QSize>("expectedSize");
3073     QTest::addColumn<QRect>("expectedNormalGeometry");
3074     const QPoint position(100, 100);
3075     const QSize size(200, 200);
3076     const QRect normalGeometry(102, 124, 200, 200);
3077
3078     QTest::newRow("geometry.dat") << ":geometry.dat" << uint(Qt::WindowNoState) << position << size << normalGeometry;
3079     QTest::newRow("geometry-maximized.dat") << ":geometry-maximized.dat" << uint(Qt::WindowMaximized) << position << size << normalGeometry;
3080     QTest::newRow("geometry-fullscreen.dat") << ":geometry-fullscreen.dat" << uint(Qt::WindowFullScreen) << position << size << normalGeometry;
3081 }
3082
3083 /*
3084     Test that the current version of restoreGeometry() can restore geometry
3085     saved width saveGeometry() version 1.0.
3086 */
3087 void tst_QWidget::restoreVersion1Geometry()
3088 {
3089     QFETCH(QString, fileName);
3090     QFETCH(uint, expectedWindowState);
3091     QFETCH(QPoint, expectedPosition);
3092     QFETCH(QSize, expectedSize);
3093     QFETCH(QRect, expectedNormalGeometry);
3094
3095     // WindowActive is uninteresting for this test
3096     const uint WindowStateMask = Qt::WindowFullScreen | Qt::WindowMaximized | Qt::WindowMinimized;
3097
3098     QFile f(fileName);
3099     QVERIFY(f.exists());
3100     f.open(QIODevice::ReadOnly);
3101     const QByteArray savedGeometry = f.readAll();
3102     QCOMPARE(savedGeometry.count(), 46);
3103     f.close();
3104
3105     QWidget widget;
3106
3107     QVERIFY(widget.restoreGeometry(savedGeometry));
3108
3109     QCOMPARE(uint(widget.windowState() & WindowStateMask), expectedWindowState);
3110     if (expectedWindowState == Qt::WindowNoState) {
3111         QCOMPARE(widget.pos(), expectedPosition);
3112         QCOMPARE(widget.size(), expectedSize);
3113     }
3114     widget.show();
3115     QVERIFY(QTest::qWaitForWindowExposed(&widget));
3116     QTest::qWait(100);
3117
3118     if (expectedWindowState == Qt::WindowNoState) {
3119         QTRY_COMPARE(widget.pos(), expectedPosition);
3120         QTRY_COMPARE(widget.size(), expectedSize);
3121     }
3122
3123     widget.showNormal();
3124     QTest::qWait(10);
3125
3126     if (m_platform == QStringLiteral("xcb") || m_platform == QStringLiteral("windows"))
3127         QSKIP("QTBUG-26421");
3128
3129     if (expectedWindowState != Qt::WindowNoState) {
3130         // restoring from maximized or fullscreen, we can only restore to the normal geometry
3131         QTRY_COMPARE(widget.geometry(), expectedNormalGeometry);
3132     } else {
3133         QTRY_COMPARE(widget.pos(), expectedPosition);
3134         QTRY_COMPARE(widget.size(), expectedSize);
3135     }
3136
3137 #if 0
3138     // Code for saving a new geometry*.dat files
3139     {
3140         QWidget widgetToSave;
3141         widgetToSave.move(expectedPosition);
3142         widgetToSave.resize(expectedSize);
3143         widgetToSave.show();
3144         QVERIFY(QTest::qWaitForWindowExposed(&widget));
3145         QTest::qWait(500); // stabilize
3146         widgetToSave.setWindowState(Qt::WindowStates(expectedWindowState));
3147         QTest::qWait(500); // stabilize
3148
3149         QByteArray geometryToSave = widgetToSave.saveGeometry();
3150
3151         // Code for saving a new geometry.dat file.
3152         f.setFileName(fileName.mid(1));
3153         QVERIFY(f.open(QIODevice::WriteOnly)); // did you forget to 'p4 edit *.dat'? :)
3154         f.write(geometryToSave);
3155         f.close();
3156     }
3157 #endif
3158 }
3159
3160 void tst_QWidget::widgetAt()
3161 {
3162     Q_CHECK_PAINTEVENTS
3163
3164     QScopedPointer<QWidget> w1(new QWidget(0, Qt::X11BypassWindowManagerHint));
3165     w1->setGeometry(0, 0, 160, 150);
3166     w1->setObjectName(QLatin1String("w1"));
3167     w1->setWindowTitle(w1->objectName());
3168     QScopedPointer<QWidget> w2(new QWidget(0, Qt::X11BypassWindowManagerHint  | Qt::FramelessWindowHint));
3169     w2->setGeometry(50,50, 160, 100);
3170     w2->setObjectName(QLatin1String("w2"));
3171     w2->setWindowTitle(w2->objectName());
3172     w1->show();
3173     QVERIFY(QTest::qWaitForWindowExposed(w1.data()));
3174     qApp->processEvents();
3175     QWidget *wr;
3176     QTRY_VERIFY((wr = QApplication::widgetAt(100, 100)));
3177     QCOMPARE(wr->objectName(), QString("w1"));
3178
3179     w2->show();
3180     QVERIFY(QTest::qWaitForWindowExposed(w2.data()));
3181     qApp->processEvents();
3182     qApp->processEvents();
3183     qApp->processEvents();
3184     QTRY_VERIFY((wr = QApplication::widgetAt(100, 100)));
3185     QCOMPARE(wr->objectName(), QString("w2"));
3186
3187     w2->lower();
3188     qApp->processEvents();
3189     QTRY_VERIFY((wr = QApplication::widgetAt(100, 100)) && wr->objectName() == QString("w1"));
3190     w2->raise();
3191
3192     qApp->processEvents();
3193     QTRY_VERIFY((wr = QApplication::widgetAt(100, 100)) && wr->objectName() == QString("w2"));
3194
3195     QWidget *w3 = new QWidget(w2.data());
3196     w3->setGeometry(10,10,50,50);
3197     w3->setObjectName("w3");
3198     w3->show();
3199     qApp->processEvents();
3200     QTRY_VERIFY((wr = QApplication::widgetAt(100,100)) && wr->objectName() == QString("w3"));
3201
3202     w3->setAttribute(Qt::WA_TransparentForMouseEvents);
3203     qApp->processEvents();
3204     QTRY_VERIFY((wr = QApplication::widgetAt(100, 100)) && wr->objectName() == QString("w2"));
3205
3206     QRegion rgn = QRect(QPoint(0,0), w2->size());
3207     QPoint point = w2->mapFromGlobal(QPoint(100,100));
3208     rgn -= QRect(point, QSize(1,1));
3209     w2->setMask(rgn);
3210     qApp->processEvents();
3211     QTest::qWait(10);
3212 #if defined(Q_OS_WINCE)
3213     QEXPECT_FAIL("", "Windows CE does only support rectangular regions", Continue); //See also task 147191
3214 #endif
3215     if (!QGuiApplication::platformName().compare(QLatin1String("cocoa"), Qt::CaseInsensitive))
3216         QEXPECT_FAIL("", "Window mask not implemented on Mac QTBUG-22326", Continue);
3217
3218     QTRY_VERIFY((wr = QApplication::widgetAt(100,100)));
3219     QTRY_COMPARE(wr->objectName(), w1->objectName());
3220     QTRY_VERIFY((wr = QApplication::widgetAt(101,101)));
3221     QTRY_COMPARE(wr->objectName(), w2->objectName());
3222
3223     QBitmap bitmap(w2->size());
3224     QPainter p(&bitmap);
3225     p.fillRect(bitmap.rect(), Qt::color1);
3226     p.setPen(Qt::color0);
3227     p.drawPoint(w2->mapFromGlobal(QPoint(100,100)));
3228     p.end();
3229     w2->setMask(bitmap);
3230     qApp->processEvents();
3231     QTest::qWait(10);
3232 #if defined(Q_OS_WINCE)
3233     QEXPECT_FAIL("", "Windows CE does only support rectangular regions", Continue); //See also task 147191
3234 #endif
3235     if (!QGuiApplication::platformName().compare(QLatin1String("cocoa"), Qt::CaseInsensitive))
3236         QEXPECT_FAIL("", "Window mask not implemented on Mac QTBUG-22326", Continue);
3237     QTRY_VERIFY(QApplication::widgetAt(100,100) == w1.data());
3238     QTRY_VERIFY(QApplication::widgetAt(101,101) == w2.data());
3239 }
3240
3241 void tst_QWidget::task110173()
3242 {
3243     QWidget w;
3244
3245     QPushButton *pb1 = new QPushButton("click", &w);
3246     pb1->setFocusPolicy(Qt::ClickFocus);
3247     pb1->move(100, 100);
3248
3249     QPushButton *pb2 = new QPushButton("push", &w);
3250     pb2->setFocusPolicy(Qt::ClickFocus);
3251     pb2->move(300, 300);
3252
3253     QTest::keyClick( &w, Qt::Key_Tab );
3254     w.show();
3255     QVERIFY(QTest::qWaitForWindowExposed(&w));
3256     QTest::qWait(200);
3257 }
3258
3259 class Widget : public QWidget
3260 {
3261 public:
3262     Widget() : deleteThis(false) { setFocusPolicy(Qt::StrongFocus); }
3263     void actionEvent(QActionEvent *) { if (deleteThis) delete this; }
3264     void changeEvent(QEvent *) { if (deleteThis) delete this; }
3265     void closeEvent(QCloseEvent *) { if (deleteThis) delete this; }
3266     void hideEvent(QHideEvent *) { if (deleteThis) delete this; }
3267     void focusOutEvent(QFocusEvent *) { if (deleteThis) delete this; }
3268     void keyPressEvent(QKeyEvent *) { if (deleteThis) delete this; }
3269     void keyReleaseEvent(QKeyEvent *) { if (deleteThis) delete this; }
3270     void mouseDoubleClickEvent(QMouseEvent *) { if (deleteThis) delete this; }
3271     void mousePressEvent(QMouseEvent *) { if (deleteThis) delete this; }
3272     void mouseReleaseEvent(QMouseEvent *) { if (deleteThis) delete this; }
3273     void mouseMoveEvent(QMouseEvent *) { if (deleteThis) delete this; }
3274
3275     bool deleteThis;
3276 };
3277
3278 void tst_QWidget::testDeletionInEventHandlers()
3279 {
3280     // closeEvent
3281     QPointer<Widget> w = new Widget;
3282     w->deleteThis = true;
3283     w->close();
3284     QVERIFY(w == 0);
3285     delete w;
3286
3287     // focusOut (crashes)
3288     //w = new Widget;
3289     //w->show();
3290     //w->setFocus();
3291     //QVERIFY(qApp->focusWidget() == w);
3292     //w->deleteThis = true;
3293     //w->clearFocus();
3294     //QVERIFY(w == 0);
3295
3296     // key press
3297     w = new Widget;
3298     w->show();
3299     w->deleteThis = true;
3300     QTest::keyPress(w, Qt::Key_A);
3301     QVERIFY(w == 0);
3302     delete w;
3303
3304     // key release
3305     w = new Widget;
3306     w->show();
3307     w->deleteThis = true;
3308     QTest::keyRelease(w, Qt::Key_A);
3309     QVERIFY(w == 0);
3310     delete w;
3311
3312     // mouse press
3313     w = new Widget;
3314     w->show();
3315     w->deleteThis = true;
3316     QTest::mousePress(w, Qt::LeftButton);
3317     QVERIFY(w == 0);
3318     delete w;
3319
3320     // mouse release
3321     w = new Widget;
3322     w->show();
3323     w->deleteThis = true;
3324     QTest::mouseRelease(w, Qt::LeftButton);
3325     QVERIFY(w == 0);
3326     delete w;
3327
3328     // mouse double click
3329     w = new Widget;
3330     w->show();
3331     w->deleteThis = true;
3332     QTest::mouseDClick(w, Qt::LeftButton);
3333     QVERIFY(w == 0);
3334     delete w;
3335
3336     // hide event (crashes)
3337     //w = new Widget;
3338     //w->show();
3339     //w->deleteThis = true;
3340     //w->hide();
3341     //QVERIFY(w == 0);
3342
3343     // action event
3344     w = new Widget;
3345     w->deleteThis = true;
3346     w->addAction(new QAction(w));
3347     QVERIFY(w == 0);
3348     delete w;
3349
3350     // change event
3351     w = new Widget;
3352     w->show();
3353     w->deleteThis = true;
3354     w->setMouseTracking(true);
3355     QVERIFY(w == 0);
3356     delete w;
3357
3358     w = new Widget;
3359     w->setMouseTracking(true);
3360     w->show();
3361     w->deleteThis = true;
3362     QMouseEvent me(QEvent::MouseMove, QPoint(0, 0), Qt::NoButton, Qt::NoButton, Qt::NoModifier);
3363     QApplication::sendEvent(w, &me);
3364     QVERIFY(w == 0);
3365     delete w;
3366 }
3367
3368 #ifdef Q_OS_MAC
3369 void tst_QWidget::sheetOpacity()
3370 {
3371     QWidget tmpWindow;
3372     QWidget sheet(&tmpWindow, Qt::Sheet);
3373     tmpWindow.show();
3374     sheet.show();
3375     QCOMPARE(int(sheet.windowOpacity() * 255), 242);  // 95%
3376     sheet.setParent(0, Qt::Dialog);
3377     QCOMPARE(int(sheet.windowOpacity() * 255), 255);
3378 }
3379
3380 class MaskedPainter : public QWidget
3381 {
3382 public:
3383     QRect mask;
3384
3385     MaskedPainter()
3386     : mask(20, 20, 50, 50)
3387     {
3388         setMask(mask);
3389     }
3390
3391     void paintEvent(QPaintEvent *)
3392     {
3393         QPainter p(this);
3394         p.fillRect(mask, QColor(Qt::red));
3395     }
3396 };
3397
3398 /*
3399     Verifies that the entire area inside the mask is painted red.
3400 */
3401 bool verifyWidgetMask(QWidget *widget, QRect mask)
3402 {
3403     const QImage image = widget->grab(QRect(QPoint(0, 0), widget->size())).toImage();
3404
3405     const QImage masked = image.copy(mask);
3406     QImage red(masked);
3407     red.fill(QColor(Qt::red).rgb());
3408
3409     return (masked == red);
3410 }
3411
3412 void tst_QWidget::setMask()
3413 {
3414     testWidget->hide(); // get this out of the way.
3415
3416     {
3417         MaskedPainter w;
3418         w.resize(200, 200);
3419         w.show();
3420         QTest::qWait(100);
3421         QVERIFY(verifyWidgetMask(&w, w.mask));
3422     }
3423     {
3424         MaskedPainter w;
3425         w.resize(200, 200);
3426         w.setWindowFlags(w.windowFlags() | Qt::FramelessWindowHint);
3427         w.show();
3428         QTest::qWait(100);
3429         QRect mask = w.mask;
3430
3431         QVERIFY(verifyWidgetMask(&w, mask));
3432     }
3433 }
3434 #endif
3435
3436 class StaticWidget : public QWidget
3437 {
3438 Q_OBJECT
3439 public:
3440     bool partial;
3441     bool gotPaintEvent;
3442     QRegion paintedRegion;
3443
3444     StaticWidget(QWidget *parent = 0)
3445     :QWidget(parent)
3446     {
3447         setAttribute(Qt::WA_StaticContents);
3448         setAttribute(Qt::WA_OpaquePaintEvent);
3449         setPalette(Qt::red); // Make sure we have an opaque palette.
3450         setAutoFillBackground(true);
3451         gotPaintEvent = false;
3452     }
3453
3454     void paintEvent(QPaintEvent *e)
3455     {
3456         paintedRegion += e->region();
3457         gotPaintEvent = true;
3458 //        qDebug() << "paint" << e->region();
3459         // Look for a full update, set partial to false if found.
3460         foreach(QRect r, e->region().rects()) {
3461             partial = (r != rect());
3462             if (partial == false)
3463                 break;
3464         }
3465     }
3466 };
3467
3468 /*
3469     Test that widget resizes and moves can be done with minimal repaints when WA_StaticContents
3470     and WA_OpaquePaintEvent is set. Test is mac-only for now.
3471 */
3472 void tst_QWidget::optimizedResizeMove()
3473 {
3474     QWidget parent;
3475     parent.resize(400, 400);
3476
3477     StaticWidget staticWidget(&parent);
3478     staticWidget.gotPaintEvent = false;
3479     staticWidget.move(150, 150);
3480     staticWidget.resize(150, 150);
3481     parent.show();
3482     QVERIFY(QTest::qWaitForWindowExposed(&parent));
3483     QTest::qWait(20);
3484     QTRY_COMPARE(staticWidget.gotPaintEvent, true);
3485
3486     staticWidget.gotPaintEvent = false;
3487     staticWidget.move(staticWidget.pos() + QPoint(10, 10));
3488     QTest::qWait(20);
3489     QCOMPARE(staticWidget.gotPaintEvent, false);
3490
3491     staticWidget.gotPaintEvent = false;
3492     staticWidget.move(staticWidget.pos() + QPoint(-10, -10));
3493     QTest::qWait(20);
3494     QCOMPARE(staticWidget.gotPaintEvent, false);
3495
3496     staticWidget.gotPaintEvent = false;
3497     staticWidget.move(staticWidget.pos() + QPoint(-10, 10));
3498     QTest::qWait(20);
3499     QCOMPARE(staticWidget.gotPaintEvent, false);
3500
3501     staticWidget.gotPaintEvent = false;
3502     staticWidget.resize(staticWidget.size() + QSize(10, 10));
3503     QTest::qWait(20);
3504     QCOMPARE(staticWidget.gotPaintEvent, true);
3505     QCOMPARE(staticWidget.partial, true);
3506
3507     staticWidget.gotPaintEvent = false;
3508     staticWidget.resize(staticWidget.size() + QSize(-10, -10));
3509     QTest::qWait(20);
3510     QCOMPARE(staticWidget.gotPaintEvent, false);
3511
3512     staticWidget.gotPaintEvent = false;
3513     staticWidget.resize(staticWidget.size() + QSize(10, -10));
3514     QTest::qWait(20);
3515     QCOMPARE(staticWidget.gotPaintEvent, true);
3516     QCOMPARE(staticWidget.partial, true);
3517
3518     staticWidget.gotPaintEvent = false;
3519     staticWidget.move(staticWidget.pos() + QPoint(10, 10));
3520     staticWidget.resize(staticWidget.size() + QSize(-10, -10));
3521     QTest::qWait(20);
3522     QCOMPARE(staticWidget.gotPaintEvent, false);
3523
3524     staticWidget.gotPaintEvent = false;
3525     staticWidget.move(staticWidget.pos() + QPoint(10, 10));
3526     staticWidget.resize(staticWidget.size() + QSize(10, 10));
3527     QTest::qWait(20);
3528     QCOMPARE(staticWidget.gotPaintEvent, true);
3529     QCOMPARE(staticWidget.partial, true);
3530
3531     staticWidget.gotPaintEvent = false;
3532     staticWidget.move(staticWidget.pos() + QPoint(-10, -10));
3533     staticWidget.resize(staticWidget.size() + QSize(-10, -10));
3534     QTest::qWait(20);
3535     QCOMPARE(staticWidget.gotPaintEvent, false);
3536
3537     staticWidget.setAttribute(Qt::WA_StaticContents, false);
3538     staticWidget.gotPaintEvent = false;
3539     staticWidget.move(staticWidget.pos() + QPoint(-10, -10));
3540     staticWidget.resize(staticWidget.size() + QSize(-10, -10));
3541     QTest::qWait(20);
3542     QCOMPARE(staticWidget.gotPaintEvent, true);
3543     QCOMPARE(staticWidget.partial, false);
3544     staticWidget.setAttribute(Qt::WA_StaticContents, true);
3545
3546     staticWidget.setAttribute(Qt::WA_StaticContents, false);
3547     staticWidget.gotPaintEvent = false;
3548     staticWidget.move(staticWidget.pos() + QPoint(10, 10));
3549     QTest::qWait(20);
3550     QCOMPARE(staticWidget.gotPaintEvent, false);
3551     staticWidget.setAttribute(Qt::WA_StaticContents, true);
3552 }
3553
3554 void tst_QWidget::optimizedResize_topLevel()
3555 {
3556     QSKIP("We do not yet have static contents support, see QTBUG-28012");
3557
3558     StaticWidget topLevel;
3559     topLevel.gotPaintEvent = false;
3560     topLevel.show();
3561     QVERIFY(QTest::qWaitForWindowExposed(&topLevel));
3562     QTest::qWait(10);
3563     QTRY_COMPARE(topLevel.gotPaintEvent, true);
3564
3565     topLevel.gotPaintEvent = false;
3566     topLevel.partial = false;
3567     topLevel.paintedRegion = QRegion();
3568
3569 #ifndef Q_OS_WIN
3570     topLevel.resize(topLevel.size() + QSize(10, 10));
3571 #else
3572     // Static contents does not work when programmatically resizing
3573     // top-levels with QWidget::resize. We do some funky stuff in
3574     // setGeometry_sys. However, resizing it with the mouse or with
3575     // a native function call works (it basically has to go through
3576     // WM_RESIZE in QApplication). This is a corner case, though.
3577     // See task 243708
3578     const QRect frame = topLevel.frameGeometry();
3579     MoveWindow(winHandleOf(&topLevel), frame.x(), frame.y(),
3580                frame.width() + 10, frame.height() + 10,
3581                true);
3582 #endif
3583
3584     QTest::qWait(100);
3585
3586     // Expected update region: New rect - old rect.
3587     QRegion expectedUpdateRegion(topLevel.rect());
3588     expectedUpdateRegion -= QRect(QPoint(), topLevel.size() - QSize(10, 10));
3589
3590     QTRY_COMPARE(topLevel.gotPaintEvent, true);
3591     if (m_platform == QStringLiteral("xcb"))
3592         QSKIP("QTBUG-26424");
3593     QCOMPARE(topLevel.partial, true);
3594     QCOMPARE(topLevel.paintedRegion, expectedUpdateRegion);
3595 }
3596
3597 class SiblingDeleter : public QWidget
3598 {
3599 public:
3600     inline SiblingDeleter(QWidget *sibling, QWidget *parent)
3601         : QWidget(parent), sibling(sibling) {}
3602     inline virtual ~SiblingDeleter() { delete sibling; }
3603
3604 private:
3605     QPointer<QWidget> sibling;
3606 };
3607
3608
3609 void tst_QWidget::childDeletesItsSibling()
3610 {
3611     QWidget *commonParent = new QWidget(0);
3612     QPointer<QWidget> child = new QWidget(0);
3613     QPointer<QWidget> siblingDeleter = new SiblingDeleter(child, commonParent);
3614     child->setParent(commonParent);
3615     delete commonParent; // don't crash
3616     QVERIFY(!child);
3617     QVERIFY(!siblingDeleter);
3618
3619 }
3620
3621 void tst_QWidget::setMinimumSize()
3622 {
3623     QWidget w;
3624     QSize defaultSize = w.size();
3625
3626     w.setMinimumSize(defaultSize + QSize(100, 100));
3627     QCOMPARE(w.size(), defaultSize + QSize(100, 100));
3628     QVERIFY(!w.testAttribute(Qt::WA_Resized));
3629
3630     w.setMinimumSize(defaultSize + QSize(50, 50));
3631     QCOMPARE(w.size(), defaultSize + QSize(100, 100));
3632     QVERIFY(!w.testAttribute(Qt::WA_Resized));
3633
3634     w.setMinimumSize(defaultSize + QSize(200, 200));
3635     QCOMPARE(w.size(), defaultSize + QSize(200, 200));
3636     QVERIFY(!w.testAttribute(Qt::WA_Resized));
3637
3638     // Setting a minimum size larger than the desktop does not work on WinCE,
3639     // so skip this part of the test.
3640 #ifndef Q_OS_WINCE
3641     QSize nonDefaultSize = defaultSize + QSize(5,5);
3642     w.setMinimumSize(nonDefaultSize);
3643     w.show();
3644     QTest::qWait(50);
3645     QVERIFY(w.height() >= nonDefaultSize.height());
3646     QVERIFY(w.width() >= nonDefaultSize.width());
3647 #endif
3648 }
3649
3650 void tst_QWidget::setMaximumSize()
3651 {
3652     QWidget w;
3653     QSize defaultSize = w.size();
3654
3655     w.setMinimumSize(defaultSize + QSize(100, 100));
3656     QCOMPARE(w.size(), defaultSize + QSize(100, 100));
3657     QVERIFY(!w.testAttribute(Qt::WA_Resized));
3658     w.setMinimumSize(defaultSize);
3659
3660     w.setMaximumSize(defaultSize + QSize(200, 200));
3661     QCOMPARE(w.size(), defaultSize + QSize(100, 100));
3662     QVERIFY(!w.testAttribute(Qt::WA_Resized));
3663
3664     w.setMaximumSize(defaultSize + QSize(50, 50));
3665     QCOMPARE(w.size(), defaultSize + QSize(50, 50));
3666     QVERIFY(!w.testAttribute(Qt::WA_Resized));
3667 }
3668
3669 void tst_QWidget::setFixedSize()
3670 {
3671     QWidget w;
3672     QSize defaultSize = w.size();
3673
3674     w.setFixedSize(defaultSize + QSize(100, 100));
3675     QCOMPARE(w.size(), defaultSize + QSize(100, 100));
3676     QVERIFY(w.testAttribute(Qt::WA_Resized));
3677
3678     w.setFixedSize(defaultSize + QSize(200, 200));
3679
3680     QCOMPARE(w.minimumSize(), defaultSize + QSize(200,200));
3681     QCOMPARE(w.maximumSize(), defaultSize + QSize(200,200));
3682     QCOMPARE(w.size(), defaultSize + QSize(200, 200));
3683     QVERIFY(w.testAttribute(Qt::WA_Resized));
3684
3685     w.setFixedSize(defaultSize + QSize(50, 50));
3686     QCOMPARE(w.size(), defaultSize + QSize(50, 50));
3687     QVERIFY(w.testAttribute(Qt::WA_Resized));
3688
3689     w.setAttribute(Qt::WA_Resized, false);
3690     w.setFixedSize(defaultSize + QSize(50, 50));
3691     QVERIFY(!w.testAttribute(Qt::WA_Resized));
3692
3693     w.setFixedSize(defaultSize + QSize(150, 150));
3694     w.show();
3695     QTest::qWait(50);
3696     if (m_platform == QStringLiteral("xcb"))
3697         QSKIP("QTBUG-26424");
3698     QVERIFY(w.size() == defaultSize + QSize(150,150));
3699 }
3700
3701 void tst_QWidget::ensureCreated()
3702 {
3703     {
3704         QWidget widget;
3705         WId widgetWinId = widget.winId();
3706         Q_UNUSED(widgetWinId);
3707         QVERIFY(widget.testAttribute(Qt::WA_WState_Created));
3708     }
3709
3710     {
3711         QWidget window;
3712
3713         QDialog dialog(&window);
3714         dialog.setWindowModality(Qt::NonModal);
3715
3716         WId dialogWinId = dialog.winId();
3717         Q_UNUSED(dialogWinId);
3718         QVERIFY(dialog.testAttribute(Qt::WA_WState_Created));
3719         QVERIFY(window.testAttribute(Qt::WA_WState_Created));
3720     }
3721
3722     {
3723         QWidget window;
3724
3725         QDialog dialog(&window);
3726         dialog.setWindowModality(Qt::WindowModal);
3727
3728         WId dialogWinId = dialog.winId();
3729         Q_UNUSED(dialogWinId);
3730         QVERIFY(dialog.testAttribute(Qt::WA_WState_Created));
3731         QVERIFY(window.testAttribute(Qt::WA_WState_Created));
3732     }
3733
3734     {
3735         QWidget window;
3736
3737         QDialog dialog(&window);
3738         dialog.setWindowModality(Qt::ApplicationModal);
3739
3740         WId dialogWinId = dialog.winId();
3741         Q_UNUSED(dialogWinId);
3742         QVERIFY(dialog.testAttribute(Qt::WA_WState_Created));
3743         QVERIFY(window.testAttribute(Qt::WA_WState_Created));
3744     }
3745 }
3746
3747 class WinIdChangeWidget : public QWidget {
3748 public:
3749     WinIdChangeWidget(QWidget *p = 0)
3750         : QWidget(p)
3751     {
3752
3753     }
3754 protected:
3755     bool event(QEvent *e)
3756     {
3757         if (e->type() == QEvent::WinIdChange) {
3758             m_winIdList.append(internalWinId());
3759             return true;
3760         }
3761         return QWidget::event(e);
3762     }
3763 public:
3764     QList<WId> m_winIdList;
3765     int winIdChangeEventCount() const { return m_winIdList.count(); }
3766 };
3767
3768 void tst_QWidget::winIdChangeEvent()
3769 {
3770     {
3771         // Transforming an alien widget into a native widget
3772         WinIdChangeWidget widget;
3773         const WId winIdBefore = widget.internalWinId();
3774         const WId winIdAfter = widget.winId();
3775         QVERIFY(winIdBefore != winIdAfter);
3776         QCOMPARE(widget.winIdChangeEventCount(), 1);
3777     }
3778
3779     {
3780         // Changing parent of a native widget
3781         QWidget parent1, parent2;
3782         WinIdChangeWidget child(&parent1);
3783         const WId winIdBefore = child.winId();
3784         QCOMPARE(child.winIdChangeEventCount(), 1);
3785         child.setParent(&parent2);
3786         const WId winIdAfter = child.internalWinId();
3787         QCOMPARE(winIdBefore, winIdAfter);
3788         QCOMPARE(child.winIdChangeEventCount(), 3);
3789         // winId is set to zero during reparenting
3790         QVERIFY(0 == child.m_winIdList[1]);
3791     }
3792
3793     {
3794         // Changing grandparent of a native widget
3795         QWidget grandparent1, grandparent2;
3796         QWidget parent(&grandparent1);
3797         WinIdChangeWidget child(&parent);
3798         const WId winIdBefore = child.winId();
3799         QCOMPARE(child.winIdChangeEventCount(), 1);
3800         parent.setParent(&grandparent2);
3801         const WId winIdAfter = child.internalWinId();
3802         QCOMPARE(winIdBefore, winIdAfter);
3803         QCOMPARE(child.winIdChangeEventCount(), 1);
3804     }
3805
3806     {
3807         // Changing parent of an alien widget
3808         QWidget parent1, parent2;
3809         WinIdChangeWidget child(&parent1);
3810         const WId winIdBefore = child.internalWinId();
3811         child.setParent(&parent2);
3812         const WId winIdAfter = child.internalWinId();
3813         QCOMPARE(winIdBefore, winIdAfter);
3814         QCOMPARE(child.winIdChangeEventCount(), 0);
3815     }
3816
3817     {
3818         // Making native child widget into a top-level window
3819         QWidget parent;
3820         WinIdChangeWidget child(&parent);
3821         child.winId();
3822         const WId winIdBefore = child.internalWinId();
3823         QCOMPARE(child.winIdChangeEventCount(), 1);
3824         const Qt::WindowFlags flags = child.windowFlags();
3825         child.setWindowFlags(flags | Qt::Window);
3826         const WId winIdAfter = child.internalWinId();
3827         QCOMPARE(winIdBefore, winIdAfter);
3828         QCOMPARE(child.winIdChangeEventCount(), 3);
3829         // winId is set to zero during reparenting
3830         QVERIFY(0 == child.m_winIdList[1]);
3831     }
3832 }
3833
3834 void tst_QWidget::persistentWinId()
3835 {
3836     QScopedPointer<QWidget> parent(new QWidget);
3837     QWidget *w1 = new QWidget;
3838     QWidget *w2 = new QWidget;
3839     QWidget *w3 = new QWidget;
3840     w1->setParent(parent.data());
3841     w2->setParent(w1);
3842     w3->setParent(w2);
3843
3844     WId winId1 = w1->winId();
3845     WId winId2 = w2->winId();
3846     WId winId3 = w3->winId();
3847
3848     // reparenting should preserve the winId of the widget being reparented and of its children
3849     w1->setParent(0);
3850     QCOMPARE(w1->winId(), winId1);
3851     QCOMPARE(w2->winId(), winId2);
3852     QCOMPARE(w3->winId(), winId3);
3853
3854     w1->setParent(parent.data());
3855     QCOMPARE(w1->winId(), winId1);
3856     QCOMPARE(w2->winId(), winId2);
3857     QCOMPARE(w3->winId(), winId3);
3858
3859     w2->setParent(0);
3860     QCOMPARE(w2->winId(), winId2);
3861     QCOMPARE(w3->winId(), winId3);
3862
3863     w2->setParent(parent.data());
3864     QCOMPARE(w2->winId(), winId2);
3865     QCOMPARE(w3->winId(), winId3);
3866
3867     w2->setParent(w1);
3868     QCOMPARE(w2->winId(), winId2);
3869     QCOMPARE(w3->winId(), winId3);
3870
3871     w3->setParent(0);
3872     QCOMPARE(w3->winId(), winId3);
3873
3874     w3->setParent(w1);
3875     QCOMPARE(w3->winId(), winId3);
3876
3877     w3->setParent(w2);
3878     QCOMPARE(w3->winId(), winId3);
3879 }
3880
3881 void tst_QWidget::showNativeChild()
3882 {
3883     QWidget topLevel;
3884     topLevel.setGeometry(0, 0, 160, 160);
3885     QWidget child(&topLevel);
3886     child.winId();
3887     topLevel.show();
3888     QVERIFY(QTest::qWaitForWindowExposed(&topLevel));
3889 }
3890
3891 class ShowHideEventWidget : public QWidget
3892 {
3893 public:
3894     int numberOfShowEvents, numberOfHideEvents;
3895
3896     ShowHideEventWidget(QWidget *parent = 0)
3897         : QWidget(parent), numberOfShowEvents(0), numberOfHideEvents(0)
3898     { }
3899
3900     void create()
3901     { QWidget::create(); }
3902
3903     void showEvent(QShowEvent *)
3904     { ++numberOfShowEvents; }
3905
3906     void hideEvent(QHideEvent *)
3907     { ++numberOfHideEvents; }
3908 };
3909
3910 void tst_QWidget::showHideEvent_data()
3911 {
3912     QTest::addColumn<bool>("show");
3913     QTest::addColumn<bool>("hide");
3914     QTest::addColumn<bool>("create");
3915     QTest::addColumn<int>("expectedShowEvents");
3916     QTest::addColumn<int>("expectedHideEvents");
3917
3918     QTest::newRow("window: only show")
3919             << true
3920             << false
3921             << false
3922             << 1
3923             << 0;
3924     QTest::newRow("window: show/hide")
3925             << true
3926             << true
3927             << false
3928             << 1
3929             << 1;
3930     QTest::newRow("window: show/hide/create")
3931             << true
3932             << true
3933             << true
3934             << 1
3935             << 1;
3936     QTest::newRow("window: hide/create")
3937             << false
3938             << true
3939             << true
3940             << 0
3941             << 0;
3942     QTest::newRow("window: only hide")
3943             << false
3944             << true
3945             << false
3946             << 0
3947             << 0;
3948     QTest::newRow("window: nothing")
3949             << false
3950             << false
3951             << false
3952             << 0
3953             << 0;
3954 }
3955
3956 void tst_QWidget::showHideEvent()
3957 {
3958     QFETCH(bool, show);
3959     QFETCH(bool, hide);
3960     QFETCH(bool, create);
3961     QFETCH(int, expectedShowEvents);
3962     QFETCH(int, expectedHideEvents);
3963
3964     ShowHideEventWidget widget;
3965     if (show)
3966         widget.show();
3967     if (hide)
3968         widget.hide();
3969     if (create && !widget.testAttribute(Qt::WA_WState_Created))
3970         widget.create();
3971
3972     QCOMPARE(widget.numberOfShowEvents, expectedShowEvents);
3973     QCOMPARE(widget.numberOfHideEvents, expectedHideEvents);
3974 }
3975
3976 void tst_QWidget::update()
3977 {
3978     QTest::qWait(10);  // Wait for the initStuff to do it's stuff.
3979     Q_CHECK_PAINTEVENTS
3980
3981     UpdateWidget w;
3982     w.setGeometry(50, 50, 100, 100);
3983     w.show();
3984     QVERIFY(QTest::qWaitForWindowExposed(&w));
3985
3986     QApplication::processEvents();
3987     QApplication::processEvents();
3988
3989 #ifdef Q_OS_MAC
3990     QEXPECT_FAIL(0, "Cocoa compositor says to paint this twice.", Continue);
3991 #endif
3992     QTRY_COMPARE(w.numPaintEvents, 1);
3993
3994     QCOMPARE(w.visibleRegion(), QRegion(w.rect()));
3995     QCOMPARE(w.paintedRegion, w.visibleRegion());
3996     w.reset();
3997
3998     UpdateWidget child(&w);
3999     child.setGeometry(10, 10, 80, 80);
4000     child.show();
4001
4002     QPoint childOffset = child.mapToParent(QPoint());
4003
4004     // widgets are transparent by default, so both should get repaints
4005     {
4006         QApplication::processEvents();
4007         QApplication::processEvents();
4008         QCOMPARE(child.numPaintEvents, 1);
4009         QCOMPARE(child.visibleRegion(), QRegion(child.rect()));
4010         QCOMPARE(child.paintedRegion, child.visibleRegion());
4011         QCOMPARE(w.numPaintEvents, 1);
4012         QCOMPARE(w.visibleRegion(), QRegion(w.rect()));
4013         QCOMPARE(w.paintedRegion, child.visibleRegion().translated(childOffset));
4014
4015         w.reset();
4016         child.reset();
4017
4018         w.update();
4019         QApplication::processEvents();
4020         QApplication::processEvents();
4021         QCOMPARE(child.numPaintEvents, 1);
4022         QCOMPARE(child.visibleRegion(), QRegion(child.rect()));
4023         QCOMPARE(child.paintedRegion, child.visibleRegion());
4024         QCOMPARE(w.numPaintEvents, 1);
4025         QCOMPARE(w.visibleRegion(), QRegion(w.rect()));
4026         QCOMPARE(w.paintedRegion, w.visibleRegion());
4027     }
4028
4029     QPalette opaquePalette = child.palette();
4030     opaquePalette.setColor(child.backgroundRole(), QColor(Qt::red));
4031
4032     // setting an opaque background on the child should prevent paint-events
4033     // for the parent in the child area
4034     {
4035         child.setPalette(opaquePalette);
4036         child.setAutoFillBackground(true);
4037         QApplication::processEvents();
4038
4039         w.reset();
4040         child.reset();
4041
4042         w.update();
4043         QApplication::processEvents();
4044         QApplication::processEvents();
4045
4046         QCOMPARE(w.numPaintEvents, 1);
4047         QRegion expectedVisible = QRegion(w.rect())
4048                                   - child.visibleRegion().translated(childOffset);
4049         QCOMPARE(w.visibleRegion(), expectedVisible);
4050         QCOMPARE(w.paintedRegion, expectedVisible);
4051         QCOMPARE(child.numPaintEvents, 0);
4052
4053         w.reset();
4054         child.reset();
4055
4056         child.update();
4057         QApplication::processEvents();
4058         QApplication::processEvents();
4059
4060         QCOMPARE(w.numPaintEvents, 0);
4061         QCOMPARE(child.numPaintEvents, 1);
4062         QCOMPARE(child.paintedRegion, child.visibleRegion());
4063
4064         w.reset();
4065         child.reset();
4066     }
4067
4068     // overlapping sibling
4069     UpdateWidget sibling(&w);
4070     child.setGeometry(10, 10, 20, 20);
4071     sibling.setGeometry(15, 15, 20, 20);
4072     sibling.show();
4073
4074     QApplication::processEvents();
4075     w.reset();
4076     child.reset();
4077     sibling.reset();
4078
4079     const QPoint siblingOffset = sibling.mapToParent(QPoint());
4080
4081     sibling.update();
4082     QApplication::processEvents();
4083     QApplication::processEvents();
4084
4085     // child is opaque, sibling transparent
4086     {
4087         QCOMPARE(sibling.numPaintEvents, 1);
4088         QCOMPARE(sibling.paintedRegion, sibling.visibleRegion());
4089
4090         QCOMPARE(child.numPaintEvents, 1);
4091         QCOMPARE(child.paintedRegion.translated(childOffset),
4092                  child.visibleRegion().translated(childOffset)
4093                  & sibling.visibleRegion().translated(siblingOffset));
4094
4095         QCOMPARE(w.numPaintEvents, 1);
4096         QCOMPARE(w.paintedRegion,
4097                  w.visibleRegion() & sibling.visibleRegion().translated(siblingOffset));
4098         QCOMPARE(w.paintedRegion,
4099                  (w.visibleRegion() - child.visibleRegion().translated(childOffset))
4100                  & sibling.visibleRegion().translated(siblingOffset));
4101
4102     }
4103     w.reset();
4104     child.reset();
4105     sibling.reset();
4106
4107     sibling.setPalette(opaquePalette);
4108     sibling.setAutoFillBackground(true);
4109
4110     sibling.update();
4111     QApplication::processEvents();
4112     QApplication::processEvents();
4113
4114     // child opaque, sibling opaque
4115     {
4116         QCOMPARE(sibling.numPaintEvents, 1);
4117         QCOMPARE(sibling.paintedRegion, sibling.visibleRegion());
4118
4119 #ifdef Q_OS_MAC
4120         if (child.internalWinId()) // child is native
4121             QEXPECT_FAIL(0, "Cocoa compositor paints child and sibling", Continue);
4122 #endif
4123         QCOMPARE(child.numPaintEvents, 0);
4124         QCOMPARE(child.visibleRegion(),
4125                  QRegion(child.rect())
4126                  - sibling.visibleRegion().translated(siblingOffset - childOffset));
4127
4128         QCOMPARE(w.numPaintEvents, 0);
4129         QCOMPARE(w.visibleRegion(),
4130                  QRegion(w.rect())
4131                  - child.visibleRegion().translated(childOffset)
4132                  - sibling.visibleRegion().translated(siblingOffset));
4133     }
4134 }
4135
4136 static inline bool isOpaque(QWidget *widget)
4137 {
4138     if (!widget)
4139         return false;
4140     return qt_widget_private(widget)->isOpaque;
4141 }
4142
4143 void tst_QWidget::isOpaque()
4144 {
4145 #ifndef Q_OS_MAC
4146     QWidget w;
4147     QVERIFY(::isOpaque(&w));
4148
4149     QWidget child(&w);
4150     QVERIFY(!::isOpaque(&child));
4151
4152     child.setAutoFillBackground(true);
4153     QVERIFY(::isOpaque(&child));
4154
4155     QPalette palette;
4156
4157     // background color
4158
4159     palette = child.palette();
4160     palette.setColor(child.backgroundRole(), QColor(255, 0, 0, 127));
4161     child.setPalette(palette);
4162     QVERIFY(!::isOpaque(&child));
4163
4164     palette.setColor(child.backgroundRole(), QColor(255, 0, 0, 255));
4165     child.setPalette(palette);
4166     QVERIFY(::isOpaque(&child));
4167
4168     palette.setColor(QPalette::Window, QColor(0, 0, 255, 127));
4169     w.setPalette(palette);
4170
4171     QVERIFY(!::isOpaque(&w));
4172
4173     child.setAutoFillBackground(false);
4174     QVERIFY(!::isOpaque(&child));
4175
4176     // Qt::WA_OpaquePaintEvent
4177
4178     child.setAttribute(Qt::WA_OpaquePaintEvent);
4179     QVERIFY(::isOpaque(&child));
4180
4181     child.setAttribute(Qt::WA_OpaquePaintEvent, false);
4182     QVERIFY(!::isOpaque(&child));
4183
4184     // Qt::WA_NoSystemBackground
4185
4186     child.setAttribute(Qt::WA_NoSystemBackground);
4187     QVERIFY(!::isOpaque(&child));
4188
4189     child.setAttribute(Qt::WA_NoSystemBackground, false);
4190     QVERIFY(!::isOpaque(&child));
4191
4192     palette.setColor(QPalette::Window, QColor(0, 0, 255, 255));
4193     w.setPalette(palette);
4194     QVERIFY(::isOpaque(&w));
4195
4196     w.setAttribute(Qt::WA_NoSystemBackground);
4197     QVERIFY(!::isOpaque(&w));
4198
4199     w.setAttribute(Qt::WA_NoSystemBackground, false);
4200     QVERIFY(::isOpaque(&w));
4201
4202     {
4203         QPalette palette = QApplication::palette();
4204         QPalette old = palette;
4205         palette.setColor(QPalette::Window, Qt::transparent);
4206         QApplication::setPalette(palette);
4207
4208         QWidget widget;
4209         QVERIFY(!::isOpaque(&widget));
4210
4211         QApplication::setPalette(old);
4212         QCOMPARE(::isOpaque(&widget), old.color(QPalette::Window).alpha() == 255);
4213     }
4214 #endif
4215 }
4216
4217 #ifndef Q_OS_MAC
4218 /*
4219     Test that scrolling of a widget invalidates the correct regions
4220 */
4221 void tst_QWidget::scroll()
4222 {
4223     UpdateWidget updateWidget;
4224     updateWidget.resize(500, 500);
4225     updateWidget.reset();
4226     updateWidget.show();
4227     qApp->setActiveWindow(&updateWidget);
4228     QVERIFY(QTest::qWaitForWindowActive(&updateWidget));
4229     QVERIFY(updateWidget.numPaintEvents > 0);
4230
4231     {
4232         updateWidget.reset();
4233         updateWidget.scroll(10, 10);
4234         qApp->processEvents();
4235         QRegion dirty(QRect(0, 0, 500, 10));
4236         dirty += QRegion(QRect(0, 10, 10, 490));
4237         QCOMPARE(updateWidget.paintedRegion, dirty);
4238     }
4239
4240     {
4241         updateWidget.reset();
4242         updateWidget.update(0, 0, 10, 10);
4243         updateWidget.scroll(0, 10);
4244         qApp->processEvents();
4245         QRegion dirty(QRect(0, 0, 500, 10));
4246         dirty += QRegion(QRect(0, 10, 10, 10));
4247         QCOMPARE(updateWidget.paintedRegion, dirty);
4248     }
4249
4250     {
4251         updateWidget.reset();
4252         updateWidget.update(0, 0, 100, 100);
4253         updateWidget.scroll(10, 10, QRect(50, 50, 100, 100));
4254         qApp->processEvents();
4255         QRegion dirty(QRect(0, 0, 100, 50));
4256         dirty += QRegion(QRect(0, 50, 150, 10));
4257         dirty += QRegion(QRect(0, 60, 110, 40));
4258         dirty += QRegion(QRect(50, 100, 60, 10));
4259         dirty += QRegion(QRect(50, 110, 10, 40));
4260         QCOMPARE(updateWidget.paintedRegion, dirty);
4261     }
4262
4263     {
4264         updateWidget.reset();
4265         updateWidget.update(0, 0, 100, 100);
4266         updateWidget.scroll(10, 10, QRect(100, 100, 100, 100));
4267         qApp->processEvents();
4268         QRegion dirty(QRect(0, 0, 100, 100));
4269         dirty += QRegion(QRect(100, 100, 100, 10));
4270         dirty += QRegion(QRect(100, 110, 10, 90));
4271         QCOMPARE(updateWidget.paintedRegion, dirty);
4272     }
4273 }
4274 #endif
4275
4276 class DestroyedSlotChecker : public QObject
4277 {
4278     Q_OBJECT
4279
4280 public:
4281     bool wasQWidget;
4282
4283     DestroyedSlotChecker()
4284         : wasQWidget(false)
4285     {
4286     }
4287
4288 public slots:
4289     void destroyedSlot(QObject *object)
4290     {
4291         wasQWidget = (qobject_cast<QWidget *>(object) != 0 || object->isWidgetType());
4292     }
4293 };
4294
4295 /*
4296     Test that qobject_cast<QWidget*> returns 0 in a slot
4297     connected to QObject::destroyed.
4298 */
4299 void tst_QWidget::qobject_castInDestroyedSlot()
4300 {
4301     DestroyedSlotChecker checker;
4302
4303     QWidget *widget = new QWidget();
4304
4305     QObject::connect(widget, SIGNAL(destroyed(QObject*)), &checker, SLOT(destroyedSlot(QObject*)));
4306     delete widget;
4307
4308     QVERIFY(checker.wasQWidget == true);
4309 }
4310
4311 Q_DECLARE_METATYPE(QList<QRect>)
4312
4313 // Since X11 WindowManager operations are all async, and we have no way to know if the window
4314 // manager has finished playing with the window geometry, this test can't be reliable on X11.
4315
4316 void tst_QWidget::setWindowGeometry_data()
4317 {
4318     QTest::addColumn<QList<QRect> >("rects");
4319     QTest::addColumn<int>("windowFlags");
4320
4321     QList<QList<QRect> > rects;
4322     rects << (QList<QRect>()
4323               << QRect(100, 100, 200, 200)
4324               << QApplication::desktop()->availableGeometry().adjusted(100, 100, -100, -100)
4325               << QRect(130, 100, 0, 200)
4326               << QRect(100, 50, 200, 0)
4327               << QRect(130, 50, 0, 0))
4328           << (QList<QRect>()
4329               << QApplication::desktop()->availableGeometry().adjusted(100, 100, -100, -100)
4330               << QRect(130, 100, 0, 200)
4331               << QRect(100, 50, 200, 0)
4332               << QRect(130, 50, 0, 0)
4333               << QRect(100, 100, 200, 200))
4334           << (QList<QRect>()
4335               << QRect(130, 100, 0, 200)
4336               << QRect(100, 50, 200, 0)
4337               << QRect(130, 50, 0, 0)
4338               << QRect(100, 100, 200, 200)
4339               << QApplication::desktop()->availableGeometry().adjusted(100, 100, -100, -100))
4340           << (QList<QRect>()
4341               << QRect(100, 50, 200, 0)
4342               << QRect(130, 50, 0, 0)
4343               << QRect(100, 100, 200, 200)
4344               << QApplication::desktop()->availableGeometry().adjusted(100, 100, -100, -100)
4345               << QRect(130, 100, 0, 200))
4346           << (QList<QRect>()
4347               << QRect(130, 50, 0, 0)
4348               << QRect(100, 100, 200, 200)
4349               << QApplication::desktop()->availableGeometry().adjusted(100, 100, -100, -100)
4350               << QRect(130, 100, 0, 200)
4351               << QRect(100, 50, 200, 0));
4352
4353     QList<int> windowFlags;
4354     windowFlags << 0 << Qt::FramelessWindowHint;
4355
4356     foreach (QList<QRect> l, rects) {
4357         QRect rect = l.first();
4358         foreach (int windowFlag, windowFlags) {
4359             QTest::newRow(QString("%1,%2 %3x%4, flags %5")
4360                           .arg(rect.x())
4361                           .arg(rect.y())
4362                           .arg(rect.width())
4363                           .arg(rect.height())
4364                           .arg(windowFlag, 0, 16).toLatin1())
4365                 << l
4366                 << windowFlag;
4367         }
4368     }
4369 }
4370
4371 void tst_QWidget::setWindowGeometry()
4372 {
4373     if (m_platform == QStringLiteral("xcb"))
4374          QSKIP("X11: Skip this test due to Window manager positioning issues.");
4375
4376     QFETCH(QList<QRect>, rects);
4377     QFETCH(int, windowFlags);
4378     QRect rect = rects.takeFirst();
4379
4380     {
4381         // test setGeometry() without actually showing the window
4382         QWidget widget;
4383         if (windowFlags != 0)
4384             widget.setWindowFlags(Qt::WindowFlags(windowFlags));
4385
4386         widget.setGeometry(rect);
4387         QTest::qWait(100);
4388         QCOMPARE(widget.geometry(), rect);
4389
4390         // setGeometry() without showing
4391         foreach (QRect r, rects) {
4392             widget.setGeometry(r);
4393             QTest::qWait(100);
4394             QCOMPARE(widget.geometry(), r);
4395         }
4396     }
4397
4398     {
4399         // setGeometry() first, then show()
4400         QWidget widget;
4401         if (windowFlags != 0)
4402             widget.setWindowFlags(Qt::WindowFlags(windowFlags));
4403
4404         widget.setGeometry(rect);
4405         widget.show();
4406         QVERIFY(QTest::qWaitForWindowExposed(&widget));
4407         if (m_platform == QStringLiteral("windows")) {
4408             QEXPECT_FAIL("130,100 0x200, flags 0", "QTBUG-26424", Continue);
4409             QEXPECT_FAIL("130,50 0x0, flags 0", "QTBUG-26424", Continue);
4410         }
4411         QTRY_COMPARE(widget.geometry(), rect);
4412
4413         // setGeometry() while shown
4414         foreach (QRect r, rects) {
4415             widget.setGeometry(r);
4416             QTest::qWait(10);
4417             QTRY_COMPARE(widget.geometry(), r);
4418         }
4419         widget.setGeometry(rect);
4420         QTest::qWait(20);
4421         QTRY_COMPARE(widget.geometry(), rect);
4422
4423         // now hide
4424         widget.hide();
4425         QTest::qWait(20);
4426         QTRY_COMPARE(widget.geometry(), rect);
4427
4428         // setGeometry() after hide()
4429         foreach (QRect r, rects) {
4430             widget.setGeometry(r);
4431             QTest::qWait(10);
4432             QTRY_COMPARE(widget.geometry(), r);
4433         }
4434         widget.setGeometry(rect);
4435         QTest::qWait(10);
4436         QTRY_COMPARE(widget.geometry(), rect);
4437
4438         // show() again, geometry() should still be the same
4439         widget.show();
4440         QVERIFY(QTest::qWaitForWindowExposed(&widget));
4441         QTRY_COMPARE(widget.geometry(), rect);
4442
4443         // final hide(), again geometry() should be unchanged
4444         widget.hide();
4445         QTest::qWait(10);
4446         QTRY_COMPARE(widget.geometry(), rect);
4447     }
4448
4449     {
4450         // show() first, then setGeometry()
4451         QWidget widget;
4452         if (windowFlags != 0)
4453             widget.setWindowFlags(Qt::WindowFlags(windowFlags));
4454
4455         widget.show();
4456         QVERIFY(QTest::qWaitForWindowExposed(&widget));
4457         widget.setGeometry(rect);
4458         QTest::qWait(10);
4459         QTRY_COMPARE(widget.geometry(), rect);
4460
4461         // setGeometry() while shown
4462         foreach (QRect r, rects) {
4463             widget.setGeometry(r);
4464             QTest::qWait(10);
4465             QTRY_COMPARE(widget.geometry(), r);
4466         }
4467         widget.setGeometry(rect);
4468         QTest::qWait(10);
4469         QTRY_COMPARE(widget.geometry(), rect);
4470
4471         // now hide
4472         widget.hide();
4473         QTest::qWait(10);
4474         QTRY_COMPARE(widget.geometry(), rect);
4475
4476         // setGeometry() after hide()
4477         foreach (QRect r, rects) {
4478             widget.setGeometry(r);
4479             QTest::qWait(10);
4480             QTRY_COMPARE(widget.geometry(), r);
4481         }
4482         widget.setGeometry(rect);
4483         QTest::qWait(10);
4484         QTRY_COMPARE(widget.geometry(), rect);
4485
4486         // show() again, geometry() should still be the same
4487         widget.show();
4488         QVERIFY(QTest::qWaitForWindowExposed(&widget));
4489         QTest::qWait(10);
4490         QTRY_COMPARE(widget.geometry(), rect);
4491
4492         // final hide(), again geometry() should be unchanged
4493         widget.hide();
4494         QTest::qWait(10);
4495         QTRY_COMPARE(widget.geometry(), rect);
4496     }
4497 }
4498
4499 #if defined (Q_OS_WIN) && !defined(Q_OS_WINCE)
4500 void tst_QWidget::setGeometry_win()
4501 {
4502     QWidget widget;
4503     widget.setGeometry(0, 600, 100,100);
4504     widget.show();
4505     widget.setWindowState(widget.windowState() | Qt::WindowMaximized);
4506     QRect geom = widget.normalGeometry();
4507     widget.close();
4508     widget.setGeometry(geom);
4509     widget.setWindowState(widget.windowState() | Qt::WindowMaximized);
4510     widget.show();
4511     RECT rt;
4512     ::GetWindowRect(winHandleOf(&widget), &rt);
4513     QVERIFY(rt.left <= 0);
4514     QEXPECT_FAIL("", "QTBUG-26424", Continue);
4515     QVERIFY(rt.top <= 0);
4516 }
4517 #endif // defined (Q_OS_WIN) && !defined(Q_OS_WINCE)
4518
4519 // Since X11 WindowManager operation are all async, and we have no way to know if the window
4520 // manager has finished playing with the window geometry, this test can't be reliable on X11.
4521
4522 void tst_QWidget::windowMoveResize_data()
4523 {
4524     setWindowGeometry_data();
4525 }
4526
4527 void tst_QWidget::windowMoveResize()
4528 {
4529     if (m_platform == QStringLiteral("xcb"))
4530          QSKIP("X11: Skip this test due to Window manager positioning issues.");
4531
4532     QFETCH(QList<QRect>, rects);
4533     QFETCH(int, windowFlags);
4534
4535     QRect rect = rects.takeFirst();
4536
4537     {
4538         // test setGeometry() without actually showing the window
4539         QWidget widget;
4540         if (windowFlags != 0)
4541             widget.setWindowFlags(Qt::WindowFlags(windowFlags));
4542
4543         widget.move(rect.topLeft());
4544         widget.resize(rect.size());
4545         QTest::qWait(10);
4546         QTRY_COMPARE(widget.pos(), rect.topLeft());
4547         QTRY_COMPARE(widget.size(), rect.size());
4548
4549         // move() without showing
4550         foreach (QRect r, rects) {
4551             widget.move(r.topLeft());
4552             widget.resize(r.size());
4553             QApplication::processEvents();
4554             QTRY_COMPARE(widget.pos(), r.topLeft());
4555             QTRY_COMPARE(widget.size(), r.size());
4556         }
4557     }
4558
4559     {
4560         // move() first, then show()
4561         QWidget widget;
4562         if (windowFlags != 0)
4563             widget.setWindowFlags(Qt::WindowFlags(windowFlags));
4564
4565         widget.move(rect.topLeft());
4566         widget.resize(rect.size());
4567         widget.show();
4568
4569         QTest::qWait(10);
4570         QTRY_COMPARE(widget.pos(), rect.topLeft());
4571         if (m_platform == QStringLiteral("windows")) {
4572             QEXPECT_FAIL("130,100 0x200, flags 0", "QTBUG-26424", Continue);
4573             QEXPECT_FAIL("130,50 0x0, flags 0", "QTBUG-26424", Continue);
4574         }
4575         QTRY_COMPARE(widget.size(), rect.size());
4576
4577         // move() while shown
4578         foreach (const QRect &r, rects) {
4579             if (m_platform == QStringLiteral("xcb")
4580                && ((widget.width() == 0 || widget.height() == 0) && r.width() != 0 && r.height() != 0)) {
4581                 QEXPECT_FAIL("130,100 0x200, flags 0",
4582                              "First resize after show of zero-sized gets wrong win_gravity.",
4583                              Continue);
4584                 QEXPECT_FAIL("100,50 200x0, flags 0",
4585                              "First resize after show of zero-sized gets wrong win_gravity.",
4586                              Continue);
4587                 QEXPECT_FAIL("130,50 0x0, flags 0",
4588                              "First resize after show of zero-sized gets wrong win_gravity.",
4589                              Continue);
4590             }
4591
4592             widget.move(r.topLeft());
4593             widget.resize(r.size());
4594             QApplication::processEvents();
4595             QTRY_COMPARE(widget.pos(), r.topLeft());
4596             QTRY_COMPARE(widget.size(), r.size());
4597         }
4598         widget.move(rect.topLeft());
4599         widget.resize(rect.size());
4600         QApplication::processEvents();
4601         QTRY_COMPARE(widget.pos(), rect.topLeft());
4602         QTRY_COMPARE(widget.size(), rect.size());
4603
4604         // now hide
4605         widget.hide();
4606         QTest::qWait(10);
4607         QTRY_COMPARE(widget.pos(), rect.topLeft());
4608         QTRY_COMPARE(widget.size(), rect.size());
4609
4610         // move() after hide()
4611         foreach (QRect r, rects) {
4612             widget.move(r.topLeft());
4613             widget.resize(r.size());
4614             QApplication::processEvents();
4615 #if defined(Q_OS_MAC)
4616             if (r.width() == 0 && r.height() > 0) {
4617                 widget.move(r.topLeft());
4618                 widget.resize(r.size());
4619              }
4620 #endif
4621             QTRY_COMPARE(widget.pos(), r.topLeft());
4622             QTRY_COMPARE(widget.size(), r.size());
4623         }
4624         widget.move(rect.topLeft());
4625         widget.resize(rect.size());
4626         QTest::qWait(10);
4627         QTRY_COMPARE(widget.pos(), rect.topLeft());
4628         QTRY_COMPARE(widget.size(), rect.size());
4629
4630         // show() again, pos() should be the same
4631         widget.show();
4632         QVERIFY(QTest::qWaitForWindowExposed(&widget));
4633         QApplication::processEvents();
4634         QTRY_COMPARE(widget.pos(), rect.topLeft());
4635         QTRY_COMPARE(widget.size(), rect.size());
4636
4637         // final hide(), again pos() should be unchanged
4638         widget.hide();
4639         QApplication::processEvents();
4640         QTRY_COMPARE(widget.pos(), rect.topLeft());
4641         QTRY_COMPARE(widget.size(), rect.size());
4642     }
4643
4644     {
4645         // show() first, then move()
4646         QWidget widget;
4647         if (windowFlags != 0)
4648             widget.setWindowFlags(Qt::WindowFlags(windowFlags));
4649
4650         widget.show();
4651         QVERIFY(QTest::qWaitForWindowExposed(&widget));
4652         QApplication::processEvents();
4653         widget.move(rect.topLeft());
4654         widget.resize(rect.size());
4655         QApplication::processEvents();
4656         QTRY_COMPARE(widget.pos(), rect.topLeft());
4657         QTRY_COMPARE(widget.size(), rect.size());
4658
4659         // move() while shown
4660         foreach (QRect r, rects) {
4661             widget.move(r.topLeft());
4662             widget.resize(r.size());
4663             QApplication::processEvents();
4664             QTRY_COMPARE(widget.pos(), r.topLeft());
4665             QTRY_COMPARE(widget.size(), r.size());
4666         }
4667         widget.move(rect.topLeft());
4668         widget.resize(rect.size());
4669         QApplication::processEvents();
4670         QTRY_COMPARE(widget.pos(), rect.topLeft());
4671         QTRY_COMPARE(widget.size(), rect.size());
4672
4673         // now hide
4674         widget.hide();
4675         QApplication::processEvents();
4676         QTRY_COMPARE(widget.pos(), rect.topLeft());
4677         QTRY_COMPARE(widget.size(), rect.size());
4678
4679         // move() after hide()
4680         foreach (QRect r, rects) {
4681             widget.move(r.topLeft());
4682             widget.resize(r.size());
4683             QApplication::processEvents();
4684 #if defined(Q_OS_MAC)
4685             if (r.width() == 0 && r.height() > 0) {
4686                 widget.move(r.topLeft());
4687                 widget.resize(r.size());
4688              }
4689 #endif
4690             QTRY_COMPARE(widget.pos(), r.topLeft());
4691             QTRY_COMPARE(widget.size(), r.size());
4692         }
4693         widget.move(rect.topLeft());
4694         widget.resize(rect.size());
4695         QApplication::processEvents();
4696         QTRY_COMPARE(widget.pos(), rect.topLeft());
4697         QTRY_COMPARE(widget.size(), rect.size());
4698
4699         // show() again, pos() should be the same
4700         widget.show();
4701         QVERIFY(QTest::qWaitForWindowExposed(&widget));
4702         QTest::qWait(10);
4703         QTRY_COMPARE(widget.pos(), rect.topLeft());
4704         QTRY_COMPARE(widget.size(), rect.size());
4705
4706         // final hide(), again pos() should be unchanged
4707         widget.hide();
4708         QTest::qWait(10);
4709         QTRY_COMPARE(widget.pos(), rect.topLeft());
4710         QTRY_COMPARE(widget.size(), rect.size());
4711     }
4712 }
4713
4714 class ColorWidget : public QWidget
4715 {
4716 public:
4717     ColorWidget(QWidget *parent = 0, const QColor &c = QColor(Qt::red))
4718         : QWidget(parent, Qt::FramelessWindowHint), color(c), enters(0), leaves(0)
4719     {
4720         QPalette opaquePalette = palette();
4721         opaquePalette.setColor(backgroundRole(), color);
4722         setPalette(opaquePalette);
4723         setAutoFillBackground(true);
4724     }
4725
4726     void paintEvent(QPaintEvent *e) {
4727         r += e->region();
4728     }
4729
4730     void reset() {
4731         r = QRegion();
4732     }
4733
4734     void enterEvent(QEvent *) { ++enters; }
4735     void leaveEvent(QEvent *) { ++leaves; }
4736
4737     void resetCounts()
4738     {
4739         enters = 0;
4740         leaves = 0;
4741     }
4742
4743     QColor color;
4744     QRegion r;
4745     int enters;
4746     int leaves;
4747 };
4748
4749 #define VERIFY_COLOR(region, color) {                                   \
4750     const QRegion r = QRegion(region);                                  \
4751     QScreen *screen = qApp->primaryScreen();                            \
4752     const WId desktopWinId = QDesktopWidget().winId();                      \
4753     for (int i = 0; i < r.rects().size(); ++i) {                        \
4754         const QRect rect = r.rects().at(i);                             \
4755         for (int t = 0; t < 5; t++) {                                   \
4756             const QPixmap pixmap = screen->grabWindow(desktopWinId,     \
4757                                                    rect.left(), rect.top(), \
4758                                                    rect.width(), rect.height()); \
4759             QCOMPARE(pixmap.size(), rect.size());                       \
4760             QPixmap expectedPixmap(pixmap); /* ensure equal formats */  \
4761             expectedPixmap.detach(); \
4762             expectedPixmap.fill(color);                                 \
4763             QImage image = pixmap.toImage();                          \
4764             uint alphaCorrection = image.format() == QImage::Format_RGB32 ? 0xff000000 : 0; \
4765             uint firstPixel = image.pixel(0,0) | alphaCorrection;        \
4766             if ( firstPixel != QColor(color).rgb() && t < 4 )          \
4767             { QTest::qWait(200); continue; }                            \
4768             QCOMPARE(firstPixel, QColor(color).rgb());                  \
4769             QCOMPARE(pixmap, expectedPixmap);                           \
4770             break;                                                      \
4771         }                                                               \
4772     }                                                                   \
4773 }
4774
4775 void tst_QWidget::popupEnterLeave()
4776 {
4777     QWidget parent;
4778     parent.setWindowFlags(Qt::FramelessWindowHint);
4779     parent.setGeometry(10, 10, 200, 100);
4780
4781     ColorWidget alien(&parent, Qt::black);
4782     alien.setGeometry(0, 0, 10, 10);
4783     alien.show();
4784
4785     parent.show();
4786
4787     QVERIFY(QTest::qWaitForWindowExposed(&parent));
4788
4789     QWindowSystemInterface::handleMouseEvent(parent.windowHandle(), QPointF(5, 5), QPointF(), Qt::LeftButton, Qt::NoModifier);
4790     QTest::qWait(100);
4791     QWindowSystemInterface::handleMouseEvent(parent.windowHandle(), QPointF(5, 5), QPointF(), Qt::NoButton, Qt::NoModifier);
4792     QTest::qWait(100);
4793
4794     QStringList wordList;
4795     wordList << "alpha" << "omega" << "omicron" << "zeta";
4796
4797     QLineEdit popup(&parent);
4798
4799     QCompleter completer(wordList);
4800     completer.setCaseSensitivity(Qt::CaseInsensitive);
4801     popup.setCompleter(&completer);
4802     popup.setWindowFlags(Qt::Popup);
4803     popup.setGeometry(20, 20, 80, 20);
4804
4805     popup.show();
4806
4807     QVERIFY(QTest::qWaitForWindowExposed(&popup));
4808
4809     QTest::qWait(100);
4810
4811     QWindowSystemInterface::handleMouseEvent(popup.windowHandle(), QPointF(-5, -5), QPointF(), Qt::LeftButton, Qt::NoModifier);
4812     QTest::qWait(100);
4813     QWindowSystemInterface::handleMouseEvent(popup.windowHandle(), QPointF(-5, -5), QPointF(), Qt::NoButton, Qt::NoModifier);
4814     QTest::qWait(100);
4815
4816     QTest::qWait(1000);
4817     QVERIFY(!popup.underMouse());
4818 }
4819
4820 void tst_QWidget::moveChild_data()
4821 {
4822     QTest::addColumn<QPoint>("offset");
4823
4824     QTest::newRow("right") << QPoint(20, 0);
4825     QTest::newRow("down") << QPoint(0, 20);
4826     QTest::newRow("left") << QPoint(-20, 0);
4827     QTest::newRow("up") << QPoint(0, -20);
4828 }
4829
4830 void tst_QWidget::moveChild()
4831 {
4832     QFETCH(QPoint, offset);
4833
4834     ColorWidget parent;
4835     // prevent custom styles
4836     parent.setStyle(QStyleFactory::create(QLatin1String("Windows")));
4837     ColorWidget child(&parent, Qt::blue);
4838
4839 #ifndef Q_OS_WINCE
4840     parent.setGeometry(QRect(QPoint(QApplication::desktop()->availableGeometry(&parent).topLeft()),
4841                              QSize(100, 100)));
4842 #else
4843     parent.setGeometry(60, 60, 150, 150);
4844 #endif
4845     child.setGeometry(25, 25, 50, 50);
4846     parent.show();
4847     QVERIFY(QTest::qWaitForWindowExposed(&parent));
4848     QTest::qWait(30);
4849     const QPoint tlwOffset = parent.geometry().topLeft();
4850
4851     QTRY_COMPARE(parent.r, QRegion(parent.rect()) - child.geometry());
4852     QTRY_COMPARE(child.r, QRegion(child.rect()));
4853     VERIFY_COLOR(child.geometry().translated(tlwOffset),
4854                  child.color);
4855     VERIFY_COLOR(QRegion(parent.geometry()) - child.geometry().translated(tlwOffset),
4856                  parent.color);
4857     parent.reset();
4858     child.reset();
4859
4860     // move
4861
4862     const QRect oldGeometry = child.geometry();
4863
4864     QPoint pos = child.pos() + offset;
4865     child.move(pos);
4866     QTest::qWait(100);
4867     QTRY_COMPARE(pos, child.pos());
4868
4869     QCOMPARE(parent.r, QRegion(oldGeometry) - child.geometry());
4870 #if !defined(Q_OS_MAC)
4871     // should be scrolled in backingstore
4872     QCOMPARE(child.r, QRegion());
4873 #endif
4874     VERIFY_COLOR(child.geometry().translated(tlwOffset),
4875                 child.color);
4876     VERIFY_COLOR(QRegion(parent.geometry()) - child.geometry().translated(tlwOffset),
4877                 parent.color);
4878 }
4879
4880 void tst_QWidget::showAndMoveChild()
4881 {
4882     QWidget parent(0, Qt::FramelessWindowHint);
4883     // prevent custom styles
4884     parent.setStyle(QStyleFactory::create(QLatin1String("Windows")));
4885
4886     QDesktopWidget desktop;
4887     QRect desktopDimensions = desktop.availableGeometry(&parent);
4888     desktopDimensions = desktopDimensions.adjusted(64, 64, -64, -64);
4889
4890     parent.setGeometry(desktopDimensions);
4891     parent.setPalette(Qt::red);
4892     parent.show();
4893     qApp->setActiveWindow(&parent);
4894     QVERIFY(QTest::qWaitForWindowActive(&parent));
4895     QTest::qWait(10);
4896
4897     const QPoint tlwOffset = parent.geometry().topLeft();
4898     QWidget child(&parent);
4899     child.resize(desktopDimensions.width()/2, desktopDimensions.height()/2);
4900     child.setPalette(Qt::blue);
4901     child.setAutoFillBackground(true);
4902
4903     // Ensure that the child is repainted correctly when moved right after show.
4904     // NB! Do NOT processEvents() (or qWait()) in between show() and move().
4905     child.show();
4906     child.move(desktopDimensions.width()/2, desktopDimensions.height()/2);
4907     qApp->processEvents();
4908
4909     VERIFY_COLOR(child.geometry().translated(tlwOffset), Qt::blue);
4910     VERIFY_COLOR(QRegion(parent.geometry()) - child.geometry().translated(tlwOffset), Qt::red);
4911 }
4912
4913 // Cocoa only has rect granularity.
4914 #ifndef QT_OS_MAC
4915 void tst_QWidget::subtractOpaqueSiblings()
4916 {
4917     QWidget w;
4918     w.setGeometry(50, 50, 300, 300);
4919
4920     ColorWidget *large = new ColorWidget(&w, Qt::red);
4921     large->setGeometry(50, 50, 200, 200);
4922
4923     ColorWidget *medium = new ColorWidget(large, Qt::gray);
4924     medium->setGeometry(50, 50, 100, 100);
4925
4926     ColorWidget *tall = new ColorWidget(&w, Qt::blue);
4927     tall->setGeometry(100, 30, 50, 100);
4928
4929     w.show();
4930     QVERIFY(QTest::qWaitForWindowExposed(&w));
4931     QTest::qWait(10);
4932
4933     large->reset();
4934     medium->reset();
4935     tall->reset();
4936
4937     medium->update();
4938     QTest::qWait(10);
4939
4940     // QWidgetPrivate::subtractOpaqueSiblings() should prevent parts of medium
4941     // to be repainted and tall from be repainted at all.
4942
4943     QTRY_COMPARE(large->r, QRegion());
4944     QTRY_COMPARE(tall->r, QRegion());
4945     QTRY_COMPARE(medium->r.translated(medium->mapTo(&w, QPoint())),
4946              QRegion(medium->geometry().translated(large->pos()))
4947              - tall->geometry());
4948 }
4949 #endif
4950
4951 void tst_QWidget::deleteStyle()
4952 {
4953     QWidget widget;
4954     widget.setStyle(QStyleFactory::create(QLatin1String("Windows")));
4955     widget.show();
4956     delete widget.style();
4957     qApp->processEvents();
4958 }
4959
4960 class TopLevelFocusCheck: public QWidget
4961 {
4962     Q_OBJECT
4963 public:
4964     QLineEdit* edit;
4965     TopLevelFocusCheck(QWidget* parent = 0) : QWidget(parent)
4966     {
4967         edit = new QLineEdit(this);
4968         edit->hide();
4969         edit->installEventFilter(this);
4970     }
4971
4972 public slots:
4973     void mouseDoubleClickEvent ( QMouseEvent * /*event*/ )
4974     {
4975         edit->show();
4976         edit->setFocus(Qt::OtherFocusReason);
4977         qApp->processEvents();
4978     }
4979     bool eventFilter(QObject *obj, QEvent *event)
4980     {
4981         if (obj == edit && event->type()== QEvent::FocusOut) {
4982             edit->hide();
4983             return true;
4984         }
4985         return false;
4986     }
4987 };
4988
4989 void tst_QWidget::multipleToplevelFocusCheck()
4990 {
4991     TopLevelFocusCheck w1;
4992     TopLevelFocusCheck w2;
4993
4994     w1.resize(200, 200);
4995     w1.show();
4996     QVERIFY(QTest::qWaitForWindowExposed(&w1));
4997     w2.resize(200,200);
4998     w2.show();
4999     QVERIFY(QTest::qWaitForWindowExposed(&w2));
5000
5001     QApplication::setActiveWindow(&w1);
5002     w1.activateWindow();
5003     QVERIFY(QTest::qWaitForWindowActive(&w1));
5004     QCOMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&w1));
5005     QTest::qWait(50);
5006     QTest::mouseDClick(&w1, Qt::LeftButton);
5007     QTRY_COMPARE(QApplication::focusWidget(), static_cast<QWidget *>(w1.edit));
5008
5009     w2.activateWindow();
5010     QApplication::setActiveWindow(&w2);
5011     QVERIFY(QTest::qWaitForWindowActive(&w2));
5012     QCOMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&w2));
5013     QTest::mouseClick(&w2, Qt::LeftButton);
5014     QTRY_COMPARE(QApplication::focusWidget(), (QWidget *)0);
5015
5016     QTest::mouseDClick(&w2, Qt::LeftButton);
5017     QTRY_COMPARE(QApplication::focusWidget(), static_cast<QWidget *>(w2.edit));
5018
5019     w1.activateWindow();
5020     QApplication::setActiveWindow(&w1);
5021     QVERIFY(QTest::qWaitForWindowActive(&w1));
5022     QCOMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&w1));
5023     QTest::mouseDClick(&w1, Qt::LeftButton);
5024     QTRY_COMPARE(QApplication::focusWidget(), static_cast<QWidget *>(w1.edit));
5025
5026     w2.activateWindow();
5027     QApplication::setActiveWindow(&w2);
5028     QVERIFY(QTest::qWaitForWindowActive(&w2));
5029     QCOMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&w2));
5030     QTest::mouseClick(&w2, Qt::LeftButton);
5031     QTRY_COMPARE(QApplication::focusWidget(), (QWidget *)0);
5032 }
5033
5034 class FocusWidget: public QWidget
5035 {
5036 protected:
5037     virtual bool event(QEvent *ev)
5038     {
5039         if (ev->type() == QEvent::FocusAboutToChange)
5040             widgetDuringFocusAboutToChange = qApp->focusWidget();
5041         return QWidget::event(ev);
5042     }
5043     virtual void focusOutEvent(QFocusEvent *)
5044     {
5045         widgetDuringFocusOut = qApp->focusWidget();
5046     }
5047
5048 public:
5049     FocusWidget(QWidget *parent) : QWidget(parent), widgetDuringFocusAboutToChange(0), widgetDuringFocusOut(0) {}
5050
5051     QWidget *widgetDuringFocusAboutToChange;
5052     QWidget *widgetDuringFocusOut;
5053 };
5054
5055 void tst_QWidget::setFocus()
5056 {
5057     {
5058         // move focus to another window
5059         testWidget->activateWindow();
5060         QApplication::setActiveWindow(testWidget);
5061         if (testWidget->focusWidget())
5062             testWidget->focusWidget()->clearFocus();
5063         else
5064             testWidget->clearFocus();
5065
5066         // window and children never shown, nobody gets focus
5067         QWidget window;
5068         window.resize(200, 200);
5069
5070         QWidget child1(&window);
5071         child1.setFocusPolicy(Qt::StrongFocus);
5072
5073         QWidget child2(&window);
5074         child2.setFocusPolicy(Qt::StrongFocus);
5075
5076         child1.setFocus();
5077         QVERIFY(!child1.hasFocus());
5078         QCOMPARE(window.focusWidget(), &child1);
5079         QCOMPARE(QApplication::focusWidget(), static_cast<QWidget *>(0));
5080
5081         child2.setFocus();
5082         QVERIFY(!child2.hasFocus());
5083         QCOMPARE(window.focusWidget(), &child2);
5084         QCOMPARE(QApplication::focusWidget(), static_cast<QWidget *>(0));
5085     }
5086
5087     {
5088         // window and children show, but window not active, nobody gets focus
5089         QWidget window;
5090         window.resize(200, 200);
5091
5092         QWidget child1(&window);
5093         child1.setFocusPolicy(Qt::StrongFocus);
5094
5095         QWidget child2(&window);
5096         child2.setFocusPolicy(Qt::StrongFocus);
5097
5098         window.show();
5099
5100         // note: window may be active, but we don't want it to be
5101         testWidget->activateWindow();
5102         QApplication::setActiveWindow(testWidget);
5103         if (testWidget->focusWidget())
5104             testWidget->focusWidget()->clearFocus();
5105         else
5106             testWidget->clearFocus();
5107
5108         child1.setFocus();
5109         QVERIFY(!child1.hasFocus());
5110         QCOMPARE(window.focusWidget(), &child1);
5111         QCOMPARE(QApplication::focusWidget(), static_cast<QWidget *>(0));
5112
5113         child2.setFocus();
5114         QVERIFY(!child2.hasFocus());
5115         QCOMPARE(window.focusWidget(), &child2);
5116         QCOMPARE(QApplication::focusWidget(), static_cast<QWidget *>(0));
5117     }
5118
5119     {
5120         // window and children show, but window *is* active, children get focus
5121         QWidget window;
5122         window.resize(200, 200);
5123
5124         FocusWidget child1(&window);
5125         child1.setFocusPolicy(Qt::StrongFocus);
5126
5127         QWidget child2(&window);
5128         child2.setFocusPolicy(Qt::StrongFocus);
5129
5130         window.show();
5131         window.activateWindow();
5132         QVERIFY(QTest::qWaitForWindowExposed(&window));
5133         QTRY_VERIFY(qGuiApp->focusWindow());
5134
5135         child1.setFocus();
5136         QTRY_VERIFY(child1.hasFocus());
5137         QCOMPARE(window.focusWidget(), &child1);
5138         QCOMPARE(QApplication::focusWidget(), &child1);
5139
5140         child2.setFocus();
5141         QVERIFY(child2.hasFocus());
5142         QCOMPARE(window.focusWidget(), &child2);
5143         QCOMPARE(QApplication::focusWidget(), &child2);
5144
5145         // focus changed in between the events
5146         QCOMPARE(child1.widgetDuringFocusAboutToChange, &child1);
5147         QCOMPARE(child1.widgetDuringFocusOut, &child2);
5148     }
5149
5150     {
5151         // window shown and active, children created, don't get focus, but get focus when shown
5152         QWidget window;
5153         window.resize(200, 200);
5154
5155         window.show();
5156         window.activateWindow();
5157         QVERIFY(QTest::qWaitForWindowExposed(&window));
5158         QTRY_VERIFY(qGuiApp->focusWindow());
5159
5160         QWidget child1(&window);
5161         child1.setFocusPolicy(Qt::StrongFocus);
5162
5163         QWidget child2(&window);
5164         child2.setFocusPolicy(Qt::StrongFocus);
5165
5166         child1.setFocus();
5167         QVERIFY(!child1.hasFocus());
5168         QCOMPARE(window.focusWidget(), static_cast<QWidget *>(0));
5169         QCOMPARE(QApplication::focusWidget(), static_cast<QWidget *>(0));
5170
5171         child1.show();
5172         QApplication::processEvents();
5173         QTRY_VERIFY(child1.hasFocus());
5174         QCOMPARE(window.focusWidget(), &child1);
5175         QCOMPARE(QApplication::focusWidget(), &child1);
5176
5177         child2.setFocus();
5178         QVERIFY(!child2.hasFocus());
5179         QCOMPARE(window.focusWidget(), &child1);
5180         QCOMPARE(QApplication::focusWidget(), &child1);
5181
5182         child2.show();
5183         QVERIFY(child2.hasFocus());
5184         QCOMPARE(window.focusWidget(), &child2);
5185         QCOMPARE(QApplication::focusWidget(), &child2);
5186     }
5187
5188     {
5189         // window shown and active, children created, don't get focus,
5190         // even after setFocus(), hide(), then show()
5191         QWidget window;
5192         window.resize(200, 200);
5193
5194         window.show();
5195         window.activateWindow();
5196         QVERIFY(QTest::qWaitForWindowExposed(&window));
5197         QTRY_VERIFY(qGuiApp->focusWindow());
5198
5199         QWidget child1(&window);
5200         child1.setFocusPolicy(Qt::StrongFocus);
5201
5202         QWidget child2(&window);
5203         child2.setFocusPolicy(Qt::StrongFocus);
5204
5205         child1.setFocus();
5206         QVERIFY(!child1.hasFocus());
5207         QCOMPARE(window.focusWidget(), static_cast<QWidget *>(0));
5208         QCOMPARE(QApplication::focusWidget(), static_cast<QWidget *>(0));
5209
5210         child1.hide();
5211         QVERIFY(!child1.hasFocus());
5212         QCOMPARE(window.focusWidget(), static_cast<QWidget *>(0));
5213         QCOMPARE(QApplication::focusWidget(), static_cast<QWidget *>(0));
5214
5215         child1.show();
5216         QVERIFY(!child1.hasFocus());
5217         QCOMPARE(window.focusWidget(), static_cast<QWidget *>(0));
5218         QCOMPARE(QApplication::focusWidget(), static_cast<QWidget *>(0));
5219
5220         child2.setFocus();
5221         QVERIFY(!child2.hasFocus());
5222         QCOMPARE(window.focusWidget(), static_cast<QWidget *>(0));
5223         QCOMPARE(QApplication::focusWidget(), static_cast<QWidget *>(0));
5224
5225         child2.hide();
5226         QVERIFY(!child2.hasFocus());
5227         QCOMPARE(window.focusWidget(), static_cast<QWidget *>(0));
5228         QCOMPARE(QApplication::focusWidget(), static_cast<QWidget *>(0));
5229
5230         child2.show();
5231         QVERIFY(!child2.hasFocus());
5232         QCOMPARE(window.focusWidget(), static_cast<QWidget *>(0));
5233         QCOMPARE(QApplication::focusWidget(), static_cast<QWidget *>(0));
5234     }
5235 }
5236
5237 class EventSpy : public QObject
5238 {
5239 public:
5240     EventSpy(QWidget *widget, QEvent::Type event)
5241         : m_widget(widget), eventToSpy(event), m_count(0)
5242     {
5243         if (m_widget)
5244             m_widget->installEventFilter(this);
5245     }
5246
5247     QWidget *widget() const { return m_widget; }
5248     int count() const { return m_count; }
5249     void clear() { m_count = 0; }
5250
5251 protected:
5252     bool eventFilter(QObject *object, QEvent *event)
5253     {
5254         if (event->type() == eventToSpy)
5255             ++m_count;
5256         return  QObject::eventFilter(object, event);
5257     }
5258
5259 private:
5260     QWidget *m_widget;
5261     QEvent::Type eventToSpy;
5262     int m_count;
5263 };
5264
5265 #ifndef QTEST_NO_CURSOR
5266 void tst_QWidget::setCursor()
5267 {
5268     {
5269         QWidget window;
5270         window.resize(200, 200);
5271         QWidget child(&window);
5272
5273         QVERIFY(!window.testAttribute(Qt::WA_SetCursor));
5274         QVERIFY(!child.testAttribute(Qt::WA_SetCursor));
5275
5276         window.setCursor(window.cursor());
5277         QVERIFY(window.testAttribute(Qt::WA_SetCursor));
5278         QVERIFY(!child.testAttribute(Qt::WA_SetCursor));
5279         QCOMPARE(child.cursor().shape(), window.cursor().shape());
5280     }
5281
5282     // do it again, but with window show()n
5283     {
5284         QWidget window;
5285         window.resize(200, 200);
5286         QWidget child(&window);
5287         window.show();
5288
5289         QVERIFY(!window.testAttribute(Qt::WA_SetCursor));
5290         QVERIFY(!child.testAttribute(Qt::WA_SetCursor));
5291
5292         window.setCursor(window.cursor());
5293         QVERIFY(window.testAttribute(Qt::WA_SetCursor));
5294         QVERIFY(!child.testAttribute(Qt::WA_SetCursor));
5295         QCOMPARE(child.cursor().shape(), window.cursor().shape());
5296     }
5297
5298
5299     {
5300         QWidget window;
5301         window.resize(200, 200);
5302         QWidget child(&window);
5303
5304         window.setCursor(Qt::WaitCursor);
5305         QVERIFY(window.testAttribute(Qt::WA_SetCursor));
5306         QVERIFY(!child.testAttribute(Qt::WA_SetCursor));
5307         QCOMPARE(child.cursor().shape(), window.cursor().shape());
5308     }
5309
5310     // same thing again, just with window show()n
5311     {
5312         QWidget window;
5313         window.resize(200, 200);
5314         QWidget child(&window);
5315
5316         window.show();
5317         QVERIFY(QTest::qWaitForWindowExposed(&window));
5318         window.setCursor(Qt::WaitCursor);
5319         QVERIFY(window.testAttribute(Qt::WA_SetCursor));
5320         QVERIFY(!child.testAttribute(Qt::WA_SetCursor));
5321         QCOMPARE(child.cursor().shape(), window.cursor().shape());
5322     }
5323
5324     // reparenting child should not cause the WA_SetCursor to become set
5325     {
5326         QWidget window;
5327         window.resize(200, 200);
5328         QWidget window2;
5329         window2.resize(200, 200);
5330         QWidget child(&window);
5331
5332         window.setCursor(Qt::WaitCursor);
5333
5334         child.setParent(0);
5335         QVERIFY(!child.testAttribute(Qt::WA_SetCursor));
5336         QCOMPARE(child.cursor().shape(), QCursor().shape());
5337
5338         child.setParent(&window2);
5339         QVERIFY(!child.testAttribute(Qt::WA_SetCursor));
5340         QCOMPARE(child.cursor().shape(), window2.cursor().shape());
5341
5342             window2.setCursor(Qt::WaitCursor);
5343         QVERIFY(!child.testAttribute(Qt::WA_SetCursor));
5344         QCOMPARE(child.cursor().shape(), window2.cursor().shape());
5345     }
5346
5347     // again, with windows show()n
5348     {
5349         QWidget window;
5350         window.resize(200, 200);
5351         QWidget window2;
5352         window2.resize(200, 200);
5353         QWidget child(&window);
5354
5355         window.setCursor(Qt::WaitCursor);
5356         window.show();
5357
5358         child.setParent(0);
5359         QVERIFY(!child.testAttribute(Qt::WA_SetCursor));
5360         QCOMPARE(child.cursor().shape(), QCursor().shape());
5361
5362         child.setParent(&window2);
5363         QVERIFY(!child.testAttribute(Qt::WA_SetCursor));
5364         QCOMPARE(child.cursor().shape(), window2.cursor().shape());
5365
5366         window2.show();
5367         window2.setCursor(Qt::WaitCursor);
5368         QVERIFY(!child.testAttribute(Qt::WA_SetCursor));
5369         QCOMPARE(child.cursor().shape(), window2.cursor().shape());
5370     }
5371
5372     // test if CursorChange is sent
5373     {
5374         QWidget widget;
5375         EventSpy spy(&widget, QEvent::CursorChange);
5376         QCOMPARE(spy.count(), 0);
5377         widget.setCursor(QCursor(Qt::WaitCursor));
5378         QCOMPARE(spy.count(), 1);
5379         widget.unsetCursor();
5380         QCOMPARE(spy.count(), 2);
5381     }
5382 }
5383 #endif
5384
5385 void tst_QWidget::setToolTip()
5386 {
5387     QWidget widget;
5388     widget.resize(200, 200);
5389     // Showing the widget is not required for the tooltip event count test
5390     // to work. It should just prevent the application from becoming inactive
5391     // which would cause it to close all popups, interfering with the test
5392     // in the loop below.
5393     widget.setObjectName(QLatin1String("tst_qwidget setToolTip"));
5394     widget.setWindowTitle(widget.objectName());
5395     widget.show();
5396     QVERIFY(QTest::qWaitForWindowExposed(&widget));
5397     EventSpy spy(&widget, QEvent::ToolTipChange);
5398     QCOMPARE(spy.count(), 0);
5399
5400     QCOMPARE(widget.toolTip(), QString());
5401     widget.setToolTip(QString("Hello"));
5402     QCOMPARE(widget.toolTip(), QString("Hello"));
5403     QCOMPARE(spy.count(), 1);
5404     widget.setToolTip(QString());
5405     QCOMPARE(widget.toolTip(), QString());
5406     QCOMPARE(spy.count(), 2);
5407
5408     // Mouse over doesn't work on Windows mobile, so skip the rest of the test for that platform.
5409 #ifndef Q_OS_WINCE_WM
5410     for (int pass = 0; pass < 2; ++pass) {
5411         QCursor::setPos(0, 0);
5412         QScopedPointer<QWidget> popup(new QWidget(0, Qt::Popup));
5413         popup->setObjectName(QString::fromLatin1("tst_qwidget setToolTip #%1").arg(pass));
5414         popup->setWindowTitle(popup->objectName());
5415         popup->resize(150, 50);
5416         QFrame *frame = new QFrame(popup.data());
5417         frame->setGeometry(0, 0, 50, 50);
5418         frame->setFrameStyle(QFrame::Box | QFrame::Plain);
5419         EventSpy spy1(frame, QEvent::ToolTip);
5420         EventSpy spy2(popup.data(), QEvent::ToolTip);
5421         frame->setMouseTracking(pass == 0 ? false : true);
5422         frame->setToolTip(QLatin1String("TOOLTIP FRAME"));
5423         popup->setToolTip(QLatin1String("TOOLTIP POPUP"));
5424         popup->show();
5425         QVERIFY(QTest::qWaitForWindowExposed(popup.data()));
5426         QWindow *popupWindow = popup->windowHandle();
5427         QTest::qWait(10);
5428         QTest::mouseMove(popupWindow, QPoint(25, 25));
5429         QTest::qWait(900);          // delay is 700
5430
5431         QCOMPARE(spy1.count(), 1);
5432         QCOMPARE(spy2.count(), 0);
5433         if (pass == 0)
5434             QTest::qWait(2200);     // delay is 2000
5435         QTest::mouseMove(popupWindow);
5436     }
5437 #endif
5438 }
5439
5440 void tst_QWidget::testWindowIconChangeEventPropagation()
5441 {
5442     typedef QSharedPointer<EventSpy> EventSpyPtr;
5443     // Create widget hierarchy.
5444     QWidget topLevelWidget;
5445     QWidget topLevelChild(&topLevelWidget);
5446
5447     QDialog dialog(&topLevelWidget);
5448     QWidget dialogChild(&dialog);
5449
5450     QWidgetList widgets;
5451     widgets << &topLevelWidget << &topLevelChild
5452             << &dialog << &dialogChild;
5453     QCOMPARE(widgets.count(), 4);
5454
5455     // Create spy lists.
5456     QList <EventSpyPtr> applicationEventSpies;
5457     QList <EventSpyPtr> widgetEventSpies;
5458     foreach (QWidget *widget, widgets) {
5459         applicationEventSpies.append(EventSpyPtr(new EventSpy(widget, QEvent::ApplicationWindowIconChange)));
5460         widgetEventSpies.append(EventSpyPtr(new EventSpy(widget, QEvent::WindowIconChange)));
5461     }
5462
5463     // QApplication::setWindowIcon
5464     const QIcon windowIcon = qApp->style()->standardIcon(QStyle::SP_TitleBarMenuButton);
5465     qApp->setWindowIcon(windowIcon);
5466
5467     for (int i = 0; i < widgets.count(); ++i) {
5468         // Check QEvent::ApplicationWindowIconChange
5469         EventSpyPtr spy = applicationEventSpies.at(i);
5470         QWidget *widget = spy->widget();
5471         if (widget->isWindow()) {
5472             QCOMPARE(spy->count(), 1);
5473             QCOMPARE(widget->windowIcon(), windowIcon);
5474         } else {
5475             QCOMPARE(spy->count(), 0);
5476         }
5477         spy->clear();
5478
5479         // Check QEvent::WindowIconChange
5480         spy = widgetEventSpies.at(i);
5481         QCOMPARE(spy->count(), 1);
5482         spy->clear();
5483     }
5484
5485     // Set icon on a top-level widget.
5486     topLevelWidget.setWindowIcon(QIcon());
5487
5488     for (int i = 0; i < widgets.count(); ++i) {
5489         // Check QEvent::ApplicationWindowIconChange
5490         EventSpyPtr spy = applicationEventSpies.at(i);
5491         QCOMPARE(spy->count(), 0);
5492         spy->clear();
5493
5494         // Check QEvent::WindowIconChange
5495         spy = widgetEventSpies.at(i);
5496         QWidget *widget = spy->widget();
5497         if (widget == &topLevelWidget) {
5498             QCOMPARE(widget->windowIcon(), QIcon());
5499             QCOMPARE(spy->count(), 1);
5500         } else if (topLevelWidget.isAncestorOf(widget)) {
5501             QCOMPARE(spy->count(), 1);
5502         } else {
5503             QCOMPARE(spy->count(), 0);
5504         }
5505         spy->clear();
5506     }
5507
5508     // Cleanup.
5509     qApp->setWindowIcon(QIcon());
5510 }
5511
5512 void tst_QWidget::minAndMaxSizeWithX11BypassWindowManagerHint()
5513 {
5514     if (m_platform != QStringLiteral("xcb"))
5515         QSKIP("This test is for X11 only.");
5516     // Same size as in QWidget::create_sys().
5517     const QSize desktopSize = QApplication::desktop()->size();
5518     const QSize originalSize(desktopSize.width() / 2, desktopSize.height() * 4 / 10);
5519
5520     { // Maximum size.
5521     QWidget widget(0, Qt::X11BypassWindowManagerHint);
5522
5523     const QSize newMaximumSize = widget.size().boundedTo(originalSize) - QSize(10, 10);
5524     widget.setMaximumSize(newMaximumSize);
5525     QCOMPARE(widget.size(), newMaximumSize);
5526
5527     widget.show();
5528     QVERIFY(QTest::qWaitForWindowExposed(&widget));
5529     QCOMPARE(widget.size(), newMaximumSize);
5530     }
5531
5532     { // Minimum size.
5533     QWidget widget(0, Qt::X11BypassWindowManagerHint);
5534
5535     const QSize newMinimumSize = widget.size().expandedTo(originalSize) + QSize(10, 10);
5536     widget.setMinimumSize(newMinimumSize);
5537     QCOMPARE(widget.size(), newMinimumSize);
5538
5539     widget.show();
5540     QVERIFY(QTest::qWaitForWindowExposed(&widget));
5541     QCOMPARE(widget.size(), newMinimumSize);
5542     }
5543 }
5544
5545 class ShowHideShowWidget : public QWidget, public QAbstractNativeEventFilter
5546 {
5547     Q_OBJECT
5548
5549     int state;
5550 public:
5551     bool gotExpectedMapNotify;
5552     bool gotExpectedGlobalEvent;
5553
5554     ShowHideShowWidget()
5555         : state(0), gotExpectedMapNotify(false), gotExpectedGlobalEvent(false)
5556     {
5557         startTimer(1000);
5558     }
5559
5560     void timerEvent(QTimerEvent *)
5561     {
5562         switch (state++) {
5563         case 0:
5564             show();
5565             break;
5566         case 1:
5567             emit done();
5568             break;
5569         }
5570     }
5571
5572     bool isMapNotify(const QByteArray &eventType, void *message)
5573     {
5574         enum { XCB_MAP_NOTIFY = 19 };
5575         if (state == 1 && eventType == QByteArrayLiteral("xcb_generic_event_t")) {
5576             // XCB events have a uint8 response_type member at the beginning.
5577             const unsigned char responseType = *(const unsigned char *)(message);
5578             return ((responseType & ~0x80) == XCB_MAP_NOTIFY);
5579         }
5580         return false;
5581     }
5582
5583     bool nativeEvent(const QByteArray &eventType, void *message, long *)
5584     {
5585         if (isMapNotify(eventType, message))
5586             gotExpectedMapNotify = true;
5587         return false;
5588     }
5589
5590     // QAbstractNativeEventFilter interface
5591     virtual bool nativeEventFilter(const QByteArray &eventType, void *message, long *) Q_DECL_OVERRIDE
5592     {
5593         if (isMapNotify(eventType, message))
5594             gotExpectedGlobalEvent = true;
5595         return false;
5596     }
5597
5598 signals:
5599     void done();
5600 };
5601
5602 void tst_QWidget::showHideShowX11()
5603 {
5604     if (m_platform != QStringLiteral("xcb"))
5605         QSKIP("This test is for X11 only.");
5606
5607     ShowHideShowWidget w;
5608     qApp->installNativeEventFilter(&w);
5609
5610     w.show();
5611     w.hide();
5612
5613     QEventLoop eventLoop;
5614     connect(&w, SIGNAL(done()), &eventLoop, SLOT(quit()));
5615     eventLoop.exec();
5616
5617     QVERIFY(w.gotExpectedGlobalEvent);
5618     QVERIFY(w.gotExpectedMapNotify);
5619 }
5620
5621 void tst_QWidget::clean_qt_x11_enforce_cursor()
5622 {
5623     if (m_platform != QStringLiteral("xcb"))
5624         QSKIP("This test is for X11 only.");
5625
5626     {
5627         QWidget window;
5628         QWidget *w = new QWidget(&window);
5629         QWidget *child = new QWidget(w);
5630         child->setAttribute(Qt::WA_SetCursor, true);
5631
5632         window.show();
5633         QApplication::setActiveWindow(&window);
5634         QVERIFY(QTest::qWaitForWindowActive(&window));
5635         QTest::qWait(100);
5636         QCursor::setPos(window.geometry().center());
5637         QTest::qWait(100);
5638
5639         child->setFocus();
5640         QApplication::processEvents();
5641         QTest::qWait(100);
5642
5643         delete w;
5644     }
5645
5646     QGraphicsScene scene;
5647     QLineEdit *edit = new QLineEdit;
5648     scene.addWidget(edit);
5649
5650     // If the test didn't crash, then it passed.
5651 }
5652
5653 class EventRecorder : public QObject
5654 {
5655     Q_OBJECT
5656
5657 public:
5658     typedef QPair<QWidget *, QEvent::Type> WidgetEventTypePair;
5659     typedef QList<WidgetEventTypePair> EventList;
5660
5661     EventRecorder(QObject *parent = 0)
5662         : QObject(parent)
5663     { }
5664
5665     EventList eventList()
5666     {
5667         return events;
5668     }
5669
5670     void clear()
5671     {
5672         events.clear();
5673     }
5674
5675     bool eventFilter(QObject *object, QEvent *event)
5676     {
5677         QWidget *widget = qobject_cast<QWidget *>(object);
5678         if (widget && !event->spontaneous())
5679             events.append(qMakePair(widget, event->type()));
5680         return false;
5681     }
5682
5683     static QByteArray msgEventListMismatch(const EventList &expected, const EventList &actual);
5684     static QByteArray msgExpectFailQtBug26424(const EventList &expected, const EventList &actual)
5685     { return QByteArrayLiteral("QTBUG-26424: ") + msgEventListMismatch(expected, actual); }
5686
5687 private:
5688     static inline void formatEventList(const EventList &l, QDebug &d);
5689
5690     EventList events;
5691 };
5692
5693 void EventRecorder::formatEventList(const EventList &l, QDebug &d)
5694 {
5695     QWidget *lastWidget = 0;
5696     foreach (const WidgetEventTypePair &p, l) {
5697         if (p.first != lastWidget) {
5698             d << p.first << ':';
5699             lastWidget = p.first;
5700         }
5701         d << p.second << ' ';
5702     }
5703 }
5704
5705 QByteArray EventRecorder::msgEventListMismatch(const EventList &expected, const EventList &actual)
5706 {
5707     QString result;
5708     QDebug d = QDebug(&result).nospace();
5709     d << "Event list mismatch, expected " << expected.size() << " (";
5710     EventRecorder::formatEventList(expected, d);
5711     d << "), actual " << actual.size() << " (";
5712     EventRecorder::formatEventList(actual, d);
5713     d << ')';
5714     return result.toLocal8Bit();
5715 }
5716
5717 void tst_QWidget::childEvents()
5718 {
5719     EventRecorder::EventList expected;
5720
5721     // Move away the cursor; otherwise it might result in an enter event if it's
5722     // inside the widget when the widget is shown.
5723     QCursor::setPos(qApp->desktop()->availableGeometry().bottomRight());
5724     QTest::qWait(100);
5725
5726     {
5727         // no children created, not shown
5728         QWidget widget;
5729         EventRecorder spy;
5730         widget.installEventFilter(&spy);
5731
5732         QCoreApplication::postEvent(&widget, new QEvent(QEvent::Type(QEvent::User + 1)));
5733
5734         QCoreApplication::sendPostedEvents();
5735
5736         expected =
5737             EventRecorder::EventList()
5738             << qMakePair(&widget, QEvent::PolishRequest)
5739             << qMakePair(&widget, QEvent::Polish)
5740             << qMakePair(&widget, QEvent::Type(QEvent::User + 1));
5741         QVERIFY2(spy.eventList() == expected,
5742                  EventRecorder::msgEventListMismatch(expected, spy.eventList()).constData());
5743     }
5744
5745     {
5746         // no children, shown
5747         QWidget widget;
5748         EventRecorder spy;
5749         widget.installEventFilter(&spy);
5750
5751         QCoreApplication::postEvent(&widget, new QEvent(QEvent::Type(QEvent::User + 1)));
5752
5753         widget.show();
5754         expected =
5755             EventRecorder::EventList()
5756             << qMakePair(&widget, QEvent::WinIdChange)
5757             << qMakePair(&widget, QEvent::Polish)
5758             << qMakePair(&widget, QEvent::Move)
5759             << qMakePair(&widget, QEvent::Resize)
5760             << qMakePair(&widget, QEvent::Show);
5761
5762         expected << qMakePair(&widget, QEvent::ShowToParent);
5763
5764         QVERIFY2(spy.eventList() == expected,
5765                  EventRecorder::msgEventListMismatch(expected, spy.eventList()).constData());
5766         spy.clear();
5767
5768         QCoreApplication::sendPostedEvents();
5769         expected =
5770             EventRecorder::EventList()
5771             << qMakePair(&widget, QEvent::PolishRequest)
5772             << qMakePair(&widget, QEvent::Type(QEvent::User + 1));
5773
5774 #ifdef Q_OS_MAC
5775         expected << qMakePair(&widget, QEvent::UpdateLater);
5776 #endif
5777         expected << qMakePair(&widget, QEvent::UpdateRequest);
5778
5779         if (m_platform == QStringLiteral("windows") || m_platform == QStringLiteral("xcb"))
5780             QEXPECT_FAIL("", EventRecorder::msgExpectFailQtBug26424(expected, spy.eventList()).constData(), Continue);
5781         QVERIFY2(spy.eventList() == expected,
5782                  EventRecorder::msgEventListMismatch(expected, spy.eventList()).constData());
5783     }
5784
5785     {
5786         // 2 children, not shown
5787         QWidget widget;
5788         EventRecorder spy;
5789         widget.installEventFilter(&spy);
5790
5791         QCoreApplication::postEvent(&widget, new QEvent(QEvent::Type(QEvent::User + 1)));
5792
5793         QWidget child1(&widget);
5794         QWidget child2;
5795         child2.setParent(&widget);
5796
5797         QCoreApplication::postEvent(&widget, new QEvent(QEvent::Type(QEvent::User + 2)));
5798
5799         expected =
5800             EventRecorder::EventList()
5801             << qMakePair(&widget, QEvent::ChildAdded)
5802             << qMakePair(&widget, QEvent::ChildAdded);
5803         QVERIFY2(spy.eventList() == expected,
5804                  EventRecorder::msgEventListMismatch(expected, spy.eventList()).constData());
5805         spy.clear();
5806
5807         QCoreApplication::sendPostedEvents();
5808         expected =
5809             EventRecorder::EventList()
5810             << qMakePair(&widget, QEvent::PolishRequest)
5811             << qMakePair(&widget, QEvent::Polish)
5812             << qMakePair(&widget, QEvent::ChildPolished)
5813             << qMakePair(&widget, QEvent::ChildPolished)
5814             << qMakePair(&widget, QEvent::Type(QEvent::User + 1))
5815             << qMakePair(&widget, QEvent::Type(QEvent::User + 2));
5816         QVERIFY2(spy.eventList() == expected,
5817                  EventRecorder::msgEventListMismatch(expected, spy.eventList()).constData());
5818     }
5819
5820     {
5821         // 2 children, widget shown
5822         QWidget widget;
5823         EventRecorder spy;
5824         widget.installEventFilter(&spy);
5825
5826         QCoreApplication::postEvent(&widget, new QEvent(QEvent::Type(QEvent::User + 1)));
5827
5828         QWidget child1(&widget);
5829         QWidget child2;
5830         child2.setParent(&widget);
5831
5832         QCoreApplication::postEvent(&widget, new QEvent(QEvent::Type(QEvent::User + 2)));
5833
5834         expected =
5835             EventRecorder::EventList()
5836             << qMakePair(&widget, QEvent::ChildAdded)
5837             << qMakePair(&widget, QEvent::ChildAdded);
5838         QCOMPARE(spy.eventList(), expected);
5839         spy.clear();
5840
5841         widget.show();
5842         expected =
5843             EventRecorder::EventList()
5844             << qMakePair(&widget, QEvent::WinIdChange)
5845             << qMakePair(&widget, QEvent::Polish)
5846             << qMakePair(&widget, QEvent::ChildPolished)
5847             << qMakePair(&widget, QEvent::ChildPolished)
5848             << qMakePair(&widget, QEvent::Move)
5849             << qMakePair(&widget, QEvent::Resize)
5850             << qMakePair(&widget, QEvent::Show);
5851
5852         expected << qMakePair(&widget, QEvent::ShowToParent);
5853
5854         QVERIFY2(spy.eventList() == expected,
5855                  EventRecorder::msgEventListMismatch(expected, spy.eventList()).constData());
5856         spy.clear();
5857
5858         QCoreApplication::sendPostedEvents();
5859         expected =
5860             EventRecorder::EventList()
5861             << qMakePair(&widget, QEvent::PolishRequest)
5862             << qMakePair(&widget, QEvent::Type(QEvent::User + 1))
5863             << qMakePair(&widget, QEvent::Type(QEvent::User + 2));
5864
5865 #ifdef Q_OS_MAC
5866         expected << qMakePair(&widget, QEvent::UpdateLater);
5867 #endif
5868         expected << qMakePair(&widget, QEvent::UpdateRequest);
5869
5870         if (m_platform == QStringLiteral("windows") || m_platform == QStringLiteral("xcb"))
5871             QEXPECT_FAIL("", EventRecorder::msgExpectFailQtBug26424(expected, spy.eventList()).constData(), Continue);
5872         QVERIFY2(spy.eventList() == expected,
5873                  EventRecorder::msgEventListMismatch(expected, spy.eventList()).constData());
5874     }
5875
5876     {
5877         // 2 children, but one is reparented away, not shown
5878         QWidget widget;
5879         EventRecorder spy;
5880         widget.installEventFilter(&spy);
5881
5882         QCoreApplication::postEvent(&widget, new QEvent(QEvent::Type(QEvent::User + 1)));
5883
5884         QWidget child1(&widget);
5885         QWidget child2;
5886         child2.setParent(&widget);
5887         child2.setParent(0);
5888
5889         QCoreApplication::postEvent(&widget, new QEvent(QEvent::Type(QEvent::User + 2)));
5890
5891         expected =
5892             EventRecorder::EventList()
5893             << qMakePair(&widget, QEvent::ChildAdded)
5894             << qMakePair(&widget, QEvent::ChildAdded)
5895             << qMakePair(&widget, QEvent::ChildRemoved);
5896         QCOMPARE(spy.eventList(), expected);
5897         spy.clear();
5898
5899         QCoreApplication::sendPostedEvents();
5900         expected =
5901             EventRecorder::EventList()
5902             << qMakePair(&widget, QEvent::PolishRequest)
5903             << qMakePair(&widget, QEvent::Polish)
5904             << qMakePair(&widget, QEvent::ChildPolished)
5905             << qMakePair(&widget, QEvent::Type(QEvent::User + 1))
5906             << qMakePair(&widget, QEvent::Type(QEvent::User + 2));
5907
5908         QVERIFY2(spy.eventList() == expected,
5909                  EventRecorder::msgEventListMismatch(expected, spy.eventList()).constData());
5910     }
5911
5912     {
5913         // 2 children, but one is reparented away, then widget is shown
5914         QWidget widget;
5915         EventRecorder spy;
5916         widget.installEventFilter(&spy);
5917
5918         QCoreApplication::postEvent(&widget, new QEvent(QEvent::Type(QEvent::User + 1)));
5919
5920         QWidget child1(&widget);
5921         QWidget child2;
5922         child2.setParent(&widget);
5923         child2.setParent(0);
5924
5925         QCoreApplication::postEvent(&widget, new QEvent(QEvent::Type(QEvent::User + 2)));
5926
5927         expected =
5928             EventRecorder::EventList()
5929             << qMakePair(&widget, QEvent::ChildAdded)
5930             << qMakePair(&widget, QEvent::ChildAdded)
5931             << qMakePair(&widget, QEvent::ChildRemoved);
5932         QCOMPARE(spy.eventList(), expected);
5933         spy.clear();
5934
5935         widget.show();
5936         expected =
5937             EventRecorder::EventList()
5938             << qMakePair(&widget, QEvent::WinIdChange)
5939             << qMakePair(&widget, QEvent::Polish)
5940             << qMakePair(&widget, QEvent::ChildPolished)
5941             << qMakePair(&widget, QEvent::Move)
5942             << qMakePair(&widget, QEvent::Resize)
5943             << qMakePair(&widget, QEvent::Show);
5944
5945         expected << qMakePair(&widget, QEvent::ShowToParent);
5946         QVERIFY2(spy.eventList() == expected,
5947                  EventRecorder::msgEventListMismatch(expected, spy.eventList()).constData());
5948         spy.clear();
5949
5950         QCoreApplication::sendPostedEvents();
5951         expected =
5952             EventRecorder::EventList()
5953             << qMakePair(&widget, QEvent::PolishRequest)
5954             << qMakePair(&widget, QEvent::Type(QEvent::User + 1))
5955             << qMakePair(&widget, QEvent::Type(QEvent::User + 2));
5956
5957 #ifdef Q_OS_MAC
5958         expected << qMakePair(&widget, QEvent::UpdateLater);
5959 #endif
5960         expected << qMakePair(&widget, QEvent::UpdateRequest);
5961
5962         if (m_platform == QStringLiteral("windows") || m_platform == QStringLiteral("xcb"))
5963             QEXPECT_FAIL("", EventRecorder::msgExpectFailQtBug26424(expected, spy.eventList()).constData(), Continue);
5964         QVERIFY2(spy.eventList() == expected,
5965                  EventRecorder::msgEventListMismatch(expected, spy.eventList()).constData());
5966     }
5967 }
5968
5969 class RenderWidget : public QWidget
5970 {
5971 public:
5972     RenderWidget(QWidget *source)
5973         : source(source), ellipse(false) {}
5974
5975     void setEllipseEnabled(bool enable = true)
5976     {
5977         ellipse = enable;
5978         update();
5979     }
5980
5981 protected:
5982     void paintEvent(QPaintEvent *)
5983     {
5984         if (ellipse) {
5985             QPainter painter(this);
5986             painter.fillRect(rect(), Qt::red);
5987             painter.end();
5988             QRegion regionToRender = QRegion(0, 0, source->width(), source->height() / 2,
5989                                              QRegion::Ellipse);
5990             source->render(this, QPoint(0, 30), regionToRender);
5991         } else {
5992             source->render(this);
5993         }
5994     }
5995
5996 private:
5997     QWidget *source;
5998     bool ellipse;
5999 };
6000
6001 void tst_QWidget::render()
6002 {
6003     return;
6004     QCalendarWidget source;
6005     // disable anti-aliasing to eliminate potential differences when subpixel antialiasing
6006     // is enabled on the screen
6007     QFont f;
6008     f.setStyleStrategy(QFont::NoAntialias);
6009     source.setFont(f);
6010     source.show();
6011     QVERIFY(QTest::qWaitForWindowExposed(&source));
6012
6013     // Render the entire source into target.
6014     RenderWidget target(&source);
6015     target.resize(source.size());
6016     target.show();
6017
6018     qApp->processEvents();
6019     qApp->sendPostedEvents();
6020     QTest::qWait(250);
6021
6022     const QImage sourceImage = source.grab(QRect(QPoint(0, 0), QSize(-1, -1))).toImage();
6023     qApp->processEvents();
6024     QImage targetImage = target.grab(QRect(QPoint(0, 0), QSize(-1, -1))).toImage();
6025     qApp->processEvents();
6026     QCOMPARE(sourceImage, targetImage);
6027
6028     // Fill target.rect() will Qt::red and render
6029     // QRegion(0, 0, source->width(), source->height() / 2, QRegion::Ellipse)
6030     // of source into target with offset (0, 30).
6031     target.setEllipseEnabled();
6032     qApp->processEvents();
6033     qApp->sendPostedEvents();
6034
6035     targetImage = target.grab(QRect(QPoint(0, 0), QSize(-1, -1))).toImage();
6036     QVERIFY(sourceImage != targetImage);
6037
6038     QCOMPARE(targetImage.pixel(target.width() / 2, 29), QColor(Qt::red).rgb());
6039     QCOMPARE(targetImage.pixel(target.width() / 2, 30), sourceImage.pixel(source.width() / 2, 0));
6040
6041     // Test that a child widget properly fills its background
6042     {
6043         QWidget window;
6044         window.resize(100, 100);
6045         // prevent custom styles
6046         window.setStyle(QStyleFactory::create(QLatin1String("Windows")));
6047         window.show();
6048         QVERIFY(QTest::qWaitForWindowExposed(&window));
6049         QWidget child(&window);
6050         child.resize(window.size());
6051         child.show();
6052
6053         qApp->processEvents();
6054         const QPixmap childPixmap = child.grab(QRect(QPoint(0, 0), QSize(-1, -1)));
6055         const QPixmap windowPixmap = window.grab(QRect(QPoint(0, 0), QSize(-1, -1)));
6056         QCOMPARE(childPixmap, windowPixmap);
6057     }
6058
6059     { // Check that the target offset is correct.
6060         QWidget widget;
6061         widget.resize(200, 200);
6062         widget.setAutoFillBackground(true);
6063         widget.setPalette(Qt::red);
6064         // prevent custom styles
6065         widget.setStyle(QStyleFactory::create(QLatin1String("Windows")));
6066         widget.show();
6067         QVERIFY(QTest::qWaitForWindowExposed(&widget));
6068         QImage image(widget.size(), QImage::Format_RGB32);
6069         image.fill(QColor(Qt::blue).rgb());
6070
6071         // Target offset (0, 0)
6072         widget.render(&image, QPoint(), QRect(20, 20, 100, 100));
6073         QCOMPARE(image.pixel(0, 0), QColor(Qt::red).rgb());
6074         QCOMPARE(image.pixel(99, 99), QColor(Qt::red).rgb());
6075         QCOMPARE(image.pixel(100, 100), QColor(Qt::blue).rgb());
6076
6077         // Target offset (20, 20).
6078         image.fill(QColor(Qt::blue).rgb());
6079         widget.render(&image, QPoint(20, 20), QRect(20, 20, 100, 100));
6080         QCOMPARE(image.pixel(0, 0), QColor(Qt::blue).rgb());
6081         QCOMPARE(image.pixel(19, 19), QColor(Qt::blue).rgb());
6082         QCOMPARE(image.pixel(20, 20), QColor(Qt::red).rgb());
6083         QCOMPARE(image.pixel(119, 119), QColor(Qt::red).rgb());
6084         QCOMPARE(image.pixel(120, 120), QColor(Qt::blue).rgb());
6085     }
6086 }
6087
6088 // On Windows the active palette is used instead of the inactive palette even
6089 // though the widget is invisible. This is probably related to task 178507/168682,
6090 // but for the renderInvisible test it doesn't matter, we're mostly interested
6091 // in testing the geometry so just workaround the palette issue for now.
6092 static void workaroundPaletteIssue(QWidget *widget)
6093 {
6094 #ifndef Q_OS_WIN
6095     return;
6096 #endif
6097     if (!widget)
6098         return;
6099
6100     QWidget *navigationBar = qFindChild<QWidget *>(widget, QLatin1String("qt_calendar_navigationbar"));
6101     QVERIFY(navigationBar);
6102
6103     QPalette palette = navigationBar->palette();
6104     const QColor background = palette.color(QPalette::Inactive, navigationBar->backgroundRole());
6105     const QColor highlightedText = palette.color(QPalette::Inactive, QPalette::HighlightedText);
6106     palette.setColor(QPalette::Active, navigationBar->backgroundRole(), background);
6107     palette.setColor(QPalette::Active, QPalette::HighlightedText, highlightedText);
6108     navigationBar->setPalette(palette);
6109 }
6110
6111 //#define RENDER_DEBUG
6112 void tst_QWidget::renderInvisible()
6113 {
6114     if (m_platform == QStringLiteral("xcb"))
6115         QSKIP("QTBUG-26424");
6116
6117     QScopedPointer<QCalendarWidget> calendar(new QCalendarWidget);
6118     // disable anti-aliasing to eliminate potential differences when subpixel antialiasing
6119     // is enabled on the screen
6120     QFont f;
6121     f.setStyleStrategy(QFont::NoAntialias);
6122     calendar->setFont(f);
6123     calendar->show();
6124     QVERIFY(QTest::qWaitForWindowExposed(calendar.data()));
6125
6126     // Create a dummy focus widget to get rid of focus rect in reference image.
6127     QLineEdit dummyFocusWidget;
6128     dummyFocusWidget.show();
6129     QVERIFY(QTest::qWaitForWindowExposed(&dummyFocusWidget));
6130     qApp->processEvents();
6131     QTest::qWait(120);
6132
6133     // Create normal reference image.
6134     const QSize calendarSize = calendar->size();
6135     QImage referenceImage(calendarSize, QImage::Format_ARGB32);
6136     calendar->render(&referenceImage);
6137 #ifdef RENDER_DEBUG
6138     referenceImage.save("referenceImage.png");
6139 #endif
6140     QVERIFY(!referenceImage.isNull());
6141
6142     // Create resized reference image.
6143     const QSize calendarSizeResized = calendar->size() + QSize(50, 50);
6144     calendar->resize(calendarSizeResized);
6145     qApp->processEvents();
6146     QTest::qWait(30);
6147     QImage referenceImageResized(calendarSizeResized, QImage::Format_ARGB32);
6148     calendar->render(&referenceImageResized);
6149 #ifdef RENDER_DEBUG
6150     referenceImageResized.save("referenceImageResized.png");
6151 #endif
6152     QVERIFY(!referenceImageResized.isNull());
6153
6154     // Explicitly hide the calendar.
6155     calendar->hide();
6156     qApp->processEvents();
6157     QTest::qWait(30);
6158     workaroundPaletteIssue(calendar.data());
6159
6160     { // Make sure we get the same image when the calendar is explicitly hidden.
6161     QImage testImage(calendarSizeResized, QImage::Format_ARGB32);
6162     calendar->render(&testImage);
6163 #ifdef RENDER_DEBUG
6164     testImage.save("explicitlyHiddenCalendarResized.png");
6165 #endif
6166     QCOMPARE(testImage, referenceImageResized);
6167     }
6168
6169     // Now that we have reference images we can delete the source and re-create
6170     // the calendar and check that we get the same images from a calendar which has never
6171     // been visible, laid out or created (Qt::WA_WState_Created).
6172     calendar.reset(new QCalendarWidget);
6173     calendar->setFont(f);
6174     workaroundPaletteIssue(calendar.data());
6175
6176     { // Never been visible, created or laid out.
6177     QImage testImage(calendarSize, QImage::Format_ARGB32);
6178     calendar->render(&testImage);
6179 #ifdef RENDER_DEBUG
6180     testImage.save("neverBeenVisibleCreatedOrLaidOut.png");
6181 #endif
6182     QCOMPARE(testImage, referenceImage);
6183     }
6184
6185     calendar->hide();
6186     qApp->processEvents();
6187     QTest::qWait(30);
6188
6189     { // Calendar explicitly hidden.
6190     QImage testImage(calendarSize, QImage::Format_ARGB32);
6191     calendar->render(&testImage);
6192 #ifdef RENDER_DEBUG
6193     testImage.save("explicitlyHiddenCalendar.png");
6194 #endif
6195     QCOMPARE(testImage, referenceImage);
6196     }
6197
6198     // Get navigation bar and explicitly hide it.
6199     QWidget *navigationBar = qFindChild<QWidget *>(calendar.data(), QLatin1String("qt_calendar_navigationbar"));
6200     QVERIFY(navigationBar);
6201     navigationBar->hide();
6202
6203     { // Check that the navigation bar isn't drawn when rendering the entire calendar.
6204     QImage testImage(calendarSize, QImage::Format_ARGB32);
6205     calendar->render(&testImage);
6206 #ifdef RENDER_DEBUG
6207     testImage.save("calendarWithoutNavigationBar.png");
6208 #endif
6209     QVERIFY(testImage != referenceImage);
6210     }
6211
6212     { // Make sure the navigation bar renders correctly even though it's hidden.
6213     QImage testImage(navigationBar->size(), QImage::Format_ARGB32);
6214     navigationBar->render(&testImage);
6215 #ifdef RENDER_DEBUG
6216     testImage.save("explicitlyHiddenNavigationBar.png");
6217 #endif
6218     QCOMPARE(testImage, referenceImage.copy(navigationBar->rect()));
6219     }
6220
6221     // Get next month button.
6222     QWidget *nextMonthButton = qFindChild<QWidget *>(navigationBar, QLatin1String("qt_calendar_nextmonth"));
6223     QVERIFY(nextMonthButton);
6224
6225     { // Render next month button.
6226     // Fill test image with correct background color.
6227     QImage testImage(nextMonthButton->size(), QImage::Format_ARGB32);
6228     navigationBar->render(&testImage, QPoint(), QRegion(), QWidget::RenderFlags());
6229 #ifdef RENDER_DEBUG
6230     testImage.save("nextMonthButtonBackground.png");
6231 #endif
6232
6233     // Set the button's background color to Qt::transparent; otherwise it will fill the
6234     // background with QPalette::Window.
6235     const QPalette originalPalette = nextMonthButton->palette();
6236     QPalette palette = originalPalette;
6237     palette.setColor(QPalette::Window, Qt::transparent);
6238     nextMonthButton->setPalette(palette);
6239
6240     // Render the button on top of the background.
6241     nextMonthButton->render(&testImage);
6242 #ifdef RENDER_DEBUG
6243     testImage.save("nextMonthButton.png");
6244 #endif
6245     const QRect buttonRect(nextMonthButton->mapTo(calendar.data(), QPoint()), nextMonthButton->size());
6246     QCOMPARE(testImage, referenceImage.copy(buttonRect));
6247
6248     // Restore palette.
6249     nextMonthButton->setPalette(originalPalette);
6250     }
6251
6252     // Navigation bar isn't explicitly hidden anymore.
6253     navigationBar->show();
6254     qApp->processEvents();
6255     QTest::qWait(30);
6256     QVERIFY(!calendar->isVisible());
6257
6258     // Now, completely mess up the layout. This will trigger an update on the layout
6259     // when the calendar is visible or shown, but it's not. QWidget::render must therefore
6260     // make sure the layout is activated before rendering.
6261     QVERIFY(!calendar->isVisible());
6262     calendar->resize(calendarSizeResized);
6263     qApp->processEvents();
6264
6265     { // Make sure we get an image equal to the resized reference image.
6266     QImage testImage(calendarSizeResized, QImage::Format_ARGB32);
6267     calendar->render(&testImage);
6268 #ifdef RENDER_DEBUG
6269     testImage.save("calendarResized.png");
6270 #endif
6271     QCOMPARE(testImage, referenceImageResized);
6272     }
6273
6274     { // Make sure we lay out the widget correctly the first time it's rendered.
6275     QCalendarWidget calendar;
6276     const QSize calendarSize = calendar.sizeHint();
6277
6278     QImage image(2 * calendarSize, QImage::Format_ARGB32);
6279     image.fill(QColor(Qt::red).rgb());
6280     calendar.render(&image);
6281
6282     for (int i = calendarSize.height(); i < 2 * calendarSize.height(); ++i)
6283         for (int j = calendarSize.width(); j < 2 * calendarSize.width(); ++j)
6284             QCOMPARE(image.pixel(j, i), QColor(Qt::red).rgb());
6285     }
6286
6287     { // Ensure that we don't call adjustSize() on invisible top-levels if render() is called
6288       // right after widgets have been added/removed to/from its layout.
6289     QWidget topLevel;
6290     topLevel.setLayout(new QVBoxLayout);
6291
6292     QWidget *widget = new QLineEdit;
6293     topLevel.layout()->addWidget(widget);
6294
6295     const QSize initialSize = topLevel.size();
6296     QPixmap pixmap(topLevel.sizeHint());
6297     topLevel.render(&pixmap); // triggers adjustSize()
6298     const QSize finalSize = topLevel.size();
6299     QVERIFY(finalSize != initialSize);
6300
6301     topLevel.layout()->removeWidget(widget);
6302     QCOMPARE(topLevel.size(), finalSize);
6303     topLevel.render(&pixmap);
6304     QCOMPARE(topLevel.size(), finalSize);
6305
6306     topLevel.layout()->addWidget(widget);
6307     QCOMPARE(topLevel.size(), finalSize);
6308     topLevel.render(&pixmap);
6309     QCOMPARE(topLevel.size(), finalSize);
6310     }
6311 }
6312
6313 void tst_QWidget::renderWithPainter()
6314 {
6315     QWidget widget(0, Qt::Tool);
6316     // prevent custom styles
6317     widget.setStyle(QStyleFactory::create(QLatin1String("Windows")));
6318     widget.show();
6319     widget.resize(70, 50);
6320     widget.setAutoFillBackground(true);
6321     widget.setPalette(Qt::black);
6322
6323     // Render the entire widget onto the image.
6324     QImage image(QSize(70, 50), QImage::Format_ARGB32);
6325     image.fill(QColor(Qt::red).rgb());
6326     QPainter painter(&image);
6327     widget.render(&painter);
6328
6329     for (int i = 0; i < image.height(); ++i) {
6330         for (int j = 0; j < image.width(); ++j)
6331             QCOMPARE(image.pixel(j, i), QColor(Qt::black).rgb());
6332     }
6333
6334     // Translate painter (10, 10).
6335     painter.save();
6336     image.fill(QColor(Qt::red).rgb());
6337     painter.translate(10, 10);
6338     widget.render(&painter);
6339     painter.restore();
6340
6341     for (int i = 0; i < image.height(); ++i) {
6342         for (int j = 0; j < image.width(); ++j) {
6343             if (i < 10 || j < 10)
6344                 QCOMPARE(image.pixel(j, i), QColor(Qt::red).rgb());
6345             else
6346                 QCOMPARE(image.pixel(j, i), QColor(Qt::black).rgb());
6347         }
6348     }
6349
6350     // Pass target offset (10, 10) (the same as QPainter::translate).
6351     image.fill(QColor(Qt::red).rgb());
6352     widget.render(&painter, QPoint(10, 10));
6353
6354     for (int i = 0; i < image.height(); ++i) {
6355         for (int j = 0; j < image.width(); ++j) {
6356             if (i < 10 || j < 10)
6357                 QCOMPARE(image.pixel(j, i), QColor(Qt::red).rgb());
6358             else
6359                 QCOMPARE(image.pixel(j, i), QColor(Qt::black).rgb());
6360         }
6361     }
6362
6363     // Translate (10, 10) and pass target offset (10, 10).
6364     painter.save();
6365     image.fill(QColor(Qt::red).rgb());
6366     painter.translate(10, 10);
6367     widget.render(&painter, QPoint(10, 10));
6368     painter.restore();
6369
6370     for (int i = 0; i < image.height(); ++i) {
6371         for (int j = 0; j < image.width(); ++j) {
6372             if (i < 20 || j < 20)
6373                 QCOMPARE(image.pixel(j, i), QColor(Qt::red).rgb());
6374             else
6375                 QCOMPARE(image.pixel(j, i), QColor(Qt::black).rgb());
6376         }
6377     }
6378
6379     // Rotate painter 90 degrees.
6380     painter.save();
6381     image.fill(QColor(Qt::red).rgb());
6382     painter.rotate(90);
6383     widget.render(&painter);
6384     painter.restore();
6385
6386     for (int i = 0; i < image.height(); ++i) {
6387         for (int j = 0; j < image.width(); ++j)
6388             QCOMPARE(image.pixel(j, i), QColor(Qt::red).rgb());
6389     }
6390
6391     // Translate and rotate.
6392     image.fill(QColor(Qt::red).rgb());
6393     widget.resize(40, 10);
6394     painter.translate(10, 10);
6395     painter.rotate(90);
6396     widget.render(&painter);
6397
6398     for (int i = 0; i < image.height(); ++i) {
6399         for (int j = 0; j < image.width(); ++j) {
6400             if (i >= 10 && j >= 0 && j < 10)
6401                 QCOMPARE(image.pixel(j, i), QColor(Qt::black).rgb());
6402             else
6403                 QCOMPARE(image.pixel(j, i), QColor(Qt::red).rgb());
6404         }
6405     }
6406
6407     // Make sure QWidget::render does not modify the render hints set on the painter.
6408     painter.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform
6409                            | QPainter::NonCosmeticDefaultPen | QPainter::TextAntialiasing);
6410     QPainter::RenderHints oldRenderHints = painter.renderHints();
6411     widget.render(&painter);
6412     QCOMPARE(painter.renderHints(), oldRenderHints);
6413 }
6414
6415 void tst_QWidget::render_task188133()
6416 {
6417     QMainWindow mainWindow;
6418
6419     // Make sure QWidget::render does not trigger QWidget::repaint/update
6420     // and asserts for Qt::WA_WState_Created.
6421     const QPixmap pixmap = mainWindow.grab(QRect(QPoint(0, 0), QSize(-1, -1)));
6422     Q_UNUSED(pixmap)
6423 }
6424
6425 void tst_QWidget::render_task211796()
6426 {
6427     class MyWidget : public QWidget
6428     {
6429         void resizeEvent(QResizeEvent *)
6430         {
6431             QPixmap pixmap(size());
6432             render(&pixmap);
6433         }
6434     };
6435
6436     { // Please don't die in a resize recursion.
6437         MyWidget widget;
6438         widget.resize(200, 200);
6439         widget.show();
6440     }
6441
6442     { // Same check with a deeper hierarchy.
6443         QWidget widget;
6444         widget.show();
6445         QWidget child(&widget);
6446         MyWidget grandChild;
6447         grandChild.setParent(&child);
6448         grandChild.resize(100, 100);
6449         child.show();
6450     }
6451 }
6452
6453 void tst_QWidget::render_task217815()
6454 {
6455     // Make sure we don't change the size of the widget when calling
6456     // render() and the widget has an explicit size set.
6457     // This was a problem on Windows because we called createWinId(),
6458     // which in turn enforced the size to be bigger than the smallest
6459     // possible native window size (which is (115,something) on WinXP).
6460     QWidget widget;
6461     const QSize explicitSize(80, 20);
6462     widget.resize(explicitSize);
6463     QCOMPARE(widget.size(), explicitSize);
6464
6465     QPixmap pixmap(explicitSize);
6466     widget.render(&pixmap);
6467
6468     QCOMPARE(widget.size(), explicitSize);
6469 }
6470
6471 // Window Opacity is not supported on Windows CE.
6472 #ifndef Q_OS_WINCE
6473 void tst_QWidget::render_windowOpacity()
6474 {
6475     const qreal opacity = 0.5;
6476
6477     { // Check that the painter opacity effects the widget drawing.
6478     QWidget topLevel;
6479     QWidget child(&topLevel);
6480     child.resize(50, 50);
6481     child.setPalette(Qt::red);
6482     child.setAutoFillBackground(true);
6483
6484     QPixmap expected(child.size());
6485
6486     if (m_platform == QStringLiteral("xcb") && expected.depth() < 24)
6487         QSKIP("This test won't give correct results with dithered pixmaps");
6488
6489     expected.fill(Qt::green);
6490     QPainter painter(&expected);
6491     painter.setOpacity(opacity);
6492     painter.fillRect(QRect(QPoint(0, 0), child.size()), Qt::red);
6493     painter.end();
6494
6495     QPixmap result(child.size());
6496     result.fill(Qt::green);
6497     painter.begin(&result);
6498     painter.setOpacity(opacity);
6499     child.render(&painter);
6500     painter.end();
6501     QCOMPARE(result, expected);
6502     }
6503
6504     { // Combine the opacity set on the painter with the widget opacity.
6505     class MyWidget : public QWidget
6506     {
6507     public:
6508         void paintEvent(QPaintEvent *)
6509         {
6510             QPainter painter(this);
6511             painter.setOpacity(opacity);
6512             QCOMPARE(painter.opacity(), opacity);
6513             painter.fillRect(rect(), Qt::red);
6514         }
6515         qreal opacity;
6516     };
6517
6518     MyWidget widget;
6519     widget.resize(50, 50);
6520     widget.opacity = opacity;
6521     widget.setPalette(Qt::blue);
6522     widget.setAutoFillBackground(true);
6523
6524     QPixmap expected(widget.size());
6525     expected.fill(Qt::green);
6526     QPainter painter(&expected);
6527     painter.setOpacity(opacity);
6528     QPixmap pixmap(widget.size());
6529     pixmap.fill(Qt::blue);
6530     QPainter pixmapPainter(&pixmap);
6531     pixmapPainter.setOpacity(opacity);
6532     pixmapPainter.fillRect(QRect(QPoint(), widget.size()), Qt::red);
6533     painter.drawPixmap(QPoint(), pixmap);
6534     painter.end();
6535
6536     QPixmap result(widget.size());
6537     result.fill(Qt::green);
6538     painter.begin(&result);
6539     painter.setOpacity(opacity);
6540     widget.render(&painter);
6541     painter.end();
6542     QCOMPARE(result, expected);
6543     }
6544 }
6545 #endif
6546
6547 void tst_QWidget::render_systemClip()
6548 {
6549     QWidget widget;
6550     widget.setPalette(Qt::blue);
6551     widget.resize(100, 100);
6552
6553     QImage image(widget.size(), QImage::Format_RGB32);
6554     image.fill(QColor(Qt::red).rgb());
6555
6556     QPaintEngine *paintEngine = image.paintEngine();
6557     QVERIFY(paintEngine);
6558     paintEngine->setSystemClip(QRegion(0, 0, 50, 50));
6559
6560     QPainter painter(&image);
6561     // Make sure we're using the same paint engine and has the right clip set.
6562     QCOMPARE(painter.paintEngine(), paintEngine);
6563     QCOMPARE(paintEngine->systemClip(), QRegion(0, 0, 50, 50));
6564
6565     // Translate painter outside system clip.
6566     painter.translate(50, 0);
6567     widget.render(&painter);
6568
6569 #ifdef RENDER_DEBUG
6570     image.save("outside_systemclip.png");
6571 #endif
6572
6573     // All pixels should be red.
6574     for (int i = 0; i < image.height(); ++i) {
6575         for (int j = 0; j < image.width(); ++j)
6576             QCOMPARE(image.pixel(j, i), QColor(Qt::red).rgb());
6577     }
6578
6579     // Restore painter and refill image with red.
6580     image.fill(QColor(Qt::red).rgb());
6581     painter.translate(-50, 0);
6582
6583     // Set transform on the painter.
6584     QTransform transform;
6585     transform.shear(0, 1);
6586     painter.setTransform(transform);
6587     widget.render(&painter);
6588
6589 #ifdef RENDER_DEBUG
6590     image.save("blue_triangle.png");
6591 #endif
6592
6593     // We should now have a blue triangle starting at scan line 1, and the rest should be red.
6594     // rrrrrrrrrr
6595     // brrrrrrrrr
6596     // bbrrrrrrrr
6597     // bbbrrrrrrr
6598     // bbbbrrrrrr
6599     // rrrrrrrrrr
6600     // ...
6601
6602 #ifndef Q_OS_MAC
6603     for (int i = 0; i < image.height(); ++i) {
6604         for (int j = 0; j < image.width(); ++j) {
6605             if (i < 50 && j < i)
6606                 QCOMPARE(image.pixel(j, i), QColor(Qt::blue).rgb());
6607             else
6608                 QCOMPARE(image.pixel(j, i), QColor(Qt::red).rgb());
6609         }
6610     }
6611 #else
6612     // We don't paint directly on the image on the Mac, so we cannot do the pixel comparison
6613     // as above due to QPainter::SmoothPixmapTransform. We therefore need to generate an
6614     // expected image by first painting on a pixmap, and then draw the pixmap onto
6615     // the image using QPainter::SmoothPixmapTransform. Then we can compare pixels :)
6616     // The check is basically the same, except that it takes the smoothening into account.
6617     QPixmap pixmap(50, 50);
6618     const QRegion sysClip(0, 0, 50, 50);
6619     widget.render(&pixmap, QPoint(), sysClip);
6620
6621     QImage expectedImage(widget.size(), QImage::Format_RGB32);
6622     expectedImage.fill(QColor(Qt::red).rgb());
6623     expectedImage.paintEngine()->setSystemClip(sysClip);
6624
6625     QPainter expectedImagePainter(&expectedImage);
6626     expectedImagePainter.setTransform(QTransform().shear(0, 1));
6627     // NB! This is the important part (SmoothPixmapTransform).
6628     expectedImagePainter.setRenderHints(QPainter::SmoothPixmapTransform);
6629     expectedImagePainter.drawPixmap(QPoint(0, 0), pixmap);
6630     expectedImagePainter.end();
6631
6632     QCOMPARE(image, expectedImage);
6633 #endif
6634 }
6635
6636 void tst_QWidget::render_systemClip2_data()
6637 {
6638     QTest::addColumn<bool>("autoFillBackground");
6639     QTest::addColumn<bool>("usePaintEvent");
6640     QTest::addColumn<QColor>("expectedColor");
6641
6642     QTest::newRow("Only auto-fill background") << true << false << QColor(Qt::blue);
6643     QTest::newRow("Only draw in paintEvent") << false << true << QColor(Qt::green);
6644     QTest::newRow("Auto-fill background and draw in paintEvent") << true << true << QColor(Qt::green);
6645 }
6646
6647 void tst_QWidget::render_systemClip2()
6648 {
6649     QFETCH(bool, autoFillBackground);
6650     QFETCH(bool, usePaintEvent);
6651     QFETCH(QColor, expectedColor);
6652
6653     QVERIFY2(expectedColor != QColor(Qt::red), "Qt::red is the reference color for the image, pick another color");
6654
6655     class MyWidget : public QWidget
6656     {
6657     public:
6658         bool usePaintEvent;
6659         void paintEvent(QPaintEvent *)
6660         {
6661             if (usePaintEvent)
6662                 QPainter(this).fillRect(rect(), Qt::green);
6663         }
6664     };
6665
6666     MyWidget widget;
6667     widget.usePaintEvent = usePaintEvent;
6668     widget.setPalette(Qt::blue);
6669     // NB! widget.setAutoFillBackground(autoFillBackground) won't do the
6670     // trick here since the widget is a top-level. The background is filled
6671     // regardless, unless Qt::WA_OpaquePaintEvent or Qt::WA_NoSystemBackground
6672     // is set. We therefore use the opaque attribute to turn off auto-fill.
6673     if (!autoFillBackground)
6674         widget.setAttribute(Qt::WA_OpaquePaintEvent);
6675     widget.resize(100, 100);
6676
6677     QImage image(widget.size(), QImage::Format_RGB32);
6678     image.fill(QColor(Qt::red).rgb());
6679
6680     QPaintEngine *paintEngine = image.paintEngine();
6681     QVERIFY(paintEngine);
6682
6683     QRegion systemClip(QRegion(50, 0, 50, 10));
6684     systemClip += QRegion(90, 10, 10, 40);
6685     paintEngine->setSystemClip(systemClip);
6686
6687     // Render entire widget directly onto device.
6688     widget.render(&image);
6689
6690 #ifdef RENDER_DEBUG
6691     image.save("systemclip_with_device.png");
6692 #endif
6693     // All pixels within the system clip should now be
6694     // the expectedColor, and the rest should be red.
6695     for (int i = 0; i < image.height(); ++i) {
6696         for (int j = 0; j < image.width(); ++j) {
6697             if (systemClip.contains(QPoint(j, i)))
6698                 QCOMPARE(image.pixel(j, i), expectedColor.rgb());
6699             else
6700                 QCOMPARE(image.pixel(j, i), QColor(Qt::red).rgb());
6701         }
6702     }
6703
6704     // Refill image with red.
6705     image.fill(QColor(Qt::red).rgb());
6706     paintEngine->setSystemClip(systemClip);
6707
6708     // Do the same with an untransformed painter.
6709     QPainter painter(&image);
6710     //Make sure we're using the same paint engine and has the right clip set.
6711     QCOMPARE(painter.paintEngine(), paintEngine);
6712     QCOMPARE(paintEngine->systemClip(), systemClip);
6713
6714     widget.render(&painter);
6715
6716 #ifdef RENDER_DEBUG
6717     image.save("systemclip_with_untransformed_painter.png");
6718 #endif
6719     // All pixels within the system clip should now be
6720     // the expectedColor, and the rest should be red.
6721     for (int i = 0; i < image.height(); ++i) {
6722         for (int j = 0; j < image.width(); ++j) {
6723             if (systemClip.contains(QPoint(j, i)))
6724                 QCOMPARE(image.pixel(j, i), expectedColor.rgb());
6725             else
6726                 QCOMPARE(image.pixel(j, i), QColor(Qt::red).rgb());
6727         }
6728     }
6729 }
6730
6731 void tst_QWidget::render_systemClip3_data()
6732 {
6733     QTest::addColumn<QSize>("size");
6734     QTest::addColumn<bool>("useSystemClip");
6735
6736     // Reference: http://en.wikipedia.org/wiki/Flag_of_Norway
6737     QTest::newRow("Norwegian Civil Flag") << QSize(220, 160) << false;
6738     QTest::newRow("Norwegian War Flag") << QSize(270, 160) << true;
6739 }
6740
6741 // This test ensures that the current engine clip (systemClip + painter clip)
6742 // is preserved after QPainter::setClipRegion(..., Qt::ReplaceClip);
6743 void tst_QWidget::render_systemClip3()
6744 {
6745     QFETCH(QSize, size);
6746     QFETCH(bool, useSystemClip);
6747
6748     // Calculate the inner/outer cross of the flag.
6749     QRegion outerCross(0, 0, size.width(), size.height());
6750     outerCross -= QRect(0, 0, 60, 60);
6751     outerCross -= QRect(100, 0, size.width() - 100, 60);
6752     outerCross -= QRect(0, 100, 60, 60);
6753     outerCross -= QRect(100, 100, size.width() - 100, 60);
6754
6755     QRegion innerCross(0, 0, size.width(), size.height());
6756     innerCross -= QRect(0, 0, 70, 70);
6757     innerCross -= QRect(90, 0, size.width() - 90, 70);
6758     innerCross -= QRect(0, 90, 70, 70);
6759     innerCross -= QRect(90, 90, size.width() - 90, 70);
6760
6761     const QRegion redArea(QRegion(0, 0, size.width(), size.height()) - outerCross);
6762     const QRegion whiteArea(outerCross - innerCross);
6763     const QRegion blueArea(innerCross);
6764     QRegion systemClip;
6765
6766     // Okay, here's the image that should look like a Norwegian civil/war flag in the end.
6767     QImage flag(size, QImage::Format_ARGB32);
6768     flag.fill(QColor(Qt::transparent).rgba());
6769
6770     if (useSystemClip) {
6771         QPainterPath warClip(QPoint(size.width(), 0));
6772         warClip.lineTo(size.width() - 110, 60);
6773         warClip.lineTo(size.width(), 80);
6774         warClip.lineTo(size.width() - 110, 100);
6775         warClip.lineTo(size.width(), 160);
6776         warClip.closeSubpath();
6777         systemClip = QRegion(0, 0, size.width(), size.height()) - QRegion(warClip.toFillPolygon().toPolygon());
6778         flag.paintEngine()->setSystemClip(systemClip);
6779     }
6780
6781     QPainter painter(&flag);
6782     painter.fillRect(QRect(QPoint(), size), Qt::red); // Fill image background with red.
6783     painter.setClipRegion(outerCross); // Limit widget painting to inside the outer cross.
6784
6785     // Here's the widget that's supposed to draw the inner/outer cross of the flag.
6786     // The outer cross (white) should be drawn when the background is auto-filled, and
6787     // the inner cross (blue) should be drawn in the paintEvent.
6788     class MyWidget : public QWidget
6789     { public:
6790         void paintEvent(QPaintEvent *)
6791         {
6792             QPainter painter(this);
6793             // Be evil and try to paint outside the outer cross. This should not be
6794             // possible since the shared painter is clipped to the outer cross.
6795             painter.setClipRect(0, 0, 60, 60, Qt::ReplaceClip);
6796             painter.fillRect(rect(), Qt::green);
6797             painter.setClipRegion(clip, Qt::ReplaceClip);
6798             painter.fillRect(rect(), Qt::blue);
6799         }
6800         QRegion clip;
6801     };
6802
6803     MyWidget widget;
6804     widget.clip = innerCross;
6805     widget.setFixedSize(size);
6806     widget.setPalette(Qt::white);
6807     widget.setAutoFillBackground(true);
6808     widget.render(&painter);
6809
6810 #ifdef RENDER_DEBUG
6811     flag.save("flag.png");
6812 #endif
6813
6814     // Let's make sure we got a Norwegian flag.
6815     for (int i = 0; i < flag.height(); ++i) {
6816         for (int j = 0; j < flag.width(); ++j) {
6817             const QPoint pixel(j, i);
6818             const QRgb pixelValue = flag.pixel(pixel);
6819             if (useSystemClip && !systemClip.contains(pixel))
6820                 QCOMPARE(pixelValue, QColor(Qt::transparent).rgba());
6821             else if (redArea.contains(pixel))
6822                 QCOMPARE(pixelValue, QColor(Qt::red).rgba());
6823             else if (whiteArea.contains(pixel))
6824                 QCOMPARE(pixelValue, QColor(Qt::white).rgba());
6825             else
6826                 QCOMPARE(pixelValue, QColor(Qt::blue).rgba());
6827         }
6828     }
6829 }
6830
6831 void tst_QWidget::render_task252837()
6832 {
6833     QWidget widget;
6834     widget.resize(200, 200);
6835
6836     QPixmap pixmap(widget.size());
6837     QPainter painter(&pixmap);
6838     // Please do not crash.
6839     widget.render(&painter);
6840 }
6841
6842 void tst_QWidget::render_worldTransform()
6843 {
6844     class MyWidget : public QWidget
6845     { public:
6846         void paintEvent(QPaintEvent *)
6847         {
6848             QPainter painter(this);
6849             // Make sure world transform is identity.
6850             QCOMPARE(painter.worldTransform(), QTransform());
6851
6852             // Make sure device transform is correct.
6853             const QPoint widgetOffset = geometry().topLeft();
6854             QTransform expectedDeviceTransform = QTransform::fromTranslate(105, 5);
6855             expectedDeviceTransform.rotate(90);
6856             expectedDeviceTransform.translate(widgetOffset.x(), widgetOffset.y());
6857             QCOMPARE(painter.deviceTransform(), expectedDeviceTransform);
6858
6859             // Set new world transform.
6860             QTransform newWorldTransform = QTransform::fromTranslate(10, 10);
6861             newWorldTransform.rotate(90);
6862             painter.setWorldTransform(newWorldTransform);
6863             QCOMPARE(painter.worldTransform(), newWorldTransform);
6864
6865             // Again, check device transform.
6866             expectedDeviceTransform.translate(10, 10);
6867             expectedDeviceTransform.rotate(90);
6868             QCOMPARE(painter.deviceTransform(), expectedDeviceTransform);
6869
6870             painter.fillRect(QRect(0, 0, 20, 10), Qt::green);
6871         }
6872     };
6873
6874     MyWidget widget;
6875     widget.setFixedSize(100, 100);
6876     widget.setPalette(Qt::red);
6877     widget.setAutoFillBackground(true);
6878
6879     MyWidget child;
6880     child.setParent(&widget);
6881     child.move(50, 50);
6882     child.setFixedSize(50, 50);
6883     child.setPalette(Qt::blue);
6884     child.setAutoFillBackground(true);
6885
6886     QImage image(QSize(110, 110), QImage::Format_RGB32);
6887     image.fill(QColor(Qt::black).rgb());
6888
6889     QPainter painter(&image);
6890     painter.translate(105, 5);
6891     painter.rotate(90);
6892
6893     // Render widgets onto image.
6894     widget.render(&painter);
6895 #ifdef RENDER_DEBUG
6896     image.save("render_worldTransform_image.png");
6897 #endif
6898
6899     // Ensure the transforms are unchanged after render.
6900     QCOMPARE(painter.worldTransform(), painter.worldTransform());
6901     QCOMPARE(painter.deviceTransform(), painter.deviceTransform());
6902     painter.end();
6903
6904     // Paint expected image.
6905     QImage expected(QSize(110, 110), QImage::Format_RGB32);
6906     expected.fill(QColor(Qt::black).rgb());
6907
6908     QPainter expectedPainter(&expected);
6909     expectedPainter.translate(105, 5);
6910     expectedPainter.rotate(90);
6911     expectedPainter.save();
6912     expectedPainter.fillRect(widget.rect(),Qt::red);
6913     expectedPainter.translate(10, 10);
6914     expectedPainter.rotate(90);
6915     expectedPainter.fillRect(QRect(0, 0, 20, 10), Qt::green);
6916     expectedPainter.restore();
6917     expectedPainter.translate(50, 50);
6918     expectedPainter.fillRect(child.rect(),Qt::blue);
6919     expectedPainter.translate(10, 10);
6920     expectedPainter.rotate(90);
6921     expectedPainter.fillRect(QRect(0, 0, 20, 10), Qt::green);
6922     expectedPainter.end();
6923
6924 #ifdef RENDER_DEBUG
6925     expected.save("render_worldTransform_expected.png");
6926 #endif
6927
6928     QCOMPARE(image, expected);
6929 }
6930
6931 void tst_QWidget::setContentsMargins()
6932 {
6933     QLabel label("why does it always rain on me?");
6934     QSize oldSize = label.sizeHint();
6935     label.setFrameStyle(QFrame::Sunken | QFrame::Box);
6936     QSize newSize = label.sizeHint();
6937     QVERIFY(oldSize != newSize);
6938
6939     QLabel label2("why does it always rain on me?");
6940     label2.show();
6941     label2.setFrameStyle(QFrame::Sunken | QFrame::Box);
6942     QCOMPARE(newSize, label2.sizeHint());
6943
6944     QLabel label3("why does it always rain on me?");
6945     label3.setFrameStyle(QFrame::Sunken | QFrame::Box);
6946     QCOMPARE(newSize, label3.sizeHint());
6947 }
6948
6949 void tst_QWidget::moveWindowInShowEvent_data()
6950 {
6951     QTest::addColumn<QPoint>("initial");
6952     QTest::addColumn<QPoint>("position");
6953
6954     QPoint p = QApplication::desktop()->availableGeometry().topLeft();
6955
6956     QTest::newRow("1") << p << (p + QPoint(10, 10));
6957     QTest::newRow("2") << (p + QPoint(10,10)) << p;
6958 }
6959
6960 void tst_QWidget::moveWindowInShowEvent()
6961 {
6962     if (m_platform == QStringLiteral("xcb"))
6963         QSKIP("QTBUG-26424");
6964
6965     QFETCH(QPoint, initial);
6966     QFETCH(QPoint, position);
6967
6968     class MoveWindowInShowEventWidget : public QWidget
6969     {
6970     public:
6971         QPoint position;
6972         void showEvent(QShowEvent *)
6973         {
6974             move(position);
6975         }
6976     };
6977
6978     MoveWindowInShowEventWidget widget;
6979     widget.resize(QSize(qApp->desktop()->availableGeometry().size() / 3).expandedTo(QSize(1, 1)));
6980     // move to this position in showEvent()
6981     widget.position = position;
6982
6983     // put the widget in it's starting position
6984     widget.move(initial);
6985     QCOMPARE(widget.pos(), initial);
6986
6987     // show it
6988     widget.show();
6989     QVERIFY(QTest::qWaitForWindowShown(&widget));
6990     QTest::qWait(100);
6991     // it should have moved
6992     QCOMPARE(widget.pos(), position);
6993 }
6994
6995 void tst_QWidget::repaintWhenChildDeleted()
6996 {
6997 #ifdef Q_OS_WIN
6998     if (QSysInfo::WindowsVersion & QSysInfo::WV_VISTA) {
6999         QTest::qWait(1000);
7000     }
7001 #endif
7002     ColorWidget w(0, Qt::red);
7003 #if !defined(Q_OS_WINCE)
7004     QPoint startPoint = QApplication::desktop()->availableGeometry(&w).topLeft();
7005     startPoint.rx() += 50;
7006     startPoint.ry() += 50;
7007     w.setGeometry(QRect(startPoint, QSize(100, 100)));
7008 #else
7009     w.setGeometry(60, 60, 110, 110);
7010 #endif
7011     w.show();
7012     QVERIFY(QTest::qWaitForWindowExposed(&w));
7013     QTest::qWait(10);
7014     QTRY_COMPARE(w.r, QRegion(w.rect()));
7015     w.r = QRegion();
7016
7017     {
7018         ColorWidget child(&w, Qt::blue);
7019         child.setGeometry(10, 10, 10, 10);
7020         child.show();
7021         QTest::qWait(10);
7022         QTRY_COMPARE(child.r, QRegion(child.rect()));
7023         w.r = QRegion();
7024     }
7025
7026     QTest::qWait(10);
7027     QTRY_COMPARE(w.r, QRegion(10, 10, 10, 10));
7028 }
7029
7030 // task 175114
7031 void tst_QWidget::hideOpaqueChildWhileHidden()
7032 {
7033     ColorWidget w(0, Qt::red);
7034 #if !defined(Q_OS_WINCE)
7035     QPoint startPoint = QApplication::desktop()->availableGeometry(&w).topLeft();
7036     startPoint.rx() += 50;
7037     startPoint.ry() += 50;
7038     w.setGeometry(QRect(startPoint, QSize(100, 100)));
7039 #else
7040     w.setGeometry(60, 60, 110, 110);
7041 #endif
7042
7043     ColorWidget child(&w, Qt::blue);
7044     child.setGeometry(10, 10, 80, 80);
7045
7046     ColorWidget child2(&child, Qt::white);
7047     child2.setGeometry(10, 10, 60, 60);
7048
7049     w.show();
7050     QVERIFY(QTest::qWaitForWindowExposed(&w));
7051     QTest::qWait(10);
7052     QTRY_COMPARE(child2.r, QRegion(child2.rect()));
7053     child.r = QRegion();
7054     child2.r = QRegion();
7055     w.r = QRegion();
7056
7057     child.hide();
7058     child2.hide();
7059     QTest::qWait(100);
7060
7061     QCOMPARE(w.r, QRegion(child.geometry()));
7062
7063     child.show();
7064     QTest::qWait(100);
7065     QCOMPARE(child.r, QRegion(child.rect()));
7066     QCOMPARE(child2.r, QRegion());
7067 }
7068
7069 // This test doesn't make sense without support for showMinimized().
7070 #if !defined(Q_OS_WINCE)
7071 void tst_QWidget::updateWhileMinimized()
7072 {
7073     UpdateWidget widget;
7074    // Filter out activation change and focus events to avoid update() calls in QWidget.
7075     widget.updateOnActivationChangeAndFocusIn = false;
7076     widget.reset();
7077     widget.show();
7078     QVERIFY(QTest::qWaitForWindowExposed(&widget));
7079     QApplication::processEvents();
7080     QTRY_VERIFY(widget.numPaintEvents > 0);
7081     QTest::qWait(150);
7082
7083     // Minimize window.
7084     widget.showMinimized();
7085     QTest::qWait(110);
7086
7087     widget.reset();
7088
7089     // The widget is not visible on the screen (but isVisible() still returns true).
7090     // Make sure update requests are discarded until the widget is shown again.
7091     widget.update(0, 0, 50, 50);
7092     QTest::qWait(10);
7093     if (m_platform == QStringLiteral("windows"))
7094         QEXPECT_FAIL("", "QTBUG-26424", Continue);
7095     QCOMPARE(widget.numPaintEvents, 0);
7096
7097     // Restore window.
7098     widget.showNormal();
7099     QTest::qWait(30);
7100     if (m_platform == QStringLiteral("xcb"))
7101         QSKIP("QTBUG-26424");
7102     QTRY_COMPARE(widget.numPaintEvents, 1);
7103     QCOMPARE(widget.paintedRegion, QRegion(0, 0, 50, 50));
7104 }
7105 #endif
7106
7107 class PaintOnScreenWidget: public QWidget
7108 {
7109 public:
7110     PaintOnScreenWidget(QWidget *parent = 0, Qt::WindowFlags f = 0)
7111         :QWidget(parent, f)
7112     {
7113     }
7114 #if defined(Q_OS_WIN)
7115     // This is the only way to enable PaintOnScreen on Windows.
7116     QPaintEngine * paintEngine () const {return 0;}
7117 #endif
7118 };
7119
7120 void tst_QWidget::alienWidgets()
7121 {
7122     if (m_platform != QStringLiteral("xcb") && m_platform != QStringLiteral("windows"))
7123         QSKIP("This test is only for X11/Windows.");
7124
7125     qApp->setAttribute(Qt::AA_DontCreateNativeWidgetSiblings);
7126     QWidget parent;
7127     parent.resize(200, 200);
7128     QWidget child(&parent);
7129     QWidget grandChild(&child);
7130     QWidget greatGrandChild(&grandChild);
7131     parent.show();
7132
7133     QVERIFY(QTest::qWaitForWindowExposed(&parent));
7134
7135     // Verify that the WA_WState_Created attribute is set
7136     // and the top-level is the only native window.
7137     QVERIFY(parent.testAttribute(Qt::WA_WState_Created));
7138     QVERIFY(parent.internalWinId());
7139
7140     QVERIFY(child.testAttribute(Qt::WA_WState_Created));
7141     QVERIFY(!child.internalWinId());
7142
7143     QVERIFY(grandChild.testAttribute(Qt::WA_WState_Created));
7144     QVERIFY(!grandChild.internalWinId());
7145
7146     QVERIFY(greatGrandChild.testAttribute(Qt::WA_WState_Created));
7147     QVERIFY(!greatGrandChild.internalWinId());
7148
7149     // Enforce native windows all the way up in the parent hierarchy
7150     // if not WA_DontCreateNativeAncestors is set.
7151     grandChild.setAttribute(Qt::WA_DontCreateNativeAncestors);
7152     greatGrandChild.setAttribute(Qt::WA_NativeWindow);
7153     QVERIFY(greatGrandChild.internalWinId());
7154     QVERIFY(grandChild.internalWinId());
7155     QVERIFY(!child.internalWinId());
7156
7157     {
7158         // Ensure that hide() on an ancestor of a widget with
7159         // Qt::WA_DontCreateNativeAncestors still gets unmapped
7160         QWidget window;
7161         window.resize(200, 200);
7162         QWidget widget(&window);
7163         QWidget child(&widget);
7164         child.setAttribute(Qt::WA_NativeWindow);
7165         child.setAttribute(Qt::WA_DontCreateNativeAncestors);
7166         window.show();
7167         QVERIFY(QTest::qWaitForWindowExposed(&window));
7168         QTRY_VERIFY(child.testAttribute(Qt::WA_Mapped));
7169         widget.hide();
7170         QTRY_VERIFY(!child.testAttribute(Qt::WA_Mapped));
7171     }
7172
7173     // Enforce a native window when calling QWidget::winId.
7174     QVERIFY(child.winId());
7175     QVERIFY(child.internalWinId());
7176
7177     // Check that paint on screen widgets (incl. children) are native.
7178     PaintOnScreenWidget paintOnScreen(&parent);
7179     QWidget paintOnScreenChild(&paintOnScreen);
7180     paintOnScreen.show();
7181     QVERIFY(paintOnScreen.testAttribute(Qt::WA_WState_Created));
7182     QVERIFY(!paintOnScreen.testAttribute(Qt::WA_NativeWindow));
7183     QVERIFY(!paintOnScreen.internalWinId());
7184     QVERIFY(!paintOnScreenChild.testAttribute(Qt::WA_NativeWindow));
7185     QVERIFY(!paintOnScreenChild.internalWinId());
7186
7187     paintOnScreen.setAttribute(Qt::WA_PaintOnScreen);
7188     if (m_platform == QStringLiteral("xcb") || m_platform == QStringLiteral("windows"))
7189         QEXPECT_FAIL("", "QTBUG-26424", Continue);
7190     QVERIFY(paintOnScreen.testAttribute(Qt::WA_NativeWindow));
7191     if (m_platform == QStringLiteral("xcb") || m_platform == QStringLiteral("windows"))
7192         QEXPECT_FAIL("", "QTBUG-26424", Continue);
7193     QVERIFY(paintOnScreen.internalWinId());
7194     if (m_platform == QStringLiteral("xcb") || m_platform == QStringLiteral("windows"))
7195         QEXPECT_FAIL("", "QTBUG-26424", Continue);
7196     QVERIFY(paintOnScreenChild.testAttribute(Qt::WA_NativeWindow));
7197     if (m_platform == QStringLiteral("xcb") || m_platform == QStringLiteral("windows"))
7198         QEXPECT_FAIL("", "QTBUG-26424", Continue);
7199     QVERIFY(paintOnScreenChild.internalWinId());
7200
7201     // Check that widgets with the Qt::MSWindowsOwnDC attribute set
7202     // are native.
7203     QWidget msWindowsOwnDC(&parent, Qt::MSWindowsOwnDC);
7204     msWindowsOwnDC.show();
7205     QVERIFY(msWindowsOwnDC.testAttribute(Qt::WA_WState_Created));
7206     QVERIFY(msWindowsOwnDC.testAttribute(Qt::WA_NativeWindow));
7207     QVERIFY(msWindowsOwnDC.internalWinId());
7208
7209     { // Enforce a native window when calling QWidget::handle() (on X11) or QWidget::getDC() (on Windows).
7210         QWidget widget(&parent);
7211         widget.show();
7212         QVERIFY(widget.testAttribute(Qt::WA_WState_Created));
7213         QVERIFY(!widget.internalWinId());
7214
7215         widget.winId();
7216         QVERIFY(widget.internalWinId());
7217     }
7218
7219     if (m_platform == QStringLiteral("xcb")) {
7220         // Make sure we don't create native windows when setting Qt::WA_X11NetWmWindowType attributes
7221         // on alien widgets (see task 194231).
7222         QWidget dummy;
7223         dummy.resize(200, 200);
7224         QVERIFY(dummy.winId());
7225         QWidget widget(&dummy);
7226         widget.setAttribute(Qt::WA_X11NetWmWindowTypeToolBar);
7227         QVERIFY(!widget.internalWinId());
7228     }
7229
7230     { // Make sure we create native ancestors when setting Qt::WA_PaintOnScreen before show().
7231         QWidget topLevel;
7232         topLevel.resize(200, 200);
7233         QWidget child(&topLevel);
7234         QWidget grandChild(&child);
7235         PaintOnScreenWidget greatGrandChild(&grandChild);
7236
7237         greatGrandChild.setAttribute(Qt::WA_PaintOnScreen);
7238         QVERIFY(!child.internalWinId());
7239         QVERIFY(!grandChild.internalWinId());
7240         QVERIFY(!greatGrandChild.internalWinId());
7241
7242         topLevel.show();
7243         if (m_platform == QStringLiteral("xcb") || m_platform == QStringLiteral("windows"))
7244             QEXPECT_FAIL("", "QTBUG-26424", Continue);
7245         QVERIFY(child.internalWinId());
7246         if (m_platform == QStringLiteral("xcb") || m_platform == QStringLiteral("windows"))
7247             QEXPECT_FAIL("", "QTBUG-26424", Continue);
7248         QVERIFY(grandChild.internalWinId());
7249         if (m_platform == QStringLiteral("xcb") || m_platform == QStringLiteral("windows"))
7250             QEXPECT_FAIL("", "QTBUG-26424", Continue);
7251         QVERIFY(greatGrandChild.internalWinId());
7252     }
7253
7254     { // Ensure that widgets reparented into Qt::WA_PaintOnScreen widgets become native.
7255         QWidget topLevel;
7256         topLevel.resize(200, 200);
7257         QWidget *widget = new PaintOnScreenWidget(&topLevel);
7258         widget->setAttribute(Qt::WA_PaintOnScreen);
7259         QWidget *child = new QWidget;
7260         QWidget *dummy = new QWidget(child);
7261         QWidget *grandChild = new QWidget(child);
7262         QWidget *dummy2 = new QWidget(grandChild);
7263
7264         child->setParent(widget);
7265
7266         QVERIFY(!topLevel.internalWinId());
7267         QVERIFY(!child->internalWinId());
7268         QVERIFY(!dummy->internalWinId());
7269         QVERIFY(!grandChild->internalWinId());
7270         QVERIFY(!dummy2->internalWinId());
7271
7272         topLevel.show();
7273         QVERIFY(topLevel.internalWinId());
7274         QVERIFY(widget->testAttribute(Qt::WA_NativeWindow));
7275         QVERIFY(child->internalWinId());
7276         QVERIFY(child->testAttribute(Qt::WA_NativeWindow));
7277         QVERIFY(!child->testAttribute(Qt::WA_PaintOnScreen));
7278         QVERIFY(!dummy->internalWinId());
7279         QVERIFY(!dummy->testAttribute(Qt::WA_NativeWindow));
7280         QVERIFY(!grandChild->internalWinId());
7281         QVERIFY(!grandChild->testAttribute(Qt::WA_NativeWindow));
7282         QVERIFY(!dummy2->internalWinId());
7283         QVERIFY(!dummy2->testAttribute(Qt::WA_NativeWindow));
7284     }
7285
7286     { // Ensure that ancestors of a Qt::WA_PaintOnScreen widget stay native
7287       // if they are re-created (typically in QWidgetPrivate::setParent_sys) (task 210822).
7288         QWidget window;
7289         window.resize(200, 200);
7290         QWidget child(&window);
7291
7292         QWidget grandChild;
7293         grandChild.setWindowTitle("This causes the widget to be created");
7294
7295         PaintOnScreenWidget paintOnScreenWidget;
7296         paintOnScreenWidget.setAttribute(Qt::WA_PaintOnScreen);
7297         paintOnScreenWidget.setParent(&grandChild);
7298
7299         grandChild.setParent(&child);
7300
7301         window.show();
7302
7303         QVERIFY(window.internalWinId());
7304         if (m_platform == QStringLiteral("xcb") || m_platform == QStringLiteral("windows"))
7305             QEXPECT_FAIL("", "QTBUG-26424", Continue);
7306         QVERIFY(child.internalWinId());
7307         if (m_platform == QStringLiteral("xcb") || m_platform == QStringLiteral("windows"))
7308             QEXPECT_FAIL("", "QTBUG-26424", Continue);
7309         QVERIFY(child.testAttribute(Qt::WA_NativeWindow));
7310         if (m_platform == QStringLiteral("xcb") || m_platform == QStringLiteral("windows"))
7311             QEXPECT_FAIL("", "QTBUG-26424", Continue);
7312         QVERIFY(grandChild.internalWinId());
7313         if (m_platform == QStringLiteral("xcb") || m_platform == QStringLiteral("windows"))
7314             QEXPECT_FAIL("", "QTBUG-26424", Continue);
7315         QVERIFY(grandChild.testAttribute(Qt::WA_NativeWindow));
7316         if (m_platform == QStringLiteral("xcb") || m_platform == QStringLiteral("windows"))
7317             QEXPECT_FAIL("", "QTBUG-26424", Continue);
7318         QVERIFY(paintOnScreenWidget.internalWinId());
7319         if (m_platform == QStringLiteral("xcb") || m_platform == QStringLiteral("windows"))
7320             QEXPECT_FAIL("", "QTBUG-26424", Continue);
7321         QVERIFY(paintOnScreenWidget.testAttribute(Qt::WA_NativeWindow));
7322     }
7323
7324     { // Ensure that all siblings are native unless Qt::AA_DontCreateNativeWidgetSiblings is set.
7325         qApp->setAttribute(Qt::AA_DontCreateNativeWidgetSiblings, false);
7326         QWidget mainWindow;
7327         QWidget *toolBar = new QWidget(&mainWindow);
7328         QWidget *dockWidget = new QWidget(&mainWindow);
7329         QWidget *centralWidget = new QWidget(&mainWindow);
7330
7331         QWidget *button = new QWidget(centralWidget);
7332         QWidget *mdiArea = new QWidget(centralWidget);
7333
7334         QWidget *horizontalScroll = new QWidget(mdiArea);
7335         QWidget *verticalScroll = new QWidget(mdiArea);
7336         QWidget *viewport = new QWidget(mdiArea);
7337
7338         viewport->setAttribute(Qt::WA_NativeWindow);
7339         mainWindow.show();
7340
7341         // Ensure that the viewport and its siblings are native:
7342         QVERIFY(verticalScroll->testAttribute(Qt::WA_NativeWindow));
7343         QVERIFY(verticalScroll->testAttribute(Qt::WA_NativeWindow));
7344         QVERIFY(horizontalScroll->testAttribute(Qt::WA_NativeWindow));
7345
7346         // Ensure that the mdi area and its siblings are native:
7347         QVERIFY(mdiArea->testAttribute(Qt::WA_NativeWindow));
7348         QVERIFY(button->testAttribute(Qt::WA_NativeWindow));
7349
7350         // Ensure that the central widget and its siblings are native:
7351         QVERIFY(centralWidget->testAttribute(Qt::WA_NativeWindow));
7352         QVERIFY(dockWidget->testAttribute(Qt::WA_NativeWindow));
7353         QVERIFY(toolBar->testAttribute(Qt::WA_NativeWindow));
7354     }
7355 }
7356
7357 class ASWidget : public QWidget
7358 {
7359 public:
7360     ASWidget(QSize sizeHint, QSizePolicy sizePolicy, bool layout, bool hfwLayout, QWidget *parent = 0)
7361         : QWidget(parent), mySizeHint(sizeHint)
7362     {
7363         setObjectName(QStringLiteral("ASWidget"));
7364         setWindowTitle(objectName());
7365         setSizePolicy(sizePolicy);
7366         if (layout) {
7367             QSizePolicy sp = QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
7368             sp.setHeightForWidth(hfwLayout);
7369
7370             QVBoxLayout *vbox = new QVBoxLayout;
7371             vbox->setMargin(0);
7372             vbox->addWidget(new ASWidget(sizeHint + QSize(30, 20), sp, false, false));
7373             setLayout(vbox);
7374         }
7375     }
7376
7377     QSize sizeHint() const {
7378         if (layout())
7379             return layout()->totalSizeHint();
7380         return mySizeHint;
7381     }
7382     int heightForWidth(int width) const {
7383         if (sizePolicy().hasHeightForWidth()) {
7384             return width * 2;
7385         } else {
7386             return -1;
7387         }
7388     }
7389
7390     QSize mySizeHint;
7391 };
7392
7393 void tst_QWidget::adjustSize_data()
7394 {
7395     const int MagicW = 200;
7396     const int MagicH = 100;
7397
7398     QTest::addColumn<QSize>("sizeHint");
7399     QTest::addColumn<int>("hPolicy");
7400     QTest::addColumn<int>("vPolicy");
7401     QTest::addColumn<bool>("hfwSP");
7402     QTest::addColumn<bool>("layout");
7403     QTest::addColumn<bool>("hfwLayout");
7404     QTest::addColumn<bool>("haveParent");
7405     QTest::addColumn<QSize>("expectedSize");
7406
7407     QTest::newRow("1") << QSize(5, 6) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
7408         << false << false << false << false << QSize(5, qMax(6, MagicH));
7409     QTest::newRow("2") << QSize(5, 6) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
7410         << true << false << false << false << QSize(5, qMax(10, MagicH));
7411     QTest::newRow("3") << QSize(5, 6) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
7412         << false << true << false << false << QSize(35, 26);
7413     QTest::newRow("4") << QSize(5, 6) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
7414         << false << true << true << false << QSize(35, 70);
7415     QTest::newRow("5") << QSize(40001, 30001) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
7416         << false << false << false << false << QSize(100000, 100000);
7417     QTest::newRow("6") << QSize(40001, 30001) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
7418         << true << false << false << false << QSize(100000, 100000);
7419     QTest::newRow("7") << QSize(40001, 30001) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
7420         << false << true << false << false << QSize(100000, 100000);
7421     QTest::newRow("8") << QSize(40001, 30001) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
7422         << false << true << true << false << QSize(100000, 100000);
7423     QTest::newRow("9") << QSize(5, 6) << int(QSizePolicy::Expanding) << int(QSizePolicy::Minimum)
7424         << true << false << false << false << QSize(qMax(5, MagicW), 10);
7425
7426     QTest::newRow("1c") << QSize(5, 6) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
7427         << false << false << false << true << QSize(5, 6);
7428     QTest::newRow("2c") << QSize(5, 6) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
7429         << true << false << false << true << QSize(5, 6 /* or 10 would be OK too, since hfw contradicts sizeHint() */);
7430     QTest::newRow("3c") << QSize(5, 6) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
7431         << false << true << false << true << QSize(35, 26);
7432     QTest::newRow("4c") << QSize(5, 6) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
7433         << false << true << true << true << QSize(35, 70);
7434     QTest::newRow("5c") << QSize(40001, 30001) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
7435         << false << false << false << true << QSize(40001, 30001);
7436     QTest::newRow("6c") << QSize(40001, 30001) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
7437         << true << false << false << true << QSize(40001, 30001 /* or 80002 would be OK too, since hfw contradicts sizeHint() */);
7438     QTest::newRow("7c") << QSize(40001, 30001) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
7439         << false << true << false << true << QSize(40001 + 30, 30001 + 20);
7440     QTest::newRow("8c") << QSize(40001, 30001) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
7441         << false << true << true << true << QSize(40001 + 30, 80002 + 60);
7442     QTest::newRow("9c") << QSize(5, 6) << int(QSizePolicy::Expanding) << int(QSizePolicy::Minimum)
7443         << true << false << false << true << QSize(5, 6);
7444 }
7445
7446 void tst_QWidget::adjustSize()
7447 {
7448     QFETCH(QSize, sizeHint);
7449     QFETCH(int, hPolicy);
7450     QFETCH(int, vPolicy);
7451     QFETCH(bool, hfwSP);
7452     QFETCH(bool, layout);
7453     QFETCH(bool, hfwLayout);
7454     QFETCH(bool, haveParent);
7455     QFETCH(QSize, expectedSize);
7456
7457     QScopedPointer<QWidget> parent(new QWidget);
7458
7459     QSizePolicy sp = QSizePolicy(QSizePolicy::Policy(hPolicy), QSizePolicy::Policy(vPolicy));
7460     sp.setHeightForWidth(hfwSP);
7461
7462     QWidget *child = new ASWidget(sizeHint, sp, layout, hfwLayout, haveParent ? parent.data() : 0);
7463     child->resize(123, 456);
7464     child->adjustSize();
7465     if (expectedSize == QSize(100000, 100000)) {
7466         QVERIFY(child->size().width() < sizeHint.width());
7467         QVERIFY(child->size().height() < sizeHint.height());
7468     } else {
7469 #if defined (Q_OS_WINCE)
7470         if (!haveParent) {
7471             const QRect& desktopRect = qApp->desktop()->availableGeometry();
7472             expectedSize.setWidth(qMin(expectedSize.width(), desktopRect.width()));
7473             expectedSize.setHeight(qMin(expectedSize.height(), desktopRect.height()));
7474         }
7475 #endif
7476         QCOMPARE(child->size(), expectedSize);
7477     }
7478     if (!haveParent)
7479         delete child;
7480 }
7481
7482 class TestLayout : public QVBoxLayout
7483 {
7484     Q_OBJECT
7485 public:
7486     TestLayout(QWidget *w = 0) : QVBoxLayout(w)
7487     {
7488         invalidated = false;
7489     }
7490
7491     void invalidate()
7492     {
7493         invalidated = true;
7494     }
7495
7496     bool invalidated;
7497 };
7498
7499 void tst_QWidget::updateGeometry_data()
7500 {
7501     QTest::addColumn<QSize>("minSize");
7502     QTest::addColumn<bool>("shouldInvalidate");
7503     QTest::addColumn<QSize>("maxSize");
7504     QTest::addColumn<bool>("shouldInvalidate2");
7505     QTest::addColumn<int>("verticalSizePolicy");
7506     QTest::addColumn<bool>("shouldInvalidate3");
7507     QTest::addColumn<bool>("setVisible");
7508     QTest::addColumn<bool>("shouldInvalidate4");
7509
7510     QTest::newRow("setMinimumSize")
7511         << QSize(100, 100) << true
7512         << QSize() << false
7513         << int(QSizePolicy::Preferred) << false
7514         << true << false;
7515     QTest::newRow("setMaximumSize")
7516         << QSize() << false
7517         << QSize(100, 100) << true
7518         << int(QSizePolicy::Preferred) << false
7519         << true << false;
7520     QTest::newRow("setMinimumSize, then maximumSize to a different size")
7521         << QSize(100, 100) << true
7522         << QSize(300, 300) << true
7523         << int(QSizePolicy::Preferred) << false
7524         << true << false;
7525     QTest::newRow("setMinimumSize, then maximumSize to the same size")
7526         << QSize(100, 100) << true
7527         << QSize(100, 100) << true
7528         << int(QSizePolicy::Preferred) << false
7529         << true << false;
7530     QTest::newRow("setMinimumSize, then maximumSize to the same size and then hide it")
7531         << QSize(100, 100) << true
7532         << QSize(100, 100) << true
7533         << int(QSizePolicy::Preferred) << false
7534         << false << true;
7535     QTest::newRow("Change sizePolicy")
7536         << QSize() << false
7537         << QSize() << false
7538         << int(QSizePolicy::Minimum) << true
7539         << true << false;
7540
7541 }
7542
7543 void tst_QWidget::updateGeometry()
7544 {
7545     QFETCH(QSize, minSize);
7546     QFETCH(bool, shouldInvalidate);
7547     QFETCH(QSize, maxSize);
7548     QFETCH(bool, shouldInvalidate2);
7549     QFETCH(int, verticalSizePolicy);
7550     QFETCH(bool, shouldInvalidate3);
7551     QFETCH(bool, setVisible);
7552     QFETCH(bool, shouldInvalidate4);
7553     QWidget parent;
7554     parent.resize(200, 200);
7555     TestLayout *lout = new TestLayout();
7556     parent.setLayout(lout);
7557     QWidget *child = new QWidget(&parent);
7558     lout->addWidget(child);
7559     parent.show();
7560     QApplication::processEvents();
7561
7562     lout->invalidated = false;
7563     if (minSize.isValid())
7564         child->setMinimumSize(minSize);
7565     QCOMPARE(lout->invalidated, shouldInvalidate);
7566
7567     lout->invalidated = false;
7568     if (maxSize.isValid())
7569         child->setMaximumSize(maxSize);
7570     QCOMPARE(lout->invalidated, shouldInvalidate2);
7571
7572     lout->invalidated = false;
7573     child->setSizePolicy(QSizePolicy(QSizePolicy::Preferred, (QSizePolicy::Policy)verticalSizePolicy));
7574     if (shouldInvalidate3)
7575         QCOMPARE(lout->invalidated, true);
7576
7577     lout->invalidated = false;
7578     if (!setVisible)
7579         child->setVisible(false);
7580     QCOMPARE(lout->invalidated, shouldInvalidate4);
7581 }
7582
7583 void tst_QWidget::sendUpdateRequestImmediately()
7584 {
7585     UpdateWidget updateWidget;
7586     updateWidget.show();
7587
7588     QVERIFY(QTest::qWaitForWindowExposed(&updateWidget));
7589
7590     qApp->processEvents();
7591     updateWidget.reset();
7592
7593     QCOMPARE(updateWidget.numUpdateRequestEvents, 0);
7594     updateWidget.repaint();
7595     QCOMPARE(updateWidget.numUpdateRequestEvents, 1);
7596 }
7597
7598 void tst_QWidget::doubleRepaint()
7599 {
7600 #if defined(Q_OS_MAC)
7601     if (!macHasAccessToWindowsServer())
7602         QSKIP("Not having window server access causes the wrong number of repaints to be issues");
7603 #endif
7604    UpdateWidget widget;
7605    widget.setFocusPolicy(Qt::StrongFocus);
7606    // Filter out activation change and focus events to avoid update() calls in QWidget.
7607    widget.updateOnActivationChangeAndFocusIn = false;
7608
7609    // Show: 1 repaint
7610    int expectedRepaints = 1;
7611    widget.show();
7612    QVERIFY(QTest::qWaitForWindowExposed(&widget));
7613    QTest::qWait(10);
7614    QTRY_COMPARE(widget.numPaintEvents, expectedRepaints);
7615    widget.numPaintEvents = 0;
7616
7617    // Minmize: Should not trigger a repaint.
7618    widget.showMinimized();
7619    QTest::qWait(10);
7620    QCOMPARE(widget.numPaintEvents, 0);
7621    widget.numPaintEvents = 0;
7622
7623    // Restore: Should not trigger a repaint.
7624    widget.showNormal();
7625    QVERIFY(QTest::qWaitForWindowExposed(&widget));
7626    QTest::qWait(10);
7627    QCOMPARE(widget.numPaintEvents, 0);
7628 }
7629
7630 void tst_QWidget::resizeInPaintEvent()
7631 {
7632     QWidget window;
7633     UpdateWidget widget(&window);
7634     window.resize(200, 200);
7635     window.show();
7636     qApp->setActiveWindow(&window);
7637     QVERIFY(QTest::qWaitForWindowActive(&window));
7638     QTRY_VERIFY(widget.numPaintEvents > 0);
7639
7640     widget.reset();
7641     QCOMPARE(widget.numPaintEvents, 0);
7642
7643     widget.resizeInPaintEvent = true;
7644     // This will call resize in the paintEvent, which in turn will call
7645     // invalidateBuffer() and a new update request should be posted.
7646     widget.repaint();
7647     QCOMPARE(widget.numPaintEvents, 1);
7648     widget.numPaintEvents = 0;
7649
7650     QTest::qWait(10);
7651     // Make sure the resize triggers another update.
7652     QTRY_COMPARE(widget.numPaintEvents, 1);
7653 }
7654
7655 void tst_QWidget::opaqueChildren()
7656 {
7657     QWidget widget;
7658     widget.resize(200, 200);
7659
7660     QWidget child(&widget);
7661     child.setGeometry(-700, -700, 200, 200);
7662
7663     QWidget grandChild(&child);
7664     grandChild.resize(200, 200);
7665
7666     QWidget greatGrandChild(&grandChild);
7667     greatGrandChild.setGeometry(50, 50, 200, 200);
7668     greatGrandChild.setPalette(Qt::red);
7669     greatGrandChild.setAutoFillBackground(true); // Opaque child widget.
7670
7671     widget.show();
7672     QVERIFY(QTest::qWaitForWindowExposed(&widget));
7673     QTest::qWait(100);
7674
7675     // Child, grandChild and greatGrandChild are outside the ancestor clip.
7676     QRegion expectedOpaqueRegion(50, 50, 150, 150);
7677     QCOMPARE(qt_widget_private(&grandChild)->getOpaqueChildren(), expectedOpaqueRegion);
7678
7679     // Now they are all inside the ancestor clip.
7680     child.setGeometry(50, 50, 150, 150);
7681     QCOMPARE(qt_widget_private(&grandChild)->getOpaqueChildren(), expectedOpaqueRegion);
7682
7683     // Set mask on greatGrandChild.
7684     const QRegion mask(10, 10, 50, 50);
7685     greatGrandChild.setMask(mask);
7686     expectedOpaqueRegion &= mask.translated(50, 50);
7687     QCOMPARE(qt_widget_private(&grandChild)->getOpaqueChildren(), expectedOpaqueRegion);
7688
7689     // Make greatGrandChild "transparent".
7690     greatGrandChild.setAutoFillBackground(false);
7691     QCOMPARE(qt_widget_private(&grandChild)->getOpaqueChildren(), QRegion());
7692 }
7693
7694
7695 class MaskSetWidget : public QWidget
7696 {
7697     Q_OBJECT
7698 public:
7699     MaskSetWidget(QWidget* p =0)
7700             : QWidget(p) {}
7701
7702     void paintEvent(QPaintEvent* event) {
7703         QPainter p(this);
7704
7705         paintedRegion += event->region();
7706         foreach(QRect r, event->region().rects())
7707             p.fillRect(r, Qt::red);
7708     }
7709
7710     void resizeEvent(QResizeEvent*) {
7711         setMask(QRegion(QRect(0, 0, width(), 10).normalized()));
7712     }
7713
7714     QRegion paintedRegion;
7715
7716 public slots:
7717     void resizeDown() {
7718         setGeometry(QRect(0, 50, 50, 50));
7719     }
7720
7721     void resizeUp() {
7722         setGeometry(QRect(0, 50, 150, 50));
7723     }
7724
7725 };
7726
7727 void tst_QWidget::setMaskInResizeEvent()
7728 {
7729     UpdateWidget w;
7730     w.reset();
7731     w.resize(200, 200);
7732     w.setWindowFlags(Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint);
7733     w.raise();
7734
7735     MaskSetWidget testWidget(&w);
7736     testWidget.setGeometry(0, 0, 100, 100);
7737     testWidget.setMask(QRegion(QRect(0,0,100,10)));
7738     testWidget.show();
7739     w.show();
7740     QVERIFY(QTest::qWaitForWindowExposed(&w));
7741     QTest::qWait(30);
7742     QTRY_VERIFY(w.numPaintEvents > 0);
7743
7744     w.reset();
7745     testWidget.paintedRegion = QRegion();
7746     QTimer::singleShot(0, &testWidget, SLOT(resizeDown()));
7747     QTest::qWait(100);
7748
7749     QRegion expectedParentUpdate(0, 0, 100, 10); // Old testWidget area.
7750     expectedParentUpdate += testWidget.geometry(); // New testWidget area.
7751     QCOMPARE(w.paintedRegion, expectedParentUpdate);
7752     QCOMPARE(testWidget.paintedRegion, testWidget.mask());
7753
7754     testWidget.paintedRegion = QRegion();
7755     // Now resize the widget again, but in the oposite direction
7756     QTimer::singleShot(0, &testWidget, SLOT(resizeUp()));
7757     QTest::qWait(100);
7758
7759     QTRY_COMPARE(testWidget.paintedRegion, testWidget.mask());
7760 }
7761
7762 class MoveInResizeWidget : public QWidget
7763 {
7764     Q_OBJECT
7765 public:
7766     MoveInResizeWidget(QWidget* p = 0)
7767         : QWidget(p)
7768     {
7769         setWindowFlags(Qt::FramelessWindowHint);
7770     }
7771
7772     void resizeEvent(QResizeEvent*) {
7773
7774         move(QPoint(100,100));
7775
7776         static bool firstTime = true;
7777         if (firstTime)
7778             QTimer::singleShot(250, this, SLOT(resizeMe()));
7779
7780         firstTime = false;
7781     }
7782
7783 public slots:
7784     void resizeMe() {
7785         resize(100, 100);
7786     }
7787 };
7788
7789 void tst_QWidget::moveInResizeEvent()
7790 {
7791     MoveInResizeWidget testWidget;
7792     testWidget.setGeometry(50, 50, 200, 200);
7793     testWidget.show();
7794     QVERIFY(QTest::qWaitForWindowExposed(&testWidget));
7795     QTest::qWait(300);
7796
7797     QRect expectedGeometry(100,100, 100, 100);
7798     QTRY_COMPARE(testWidget.geometry(), expectedGeometry);
7799 }
7800
7801 void tst_QWidget::immediateRepaintAfterShow()
7802 {
7803     if (m_platform == QStringLiteral("xcb"))
7804         QSKIP("QTBUG-26424");
7805     if (m_platform != QStringLiteral("xcb") && m_platform != QStringLiteral("windows"))
7806         QSKIP("We don't support immediate repaint right after show on other platforms.");
7807
7808     UpdateWidget widget;
7809     widget.show();
7810     qApp->processEvents();
7811     // On X11 in particular, we are now waiting for a MapNotify event before
7812     // syncing the backing store. However, if someone request a repaint()
7813     // we must repaint immediately regardless of the current state.
7814     widget.numPaintEvents = 0;
7815     widget.repaint();
7816     QCOMPARE(widget.numPaintEvents, 1);
7817 }
7818
7819 void tst_QWidget::immediateRepaintAfterInvalidateBuffer()
7820 {
7821     if (m_platform != QStringLiteral("xcb") && m_platform != QStringLiteral("windows"))
7822         QSKIP("We don't support immediate repaint right after show on other platforms.");
7823
7824     QScopedPointer<UpdateWidget> widget(new UpdateWidget);
7825     widget->show();
7826     QVERIFY(QTest::qWaitForWindowExposed(widget.data()));
7827     QTest::qWait(200);
7828
7829     widget->numPaintEvents = 0;
7830
7831     // Marks the area covered by the widget as dirty in the backing store and
7832     // posts an UpdateRequest event.
7833     qt_widget_private(widget.data())->invalidateBuffer(widget->rect());
7834     QCOMPARE(widget->numPaintEvents, 0);
7835
7836     // The entire widget is already dirty, but this time we want to update immediately
7837     // by calling repaint(), and thus we have to repaint the widget and not wait for
7838     // the UpdateRequest to be sent when we get back to the event loop.
7839     widget->repaint();
7840     QCOMPARE(widget->numPaintEvents, 1);
7841 }
7842
7843 void tst_QWidget::effectiveWinId()
7844 {
7845     QWidget parent;
7846     QWidget child(&parent);
7847
7848     // Shouldn't crash.
7849     QVERIFY(!parent.effectiveWinId());
7850     QVERIFY(!child.effectiveWinId());
7851
7852     parent.show();
7853
7854     QVERIFY(parent.effectiveWinId());
7855     QVERIFY(child.effectiveWinId());
7856 }
7857
7858 void tst_QWidget::effectiveWinId2()
7859 {
7860     QWidget parent;
7861
7862     class MyWidget : public QWidget {
7863         bool event(QEvent *e)
7864         {
7865             if (e->type() == QEvent::WinIdChange) {
7866                 // Shouldn't crash.
7867                 effectiveWinId();
7868             }
7869
7870             return QWidget::event(e);
7871         }
7872     };
7873
7874     MyWidget child;
7875     child.setParent(&parent);
7876     parent.show();
7877
7878     child.setParent(0);
7879     child.setParent(&parent);
7880 }
7881
7882 class CustomWidget : public QWidget
7883 {
7884 public:
7885     mutable int metricCallCount;
7886
7887     CustomWidget(QWidget *parent = 0) : QWidget(parent), metricCallCount(0) {}
7888
7889     virtual int metric(PaintDeviceMetric metric) const {
7890         ++metricCallCount;
7891         return QWidget::metric(metric);
7892     }
7893 };
7894
7895 void tst_QWidget::customDpi()
7896 {
7897     QScopedPointer<QWidget> topLevel(new QWidget);
7898     CustomWidget *custom = new CustomWidget(topLevel.data());
7899     QWidget *child = new QWidget(custom);
7900
7901     custom->metricCallCount = 0;
7902     topLevel->logicalDpiX();
7903     QCOMPARE(custom->metricCallCount, 0);
7904     custom->logicalDpiX();
7905     QCOMPARE(custom->metricCallCount, 1);
7906     child->logicalDpiX();
7907     QCOMPARE(custom->metricCallCount, 2);
7908 }
7909
7910 void tst_QWidget::customDpiProperty()
7911 {
7912     QScopedPointer<QWidget> topLevel(new QWidget);
7913     QWidget *middle = new CustomWidget(topLevel.data());
7914     QWidget *child = new QWidget(middle);
7915
7916     const int initialDpiX = topLevel->logicalDpiX();
7917     const int initialDpiY = topLevel->logicalDpiY();
7918
7919     middle->setProperty("_q_customDpiX", 300);
7920     middle->setProperty("_q_customDpiY", 400);
7921
7922     QCOMPARE(topLevel->logicalDpiX(), initialDpiX);
7923     QCOMPARE(topLevel->logicalDpiY(), initialDpiY);
7924
7925     QCOMPARE(middle->logicalDpiX(), 300);
7926     QCOMPARE(middle->logicalDpiY(), 400);
7927
7928     QCOMPARE(child->logicalDpiX(), 300);
7929     QCOMPARE(child->logicalDpiY(), 400);
7930
7931     middle->setProperty("_q_customDpiX", QVariant());
7932     middle->setProperty("_q_customDpiY", QVariant());
7933
7934     QCOMPARE(topLevel->logicalDpiX(), initialDpiX);
7935     QCOMPARE(topLevel->logicalDpiY(), initialDpiY);
7936
7937     QCOMPARE(middle->logicalDpiX(), initialDpiX);
7938     QCOMPARE(middle->logicalDpiY(), initialDpiY);
7939
7940     QCOMPARE(child->logicalDpiX(), initialDpiX);
7941     QCOMPARE(child->logicalDpiY(), initialDpiY);
7942 }
7943
7944 void tst_QWidget::quitOnCloseAttribute()
7945 {
7946     QWidget w;
7947     QCOMPARE(w.testAttribute(Qt::WA_QuitOnClose), true);
7948     w.setAttribute(Qt::WA_QuitOnClose, false);
7949     QCOMPARE(w.testAttribute(Qt::WA_QuitOnClose), false);
7950
7951     w.setAttribute(Qt::WA_QuitOnClose);
7952     w.setWindowFlags(Qt::Tool);
7953     QCOMPARE(w.testAttribute(Qt::WA_QuitOnClose), false);
7954
7955     w.setAttribute(Qt::WA_QuitOnClose);
7956     w.setWindowFlags(Qt::Popup);
7957     QCOMPARE(w.testAttribute(Qt::WA_QuitOnClose), false);
7958
7959     w.setAttribute(Qt::WA_QuitOnClose);
7960     w.setWindowFlags(Qt::ToolTip);
7961     QCOMPARE(w.testAttribute(Qt::WA_QuitOnClose), false);
7962
7963     w.setAttribute(Qt::WA_QuitOnClose);
7964     w.setWindowFlags(Qt::SplashScreen);
7965     QCOMPARE(w.testAttribute(Qt::WA_QuitOnClose), false);
7966
7967     w.setAttribute(Qt::WA_QuitOnClose);
7968     w.setWindowFlags(Qt::SubWindow);
7969     QCOMPARE(w.testAttribute(Qt::WA_QuitOnClose), false);
7970
7971     w.setAttribute(Qt::WA_QuitOnClose);
7972     w.setWindowFlags(Qt::Dialog);
7973     QCOMPARE(w.testAttribute(Qt::WA_QuitOnClose), true);
7974     w.show();
7975     QCOMPARE(w.testAttribute(Qt::WA_QuitOnClose), true);
7976     w.setWindowFlags(Qt::Tool);
7977     QCOMPARE(w.testAttribute(Qt::WA_QuitOnClose), false);
7978 }
7979
7980 void tst_QWidget::moveRect()
7981 {
7982     QWidget widget;
7983     widget.resize(200, 200);
7984     widget.setUpdatesEnabled(false);
7985     QWidget child(&widget);
7986     child.setUpdatesEnabled(false);
7987     child.setAttribute(Qt::WA_OpaquePaintEvent);
7988     widget.show();
7989     QTest::qWait(200);
7990     child.move(10, 10); // Don't crash.
7991 }
7992
7993 #ifdef Q_OS_WIN
7994 class GDIWidget : public QDialog
7995 {
7996     Q_OBJECT
7997 public:
7998     GDIWidget() {
7999         setAttribute(Qt::WA_PaintOnScreen);
8000         timer.setSingleShot(true);
8001         timer.setInterval(0);
8002     }
8003     QPaintEngine *paintEngine() const { return 0; }
8004
8005     void paintEvent(QPaintEvent *) {
8006         QPlatformNativeInterface *ni = QGuiApplication::platformNativeInterface();
8007         const HDC hdc = (HDC)ni->nativeResourceForWindow(QByteArrayLiteral("getDC"), windowHandle());
8008         if (hdc) {
8009             const HBRUSH brush = CreateSolidBrush(RGB(255, 0, 0));
8010             SelectObject(hdc, brush);
8011             Rectangle(hdc, 0, 0, 10, 10);
8012             DeleteObject(brush);
8013             ni->nativeResourceForWindow(QByteArrayLiteral("releaseDC"), windowHandle());
8014         } else {
8015             qWarning("%s: Unable to obtain native DC.", Q_FUNC_INFO);
8016         }
8017         if (!timer.isActive()) {
8018             connect(&timer, &QTimer::timeout, this,
8019                     hdc ? &GDIWidget::slotTimer : &QDialog::reject);
8020             timer.start();
8021         }
8022     }
8023
8024     QSize sizeHint() const {
8025         return QSize(400, 300);
8026     }
8027
8028 private slots:
8029     void slotTimer() {
8030         QScreen *screen = windowHandle()->screen();
8031         const QImage im = screen->grabWindow(internalWinId(), 0, 0, -1, -1).toImage();
8032         color = im.pixel(1, 1);
8033         accept();
8034     }
8035
8036 public:
8037     QColor color;
8038     QTimer timer;
8039 };
8040
8041 void tst_QWidget::gdiPainting()
8042 {
8043     GDIWidget w;
8044     w.exec();
8045
8046     QCOMPARE(w.color, QColor(255, 0, 0));
8047
8048 }
8049
8050 void tst_QWidget::paintOnScreenPossible()
8051 {
8052     QWidget w1;
8053     w1.setAttribute(Qt::WA_PaintOnScreen);
8054     QVERIFY(!w1.testAttribute(Qt::WA_PaintOnScreen));
8055
8056     GDIWidget w2;
8057     w2.setAttribute(Qt::WA_PaintOnScreen);
8058     QVERIFY(w2.testAttribute(Qt::WA_PaintOnScreen));
8059 }
8060 #endif // Q_OS_WIN
8061
8062 void tst_QWidget::reparentStaticWidget()
8063 {
8064     QWidget window1;
8065
8066     QWidget *child = new QWidget(&window1);
8067     child->setPalette(Qt::red);
8068     child->setAutoFillBackground(true);
8069     child->setAttribute(Qt::WA_StaticContents);
8070     child->resize(160, 160);
8071
8072     QWidget *grandChild = new QWidget(child);
8073     grandChild->setPalette(Qt::blue);
8074     grandChild->setAutoFillBackground(true);
8075     grandChild->resize(50, 50);
8076     grandChild->setAttribute(Qt::WA_StaticContents);
8077     window1.show();
8078     QVERIFY(QTest::qWaitForWindowExposed(&window1));
8079
8080     QWidget window2;
8081     window2.show();
8082     QVERIFY(QTest::qWaitForWindowExposed(&window2));
8083     QTest::qWait(20);
8084
8085     // Reparent into another top-level.
8086     child->setParent(&window2);
8087     child->show();
8088
8089     // Please don't crash.
8090     window1.resize(window1.size() + QSize(2, 2));
8091     QTest::qWait(20);
8092
8093     // Make sure we move all static children even though
8094     // the reparented widget itself is non-static.
8095     child->setAttribute(Qt::WA_StaticContents, false);
8096     child->setParent(&window1);
8097     child->show();
8098
8099     // Please don't crash.
8100     window2.resize(window2.size() + QSize(2, 2));
8101     QTest::qWait(20);
8102
8103     child->setParent(0);
8104     child->show();
8105     QTest::qWait(20);
8106
8107     // Please don't crash.
8108     child->resize(child->size() + QSize(2, 2));
8109     window2.resize(window2.size() + QSize(2, 2));
8110     QTest::qWait(20);
8111
8112     QWidget *siblingOfGrandChild = new QWidget(child);
8113     siblingOfGrandChild->show();
8114     QTest::qWait(20);
8115
8116     // Nothing should happen when reparenting within the same top-level.
8117     grandChild->setParent(siblingOfGrandChild);
8118     grandChild->show();
8119     QTest::qWait(20);
8120
8121     QWidget paintOnScreen;
8122     paintOnScreen.setAttribute(Qt::WA_PaintOnScreen);
8123     paintOnScreen.show();
8124     QVERIFY(QTest::qWaitForWindowExposed(&paintOnScreen));
8125     QTest::qWait(20);
8126
8127     child->setParent(&paintOnScreen);
8128     child->show();
8129     QTest::qWait(20);
8130
8131     // Please don't crash.
8132     paintOnScreen.resize(paintOnScreen.size() + QSize(2, 2));
8133     QTest::qWait(20);
8134
8135 }
8136
8137 void tst_QWidget::QTBUG6883_reparentStaticWidget2()
8138 {
8139     QMainWindow mw;
8140     QDockWidget *one = new QDockWidget("one", &mw);
8141     mw.addDockWidget(Qt::LeftDockWidgetArea, one , Qt::Vertical);
8142
8143     QWidget *child = new QWidget();
8144     child->setPalette(Qt::red);
8145     child->setAutoFillBackground(true);
8146     child->setAttribute(Qt::WA_StaticContents);
8147     child->resize(100, 100);
8148     one->setWidget(child);
8149
8150     QToolBar *mainTools = mw.addToolBar("Main Tools");
8151     mainTools->addWidget(new QLineEdit);
8152
8153     mw.show();
8154     QVERIFY(QTest::qWaitForWindowExposed(&mw));
8155
8156     one->setFloating(true);
8157     QTest::qWait(20);
8158     //do not crash
8159 }
8160
8161 class ColorRedWidget : public QWidget
8162 {
8163 public:
8164     ColorRedWidget(QWidget *parent = 0)
8165         : QWidget(parent, Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint | Qt::ToolTip)
8166     {
8167     }
8168
8169     void paintEvent(QPaintEvent *) {
8170         QPainter p(this);
8171         p.fillRect(rect(),Qt::red);
8172     }
8173 };
8174
8175 void tst_QWidget::translucentWidget()
8176 {
8177     QPixmap pm(16,16);
8178     pm.fill(Qt::red);
8179     ColorRedWidget label;
8180     label.setFixedSize(16,16);
8181     label.setAttribute(Qt::WA_TranslucentBackground);
8182     const QPoint labelPos = qApp->desktop()->availableGeometry().topLeft();
8183     label.move(labelPos);
8184     label.show();
8185     QVERIFY(QTest::qWaitForWindowExposed(&label));
8186     QTest::qWait(200);
8187
8188     QPixmap widgetSnapshot;
8189
8190 #ifdef Q_OS_WIN
8191     QWidget *desktopWidget = QApplication::desktop()->screen(0);
8192     if (QSysInfo::windowsVersion() >= QSysInfo::WV_VISTA)
8193         widgetSnapshot = qApp->primaryScreen()->grabWindow(desktopWidget->winId(), labelPos.x(), labelPos.y(), label.width(), label.height());
8194     else
8195 #endif
8196         widgetSnapshot = label.grab(QRect(QPoint(0, 0), label.size()));
8197     QImage actual = widgetSnapshot.toImage().convertToFormat(QImage::Format_RGB32);
8198     QImage expected = pm.toImage().convertToFormat(QImage::Format_RGB32);
8199     QCOMPARE(actual.size(),expected.size());
8200     QCOMPARE(actual,expected);
8201 }
8202
8203 class MaskResizeTestWidget : public QWidget
8204 {
8205     Q_OBJECT
8206 public:
8207     MaskResizeTestWidget(QWidget* p =0)
8208             : QWidget(p) {
8209         setMask(QRegion(QRect(0, 0, 100, 100).normalized()));
8210     }
8211
8212     void paintEvent(QPaintEvent* event) {
8213         QPainter p(this);
8214
8215         paintedRegion += event->region();
8216         foreach(QRect r, event->region().rects())
8217             p.fillRect(r, Qt::red);
8218     }
8219
8220     QRegion paintedRegion;
8221
8222 public slots:
8223     void enlargeMask() {
8224         QRegion newMask(QRect(0, 0, 150, 150).normalized());
8225         setMask(newMask);
8226     }
8227
8228     void shrinkMask() {
8229         QRegion newMask(QRect(0, 0, 50, 50).normalized());
8230         setMask(newMask);
8231     }
8232
8233 };
8234
8235 void tst_QWidget::setClearAndResizeMask()
8236 {
8237     UpdateWidget topLevel;
8238     topLevel.resize(160, 160);
8239     topLevel.show();
8240     qApp->setActiveWindow(&topLevel);
8241     QVERIFY(QTest::qWaitForWindowActive(&topLevel));
8242     QTRY_VERIFY(topLevel.numPaintEvents > 0);
8243     topLevel.reset();
8244
8245     // Mask top-level widget
8246     const QRegion topLevelMask(0, 0, 100, 100, QRegion::Ellipse);
8247     topLevel.setMask(topLevelMask);
8248     QCOMPARE(topLevel.mask(), topLevelMask);
8249     // Ensure that the top-level doesn't get any update.
8250     // We don't control what's happening on platforms other than X11, Windows
8251     if (m_platform == QStringLiteral("xcb") || m_platform == QStringLiteral("windows"))
8252         QCOMPARE(topLevel.numPaintEvents, 0);
8253
8254     topLevel.reset();
8255
8256     // Clear top-level mask
8257     topLevel.clearMask();
8258     QCOMPARE(topLevel.mask(), QRegion());
8259     QTest::qWait(10);
8260     QRegion outsideOldMask(topLevel.rect());
8261     outsideOldMask -= topLevelMask;
8262     // Ensure that the top-level gets an update for the area outside the old mask.
8263     // We don't control what's happening on platforms other than X11, Windows
8264     if (m_platform == QStringLiteral("xcb") || m_platform == QStringLiteral("windows")) {
8265         QTRY_VERIFY(topLevel.numPaintEvents > 0);
8266         QTRY_COMPARE(topLevel.paintedRegion, outsideOldMask);
8267     }
8268
8269     UpdateWidget child(&topLevel);
8270     child.setAutoFillBackground(true); // NB! Opaque child.
8271     child.setPalette(Qt::red);
8272     child.resize(100, 100);
8273     child.show();
8274     QTest::qWait(10);
8275
8276     child.reset();
8277     topLevel.reset();
8278
8279     // Mask child widget with a mask that is smaller than the rect
8280     const QRegion childMask(0, 0, 50, 50);
8281     child.setMask(childMask);
8282     QTRY_COMPARE(child.mask(), childMask);
8283     QTest::qWait(50);
8284     // and ensure that the child widget doesn't get any update.
8285 #ifdef Q_OS_MAC
8286     // Mac always issues a full update when calling setMask, and we cannot force it to not do so.
8287     if (child.internalWinId())
8288         QCOMPARE(child.numPaintEvents, 1);
8289     else
8290 #endif
8291     QCOMPARE(child.numPaintEvents, 0);
8292     // and the parent widget gets an update for the newly exposed area.
8293     QTRY_COMPARE(topLevel.numPaintEvents, 1);
8294     QRegion expectedParentExpose(child.rect());
8295     expectedParentExpose -= childMask;
8296     QCOMPARE(topLevel.paintedRegion, expectedParentExpose);
8297
8298     child.reset();
8299     topLevel.reset();
8300
8301     // Clear child widget mask
8302     child.clearMask();
8303     QTRY_COMPARE(child.mask(), QRegion());
8304     QTest::qWait(10);
8305     // and ensure that that the child widget gets an update for the area outside the old mask.
8306     QTRY_COMPARE(child.numPaintEvents, 1);
8307     outsideOldMask = child.rect();
8308 #ifdef Q_OS_MAC
8309     // Mac always issues a full update when calling setMask, and we cannot force it to not do so.
8310     if (!child.internalWinId())
8311 #endif
8312     outsideOldMask -= childMask;
8313     QCOMPARE(child.paintedRegion, outsideOldMask);
8314     // and the parent widget doesn't get any update.
8315     QCOMPARE(topLevel.numPaintEvents, 0);
8316
8317     child.reset();
8318     topLevel.reset();
8319
8320     // Mask child widget with a mask that is bigger than the rect
8321     child.setMask(QRegion(0, 0, 1000, 1000));
8322     QTest::qWait(100);
8323 #ifdef Q_OS_MAC
8324     // Mac always issues a full update when calling setMask, and we cannot force it to not do so.
8325     if (child.internalWinId())
8326         QTRY_COMPARE(child.numPaintEvents, 1);
8327     else
8328 #endif
8329     // and ensure that we don't get any updates at all.
8330     QTRY_COMPARE(child.numPaintEvents, 0);
8331     QCOMPARE(topLevel.numPaintEvents, 0);
8332
8333     // ...and the same applies when clearing the mask.
8334     child.clearMask();
8335     QTest::qWait(100);
8336 #ifdef Q_OS_MAC
8337     // Mac always issues a full update when calling setMask, and we cannot force it to not do so.
8338     if (child.internalWinId())
8339         QTRY_VERIFY(child.numPaintEvents > 0);
8340     else
8341 #endif
8342     QCOMPARE(child.numPaintEvents, 0);
8343     QCOMPARE(topLevel.numPaintEvents, 0);
8344
8345     QWidget resizeParent;
8346     MaskResizeTestWidget resizeChild(&resizeParent);
8347
8348     resizeParent.resize(300,300);
8349     resizeParent.raise();
8350     resizeParent.setWindowFlags(Qt::WindowStaysOnTopHint);
8351     resizeChild.setGeometry(50,50,200,200);
8352     QPalette pal = resizeParent.palette();
8353     pal.setColor(QPalette::Window, QColor(Qt::white));
8354     resizeParent.setPalette(pal);
8355
8356     resizeParent.show();
8357     QVERIFY(QTest::qWaitForWindowExposed(&resizeParent));
8358     // Disable the size grip on the Mac; otherwise it'll be included when grabbing the window.
8359     resizeParent.setFixedSize(resizeParent.size());
8360     resizeChild.show();
8361     QTest::qWait(100);
8362     resizeChild.paintedRegion = QRegion();
8363
8364     QTimer::singleShot(100, &resizeChild, SLOT(shrinkMask()));
8365     QTest::qWait(200);
8366 #ifdef Q_OS_MAC
8367     // Mac always issues a full update when calling setMask, and we cannot force it to not do so.
8368     if (child.internalWinId())
8369         QTRY_COMPARE(resizeChild.paintedRegion, resizeChild.mask());
8370     else
8371 #endif
8372     QTRY_COMPARE(resizeChild.paintedRegion, QRegion());
8373
8374     resizeChild.paintedRegion = QRegion();
8375     const QRegion oldMask = resizeChild.mask();
8376     QTimer::singleShot(0, &resizeChild, SLOT(enlargeMask()));
8377     QTest::qWait(100);
8378 #ifdef Q_OS_MAC
8379     // Mac always issues a full update when calling setMask, and we cannot force it to not do so.
8380     if (child.internalWinId())
8381         QTRY_COMPARE(resizeChild.paintedRegion, resizeChild.mask());
8382     else
8383 #endif
8384     QTRY_COMPARE(resizeChild.paintedRegion, resizeChild.mask() - oldMask);
8385 }
8386
8387 void tst_QWidget::maskedUpdate()
8388 {
8389     UpdateWidget topLevel;
8390     topLevel.resize(200, 200);
8391     const QRegion topLevelMask(50, 50, 70, 70);
8392     topLevel.setMask(topLevelMask);
8393
8394     UpdateWidget child(&topLevel);
8395     child.setGeometry(20, 20, 180, 180);
8396     const QRegion childMask(60, 60, 30, 30);
8397     child.setMask(childMask);
8398
8399     UpdateWidget grandChild(&child);
8400     grandChild.setGeometry(50, 50, 100, 100);
8401     const QRegion grandChildMask(20, 20, 10, 10);
8402     grandChild.setMask(grandChildMask);
8403
8404     topLevel.show();
8405     QVERIFY(QTest::qWaitForWindowExposed(&topLevel));
8406     QTRY_VERIFY(topLevel.numPaintEvents > 0);
8407
8408
8409 #define RESET_WIDGETS \
8410     topLevel.reset(); \
8411     child.reset(); \
8412     grandChild.reset();
8413
8414 #define CLEAR_MASK(widget) \
8415     widget.clearMask(); \
8416     QTest::qWait(100); \
8417     RESET_WIDGETS;
8418
8419     // All widgets are transparent at this point, so any call to update() will result
8420     // in composition, i.e. the update propagates to ancestors and children.
8421
8422     // TopLevel update.
8423     RESET_WIDGETS;
8424     topLevel.update();
8425     QTest::qWait(10);
8426
8427     QTRY_COMPARE(topLevel.paintedRegion, topLevelMask);
8428     QTRY_COMPARE(child.paintedRegion, childMask);
8429     QTRY_COMPARE(grandChild.paintedRegion, grandChildMask);
8430
8431     // Child update.
8432     RESET_WIDGETS;
8433     child.update();
8434     QTest::qWait(10);
8435
8436     QTRY_COMPARE(topLevel.paintedRegion, childMask.translated(child.pos()));
8437     QTRY_COMPARE(child.paintedRegion, childMask);
8438     QTRY_COMPARE(grandChild.paintedRegion, grandChildMask);
8439
8440     // GrandChild update.
8441     RESET_WIDGETS;
8442     grandChild.update();
8443     QTest::qWait(10);
8444
8445     QTRY_COMPARE(topLevel.paintedRegion, grandChildMask.translated(grandChild.mapTo(&topLevel, QPoint())));
8446     QTRY_COMPARE(child.paintedRegion, grandChildMask.translated(grandChild.pos()));
8447     QTRY_COMPARE(grandChild.paintedRegion, grandChildMask);
8448
8449     topLevel.setAttribute(Qt::WA_OpaquePaintEvent);
8450     child.setAttribute(Qt::WA_OpaquePaintEvent);
8451     grandChild.setAttribute(Qt::WA_OpaquePaintEvent);
8452
8453     // All widgets are now opaque, which means no composition, i.e.
8454     // the update does not propate to ancestors and children.
8455
8456     // TopLevel update.
8457     RESET_WIDGETS;
8458     topLevel.update();
8459     QTest::qWait(10);
8460
8461     QRegion expectedTopLevelUpdate = topLevelMask;
8462     expectedTopLevelUpdate -= childMask.translated(child.pos()); // Subtract opaque children.
8463     QTRY_COMPARE(topLevel.paintedRegion, expectedTopLevelUpdate);
8464     QTRY_COMPARE(child.paintedRegion, QRegion());
8465     QTRY_COMPARE(grandChild.paintedRegion, QRegion());
8466
8467     // Child update.
8468     RESET_WIDGETS;
8469     child.update();
8470     QTest::qWait(10);
8471
8472     QTRY_COMPARE(topLevel.paintedRegion, QRegion());
8473     QRegion expectedChildUpdate = childMask;
8474     expectedChildUpdate -= grandChildMask.translated(grandChild.pos()); // Subtract oapque children.
8475     QTRY_COMPARE(child.paintedRegion, expectedChildUpdate);
8476     QTRY_COMPARE(grandChild.paintedRegion, QRegion());
8477
8478     // GrandChild update.
8479     RESET_WIDGETS;
8480     grandChild.update();
8481     QTest::qWait(10);
8482
8483     QTRY_COMPARE(topLevel.paintedRegion, QRegion());
8484     QTRY_COMPARE(child.paintedRegion, QRegion());
8485     QTRY_COMPARE(grandChild.paintedRegion, grandChildMask);
8486
8487     // GrandChild update.
8488     CLEAR_MASK(grandChild);
8489     grandChild.update();
8490     QTest::qWait(10);
8491
8492     QTRY_COMPARE(topLevel.paintedRegion, QRegion());
8493     QTRY_COMPARE(child.paintedRegion, QRegion());
8494     QRegion expectedGrandChildUpdate = grandChild.rect();
8495     // Clip with parent's mask.
8496     expectedGrandChildUpdate &= childMask.translated(-grandChild.pos());
8497     QCOMPARE(grandChild.paintedRegion, expectedGrandChildUpdate);
8498
8499     // GrandChild update.
8500     CLEAR_MASK(child);
8501     grandChild.update();
8502     QTest::qWait(10);
8503
8504     QTRY_COMPARE(topLevel.paintedRegion, QRegion());
8505     QTRY_COMPARE(child.paintedRegion, QRegion());
8506     expectedGrandChildUpdate = grandChild.rect();
8507     // Clip with parent's mask.
8508     expectedGrandChildUpdate &= topLevelMask.translated(-grandChild.mapTo(&topLevel, QPoint()));
8509     QTRY_COMPARE(grandChild.paintedRegion, expectedGrandChildUpdate);
8510
8511     // Child update.
8512     RESET_WIDGETS;
8513     child.update();
8514     QTest::qWait(10);
8515
8516     QTRY_COMPARE(topLevel.paintedRegion, QRegion());
8517     expectedChildUpdate = child.rect();
8518     // Clip with parent's mask.
8519     expectedChildUpdate &= topLevelMask.translated(-child.pos());
8520     expectedChildUpdate -= grandChild.geometry(); // Subtract opaque children.
8521     QTRY_COMPARE(child.paintedRegion, expectedChildUpdate);
8522     QTRY_COMPARE(grandChild.paintedRegion, QRegion());
8523
8524     // GrandChild update.
8525     CLEAR_MASK(topLevel);
8526     grandChild.update();
8527     QTest::qWait(10);
8528
8529     QTRY_COMPARE(topLevel.paintedRegion, QRegion());
8530     QTRY_COMPARE(child.paintedRegion, QRegion());
8531     QTRY_COMPARE(grandChild.paintedRegion, QRegion(grandChild.rect())); // Full update.
8532 }
8533
8534 #ifndef QTEST_NO_CURSOR
8535 void tst_QWidget::syntheticEnterLeave()
8536 {
8537     class MyWidget : public QWidget
8538     {
8539     public:
8540         MyWidget(QWidget *parent = 0) : QWidget(parent), numEnterEvents(0), numLeaveEvents(0) {}
8541         void enterEvent(QEvent *) { ++numEnterEvents; }
8542         void leaveEvent(QEvent *) { ++numLeaveEvents; }
8543         int numEnterEvents;
8544         int numLeaveEvents;
8545     };
8546
8547     QCursor::setPos(QPoint(0,0));
8548
8549     MyWidget window;
8550     window.setWindowFlags(Qt::WindowStaysOnTopHint);
8551     window.move(200, 200);
8552     window.resize(200, 200);
8553
8554     MyWidget *child1 = new MyWidget(&window);
8555     child1->setPalette(Qt::blue);
8556     child1->setAutoFillBackground(true);
8557     child1->resize(200, 200);
8558     child1->setCursor(Qt::OpenHandCursor);
8559
8560     MyWidget *child2 = new MyWidget(&window);
8561     child2->resize(200, 200);
8562
8563     MyWidget *grandChild = new MyWidget(child2);
8564     grandChild->setPalette(Qt::red);
8565     grandChild->setAutoFillBackground(true);
8566     grandChild->resize(200, 200);
8567     grandChild->setCursor(Qt::WaitCursor);
8568
8569     window.show();
8570     window.raise();
8571
8572     QVERIFY(QTest::qWaitForWindowExposed(&window));
8573     QTest::qWait(300);
8574
8575 #define RESET_EVENT_COUNTS \
8576     window.numEnterEvents = 0; \
8577     window.numLeaveEvents = 0; \
8578     child1->numEnterEvents = 0; \
8579     child1->numLeaveEvents = 0; \
8580     child2->numEnterEvents = 0; \
8581     child2->numLeaveEvents = 0; \
8582     grandChild->numEnterEvents = 0; \
8583     grandChild->numLeaveEvents = 0;
8584
8585     // Position the cursor in the middle of the window.
8586     const QPoint globalPos = window.mapToGlobal(QPoint(100, 100));
8587     QCursor::setPos(globalPos); // Enter child2 and grandChild.
8588     QTest::qWait(300);
8589
8590     QCOMPARE(window.numLeaveEvents, 0);
8591     QCOMPARE(child2->numLeaveEvents, 0);
8592     QCOMPARE(grandChild->numLeaveEvents, 0);
8593     QCOMPARE(child1->numLeaveEvents, 0);
8594
8595     // This event arrives asynchronously
8596     QTRY_COMPARE(window.numEnterEvents, 1);
8597     QCOMPARE(child2->numEnterEvents, 1);
8598     QCOMPARE(grandChild->numEnterEvents, 1);
8599     QCOMPARE(child1->numEnterEvents, 0);
8600
8601     RESET_EVENT_COUNTS;
8602     child2->hide(); // Leave child2 and grandChild, enter child1.
8603
8604     QCOMPARE(window.numLeaveEvents, 0);
8605     QCOMPARE(child2->numLeaveEvents, 1);
8606     QCOMPARE(grandChild->numLeaveEvents, 1);
8607     QCOMPARE(child1->numLeaveEvents, 0);
8608
8609     QCOMPARE(window.numEnterEvents, 0);
8610     QCOMPARE(child2->numEnterEvents, 0);
8611     QCOMPARE(grandChild->numEnterEvents, 0);
8612     QCOMPARE(child1->numEnterEvents, 1);
8613
8614     RESET_EVENT_COUNTS;
8615     child2->show(); // Leave child1, enter child2 and grandChild.
8616
8617     QCOMPARE(window.numLeaveEvents, 0);
8618     QCOMPARE(child2->numLeaveEvents, 0);
8619     QCOMPARE(grandChild->numLeaveEvents, 0);
8620     QCOMPARE(child1->numLeaveEvents, 1);
8621
8622     QCOMPARE(window.numEnterEvents, 0);
8623     QCOMPARE(child2->numEnterEvents, 1);
8624     QCOMPARE(grandChild->numEnterEvents, 1);
8625     QCOMPARE(child1->numEnterEvents, 0);
8626
8627     RESET_EVENT_COUNTS;
8628     delete child2; // Enter child1 (and do not send leave events to child2 and grandChild).
8629
8630     QCOMPARE(window.numLeaveEvents, 0);
8631     QCOMPARE(child1->numLeaveEvents, 0);
8632
8633     QCOMPARE(window.numEnterEvents, 0);
8634     QCOMPARE(child1->numEnterEvents, 1);
8635 }
8636 #endif
8637
8638 #ifndef QTEST_NO_CURSOR
8639 void tst_QWidget::taskQTBUG_4055_sendSyntheticEnterLeave()
8640 {
8641     class SELParent : public QWidget
8642     {
8643     public:
8644         SELParent(QWidget *parent = 0): QWidget(parent) { }
8645
8646         void mousePressEvent(QMouseEvent *) { child->show(); }
8647         QWidget *child;
8648     };
8649
8650     class SELChild : public QWidget
8651      {
8652      public:
8653          SELChild(QWidget *parent = 0) : QWidget(parent), numEnterEvents(0), numMouseMoveEvents(0) {}
8654          void enterEvent(QEvent *) { ++numEnterEvents; }
8655          void mouseMoveEvent(QMouseEvent *event)
8656          {
8657              QCOMPARE(event->button(), Qt::NoButton);
8658              QCOMPARE(event->buttons(), Qt::MouseButtons(Qt::NoButton));
8659              ++numMouseMoveEvents;
8660          }
8661          void reset() { numEnterEvents = numMouseMoveEvents = 0; }
8662          int numEnterEvents, numMouseMoveEvents;
8663      };
8664
8665     QCursor::setPos(QPoint(0,0));
8666
8667      SELParent parent;
8668      parent.move(200, 200);
8669      parent.resize(200, 200);
8670      SELChild child(&parent);
8671      child.resize(200, 200);
8672      parent.show();
8673      QVERIFY(QTest::qWaitForWindowExposed(&parent));
8674      QTest::qWait(150);
8675
8676      QCursor::setPos(child.mapToGlobal(QPoint(100, 100)));
8677      // Make sure the cursor has entered the child.
8678      QTRY_VERIFY(child.numEnterEvents > 0);
8679
8680      child.hide();
8681      child.reset();
8682      child.show();
8683
8684      // Make sure the child gets enter event and no mouse move event.
8685      QTRY_COMPARE(child.numEnterEvents, 1);
8686      QCOMPARE(child.numMouseMoveEvents, 0);
8687
8688      child.hide();
8689      child.reset();
8690      child.setMouseTracking(true);
8691      child.show();
8692
8693      // Make sure the child gets enter event and mouse move event.
8694      // Note that we verify event->button() and event->buttons()
8695      // in SELChild::mouseMoveEvent().
8696      QTRY_COMPARE(child.numEnterEvents, 1);
8697      QCOMPARE(child.numMouseMoveEvents, 1);
8698
8699      // Sending synthetic enter/leave trough the parent's mousePressEvent handler.
8700      parent.child = &child;
8701
8702      child.hide();
8703      child.reset();
8704      QTest::mouseClick(&parent, Qt::LeftButton);
8705
8706      // Make sure the child gets enter event and one mouse move event.
8707      QTRY_COMPARE(child.numEnterEvents, 1);
8708      QCOMPARE(child.numMouseMoveEvents, 1);
8709
8710      child.hide();
8711      child.reset();
8712      child.setMouseTracking(false);
8713      QTest::mouseClick(&parent, Qt::LeftButton);
8714
8715      // Make sure the child gets enter event and no mouse move event.
8716      QTRY_COMPARE(child.numEnterEvents, 1);
8717      QCOMPARE(child.numMouseMoveEvents, 0);
8718  }
8719 #endif
8720
8721 void tst_QWidget::windowFlags()
8722 {
8723     QWidget w;
8724     w.setWindowFlags(w.windowFlags() | Qt::FramelessWindowHint);
8725     QVERIFY(w.windowFlags() & Qt::FramelessWindowHint);
8726 }
8727
8728 void tst_QWidget::initialPosForDontShowOnScreenWidgets()
8729 {
8730     { // Check default position.
8731         const QPoint expectedPos(0, 0);
8732         QWidget widget;
8733         widget.setAttribute(Qt::WA_DontShowOnScreen);
8734         widget.winId(); // Make sure create_sys is called.
8735         QCOMPARE(widget.pos(), expectedPos);
8736         QCOMPARE(widget.geometry().topLeft(), expectedPos);
8737     }
8738
8739     { // Explicitly move to a position.
8740         const QPoint expectedPos(100, 100);
8741         QWidget widget;
8742         widget.setAttribute(Qt::WA_DontShowOnScreen);
8743         widget.move(expectedPos);
8744         widget.winId(); // Make sure create_sys is called.
8745         QCOMPARE(widget.pos(), expectedPos);
8746         QCOMPARE(widget.geometry().topLeft(), expectedPos);
8747     }
8748 }
8749
8750 class MyEvilObject : public QObject
8751 {
8752     Q_OBJECT
8753 public:
8754     MyEvilObject(QWidget *widgetToCrash) : QObject(), widget(widgetToCrash)
8755     {
8756         connect(widget, SIGNAL(destroyed(QObject*)), this, SLOT(beEvil(QObject*)));
8757         delete widget;
8758     }
8759     QWidget *widget;
8760
8761 private slots:
8762     void beEvil(QObject *) { widget->update(0, 0, 150, 150); }
8763 };
8764
8765 void tst_QWidget::updateOnDestroyedSignal()
8766 {
8767     QWidget widget;
8768
8769     QWidget *child = new QWidget(&widget);
8770     child->resize(200, 200);
8771     child->setAutoFillBackground(true);
8772     child->setPalette(Qt::red);
8773
8774     widget.show();
8775     QVERIFY(QTest::qWaitForWindowExposed(&widget));
8776     QTest::qWait(200);
8777
8778     // Please do not crash.
8779     MyEvilObject evil(child);
8780     QTest::qWait(200);
8781 }
8782
8783 void tst_QWidget::toplevelLineEditFocus()
8784 {
8785     testWidget->hide();
8786
8787     QLineEdit w;
8788     w.show();
8789     QVERIFY(QTest::qWaitForWindowExposed(&w));
8790     QTest::qWait(20);
8791
8792     QTRY_COMPARE(QApplication::activeWindow(), (QWidget*)&w);
8793     QTRY_COMPARE(QApplication::focusWidget(), (QWidget*)&w);
8794 }
8795
8796 void tst_QWidget::focusWidget_task254563()
8797 {
8798     //having different visibility for widget is important
8799     QWidget top;
8800     top.show();
8801     QWidget container(&top);
8802     QWidget *widget = new QWidget(&container);
8803     widget->show();
8804
8805     widget->setFocus(); //set focus (will set the focus widget up to the toplevel to be 'widget')
8806     container.setFocus();
8807     delete widget; // will call clearFocus but that doesn't help
8808     QVERIFY(top.focusWidget() != widget); //dangling pointer
8809 }
8810
8811 // This test case relies on developer build (AUTOTEST_EXPORT).
8812 #ifdef QT_BUILD_INTERNAL
8813 void tst_QWidget::destroyBackingStore()
8814 {
8815     UpdateWidget w;
8816     w.reset();
8817     w.show();
8818
8819     QVERIFY(QTest::qWaitForWindowExposed(&w));
8820     QApplication::processEvents();
8821     QTRY_VERIFY(w.numPaintEvents > 0);
8822     w.reset();
8823     w.update();
8824     qt_widget_private(&w)->topData()->backingStoreTracker.create(&w);
8825
8826     w.update();
8827     QApplication::processEvents();
8828
8829     QCOMPARE(w.numPaintEvents, 1);
8830
8831     // Check one more time, because the second time around does more caching.
8832     w.update();
8833     QApplication::processEvents();
8834     QCOMPARE(w.numPaintEvents, 2);
8835 }
8836 #endif // QT_BUILD_INTERNAL
8837
8838 // Helper function
8839 QWidgetBackingStore* backingStore(QWidget &widget)
8840 {
8841     QWidgetBackingStore *backingStore = 0;
8842 #ifdef QT_BUILD_INTERNAL
8843     if (QTLWExtra *topExtra = qt_widget_private(&widget)->maybeTopData())
8844         backingStore = topExtra->backingStoreTracker.data();
8845 #endif
8846     return backingStore;
8847 }
8848
8849 // Tables of 5000 elements do not make sense on Windows Mobile.
8850 #ifndef Q_OS_WINCE_WM
8851 void tst_QWidget::rectOutsideCoordinatesLimit_task144779()
8852 {
8853 #ifndef QTEST_NO_CURSOR
8854     QApplication::setOverrideCursor(Qt::BlankCursor); //keep the cursor out of screen grabs
8855 #endif
8856     QWidget main(0,Qt::FramelessWindowHint); //don't get confused by the size of the window frame
8857     QPalette palette;
8858     palette.setColor(QPalette::Window, Qt::red);
8859     main.setPalette(palette);
8860
8861     QDesktopWidget desktop;
8862     QRect desktopDimensions = desktop.availableGeometry(&main);
8863     QSize mainSize(400, 400);
8864     mainSize = mainSize.boundedTo(desktopDimensions.size());
8865     main.resize(mainSize);
8866
8867     QWidget *offsetWidget = new QWidget(&main);
8868     offsetWidget->setGeometry(0, -(15000 - mainSize.height()), mainSize.width(), 15000);
8869
8870     // big widget is too big for the coordinates, it must be limited by wrect
8871     // if wrect is not at the right position because of offsetWidget, bigwidget
8872     // is not painted correctly
8873     QWidget *bigWidget = new QWidget(offsetWidget);
8874     bigWidget->setGeometry(0, 0, mainSize.width(), 50000);
8875     palette.setColor(QPalette::Window, Qt::green);
8876     bigWidget->setPalette(palette);
8877     bigWidget->setAutoFillBackground(true);
8878
8879     main.show();
8880     QVERIFY(QTest::qWaitForWindowExposed(&main));
8881
8882     QPixmap correct(main.size());
8883     correct.fill(Qt::green);
8884     const QPixmap mainPixmap = main.grab(QRect(QPoint(0, 0), QSize(-1, -1)));
8885
8886     QTRY_COMPARE(mainPixmap.toImage().convertToFormat(QImage::Format_RGB32),
8887                  correct.toImage().convertToFormat(QImage::Format_RGB32));
8888 #ifndef QTEST_NO_CURSOR
8889     QApplication::restoreOverrideCursor();
8890 #endif
8891 }
8892 #endif
8893
8894 void tst_QWidget::setGraphicsEffect()
8895 {
8896     // Check that we don't have any effect by default.
8897     QScopedPointer<QWidget> widget(new QWidget);
8898     QVERIFY(!widget->graphicsEffect());
8899
8900     // SetGet check.
8901     QPointer<QGraphicsEffect> blurEffect = new QGraphicsBlurEffect;
8902     widget->setGraphicsEffect(blurEffect);
8903     QCOMPARE(widget->graphicsEffect(), static_cast<QGraphicsEffect *>(blurEffect));
8904
8905     // Ensure the existing effect is deleted when setting a new one.
8906     QPointer<QGraphicsEffect> shadowEffect = new QGraphicsDropShadowEffect;
8907     widget->setGraphicsEffect(shadowEffect);
8908     QVERIFY(!blurEffect);
8909     QCOMPARE(widget->graphicsEffect(), static_cast<QGraphicsEffect *>(shadowEffect));
8910     blurEffect = new QGraphicsBlurEffect;
8911
8912     // Ensure the effect is uninstalled when setting it on a new target.
8913     QScopedPointer<QWidget> anotherWidget(new QWidget);
8914     anotherWidget->setGraphicsEffect(blurEffect);
8915     widget->setGraphicsEffect(blurEffect);
8916     QVERIFY(!anotherWidget->graphicsEffect());
8917     QVERIFY(!shadowEffect);
8918
8919     // Ensure the existing effect is deleted when deleting the widget.
8920     widget.reset();
8921     QVERIFY(!blurEffect);
8922     anotherWidget.reset();
8923
8924     // Ensure the effect is uninstalled when deleting it
8925     widget.reset(new QWidget);
8926     blurEffect = new QGraphicsBlurEffect;
8927     widget->setGraphicsEffect(blurEffect);
8928     delete blurEffect;
8929     QVERIFY(!widget->graphicsEffect());
8930
8931     // Ensure the existing effect is uninstalled and deleted when setting a null effect
8932     blurEffect = new QGraphicsBlurEffect;
8933     widget->setGraphicsEffect(blurEffect);
8934     widget->setGraphicsEffect(0);
8935     QVERIFY(!widget->graphicsEffect());
8936     QVERIFY(!blurEffect);
8937 }
8938
8939 void tst_QWidget::activateWindow()
8940 {
8941     // Test case for QTBUG-26711
8942
8943     // Create first mainwindow and set it active
8944     QScopedPointer<QMainWindow> mainwindow(new QMainWindow);
8945     QLabel* label = new QLabel(mainwindow.data());
8946     mainwindow->setCentralWidget(label);
8947     mainwindow->setVisible(true);
8948     mainwindow->activateWindow();
8949     QVERIFY(QTest::qWaitForWindowActive(mainwindow.data()));
8950     QVERIFY(mainwindow->isActiveWindow());
8951
8952     // Create second mainwindow and set it active
8953     QScopedPointer<QMainWindow> mainwindow2(new QMainWindow);
8954     QLabel* label2 = new QLabel(mainwindow2.data());
8955     mainwindow2->setCentralWidget(label2);
8956     mainwindow2->setVisible(true);
8957     mainwindow2->activateWindow();
8958     qApp->processEvents();
8959
8960     QTRY_VERIFY(!mainwindow->isActiveWindow());
8961     QTRY_VERIFY(mainwindow2->isActiveWindow());
8962
8963     // Revert first mainwindow back to visible active
8964     mainwindow->setVisible(true);
8965     mainwindow->activateWindow();
8966     qApp->processEvents();
8967
8968     QTRY_VERIFY(mainwindow->isActiveWindow());
8969     QTRY_VERIFY(!mainwindow2->isActiveWindow());
8970 }
8971
8972 void tst_QWidget::openModal_taskQTBUG_5804()
8973 {
8974     class Widget : public QWidget
8975     {
8976     public:
8977         Widget(QWidget *parent) : QWidget(parent)
8978         {
8979             resize(200, 200);
8980         }
8981         ~Widget()
8982         {
8983             QMessageBox msgbox;
8984             QTimer::singleShot(10, &msgbox, SLOT(accept()));
8985             msgbox.exec(); //open a modal dialog
8986         }
8987     };
8988
8989     QScopedPointer<QWidget> win(new QWidget);
8990     new Widget(win.data());
8991     win->show();
8992     QVERIFY(QTest::qWaitForWindowExposed(win.data()));
8993 }
8994
8995 void tst_QWidget::focusProxyAndInputMethods()
8996 {
8997     QScopedPointer<QWidget> toplevel(new QWidget(0, Qt::X11BypassWindowManagerHint));
8998     toplevel->resize(200, 200);
8999     toplevel->setAttribute(Qt::WA_InputMethodEnabled, true);
9000
9001     QWidget *child = new QWidget(toplevel.data());
9002     child->setFocusProxy(toplevel.data());
9003     child->setAttribute(Qt::WA_InputMethodEnabled, true);
9004
9005     toplevel->setFocusPolicy(Qt::WheelFocus);
9006     child->setFocusPolicy(Qt::WheelFocus);
9007
9008     QVERIFY(!child->hasFocus());
9009     QVERIFY(!toplevel->hasFocus());
9010
9011     toplevel->show();
9012     QVERIFY(QTest::qWaitForWindowExposed(toplevel.data()));
9013     QApplication::setActiveWindow(toplevel.data());
9014     QVERIFY(QTest::qWaitForWindowActive(toplevel.data()));
9015     QVERIFY(toplevel->hasFocus());
9016     QVERIFY(child->hasFocus());
9017     QCOMPARE(qApp->focusObject(), toplevel.data());
9018 }
9019
9020 #ifdef QT_BUILD_INTERNAL
9021 class scrollWidgetWBS : public QWidget
9022 {
9023 public:
9024     void deleteBackingStore()
9025     {
9026         static_cast<QWidgetPrivate*>(d_ptr.data())->topData()->backingStoreTracker.destroy();
9027     }
9028     void enableBackingStore()
9029     {
9030         if (!static_cast<QWidgetPrivate*>(d_ptr.data())->maybeBackingStore()) {
9031             static_cast<QWidgetPrivate*>(d_ptr.data())->topData()->backingStoreTracker.create(this);
9032             static_cast<QWidgetPrivate*>(d_ptr.data())->invalidateBuffer(this->rect());
9033             repaint();
9034         }
9035     }
9036 };
9037 #endif
9038
9039 // Test case relies on developer build (AUTOTEST_EXPORT).
9040 #ifdef QT_BUILD_INTERNAL
9041 void tst_QWidget::scrollWithoutBackingStore()
9042 {
9043     scrollWidgetWBS scrollable;
9044     scrollable.resize(200, 200);
9045     QLabel child(QString("@"),&scrollable);
9046     child.resize(50,50);
9047     scrollable.show();
9048     QVERIFY(QTest::qWaitForWindowExposed(&scrollable));
9049     scrollable.scroll(50,50);
9050     QCOMPARE(child.pos(),QPoint(50,50));
9051     scrollable.deleteBackingStore();
9052     scrollable.scroll(-25,-25);
9053     QCOMPARE(child.pos(),QPoint(25,25));
9054     scrollable.enableBackingStore();
9055     QCOMPARE(child.pos(),QPoint(25,25));
9056 }
9057 #endif
9058
9059 void tst_QWidget::taskQTBUG_7532_tabOrderWithFocusProxy()
9060 {
9061     QWidget w;
9062     w.setFocusPolicy(Qt::TabFocus);
9063     QWidget *fp = new QWidget(&w);
9064     fp->setFocusPolicy(Qt::TabFocus);
9065     w.setFocusProxy(fp);
9066     QWidget::setTabOrder(&w, fp);
9067
9068     // In debug mode, no assertion failure means it's alright.
9069 }
9070
9071 void tst_QWidget::movedAndResizedAttributes()
9072 {
9073 #if defined (Q_OS_MAC)
9074     QEXPECT_FAIL("", "FixMe, QTBUG-8941 and QTBUG-8977", Abort);
9075     QVERIFY(false);
9076 #else
9077     // Use Qt::Tool as fully decorated windows have a minimum width of 160 on
9078     QWidget w(0, Qt::Tool);
9079     w.show();
9080
9081     QVERIFY(!w.testAttribute(Qt::WA_Moved));
9082     QVERIFY(!w.testAttribute(Qt::WA_Resized));
9083
9084     w.setWindowState(Qt::WindowFullScreen);
9085
9086     QVERIFY(!w.testAttribute(Qt::WA_Moved));
9087     QVERIFY(!w.testAttribute(Qt::WA_Resized));
9088
9089     w.setWindowState(Qt::WindowMaximized);
9090
9091     QVERIFY(!w.testAttribute(Qt::WA_Moved));
9092     QVERIFY(!w.testAttribute(Qt::WA_Resized));
9093
9094     w.setWindowState(Qt::WindowMinimized);
9095
9096     QVERIFY(!w.testAttribute(Qt::WA_Moved));
9097     QVERIFY(!w.testAttribute(Qt::WA_Resized));
9098
9099     w.showNormal();
9100
9101     QVERIFY(!w.testAttribute(Qt::WA_Moved));
9102     QVERIFY(!w.testAttribute(Qt::WA_Resized));
9103
9104     w.showMaximized();
9105
9106     QVERIFY(!w.testAttribute(Qt::WA_Moved));
9107     QVERIFY(!w.testAttribute(Qt::WA_Resized));
9108
9109     w.showFullScreen();
9110
9111     QVERIFY(!w.testAttribute(Qt::WA_Moved));
9112     QVERIFY(!w.testAttribute(Qt::WA_Resized));
9113
9114     w.showNormal();
9115     w.move(10,10);
9116     QVERIFY(w.testAttribute(Qt::WA_Moved));
9117     QVERIFY(!w.testAttribute(Qt::WA_Resized));
9118
9119     w.resize(100, 100);
9120     QVERIFY(w.testAttribute(Qt::WA_Moved));
9121     QVERIFY(w.testAttribute(Qt::WA_Resized));
9122 #endif
9123 }
9124
9125 void tst_QWidget::childAt()
9126 {
9127     QWidget parent(0, Qt::FramelessWindowHint);
9128     parent.resize(200, 200);
9129
9130     QWidget *child = new QWidget(&parent);
9131     child->setPalette(Qt::red);
9132     child->setAutoFillBackground(true);
9133     child->setGeometry(20, 20, 160, 160);
9134
9135     QWidget *grandChild = new QWidget(child);
9136     grandChild->setPalette(Qt::blue);
9137     grandChild->setAutoFillBackground(true);
9138     grandChild->setGeometry(-20, -20, 220, 220);
9139
9140     QVERIFY(!parent.childAt(19, 19));
9141     QVERIFY(!parent.childAt(180, 180));
9142     QCOMPARE(parent.childAt(20, 20), grandChild);
9143     QCOMPARE(parent.childAt(179, 179), grandChild);
9144
9145     grandChild->setAttribute(Qt::WA_TransparentForMouseEvents);
9146     QCOMPARE(parent.childAt(20, 20), child);
9147     QCOMPARE(parent.childAt(179, 179), child);
9148     grandChild->setAttribute(Qt::WA_TransparentForMouseEvents, false);
9149
9150     child->setMask(QRect(50, 50, 60, 60));
9151
9152     QVERIFY(!parent.childAt(69, 69));
9153     QVERIFY(!parent.childAt(130, 130));
9154     QCOMPARE(parent.childAt(70, 70), grandChild);
9155     QCOMPARE(parent.childAt(129, 129), grandChild);
9156
9157     child->setAttribute(Qt::WA_MouseNoMask);
9158     QCOMPARE(parent.childAt(69, 69), grandChild);
9159     QCOMPARE(parent.childAt(130, 130), grandChild);
9160     child->setAttribute(Qt::WA_MouseNoMask, false);
9161
9162     grandChild->setAttribute(Qt::WA_TransparentForMouseEvents);
9163     QCOMPARE(parent.childAt(70, 70), child);
9164     QCOMPARE(parent.childAt(129, 129), child);
9165     grandChild->setAttribute(Qt::WA_TransparentForMouseEvents, false);
9166
9167     grandChild->setMask(QRect(80, 80, 40, 40));
9168
9169     QCOMPARE(parent.childAt(79, 79), child);
9170     QCOMPARE(parent.childAt(120, 120), child);
9171     QCOMPARE(parent.childAt(80, 80), grandChild);
9172     QCOMPARE(parent.childAt(119, 119), grandChild);
9173
9174     grandChild->setAttribute(Qt::WA_MouseNoMask);
9175
9176     QCOMPARE(parent.childAt(79, 79), grandChild);
9177     QCOMPARE(parent.childAt(120, 120), grandChild);
9178 }
9179
9180 #ifdef Q_OS_MAC
9181 void tst_QWidget::childAt_unifiedToolBar()
9182 {
9183     QLabel *label = new QLabel(QLatin1String("foo"));
9184     QToolBar *toolBar = new QToolBar;
9185     toolBar->addWidget(new QLabel("dummy"));
9186     toolBar->addWidget(label);
9187
9188     QMainWindow mainWindow;
9189     mainWindow.addToolBar(toolBar);
9190     mainWindow.show();
9191
9192     // Calculate the top-left corner of the tool bar and the label (in mainWindow's coordinates).
9193     QPoint labelTopLeft = label->mapTo(&mainWindow, QPoint());
9194     QPoint toolBarTopLeft = toolBar->mapTo(&mainWindow, QPoint());
9195
9196     QCOMPARE(mainWindow.childAt(toolBarTopLeft), static_cast<QWidget *>(toolBar));
9197     QCOMPARE(mainWindow.childAt(labelTopLeft), static_cast<QWidget *>(label));
9198
9199     // Enable unified tool bars.
9200     mainWindow.setUnifiedTitleAndToolBarOnMac(true);
9201     QTest::qWait(50);
9202
9203     // The tool bar is now in the "non-client" area of QMainWindow, i.e.
9204     // outside the mainWindow's rect(), and since mapTo et al. doesn't work
9205     // in that case (see commit 35667fd45ada49269a5987c235fdedfc43e92bb8),
9206     // we use mapToGlobal/mapFromGlobal to re-calculate the corners.
9207     QPoint oldToolBarTopLeft = toolBarTopLeft;
9208     toolBarTopLeft = mainWindow.mapFromGlobal(toolBar->mapToGlobal(QPoint()));
9209     QVERIFY(toolBarTopLeft != oldToolBarTopLeft);
9210     QVERIFY(toolBarTopLeft.y() < 0);
9211     labelTopLeft = mainWindow.mapFromGlobal(label->mapToGlobal(QPoint()));
9212
9213     QCOMPARE(mainWindow.childAt(toolBarTopLeft), static_cast<QWidget *>(toolBar));
9214     QCOMPARE(mainWindow.childAt(labelTopLeft), static_cast<QWidget *>(label));
9215 }
9216
9217 void tst_QWidget::taskQTBUG_11373()
9218 {
9219     QScopedPointer<QMainWindow> myWindow(new QMainWindow);
9220     QWidget * center = new QWidget();
9221     myWindow -> setCentralWidget(center);
9222     QWidget * drawer = new QWidget(myWindow.data(), Qt::Drawer);
9223     drawer -> hide();
9224     QCOMPARE(drawer->isVisible(), false);
9225     myWindow -> show();
9226     myWindow -> raise();
9227     // The drawer shouldn't be visible now.
9228     QCOMPARE(drawer->isVisible(), false);
9229     myWindow -> setWindowState(Qt::WindowFullScreen);
9230     myWindow -> setWindowState(Qt::WindowNoState);
9231     // The drawer should still not be visible, since we haven't shown it.
9232     QCOMPARE(drawer->isVisible(), false);
9233 }
9234 #endif
9235
9236 void tst_QWidget::taskQTBUG_17333_ResizeInfiniteRecursion()
9237 {
9238     QTableView tb;
9239     const char *s = "border: 1px solid;";
9240     tb.setStyleSheet(s);
9241     tb.show();
9242
9243     QVERIFY(QTest::qWaitForWindowExposed(&tb));
9244     tb.setGeometry(QRect(100, 100, 0, 100));
9245     // No crash, it works.
9246 }
9247
9248 void tst_QWidget::nativeChildFocus()
9249 {
9250     QWidget w;
9251     QLayout *layout = new QVBoxLayout;
9252     w.setLayout(layout);
9253     QLineEdit *p1 = new QLineEdit;
9254     QLineEdit *p2 = new QLineEdit;
9255     layout->addWidget(p1);
9256     layout->addWidget(p2);
9257     p1->setObjectName("p1");
9258     p2->setObjectName("p2");
9259     w.show();
9260     w.activateWindow();
9261     p1->setFocus();
9262     p1->setAttribute(Qt::WA_NativeWindow);
9263     p2->setAttribute(Qt::WA_NativeWindow);
9264     QApplication::processEvents();
9265     QVERIFY(QTest::qWaitForWindowExposed(&w));
9266     QTest::qWait(10);
9267
9268     QCOMPARE(QApplication::activeWindow(), &w);
9269     QCOMPARE(QApplication::focusWidget(), static_cast<QWidget*>(p1));
9270
9271     QTest::qWait(1000);
9272 }
9273
9274 static bool lenientCompare(const QPixmap &actual, const QPixmap &expected)
9275 {
9276     QImage expectedImage = expected.toImage().convertToFormat(QImage::Format_RGB32);
9277     QImage actualImage = actual.toImage().convertToFormat(QImage::Format_RGB32);
9278
9279     if (expectedImage.size() != actualImage.size()) {
9280         qWarning("Image size comparison failed: expected: %dx%d, got %dx%d",
9281                  expectedImage.size().width(), expectedImage.size().height(),
9282                  actualImage.size().width(), actualImage.size().height());
9283         return false;
9284     }
9285
9286     const int size = actual.width() * actual.height();
9287     const int threshold = QPixmap::defaultDepth() == 16 ? 10 : 2;
9288
9289     QRgb *a = (QRgb *)actualImage.bits();
9290     QRgb *e = (QRgb *)expectedImage.bits();
9291     for (int i = 0; i < size; ++i) {
9292         const QColor ca(a[i]);
9293         const QColor ce(e[i]);
9294         if (qAbs(ca.red() - ce.red()) > threshold
9295             || qAbs(ca.green() - ce.green()) > threshold
9296             || qAbs(ca.blue() - ce.blue()) > threshold) {
9297             qWarning("Color mismatch at pixel #%d: Expected: %d,%d,%d, got %d,%d,%d",
9298                      i, ce.red(), ce.green(), ce.blue(), ca.red(), ca.green(), ca.blue());
9299             return false;
9300         }
9301     }
9302
9303     return true;
9304 }
9305
9306 void tst_QWidget::grab()
9307 {
9308     for (int opaque = 0; opaque < 2; ++opaque) {
9309         QWidget widget;
9310         QImage image(128, 128, opaque ? QImage::Format_RGB32 : QImage::Format_ARGB32_Premultiplied);
9311         for (int row = 0; row < image.height(); ++row) {
9312             QRgb *line = reinterpret_cast<QRgb *>(image.scanLine(row));
9313             for (int col = 0; col < image.width(); ++col)
9314                 line[col] = qRgba(rand() & 255, row, col, opaque ? 255 : 127);
9315         }
9316
9317         QPalette pal = widget.palette();
9318         pal.setBrush(QPalette::Window, QBrush(image));
9319         widget.setPalette(pal);
9320         widget.resize(128, 128);
9321
9322         QPixmap expected(64, 64);
9323         if (!opaque)
9324             expected.fill(Qt::transparent);
9325
9326         QPainter p(&expected);
9327         p.translate(-64, -64);
9328         p.drawTiledPixmap(0, 0, 128, 128, pal.brush(QPalette::Window).texture(), 0, 0);
9329         p.end();
9330
9331         QPixmap actual = widget.grab(QRect(64, 64, 64, 64));
9332         QVERIFY(lenientCompare(actual, expected));
9333
9334         actual = widget.grab(QRect(64, 64, -1, -1));
9335         QVERIFY(lenientCompare(actual, expected));
9336
9337         // Make sure a widget that is not yet shown is grabbed correctly.
9338         QTreeWidget widget2;
9339         actual = widget2.grab(QRect());
9340         widget2.show();
9341         expected = widget2.grab(QRect());
9342
9343         QVERIFY(lenientCompare(actual, expected));
9344     }
9345 }
9346
9347 /* grabMouse() tests whether mouse grab for a widget without window handle works.
9348  * It creates a top level widget with another nested widget inside. The inner widget grabs
9349  * the mouse and a series of mouse presses moving over the top level's window is simulated.
9350  * Only the inner widget should receive events. */
9351
9352 static inline QString mouseEventLogEntry(const QString &objectName, QEvent::Type t, const QPoint &p, Qt::MouseButtons b)
9353 {
9354     QString result;
9355     QDebug(&result).nospace() << objectName << " Mouse event " << t << " at " << p << " buttons " << b;
9356     return result;
9357 }
9358
9359 class GrabLoggerWidget : public QWidget {
9360 public:
9361     explicit GrabLoggerWidget(QStringList *log, QWidget *parent = 0)  : QWidget(parent), m_log(log) {}
9362
9363 protected:
9364     bool event(QEvent *e)
9365     {
9366         switch (e->type()) {
9367         case QEvent::MouseButtonPress:
9368         case QEvent::MouseMove:
9369         case QEvent::MouseButtonRelease: {
9370             QMouseEvent *me = static_cast<QMouseEvent *>(e);
9371             m_log->push_back(mouseEventLogEntry(objectName(), me->type(), me->pos(), me->buttons()));
9372             me->accept();
9373             return true;
9374         }
9375         default:
9376             break;
9377         }
9378         return QWidget::event(e);
9379     }
9380 private:
9381     QStringList *m_log;
9382 };
9383
9384 void tst_QWidget::grabMouse()
9385 {
9386     QStringList log;
9387     GrabLoggerWidget w(&log);
9388     w.setObjectName(QLatin1String("tst_qwidget_grabMouse"));
9389     w.setWindowTitle(w.objectName());
9390     QLayout *layout = new QVBoxLayout(&w);
9391     layout->setMargin(50);
9392     GrabLoggerWidget *grabber = new GrabLoggerWidget(&log, &w);
9393     const QString grabberObjectName = QLatin1String("tst_qwidget_grabMouse_grabber");
9394     grabber->setObjectName(grabberObjectName);
9395     grabber->setMinimumSize(100, 100);
9396     layout->addWidget(grabber);
9397     w.show();
9398     qApp->setActiveWindow(&w);
9399     QVERIFY(QTest::qWaitForWindowActive(&w));
9400
9401     QStringList expectedLog;
9402     grabber->grabMouse();
9403     QPoint mousePos = QPoint(w.width() / 2, 10);
9404     const int step = w.height() / 5;
9405     for ( ; mousePos.y() < w.height() ; mousePos.ry() += step) {
9406         QTest::mouseClick(w.windowHandle(), Qt::LeftButton, 0, mousePos);
9407         // Events should go to the grabber child using its coordinates.
9408         const QPoint expectedPos = grabber->mapFromParent(mousePos);
9409         expectedLog.push_back(mouseEventLogEntry(grabberObjectName, QEvent::MouseButtonPress, expectedPos, Qt::LeftButton));
9410         expectedLog.push_back(mouseEventLogEntry(grabberObjectName, QEvent::MouseButtonRelease, expectedPos, Qt::NoButton));
9411     }
9412     grabber->releaseMouse();
9413     QCOMPARE(log, expectedLog);
9414 }
9415
9416 void tst_QWidget::grabKeyboard()
9417 {
9418     QWidget w;
9419     w.setObjectName(QLatin1String("tst_qwidget_grabKeyboard"));
9420     w.setWindowTitle(w.objectName());
9421     QLayout *layout = new QVBoxLayout(&w);
9422     QLineEdit *grabber = new QLineEdit(&w);
9423     layout->addWidget(grabber);
9424     QLineEdit *nonGrabber = new QLineEdit(&w);
9425     layout->addWidget(nonGrabber);
9426     w.show();
9427     qApp->setActiveWindow(&w);
9428     QVERIFY(QTest::qWaitForWindowActive(&w));
9429     nonGrabber->setFocus();
9430     grabber->grabKeyboard();
9431     QTest::keyClick(w.windowHandle(), Qt::Key_A);
9432     grabber->releaseKeyboard();
9433     QCOMPARE(grabber->text().toLower(), QStringLiteral("a"));
9434     QVERIFY(nonGrabber->text().isEmpty());
9435 }
9436
9437 class TouchMouseWidget : public QWidget {
9438 public:
9439     explicit TouchMouseWidget(QWidget *parent = 0)
9440         : QWidget(parent),
9441           m_touchEventCount(0),
9442           m_acceptTouch(false),
9443           m_mouseEventCount(0),
9444           m_acceptMouse(true)
9445     {
9446         resize(200, 200);
9447     }
9448
9449     void setAcceptTouch(bool accept)
9450     {
9451         m_acceptTouch = accept;
9452         setAttribute(Qt::WA_AcceptTouchEvents, accept);
9453     }
9454
9455     void setAcceptMouse(bool accept)
9456     {
9457         m_acceptMouse = accept;
9458     }
9459
9460 protected:
9461     bool event(QEvent *e)
9462     {
9463         switch (e->type()) {
9464         case QEvent::TouchBegin:
9465         case QEvent::TouchUpdate:
9466         case QEvent::TouchEnd:
9467             ++m_touchEventCount;
9468             if (m_acceptTouch)
9469                 e->accept();
9470             else
9471                 e->ignore();
9472             return true;
9473
9474         case QEvent::MouseButtonPress:
9475         case QEvent::MouseMove:
9476         case QEvent::MouseButtonRelease:
9477             ++m_mouseEventCount;
9478             m_lastMouseEventPos = static_cast<QMouseEvent *>(e)->localPos();
9479             if (m_acceptMouse)
9480                 e->accept();
9481             else
9482                 e->ignore();
9483             return true;
9484
9485         default:
9486             return QWidget::event(e);
9487         }
9488     }
9489
9490 public:
9491     int m_touchEventCount;
9492     bool m_acceptTouch;
9493     int m_mouseEventCount;
9494     bool m_acceptMouse;
9495     QPointF m_lastMouseEventPos;
9496 };
9497
9498 void tst_QWidget::touchEventSynthesizedMouseEvent()
9499 {
9500     // Pass if the platform does not want mouse event synhesizing
9501     if (!QGuiApplicationPrivate::platformIntegration()->styleHint(QPlatformIntegration::SynthesizeMouseFromTouchEvents).toBool())
9502         return;
9503
9504     {
9505         // Simple case, we ignore the touch events, we get mouse events instead
9506         QTouchDevice *device = new QTouchDevice;
9507         device->setType(QTouchDevice::TouchScreen);
9508         QWindowSystemInterface::registerTouchDevice(device);
9509
9510         TouchMouseWidget widget;
9511         widget.show();
9512         QVERIFY(QTest::qWaitForWindowExposed(widget.windowHandle()));
9513         QCOMPARE(widget.m_touchEventCount, 0);
9514         QCOMPARE(widget.m_mouseEventCount, 0);
9515
9516         QTest::touchEvent(&widget, device).press(0, QPoint(10, 10), &widget);
9517         QCOMPARE(widget.m_touchEventCount, 0);
9518         QCOMPARE(widget.m_mouseEventCount, 1);
9519         QCOMPARE(widget.m_lastMouseEventPos, QPointF(10, 10));
9520         QTest::touchEvent(&widget, device).move(0, QPoint(15, 15), &widget);
9521         QCOMPARE(widget.m_touchEventCount, 0);
9522         QCOMPARE(widget.m_mouseEventCount, 2);
9523         QCOMPARE(widget.m_lastMouseEventPos, QPointF(15, 15));
9524         QTest::touchEvent(&widget, device).release(0, QPoint(20, 20), &widget);
9525         QCOMPARE(widget.m_touchEventCount, 0);
9526         QCOMPARE(widget.m_mouseEventCount, 3);
9527         QCOMPARE(widget.m_lastMouseEventPos, QPointF(20, 20));
9528     }
9529
9530     {
9531         // We accept the touch events, no mouse event is generated
9532         QTouchDevice *device = new QTouchDevice;
9533         device->setType(QTouchDevice::TouchScreen);
9534         QWindowSystemInterface::registerTouchDevice(device);
9535
9536         TouchMouseWidget widget;
9537         widget.setAcceptTouch(true);
9538         widget.show();
9539         QVERIFY(QTest::qWaitForWindowExposed(widget.windowHandle()));
9540         QCOMPARE(widget.m_touchEventCount, 0);
9541         QCOMPARE(widget.m_mouseEventCount, 0);
9542
9543         QTest::touchEvent(&widget, device).press(0, QPoint(10, 10), &widget);
9544         QCOMPARE(widget.m_touchEventCount, 1);
9545         QCOMPARE(widget.m_mouseEventCount, 0);
9546         QTest::touchEvent(&widget, device).move(0, QPoint(15, 15), &widget);
9547         QCOMPARE(widget.m_touchEventCount, 2);
9548         QCOMPARE(widget.m_mouseEventCount, 0);
9549         QTest::touchEvent(&widget, device).release(0, QPoint(20, 20), &widget);
9550         QCOMPARE(widget.m_touchEventCount, 3);
9551         QCOMPARE(widget.m_mouseEventCount, 0);
9552     }
9553
9554     {
9555         // Parent accepts touch events, child ignore both mouse and touch
9556         // We should see propagation of the TouchBegin
9557         QTouchDevice *device = new QTouchDevice;
9558         device->setType(QTouchDevice::TouchScreen);
9559         QWindowSystemInterface::registerTouchDevice(device);
9560
9561         TouchMouseWidget parent;
9562         parent.setAcceptTouch(true);
9563         TouchMouseWidget child(&parent);
9564         child.move(5, 5);
9565         child.setAcceptMouse(false);
9566         parent.show();
9567         QVERIFY(QTest::qWaitForWindowExposed(parent.windowHandle()));
9568         QCOMPARE(parent.m_touchEventCount, 0);
9569         QCOMPARE(parent.m_mouseEventCount, 0);
9570         QCOMPARE(child.m_touchEventCount, 0);
9571         QCOMPARE(child.m_mouseEventCount, 0);
9572
9573         QTest::touchEvent(parent.window(), device).press(0, QPoint(10, 10), &child);
9574         QCOMPARE(parent.m_touchEventCount, 1);
9575         QCOMPARE(parent.m_mouseEventCount, 0);
9576         QCOMPARE(child.m_touchEventCount, 0);
9577         QCOMPARE(child.m_mouseEventCount, 1); // Attempt at mouse event before propagation
9578         QCOMPARE(child.m_lastMouseEventPos, QPointF(10, 10));
9579     }
9580
9581     {
9582         // Parent accepts mouse events, child ignore both mouse and touch
9583         // We should see propagation of the TouchBegin into a MouseButtonPress
9584         QTouchDevice *device = new QTouchDevice;
9585         device->setType(QTouchDevice::TouchScreen);
9586         QWindowSystemInterface::registerTouchDevice(device);
9587
9588         TouchMouseWidget parent;
9589         TouchMouseWidget child(&parent);
9590         child.move(5, 5);
9591         child.setAcceptMouse(false);
9592         parent.show();
9593         QVERIFY(QTest::qWaitForWindowExposed(parent.windowHandle()));
9594         QCOMPARE(parent.m_touchEventCount, 0);
9595         QCOMPARE(parent.m_mouseEventCount, 0);
9596         QCOMPARE(child.m_touchEventCount, 0);
9597         QCOMPARE(child.m_mouseEventCount, 0);
9598
9599         QTest::touchEvent(parent.window(), device).press(0, QPoint(10, 10), &child);
9600         QCOMPARE(parent.m_touchEventCount, 0);
9601         QCOMPARE(parent.m_mouseEventCount, 1);
9602         QCOMPARE(parent.m_lastMouseEventPos, QPointF(15, 15));
9603         QCOMPARE(child.m_touchEventCount, 0);
9604         QCOMPARE(child.m_mouseEventCount, 1); // Attempt at mouse event before propagation
9605         QCOMPARE(child.m_lastMouseEventPos, QPointF(10, 10));
9606     }
9607 }
9608
9609 void tst_QWidget::styleSheetPropagation()
9610 {
9611     QTableView tw;
9612     tw.setStyleSheet("background-color: red;");
9613     foreach (QObject *child, tw.children()) {
9614         if (QWidget *w = qobject_cast<QWidget *>(child))
9615             QCOMPARE(w->style(), tw.style());
9616     }
9617 }
9618
9619 class DestroyTester : public QObject
9620 {
9621     Q_OBJECT
9622 public:
9623     DestroyTester(QObject *parent) : QObject(parent) { parentDestroyed = 0; }
9624     static int parentDestroyed;
9625 public slots:
9626     void parentDestroyedSlot() {
9627         ++parentDestroyed;
9628     }
9629 };
9630
9631 int DestroyTester::parentDestroyed = 0;
9632
9633 void tst_QWidget::destroyedSignal()
9634 {
9635     {
9636         QWidget *w = new QWidget;
9637         DestroyTester *t = new DestroyTester(w);
9638         connect(w, SIGNAL(destroyed()), t, SLOT(parentDestroyedSlot()));
9639         QCOMPARE(DestroyTester::parentDestroyed, 0);
9640         delete w;
9641         QCOMPARE(DestroyTester::parentDestroyed, 1);
9642     }
9643
9644     {
9645         QWidget *w = new QWidget;
9646         DestroyTester *t = new DestroyTester(w);
9647         connect(w, SIGNAL(destroyed()), t, SLOT(parentDestroyedSlot()));
9648         w->blockSignals(true);
9649         QCOMPARE(DestroyTester::parentDestroyed, 0);
9650         delete w;
9651         QCOMPARE(DestroyTester::parentDestroyed, 1);
9652     }
9653
9654     {
9655         QObject *o = new QWidget;
9656         DestroyTester *t = new DestroyTester(o);
9657         connect(o, SIGNAL(destroyed()), t, SLOT(parentDestroyedSlot()));
9658         QCOMPARE(DestroyTester::parentDestroyed, 0);
9659         delete o;
9660         QCOMPARE(DestroyTester::parentDestroyed, 1);
9661     }
9662
9663     {
9664         QObject *o = new QWidget;
9665         DestroyTester *t = new DestroyTester(o);
9666         connect(o, SIGNAL(destroyed()), t, SLOT(parentDestroyedSlot()));
9667         o->blockSignals(true);
9668         QCOMPARE(DestroyTester::parentDestroyed, 0);
9669         delete o;
9670         QCOMPARE(DestroyTester::parentDestroyed, 1);
9671     }
9672
9673     {
9674         QWidget *w = new QWidget;
9675         DestroyTester *t = new DestroyTester(0);
9676         connect(w, SIGNAL(destroyed()), t, SLOT(parentDestroyedSlot()));
9677         QCOMPARE(DestroyTester::parentDestroyed, 0);
9678         delete w;
9679         QCOMPARE(DestroyTester::parentDestroyed, 1);
9680         delete t;
9681     }
9682
9683     {
9684         QWidget *w = new QWidget;
9685         DestroyTester *t = new DestroyTester(0);
9686         connect(w, SIGNAL(destroyed()), t, SLOT(parentDestroyedSlot()));
9687         w->blockSignals(true);
9688         QCOMPARE(DestroyTester::parentDestroyed, 0);
9689         delete w;
9690         QCOMPARE(DestroyTester::parentDestroyed, 1);
9691         delete t;
9692     }
9693
9694     {
9695         QObject *o = new QWidget;
9696         DestroyTester *t = new DestroyTester(0);
9697         connect(o, SIGNAL(destroyed()), t, SLOT(parentDestroyedSlot()));
9698         QCOMPARE(DestroyTester::parentDestroyed, 0);
9699         delete o;
9700         QCOMPARE(DestroyTester::parentDestroyed, 1);
9701         delete t;
9702     }
9703
9704     {
9705         QObject *o = new QWidget;
9706         DestroyTester *t = new DestroyTester(0);
9707         connect(o, SIGNAL(destroyed()), t, SLOT(parentDestroyedSlot()));
9708         o->blockSignals(true);
9709         QCOMPARE(DestroyTester::parentDestroyed, 0);
9710         delete o;
9711         QCOMPARE(DestroyTester::parentDestroyed, 1);
9712         delete t;
9713     }
9714
9715 }
9716
9717 #ifndef QTEST_NO_CURSOR
9718 void tst_QWidget::underMouse()
9719 {
9720     // Move the mouse cursor to a safe location
9721     QCursor::setPos(0,0);
9722
9723     ColorWidget topLevelWidget(0, Qt::blue);
9724     ColorWidget childWidget1(&topLevelWidget, Qt::yellow);
9725     ColorWidget childWidget2(&topLevelWidget, Qt::black);
9726     ColorWidget popupWidget(0, Qt::green);
9727
9728     topLevelWidget.setObjectName("topLevelWidget");
9729     childWidget1.setObjectName("childWidget1");
9730     childWidget2.setObjectName("childWidget2");
9731     popupWidget.setObjectName("popupWidget");
9732
9733     popupWidget.setWindowFlags(Qt::Popup);
9734
9735     topLevelWidget.setGeometry(100, 100, 300, 300);
9736     childWidget1.setGeometry(20, 20, 100, 100);
9737     childWidget2.setGeometry(20, 120, 100, 100);
9738     popupWidget.setGeometry(50, 100, 50, 50);
9739
9740     topLevelWidget.show();
9741     QVERIFY(QTest::qWaitForWindowExposed(&topLevelWidget));
9742     QWindow *window = topLevelWidget.windowHandle();
9743
9744     QPoint outsideWindowPoint(30, -10);
9745     QPoint inWindowPoint(30, 10);
9746     QPoint child1Point(30, 50);
9747     QPoint child2PointA(30, 150);
9748     QPoint child2PointB(31, 151);
9749
9750     // Outside window
9751     QTest::mouseMove(window, outsideWindowPoint);
9752     QVERIFY(!topLevelWidget.underMouse());
9753     QVERIFY(!childWidget1.underMouse());
9754     QVERIFY(!childWidget2.underMouse());
9755
9756     // Enter window, outside children
9757     // Note: QTest::mouseMove will not generate enter events for windows, so send one explicitly
9758     QWindowSystemInterface::handleEnterEvent(window, inWindowPoint, window->mapToGlobal(inWindowPoint));
9759     QTest::mouseMove(window, inWindowPoint);
9760     QVERIFY(topLevelWidget.underMouse());
9761     QVERIFY(!childWidget1.underMouse());
9762     QVERIFY(!childWidget2.underMouse());
9763
9764     // In childWidget1
9765     QTest::mouseMove(window, child1Point);
9766     QVERIFY(topLevelWidget.underMouse());
9767     QVERIFY(childWidget1.underMouse());
9768     QVERIFY(!childWidget2.underMouse());
9769
9770     // In childWidget2
9771     QTest::mouseMove(window, child2PointA);
9772     QVERIFY(topLevelWidget.underMouse());
9773     QVERIFY(!childWidget1.underMouse());
9774     QVERIFY(childWidget2.underMouse());
9775
9776     topLevelWidget.resetCounts();
9777     childWidget1.resetCounts();
9778     childWidget2.resetCounts();
9779     popupWidget.resetCounts();
9780
9781     // Throw up a popup window
9782     popupWidget.show();
9783     QVERIFY(QTest::qWaitForWindowExposed(&popupWidget));
9784     QWindow *popupWindow = popupWidget.windowHandle();
9785     QVERIFY(popupWindow);
9786     QVERIFY(QApplication::activePopupWidget() == &popupWidget);
9787
9788     // Send an artificial leave event for window, as it won't get generated automatically
9789     // due to cursor not actually being over the window.
9790     QWindowSystemInterface::handleLeaveEvent(window);
9791     QApplication::processEvents();
9792
9793     // If there is an active popup, undermouse should not be reported (QTBUG-27478),
9794     // but opening a popup causes leave for widgets under mouse.
9795     QVERIFY(!topLevelWidget.underMouse());
9796     QVERIFY(!childWidget1.underMouse());
9797     QVERIFY(!childWidget2.underMouse());
9798     QVERIFY(!popupWidget.underMouse());
9799     QCOMPARE(popupWidget.enters, 0);
9800     QCOMPARE(popupWidget.leaves, 0);
9801     QCOMPARE(topLevelWidget.enters, 0);
9802     QCOMPARE(topLevelWidget.leaves, 1);
9803     QCOMPARE(childWidget1.enters, 0);
9804     QCOMPARE(childWidget1.leaves, 0);
9805     QCOMPARE(childWidget2.enters, 0);
9806     QCOMPARE(childWidget2.leaves, 1);
9807     topLevelWidget.resetCounts();
9808     childWidget2.resetCounts();
9809
9810     // Moving around while popup active should not change undermouse or cause
9811     // enter and leave events for widgets.
9812     QTest::mouseMove(popupWindow, popupWindow->mapFromGlobal(window->mapToGlobal(child2PointB)));
9813     QVERIFY(!topLevelWidget.underMouse());
9814     QVERIFY(!childWidget1.underMouse());
9815     QVERIFY(!childWidget2.underMouse());
9816     QVERIFY(!popupWidget.underMouse());
9817     QCOMPARE(popupWidget.enters, 0);
9818     QCOMPARE(popupWidget.leaves, 0);
9819     QCOMPARE(topLevelWidget.enters, 0);
9820     QCOMPARE(topLevelWidget.leaves, 0);
9821     QCOMPARE(childWidget1.enters, 0);
9822     QCOMPARE(childWidget1.leaves, 0);
9823     QCOMPARE(childWidget2.enters, 0);
9824     QCOMPARE(childWidget2.leaves, 0);
9825
9826     QTest::mouseMove(popupWindow, popupWindow->mapFromGlobal(window->mapToGlobal(inWindowPoint)));
9827     QVERIFY(!topLevelWidget.underMouse());
9828     QVERIFY(!childWidget1.underMouse());
9829     QVERIFY(!childWidget2.underMouse());
9830     QVERIFY(!popupWidget.underMouse());
9831     QCOMPARE(popupWidget.enters, 0);
9832     QCOMPARE(popupWidget.leaves, 0);
9833     QCOMPARE(topLevelWidget.enters, 0);
9834     QCOMPARE(topLevelWidget.leaves, 0);
9835     QCOMPARE(childWidget1.enters, 0);
9836     QCOMPARE(childWidget1.leaves, 0);
9837     QCOMPARE(childWidget2.enters, 0);
9838     QCOMPARE(childWidget2.leaves, 0);
9839
9840     QTest::mouseMove(popupWindow, popupWindow->mapFromGlobal(window->mapToGlobal(child1Point)));
9841     QVERIFY(!topLevelWidget.underMouse());
9842     QVERIFY(!childWidget1.underMouse());
9843     QVERIFY(!childWidget2.underMouse());
9844     QVERIFY(!popupWidget.underMouse());
9845     QCOMPARE(popupWidget.enters, 0);
9846     QCOMPARE(popupWidget.leaves, 0);
9847     QCOMPARE(topLevelWidget.enters, 0);
9848     QCOMPARE(topLevelWidget.leaves, 0);
9849     QCOMPARE(childWidget1.enters, 0);
9850     QCOMPARE(childWidget1.leaves, 0);
9851     QCOMPARE(childWidget2.enters, 0);
9852     QCOMPARE(childWidget2.leaves, 0);
9853
9854     // Note: Mouse moving off-application while there is an active popup cannot be simulated
9855     // without actually moving the cursor so it is not tested.
9856
9857     // Mouse enters popup, should cause enter to popup.
9858     // Once again, need to create artificial enter event.
9859     const QPoint popupCenter = popupWindow->geometry().center();
9860     QWindowSystemInterface::handleEnterEvent(popupWindow, popupWindow->mapFromGlobal(popupCenter), popupCenter);
9861     QTest::mouseMove(popupWindow, popupCenter);
9862     QVERIFY(!topLevelWidget.underMouse());
9863     QVERIFY(!childWidget1.underMouse());
9864     QVERIFY(!childWidget2.underMouse());
9865     QVERIFY(popupWidget.underMouse());
9866     QCOMPARE(popupWidget.enters, 1);
9867     QCOMPARE(popupWidget.leaves, 0);
9868     QCOMPARE(topLevelWidget.enters, 0);
9869     QCOMPARE(topLevelWidget.leaves, 0);
9870     QCOMPARE(childWidget1.enters, 0);
9871     QCOMPARE(childWidget1.leaves, 0);
9872     QCOMPARE(childWidget2.enters, 0);
9873     QCOMPARE(childWidget2.leaves, 0);
9874     popupWidget.resetCounts();
9875
9876     // Mouse moves around inside popup, no changes
9877     QTest::mouseMove(popupWindow, QPoint(5, 5));
9878     QVERIFY(!topLevelWidget.underMouse());
9879     QVERIFY(!childWidget1.underMouse());
9880     QVERIFY(!childWidget2.underMouse());
9881     QVERIFY(popupWidget.underMouse());
9882     QCOMPARE(popupWidget.enters, 0);
9883     QCOMPARE(popupWidget.leaves, 0);
9884     QCOMPARE(topLevelWidget.enters, 0);
9885     QCOMPARE(topLevelWidget.leaves, 0);
9886     QCOMPARE(childWidget1.enters, 0);
9887     QCOMPARE(childWidget1.leaves, 0);
9888     QCOMPARE(childWidget2.enters, 0);
9889     QCOMPARE(childWidget2.leaves, 0);
9890
9891     // Mouse leaves popup and enters topLevelWidget, should cause leave for popup
9892     // but no enter to topLevelWidget. Again, artificial leave event needed.
9893     QWindowSystemInterface::handleLeaveEvent(popupWindow);
9894     QTest::mouseMove(popupWindow, popupWindow->mapFromGlobal(window->mapToGlobal(inWindowPoint)));
9895     QApplication::processEvents();
9896     QVERIFY(!topLevelWidget.underMouse());
9897     QVERIFY(!childWidget1.underMouse());
9898     QVERIFY(!childWidget2.underMouse());
9899     QVERIFY(!popupWidget.underMouse());
9900     QCOMPARE(popupWidget.enters, 0);
9901     QCOMPARE(popupWidget.leaves, 1);
9902     QCOMPARE(topLevelWidget.enters, 0);
9903     QCOMPARE(topLevelWidget.leaves, 0);
9904     QCOMPARE(childWidget1.enters, 0);
9905     QCOMPARE(childWidget1.leaves, 0);
9906     QCOMPARE(childWidget2.enters, 0);
9907     QCOMPARE(childWidget2.leaves, 0);
9908 }
9909
9910 class EnterTestModalDialog : public QDialog
9911 {
9912     Q_OBJECT
9913 public:
9914     EnterTestModalDialog() : QDialog(), button(0)
9915     {
9916         setGeometry(100, 300, 150, 100);
9917         button = new QPushButton(this);
9918         button->setGeometry(10, 10, 50, 30);
9919     }
9920
9921     QPushButton *button;
9922 };
9923
9924 class EnterTestMainDialog : public QDialog
9925 {
9926     Q_OBJECT
9927 public:
9928     EnterTestMainDialog() : QDialog(), modal(0), enters(0) {}
9929
9930 public slots:
9931     void buttonPressed()
9932     {
9933         qApp->installEventFilter(this);
9934         modal = new EnterTestModalDialog();
9935         QTimer::singleShot(2000, modal, SLOT(close())); // Failsafe
9936         QTimer::singleShot(100, this, SLOT(doMouseMoves()));
9937         modal->exec();
9938         delete modal;
9939     }
9940
9941     void doMouseMoves()
9942     {
9943         QPoint point1(15, 15);
9944         QPoint point2(15, 20);
9945         QPoint point3(20, 20);
9946         QWindow *window = modal->windowHandle();
9947         QWindowSystemInterface::handleEnterEvent(window, point1, window->mapToGlobal(point1));
9948         QTest::mouseMove(window, point1);
9949         QTest::mouseMove(window, point2);
9950         QTest::mouseMove(window, point3);
9951         modal->close();
9952     }
9953
9954     bool eventFilter(QObject *o, QEvent *e)
9955     {
9956         if (modal && modal->button && o == modal->button) {
9957             switch (e->type()) {
9958             case QEvent::Enter:
9959                 enters++;
9960                 break;
9961             default:
9962                 break;
9963             }
9964         }
9965         return QDialog::eventFilter(o, e);
9966     }
9967
9968 public:
9969     EnterTestModalDialog *modal;
9970     int enters;
9971 };
9972
9973 // A modal dialog launched by clicking a button should not trigger excess enter events
9974 // when mousing over it.
9975 void tst_QWidget::taskQTBUG_27643_enterEvents()
9976 {
9977     // Move the mouse cursor to a safe location so it won't interfere
9978     QCursor::setPos(0,0);
9979
9980     EnterTestMainDialog dialog;
9981     QPushButton button(&dialog);
9982
9983     connect(&button, SIGNAL(clicked()), &dialog, SLOT(buttonPressed()));
9984
9985     dialog.setGeometry(100, 100, 150, 100);
9986     button.setGeometry(10, 10, 100, 50);
9987     dialog.show();
9988     QVERIFY(QTest::qWaitForWindowExposed(&dialog));
9989
9990     QWindow *window = dialog.windowHandle();
9991     QPoint overButton(25, 25);
9992
9993     QWindowSystemInterface::handleEnterEvent(window, overButton, window->mapToGlobal(overButton));
9994     QTest::mouseMove(window, overButton);
9995     QTest::mouseClick(window, Qt::LeftButton, 0, overButton, 0);
9996
9997     // Modal dialog opened in EnterTestMainDialog::buttonPressed()...
9998
9999     // Must only register only single enter on modal dialog's button after all said and done
10000     QCOMPARE(dialog.enters, 1);
10001 }
10002 #endif // QTEST_NO_CURSOR
10003
10004 QTEST_MAIN(tst_QWidget)
10005 #include "tst_qwidget.moc"