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