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