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