1 /****************************************************************************
3 ** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
6 ** This file is part of the test suite of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
40 ****************************************************************************/
43 #include <qboxlayout.h>
44 #include <qapplication.h>
47 #include <qeventloop.h>
50 #include <qlineedit.h>
51 #include <qlistview.h>
52 #include <qmessagebox.h>
55 #include <qpushbutton.h>
58 #include <qstylefactory.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>
66 #include <QtGui/qpaintengine.h>
67 #include <QtGui/qbackingstore.h>
68 #include <QtGui/qguiapplication.h>
69 #include <QtGui/qscreen.h>
71 #include <qcompleter.h>
72 #include <qtableview.h>
73 #include <qtreewidget.h>
74 #include <qabstractnativeeventfilter.h>
75 #include <qproxystyle.h>
76 #include <QtWidgets/QGraphicsView>
77 #include <QtWidgets/QGraphicsProxyWidget>
79 #include "../../../qtest-config.h"
82 #include "tst_qwidget_mac_helpers.h" // Abstract the ObjC stuff out so not everyone must run an ObjC++ compile.
85 #include <QtTest/QtTest>
88 # include <QtCore/qt_windows.h>
89 # include <QtGui/private/qguiapplication_p.h>
90 #include <qpa/qplatformnativeinterface.h>
91 #include <qpa/qplatformintegration.h>
93 static HWND winHandleOf(const QWidget *w)
95 static QPlatformNativeInterface *nativeInterface
96 = QGuiApplicationPrivate::instance()->platformIntegration()->nativeInterface();
97 if (void *handle = nativeInterface->nativeResourceForWindow("handle", w->window()->windowHandle()))
98 return reinterpret_cast<HWND>(handle);
99 qWarning() << "Cannot obtain native handle for " << w;
104 # define Q_CHECK_PAINTEVENTS
105 # ifdef Q_OS_WINCE_WM
106 # include <qguifunctions_wince.h>
107 // taken from qguifunctions_wce.cpp
108 # define SPI_GETPLATFORMTYPE 257
109 static bool qt_wince_is_platform(const QString &platformString) {
110 wchar_t tszPlatform[64];
111 if (SystemParametersInfo(SPI_GETPLATFORMTYPE,
112 sizeof(tszPlatform)/sizeof(*tszPlatform),tszPlatform,0))
113 if (0 == _tcsicmp(reinterpret_cast<const wchar_t *> (platformString.utf16()), tszPlatform))
117 static inline bool qt_wince_is_smartphone() { return qt_wince_is_platform(QString::fromLatin1("Smartphone")); }
118 # endif // Q_OS_WINCE_WM
120 # define Q_CHECK_PAINTEVENTS \
121 if (::SwitchDesktop(::GetThreadDesktop(::GetCurrentThreadId())) == 0) \
122 QSKIP("desktop is not visible, this test would fail");
123 # endif // !Q_OS_WINCE
125 # define Q_CHECK_PAINTEVENTS
126 #endif // else Q_OS_WIN
129 #if defined(Q_OS_WINCE_WM)
130 #include <qguifunctions_wince.h>
131 // taken from qguifunctions_wce.cpp
132 #define SPI_GETPLATFORMTYPE 257
133 bool qt_wince_is_platform(const QString &platformString) {
134 wchar_t tszPlatform[64];
135 if (SystemParametersInfo(SPI_GETPLATFORMTYPE,
136 sizeof(tszPlatform)/sizeof(*tszPlatform),tszPlatform,0))
137 if (0 == _tcsicmp(reinterpret_cast<const wchar_t *> (platformString.utf16()), tszPlatform))
141 bool qt_wince_is_smartphone() {
142 return qt_wince_is_platform(QString::fromLatin1("Smartphone"));
147 #include <Security/AuthSession.h>
148 bool macHasAccessToWindowsServer()
150 SecuritySessionId mySession;
151 SessionAttributeBits sessionInfo;
152 SessionGetInfo(callerSecuritySession, &mySession, &sessionInfo);
153 return (sessionInfo & sessionHasGraphicAccess);
157 class tst_QWidget : public QObject
163 virtual ~tst_QWidget();
167 void cleanupTestCase();
172 void fontPropagation();
173 void fontPropagation2();
174 void palettePropagation();
175 void palettePropagation2();
176 void enabledPropagation();
177 void ignoreKeyEventsWhenDisabled_QTBUG27417();
178 void properTabHandlingWhenDisabled_QTBUG27417();
179 void popupEnterLeave();
180 #ifndef QT_NO_DRAGANDDROP
181 void acceptDropsPropagation();
185 void visible_setWindowOpacity();
189 void mapFromAndTo_data();
191 void focusChainOnHide();
192 void focusChainOnReparent();
199 void showMaximized();
200 void showFullScreen();
201 void showMinimized();
202 void showMinimizedKeepsFocus();
204 void hideWhenFocusWidgetIsChild();
205 void normalGeometry();
208 void windowOpacity();
212 #ifndef QT_MAC_USE_COCOA
215 void testContentsPropagation();
216 void saveRestoreGeometry();
217 void restoreVersion1Geometry_data();
218 void restoreVersion1Geometry();
225 void optimizedResizeMove();
226 void optimizedResize_topLevel();
230 void testDeletionInEventHandlers();
232 void childDeletesItsSibling();
234 void setMinimumSize();
235 void setMaximumSize();
238 void ensureCreated();
239 void winIdChangeEvent();
240 void persistentWinId();
241 void showNativeChild();
242 void qobject_castInDestroyedSlot();
244 void showHideEvent_data();
245 void showHideEvent();
247 void lostUpdatesOnHide();
256 // tests QWidget::setGeometry()
257 void setWindowGeometry_data();
258 void setWindowGeometry();
260 // tests QWidget::move() and resize()
261 void windowMoveResize_data();
262 void windowMoveResize();
264 void moveChild_data();
266 void showAndMoveChild();
268 #ifndef QT_MAC_USE_COCOA
269 void subtractOpaqueSiblings();
272 #if defined (Q_OS_WIN) && !defined(Q_OS_WINCE)
273 void setGeometry_win();
278 void multipleToplevelFocusCheck();
280 #ifndef QTEST_NO_CURSOR
284 void testWindowIconChangeEventPropagation();
286 void minAndMaxSizeWithX11BypassWindowManagerHint();
287 void showHideShowX11();
288 void clean_qt_x11_enforce_cursor();
292 void renderInvisible();
293 void renderWithPainter();
294 void render_task188133();
295 void render_task211796();
296 void render_task217815();
298 void render_windowOpacity();
300 void render_systemClip();
301 void render_systemClip2_data();
302 void render_systemClip2();
303 void render_systemClip3_data();
304 void render_systemClip3();
305 void render_task252837();
306 void render_worldTransform();
308 void setContentsMargins();
310 void moveWindowInShowEvent_data();
311 void moveWindowInShowEvent();
313 void repaintWhenChildDeleted();
314 void hideOpaqueChildWhileHidden();
315 #if !defined(Q_OS_WINCE)
316 void updateWhileMinimized();
320 void adjustSize_data();
321 void updateGeometry();
322 void updateGeometry_data();
323 void sendUpdateRequestImmediately();
324 void doubleRepaint();
325 void resizeInPaintEvent();
326 void opaqueChildren();
328 void setMaskInResizeEvent();
329 void moveInResizeEvent();
331 void immediateRepaintAfterShow();
332 void immediateRepaintAfterInvalidateBuffer();
334 void effectiveWinId();
335 void effectiveWinId2();
337 void customDpiProperty();
339 void quitOnCloseAttribute();
342 #if defined (Q_OS_WIN)
344 void paintOnScreenPossible();
346 void reparentStaticWidget();
347 void QTBUG6883_reparentStaticWidget2();
349 void translucentWidget();
351 void setClearAndResizeMask();
353 #ifndef QTEST_NO_CURSOR
354 void syntheticEnterLeave();
355 void taskQTBUG_4055_sendSyntheticEnterLeave();
357 void taskQTBUG_27643_enterEvents();
360 void initialPosForDontShowOnScreenWidgets();
361 void updateOnDestroyedSignal();
362 void toplevelLineEditFocus();
364 void focusWidget_task254563();
365 #ifndef Q_OS_WINCE_WM
366 void rectOutsideCoordinatesLimit_task144779();
368 void setGraphicsEffect();
370 #ifdef QT_BUILD_INTERNAL
371 void destroyBackingStore();
374 void activateWindow();
376 void openModal_taskQTBUG_5804();
378 void focusProxyAndInputMethods();
379 #ifdef QT_BUILD_INTERNAL
380 void scrollWithoutBackingStore();
383 void taskQTBUG_7532_tabOrderWithFocusProxy();
384 void movedAndResizedAttributes();
387 void childAt_unifiedToolBar();
388 void taskQTBUG_11373();
390 void taskQTBUG_17333_ResizeInfiniteRecursion();
392 void nativeChildFocus();
397 void touchEventSynthesizedMouseEvent();
399 void styleSheetPropagation();
401 void destroyedSignal();
403 bool ensureScreenSize(int width, int height);
406 const QString m_platform;
409 bool tst_QWidget::ensureScreenSize(int width, int height)
412 available = QDesktopWidget().availableGeometry().size();
413 return (available.width() >= width && available.height() >= height);
416 // Testing get/set functions
417 void tst_QWidget::getSetCheck()
420 QWidget child1(&obj1);
421 // QStyle * QWidget::style()
422 // void QWidget::setStyle(QStyle *)
423 QScopedPointer<QStyle> var1(QStyleFactory::create(QLatin1String("Windows")));
424 obj1.setStyle(var1.data());
425 QCOMPARE(static_cast<QStyle *>(var1.data()), obj1.style());
426 obj1.setStyle((QStyle *)0);
427 QVERIFY(var1.data() != obj1.style());
428 QVERIFY(0 != obj1.style()); // style can never be 0 for a widget
430 // int QWidget::minimumWidth()
431 // void QWidget::setMinimumWidth(int)
432 obj1.setMinimumWidth(0);
433 QCOMPARE(obj1.minimumWidth(), 0);
434 obj1.setMinimumWidth(INT_MIN);
435 QCOMPARE(obj1.minimumWidth(), 0); // A widgets width can never be less than 0
436 obj1.setMinimumWidth(INT_MAX);
438 child1.setMinimumWidth(0);
439 QCOMPARE(child1.minimumWidth(), 0);
440 child1.setMinimumWidth(INT_MIN);
441 QCOMPARE(child1.minimumWidth(), 0); // A widgets width can never be less than 0
442 child1.setMinimumWidth(INT_MAX);
443 QCOMPARE(child1.minimumWidth(), QWIDGETSIZE_MAX); // The largest minimum size should only be as big as the maximium
445 // int QWidget::minimumHeight()
446 // void QWidget::setMinimumHeight(int)
447 obj1.setMinimumHeight(0);
448 QCOMPARE(obj1.minimumHeight(), 0);
449 obj1.setMinimumHeight(INT_MIN);
450 QCOMPARE(obj1.minimumHeight(), 0); // A widgets height can never be less than 0
451 obj1.setMinimumHeight(INT_MAX);
453 child1.setMinimumHeight(0);
454 QCOMPARE(child1.minimumHeight(), 0);
455 child1.setMinimumHeight(INT_MIN);
456 QCOMPARE(child1.minimumHeight(), 0); // A widgets height can never be less than 0
457 child1.setMinimumHeight(INT_MAX);
458 QCOMPARE(child1.minimumHeight(), QWIDGETSIZE_MAX); // The largest minimum size should only be as big as the maximium
460 // int QWidget::maximumWidth()
461 // void QWidget::setMaximumWidth(int)
462 obj1.setMaximumWidth(0);
463 QCOMPARE(obj1.maximumWidth(), 0);
464 obj1.setMaximumWidth(INT_MIN);
465 QCOMPARE(obj1.maximumWidth(), 0); // A widgets width can never be less than 0
466 obj1.setMaximumWidth(INT_MAX);
467 QCOMPARE(obj1.maximumWidth(), QWIDGETSIZE_MAX); // QWIDGETSIZE_MAX is the abs max, not INT_MAX
469 // int QWidget::maximumHeight()
470 // void QWidget::setMaximumHeight(int)
471 obj1.setMaximumHeight(0);
472 QCOMPARE(obj1.maximumHeight(), 0);
473 obj1.setMaximumHeight(INT_MIN);
474 QCOMPARE(obj1.maximumHeight(), 0); // A widgets height can never be less than 0
475 obj1.setMaximumHeight(INT_MAX);
476 QCOMPARE(obj1.maximumHeight(), QWIDGETSIZE_MAX); // QWIDGETSIZE_MAX is the abs max, not INT_MAX
479 obj1.setMinimumWidth(0);
480 obj1.setMinimumHeight(0);
481 obj1.setMaximumWidth(QWIDGETSIZE_MAX);
482 obj1.setMaximumHeight(QWIDGETSIZE_MAX);
484 // const QPalette & QWidget::palette()
485 // void QWidget::setPalette(const QPalette &)
487 obj1.setPalette(var6);
488 QCOMPARE(var6, obj1.palette());
489 obj1.setPalette(QPalette());
490 QCOMPARE(QPalette(), obj1.palette());
492 // const QFont & QWidget::font()
493 // void QWidget::setFont(const QFont &)
496 QCOMPARE(var7, obj1.font());
497 obj1.setFont(QFont());
498 QCOMPARE(QFont(), obj1.font());
500 // qreal QWidget::windowOpacity()
501 // void QWidget::setWindowOpacity(qreal)
502 obj1.setWindowOpacity(0.0);
503 QCOMPARE(0.0, obj1.windowOpacity());
504 obj1.setWindowOpacity(1.1f);
505 QCOMPARE(1.0, obj1.windowOpacity()); // 1.0 is the fullest opacity possible
507 // QWidget * QWidget::focusProxy()
508 // void QWidget::setFocusProxy(QWidget *)
510 QScopedPointer<QWidget> var9(new QWidget());
511 obj1.setFocusProxy(var9.data());
512 QCOMPARE(var9.data(), obj1.focusProxy());
513 obj1.setFocusProxy((QWidget *)0);
514 QCOMPARE((QWidget *)0, obj1.focusProxy());
517 // const QRect & QWidget::geometry()
518 // void QWidget::setGeometry(const QRect &)
519 qApp->processEvents();
520 QRect var10(10, 10, 100, 100);
521 obj1.setGeometry(var10);
522 qApp->processEvents();
523 qDebug() << obj1.geometry();
524 QCOMPARE(var10, obj1.geometry());
525 obj1.setGeometry(QRect(0,0,0,0));
526 qDebug() << obj1.geometry();
527 QCOMPARE(QRect(0,0,0,0), obj1.geometry());
529 // QLayout * QWidget::layout()
530 // void QWidget::setLayout(QLayout *)
531 QBoxLayout *var11 = new QBoxLayout(QBoxLayout::LeftToRight);
532 obj1.setLayout(var11);
533 QCOMPARE(static_cast<QLayout *>(var11), obj1.layout());
534 obj1.setLayout((QLayout *)0);
535 QCOMPARE(static_cast<QLayout *>(var11), obj1.layout()); // You cannot set a 0-pointer layout, that keeps the current
536 delete var11; // This will remove the layout from the widget
537 QCOMPARE((QLayout *)0, obj1.layout());
539 // bool QWidget::acceptDrops()
540 // void QWidget::setAcceptDrops(bool)
541 obj1.setAcceptDrops(false);
542 QCOMPARE(false, obj1.acceptDrops());
543 obj1.setAcceptDrops(true);
544 QCOMPARE(true, obj1.acceptDrops());
546 // bool QWidget::autoFillBackground()
547 // void QWidget::setAutoFillBackground(bool)
548 obj1.setAutoFillBackground(false);
549 QCOMPARE(false, obj1.autoFillBackground());
550 obj1.setAutoFillBackground(true);
551 QCOMPARE(true, obj1.autoFillBackground());
554 #if defined (Q_OS_WIN) && !defined(Q_OS_WINCE)
555 obj1.setWindowFlags(Qt::FramelessWindowHint | Qt::WindowSystemMenuHint);
556 const HWND handle = reinterpret_cast<HWND>(obj1.winId()); // explicitly create window handle
557 QVERIFY(GetWindowLong(handle, GWL_STYLE) & WS_POPUP);
561 tst_QWidget::tst_QWidget() : m_platform(qApp->platformName().toLower())
565 font.setPointSize(42);
566 qApp->setFont(font, "QPropagationTestWidget");
569 palette.setColor(QPalette::ToolTipBase, QColor(12, 13, 14));
570 palette.setColor(QPalette::Text, QColor(21, 22, 23));
571 qApp->setPalette(palette, "QPropagationTestWidget");
576 tst_QWidget::~tst_QWidget()
580 class BezierViewer : public QWidget {
582 explicit BezierViewer(QWidget* parent = 0);
583 void paintEvent( QPaintEvent* );
584 void setPoints( const QPolygonF& poly );
590 void tst_QWidget::initTestCase()
592 #ifdef Q_OS_WINCE //disable magic for WindowsCE
593 qApp->setAutoMaximizeThreshold(-1);
595 // Create the test class
596 testWidget = new BezierViewer;
597 testWidget->resize(200,200);
599 QVERIFY(QTest::qWaitForWindowExposed(testWidget));
602 void tst_QWidget::cleanupTestCase()
608 void tst_QWidget::init()
610 // TODO: Add initialization code here.
611 // This will be executed immediately before each test is run.
612 testWidget->setFont(QFont());
613 testWidget->setPalette(QPalette());
616 void tst_QWidget::cleanup()
622 BezierViewer::BezierViewer( QWidget* parent)
625 setObjectName(QLatin1String("TestWidget"));
626 setWindowTitle(objectName());
628 pal.setColor(backgroundRole(), Qt::white);
633 void BezierViewer::setPoints( const QPolygonF& a )
638 #include "private/qbezier_p.h"
639 void BezierViewer::paintEvent( QPaintEvent* )
641 if ( points.size() != 4 ) {
642 #if defined(QT_CHECK_RANGE)
643 qWarning( "QPolygon::bezier: The array must have 4 control points" );
648 /* Calculate Bezier curve */
649 QPolygonF bezier = QBezier::fromPoints(points.at(0),points.at(1),points.at(2),points.at(3)).toPolygon();
651 QPainter painter( this );
653 /* Calculate scale to fit in window */
654 QRectF br = bezier.boundingRect() | points.boundingRect();
656 int scl = qMax( qMin(pr.width()/br.width(), pr.height()/br.height()), qreal(1.) );
659 /* Scale Bezier curve vertices */
660 for ( QPolygonF::Iterator it = bezier.begin(); it != bezier.end(); ++it ) {
661 it->setX( (it->x()-br.x()) * scl + border );
662 it->setY( (it->y()-br.y()) * scl + border );
666 painter.setPen( Qt::lightGray );
668 for ( i = border; i <= pr.width(); i += scl ) {
669 painter.drawLine( i, 0, i, pr.height() );
671 for ( int j = border; j <= pr.height(); j += scl ) {
672 painter.drawLine( 0, j, pr.width(), j );
675 /* Write number of vertices */
676 painter.setPen( Qt::red );
677 painter.setFont( QFont("Helvetica", 14, QFont::DemiBold, true ) );
679 caption.setNum( bezier.size() );
680 caption += QString::fromLatin1( " vertices" );
681 painter.drawText( 10, pr.height()-10, caption );
683 /* Draw Bezier curve */
684 painter.setPen( Qt::black );
685 painter.drawPolyline( bezier );
687 /* Scale and draw control points */
688 painter.setPen( Qt::darkGreen );
689 for ( QPolygonF::Iterator p1 = points.begin(); p1 != points.end(); ++p1 ) {
690 int x = (p1->x()-br.x()) * scl + border;
691 int y = (p1->y()-br.y()) * scl + border;
692 painter.drawLine( x-4, y-4, x+4, y+4 );
693 painter.drawLine( x+4, y-4, x-4, y+4 );
697 painter.setPen( Qt::red );
698 painter.setBrush( Qt::red );
699 for ( QPolygonF::Iterator p2 = bezier.begin(); p2 != bezier.end(); ++p2 )
700 painter.drawEllipse( p2->x()-1, p2->y()-1, 3, 3 );
703 void tst_QWidget::fontPropagation()
705 QFont font = testWidget->font();
706 QWidget* childWidget = new QWidget( testWidget );
708 QCOMPARE( font, childWidget->font() );
710 font.setBold( true );
711 testWidget->setFont( font );
712 QCOMPARE( font, testWidget->font() );
713 QCOMPARE( font, childWidget->font() );
715 QFont newFont = font;
716 newFont.setItalic( true );
717 childWidget->setFont( newFont );
718 QWidget* grandChildWidget = new QWidget( childWidget );
719 QCOMPARE( font, testWidget->font() );
720 QCOMPARE( newFont, grandChildWidget->font() );
722 font.setUnderline( true );
723 testWidget->setFont( font );
725 // the child and grand child should now have merged bold and
727 newFont.setUnderline( true );
729 QCOMPARE( newFont, childWidget->font() );
730 QCOMPARE( newFont, grandChildWidget->font() );
732 // make sure font propagation continues working after reparenting
733 font = testWidget->font();
734 font.setPointSize(font.pointSize() + 2);
735 testWidget->setFont(font);
737 QWidget *one = new QWidget(testWidget);
738 QWidget *two = new QWidget(one);
739 QWidget *three = new QWidget(two);
740 QWidget *four = new QWidget(two);
742 four->setParent(three);
743 four->move(QPoint(0,0));
745 font.setPointSize(font.pointSize() + 2);
746 testWidget->setFont(font);
748 QCOMPARE(testWidget->font(), one->font());
749 QCOMPARE(one->font(), two->font());
750 QCOMPARE(two->font(), three->font());
751 QCOMPARE(three->font(), four->font());
753 QVERIFY(testWidget->testAttribute(Qt::WA_SetFont));
754 QVERIFY(! one->testAttribute(Qt::WA_SetFont));
755 QVERIFY(! two->testAttribute(Qt::WA_SetFont));
756 QVERIFY(! three->testAttribute(Qt::WA_SetFont));
757 QVERIFY(! four->testAttribute(Qt::WA_SetFont));
759 font.setPointSize(font.pointSize() + 2);
762 QCOMPARE(one->font(), two->font());
763 QCOMPARE(two->font(), three->font());
764 QCOMPARE(three->font(), four->font());
766 QVERIFY(one->testAttribute(Qt::WA_SetFont));
767 QVERIFY(! two->testAttribute(Qt::WA_SetFont));
768 QVERIFY(! three->testAttribute(Qt::WA_SetFont));
769 QVERIFY(! four->testAttribute(Qt::WA_SetFont));
771 font.setPointSize(font.pointSize() + 2);
774 QCOMPARE(two->font(), three->font());
775 QCOMPARE(three->font(), four->font());
777 QVERIFY(two->testAttribute(Qt::WA_SetFont));
778 QVERIFY(! three->testAttribute(Qt::WA_SetFont));
779 QVERIFY(! four->testAttribute(Qt::WA_SetFont));
781 font.setPointSize(font.pointSize() + 2);
782 three->setFont(font);
784 QCOMPARE(three->font(), four->font());
786 QVERIFY(three->testAttribute(Qt::WA_SetFont));
787 QVERIFY(! four->testAttribute(Qt::WA_SetFont));
789 font.setPointSize(font.pointSize() + 2);
792 QVERIFY(four->testAttribute(Qt::WA_SetFont));
795 class QPropagationTestWidget : public QWidget
799 QPropagationTestWidget(QWidget *parent = 0)
804 void tst_QWidget::fontPropagation2()
806 // ! Note, the code below is executed in tst_QWidget's constructor.
808 // font.setBold(true);
809 // font.setPointSize(42);
810 // qApp->setFont(font, "QPropagationTestWidget");
812 QScopedPointer<QWidget> root(new QWidget);
813 root->setObjectName(QLatin1String("fontPropagation2"));
814 root->setWindowTitle(root->objectName());
815 root->resize(200, 200);
817 QWidget *child0 = new QWidget(root.data());
818 QWidget *child1 = new QWidget(child0);
819 QWidget *child2 = new QPropagationTestWidget(child1);
820 QWidget *child3 = new QWidget(child2);
821 QWidget *child4 = new QWidget(child3);
822 QWidget *child5 = new QWidget(child4);
825 // Check that only the application fonts apply.
826 QCOMPARE(root->font(), QApplication::font());
827 QCOMPARE(child0->font(), QApplication::font());
828 QCOMPARE(child1->font(), QApplication::font());
829 QCOMPARE(child2->font().pointSize(), 42);
830 QVERIFY(child2->font().bold());
831 QCOMPARE(child3->font().pointSize(), 42);
832 QVERIFY(child3->font().bold());
833 QCOMPARE(child4->font().pointSize(), 42);
834 QVERIFY(child4->font().bold());
835 QCOMPARE(child5->font().pointSize(), 42);
836 QVERIFY(child5->font().bold());
838 // Set child0's font size to 15, and remove bold on child4.
840 font.setPointSize(15);
841 child0->setFont(font);
843 unboldFont.setBold(false);
844 child4->setFont(unboldFont);
846 // Check that the above settings propagate correctly.
847 QCOMPARE(root->font(), QApplication::font());
848 QCOMPARE(child0->font().pointSize(), 15);
849 QVERIFY(!child0->font().bold());
850 QCOMPARE(child1->font().pointSize(), 15);
851 QVERIFY(!child1->font().bold());
852 QCOMPARE(child2->font().pointSize(), 15);
853 QVERIFY(child2->font().bold());
854 QCOMPARE(child3->font().pointSize(), 15);
855 QVERIFY(child3->font().bold());
856 QCOMPARE(child4->font().pointSize(), 15);
857 QVERIFY(!child4->font().bold());
858 QCOMPARE(child5->font().pointSize(), 15);
859 QVERIFY(!child5->font().bold());
861 // Replace the app font for child2. Italic should propagate
862 // but the size should still be ignored. The previous bold
864 QFont italicSizeFont;
865 italicSizeFont.setItalic(true);
866 italicSizeFont.setPointSize(33);
867 qApp->setFont(italicSizeFont, "QPropagationTestWidget");
869 // Check that this propagates correctly.
870 QCOMPARE(root->font(), QApplication::font());
871 QCOMPARE(child0->font().pointSize(), 15);
872 QVERIFY(!child0->font().bold());
873 QVERIFY(!child0->font().italic());
874 QCOMPARE(child1->font().pointSize(), 15);
875 QVERIFY(!child1->font().bold());
876 QVERIFY(!child1->font().italic());
877 QCOMPARE(child2->font().pointSize(), 15);
878 QVERIFY(!child2->font().bold());
879 QVERIFY(child2->font().italic());
880 QCOMPARE(child3->font().pointSize(), 15);
881 QVERIFY(!child3->font().bold());
882 QVERIFY(child3->font().italic());
883 QCOMPARE(child4->font().pointSize(), 15);
884 QVERIFY(!child4->font().bold());
885 QVERIFY(child4->font().italic());
886 QCOMPARE(child5->font().pointSize(), 15);
887 QVERIFY(!child5->font().bold());
888 QVERIFY(child5->font().italic());
891 void tst_QWidget::palettePropagation()
893 QPalette palette = testWidget->palette();
894 QWidget* childWidget = new QWidget( testWidget );
896 QCOMPARE( palette, childWidget->palette() );
898 palette.setColor( QPalette::Base, Qt::red );
899 testWidget->setPalette( palette );
900 QCOMPARE( palette, testWidget->palette() );
901 QCOMPARE( palette, childWidget->palette() );
903 QPalette newPalette = palette;
904 newPalette.setColor( QPalette::Highlight, Qt::green );
905 childWidget->setPalette( newPalette );
906 QWidget* grandChildWidget = new QWidget( childWidget );
907 QCOMPARE( palette, testWidget->palette() );
908 QCOMPARE( newPalette, grandChildWidget->palette() );
910 palette.setColor( QPalette::Text, Qt::blue );
911 testWidget->setPalette( palette );
913 // the child and grand child should now have merged green
914 // highlight and blue text
915 newPalette.setColor( QPalette::Text, Qt::blue);
917 QCOMPARE( newPalette, childWidget->palette() );
918 QCOMPARE( newPalette, grandChildWidget->palette() );
921 void tst_QWidget::palettePropagation2()
923 // ! Note, the code below is executed in tst_QWidget's constructor.
925 // font.setColor(QPalette::ToolTipBase, QColor(12, 13, 14));
926 // font.setColor(QPalette::Text, QColor(21, 22, 23));
927 // qApp->setPalette(palette, "QPropagationTestWidget");
929 QScopedPointer<QWidget> root(new QWidget);
930 root->setObjectName(QLatin1String("palettePropagation2"));
931 root->setWindowTitle(root->objectName());
932 root->resize(200, 200);
933 QWidget *child0 = new QWidget(root.data());
934 QWidget *child1 = new QWidget(child0);
935 QWidget *child2 = new QPropagationTestWidget(child1);
936 QWidget *child3 = new QWidget(child2);
937 QWidget *child4 = new QWidget(child3);
938 QWidget *child5 = new QWidget(child4);
940 QVERIFY(QTest::qWaitForWindowExposed(root.data()));
942 // These colors are unlikely to be imposed on the default palette of
944 QColor sysPalText(21, 22, 23);
945 QColor sysPalToolTipBase(12, 13, 14);
946 QColor overridePalText(42, 43, 44);
947 QColor overridePalToolTipBase(45, 46, 47);
948 QColor sysPalButton(99, 98, 97);
950 // Check that only the application fonts apply.
951 QPalette appPal = QApplication::palette();
952 QCOMPARE(root->palette(), appPal);
953 QCOMPARE(child0->palette(), appPal);
954 QCOMPARE(child1->palette(), appPal);
955 QCOMPARE(child2->palette().color(QPalette::ToolTipBase), sysPalToolTipBase);
956 QCOMPARE(child2->palette().color(QPalette::Text), sysPalText);
957 QCOMPARE(child2->palette().color(QPalette::ToolTipText), appPal.color(QPalette::ToolTipText));
958 QCOMPARE(child3->palette().color(QPalette::ToolTipBase), sysPalToolTipBase);
959 QCOMPARE(child3->palette().color(QPalette::Text), sysPalText);
960 QCOMPARE(child3->palette().color(QPalette::ToolTipText), appPal.color(QPalette::ToolTipText));
961 QCOMPARE(child4->palette().color(QPalette::ToolTipBase), sysPalToolTipBase);
962 QCOMPARE(child4->palette().color(QPalette::Text), sysPalText);
963 QCOMPARE(child4->palette().color(QPalette::ToolTipText), appPal.color(QPalette::ToolTipText));
964 QCOMPARE(child5->palette().color(QPalette::ToolTipBase), sysPalToolTipBase);
965 QCOMPARE(child5->palette().color(QPalette::Text), sysPalText);
966 QCOMPARE(child5->palette().color(QPalette::ToolTipText), appPal.color(QPalette::ToolTipText));
968 // Set child0's Text, and set ToolTipBase on child4.
969 QPalette textPalette;
970 textPalette.setColor(QPalette::Text, overridePalText);
971 child0->setPalette(textPalette);
972 QPalette toolTipPalette;
973 toolTipPalette.setColor(QPalette::ToolTipBase, overridePalToolTipBase);
974 child4->setPalette(toolTipPalette);
976 // Check that the above settings propagate correctly.
977 QCOMPARE(root->palette(), appPal);
978 QCOMPARE(child0->palette().color(QPalette::Text), overridePalText);
979 QCOMPARE(child0->palette().color(QPalette::ToolTipBase), appPal.color(QPalette::ToolTipBase));
980 QCOMPARE(child0->palette().color(QPalette::ToolTipText), appPal.color(QPalette::ToolTipText));
981 QCOMPARE(child1->palette().color(QPalette::Text), overridePalText);
982 QCOMPARE(child1->palette().color(QPalette::ToolTipBase), appPal.color(QPalette::ToolTipBase));
983 QCOMPARE(child1->palette().color(QPalette::ToolTipText), appPal.color(QPalette::ToolTipText));
984 QCOMPARE(child2->palette().color(QPalette::Text), overridePalText);
985 QCOMPARE(child2->palette().color(QPalette::ToolTipBase), sysPalToolTipBase);
986 QCOMPARE(child2->palette().color(QPalette::ToolTipText), appPal.color(QPalette::ToolTipText));
987 QCOMPARE(child3->palette().color(QPalette::Text), overridePalText);
988 QCOMPARE(child3->palette().color(QPalette::ToolTipBase), sysPalToolTipBase);
989 QCOMPARE(child3->palette().color(QPalette::ToolTipText), appPal.color(QPalette::ToolTipText));
990 QCOMPARE(child4->palette().color(QPalette::Text), overridePalText);
991 QCOMPARE(child4->palette().color(QPalette::ToolTipBase), overridePalToolTipBase);
992 QCOMPARE(child4->palette().color(QPalette::ToolTipText), appPal.color(QPalette::ToolTipText));
993 QCOMPARE(child5->palette().color(QPalette::Text), overridePalText);
994 QCOMPARE(child5->palette().color(QPalette::ToolTipBase), overridePalToolTipBase);
995 QCOMPARE(child5->palette().color(QPalette::ToolTipText), appPal.color(QPalette::ToolTipText));
997 // Replace the app palette for child2. Button should propagate but Text
998 // should still be ignored. The previous ToolTipBase setting is gone.
999 QPalette buttonPalette;
1000 buttonPalette.setColor(QPalette::ToolTipText, sysPalButton);
1001 qApp->setPalette(buttonPalette, "QPropagationTestWidget");
1003 // Check that the above settings propagate correctly.
1004 QCOMPARE(root->palette(), appPal);
1005 QCOMPARE(child0->palette().color(QPalette::Text), overridePalText);
1006 QCOMPARE(child0->palette().color(QPalette::ToolTipBase), appPal.color(QPalette::ToolTipBase));
1007 QCOMPARE(child0->palette().color(QPalette::ToolTipText), appPal.color(QPalette::ToolTipText));
1008 QCOMPARE(child1->palette().color(QPalette::Text), overridePalText);
1009 QCOMPARE(child1->palette().color(QPalette::ToolTipBase), appPal.color(QPalette::ToolTipBase));
1010 QCOMPARE(child1->palette().color(QPalette::ToolTipText), appPal.color(QPalette::ToolTipText));
1011 QCOMPARE(child2->palette().color(QPalette::Text), overridePalText);
1012 QCOMPARE(child2->palette().color(QPalette::ToolTipBase), appPal.color(QPalette::ToolTipBase));
1013 QCOMPARE(child2->palette().color(QPalette::ToolTipText), sysPalButton);
1014 QCOMPARE(child3->palette().color(QPalette::Text), overridePalText);
1015 QCOMPARE(child3->palette().color(QPalette::ToolTipBase), appPal.color(QPalette::ToolTipBase));
1016 QCOMPARE(child3->palette().color(QPalette::ToolTipText), sysPalButton);
1017 QCOMPARE(child4->palette().color(QPalette::Text), overridePalText);
1018 QCOMPARE(child4->palette().color(QPalette::ToolTipBase), overridePalToolTipBase);
1019 QCOMPARE(child4->palette().color(QPalette::ToolTipText), sysPalButton);
1020 QCOMPARE(child5->palette().color(QPalette::Text), overridePalText);
1021 QCOMPARE(child5->palette().color(QPalette::ToolTipBase), overridePalToolTipBase);
1022 QCOMPARE(child5->palette().color(QPalette::ToolTipText), sysPalButton);
1025 void tst_QWidget::enabledPropagation()
1027 QWidget* childWidget = new QWidget( testWidget );
1028 childWidget->show();
1029 QVERIFY( testWidget->isEnabled() );
1030 QVERIFY( childWidget->isEnabled() );
1032 testWidget->setEnabled( false );
1033 QVERIFY( !testWidget->isEnabled() );
1034 QVERIFY( !childWidget->isEnabled() );
1036 testWidget->setDisabled( false );
1037 QVERIFY( testWidget->isEnabled() );
1038 QVERIFY( childWidget->isEnabled() );
1040 QWidget* grandChildWidget = new QWidget( childWidget );
1041 QVERIFY( grandChildWidget->isEnabled() );
1043 testWidget->setDisabled( true );
1044 QVERIFY( !testWidget->isEnabled() );
1045 QVERIFY( !childWidget->isEnabled() );
1046 QVERIFY( !grandChildWidget->isEnabled() );
1048 grandChildWidget->setEnabled( false );
1049 testWidget->setEnabled( true );
1050 QVERIFY( testWidget->isEnabled() );
1051 QVERIFY( childWidget->isEnabled() );
1052 QVERIFY( !grandChildWidget->isEnabled() );
1054 grandChildWidget->setEnabled( true );
1055 testWidget->setEnabled( false );
1056 childWidget->setDisabled( true );
1057 testWidget->setEnabled( true );
1058 QVERIFY( testWidget->isEnabled() );
1059 QVERIFY( !childWidget->isEnabled() );
1060 QVERIFY( !grandChildWidget->isEnabled() );
1063 void tst_QWidget::ignoreKeyEventsWhenDisabled_QTBUG27417()
1066 lineEdit.setDisabled(true);
1068 QTest::keyClick(&lineEdit, Qt::Key_A);
1069 QTRY_VERIFY(lineEdit.text().isEmpty());
1072 void tst_QWidget::properTabHandlingWhenDisabled_QTBUG27417()
1075 QVBoxLayout *layout = new QVBoxLayout();
1076 QLineEdit *lineEdit = new QLineEdit();
1077 layout->addWidget(lineEdit);
1078 QLineEdit *lineEdit2 = new QLineEdit();
1079 layout->addWidget(lineEdit2);
1080 QLineEdit *lineEdit3 = new QLineEdit();
1081 layout->addWidget(lineEdit3);
1082 widget.setLayout(layout);
1085 lineEdit->setFocus();
1086 QTRY_VERIFY(lineEdit->hasFocus());
1087 QTest::keyClick(&widget, Qt::Key_Tab);
1088 QTRY_VERIFY(lineEdit2->hasFocus());
1089 QTest::keyClick(&widget, Qt::Key_Tab);
1090 QTRY_VERIFY(lineEdit3->hasFocus());
1092 lineEdit2->setDisabled(true);
1093 lineEdit->setFocus();
1094 QTRY_VERIFY(lineEdit->hasFocus());
1095 QTest::keyClick(&widget, Qt::Key_Tab);
1096 QTRY_VERIFY(!lineEdit2->hasFocus());
1097 QVERIFY(lineEdit3->hasFocus());
1100 // Drag'n drop disabled in this build.
1101 #ifndef QT_NO_DRAGANDDROP
1102 void tst_QWidget::acceptDropsPropagation()
1104 QWidget *childWidget = new QWidget(testWidget);
1105 childWidget->show();
1106 QVERIFY(!testWidget->acceptDrops());
1107 QVERIFY(!childWidget->acceptDrops());
1109 testWidget->setAcceptDrops(true);
1110 QVERIFY(testWidget->acceptDrops());
1111 QVERIFY(!childWidget->acceptDrops());
1112 QVERIFY(childWidget->testAttribute(Qt::WA_DropSiteRegistered));
1114 testWidget->setAcceptDrops(false);
1115 QVERIFY(!testWidget->acceptDrops());
1116 QVERIFY(!childWidget->acceptDrops());
1117 QVERIFY(!childWidget->testAttribute(Qt::WA_DropSiteRegistered));
1119 QWidget *grandChildWidget = new QWidget(childWidget);
1120 QVERIFY(!grandChildWidget->acceptDrops());
1121 QVERIFY(!grandChildWidget->testAttribute(Qt::WA_DropSiteRegistered));
1123 testWidget->setAcceptDrops(true);
1124 QVERIFY(testWidget->acceptDrops());
1125 QVERIFY(!childWidget->acceptDrops());
1126 QVERIFY(childWidget->testAttribute(Qt::WA_DropSiteRegistered));
1127 QVERIFY(!grandChildWidget->acceptDrops());
1128 QVERIFY(grandChildWidget->testAttribute(Qt::WA_DropSiteRegistered));
1130 grandChildWidget->setAcceptDrops(true);
1131 testWidget->setAcceptDrops(false);
1132 QVERIFY(!testWidget->acceptDrops());
1133 QVERIFY(!childWidget->acceptDrops());
1134 QVERIFY(grandChildWidget->acceptDrops());
1135 QVERIFY(grandChildWidget->testAttribute(Qt::WA_DropSiteRegistered));
1137 grandChildWidget->setAcceptDrops(false);
1138 QVERIFY(!grandChildWidget->testAttribute(Qt::WA_DropSiteRegistered));
1139 testWidget->setAcceptDrops(true);
1140 childWidget->setAcceptDrops(true);
1141 testWidget->setAcceptDrops(false);
1142 QVERIFY(!testWidget->acceptDrops());
1143 QVERIFY(childWidget->acceptDrops());
1144 QVERIFY(!grandChildWidget->acceptDrops());
1145 QVERIFY(grandChildWidget->testAttribute(Qt::WA_DropSiteRegistered));
1149 void tst_QWidget::isEnabledTo()
1151 QWidget* childWidget = new QWidget( testWidget );
1152 QWidget* grandChildWidget = new QWidget( childWidget );
1154 QVERIFY( childWidget->isEnabledTo( testWidget ) );
1155 QVERIFY( grandChildWidget->isEnabledTo( testWidget ) );
1157 childWidget->setEnabled( false );
1158 QVERIFY( !childWidget->isEnabledTo( testWidget ) );
1159 QVERIFY( grandChildWidget->isEnabledTo( childWidget ) );
1160 QVERIFY( !grandChildWidget->isEnabledTo( testWidget ) );
1163 void tst_QWidget::visible()
1165 // Ensure that the testWidget is hidden for this test at the
1169 QVERIFY( !testWidget->isVisible() );
1170 QWidget* childWidget = new QWidget( testWidget );
1171 QVERIFY( !childWidget->isVisible() );
1174 QVERIFY( testWidget->isVisible() );
1175 QVERIFY( childWidget->isVisible() );
1177 QWidget* grandChildWidget = new QWidget( childWidget );
1178 QVERIFY( !grandChildWidget->isVisible() );
1179 grandChildWidget->show();
1180 QVERIFY( grandChildWidget->isVisible() );
1182 grandChildWidget->hide();
1185 QVERIFY( !grandChildWidget->isVisible() );
1186 QVERIFY( testWidget->isVisible() );
1187 QVERIFY( childWidget->isVisible() );
1189 grandChildWidget->show();
1190 childWidget->hide();
1193 QVERIFY( testWidget->isVisible() );
1194 QVERIFY( !childWidget->isVisible() );
1195 QVERIFY( !grandChildWidget->isVisible() );
1197 grandChildWidget->show();
1198 QVERIFY( !grandChildWidget->isVisible() );
1201 void tst_QWidget::setLocale()
1204 QCOMPARE(w.locale(), QLocale());
1206 w.setLocale(QLocale::Italian);
1207 QCOMPARE(w.locale(), QLocale(QLocale::Italian));
1210 QCOMPARE(child1.locale(), QLocale(QLocale::Italian));
1213 QCOMPARE(w.locale(), QLocale());
1214 QCOMPARE(child1.locale(), QLocale());
1216 w.setLocale(QLocale::French);
1217 QCOMPARE(w.locale(), QLocale(QLocale::French));
1218 QCOMPARE(child1.locale(), QLocale(QLocale::French));
1220 child1.setLocale(QLocale::Italian);
1221 QCOMPARE(w.locale(), QLocale(QLocale::French));
1222 QCOMPARE(child1.locale(), QLocale(QLocale::Italian));
1224 child1.unsetLocale();
1225 QCOMPARE(w.locale(), QLocale(QLocale::French));
1226 QCOMPARE(child1.locale(), QLocale(QLocale::French));
1229 QCOMPARE(child2.locale(), QLocale());
1230 child2.setParent(&w);
1231 QCOMPARE(child2.locale(), QLocale(QLocale::French));
1234 void tst_QWidget::visible_setWindowOpacity()
1237 QVERIFY( !testWidget->isVisible() );
1238 testWidget->setWindowOpacity(0.5);
1240 QVERIFY(!::IsWindowVisible(winHandleOf(testWidget)));
1242 testWidget->setWindowOpacity(1.0);
1245 void tst_QWidget::isVisibleTo()
1247 // Ensure that the testWidget is hidden for this test at the
1251 QWidget* childWidget = new QWidget( testWidget );
1252 QVERIFY( childWidget->isVisibleTo( testWidget ) );
1253 childWidget->hide();
1254 QVERIFY( !childWidget->isVisibleTo( testWidget ) );
1256 QWidget* grandChildWidget = new QWidget( childWidget );
1257 QVERIFY( !grandChildWidget->isVisibleTo( testWidget ) );
1258 QVERIFY( grandChildWidget->isVisibleTo( childWidget ) );
1261 childWidget->show();
1263 QVERIFY( childWidget->isVisibleTo( testWidget ) );
1264 grandChildWidget->hide();
1265 QVERIFY( !grandChildWidget->isVisibleTo( childWidget ) );
1266 QVERIFY( !grandChildWidget->isVisibleTo( testWidget ) );
1270 void tst_QWidget::isHidden()
1272 // Ensure that the testWidget is hidden for this test at the
1276 QVERIFY( testWidget->isHidden() );
1277 QWidget* childWidget = new QWidget( testWidget );
1278 QVERIFY( !childWidget->isHidden() );
1281 QVERIFY( !testWidget->isHidden() );
1282 QVERIFY( !childWidget->isHidden() );
1284 QWidget* grandChildWidget = new QWidget( childWidget );
1285 QVERIFY( grandChildWidget->isHidden() );
1286 grandChildWidget->show();
1287 QVERIFY( !grandChildWidget->isHidden() );
1289 grandChildWidget->hide();
1292 QVERIFY( grandChildWidget->isHidden() );
1293 QVERIFY( !testWidget->isHidden() );
1294 QVERIFY( !childWidget->isHidden() );
1296 grandChildWidget->show();
1297 childWidget->hide();
1300 QVERIFY( !testWidget->isHidden() );
1301 QVERIFY( childWidget->isHidden() );
1302 QVERIFY( !grandChildWidget->isHidden() );
1304 grandChildWidget->show();
1305 QVERIFY( !grandChildWidget->isHidden() );
1308 void tst_QWidget::fonts()
1310 // Tests setFont(), ownFont() and unsetFont()
1311 QWidget* cleanTestWidget = new QWidget( testWidget );
1312 QFont originalFont = cleanTestWidget->font();
1314 QVERIFY( !cleanTestWidget->testAttribute(Qt::WA_SetFont) );
1315 cleanTestWidget->setFont(QFont());
1316 QVERIFY( !cleanTestWidget->testAttribute(Qt::WA_SetFont) );
1318 QFont newFont( "times", 18 );
1319 cleanTestWidget->setFont( newFont );
1320 newFont = newFont.resolve( testWidget->font() );
1322 QVERIFY( cleanTestWidget->testAttribute(Qt::WA_SetFont) );
1323 QVERIFY( cleanTestWidget->font() == newFont );
1325 cleanTestWidget->setFont(QFont());
1326 QVERIFY( !cleanTestWidget->testAttribute(Qt::WA_SetFont) );
1327 QVERIFY( cleanTestWidget->font() == originalFont );
1330 void tst_QWidget::mapFromAndTo_data()
1332 QTest::addColumn<bool>("windowHidden");
1333 QTest::addColumn<bool>("subWindow1Hidden");
1334 QTest::addColumn<bool>("subWindow2Hidden");
1335 QTest::addColumn<bool>("subSubWindowHidden");
1336 QTest::addColumn<bool>("windowMinimized");
1337 QTest::addColumn<bool>("subWindow1Minimized");
1339 QTest::newRow("window 1 sub1 1 sub2 1 subsub 1") << false << false << false << false << false << false;
1340 QTest::newRow("window 0 sub1 1 sub2 1 subsub 1") << true << false << false << false << false << false;
1341 QTest::newRow("window 1 sub1 0 sub2 1 subsub 1") << false << true << false << false << false << false;
1342 QTest::newRow("window 0 sub1 0 sub2 1 subsub 1") << true << true << false << false << false << false;
1343 QTest::newRow("window 1 sub1 1 sub2 0 subsub 1") << false << false << true << false << false << false;
1344 QTest::newRow("window 0 sub1 1 sub2 0 subsub 1") << true << false << true << false << false << false;
1345 QTest::newRow("window 1 sub1 0 sub2 0 subsub 1") << false << true << true << false << false << false;
1346 QTest::newRow("window 0 sub1 0 sub2 0 subsub 1") << true << true << true << false << false << false;
1347 QTest::newRow("window 1 sub1 1 sub2 1 subsub 0") << false << false << false << true << false << false;
1348 QTest::newRow("window 0 sub1 1 sub2 1 subsub 0") << true << false << false << true << false << false;
1349 QTest::newRow("window 1 sub1 0 sub2 1 subsub 0") << false << true << false << true << false << false;
1350 QTest::newRow("window 0 sub1 0 sub2 1 subsub 0") << true << true << false << true << false << false;
1351 QTest::newRow("window 1 sub1 1 sub2 0 subsub 0") << false << false << true << true << false << false;
1352 QTest::newRow("window 0 sub1 1 sub2 0 subsub 0") << true << false << true << true << false << false;
1353 QTest::newRow("window 1 sub1 0 sub2 0 subsub 0") << false << true << true << true << false << false;
1354 QTest::newRow("window 0 sub1 0 sub2 0 subsub 0") << true << true << true << true << false << false;
1355 QTest::newRow("window 1 sub1 1 sub2 1 subsub 1 windowMinimized") << false << false << false << false << true << false;
1356 QTest::newRow("window 0 sub1 1 sub2 1 subsub 1 windowMinimized") << true << false << false << false << true << false;
1357 QTest::newRow("window 1 sub1 0 sub2 1 subsub 1 windowMinimized") << false << true << false << false << true << false;
1358 QTest::newRow("window 0 sub1 0 sub2 1 subsub 1 windowMinimized") << true << true << false << false << true << false;
1359 QTest::newRow("window 1 sub1 1 sub2 0 subsub 1 windowMinimized") << false << false << true << false << true << false;
1360 QTest::newRow("window 0 sub1 1 sub2 0 subsub 1 windowMinimized") << true << false << true << false << true << false;
1361 QTest::newRow("window 1 sub1 0 sub2 0 subsub 1 windowMinimized") << false << true << true << false << true << false;
1362 QTest::newRow("window 0 sub1 0 sub2 0 subsub 1 windowMinimized") << true << true << true << false << true << false;
1363 QTest::newRow("window 1 sub1 1 sub2 1 subsub 0 windowMinimized") << false << false << false << true << true << false;
1364 QTest::newRow("window 0 sub1 1 sub2 1 subsub 0 windowMinimized") << true << false << false << true << true << false;
1365 QTest::newRow("window 1 sub1 0 sub2 1 subsub 0 windowMinimized") << false << true << false << true << true << false;
1366 QTest::newRow("window 0 sub1 0 sub2 1 subsub 0 windowMinimized") << true << true << false << true << true << false;
1367 QTest::newRow("window 1 sub1 1 sub2 0 subsub 0 windowMinimized") << false << false << true << true << true << false;
1368 QTest::newRow("window 0 sub1 1 sub2 0 subsub 0 windowMinimized") << true << false << true << true << true << false;
1369 QTest::newRow("window 1 sub1 0 sub2 0 subsub 0 windowMinimized") << false << true << true << true << true << false;
1370 QTest::newRow("window 0 sub1 0 sub2 0 subsub 0 windowMinimized") << true << true << true << true << true << false;
1371 QTest::newRow("window 1 sub1 1 sub2 1 subsub 1 subWindow1Minimized") << false << false << false << false << false << true;
1372 QTest::newRow("window 0 sub1 1 sub2 1 subsub 1 subWindow1Minimized") << true << false << false << false << false << true;
1373 QTest::newRow("window 1 sub1 0 sub2 1 subsub 1 subWindow1Minimized") << false << true << false << false << false << true;
1374 QTest::newRow("window 0 sub1 0 sub2 1 subsub 1 subWindow1Minimized") << true << true << false << false << false << true;
1375 QTest::newRow("window 1 sub1 1 sub2 0 subsub 1 subWindow1Minimized") << false << false << true << false << false << true;
1376 QTest::newRow("window 0 sub1 1 sub2 0 subsub 1 subWindow1Minimized") << true << false << true << false << false << true;
1377 QTest::newRow("window 1 sub1 0 sub2 0 subsub 1 subWindow1Minimized") << false << true << true << false << false << true;
1378 QTest::newRow("window 0 sub1 0 sub2 0 subsub 1 subWindow1Minimized") << true << true << true << false << false << true;
1379 QTest::newRow("window 1 sub1 1 sub2 1 subsub 0 subWindow1Minimized") << false << false << false << true << false << true;
1380 QTest::newRow("window 0 sub1 1 sub2 1 subsub 0 subWindow1Minimized") << true << false << false << true << false << true;
1381 QTest::newRow("window 1 sub1 0 sub2 1 subsub 0 subWindow1Minimized") << false << true << false << true << false << true;
1382 QTest::newRow("window 0 sub1 0 sub2 1 subsub 0 subWindow1Minimized") << true << true << false << true << false << true;
1383 QTest::newRow("window 1 sub1 1 sub2 0 subsub 0 subWindow1Minimized") << false << false << true << true << false << true;
1384 QTest::newRow("window 0 sub1 1 sub2 0 subsub 0 subWindow1Minimized") << true << false << true << true << false << true;
1385 QTest::newRow("window 1 sub1 0 sub2 0 subsub 0 subWindow1Minimized") << false << true << true << true << false << true;
1386 QTest::newRow("window 0 sub1 0 sub2 0 subsub 0 subWindow1Minimized") << true << true << true << true << false << true;
1391 void tst_QWidget::mapFromAndTo()
1393 QFETCH(bool, windowHidden);
1394 QFETCH(bool, subWindow1Hidden);
1395 QFETCH(bool, subWindow2Hidden);
1396 QFETCH(bool, subSubWindowHidden);
1397 QFETCH(bool, windowMinimized);
1398 QFETCH(bool, subWindow1Minimized);
1400 // create a toplevel and two overlapping siblings
1402 window.setObjectName(QStringLiteral("mapFromAndTo"));
1403 window.setWindowTitle(window.objectName());
1404 window.setWindowFlags(window.windowFlags() | Qt::X11BypassWindowManagerHint);
1405 QWidget *subWindow1 = new QWidget(&window);
1406 QWidget *subWindow2 = new QWidget(&window);
1407 QWidget *subSubWindow = new QWidget(subWindow1);
1409 // set their geometries
1410 window.setGeometry(100, 100, 100, 100);
1411 subWindow1->setGeometry(50, 50, 100, 100);
1412 subWindow2->setGeometry(75, 75, 100, 100);
1413 subSubWindow->setGeometry(10, 10, 10, 10);
1415 #if !defined (Q_OS_WINCE) //still no proper minimizing
1417 if (windowMinimized) {
1418 if (!windowHidden) {
1419 window.showMinimized();
1420 QVERIFY(window.isMinimized());
1423 window.setVisible(!windowHidden);
1425 if (subWindow1Minimized) {
1427 subWindow1->showMinimized();
1428 QVERIFY(subWindow1->isMinimized());
1430 subWindow1->setVisible(!subWindow1Hidden);
1433 Q_UNUSED(windowHidden);
1434 Q_UNUSED(subWindow1Hidden);
1435 Q_UNUSED(windowMinimized);
1436 Q_UNUSED(subWindow1Minimized);
1439 subWindow2->setVisible(!subWindow2Hidden);
1440 subSubWindow->setVisible(!subSubWindowHidden);
1443 QCOMPARE(window.mapToGlobal(QPoint(0, 0)), QPoint(100, 100));
1444 QCOMPARE(window.mapToGlobal(QPoint(10, 0)), QPoint(110, 100));
1445 QCOMPARE(window.mapToGlobal(QPoint(0, 10)), QPoint(100, 110));
1446 QCOMPARE(window.mapToGlobal(QPoint(-10, 0)), QPoint(90, 100));
1447 QCOMPARE(window.mapToGlobal(QPoint(0, -10)), QPoint(100, 90));
1448 QCOMPARE(window.mapToGlobal(QPoint(100, 100)), QPoint(200, 200));
1449 QCOMPARE(window.mapToGlobal(QPoint(110, 100)), QPoint(210, 200));
1450 QCOMPARE(window.mapToGlobal(QPoint(100, 110)), QPoint(200, 210));
1451 QCOMPARE(window.mapFromGlobal(QPoint(100, 100)), QPoint(0, 0));
1452 QCOMPARE(window.mapFromGlobal(QPoint(110, 100)), QPoint(10, 0));
1453 QCOMPARE(window.mapFromGlobal(QPoint(100, 110)), QPoint(0, 10));
1454 QCOMPARE(window.mapFromGlobal(QPoint(90, 100)), QPoint(-10, 0));
1455 QCOMPARE(window.mapFromGlobal(QPoint(100, 90)), QPoint(0, -10));
1456 QCOMPARE(window.mapFromGlobal(QPoint(200, 200)), QPoint(100, 100));
1457 QCOMPARE(window.mapFromGlobal(QPoint(210, 200)), QPoint(110, 100));
1458 QCOMPARE(window.mapFromGlobal(QPoint(200, 210)), QPoint(100, 110));
1459 QCOMPARE(window.mapToParent(QPoint(0, 0)), QPoint(100, 100));
1460 QCOMPARE(window.mapToParent(QPoint(10, 0)), QPoint(110, 100));
1461 QCOMPARE(window.mapToParent(QPoint(0, 10)), QPoint(100, 110));
1462 QCOMPARE(window.mapToParent(QPoint(-10, 0)), QPoint(90, 100));
1463 QCOMPARE(window.mapToParent(QPoint(0, -10)), QPoint(100, 90));
1464 QCOMPARE(window.mapToParent(QPoint(100, 100)), QPoint(200, 200));
1465 QCOMPARE(window.mapToParent(QPoint(110, 100)), QPoint(210, 200));
1466 QCOMPARE(window.mapToParent(QPoint(100, 110)), QPoint(200, 210));
1467 QCOMPARE(window.mapFromParent(QPoint(100, 100)), QPoint(0, 0));
1468 QCOMPARE(window.mapFromParent(QPoint(110, 100)), QPoint(10, 0));
1469 QCOMPARE(window.mapFromParent(QPoint(100, 110)), QPoint(0, 10));
1470 QCOMPARE(window.mapFromParent(QPoint(90, 100)), QPoint(-10, 0));
1471 QCOMPARE(window.mapFromParent(QPoint(100, 90)), QPoint(0, -10));
1472 QCOMPARE(window.mapFromParent(QPoint(200, 200)), QPoint(100, 100));
1473 QCOMPARE(window.mapFromParent(QPoint(210, 200)), QPoint(110, 100));
1474 QCOMPARE(window.mapFromParent(QPoint(200, 210)), QPoint(100, 110));
1477 QCOMPARE(subWindow1->mapToGlobal(QPoint(0, 0)), QPoint(150, 150));
1478 QCOMPARE(subWindow1->mapToGlobal(QPoint(10, 0)), QPoint(160, 150));
1479 QCOMPARE(subWindow1->mapToGlobal(QPoint(0, 10)), QPoint(150, 160));
1480 QCOMPARE(subWindow1->mapToGlobal(QPoint(-10, 0)), QPoint(140, 150));
1481 QCOMPARE(subWindow1->mapToGlobal(QPoint(0, -10)), QPoint(150, 140));
1482 QCOMPARE(subWindow1->mapToGlobal(QPoint(100, 100)), QPoint(250, 250));
1483 QCOMPARE(subWindow1->mapToGlobal(QPoint(110, 100)), QPoint(260, 250));
1484 QCOMPARE(subWindow1->mapToGlobal(QPoint(100, 110)), QPoint(250, 260));
1485 QCOMPARE(subWindow1->mapFromGlobal(QPoint(150, 150)), QPoint(0, 0));
1486 QCOMPARE(subWindow1->mapFromGlobal(QPoint(160, 150)), QPoint(10, 0));
1487 QCOMPARE(subWindow1->mapFromGlobal(QPoint(150, 160)), QPoint(0, 10));
1488 QCOMPARE(subWindow1->mapFromGlobal(QPoint(140, 150)), QPoint(-10, 0));
1489 QCOMPARE(subWindow1->mapFromGlobal(QPoint(150, 140)), QPoint(0, -10));
1490 QCOMPARE(subWindow1->mapFromGlobal(QPoint(250, 250)), QPoint(100, 100));
1491 QCOMPARE(subWindow1->mapFromGlobal(QPoint(260, 250)), QPoint(110, 100));
1492 QCOMPARE(subWindow1->mapFromGlobal(QPoint(250, 260)), QPoint(100, 110));
1493 QCOMPARE(subWindow1->mapToParent(QPoint(0, 0)), QPoint(50, 50));
1494 QCOMPARE(subWindow1->mapToParent(QPoint(10, 0)), QPoint(60, 50));
1495 QCOMPARE(subWindow1->mapToParent(QPoint(0, 10)), QPoint(50, 60));
1496 QCOMPARE(subWindow1->mapToParent(QPoint(-10, 0)), QPoint(40, 50));
1497 QCOMPARE(subWindow1->mapToParent(QPoint(0, -10)), QPoint(50, 40));
1498 QCOMPARE(subWindow1->mapToParent(QPoint(100, 100)), QPoint(150, 150));
1499 QCOMPARE(subWindow1->mapToParent(QPoint(110, 100)), QPoint(160, 150));
1500 QCOMPARE(subWindow1->mapToParent(QPoint(100, 110)), QPoint(150, 160));
1501 QCOMPARE(subWindow1->mapFromParent(QPoint(50, 50)), QPoint(0, 0));
1502 QCOMPARE(subWindow1->mapFromParent(QPoint(60, 50)), QPoint(10, 0));
1503 QCOMPARE(subWindow1->mapFromParent(QPoint(50, 60)), QPoint(0, 10));
1504 QCOMPARE(subWindow1->mapFromParent(QPoint(40, 50)), QPoint(-10, 0));
1505 QCOMPARE(subWindow1->mapFromParent(QPoint(50, 40)), QPoint(0, -10));
1506 QCOMPARE(subWindow1->mapFromParent(QPoint(150, 150)), QPoint(100, 100));
1507 QCOMPARE(subWindow1->mapFromParent(QPoint(160, 150)), QPoint(110, 100));
1508 QCOMPARE(subWindow1->mapFromParent(QPoint(150, 160)), QPoint(100, 110));
1511 QCOMPARE(subSubWindow->mapToGlobal(QPoint(0, 0)), QPoint(160, 160));
1512 QCOMPARE(subSubWindow->mapToGlobal(QPoint(10, 0)), QPoint(170, 160));
1513 QCOMPARE(subSubWindow->mapToGlobal(QPoint(0, 10)), QPoint(160, 170));
1514 QCOMPARE(subSubWindow->mapToGlobal(QPoint(-10, 0)), QPoint(150, 160));
1515 QCOMPARE(subSubWindow->mapToGlobal(QPoint(0, -10)), QPoint(160, 150));
1516 QCOMPARE(subSubWindow->mapToGlobal(QPoint(100, 100)), QPoint(260, 260));
1517 QCOMPARE(subSubWindow->mapToGlobal(QPoint(110, 100)), QPoint(270, 260));
1518 QCOMPARE(subSubWindow->mapToGlobal(QPoint(100, 110)), QPoint(260, 270));
1519 QCOMPARE(subSubWindow->mapFromGlobal(QPoint(160, 160)), QPoint(0, 0));
1520 QCOMPARE(subSubWindow->mapFromGlobal(QPoint(170, 160)), QPoint(10, 0));
1521 QCOMPARE(subSubWindow->mapFromGlobal(QPoint(160, 170)), QPoint(0, 10));
1522 QCOMPARE(subSubWindow->mapFromGlobal(QPoint(150, 160)), QPoint(-10, 0));
1523 QCOMPARE(subSubWindow->mapFromGlobal(QPoint(160, 150)), QPoint(0, -10));
1524 QCOMPARE(subSubWindow->mapFromGlobal(QPoint(260, 260)), QPoint(100, 100));
1525 QCOMPARE(subSubWindow->mapFromGlobal(QPoint(270, 260)), QPoint(110, 100));
1526 QCOMPARE(subSubWindow->mapFromGlobal(QPoint(260, 270)), QPoint(100, 110));
1527 QCOMPARE(subSubWindow->mapToParent(QPoint(0, 0)), QPoint(10, 10));
1528 QCOMPARE(subSubWindow->mapToParent(QPoint(10, 0)), QPoint(20, 10));
1529 QCOMPARE(subSubWindow->mapToParent(QPoint(0, 10)), QPoint(10, 20));
1530 QCOMPARE(subSubWindow->mapToParent(QPoint(-10, 0)), QPoint(0, 10));
1531 QCOMPARE(subSubWindow->mapToParent(QPoint(0, -10)), QPoint(10, 0));
1532 QCOMPARE(subSubWindow->mapToParent(QPoint(100, 100)), QPoint(110, 110));
1533 QCOMPARE(subSubWindow->mapToParent(QPoint(110, 100)), QPoint(120, 110));
1534 QCOMPARE(subSubWindow->mapToParent(QPoint(100, 110)), QPoint(110, 120));
1535 QCOMPARE(subSubWindow->mapFromParent(QPoint(10, 10)), QPoint(0, 0));
1536 QCOMPARE(subSubWindow->mapFromParent(QPoint(20, 10)), QPoint(10, 0));
1537 QCOMPARE(subSubWindow->mapFromParent(QPoint(10, 20)), QPoint(0, 10));
1538 QCOMPARE(subSubWindow->mapFromParent(QPoint(0, 10)), QPoint(-10, 0));
1539 QCOMPARE(subSubWindow->mapFromParent(QPoint(10, 0)), QPoint(0, -10));
1540 QCOMPARE(subSubWindow->mapFromParent(QPoint(110, 110)), QPoint(100, 100));
1541 QCOMPARE(subSubWindow->mapFromParent(QPoint(120, 110)), QPoint(110, 100));
1542 QCOMPARE(subSubWindow->mapFromParent(QPoint(110, 120)), QPoint(100, 110));
1545 void tst_QWidget::focusChainOnReparent()
1548 QWidget *child1 = new QWidget(&window);
1549 QWidget *child2 = new QWidget(&window);
1550 QWidget *child3 = new QWidget(&window);
1551 QWidget *child21 = new QWidget(child2);
1552 QWidget *child22 = new QWidget(child2);
1553 QWidget *child4 = new QWidget(&window);
1555 QWidget *expectedOriginalChain[8] = {&window, child1, child2, child3, child21, child22, child4, &window};
1556 QWidget *w = &window;
1557 for (int i = 0; i <8; ++i) {
1558 QCOMPARE(w, expectedOriginalChain[i]);
1559 w = w->nextInFocusChain();
1561 for (int i = 7; i >= 0; --i) {
1562 w = w->previousInFocusChain();
1563 QCOMPARE(w, expectedOriginalChain[i]);
1567 child2->setParent(&window2);
1569 QWidget *expectedNewChain[5] = {&window2, child2, child21, child22, &window2};
1571 for (int i = 0; i <5; ++i) {
1572 QCOMPARE(w, expectedNewChain[i]);
1573 w = w->nextInFocusChain();
1575 for (int i = 4; i >= 0; --i) {
1576 w = w->previousInFocusChain();
1577 QCOMPARE(w, expectedNewChain[i]);
1580 QWidget *expectedOldChain[5] = {&window, child1, child3, child4, &window};
1582 for (int i = 0; i <5; ++i) {
1583 QCOMPARE(w, expectedOldChain[i]);
1584 w = w->nextInFocusChain();
1586 for (int i = 4; i >= 0; --i) {
1587 w = w->previousInFocusChain();
1588 QCOMPARE(w, expectedOldChain[i]);
1593 void tst_QWidget::focusChainOnHide()
1595 testWidget->hide(); // We do not want to get disturbed by other widgets
1596 // focus should move to the next widget in the focus chain when we hide it.
1597 QScopedPointer<QWidget> parent(new QWidget());
1598 parent->setObjectName(QLatin1String("focusChainOnHide"));
1599 parent->resize(200, 200);
1600 parent->setWindowTitle(parent->objectName());
1601 parent->setFocusPolicy(Qt::StrongFocus);
1602 QWidget *child = new QWidget(parent.data());
1603 child->setObjectName(QLatin1String("child"));
1604 child->setFocusPolicy(Qt::StrongFocus);
1605 QWidget::setTabOrder(child, parent.data());
1608 qApp->setActiveWindow(parent->window());
1609 child->activateWindow();
1611 qApp->processEvents();
1613 QTRY_COMPARE(child->hasFocus(), true);
1615 qApp->processEvents();
1617 QTRY_COMPARE(parent->hasFocus(), true);
1618 QCOMPARE(parent.data(), qApp->focusWidget());
1620 testWidget->show(); //don't disturb later tests
1623 class Container : public QWidget
1630 box = new QVBoxLayout(this);
1631 //(new QVBoxLayout(this))->setAutoAdd(true);
1636 focusNextPrevChild(true);
1641 focusNextPrevChild(false);
1645 class Composite : public QFrame
1648 Composite(QWidget* parent = 0, const char* name = 0)
1651 setObjectName(name);
1652 //QHBoxLayout* hbox = new QHBoxLayout(this, 2, 0);
1653 //hbox->setAutoAdd(true);
1654 QHBoxLayout* hbox = new QHBoxLayout(this);
1656 lineEdit = new QLineEdit(this);
1657 hbox->addWidget(lineEdit);
1659 button = new QPushButton(this);
1660 hbox->addWidget(button);
1661 button->setFocusPolicy( Qt::NoFocus );
1663 setFocusProxy( lineEdit );
1664 setFocusPolicy( Qt::StrongFocus );
1666 setTabOrder(lineEdit, button);
1670 QLineEdit* lineEdit;
1671 QPushButton* button;
1674 #define NUM_WIDGETS 4
1676 void tst_QWidget::setTabOrder()
1680 Container container;
1681 container.setObjectName("setTabOrder");
1682 container.setWindowTitle(container.objectName());
1684 Composite* comp[NUM_WIDGETS];
1686 QLineEdit *firstEdit = new QLineEdit(&container);
1687 container.box->addWidget(firstEdit);
1690 for(i = 0; i < NUM_WIDGETS; i++) {
1691 comp[i] = new Composite(&container);
1692 container.box->addWidget(comp[i]);
1695 QLineEdit *lastEdit = new QLineEdit(&container);
1696 container.box->addWidget(lastEdit);
1698 container.setTabOrder(lastEdit, comp[NUM_WIDGETS-1]);
1699 for(i = NUM_WIDGETS-1; i > 0; i--) {
1700 container.setTabOrder(comp[i], comp[i-1]);
1702 container.setTabOrder(comp[0], firstEdit);
1704 int current = NUM_WIDGETS-1;
1705 lastEdit->setFocus();
1708 container.activateWindow();
1709 qApp->setActiveWindow(&container);
1710 QVERIFY(QTest::qWaitForWindowActive(&container));
1712 QTRY_VERIFY(lastEdit->hasFocus());
1715 QVERIFY(comp[current]->focusProxy()->hasFocus());
1718 } while (current >= 0);
1720 QVERIFY(firstEdit->hasFocus());
1724 void tst_QWidget::activation()
1728 #if defined(Q_OS_WINCE)
1729 int waitTime = 1000;
1735 qApp->processEvents();
1738 widget1.setObjectName("activation-Widget1");
1739 widget1.setWindowTitle(widget1.objectName());
1742 widget1.setObjectName("activation-Widget2");
1743 widget1.setWindowTitle(widget2.objectName());
1748 QTest::qWait(waitTime);
1749 QVERIFY(qApp->activeWindow() == &widget2);
1750 widget2.showMinimized();
1751 QTest::qWait(waitTime);
1753 QVERIFY(qApp->activeWindow() == &widget1);
1754 widget2.showMaximized();
1755 QTest::qWait(waitTime);
1756 QVERIFY(qApp->activeWindow() == &widget2);
1757 widget2.showMinimized();
1758 QTest::qWait(waitTime);
1759 QVERIFY(qApp->activeWindow() == &widget1);
1760 widget2.showNormal();
1761 QTest::qWait(waitTime);
1763 if (QSysInfo::WindowsVersion >= QSysInfo::WV_VISTA)
1764 QEXPECT_FAIL("", "MS introduced new behavior after XP", Continue);
1766 QTest::qWait(waitTime);
1767 QVERIFY(qApp->activeWindow() == &widget2);
1769 QTest::qWait(waitTime);
1770 QVERIFY(qApp->activeWindow() == &widget1);
1774 void tst_QWidget::windowState()
1776 if (m_platform == QStringLiteral("xcb"))
1777 QSKIP("X11: Many window managers do not support window state properly, which causes this test to fail.");
1778 #ifdef Q_OS_WINCE_WM
1779 QPoint pos(500, 500);
1780 QSize size(200, 200);
1781 if (qt_wince_is_smartphone()) { //small screen
1782 pos = QPoint(10,10);
1783 size = QSize(100,100);
1786 const QPoint pos(500, 500);
1787 const QSize size(200, 200);
1792 widget1.resize(size);
1793 QCOMPARE(widget1.pos(), pos);
1794 QCOMPARE(widget1.size(), size);
1796 widget1.setObjectName(QStringLiteral("windowState-Widget1"));
1797 widget1.setWindowTitle(widget1.objectName());
1798 QCOMPARE(widget1.pos(), pos);
1799 QCOMPARE(widget1.size(), size);
1801 #define VERIFY_STATE(s) QCOMPARE(int(widget1.windowState() & stateMask), int(s))
1803 const int stateMask = Qt::WindowMaximized|Qt::WindowMinimized|Qt::WindowFullScreen;
1805 widget1.setWindowState(Qt::WindowMaximized);
1807 VERIFY_STATE(Qt::WindowMaximized);
1808 QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowMaximized);
1812 VERIFY_STATE(Qt::WindowMaximized);
1813 QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowMaximized);
1815 widget1.setWindowState(widget1.windowState() ^ Qt::WindowMaximized);
1817 QVERIFY(!(widget1.windowState() & Qt::WindowMaximized));
1818 QTRY_COMPARE(widget1.pos(), pos);
1819 QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowNoState);
1821 widget1.setWindowState(Qt::WindowMinimized);
1823 VERIFY_STATE(Qt::WindowMinimized);
1824 QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowMinimized);
1826 widget1.setWindowState(widget1.windowState() | Qt::WindowMaximized);
1828 VERIFY_STATE((Qt::WindowMinimized|Qt::WindowMaximized));
1829 QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowMinimized);
1831 widget1.setWindowState(widget1.windowState() ^ Qt::WindowMinimized);
1833 VERIFY_STATE(Qt::WindowMaximized);
1834 QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowMaximized);
1836 widget1.setWindowState(widget1.windowState() ^ Qt::WindowMaximized);
1838 QVERIFY(!(widget1.windowState() & (Qt::WindowMinimized|Qt::WindowMaximized)));
1839 QTRY_COMPARE(widget1.pos(), pos);
1840 QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowNoState);
1842 widget1.setWindowState(Qt::WindowFullScreen);
1844 VERIFY_STATE(Qt::WindowFullScreen);
1845 QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowFullScreen);
1847 widget1.setWindowState(widget1.windowState() ^ Qt::WindowMinimized);
1849 VERIFY_STATE((Qt::WindowFullScreen|Qt::WindowMinimized));
1850 QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowMinimized);
1852 widget1.setWindowState(widget1.windowState() ^ Qt::WindowMinimized);
1854 VERIFY_STATE(Qt::WindowFullScreen);
1855 QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowFullScreen);
1857 widget1.setWindowState(Qt::WindowNoState);
1859 VERIFY_STATE(Qt::WindowNoState);
1860 QTRY_COMPARE(widget1.pos(), pos);
1861 QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowNoState);
1863 widget1.setWindowState(Qt::WindowFullScreen);
1865 VERIFY_STATE(Qt::WindowFullScreen);
1866 QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowFullScreen);
1868 widget1.setWindowState(widget1.windowState() ^ Qt::WindowMaximized);
1870 VERIFY_STATE((Qt::WindowFullScreen|Qt::WindowMaximized));
1871 QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowFullScreen);
1873 widget1.setWindowState(widget1.windowState() ^ Qt::WindowMinimized);
1875 VERIFY_STATE((Qt::WindowFullScreen|Qt::WindowMaximized|Qt::WindowMinimized));
1876 QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowMinimized);
1878 widget1.setWindowState(widget1.windowState() ^ Qt::WindowMinimized);
1880 VERIFY_STATE((Qt::WindowFullScreen|Qt::WindowMaximized));
1881 QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowFullScreen);
1883 widget1.setWindowState(widget1.windowState() ^ Qt::WindowFullScreen);
1885 VERIFY_STATE(Qt::WindowMaximized);
1886 QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowMaximized);
1888 widget1.setWindowState(widget1.windowState() ^ Qt::WindowMaximized);
1890 QVERIFY(!(widget1.windowState() & stateMask));
1891 QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowNoState);
1893 QTRY_COMPARE(widget1.pos(), pos);
1894 QTRY_COMPARE(widget1.size(), size);
1897 void tst_QWidget::showMaximized()
1900 QHBoxLayout *layout;
1901 layout = new QHBoxLayout;
1907 layout->addWidget(&le);
1908 layout->addWidget(&le2);
1909 layout->addWidget(&le3);
1911 layouted.setLayout(layout);
1913 plain.showMaximized();
1914 QVERIFY(plain.windowState() & Qt::WindowMaximized);
1917 QVERIFY(!(plain.windowState() & Qt::WindowMaximized));
1919 layouted.showMaximized();
1920 QVERIFY(layouted.windowState() & Qt::WindowMaximized);
1922 layouted.showNormal();
1923 QVERIFY(!(layouted.windowState() & Qt::WindowMaximized));
1925 // ### fixme: embedded may choose a different size to fit on the screen.
1926 if (layouted.size() != layouted.sizeHint())
1927 QEXPECT_FAIL("", "QTBUG-22326", Continue);
1928 QCOMPARE(layouted.size(), layouted.sizeHint());
1930 layouted.showMaximized();
1931 QVERIFY(layouted.isMaximized());
1932 QVERIFY(layouted.isVisible());
1935 QVERIFY(layouted.isMaximized());
1936 QVERIFY(!layouted.isVisible());
1938 layouted.showMaximized();
1939 QVERIFY(layouted.isMaximized());
1940 QVERIFY(layouted.isVisible());
1942 layouted.showMinimized();
1943 QVERIFY(layouted.isMinimized());
1944 QVERIFY(layouted.isMaximized());
1946 layouted.showMaximized();
1947 QVERIFY(!layouted.isMinimized());
1948 QVERIFY(layouted.isMaximized());
1949 QVERIFY(layouted.isVisible());
1951 layouted.showMinimized();
1952 QVERIFY(layouted.isMinimized());
1953 QVERIFY(layouted.isMaximized());
1955 layouted.showMaximized();
1956 QVERIFY(!layouted.isMinimized());
1957 QVERIFY(layouted.isMaximized());
1958 QVERIFY(layouted.isVisible());
1962 QWidget widget(&frame);
1963 widget.showMaximized();
1964 QVERIFY(widget.isMaximized());
1969 widget.setGeometry(0, 0, 10, 10);
1970 widget.showMaximized();
1971 QTRY_VERIFY(widget.size().width() > 20 && widget.size().height() > 20);
1975 void tst_QWidget::showFullScreen()
1978 QHBoxLayout *layout;
1983 layout = new QHBoxLayout;
1985 layout->addWidget(&le);
1986 layout->addWidget(&le2);
1987 layout->addWidget(&le3);
1989 layouted.setLayout(layout);
1991 plain.showFullScreen();
1992 QVERIFY(plain.windowState() & Qt::WindowFullScreen);
1993 QVERIFY(plain.windowHandle());
1994 QVERIFY(plain.windowHandle()->screen());
1995 const QRect expectedFullScreenGeometry = plain.windowHandle()->screen()->geometry();
1996 QTRY_COMPARE(plain.geometry(), expectedFullScreenGeometry);
1999 QVERIFY(!(plain.windowState() & Qt::WindowFullScreen));
2001 layouted.showFullScreen();
2002 QVERIFY(layouted.windowState() & Qt::WindowFullScreen);
2003 QTRY_COMPARE(layouted.geometry(), expectedFullScreenGeometry);
2005 layouted.showNormal();
2006 QVERIFY(!(layouted.windowState() & Qt::WindowFullScreen));
2008 // ### fixme: embedded may choose a different size to fit on the screen.
2009 if (layouted.size() != layouted.sizeHint())
2010 QEXPECT_FAIL("", "QTBUG-22326", Continue);
2011 QCOMPARE(layouted.size(), layouted.sizeHint());
2013 layouted.showFullScreen();
2014 QVERIFY(layouted.isFullScreen());
2015 QVERIFY(layouted.isVisible());
2016 QTRY_COMPARE(layouted.geometry(), expectedFullScreenGeometry);
2019 QVERIFY(layouted.isFullScreen());
2020 QVERIFY(!layouted.isVisible());
2022 layouted.showFullScreen();
2023 QVERIFY(layouted.isFullScreen());
2024 QVERIFY(layouted.isVisible());
2025 QTRY_COMPARE(layouted.geometry(), expectedFullScreenGeometry);
2027 layouted.showMinimized();
2028 QVERIFY(layouted.isMinimized());
2029 QVERIFY(layouted.isFullScreen());
2031 layouted.showFullScreen();
2032 if (m_platform == QStringLiteral("windows"))
2033 QEXPECT_FAIL("", "QTBUG-26424", Continue);
2034 QVERIFY(!layouted.isMinimized());
2035 QVERIFY(layouted.isFullScreen());
2036 QVERIFY(layouted.isVisible());
2037 QTRY_COMPARE(layouted.geometry(), expectedFullScreenGeometry);
2039 layouted.showMinimized();
2040 QVERIFY(layouted.isMinimized());
2041 QVERIFY(layouted.isFullScreen());
2043 layouted.showFullScreen();
2044 QVERIFY(!layouted.isMinimized());
2045 QVERIFY(layouted.isFullScreen());
2046 QVERIFY(layouted.isVisible());
2047 QTRY_COMPARE(layouted.geometry(), expectedFullScreenGeometry);
2051 QWidget widget(&frame);
2052 widget.showFullScreen();
2053 QVERIFY(widget.isFullScreen());
2054 QTRY_COMPARE(layouted.geometry(), expectedFullScreenGeometry);
2058 class ResizeWidget : public QWidget {
2060 ResizeWidget(QWidget *p = 0) : QWidget(p)
2062 setObjectName(QLatin1String("ResizeWidget"));
2063 setWindowTitle(objectName());
2064 m_resizeEventCount = 0;
2067 void resizeEvent(QResizeEvent *e){
2068 QCOMPARE(size(), e->size());
2069 ++m_resizeEventCount;
2073 int m_resizeEventCount;
2076 void tst_QWidget::resizeEvent()
2080 ResizeWidget wChild(&wParent);
2082 QCOMPARE (wChild.m_resizeEventCount, 1); // initial resize event before paint
2084 QSize safeSize(640,480);
2085 if (wChild.size() == safeSize)
2086 safeSize.setWidth(639);
2087 wChild.resize(safeSize);
2088 QCOMPARE (wChild.m_resizeEventCount, 1);
2090 QCOMPARE (wChild.m_resizeEventCount, 2);
2094 ResizeWidget wTopLevel;
2096 QCOMPARE (wTopLevel.m_resizeEventCount, 1); // initial resize event before paint for toplevels
2098 QSize safeSize(640,480);
2099 if (wTopLevel.size() == safeSize)
2100 safeSize.setWidth(639);
2101 wTopLevel.resize(safeSize);
2102 QCOMPARE (wTopLevel.m_resizeEventCount, 1);
2104 QCOMPARE (wTopLevel.m_resizeEventCount, 2);
2108 void tst_QWidget::showMinimized()
2111 plain.move(100, 100);
2112 plain.resize(200, 200);
2113 QPoint pos = plain.pos();
2115 plain.showMinimized();
2116 QVERIFY(plain.isMinimized());
2117 QVERIFY(plain.isVisible());
2118 QCOMPARE(plain.pos(), pos);
2121 QVERIFY(!plain.isMinimized());
2122 QVERIFY(plain.isVisible());
2123 QCOMPARE(plain.pos(), pos);
2125 plain.showMinimized();
2126 QVERIFY(plain.isMinimized());
2127 QVERIFY(plain.isVisible());
2128 QCOMPARE(plain.pos(), pos);
2131 QVERIFY(plain.isMinimized());
2132 QVERIFY(!plain.isVisible());
2134 plain.showMinimized();
2135 QVERIFY(plain.isMinimized());
2136 QVERIFY(plain.isVisible());
2138 plain.setGeometry(200, 200, 300, 300);
2140 QCOMPARE(plain.geometry(), QRect(200, 200, 300, 300));
2144 QWidget widget(&frame);
2145 widget.showMinimized();
2146 QVERIFY(widget.isMinimized());
2150 void tst_QWidget::showMinimizedKeepsFocus()
2152 if (m_platform == QStringLiteral("xcb"))
2153 QSKIP("QTBUG-26424");
2155 //here we test that minimizing a widget and restoring it doesn't change the focus inside of it
2158 window.resize(200, 200);
2159 QWidget child1(&window), child2(&window);
2160 child1.setFocusPolicy(Qt::StrongFocus);
2161 child2.setFocusPolicy(Qt::StrongFocus);
2163 qApp->setActiveWindow(&window);
2164 QVERIFY(QTest::qWaitForWindowActive(&window));
2167 QTRY_COMPARE(window.focusWidget(), &child2);
2168 QTRY_COMPARE(qApp->focusWidget(), &child2);
2170 window.showMinimized();
2171 QTRY_VERIFY(window.isMinimized());
2172 QTRY_COMPARE(window.focusWidget(), &child2);
2174 window.showNormal();
2176 QTRY_COMPARE(window.focusWidget(), &child2);
2179 //testing deletion of the focusWidget
2182 QWidget *child = new QWidget(&window);
2183 child->setFocusPolicy(Qt::StrongFocus);
2185 qApp->setActiveWindow(&window);
2186 QVERIFY(QTest::qWaitForWindowActive(&window));
2188 QTRY_COMPARE(window.focusWidget(), child);
2189 QTRY_COMPARE(qApp->focusWidget(), child);
2192 QCOMPARE(window.focusWidget(), static_cast<QWidget*>(0));
2193 QCOMPARE(qApp->focusWidget(), static_cast<QWidget*>(0));
2196 //testing reparenting the focus widget
2199 QWidget *child = new QWidget(&window);
2200 child->setFocusPolicy(Qt::StrongFocus);
2202 qApp->setActiveWindow(&window);
2203 QVERIFY(QTest::qWaitForWindowActive(&window));
2205 QTRY_COMPARE(window.focusWidget(), child);
2206 QTRY_COMPARE(qApp->focusWidget(), child);
2208 child->setParent(0);
2209 QCOMPARE(window.focusWidget(), static_cast<QWidget*>(0));
2210 QCOMPARE(qApp->focusWidget(), static_cast<QWidget*>(0));
2213 //testing setEnabled(false)
2216 QWidget *child = new QWidget(&window);
2217 child->setFocusPolicy(Qt::StrongFocus);
2219 qApp->setActiveWindow(&window);
2220 QVERIFY(QTest::qWaitForWindowActive(&window));
2222 QTRY_COMPARE(window.focusWidget(), child);
2223 QTRY_COMPARE(qApp->focusWidget(), child);
2225 child->setEnabled(false);
2226 QCOMPARE(window.focusWidget(), static_cast<QWidget*>(0));
2227 QCOMPARE(qApp->focusWidget(), static_cast<QWidget*>(0));
2230 //testing clearFocus
2233 QWidget *firstchild = new QWidget(&window);
2234 firstchild->setFocusPolicy(Qt::StrongFocus);
2235 QWidget *child = new QWidget(&window);
2236 child->setFocusPolicy(Qt::StrongFocus);
2238 qApp->setActiveWindow(&window);
2239 QVERIFY(QTest::qWaitForWindowActive(&window));
2241 QTRY_COMPARE(window.focusWidget(), child);
2242 QTRY_COMPARE(qApp->focusWidget(), child);
2244 child->clearFocus();
2245 QCOMPARE(window.focusWidget(), static_cast<QWidget*>(0));
2246 QCOMPARE(qApp->focusWidget(), static_cast<QWidget*>(0));
2248 window.showMinimized();
2250 QTRY_VERIFY(window.isMinimized());
2251 QCOMPARE(window.focusWidget(), static_cast<QWidget*>(0));
2252 QTRY_COMPARE(qApp->focusWidget(), static_cast<QWidget*>(0));
2254 window.showNormal();
2255 qApp->setActiveWindow(&window);
2256 QVERIFY(QTest::qWaitForWindowActive(&window));
2258 if (!macHasAccessToWindowsServer())
2259 QEXPECT_FAIL("", "When not having WindowServer access, we lose focus.", Continue);
2261 QTRY_COMPARE(window.focusWidget(), firstchild);
2263 if (!macHasAccessToWindowsServer())
2264 QEXPECT_FAIL("", "When not having WindowServer access, we lose focus.", Continue);
2266 QTRY_COMPARE(qApp->focusWidget(), firstchild);
2271 void tst_QWidget::reparent()
2274 parent.setWindowTitle("Toplevel");
2275 parent.setGeometry(300, 300, 200, 150);
2278 child.setObjectName("child");
2279 child.setGeometry(10, 10, 180, 130);
2281 pal1.setColor(child.backgroundRole(), Qt::white);
2282 child.setPalette(pal1);
2284 QWidget childTLW(&child, Qt::Window);
2285 childTLW.setObjectName("childTLW");
2286 childTLW.setGeometry(100, 100, 50, 50);
2288 pal2.setColor(childTLW.backgroundRole(), Qt::yellow);
2289 childTLW.setPalette(pal2);
2293 QVERIFY(QTest::qWaitForWindowExposed(&parent));
2296 parent.move(50, 50);
2298 parent.move(300, 300);
2301 QPoint childPos = parent.mapToGlobal(child.pos());
2302 QPoint tlwPos = childTLW.pos();
2304 child.setParent(0, child.windowFlags() & ~Qt::WindowType_Mask);
2305 child.setGeometry(childPos.x(), childPos.y(), child.width(), child.height());
2308 #if 0 // QTBUG-26424
2309 if (m_platform == QStringLiteral("xcb"))
2310 QEXPECT_FAIL("", "On X11, the window manager will apply NorthWestGravity rules to 'child', which"
2311 " means the top-left corner of the window frame will be placed at 'childPos'"
2312 " causing this test to fail.", Continue);
2315 QCOMPARE(child.geometry().topLeft(), childPos);
2316 QTRY_COMPARE(childTLW.pos(), tlwPos);
2319 // Qt/Embedded does it differently.
2320 void tst_QWidget::icon()
2324 testWidget->setWindowIcon(p);
2326 QVERIFY(!testWidget->windowIcon().isNull());
2328 QVERIFY(!testWidget->windowIcon().isNull());
2329 testWidget->showFullScreen();
2330 QVERIFY(!testWidget->windowIcon().isNull());
2331 testWidget->showNormal();
2332 QVERIFY(!testWidget->windowIcon().isNull());
2335 void tst_QWidget::hideWhenFocusWidgetIsChild()
2337 testWidget->activateWindow();
2338 QScopedPointer<QWidget> parentWidget(new QWidget(testWidget));
2339 parentWidget->setObjectName("parentWidget");
2340 parentWidget->setGeometry(0, 0, 100, 100);
2341 QLineEdit *edit = new QLineEdit(parentWidget.data());
2342 edit->setObjectName("edit1");
2343 QLineEdit *edit3 = new QLineEdit(parentWidget.data());
2344 edit3->setObjectName("edit3");
2346 parentWidget->show();
2347 QLineEdit *edit2 = new QLineEdit(testWidget);
2348 edit2->setObjectName("edit2");
2350 edit2->move(110, 100);
2352 qApp->processEvents();
2353 QString actualFocusWidget, expectedFocusWidget;
2354 if (!qApp->focusWidget() && m_platform == QStringLiteral("xcb"))
2355 QSKIP("X11: Your window manager is too broken for this test");
2357 QVERIFY(qApp->focusWidget());
2358 actualFocusWidget.sprintf("%p %s %s", qApp->focusWidget(), qApp->focusWidget()->objectName().toLatin1().constData(), qApp->focusWidget()->metaObject()->className());
2359 expectedFocusWidget.sprintf("%p %s %s", edit, edit->objectName().toLatin1().constData(), edit->metaObject()->className());
2360 QCOMPARE(actualFocusWidget, expectedFocusWidget);
2362 parentWidget->hide();
2363 qApp->processEvents();
2364 actualFocusWidget.sprintf("%p %s %s", qApp->focusWidget(), qApp->focusWidget()->objectName().toLatin1().constData(), qApp->focusWidget()->metaObject()->className());
2365 expectedFocusWidget.sprintf("%p %s %s", edit2, edit2->objectName().toLatin1().constData(), edit2->metaObject()->className());
2366 QCOMPARE(actualFocusWidget, expectedFocusWidget);
2369 void tst_QWidget::normalGeometry()
2372 parent.setWindowTitle("NormalGeometry parent");
2373 QWidget *child = new QWidget(&parent);
2375 QCOMPARE(parent.normalGeometry(), parent.geometry());
2376 QCOMPARE(child->normalGeometry(), QRect());
2378 parent.setGeometry(100, 100, 200, 200);
2380 QVERIFY(QTest::qWaitForWindowExposed(&parent));
2381 QApplication::processEvents();
2383 QRect geom = parent.geometry();
2384 // ### the window manager places the top-left corner at
2385 // ### 100,100... making geom something like 102,124 (offset by
2386 // ### the frame/frame)... this indicates a rather large different
2387 // ### between how X11 and Windows works
2388 // QCOMPARE(geom, QRect(100, 100, 200, 200));
2389 QCOMPARE(parent.normalGeometry(), geom);
2391 parent.setWindowState(parent.windowState() ^ Qt::WindowMaximized);
2393 QTRY_VERIFY(parent.windowState() & Qt::WindowMaximized);
2394 QTRY_VERIFY(parent.geometry() != geom);
2395 QTRY_COMPARE(parent.normalGeometry(), geom);
2397 parent.setWindowState(parent.windowState() ^ Qt::WindowMaximized);
2399 QTRY_VERIFY(!(parent.windowState() & Qt::WindowMaximized));
2400 QTRY_COMPARE(parent.geometry(), geom);
2401 QTRY_COMPARE(parent.normalGeometry(), geom);
2403 parent.showMaximized();
2405 QTRY_VERIFY(parent.windowState() & Qt::WindowMaximized);
2406 QTRY_VERIFY(parent.geometry() != geom);
2407 QCOMPARE(parent.normalGeometry(), geom);
2409 parent.showNormal();
2411 QTRY_VERIFY(!(parent.windowState() & Qt::WindowMaximized));
2412 QTRY_COMPARE(parent.geometry(), geom);
2413 QCOMPARE(parent.normalGeometry(), geom);
2415 parent.setWindowState(parent.windowState() ^ Qt::WindowMinimized);
2417 parent.setWindowState(parent.windowState() ^ Qt::WindowMaximized);
2419 if (m_platform == QStringLiteral("xcb"))
2420 QSKIP("QTBUG-26424");
2421 QTRY_VERIFY(parent.windowState() & (Qt::WindowMinimized|Qt::WindowMaximized));
2422 // ### when minimized and maximized at the same time, the geometry
2423 // ### does *NOT* have to be the normal geometry, it could be the
2424 // ### maximized geometry.
2425 // QCOMPARE(parent.geometry(), geom);
2426 QTRY_COMPARE(parent.normalGeometry(), geom);
2428 parent.setWindowState(parent.windowState() ^ Qt::WindowMinimized);
2430 QTRY_VERIFY(!(parent.windowState() & Qt::WindowMinimized));
2431 QTRY_VERIFY(parent.windowState() & Qt::WindowMaximized);
2432 QTRY_VERIFY(parent.geometry() != geom);
2433 QTRY_COMPARE(parent.normalGeometry(), geom);
2435 parent.setWindowState(parent.windowState() ^ Qt::WindowMaximized);
2437 QTRY_VERIFY(!(parent.windowState() & Qt::WindowMaximized));
2438 QTRY_COMPARE(parent.geometry(), geom);
2439 QTRY_COMPARE(parent.normalGeometry(), geom);
2441 parent.setWindowState(parent.windowState() ^ Qt::WindowFullScreen);
2443 QTRY_VERIFY(parent.windowState() & Qt::WindowFullScreen);
2444 QTRY_VERIFY(parent.geometry() != geom);
2445 QTRY_COMPARE(parent.normalGeometry(), geom);
2447 parent.setWindowState(parent.windowState() ^ Qt::WindowFullScreen);
2449 QVERIFY(!(parent.windowState() & Qt::WindowFullScreen));
2450 QTRY_COMPARE(parent.geometry(), geom);
2451 QTRY_COMPARE(parent.normalGeometry(), geom);
2453 parent.showFullScreen();
2455 QTRY_VERIFY(parent.windowState() & Qt::WindowFullScreen);
2456 QTRY_VERIFY(parent.geometry() != geom);
2457 QTRY_COMPARE(parent.normalGeometry(), geom);
2459 parent.showNormal();
2461 QTRY_VERIFY(!(parent.windowState() & Qt::WindowFullScreen));
2462 QTRY_COMPARE(parent.geometry(), geom);
2463 QTRY_COMPARE(parent.normalGeometry(), geom);
2465 parent.showNormal();
2466 parent.setWindowState(Qt:: WindowFullScreen | Qt::WindowMaximized);
2467 parent.setWindowState(Qt::WindowMinimized | Qt:: WindowFullScreen | Qt::WindowMaximized);
2468 parent.setWindowState(Qt:: WindowFullScreen | Qt::WindowMaximized);
2470 QTRY_COMPARE(parent.normalGeometry(), geom);
2473 void tst_QWidget::setGeometry()
2476 QWidget child(&tlw);
2478 QRect tr(100,100,200,200);
2479 QRect cr(50,50,50,50);
2480 tlw.setGeometry(tr);
2481 child.setGeometry(cr);
2484 QCOMPARE(tlw.geometry().size(), tr.size());
2485 QCOMPARE(child.geometry(), cr);
2487 tlw.setParent(0, Qt::Window|Qt::FramelessWindowHint);
2488 tr = QRect(0,0,100,100);
2489 tr.moveTopLeft(QApplication::desktop()->availableGeometry().topLeft());
2490 tlw.setGeometry(tr);
2491 QCOMPARE(tlw.geometry(), tr);
2494 if (tlw.frameGeometry() != tlw.geometry())
2495 QSKIP("Your window manager is too broken for this test");
2496 if (m_platform == QStringLiteral("xcb"))
2497 QSKIP("QTBUG-26424");
2498 QCOMPARE(tlw.geometry(), tr);
2501 // Windows CE does not support windowOpacity.
2503 void tst_QWidget::windowOpacity()
2506 QWidget child(&widget);
2508 // Initial value should be 1.0
2509 QCOMPARE(widget.windowOpacity(), 1.0);
2510 // children should always return 1.0
2511 QCOMPARE(child.windowOpacity(), 1.0);
2513 widget.setWindowOpacity(0.0);
2514 QCOMPARE(widget.windowOpacity(), 0.0);
2515 child.setWindowOpacity(0.0);
2516 QCOMPARE(child.windowOpacity(), 1.0);
2518 widget.setWindowOpacity(1.0);
2519 QCOMPARE(widget.windowOpacity(), 1.0);
2520 child.setWindowOpacity(1.0);
2521 QCOMPARE(child.windowOpacity(), 1.0);
2523 widget.setWindowOpacity(2.0);
2524 QCOMPARE(widget.windowOpacity(), 1.0);
2525 child.setWindowOpacity(2.0);
2526 QCOMPARE(child.windowOpacity(), 1.0);
2528 widget.setWindowOpacity(-1.0);
2529 QCOMPARE(widget.windowOpacity(), 0.0);
2530 child.setWindowOpacity(-1.0);
2531 QCOMPARE(child.windowOpacity(), 1.0);
2535 class UpdateWidget : public QWidget
2538 UpdateWidget(QWidget *parent = 0) : QWidget(parent) {
2539 setObjectName(QLatin1String("UpdateWidget"));
2540 setWindowTitle(objectName());
2544 void paintEvent(QPaintEvent *e) {
2545 paintedRegion += e->region();
2547 if (resizeInPaintEvent) {
2548 resizeInPaintEvent = false;
2549 resize(size() + QSize(2, 2));
2553 bool event(QEvent *event)
2555 switch (event->type()) {
2556 case QEvent::ZOrderChange:
2557 ++numZOrderChangeEvents;
2559 case QEvent::UpdateRequest:
2560 ++numUpdateRequestEvents;
2562 case QEvent::ActivationChange:
2563 case QEvent::FocusIn:
2564 case QEvent::FocusOut:
2565 case QEvent::WindowActivate:
2566 case QEvent::WindowDeactivate:
2567 if (!updateOnActivationChangeAndFocusIn)
2568 return true; // Filter out to avoid update() calls in QWidget.
2573 return QWidget::event(event);
2578 numZOrderChangeEvents = 0;
2579 numUpdateRequestEvents = 0;
2580 updateOnActivationChangeAndFocusIn = false;
2581 resizeInPaintEvent = false;
2582 paintedRegion = QRegion();
2586 int numZOrderChangeEvents;
2587 int numUpdateRequestEvents;
2588 bool updateOnActivationChangeAndFocusIn;
2589 bool resizeInPaintEvent;
2590 QRegion paintedRegion;
2593 void tst_QWidget::lostUpdatesOnHide()
2596 UpdateWidget widget;
2597 widget.setAttribute(Qt::WA_DontShowOnScreen);
2604 QCOMPARE(widget.numPaintEvents, 1);
2608 void tst_QWidget::raise()
2611 QScopedPointer<QWidget> parentPtr(new QWidget);
2612 parentPtr->resize(200, 200);
2613 parentPtr->setObjectName(QLatin1String("raise"));
2614 parentPtr->setWindowTitle(parentPtr->objectName());
2615 QList<UpdateWidget *> allChildren;
2617 UpdateWidget *child1 = new UpdateWidget(parentPtr.data());
2618 child1->setAutoFillBackground(true);
2619 allChildren.append(child1);
2621 UpdateWidget *child2 = new UpdateWidget(parentPtr.data());
2622 child2->setAutoFillBackground(true);
2623 allChildren.append(child2);
2625 UpdateWidget *child3 = new UpdateWidget(parentPtr.data());
2626 child3->setAutoFillBackground(true);
2627 allChildren.append(child3);
2629 UpdateWidget *child4 = new UpdateWidget(parentPtr.data());
2630 child4->setAutoFillBackground(true);
2631 allChildren.append(child4);
2634 QVERIFY(QTest::qWaitForWindowExposed(parentPtr.data()));
2638 if (child1->internalWinId()) {
2639 QSKIP("Cocoa has no Z-Order for views, we hack it, but it results in paint events.");
2643 QList<QObject *> list1;
2644 list1 << child1 << child2 << child3 << child4;
2645 QVERIFY(parentPtr->children() == list1);
2646 QCOMPARE(allChildren.count(), list1.count());
2648 foreach (UpdateWidget *child, allChildren) {
2649 int expectedPaintEvents = child == child4 ? 1 : 0;
2650 if (expectedPaintEvents == 0) {
2651 QVERIFY(child->numPaintEvents == 0);
2653 // show() issues multiple paint events on some window managers
2654 QTRY_VERIFY(child->numPaintEvents >= expectedPaintEvents);
2656 QCOMPARE(child->numZOrderChangeEvents, 0);
2660 for (int i = 0; i < 5; ++i)
2664 foreach (UpdateWidget *child, allChildren) {
2665 int expectedPaintEvents = child == child2 ? 1 : 0;
2666 int expectedZOrderChangeEvents = child == child2 ? 1 : 0;
2667 QTRY_COMPARE(child->numPaintEvents, expectedPaintEvents);
2668 QCOMPARE(child->numZOrderChangeEvents, expectedZOrderChangeEvents);
2672 QList<QObject *> list2;
2673 list2 << child1 << child3 << child4 << child2;
2674 QVERIFY(parentPtr->children() == list2);
2676 // Creates a widget on top of all the children and checks that raising one of
2677 // the children underneath doesn't trigger a repaint on the covering widget.
2679 QWidget *parent = parentPtr.take();
2680 parent->setParent(&topLevel);
2682 QVERIFY(QTest::qWaitForWindowExposed(&topLevel));
2685 UpdateWidget *onTop = new UpdateWidget(&topLevel);
2687 onTop->resize(topLevel.size());
2688 onTop->setAutoFillBackground(true);
2691 QTRY_VERIFY(onTop->numPaintEvents > 0);
2694 // Reset all the children.
2695 foreach (UpdateWidget *child, allChildren)
2698 for (int i = 0; i < 5; ++i)
2702 QCOMPARE(onTop->numPaintEvents, 0);
2703 QCOMPARE(onTop->numZOrderChangeEvents, 0);
2705 QList<QObject *> list3;
2706 list3 << child1 << child4 << child2 << child3;
2707 QVERIFY(parent->children() == list3);
2709 foreach (UpdateWidget *child, allChildren) {
2710 int expectedPaintEvents = 0;
2711 int expectedZOrderChangeEvents = child == child3 ? 1 : 0;
2712 QTRY_COMPARE(child->numPaintEvents, expectedPaintEvents);
2713 QCOMPARE(child->numZOrderChangeEvents, expectedZOrderChangeEvents);
2718 // Cocoa has no Z-Order for views, we hack it, but it results in paint events.
2720 void tst_QWidget::lower()
2722 QScopedPointer<QWidget> parent(new QWidget);
2723 parent->setObjectName(QLatin1String("lower"));
2724 parent->setWindowTitle(parent->objectName());
2725 parent->resize(200, 200);
2726 QList<UpdateWidget *> allChildren;
2728 UpdateWidget *child1 = new UpdateWidget(parent.data());
2729 child1->setAutoFillBackground(true);
2730 allChildren.append(child1);
2732 UpdateWidget *child2 = new UpdateWidget(parent.data());
2733 child2->setAutoFillBackground(true);
2734 allChildren.append(child2);
2736 UpdateWidget *child3 = new UpdateWidget(parent.data());
2737 child3->setAutoFillBackground(true);
2738 allChildren.append(child3);
2740 UpdateWidget *child4 = new UpdateWidget(parent.data());
2741 child4->setAutoFillBackground(true);
2742 allChildren.append(child4);
2745 QVERIFY(QTest::qWaitForWindowExposed(parent.data()));
2747 QList<QObject *> list1;
2748 list1 << child1 << child2 << child3 << child4;
2749 QVERIFY(parent->children() == list1);
2750 QCOMPARE(allChildren.count(), list1.count());
2752 foreach (UpdateWidget *child, allChildren) {
2753 int expectedPaintEvents = child == child4 ? 1 : 0;
2754 if (expectedPaintEvents == 0) {
2755 QVERIFY(child->numPaintEvents == 0);
2757 // show() issues multiple paint events on some window managers
2758 QTRY_VERIFY(child->numPaintEvents >= expectedPaintEvents);
2760 QCOMPARE(child->numZOrderChangeEvents, 0);
2764 for (int i = 0; i < 5; ++i)
2769 foreach (UpdateWidget *child, allChildren) {
2770 int expectedPaintEvents = child == child3 ? 1 : 0;
2771 int expectedZOrderChangeEvents = child == child4 ? 1 : 0;
2772 QTRY_COMPARE(child->numZOrderChangeEvents, expectedZOrderChangeEvents);
2773 QTRY_COMPARE(child->numPaintEvents, expectedPaintEvents);
2777 QList<QObject *> list2;
2778 list2 << child4 << child1 << child2 << child3;
2779 QVERIFY(parent->children() == list2);
2783 // Cocoa has no Z-Order for views, we hack it, but it results in paint events.
2785 void tst_QWidget::stackUnder()
2787 QScopedPointer<QWidget> parent(new QWidget);
2788 parent->setObjectName(QLatin1String("stackUnder"));
2789 parent->setWindowTitle(parent->objectName());
2790 parent->resize(200, 200);
2791 QList<UpdateWidget *> allChildren;
2793 UpdateWidget *child1 = new UpdateWidget(parent.data());
2794 child1->setAutoFillBackground(true);
2795 allChildren.append(child1);
2797 UpdateWidget *child2 = new UpdateWidget(parent.data());
2798 child2->setAutoFillBackground(true);
2799 allChildren.append(child2);
2801 UpdateWidget *child3 = new UpdateWidget(parent.data());
2802 child3->setAutoFillBackground(true);
2803 allChildren.append(child3);
2805 UpdateWidget *child4 = new UpdateWidget(parent.data());
2806 child4->setAutoFillBackground(true);
2807 allChildren.append(child4);
2810 QVERIFY(QTest::qWaitForWindowExposed(parent.data()));
2811 QList<QObject *> list1;
2812 list1 << child1 << child2 << child3 << child4;
2813 QVERIFY(parent->children() == list1);
2815 foreach (UpdateWidget *child, allChildren) {
2816 int expectedPaintEvents = child == child4 ? 1 : 0;
2817 #if defined(Q_OS_WIN) || defined(Q_OS_MAC)
2818 if (expectedPaintEvents == 1 && child->numPaintEvents == 2)
2819 QEXPECT_FAIL(0, "Mac and Windows issues double repaints for Z-Order change", Continue);
2821 QTRY_COMPARE(child->numPaintEvents, expectedPaintEvents);
2822 QCOMPARE(child->numZOrderChangeEvents, 0);
2826 for (int i = 0; i < 5; ++i)
2827 child4->stackUnder(child2);
2830 QList<QObject *> list2;
2831 list2 << child1 << child4 << child2 << child3;
2832 QVERIFY(parent->children() == list2);
2834 foreach (UpdateWidget *child, allChildren) {
2835 int expectedPaintEvents = child == child3 ? 1 : 0;
2836 int expectedZOrderChangeEvents = child == child4 ? 1 : 0;
2837 QTRY_COMPARE(child->numPaintEvents, expectedPaintEvents);
2838 QTRY_COMPARE(child->numZOrderChangeEvents, expectedZOrderChangeEvents);
2842 for (int i = 0; i < 5; ++i)
2843 child1->stackUnder(child3);
2846 QList<QObject *> list3;
2847 list3 << child4 << child2 << child1 << child3;
2848 QVERIFY(parent->children() == list3);
2850 foreach (UpdateWidget *child, allChildren) {
2851 int expectedZOrderChangeEvents = child == child1 ? 1 : 0;
2852 if (child == child3) {
2854 qApp->processEvents();
2857 QEXPECT_FAIL(0, "See QTBUG-493", Continue);
2859 QCOMPARE(child->numPaintEvents, 0);
2861 QCOMPARE(child->numPaintEvents, 0);
2863 QTRY_COMPARE(child->numZOrderChangeEvents, expectedZOrderChangeEvents);
2869 void drawPolygon(QPaintDevice *dev, int w, int h)
2872 p.fillRect(0, 0, w, h, Qt::white);
2875 a << QPoint(0, 0) << QPoint(w/2, h/2) << QPoint(w, 0)
2876 << QPoint(w/2, h) << QPoint(0, 0);
2878 p.setPen(QPen(Qt::black, 1));
2879 p.setBrush(Qt::DiagCrossPattern);
2883 class ContentsPropagationWidget : public QWidget
2887 ContentsPropagationWidget(QWidget *parent = 0) : QWidget(parent)
2889 setObjectName(QLatin1String("ContentsPropagationWidget"));
2890 setWindowTitle(objectName());
2891 QWidget *child = this;
2892 for (int i=0; i<32; ++i) {
2893 child = new QWidget(child);
2894 child->setGeometry(i, i, 400 - i*2, 400 - i*2);
2898 void setContentsPropagation(bool enable) {
2899 foreach (QObject *child, children())
2900 qobject_cast<QWidget *>(child)->setAutoFillBackground(!enable);
2904 void paintEvent(QPaintEvent *)
2906 int w = width(), h = height();
2907 drawPolygon(this, w, h);
2910 QSize sizeHint() const { return QSize(500, 500); }
2913 void tst_QWidget::testContentsPropagation()
2915 ContentsPropagationWidget widget;
2916 widget.setFixedSize(500, 500);
2917 widget.setContentsPropagation(false);
2918 QPixmap widgetSnapshot = widget.grab(QRect(QPoint(0, 0), QSize(-1, -1)));
2920 QPixmap correct(500, 500);
2921 drawPolygon(&correct, 500, 500);
2922 //correct.save("correct.png", "PNG");
2924 //widgetSnapshot.save("snap1.png", "PNG");
2925 QVERIFY(widgetSnapshot.toImage() != correct.toImage());
2927 widget.setContentsPropagation(true);
2928 widgetSnapshot = widgetSnapshot = widget.grab(QRect(QPoint(0, 0), QSize(-1, -1)));
2929 //widgetSnapshot.save("snap2.png", "PNG");
2931 QCOMPARE(widgetSnapshot, correct);
2935 Test that saving and restoring window geometry with
2936 saveGeometry() and restoreGeometry() works.
2939 void tst_QWidget::saveRestoreGeometry()
2941 const QPoint position(100, 100);
2942 const QSize size(200, 200);
2944 QByteArray savedGeometry;
2948 widget.move(position);
2949 widget.resize(size);
2951 QVERIFY(QTest::qWaitForWindowExposed(&widget));
2952 QApplication::processEvents();
2954 QTRY_COMPARE(widget.pos(), position);
2955 QCOMPARE(widget.size(), size);
2956 savedGeometry = widget.saveGeometry();
2962 const QByteArray empty;
2963 const QByteArray one("a");
2964 const QByteArray two("ab");
2965 const QByteArray three("abc");
2966 const QByteArray four("abca");
2967 const QByteArray garbage("abcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabc");
2969 QVERIFY(widget.restoreGeometry(empty) == false);
2970 QVERIFY(widget.restoreGeometry(one) == false);
2971 QVERIFY(widget.restoreGeometry(two) == false);
2972 QVERIFY(widget.restoreGeometry(three) == false);
2973 QVERIFY(widget.restoreGeometry(four) == false);
2974 QVERIFY(widget.restoreGeometry(garbage) == false);
2976 QVERIFY(widget.restoreGeometry(savedGeometry));
2978 QVERIFY(QTest::qWaitForWindowExposed(&widget));
2979 QApplication::processEvents();
2981 QTRY_COMPARE(widget.pos(), position);
2982 QCOMPARE(widget.size(), size);
2984 QCOMPARE(widget.pos(), position);
2985 QCOMPARE(widget.size(), size);
2990 widget.move(position);
2991 widget.resize(size);
2993 QVERIFY(QTest::qWaitForWindowExposed(&widget));
2994 QTRY_COMPARE(widget.geometry().size(), size);
2998 //Restore from Full screen
2999 savedGeometry = widget.saveGeometry();
3000 geom = widget.geometry();
3001 widget.setWindowState(widget.windowState() | Qt::WindowFullScreen);
3002 QTRY_VERIFY((widget.windowState() & Qt::WindowFullScreen));
3004 QVERIFY(widget.restoreGeometry(savedGeometry));
3006 QTRY_VERIFY(!(widget.windowState() & Qt::WindowFullScreen));
3007 QTRY_COMPARE(widget.geometry(), geom);
3009 //Restore to full screen
3010 widget.setWindowState(widget.windowState() | Qt::WindowFullScreen);
3012 QTRY_VERIFY((widget.windowState() & Qt::WindowFullScreen));
3014 savedGeometry = widget.saveGeometry();
3015 geom = widget.geometry();
3016 widget.setWindowState(widget.windowState() ^ Qt::WindowFullScreen);
3018 QTRY_VERIFY(!(widget.windowState() & Qt::WindowFullScreen));
3020 QVERIFY(widget.restoreGeometry(savedGeometry));
3022 QTRY_VERIFY((widget.windowState() & Qt::WindowFullScreen));
3023 QTRY_COMPARE(widget.geometry(), geom);
3024 QVERIFY((widget.windowState() & Qt::WindowFullScreen));
3025 widget.setWindowState(widget.windowState() ^ Qt::WindowFullScreen);
3027 QTRY_VERIFY(!(widget.windowState() & Qt::WindowFullScreen));
3030 //Restore from Maximised
3031 widget.move(position);
3032 widget.resize(size);
3034 QTRY_COMPARE(widget.size(), size);
3036 savedGeometry = widget.saveGeometry();
3037 geom = widget.geometry();
3038 widget.setWindowState(widget.windowState() | Qt::WindowMaximized);
3040 QTRY_VERIFY((widget.windowState() & Qt::WindowMaximized));
3041 QTRY_VERIFY(widget.geometry() != geom);
3043 QVERIFY(widget.restoreGeometry(savedGeometry));
3045 QTRY_COMPARE(widget.geometry(), geom);
3047 QVERIFY(!(widget.windowState() & Qt::WindowMaximized));
3049 //Restore to maximised
3050 widget.setWindowState(widget.windowState() | Qt::WindowMaximized);
3052 QTRY_VERIFY((widget.windowState() & Qt::WindowMaximized));
3054 geom = widget.geometry();
3055 savedGeometry = widget.saveGeometry();
3056 widget.setWindowState(widget.windowState() ^ Qt::WindowMaximized);
3058 QTRY_VERIFY(!(widget.windowState() & Qt::WindowMaximized));
3060 QVERIFY(widget.restoreGeometry(savedGeometry));
3062 QTRY_VERIFY((widget.windowState() & Qt::WindowMaximized));
3063 QTRY_COMPARE(widget.geometry(), geom);
3067 void tst_QWidget::restoreVersion1Geometry_data()
3069 QTest::addColumn<QString>("fileName");
3070 QTest::addColumn<uint>("expectedWindowState");
3071 QTest::addColumn<QPoint>("expectedPosition");
3072 QTest::addColumn<QSize>("expectedSize");
3073 QTest::addColumn<QRect>("expectedNormalGeometry");
3074 const QPoint position(100, 100);
3075 const QSize size(200, 200);
3076 const QRect normalGeometry(102, 124, 200, 200);
3078 QTest::newRow("geometry.dat") << ":geometry.dat" << uint(Qt::WindowNoState) << position << size << normalGeometry;
3079 QTest::newRow("geometry-maximized.dat") << ":geometry-maximized.dat" << uint(Qt::WindowMaximized) << position << size << normalGeometry;
3080 QTest::newRow("geometry-fullscreen.dat") << ":geometry-fullscreen.dat" << uint(Qt::WindowFullScreen) << position << size << normalGeometry;
3084 Test that the current version of restoreGeometry() can restore geometry
3085 saved width saveGeometry() version 1.0.
3087 void tst_QWidget::restoreVersion1Geometry()
3089 QFETCH(QString, fileName);
3090 QFETCH(uint, expectedWindowState);
3091 QFETCH(QPoint, expectedPosition);
3092 QFETCH(QSize, expectedSize);
3093 QFETCH(QRect, expectedNormalGeometry);
3095 // WindowActive is uninteresting for this test
3096 const uint WindowStateMask = Qt::WindowFullScreen | Qt::WindowMaximized | Qt::WindowMinimized;
3099 QVERIFY(f.exists());
3100 f.open(QIODevice::ReadOnly);
3101 const QByteArray savedGeometry = f.readAll();
3102 QCOMPARE(savedGeometry.count(), 46);
3107 QVERIFY(widget.restoreGeometry(savedGeometry));
3109 QCOMPARE(uint(widget.windowState() & WindowStateMask), expectedWindowState);
3110 if (expectedWindowState == Qt::WindowNoState) {
3111 QCOMPARE(widget.pos(), expectedPosition);
3112 QCOMPARE(widget.size(), expectedSize);
3115 QVERIFY(QTest::qWaitForWindowExposed(&widget));
3118 if (expectedWindowState == Qt::WindowNoState) {
3119 QTRY_COMPARE(widget.pos(), expectedPosition);
3120 QTRY_COMPARE(widget.size(), expectedSize);
3123 widget.showNormal();
3126 if (m_platform == QStringLiteral("xcb") || m_platform == QStringLiteral("windows"))
3127 QSKIP("QTBUG-26421");
3129 if (expectedWindowState != Qt::WindowNoState) {
3130 // restoring from maximized or fullscreen, we can only restore to the normal geometry
3131 QTRY_COMPARE(widget.geometry(), expectedNormalGeometry);
3133 QTRY_COMPARE(widget.pos(), expectedPosition);
3134 QTRY_COMPARE(widget.size(), expectedSize);
3138 // Code for saving a new geometry*.dat files
3140 QWidget widgetToSave;
3141 widgetToSave.move(expectedPosition);
3142 widgetToSave.resize(expectedSize);
3143 widgetToSave.show();
3144 QVERIFY(QTest::qWaitForWindowExposed(&widget));
3145 QTest::qWait(500); // stabilize
3146 widgetToSave.setWindowState(Qt::WindowStates(expectedWindowState));
3147 QTest::qWait(500); // stabilize
3149 QByteArray geometryToSave = widgetToSave.saveGeometry();
3151 // Code for saving a new geometry.dat file.
3152 f.setFileName(fileName.mid(1));
3153 QVERIFY(f.open(QIODevice::WriteOnly)); // did you forget to 'p4 edit *.dat'? :)
3154 f.write(geometryToSave);
3160 void tst_QWidget::widgetAt()
3164 QScopedPointer<QWidget> w1(new QWidget(0, Qt::X11BypassWindowManagerHint));
3165 w1->setGeometry(0, 0, 160, 150);
3166 w1->setObjectName(QLatin1String("w1"));
3167 w1->setWindowTitle(w1->objectName());
3168 QScopedPointer<QWidget> w2(new QWidget(0, Qt::X11BypassWindowManagerHint | Qt::FramelessWindowHint));
3169 w2->setGeometry(50,50, 160, 100);
3170 w2->setObjectName(QLatin1String("w2"));
3171 w2->setWindowTitle(w2->objectName());
3173 QVERIFY(QTest::qWaitForWindowExposed(w1.data()));
3174 qApp->processEvents();
3176 QTRY_VERIFY((wr = QApplication::widgetAt(100, 100)));
3177 QCOMPARE(wr->objectName(), QString("w1"));
3180 QVERIFY(QTest::qWaitForWindowExposed(w2.data()));
3181 qApp->processEvents();
3182 qApp->processEvents();
3183 qApp->processEvents();
3184 QTRY_VERIFY((wr = QApplication::widgetAt(100, 100)));
3185 QCOMPARE(wr->objectName(), QString("w2"));
3188 qApp->processEvents();
3189 QTRY_VERIFY((wr = QApplication::widgetAt(100, 100)) && wr->objectName() == QString("w1"));
3192 qApp->processEvents();
3193 QTRY_VERIFY((wr = QApplication::widgetAt(100, 100)) && wr->objectName() == QString("w2"));
3195 QWidget *w3 = new QWidget(w2.data());
3196 w3->setGeometry(10,10,50,50);
3197 w3->setObjectName("w3");
3199 qApp->processEvents();
3200 QTRY_VERIFY((wr = QApplication::widgetAt(100,100)) && wr->objectName() == QString("w3"));
3202 w3->setAttribute(Qt::WA_TransparentForMouseEvents);
3203 qApp->processEvents();
3204 QTRY_VERIFY((wr = QApplication::widgetAt(100, 100)) && wr->objectName() == QString("w2"));
3206 QRegion rgn = QRect(QPoint(0,0), w2->size());
3207 QPoint point = w2->mapFromGlobal(QPoint(100,100));
3208 rgn -= QRect(point, QSize(1,1));
3210 qApp->processEvents();
3212 #if defined(Q_OS_WINCE)
3213 QEXPECT_FAIL("", "Windows CE does only support rectangular regions", Continue); //See also task 147191
3215 if (!QGuiApplication::platformName().compare(QLatin1String("cocoa"), Qt::CaseInsensitive))
3216 QEXPECT_FAIL("", "Window mask not implemented on Mac QTBUG-22326", Continue);
3218 QTRY_VERIFY((wr = QApplication::widgetAt(100,100)));
3219 QTRY_COMPARE(wr->objectName(), w1->objectName());
3220 QTRY_VERIFY((wr = QApplication::widgetAt(101,101)));
3221 QTRY_COMPARE(wr->objectName(), w2->objectName());
3223 QBitmap bitmap(w2->size());
3224 QPainter p(&bitmap);
3225 p.fillRect(bitmap.rect(), Qt::color1);
3226 p.setPen(Qt::color0);
3227 p.drawPoint(w2->mapFromGlobal(QPoint(100,100)));
3229 w2->setMask(bitmap);
3230 qApp->processEvents();
3232 #if defined(Q_OS_WINCE)
3233 QEXPECT_FAIL("", "Windows CE does only support rectangular regions", Continue); //See also task 147191
3235 if (!QGuiApplication::platformName().compare(QLatin1String("cocoa"), Qt::CaseInsensitive))
3236 QEXPECT_FAIL("", "Window mask not implemented on Mac QTBUG-22326", Continue);
3237 QTRY_VERIFY(QApplication::widgetAt(100,100) == w1.data());
3238 QTRY_VERIFY(QApplication::widgetAt(101,101) == w2.data());
3241 void tst_QWidget::task110173()
3245 QPushButton *pb1 = new QPushButton("click", &w);
3246 pb1->setFocusPolicy(Qt::ClickFocus);
3247 pb1->move(100, 100);
3249 QPushButton *pb2 = new QPushButton("push", &w);
3250 pb2->setFocusPolicy(Qt::ClickFocus);
3251 pb2->move(300, 300);
3253 QTest::keyClick( &w, Qt::Key_Tab );
3255 QVERIFY(QTest::qWaitForWindowExposed(&w));
3259 class Widget : public QWidget
3262 Widget() : deleteThis(false) { setFocusPolicy(Qt::StrongFocus); }
3263 void actionEvent(QActionEvent *) { if (deleteThis) delete this; }
3264 void changeEvent(QEvent *) { if (deleteThis) delete this; }
3265 void closeEvent(QCloseEvent *) { if (deleteThis) delete this; }
3266 void hideEvent(QHideEvent *) { if (deleteThis) delete this; }
3267 void focusOutEvent(QFocusEvent *) { if (deleteThis) delete this; }
3268 void keyPressEvent(QKeyEvent *) { if (deleteThis) delete this; }
3269 void keyReleaseEvent(QKeyEvent *) { if (deleteThis) delete this; }
3270 void mouseDoubleClickEvent(QMouseEvent *) { if (deleteThis) delete this; }
3271 void mousePressEvent(QMouseEvent *) { if (deleteThis) delete this; }
3272 void mouseReleaseEvent(QMouseEvent *) { if (deleteThis) delete this; }
3273 void mouseMoveEvent(QMouseEvent *) { if (deleteThis) delete this; }
3278 void tst_QWidget::testDeletionInEventHandlers()
3281 QPointer<Widget> w = new Widget;
3282 w->deleteThis = true;
3287 // focusOut (crashes)
3291 //QVERIFY(qApp->focusWidget() == w);
3292 //w->deleteThis = true;
3299 w->deleteThis = true;
3300 QTest::keyPress(w, Qt::Key_A);
3307 w->deleteThis = true;
3308 QTest::keyRelease(w, Qt::Key_A);
3315 w->deleteThis = true;
3316 QTest::mousePress(w, Qt::LeftButton);
3323 w->deleteThis = true;
3324 QTest::mouseRelease(w, Qt::LeftButton);
3328 // mouse double click
3331 w->deleteThis = true;
3332 QTest::mouseDClick(w, Qt::LeftButton);
3336 // hide event (crashes)
3339 //w->deleteThis = true;
3345 w->deleteThis = true;
3346 w->addAction(new QAction(w));
3353 w->deleteThis = true;
3354 w->setMouseTracking(true);
3359 w->setMouseTracking(true);
3361 w->deleteThis = true;
3362 QMouseEvent me(QEvent::MouseMove, QPoint(0, 0), Qt::NoButton, Qt::NoButton, Qt::NoModifier);
3363 QApplication::sendEvent(w, &me);
3369 void tst_QWidget::sheetOpacity()
3372 QWidget sheet(&tmpWindow, Qt::Sheet);
3375 QCOMPARE(int(sheet.windowOpacity() * 255), 242); // 95%
3376 sheet.setParent(0, Qt::Dialog);
3377 QCOMPARE(int(sheet.windowOpacity() * 255), 255);
3380 class MaskedPainter : public QWidget
3386 : mask(20, 20, 50, 50)
3391 void paintEvent(QPaintEvent *)
3394 p.fillRect(mask, QColor(Qt::red));
3399 Verifies that the entire area inside the mask is painted red.
3401 bool verifyWidgetMask(QWidget *widget, QRect mask)
3403 const QImage image = widget->grab(QRect(QPoint(0, 0), widget->size())).toImage();
3405 const QImage masked = image.copy(mask);
3407 red.fill(QColor(Qt::red).rgb());
3409 return (masked == red);
3412 void tst_QWidget::setMask()
3414 testWidget->hide(); // get this out of the way.
3421 QVERIFY(verifyWidgetMask(&w, w.mask));
3426 w.setWindowFlags(w.windowFlags() | Qt::FramelessWindowHint);
3429 QRect mask = w.mask;
3431 QVERIFY(verifyWidgetMask(&w, mask));
3436 class StaticWidget : public QWidget
3442 QRegion paintedRegion;
3444 StaticWidget(QWidget *parent = 0)
3447 setAttribute(Qt::WA_StaticContents);
3448 setAttribute(Qt::WA_OpaquePaintEvent);
3449 setPalette(Qt::red); // Make sure we have an opaque palette.
3450 setAutoFillBackground(true);
3451 gotPaintEvent = false;
3454 void paintEvent(QPaintEvent *e)
3456 paintedRegion += e->region();
3457 gotPaintEvent = true;
3458 // qDebug() << "paint" << e->region();
3459 // Look for a full update, set partial to false if found.
3460 foreach(QRect r, e->region().rects()) {
3461 partial = (r != rect());
3462 if (partial == false)
3469 Test that widget resizes and moves can be done with minimal repaints when WA_StaticContents
3470 and WA_OpaquePaintEvent is set. Test is mac-only for now.
3472 void tst_QWidget::optimizedResizeMove()
3475 parent.resize(400, 400);
3477 StaticWidget staticWidget(&parent);
3478 staticWidget.gotPaintEvent = false;
3479 staticWidget.move(150, 150);
3480 staticWidget.resize(150, 150);
3482 QVERIFY(QTest::qWaitForWindowExposed(&parent));
3484 QTRY_COMPARE(staticWidget.gotPaintEvent, true);
3486 staticWidget.gotPaintEvent = false;
3487 staticWidget.move(staticWidget.pos() + QPoint(10, 10));
3489 QCOMPARE(staticWidget.gotPaintEvent, false);
3491 staticWidget.gotPaintEvent = false;
3492 staticWidget.move(staticWidget.pos() + QPoint(-10, -10));
3494 QCOMPARE(staticWidget.gotPaintEvent, false);
3496 staticWidget.gotPaintEvent = false;
3497 staticWidget.move(staticWidget.pos() + QPoint(-10, 10));
3499 QCOMPARE(staticWidget.gotPaintEvent, false);
3501 staticWidget.gotPaintEvent = false;
3502 staticWidget.resize(staticWidget.size() + QSize(10, 10));
3504 QCOMPARE(staticWidget.gotPaintEvent, true);
3505 QCOMPARE(staticWidget.partial, true);
3507 staticWidget.gotPaintEvent = false;
3508 staticWidget.resize(staticWidget.size() + QSize(-10, -10));
3510 QCOMPARE(staticWidget.gotPaintEvent, false);
3512 staticWidget.gotPaintEvent = false;
3513 staticWidget.resize(staticWidget.size() + QSize(10, -10));
3515 QCOMPARE(staticWidget.gotPaintEvent, true);
3516 QCOMPARE(staticWidget.partial, true);
3518 staticWidget.gotPaintEvent = false;
3519 staticWidget.move(staticWidget.pos() + QPoint(10, 10));
3520 staticWidget.resize(staticWidget.size() + QSize(-10, -10));
3522 QCOMPARE(staticWidget.gotPaintEvent, false);
3524 staticWidget.gotPaintEvent = false;
3525 staticWidget.move(staticWidget.pos() + QPoint(10, 10));
3526 staticWidget.resize(staticWidget.size() + QSize(10, 10));
3528 QCOMPARE(staticWidget.gotPaintEvent, true);
3529 QCOMPARE(staticWidget.partial, true);
3531 staticWidget.gotPaintEvent = false;
3532 staticWidget.move(staticWidget.pos() + QPoint(-10, -10));
3533 staticWidget.resize(staticWidget.size() + QSize(-10, -10));
3535 QCOMPARE(staticWidget.gotPaintEvent, false);
3537 staticWidget.setAttribute(Qt::WA_StaticContents, false);
3538 staticWidget.gotPaintEvent = false;
3539 staticWidget.move(staticWidget.pos() + QPoint(-10, -10));
3540 staticWidget.resize(staticWidget.size() + QSize(-10, -10));
3542 QCOMPARE(staticWidget.gotPaintEvent, true);
3543 QCOMPARE(staticWidget.partial, false);
3544 staticWidget.setAttribute(Qt::WA_StaticContents, true);
3546 staticWidget.setAttribute(Qt::WA_StaticContents, false);
3547 staticWidget.gotPaintEvent = false;
3548 staticWidget.move(staticWidget.pos() + QPoint(10, 10));
3550 QCOMPARE(staticWidget.gotPaintEvent, false);
3551 staticWidget.setAttribute(Qt::WA_StaticContents, true);
3554 void tst_QWidget::optimizedResize_topLevel()
3556 QSKIP("We do not yet have static contents support, see QTBUG-28012");
3558 StaticWidget topLevel;
3559 topLevel.gotPaintEvent = false;
3561 QVERIFY(QTest::qWaitForWindowExposed(&topLevel));
3563 QTRY_COMPARE(topLevel.gotPaintEvent, true);
3565 topLevel.gotPaintEvent = false;
3566 topLevel.partial = false;
3567 topLevel.paintedRegion = QRegion();
3570 topLevel.resize(topLevel.size() + QSize(10, 10));
3572 // Static contents does not work when programmatically resizing
3573 // top-levels with QWidget::resize. We do some funky stuff in
3574 // setGeometry_sys. However, resizing it with the mouse or with
3575 // a native function call works (it basically has to go through
3576 // WM_RESIZE in QApplication). This is a corner case, though.
3578 const QRect frame = topLevel.frameGeometry();
3579 MoveWindow(winHandleOf(&topLevel), frame.x(), frame.y(),
3580 frame.width() + 10, frame.height() + 10,
3586 // Expected update region: New rect - old rect.
3587 QRegion expectedUpdateRegion(topLevel.rect());
3588 expectedUpdateRegion -= QRect(QPoint(), topLevel.size() - QSize(10, 10));
3590 QTRY_COMPARE(topLevel.gotPaintEvent, true);
3591 if (m_platform == QStringLiteral("xcb"))
3592 QSKIP("QTBUG-26424");
3593 QCOMPARE(topLevel.partial, true);
3594 QCOMPARE(topLevel.paintedRegion, expectedUpdateRegion);
3597 class SiblingDeleter : public QWidget
3600 inline SiblingDeleter(QWidget *sibling, QWidget *parent)
3601 : QWidget(parent), sibling(sibling) {}
3602 inline virtual ~SiblingDeleter() { delete sibling; }
3605 QPointer<QWidget> sibling;
3609 void tst_QWidget::childDeletesItsSibling()
3611 QWidget *commonParent = new QWidget(0);
3612 QPointer<QWidget> child = new QWidget(0);
3613 QPointer<QWidget> siblingDeleter = new SiblingDeleter(child, commonParent);
3614 child->setParent(commonParent);
3615 delete commonParent; // don't crash
3617 QVERIFY(!siblingDeleter);
3621 void tst_QWidget::setMinimumSize()
3624 QSize defaultSize = w.size();
3626 w.setMinimumSize(defaultSize + QSize(100, 100));
3627 QCOMPARE(w.size(), defaultSize + QSize(100, 100));
3628 QVERIFY(!w.testAttribute(Qt::WA_Resized));
3630 w.setMinimumSize(defaultSize + QSize(50, 50));
3631 QCOMPARE(w.size(), defaultSize + QSize(100, 100));
3632 QVERIFY(!w.testAttribute(Qt::WA_Resized));
3634 w.setMinimumSize(defaultSize + QSize(200, 200));
3635 QCOMPARE(w.size(), defaultSize + QSize(200, 200));
3636 QVERIFY(!w.testAttribute(Qt::WA_Resized));
3638 // Setting a minimum size larger than the desktop does not work on WinCE,
3639 // so skip this part of the test.
3641 QSize nonDefaultSize = defaultSize + QSize(5,5);
3642 w.setMinimumSize(nonDefaultSize);
3645 QVERIFY(w.height() >= nonDefaultSize.height());
3646 QVERIFY(w.width() >= nonDefaultSize.width());
3650 void tst_QWidget::setMaximumSize()
3653 QSize defaultSize = w.size();
3655 w.setMinimumSize(defaultSize + QSize(100, 100));
3656 QCOMPARE(w.size(), defaultSize + QSize(100, 100));
3657 QVERIFY(!w.testAttribute(Qt::WA_Resized));
3658 w.setMinimumSize(defaultSize);
3660 w.setMaximumSize(defaultSize + QSize(200, 200));
3661 QCOMPARE(w.size(), defaultSize + QSize(100, 100));
3662 QVERIFY(!w.testAttribute(Qt::WA_Resized));
3664 w.setMaximumSize(defaultSize + QSize(50, 50));
3665 QCOMPARE(w.size(), defaultSize + QSize(50, 50));
3666 QVERIFY(!w.testAttribute(Qt::WA_Resized));
3669 void tst_QWidget::setFixedSize()
3672 QSize defaultSize = w.size();
3674 w.setFixedSize(defaultSize + QSize(100, 100));
3675 QCOMPARE(w.size(), defaultSize + QSize(100, 100));
3676 QVERIFY(w.testAttribute(Qt::WA_Resized));
3678 w.setFixedSize(defaultSize + QSize(200, 200));
3680 QCOMPARE(w.minimumSize(), defaultSize + QSize(200,200));
3681 QCOMPARE(w.maximumSize(), defaultSize + QSize(200,200));
3682 QCOMPARE(w.size(), defaultSize + QSize(200, 200));
3683 QVERIFY(w.testAttribute(Qt::WA_Resized));
3685 w.setFixedSize(defaultSize + QSize(50, 50));
3686 QCOMPARE(w.size(), defaultSize + QSize(50, 50));
3687 QVERIFY(w.testAttribute(Qt::WA_Resized));
3689 w.setAttribute(Qt::WA_Resized, false);
3690 w.setFixedSize(defaultSize + QSize(50, 50));
3691 QVERIFY(!w.testAttribute(Qt::WA_Resized));
3693 w.setFixedSize(defaultSize + QSize(150, 150));
3696 if (m_platform == QStringLiteral("xcb"))
3697 QSKIP("QTBUG-26424");
3698 QVERIFY(w.size() == defaultSize + QSize(150,150));
3701 void tst_QWidget::ensureCreated()
3705 WId widgetWinId = widget.winId();
3706 Q_UNUSED(widgetWinId);
3707 QVERIFY(widget.testAttribute(Qt::WA_WState_Created));
3713 QDialog dialog(&window);
3714 dialog.setWindowModality(Qt::NonModal);
3716 WId dialogWinId = dialog.winId();
3717 Q_UNUSED(dialogWinId);
3718 QVERIFY(dialog.testAttribute(Qt::WA_WState_Created));
3719 QVERIFY(window.testAttribute(Qt::WA_WState_Created));
3725 QDialog dialog(&window);
3726 dialog.setWindowModality(Qt::WindowModal);
3728 WId dialogWinId = dialog.winId();
3729 Q_UNUSED(dialogWinId);
3730 QVERIFY(dialog.testAttribute(Qt::WA_WState_Created));
3731 QVERIFY(window.testAttribute(Qt::WA_WState_Created));
3737 QDialog dialog(&window);
3738 dialog.setWindowModality(Qt::ApplicationModal);
3740 WId dialogWinId = dialog.winId();
3741 Q_UNUSED(dialogWinId);
3742 QVERIFY(dialog.testAttribute(Qt::WA_WState_Created));
3743 QVERIFY(window.testAttribute(Qt::WA_WState_Created));
3747 class WinIdChangeWidget : public QWidget {
3749 WinIdChangeWidget(QWidget *p = 0)
3755 bool event(QEvent *e)
3757 if (e->type() == QEvent::WinIdChange) {
3758 m_winIdList.append(internalWinId());
3761 return QWidget::event(e);
3764 QList<WId> m_winIdList;
3765 int winIdChangeEventCount() const { return m_winIdList.count(); }
3768 void tst_QWidget::winIdChangeEvent()
3771 // Transforming an alien widget into a native widget
3772 WinIdChangeWidget widget;
3773 const WId winIdBefore = widget.internalWinId();
3774 const WId winIdAfter = widget.winId();
3775 QVERIFY(winIdBefore != winIdAfter);
3776 QCOMPARE(widget.winIdChangeEventCount(), 1);
3780 // Changing parent of a native widget
3781 QWidget parent1, parent2;
3782 WinIdChangeWidget child(&parent1);
3783 const WId winIdBefore = child.winId();
3784 QCOMPARE(child.winIdChangeEventCount(), 1);
3785 child.setParent(&parent2);
3786 const WId winIdAfter = child.internalWinId();
3787 QCOMPARE(winIdBefore, winIdAfter);
3788 QCOMPARE(child.winIdChangeEventCount(), 3);
3789 // winId is set to zero during reparenting
3790 QVERIFY(0 == child.m_winIdList[1]);
3794 // Changing grandparent of a native widget
3795 QWidget grandparent1, grandparent2;
3796 QWidget parent(&grandparent1);
3797 WinIdChangeWidget child(&parent);
3798 const WId winIdBefore = child.winId();
3799 QCOMPARE(child.winIdChangeEventCount(), 1);
3800 parent.setParent(&grandparent2);
3801 const WId winIdAfter = child.internalWinId();
3802 QCOMPARE(winIdBefore, winIdAfter);
3803 QCOMPARE(child.winIdChangeEventCount(), 1);
3807 // Changing parent of an alien widget
3808 QWidget parent1, parent2;
3809 WinIdChangeWidget child(&parent1);
3810 const WId winIdBefore = child.internalWinId();
3811 child.setParent(&parent2);
3812 const WId winIdAfter = child.internalWinId();
3813 QCOMPARE(winIdBefore, winIdAfter);
3814 QCOMPARE(child.winIdChangeEventCount(), 0);
3818 // Making native child widget into a top-level window
3820 WinIdChangeWidget child(&parent);
3822 const WId winIdBefore = child.internalWinId();
3823 QCOMPARE(child.winIdChangeEventCount(), 1);
3824 const Qt::WindowFlags flags = child.windowFlags();
3825 child.setWindowFlags(flags | Qt::Window);
3826 const WId winIdAfter = child.internalWinId();
3827 QCOMPARE(winIdBefore, winIdAfter);
3828 QCOMPARE(child.winIdChangeEventCount(), 3);
3829 // winId is set to zero during reparenting
3830 QVERIFY(0 == child.m_winIdList[1]);
3834 void tst_QWidget::persistentWinId()
3836 QScopedPointer<QWidget> parent(new QWidget);
3837 QWidget *w1 = new QWidget;
3838 QWidget *w2 = new QWidget;
3839 QWidget *w3 = new QWidget;
3840 w1->setParent(parent.data());
3844 WId winId1 = w1->winId();
3845 WId winId2 = w2->winId();
3846 WId winId3 = w3->winId();
3848 // reparenting should preserve the winId of the widget being reparented and of its children
3850 QCOMPARE(w1->winId(), winId1);
3851 QCOMPARE(w2->winId(), winId2);
3852 QCOMPARE(w3->winId(), winId3);
3854 w1->setParent(parent.data());
3855 QCOMPARE(w1->winId(), winId1);
3856 QCOMPARE(w2->winId(), winId2);
3857 QCOMPARE(w3->winId(), winId3);
3860 QCOMPARE(w2->winId(), winId2);
3861 QCOMPARE(w3->winId(), winId3);
3863 w2->setParent(parent.data());
3864 QCOMPARE(w2->winId(), winId2);
3865 QCOMPARE(w3->winId(), winId3);
3868 QCOMPARE(w2->winId(), winId2);
3869 QCOMPARE(w3->winId(), winId3);
3872 QCOMPARE(w3->winId(), winId3);
3875 QCOMPARE(w3->winId(), winId3);
3878 QCOMPARE(w3->winId(), winId3);
3881 void tst_QWidget::showNativeChild()
3884 topLevel.setGeometry(0, 0, 160, 160);
3885 QWidget child(&topLevel);
3888 QVERIFY(QTest::qWaitForWindowExposed(&topLevel));
3891 class ShowHideEventWidget : public QWidget
3894 int numberOfShowEvents, numberOfHideEvents;
3896 ShowHideEventWidget(QWidget *parent = 0)
3897 : QWidget(parent), numberOfShowEvents(0), numberOfHideEvents(0)
3901 { QWidget::create(); }
3903 void showEvent(QShowEvent *)
3904 { ++numberOfShowEvents; }
3906 void hideEvent(QHideEvent *)
3907 { ++numberOfHideEvents; }
3910 void tst_QWidget::showHideEvent_data()
3912 QTest::addColumn<bool>("show");
3913 QTest::addColumn<bool>("hide");
3914 QTest::addColumn<bool>("create");
3915 QTest::addColumn<int>("expectedShowEvents");
3916 QTest::addColumn<int>("expectedHideEvents");
3918 QTest::newRow("window: only show")
3924 QTest::newRow("window: show/hide")
3930 QTest::newRow("window: show/hide/create")
3936 QTest::newRow("window: hide/create")
3942 QTest::newRow("window: only hide")
3948 QTest::newRow("window: nothing")
3956 void tst_QWidget::showHideEvent()
3960 QFETCH(bool, create);
3961 QFETCH(int, expectedShowEvents);
3962 QFETCH(int, expectedHideEvents);
3964 ShowHideEventWidget widget;
3969 if (create && !widget.testAttribute(Qt::WA_WState_Created))
3972 QCOMPARE(widget.numberOfShowEvents, expectedShowEvents);
3973 QCOMPARE(widget.numberOfHideEvents, expectedHideEvents);
3976 void tst_QWidget::update()
3978 QTest::qWait(10); // Wait for the initStuff to do it's stuff.
3982 w.setGeometry(50, 50, 100, 100);
3984 QVERIFY(QTest::qWaitForWindowExposed(&w));
3986 QApplication::processEvents();
3987 QApplication::processEvents();
3990 QEXPECT_FAIL(0, "Cocoa compositor says to paint this twice.", Continue);
3992 QTRY_COMPARE(w.numPaintEvents, 1);
3994 QCOMPARE(w.visibleRegion(), QRegion(w.rect()));
3995 QCOMPARE(w.paintedRegion, w.visibleRegion());
3998 UpdateWidget child(&w);
3999 child.setGeometry(10, 10, 80, 80);
4002 QPoint childOffset = child.mapToParent(QPoint());
4004 // widgets are transparent by default, so both should get repaints
4006 QApplication::processEvents();
4007 QApplication::processEvents();
4008 QCOMPARE(child.numPaintEvents, 1);
4009 QCOMPARE(child.visibleRegion(), QRegion(child.rect()));
4010 QCOMPARE(child.paintedRegion, child.visibleRegion());
4011 QCOMPARE(w.numPaintEvents, 1);
4012 QCOMPARE(w.visibleRegion(), QRegion(w.rect()));
4013 QCOMPARE(w.paintedRegion, child.visibleRegion().translated(childOffset));
4019 QApplication::processEvents();
4020 QApplication::processEvents();
4021 QCOMPARE(child.numPaintEvents, 1);
4022 QCOMPARE(child.visibleRegion(), QRegion(child.rect()));
4023 QCOMPARE(child.paintedRegion, child.visibleRegion());
4024 QCOMPARE(w.numPaintEvents, 1);
4025 QCOMPARE(w.visibleRegion(), QRegion(w.rect()));
4026 QCOMPARE(w.paintedRegion, w.visibleRegion());
4029 QPalette opaquePalette = child.palette();
4030 opaquePalette.setColor(child.backgroundRole(), QColor(Qt::red));
4032 // setting an opaque background on the child should prevent paint-events
4033 // for the parent in the child area
4035 child.setPalette(opaquePalette);
4036 child.setAutoFillBackground(true);
4037 QApplication::processEvents();
4043 QApplication::processEvents();
4044 QApplication::processEvents();
4046 QCOMPARE(w.numPaintEvents, 1);
4047 QRegion expectedVisible = QRegion(w.rect())
4048 - child.visibleRegion().translated(childOffset);
4049 QCOMPARE(w.visibleRegion(), expectedVisible);
4050 QCOMPARE(w.paintedRegion, expectedVisible);
4051 QCOMPARE(child.numPaintEvents, 0);
4057 QApplication::processEvents();
4058 QApplication::processEvents();
4060 QCOMPARE(w.numPaintEvents, 0);
4061 QCOMPARE(child.numPaintEvents, 1);
4062 QCOMPARE(child.paintedRegion, child.visibleRegion());
4068 // overlapping sibling
4069 UpdateWidget sibling(&w);
4070 child.setGeometry(10, 10, 20, 20);
4071 sibling.setGeometry(15, 15, 20, 20);
4074 QApplication::processEvents();
4079 const QPoint siblingOffset = sibling.mapToParent(QPoint());
4082 QApplication::processEvents();
4083 QApplication::processEvents();
4085 // child is opaque, sibling transparent
4087 QCOMPARE(sibling.numPaintEvents, 1);
4088 QCOMPARE(sibling.paintedRegion, sibling.visibleRegion());
4090 QCOMPARE(child.numPaintEvents, 1);
4091 QCOMPARE(child.paintedRegion.translated(childOffset),
4092 child.visibleRegion().translated(childOffset)
4093 & sibling.visibleRegion().translated(siblingOffset));
4095 QCOMPARE(w.numPaintEvents, 1);
4096 QCOMPARE(w.paintedRegion,
4097 w.visibleRegion() & sibling.visibleRegion().translated(siblingOffset));
4098 QCOMPARE(w.paintedRegion,
4099 (w.visibleRegion() - child.visibleRegion().translated(childOffset))
4100 & sibling.visibleRegion().translated(siblingOffset));
4107 sibling.setPalette(opaquePalette);
4108 sibling.setAutoFillBackground(true);
4111 QApplication::processEvents();
4112 QApplication::processEvents();
4114 // child opaque, sibling opaque
4116 QCOMPARE(sibling.numPaintEvents, 1);
4117 QCOMPARE(sibling.paintedRegion, sibling.visibleRegion());
4120 if (child.internalWinId()) // child is native
4121 QEXPECT_FAIL(0, "Cocoa compositor paints child and sibling", Continue);
4123 QCOMPARE(child.numPaintEvents, 0);
4124 QCOMPARE(child.visibleRegion(),
4125 QRegion(child.rect())
4126 - sibling.visibleRegion().translated(siblingOffset - childOffset));
4128 QCOMPARE(w.numPaintEvents, 0);
4129 QCOMPARE(w.visibleRegion(),
4131 - child.visibleRegion().translated(childOffset)
4132 - sibling.visibleRegion().translated(siblingOffset));
4136 static inline bool isOpaque(QWidget *widget)
4140 return qt_widget_private(widget)->isOpaque;
4143 void tst_QWidget::isOpaque()
4147 QVERIFY(::isOpaque(&w));
4150 QVERIFY(!::isOpaque(&child));
4152 child.setAutoFillBackground(true);
4153 QVERIFY(::isOpaque(&child));
4159 palette = child.palette();
4160 palette.setColor(child.backgroundRole(), QColor(255, 0, 0, 127));
4161 child.setPalette(palette);
4162 QVERIFY(!::isOpaque(&child));
4164 palette.setColor(child.backgroundRole(), QColor(255, 0, 0, 255));
4165 child.setPalette(palette);
4166 QVERIFY(::isOpaque(&child));
4168 palette.setColor(QPalette::Window, QColor(0, 0, 255, 127));
4169 w.setPalette(palette);
4171 QVERIFY(!::isOpaque(&w));
4173 child.setAutoFillBackground(false);
4174 QVERIFY(!::isOpaque(&child));
4176 // Qt::WA_OpaquePaintEvent
4178 child.setAttribute(Qt::WA_OpaquePaintEvent);
4179 QVERIFY(::isOpaque(&child));
4181 child.setAttribute(Qt::WA_OpaquePaintEvent, false);
4182 QVERIFY(!::isOpaque(&child));
4184 // Qt::WA_NoSystemBackground
4186 child.setAttribute(Qt::WA_NoSystemBackground);
4187 QVERIFY(!::isOpaque(&child));
4189 child.setAttribute(Qt::WA_NoSystemBackground, false);
4190 QVERIFY(!::isOpaque(&child));
4192 palette.setColor(QPalette::Window, QColor(0, 0, 255, 255));
4193 w.setPalette(palette);
4194 QVERIFY(::isOpaque(&w));
4196 w.setAttribute(Qt::WA_NoSystemBackground);
4197 QVERIFY(!::isOpaque(&w));
4199 w.setAttribute(Qt::WA_NoSystemBackground, false);
4200 QVERIFY(::isOpaque(&w));
4203 QPalette palette = QApplication::palette();
4204 QPalette old = palette;
4205 palette.setColor(QPalette::Window, Qt::transparent);
4206 QApplication::setPalette(palette);
4209 QVERIFY(!::isOpaque(&widget));
4211 QApplication::setPalette(old);
4212 QCOMPARE(::isOpaque(&widget), old.color(QPalette::Window).alpha() == 255);
4219 Test that scrolling of a widget invalidates the correct regions
4221 void tst_QWidget::scroll()
4223 UpdateWidget updateWidget;
4224 updateWidget.resize(500, 500);
4225 updateWidget.reset();
4226 updateWidget.show();
4227 qApp->setActiveWindow(&updateWidget);
4228 QVERIFY(QTest::qWaitForWindowActive(&updateWidget));
4229 QVERIFY(updateWidget.numPaintEvents > 0);
4232 updateWidget.reset();
4233 updateWidget.scroll(10, 10);
4234 qApp->processEvents();
4235 QRegion dirty(QRect(0, 0, 500, 10));
4236 dirty += QRegion(QRect(0, 10, 10, 490));
4237 QCOMPARE(updateWidget.paintedRegion, dirty);
4241 updateWidget.reset();
4242 updateWidget.update(0, 0, 10, 10);
4243 updateWidget.scroll(0, 10);
4244 qApp->processEvents();
4245 QRegion dirty(QRect(0, 0, 500, 10));
4246 dirty += QRegion(QRect(0, 10, 10, 10));
4247 QCOMPARE(updateWidget.paintedRegion, dirty);
4251 updateWidget.reset();
4252 updateWidget.update(0, 0, 100, 100);
4253 updateWidget.scroll(10, 10, QRect(50, 50, 100, 100));
4254 qApp->processEvents();
4255 QRegion dirty(QRect(0, 0, 100, 50));
4256 dirty += QRegion(QRect(0, 50, 150, 10));
4257 dirty += QRegion(QRect(0, 60, 110, 40));
4258 dirty += QRegion(QRect(50, 100, 60, 10));
4259 dirty += QRegion(QRect(50, 110, 10, 40));
4260 QCOMPARE(updateWidget.paintedRegion, dirty);
4264 updateWidget.reset();
4265 updateWidget.update(0, 0, 100, 100);
4266 updateWidget.scroll(10, 10, QRect(100, 100, 100, 100));
4267 qApp->processEvents();
4268 QRegion dirty(QRect(0, 0, 100, 100));
4269 dirty += QRegion(QRect(100, 100, 100, 10));
4270 dirty += QRegion(QRect(100, 110, 10, 90));
4271 QCOMPARE(updateWidget.paintedRegion, dirty);
4276 class DestroyedSlotChecker : public QObject
4283 DestroyedSlotChecker()
4289 void destroyedSlot(QObject *object)
4291 wasQWidget = (qobject_cast<QWidget *>(object) != 0 || object->isWidgetType());
4296 Test that qobject_cast<QWidget*> returns 0 in a slot
4297 connected to QObject::destroyed.
4299 void tst_QWidget::qobject_castInDestroyedSlot()
4301 DestroyedSlotChecker checker;
4303 QWidget *widget = new QWidget();
4305 QObject::connect(widget, SIGNAL(destroyed(QObject*)), &checker, SLOT(destroyedSlot(QObject*)));
4308 QVERIFY(checker.wasQWidget == true);
4311 Q_DECLARE_METATYPE(QList<QRect>)
4313 // Since X11 WindowManager operations are all async, and we have no way to know if the window
4314 // manager has finished playing with the window geometry, this test can't be reliable on X11.
4316 void tst_QWidget::setWindowGeometry_data()
4318 QTest::addColumn<QList<QRect> >("rects");
4319 QTest::addColumn<int>("windowFlags");
4321 QList<QList<QRect> > rects;
4322 rects << (QList<QRect>()
4323 << QRect(100, 100, 200, 200)
4324 << QApplication::desktop()->availableGeometry().adjusted(100, 100, -100, -100)
4325 << QRect(130, 100, 0, 200)
4326 << QRect(100, 50, 200, 0)
4327 << QRect(130, 50, 0, 0))
4329 << QApplication::desktop()->availableGeometry().adjusted(100, 100, -100, -100)
4330 << QRect(130, 100, 0, 200)
4331 << QRect(100, 50, 200, 0)
4332 << QRect(130, 50, 0, 0)
4333 << QRect(100, 100, 200, 200))
4335 << QRect(130, 100, 0, 200)
4336 << QRect(100, 50, 200, 0)
4337 << QRect(130, 50, 0, 0)
4338 << QRect(100, 100, 200, 200)
4339 << QApplication::desktop()->availableGeometry().adjusted(100, 100, -100, -100))
4341 << QRect(100, 50, 200, 0)
4342 << QRect(130, 50, 0, 0)
4343 << QRect(100, 100, 200, 200)
4344 << QApplication::desktop()->availableGeometry().adjusted(100, 100, -100, -100)
4345 << QRect(130, 100, 0, 200))
4347 << QRect(130, 50, 0, 0)
4348 << QRect(100, 100, 200, 200)
4349 << QApplication::desktop()->availableGeometry().adjusted(100, 100, -100, -100)
4350 << QRect(130, 100, 0, 200)
4351 << QRect(100, 50, 200, 0));
4353 QList<int> windowFlags;
4354 windowFlags << 0 << Qt::FramelessWindowHint;
4356 foreach (QList<QRect> l, rects) {
4357 QRect rect = l.first();
4358 foreach (int windowFlag, windowFlags) {
4359 QTest::newRow(QString("%1,%2 %3x%4, flags %5")
4364 .arg(windowFlag, 0, 16).toLatin1())
4371 void tst_QWidget::setWindowGeometry()
4373 if (m_platform == QStringLiteral("xcb"))
4374 QSKIP("X11: Skip this test due to Window manager positioning issues.");
4376 QFETCH(QList<QRect>, rects);
4377 QFETCH(int, windowFlags);
4378 QRect rect = rects.takeFirst();
4381 // test setGeometry() without actually showing the window
4383 if (windowFlags != 0)
4384 widget.setWindowFlags(Qt::WindowFlags(windowFlags));
4386 widget.setGeometry(rect);
4388 QCOMPARE(widget.geometry(), rect);
4390 // setGeometry() without showing
4391 foreach (QRect r, rects) {
4392 widget.setGeometry(r);
4394 QCOMPARE(widget.geometry(), r);
4399 // setGeometry() first, then show()
4401 if (windowFlags != 0)
4402 widget.setWindowFlags(Qt::WindowFlags(windowFlags));
4404 widget.setGeometry(rect);
4406 QVERIFY(QTest::qWaitForWindowExposed(&widget));
4407 if (m_platform == QStringLiteral("windows")) {
4408 QEXPECT_FAIL("130,100 0x200, flags 0", "QTBUG-26424", Continue);
4409 QEXPECT_FAIL("130,50 0x0, flags 0", "QTBUG-26424", Continue);
4411 QTRY_COMPARE(widget.geometry(), rect);
4413 // setGeometry() while shown
4414 foreach (QRect r, rects) {
4415 widget.setGeometry(r);
4417 QTRY_COMPARE(widget.geometry(), r);
4419 widget.setGeometry(rect);
4421 QTRY_COMPARE(widget.geometry(), rect);
4426 QTRY_COMPARE(widget.geometry(), rect);
4428 // setGeometry() after hide()
4429 foreach (QRect r, rects) {
4430 widget.setGeometry(r);
4432 QTRY_COMPARE(widget.geometry(), r);
4434 widget.setGeometry(rect);
4436 QTRY_COMPARE(widget.geometry(), rect);
4438 // show() again, geometry() should still be the same
4440 QVERIFY(QTest::qWaitForWindowExposed(&widget));
4441 QTRY_COMPARE(widget.geometry(), rect);
4443 // final hide(), again geometry() should be unchanged
4446 QTRY_COMPARE(widget.geometry(), rect);
4450 // show() first, then setGeometry()
4452 if (windowFlags != 0)
4453 widget.setWindowFlags(Qt::WindowFlags(windowFlags));
4456 QVERIFY(QTest::qWaitForWindowExposed(&widget));
4457 widget.setGeometry(rect);
4459 QTRY_COMPARE(widget.geometry(), rect);
4461 // setGeometry() while shown
4462 foreach (QRect r, rects) {
4463 widget.setGeometry(r);
4465 QTRY_COMPARE(widget.geometry(), r);
4467 widget.setGeometry(rect);
4469 QTRY_COMPARE(widget.geometry(), rect);
4474 QTRY_COMPARE(widget.geometry(), rect);
4476 // setGeometry() after hide()
4477 foreach (QRect r, rects) {
4478 widget.setGeometry(r);
4480 QTRY_COMPARE(widget.geometry(), r);
4482 widget.setGeometry(rect);
4484 QTRY_COMPARE(widget.geometry(), rect);
4486 // show() again, geometry() should still be the same
4488 QVERIFY(QTest::qWaitForWindowExposed(&widget));
4490 QTRY_COMPARE(widget.geometry(), rect);
4492 // final hide(), again geometry() should be unchanged
4495 QTRY_COMPARE(widget.geometry(), rect);
4499 #if defined (Q_OS_WIN) && !defined(Q_OS_WINCE)
4500 void tst_QWidget::setGeometry_win()
4503 widget.setGeometry(0, 600, 100,100);
4505 widget.setWindowState(widget.windowState() | Qt::WindowMaximized);
4506 QRect geom = widget.normalGeometry();
4508 widget.setGeometry(geom);
4509 widget.setWindowState(widget.windowState() | Qt::WindowMaximized);
4512 ::GetWindowRect(winHandleOf(&widget), &rt);
4513 QVERIFY(rt.left <= 0);
4514 QEXPECT_FAIL("", "QTBUG-26424", Continue);
4515 QVERIFY(rt.top <= 0);
4517 #endif // defined (Q_OS_WIN) && !defined(Q_OS_WINCE)
4519 // Since X11 WindowManager operation are all async, and we have no way to know if the window
4520 // manager has finished playing with the window geometry, this test can't be reliable on X11.
4522 void tst_QWidget::windowMoveResize_data()
4524 setWindowGeometry_data();
4527 void tst_QWidget::windowMoveResize()
4529 if (m_platform == QStringLiteral("xcb"))
4530 QSKIP("X11: Skip this test due to Window manager positioning issues.");
4532 QFETCH(QList<QRect>, rects);
4533 QFETCH(int, windowFlags);
4535 QRect rect = rects.takeFirst();
4538 // test setGeometry() without actually showing the window
4540 if (windowFlags != 0)
4541 widget.setWindowFlags(Qt::WindowFlags(windowFlags));
4543 widget.move(rect.topLeft());
4544 widget.resize(rect.size());
4546 QTRY_COMPARE(widget.pos(), rect.topLeft());
4547 QTRY_COMPARE(widget.size(), rect.size());
4549 // move() without showing
4550 foreach (QRect r, rects) {
4551 widget.move(r.topLeft());
4552 widget.resize(r.size());
4553 QApplication::processEvents();
4554 QTRY_COMPARE(widget.pos(), r.topLeft());
4555 QTRY_COMPARE(widget.size(), r.size());
4560 // move() first, then show()
4562 if (windowFlags != 0)
4563 widget.setWindowFlags(Qt::WindowFlags(windowFlags));
4565 widget.move(rect.topLeft());
4566 widget.resize(rect.size());
4570 QTRY_COMPARE(widget.pos(), rect.topLeft());
4571 if (m_platform == QStringLiteral("windows")) {
4572 QEXPECT_FAIL("130,100 0x200, flags 0", "QTBUG-26424", Continue);
4573 QEXPECT_FAIL("130,50 0x0, flags 0", "QTBUG-26424", Continue);
4575 QTRY_COMPARE(widget.size(), rect.size());
4577 // move() while shown
4578 foreach (const QRect &r, rects) {
4579 if (m_platform == QStringLiteral("xcb")
4580 && ((widget.width() == 0 || widget.height() == 0) && r.width() != 0 && r.height() != 0)) {
4581 QEXPECT_FAIL("130,100 0x200, flags 0",
4582 "First resize after show of zero-sized gets wrong win_gravity.",
4584 QEXPECT_FAIL("100,50 200x0, flags 0",
4585 "First resize after show of zero-sized gets wrong win_gravity.",
4587 QEXPECT_FAIL("130,50 0x0, flags 0",
4588 "First resize after show of zero-sized gets wrong win_gravity.",
4592 widget.move(r.topLeft());
4593 widget.resize(r.size());
4594 QApplication::processEvents();
4595 QTRY_COMPARE(widget.pos(), r.topLeft());
4596 QTRY_COMPARE(widget.size(), r.size());
4598 widget.move(rect.topLeft());
4599 widget.resize(rect.size());
4600 QApplication::processEvents();
4601 QTRY_COMPARE(widget.pos(), rect.topLeft());
4602 QTRY_COMPARE(widget.size(), rect.size());
4607 QTRY_COMPARE(widget.pos(), rect.topLeft());
4608 QTRY_COMPARE(widget.size(), rect.size());
4610 // move() after hide()
4611 foreach (QRect r, rects) {
4612 widget.move(r.topLeft());
4613 widget.resize(r.size());
4614 QApplication::processEvents();
4615 #if defined(Q_OS_MAC)
4616 if (r.width() == 0 && r.height() > 0) {
4617 widget.move(r.topLeft());
4618 widget.resize(r.size());
4621 QTRY_COMPARE(widget.pos(), r.topLeft());
4622 QTRY_COMPARE(widget.size(), r.size());
4624 widget.move(rect.topLeft());
4625 widget.resize(rect.size());
4627 QTRY_COMPARE(widget.pos(), rect.topLeft());
4628 QTRY_COMPARE(widget.size(), rect.size());
4630 // show() again, pos() should be the same
4632 QVERIFY(QTest::qWaitForWindowExposed(&widget));
4633 QApplication::processEvents();
4634 QTRY_COMPARE(widget.pos(), rect.topLeft());
4635 QTRY_COMPARE(widget.size(), rect.size());
4637 // final hide(), again pos() should be unchanged
4639 QApplication::processEvents();
4640 QTRY_COMPARE(widget.pos(), rect.topLeft());
4641 QTRY_COMPARE(widget.size(), rect.size());
4645 // show() first, then move()
4647 if (windowFlags != 0)
4648 widget.setWindowFlags(Qt::WindowFlags(windowFlags));
4651 QVERIFY(QTest::qWaitForWindowExposed(&widget));
4652 QApplication::processEvents();
4653 widget.move(rect.topLeft());
4654 widget.resize(rect.size());
4655 QApplication::processEvents();
4656 QTRY_COMPARE(widget.pos(), rect.topLeft());
4657 QTRY_COMPARE(widget.size(), rect.size());
4659 // move() while shown
4660 foreach (QRect r, rects) {
4661 widget.move(r.topLeft());
4662 widget.resize(r.size());
4663 QApplication::processEvents();
4664 QTRY_COMPARE(widget.pos(), r.topLeft());
4665 QTRY_COMPARE(widget.size(), r.size());
4667 widget.move(rect.topLeft());
4668 widget.resize(rect.size());
4669 QApplication::processEvents();
4670 QTRY_COMPARE(widget.pos(), rect.topLeft());
4671 QTRY_COMPARE(widget.size(), rect.size());
4675 QApplication::processEvents();
4676 QTRY_COMPARE(widget.pos(), rect.topLeft());
4677 QTRY_COMPARE(widget.size(), rect.size());
4679 // move() after hide()
4680 foreach (QRect r, rects) {
4681 widget.move(r.topLeft());
4682 widget.resize(r.size());
4683 QApplication::processEvents();
4684 #if defined(Q_OS_MAC)
4685 if (r.width() == 0 && r.height() > 0) {
4686 widget.move(r.topLeft());
4687 widget.resize(r.size());
4690 QTRY_COMPARE(widget.pos(), r.topLeft());
4691 QTRY_COMPARE(widget.size(), r.size());
4693 widget.move(rect.topLeft());
4694 widget.resize(rect.size());
4695 QApplication::processEvents();
4696 QTRY_COMPARE(widget.pos(), rect.topLeft());
4697 QTRY_COMPARE(widget.size(), rect.size());
4699 // show() again, pos() should be the same
4701 QVERIFY(QTest::qWaitForWindowExposed(&widget));
4703 QTRY_COMPARE(widget.pos(), rect.topLeft());
4704 QTRY_COMPARE(widget.size(), rect.size());
4706 // final hide(), again pos() should be unchanged
4709 QTRY_COMPARE(widget.pos(), rect.topLeft());
4710 QTRY_COMPARE(widget.size(), rect.size());
4714 class ColorWidget : public QWidget
4717 ColorWidget(QWidget *parent = 0, const QColor &c = QColor(Qt::red))
4718 : QWidget(parent, Qt::FramelessWindowHint), color(c), enters(0), leaves(0)
4720 QPalette opaquePalette = palette();
4721 opaquePalette.setColor(backgroundRole(), color);
4722 setPalette(opaquePalette);
4723 setAutoFillBackground(true);
4726 void paintEvent(QPaintEvent *e) {
4734 void enterEvent(QEvent *) { ++enters; }
4735 void leaveEvent(QEvent *) { ++leaves; }
4749 #define VERIFY_COLOR(region, color) { \
4750 const QRegion r = QRegion(region); \
4751 QScreen *screen = qApp->primaryScreen(); \
4752 const WId desktopWinId = QDesktopWidget().winId(); \
4753 for (int i = 0; i < r.rects().size(); ++i) { \
4754 const QRect rect = r.rects().at(i); \
4755 for (int t = 0; t < 5; t++) { \
4756 const QPixmap pixmap = screen->grabWindow(desktopWinId, \
4757 rect.left(), rect.top(), \
4758 rect.width(), rect.height()); \
4759 QCOMPARE(pixmap.size(), rect.size()); \
4760 QPixmap expectedPixmap(pixmap); /* ensure equal formats */ \
4761 expectedPixmap.detach(); \
4762 expectedPixmap.fill(color); \
4763 QImage image = pixmap.toImage(); \
4764 uint alphaCorrection = image.format() == QImage::Format_RGB32 ? 0xff000000 : 0; \
4765 uint firstPixel = image.pixel(0,0) | alphaCorrection; \
4766 if ( firstPixel != QColor(color).rgb() && t < 4 ) \
4767 { QTest::qWait(200); continue; } \
4768 QCOMPARE(firstPixel, QColor(color).rgb()); \
4769 QCOMPARE(pixmap, expectedPixmap); \
4775 void tst_QWidget::popupEnterLeave()
4778 parent.setWindowFlags(Qt::FramelessWindowHint);
4779 parent.setGeometry(10, 10, 200, 100);
4781 ColorWidget alien(&parent, Qt::black);
4782 alien.setGeometry(0, 0, 10, 10);
4787 QVERIFY(QTest::qWaitForWindowExposed(&parent));
4789 QWindowSystemInterface::handleMouseEvent(parent.windowHandle(), QPointF(5, 5), QPointF(), Qt::LeftButton, Qt::NoModifier);
4791 QWindowSystemInterface::handleMouseEvent(parent.windowHandle(), QPointF(5, 5), QPointF(), Qt::NoButton, Qt::NoModifier);
4794 QStringList wordList;
4795 wordList << "alpha" << "omega" << "omicron" << "zeta";
4797 QLineEdit popup(&parent);
4799 QCompleter completer(wordList);
4800 completer.setCaseSensitivity(Qt::CaseInsensitive);
4801 popup.setCompleter(&completer);
4802 popup.setWindowFlags(Qt::Popup);
4803 popup.setGeometry(20, 20, 80, 20);
4807 QVERIFY(QTest::qWaitForWindowExposed(&popup));
4811 QWindowSystemInterface::handleMouseEvent(popup.windowHandle(), QPointF(-5, -5), QPointF(), Qt::LeftButton, Qt::NoModifier);
4813 QWindowSystemInterface::handleMouseEvent(popup.windowHandle(), QPointF(-5, -5), QPointF(), Qt::NoButton, Qt::NoModifier);
4817 QVERIFY(!popup.underMouse());
4820 void tst_QWidget::moveChild_data()
4822 QTest::addColumn<QPoint>("offset");
4824 QTest::newRow("right") << QPoint(20, 0);
4825 QTest::newRow("down") << QPoint(0, 20);
4826 QTest::newRow("left") << QPoint(-20, 0);
4827 QTest::newRow("up") << QPoint(0, -20);
4830 void tst_QWidget::moveChild()
4832 QFETCH(QPoint, offset);
4835 // prevent custom styles
4836 parent.setStyle(QStyleFactory::create(QLatin1String("Windows")));
4837 ColorWidget child(&parent, Qt::blue);
4840 parent.setGeometry(QRect(QPoint(QApplication::desktop()->availableGeometry(&parent).topLeft()),
4843 parent.setGeometry(60, 60, 150, 150);
4845 child.setGeometry(25, 25, 50, 50);
4847 QVERIFY(QTest::qWaitForWindowExposed(&parent));
4849 const QPoint tlwOffset = parent.geometry().topLeft();
4851 QTRY_COMPARE(parent.r, QRegion(parent.rect()) - child.geometry());
4852 QTRY_COMPARE(child.r, QRegion(child.rect()));
4853 VERIFY_COLOR(child.geometry().translated(tlwOffset),
4855 VERIFY_COLOR(QRegion(parent.geometry()) - child.geometry().translated(tlwOffset),
4862 const QRect oldGeometry = child.geometry();
4864 QPoint pos = child.pos() + offset;
4867 QTRY_COMPARE(pos, child.pos());
4869 QCOMPARE(parent.r, QRegion(oldGeometry) - child.geometry());
4870 #if !defined(Q_OS_MAC)
4871 // should be scrolled in backingstore
4872 QCOMPARE(child.r, QRegion());
4874 VERIFY_COLOR(child.geometry().translated(tlwOffset),
4876 VERIFY_COLOR(QRegion(parent.geometry()) - child.geometry().translated(tlwOffset),
4880 void tst_QWidget::showAndMoveChild()
4882 QWidget parent(0, Qt::FramelessWindowHint);
4883 // prevent custom styles
4884 parent.setStyle(QStyleFactory::create(QLatin1String("Windows")));
4886 QDesktopWidget desktop;
4887 QRect desktopDimensions = desktop.availableGeometry(&parent);
4888 desktopDimensions = desktopDimensions.adjusted(64, 64, -64, -64);
4890 parent.setGeometry(desktopDimensions);
4891 parent.setPalette(Qt::red);
4893 qApp->setActiveWindow(&parent);
4894 QVERIFY(QTest::qWaitForWindowActive(&parent));
4897 const QPoint tlwOffset = parent.geometry().topLeft();
4898 QWidget child(&parent);
4899 child.resize(desktopDimensions.width()/2, desktopDimensions.height()/2);
4900 child.setPalette(Qt::blue);
4901 child.setAutoFillBackground(true);
4903 // Ensure that the child is repainted correctly when moved right after show.
4904 // NB! Do NOT processEvents() (or qWait()) in between show() and move().
4906 child.move(desktopDimensions.width()/2, desktopDimensions.height()/2);
4907 qApp->processEvents();
4909 VERIFY_COLOR(child.geometry().translated(tlwOffset), Qt::blue);
4910 VERIFY_COLOR(QRegion(parent.geometry()) - child.geometry().translated(tlwOffset), Qt::red);
4913 // Cocoa only has rect granularity.
4915 void tst_QWidget::subtractOpaqueSiblings()
4918 w.setGeometry(50, 50, 300, 300);
4920 ColorWidget *large = new ColorWidget(&w, Qt::red);
4921 large->setGeometry(50, 50, 200, 200);
4923 ColorWidget *medium = new ColorWidget(large, Qt::gray);
4924 medium->setGeometry(50, 50, 100, 100);
4926 ColorWidget *tall = new ColorWidget(&w, Qt::blue);
4927 tall->setGeometry(100, 30, 50, 100);
4930 QVERIFY(QTest::qWaitForWindowExposed(&w));
4940 // QWidgetPrivate::subtractOpaqueSiblings() should prevent parts of medium
4941 // to be repainted and tall from be repainted at all.
4943 QTRY_COMPARE(large->r, QRegion());
4944 QTRY_COMPARE(tall->r, QRegion());
4945 QTRY_COMPARE(medium->r.translated(medium->mapTo(&w, QPoint())),
4946 QRegion(medium->geometry().translated(large->pos()))
4947 - tall->geometry());
4951 void tst_QWidget::deleteStyle()
4954 widget.setStyle(QStyleFactory::create(QLatin1String("Windows")));
4956 delete widget.style();
4957 qApp->processEvents();
4960 class TopLevelFocusCheck: public QWidget
4965 TopLevelFocusCheck(QWidget* parent = 0) : QWidget(parent)
4967 edit = new QLineEdit(this);
4969 edit->installEventFilter(this);
4973 void mouseDoubleClickEvent ( QMouseEvent * /*event*/ )
4976 edit->setFocus(Qt::OtherFocusReason);
4977 qApp->processEvents();
4979 bool eventFilter(QObject *obj, QEvent *event)
4981 if (obj == edit && event->type()== QEvent::FocusOut) {
4989 void tst_QWidget::multipleToplevelFocusCheck()
4991 TopLevelFocusCheck w1;
4992 TopLevelFocusCheck w2;
4994 w1.resize(200, 200);
4996 QVERIFY(QTest::qWaitForWindowExposed(&w1));
4999 QVERIFY(QTest::qWaitForWindowExposed(&w2));
5001 QApplication::setActiveWindow(&w1);
5002 w1.activateWindow();
5003 QVERIFY(QTest::qWaitForWindowActive(&w1));
5004 QCOMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&w1));
5006 QTest::mouseDClick(&w1, Qt::LeftButton);
5007 QTRY_COMPARE(QApplication::focusWidget(), static_cast<QWidget *>(w1.edit));
5009 w2.activateWindow();
5010 QApplication::setActiveWindow(&w2);
5011 QVERIFY(QTest::qWaitForWindowActive(&w2));
5012 QCOMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&w2));
5013 QTest::mouseClick(&w2, Qt::LeftButton);
5014 QTRY_COMPARE(QApplication::focusWidget(), (QWidget *)0);
5016 QTest::mouseDClick(&w2, Qt::LeftButton);
5017 QTRY_COMPARE(QApplication::focusWidget(), static_cast<QWidget *>(w2.edit));
5019 w1.activateWindow();
5020 QApplication::setActiveWindow(&w1);
5021 QVERIFY(QTest::qWaitForWindowActive(&w1));
5022 QCOMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&w1));
5023 QTest::mouseDClick(&w1, Qt::LeftButton);
5024 QTRY_COMPARE(QApplication::focusWidget(), static_cast<QWidget *>(w1.edit));
5026 w2.activateWindow();
5027 QApplication::setActiveWindow(&w2);
5028 QVERIFY(QTest::qWaitForWindowActive(&w2));
5029 QCOMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&w2));
5030 QTest::mouseClick(&w2, Qt::LeftButton);
5031 QTRY_COMPARE(QApplication::focusWidget(), (QWidget *)0);
5034 class FocusWidget: public QWidget
5037 virtual bool event(QEvent *ev)
5039 if (ev->type() == QEvent::FocusAboutToChange)
5040 widgetDuringFocusAboutToChange = qApp->focusWidget();
5041 return QWidget::event(ev);
5043 virtual void focusOutEvent(QFocusEvent *)
5045 widgetDuringFocusOut = qApp->focusWidget();
5049 FocusWidget(QWidget *parent) : QWidget(parent), widgetDuringFocusAboutToChange(0), widgetDuringFocusOut(0) {}
5051 QWidget *widgetDuringFocusAboutToChange;
5052 QWidget *widgetDuringFocusOut;
5055 void tst_QWidget::setFocus()
5058 // move focus to another window
5059 testWidget->activateWindow();
5060 QApplication::setActiveWindow(testWidget);
5061 if (testWidget->focusWidget())
5062 testWidget->focusWidget()->clearFocus();
5064 testWidget->clearFocus();
5066 // window and children never shown, nobody gets focus
5068 window.resize(200, 200);
5070 QWidget child1(&window);
5071 child1.setFocusPolicy(Qt::StrongFocus);
5073 QWidget child2(&window);
5074 child2.setFocusPolicy(Qt::StrongFocus);
5077 QVERIFY(!child1.hasFocus());
5078 QCOMPARE(window.focusWidget(), &child1);
5079 QCOMPARE(QApplication::focusWidget(), static_cast<QWidget *>(0));
5082 QVERIFY(!child2.hasFocus());
5083 QCOMPARE(window.focusWidget(), &child2);
5084 QCOMPARE(QApplication::focusWidget(), static_cast<QWidget *>(0));
5088 // window and children show, but window not active, nobody gets focus
5090 window.resize(200, 200);
5092 QWidget child1(&window);
5093 child1.setFocusPolicy(Qt::StrongFocus);
5095 QWidget child2(&window);
5096 child2.setFocusPolicy(Qt::StrongFocus);
5100 // note: window may be active, but we don't want it to be
5101 testWidget->activateWindow();
5102 QApplication::setActiveWindow(testWidget);
5103 if (testWidget->focusWidget())
5104 testWidget->focusWidget()->clearFocus();
5106 testWidget->clearFocus();
5109 QVERIFY(!child1.hasFocus());
5110 QCOMPARE(window.focusWidget(), &child1);
5111 QCOMPARE(QApplication::focusWidget(), static_cast<QWidget *>(0));
5114 QVERIFY(!child2.hasFocus());
5115 QCOMPARE(window.focusWidget(), &child2);
5116 QCOMPARE(QApplication::focusWidget(), static_cast<QWidget *>(0));
5120 // window and children show, but window *is* active, children get focus
5122 window.resize(200, 200);
5124 FocusWidget child1(&window);
5125 child1.setFocusPolicy(Qt::StrongFocus);
5127 QWidget child2(&window);
5128 child2.setFocusPolicy(Qt::StrongFocus);
5131 window.activateWindow();
5132 QVERIFY(QTest::qWaitForWindowExposed(&window));
5133 QTRY_VERIFY(qGuiApp->focusWindow());
5136 QTRY_VERIFY(child1.hasFocus());
5137 QCOMPARE(window.focusWidget(), &child1);
5138 QCOMPARE(QApplication::focusWidget(), &child1);
5141 QVERIFY(child2.hasFocus());
5142 QCOMPARE(window.focusWidget(), &child2);
5143 QCOMPARE(QApplication::focusWidget(), &child2);
5145 // focus changed in between the events
5146 QCOMPARE(child1.widgetDuringFocusAboutToChange, &child1);
5147 QCOMPARE(child1.widgetDuringFocusOut, &child2);
5151 // window shown and active, children created, don't get focus, but get focus when shown
5153 window.resize(200, 200);
5156 window.activateWindow();
5157 QVERIFY(QTest::qWaitForWindowExposed(&window));
5158 QTRY_VERIFY(qGuiApp->focusWindow());
5160 QWidget child1(&window);
5161 child1.setFocusPolicy(Qt::StrongFocus);
5163 QWidget child2(&window);
5164 child2.setFocusPolicy(Qt::StrongFocus);
5167 QVERIFY(!child1.hasFocus());
5168 QCOMPARE(window.focusWidget(), static_cast<QWidget *>(0));
5169 QCOMPARE(QApplication::focusWidget(), static_cast<QWidget *>(0));
5172 QApplication::processEvents();
5173 QTRY_VERIFY(child1.hasFocus());
5174 QCOMPARE(window.focusWidget(), &child1);
5175 QCOMPARE(QApplication::focusWidget(), &child1);
5178 QVERIFY(!child2.hasFocus());
5179 QCOMPARE(window.focusWidget(), &child1);
5180 QCOMPARE(QApplication::focusWidget(), &child1);
5183 QVERIFY(child2.hasFocus());
5184 QCOMPARE(window.focusWidget(), &child2);
5185 QCOMPARE(QApplication::focusWidget(), &child2);
5189 // window shown and active, children created, don't get focus,
5190 // even after setFocus(), hide(), then show()
5192 window.resize(200, 200);
5195 window.activateWindow();
5196 QVERIFY(QTest::qWaitForWindowExposed(&window));
5197 QTRY_VERIFY(qGuiApp->focusWindow());
5199 QWidget child1(&window);
5200 child1.setFocusPolicy(Qt::StrongFocus);
5202 QWidget child2(&window);
5203 child2.setFocusPolicy(Qt::StrongFocus);
5206 QVERIFY(!child1.hasFocus());
5207 QCOMPARE(window.focusWidget(), static_cast<QWidget *>(0));
5208 QCOMPARE(QApplication::focusWidget(), static_cast<QWidget *>(0));
5211 QVERIFY(!child1.hasFocus());
5212 QCOMPARE(window.focusWidget(), static_cast<QWidget *>(0));
5213 QCOMPARE(QApplication::focusWidget(), static_cast<QWidget *>(0));
5216 QVERIFY(!child1.hasFocus());
5217 QCOMPARE(window.focusWidget(), static_cast<QWidget *>(0));
5218 QCOMPARE(QApplication::focusWidget(), static_cast<QWidget *>(0));
5221 QVERIFY(!child2.hasFocus());
5222 QCOMPARE(window.focusWidget(), static_cast<QWidget *>(0));
5223 QCOMPARE(QApplication::focusWidget(), static_cast<QWidget *>(0));
5226 QVERIFY(!child2.hasFocus());
5227 QCOMPARE(window.focusWidget(), static_cast<QWidget *>(0));
5228 QCOMPARE(QApplication::focusWidget(), static_cast<QWidget *>(0));
5231 QVERIFY(!child2.hasFocus());
5232 QCOMPARE(window.focusWidget(), static_cast<QWidget *>(0));
5233 QCOMPARE(QApplication::focusWidget(), static_cast<QWidget *>(0));
5237 class EventSpy : public QObject
5240 EventSpy(QWidget *widget, QEvent::Type event)
5241 : m_widget(widget), eventToSpy(event), m_count(0)
5244 m_widget->installEventFilter(this);
5247 QWidget *widget() const { return m_widget; }
5248 int count() const { return m_count; }
5249 void clear() { m_count = 0; }
5252 bool eventFilter(QObject *object, QEvent *event)
5254 if (event->type() == eventToSpy)
5256 return QObject::eventFilter(object, event);
5261 QEvent::Type eventToSpy;
5265 #ifndef QTEST_NO_CURSOR
5266 void tst_QWidget::setCursor()
5270 window.resize(200, 200);
5271 QWidget child(&window);
5273 QVERIFY(!window.testAttribute(Qt::WA_SetCursor));
5274 QVERIFY(!child.testAttribute(Qt::WA_SetCursor));
5276 window.setCursor(window.cursor());
5277 QVERIFY(window.testAttribute(Qt::WA_SetCursor));
5278 QVERIFY(!child.testAttribute(Qt::WA_SetCursor));
5279 QCOMPARE(child.cursor().shape(), window.cursor().shape());
5282 // do it again, but with window show()n
5285 window.resize(200, 200);
5286 QWidget child(&window);
5289 QVERIFY(!window.testAttribute(Qt::WA_SetCursor));
5290 QVERIFY(!child.testAttribute(Qt::WA_SetCursor));
5292 window.setCursor(window.cursor());
5293 QVERIFY(window.testAttribute(Qt::WA_SetCursor));
5294 QVERIFY(!child.testAttribute(Qt::WA_SetCursor));
5295 QCOMPARE(child.cursor().shape(), window.cursor().shape());
5301 window.resize(200, 200);
5302 QWidget child(&window);
5304 window.setCursor(Qt::WaitCursor);
5305 QVERIFY(window.testAttribute(Qt::WA_SetCursor));
5306 QVERIFY(!child.testAttribute(Qt::WA_SetCursor));
5307 QCOMPARE(child.cursor().shape(), window.cursor().shape());
5310 // same thing again, just with window show()n
5313 window.resize(200, 200);
5314 QWidget child(&window);
5317 QVERIFY(QTest::qWaitForWindowExposed(&window));
5318 window.setCursor(Qt::WaitCursor);
5319 QVERIFY(window.testAttribute(Qt::WA_SetCursor));
5320 QVERIFY(!child.testAttribute(Qt::WA_SetCursor));
5321 QCOMPARE(child.cursor().shape(), window.cursor().shape());
5324 // reparenting child should not cause the WA_SetCursor to become set
5327 window.resize(200, 200);
5329 window2.resize(200, 200);
5330 QWidget child(&window);
5332 window.setCursor(Qt::WaitCursor);
5335 QVERIFY(!child.testAttribute(Qt::WA_SetCursor));
5336 QCOMPARE(child.cursor().shape(), QCursor().shape());
5338 child.setParent(&window2);
5339 QVERIFY(!child.testAttribute(Qt::WA_SetCursor));
5340 QCOMPARE(child.cursor().shape(), window2.cursor().shape());
5342 window2.setCursor(Qt::WaitCursor);
5343 QVERIFY(!child.testAttribute(Qt::WA_SetCursor));
5344 QCOMPARE(child.cursor().shape(), window2.cursor().shape());
5347 // again, with windows show()n
5350 window.resize(200, 200);
5352 window2.resize(200, 200);
5353 QWidget child(&window);
5355 window.setCursor(Qt::WaitCursor);
5359 QVERIFY(!child.testAttribute(Qt::WA_SetCursor));
5360 QCOMPARE(child.cursor().shape(), QCursor().shape());
5362 child.setParent(&window2);
5363 QVERIFY(!child.testAttribute(Qt::WA_SetCursor));
5364 QCOMPARE(child.cursor().shape(), window2.cursor().shape());
5367 window2.setCursor(Qt::WaitCursor);
5368 QVERIFY(!child.testAttribute(Qt::WA_SetCursor));
5369 QCOMPARE(child.cursor().shape(), window2.cursor().shape());
5372 // test if CursorChange is sent
5375 EventSpy spy(&widget, QEvent::CursorChange);
5376 QCOMPARE(spy.count(), 0);
5377 widget.setCursor(QCursor(Qt::WaitCursor));
5378 QCOMPARE(spy.count(), 1);
5379 widget.unsetCursor();
5380 QCOMPARE(spy.count(), 2);
5385 void tst_QWidget::setToolTip()
5388 widget.resize(200, 200);
5389 // Showing the widget is not required for the tooltip event count test
5390 // to work. It should just prevent the application from becoming inactive
5391 // which would cause it to close all popups, interfering with the test
5392 // in the loop below.
5393 widget.setObjectName(QLatin1String("tst_qwidget setToolTip"));
5394 widget.setWindowTitle(widget.objectName());
5396 QVERIFY(QTest::qWaitForWindowExposed(&widget));
5397 EventSpy spy(&widget, QEvent::ToolTipChange);
5398 QCOMPARE(spy.count(), 0);
5400 QCOMPARE(widget.toolTip(), QString());
5401 widget.setToolTip(QString("Hello"));
5402 QCOMPARE(widget.toolTip(), QString("Hello"));
5403 QCOMPARE(spy.count(), 1);
5404 widget.setToolTip(QString());
5405 QCOMPARE(widget.toolTip(), QString());
5406 QCOMPARE(spy.count(), 2);
5408 // Mouse over doesn't work on Windows mobile, so skip the rest of the test for that platform.
5409 #ifndef Q_OS_WINCE_WM
5410 for (int pass = 0; pass < 2; ++pass) {
5411 QCursor::setPos(0, 0);
5412 QScopedPointer<QWidget> popup(new QWidget(0, Qt::Popup));
5413 popup->setObjectName(QString::fromLatin1("tst_qwidget setToolTip #%1").arg(pass));
5414 popup->setWindowTitle(popup->objectName());
5415 popup->resize(150, 50);
5416 QFrame *frame = new QFrame(popup.data());
5417 frame->setGeometry(0, 0, 50, 50);
5418 frame->setFrameStyle(QFrame::Box | QFrame::Plain);
5419 EventSpy spy1(frame, QEvent::ToolTip);
5420 EventSpy spy2(popup.data(), QEvent::ToolTip);
5421 frame->setMouseTracking(pass == 0 ? false : true);
5422 frame->setToolTip(QLatin1String("TOOLTIP FRAME"));
5423 popup->setToolTip(QLatin1String("TOOLTIP POPUP"));
5425 QVERIFY(QTest::qWaitForWindowExposed(popup.data()));
5426 QWindow *popupWindow = popup->windowHandle();
5428 QTest::mouseMove(popupWindow, QPoint(25, 25));
5429 QTest::qWait(900); // delay is 700
5431 QCOMPARE(spy1.count(), 1);
5432 QCOMPARE(spy2.count(), 0);
5434 QTest::qWait(2200); // delay is 2000
5435 QTest::mouseMove(popupWindow);
5440 void tst_QWidget::testWindowIconChangeEventPropagation()
5442 typedef QSharedPointer<EventSpy> EventSpyPtr;
5443 // Create widget hierarchy.
5444 QWidget topLevelWidget;
5445 QWidget topLevelChild(&topLevelWidget);
5447 QDialog dialog(&topLevelWidget);
5448 QWidget dialogChild(&dialog);
5450 QWidgetList widgets;
5451 widgets << &topLevelWidget << &topLevelChild
5452 << &dialog << &dialogChild;
5453 QCOMPARE(widgets.count(), 4);
5455 // Create spy lists.
5456 QList <EventSpyPtr> applicationEventSpies;
5457 QList <EventSpyPtr> widgetEventSpies;
5458 foreach (QWidget *widget, widgets) {
5459 applicationEventSpies.append(EventSpyPtr(new EventSpy(widget, QEvent::ApplicationWindowIconChange)));
5460 widgetEventSpies.append(EventSpyPtr(new EventSpy(widget, QEvent::WindowIconChange)));
5463 // QApplication::setWindowIcon
5464 const QIcon windowIcon = qApp->style()->standardIcon(QStyle::SP_TitleBarMenuButton);
5465 qApp->setWindowIcon(windowIcon);
5467 for (int i = 0; i < widgets.count(); ++i) {
5468 // Check QEvent::ApplicationWindowIconChange
5469 EventSpyPtr spy = applicationEventSpies.at(i);
5470 QWidget *widget = spy->widget();
5471 if (widget->isWindow()) {
5472 QCOMPARE(spy->count(), 1);
5473 QCOMPARE(widget->windowIcon(), windowIcon);
5475 QCOMPARE(spy->count(), 0);
5479 // Check QEvent::WindowIconChange
5480 spy = widgetEventSpies.at(i);
5481 QCOMPARE(spy->count(), 1);
5485 // Set icon on a top-level widget.
5486 topLevelWidget.setWindowIcon(QIcon());
5488 for (int i = 0; i < widgets.count(); ++i) {
5489 // Check QEvent::ApplicationWindowIconChange
5490 EventSpyPtr spy = applicationEventSpies.at(i);
5491 QCOMPARE(spy->count(), 0);
5494 // Check QEvent::WindowIconChange
5495 spy = widgetEventSpies.at(i);
5496 QWidget *widget = spy->widget();
5497 if (widget == &topLevelWidget) {
5498 QCOMPARE(widget->windowIcon(), QIcon());
5499 QCOMPARE(spy->count(), 1);
5500 } else if (topLevelWidget.isAncestorOf(widget)) {
5501 QCOMPARE(spy->count(), 1);
5503 QCOMPARE(spy->count(), 0);
5509 qApp->setWindowIcon(QIcon());
5512 void tst_QWidget::minAndMaxSizeWithX11BypassWindowManagerHint()
5514 if (m_platform != QStringLiteral("xcb"))
5515 QSKIP("This test is for X11 only.");
5516 // Same size as in QWidget::create_sys().
5517 const QSize desktopSize = QApplication::desktop()->size();
5518 const QSize originalSize(desktopSize.width() / 2, desktopSize.height() * 4 / 10);
5521 QWidget widget(0, Qt::X11BypassWindowManagerHint);
5523 const QSize newMaximumSize = widget.size().boundedTo(originalSize) - QSize(10, 10);
5524 widget.setMaximumSize(newMaximumSize);
5525 QCOMPARE(widget.size(), newMaximumSize);
5528 QVERIFY(QTest::qWaitForWindowExposed(&widget));
5529 QCOMPARE(widget.size(), newMaximumSize);
5533 QWidget widget(0, Qt::X11BypassWindowManagerHint);
5535 const QSize newMinimumSize = widget.size().expandedTo(originalSize) + QSize(10, 10);
5536 widget.setMinimumSize(newMinimumSize);
5537 QCOMPARE(widget.size(), newMinimumSize);
5540 QVERIFY(QTest::qWaitForWindowExposed(&widget));
5541 QCOMPARE(widget.size(), newMinimumSize);
5545 class ShowHideShowWidget : public QWidget, public QAbstractNativeEventFilter
5551 bool gotExpectedMapNotify;
5552 bool gotExpectedGlobalEvent;
5554 ShowHideShowWidget()
5555 : state(0), gotExpectedMapNotify(false), gotExpectedGlobalEvent(false)
5560 void timerEvent(QTimerEvent *)
5572 bool isMapNotify(const QByteArray &eventType, void *message)
5574 enum { XCB_MAP_NOTIFY = 19 };
5575 if (state == 1 && eventType == QByteArrayLiteral("xcb_generic_event_t")) {
5576 // XCB events have a uint8 response_type member at the beginning.
5577 const unsigned char responseType = *(const unsigned char *)(message);
5578 return ((responseType & ~0x80) == XCB_MAP_NOTIFY);
5583 bool nativeEvent(const QByteArray &eventType, void *message, long *)
5585 if (isMapNotify(eventType, message))
5586 gotExpectedMapNotify = true;
5590 // QAbstractNativeEventFilter interface
5591 virtual bool nativeEventFilter(const QByteArray &eventType, void *message, long *) Q_DECL_OVERRIDE
5593 if (isMapNotify(eventType, message))
5594 gotExpectedGlobalEvent = true;
5602 void tst_QWidget::showHideShowX11()
5604 if (m_platform != QStringLiteral("xcb"))
5605 QSKIP("This test is for X11 only.");
5607 ShowHideShowWidget w;
5608 qApp->installNativeEventFilter(&w);
5613 QEventLoop eventLoop;
5614 connect(&w, SIGNAL(done()), &eventLoop, SLOT(quit()));
5617 QVERIFY(w.gotExpectedGlobalEvent);
5618 QVERIFY(w.gotExpectedMapNotify);
5621 void tst_QWidget::clean_qt_x11_enforce_cursor()
5623 if (m_platform != QStringLiteral("xcb"))
5624 QSKIP("This test is for X11 only.");
5628 QWidget *w = new QWidget(&window);
5629 QWidget *child = new QWidget(w);
5630 child->setAttribute(Qt::WA_SetCursor, true);
5633 QApplication::setActiveWindow(&window);
5634 QVERIFY(QTest::qWaitForWindowActive(&window));
5636 QCursor::setPos(window.geometry().center());
5640 QApplication::processEvents();
5646 QGraphicsScene scene;
5647 QLineEdit *edit = new QLineEdit;
5648 scene.addWidget(edit);
5650 // If the test didn't crash, then it passed.
5653 class EventRecorder : public QObject
5658 typedef QPair<QWidget *, QEvent::Type> WidgetEventTypePair;
5659 typedef QList<WidgetEventTypePair> EventList;
5661 EventRecorder(QObject *parent = 0)
5665 EventList eventList()
5675 bool eventFilter(QObject *object, QEvent *event)
5677 QWidget *widget = qobject_cast<QWidget *>(object);
5678 if (widget && !event->spontaneous())
5679 events.append(qMakePair(widget, event->type()));
5683 static QByteArray msgEventListMismatch(const EventList &expected, const EventList &actual);
5684 static QByteArray msgExpectFailQtBug26424(const EventList &expected, const EventList &actual)
5685 { return QByteArrayLiteral("QTBUG-26424: ") + msgEventListMismatch(expected, actual); }
5688 static inline void formatEventList(const EventList &l, QDebug &d);
5693 void EventRecorder::formatEventList(const EventList &l, QDebug &d)
5695 QWidget *lastWidget = 0;
5696 foreach (const WidgetEventTypePair &p, l) {
5697 if (p.first != lastWidget) {
5698 d << p.first << ':';
5699 lastWidget = p.first;
5701 d << p.second << ' ';
5705 QByteArray EventRecorder::msgEventListMismatch(const EventList &expected, const EventList &actual)
5708 QDebug d = QDebug(&result).nospace();
5709 d << "Event list mismatch, expected " << expected.size() << " (";
5710 EventRecorder::formatEventList(expected, d);
5711 d << "), actual " << actual.size() << " (";
5712 EventRecorder::formatEventList(actual, d);
5714 return result.toLocal8Bit();
5717 void tst_QWidget::childEvents()
5719 EventRecorder::EventList expected;
5721 // Move away the cursor; otherwise it might result in an enter event if it's
5722 // inside the widget when the widget is shown.
5723 QCursor::setPos(qApp->desktop()->availableGeometry().bottomRight());
5727 // no children created, not shown
5730 widget.installEventFilter(&spy);
5732 QCoreApplication::postEvent(&widget, new QEvent(QEvent::Type(QEvent::User + 1)));
5734 QCoreApplication::sendPostedEvents();
5737 EventRecorder::EventList()
5738 << qMakePair(&widget, QEvent::PolishRequest)
5739 << qMakePair(&widget, QEvent::Polish)
5740 << qMakePair(&widget, QEvent::Type(QEvent::User + 1));
5741 QVERIFY2(spy.eventList() == expected,
5742 EventRecorder::msgEventListMismatch(expected, spy.eventList()).constData());
5746 // no children, shown
5749 widget.installEventFilter(&spy);
5751 QCoreApplication::postEvent(&widget, new QEvent(QEvent::Type(QEvent::User + 1)));
5755 EventRecorder::EventList()
5756 << qMakePair(&widget, QEvent::WinIdChange)
5757 << qMakePair(&widget, QEvent::Polish)
5758 << qMakePair(&widget, QEvent::Move)
5759 << qMakePair(&widget, QEvent::Resize)
5760 << qMakePair(&widget, QEvent::Show);
5762 expected << qMakePair(&widget, QEvent::ShowToParent);
5764 QVERIFY2(spy.eventList() == expected,
5765 EventRecorder::msgEventListMismatch(expected, spy.eventList()).constData());
5768 QCoreApplication::sendPostedEvents();
5770 EventRecorder::EventList()
5771 << qMakePair(&widget, QEvent::PolishRequest)
5772 << qMakePair(&widget, QEvent::Type(QEvent::User + 1));
5775 expected << qMakePair(&widget, QEvent::UpdateLater);
5777 expected << qMakePair(&widget, QEvent::UpdateRequest);
5779 if (m_platform == QStringLiteral("windows") || m_platform == QStringLiteral("xcb"))
5780 QEXPECT_FAIL("", EventRecorder::msgExpectFailQtBug26424(expected, spy.eventList()).constData(), Continue);
5781 QVERIFY2(spy.eventList() == expected,
5782 EventRecorder::msgEventListMismatch(expected, spy.eventList()).constData());
5786 // 2 children, not shown
5789 widget.installEventFilter(&spy);
5791 QCoreApplication::postEvent(&widget, new QEvent(QEvent::Type(QEvent::User + 1)));
5793 QWidget child1(&widget);
5795 child2.setParent(&widget);
5797 QCoreApplication::postEvent(&widget, new QEvent(QEvent::Type(QEvent::User + 2)));
5800 EventRecorder::EventList()
5801 << qMakePair(&widget, QEvent::ChildAdded)
5802 << qMakePair(&widget, QEvent::ChildAdded);
5803 QVERIFY2(spy.eventList() == expected,
5804 EventRecorder::msgEventListMismatch(expected, spy.eventList()).constData());
5807 QCoreApplication::sendPostedEvents();
5809 EventRecorder::EventList()
5810 << qMakePair(&widget, QEvent::PolishRequest)
5811 << qMakePair(&widget, QEvent::Polish)
5812 << qMakePair(&widget, QEvent::ChildPolished)
5813 << qMakePair(&widget, QEvent::ChildPolished)
5814 << qMakePair(&widget, QEvent::Type(QEvent::User + 1))
5815 << qMakePair(&widget, QEvent::Type(QEvent::User + 2));
5816 QVERIFY2(spy.eventList() == expected,
5817 EventRecorder::msgEventListMismatch(expected, spy.eventList()).constData());
5821 // 2 children, widget shown
5824 widget.installEventFilter(&spy);
5826 QCoreApplication::postEvent(&widget, new QEvent(QEvent::Type(QEvent::User + 1)));
5828 QWidget child1(&widget);
5830 child2.setParent(&widget);
5832 QCoreApplication::postEvent(&widget, new QEvent(QEvent::Type(QEvent::User + 2)));
5835 EventRecorder::EventList()
5836 << qMakePair(&widget, QEvent::ChildAdded)
5837 << qMakePair(&widget, QEvent::ChildAdded);
5838 QCOMPARE(spy.eventList(), expected);
5843 EventRecorder::EventList()
5844 << qMakePair(&widget, QEvent::WinIdChange)
5845 << qMakePair(&widget, QEvent::Polish)
5846 << qMakePair(&widget, QEvent::ChildPolished)
5847 << qMakePair(&widget, QEvent::ChildPolished)
5848 << qMakePair(&widget, QEvent::Move)
5849 << qMakePair(&widget, QEvent::Resize)
5850 << qMakePair(&widget, QEvent::Show);
5852 expected << qMakePair(&widget, QEvent::ShowToParent);
5854 QVERIFY2(spy.eventList() == expected,
5855 EventRecorder::msgEventListMismatch(expected, spy.eventList()).constData());
5858 QCoreApplication::sendPostedEvents();
5860 EventRecorder::EventList()
5861 << qMakePair(&widget, QEvent::PolishRequest)
5862 << qMakePair(&widget, QEvent::Type(QEvent::User + 1))
5863 << qMakePair(&widget, QEvent::Type(QEvent::User + 2));
5866 expected << qMakePair(&widget, QEvent::UpdateLater);
5868 expected << qMakePair(&widget, QEvent::UpdateRequest);
5870 if (m_platform == QStringLiteral("windows") || m_platform == QStringLiteral("xcb"))
5871 QEXPECT_FAIL("", EventRecorder::msgExpectFailQtBug26424(expected, spy.eventList()).constData(), Continue);
5872 QVERIFY2(spy.eventList() == expected,
5873 EventRecorder::msgEventListMismatch(expected, spy.eventList()).constData());
5877 // 2 children, but one is reparented away, not shown
5880 widget.installEventFilter(&spy);
5882 QCoreApplication::postEvent(&widget, new QEvent(QEvent::Type(QEvent::User + 1)));
5884 QWidget child1(&widget);
5886 child2.setParent(&widget);
5887 child2.setParent(0);
5889 QCoreApplication::postEvent(&widget, new QEvent(QEvent::Type(QEvent::User + 2)));
5892 EventRecorder::EventList()
5893 << qMakePair(&widget, QEvent::ChildAdded)
5894 << qMakePair(&widget, QEvent::ChildAdded)
5895 << qMakePair(&widget, QEvent::ChildRemoved);
5896 QCOMPARE(spy.eventList(), expected);
5899 QCoreApplication::sendPostedEvents();
5901 EventRecorder::EventList()
5902 << qMakePair(&widget, QEvent::PolishRequest)
5903 << qMakePair(&widget, QEvent::Polish)
5904 << qMakePair(&widget, QEvent::ChildPolished)
5905 << qMakePair(&widget, QEvent::Type(QEvent::User + 1))
5906 << qMakePair(&widget, QEvent::Type(QEvent::User + 2));
5908 QVERIFY2(spy.eventList() == expected,
5909 EventRecorder::msgEventListMismatch(expected, spy.eventList()).constData());
5913 // 2 children, but one is reparented away, then widget is shown
5916 widget.installEventFilter(&spy);
5918 QCoreApplication::postEvent(&widget, new QEvent(QEvent::Type(QEvent::User + 1)));
5920 QWidget child1(&widget);
5922 child2.setParent(&widget);
5923 child2.setParent(0);
5925 QCoreApplication::postEvent(&widget, new QEvent(QEvent::Type(QEvent::User + 2)));
5928 EventRecorder::EventList()
5929 << qMakePair(&widget, QEvent::ChildAdded)
5930 << qMakePair(&widget, QEvent::ChildAdded)
5931 << qMakePair(&widget, QEvent::ChildRemoved);
5932 QCOMPARE(spy.eventList(), expected);
5937 EventRecorder::EventList()
5938 << qMakePair(&widget, QEvent::WinIdChange)
5939 << qMakePair(&widget, QEvent::Polish)
5940 << qMakePair(&widget, QEvent::ChildPolished)
5941 << qMakePair(&widget, QEvent::Move)
5942 << qMakePair(&widget, QEvent::Resize)
5943 << qMakePair(&widget, QEvent::Show);
5945 expected << qMakePair(&widget, QEvent::ShowToParent);
5946 QVERIFY2(spy.eventList() == expected,
5947 EventRecorder::msgEventListMismatch(expected, spy.eventList()).constData());
5950 QCoreApplication::sendPostedEvents();
5952 EventRecorder::EventList()
5953 << qMakePair(&widget, QEvent::PolishRequest)
5954 << qMakePair(&widget, QEvent::Type(QEvent::User + 1))
5955 << qMakePair(&widget, QEvent::Type(QEvent::User + 2));
5958 expected << qMakePair(&widget, QEvent::UpdateLater);
5960 expected << qMakePair(&widget, QEvent::UpdateRequest);
5962 if (m_platform == QStringLiteral("windows") || m_platform == QStringLiteral("xcb"))
5963 QEXPECT_FAIL("", EventRecorder::msgExpectFailQtBug26424(expected, spy.eventList()).constData(), Continue);
5964 QVERIFY2(spy.eventList() == expected,
5965 EventRecorder::msgEventListMismatch(expected, spy.eventList()).constData());
5969 class RenderWidget : public QWidget
5972 RenderWidget(QWidget *source)
5973 : source(source), ellipse(false) {}
5975 void setEllipseEnabled(bool enable = true)
5982 void paintEvent(QPaintEvent *)
5985 QPainter painter(this);
5986 painter.fillRect(rect(), Qt::red);
5988 QRegion regionToRender = QRegion(0, 0, source->width(), source->height() / 2,
5990 source->render(this, QPoint(0, 30), regionToRender);
5992 source->render(this);
6001 void tst_QWidget::render()
6004 QCalendarWidget source;
6005 // disable anti-aliasing to eliminate potential differences when subpixel antialiasing
6006 // is enabled on the screen
6008 f.setStyleStrategy(QFont::NoAntialias);
6011 QVERIFY(QTest::qWaitForWindowExposed(&source));
6013 // Render the entire source into target.
6014 RenderWidget target(&source);
6015 target.resize(source.size());
6018 qApp->processEvents();
6019 qApp->sendPostedEvents();
6022 const QImage sourceImage = source.grab(QRect(QPoint(0, 0), QSize(-1, -1))).toImage();
6023 qApp->processEvents();
6024 QImage targetImage = target.grab(QRect(QPoint(0, 0), QSize(-1, -1))).toImage();
6025 qApp->processEvents();
6026 QCOMPARE(sourceImage, targetImage);
6028 // Fill target.rect() will Qt::red and render
6029 // QRegion(0, 0, source->width(), source->height() / 2, QRegion::Ellipse)
6030 // of source into target with offset (0, 30).
6031 target.setEllipseEnabled();
6032 qApp->processEvents();
6033 qApp->sendPostedEvents();
6035 targetImage = target.grab(QRect(QPoint(0, 0), QSize(-1, -1))).toImage();
6036 QVERIFY(sourceImage != targetImage);
6038 QCOMPARE(targetImage.pixel(target.width() / 2, 29), QColor(Qt::red).rgb());
6039 QCOMPARE(targetImage.pixel(target.width() / 2, 30), sourceImage.pixel(source.width() / 2, 0));
6041 // Test that a child widget properly fills its background
6044 window.resize(100, 100);
6045 // prevent custom styles
6046 window.setStyle(QStyleFactory::create(QLatin1String("Windows")));
6048 QVERIFY(QTest::qWaitForWindowExposed(&window));
6049 QWidget child(&window);
6050 child.resize(window.size());
6053 qApp->processEvents();
6054 const QPixmap childPixmap = child.grab(QRect(QPoint(0, 0), QSize(-1, -1)));
6055 const QPixmap windowPixmap = window.grab(QRect(QPoint(0, 0), QSize(-1, -1)));
6056 QCOMPARE(childPixmap, windowPixmap);
6059 { // Check that the target offset is correct.
6061 widget.resize(200, 200);
6062 widget.setAutoFillBackground(true);
6063 widget.setPalette(Qt::red);
6064 // prevent custom styles
6065 widget.setStyle(QStyleFactory::create(QLatin1String("Windows")));
6067 QVERIFY(QTest::qWaitForWindowExposed(&widget));
6068 QImage image(widget.size(), QImage::Format_RGB32);
6069 image.fill(QColor(Qt::blue).rgb());
6071 // Target offset (0, 0)
6072 widget.render(&image, QPoint(), QRect(20, 20, 100, 100));
6073 QCOMPARE(image.pixel(0, 0), QColor(Qt::red).rgb());
6074 QCOMPARE(image.pixel(99, 99), QColor(Qt::red).rgb());
6075 QCOMPARE(image.pixel(100, 100), QColor(Qt::blue).rgb());
6077 // Target offset (20, 20).
6078 image.fill(QColor(Qt::blue).rgb());
6079 widget.render(&image, QPoint(20, 20), QRect(20, 20, 100, 100));
6080 QCOMPARE(image.pixel(0, 0), QColor(Qt::blue).rgb());
6081 QCOMPARE(image.pixel(19, 19), QColor(Qt::blue).rgb());
6082 QCOMPARE(image.pixel(20, 20), QColor(Qt::red).rgb());
6083 QCOMPARE(image.pixel(119, 119), QColor(Qt::red).rgb());
6084 QCOMPARE(image.pixel(120, 120), QColor(Qt::blue).rgb());
6088 // On Windows the active palette is used instead of the inactive palette even
6089 // though the widget is invisible. This is probably related to task 178507/168682,
6090 // but for the renderInvisible test it doesn't matter, we're mostly interested
6091 // in testing the geometry so just workaround the palette issue for now.
6092 static void workaroundPaletteIssue(QWidget *widget)
6100 QWidget *navigationBar = qFindChild<QWidget *>(widget, QLatin1String("qt_calendar_navigationbar"));
6101 QVERIFY(navigationBar);
6103 QPalette palette = navigationBar->palette();
6104 const QColor background = palette.color(QPalette::Inactive, navigationBar->backgroundRole());
6105 const QColor highlightedText = palette.color(QPalette::Inactive, QPalette::HighlightedText);
6106 palette.setColor(QPalette::Active, navigationBar->backgroundRole(), background);
6107 palette.setColor(QPalette::Active, QPalette::HighlightedText, highlightedText);
6108 navigationBar->setPalette(palette);
6111 //#define RENDER_DEBUG
6112 void tst_QWidget::renderInvisible()
6114 if (m_platform == QStringLiteral("xcb"))
6115 QSKIP("QTBUG-26424");
6117 QScopedPointer<QCalendarWidget> calendar(new QCalendarWidget);
6118 // disable anti-aliasing to eliminate potential differences when subpixel antialiasing
6119 // is enabled on the screen
6121 f.setStyleStrategy(QFont::NoAntialias);
6122 calendar->setFont(f);
6124 QVERIFY(QTest::qWaitForWindowExposed(calendar.data()));
6126 // Create a dummy focus widget to get rid of focus rect in reference image.
6127 QLineEdit dummyFocusWidget;
6128 dummyFocusWidget.show();
6129 QVERIFY(QTest::qWaitForWindowExposed(&dummyFocusWidget));
6130 qApp->processEvents();
6133 // Create normal reference image.
6134 const QSize calendarSize = calendar->size();
6135 QImage referenceImage(calendarSize, QImage::Format_ARGB32);
6136 calendar->render(&referenceImage);
6138 referenceImage.save("referenceImage.png");
6140 QVERIFY(!referenceImage.isNull());
6142 // Create resized reference image.
6143 const QSize calendarSizeResized = calendar->size() + QSize(50, 50);
6144 calendar->resize(calendarSizeResized);
6145 qApp->processEvents();
6147 QImage referenceImageResized(calendarSizeResized, QImage::Format_ARGB32);
6148 calendar->render(&referenceImageResized);
6150 referenceImageResized.save("referenceImageResized.png");
6152 QVERIFY(!referenceImageResized.isNull());
6154 // Explicitly hide the calendar.
6156 qApp->processEvents();
6158 workaroundPaletteIssue(calendar.data());
6160 { // Make sure we get the same image when the calendar is explicitly hidden.
6161 QImage testImage(calendarSizeResized, QImage::Format_ARGB32);
6162 calendar->render(&testImage);
6164 testImage.save("explicitlyHiddenCalendarResized.png");
6166 QCOMPARE(testImage, referenceImageResized);
6169 // Now that we have reference images we can delete the source and re-create
6170 // the calendar and check that we get the same images from a calendar which has never
6171 // been visible, laid out or created (Qt::WA_WState_Created).
6172 calendar.reset(new QCalendarWidget);
6173 calendar->setFont(f);
6174 workaroundPaletteIssue(calendar.data());
6176 { // Never been visible, created or laid out.
6177 QImage testImage(calendarSize, QImage::Format_ARGB32);
6178 calendar->render(&testImage);
6180 testImage.save("neverBeenVisibleCreatedOrLaidOut.png");
6182 QCOMPARE(testImage, referenceImage);
6186 qApp->processEvents();
6189 { // Calendar explicitly hidden.
6190 QImage testImage(calendarSize, QImage::Format_ARGB32);
6191 calendar->render(&testImage);
6193 testImage.save("explicitlyHiddenCalendar.png");
6195 QCOMPARE(testImage, referenceImage);
6198 // Get navigation bar and explicitly hide it.
6199 QWidget *navigationBar = qFindChild<QWidget *>(calendar.data(), QLatin1String("qt_calendar_navigationbar"));
6200 QVERIFY(navigationBar);
6201 navigationBar->hide();
6203 { // Check that the navigation bar isn't drawn when rendering the entire calendar.
6204 QImage testImage(calendarSize, QImage::Format_ARGB32);
6205 calendar->render(&testImage);
6207 testImage.save("calendarWithoutNavigationBar.png");
6209 QVERIFY(testImage != referenceImage);
6212 { // Make sure the navigation bar renders correctly even though it's hidden.
6213 QImage testImage(navigationBar->size(), QImage::Format_ARGB32);
6214 navigationBar->render(&testImage);
6216 testImage.save("explicitlyHiddenNavigationBar.png");
6218 QCOMPARE(testImage, referenceImage.copy(navigationBar->rect()));
6221 // Get next month button.
6222 QWidget *nextMonthButton = qFindChild<QWidget *>(navigationBar, QLatin1String("qt_calendar_nextmonth"));
6223 QVERIFY(nextMonthButton);
6225 { // Render next month button.
6226 // Fill test image with correct background color.
6227 QImage testImage(nextMonthButton->size(), QImage::Format_ARGB32);
6228 navigationBar->render(&testImage, QPoint(), QRegion(), QWidget::RenderFlags());
6230 testImage.save("nextMonthButtonBackground.png");
6233 // Set the button's background color to Qt::transparent; otherwise it will fill the
6234 // background with QPalette::Window.
6235 const QPalette originalPalette = nextMonthButton->palette();
6236 QPalette palette = originalPalette;
6237 palette.setColor(QPalette::Window, Qt::transparent);
6238 nextMonthButton->setPalette(palette);
6240 // Render the button on top of the background.
6241 nextMonthButton->render(&testImage);
6243 testImage.save("nextMonthButton.png");
6245 const QRect buttonRect(nextMonthButton->mapTo(calendar.data(), QPoint()), nextMonthButton->size());
6246 QCOMPARE(testImage, referenceImage.copy(buttonRect));
6249 nextMonthButton->setPalette(originalPalette);
6252 // Navigation bar isn't explicitly hidden anymore.
6253 navigationBar->show();
6254 qApp->processEvents();
6256 QVERIFY(!calendar->isVisible());
6258 // Now, completely mess up the layout. This will trigger an update on the layout
6259 // when the calendar is visible or shown, but it's not. QWidget::render must therefore
6260 // make sure the layout is activated before rendering.
6261 QVERIFY(!calendar->isVisible());
6262 calendar->resize(calendarSizeResized);
6263 qApp->processEvents();
6265 { // Make sure we get an image equal to the resized reference image.
6266 QImage testImage(calendarSizeResized, QImage::Format_ARGB32);
6267 calendar->render(&testImage);
6269 testImage.save("calendarResized.png");
6271 QCOMPARE(testImage, referenceImageResized);
6274 { // Make sure we lay out the widget correctly the first time it's rendered.
6275 QCalendarWidget calendar;
6276 const QSize calendarSize = calendar.sizeHint();
6278 QImage image(2 * calendarSize, QImage::Format_ARGB32);
6279 image.fill(QColor(Qt::red).rgb());
6280 calendar.render(&image);
6282 for (int i = calendarSize.height(); i < 2 * calendarSize.height(); ++i)
6283 for (int j = calendarSize.width(); j < 2 * calendarSize.width(); ++j)
6284 QCOMPARE(image.pixel(j, i), QColor(Qt::red).rgb());
6287 { // Ensure that we don't call adjustSize() on invisible top-levels if render() is called
6288 // right after widgets have been added/removed to/from its layout.
6290 topLevel.setLayout(new QVBoxLayout);
6292 QWidget *widget = new QLineEdit;
6293 topLevel.layout()->addWidget(widget);
6295 const QSize initialSize = topLevel.size();
6296 QPixmap pixmap(topLevel.sizeHint());
6297 topLevel.render(&pixmap); // triggers adjustSize()
6298 const QSize finalSize = topLevel.size();
6299 QVERIFY(finalSize != initialSize);
6301 topLevel.layout()->removeWidget(widget);
6302 QCOMPARE(topLevel.size(), finalSize);
6303 topLevel.render(&pixmap);
6304 QCOMPARE(topLevel.size(), finalSize);
6306 topLevel.layout()->addWidget(widget);
6307 QCOMPARE(topLevel.size(), finalSize);
6308 topLevel.render(&pixmap);
6309 QCOMPARE(topLevel.size(), finalSize);
6313 void tst_QWidget::renderWithPainter()
6315 QWidget widget(0, Qt::Tool);
6316 // prevent custom styles
6317 widget.setStyle(QStyleFactory::create(QLatin1String("Windows")));
6319 widget.resize(70, 50);
6320 widget.setAutoFillBackground(true);
6321 widget.setPalette(Qt::black);
6323 // Render the entire widget onto the image.
6324 QImage image(QSize(70, 50), QImage::Format_ARGB32);
6325 image.fill(QColor(Qt::red).rgb());
6326 QPainter painter(&image);
6327 widget.render(&painter);
6329 for (int i = 0; i < image.height(); ++i) {
6330 for (int j = 0; j < image.width(); ++j)
6331 QCOMPARE(image.pixel(j, i), QColor(Qt::black).rgb());
6334 // Translate painter (10, 10).
6336 image.fill(QColor(Qt::red).rgb());
6337 painter.translate(10, 10);
6338 widget.render(&painter);
6341 for (int i = 0; i < image.height(); ++i) {
6342 for (int j = 0; j < image.width(); ++j) {
6343 if (i < 10 || j < 10)
6344 QCOMPARE(image.pixel(j, i), QColor(Qt::red).rgb());
6346 QCOMPARE(image.pixel(j, i), QColor(Qt::black).rgb());
6350 // Pass target offset (10, 10) (the same as QPainter::translate).
6351 image.fill(QColor(Qt::red).rgb());
6352 widget.render(&painter, QPoint(10, 10));
6354 for (int i = 0; i < image.height(); ++i) {
6355 for (int j = 0; j < image.width(); ++j) {
6356 if (i < 10 || j < 10)
6357 QCOMPARE(image.pixel(j, i), QColor(Qt::red).rgb());
6359 QCOMPARE(image.pixel(j, i), QColor(Qt::black).rgb());
6363 // Translate (10, 10) and pass target offset (10, 10).
6365 image.fill(QColor(Qt::red).rgb());
6366 painter.translate(10, 10);
6367 widget.render(&painter, QPoint(10, 10));
6370 for (int i = 0; i < image.height(); ++i) {
6371 for (int j = 0; j < image.width(); ++j) {
6372 if (i < 20 || j < 20)
6373 QCOMPARE(image.pixel(j, i), QColor(Qt::red).rgb());
6375 QCOMPARE(image.pixel(j, i), QColor(Qt::black).rgb());
6379 // Rotate painter 90 degrees.
6381 image.fill(QColor(Qt::red).rgb());
6383 widget.render(&painter);
6386 for (int i = 0; i < image.height(); ++i) {
6387 for (int j = 0; j < image.width(); ++j)
6388 QCOMPARE(image.pixel(j, i), QColor(Qt::red).rgb());
6391 // Translate and rotate.
6392 image.fill(QColor(Qt::red).rgb());
6393 widget.resize(40, 10);
6394 painter.translate(10, 10);
6396 widget.render(&painter);
6398 for (int i = 0; i < image.height(); ++i) {
6399 for (int j = 0; j < image.width(); ++j) {
6400 if (i >= 10 && j >= 0 && j < 10)
6401 QCOMPARE(image.pixel(j, i), QColor(Qt::black).rgb());
6403 QCOMPARE(image.pixel(j, i), QColor(Qt::red).rgb());
6407 // Make sure QWidget::render does not modify the render hints set on the painter.
6408 painter.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform
6409 | QPainter::NonCosmeticDefaultPen | QPainter::TextAntialiasing);
6410 QPainter::RenderHints oldRenderHints = painter.renderHints();
6411 widget.render(&painter);
6412 QCOMPARE(painter.renderHints(), oldRenderHints);
6415 void tst_QWidget::render_task188133()
6417 QMainWindow mainWindow;
6419 // Make sure QWidget::render does not trigger QWidget::repaint/update
6420 // and asserts for Qt::WA_WState_Created.
6421 const QPixmap pixmap = mainWindow.grab(QRect(QPoint(0, 0), QSize(-1, -1)));
6425 void tst_QWidget::render_task211796()
6427 class MyWidget : public QWidget
6429 void resizeEvent(QResizeEvent *)
6431 QPixmap pixmap(size());
6436 { // Please don't die in a resize recursion.
6438 widget.resize(200, 200);
6442 { // Same check with a deeper hierarchy.
6445 QWidget child(&widget);
6446 MyWidget grandChild;
6447 grandChild.setParent(&child);
6448 grandChild.resize(100, 100);
6453 void tst_QWidget::render_task217815()
6455 // Make sure we don't change the size of the widget when calling
6456 // render() and the widget has an explicit size set.
6457 // This was a problem on Windows because we called createWinId(),
6458 // which in turn enforced the size to be bigger than the smallest
6459 // possible native window size (which is (115,something) on WinXP).
6461 const QSize explicitSize(80, 20);
6462 widget.resize(explicitSize);
6463 QCOMPARE(widget.size(), explicitSize);
6465 QPixmap pixmap(explicitSize);
6466 widget.render(&pixmap);
6468 QCOMPARE(widget.size(), explicitSize);
6471 // Window Opacity is not supported on Windows CE.
6473 void tst_QWidget::render_windowOpacity()
6475 const qreal opacity = 0.5;
6477 { // Check that the painter opacity effects the widget drawing.
6479 QWidget child(&topLevel);
6480 child.resize(50, 50);
6481 child.setPalette(Qt::red);
6482 child.setAutoFillBackground(true);
6484 QPixmap expected(child.size());
6486 if (m_platform == QStringLiteral("xcb") && expected.depth() < 24)
6487 QSKIP("This test won't give correct results with dithered pixmaps");
6489 expected.fill(Qt::green);
6490 QPainter painter(&expected);
6491 painter.setOpacity(opacity);
6492 painter.fillRect(QRect(QPoint(0, 0), child.size()), Qt::red);
6495 QPixmap result(child.size());
6496 result.fill(Qt::green);
6497 painter.begin(&result);
6498 painter.setOpacity(opacity);
6499 child.render(&painter);
6501 QCOMPARE(result, expected);
6504 { // Combine the opacity set on the painter with the widget opacity.
6505 class MyWidget : public QWidget
6508 void paintEvent(QPaintEvent *)
6510 QPainter painter(this);
6511 painter.setOpacity(opacity);
6512 QCOMPARE(painter.opacity(), opacity);
6513 painter.fillRect(rect(), Qt::red);
6519 widget.resize(50, 50);
6520 widget.opacity = opacity;
6521 widget.setPalette(Qt::blue);
6522 widget.setAutoFillBackground(true);
6524 QPixmap expected(widget.size());
6525 expected.fill(Qt::green);
6526 QPainter painter(&expected);
6527 painter.setOpacity(opacity);
6528 QPixmap pixmap(widget.size());
6529 pixmap.fill(Qt::blue);
6530 QPainter pixmapPainter(&pixmap);
6531 pixmapPainter.setOpacity(opacity);
6532 pixmapPainter.fillRect(QRect(QPoint(), widget.size()), Qt::red);
6533 painter.drawPixmap(QPoint(), pixmap);
6536 QPixmap result(widget.size());
6537 result.fill(Qt::green);
6538 painter.begin(&result);
6539 painter.setOpacity(opacity);
6540 widget.render(&painter);
6542 QCOMPARE(result, expected);
6547 void tst_QWidget::render_systemClip()
6550 widget.setPalette(Qt::blue);
6551 widget.resize(100, 100);
6553 QImage image(widget.size(), QImage::Format_RGB32);
6554 image.fill(QColor(Qt::red).rgb());
6556 QPaintEngine *paintEngine = image.paintEngine();
6557 QVERIFY(paintEngine);
6558 paintEngine->setSystemClip(QRegion(0, 0, 50, 50));
6560 QPainter painter(&image);
6561 // Make sure we're using the same paint engine and has the right clip set.
6562 QCOMPARE(painter.paintEngine(), paintEngine);
6563 QCOMPARE(paintEngine->systemClip(), QRegion(0, 0, 50, 50));
6565 // Translate painter outside system clip.
6566 painter.translate(50, 0);
6567 widget.render(&painter);
6570 image.save("outside_systemclip.png");
6573 // All pixels should be red.
6574 for (int i = 0; i < image.height(); ++i) {
6575 for (int j = 0; j < image.width(); ++j)
6576 QCOMPARE(image.pixel(j, i), QColor(Qt::red).rgb());
6579 // Restore painter and refill image with red.
6580 image.fill(QColor(Qt::red).rgb());
6581 painter.translate(-50, 0);
6583 // Set transform on the painter.
6584 QTransform transform;
6585 transform.shear(0, 1);
6586 painter.setTransform(transform);
6587 widget.render(&painter);
6590 image.save("blue_triangle.png");
6593 // We should now have a blue triangle starting at scan line 1, and the rest should be red.
6603 for (int i = 0; i < image.height(); ++i) {
6604 for (int j = 0; j < image.width(); ++j) {
6605 if (i < 50 && j < i)
6606 QCOMPARE(image.pixel(j, i), QColor(Qt::blue).rgb());
6608 QCOMPARE(image.pixel(j, i), QColor(Qt::red).rgb());
6612 // We don't paint directly on the image on the Mac, so we cannot do the pixel comparison
6613 // as above due to QPainter::SmoothPixmapTransform. We therefore need to generate an
6614 // expected image by first painting on a pixmap, and then draw the pixmap onto
6615 // the image using QPainter::SmoothPixmapTransform. Then we can compare pixels :)
6616 // The check is basically the same, except that it takes the smoothening into account.
6617 QPixmap pixmap(50, 50);
6618 const QRegion sysClip(0, 0, 50, 50);
6619 widget.render(&pixmap, QPoint(), sysClip);
6621 QImage expectedImage(widget.size(), QImage::Format_RGB32);
6622 expectedImage.fill(QColor(Qt::red).rgb());
6623 expectedImage.paintEngine()->setSystemClip(sysClip);
6625 QPainter expectedImagePainter(&expectedImage);
6626 expectedImagePainter.setTransform(QTransform().shear(0, 1));
6627 // NB! This is the important part (SmoothPixmapTransform).
6628 expectedImagePainter.setRenderHints(QPainter::SmoothPixmapTransform);
6629 expectedImagePainter.drawPixmap(QPoint(0, 0), pixmap);
6630 expectedImagePainter.end();
6632 QCOMPARE(image, expectedImage);
6636 void tst_QWidget::render_systemClip2_data()
6638 QTest::addColumn<bool>("autoFillBackground");
6639 QTest::addColumn<bool>("usePaintEvent");
6640 QTest::addColumn<QColor>("expectedColor");
6642 QTest::newRow("Only auto-fill background") << true << false << QColor(Qt::blue);
6643 QTest::newRow("Only draw in paintEvent") << false << true << QColor(Qt::green);
6644 QTest::newRow("Auto-fill background and draw in paintEvent") << true << true << QColor(Qt::green);
6647 void tst_QWidget::render_systemClip2()
6649 QFETCH(bool, autoFillBackground);
6650 QFETCH(bool, usePaintEvent);
6651 QFETCH(QColor, expectedColor);
6653 QVERIFY2(expectedColor != QColor(Qt::red), "Qt::red is the reference color for the image, pick another color");
6655 class MyWidget : public QWidget
6659 void paintEvent(QPaintEvent *)
6662 QPainter(this).fillRect(rect(), Qt::green);
6667 widget.usePaintEvent = usePaintEvent;
6668 widget.setPalette(Qt::blue);
6669 // NB! widget.setAutoFillBackground(autoFillBackground) won't do the
6670 // trick here since the widget is a top-level. The background is filled
6671 // regardless, unless Qt::WA_OpaquePaintEvent or Qt::WA_NoSystemBackground
6672 // is set. We therefore use the opaque attribute to turn off auto-fill.
6673 if (!autoFillBackground)
6674 widget.setAttribute(Qt::WA_OpaquePaintEvent);
6675 widget.resize(100, 100);
6677 QImage image(widget.size(), QImage::Format_RGB32);
6678 image.fill(QColor(Qt::red).rgb());
6680 QPaintEngine *paintEngine = image.paintEngine();
6681 QVERIFY(paintEngine);
6683 QRegion systemClip(QRegion(50, 0, 50, 10));
6684 systemClip += QRegion(90, 10, 10, 40);
6685 paintEngine->setSystemClip(systemClip);
6687 // Render entire widget directly onto device.
6688 widget.render(&image);
6691 image.save("systemclip_with_device.png");
6693 // All pixels within the system clip should now be
6694 // the expectedColor, and the rest should be red.
6695 for (int i = 0; i < image.height(); ++i) {
6696 for (int j = 0; j < image.width(); ++j) {
6697 if (systemClip.contains(QPoint(j, i)))
6698 QCOMPARE(image.pixel(j, i), expectedColor.rgb());
6700 QCOMPARE(image.pixel(j, i), QColor(Qt::red).rgb());
6704 // Refill image with red.
6705 image.fill(QColor(Qt::red).rgb());
6706 paintEngine->setSystemClip(systemClip);
6708 // Do the same with an untransformed painter.
6709 QPainter painter(&image);
6710 //Make sure we're using the same paint engine and has the right clip set.
6711 QCOMPARE(painter.paintEngine(), paintEngine);
6712 QCOMPARE(paintEngine->systemClip(), systemClip);
6714 widget.render(&painter);
6717 image.save("systemclip_with_untransformed_painter.png");
6719 // All pixels within the system clip should now be
6720 // the expectedColor, and the rest should be red.
6721 for (int i = 0; i < image.height(); ++i) {
6722 for (int j = 0; j < image.width(); ++j) {
6723 if (systemClip.contains(QPoint(j, i)))
6724 QCOMPARE(image.pixel(j, i), expectedColor.rgb());
6726 QCOMPARE(image.pixel(j, i), QColor(Qt::red).rgb());
6731 void tst_QWidget::render_systemClip3_data()
6733 QTest::addColumn<QSize>("size");
6734 QTest::addColumn<bool>("useSystemClip");
6736 // Reference: http://en.wikipedia.org/wiki/Flag_of_Norway
6737 QTest::newRow("Norwegian Civil Flag") << QSize(220, 160) << false;
6738 QTest::newRow("Norwegian War Flag") << QSize(270, 160) << true;
6741 // This test ensures that the current engine clip (systemClip + painter clip)
6742 // is preserved after QPainter::setClipRegion(..., Qt::ReplaceClip);
6743 void tst_QWidget::render_systemClip3()
6745 QFETCH(QSize, size);
6746 QFETCH(bool, useSystemClip);
6748 // Calculate the inner/outer cross of the flag.
6749 QRegion outerCross(0, 0, size.width(), size.height());
6750 outerCross -= QRect(0, 0, 60, 60);
6751 outerCross -= QRect(100, 0, size.width() - 100, 60);
6752 outerCross -= QRect(0, 100, 60, 60);
6753 outerCross -= QRect(100, 100, size.width() - 100, 60);
6755 QRegion innerCross(0, 0, size.width(), size.height());
6756 innerCross -= QRect(0, 0, 70, 70);
6757 innerCross -= QRect(90, 0, size.width() - 90, 70);
6758 innerCross -= QRect(0, 90, 70, 70);
6759 innerCross -= QRect(90, 90, size.width() - 90, 70);
6761 const QRegion redArea(QRegion(0, 0, size.width(), size.height()) - outerCross);
6762 const QRegion whiteArea(outerCross - innerCross);
6763 const QRegion blueArea(innerCross);
6766 // Okay, here's the image that should look like a Norwegian civil/war flag in the end.
6767 QImage flag(size, QImage::Format_ARGB32);
6768 flag.fill(QColor(Qt::transparent).rgba());
6770 if (useSystemClip) {
6771 QPainterPath warClip(QPoint(size.width(), 0));
6772 warClip.lineTo(size.width() - 110, 60);
6773 warClip.lineTo(size.width(), 80);
6774 warClip.lineTo(size.width() - 110, 100);
6775 warClip.lineTo(size.width(), 160);
6776 warClip.closeSubpath();
6777 systemClip = QRegion(0, 0, size.width(), size.height()) - QRegion(warClip.toFillPolygon().toPolygon());
6778 flag.paintEngine()->setSystemClip(systemClip);
6781 QPainter painter(&flag);
6782 painter.fillRect(QRect(QPoint(), size), Qt::red); // Fill image background with red.
6783 painter.setClipRegion(outerCross); // Limit widget painting to inside the outer cross.
6785 // Here's the widget that's supposed to draw the inner/outer cross of the flag.
6786 // The outer cross (white) should be drawn when the background is auto-filled, and
6787 // the inner cross (blue) should be drawn in the paintEvent.
6788 class MyWidget : public QWidget
6790 void paintEvent(QPaintEvent *)
6792 QPainter painter(this);
6793 // Be evil and try to paint outside the outer cross. This should not be
6794 // possible since the shared painter is clipped to the outer cross.
6795 painter.setClipRect(0, 0, 60, 60, Qt::ReplaceClip);
6796 painter.fillRect(rect(), Qt::green);
6797 painter.setClipRegion(clip, Qt::ReplaceClip);
6798 painter.fillRect(rect(), Qt::blue);
6804 widget.clip = innerCross;
6805 widget.setFixedSize(size);
6806 widget.setPalette(Qt::white);
6807 widget.setAutoFillBackground(true);
6808 widget.render(&painter);
6811 flag.save("flag.png");
6814 // Let's make sure we got a Norwegian flag.
6815 for (int i = 0; i < flag.height(); ++i) {
6816 for (int j = 0; j < flag.width(); ++j) {
6817 const QPoint pixel(j, i);
6818 const QRgb pixelValue = flag.pixel(pixel);
6819 if (useSystemClip && !systemClip.contains(pixel))
6820 QCOMPARE(pixelValue, QColor(Qt::transparent).rgba());
6821 else if (redArea.contains(pixel))
6822 QCOMPARE(pixelValue, QColor(Qt::red).rgba());
6823 else if (whiteArea.contains(pixel))
6824 QCOMPARE(pixelValue, QColor(Qt::white).rgba());
6826 QCOMPARE(pixelValue, QColor(Qt::blue).rgba());
6831 void tst_QWidget::render_task252837()
6834 widget.resize(200, 200);
6836 QPixmap pixmap(widget.size());
6837 QPainter painter(&pixmap);
6838 // Please do not crash.
6839 widget.render(&painter);
6842 void tst_QWidget::render_worldTransform()
6844 class MyWidget : public QWidget
6846 void paintEvent(QPaintEvent *)
6848 QPainter painter(this);
6849 // Make sure world transform is identity.
6850 QCOMPARE(painter.worldTransform(), QTransform());
6852 // Make sure device transform is correct.
6853 const QPoint widgetOffset = geometry().topLeft();
6854 QTransform expectedDeviceTransform = QTransform::fromTranslate(105, 5);
6855 expectedDeviceTransform.rotate(90);
6856 expectedDeviceTransform.translate(widgetOffset.x(), widgetOffset.y());
6857 QCOMPARE(painter.deviceTransform(), expectedDeviceTransform);
6859 // Set new world transform.
6860 QTransform newWorldTransform = QTransform::fromTranslate(10, 10);
6861 newWorldTransform.rotate(90);
6862 painter.setWorldTransform(newWorldTransform);
6863 QCOMPARE(painter.worldTransform(), newWorldTransform);
6865 // Again, check device transform.
6866 expectedDeviceTransform.translate(10, 10);
6867 expectedDeviceTransform.rotate(90);
6868 QCOMPARE(painter.deviceTransform(), expectedDeviceTransform);
6870 painter.fillRect(QRect(0, 0, 20, 10), Qt::green);
6875 widget.setFixedSize(100, 100);
6876 widget.setPalette(Qt::red);
6877 widget.setAutoFillBackground(true);
6880 child.setParent(&widget);
6882 child.setFixedSize(50, 50);
6883 child.setPalette(Qt::blue);
6884 child.setAutoFillBackground(true);
6886 QImage image(QSize(110, 110), QImage::Format_RGB32);
6887 image.fill(QColor(Qt::black).rgb());
6889 QPainter painter(&image);
6890 painter.translate(105, 5);
6893 // Render widgets onto image.
6894 widget.render(&painter);
6896 image.save("render_worldTransform_image.png");
6899 // Ensure the transforms are unchanged after render.
6900 QCOMPARE(painter.worldTransform(), painter.worldTransform());
6901 QCOMPARE(painter.deviceTransform(), painter.deviceTransform());
6904 // Paint expected image.
6905 QImage expected(QSize(110, 110), QImage::Format_RGB32);
6906 expected.fill(QColor(Qt::black).rgb());
6908 QPainter expectedPainter(&expected);
6909 expectedPainter.translate(105, 5);
6910 expectedPainter.rotate(90);
6911 expectedPainter.save();
6912 expectedPainter.fillRect(widget.rect(),Qt::red);
6913 expectedPainter.translate(10, 10);
6914 expectedPainter.rotate(90);
6915 expectedPainter.fillRect(QRect(0, 0, 20, 10), Qt::green);
6916 expectedPainter.restore();
6917 expectedPainter.translate(50, 50);
6918 expectedPainter.fillRect(child.rect(),Qt::blue);
6919 expectedPainter.translate(10, 10);
6920 expectedPainter.rotate(90);
6921 expectedPainter.fillRect(QRect(0, 0, 20, 10), Qt::green);
6922 expectedPainter.end();
6925 expected.save("render_worldTransform_expected.png");
6928 QCOMPARE(image, expected);
6931 void tst_QWidget::setContentsMargins()
6933 QLabel label("why does it always rain on me?");
6934 QSize oldSize = label.sizeHint();
6935 label.setFrameStyle(QFrame::Sunken | QFrame::Box);
6936 QSize newSize = label.sizeHint();
6937 QVERIFY(oldSize != newSize);
6939 QLabel label2("why does it always rain on me?");
6941 label2.setFrameStyle(QFrame::Sunken | QFrame::Box);
6942 QCOMPARE(newSize, label2.sizeHint());
6944 QLabel label3("why does it always rain on me?");
6945 label3.setFrameStyle(QFrame::Sunken | QFrame::Box);
6946 QCOMPARE(newSize, label3.sizeHint());
6949 void tst_QWidget::moveWindowInShowEvent_data()
6951 QTest::addColumn<QPoint>("initial");
6952 QTest::addColumn<QPoint>("position");
6954 QPoint p = QApplication::desktop()->availableGeometry().topLeft();
6956 QTest::newRow("1") << p << (p + QPoint(10, 10));
6957 QTest::newRow("2") << (p + QPoint(10,10)) << p;
6960 void tst_QWidget::moveWindowInShowEvent()
6962 if (m_platform == QStringLiteral("xcb"))
6963 QSKIP("QTBUG-26424");
6965 QFETCH(QPoint, initial);
6966 QFETCH(QPoint, position);
6968 class MoveWindowInShowEventWidget : public QWidget
6972 void showEvent(QShowEvent *)
6978 MoveWindowInShowEventWidget widget;
6979 widget.resize(QSize(qApp->desktop()->availableGeometry().size() / 3).expandedTo(QSize(1, 1)));
6980 // move to this position in showEvent()
6981 widget.position = position;
6983 // put the widget in it's starting position
6984 widget.move(initial);
6985 QCOMPARE(widget.pos(), initial);
6989 QVERIFY(QTest::qWaitForWindowShown(&widget));
6991 // it should have moved
6992 QCOMPARE(widget.pos(), position);
6995 void tst_QWidget::repaintWhenChildDeleted()
6998 if (QSysInfo::WindowsVersion & QSysInfo::WV_VISTA) {
7002 ColorWidget w(0, Qt::red);
7003 #if !defined(Q_OS_WINCE)
7004 QPoint startPoint = QApplication::desktop()->availableGeometry(&w).topLeft();
7005 startPoint.rx() += 50;
7006 startPoint.ry() += 50;
7007 w.setGeometry(QRect(startPoint, QSize(100, 100)));
7009 w.setGeometry(60, 60, 110, 110);
7012 QVERIFY(QTest::qWaitForWindowExposed(&w));
7014 QTRY_COMPARE(w.r, QRegion(w.rect()));
7018 ColorWidget child(&w, Qt::blue);
7019 child.setGeometry(10, 10, 10, 10);
7022 QTRY_COMPARE(child.r, QRegion(child.rect()));
7027 QTRY_COMPARE(w.r, QRegion(10, 10, 10, 10));
7031 void tst_QWidget::hideOpaqueChildWhileHidden()
7033 ColorWidget w(0, Qt::red);
7034 #if !defined(Q_OS_WINCE)
7035 QPoint startPoint = QApplication::desktop()->availableGeometry(&w).topLeft();
7036 startPoint.rx() += 50;
7037 startPoint.ry() += 50;
7038 w.setGeometry(QRect(startPoint, QSize(100, 100)));
7040 w.setGeometry(60, 60, 110, 110);
7043 ColorWidget child(&w, Qt::blue);
7044 child.setGeometry(10, 10, 80, 80);
7046 ColorWidget child2(&child, Qt::white);
7047 child2.setGeometry(10, 10, 60, 60);
7050 QVERIFY(QTest::qWaitForWindowExposed(&w));
7052 QTRY_COMPARE(child2.r, QRegion(child2.rect()));
7053 child.r = QRegion();
7054 child2.r = QRegion();
7061 QCOMPARE(w.r, QRegion(child.geometry()));
7065 QCOMPARE(child.r, QRegion(child.rect()));
7066 QCOMPARE(child2.r, QRegion());
7069 // This test doesn't make sense without support for showMinimized().
7070 #if !defined(Q_OS_WINCE)
7071 void tst_QWidget::updateWhileMinimized()
7073 UpdateWidget widget;
7074 // Filter out activation change and focus events to avoid update() calls in QWidget.
7075 widget.updateOnActivationChangeAndFocusIn = false;
7078 QVERIFY(QTest::qWaitForWindowExposed(&widget));
7079 QApplication::processEvents();
7080 QTRY_VERIFY(widget.numPaintEvents > 0);
7084 widget.showMinimized();
7089 // The widget is not visible on the screen (but isVisible() still returns true).
7090 // Make sure update requests are discarded until the widget is shown again.
7091 widget.update(0, 0, 50, 50);
7093 if (m_platform == QStringLiteral("windows"))
7094 QEXPECT_FAIL("", "QTBUG-26424", Continue);
7095 QCOMPARE(widget.numPaintEvents, 0);
7098 widget.showNormal();
7100 if (m_platform == QStringLiteral("xcb"))
7101 QSKIP("QTBUG-26424");
7102 QTRY_COMPARE(widget.numPaintEvents, 1);
7103 QCOMPARE(widget.paintedRegion, QRegion(0, 0, 50, 50));
7107 class PaintOnScreenWidget: public QWidget
7110 PaintOnScreenWidget(QWidget *parent = 0, Qt::WindowFlags f = 0)
7114 #if defined(Q_OS_WIN)
7115 // This is the only way to enable PaintOnScreen on Windows.
7116 QPaintEngine * paintEngine () const {return 0;}
7120 void tst_QWidget::alienWidgets()
7122 if (m_platform != QStringLiteral("xcb") && m_platform != QStringLiteral("windows"))
7123 QSKIP("This test is only for X11/Windows.");
7125 qApp->setAttribute(Qt::AA_DontCreateNativeWidgetSiblings);
7127 parent.resize(200, 200);
7128 QWidget child(&parent);
7129 QWidget grandChild(&child);
7130 QWidget greatGrandChild(&grandChild);
7133 QVERIFY(QTest::qWaitForWindowExposed(&parent));
7135 // Verify that the WA_WState_Created attribute is set
7136 // and the top-level is the only native window.
7137 QVERIFY(parent.testAttribute(Qt::WA_WState_Created));
7138 QVERIFY(parent.internalWinId());
7140 QVERIFY(child.testAttribute(Qt::WA_WState_Created));
7141 QVERIFY(!child.internalWinId());
7143 QVERIFY(grandChild.testAttribute(Qt::WA_WState_Created));
7144 QVERIFY(!grandChild.internalWinId());
7146 QVERIFY(greatGrandChild.testAttribute(Qt::WA_WState_Created));
7147 QVERIFY(!greatGrandChild.internalWinId());
7149 // Enforce native windows all the way up in the parent hierarchy
7150 // if not WA_DontCreateNativeAncestors is set.
7151 grandChild.setAttribute(Qt::WA_DontCreateNativeAncestors);
7152 greatGrandChild.setAttribute(Qt::WA_NativeWindow);
7153 QVERIFY(greatGrandChild.internalWinId());
7154 QVERIFY(grandChild.internalWinId());
7155 QVERIFY(!child.internalWinId());
7158 // Ensure that hide() on an ancestor of a widget with
7159 // Qt::WA_DontCreateNativeAncestors still gets unmapped
7161 window.resize(200, 200);
7162 QWidget widget(&window);
7163 QWidget child(&widget);
7164 child.setAttribute(Qt::WA_NativeWindow);
7165 child.setAttribute(Qt::WA_DontCreateNativeAncestors);
7167 QVERIFY(QTest::qWaitForWindowExposed(&window));
7168 QTRY_VERIFY(child.testAttribute(Qt::WA_Mapped));
7170 QTRY_VERIFY(!child.testAttribute(Qt::WA_Mapped));
7173 // Enforce a native window when calling QWidget::winId.
7174 QVERIFY(child.winId());
7175 QVERIFY(child.internalWinId());
7177 // Check that paint on screen widgets (incl. children) are native.
7178 PaintOnScreenWidget paintOnScreen(&parent);
7179 QWidget paintOnScreenChild(&paintOnScreen);
7180 paintOnScreen.show();
7181 QVERIFY(paintOnScreen.testAttribute(Qt::WA_WState_Created));
7182 QVERIFY(!paintOnScreen.testAttribute(Qt::WA_NativeWindow));
7183 QVERIFY(!paintOnScreen.internalWinId());
7184 QVERIFY(!paintOnScreenChild.testAttribute(Qt::WA_NativeWindow));
7185 QVERIFY(!paintOnScreenChild.internalWinId());
7187 paintOnScreen.setAttribute(Qt::WA_PaintOnScreen);
7188 if (m_platform == QStringLiteral("xcb") || m_platform == QStringLiteral("windows"))
7189 QEXPECT_FAIL("", "QTBUG-26424", Continue);
7190 QVERIFY(paintOnScreen.testAttribute(Qt::WA_NativeWindow));
7191 if (m_platform == QStringLiteral("xcb") || m_platform == QStringLiteral("windows"))
7192 QEXPECT_FAIL("", "QTBUG-26424", Continue);
7193 QVERIFY(paintOnScreen.internalWinId());
7194 if (m_platform == QStringLiteral("xcb") || m_platform == QStringLiteral("windows"))
7195 QEXPECT_FAIL("", "QTBUG-26424", Continue);
7196 QVERIFY(paintOnScreenChild.testAttribute(Qt::WA_NativeWindow));
7197 if (m_platform == QStringLiteral("xcb") || m_platform == QStringLiteral("windows"))
7198 QEXPECT_FAIL("", "QTBUG-26424", Continue);
7199 QVERIFY(paintOnScreenChild.internalWinId());
7201 // Check that widgets with the Qt::MSWindowsOwnDC attribute set
7203 QWidget msWindowsOwnDC(&parent, Qt::MSWindowsOwnDC);
7204 msWindowsOwnDC.show();
7205 QVERIFY(msWindowsOwnDC.testAttribute(Qt::WA_WState_Created));
7206 QVERIFY(msWindowsOwnDC.testAttribute(Qt::WA_NativeWindow));
7207 QVERIFY(msWindowsOwnDC.internalWinId());
7209 { // Enforce a native window when calling QWidget::handle() (on X11) or QWidget::getDC() (on Windows).
7210 QWidget widget(&parent);
7212 QVERIFY(widget.testAttribute(Qt::WA_WState_Created));
7213 QVERIFY(!widget.internalWinId());
7216 QVERIFY(widget.internalWinId());
7219 if (m_platform == QStringLiteral("xcb")) {
7220 // Make sure we don't create native windows when setting Qt::WA_X11NetWmWindowType attributes
7221 // on alien widgets (see task 194231).
7223 dummy.resize(200, 200);
7224 QVERIFY(dummy.winId());
7225 QWidget widget(&dummy);
7226 widget.setAttribute(Qt::WA_X11NetWmWindowTypeToolBar);
7227 QVERIFY(!widget.internalWinId());
7230 { // Make sure we create native ancestors when setting Qt::WA_PaintOnScreen before show().
7232 topLevel.resize(200, 200);
7233 QWidget child(&topLevel);
7234 QWidget grandChild(&child);
7235 PaintOnScreenWidget greatGrandChild(&grandChild);
7237 greatGrandChild.setAttribute(Qt::WA_PaintOnScreen);
7238 QVERIFY(!child.internalWinId());
7239 QVERIFY(!grandChild.internalWinId());
7240 QVERIFY(!greatGrandChild.internalWinId());
7243 if (m_platform == QStringLiteral("xcb") || m_platform == QStringLiteral("windows"))
7244 QEXPECT_FAIL("", "QTBUG-26424", Continue);
7245 QVERIFY(child.internalWinId());
7246 if (m_platform == QStringLiteral("xcb") || m_platform == QStringLiteral("windows"))
7247 QEXPECT_FAIL("", "QTBUG-26424", Continue);
7248 QVERIFY(grandChild.internalWinId());
7249 if (m_platform == QStringLiteral("xcb") || m_platform == QStringLiteral("windows"))
7250 QEXPECT_FAIL("", "QTBUG-26424", Continue);
7251 QVERIFY(greatGrandChild.internalWinId());
7254 { // Ensure that widgets reparented into Qt::WA_PaintOnScreen widgets become native.
7256 topLevel.resize(200, 200);
7257 QWidget *widget = new PaintOnScreenWidget(&topLevel);
7258 widget->setAttribute(Qt::WA_PaintOnScreen);
7259 QWidget *child = new QWidget;
7260 QWidget *dummy = new QWidget(child);
7261 QWidget *grandChild = new QWidget(child);
7262 QWidget *dummy2 = new QWidget(grandChild);
7264 child->setParent(widget);
7266 QVERIFY(!topLevel.internalWinId());
7267 QVERIFY(!child->internalWinId());
7268 QVERIFY(!dummy->internalWinId());
7269 QVERIFY(!grandChild->internalWinId());
7270 QVERIFY(!dummy2->internalWinId());
7273 QVERIFY(topLevel.internalWinId());
7274 QVERIFY(widget->testAttribute(Qt::WA_NativeWindow));
7275 QVERIFY(child->internalWinId());
7276 QVERIFY(child->testAttribute(Qt::WA_NativeWindow));
7277 QVERIFY(!child->testAttribute(Qt::WA_PaintOnScreen));
7278 QVERIFY(!dummy->internalWinId());
7279 QVERIFY(!dummy->testAttribute(Qt::WA_NativeWindow));
7280 QVERIFY(!grandChild->internalWinId());
7281 QVERIFY(!grandChild->testAttribute(Qt::WA_NativeWindow));
7282 QVERIFY(!dummy2->internalWinId());
7283 QVERIFY(!dummy2->testAttribute(Qt::WA_NativeWindow));
7286 { // Ensure that ancestors of a Qt::WA_PaintOnScreen widget stay native
7287 // if they are re-created (typically in QWidgetPrivate::setParent_sys) (task 210822).
7289 window.resize(200, 200);
7290 QWidget child(&window);
7293 grandChild.setWindowTitle("This causes the widget to be created");
7295 PaintOnScreenWidget paintOnScreenWidget;
7296 paintOnScreenWidget.setAttribute(Qt::WA_PaintOnScreen);
7297 paintOnScreenWidget.setParent(&grandChild);
7299 grandChild.setParent(&child);
7303 QVERIFY(window.internalWinId());
7304 if (m_platform == QStringLiteral("xcb") || m_platform == QStringLiteral("windows"))
7305 QEXPECT_FAIL("", "QTBUG-26424", Continue);
7306 QVERIFY(child.internalWinId());
7307 if (m_platform == QStringLiteral("xcb") || m_platform == QStringLiteral("windows"))
7308 QEXPECT_FAIL("", "QTBUG-26424", Continue);
7309 QVERIFY(child.testAttribute(Qt::WA_NativeWindow));
7310 if (m_platform == QStringLiteral("xcb") || m_platform == QStringLiteral("windows"))
7311 QEXPECT_FAIL("", "QTBUG-26424", Continue);
7312 QVERIFY(grandChild.internalWinId());
7313 if (m_platform == QStringLiteral("xcb") || m_platform == QStringLiteral("windows"))
7314 QEXPECT_FAIL("", "QTBUG-26424", Continue);
7315 QVERIFY(grandChild.testAttribute(Qt::WA_NativeWindow));
7316 if (m_platform == QStringLiteral("xcb") || m_platform == QStringLiteral("windows"))
7317 QEXPECT_FAIL("", "QTBUG-26424", Continue);
7318 QVERIFY(paintOnScreenWidget.internalWinId());
7319 if (m_platform == QStringLiteral("xcb") || m_platform == QStringLiteral("windows"))
7320 QEXPECT_FAIL("", "QTBUG-26424", Continue);
7321 QVERIFY(paintOnScreenWidget.testAttribute(Qt::WA_NativeWindow));
7324 { // Ensure that all siblings are native unless Qt::AA_DontCreateNativeWidgetSiblings is set.
7325 qApp->setAttribute(Qt::AA_DontCreateNativeWidgetSiblings, false);
7327 QWidget *toolBar = new QWidget(&mainWindow);
7328 QWidget *dockWidget = new QWidget(&mainWindow);
7329 QWidget *centralWidget = new QWidget(&mainWindow);
7331 QWidget *button = new QWidget(centralWidget);
7332 QWidget *mdiArea = new QWidget(centralWidget);
7334 QWidget *horizontalScroll = new QWidget(mdiArea);
7335 QWidget *verticalScroll = new QWidget(mdiArea);
7336 QWidget *viewport = new QWidget(mdiArea);
7338 viewport->setAttribute(Qt::WA_NativeWindow);
7341 // Ensure that the viewport and its siblings are native:
7342 QVERIFY(verticalScroll->testAttribute(Qt::WA_NativeWindow));
7343 QVERIFY(verticalScroll->testAttribute(Qt::WA_NativeWindow));
7344 QVERIFY(horizontalScroll->testAttribute(Qt::WA_NativeWindow));
7346 // Ensure that the mdi area and its siblings are native:
7347 QVERIFY(mdiArea->testAttribute(Qt::WA_NativeWindow));
7348 QVERIFY(button->testAttribute(Qt::WA_NativeWindow));
7350 // Ensure that the central widget and its siblings are native:
7351 QVERIFY(centralWidget->testAttribute(Qt::WA_NativeWindow));
7352 QVERIFY(dockWidget->testAttribute(Qt::WA_NativeWindow));
7353 QVERIFY(toolBar->testAttribute(Qt::WA_NativeWindow));
7357 class ASWidget : public QWidget
7360 ASWidget(QSize sizeHint, QSizePolicy sizePolicy, bool layout, bool hfwLayout, QWidget *parent = 0)
7361 : QWidget(parent), mySizeHint(sizeHint)
7363 setObjectName(QStringLiteral("ASWidget"));
7364 setWindowTitle(objectName());
7365 setSizePolicy(sizePolicy);
7367 QSizePolicy sp = QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
7368 sp.setHeightForWidth(hfwLayout);
7370 QVBoxLayout *vbox = new QVBoxLayout;
7372 vbox->addWidget(new ASWidget(sizeHint + QSize(30, 20), sp, false, false));
7377 QSize sizeHint() const {
7379 return layout()->totalSizeHint();
7382 int heightForWidth(int width) const {
7383 if (sizePolicy().hasHeightForWidth()) {
7393 void tst_QWidget::adjustSize_data()
7395 const int MagicW = 200;
7396 const int MagicH = 100;
7398 QTest::addColumn<QSize>("sizeHint");
7399 QTest::addColumn<int>("hPolicy");
7400 QTest::addColumn<int>("vPolicy");
7401 QTest::addColumn<bool>("hfwSP");
7402 QTest::addColumn<bool>("layout");
7403 QTest::addColumn<bool>("hfwLayout");
7404 QTest::addColumn<bool>("haveParent");
7405 QTest::addColumn<QSize>("expectedSize");
7407 QTest::newRow("1") << QSize(5, 6) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
7408 << false << false << false << false << QSize(5, qMax(6, MagicH));
7409 QTest::newRow("2") << QSize(5, 6) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
7410 << true << false << false << false << QSize(5, qMax(10, MagicH));
7411 QTest::newRow("3") << QSize(5, 6) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
7412 << false << true << false << false << QSize(35, 26);
7413 QTest::newRow("4") << QSize(5, 6) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
7414 << false << true << true << false << QSize(35, 70);
7415 QTest::newRow("5") << QSize(40001, 30001) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
7416 << false << false << false << false << QSize(100000, 100000);
7417 QTest::newRow("6") << QSize(40001, 30001) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
7418 << true << false << false << false << QSize(100000, 100000);
7419 QTest::newRow("7") << QSize(40001, 30001) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
7420 << false << true << false << false << QSize(100000, 100000);
7421 QTest::newRow("8") << QSize(40001, 30001) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
7422 << false << true << true << false << QSize(100000, 100000);
7423 QTest::newRow("9") << QSize(5, 6) << int(QSizePolicy::Expanding) << int(QSizePolicy::Minimum)
7424 << true << false << false << false << QSize(qMax(5, MagicW), 10);
7426 QTest::newRow("1c") << QSize(5, 6) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
7427 << false << false << false << true << QSize(5, 6);
7428 QTest::newRow("2c") << QSize(5, 6) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
7429 << true << false << false << true << QSize(5, 6 /* or 10 would be OK too, since hfw contradicts sizeHint() */);
7430 QTest::newRow("3c") << QSize(5, 6) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
7431 << false << true << false << true << QSize(35, 26);
7432 QTest::newRow("4c") << QSize(5, 6) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
7433 << false << true << true << true << QSize(35, 70);
7434 QTest::newRow("5c") << QSize(40001, 30001) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
7435 << false << false << false << true << QSize(40001, 30001);
7436 QTest::newRow("6c") << QSize(40001, 30001) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
7437 << true << false << false << true << QSize(40001, 30001 /* or 80002 would be OK too, since hfw contradicts sizeHint() */);
7438 QTest::newRow("7c") << QSize(40001, 30001) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
7439 << false << true << false << true << QSize(40001 + 30, 30001 + 20);
7440 QTest::newRow("8c") << QSize(40001, 30001) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
7441 << false << true << true << true << QSize(40001 + 30, 80002 + 60);
7442 QTest::newRow("9c") << QSize(5, 6) << int(QSizePolicy::Expanding) << int(QSizePolicy::Minimum)
7443 << true << false << false << true << QSize(5, 6);
7446 void tst_QWidget::adjustSize()
7448 QFETCH(QSize, sizeHint);
7449 QFETCH(int, hPolicy);
7450 QFETCH(int, vPolicy);
7451 QFETCH(bool, hfwSP);
7452 QFETCH(bool, layout);
7453 QFETCH(bool, hfwLayout);
7454 QFETCH(bool, haveParent);
7455 QFETCH(QSize, expectedSize);
7457 QScopedPointer<QWidget> parent(new QWidget);
7459 QSizePolicy sp = QSizePolicy(QSizePolicy::Policy(hPolicy), QSizePolicy::Policy(vPolicy));
7460 sp.setHeightForWidth(hfwSP);
7462 QWidget *child = new ASWidget(sizeHint, sp, layout, hfwLayout, haveParent ? parent.data() : 0);
7463 child->resize(123, 456);
7464 child->adjustSize();
7465 if (expectedSize == QSize(100000, 100000)) {
7466 QVERIFY(child->size().width() < sizeHint.width());
7467 QVERIFY(child->size().height() < sizeHint.height());
7469 #if defined (Q_OS_WINCE)
7471 const QRect& desktopRect = qApp->desktop()->availableGeometry();
7472 expectedSize.setWidth(qMin(expectedSize.width(), desktopRect.width()));
7473 expectedSize.setHeight(qMin(expectedSize.height(), desktopRect.height()));
7476 QCOMPARE(child->size(), expectedSize);
7482 class TestLayout : public QVBoxLayout
7486 TestLayout(QWidget *w = 0) : QVBoxLayout(w)
7488 invalidated = false;
7499 void tst_QWidget::updateGeometry_data()
7501 QTest::addColumn<QSize>("minSize");
7502 QTest::addColumn<bool>("shouldInvalidate");
7503 QTest::addColumn<QSize>("maxSize");
7504 QTest::addColumn<bool>("shouldInvalidate2");
7505 QTest::addColumn<int>("verticalSizePolicy");
7506 QTest::addColumn<bool>("shouldInvalidate3");
7507 QTest::addColumn<bool>("setVisible");
7508 QTest::addColumn<bool>("shouldInvalidate4");
7510 QTest::newRow("setMinimumSize")
7511 << QSize(100, 100) << true
7513 << int(QSizePolicy::Preferred) << false
7515 QTest::newRow("setMaximumSize")
7517 << QSize(100, 100) << true
7518 << int(QSizePolicy::Preferred) << false
7520 QTest::newRow("setMinimumSize, then maximumSize to a different size")
7521 << QSize(100, 100) << true
7522 << QSize(300, 300) << true
7523 << int(QSizePolicy::Preferred) << false
7525 QTest::newRow("setMinimumSize, then maximumSize to the same size")
7526 << QSize(100, 100) << true
7527 << QSize(100, 100) << true
7528 << int(QSizePolicy::Preferred) << false
7530 QTest::newRow("setMinimumSize, then maximumSize to the same size and then hide it")
7531 << QSize(100, 100) << true
7532 << QSize(100, 100) << true
7533 << int(QSizePolicy::Preferred) << false
7535 QTest::newRow("Change sizePolicy")
7538 << int(QSizePolicy::Minimum) << true
7543 void tst_QWidget::updateGeometry()
7545 QFETCH(QSize, minSize);
7546 QFETCH(bool, shouldInvalidate);
7547 QFETCH(QSize, maxSize);
7548 QFETCH(bool, shouldInvalidate2);
7549 QFETCH(int, verticalSizePolicy);
7550 QFETCH(bool, shouldInvalidate3);
7551 QFETCH(bool, setVisible);
7552 QFETCH(bool, shouldInvalidate4);
7554 parent.resize(200, 200);
7555 TestLayout *lout = new TestLayout();
7556 parent.setLayout(lout);
7557 QWidget *child = new QWidget(&parent);
7558 lout->addWidget(child);
7560 QApplication::processEvents();
7562 lout->invalidated = false;
7563 if (minSize.isValid())
7564 child->setMinimumSize(minSize);
7565 QCOMPARE(lout->invalidated, shouldInvalidate);
7567 lout->invalidated = false;
7568 if (maxSize.isValid())
7569 child->setMaximumSize(maxSize);
7570 QCOMPARE(lout->invalidated, shouldInvalidate2);
7572 lout->invalidated = false;
7573 child->setSizePolicy(QSizePolicy(QSizePolicy::Preferred, (QSizePolicy::Policy)verticalSizePolicy));
7574 if (shouldInvalidate3)
7575 QCOMPARE(lout->invalidated, true);
7577 lout->invalidated = false;
7579 child->setVisible(false);
7580 QCOMPARE(lout->invalidated, shouldInvalidate4);
7583 void tst_QWidget::sendUpdateRequestImmediately()
7585 UpdateWidget updateWidget;
7586 updateWidget.show();
7588 QVERIFY(QTest::qWaitForWindowExposed(&updateWidget));
7590 qApp->processEvents();
7591 updateWidget.reset();
7593 QCOMPARE(updateWidget.numUpdateRequestEvents, 0);
7594 updateWidget.repaint();
7595 QCOMPARE(updateWidget.numUpdateRequestEvents, 1);
7598 void tst_QWidget::doubleRepaint()
7600 #if defined(Q_OS_MAC)
7601 if (!macHasAccessToWindowsServer())
7602 QSKIP("Not having window server access causes the wrong number of repaints to be issues");
7604 UpdateWidget widget;
7605 widget.setFocusPolicy(Qt::StrongFocus);
7606 // Filter out activation change and focus events to avoid update() calls in QWidget.
7607 widget.updateOnActivationChangeAndFocusIn = false;
7610 int expectedRepaints = 1;
7612 QVERIFY(QTest::qWaitForWindowExposed(&widget));
7614 QTRY_COMPARE(widget.numPaintEvents, expectedRepaints);
7615 widget.numPaintEvents = 0;
7617 // Minmize: Should not trigger a repaint.
7618 widget.showMinimized();
7620 QCOMPARE(widget.numPaintEvents, 0);
7621 widget.numPaintEvents = 0;
7623 // Restore: Should not trigger a repaint.
7624 widget.showNormal();
7625 QVERIFY(QTest::qWaitForWindowExposed(&widget));
7627 QCOMPARE(widget.numPaintEvents, 0);
7630 void tst_QWidget::resizeInPaintEvent()
7633 UpdateWidget widget(&window);
7634 window.resize(200, 200);
7636 qApp->setActiveWindow(&window);
7637 QVERIFY(QTest::qWaitForWindowActive(&window));
7638 QTRY_VERIFY(widget.numPaintEvents > 0);
7641 QCOMPARE(widget.numPaintEvents, 0);
7643 widget.resizeInPaintEvent = true;
7644 // This will call resize in the paintEvent, which in turn will call
7645 // invalidateBuffer() and a new update request should be posted.
7647 QCOMPARE(widget.numPaintEvents, 1);
7648 widget.numPaintEvents = 0;
7651 // Make sure the resize triggers another update.
7652 QTRY_COMPARE(widget.numPaintEvents, 1);
7655 void tst_QWidget::opaqueChildren()
7658 widget.resize(200, 200);
7660 QWidget child(&widget);
7661 child.setGeometry(-700, -700, 200, 200);
7663 QWidget grandChild(&child);
7664 grandChild.resize(200, 200);
7666 QWidget greatGrandChild(&grandChild);
7667 greatGrandChild.setGeometry(50, 50, 200, 200);
7668 greatGrandChild.setPalette(Qt::red);
7669 greatGrandChild.setAutoFillBackground(true); // Opaque child widget.
7672 QVERIFY(QTest::qWaitForWindowExposed(&widget));
7675 // Child, grandChild and greatGrandChild are outside the ancestor clip.
7676 QRegion expectedOpaqueRegion(50, 50, 150, 150);
7677 QCOMPARE(qt_widget_private(&grandChild)->getOpaqueChildren(), expectedOpaqueRegion);
7679 // Now they are all inside the ancestor clip.
7680 child.setGeometry(50, 50, 150, 150);
7681 QCOMPARE(qt_widget_private(&grandChild)->getOpaqueChildren(), expectedOpaqueRegion);
7683 // Set mask on greatGrandChild.
7684 const QRegion mask(10, 10, 50, 50);
7685 greatGrandChild.setMask(mask);
7686 expectedOpaqueRegion &= mask.translated(50, 50);
7687 QCOMPARE(qt_widget_private(&grandChild)->getOpaqueChildren(), expectedOpaqueRegion);
7689 // Make greatGrandChild "transparent".
7690 greatGrandChild.setAutoFillBackground(false);
7691 QCOMPARE(qt_widget_private(&grandChild)->getOpaqueChildren(), QRegion());
7695 class MaskSetWidget : public QWidget
7699 MaskSetWidget(QWidget* p =0)
7702 void paintEvent(QPaintEvent* event) {
7705 paintedRegion += event->region();
7706 foreach(QRect r, event->region().rects())
7707 p.fillRect(r, Qt::red);
7710 void resizeEvent(QResizeEvent*) {
7711 setMask(QRegion(QRect(0, 0, width(), 10).normalized()));
7714 QRegion paintedRegion;
7718 setGeometry(QRect(0, 50, 50, 50));
7722 setGeometry(QRect(0, 50, 150, 50));
7727 void tst_QWidget::setMaskInResizeEvent()
7732 w.setWindowFlags(Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint);
7735 MaskSetWidget testWidget(&w);
7736 testWidget.setGeometry(0, 0, 100, 100);
7737 testWidget.setMask(QRegion(QRect(0,0,100,10)));
7740 QVERIFY(QTest::qWaitForWindowExposed(&w));
7742 QTRY_VERIFY(w.numPaintEvents > 0);
7745 testWidget.paintedRegion = QRegion();
7746 QTimer::singleShot(0, &testWidget, SLOT(resizeDown()));
7749 QRegion expectedParentUpdate(0, 0, 100, 10); // Old testWidget area.
7750 expectedParentUpdate += testWidget.geometry(); // New testWidget area.
7751 QCOMPARE(w.paintedRegion, expectedParentUpdate);
7752 QCOMPARE(testWidget.paintedRegion, testWidget.mask());
7754 testWidget.paintedRegion = QRegion();
7755 // Now resize the widget again, but in the oposite direction
7756 QTimer::singleShot(0, &testWidget, SLOT(resizeUp()));
7759 QTRY_COMPARE(testWidget.paintedRegion, testWidget.mask());
7762 class MoveInResizeWidget : public QWidget
7766 MoveInResizeWidget(QWidget* p = 0)
7769 setWindowFlags(Qt::FramelessWindowHint);
7772 void resizeEvent(QResizeEvent*) {
7774 move(QPoint(100,100));
7776 static bool firstTime = true;
7778 QTimer::singleShot(250, this, SLOT(resizeMe()));
7789 void tst_QWidget::moveInResizeEvent()
7791 MoveInResizeWidget testWidget;
7792 testWidget.setGeometry(50, 50, 200, 200);
7794 QVERIFY(QTest::qWaitForWindowExposed(&testWidget));
7797 QRect expectedGeometry(100,100, 100, 100);
7798 QTRY_COMPARE(testWidget.geometry(), expectedGeometry);
7801 void tst_QWidget::immediateRepaintAfterShow()
7803 if (m_platform == QStringLiteral("xcb"))
7804 QSKIP("QTBUG-26424");
7805 if (m_platform != QStringLiteral("xcb") && m_platform != QStringLiteral("windows"))
7806 QSKIP("We don't support immediate repaint right after show on other platforms.");
7808 UpdateWidget widget;
7810 qApp->processEvents();
7811 // On X11 in particular, we are now waiting for a MapNotify event before
7812 // syncing the backing store. However, if someone request a repaint()
7813 // we must repaint immediately regardless of the current state.
7814 widget.numPaintEvents = 0;
7816 QCOMPARE(widget.numPaintEvents, 1);
7819 void tst_QWidget::immediateRepaintAfterInvalidateBuffer()
7821 if (m_platform != QStringLiteral("xcb") && m_platform != QStringLiteral("windows"))
7822 QSKIP("We don't support immediate repaint right after show on other platforms.");
7824 QScopedPointer<UpdateWidget> widget(new UpdateWidget);
7826 QVERIFY(QTest::qWaitForWindowExposed(widget.data()));
7829 widget->numPaintEvents = 0;
7831 // Marks the area covered by the widget as dirty in the backing store and
7832 // posts an UpdateRequest event.
7833 qt_widget_private(widget.data())->invalidateBuffer(widget->rect());
7834 QCOMPARE(widget->numPaintEvents, 0);
7836 // The entire widget is already dirty, but this time we want to update immediately
7837 // by calling repaint(), and thus we have to repaint the widget and not wait for
7838 // the UpdateRequest to be sent when we get back to the event loop.
7840 QCOMPARE(widget->numPaintEvents, 1);
7843 void tst_QWidget::effectiveWinId()
7846 QWidget child(&parent);
7849 QVERIFY(!parent.effectiveWinId());
7850 QVERIFY(!child.effectiveWinId());
7854 QVERIFY(parent.effectiveWinId());
7855 QVERIFY(child.effectiveWinId());
7858 void tst_QWidget::effectiveWinId2()
7862 class MyWidget : public QWidget {
7863 bool event(QEvent *e)
7865 if (e->type() == QEvent::WinIdChange) {
7870 return QWidget::event(e);
7875 child.setParent(&parent);
7879 child.setParent(&parent);
7882 class CustomWidget : public QWidget
7885 mutable int metricCallCount;
7887 CustomWidget(QWidget *parent = 0) : QWidget(parent), metricCallCount(0) {}
7889 virtual int metric(PaintDeviceMetric metric) const {
7891 return QWidget::metric(metric);
7895 void tst_QWidget::customDpi()
7897 QScopedPointer<QWidget> topLevel(new QWidget);
7898 CustomWidget *custom = new CustomWidget(topLevel.data());
7899 QWidget *child = new QWidget(custom);
7901 custom->metricCallCount = 0;
7902 topLevel->logicalDpiX();
7903 QCOMPARE(custom->metricCallCount, 0);
7904 custom->logicalDpiX();
7905 QCOMPARE(custom->metricCallCount, 1);
7906 child->logicalDpiX();
7907 QCOMPARE(custom->metricCallCount, 2);
7910 void tst_QWidget::customDpiProperty()
7912 QScopedPointer<QWidget> topLevel(new QWidget);
7913 QWidget *middle = new CustomWidget(topLevel.data());
7914 QWidget *child = new QWidget(middle);
7916 const int initialDpiX = topLevel->logicalDpiX();
7917 const int initialDpiY = topLevel->logicalDpiY();
7919 middle->setProperty("_q_customDpiX", 300);
7920 middle->setProperty("_q_customDpiY", 400);
7922 QCOMPARE(topLevel->logicalDpiX(), initialDpiX);
7923 QCOMPARE(topLevel->logicalDpiY(), initialDpiY);
7925 QCOMPARE(middle->logicalDpiX(), 300);
7926 QCOMPARE(middle->logicalDpiY(), 400);
7928 QCOMPARE(child->logicalDpiX(), 300);
7929 QCOMPARE(child->logicalDpiY(), 400);
7931 middle->setProperty("_q_customDpiX", QVariant());
7932 middle->setProperty("_q_customDpiY", QVariant());
7934 QCOMPARE(topLevel->logicalDpiX(), initialDpiX);
7935 QCOMPARE(topLevel->logicalDpiY(), initialDpiY);
7937 QCOMPARE(middle->logicalDpiX(), initialDpiX);
7938 QCOMPARE(middle->logicalDpiY(), initialDpiY);
7940 QCOMPARE(child->logicalDpiX(), initialDpiX);
7941 QCOMPARE(child->logicalDpiY(), initialDpiY);
7944 void tst_QWidget::quitOnCloseAttribute()
7947 QCOMPARE(w.testAttribute(Qt::WA_QuitOnClose), true);
7948 w.setAttribute(Qt::WA_QuitOnClose, false);
7949 QCOMPARE(w.testAttribute(Qt::WA_QuitOnClose), false);
7951 w.setAttribute(Qt::WA_QuitOnClose);
7952 w.setWindowFlags(Qt::Tool);
7953 QCOMPARE(w.testAttribute(Qt::WA_QuitOnClose), false);
7955 w.setAttribute(Qt::WA_QuitOnClose);
7956 w.setWindowFlags(Qt::Popup);
7957 QCOMPARE(w.testAttribute(Qt::WA_QuitOnClose), false);
7959 w.setAttribute(Qt::WA_QuitOnClose);
7960 w.setWindowFlags(Qt::ToolTip);
7961 QCOMPARE(w.testAttribute(Qt::WA_QuitOnClose), false);
7963 w.setAttribute(Qt::WA_QuitOnClose);
7964 w.setWindowFlags(Qt::SplashScreen);
7965 QCOMPARE(w.testAttribute(Qt::WA_QuitOnClose), false);
7967 w.setAttribute(Qt::WA_QuitOnClose);
7968 w.setWindowFlags(Qt::SubWindow);
7969 QCOMPARE(w.testAttribute(Qt::WA_QuitOnClose), false);
7971 w.setAttribute(Qt::WA_QuitOnClose);
7972 w.setWindowFlags(Qt::Dialog);
7973 QCOMPARE(w.testAttribute(Qt::WA_QuitOnClose), true);
7975 QCOMPARE(w.testAttribute(Qt::WA_QuitOnClose), true);
7976 w.setWindowFlags(Qt::Tool);
7977 QCOMPARE(w.testAttribute(Qt::WA_QuitOnClose), false);
7980 void tst_QWidget::moveRect()
7983 widget.resize(200, 200);
7984 widget.setUpdatesEnabled(false);
7985 QWidget child(&widget);
7986 child.setUpdatesEnabled(false);
7987 child.setAttribute(Qt::WA_OpaquePaintEvent);
7990 child.move(10, 10); // Don't crash.
7994 class GDIWidget : public QDialog
7999 setAttribute(Qt::WA_PaintOnScreen);
8000 timer.setSingleShot(true);
8001 timer.setInterval(0);
8003 QPaintEngine *paintEngine() const { return 0; }
8005 void paintEvent(QPaintEvent *) {
8006 QPlatformNativeInterface *ni = QGuiApplication::platformNativeInterface();
8007 const HDC hdc = (HDC)ni->nativeResourceForWindow(QByteArrayLiteral("getDC"), windowHandle());
8009 const HBRUSH brush = CreateSolidBrush(RGB(255, 0, 0));
8010 SelectObject(hdc, brush);
8011 Rectangle(hdc, 0, 0, 10, 10);
8012 DeleteObject(brush);
8013 ni->nativeResourceForWindow(QByteArrayLiteral("releaseDC"), windowHandle());
8015 qWarning("%s: Unable to obtain native DC.", Q_FUNC_INFO);
8017 if (!timer.isActive()) {
8018 connect(&timer, &QTimer::timeout, this,
8019 hdc ? &GDIWidget::slotTimer : &QDialog::reject);
8024 QSize sizeHint() const {
8025 return QSize(400, 300);
8030 QScreen *screen = windowHandle()->screen();
8031 const QImage im = screen->grabWindow(internalWinId(), 0, 0, -1, -1).toImage();
8032 color = im.pixel(1, 1);
8041 void tst_QWidget::gdiPainting()
8046 QCOMPARE(w.color, QColor(255, 0, 0));
8050 void tst_QWidget::paintOnScreenPossible()
8053 w1.setAttribute(Qt::WA_PaintOnScreen);
8054 QVERIFY(!w1.testAttribute(Qt::WA_PaintOnScreen));
8057 w2.setAttribute(Qt::WA_PaintOnScreen);
8058 QVERIFY(w2.testAttribute(Qt::WA_PaintOnScreen));
8062 void tst_QWidget::reparentStaticWidget()
8066 QWidget *child = new QWidget(&window1);
8067 child->setPalette(Qt::red);
8068 child->setAutoFillBackground(true);
8069 child->setAttribute(Qt::WA_StaticContents);
8070 child->resize(160, 160);
8072 QWidget *grandChild = new QWidget(child);
8073 grandChild->setPalette(Qt::blue);
8074 grandChild->setAutoFillBackground(true);
8075 grandChild->resize(50, 50);
8076 grandChild->setAttribute(Qt::WA_StaticContents);
8078 QVERIFY(QTest::qWaitForWindowExposed(&window1));
8082 QVERIFY(QTest::qWaitForWindowExposed(&window2));
8085 // Reparent into another top-level.
8086 child->setParent(&window2);
8089 // Please don't crash.
8090 window1.resize(window1.size() + QSize(2, 2));
8093 // Make sure we move all static children even though
8094 // the reparented widget itself is non-static.
8095 child->setAttribute(Qt::WA_StaticContents, false);
8096 child->setParent(&window1);
8099 // Please don't crash.
8100 window2.resize(window2.size() + QSize(2, 2));
8103 child->setParent(0);
8107 // Please don't crash.
8108 child->resize(child->size() + QSize(2, 2));
8109 window2.resize(window2.size() + QSize(2, 2));
8112 QWidget *siblingOfGrandChild = new QWidget(child);
8113 siblingOfGrandChild->show();
8116 // Nothing should happen when reparenting within the same top-level.
8117 grandChild->setParent(siblingOfGrandChild);
8121 QWidget paintOnScreen;
8122 paintOnScreen.setAttribute(Qt::WA_PaintOnScreen);
8123 paintOnScreen.show();
8124 QVERIFY(QTest::qWaitForWindowExposed(&paintOnScreen));
8127 child->setParent(&paintOnScreen);
8131 // Please don't crash.
8132 paintOnScreen.resize(paintOnScreen.size() + QSize(2, 2));
8137 void tst_QWidget::QTBUG6883_reparentStaticWidget2()
8140 QDockWidget *one = new QDockWidget("one", &mw);
8141 mw.addDockWidget(Qt::LeftDockWidgetArea, one , Qt::Vertical);
8143 QWidget *child = new QWidget();
8144 child->setPalette(Qt::red);
8145 child->setAutoFillBackground(true);
8146 child->setAttribute(Qt::WA_StaticContents);
8147 child->resize(100, 100);
8148 one->setWidget(child);
8150 QToolBar *mainTools = mw.addToolBar("Main Tools");
8151 mainTools->addWidget(new QLineEdit);
8154 QVERIFY(QTest::qWaitForWindowExposed(&mw));
8156 one->setFloating(true);
8161 class ColorRedWidget : public QWidget
8164 ColorRedWidget(QWidget *parent = 0)
8165 : QWidget(parent, Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint | Qt::ToolTip)
8169 void paintEvent(QPaintEvent *) {
8171 p.fillRect(rect(),Qt::red);
8175 void tst_QWidget::translucentWidget()
8179 ColorRedWidget label;
8180 label.setFixedSize(16,16);
8181 label.setAttribute(Qt::WA_TranslucentBackground);
8182 const QPoint labelPos = qApp->desktop()->availableGeometry().topLeft();
8183 label.move(labelPos);
8185 QVERIFY(QTest::qWaitForWindowExposed(&label));
8188 QPixmap widgetSnapshot;
8191 QWidget *desktopWidget = QApplication::desktop()->screen(0);
8192 if (QSysInfo::windowsVersion() >= QSysInfo::WV_VISTA)
8193 widgetSnapshot = qApp->primaryScreen()->grabWindow(desktopWidget->winId(), labelPos.x(), labelPos.y(), label.width(), label.height());
8196 widgetSnapshot = label.grab(QRect(QPoint(0, 0), label.size()));
8197 QImage actual = widgetSnapshot.toImage().convertToFormat(QImage::Format_RGB32);
8198 QImage expected = pm.toImage().convertToFormat(QImage::Format_RGB32);
8199 QCOMPARE(actual.size(),expected.size());
8200 QCOMPARE(actual,expected);
8203 class MaskResizeTestWidget : public QWidget
8207 MaskResizeTestWidget(QWidget* p =0)
8209 setMask(QRegion(QRect(0, 0, 100, 100).normalized()));
8212 void paintEvent(QPaintEvent* event) {
8215 paintedRegion += event->region();
8216 foreach(QRect r, event->region().rects())
8217 p.fillRect(r, Qt::red);
8220 QRegion paintedRegion;
8223 void enlargeMask() {
8224 QRegion newMask(QRect(0, 0, 150, 150).normalized());
8229 QRegion newMask(QRect(0, 0, 50, 50).normalized());
8235 void tst_QWidget::setClearAndResizeMask()
8237 UpdateWidget topLevel;
8238 topLevel.resize(160, 160);
8240 qApp->setActiveWindow(&topLevel);
8241 QVERIFY(QTest::qWaitForWindowActive(&topLevel));
8242 QTRY_VERIFY(topLevel.numPaintEvents > 0);
8245 // Mask top-level widget
8246 const QRegion topLevelMask(0, 0, 100, 100, QRegion::Ellipse);
8247 topLevel.setMask(topLevelMask);
8248 QCOMPARE(topLevel.mask(), topLevelMask);
8249 // Ensure that the top-level doesn't get any update.
8250 // We don't control what's happening on platforms other than X11, Windows
8251 if (m_platform == QStringLiteral("xcb") || m_platform == QStringLiteral("windows"))
8252 QCOMPARE(topLevel.numPaintEvents, 0);
8256 // Clear top-level mask
8257 topLevel.clearMask();
8258 QCOMPARE(topLevel.mask(), QRegion());
8260 QRegion outsideOldMask(topLevel.rect());
8261 outsideOldMask -= topLevelMask;
8262 // Ensure that the top-level gets an update for the area outside the old mask.
8263 // We don't control what's happening on platforms other than X11, Windows
8264 if (m_platform == QStringLiteral("xcb") || m_platform == QStringLiteral("windows")) {
8265 QTRY_VERIFY(topLevel.numPaintEvents > 0);
8266 QTRY_COMPARE(topLevel.paintedRegion, outsideOldMask);
8269 UpdateWidget child(&topLevel);
8270 child.setAutoFillBackground(true); // NB! Opaque child.
8271 child.setPalette(Qt::red);
8272 child.resize(100, 100);
8279 // Mask child widget with a mask that is smaller than the rect
8280 const QRegion childMask(0, 0, 50, 50);
8281 child.setMask(childMask);
8282 QTRY_COMPARE(child.mask(), childMask);
8284 // and ensure that the child widget doesn't get any update.
8286 // Mac always issues a full update when calling setMask, and we cannot force it to not do so.
8287 if (child.internalWinId())
8288 QCOMPARE(child.numPaintEvents, 1);
8291 QCOMPARE(child.numPaintEvents, 0);
8292 // and the parent widget gets an update for the newly exposed area.
8293 QTRY_COMPARE(topLevel.numPaintEvents, 1);
8294 QRegion expectedParentExpose(child.rect());
8295 expectedParentExpose -= childMask;
8296 QCOMPARE(topLevel.paintedRegion, expectedParentExpose);
8301 // Clear child widget mask
8303 QTRY_COMPARE(child.mask(), QRegion());
8305 // and ensure that that the child widget gets an update for the area outside the old mask.
8306 QTRY_COMPARE(child.numPaintEvents, 1);
8307 outsideOldMask = child.rect();
8309 // Mac always issues a full update when calling setMask, and we cannot force it to not do so.
8310 if (!child.internalWinId())
8312 outsideOldMask -= childMask;
8313 QCOMPARE(child.paintedRegion, outsideOldMask);
8314 // and the parent widget doesn't get any update.
8315 QCOMPARE(topLevel.numPaintEvents, 0);
8320 // Mask child widget with a mask that is bigger than the rect
8321 child.setMask(QRegion(0, 0, 1000, 1000));
8324 // Mac always issues a full update when calling setMask, and we cannot force it to not do so.
8325 if (child.internalWinId())
8326 QTRY_COMPARE(child.numPaintEvents, 1);
8329 // and ensure that we don't get any updates at all.
8330 QTRY_COMPARE(child.numPaintEvents, 0);
8331 QCOMPARE(topLevel.numPaintEvents, 0);
8333 // ...and the same applies when clearing the mask.
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_VERIFY(child.numPaintEvents > 0);
8342 QCOMPARE(child.numPaintEvents, 0);
8343 QCOMPARE(topLevel.numPaintEvents, 0);
8345 QWidget resizeParent;
8346 MaskResizeTestWidget resizeChild(&resizeParent);
8348 resizeParent.resize(300,300);
8349 resizeParent.raise();
8350 resizeParent.setWindowFlags(Qt::WindowStaysOnTopHint);
8351 resizeChild.setGeometry(50,50,200,200);
8352 QPalette pal = resizeParent.palette();
8353 pal.setColor(QPalette::Window, QColor(Qt::white));
8354 resizeParent.setPalette(pal);
8356 resizeParent.show();
8357 QVERIFY(QTest::qWaitForWindowExposed(&resizeParent));
8358 // Disable the size grip on the Mac; otherwise it'll be included when grabbing the window.
8359 resizeParent.setFixedSize(resizeParent.size());
8362 resizeChild.paintedRegion = QRegion();
8364 QTimer::singleShot(100, &resizeChild, SLOT(shrinkMask()));
8367 // Mac always issues a full update when calling setMask, and we cannot force it to not do so.
8368 if (child.internalWinId())
8369 QTRY_COMPARE(resizeChild.paintedRegion, resizeChild.mask());
8372 QTRY_COMPARE(resizeChild.paintedRegion, QRegion());
8374 resizeChild.paintedRegion = QRegion();
8375 const QRegion oldMask = resizeChild.mask();
8376 QTimer::singleShot(0, &resizeChild, SLOT(enlargeMask()));
8379 // Mac always issues a full update when calling setMask, and we cannot force it to not do so.
8380 if (child.internalWinId())
8381 QTRY_COMPARE(resizeChild.paintedRegion, resizeChild.mask());
8384 QTRY_COMPARE(resizeChild.paintedRegion, resizeChild.mask() - oldMask);
8387 void tst_QWidget::maskedUpdate()
8389 UpdateWidget topLevel;
8390 topLevel.resize(200, 200);
8391 const QRegion topLevelMask(50, 50, 70, 70);
8392 topLevel.setMask(topLevelMask);
8394 UpdateWidget child(&topLevel);
8395 child.setGeometry(20, 20, 180, 180);
8396 const QRegion childMask(60, 60, 30, 30);
8397 child.setMask(childMask);
8399 UpdateWidget grandChild(&child);
8400 grandChild.setGeometry(50, 50, 100, 100);
8401 const QRegion grandChildMask(20, 20, 10, 10);
8402 grandChild.setMask(grandChildMask);
8405 QVERIFY(QTest::qWaitForWindowExposed(&topLevel));
8406 QTRY_VERIFY(topLevel.numPaintEvents > 0);
8409 #define RESET_WIDGETS \
8414 #define CLEAR_MASK(widget) \
8415 widget.clearMask(); \
8416 QTest::qWait(100); \
8419 // All widgets are transparent at this point, so any call to update() will result
8420 // in composition, i.e. the update propagates to ancestors and children.
8427 QTRY_COMPARE(topLevel.paintedRegion, topLevelMask);
8428 QTRY_COMPARE(child.paintedRegion, childMask);
8429 QTRY_COMPARE(grandChild.paintedRegion, grandChildMask);
8436 QTRY_COMPARE(topLevel.paintedRegion, childMask.translated(child.pos()));
8437 QTRY_COMPARE(child.paintedRegion, childMask);
8438 QTRY_COMPARE(grandChild.paintedRegion, grandChildMask);
8440 // GrandChild update.
8442 grandChild.update();
8445 QTRY_COMPARE(topLevel.paintedRegion, grandChildMask.translated(grandChild.mapTo(&topLevel, QPoint())));
8446 QTRY_COMPARE(child.paintedRegion, grandChildMask.translated(grandChild.pos()));
8447 QTRY_COMPARE(grandChild.paintedRegion, grandChildMask);
8449 topLevel.setAttribute(Qt::WA_OpaquePaintEvent);
8450 child.setAttribute(Qt::WA_OpaquePaintEvent);
8451 grandChild.setAttribute(Qt::WA_OpaquePaintEvent);
8453 // All widgets are now opaque, which means no composition, i.e.
8454 // the update does not propate to ancestors and children.
8461 QRegion expectedTopLevelUpdate = topLevelMask;
8462 expectedTopLevelUpdate -= childMask.translated(child.pos()); // Subtract opaque children.
8463 QTRY_COMPARE(topLevel.paintedRegion, expectedTopLevelUpdate);
8464 QTRY_COMPARE(child.paintedRegion, QRegion());
8465 QTRY_COMPARE(grandChild.paintedRegion, QRegion());
8472 QTRY_COMPARE(topLevel.paintedRegion, QRegion());
8473 QRegion expectedChildUpdate = childMask;
8474 expectedChildUpdate -= grandChildMask.translated(grandChild.pos()); // Subtract oapque children.
8475 QTRY_COMPARE(child.paintedRegion, expectedChildUpdate);
8476 QTRY_COMPARE(grandChild.paintedRegion, QRegion());
8478 // GrandChild update.
8480 grandChild.update();
8483 QTRY_COMPARE(topLevel.paintedRegion, QRegion());
8484 QTRY_COMPARE(child.paintedRegion, QRegion());
8485 QTRY_COMPARE(grandChild.paintedRegion, grandChildMask);
8487 // GrandChild update.
8488 CLEAR_MASK(grandChild);
8489 grandChild.update();
8492 QTRY_COMPARE(topLevel.paintedRegion, QRegion());
8493 QTRY_COMPARE(child.paintedRegion, QRegion());
8494 QRegion expectedGrandChildUpdate = grandChild.rect();
8495 // Clip with parent's mask.
8496 expectedGrandChildUpdate &= childMask.translated(-grandChild.pos());
8497 QCOMPARE(grandChild.paintedRegion, expectedGrandChildUpdate);
8499 // GrandChild update.
8501 grandChild.update();
8504 QTRY_COMPARE(topLevel.paintedRegion, QRegion());
8505 QTRY_COMPARE(child.paintedRegion, QRegion());
8506 expectedGrandChildUpdate = grandChild.rect();
8507 // Clip with parent's mask.
8508 expectedGrandChildUpdate &= topLevelMask.translated(-grandChild.mapTo(&topLevel, QPoint()));
8509 QTRY_COMPARE(grandChild.paintedRegion, expectedGrandChildUpdate);
8516 QTRY_COMPARE(topLevel.paintedRegion, QRegion());
8517 expectedChildUpdate = child.rect();
8518 // Clip with parent's mask.
8519 expectedChildUpdate &= topLevelMask.translated(-child.pos());
8520 expectedChildUpdate -= grandChild.geometry(); // Subtract opaque children.
8521 QTRY_COMPARE(child.paintedRegion, expectedChildUpdate);
8522 QTRY_COMPARE(grandChild.paintedRegion, QRegion());
8524 // GrandChild update.
8525 CLEAR_MASK(topLevel);
8526 grandChild.update();
8529 QTRY_COMPARE(topLevel.paintedRegion, QRegion());
8530 QTRY_COMPARE(child.paintedRegion, QRegion());
8531 QTRY_COMPARE(grandChild.paintedRegion, QRegion(grandChild.rect())); // Full update.
8534 #ifndef QTEST_NO_CURSOR
8535 void tst_QWidget::syntheticEnterLeave()
8537 class MyWidget : public QWidget
8540 MyWidget(QWidget *parent = 0) : QWidget(parent), numEnterEvents(0), numLeaveEvents(0) {}
8541 void enterEvent(QEvent *) { ++numEnterEvents; }
8542 void leaveEvent(QEvent *) { ++numLeaveEvents; }
8547 QCursor::setPos(QPoint(0,0));
8550 window.setWindowFlags(Qt::WindowStaysOnTopHint);
8551 window.move(200, 200);
8552 window.resize(200, 200);
8554 MyWidget *child1 = new MyWidget(&window);
8555 child1->setPalette(Qt::blue);
8556 child1->setAutoFillBackground(true);
8557 child1->resize(200, 200);
8558 child1->setCursor(Qt::OpenHandCursor);
8560 MyWidget *child2 = new MyWidget(&window);
8561 child2->resize(200, 200);
8563 MyWidget *grandChild = new MyWidget(child2);
8564 grandChild->setPalette(Qt::red);
8565 grandChild->setAutoFillBackground(true);
8566 grandChild->resize(200, 200);
8567 grandChild->setCursor(Qt::WaitCursor);
8572 QVERIFY(QTest::qWaitForWindowExposed(&window));
8575 #define RESET_EVENT_COUNTS \
8576 window.numEnterEvents = 0; \
8577 window.numLeaveEvents = 0; \
8578 child1->numEnterEvents = 0; \
8579 child1->numLeaveEvents = 0; \
8580 child2->numEnterEvents = 0; \
8581 child2->numLeaveEvents = 0; \
8582 grandChild->numEnterEvents = 0; \
8583 grandChild->numLeaveEvents = 0;
8585 // Position the cursor in the middle of the window.
8586 const QPoint globalPos = window.mapToGlobal(QPoint(100, 100));
8587 QCursor::setPos(globalPos); // Enter child2 and grandChild.
8590 QCOMPARE(window.numLeaveEvents, 0);
8591 QCOMPARE(child2->numLeaveEvents, 0);
8592 QCOMPARE(grandChild->numLeaveEvents, 0);
8593 QCOMPARE(child1->numLeaveEvents, 0);
8595 // This event arrives asynchronously
8596 QTRY_COMPARE(window.numEnterEvents, 1);
8597 QCOMPARE(child2->numEnterEvents, 1);
8598 QCOMPARE(grandChild->numEnterEvents, 1);
8599 QCOMPARE(child1->numEnterEvents, 0);
8602 child2->hide(); // Leave child2 and grandChild, enter child1.
8604 QCOMPARE(window.numLeaveEvents, 0);
8605 QCOMPARE(child2->numLeaveEvents, 1);
8606 QCOMPARE(grandChild->numLeaveEvents, 1);
8607 QCOMPARE(child1->numLeaveEvents, 0);
8609 QCOMPARE(window.numEnterEvents, 0);
8610 QCOMPARE(child2->numEnterEvents, 0);
8611 QCOMPARE(grandChild->numEnterEvents, 0);
8612 QCOMPARE(child1->numEnterEvents, 1);
8615 child2->show(); // Leave child1, enter child2 and grandChild.
8617 QCOMPARE(window.numLeaveEvents, 0);
8618 QCOMPARE(child2->numLeaveEvents, 0);
8619 QCOMPARE(grandChild->numLeaveEvents, 0);
8620 QCOMPARE(child1->numLeaveEvents, 1);
8622 QCOMPARE(window.numEnterEvents, 0);
8623 QCOMPARE(child2->numEnterEvents, 1);
8624 QCOMPARE(grandChild->numEnterEvents, 1);
8625 QCOMPARE(child1->numEnterEvents, 0);
8628 delete child2; // Enter child1 (and do not send leave events to child2 and grandChild).
8630 QCOMPARE(window.numLeaveEvents, 0);
8631 QCOMPARE(child1->numLeaveEvents, 0);
8633 QCOMPARE(window.numEnterEvents, 0);
8634 QCOMPARE(child1->numEnterEvents, 1);
8638 #ifndef QTEST_NO_CURSOR
8639 void tst_QWidget::taskQTBUG_4055_sendSyntheticEnterLeave()
8641 class SELParent : public QWidget
8644 SELParent(QWidget *parent = 0): QWidget(parent) { }
8646 void mousePressEvent(QMouseEvent *) { child->show(); }
8650 class SELChild : public QWidget
8653 SELChild(QWidget *parent = 0) : QWidget(parent), numEnterEvents(0), numMouseMoveEvents(0) {}
8654 void enterEvent(QEvent *) { ++numEnterEvents; }
8655 void mouseMoveEvent(QMouseEvent *event)
8657 QCOMPARE(event->button(), Qt::NoButton);
8658 QCOMPARE(event->buttons(), Qt::MouseButtons(Qt::NoButton));
8659 ++numMouseMoveEvents;
8661 void reset() { numEnterEvents = numMouseMoveEvents = 0; }
8662 int numEnterEvents, numMouseMoveEvents;
8665 QCursor::setPos(QPoint(0,0));
8668 parent.move(200, 200);
8669 parent.resize(200, 200);
8670 SELChild child(&parent);
8671 child.resize(200, 200);
8673 QVERIFY(QTest::qWaitForWindowExposed(&parent));
8676 QCursor::setPos(child.mapToGlobal(QPoint(100, 100)));
8677 // Make sure the cursor has entered the child.
8678 QTRY_VERIFY(child.numEnterEvents > 0);
8684 // Make sure the child gets enter event and no mouse move event.
8685 QTRY_COMPARE(child.numEnterEvents, 1);
8686 QCOMPARE(child.numMouseMoveEvents, 0);
8690 child.setMouseTracking(true);
8693 // Make sure the child gets enter event and mouse move event.
8694 // Note that we verify event->button() and event->buttons()
8695 // in SELChild::mouseMoveEvent().
8696 QTRY_COMPARE(child.numEnterEvents, 1);
8697 QCOMPARE(child.numMouseMoveEvents, 1);
8699 // Sending synthetic enter/leave trough the parent's mousePressEvent handler.
8700 parent.child = &child;
8704 QTest::mouseClick(&parent, Qt::LeftButton);
8706 // Make sure the child gets enter event and one mouse move event.
8707 QTRY_COMPARE(child.numEnterEvents, 1);
8708 QCOMPARE(child.numMouseMoveEvents, 1);
8712 child.setMouseTracking(false);
8713 QTest::mouseClick(&parent, Qt::LeftButton);
8715 // Make sure the child gets enter event and no mouse move event.
8716 QTRY_COMPARE(child.numEnterEvents, 1);
8717 QCOMPARE(child.numMouseMoveEvents, 0);
8721 void tst_QWidget::windowFlags()
8724 w.setWindowFlags(w.windowFlags() | Qt::FramelessWindowHint);
8725 QVERIFY(w.windowFlags() & Qt::FramelessWindowHint);
8728 void tst_QWidget::initialPosForDontShowOnScreenWidgets()
8730 { // Check default position.
8731 const QPoint expectedPos(0, 0);
8733 widget.setAttribute(Qt::WA_DontShowOnScreen);
8734 widget.winId(); // Make sure create_sys is called.
8735 QCOMPARE(widget.pos(), expectedPos);
8736 QCOMPARE(widget.geometry().topLeft(), expectedPos);
8739 { // Explicitly move to a position.
8740 const QPoint expectedPos(100, 100);
8742 widget.setAttribute(Qt::WA_DontShowOnScreen);
8743 widget.move(expectedPos);
8744 widget.winId(); // Make sure create_sys is called.
8745 QCOMPARE(widget.pos(), expectedPos);
8746 QCOMPARE(widget.geometry().topLeft(), expectedPos);
8750 class MyEvilObject : public QObject
8754 MyEvilObject(QWidget *widgetToCrash) : QObject(), widget(widgetToCrash)
8756 connect(widget, SIGNAL(destroyed(QObject*)), this, SLOT(beEvil(QObject*)));
8762 void beEvil(QObject *) { widget->update(0, 0, 150, 150); }
8765 void tst_QWidget::updateOnDestroyedSignal()
8769 QWidget *child = new QWidget(&widget);
8770 child->resize(200, 200);
8771 child->setAutoFillBackground(true);
8772 child->setPalette(Qt::red);
8775 QVERIFY(QTest::qWaitForWindowExposed(&widget));
8778 // Please do not crash.
8779 MyEvilObject evil(child);
8783 void tst_QWidget::toplevelLineEditFocus()
8789 QVERIFY(QTest::qWaitForWindowExposed(&w));
8792 QTRY_COMPARE(QApplication::activeWindow(), (QWidget*)&w);
8793 QTRY_COMPARE(QApplication::focusWidget(), (QWidget*)&w);
8796 void tst_QWidget::focusWidget_task254563()
8798 //having different visibility for widget is important
8801 QWidget container(&top);
8802 QWidget *widget = new QWidget(&container);
8805 widget->setFocus(); //set focus (will set the focus widget up to the toplevel to be 'widget')
8806 container.setFocus();
8807 delete widget; // will call clearFocus but that doesn't help
8808 QVERIFY(top.focusWidget() != widget); //dangling pointer
8811 // This test case relies on developer build (AUTOTEST_EXPORT).
8812 #ifdef QT_BUILD_INTERNAL
8813 void tst_QWidget::destroyBackingStore()
8819 QVERIFY(QTest::qWaitForWindowExposed(&w));
8820 QApplication::processEvents();
8821 QTRY_VERIFY(w.numPaintEvents > 0);
8824 qt_widget_private(&w)->topData()->backingStoreTracker.create(&w);
8827 QApplication::processEvents();
8829 QCOMPARE(w.numPaintEvents, 1);
8831 // Check one more time, because the second time around does more caching.
8833 QApplication::processEvents();
8834 QCOMPARE(w.numPaintEvents, 2);
8836 #endif // QT_BUILD_INTERNAL
8839 QWidgetBackingStore* backingStore(QWidget &widget)
8841 QWidgetBackingStore *backingStore = 0;
8842 #ifdef QT_BUILD_INTERNAL
8843 if (QTLWExtra *topExtra = qt_widget_private(&widget)->maybeTopData())
8844 backingStore = topExtra->backingStoreTracker.data();
8846 return backingStore;
8849 // Tables of 5000 elements do not make sense on Windows Mobile.
8850 #ifndef Q_OS_WINCE_WM
8851 void tst_QWidget::rectOutsideCoordinatesLimit_task144779()
8853 #ifndef QTEST_NO_CURSOR
8854 QApplication::setOverrideCursor(Qt::BlankCursor); //keep the cursor out of screen grabs
8856 QWidget main(0,Qt::FramelessWindowHint); //don't get confused by the size of the window frame
8858 palette.setColor(QPalette::Window, Qt::red);
8859 main.setPalette(palette);
8861 QDesktopWidget desktop;
8862 QRect desktopDimensions = desktop.availableGeometry(&main);
8863 QSize mainSize(400, 400);
8864 mainSize = mainSize.boundedTo(desktopDimensions.size());
8865 main.resize(mainSize);
8867 QWidget *offsetWidget = new QWidget(&main);
8868 offsetWidget->setGeometry(0, -(15000 - mainSize.height()), mainSize.width(), 15000);
8870 // big widget is too big for the coordinates, it must be limited by wrect
8871 // if wrect is not at the right position because of offsetWidget, bigwidget
8872 // is not painted correctly
8873 QWidget *bigWidget = new QWidget(offsetWidget);
8874 bigWidget->setGeometry(0, 0, mainSize.width(), 50000);
8875 palette.setColor(QPalette::Window, Qt::green);
8876 bigWidget->setPalette(palette);
8877 bigWidget->setAutoFillBackground(true);
8880 QVERIFY(QTest::qWaitForWindowExposed(&main));
8882 QPixmap correct(main.size());
8883 correct.fill(Qt::green);
8884 const QPixmap mainPixmap = main.grab(QRect(QPoint(0, 0), QSize(-1, -1)));
8886 QTRY_COMPARE(mainPixmap.toImage().convertToFormat(QImage::Format_RGB32),
8887 correct.toImage().convertToFormat(QImage::Format_RGB32));
8888 #ifndef QTEST_NO_CURSOR
8889 QApplication::restoreOverrideCursor();
8894 void tst_QWidget::setGraphicsEffect()
8896 // Check that we don't have any effect by default.
8897 QScopedPointer<QWidget> widget(new QWidget);
8898 QVERIFY(!widget->graphicsEffect());
8901 QPointer<QGraphicsEffect> blurEffect = new QGraphicsBlurEffect;
8902 widget->setGraphicsEffect(blurEffect);
8903 QCOMPARE(widget->graphicsEffect(), static_cast<QGraphicsEffect *>(blurEffect));
8905 // Ensure the existing effect is deleted when setting a new one.
8906 QPointer<QGraphicsEffect> shadowEffect = new QGraphicsDropShadowEffect;
8907 widget->setGraphicsEffect(shadowEffect);
8908 QVERIFY(!blurEffect);
8909 QCOMPARE(widget->graphicsEffect(), static_cast<QGraphicsEffect *>(shadowEffect));
8910 blurEffect = new QGraphicsBlurEffect;
8912 // Ensure the effect is uninstalled when setting it on a new target.
8913 QScopedPointer<QWidget> anotherWidget(new QWidget);
8914 anotherWidget->setGraphicsEffect(blurEffect);
8915 widget->setGraphicsEffect(blurEffect);
8916 QVERIFY(!anotherWidget->graphicsEffect());
8917 QVERIFY(!shadowEffect);
8919 // Ensure the existing effect is deleted when deleting the widget.
8921 QVERIFY(!blurEffect);
8922 anotherWidget.reset();
8924 // Ensure the effect is uninstalled when deleting it
8925 widget.reset(new QWidget);
8926 blurEffect = new QGraphicsBlurEffect;
8927 widget->setGraphicsEffect(blurEffect);
8929 QVERIFY(!widget->graphicsEffect());
8931 // Ensure the existing effect is uninstalled and deleted when setting a null effect
8932 blurEffect = new QGraphicsBlurEffect;
8933 widget->setGraphicsEffect(blurEffect);
8934 widget->setGraphicsEffect(0);
8935 QVERIFY(!widget->graphicsEffect());
8936 QVERIFY(!blurEffect);
8939 void tst_QWidget::activateWindow()
8941 // Test case for QTBUG-26711
8943 // Create first mainwindow and set it active
8944 QScopedPointer<QMainWindow> mainwindow(new QMainWindow);
8945 QLabel* label = new QLabel(mainwindow.data());
8946 mainwindow->setCentralWidget(label);
8947 mainwindow->setVisible(true);
8948 mainwindow->activateWindow();
8949 QVERIFY(QTest::qWaitForWindowActive(mainwindow.data()));
8950 QVERIFY(mainwindow->isActiveWindow());
8952 // Create second mainwindow and set it active
8953 QScopedPointer<QMainWindow> mainwindow2(new QMainWindow);
8954 QLabel* label2 = new QLabel(mainwindow2.data());
8955 mainwindow2->setCentralWidget(label2);
8956 mainwindow2->setVisible(true);
8957 mainwindow2->activateWindow();
8958 qApp->processEvents();
8960 QTRY_VERIFY(!mainwindow->isActiveWindow());
8961 QTRY_VERIFY(mainwindow2->isActiveWindow());
8963 // Revert first mainwindow back to visible active
8964 mainwindow->setVisible(true);
8965 mainwindow->activateWindow();
8966 qApp->processEvents();
8968 QTRY_VERIFY(mainwindow->isActiveWindow());
8969 QTRY_VERIFY(!mainwindow2->isActiveWindow());
8972 void tst_QWidget::openModal_taskQTBUG_5804()
8974 class Widget : public QWidget
8977 Widget(QWidget *parent) : QWidget(parent)
8984 QTimer::singleShot(10, &msgbox, SLOT(accept()));
8985 msgbox.exec(); //open a modal dialog
8989 QScopedPointer<QWidget> win(new QWidget);
8990 new Widget(win.data());
8992 QVERIFY(QTest::qWaitForWindowExposed(win.data()));
8995 void tst_QWidget::focusProxyAndInputMethods()
8997 QScopedPointer<QWidget> toplevel(new QWidget(0, Qt::X11BypassWindowManagerHint));
8998 toplevel->resize(200, 200);
8999 toplevel->setAttribute(Qt::WA_InputMethodEnabled, true);
9001 QWidget *child = new QWidget(toplevel.data());
9002 child->setFocusProxy(toplevel.data());
9003 child->setAttribute(Qt::WA_InputMethodEnabled, true);
9005 toplevel->setFocusPolicy(Qt::WheelFocus);
9006 child->setFocusPolicy(Qt::WheelFocus);
9008 QVERIFY(!child->hasFocus());
9009 QVERIFY(!toplevel->hasFocus());
9012 QVERIFY(QTest::qWaitForWindowExposed(toplevel.data()));
9013 QApplication::setActiveWindow(toplevel.data());
9014 QVERIFY(QTest::qWaitForWindowActive(toplevel.data()));
9015 QVERIFY(toplevel->hasFocus());
9016 QVERIFY(child->hasFocus());
9017 QCOMPARE(qApp->focusObject(), toplevel.data());
9020 #ifdef QT_BUILD_INTERNAL
9021 class scrollWidgetWBS : public QWidget
9024 void deleteBackingStore()
9026 static_cast<QWidgetPrivate*>(d_ptr.data())->topData()->backingStoreTracker.destroy();
9028 void enableBackingStore()
9030 if (!static_cast<QWidgetPrivate*>(d_ptr.data())->maybeBackingStore()) {
9031 static_cast<QWidgetPrivate*>(d_ptr.data())->topData()->backingStoreTracker.create(this);
9032 static_cast<QWidgetPrivate*>(d_ptr.data())->invalidateBuffer(this->rect());
9039 // Test case relies on developer build (AUTOTEST_EXPORT).
9040 #ifdef QT_BUILD_INTERNAL
9041 void tst_QWidget::scrollWithoutBackingStore()
9043 scrollWidgetWBS scrollable;
9044 scrollable.resize(200, 200);
9045 QLabel child(QString("@"),&scrollable);
9046 child.resize(50,50);
9048 QVERIFY(QTest::qWaitForWindowExposed(&scrollable));
9049 scrollable.scroll(50,50);
9050 QCOMPARE(child.pos(),QPoint(50,50));
9051 scrollable.deleteBackingStore();
9052 scrollable.scroll(-25,-25);
9053 QCOMPARE(child.pos(),QPoint(25,25));
9054 scrollable.enableBackingStore();
9055 QCOMPARE(child.pos(),QPoint(25,25));
9059 void tst_QWidget::taskQTBUG_7532_tabOrderWithFocusProxy()
9062 w.setFocusPolicy(Qt::TabFocus);
9063 QWidget *fp = new QWidget(&w);
9064 fp->setFocusPolicy(Qt::TabFocus);
9065 w.setFocusProxy(fp);
9066 QWidget::setTabOrder(&w, fp);
9068 // In debug mode, no assertion failure means it's alright.
9071 void tst_QWidget::movedAndResizedAttributes()
9073 #if defined (Q_OS_MAC)
9074 QEXPECT_FAIL("", "FixMe, QTBUG-8941 and QTBUG-8977", Abort);
9077 // Use Qt::Tool as fully decorated windows have a minimum width of 160 on
9078 QWidget w(0, Qt::Tool);
9081 QVERIFY(!w.testAttribute(Qt::WA_Moved));
9082 QVERIFY(!w.testAttribute(Qt::WA_Resized));
9084 w.setWindowState(Qt::WindowFullScreen);
9086 QVERIFY(!w.testAttribute(Qt::WA_Moved));
9087 QVERIFY(!w.testAttribute(Qt::WA_Resized));
9089 w.setWindowState(Qt::WindowMaximized);
9091 QVERIFY(!w.testAttribute(Qt::WA_Moved));
9092 QVERIFY(!w.testAttribute(Qt::WA_Resized));
9094 w.setWindowState(Qt::WindowMinimized);
9096 QVERIFY(!w.testAttribute(Qt::WA_Moved));
9097 QVERIFY(!w.testAttribute(Qt::WA_Resized));
9101 QVERIFY(!w.testAttribute(Qt::WA_Moved));
9102 QVERIFY(!w.testAttribute(Qt::WA_Resized));
9106 QVERIFY(!w.testAttribute(Qt::WA_Moved));
9107 QVERIFY(!w.testAttribute(Qt::WA_Resized));
9111 QVERIFY(!w.testAttribute(Qt::WA_Moved));
9112 QVERIFY(!w.testAttribute(Qt::WA_Resized));
9116 QVERIFY(w.testAttribute(Qt::WA_Moved));
9117 QVERIFY(!w.testAttribute(Qt::WA_Resized));
9120 QVERIFY(w.testAttribute(Qt::WA_Moved));
9121 QVERIFY(w.testAttribute(Qt::WA_Resized));
9125 void tst_QWidget::childAt()
9127 QWidget parent(0, Qt::FramelessWindowHint);
9128 parent.resize(200, 200);
9130 QWidget *child = new QWidget(&parent);
9131 child->setPalette(Qt::red);
9132 child->setAutoFillBackground(true);
9133 child->setGeometry(20, 20, 160, 160);
9135 QWidget *grandChild = new QWidget(child);
9136 grandChild->setPalette(Qt::blue);
9137 grandChild->setAutoFillBackground(true);
9138 grandChild->setGeometry(-20, -20, 220, 220);
9140 QVERIFY(!parent.childAt(19, 19));
9141 QVERIFY(!parent.childAt(180, 180));
9142 QCOMPARE(parent.childAt(20, 20), grandChild);
9143 QCOMPARE(parent.childAt(179, 179), grandChild);
9145 grandChild->setAttribute(Qt::WA_TransparentForMouseEvents);
9146 QCOMPARE(parent.childAt(20, 20), child);
9147 QCOMPARE(parent.childAt(179, 179), child);
9148 grandChild->setAttribute(Qt::WA_TransparentForMouseEvents, false);
9150 child->setMask(QRect(50, 50, 60, 60));
9152 QVERIFY(!parent.childAt(69, 69));
9153 QVERIFY(!parent.childAt(130, 130));
9154 QCOMPARE(parent.childAt(70, 70), grandChild);
9155 QCOMPARE(parent.childAt(129, 129), grandChild);
9157 child->setAttribute(Qt::WA_MouseNoMask);
9158 QCOMPARE(parent.childAt(69, 69), grandChild);
9159 QCOMPARE(parent.childAt(130, 130), grandChild);
9160 child->setAttribute(Qt::WA_MouseNoMask, false);
9162 grandChild->setAttribute(Qt::WA_TransparentForMouseEvents);
9163 QCOMPARE(parent.childAt(70, 70), child);
9164 QCOMPARE(parent.childAt(129, 129), child);
9165 grandChild->setAttribute(Qt::WA_TransparentForMouseEvents, false);
9167 grandChild->setMask(QRect(80, 80, 40, 40));
9169 QCOMPARE(parent.childAt(79, 79), child);
9170 QCOMPARE(parent.childAt(120, 120), child);
9171 QCOMPARE(parent.childAt(80, 80), grandChild);
9172 QCOMPARE(parent.childAt(119, 119), grandChild);
9174 grandChild->setAttribute(Qt::WA_MouseNoMask);
9176 QCOMPARE(parent.childAt(79, 79), grandChild);
9177 QCOMPARE(parent.childAt(120, 120), grandChild);
9181 void tst_QWidget::childAt_unifiedToolBar()
9183 QLabel *label = new QLabel(QLatin1String("foo"));
9184 QToolBar *toolBar = new QToolBar;
9185 toolBar->addWidget(new QLabel("dummy"));
9186 toolBar->addWidget(label);
9188 QMainWindow mainWindow;
9189 mainWindow.addToolBar(toolBar);
9192 // Calculate the top-left corner of the tool bar and the label (in mainWindow's coordinates).
9193 QPoint labelTopLeft = label->mapTo(&mainWindow, QPoint());
9194 QPoint toolBarTopLeft = toolBar->mapTo(&mainWindow, QPoint());
9196 QCOMPARE(mainWindow.childAt(toolBarTopLeft), static_cast<QWidget *>(toolBar));
9197 QCOMPARE(mainWindow.childAt(labelTopLeft), static_cast<QWidget *>(label));
9199 // Enable unified tool bars.
9200 mainWindow.setUnifiedTitleAndToolBarOnMac(true);
9203 // The tool bar is now in the "non-client" area of QMainWindow, i.e.
9204 // outside the mainWindow's rect(), and since mapTo et al. doesn't work
9205 // in that case (see commit 35667fd45ada49269a5987c235fdedfc43e92bb8),
9206 // we use mapToGlobal/mapFromGlobal to re-calculate the corners.
9207 QPoint oldToolBarTopLeft = toolBarTopLeft;
9208 toolBarTopLeft = mainWindow.mapFromGlobal(toolBar->mapToGlobal(QPoint()));
9209 QVERIFY(toolBarTopLeft != oldToolBarTopLeft);
9210 QVERIFY(toolBarTopLeft.y() < 0);
9211 labelTopLeft = mainWindow.mapFromGlobal(label->mapToGlobal(QPoint()));
9213 QCOMPARE(mainWindow.childAt(toolBarTopLeft), static_cast<QWidget *>(toolBar));
9214 QCOMPARE(mainWindow.childAt(labelTopLeft), static_cast<QWidget *>(label));
9217 void tst_QWidget::taskQTBUG_11373()
9219 QScopedPointer<QMainWindow> myWindow(new QMainWindow);
9220 QWidget * center = new QWidget();
9221 myWindow -> setCentralWidget(center);
9222 QWidget * drawer = new QWidget(myWindow.data(), Qt::Drawer);
9224 QCOMPARE(drawer->isVisible(), false);
9226 myWindow -> raise();
9227 // The drawer shouldn't be visible now.
9228 QCOMPARE(drawer->isVisible(), false);
9229 myWindow -> setWindowState(Qt::WindowFullScreen);
9230 myWindow -> setWindowState(Qt::WindowNoState);
9231 // The drawer should still not be visible, since we haven't shown it.
9232 QCOMPARE(drawer->isVisible(), false);
9236 void tst_QWidget::taskQTBUG_17333_ResizeInfiniteRecursion()
9239 const char *s = "border: 1px solid;";
9240 tb.setStyleSheet(s);
9243 QVERIFY(QTest::qWaitForWindowExposed(&tb));
9244 tb.setGeometry(QRect(100, 100, 0, 100));
9245 // No crash, it works.
9248 void tst_QWidget::nativeChildFocus()
9251 QLayout *layout = new QVBoxLayout;
9252 w.setLayout(layout);
9253 QLineEdit *p1 = new QLineEdit;
9254 QLineEdit *p2 = new QLineEdit;
9255 layout->addWidget(p1);
9256 layout->addWidget(p2);
9257 p1->setObjectName("p1");
9258 p2->setObjectName("p2");
9262 p1->setAttribute(Qt::WA_NativeWindow);
9263 p2->setAttribute(Qt::WA_NativeWindow);
9264 QApplication::processEvents();
9265 QVERIFY(QTest::qWaitForWindowExposed(&w));
9268 QCOMPARE(QApplication::activeWindow(), &w);
9269 QCOMPARE(QApplication::focusWidget(), static_cast<QWidget*>(p1));
9274 static bool lenientCompare(const QPixmap &actual, const QPixmap &expected)
9276 QImage expectedImage = expected.toImage().convertToFormat(QImage::Format_RGB32);
9277 QImage actualImage = actual.toImage().convertToFormat(QImage::Format_RGB32);
9279 if (expectedImage.size() != actualImage.size()) {
9280 qWarning("Image size comparison failed: expected: %dx%d, got %dx%d",
9281 expectedImage.size().width(), expectedImage.size().height(),
9282 actualImage.size().width(), actualImage.size().height());
9286 const int size = actual.width() * actual.height();
9287 const int threshold = QPixmap::defaultDepth() == 16 ? 10 : 2;
9289 QRgb *a = (QRgb *)actualImage.bits();
9290 QRgb *e = (QRgb *)expectedImage.bits();
9291 for (int i = 0; i < size; ++i) {
9292 const QColor ca(a[i]);
9293 const QColor ce(e[i]);
9294 if (qAbs(ca.red() - ce.red()) > threshold
9295 || qAbs(ca.green() - ce.green()) > threshold
9296 || qAbs(ca.blue() - ce.blue()) > threshold) {
9297 qWarning("Color mismatch at pixel #%d: Expected: %d,%d,%d, got %d,%d,%d",
9298 i, ce.red(), ce.green(), ce.blue(), ca.red(), ca.green(), ca.blue());
9306 void tst_QWidget::grab()
9308 for (int opaque = 0; opaque < 2; ++opaque) {
9310 QImage image(128, 128, opaque ? QImage::Format_RGB32 : QImage::Format_ARGB32_Premultiplied);
9311 for (int row = 0; row < image.height(); ++row) {
9312 QRgb *line = reinterpret_cast<QRgb *>(image.scanLine(row));
9313 for (int col = 0; col < image.width(); ++col)
9314 line[col] = qRgba(rand() & 255, row, col, opaque ? 255 : 127);
9317 QPalette pal = widget.palette();
9318 pal.setBrush(QPalette::Window, QBrush(image));
9319 widget.setPalette(pal);
9320 widget.resize(128, 128);
9322 QPixmap expected(64, 64);
9324 expected.fill(Qt::transparent);
9326 QPainter p(&expected);
9327 p.translate(-64, -64);
9328 p.drawTiledPixmap(0, 0, 128, 128, pal.brush(QPalette::Window).texture(), 0, 0);
9331 QPixmap actual = widget.grab(QRect(64, 64, 64, 64));
9332 QVERIFY(lenientCompare(actual, expected));
9334 actual = widget.grab(QRect(64, 64, -1, -1));
9335 QVERIFY(lenientCompare(actual, expected));
9337 // Make sure a widget that is not yet shown is grabbed correctly.
9338 QTreeWidget widget2;
9339 actual = widget2.grab(QRect());
9341 expected = widget2.grab(QRect());
9343 QVERIFY(lenientCompare(actual, expected));
9347 /* grabMouse() tests whether mouse grab for a widget without window handle works.
9348 * It creates a top level widget with another nested widget inside. The inner widget grabs
9349 * the mouse and a series of mouse presses moving over the top level's window is simulated.
9350 * Only the inner widget should receive events. */
9352 static inline QString mouseEventLogEntry(const QString &objectName, QEvent::Type t, const QPoint &p, Qt::MouseButtons b)
9355 QDebug(&result).nospace() << objectName << " Mouse event " << t << " at " << p << " buttons " << b;
9359 class GrabLoggerWidget : public QWidget {
9361 explicit GrabLoggerWidget(QStringList *log, QWidget *parent = 0) : QWidget(parent), m_log(log) {}
9364 bool event(QEvent *e)
9366 switch (e->type()) {
9367 case QEvent::MouseButtonPress:
9368 case QEvent::MouseMove:
9369 case QEvent::MouseButtonRelease: {
9370 QMouseEvent *me = static_cast<QMouseEvent *>(e);
9371 m_log->push_back(mouseEventLogEntry(objectName(), me->type(), me->pos(), me->buttons()));
9378 return QWidget::event(e);
9384 void tst_QWidget::grabMouse()
9387 GrabLoggerWidget w(&log);
9388 w.setObjectName(QLatin1String("tst_qwidget_grabMouse"));
9389 w.setWindowTitle(w.objectName());
9390 QLayout *layout = new QVBoxLayout(&w);
9391 layout->setMargin(50);
9392 GrabLoggerWidget *grabber = new GrabLoggerWidget(&log, &w);
9393 const QString grabberObjectName = QLatin1String("tst_qwidget_grabMouse_grabber");
9394 grabber->setObjectName(grabberObjectName);
9395 grabber->setMinimumSize(100, 100);
9396 layout->addWidget(grabber);
9398 qApp->setActiveWindow(&w);
9399 QVERIFY(QTest::qWaitForWindowActive(&w));
9401 QStringList expectedLog;
9402 grabber->grabMouse();
9403 QPoint mousePos = QPoint(w.width() / 2, 10);
9404 const int step = w.height() / 5;
9405 for ( ; mousePos.y() < w.height() ; mousePos.ry() += step) {
9406 QTest::mouseClick(w.windowHandle(), Qt::LeftButton, 0, mousePos);
9407 // Events should go to the grabber child using its coordinates.
9408 const QPoint expectedPos = grabber->mapFromParent(mousePos);
9409 expectedLog.push_back(mouseEventLogEntry(grabberObjectName, QEvent::MouseButtonPress, expectedPos, Qt::LeftButton));
9410 expectedLog.push_back(mouseEventLogEntry(grabberObjectName, QEvent::MouseButtonRelease, expectedPos, Qt::NoButton));
9412 grabber->releaseMouse();
9413 QCOMPARE(log, expectedLog);
9416 void tst_QWidget::grabKeyboard()
9419 w.setObjectName(QLatin1String("tst_qwidget_grabKeyboard"));
9420 w.setWindowTitle(w.objectName());
9421 QLayout *layout = new QVBoxLayout(&w);
9422 QLineEdit *grabber = new QLineEdit(&w);
9423 layout->addWidget(grabber);
9424 QLineEdit *nonGrabber = new QLineEdit(&w);
9425 layout->addWidget(nonGrabber);
9427 qApp->setActiveWindow(&w);
9428 QVERIFY(QTest::qWaitForWindowActive(&w));
9429 nonGrabber->setFocus();
9430 grabber->grabKeyboard();
9431 QTest::keyClick(w.windowHandle(), Qt::Key_A);
9432 grabber->releaseKeyboard();
9433 QCOMPARE(grabber->text().toLower(), QStringLiteral("a"));
9434 QVERIFY(nonGrabber->text().isEmpty());
9437 class TouchMouseWidget : public QWidget {
9439 explicit TouchMouseWidget(QWidget *parent = 0)
9441 m_touchEventCount(0),
9442 m_acceptTouch(false),
9443 m_mouseEventCount(0),
9449 void setAcceptTouch(bool accept)
9451 m_acceptTouch = accept;
9452 setAttribute(Qt::WA_AcceptTouchEvents, accept);
9455 void setAcceptMouse(bool accept)
9457 m_acceptMouse = accept;
9461 bool event(QEvent *e)
9463 switch (e->type()) {
9464 case QEvent::TouchBegin:
9465 case QEvent::TouchUpdate:
9466 case QEvent::TouchEnd:
9467 ++m_touchEventCount;
9474 case QEvent::MouseButtonPress:
9475 case QEvent::MouseMove:
9476 case QEvent::MouseButtonRelease:
9477 ++m_mouseEventCount;
9478 m_lastMouseEventPos = static_cast<QMouseEvent *>(e)->localPos();
9486 return QWidget::event(e);
9491 int m_touchEventCount;
9493 int m_mouseEventCount;
9495 QPointF m_lastMouseEventPos;
9498 void tst_QWidget::touchEventSynthesizedMouseEvent()
9500 // Pass if the platform does not want mouse event synhesizing
9501 if (!QGuiApplicationPrivate::platformIntegration()->styleHint(QPlatformIntegration::SynthesizeMouseFromTouchEvents).toBool())
9505 // Simple case, we ignore the touch events, we get mouse events instead
9506 QTouchDevice *device = new QTouchDevice;
9507 device->setType(QTouchDevice::TouchScreen);
9508 QWindowSystemInterface::registerTouchDevice(device);
9510 TouchMouseWidget widget;
9512 QVERIFY(QTest::qWaitForWindowExposed(widget.windowHandle()));
9513 QCOMPARE(widget.m_touchEventCount, 0);
9514 QCOMPARE(widget.m_mouseEventCount, 0);
9516 QTest::touchEvent(&widget, device).press(0, QPoint(10, 10), &widget);
9517 QCOMPARE(widget.m_touchEventCount, 0);
9518 QCOMPARE(widget.m_mouseEventCount, 1);
9519 QCOMPARE(widget.m_lastMouseEventPos, QPointF(10, 10));
9520 QTest::touchEvent(&widget, device).move(0, QPoint(15, 15), &widget);
9521 QCOMPARE(widget.m_touchEventCount, 0);
9522 QCOMPARE(widget.m_mouseEventCount, 2);
9523 QCOMPARE(widget.m_lastMouseEventPos, QPointF(15, 15));
9524 QTest::touchEvent(&widget, device).release(0, QPoint(20, 20), &widget);
9525 QCOMPARE(widget.m_touchEventCount, 0);
9526 QCOMPARE(widget.m_mouseEventCount, 3);
9527 QCOMPARE(widget.m_lastMouseEventPos, QPointF(20, 20));
9531 // We accept the touch events, no mouse event is generated
9532 QTouchDevice *device = new QTouchDevice;
9533 device->setType(QTouchDevice::TouchScreen);
9534 QWindowSystemInterface::registerTouchDevice(device);
9536 TouchMouseWidget widget;
9537 widget.setAcceptTouch(true);
9539 QVERIFY(QTest::qWaitForWindowExposed(widget.windowHandle()));
9540 QCOMPARE(widget.m_touchEventCount, 0);
9541 QCOMPARE(widget.m_mouseEventCount, 0);
9543 QTest::touchEvent(&widget, device).press(0, QPoint(10, 10), &widget);
9544 QCOMPARE(widget.m_touchEventCount, 1);
9545 QCOMPARE(widget.m_mouseEventCount, 0);
9546 QTest::touchEvent(&widget, device).move(0, QPoint(15, 15), &widget);
9547 QCOMPARE(widget.m_touchEventCount, 2);
9548 QCOMPARE(widget.m_mouseEventCount, 0);
9549 QTest::touchEvent(&widget, device).release(0, QPoint(20, 20), &widget);
9550 QCOMPARE(widget.m_touchEventCount, 3);
9551 QCOMPARE(widget.m_mouseEventCount, 0);
9555 // Parent accepts touch events, child ignore both mouse and touch
9556 // We should see propagation of the TouchBegin
9557 QTouchDevice *device = new QTouchDevice;
9558 device->setType(QTouchDevice::TouchScreen);
9559 QWindowSystemInterface::registerTouchDevice(device);
9561 TouchMouseWidget parent;
9562 parent.setAcceptTouch(true);
9563 TouchMouseWidget child(&parent);
9565 child.setAcceptMouse(false);
9567 QVERIFY(QTest::qWaitForWindowExposed(parent.windowHandle()));
9568 QCOMPARE(parent.m_touchEventCount, 0);
9569 QCOMPARE(parent.m_mouseEventCount, 0);
9570 QCOMPARE(child.m_touchEventCount, 0);
9571 QCOMPARE(child.m_mouseEventCount, 0);
9573 QTest::touchEvent(parent.window(), device).press(0, QPoint(10, 10), &child);
9574 QCOMPARE(parent.m_touchEventCount, 1);
9575 QCOMPARE(parent.m_mouseEventCount, 0);
9576 QCOMPARE(child.m_touchEventCount, 0);
9577 QCOMPARE(child.m_mouseEventCount, 1); // Attempt at mouse event before propagation
9578 QCOMPARE(child.m_lastMouseEventPos, QPointF(10, 10));
9582 // Parent accepts mouse events, child ignore both mouse and touch
9583 // We should see propagation of the TouchBegin into a MouseButtonPress
9584 QTouchDevice *device = new QTouchDevice;
9585 device->setType(QTouchDevice::TouchScreen);
9586 QWindowSystemInterface::registerTouchDevice(device);
9588 TouchMouseWidget parent;
9589 TouchMouseWidget child(&parent);
9591 child.setAcceptMouse(false);
9593 QVERIFY(QTest::qWaitForWindowExposed(parent.windowHandle()));
9594 QCOMPARE(parent.m_touchEventCount, 0);
9595 QCOMPARE(parent.m_mouseEventCount, 0);
9596 QCOMPARE(child.m_touchEventCount, 0);
9597 QCOMPARE(child.m_mouseEventCount, 0);
9599 QTest::touchEvent(parent.window(), device).press(0, QPoint(10, 10), &child);
9600 QCOMPARE(parent.m_touchEventCount, 0);
9601 QCOMPARE(parent.m_mouseEventCount, 1);
9602 QCOMPARE(parent.m_lastMouseEventPos, QPointF(15, 15));
9603 QCOMPARE(child.m_touchEventCount, 0);
9604 QCOMPARE(child.m_mouseEventCount, 1); // Attempt at mouse event before propagation
9605 QCOMPARE(child.m_lastMouseEventPos, QPointF(10, 10));
9609 void tst_QWidget::styleSheetPropagation()
9612 tw.setStyleSheet("background-color: red;");
9613 foreach (QObject *child, tw.children()) {
9614 if (QWidget *w = qobject_cast<QWidget *>(child))
9615 QCOMPARE(w->style(), tw.style());
9619 class DestroyTester : public QObject
9623 DestroyTester(QObject *parent) : QObject(parent) { parentDestroyed = 0; }
9624 static int parentDestroyed;
9626 void parentDestroyedSlot() {
9631 int DestroyTester::parentDestroyed = 0;
9633 void tst_QWidget::destroyedSignal()
9636 QWidget *w = new QWidget;
9637 DestroyTester *t = new DestroyTester(w);
9638 connect(w, SIGNAL(destroyed()), t, SLOT(parentDestroyedSlot()));
9639 QCOMPARE(DestroyTester::parentDestroyed, 0);
9641 QCOMPARE(DestroyTester::parentDestroyed, 1);
9645 QWidget *w = new QWidget;
9646 DestroyTester *t = new DestroyTester(w);
9647 connect(w, SIGNAL(destroyed()), t, SLOT(parentDestroyedSlot()));
9648 w->blockSignals(true);
9649 QCOMPARE(DestroyTester::parentDestroyed, 0);
9651 QCOMPARE(DestroyTester::parentDestroyed, 1);
9655 QObject *o = new QWidget;
9656 DestroyTester *t = new DestroyTester(o);
9657 connect(o, SIGNAL(destroyed()), t, SLOT(parentDestroyedSlot()));
9658 QCOMPARE(DestroyTester::parentDestroyed, 0);
9660 QCOMPARE(DestroyTester::parentDestroyed, 1);
9664 QObject *o = new QWidget;
9665 DestroyTester *t = new DestroyTester(o);
9666 connect(o, SIGNAL(destroyed()), t, SLOT(parentDestroyedSlot()));
9667 o->blockSignals(true);
9668 QCOMPARE(DestroyTester::parentDestroyed, 0);
9670 QCOMPARE(DestroyTester::parentDestroyed, 1);
9674 QWidget *w = new QWidget;
9675 DestroyTester *t = new DestroyTester(0);
9676 connect(w, SIGNAL(destroyed()), t, SLOT(parentDestroyedSlot()));
9677 QCOMPARE(DestroyTester::parentDestroyed, 0);
9679 QCOMPARE(DestroyTester::parentDestroyed, 1);
9684 QWidget *w = new QWidget;
9685 DestroyTester *t = new DestroyTester(0);
9686 connect(w, SIGNAL(destroyed()), t, SLOT(parentDestroyedSlot()));
9687 w->blockSignals(true);
9688 QCOMPARE(DestroyTester::parentDestroyed, 0);
9690 QCOMPARE(DestroyTester::parentDestroyed, 1);
9695 QObject *o = new QWidget;
9696 DestroyTester *t = new DestroyTester(0);
9697 connect(o, SIGNAL(destroyed()), t, SLOT(parentDestroyedSlot()));
9698 QCOMPARE(DestroyTester::parentDestroyed, 0);
9700 QCOMPARE(DestroyTester::parentDestroyed, 1);
9705 QObject *o = new QWidget;
9706 DestroyTester *t = new DestroyTester(0);
9707 connect(o, SIGNAL(destroyed()), t, SLOT(parentDestroyedSlot()));
9708 o->blockSignals(true);
9709 QCOMPARE(DestroyTester::parentDestroyed, 0);
9711 QCOMPARE(DestroyTester::parentDestroyed, 1);
9717 #ifndef QTEST_NO_CURSOR
9718 void tst_QWidget::underMouse()
9720 // Move the mouse cursor to a safe location
9721 QCursor::setPos(0,0);
9723 ColorWidget topLevelWidget(0, Qt::blue);
9724 ColorWidget childWidget1(&topLevelWidget, Qt::yellow);
9725 ColorWidget childWidget2(&topLevelWidget, Qt::black);
9726 ColorWidget popupWidget(0, Qt::green);
9728 topLevelWidget.setObjectName("topLevelWidget");
9729 childWidget1.setObjectName("childWidget1");
9730 childWidget2.setObjectName("childWidget2");
9731 popupWidget.setObjectName("popupWidget");
9733 popupWidget.setWindowFlags(Qt::Popup);
9735 topLevelWidget.setGeometry(100, 100, 300, 300);
9736 childWidget1.setGeometry(20, 20, 100, 100);
9737 childWidget2.setGeometry(20, 120, 100, 100);
9738 popupWidget.setGeometry(50, 100, 50, 50);
9740 topLevelWidget.show();
9741 QVERIFY(QTest::qWaitForWindowExposed(&topLevelWidget));
9742 QWindow *window = topLevelWidget.windowHandle();
9744 QPoint outsideWindowPoint(30, -10);
9745 QPoint inWindowPoint(30, 10);
9746 QPoint child1Point(30, 50);
9747 QPoint child2PointA(30, 150);
9748 QPoint child2PointB(31, 151);
9751 QTest::mouseMove(window, outsideWindowPoint);
9752 QVERIFY(!topLevelWidget.underMouse());
9753 QVERIFY(!childWidget1.underMouse());
9754 QVERIFY(!childWidget2.underMouse());
9756 // Enter window, outside children
9757 // Note: QTest::mouseMove will not generate enter events for windows, so send one explicitly
9758 QWindowSystemInterface::handleEnterEvent(window, inWindowPoint, window->mapToGlobal(inWindowPoint));
9759 QTest::mouseMove(window, inWindowPoint);
9760 QVERIFY(topLevelWidget.underMouse());
9761 QVERIFY(!childWidget1.underMouse());
9762 QVERIFY(!childWidget2.underMouse());
9765 QTest::mouseMove(window, child1Point);
9766 QVERIFY(topLevelWidget.underMouse());
9767 QVERIFY(childWidget1.underMouse());
9768 QVERIFY(!childWidget2.underMouse());
9771 QTest::mouseMove(window, child2PointA);
9772 QVERIFY(topLevelWidget.underMouse());
9773 QVERIFY(!childWidget1.underMouse());
9774 QVERIFY(childWidget2.underMouse());
9776 topLevelWidget.resetCounts();
9777 childWidget1.resetCounts();
9778 childWidget2.resetCounts();
9779 popupWidget.resetCounts();
9781 // Throw up a popup window
9783 QVERIFY(QTest::qWaitForWindowExposed(&popupWidget));
9784 QWindow *popupWindow = popupWidget.windowHandle();
9785 QVERIFY(popupWindow);
9786 QVERIFY(QApplication::activePopupWidget() == &popupWidget);
9788 // Send an artificial leave event for window, as it won't get generated automatically
9789 // due to cursor not actually being over the window.
9790 QWindowSystemInterface::handleLeaveEvent(window);
9791 QApplication::processEvents();
9793 // If there is an active popup, undermouse should not be reported (QTBUG-27478),
9794 // but opening a popup causes leave for widgets under mouse.
9795 QVERIFY(!topLevelWidget.underMouse());
9796 QVERIFY(!childWidget1.underMouse());
9797 QVERIFY(!childWidget2.underMouse());
9798 QVERIFY(!popupWidget.underMouse());
9799 QCOMPARE(popupWidget.enters, 0);
9800 QCOMPARE(popupWidget.leaves, 0);
9801 QCOMPARE(topLevelWidget.enters, 0);
9802 QCOMPARE(topLevelWidget.leaves, 1);
9803 QCOMPARE(childWidget1.enters, 0);
9804 QCOMPARE(childWidget1.leaves, 0);
9805 QCOMPARE(childWidget2.enters, 0);
9806 QCOMPARE(childWidget2.leaves, 1);
9807 topLevelWidget.resetCounts();
9808 childWidget2.resetCounts();
9810 // Moving around while popup active should not change undermouse or cause
9811 // enter and leave events for widgets.
9812 QTest::mouseMove(popupWindow, popupWindow->mapFromGlobal(window->mapToGlobal(child2PointB)));
9813 QVERIFY(!topLevelWidget.underMouse());
9814 QVERIFY(!childWidget1.underMouse());
9815 QVERIFY(!childWidget2.underMouse());
9816 QVERIFY(!popupWidget.underMouse());
9817 QCOMPARE(popupWidget.enters, 0);
9818 QCOMPARE(popupWidget.leaves, 0);
9819 QCOMPARE(topLevelWidget.enters, 0);
9820 QCOMPARE(topLevelWidget.leaves, 0);
9821 QCOMPARE(childWidget1.enters, 0);
9822 QCOMPARE(childWidget1.leaves, 0);
9823 QCOMPARE(childWidget2.enters, 0);
9824 QCOMPARE(childWidget2.leaves, 0);
9826 QTest::mouseMove(popupWindow, popupWindow->mapFromGlobal(window->mapToGlobal(inWindowPoint)));
9827 QVERIFY(!topLevelWidget.underMouse());
9828 QVERIFY(!childWidget1.underMouse());
9829 QVERIFY(!childWidget2.underMouse());
9830 QVERIFY(!popupWidget.underMouse());
9831 QCOMPARE(popupWidget.enters, 0);
9832 QCOMPARE(popupWidget.leaves, 0);
9833 QCOMPARE(topLevelWidget.enters, 0);
9834 QCOMPARE(topLevelWidget.leaves, 0);
9835 QCOMPARE(childWidget1.enters, 0);
9836 QCOMPARE(childWidget1.leaves, 0);
9837 QCOMPARE(childWidget2.enters, 0);
9838 QCOMPARE(childWidget2.leaves, 0);
9840 QTest::mouseMove(popupWindow, popupWindow->mapFromGlobal(window->mapToGlobal(child1Point)));
9841 QVERIFY(!topLevelWidget.underMouse());
9842 QVERIFY(!childWidget1.underMouse());
9843 QVERIFY(!childWidget2.underMouse());
9844 QVERIFY(!popupWidget.underMouse());
9845 QCOMPARE(popupWidget.enters, 0);
9846 QCOMPARE(popupWidget.leaves, 0);
9847 QCOMPARE(topLevelWidget.enters, 0);
9848 QCOMPARE(topLevelWidget.leaves, 0);
9849 QCOMPARE(childWidget1.enters, 0);
9850 QCOMPARE(childWidget1.leaves, 0);
9851 QCOMPARE(childWidget2.enters, 0);
9852 QCOMPARE(childWidget2.leaves, 0);
9854 // Note: Mouse moving off-application while there is an active popup cannot be simulated
9855 // without actually moving the cursor so it is not tested.
9857 // Mouse enters popup, should cause enter to popup.
9858 // Once again, need to create artificial enter event.
9859 const QPoint popupCenter = popupWindow->geometry().center();
9860 QWindowSystemInterface::handleEnterEvent(popupWindow, popupWindow->mapFromGlobal(popupCenter), popupCenter);
9861 QTest::mouseMove(popupWindow, popupCenter);
9862 QVERIFY(!topLevelWidget.underMouse());
9863 QVERIFY(!childWidget1.underMouse());
9864 QVERIFY(!childWidget2.underMouse());
9865 QVERIFY(popupWidget.underMouse());
9866 QCOMPARE(popupWidget.enters, 1);
9867 QCOMPARE(popupWidget.leaves, 0);
9868 QCOMPARE(topLevelWidget.enters, 0);
9869 QCOMPARE(topLevelWidget.leaves, 0);
9870 QCOMPARE(childWidget1.enters, 0);
9871 QCOMPARE(childWidget1.leaves, 0);
9872 QCOMPARE(childWidget2.enters, 0);
9873 QCOMPARE(childWidget2.leaves, 0);
9874 popupWidget.resetCounts();
9876 // Mouse moves around inside popup, no changes
9877 QTest::mouseMove(popupWindow, QPoint(5, 5));
9878 QVERIFY(!topLevelWidget.underMouse());
9879 QVERIFY(!childWidget1.underMouse());
9880 QVERIFY(!childWidget2.underMouse());
9881 QVERIFY(popupWidget.underMouse());
9882 QCOMPARE(popupWidget.enters, 0);
9883 QCOMPARE(popupWidget.leaves, 0);
9884 QCOMPARE(topLevelWidget.enters, 0);
9885 QCOMPARE(topLevelWidget.leaves, 0);
9886 QCOMPARE(childWidget1.enters, 0);
9887 QCOMPARE(childWidget1.leaves, 0);
9888 QCOMPARE(childWidget2.enters, 0);
9889 QCOMPARE(childWidget2.leaves, 0);
9891 // Mouse leaves popup and enters topLevelWidget, should cause leave for popup
9892 // but no enter to topLevelWidget. Again, artificial leave event needed.
9893 QWindowSystemInterface::handleLeaveEvent(popupWindow);
9894 QTest::mouseMove(popupWindow, popupWindow->mapFromGlobal(window->mapToGlobal(inWindowPoint)));
9895 QApplication::processEvents();
9896 QVERIFY(!topLevelWidget.underMouse());
9897 QVERIFY(!childWidget1.underMouse());
9898 QVERIFY(!childWidget2.underMouse());
9899 QVERIFY(!popupWidget.underMouse());
9900 QCOMPARE(popupWidget.enters, 0);
9901 QCOMPARE(popupWidget.leaves, 1);
9902 QCOMPARE(topLevelWidget.enters, 0);
9903 QCOMPARE(topLevelWidget.leaves, 0);
9904 QCOMPARE(childWidget1.enters, 0);
9905 QCOMPARE(childWidget1.leaves, 0);
9906 QCOMPARE(childWidget2.enters, 0);
9907 QCOMPARE(childWidget2.leaves, 0);
9910 class EnterTestModalDialog : public QDialog
9914 EnterTestModalDialog() : QDialog(), button(0)
9916 setGeometry(100, 300, 150, 100);
9917 button = new QPushButton(this);
9918 button->setGeometry(10, 10, 50, 30);
9921 QPushButton *button;
9924 class EnterTestMainDialog : public QDialog
9928 EnterTestMainDialog() : QDialog(), modal(0), enters(0) {}
9931 void buttonPressed()
9933 qApp->installEventFilter(this);
9934 modal = new EnterTestModalDialog();
9935 QTimer::singleShot(2000, modal, SLOT(close())); // Failsafe
9936 QTimer::singleShot(100, this, SLOT(doMouseMoves()));
9943 QPoint point1(15, 15);
9944 QPoint point2(15, 20);
9945 QPoint point3(20, 20);
9946 QWindow *window = modal->windowHandle();
9947 QWindowSystemInterface::handleEnterEvent(window, point1, window->mapToGlobal(point1));
9948 QTest::mouseMove(window, point1);
9949 QTest::mouseMove(window, point2);
9950 QTest::mouseMove(window, point3);
9954 bool eventFilter(QObject *o, QEvent *e)
9956 if (modal && modal->button && o == modal->button) {
9957 switch (e->type()) {
9965 return QDialog::eventFilter(o, e);
9969 EnterTestModalDialog *modal;
9973 // A modal dialog launched by clicking a button should not trigger excess enter events
9974 // when mousing over it.
9975 void tst_QWidget::taskQTBUG_27643_enterEvents()
9977 // Move the mouse cursor to a safe location so it won't interfere
9978 QCursor::setPos(0,0);
9980 EnterTestMainDialog dialog;
9981 QPushButton button(&dialog);
9983 connect(&button, SIGNAL(clicked()), &dialog, SLOT(buttonPressed()));
9985 dialog.setGeometry(100, 100, 150, 100);
9986 button.setGeometry(10, 10, 100, 50);
9988 QVERIFY(QTest::qWaitForWindowExposed(&dialog));
9990 QWindow *window = dialog.windowHandle();
9991 QPoint overButton(25, 25);
9993 QWindowSystemInterface::handleEnterEvent(window, overButton, window->mapToGlobal(overButton));
9994 QTest::mouseMove(window, overButton);
9995 QTest::mouseClick(window, Qt::LeftButton, 0, overButton, 0);
9997 // Modal dialog opened in EnterTestMainDialog::buttonPressed()...
9999 // Must only register only single enter on modal dialog's button after all said and done
10000 QCOMPARE(dialog.enters, 1);
10002 #endif // QTEST_NO_CURSOR
10004 QTEST_MAIN(tst_QWidget)
10005 #include "tst_qwidget.moc"