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