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