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