1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
6 ** This file is part of the test suite of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
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 <qwindowsstyle.h>
59 #include <qdesktopwidget.h>
60 #include <private/qwidget_p.h>
61 #include <private/qapplication_p.h>
62 #include <qcalendarwidget.h>
63 #include <qmainwindow.h>
64 #include <qdockwidget.h>
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>
76 #include <QtWidgets/QGraphicsView>
77 #include <QtWidgets/QGraphicsProxyWidget>
80 #include "tst_qwidget_mac_helpers.h" // Abstract the ObjC stuff out so not everyone must run an ObjC++ compile.
83 #include <QtTest/QtTest>
86 # include <QtCore/qt_windows.h>
87 # include <QtGui/private/qguiapplication_p.h>
88 #include <qpa/qplatformnativeinterface.h>
89 #include <qpa/qplatformintegration.h>
91 static HWND winHandleOf(const QWidget *w)
93 static QPlatformNativeInterface *nativeInterface
94 = QGuiApplicationPrivate::instance()->platformIntegration()->nativeInterface();
95 if (void *handle = nativeInterface->nativeResourceForWindow("handle", w->window()->windowHandle()))
96 return reinterpret_cast<HWND>(handle);
97 qWarning() << "Cannot obtain native handle for " << w;
102 # define Q_CHECK_PAINTEVENTS
103 # ifdef Q_OS_WINCE_WM
104 # include <qguifunctions_wince.h>
105 // taken from qguifunctions_wce.cpp
106 # define SPI_GETPLATFORMTYPE 257
107 static bool qt_wince_is_platform(const QString &platformString) {
108 wchar_t tszPlatform[64];
109 if (SystemParametersInfo(SPI_GETPLATFORMTYPE,
110 sizeof(tszPlatform)/sizeof(*tszPlatform),tszPlatform,0))
111 if (0 == _tcsicmp(reinterpret_cast<const wchar_t *> (platformString.utf16()), tszPlatform))
115 static inline bool qt_wince_is_smartphone() { return qt_wince_is_platform(QString::fromLatin1("Smartphone")); }
116 # endif // Q_OS_WINCE_WM
118 # define Q_CHECK_PAINTEVENTS \
119 if (::SwitchDesktop(::GetThreadDesktop(::GetCurrentThreadId())) == 0) \
120 QSKIP("desktop is not visible, this test would fail");
121 # endif // !Q_OS_WINCE
123 # define Q_CHECK_PAINTEVENTS
124 #endif // else Q_OS_WIN
127 #if defined(Q_OS_WINCE_WM)
128 #include <qguifunctions_wince.h>
129 // taken from qguifunctions_wce.cpp
130 #define SPI_GETPLATFORMTYPE 257
131 bool qt_wince_is_platform(const QString &platformString) {
132 wchar_t tszPlatform[64];
133 if (SystemParametersInfo(SPI_GETPLATFORMTYPE,
134 sizeof(tszPlatform)/sizeof(*tszPlatform),tszPlatform,0))
135 if (0 == _tcsicmp(reinterpret_cast<const wchar_t *> (platformString.utf16()), tszPlatform))
139 bool qt_wince_is_smartphone() {
140 return qt_wince_is_platform(QString::fromLatin1("Smartphone"));
145 #include <Security/AuthSession.h>
146 bool macHasAccessToWindowsServer()
148 SecuritySessionId mySession;
149 SessionAttributeBits sessionInfo;
150 SessionGetInfo(callerSecuritySession, &mySession, &sessionInfo);
151 return (sessionInfo & sessionHasGraphicAccess);
155 class tst_QWidget : public QObject
161 virtual ~tst_QWidget();
165 void cleanupTestCase();
170 void fontPropagation();
171 void fontPropagation2();
172 void palettePropagation();
173 void palettePropagation2();
174 void enabledPropagation();
175 void popupEnterLeave();
176 #ifndef QT_NO_DRAGANDDROP
177 void acceptDropsPropagation();
181 void visible_setWindowOpacity();
185 void mapFromAndTo_data();
187 void focusChainOnHide();
188 void focusChainOnReparent();
195 void showMaximized();
196 void showFullScreen();
197 void showMinimized();
198 void showMinimizedKeepsFocus();
200 void hideWhenFocusWidgetIsChild();
201 void normalGeometry();
204 void windowOpacity();
208 #ifndef QT_MAC_USE_COCOA
211 void testContentsPropagation();
212 void saveRestoreGeometry();
213 void restoreVersion1Geometry_data();
214 void restoreVersion1Geometry();
221 void optimizedResizeMove();
222 void optimizedResize_topLevel();
226 void testDeletionInEventHandlers();
228 void childDeletesItsSibling();
230 void setMinimumSize();
231 void setMaximumSize();
234 void ensureCreated();
235 void winIdChangeEvent();
236 void persistentWinId();
237 void showNativeChild();
238 void qobject_castInDestroyedSlot();
240 void showHideEvent_data();
241 void showHideEvent();
243 void lostUpdatesOnHide();
252 // tests QWidget::setGeometry()
253 void setWindowGeometry_data();
254 void setWindowGeometry();
256 // tests QWidget::move() and resize()
257 void windowMoveResize_data();
258 void windowMoveResize();
260 void moveChild_data();
262 void showAndMoveChild();
264 #ifndef QT_MAC_USE_COCOA
265 void subtractOpaqueSiblings();
268 #if defined (Q_OS_WIN) && !defined(Q_OS_WINCE)
269 void setGeometry_win();
274 void multipleToplevelFocusCheck();
278 void testWindowIconChangeEventPropagation();
280 void minAndMaxSizeWithX11BypassWindowManagerHint();
281 void showHideShowX11();
282 void clean_qt_x11_enforce_cursor();
286 void renderInvisible();
287 void renderWithPainter();
288 void render_task188133();
289 void render_task211796();
290 void render_task217815();
292 void render_windowOpacity();
294 void render_systemClip();
295 void render_systemClip2_data();
296 void render_systemClip2();
297 void render_systemClip3_data();
298 void render_systemClip3();
299 void render_task252837();
300 void render_worldTransform();
302 void setContentsMargins();
304 void moveWindowInShowEvent_data();
305 void moveWindowInShowEvent();
307 void repaintWhenChildDeleted();
308 void hideOpaqueChildWhileHidden();
309 #if !defined(Q_OS_WINCE)
310 void updateWhileMinimized();
314 void adjustSize_data();
315 void updateGeometry();
316 void updateGeometry_data();
317 void sendUpdateRequestImmediately();
318 void doubleRepaint();
319 void resizeInPaintEvent();
320 void opaqueChildren();
322 void setMaskInResizeEvent();
323 void moveInResizeEvent();
325 void immediateRepaintAfterShow();
326 void immediateRepaintAfterInvalidateBuffer();
328 void effectiveWinId();
329 void effectiveWinId2();
331 void customDpiProperty();
333 void quitOnCloseAttribute();
336 #if defined (Q_OS_WIN)
338 void paintOnScreenPossible();
340 void reparentStaticWidget();
341 void QTBUG6883_reparentStaticWidget2();
343 void translucentWidget();
345 void setClearAndResizeMask();
347 #if !defined(Q_OS_WINCE_WM)
348 void syntheticEnterLeave();
349 void taskQTBUG_4055_sendSyntheticEnterLeave();
352 void initialPosForDontShowOnScreenWidgets();
353 void updateOnDestroyedSignal();
354 void toplevelLineEditFocus();
355 void inputFocus_task257832();
357 void focusWidget_task254563();
358 #ifndef Q_OS_WINCE_WM
359 void rectOutsideCoordinatesLimit_task144779();
361 void setGraphicsEffect();
363 #ifdef QT_BUILD_INTERNAL
364 void destroyBackingStore();
367 void activateWindow();
369 void openModal_taskQTBUG_5804();
371 void focusProxyAndInputMethods();
372 #ifdef QT_BUILD_INTERNAL
373 void scrollWithoutBackingStore();
376 void taskQTBUG_7532_tabOrderWithFocusProxy();
377 void movedAndResizedAttributes();
380 void childAt_unifiedToolBar();
381 void taskQTBUG_11373();
383 void taskQTBUG_17333_ResizeInfiniteRecursion();
385 void nativeChildFocus();
388 void touchEventSynthesizedMouseEvent();
391 bool ensureScreenSize(int width, int height);
394 const QString m_platform;
397 bool tst_QWidget::ensureScreenSize(int width, int height)
400 available = QDesktopWidget().availableGeometry().size();
401 return (available.width() >= width && available.height() >= height);
404 // Testing get/set functions
405 void tst_QWidget::getSetCheck()
408 QWidget child1(&obj1);
409 // QStyle * QWidget::style()
410 // void QWidget::setStyle(QStyle *)
411 QScopedPointer<QWindowsStyle> var1(new QWindowsStyle);
412 obj1.setStyle(var1.data());
413 QCOMPARE(static_cast<QStyle *>(var1.data()), obj1.style());
414 obj1.setStyle((QStyle *)0);
415 QVERIFY(var1.data() != obj1.style());
416 QVERIFY(0 != obj1.style()); // style can never be 0 for a widget
418 // int QWidget::minimumWidth()
419 // void QWidget::setMinimumWidth(int)
420 obj1.setMinimumWidth(0);
421 QCOMPARE(obj1.minimumWidth(), 0);
422 obj1.setMinimumWidth(INT_MIN);
423 QCOMPARE(obj1.minimumWidth(), 0); // A widgets width can never be less than 0
424 obj1.setMinimumWidth(INT_MAX);
426 child1.setMinimumWidth(0);
427 QCOMPARE(child1.minimumWidth(), 0);
428 child1.setMinimumWidth(INT_MIN);
429 QCOMPARE(child1.minimumWidth(), 0); // A widgets width can never be less than 0
430 child1.setMinimumWidth(INT_MAX);
431 QCOMPARE(child1.minimumWidth(), QWIDGETSIZE_MAX); // The largest minimum size should only be as big as the maximium
433 // int QWidget::minimumHeight()
434 // void QWidget::setMinimumHeight(int)
435 obj1.setMinimumHeight(0);
436 QCOMPARE(obj1.minimumHeight(), 0);
437 obj1.setMinimumHeight(INT_MIN);
438 QCOMPARE(obj1.minimumHeight(), 0); // A widgets height can never be less than 0
439 obj1.setMinimumHeight(INT_MAX);
441 child1.setMinimumHeight(0);
442 QCOMPARE(child1.minimumHeight(), 0);
443 child1.setMinimumHeight(INT_MIN);
444 QCOMPARE(child1.minimumHeight(), 0); // A widgets height can never be less than 0
445 child1.setMinimumHeight(INT_MAX);
446 QCOMPARE(child1.minimumHeight(), QWIDGETSIZE_MAX); // The largest minimum size should only be as big as the maximium
448 // int QWidget::maximumWidth()
449 // void QWidget::setMaximumWidth(int)
450 obj1.setMaximumWidth(0);
451 QCOMPARE(obj1.maximumWidth(), 0);
452 obj1.setMaximumWidth(INT_MIN);
453 QCOMPARE(obj1.maximumWidth(), 0); // A widgets width can never be less than 0
454 obj1.setMaximumWidth(INT_MAX);
455 QCOMPARE(obj1.maximumWidth(), QWIDGETSIZE_MAX); // QWIDGETSIZE_MAX is the abs max, not INT_MAX
457 // int QWidget::maximumHeight()
458 // void QWidget::setMaximumHeight(int)
459 obj1.setMaximumHeight(0);
460 QCOMPARE(obj1.maximumHeight(), 0);
461 obj1.setMaximumHeight(INT_MIN);
462 QCOMPARE(obj1.maximumHeight(), 0); // A widgets height can never be less than 0
463 obj1.setMaximumHeight(INT_MAX);
464 QCOMPARE(obj1.maximumHeight(), QWIDGETSIZE_MAX); // QWIDGETSIZE_MAX is the abs max, not INT_MAX
467 obj1.setMinimumWidth(0);
468 obj1.setMinimumHeight(0);
469 obj1.setMaximumWidth(QWIDGETSIZE_MAX);
470 obj1.setMaximumHeight(QWIDGETSIZE_MAX);
472 // const QPalette & QWidget::palette()
473 // void QWidget::setPalette(const QPalette &)
475 obj1.setPalette(var6);
476 QCOMPARE(var6, obj1.palette());
477 obj1.setPalette(QPalette());
478 QCOMPARE(QPalette(), obj1.palette());
480 // const QFont & QWidget::font()
481 // void QWidget::setFont(const QFont &)
484 QCOMPARE(var7, obj1.font());
485 obj1.setFont(QFont());
486 QCOMPARE(QFont(), obj1.font());
488 // qreal QWidget::windowOpacity()
489 // void QWidget::setWindowOpacity(qreal)
490 obj1.setWindowOpacity(0.0);
491 QCOMPARE(0.0, obj1.windowOpacity());
492 obj1.setWindowOpacity(1.1f);
493 QCOMPARE(1.0, obj1.windowOpacity()); // 1.0 is the fullest opacity possible
495 // QWidget * QWidget::focusProxy()
496 // void QWidget::setFocusProxy(QWidget *)
498 QScopedPointer<QWidget> var9(new QWidget());
499 obj1.setFocusProxy(var9.data());
500 QCOMPARE(var9.data(), obj1.focusProxy());
501 obj1.setFocusProxy((QWidget *)0);
502 QCOMPARE((QWidget *)0, obj1.focusProxy());
505 // const QRect & QWidget::geometry()
506 // void QWidget::setGeometry(const QRect &)
507 qApp->processEvents();
508 QRect var10(10, 10, 100, 100);
509 obj1.setGeometry(var10);
510 qApp->processEvents();
511 qDebug() << obj1.geometry();
512 QCOMPARE(var10, obj1.geometry());
513 obj1.setGeometry(QRect(0,0,0,0));
514 qDebug() << obj1.geometry();
515 QCOMPARE(QRect(0,0,0,0), obj1.geometry());
517 // QLayout * QWidget::layout()
518 // void QWidget::setLayout(QLayout *)
519 QBoxLayout *var11 = new QBoxLayout(QBoxLayout::LeftToRight);
520 obj1.setLayout(var11);
521 QCOMPARE(static_cast<QLayout *>(var11), obj1.layout());
522 obj1.setLayout((QLayout *)0);
523 QCOMPARE(static_cast<QLayout *>(var11), obj1.layout()); // You cannot set a 0-pointer layout, that keeps the current
524 delete var11; // This will remove the layout from the widget
525 QCOMPARE((QLayout *)0, obj1.layout());
527 // bool QWidget::acceptDrops()
528 // void QWidget::setAcceptDrops(bool)
529 obj1.setAcceptDrops(false);
530 QCOMPARE(false, obj1.acceptDrops());
531 obj1.setAcceptDrops(true);
532 QCOMPARE(true, obj1.acceptDrops());
534 // bool QWidget::autoFillBackground()
535 // void QWidget::setAutoFillBackground(bool)
536 obj1.setAutoFillBackground(false);
537 QCOMPARE(false, obj1.autoFillBackground());
538 obj1.setAutoFillBackground(true);
539 QCOMPARE(true, obj1.autoFillBackground());
542 #if defined (Q_OS_WIN) && !defined(Q_OS_WINCE)
543 obj1.setWindowFlags(Qt::FramelessWindowHint | Qt::WindowSystemMenuHint);
544 const HWND handle = reinterpret_cast<HWND>(obj1.winId()); // explicitly create window handle
545 QVERIFY(GetWindowLong(handle, GWL_STYLE) & WS_POPUP);
549 tst_QWidget::tst_QWidget() : m_platform(qApp->platformName().toLower())
553 font.setPointSize(42);
554 qApp->setFont(font, "QPropagationTestWidget");
557 palette.setColor(QPalette::ToolTipBase, QColor(12, 13, 14));
558 palette.setColor(QPalette::Text, QColor(21, 22, 23));
559 qApp->setPalette(palette, "QPropagationTestWidget");
564 tst_QWidget::~tst_QWidget()
568 class BezierViewer : public QWidget {
570 explicit BezierViewer(QWidget* parent = 0);
571 void paintEvent( QPaintEvent* );
572 void setPoints( const QPolygonF& poly );
578 void tst_QWidget::initTestCase()
580 #ifdef Q_OS_WINCE //disable magic for WindowsCE
581 qApp->setAutoMaximizeThreshold(-1);
583 // Create the test class
584 testWidget = new BezierViewer;
585 testWidget->resize(200,200);
587 QVERIFY(QTest::qWaitForWindowExposed(testWidget));
590 void tst_QWidget::cleanupTestCase()
596 void tst_QWidget::init()
598 // TODO: Add initialization code here.
599 // This will be executed immediately before each test is run.
600 testWidget->setFont(QFont());
601 testWidget->setPalette(QPalette());
604 void tst_QWidget::cleanup()
610 BezierViewer::BezierViewer( QWidget* parent)
613 setObjectName(QLatin1String("TestWidget"));
614 setWindowTitle(objectName());
616 pal.setColor(backgroundRole(), Qt::white);
621 void BezierViewer::setPoints( const QPolygonF& a )
626 #include "private/qbezier_p.h"
627 void BezierViewer::paintEvent( QPaintEvent* )
629 if ( points.size() != 4 ) {
630 #if defined(QT_CHECK_RANGE)
631 qWarning( "QPolygon::bezier: The array must have 4 control points" );
636 /* Calculate Bezier curve */
637 QPolygonF bezier = QBezier::fromPoints(points.at(0),points.at(1),points.at(2),points.at(3)).toPolygon();
639 QPainter painter( this );
641 /* Calculate scale to fit in window */
642 QRectF br = bezier.boundingRect() | points.boundingRect();
644 int scl = qMax( qMin(pr.width()/br.width(), pr.height()/br.height()), qreal(1.) );
647 /* Scale Bezier curve vertices */
648 for ( QPolygonF::Iterator it = bezier.begin(); it != bezier.end(); ++it ) {
649 it->setX( (it->x()-br.x()) * scl + border );
650 it->setY( (it->y()-br.y()) * scl + border );
654 painter.setPen( Qt::lightGray );
656 for ( i = border; i <= pr.width(); i += scl ) {
657 painter.drawLine( i, 0, i, pr.height() );
659 for ( int j = border; j <= pr.height(); j += scl ) {
660 painter.drawLine( 0, j, pr.width(), j );
663 /* Write number of vertices */
664 painter.setPen( Qt::red );
665 painter.setFont( QFont("Helvetica", 14, QFont::DemiBold, true ) );
667 caption.setNum( bezier.size() );
668 caption += QString::fromLatin1( " vertices" );
669 painter.drawText( 10, pr.height()-10, caption );
671 /* Draw Bezier curve */
672 painter.setPen( Qt::black );
673 painter.drawPolyline( bezier );
675 /* Scale and draw control points */
676 painter.setPen( Qt::darkGreen );
677 for ( QPolygonF::Iterator p1 = points.begin(); p1 != points.end(); ++p1 ) {
678 int x = (p1->x()-br.x()) * scl + border;
679 int y = (p1->y()-br.y()) * scl + border;
680 painter.drawLine( x-4, y-4, x+4, y+4 );
681 painter.drawLine( x+4, y-4, x-4, y+4 );
685 painter.setPen( Qt::red );
686 painter.setBrush( Qt::red );
687 for ( QPolygonF::Iterator p2 = bezier.begin(); p2 != bezier.end(); ++p2 )
688 painter.drawEllipse( p2->x()-1, p2->y()-1, 3, 3 );
691 void tst_QWidget::fontPropagation()
693 QFont font = testWidget->font();
694 QWidget* childWidget = new QWidget( testWidget );
696 QCOMPARE( font, childWidget->font() );
698 font.setBold( true );
699 testWidget->setFont( font );
700 QCOMPARE( font, testWidget->font() );
701 QCOMPARE( font, childWidget->font() );
703 QFont newFont = font;
704 newFont.setItalic( true );
705 childWidget->setFont( newFont );
706 QWidget* grandChildWidget = new QWidget( childWidget );
707 QCOMPARE( font, testWidget->font() );
708 QCOMPARE( newFont, grandChildWidget->font() );
710 font.setUnderline( true );
711 testWidget->setFont( font );
713 // the child and grand child should now have merged bold and
715 newFont.setUnderline( true );
717 QCOMPARE( newFont, childWidget->font() );
718 QCOMPARE( newFont, grandChildWidget->font() );
720 // make sure font propagation continues working after reparenting
721 font = testWidget->font();
722 font.setPointSize(font.pointSize() + 2);
723 testWidget->setFont(font);
725 QWidget *one = new QWidget(testWidget);
726 QWidget *two = new QWidget(one);
727 QWidget *three = new QWidget(two);
728 QWidget *four = new QWidget(two);
730 four->setParent(three);
731 four->move(QPoint(0,0));
733 font.setPointSize(font.pointSize() + 2);
734 testWidget->setFont(font);
736 QCOMPARE(testWidget->font(), one->font());
737 QCOMPARE(one->font(), two->font());
738 QCOMPARE(two->font(), three->font());
739 QCOMPARE(three->font(), four->font());
741 QVERIFY(testWidget->testAttribute(Qt::WA_SetFont));
742 QVERIFY(! one->testAttribute(Qt::WA_SetFont));
743 QVERIFY(! two->testAttribute(Qt::WA_SetFont));
744 QVERIFY(! three->testAttribute(Qt::WA_SetFont));
745 QVERIFY(! four->testAttribute(Qt::WA_SetFont));
747 font.setPointSize(font.pointSize() + 2);
750 QCOMPARE(one->font(), two->font());
751 QCOMPARE(two->font(), three->font());
752 QCOMPARE(three->font(), four->font());
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(two->font(), three->font());
763 QCOMPARE(three->font(), four->font());
765 QVERIFY(two->testAttribute(Qt::WA_SetFont));
766 QVERIFY(! three->testAttribute(Qt::WA_SetFont));
767 QVERIFY(! four->testAttribute(Qt::WA_SetFont));
769 font.setPointSize(font.pointSize() + 2);
770 three->setFont(font);
772 QCOMPARE(three->font(), four->font());
774 QVERIFY(three->testAttribute(Qt::WA_SetFont));
775 QVERIFY(! four->testAttribute(Qt::WA_SetFont));
777 font.setPointSize(font.pointSize() + 2);
780 QVERIFY(four->testAttribute(Qt::WA_SetFont));
783 class QPropagationTestWidget : public QWidget
787 QPropagationTestWidget(QWidget *parent = 0)
792 void tst_QWidget::fontPropagation2()
794 // ! Note, the code below is executed in tst_QWidget's constructor.
796 // font.setBold(true);
797 // font.setPointSize(42);
798 // qApp->setFont(font, "QPropagationTestWidget");
800 QScopedPointer<QWidget> root(new QWidget);
801 root->setObjectName(QLatin1String("fontPropagation2"));
802 root->setWindowTitle(root->objectName());
803 root->resize(200, 200);
805 QWidget *child0 = new QWidget(root.data());
806 QWidget *child1 = new QWidget(child0);
807 QWidget *child2 = new QPropagationTestWidget(child1);
808 QWidget *child3 = new QWidget(child2);
809 QWidget *child4 = new QWidget(child3);
810 QWidget *child5 = new QWidget(child4);
813 // Check that only the application fonts apply.
814 QCOMPARE(root->font(), QApplication::font());
815 QCOMPARE(child0->font(), QApplication::font());
816 QCOMPARE(child1->font(), QApplication::font());
817 QCOMPARE(child2->font().pointSize(), 42);
818 QVERIFY(child2->font().bold());
819 QCOMPARE(child3->font().pointSize(), 42);
820 QVERIFY(child3->font().bold());
821 QCOMPARE(child4->font().pointSize(), 42);
822 QVERIFY(child4->font().bold());
823 QCOMPARE(child5->font().pointSize(), 42);
824 QVERIFY(child5->font().bold());
826 // Set child0's font size to 15, and remove bold on child4.
828 font.setPointSize(15);
829 child0->setFont(font);
831 unboldFont.setBold(false);
832 child4->setFont(unboldFont);
834 // Check that the above settings propagate correctly.
835 QCOMPARE(root->font(), QApplication::font());
836 QCOMPARE(child0->font().pointSize(), 15);
837 QVERIFY(!child0->font().bold());
838 QCOMPARE(child1->font().pointSize(), 15);
839 QVERIFY(!child1->font().bold());
840 QCOMPARE(child2->font().pointSize(), 15);
841 QVERIFY(child2->font().bold());
842 QCOMPARE(child3->font().pointSize(), 15);
843 QVERIFY(child3->font().bold());
844 QCOMPARE(child4->font().pointSize(), 15);
845 QVERIFY(!child4->font().bold());
846 QCOMPARE(child5->font().pointSize(), 15);
847 QVERIFY(!child5->font().bold());
849 // Replace the app font for child2. Italic should propagate
850 // but the size should still be ignored. The previous bold
852 QFont italicSizeFont;
853 italicSizeFont.setItalic(true);
854 italicSizeFont.setPointSize(33);
855 qApp->setFont(italicSizeFont, "QPropagationTestWidget");
857 // Check that this propagates correctly.
858 QCOMPARE(root->font(), QApplication::font());
859 QCOMPARE(child0->font().pointSize(), 15);
860 QVERIFY(!child0->font().bold());
861 QVERIFY(!child0->font().italic());
862 QCOMPARE(child1->font().pointSize(), 15);
863 QVERIFY(!child1->font().bold());
864 QVERIFY(!child1->font().italic());
865 QCOMPARE(child2->font().pointSize(), 15);
866 QVERIFY(!child2->font().bold());
867 QVERIFY(child2->font().italic());
868 QCOMPARE(child3->font().pointSize(), 15);
869 QVERIFY(!child3->font().bold());
870 QVERIFY(child3->font().italic());
871 QCOMPARE(child4->font().pointSize(), 15);
872 QVERIFY(!child4->font().bold());
873 QVERIFY(child4->font().italic());
874 QCOMPARE(child5->font().pointSize(), 15);
875 QVERIFY(!child5->font().bold());
876 QVERIFY(child5->font().italic());
879 void tst_QWidget::palettePropagation()
881 QPalette palette = testWidget->palette();
882 QWidget* childWidget = new QWidget( testWidget );
884 QCOMPARE( palette, childWidget->palette() );
886 palette.setColor( QPalette::Base, Qt::red );
887 testWidget->setPalette( palette );
888 QCOMPARE( palette, testWidget->palette() );
889 QCOMPARE( palette, childWidget->palette() );
891 QPalette newPalette = palette;
892 newPalette.setColor( QPalette::Highlight, Qt::green );
893 childWidget->setPalette( newPalette );
894 QWidget* grandChildWidget = new QWidget( childWidget );
895 QCOMPARE( palette, testWidget->palette() );
896 QCOMPARE( newPalette, grandChildWidget->palette() );
898 palette.setColor( QPalette::Text, Qt::blue );
899 testWidget->setPalette( palette );
901 // the child and grand child should now have merged green
902 // highlight and blue text
903 newPalette.setColor( QPalette::Text, Qt::blue);
905 QCOMPARE( newPalette, childWidget->palette() );
906 QCOMPARE( newPalette, grandChildWidget->palette() );
909 void tst_QWidget::palettePropagation2()
911 // ! Note, the code below is executed in tst_QWidget's constructor.
913 // font.setColor(QPalette::ToolTipBase, QColor(12, 13, 14));
914 // font.setColor(QPalette::Text, QColor(21, 22, 23));
915 // qApp->setPalette(palette, "QPropagationTestWidget");
917 QScopedPointer<QWidget> root(new QWidget);
918 root->setObjectName(QLatin1String("palettePropagation2"));
919 root->setWindowTitle(root->objectName());
920 root->resize(200, 200);
921 QWidget *child0 = new QWidget(root.data());
922 QWidget *child1 = new QWidget(child0);
923 QWidget *child2 = new QPropagationTestWidget(child1);
924 QWidget *child3 = new QWidget(child2);
925 QWidget *child4 = new QWidget(child3);
926 QWidget *child5 = new QWidget(child4);
928 QVERIFY(QTest::qWaitForWindowExposed(root.data()));
930 // These colors are unlikely to be imposed on the default palette of
932 QColor sysPalText(21, 22, 23);
933 QColor sysPalToolTipBase(12, 13, 14);
934 QColor overridePalText(42, 43, 44);
935 QColor overridePalToolTipBase(45, 46, 47);
936 QColor sysPalButton(99, 98, 97);
938 // Check that only the application fonts apply.
939 QPalette appPal = QApplication::palette();
940 QCOMPARE(root->palette(), appPal);
941 QCOMPARE(child0->palette(), appPal);
942 QCOMPARE(child1->palette(), appPal);
943 QCOMPARE(child2->palette().color(QPalette::ToolTipBase), sysPalToolTipBase);
944 QCOMPARE(child2->palette().color(QPalette::Text), sysPalText);
945 QCOMPARE(child2->palette().color(QPalette::ToolTipText), appPal.color(QPalette::ToolTipText));
946 QCOMPARE(child3->palette().color(QPalette::ToolTipBase), sysPalToolTipBase);
947 QCOMPARE(child3->palette().color(QPalette::Text), sysPalText);
948 QCOMPARE(child3->palette().color(QPalette::ToolTipText), appPal.color(QPalette::ToolTipText));
949 QCOMPARE(child4->palette().color(QPalette::ToolTipBase), sysPalToolTipBase);
950 QCOMPARE(child4->palette().color(QPalette::Text), sysPalText);
951 QCOMPARE(child4->palette().color(QPalette::ToolTipText), appPal.color(QPalette::ToolTipText));
952 QCOMPARE(child5->palette().color(QPalette::ToolTipBase), sysPalToolTipBase);
953 QCOMPARE(child5->palette().color(QPalette::Text), sysPalText);
954 QCOMPARE(child5->palette().color(QPalette::ToolTipText), appPal.color(QPalette::ToolTipText));
956 // Set child0's Text, and set ToolTipBase on child4.
957 QPalette textPalette;
958 textPalette.setColor(QPalette::Text, overridePalText);
959 child0->setPalette(textPalette);
960 QPalette toolTipPalette;
961 toolTipPalette.setColor(QPalette::ToolTipBase, overridePalToolTipBase);
962 child4->setPalette(toolTipPalette);
964 // Check that the above settings propagate correctly.
965 QCOMPARE(root->palette(), appPal);
966 QCOMPARE(child0->palette().color(QPalette::Text), overridePalText);
967 QCOMPARE(child0->palette().color(QPalette::ToolTipBase), appPal.color(QPalette::ToolTipBase));
968 QCOMPARE(child0->palette().color(QPalette::ToolTipText), appPal.color(QPalette::ToolTipText));
969 QCOMPARE(child1->palette().color(QPalette::Text), overridePalText);
970 QCOMPARE(child1->palette().color(QPalette::ToolTipBase), appPal.color(QPalette::ToolTipBase));
971 QCOMPARE(child1->palette().color(QPalette::ToolTipText), appPal.color(QPalette::ToolTipText));
972 QCOMPARE(child2->palette().color(QPalette::Text), overridePalText);
973 QCOMPARE(child2->palette().color(QPalette::ToolTipBase), sysPalToolTipBase);
974 QCOMPARE(child2->palette().color(QPalette::ToolTipText), appPal.color(QPalette::ToolTipText));
975 QCOMPARE(child3->palette().color(QPalette::Text), overridePalText);
976 QCOMPARE(child3->palette().color(QPalette::ToolTipBase), sysPalToolTipBase);
977 QCOMPARE(child3->palette().color(QPalette::ToolTipText), appPal.color(QPalette::ToolTipText));
978 QCOMPARE(child4->palette().color(QPalette::Text), overridePalText);
979 QCOMPARE(child4->palette().color(QPalette::ToolTipBase), overridePalToolTipBase);
980 QCOMPARE(child4->palette().color(QPalette::ToolTipText), appPal.color(QPalette::ToolTipText));
981 QCOMPARE(child5->palette().color(QPalette::Text), overridePalText);
982 QCOMPARE(child5->palette().color(QPalette::ToolTipBase), overridePalToolTipBase);
983 QCOMPARE(child5->palette().color(QPalette::ToolTipText), appPal.color(QPalette::ToolTipText));
985 // Replace the app palette for child2. Button should propagate but Text
986 // should still be ignored. The previous ToolTipBase setting is gone.
987 QPalette buttonPalette;
988 buttonPalette.setColor(QPalette::ToolTipText, sysPalButton);
989 qApp->setPalette(buttonPalette, "QPropagationTestWidget");
991 // Check that the above settings propagate correctly.
992 QCOMPARE(root->palette(), appPal);
993 QCOMPARE(child0->palette().color(QPalette::Text), overridePalText);
994 QCOMPARE(child0->palette().color(QPalette::ToolTipBase), appPal.color(QPalette::ToolTipBase));
995 QCOMPARE(child0->palette().color(QPalette::ToolTipText), appPal.color(QPalette::ToolTipText));
996 QCOMPARE(child1->palette().color(QPalette::Text), overridePalText);
997 QCOMPARE(child1->palette().color(QPalette::ToolTipBase), appPal.color(QPalette::ToolTipBase));
998 QCOMPARE(child1->palette().color(QPalette::ToolTipText), appPal.color(QPalette::ToolTipText));
999 QCOMPARE(child2->palette().color(QPalette::Text), overridePalText);
1000 QCOMPARE(child2->palette().color(QPalette::ToolTipBase), appPal.color(QPalette::ToolTipBase));
1001 QCOMPARE(child2->palette().color(QPalette::ToolTipText), sysPalButton);
1002 QCOMPARE(child3->palette().color(QPalette::Text), overridePalText);
1003 QCOMPARE(child3->palette().color(QPalette::ToolTipBase), appPal.color(QPalette::ToolTipBase));
1004 QCOMPARE(child3->palette().color(QPalette::ToolTipText), sysPalButton);
1005 QCOMPARE(child4->palette().color(QPalette::Text), overridePalText);
1006 QCOMPARE(child4->palette().color(QPalette::ToolTipBase), overridePalToolTipBase);
1007 QCOMPARE(child4->palette().color(QPalette::ToolTipText), sysPalButton);
1008 QCOMPARE(child5->palette().color(QPalette::Text), overridePalText);
1009 QCOMPARE(child5->palette().color(QPalette::ToolTipBase), overridePalToolTipBase);
1010 QCOMPARE(child5->palette().color(QPalette::ToolTipText), sysPalButton);
1013 void tst_QWidget::enabledPropagation()
1015 QWidget* childWidget = new QWidget( testWidget );
1016 childWidget->show();
1017 QVERIFY( testWidget->isEnabled() );
1018 QVERIFY( childWidget->isEnabled() );
1020 testWidget->setEnabled( false );
1021 QVERIFY( !testWidget->isEnabled() );
1022 QVERIFY( !childWidget->isEnabled() );
1024 testWidget->setDisabled( false );
1025 QVERIFY( testWidget->isEnabled() );
1026 QVERIFY( childWidget->isEnabled() );
1028 QWidget* grandChildWidget = new QWidget( childWidget );
1029 QVERIFY( grandChildWidget->isEnabled() );
1031 testWidget->setDisabled( true );
1032 QVERIFY( !testWidget->isEnabled() );
1033 QVERIFY( !childWidget->isEnabled() );
1034 QVERIFY( !grandChildWidget->isEnabled() );
1036 grandChildWidget->setEnabled( false );
1037 testWidget->setEnabled( true );
1038 QVERIFY( testWidget->isEnabled() );
1039 QVERIFY( childWidget->isEnabled() );
1040 QVERIFY( !grandChildWidget->isEnabled() );
1042 grandChildWidget->setEnabled( true );
1043 testWidget->setEnabled( false );
1044 childWidget->setDisabled( true );
1045 testWidget->setEnabled( true );
1046 QVERIFY( testWidget->isEnabled() );
1047 QVERIFY( !childWidget->isEnabled() );
1048 QVERIFY( !grandChildWidget->isEnabled() );
1051 // Drag'n drop disabled in this build.
1052 #ifndef QT_NO_DRAGANDDROP
1053 void tst_QWidget::acceptDropsPropagation()
1055 QWidget *childWidget = new QWidget(testWidget);
1056 childWidget->show();
1057 QVERIFY(!testWidget->acceptDrops());
1058 QVERIFY(!childWidget->acceptDrops());
1060 testWidget->setAcceptDrops(true);
1061 QVERIFY(testWidget->acceptDrops());
1062 QVERIFY(!childWidget->acceptDrops());
1063 QVERIFY(childWidget->testAttribute(Qt::WA_DropSiteRegistered));
1065 testWidget->setAcceptDrops(false);
1066 QVERIFY(!testWidget->acceptDrops());
1067 QVERIFY(!childWidget->acceptDrops());
1068 QVERIFY(!childWidget->testAttribute(Qt::WA_DropSiteRegistered));
1070 QWidget *grandChildWidget = new QWidget(childWidget);
1071 QVERIFY(!grandChildWidget->acceptDrops());
1072 QVERIFY(!grandChildWidget->testAttribute(Qt::WA_DropSiteRegistered));
1074 testWidget->setAcceptDrops(true);
1075 QVERIFY(testWidget->acceptDrops());
1076 QVERIFY(!childWidget->acceptDrops());
1077 QVERIFY(childWidget->testAttribute(Qt::WA_DropSiteRegistered));
1078 QVERIFY(!grandChildWidget->acceptDrops());
1079 QVERIFY(grandChildWidget->testAttribute(Qt::WA_DropSiteRegistered));
1081 grandChildWidget->setAcceptDrops(true);
1082 testWidget->setAcceptDrops(false);
1083 QVERIFY(!testWidget->acceptDrops());
1084 QVERIFY(!childWidget->acceptDrops());
1085 QVERIFY(grandChildWidget->acceptDrops());
1086 QVERIFY(grandChildWidget->testAttribute(Qt::WA_DropSiteRegistered));
1088 grandChildWidget->setAcceptDrops(false);
1089 QVERIFY(!grandChildWidget->testAttribute(Qt::WA_DropSiteRegistered));
1090 testWidget->setAcceptDrops(true);
1091 childWidget->setAcceptDrops(true);
1092 testWidget->setAcceptDrops(false);
1093 QVERIFY(!testWidget->acceptDrops());
1094 QVERIFY(childWidget->acceptDrops());
1095 QVERIFY(!grandChildWidget->acceptDrops());
1096 QVERIFY(grandChildWidget->testAttribute(Qt::WA_DropSiteRegistered));
1100 void tst_QWidget::isEnabledTo()
1102 QWidget* childWidget = new QWidget( testWidget );
1103 QWidget* grandChildWidget = new QWidget( childWidget );
1105 QVERIFY( childWidget->isEnabledTo( testWidget ) );
1106 QVERIFY( grandChildWidget->isEnabledTo( testWidget ) );
1108 childWidget->setEnabled( false );
1109 QVERIFY( !childWidget->isEnabledTo( testWidget ) );
1110 QVERIFY( grandChildWidget->isEnabledTo( childWidget ) );
1111 QVERIFY( !grandChildWidget->isEnabledTo( testWidget ) );
1114 void tst_QWidget::visible()
1116 // Ensure that the testWidget is hidden for this test at the
1120 QVERIFY( !testWidget->isVisible() );
1121 QWidget* childWidget = new QWidget( testWidget );
1122 QVERIFY( !childWidget->isVisible() );
1125 QVERIFY( testWidget->isVisible() );
1126 QVERIFY( childWidget->isVisible() );
1128 QWidget* grandChildWidget = new QWidget( childWidget );
1129 QVERIFY( !grandChildWidget->isVisible() );
1130 grandChildWidget->show();
1131 QVERIFY( grandChildWidget->isVisible() );
1133 grandChildWidget->hide();
1136 QVERIFY( !grandChildWidget->isVisible() );
1137 QVERIFY( testWidget->isVisible() );
1138 QVERIFY( childWidget->isVisible() );
1140 grandChildWidget->show();
1141 childWidget->hide();
1144 QVERIFY( testWidget->isVisible() );
1145 QVERIFY( !childWidget->isVisible() );
1146 QVERIFY( !grandChildWidget->isVisible() );
1148 grandChildWidget->show();
1149 QVERIFY( !grandChildWidget->isVisible() );
1152 void tst_QWidget::setLocale()
1155 QCOMPARE(w.locale(), QLocale());
1157 w.setLocale(QLocale::Italian);
1158 QCOMPARE(w.locale(), QLocale(QLocale::Italian));
1161 QCOMPARE(child1.locale(), QLocale(QLocale::Italian));
1164 QCOMPARE(w.locale(), QLocale());
1165 QCOMPARE(child1.locale(), QLocale());
1167 w.setLocale(QLocale::French);
1168 QCOMPARE(w.locale(), QLocale(QLocale::French));
1169 QCOMPARE(child1.locale(), QLocale(QLocale::French));
1171 child1.setLocale(QLocale::Italian);
1172 QCOMPARE(w.locale(), QLocale(QLocale::French));
1173 QCOMPARE(child1.locale(), QLocale(QLocale::Italian));
1175 child1.unsetLocale();
1176 QCOMPARE(w.locale(), QLocale(QLocale::French));
1177 QCOMPARE(child1.locale(), QLocale(QLocale::French));
1180 QCOMPARE(child2.locale(), QLocale());
1181 child2.setParent(&w);
1182 QCOMPARE(child2.locale(), QLocale(QLocale::French));
1185 void tst_QWidget::visible_setWindowOpacity()
1188 QVERIFY( !testWidget->isVisible() );
1189 testWidget->setWindowOpacity(0.5);
1191 QVERIFY(!::IsWindowVisible(winHandleOf(testWidget)));
1193 testWidget->setWindowOpacity(1.0);
1196 void tst_QWidget::isVisibleTo()
1198 // Ensure that the testWidget is hidden for this test at the
1202 QWidget* childWidget = new QWidget( testWidget );
1203 QVERIFY( childWidget->isVisibleTo( testWidget ) );
1204 childWidget->hide();
1205 QVERIFY( !childWidget->isVisibleTo( testWidget ) );
1207 QWidget* grandChildWidget = new QWidget( childWidget );
1208 QVERIFY( !grandChildWidget->isVisibleTo( testWidget ) );
1209 QVERIFY( grandChildWidget->isVisibleTo( childWidget ) );
1212 childWidget->show();
1214 QVERIFY( childWidget->isVisibleTo( testWidget ) );
1215 grandChildWidget->hide();
1216 QVERIFY( !grandChildWidget->isVisibleTo( childWidget ) );
1217 QVERIFY( !grandChildWidget->isVisibleTo( testWidget ) );
1221 void tst_QWidget::isHidden()
1223 // Ensure that the testWidget is hidden for this test at the
1227 QVERIFY( testWidget->isHidden() );
1228 QWidget* childWidget = new QWidget( testWidget );
1229 QVERIFY( !childWidget->isHidden() );
1232 QVERIFY( !testWidget->isHidden() );
1233 QVERIFY( !childWidget->isHidden() );
1235 QWidget* grandChildWidget = new QWidget( childWidget );
1236 QVERIFY( grandChildWidget->isHidden() );
1237 grandChildWidget->show();
1238 QVERIFY( !grandChildWidget->isHidden() );
1240 grandChildWidget->hide();
1243 QVERIFY( grandChildWidget->isHidden() );
1244 QVERIFY( !testWidget->isHidden() );
1245 QVERIFY( !childWidget->isHidden() );
1247 grandChildWidget->show();
1248 childWidget->hide();
1251 QVERIFY( !testWidget->isHidden() );
1252 QVERIFY( childWidget->isHidden() );
1253 QVERIFY( !grandChildWidget->isHidden() );
1255 grandChildWidget->show();
1256 QVERIFY( !grandChildWidget->isHidden() );
1259 void tst_QWidget::fonts()
1261 // Tests setFont(), ownFont() and unsetFont()
1262 QWidget* cleanTestWidget = new QWidget( testWidget );
1263 QFont originalFont = cleanTestWidget->font();
1265 QVERIFY( !cleanTestWidget->testAttribute(Qt::WA_SetFont) );
1266 cleanTestWidget->setFont(QFont());
1267 QVERIFY( !cleanTestWidget->testAttribute(Qt::WA_SetFont) );
1269 QFont newFont( "times", 18 );
1270 cleanTestWidget->setFont( newFont );
1271 newFont = newFont.resolve( testWidget->font() );
1273 QVERIFY( cleanTestWidget->testAttribute(Qt::WA_SetFont) );
1274 QVERIFY( cleanTestWidget->font() == newFont );
1276 cleanTestWidget->setFont(QFont());
1277 QVERIFY( !cleanTestWidget->testAttribute(Qt::WA_SetFont) );
1278 QVERIFY( cleanTestWidget->font() == originalFont );
1281 void tst_QWidget::mapFromAndTo_data()
1283 QTest::addColumn<bool>("windowHidden");
1284 QTest::addColumn<bool>("subWindow1Hidden");
1285 QTest::addColumn<bool>("subWindow2Hidden");
1286 QTest::addColumn<bool>("subSubWindowHidden");
1287 QTest::addColumn<bool>("windowMinimized");
1288 QTest::addColumn<bool>("subWindow1Minimized");
1290 QTest::newRow("window 1 sub1 1 sub2 1 subsub 1") << false << false << false << false << false << false;
1291 QTest::newRow("window 0 sub1 1 sub2 1 subsub 1") << true << false << false << false << false << false;
1292 QTest::newRow("window 1 sub1 0 sub2 1 subsub 1") << false << true << false << false << false << false;
1293 QTest::newRow("window 0 sub1 0 sub2 1 subsub 1") << true << true << false << false << false << false;
1294 QTest::newRow("window 1 sub1 1 sub2 0 subsub 1") << false << false << true << false << false << false;
1295 QTest::newRow("window 0 sub1 1 sub2 0 subsub 1") << true << false << true << false << false << false;
1296 QTest::newRow("window 1 sub1 0 sub2 0 subsub 1") << false << true << true << false << false << false;
1297 QTest::newRow("window 0 sub1 0 sub2 0 subsub 1") << true << true << true << false << false << false;
1298 QTest::newRow("window 1 sub1 1 sub2 1 subsub 0") << false << false << false << true << false << false;
1299 QTest::newRow("window 0 sub1 1 sub2 1 subsub 0") << true << false << false << true << false << false;
1300 QTest::newRow("window 1 sub1 0 sub2 1 subsub 0") << false << true << false << true << false << false;
1301 QTest::newRow("window 0 sub1 0 sub2 1 subsub 0") << true << true << false << true << false << false;
1302 QTest::newRow("window 1 sub1 1 sub2 0 subsub 0") << false << false << true << true << false << false;
1303 QTest::newRow("window 0 sub1 1 sub2 0 subsub 0") << true << false << true << true << false << false;
1304 QTest::newRow("window 1 sub1 0 sub2 0 subsub 0") << false << true << true << true << false << false;
1305 QTest::newRow("window 0 sub1 0 sub2 0 subsub 0") << true << true << true << true << false << false;
1306 QTest::newRow("window 1 sub1 1 sub2 1 subsub 1 windowMinimized") << false << false << false << false << true << false;
1307 QTest::newRow("window 0 sub1 1 sub2 1 subsub 1 windowMinimized") << true << false << false << false << true << false;
1308 QTest::newRow("window 1 sub1 0 sub2 1 subsub 1 windowMinimized") << false << true << false << false << true << false;
1309 QTest::newRow("window 0 sub1 0 sub2 1 subsub 1 windowMinimized") << true << true << false << false << true << false;
1310 QTest::newRow("window 1 sub1 1 sub2 0 subsub 1 windowMinimized") << false << false << true << false << true << false;
1311 QTest::newRow("window 0 sub1 1 sub2 0 subsub 1 windowMinimized") << true << false << true << false << true << false;
1312 QTest::newRow("window 1 sub1 0 sub2 0 subsub 1 windowMinimized") << false << true << true << false << true << false;
1313 QTest::newRow("window 0 sub1 0 sub2 0 subsub 1 windowMinimized") << true << true << true << false << true << false;
1314 QTest::newRow("window 1 sub1 1 sub2 1 subsub 0 windowMinimized") << false << false << false << true << true << false;
1315 QTest::newRow("window 0 sub1 1 sub2 1 subsub 0 windowMinimized") << true << false << false << true << true << false;
1316 QTest::newRow("window 1 sub1 0 sub2 1 subsub 0 windowMinimized") << false << true << false << true << true << false;
1317 QTest::newRow("window 0 sub1 0 sub2 1 subsub 0 windowMinimized") << true << true << false << true << true << false;
1318 QTest::newRow("window 1 sub1 1 sub2 0 subsub 0 windowMinimized") << false << false << true << true << true << false;
1319 QTest::newRow("window 0 sub1 1 sub2 0 subsub 0 windowMinimized") << true << false << true << true << true << false;
1320 QTest::newRow("window 1 sub1 0 sub2 0 subsub 0 windowMinimized") << false << true << true << true << true << false;
1321 QTest::newRow("window 0 sub1 0 sub2 0 subsub 0 windowMinimized") << true << true << true << true << true << false;
1322 QTest::newRow("window 1 sub1 1 sub2 1 subsub 1 subWindow1Minimized") << false << false << false << false << false << true;
1323 QTest::newRow("window 0 sub1 1 sub2 1 subsub 1 subWindow1Minimized") << true << false << false << false << false << true;
1324 QTest::newRow("window 1 sub1 0 sub2 1 subsub 1 subWindow1Minimized") << false << true << false << false << false << true;
1325 QTest::newRow("window 0 sub1 0 sub2 1 subsub 1 subWindow1Minimized") << true << true << false << false << false << true;
1326 QTest::newRow("window 1 sub1 1 sub2 0 subsub 1 subWindow1Minimized") << false << false << true << false << false << true;
1327 QTest::newRow("window 0 sub1 1 sub2 0 subsub 1 subWindow1Minimized") << true << false << true << false << false << true;
1328 QTest::newRow("window 1 sub1 0 sub2 0 subsub 1 subWindow1Minimized") << false << true << true << false << false << true;
1329 QTest::newRow("window 0 sub1 0 sub2 0 subsub 1 subWindow1Minimized") << true << true << true << false << false << true;
1330 QTest::newRow("window 1 sub1 1 sub2 1 subsub 0 subWindow1Minimized") << false << false << false << true << false << true;
1331 QTest::newRow("window 0 sub1 1 sub2 1 subsub 0 subWindow1Minimized") << true << false << false << true << false << true;
1332 QTest::newRow("window 1 sub1 0 sub2 1 subsub 0 subWindow1Minimized") << false << true << false << true << false << true;
1333 QTest::newRow("window 0 sub1 0 sub2 1 subsub 0 subWindow1Minimized") << true << true << false << true << false << true;
1334 QTest::newRow("window 1 sub1 1 sub2 0 subsub 0 subWindow1Minimized") << false << false << true << true << false << true;
1335 QTest::newRow("window 0 sub1 1 sub2 0 subsub 0 subWindow1Minimized") << true << false << true << true << false << true;
1336 QTest::newRow("window 1 sub1 0 sub2 0 subsub 0 subWindow1Minimized") << false << true << true << true << false << true;
1337 QTest::newRow("window 0 sub1 0 sub2 0 subsub 0 subWindow1Minimized") << true << true << true << true << false << true;
1342 void tst_QWidget::mapFromAndTo()
1344 QFETCH(bool, windowHidden);
1345 QFETCH(bool, subWindow1Hidden);
1346 QFETCH(bool, subWindow2Hidden);
1347 QFETCH(bool, subSubWindowHidden);
1348 QFETCH(bool, windowMinimized);
1349 QFETCH(bool, subWindow1Minimized);
1351 // create a toplevel and two overlapping siblings
1353 window.setObjectName(QStringLiteral("mapFromAndTo"));
1354 window.setWindowTitle(window.objectName());
1355 window.setWindowFlags(window.windowFlags() | Qt::X11BypassWindowManagerHint);
1356 QWidget *subWindow1 = new QWidget(&window);
1357 QWidget *subWindow2 = new QWidget(&window);
1358 QWidget *subSubWindow = new QWidget(subWindow1);
1360 // set their geometries
1361 window.setGeometry(100, 100, 100, 100);
1362 subWindow1->setGeometry(50, 50, 100, 100);
1363 subWindow2->setGeometry(75, 75, 100, 100);
1364 subSubWindow->setGeometry(10, 10, 10, 10);
1366 #if !defined (Q_OS_WINCE) //still no proper minimizing
1368 if (windowMinimized) {
1369 if (!windowHidden) {
1370 window.showMinimized();
1371 QVERIFY(window.isMinimized());
1374 window.setVisible(!windowHidden);
1376 if (subWindow1Minimized) {
1378 subWindow1->showMinimized();
1379 QVERIFY(subWindow1->isMinimized());
1381 subWindow1->setVisible(!subWindow1Hidden);
1384 Q_UNUSED(windowHidden);
1385 Q_UNUSED(subWindow1Hidden);
1386 Q_UNUSED(windowMinimized);
1387 Q_UNUSED(subWindow1Minimized);
1390 subWindow2->setVisible(!subWindow2Hidden);
1391 subSubWindow->setVisible(!subSubWindowHidden);
1394 QCOMPARE(window.mapToGlobal(QPoint(0, 0)), QPoint(100, 100));
1395 QCOMPARE(window.mapToGlobal(QPoint(10, 0)), QPoint(110, 100));
1396 QCOMPARE(window.mapToGlobal(QPoint(0, 10)), QPoint(100, 110));
1397 QCOMPARE(window.mapToGlobal(QPoint(-10, 0)), QPoint(90, 100));
1398 QCOMPARE(window.mapToGlobal(QPoint(0, -10)), QPoint(100, 90));
1399 QCOMPARE(window.mapToGlobal(QPoint(100, 100)), QPoint(200, 200));
1400 QCOMPARE(window.mapToGlobal(QPoint(110, 100)), QPoint(210, 200));
1401 QCOMPARE(window.mapToGlobal(QPoint(100, 110)), QPoint(200, 210));
1402 QCOMPARE(window.mapFromGlobal(QPoint(100, 100)), QPoint(0, 0));
1403 QCOMPARE(window.mapFromGlobal(QPoint(110, 100)), QPoint(10, 0));
1404 QCOMPARE(window.mapFromGlobal(QPoint(100, 110)), QPoint(0, 10));
1405 QCOMPARE(window.mapFromGlobal(QPoint(90, 100)), QPoint(-10, 0));
1406 QCOMPARE(window.mapFromGlobal(QPoint(100, 90)), QPoint(0, -10));
1407 QCOMPARE(window.mapFromGlobal(QPoint(200, 200)), QPoint(100, 100));
1408 QCOMPARE(window.mapFromGlobal(QPoint(210, 200)), QPoint(110, 100));
1409 QCOMPARE(window.mapFromGlobal(QPoint(200, 210)), QPoint(100, 110));
1410 QCOMPARE(window.mapToParent(QPoint(0, 0)), QPoint(100, 100));
1411 QCOMPARE(window.mapToParent(QPoint(10, 0)), QPoint(110, 100));
1412 QCOMPARE(window.mapToParent(QPoint(0, 10)), QPoint(100, 110));
1413 QCOMPARE(window.mapToParent(QPoint(-10, 0)), QPoint(90, 100));
1414 QCOMPARE(window.mapToParent(QPoint(0, -10)), QPoint(100, 90));
1415 QCOMPARE(window.mapToParent(QPoint(100, 100)), QPoint(200, 200));
1416 QCOMPARE(window.mapToParent(QPoint(110, 100)), QPoint(210, 200));
1417 QCOMPARE(window.mapToParent(QPoint(100, 110)), QPoint(200, 210));
1418 QCOMPARE(window.mapFromParent(QPoint(100, 100)), QPoint(0, 0));
1419 QCOMPARE(window.mapFromParent(QPoint(110, 100)), QPoint(10, 0));
1420 QCOMPARE(window.mapFromParent(QPoint(100, 110)), QPoint(0, 10));
1421 QCOMPARE(window.mapFromParent(QPoint(90, 100)), QPoint(-10, 0));
1422 QCOMPARE(window.mapFromParent(QPoint(100, 90)), QPoint(0, -10));
1423 QCOMPARE(window.mapFromParent(QPoint(200, 200)), QPoint(100, 100));
1424 QCOMPARE(window.mapFromParent(QPoint(210, 200)), QPoint(110, 100));
1425 QCOMPARE(window.mapFromParent(QPoint(200, 210)), QPoint(100, 110));
1428 QCOMPARE(subWindow1->mapToGlobal(QPoint(0, 0)), QPoint(150, 150));
1429 QCOMPARE(subWindow1->mapToGlobal(QPoint(10, 0)), QPoint(160, 150));
1430 QCOMPARE(subWindow1->mapToGlobal(QPoint(0, 10)), QPoint(150, 160));
1431 QCOMPARE(subWindow1->mapToGlobal(QPoint(-10, 0)), QPoint(140, 150));
1432 QCOMPARE(subWindow1->mapToGlobal(QPoint(0, -10)), QPoint(150, 140));
1433 QCOMPARE(subWindow1->mapToGlobal(QPoint(100, 100)), QPoint(250, 250));
1434 QCOMPARE(subWindow1->mapToGlobal(QPoint(110, 100)), QPoint(260, 250));
1435 QCOMPARE(subWindow1->mapToGlobal(QPoint(100, 110)), QPoint(250, 260));
1436 QCOMPARE(subWindow1->mapFromGlobal(QPoint(150, 150)), QPoint(0, 0));
1437 QCOMPARE(subWindow1->mapFromGlobal(QPoint(160, 150)), QPoint(10, 0));
1438 QCOMPARE(subWindow1->mapFromGlobal(QPoint(150, 160)), QPoint(0, 10));
1439 QCOMPARE(subWindow1->mapFromGlobal(QPoint(140, 150)), QPoint(-10, 0));
1440 QCOMPARE(subWindow1->mapFromGlobal(QPoint(150, 140)), QPoint(0, -10));
1441 QCOMPARE(subWindow1->mapFromGlobal(QPoint(250, 250)), QPoint(100, 100));
1442 QCOMPARE(subWindow1->mapFromGlobal(QPoint(260, 250)), QPoint(110, 100));
1443 QCOMPARE(subWindow1->mapFromGlobal(QPoint(250, 260)), QPoint(100, 110));
1444 QCOMPARE(subWindow1->mapToParent(QPoint(0, 0)), QPoint(50, 50));
1445 QCOMPARE(subWindow1->mapToParent(QPoint(10, 0)), QPoint(60, 50));
1446 QCOMPARE(subWindow1->mapToParent(QPoint(0, 10)), QPoint(50, 60));
1447 QCOMPARE(subWindow1->mapToParent(QPoint(-10, 0)), QPoint(40, 50));
1448 QCOMPARE(subWindow1->mapToParent(QPoint(0, -10)), QPoint(50, 40));
1449 QCOMPARE(subWindow1->mapToParent(QPoint(100, 100)), QPoint(150, 150));
1450 QCOMPARE(subWindow1->mapToParent(QPoint(110, 100)), QPoint(160, 150));
1451 QCOMPARE(subWindow1->mapToParent(QPoint(100, 110)), QPoint(150, 160));
1452 QCOMPARE(subWindow1->mapFromParent(QPoint(50, 50)), QPoint(0, 0));
1453 QCOMPARE(subWindow1->mapFromParent(QPoint(60, 50)), QPoint(10, 0));
1454 QCOMPARE(subWindow1->mapFromParent(QPoint(50, 60)), QPoint(0, 10));
1455 QCOMPARE(subWindow1->mapFromParent(QPoint(40, 50)), QPoint(-10, 0));
1456 QCOMPARE(subWindow1->mapFromParent(QPoint(50, 40)), QPoint(0, -10));
1457 QCOMPARE(subWindow1->mapFromParent(QPoint(150, 150)), QPoint(100, 100));
1458 QCOMPARE(subWindow1->mapFromParent(QPoint(160, 150)), QPoint(110, 100));
1459 QCOMPARE(subWindow1->mapFromParent(QPoint(150, 160)), QPoint(100, 110));
1462 QCOMPARE(subSubWindow->mapToGlobal(QPoint(0, 0)), QPoint(160, 160));
1463 QCOMPARE(subSubWindow->mapToGlobal(QPoint(10, 0)), QPoint(170, 160));
1464 QCOMPARE(subSubWindow->mapToGlobal(QPoint(0, 10)), QPoint(160, 170));
1465 QCOMPARE(subSubWindow->mapToGlobal(QPoint(-10, 0)), QPoint(150, 160));
1466 QCOMPARE(subSubWindow->mapToGlobal(QPoint(0, -10)), QPoint(160, 150));
1467 QCOMPARE(subSubWindow->mapToGlobal(QPoint(100, 100)), QPoint(260, 260));
1468 QCOMPARE(subSubWindow->mapToGlobal(QPoint(110, 100)), QPoint(270, 260));
1469 QCOMPARE(subSubWindow->mapToGlobal(QPoint(100, 110)), QPoint(260, 270));
1470 QCOMPARE(subSubWindow->mapFromGlobal(QPoint(160, 160)), QPoint(0, 0));
1471 QCOMPARE(subSubWindow->mapFromGlobal(QPoint(170, 160)), QPoint(10, 0));
1472 QCOMPARE(subSubWindow->mapFromGlobal(QPoint(160, 170)), QPoint(0, 10));
1473 QCOMPARE(subSubWindow->mapFromGlobal(QPoint(150, 160)), QPoint(-10, 0));
1474 QCOMPARE(subSubWindow->mapFromGlobal(QPoint(160, 150)), QPoint(0, -10));
1475 QCOMPARE(subSubWindow->mapFromGlobal(QPoint(260, 260)), QPoint(100, 100));
1476 QCOMPARE(subSubWindow->mapFromGlobal(QPoint(270, 260)), QPoint(110, 100));
1477 QCOMPARE(subSubWindow->mapFromGlobal(QPoint(260, 270)), QPoint(100, 110));
1478 QCOMPARE(subSubWindow->mapToParent(QPoint(0, 0)), QPoint(10, 10));
1479 QCOMPARE(subSubWindow->mapToParent(QPoint(10, 0)), QPoint(20, 10));
1480 QCOMPARE(subSubWindow->mapToParent(QPoint(0, 10)), QPoint(10, 20));
1481 QCOMPARE(subSubWindow->mapToParent(QPoint(-10, 0)), QPoint(0, 10));
1482 QCOMPARE(subSubWindow->mapToParent(QPoint(0, -10)), QPoint(10, 0));
1483 QCOMPARE(subSubWindow->mapToParent(QPoint(100, 100)), QPoint(110, 110));
1484 QCOMPARE(subSubWindow->mapToParent(QPoint(110, 100)), QPoint(120, 110));
1485 QCOMPARE(subSubWindow->mapToParent(QPoint(100, 110)), QPoint(110, 120));
1486 QCOMPARE(subSubWindow->mapFromParent(QPoint(10, 10)), QPoint(0, 0));
1487 QCOMPARE(subSubWindow->mapFromParent(QPoint(20, 10)), QPoint(10, 0));
1488 QCOMPARE(subSubWindow->mapFromParent(QPoint(10, 20)), QPoint(0, 10));
1489 QCOMPARE(subSubWindow->mapFromParent(QPoint(0, 10)), QPoint(-10, 0));
1490 QCOMPARE(subSubWindow->mapFromParent(QPoint(10, 0)), QPoint(0, -10));
1491 QCOMPARE(subSubWindow->mapFromParent(QPoint(110, 110)), QPoint(100, 100));
1492 QCOMPARE(subSubWindow->mapFromParent(QPoint(120, 110)), QPoint(110, 100));
1493 QCOMPARE(subSubWindow->mapFromParent(QPoint(110, 120)), QPoint(100, 110));
1496 void tst_QWidget::focusChainOnReparent()
1499 QWidget *child1 = new QWidget(&window);
1500 QWidget *child2 = new QWidget(&window);
1501 QWidget *child3 = new QWidget(&window);
1502 QWidget *child21 = new QWidget(child2);
1503 QWidget *child22 = new QWidget(child2);
1504 QWidget *child4 = new QWidget(&window);
1506 QWidget *expectedOriginalChain[8] = {&window, child1, child2, child3, child21, child22, child4, &window};
1507 QWidget *w = &window;
1508 for (int i = 0; i <8; ++i) {
1509 QCOMPARE(w, expectedOriginalChain[i]);
1510 w = w->nextInFocusChain();
1512 for (int i = 7; i >= 0; --i) {
1513 w = w->previousInFocusChain();
1514 QCOMPARE(w, expectedOriginalChain[i]);
1518 child2->setParent(&window2);
1520 QWidget *expectedNewChain[5] = {&window2, child2, child21, child22, &window2};
1522 for (int i = 0; i <5; ++i) {
1523 QCOMPARE(w, expectedNewChain[i]);
1524 w = w->nextInFocusChain();
1526 for (int i = 4; i >= 0; --i) {
1527 w = w->previousInFocusChain();
1528 QCOMPARE(w, expectedNewChain[i]);
1531 QWidget *expectedOldChain[5] = {&window, child1, child3, child4, &window};
1533 for (int i = 0; i <5; ++i) {
1534 QCOMPARE(w, expectedOldChain[i]);
1535 w = w->nextInFocusChain();
1537 for (int i = 4; i >= 0; --i) {
1538 w = w->previousInFocusChain();
1539 QCOMPARE(w, expectedOldChain[i]);
1544 void tst_QWidget::focusChainOnHide()
1546 testWidget->hide(); // We do not want to get disturbed by other widgets
1547 // focus should move to the next widget in the focus chain when we hide it.
1548 QScopedPointer<QWidget> parent(new QWidget());
1549 parent->setObjectName(QLatin1String("focusChainOnHide"));
1550 parent->resize(200, 200);
1551 parent->setWindowTitle(parent->objectName());
1552 parent->setFocusPolicy(Qt::StrongFocus);
1553 QWidget *child = new QWidget(parent.data());
1554 child->setObjectName(QLatin1String("child"));
1555 child->setFocusPolicy(Qt::StrongFocus);
1556 QWidget::setTabOrder(child, parent.data());
1559 qApp->setActiveWindow(parent->window());
1560 child->activateWindow();
1562 qApp->processEvents();
1564 QTRY_COMPARE(child->hasFocus(), true);
1566 qApp->processEvents();
1568 QTRY_COMPARE(parent->hasFocus(), true);
1569 QCOMPARE(parent.data(), qApp->focusWidget());
1571 testWidget->show(); //don't disturb later tests
1574 class Container : public QWidget
1581 box = new QVBoxLayout(this);
1582 //(new QVBoxLayout(this))->setAutoAdd(true);
1587 focusNextPrevChild(true);
1592 focusNextPrevChild(false);
1596 class Composite : public QFrame
1599 Composite(QWidget* parent = 0, const char* name = 0)
1602 setObjectName(name);
1603 //QHBoxLayout* hbox = new QHBoxLayout(this, 2, 0);
1604 //hbox->setAutoAdd(true);
1605 QHBoxLayout* hbox = new QHBoxLayout(this);
1607 lineEdit = new QLineEdit(this);
1608 hbox->addWidget(lineEdit);
1610 button = new QPushButton(this);
1611 hbox->addWidget(button);
1612 button->setFocusPolicy( Qt::NoFocus );
1614 setFocusProxy( lineEdit );
1615 setFocusPolicy( Qt::StrongFocus );
1617 setTabOrder(lineEdit, button);
1621 QLineEdit* lineEdit;
1622 QPushButton* button;
1625 #define NUM_WIDGETS 4
1627 void tst_QWidget::setTabOrder()
1631 Container container;
1632 container.setObjectName("setTabOrder");
1633 container.setWindowTitle(container.objectName());
1635 Composite* comp[NUM_WIDGETS];
1637 QLineEdit *firstEdit = new QLineEdit(&container);
1638 container.box->addWidget(firstEdit);
1641 for(i = 0; i < NUM_WIDGETS; i++) {
1642 comp[i] = new Composite(&container);
1643 container.box->addWidget(comp[i]);
1646 QLineEdit *lastEdit = new QLineEdit(&container);
1647 container.box->addWidget(lastEdit);
1649 container.setTabOrder(lastEdit, comp[NUM_WIDGETS-1]);
1650 for(i = NUM_WIDGETS-1; i > 0; i--) {
1651 container.setTabOrder(comp[i], comp[i-1]);
1653 container.setTabOrder(comp[0], firstEdit);
1655 int current = NUM_WIDGETS-1;
1656 lastEdit->setFocus();
1659 container.activateWindow();
1660 qApp->setActiveWindow(&container);
1661 QVERIFY(QTest::qWaitForWindowActive(&container));
1663 QTRY_VERIFY(lastEdit->hasFocus());
1666 QVERIFY(comp[current]->focusProxy()->hasFocus());
1669 } while (current >= 0);
1671 QVERIFY(firstEdit->hasFocus());
1675 void tst_QWidget::activation()
1679 #if defined(Q_OS_WINCE)
1680 int waitTime = 1000;
1686 qApp->processEvents();
1689 widget1.setObjectName("activation-Widget1");
1690 widget1.setWindowTitle(widget1.objectName());
1693 widget1.setObjectName("activation-Widget2");
1694 widget1.setWindowTitle(widget2.objectName());
1699 QTest::qWait(waitTime);
1700 QVERIFY(qApp->activeWindow() == &widget2);
1701 widget2.showMinimized();
1702 QTest::qWait(waitTime);
1704 QEXPECT_FAIL("", "QTBUG-26418", Continue);
1705 QVERIFY(qApp->activeWindow() == &widget1);
1706 widget2.showMaximized();
1707 QTest::qWait(waitTime);
1708 QVERIFY(qApp->activeWindow() == &widget2);
1709 widget2.showMinimized();
1710 QTest::qWait(waitTime);
1711 QEXPECT_FAIL("", "QTBUG-26418", Continue);
1712 QVERIFY(qApp->activeWindow() == &widget1);
1713 widget2.showNormal();
1714 QTest::qWait(waitTime);
1715 #if 0 // QTBUG-26418, widget2 is always set to active
1717 if (QSysInfo::WindowsVersion >= QSysInfo::WV_VISTA)
1718 QEXPECT_FAIL("", "MS introduced new behavior after XP", Continue);
1721 QTest::qWait(waitTime);
1722 QVERIFY(qApp->activeWindow() == &widget2);
1724 QTest::qWait(waitTime);
1725 QVERIFY(qApp->activeWindow() == &widget1);
1729 void tst_QWidget::windowState()
1731 if (m_platform == QStringLiteral("xcb"))
1732 QSKIP("X11: Many window managers do not support window state properly, which causes this test to fail.");
1733 #ifdef Q_OS_WINCE_WM
1734 QPoint pos(500, 500);
1735 QSize size(200, 200);
1736 if (qt_wince_is_smartphone()) { //small screen
1737 pos = QPoint(10,10);
1738 size = QSize(100,100);
1741 const QPoint pos(500, 500);
1742 const QSize size(200, 200);
1747 widget1.resize(size);
1748 QCOMPARE(widget1.pos(), pos);
1749 QCOMPARE(widget1.size(), size);
1751 widget1.setObjectName(QStringLiteral("windowState-Widget1"));
1752 widget1.setWindowTitle(widget1.objectName());
1753 QCOMPARE(widget1.pos(), pos);
1754 QCOMPARE(widget1.size(), size);
1756 #define VERIFY_STATE(s) QCOMPARE(int(widget1.windowState() & stateMask), int(s))
1758 const int stateMask = Qt::WindowMaximized|Qt::WindowMinimized|Qt::WindowFullScreen;
1760 widget1.setWindowState(Qt::WindowMaximized);
1762 VERIFY_STATE(Qt::WindowMaximized);
1763 QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowMaximized);
1767 VERIFY_STATE(Qt::WindowMaximized);
1768 QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowMaximized);
1770 widget1.setWindowState(widget1.windowState() ^ Qt::WindowMaximized);
1772 QVERIFY(!(widget1.windowState() & Qt::WindowMaximized));
1773 QTRY_COMPARE(widget1.pos(), pos);
1774 QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowNoState);
1776 widget1.setWindowState(Qt::WindowMinimized);
1778 VERIFY_STATE(Qt::WindowMinimized);
1779 QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowMinimized);
1781 widget1.setWindowState(widget1.windowState() | Qt::WindowMaximized);
1783 VERIFY_STATE((Qt::WindowMinimized|Qt::WindowMaximized));
1784 QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowMinimized);
1786 widget1.setWindowState(widget1.windowState() ^ Qt::WindowMinimized);
1788 VERIFY_STATE(Qt::WindowMaximized);
1789 QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowMaximized);
1791 widget1.setWindowState(widget1.windowState() ^ Qt::WindowMaximized);
1793 QVERIFY(!(widget1.windowState() & (Qt::WindowMinimized|Qt::WindowMaximized)));
1794 QTRY_COMPARE(widget1.pos(), pos);
1795 QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowNoState);
1797 widget1.setWindowState(Qt::WindowFullScreen);
1799 VERIFY_STATE(Qt::WindowFullScreen);
1800 QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowFullScreen);
1802 widget1.setWindowState(widget1.windowState() ^ Qt::WindowMinimized);
1804 VERIFY_STATE((Qt::WindowFullScreen|Qt::WindowMinimized));
1805 QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowMinimized);
1807 widget1.setWindowState(widget1.windowState() ^ Qt::WindowMinimized);
1809 VERIFY_STATE(Qt::WindowFullScreen);
1810 QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowFullScreen);
1812 widget1.setWindowState(Qt::WindowNoState);
1814 VERIFY_STATE(Qt::WindowNoState);
1815 QTRY_COMPARE(widget1.pos(), pos);
1816 QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowNoState);
1818 widget1.setWindowState(Qt::WindowFullScreen);
1820 VERIFY_STATE(Qt::WindowFullScreen);
1821 QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowFullScreen);
1823 widget1.setWindowState(widget1.windowState() ^ Qt::WindowMaximized);
1825 VERIFY_STATE((Qt::WindowFullScreen|Qt::WindowMaximized));
1826 QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowFullScreen);
1828 widget1.setWindowState(widget1.windowState() ^ Qt::WindowMinimized);
1830 VERIFY_STATE((Qt::WindowFullScreen|Qt::WindowMaximized|Qt::WindowMinimized));
1831 QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowMinimized);
1833 widget1.setWindowState(widget1.windowState() ^ Qt::WindowMinimized);
1835 VERIFY_STATE((Qt::WindowFullScreen|Qt::WindowMaximized));
1836 QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowFullScreen);
1838 widget1.setWindowState(widget1.windowState() ^ Qt::WindowFullScreen);
1840 VERIFY_STATE(Qt::WindowMaximized);
1841 QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowMaximized);
1843 widget1.setWindowState(widget1.windowState() ^ Qt::WindowMaximized);
1845 QVERIFY(!(widget1.windowState() & stateMask));
1846 QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowNoState);
1848 QTRY_COMPARE(widget1.pos(), pos);
1849 QTRY_COMPARE(widget1.size(), size);
1852 void tst_QWidget::showMaximized()
1855 QHBoxLayout *layout;
1856 layout = new QHBoxLayout;
1862 layout->addWidget(&le);
1863 layout->addWidget(&le2);
1864 layout->addWidget(&le3);
1866 layouted.setLayout(layout);
1868 plain.showMaximized();
1869 QVERIFY(plain.windowState() & Qt::WindowMaximized);
1872 QVERIFY(!(plain.windowState() & Qt::WindowMaximized));
1874 layouted.showMaximized();
1875 QVERIFY(layouted.windowState() & Qt::WindowMaximized);
1877 layouted.showNormal();
1878 QVERIFY(!(layouted.windowState() & Qt::WindowMaximized));
1880 // ### fixme: embedded may choose a different size to fit on the screen.
1881 if (layouted.size() != layouted.sizeHint())
1882 QEXPECT_FAIL("", "QTBUG-22326", Continue);
1883 QCOMPARE(layouted.size(), layouted.sizeHint());
1885 layouted.showMaximized();
1886 QVERIFY(layouted.isMaximized());
1887 QVERIFY(layouted.isVisible());
1890 QVERIFY(layouted.isMaximized());
1891 QVERIFY(!layouted.isVisible());
1893 layouted.showMaximized();
1894 QVERIFY(layouted.isMaximized());
1895 QVERIFY(layouted.isVisible());
1897 layouted.showMinimized();
1898 QVERIFY(layouted.isMinimized());
1899 QVERIFY(layouted.isMaximized());
1901 layouted.showMaximized();
1902 QVERIFY(!layouted.isMinimized());
1903 QVERIFY(layouted.isMaximized());
1904 QVERIFY(layouted.isVisible());
1906 layouted.showMinimized();
1907 QVERIFY(layouted.isMinimized());
1908 QVERIFY(layouted.isMaximized());
1910 layouted.showMaximized();
1911 QVERIFY(!layouted.isMinimized());
1912 QVERIFY(layouted.isMaximized());
1913 QVERIFY(layouted.isVisible());
1917 QWidget widget(&frame);
1918 widget.showMaximized();
1919 QVERIFY(widget.isMaximized());
1924 widget.setGeometry(0, 0, 10, 10);
1925 widget.showMaximized();
1926 QTRY_VERIFY(widget.size().width() > 20 && widget.size().height() > 20);
1930 void tst_QWidget::showFullScreen()
1933 QHBoxLayout *layout;
1938 layout = new QHBoxLayout;
1940 layout->addWidget(&le);
1941 layout->addWidget(&le2);
1942 layout->addWidget(&le3);
1944 layouted.setLayout(layout);
1946 plain.showFullScreen();
1947 QVERIFY(plain.windowState() & Qt::WindowFullScreen);
1948 QVERIFY(plain.windowHandle());
1949 QVERIFY(plain.windowHandle()->screen());
1950 const QRect expectedFullScreenGeometry = plain.windowHandle()->screen()->geometry();
1951 QTRY_COMPARE(plain.geometry(), expectedFullScreenGeometry);
1954 QVERIFY(!(plain.windowState() & Qt::WindowFullScreen));
1956 layouted.showFullScreen();
1957 QVERIFY(layouted.windowState() & Qt::WindowFullScreen);
1958 QTRY_COMPARE(layouted.geometry(), expectedFullScreenGeometry);
1960 layouted.showNormal();
1961 QVERIFY(!(layouted.windowState() & Qt::WindowFullScreen));
1963 // ### fixme: embedded may choose a different size to fit on the screen.
1964 if (layouted.size() != layouted.sizeHint())
1965 QEXPECT_FAIL("", "QTBUG-22326", Continue);
1966 QCOMPARE(layouted.size(), layouted.sizeHint());
1968 layouted.showFullScreen();
1969 QVERIFY(layouted.isFullScreen());
1970 QVERIFY(layouted.isVisible());
1971 QTRY_COMPARE(layouted.geometry(), expectedFullScreenGeometry);
1974 QVERIFY(layouted.isFullScreen());
1975 QVERIFY(!layouted.isVisible());
1977 layouted.showFullScreen();
1978 QVERIFY(layouted.isFullScreen());
1979 QVERIFY(layouted.isVisible());
1980 QTRY_COMPARE(layouted.geometry(), expectedFullScreenGeometry);
1982 layouted.showMinimized();
1983 QVERIFY(layouted.isMinimized());
1984 QVERIFY(layouted.isFullScreen());
1986 layouted.showFullScreen();
1987 QVERIFY(!layouted.isMinimized());
1988 QVERIFY(layouted.isFullScreen());
1989 QVERIFY(layouted.isVisible());
1990 QTRY_COMPARE(layouted.geometry(), expectedFullScreenGeometry);
1992 layouted.showMinimized();
1993 QVERIFY(layouted.isMinimized());
1994 QVERIFY(layouted.isFullScreen());
1996 layouted.showFullScreen();
1997 QVERIFY(!layouted.isMinimized());
1998 QVERIFY(layouted.isFullScreen());
1999 QVERIFY(layouted.isVisible());
2000 QTRY_COMPARE(layouted.geometry(), expectedFullScreenGeometry);
2004 QWidget widget(&frame);
2005 widget.showFullScreen();
2006 QVERIFY(widget.isFullScreen());
2007 QTRY_COMPARE(layouted.geometry(), expectedFullScreenGeometry);
2011 class ResizeWidget : public QWidget {
2013 ResizeWidget(QWidget *p = 0) : QWidget(p)
2015 setObjectName(QLatin1String("ResizeWidget"));
2016 setWindowTitle(objectName());
2017 m_resizeEventCount = 0;
2020 void resizeEvent(QResizeEvent *e){
2021 QCOMPARE(size(), e->size());
2022 ++m_resizeEventCount;
2026 int m_resizeEventCount;
2029 void tst_QWidget::resizeEvent()
2033 ResizeWidget wChild(&wParent);
2035 QCOMPARE (wChild.m_resizeEventCount, 1); // initial resize event before paint
2037 QSize safeSize(640,480);
2038 if (wChild.size() == safeSize)
2039 safeSize.setWidth(639);
2040 wChild.resize(safeSize);
2041 QCOMPARE (wChild.m_resizeEventCount, 1);
2043 QCOMPARE (wChild.m_resizeEventCount, 2);
2047 ResizeWidget wTopLevel;
2049 if (m_platform == QStringLiteral("windows"))
2050 QSKIP("QTBUG-26424");
2051 QCOMPARE (wTopLevel.m_resizeEventCount, 1); // initial resize event before paint for toplevels
2053 QSize safeSize(640,480);
2054 if (wTopLevel.size() == safeSize)
2055 safeSize.setWidth(639);
2056 wTopLevel.resize(safeSize);
2057 QCOMPARE (wTopLevel.m_resizeEventCount, 1);
2059 QCOMPARE (wTopLevel.m_resizeEventCount, 2);
2063 void tst_QWidget::showMinimized()
2066 plain.move(100, 100);
2067 plain.resize(200, 200);
2068 QPoint pos = plain.pos();
2070 plain.showMinimized();
2071 QVERIFY(plain.isMinimized());
2072 QVERIFY(plain.isVisible());
2073 QCOMPARE(plain.pos(), pos);
2076 QVERIFY(!plain.isMinimized());
2077 QVERIFY(plain.isVisible());
2078 QCOMPARE(plain.pos(), pos);
2080 plain.showMinimized();
2081 QVERIFY(plain.isMinimized());
2082 QVERIFY(plain.isVisible());
2083 QCOMPARE(plain.pos(), pos);
2086 QVERIFY(plain.isMinimized());
2087 QVERIFY(!plain.isVisible());
2089 plain.showMinimized();
2090 QVERIFY(plain.isMinimized());
2091 QVERIFY(plain.isVisible());
2093 plain.setGeometry(200, 200, 300, 300);
2095 QCOMPARE(plain.geometry(), QRect(200, 200, 300, 300));
2099 QWidget widget(&frame);
2100 widget.showMinimized();
2101 QVERIFY(widget.isMinimized());
2105 void tst_QWidget::showMinimizedKeepsFocus()
2107 if (m_platform == QStringLiteral("xcb"))
2108 QSKIP("QTBUG-26424");
2110 //here we test that minimizing a widget and restoring it doesn't change the focus inside of it
2113 window.resize(200, 200);
2114 QWidget child1(&window), child2(&window);
2115 child1.setFocusPolicy(Qt::StrongFocus);
2116 child2.setFocusPolicy(Qt::StrongFocus);
2118 qApp->setActiveWindow(&window);
2119 QVERIFY(QTest::qWaitForWindowActive(&window));
2122 QTRY_COMPARE(window.focusWidget(), &child2);
2123 QTRY_COMPARE(qApp->focusWidget(), &child2);
2125 window.showMinimized();
2126 QTRY_VERIFY(window.isMinimized());
2127 QTRY_COMPARE(window.focusWidget(), &child2);
2129 window.showNormal();
2131 QTRY_COMPARE(window.focusWidget(), &child2);
2134 //testing deletion of the focusWidget
2137 QWidget *child = new QWidget(&window);
2138 child->setFocusPolicy(Qt::StrongFocus);
2140 qApp->setActiveWindow(&window);
2141 QVERIFY(QTest::qWaitForWindowActive(&window));
2143 QTRY_COMPARE(window.focusWidget(), child);
2144 QTRY_COMPARE(qApp->focusWidget(), child);
2147 QCOMPARE(window.focusWidget(), static_cast<QWidget*>(0));
2148 QCOMPARE(qApp->focusWidget(), static_cast<QWidget*>(0));
2151 //testing reparenting the focus widget
2154 QWidget *child = new QWidget(&window);
2155 child->setFocusPolicy(Qt::StrongFocus);
2157 qApp->setActiveWindow(&window);
2158 QVERIFY(QTest::qWaitForWindowActive(&window));
2160 QTRY_COMPARE(window.focusWidget(), child);
2161 QTRY_COMPARE(qApp->focusWidget(), child);
2163 child->setParent(0);
2164 QCOMPARE(window.focusWidget(), static_cast<QWidget*>(0));
2165 QCOMPARE(qApp->focusWidget(), static_cast<QWidget*>(0));
2168 //testing setEnabled(false)
2171 QWidget *child = new QWidget(&window);
2172 child->setFocusPolicy(Qt::StrongFocus);
2174 qApp->setActiveWindow(&window);
2175 QVERIFY(QTest::qWaitForWindowActive(&window));
2177 QTRY_COMPARE(window.focusWidget(), child);
2178 QTRY_COMPARE(qApp->focusWidget(), child);
2180 child->setEnabled(false);
2181 QCOMPARE(window.focusWidget(), static_cast<QWidget*>(0));
2182 QCOMPARE(qApp->focusWidget(), static_cast<QWidget*>(0));
2185 //testing clearFocus
2188 QWidget *firstchild = new QWidget(&window);
2189 firstchild->setFocusPolicy(Qt::StrongFocus);
2190 QWidget *child = new QWidget(&window);
2191 child->setFocusPolicy(Qt::StrongFocus);
2193 qApp->setActiveWindow(&window);
2194 QVERIFY(QTest::qWaitForWindowActive(&window));
2196 QTRY_COMPARE(window.focusWidget(), child);
2197 QTRY_COMPARE(qApp->focusWidget(), child);
2199 child->clearFocus();
2200 QCOMPARE(window.focusWidget(), static_cast<QWidget*>(0));
2201 QCOMPARE(qApp->focusWidget(), static_cast<QWidget*>(0));
2203 window.showMinimized();
2205 QTRY_VERIFY(window.isMinimized());
2206 QCOMPARE(window.focusWidget(), static_cast<QWidget*>(0));
2207 QTRY_COMPARE(qApp->focusWidget(), static_cast<QWidget*>(0));
2209 window.showNormal();
2210 qApp->setActiveWindow(&window);
2211 QVERIFY(QTest::qWaitForWindowActive(&window));
2213 if (!macHasAccessToWindowsServer())
2214 QEXPECT_FAIL("", "When not having WindowServer access, we lose focus.", Continue);
2216 QTRY_COMPARE(window.focusWidget(), firstchild);
2218 if (!macHasAccessToWindowsServer())
2219 QEXPECT_FAIL("", "When not having WindowServer access, we lose focus.", Continue);
2221 QTRY_COMPARE(qApp->focusWidget(), firstchild);
2226 void tst_QWidget::reparent()
2229 parent.setWindowTitle("Toplevel");
2230 parent.setGeometry(300, 300, 200, 150);
2233 child.setObjectName("child");
2234 child.setGeometry(10, 10, 180, 130);
2236 pal1.setColor(child.backgroundRole(), Qt::white);
2237 child.setPalette(pal1);
2239 QWidget childTLW(&child, Qt::Window);
2240 childTLW.setObjectName("childTLW");
2241 childTLW.setGeometry(100, 100, 50, 50);
2243 pal2.setColor(childTLW.backgroundRole(), Qt::yellow);
2244 childTLW.setPalette(pal2);
2248 QVERIFY(QTest::qWaitForWindowExposed(&parent));
2251 parent.move(50, 50);
2253 parent.move(300, 300);
2256 QPoint childPos = parent.mapToGlobal(child.pos());
2257 QPoint tlwPos = childTLW.pos();
2259 child.setParent(0, child.windowFlags() & ~Qt::WindowType_Mask);
2260 child.setGeometry(childPos.x(), childPos.y(), child.width(), child.height());
2263 #if 0 // QTBUG-26424
2264 if (m_platform == QStringLiteral("xcb"))
2265 QEXPECT_FAIL("", "On X11, the window manager will apply NorthWestGravity rules to 'child', which"
2266 " means the top-left corner of the window frame will be placed at 'childPos'"
2267 " causing this test to fail.", Continue);
2270 QCOMPARE(child.geometry().topLeft(), childPos);
2271 QTRY_COMPARE(childTLW.pos(), tlwPos);
2274 // Qt/Embedded does it differently.
2275 void tst_QWidget::icon()
2279 testWidget->setWindowIcon(p);
2281 QVERIFY(!testWidget->windowIcon().isNull());
2283 QVERIFY(!testWidget->windowIcon().isNull());
2284 testWidget->showFullScreen();
2285 QVERIFY(!testWidget->windowIcon().isNull());
2286 testWidget->showNormal();
2287 QVERIFY(!testWidget->windowIcon().isNull());
2290 void tst_QWidget::hideWhenFocusWidgetIsChild()
2292 testWidget->activateWindow();
2293 QScopedPointer<QWidget> parentWidget(new QWidget(testWidget));
2294 parentWidget->setObjectName("parentWidget");
2295 parentWidget->setGeometry(0, 0, 100, 100);
2296 QLineEdit *edit = new QLineEdit(parentWidget.data());
2297 edit->setObjectName("edit1");
2298 QLineEdit *edit3 = new QLineEdit(parentWidget.data());
2299 edit3->setObjectName("edit3");
2301 parentWidget->show();
2302 QLineEdit *edit2 = new QLineEdit(testWidget);
2303 edit2->setObjectName("edit2");
2305 edit2->move(110, 100);
2307 qApp->processEvents();
2308 QString actualFocusWidget, expectedFocusWidget;
2309 if (!qApp->focusWidget() && m_platform == QStringLiteral("xcb"))
2310 QSKIP("X11: Your window manager is too broken for this test");
2312 QVERIFY(qApp->focusWidget());
2313 actualFocusWidget.sprintf("%p %s %s", qApp->focusWidget(), qApp->focusWidget()->objectName().toLatin1().constData(), qApp->focusWidget()->metaObject()->className());
2314 expectedFocusWidget.sprintf("%p %s %s", edit, edit->objectName().toLatin1().constData(), edit->metaObject()->className());
2315 QCOMPARE(actualFocusWidget, expectedFocusWidget);
2317 parentWidget->hide();
2318 qApp->processEvents();
2319 actualFocusWidget.sprintf("%p %s %s", qApp->focusWidget(), qApp->focusWidget()->objectName().toLatin1().constData(), qApp->focusWidget()->metaObject()->className());
2320 expectedFocusWidget.sprintf("%p %s %s", edit2, edit2->objectName().toLatin1().constData(), edit2->metaObject()->className());
2321 QCOMPARE(actualFocusWidget, expectedFocusWidget);
2324 void tst_QWidget::normalGeometry()
2327 parent.setWindowTitle("NormalGeometry parent");
2328 QWidget *child = new QWidget(&parent);
2330 QCOMPARE(parent.normalGeometry(), parent.geometry());
2331 QCOMPARE(child->normalGeometry(), QRect());
2333 parent.setGeometry(100, 100, 200, 200);
2335 QVERIFY(QTest::qWaitForWindowExposed(&parent));
2336 QApplication::processEvents();
2338 QRect geom = parent.geometry();
2339 // ### the window manager places the top-left corner at
2340 // ### 100,100... making geom something like 102,124 (offset by
2341 // ### the frame/frame)... this indicates a rather large different
2342 // ### between how X11 and Windows works
2343 // QCOMPARE(geom, QRect(100, 100, 200, 200));
2344 QCOMPARE(parent.normalGeometry(), geom);
2346 parent.setWindowState(parent.windowState() ^ Qt::WindowMaximized);
2348 QTRY_VERIFY(parent.windowState() & Qt::WindowMaximized);
2349 QTRY_VERIFY(parent.geometry() != geom);
2350 QTRY_COMPARE(parent.normalGeometry(), geom);
2352 parent.setWindowState(parent.windowState() ^ Qt::WindowMaximized);
2354 QTRY_VERIFY(!(parent.windowState() & Qt::WindowMaximized));
2355 QTRY_COMPARE(parent.geometry(), geom);
2356 QTRY_COMPARE(parent.normalGeometry(), geom);
2358 parent.showMaximized();
2360 QTRY_VERIFY(parent.windowState() & Qt::WindowMaximized);
2361 QTRY_VERIFY(parent.geometry() != geom);
2362 QCOMPARE(parent.normalGeometry(), geom);
2364 parent.showNormal();
2366 QTRY_VERIFY(!(parent.windowState() & Qt::WindowMaximized));
2367 QTRY_COMPARE(parent.geometry(), geom);
2368 QCOMPARE(parent.normalGeometry(), geom);
2370 parent.setWindowState(parent.windowState() ^ Qt::WindowMinimized);
2372 parent.setWindowState(parent.windowState() ^ Qt::WindowMaximized);
2374 if (m_platform == QStringLiteral("xcb"))
2375 QSKIP("QTBUG-26424");
2376 QTRY_VERIFY(parent.windowState() & (Qt::WindowMinimized|Qt::WindowMaximized));
2377 // ### when minimized and maximized at the same time, the geometry
2378 // ### does *NOT* have to be the normal geometry, it could be the
2379 // ### maximized geometry.
2380 // QCOMPARE(parent.geometry(), geom);
2381 QTRY_COMPARE(parent.normalGeometry(), geom);
2383 parent.setWindowState(parent.windowState() ^ Qt::WindowMinimized);
2385 QTRY_VERIFY(!(parent.windowState() & Qt::WindowMinimized));
2386 QTRY_VERIFY(parent.windowState() & Qt::WindowMaximized);
2387 QTRY_VERIFY(parent.geometry() != geom);
2388 QTRY_COMPARE(parent.normalGeometry(), geom);
2390 parent.setWindowState(parent.windowState() ^ Qt::WindowMaximized);
2392 QTRY_VERIFY(!(parent.windowState() & Qt::WindowMaximized));
2393 QTRY_COMPARE(parent.geometry(), geom);
2394 QTRY_COMPARE(parent.normalGeometry(), geom);
2396 parent.setWindowState(parent.windowState() ^ Qt::WindowFullScreen);
2398 QTRY_VERIFY(parent.windowState() & Qt::WindowFullScreen);
2399 QTRY_VERIFY(parent.geometry() != geom);
2400 QTRY_COMPARE(parent.normalGeometry(), geom);
2402 parent.setWindowState(parent.windowState() ^ Qt::WindowFullScreen);
2404 QVERIFY(!(parent.windowState() & Qt::WindowFullScreen));
2405 QTRY_COMPARE(parent.geometry(), geom);
2406 QTRY_COMPARE(parent.normalGeometry(), geom);
2408 parent.showFullScreen();
2410 QTRY_VERIFY(parent.windowState() & Qt::WindowFullScreen);
2411 QTRY_VERIFY(parent.geometry() != geom);
2412 QTRY_COMPARE(parent.normalGeometry(), geom);
2414 parent.showNormal();
2416 QTRY_VERIFY(!(parent.windowState() & Qt::WindowFullScreen));
2417 QTRY_COMPARE(parent.geometry(), geom);
2418 QTRY_COMPARE(parent.normalGeometry(), geom);
2420 parent.showNormal();
2421 parent.setWindowState(Qt:: WindowFullScreen | Qt::WindowMaximized);
2422 parent.setWindowState(Qt::WindowMinimized | Qt:: WindowFullScreen | Qt::WindowMaximized);
2423 parent.setWindowState(Qt:: WindowFullScreen | Qt::WindowMaximized);
2425 QTRY_COMPARE(parent.normalGeometry(), geom);
2428 void tst_QWidget::setGeometry()
2431 QWidget child(&tlw);
2433 QRect tr(100,100,200,200);
2434 QRect cr(50,50,50,50);
2435 tlw.setGeometry(tr);
2436 child.setGeometry(cr);
2439 QCOMPARE(tlw.geometry().size(), tr.size());
2440 QCOMPARE(child.geometry(), cr);
2442 tlw.setParent(0, Qt::Window|Qt::FramelessWindowHint);
2443 tr = QRect(0,0,100,100);
2444 tr.moveTopLeft(QApplication::desktop()->availableGeometry().topLeft());
2445 tlw.setGeometry(tr);
2446 QCOMPARE(tlw.geometry(), tr);
2449 if (tlw.frameGeometry() != tlw.geometry())
2450 QSKIP("Your window manager is too broken for this test");
2451 if (m_platform == QStringLiteral("xcb"))
2452 QSKIP("QTBUG-26424");
2453 QCOMPARE(tlw.geometry(), tr);
2456 // Windows CE does not support windowOpacity.
2458 void tst_QWidget::windowOpacity()
2461 QWidget child(&widget);
2463 // Initial value should be 1.0
2464 QCOMPARE(widget.windowOpacity(), 1.0);
2465 // children should always return 1.0
2466 QCOMPARE(child.windowOpacity(), 1.0);
2468 widget.setWindowOpacity(0.0);
2469 QCOMPARE(widget.windowOpacity(), 0.0);
2470 child.setWindowOpacity(0.0);
2471 QCOMPARE(child.windowOpacity(), 1.0);
2473 widget.setWindowOpacity(1.0);
2474 QCOMPARE(widget.windowOpacity(), 1.0);
2475 child.setWindowOpacity(1.0);
2476 QCOMPARE(child.windowOpacity(), 1.0);
2478 widget.setWindowOpacity(2.0);
2479 QCOMPARE(widget.windowOpacity(), 1.0);
2480 child.setWindowOpacity(2.0);
2481 QCOMPARE(child.windowOpacity(), 1.0);
2483 widget.setWindowOpacity(-1.0);
2484 QCOMPARE(widget.windowOpacity(), 0.0);
2485 child.setWindowOpacity(-1.0);
2486 QCOMPARE(child.windowOpacity(), 1.0);
2490 class UpdateWidget : public QWidget
2493 UpdateWidget(QWidget *parent = 0) : QWidget(parent) {
2494 setObjectName(QLatin1String("UpdateWidget"));
2495 setWindowTitle(objectName());
2499 void paintEvent(QPaintEvent *e) {
2500 paintedRegion += e->region();
2502 if (resizeInPaintEvent) {
2503 resizeInPaintEvent = false;
2504 resize(size() + QSize(2, 2));
2508 bool event(QEvent *event)
2510 switch (event->type()) {
2511 case QEvent::ZOrderChange:
2512 ++numZOrderChangeEvents;
2514 case QEvent::UpdateRequest:
2515 ++numUpdateRequestEvents;
2517 case QEvent::ActivationChange:
2518 case QEvent::FocusIn:
2519 case QEvent::FocusOut:
2520 case QEvent::WindowActivate:
2521 case QEvent::WindowDeactivate:
2522 if (!updateOnActivationChangeAndFocusIn)
2523 return true; // Filter out to avoid update() calls in QWidget.
2528 return QWidget::event(event);
2533 numZOrderChangeEvents = 0;
2534 numUpdateRequestEvents = 0;
2535 updateOnActivationChangeAndFocusIn = false;
2536 resizeInPaintEvent = false;
2537 paintedRegion = QRegion();
2541 int numZOrderChangeEvents;
2542 int numUpdateRequestEvents;
2543 bool updateOnActivationChangeAndFocusIn;
2544 bool resizeInPaintEvent;
2545 QRegion paintedRegion;
2548 void tst_QWidget::lostUpdatesOnHide()
2551 UpdateWidget widget;
2552 widget.setAttribute(Qt::WA_DontShowOnScreen);
2559 QCOMPARE(widget.numPaintEvents, 1);
2563 void tst_QWidget::raise()
2566 QScopedPointer<QWidget> parentPtr(new QWidget);
2567 parentPtr->resize(200, 200);
2568 parentPtr->setObjectName(QLatin1String("raise"));
2569 parentPtr->setWindowTitle(parentPtr->objectName());
2570 QList<UpdateWidget *> allChildren;
2572 UpdateWidget *child1 = new UpdateWidget(parentPtr.data());
2573 child1->setAutoFillBackground(true);
2574 allChildren.append(child1);
2576 UpdateWidget *child2 = new UpdateWidget(parentPtr.data());
2577 child2->setAutoFillBackground(true);
2578 allChildren.append(child2);
2580 UpdateWidget *child3 = new UpdateWidget(parentPtr.data());
2581 child3->setAutoFillBackground(true);
2582 allChildren.append(child3);
2584 UpdateWidget *child4 = new UpdateWidget(parentPtr.data());
2585 child4->setAutoFillBackground(true);
2586 allChildren.append(child4);
2589 QVERIFY(QTest::qWaitForWindowExposed(parentPtr.data()));
2593 if (child1->internalWinId()) {
2594 QSKIP("Cocoa has no Z-Order for views, we hack it, but it results in paint events.");
2598 QList<QObject *> list1;
2599 list1 << child1 << child2 << child3 << child4;
2600 QVERIFY(parentPtr->children() == list1);
2601 QCOMPARE(allChildren.count(), list1.count());
2603 foreach (UpdateWidget *child, allChildren) {
2604 int expectedPaintEvents = child == child4 ? 1 : 0;
2605 if (expectedPaintEvents == 0) {
2606 QVERIFY(child->numPaintEvents == 0);
2608 // show() issues multiple paint events on some window managers
2609 QTRY_VERIFY(child->numPaintEvents >= expectedPaintEvents);
2611 QCOMPARE(child->numZOrderChangeEvents, 0);
2615 for (int i = 0; i < 5; ++i)
2619 foreach (UpdateWidget *child, allChildren) {
2620 int expectedPaintEvents = child == child2 ? 1 : 0;
2621 int expectedZOrderChangeEvents = child == child2 ? 1 : 0;
2623 QSKIP("Not yet sure why this fails.");
2625 QTRY_COMPARE(child->numPaintEvents, expectedPaintEvents);
2626 QCOMPARE(child->numZOrderChangeEvents, expectedZOrderChangeEvents);
2630 QList<QObject *> list2;
2631 list2 << child1 << child3 << child4 << child2;
2632 QVERIFY(parentPtr->children() == list2);
2634 // Creates a widget on top of all the children and checks that raising one of
2635 // the children underneath doesn't trigger a repaint on the covering widget.
2637 QWidget *parent = parentPtr.take();
2638 parent->setParent(&topLevel);
2640 QVERIFY(QTest::qWaitForWindowExposed(&topLevel));
2643 UpdateWidget *onTop = new UpdateWidget(&topLevel);
2645 onTop->resize(topLevel.size());
2646 onTop->setAutoFillBackground(true);
2649 QTRY_VERIFY(onTop->numPaintEvents > 0);
2652 // Reset all the children.
2653 foreach (UpdateWidget *child, allChildren)
2656 for (int i = 0; i < 5; ++i)
2660 QCOMPARE(onTop->numPaintEvents, 0);
2661 QCOMPARE(onTop->numZOrderChangeEvents, 0);
2663 QList<QObject *> list3;
2664 list3 << child1 << child4 << child2 << child3;
2665 QVERIFY(parent->children() == list3);
2667 foreach (UpdateWidget *child, allChildren) {
2668 int expectedPaintEvents = 0;
2669 int expectedZOrderChangeEvents = child == child3 ? 1 : 0;
2670 QTRY_COMPARE(child->numPaintEvents, expectedPaintEvents);
2671 QCOMPARE(child->numZOrderChangeEvents, expectedZOrderChangeEvents);
2676 // Cocoa has no Z-Order for views, we hack it, but it results in paint events.
2678 void tst_QWidget::lower()
2680 QScopedPointer<QWidget> parent(new QWidget);
2681 parent->setObjectName(QLatin1String("lower"));
2682 parent->setWindowTitle(parent->objectName());
2683 parent->resize(200, 200);
2684 QList<UpdateWidget *> allChildren;
2686 UpdateWidget *child1 = new UpdateWidget(parent.data());
2687 child1->setAutoFillBackground(true);
2688 allChildren.append(child1);
2690 UpdateWidget *child2 = new UpdateWidget(parent.data());
2691 child2->setAutoFillBackground(true);
2692 allChildren.append(child2);
2694 UpdateWidget *child3 = new UpdateWidget(parent.data());
2695 child3->setAutoFillBackground(true);
2696 allChildren.append(child3);
2698 UpdateWidget *child4 = new UpdateWidget(parent.data());
2699 child4->setAutoFillBackground(true);
2700 allChildren.append(child4);
2703 QVERIFY(QTest::qWaitForWindowExposed(parent.data()));
2705 QList<QObject *> list1;
2706 list1 << child1 << child2 << child3 << child4;
2707 QVERIFY(parent->children() == list1);
2708 QCOMPARE(allChildren.count(), list1.count());
2710 foreach (UpdateWidget *child, allChildren) {
2711 int expectedPaintEvents = child == child4 ? 1 : 0;
2712 if (expectedPaintEvents == 0) {
2713 QVERIFY(child->numPaintEvents == 0);
2715 // show() issues multiple paint events on some window managers
2716 QTRY_VERIFY(child->numPaintEvents >= expectedPaintEvents);
2718 QCOMPARE(child->numZOrderChangeEvents, 0);
2722 for (int i = 0; i < 5; ++i)
2727 foreach (UpdateWidget *child, allChildren) {
2728 int expectedPaintEvents = child == child3 ? 1 : 0;
2729 int expectedZOrderChangeEvents = child == child4 ? 1 : 0;
2730 QTRY_COMPARE(child->numZOrderChangeEvents, expectedZOrderChangeEvents);
2731 QTRY_COMPARE(child->numPaintEvents, expectedPaintEvents);
2735 QList<QObject *> list2;
2736 list2 << child4 << child1 << child2 << child3;
2737 QVERIFY(parent->children() == list2);
2741 // Cocoa has no Z-Order for views, we hack it, but it results in paint events.
2743 void tst_QWidget::stackUnder()
2745 QScopedPointer<QWidget> parent(new QWidget);
2746 parent->setObjectName(QLatin1String("stackUnder"));
2747 parent->setWindowTitle(parent->objectName());
2748 parent->resize(200, 200);
2749 QList<UpdateWidget *> allChildren;
2751 UpdateWidget *child1 = new UpdateWidget(parent.data());
2752 child1->setAutoFillBackground(true);
2753 allChildren.append(child1);
2755 UpdateWidget *child2 = new UpdateWidget(parent.data());
2756 child2->setAutoFillBackground(true);
2757 allChildren.append(child2);
2759 UpdateWidget *child3 = new UpdateWidget(parent.data());
2760 child3->setAutoFillBackground(true);
2761 allChildren.append(child3);
2763 UpdateWidget *child4 = new UpdateWidget(parent.data());
2764 child4->setAutoFillBackground(true);
2765 allChildren.append(child4);
2768 QVERIFY(QTest::qWaitForWindowExposed(parent.data()));
2769 QList<QObject *> list1;
2770 list1 << child1 << child2 << child3 << child4;
2771 QVERIFY(parent->children() == list1);
2773 foreach (UpdateWidget *child, allChildren) {
2774 int expectedPaintEvents = child == child4 ? 1 : 0;
2775 #if defined(Q_OS_WIN) || defined(Q_OS_MAC)
2776 if (expectedPaintEvents == 1 && child->numPaintEvents == 2)
2777 QEXPECT_FAIL(0, "Mac and Windows issues double repaints for Z-Order change", Continue);
2779 QTRY_COMPARE(child->numPaintEvents, expectedPaintEvents);
2780 QCOMPARE(child->numZOrderChangeEvents, 0);
2784 for (int i = 0; i < 5; ++i)
2785 child4->stackUnder(child2);
2788 QList<QObject *> list2;
2789 list2 << child1 << child4 << child2 << child3;
2790 QVERIFY(parent->children() == list2);
2792 foreach (UpdateWidget *child, allChildren) {
2793 int expectedPaintEvents = child == child3 ? 1 : 0;
2794 int expectedZOrderChangeEvents = child == child4 ? 1 : 0;
2795 QTRY_COMPARE(child->numPaintEvents, expectedPaintEvents);
2796 QTRY_COMPARE(child->numZOrderChangeEvents, expectedZOrderChangeEvents);
2800 for (int i = 0; i < 5; ++i)
2801 child1->stackUnder(child3);
2804 QList<QObject *> list3;
2805 list3 << child4 << child2 << child1 << child3;
2806 QVERIFY(parent->children() == list3);
2808 foreach (UpdateWidget *child, allChildren) {
2809 int expectedZOrderChangeEvents = child == child1 ? 1 : 0;
2810 if (child == child3) {
2812 qApp->processEvents();
2815 QEXPECT_FAIL(0, "See QTBUG-493", Continue);
2817 QCOMPARE(child->numPaintEvents, 0);
2819 QCOMPARE(child->numPaintEvents, 0);
2821 QTRY_COMPARE(child->numZOrderChangeEvents, expectedZOrderChangeEvents);
2827 void drawPolygon(QPaintDevice *dev, int w, int h)
2830 p.fillRect(0, 0, w, h, Qt::white);
2833 a << QPoint(0, 0) << QPoint(w/2, h/2) << QPoint(w, 0)
2834 << QPoint(w/2, h) << QPoint(0, 0);
2836 p.setPen(QPen(Qt::black, 1));
2837 p.setBrush(Qt::DiagCrossPattern);
2841 class ContentsPropagationWidget : public QWidget
2845 ContentsPropagationWidget(QWidget *parent = 0) : QWidget(parent)
2847 setObjectName(QLatin1String("ContentsPropagationWidget"));
2848 setWindowTitle(objectName());
2849 QWidget *child = this;
2850 for (int i=0; i<32; ++i) {
2851 child = new QWidget(child);
2852 child->setGeometry(i, i, 400 - i*2, 400 - i*2);
2856 void setContentsPropagation(bool enable) {
2857 foreach (QObject *child, children())
2858 qobject_cast<QWidget *>(child)->setAutoFillBackground(!enable);
2862 void paintEvent(QPaintEvent *)
2864 int w = width(), h = height();
2865 drawPolygon(this, w, h);
2868 QSize sizeHint() const { return QSize(500, 500); }
2871 void tst_QWidget::testContentsPropagation()
2873 ContentsPropagationWidget widget;
2874 widget.setFixedSize(500, 500);
2875 widget.setContentsPropagation(false);
2876 QPixmap widgetSnapshot = widget.grab(QRect(QPoint(0, 0), QSize(-1, -1)));
2878 QPixmap correct(500, 500);
2879 drawPolygon(&correct, 500, 500);
2880 //correct.save("correct.png", "PNG");
2882 //widgetSnapshot.save("snap1.png", "PNG");
2883 QVERIFY(widgetSnapshot.toImage() != correct.toImage());
2885 widget.setContentsPropagation(true);
2886 widgetSnapshot = widgetSnapshot = widget.grab(QRect(QPoint(0, 0), QSize(-1, -1)));
2887 //widgetSnapshot.save("snap2.png", "PNG");
2889 QCOMPARE(widgetSnapshot, correct);
2893 Test that saving and restoring window geometry with
2894 saveGeometry() and restoreGeometry() works.
2897 void tst_QWidget::saveRestoreGeometry()
2899 const QPoint position(100, 100);
2900 const QSize size(200, 200);
2902 QByteArray savedGeometry;
2906 widget.move(position);
2907 widget.resize(size);
2909 QVERIFY(QTest::qWaitForWindowExposed(&widget));
2910 QApplication::processEvents();
2912 QTRY_COMPARE(widget.pos(), position);
2913 QCOMPARE(widget.size(), size);
2914 savedGeometry = widget.saveGeometry();
2920 const QByteArray empty;
2921 const QByteArray one("a");
2922 const QByteArray two("ab");
2923 const QByteArray three("abc");
2924 const QByteArray four("abca");
2925 const QByteArray garbage("abcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabc");
2927 QVERIFY(widget.restoreGeometry(empty) == false);
2928 QVERIFY(widget.restoreGeometry(one) == false);
2929 QVERIFY(widget.restoreGeometry(two) == false);
2930 QVERIFY(widget.restoreGeometry(three) == false);
2931 QVERIFY(widget.restoreGeometry(four) == false);
2932 QVERIFY(widget.restoreGeometry(garbage) == false);
2934 QVERIFY(widget.restoreGeometry(savedGeometry));
2936 QVERIFY(QTest::qWaitForWindowExposed(&widget));
2937 QApplication::processEvents();
2939 QTRY_COMPARE(widget.pos(), position);
2940 QCOMPARE(widget.size(), size);
2942 QCOMPARE(widget.pos(), position);
2943 QCOMPARE(widget.size(), size);
2948 widget.move(position);
2949 widget.resize(size);
2951 QVERIFY(QTest::qWaitForWindowExposed(&widget));
2952 QTRY_COMPARE(widget.geometry().size(), size);
2956 //Restore from Full screen
2957 savedGeometry = widget.saveGeometry();
2958 geom = widget.geometry();
2959 widget.setWindowState(widget.windowState() | Qt::WindowFullScreen);
2960 QTRY_VERIFY((widget.windowState() & Qt::WindowFullScreen));
2962 QVERIFY(widget.restoreGeometry(savedGeometry));
2964 QTRY_VERIFY(!(widget.windowState() & Qt::WindowFullScreen));
2965 QTRY_COMPARE(widget.geometry(), geom);
2967 //Restore to full screen
2968 widget.setWindowState(widget.windowState() | Qt::WindowFullScreen);
2970 QTRY_VERIFY((widget.windowState() & Qt::WindowFullScreen));
2972 savedGeometry = widget.saveGeometry();
2973 geom = widget.geometry();
2974 widget.setWindowState(widget.windowState() ^ Qt::WindowFullScreen);
2976 QTRY_VERIFY(!(widget.windowState() & Qt::WindowFullScreen));
2978 QVERIFY(widget.restoreGeometry(savedGeometry));
2980 QTRY_VERIFY((widget.windowState() & Qt::WindowFullScreen));
2981 QTRY_COMPARE(widget.geometry(), geom);
2982 QVERIFY((widget.windowState() & Qt::WindowFullScreen));
2983 widget.setWindowState(widget.windowState() ^ Qt::WindowFullScreen);
2985 QTRY_VERIFY(!(widget.windowState() & Qt::WindowFullScreen));
2988 //Restore from Maximised
2989 widget.move(position);
2990 widget.resize(size);
2992 QTRY_COMPARE(widget.size(), size);
2994 savedGeometry = widget.saveGeometry();
2995 geom = widget.geometry();
2996 widget.setWindowState(widget.windowState() | Qt::WindowMaximized);
2998 QTRY_VERIFY((widget.windowState() & Qt::WindowMaximized));
2999 QTRY_VERIFY(widget.geometry() != geom);
3001 QVERIFY(widget.restoreGeometry(savedGeometry));
3003 QTRY_COMPARE(widget.geometry(), geom);
3005 QVERIFY(!(widget.windowState() & Qt::WindowMaximized));
3007 //Restore to maximised
3008 widget.setWindowState(widget.windowState() | Qt::WindowMaximized);
3010 QTRY_VERIFY((widget.windowState() & Qt::WindowMaximized));
3012 geom = widget.geometry();
3013 savedGeometry = widget.saveGeometry();
3014 widget.setWindowState(widget.windowState() ^ Qt::WindowMaximized);
3016 QTRY_VERIFY(!(widget.windowState() & Qt::WindowMaximized));
3018 QVERIFY(widget.restoreGeometry(savedGeometry));
3020 QTRY_VERIFY((widget.windowState() & Qt::WindowMaximized));
3021 QTRY_COMPARE(widget.geometry(), geom);
3025 void tst_QWidget::restoreVersion1Geometry_data()
3027 QTest::addColumn<QString>("fileName");
3028 QTest::addColumn<uint>("expectedWindowState");
3029 QTest::addColumn<QPoint>("expectedPosition");
3030 QTest::addColumn<QSize>("expectedSize");
3031 QTest::addColumn<QRect>("expectedNormalGeometry");
3032 const QPoint position(100, 100);
3033 const QSize size(200, 200);
3034 const QRect normalGeometry(102, 124, 200, 200);
3036 QTest::newRow("geometry.dat") << ":geometry.dat" << uint(Qt::WindowNoState) << position << size << normalGeometry;
3037 QTest::newRow("geometry-maximized.dat") << ":geometry-maximized.dat" << uint(Qt::WindowMaximized) << position << size << normalGeometry;
3038 QTest::newRow("geometry-fullscreen.dat") << ":geometry-fullscreen.dat" << uint(Qt::WindowFullScreen) << position << size << normalGeometry;
3042 Test that the current version of restoreGeometry() can restore geometry
3043 saved width saveGeometry() version 1.0.
3045 void tst_QWidget::restoreVersion1Geometry()
3047 QFETCH(QString, fileName);
3048 QFETCH(uint, expectedWindowState);
3049 QFETCH(QPoint, expectedPosition);
3050 QFETCH(QSize, expectedSize);
3051 QFETCH(QRect, expectedNormalGeometry);
3053 // WindowActive is uninteresting for this test
3054 const uint WindowStateMask = Qt::WindowFullScreen | Qt::WindowMaximized | Qt::WindowMinimized;
3057 QVERIFY(f.exists());
3058 f.open(QIODevice::ReadOnly);
3059 const QByteArray savedGeometry = f.readAll();
3060 QCOMPARE(savedGeometry.count(), 46);
3065 QVERIFY(widget.restoreGeometry(savedGeometry));
3067 QCOMPARE(uint(widget.windowState() & WindowStateMask), expectedWindowState);
3068 if (expectedWindowState == Qt::WindowNoState) {
3069 QCOMPARE(widget.pos(), expectedPosition);
3070 QCOMPARE(widget.size(), expectedSize);
3073 QVERIFY(QTest::qWaitForWindowExposed(&widget));
3076 if (expectedWindowState == Qt::WindowNoState) {
3077 QTRY_COMPARE(widget.pos(), expectedPosition);
3078 QTRY_COMPARE(widget.size(), expectedSize);
3081 widget.showNormal();
3084 if (m_platform == QStringLiteral("xcb") || m_platform == QStringLiteral("windows"))
3085 QSKIP("QTBUG-26421");
3087 if (expectedWindowState != Qt::WindowNoState) {
3088 // restoring from maximized or fullscreen, we can only restore to the normal geometry
3089 QTRY_COMPARE(widget.geometry(), expectedNormalGeometry);
3091 QTRY_COMPARE(widget.pos(), expectedPosition);
3092 QTRY_COMPARE(widget.size(), expectedSize);
3096 // Code for saving a new geometry*.dat files
3098 QWidget widgetToSave;
3099 widgetToSave.move(expectedPosition);
3100 widgetToSave.resize(expectedSize);
3101 widgetToSave.show();
3102 QVERIFY(QTest::qWaitForWindowExposed(&widget));
3103 QTest::qWait(500); // stabilize
3104 widgetToSave.setWindowState(Qt::WindowStates(expectedWindowState));
3105 QTest::qWait(500); // stabilize
3107 QByteArray geometryToSave = widgetToSave.saveGeometry();
3109 // Code for saving a new geometry.dat file.
3110 f.setFileName(fileName.mid(1));
3111 QVERIFY(f.open(QIODevice::WriteOnly)); // did you forget to 'p4 edit *.dat'? :)
3112 f.write(geometryToSave);
3118 void tst_QWidget::widgetAt()
3122 QScopedPointer<QWidget> w1(new QWidget(0, Qt::X11BypassWindowManagerHint));
3123 w1->setGeometry(0, 0, 160, 150);
3124 w1->setObjectName(QLatin1String("w1"));
3125 w1->setWindowTitle(w1->objectName());
3126 QScopedPointer<QWidget> w2(new QWidget(0, Qt::X11BypassWindowManagerHint | Qt::FramelessWindowHint));
3127 w2->setGeometry(50,50, 160, 100);
3128 w2->setObjectName(QLatin1String("w2"));
3129 w2->setWindowTitle(w2->objectName());
3131 QVERIFY(QTest::qWaitForWindowExposed(w1.data()));
3132 qApp->processEvents();
3134 QTRY_VERIFY((wr = QApplication::widgetAt(100, 100)));
3135 QCOMPARE(wr->objectName(), QString("w1"));
3138 QVERIFY(QTest::qWaitForWindowExposed(w2.data()));
3139 qApp->processEvents();
3140 qApp->processEvents();
3141 qApp->processEvents();
3142 QTRY_VERIFY((wr = QApplication::widgetAt(100, 100)));
3143 QCOMPARE(wr->objectName(), QString("w2"));
3146 qApp->processEvents();
3147 QTRY_VERIFY((wr = QApplication::widgetAt(100, 100)) && wr->objectName() == QString("w1"));
3150 qApp->processEvents();
3151 QTRY_VERIFY((wr = QApplication::widgetAt(100, 100)) && wr->objectName() == QString("w2"));
3153 QWidget *w3 = new QWidget(w2.data());
3154 w3->setGeometry(10,10,50,50);
3155 w3->setObjectName("w3");
3157 qApp->processEvents();
3158 QTRY_VERIFY((wr = QApplication::widgetAt(100,100)) && wr->objectName() == QString("w3"));
3160 w3->setAttribute(Qt::WA_TransparentForMouseEvents);
3161 qApp->processEvents();
3162 QTRY_VERIFY((wr = QApplication::widgetAt(100, 100)) && wr->objectName() == QString("w2"));
3164 QRegion rgn = QRect(QPoint(0,0), w2->size());
3165 QPoint point = w2->mapFromGlobal(QPoint(100,100));
3166 rgn -= QRect(point, QSize(1,1));
3168 qApp->processEvents();
3170 #if defined(Q_OS_WINCE)
3171 QEXPECT_FAIL("", "Windows CE does only support rectangular regions", Continue); //See also task 147191
3173 if (!QGuiApplication::platformName().compare(QLatin1String("cocoa"), Qt::CaseInsensitive))
3174 QEXPECT_FAIL("", "Window mask not implemented on Mac QTBUG-22326", Continue);
3176 QTRY_VERIFY((wr = QApplication::widgetAt(100,100)));
3177 QTRY_COMPARE(wr->objectName(), w1->objectName());
3178 QTRY_VERIFY((wr = QApplication::widgetAt(101,101)));
3179 QTRY_COMPARE(wr->objectName(), w2->objectName());
3181 QBitmap bitmap(w2->size());
3182 QPainter p(&bitmap);
3183 p.fillRect(bitmap.rect(), Qt::color1);
3184 p.setPen(Qt::color0);
3185 p.drawPoint(w2->mapFromGlobal(QPoint(100,100)));
3187 w2->setMask(bitmap);
3188 qApp->processEvents();
3190 #if defined(Q_OS_WINCE)
3191 QEXPECT_FAIL("", "Windows CE does only support rectangular regions", Continue); //See also task 147191
3193 if (!QGuiApplication::platformName().compare(QLatin1String("cocoa"), Qt::CaseInsensitive))
3194 QEXPECT_FAIL("", "Window mask not implemented on Mac QTBUG-22326", Continue);
3195 QTRY_VERIFY(QApplication::widgetAt(100,100) == w1.data());
3196 QTRY_VERIFY(QApplication::widgetAt(101,101) == w2.data());
3199 void tst_QWidget::task110173()
3203 QPushButton *pb1 = new QPushButton("click", &w);
3204 pb1->setFocusPolicy(Qt::ClickFocus);
3205 pb1->move(100, 100);
3207 QPushButton *pb2 = new QPushButton("push", &w);
3208 pb2->setFocusPolicy(Qt::ClickFocus);
3209 pb2->move(300, 300);
3211 QTest::keyClick( &w, Qt::Key_Tab );
3213 QVERIFY(QTest::qWaitForWindowExposed(&w));
3217 class Widget : public QWidget
3220 Widget() : deleteThis(false) { setFocusPolicy(Qt::StrongFocus); }
3221 void actionEvent(QActionEvent *) { if (deleteThis) delete this; }
3222 void changeEvent(QEvent *) { if (deleteThis) delete this; }
3223 void closeEvent(QCloseEvent *) { if (deleteThis) delete this; }
3224 void hideEvent(QHideEvent *) { if (deleteThis) delete this; }
3225 void focusOutEvent(QFocusEvent *) { if (deleteThis) delete this; }
3226 void keyPressEvent(QKeyEvent *) { if (deleteThis) delete this; }
3227 void keyReleaseEvent(QKeyEvent *) { if (deleteThis) delete this; }
3228 void mouseDoubleClickEvent(QMouseEvent *) { if (deleteThis) delete this; }
3229 void mousePressEvent(QMouseEvent *) { if (deleteThis) delete this; }
3230 void mouseReleaseEvent(QMouseEvent *) { if (deleteThis) delete this; }
3231 void mouseMoveEvent(QMouseEvent *) { if (deleteThis) delete this; }
3236 void tst_QWidget::testDeletionInEventHandlers()
3239 QPointer<Widget> w = new Widget;
3240 w->deleteThis = true;
3245 // focusOut (crashes)
3249 //QVERIFY(qApp->focusWidget() == w);
3250 //w->deleteThis = true;
3257 w->deleteThis = true;
3258 QTest::keyPress(w, Qt::Key_A);
3265 w->deleteThis = true;
3266 QTest::keyRelease(w, Qt::Key_A);
3273 w->deleteThis = true;
3274 QTest::mousePress(w, Qt::LeftButton);
3281 w->deleteThis = true;
3282 QTest::mouseRelease(w, Qt::LeftButton);
3286 // mouse double click
3289 w->deleteThis = true;
3290 QTest::mouseDClick(w, Qt::LeftButton);
3294 // hide event (crashes)
3297 //w->deleteThis = true;
3303 w->deleteThis = true;
3304 w->addAction(new QAction(w));
3311 w->deleteThis = true;
3312 w->setMouseTracking(true);
3317 w->setMouseTracking(true);
3319 w->deleteThis = true;
3320 QMouseEvent me(QEvent::MouseMove, QPoint(0, 0), Qt::NoButton, Qt::NoButton, Qt::NoModifier);
3321 QApplication::sendEvent(w, &me);
3327 void tst_QWidget::sheetOpacity()
3330 QWidget sheet(&tmpWindow, Qt::Sheet);
3333 QCOMPARE(int(sheet.windowOpacity() * 255), 242); // 95%
3334 sheet.setParent(0, Qt::Dialog);
3335 QCOMPARE(int(sheet.windowOpacity() * 255), 255);
3338 class MaskedPainter : public QWidget
3344 : mask(20, 20, 50, 50)
3349 void paintEvent(QPaintEvent *)
3352 p.fillRect(mask, QColor(Qt::red));
3357 Verifies that the entire area inside the mask is painted red.
3359 bool verifyWidgetMask(QWidget *widget, QRect mask)
3361 const QImage image = widget->grab(QRect(QPoint(0, 0), widget->size())).toImage();
3363 const QImage masked = image.copy(mask);
3365 red.fill(QColor(Qt::red).rgb());
3367 return (masked == red);
3370 void tst_QWidget::setMask()
3372 testWidget->hide(); // get this out of the way.
3379 QVERIFY(verifyWidgetMask(&w, w.mask));
3384 w.setWindowFlags(w.windowFlags() | Qt::FramelessWindowHint);
3387 QRect mask = w.mask;
3389 QVERIFY(verifyWidgetMask(&w, mask));
3394 class StaticWidget : public QWidget
3400 QRegion paintedRegion;
3402 StaticWidget(QWidget *parent = 0)
3405 setAttribute(Qt::WA_StaticContents);
3406 setAttribute(Qt::WA_OpaquePaintEvent);
3407 setPalette(Qt::red); // Make sure we have an opaque palette.
3408 setAutoFillBackground(true);
3409 gotPaintEvent = false;
3412 void paintEvent(QPaintEvent *e)
3414 paintedRegion += e->region();
3415 gotPaintEvent = true;
3416 // qDebug() << "paint" << e->region();
3417 // Look for a full update, set partial to false if found.
3418 foreach(QRect r, e->region().rects()) {
3419 partial = (r != rect());
3420 if (partial == false)
3427 Test that widget resizes and moves can be done with minimal repaints when WA_StaticContents
3428 and WA_OpaquePaintEvent is set. Test is mac-only for now.
3430 void tst_QWidget::optimizedResizeMove()
3433 parent.resize(400, 400);
3435 StaticWidget staticWidget(&parent);
3436 staticWidget.gotPaintEvent = false;
3437 staticWidget.move(150, 150);
3438 staticWidget.resize(150, 150);
3440 QVERIFY(QTest::qWaitForWindowExposed(&parent));
3442 QTRY_COMPARE(staticWidget.gotPaintEvent, true);
3444 staticWidget.gotPaintEvent = false;
3445 staticWidget.move(staticWidget.pos() + QPoint(10, 10));
3447 QCOMPARE(staticWidget.gotPaintEvent, false);
3449 staticWidget.gotPaintEvent = false;
3450 staticWidget.move(staticWidget.pos() + QPoint(-10, -10));
3452 QCOMPARE(staticWidget.gotPaintEvent, false);
3454 staticWidget.gotPaintEvent = false;
3455 staticWidget.move(staticWidget.pos() + QPoint(-10, 10));
3457 QCOMPARE(staticWidget.gotPaintEvent, false);
3459 staticWidget.gotPaintEvent = false;
3460 staticWidget.resize(staticWidget.size() + QSize(10, 10));
3462 QCOMPARE(staticWidget.gotPaintEvent, true);
3463 QCOMPARE(staticWidget.partial, true);
3465 staticWidget.gotPaintEvent = false;
3466 staticWidget.resize(staticWidget.size() + QSize(-10, -10));
3468 QCOMPARE(staticWidget.gotPaintEvent, false);
3470 staticWidget.gotPaintEvent = false;
3471 staticWidget.resize(staticWidget.size() + QSize(10, -10));
3473 QCOMPARE(staticWidget.gotPaintEvent, true);
3474 QCOMPARE(staticWidget.partial, true);
3476 staticWidget.gotPaintEvent = false;
3477 staticWidget.move(staticWidget.pos() + QPoint(10, 10));
3478 staticWidget.resize(staticWidget.size() + QSize(-10, -10));
3480 QCOMPARE(staticWidget.gotPaintEvent, false);
3482 staticWidget.gotPaintEvent = false;
3483 staticWidget.move(staticWidget.pos() + QPoint(10, 10));
3484 staticWidget.resize(staticWidget.size() + QSize(10, 10));
3486 QCOMPARE(staticWidget.gotPaintEvent, true);
3487 QCOMPARE(staticWidget.partial, true);
3489 staticWidget.gotPaintEvent = false;
3490 staticWidget.move(staticWidget.pos() + QPoint(-10, -10));
3491 staticWidget.resize(staticWidget.size() + QSize(-10, -10));
3493 QCOMPARE(staticWidget.gotPaintEvent, false);
3495 staticWidget.setAttribute(Qt::WA_StaticContents, false);
3496 staticWidget.gotPaintEvent = false;
3497 staticWidget.move(staticWidget.pos() + QPoint(-10, -10));
3498 staticWidget.resize(staticWidget.size() + QSize(-10, -10));
3500 QCOMPARE(staticWidget.gotPaintEvent, true);
3501 QCOMPARE(staticWidget.partial, false);
3502 staticWidget.setAttribute(Qt::WA_StaticContents, true);
3504 staticWidget.setAttribute(Qt::WA_StaticContents, false);
3505 staticWidget.gotPaintEvent = false;
3506 staticWidget.move(staticWidget.pos() + QPoint(10, 10));
3508 QCOMPARE(staticWidget.gotPaintEvent, false);
3509 staticWidget.setAttribute(Qt::WA_StaticContents, true);
3512 void tst_QWidget::optimizedResize_topLevel()
3514 #if defined(Q_OS_MAC)
3515 QSKIP("We do not yet have static contents support for *top-levels* on this platform");
3518 StaticWidget topLevel;
3519 topLevel.gotPaintEvent = false;
3521 QVERIFY(QTest::qWaitForWindowExposed(&topLevel));
3523 QTRY_COMPARE(topLevel.gotPaintEvent, true);
3525 topLevel.gotPaintEvent = false;
3526 topLevel.partial = false;
3527 topLevel.paintedRegion = QRegion();
3530 topLevel.resize(topLevel.size() + QSize(10, 10));
3532 // Static contents does not work when programmatically resizing
3533 // top-levels with QWidget::resize. We do some funky stuff in
3534 // setGeometry_sys. However, resizing it with the mouse or with
3535 // a native function call works (it basically has to go through
3536 // WM_RESIZE in QApplication). This is a corner case, though.
3538 const QRect frame = topLevel.frameGeometry();
3539 MoveWindow(winHandleOf(&topLevel), frame.x(), frame.y(),
3540 frame.width() + 10, frame.height() + 10,
3546 // Expected update region: New rect - old rect.
3547 QRegion expectedUpdateRegion(topLevel.rect());
3548 expectedUpdateRegion -= QRect(QPoint(), topLevel.size() - QSize(10, 10));
3550 QTRY_COMPARE(topLevel.gotPaintEvent, true);
3551 if (m_platform == QStringLiteral("xcb"))
3552 QSKIP("QTBUG-26424");
3553 QCOMPARE(topLevel.partial, true);
3554 QCOMPARE(topLevel.paintedRegion, expectedUpdateRegion);
3557 class SiblingDeleter : public QWidget
3560 inline SiblingDeleter(QWidget *sibling, QWidget *parent)
3561 : QWidget(parent), sibling(sibling) {}
3562 inline virtual ~SiblingDeleter() { delete sibling; }
3565 QPointer<QWidget> sibling;
3569 void tst_QWidget::childDeletesItsSibling()
3571 QWidget *commonParent = new QWidget(0);
3572 QPointer<QWidget> child = new QWidget(0);
3573 QPointer<QWidget> siblingDeleter = new SiblingDeleter(child, commonParent);
3574 child->setParent(commonParent);
3575 delete commonParent; // don't crash
3577 QVERIFY(!siblingDeleter);
3581 void tst_QWidget::setMinimumSize()
3584 QSize defaultSize = w.size();
3586 w.setMinimumSize(defaultSize + QSize(100, 100));
3587 QCOMPARE(w.size(), defaultSize + QSize(100, 100));
3588 QVERIFY(!w.testAttribute(Qt::WA_Resized));
3590 w.setMinimumSize(defaultSize + QSize(50, 50));
3591 QCOMPARE(w.size(), defaultSize + QSize(100, 100));
3592 QVERIFY(!w.testAttribute(Qt::WA_Resized));
3594 w.setMinimumSize(defaultSize + QSize(200, 200));
3595 QCOMPARE(w.size(), defaultSize + QSize(200, 200));
3596 QVERIFY(!w.testAttribute(Qt::WA_Resized));
3598 // Setting a minimum size larger than the desktop does not work on WinCE,
3599 // so skip this part of the test.
3601 QSize nonDefaultSize = defaultSize + QSize(5,5);
3602 w.setMinimumSize(nonDefaultSize);
3605 QVERIFY(w.height() >= nonDefaultSize.height());
3606 QVERIFY(w.width() >= nonDefaultSize.width());
3610 void tst_QWidget::setMaximumSize()
3613 QSize defaultSize = w.size();
3615 w.setMinimumSize(defaultSize + QSize(100, 100));
3616 QCOMPARE(w.size(), defaultSize + QSize(100, 100));
3617 QVERIFY(!w.testAttribute(Qt::WA_Resized));
3618 w.setMinimumSize(defaultSize);
3620 w.setMaximumSize(defaultSize + QSize(200, 200));
3621 QCOMPARE(w.size(), defaultSize + QSize(100, 100));
3622 QVERIFY(!w.testAttribute(Qt::WA_Resized));
3624 w.setMaximumSize(defaultSize + QSize(50, 50));
3625 QCOMPARE(w.size(), defaultSize + QSize(50, 50));
3626 QVERIFY(!w.testAttribute(Qt::WA_Resized));
3629 void tst_QWidget::setFixedSize()
3632 QSize defaultSize = w.size();
3634 w.setFixedSize(defaultSize + QSize(100, 100));
3635 QCOMPARE(w.size(), defaultSize + QSize(100, 100));
3636 QVERIFY(w.testAttribute(Qt::WA_Resized));
3638 w.setFixedSize(defaultSize + QSize(200, 200));
3640 QCOMPARE(w.minimumSize(), defaultSize + QSize(200,200));
3641 QCOMPARE(w.maximumSize(), defaultSize + QSize(200,200));
3642 QCOMPARE(w.size(), defaultSize + QSize(200, 200));
3643 QVERIFY(w.testAttribute(Qt::WA_Resized));
3645 w.setFixedSize(defaultSize + QSize(50, 50));
3646 QCOMPARE(w.size(), defaultSize + QSize(50, 50));
3647 QVERIFY(w.testAttribute(Qt::WA_Resized));
3649 w.setAttribute(Qt::WA_Resized, false);
3650 w.setFixedSize(defaultSize + QSize(50, 50));
3651 QVERIFY(!w.testAttribute(Qt::WA_Resized));
3653 w.setFixedSize(defaultSize + QSize(150, 150));
3656 if (m_platform == QStringLiteral("xcb"))
3657 QSKIP("QTBUG-26424");
3658 QVERIFY(w.size() == defaultSize + QSize(150,150));
3661 void tst_QWidget::ensureCreated()
3665 WId widgetWinId = widget.winId();
3666 Q_UNUSED(widgetWinId);
3667 QVERIFY(widget.testAttribute(Qt::WA_WState_Created));
3673 QDialog dialog(&window);
3674 dialog.setWindowModality(Qt::NonModal);
3676 WId dialogWinId = dialog.winId();
3677 Q_UNUSED(dialogWinId);
3678 QVERIFY(dialog.testAttribute(Qt::WA_WState_Created));
3679 QVERIFY(window.testAttribute(Qt::WA_WState_Created));
3685 QDialog dialog(&window);
3686 dialog.setWindowModality(Qt::WindowModal);
3688 WId dialogWinId = dialog.winId();
3689 Q_UNUSED(dialogWinId);
3690 QVERIFY(dialog.testAttribute(Qt::WA_WState_Created));
3691 QVERIFY(window.testAttribute(Qt::WA_WState_Created));
3697 QDialog dialog(&window);
3698 dialog.setWindowModality(Qt::ApplicationModal);
3700 WId dialogWinId = dialog.winId();
3701 Q_UNUSED(dialogWinId);
3702 QVERIFY(dialog.testAttribute(Qt::WA_WState_Created));
3703 QVERIFY(window.testAttribute(Qt::WA_WState_Created));
3707 class WinIdChangeWidget : public QWidget {
3709 WinIdChangeWidget(QWidget *p = 0)
3715 bool event(QEvent *e)
3717 if (e->type() == QEvent::WinIdChange) {
3718 m_winIdList.append(internalWinId());
3721 return QWidget::event(e);
3724 QList<WId> m_winIdList;
3725 int winIdChangeEventCount() const { return m_winIdList.count(); }
3728 void tst_QWidget::winIdChangeEvent()
3731 // Transforming an alien widget into a native widget
3732 WinIdChangeWidget widget;
3733 const WId winIdBefore = widget.internalWinId();
3734 const WId winIdAfter = widget.winId();
3735 QVERIFY(winIdBefore != winIdAfter);
3736 QCOMPARE(widget.winIdChangeEventCount(), 1);
3740 // Changing parent of a native widget
3741 // Should cause winId of child to change, on all platforms
3742 QWidget parent1, parent2;
3743 WinIdChangeWidget child(&parent1);
3744 const WId winIdBefore = child.winId();
3745 QCOMPARE(child.winIdChangeEventCount(), 1);
3746 child.setParent(&parent2);
3747 const WId winIdAfter = child.internalWinId();
3748 if (m_platform == QStringLiteral("windows"))
3749 QEXPECT_FAIL("", "QTBUG-26424", Continue);
3750 QVERIFY(winIdBefore != winIdAfter);
3751 QCOMPARE(child.winIdChangeEventCount(), 3);
3752 // winId is set to zero during reparenting
3753 QVERIFY(0 == child.m_winIdList[1]);
3757 // Changing grandparent of a native widget
3758 QWidget grandparent1, grandparent2;
3759 QWidget parent(&grandparent1);
3760 WinIdChangeWidget child(&parent);
3761 const WId winIdBefore = child.winId();
3762 QCOMPARE(child.winIdChangeEventCount(), 1);
3763 parent.setParent(&grandparent2);
3764 const WId winIdAfter = child.internalWinId();
3765 QCOMPARE(winIdBefore, winIdAfter);
3766 QCOMPARE(child.winIdChangeEventCount(), 1);
3770 // Changing parent of an alien widget
3771 QWidget parent1, parent2;
3772 WinIdChangeWidget child(&parent1);
3773 const WId winIdBefore = child.internalWinId();
3774 child.setParent(&parent2);
3775 const WId winIdAfter = child.internalWinId();
3776 QCOMPARE(winIdBefore, winIdAfter);
3777 QCOMPARE(child.winIdChangeEventCount(), 0);
3781 // Making native child widget into a top-level window
3783 WinIdChangeWidget child(&parent);
3785 const WId winIdBefore = child.internalWinId();
3786 QCOMPARE(child.winIdChangeEventCount(), 1);
3787 const Qt::WindowFlags flags = child.windowFlags();
3788 child.setWindowFlags(flags | Qt::Window);
3789 const WId winIdAfter = child.internalWinId();
3790 if (m_platform == QStringLiteral("windows"))
3791 QEXPECT_FAIL("", "QTBUG-26424", Continue);
3792 QVERIFY(winIdBefore != winIdAfter);
3793 QCOMPARE(child.winIdChangeEventCount(), 3);
3794 // winId is set to zero during reparenting
3795 QVERIFY(0 == child.m_winIdList[1]);
3799 void tst_QWidget::persistentWinId()
3801 QScopedPointer<QWidget> parent(new QWidget);
3802 QWidget *w1 = new QWidget;
3803 QWidget *w2 = new QWidget;
3804 QWidget *w3 = new QWidget;
3805 w1->setParent(parent.data());
3809 WId winId1 = w1->winId();
3810 WId winId2 = w2->winId();
3811 WId winId3 = w3->winId();
3813 // reparenting should change the winId of the widget being reparented, but not of its children
3815 if (m_platform == QStringLiteral("windows"))
3816 QEXPECT_FAIL("", "QTBUG-26424", Continue);
3817 QVERIFY(w1->winId() != winId1);
3818 winId1 = w1->winId();
3819 QCOMPARE(w2->winId(), winId2);
3820 QCOMPARE(w3->winId(), winId3);
3822 w1->setParent(parent.data());
3823 if (m_platform == QStringLiteral("windows"))
3824 QEXPECT_FAIL("", "QTBUG-26424", Continue);
3825 QVERIFY(w1->winId() != winId1);
3826 winId1 = w1->winId();
3827 QCOMPARE(w2->winId(), winId2);
3828 QCOMPARE(w3->winId(), winId3);
3831 if (m_platform == QStringLiteral("windows"))
3832 QEXPECT_FAIL("", "QTBUG-26424", Continue);
3833 QVERIFY(w2->winId() != winId2);
3834 winId2 = w2->winId();
3835 QCOMPARE(w3->winId(), winId3);
3837 w2->setParent(parent.data());
3838 if (m_platform == QStringLiteral("windows"))
3839 QEXPECT_FAIL("", "QTBUG-26424", Continue);
3840 QVERIFY(w2->winId() != winId2);
3841 winId2 = w2->winId();
3842 QCOMPARE(w3->winId(), winId3);
3845 if (m_platform == QStringLiteral("windows"))
3846 QEXPECT_FAIL("", "QTBUG-26424", Continue);
3847 QVERIFY(w2->winId() != winId2);
3848 winId2 = w2->winId();
3849 QCOMPARE(w3->winId(), winId3);
3852 if (m_platform == QStringLiteral("windows"))
3853 QEXPECT_FAIL("", "QTBUG-26424", Continue);
3854 QVERIFY(w3->winId() != winId3);
3855 winId3 = w3->winId();
3858 if (m_platform == QStringLiteral("windows"))
3859 QEXPECT_FAIL("", "QTBUG-26424", Continue);
3860 QVERIFY(w3->winId() != winId3);
3861 winId3 = w3->winId();
3864 if (m_platform == QStringLiteral("windows"))
3865 QEXPECT_FAIL("", "QTBUG-26424", Continue);
3866 QVERIFY(w3->winId() != winId3);
3867 winId3 = w3->winId();
3870 void tst_QWidget::showNativeChild()
3873 topLevel.setGeometry(0, 0, 160, 160);
3874 QWidget child(&topLevel);
3877 QVERIFY(QTest::qWaitForWindowExposed(&topLevel));
3880 class ShowHideEventWidget : public QWidget
3883 int numberOfShowEvents, numberOfHideEvents;
3885 ShowHideEventWidget(QWidget *parent = 0)
3886 : QWidget(parent), numberOfShowEvents(0), numberOfHideEvents(0)
3890 { QWidget::create(); }
3892 void showEvent(QShowEvent *)
3893 { ++numberOfShowEvents; }
3895 void hideEvent(QHideEvent *)
3896 { ++numberOfHideEvents; }
3899 void tst_QWidget::showHideEvent_data()
3901 QTest::addColumn<bool>("show");
3902 QTest::addColumn<bool>("hide");
3903 QTest::addColumn<bool>("create");
3904 QTest::addColumn<int>("expectedShowEvents");
3905 QTest::addColumn<int>("expectedHideEvents");
3907 QTest::newRow("window: only show")
3913 QTest::newRow("window: show/hide")
3919 QTest::newRow("window: show/hide/create")
3925 QTest::newRow("window: hide/create")
3931 QTest::newRow("window: only hide")
3937 QTest::newRow("window: nothing")
3945 void tst_QWidget::showHideEvent()
3949 QFETCH(bool, create);
3950 QFETCH(int, expectedShowEvents);
3951 QFETCH(int, expectedHideEvents);
3953 ShowHideEventWidget widget;
3958 if (create && !widget.testAttribute(Qt::WA_WState_Created))
3961 if (m_platform == QStringLiteral("windows") || m_platform == QStringLiteral("xcb")) {
3962 QEXPECT_FAIL("window: only show", "QTBUG-26424", Continue);
3963 QEXPECT_FAIL("window: show/hide", "QTBUG-26424", Continue);
3964 QEXPECT_FAIL("window: show/hide/create", "QTBUG-26424", Continue);
3966 QCOMPARE(widget.numberOfShowEvents, expectedShowEvents);
3967 if (m_platform == QStringLiteral("windows") || m_platform == QStringLiteral("xcb")) {
3968 QEXPECT_FAIL("window: show/hide", "QTBUG-26424", Continue);
3969 QEXPECT_FAIL("window: show/hide/create", "QTBUG-26424", Continue);
3971 QCOMPARE(widget.numberOfHideEvents, expectedHideEvents);
3974 void tst_QWidget::update()
3976 QTest::qWait(10); // Wait for the initStuff to do it's stuff.
3980 w.setGeometry(50, 50, 100, 100);
3982 QVERIFY(QTest::qWaitForWindowExposed(&w));
3984 QApplication::processEvents();
3985 QApplication::processEvents();
3988 QEXPECT_FAIL(0, "Cocoa compositor says to paint this twice.", Continue);
3990 if (m_platform == QStringLiteral("windows"))
3991 QEXPECT_FAIL("", "QTBUG-26424", 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)
4720 QPalette opaquePalette = palette();
4721 opaquePalette.setColor(backgroundRole(), color);
4722 setPalette(opaquePalette);
4723 setAutoFillBackground(true);
4726 void paintEvent(QPaintEvent *e) {
4738 #define VERIFY_COLOR(region, color) { \
4739 const QRegion r = QRegion(region); \
4740 QScreen *screen = qApp->primaryScreen(); \
4741 const WId desktopWinId = QDesktopWidget().winId(); \
4742 for (int i = 0; i < r.rects().size(); ++i) { \
4743 const QRect rect = r.rects().at(i); \
4744 for (int t = 0; t < 5; t++) { \
4745 const QPixmap pixmap = screen->grabWindow(desktopWinId, \
4746 rect.left(), rect.top(), \
4747 rect.width(), rect.height()); \
4748 QCOMPARE(pixmap.size(), rect.size()); \
4749 QPixmap expectedPixmap(pixmap); /* ensure equal formats */ \
4750 expectedPixmap.detach(); \
4751 expectedPixmap.fill(color); \
4752 QImage image = pixmap.toImage(); \
4753 uint alphaCorrection = image.format() == QImage::Format_RGB32 ? 0xff000000 : 0; \
4754 uint firstPixel = image.pixel(0,0) | alphaCorrection; \
4755 if ( firstPixel != QColor(color).rgb() && t < 4 ) \
4756 { QTest::qWait(200); continue; } \
4757 QCOMPARE(firstPixel, QColor(color).rgb()); \
4758 QCOMPARE(pixmap, expectedPixmap); \
4764 void tst_QWidget::popupEnterLeave()
4766 if (m_platform == QStringLiteral("windows"))
4767 QSKIP("QTBUG-26424");
4770 parent.setWindowFlags(Qt::FramelessWindowHint);
4771 parent.setGeometry(10, 10, 200, 100);
4773 ColorWidget alien(&parent, Qt::black);
4774 alien.setGeometry(0, 0, 10, 10);
4779 QVERIFY(QTest::qWaitForWindowExposed(&parent));
4781 QWindowSystemInterface::handleMouseEvent(parent.windowHandle(), QPointF(5, 5), QPointF(), Qt::LeftButton, Qt::NoModifier);
4783 QWindowSystemInterface::handleMouseEvent(parent.windowHandle(), QPointF(5, 5), QPointF(), Qt::NoButton, Qt::NoModifier);
4786 QStringList wordList;
4787 wordList << "alpha" << "omega" << "omicron" << "zeta";
4789 QLineEdit popup(&parent);
4791 QCompleter completer(wordList);
4792 completer.setCaseSensitivity(Qt::CaseInsensitive);
4793 popup.setCompleter(&completer);
4794 popup.setWindowFlags(Qt::Popup);
4795 popup.setGeometry(20, 20, 80, 20);
4799 QVERIFY(QTest::qWaitForWindowExposed(&popup));
4803 QWindowSystemInterface::handleMouseEvent(popup.windowHandle(), QPointF(-5, -5), QPointF(), Qt::LeftButton, Qt::NoModifier);
4805 QWindowSystemInterface::handleMouseEvent(popup.windowHandle(), QPointF(-5, -5), QPointF(), Qt::NoButton, Qt::NoModifier);
4809 QVERIFY(!popup.underMouse());
4812 void tst_QWidget::moveChild_data()
4814 QTest::addColumn<QPoint>("offset");
4816 QTest::newRow("right") << QPoint(20, 0);
4817 QTest::newRow("down") << QPoint(0, 20);
4818 QTest::newRow("left") << QPoint(-20, 0);
4819 QTest::newRow("up") << QPoint(0, -20);
4822 void tst_QWidget::moveChild()
4824 QFETCH(QPoint, offset);
4827 // prevent custom styles
4828 parent.setStyle(new QWindowsStyle);
4829 ColorWidget child(&parent, Qt::blue);
4832 parent.setGeometry(QRect(QPoint(QApplication::desktop()->availableGeometry(&parent).topLeft()),
4835 parent.setGeometry(60, 60, 150, 150);
4837 child.setGeometry(25, 25, 50, 50);
4839 QVERIFY(QTest::qWaitForWindowExposed(&parent));
4841 const QPoint tlwOffset = parent.geometry().topLeft();
4843 QTRY_COMPARE(parent.r, QRegion(parent.rect()) - child.geometry());
4844 QTRY_COMPARE(child.r, QRegion(child.rect()));
4845 VERIFY_COLOR(child.geometry().translated(tlwOffset),
4847 VERIFY_COLOR(QRegion(parent.geometry()) - child.geometry().translated(tlwOffset),
4854 const QRect oldGeometry = child.geometry();
4856 QPoint pos = child.pos() + offset;
4859 QTRY_COMPARE(pos, child.pos());
4861 QCOMPARE(parent.r, QRegion(oldGeometry) - child.geometry());
4862 #if !defined(Q_OS_MAC)
4863 // should be scrolled in backingstore
4864 QCOMPARE(child.r, QRegion());
4866 VERIFY_COLOR(child.geometry().translated(tlwOffset),
4868 VERIFY_COLOR(QRegion(parent.geometry()) - child.geometry().translated(tlwOffset),
4872 void tst_QWidget::showAndMoveChild()
4874 if (m_platform == QStringLiteral("windows"))
4875 QSKIP("QTBUG-26424");
4877 QWidget parent(0, Qt::FramelessWindowHint);
4878 // prevent custom styles
4879 parent.setStyle(new QWindowsStyle);
4881 QDesktopWidget desktop;
4882 QRect desktopDimensions = desktop.availableGeometry(&parent);
4883 desktopDimensions = desktopDimensions.adjusted(64, 64, -64, -64);
4885 parent.setGeometry(desktopDimensions);
4886 parent.setPalette(Qt::red);
4888 qApp->setActiveWindow(&parent);
4889 QVERIFY(QTest::qWaitForWindowActive(&parent));
4892 const QPoint tlwOffset = parent.geometry().topLeft();
4893 QWidget child(&parent);
4894 child.resize(desktopDimensions.width()/2, desktopDimensions.height()/2);
4895 child.setPalette(Qt::blue);
4896 child.setAutoFillBackground(true);
4898 // Ensure that the child is repainted correctly when moved right after show.
4899 // NB! Do NOT processEvents() (or qWait()) in between show() and move().
4901 child.move(desktopDimensions.width()/2, desktopDimensions.height()/2);
4902 qApp->processEvents();
4904 VERIFY_COLOR(child.geometry().translated(tlwOffset), Qt::blue);
4905 VERIFY_COLOR(QRegion(parent.geometry()) - child.geometry().translated(tlwOffset), Qt::red);
4908 // Cocoa only has rect granularity.
4910 void tst_QWidget::subtractOpaqueSiblings()
4913 w.setGeometry(50, 50, 300, 300);
4915 ColorWidget *large = new ColorWidget(&w, Qt::red);
4916 large->setGeometry(50, 50, 200, 200);
4918 ColorWidget *medium = new ColorWidget(large, Qt::gray);
4919 medium->setGeometry(50, 50, 100, 100);
4921 ColorWidget *tall = new ColorWidget(&w, Qt::blue);
4922 tall->setGeometry(100, 30, 50, 100);
4925 QVERIFY(QTest::qWaitForWindowExposed(&w));
4935 // QWidgetPrivate::subtractOpaqueSiblings() should prevent parts of medium
4936 // to be repainted and tall from be repainted at all.
4938 QTRY_COMPARE(large->r, QRegion());
4939 QTRY_COMPARE(tall->r, QRegion());
4940 QTRY_COMPARE(medium->r.translated(medium->mapTo(&w, QPoint())),
4941 QRegion(medium->geometry().translated(large->pos()))
4942 - tall->geometry());
4946 void tst_QWidget::deleteStyle()
4949 widget.setStyle(new QWindowsStyle);
4951 delete widget.style();
4952 qApp->processEvents();
4955 class TopLevelFocusCheck: public QWidget
4960 TopLevelFocusCheck(QWidget* parent = 0) : QWidget(parent)
4962 edit = new QLineEdit(this);
4964 edit->installEventFilter(this);
4968 void mouseDoubleClickEvent ( QMouseEvent * /*event*/ )
4971 edit->setFocus(Qt::OtherFocusReason);
4972 qApp->processEvents();
4974 bool eventFilter(QObject *obj, QEvent *event)
4976 if (obj == edit && event->type()== QEvent::FocusOut) {
4984 void tst_QWidget::multipleToplevelFocusCheck()
4986 TopLevelFocusCheck w1;
4987 TopLevelFocusCheck w2;
4989 w1.resize(200, 200);
4991 QVERIFY(QTest::qWaitForWindowExposed(&w1));
4994 QVERIFY(QTest::qWaitForWindowExposed(&w2));
4996 QApplication::setActiveWindow(&w1);
4997 w1.activateWindow();
4998 QVERIFY(QTest::qWaitForWindowActive(&w1));
4999 QCOMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&w1));
5001 QTest::mouseDClick(&w1, Qt::LeftButton);
5002 QTRY_COMPARE(QApplication::focusWidget(), static_cast<QWidget *>(w1.edit));
5004 w2.activateWindow();
5005 QApplication::setActiveWindow(&w2);
5006 QVERIFY(QTest::qWaitForWindowActive(&w2));
5007 QCOMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&w2));
5008 QTest::mouseClick(&w2, Qt::LeftButton);
5009 QTRY_COMPARE(QApplication::focusWidget(), (QWidget *)0);
5011 QTest::mouseDClick(&w2, Qt::LeftButton);
5012 QTRY_COMPARE(QApplication::focusWidget(), static_cast<QWidget *>(w2.edit));
5014 w1.activateWindow();
5015 QApplication::setActiveWindow(&w1);
5016 QVERIFY(QTest::qWaitForWindowActive(&w1));
5017 QCOMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&w1));
5018 QTest::mouseDClick(&w1, Qt::LeftButton);
5019 QTRY_COMPARE(QApplication::focusWidget(), static_cast<QWidget *>(w1.edit));
5021 w2.activateWindow();
5022 QApplication::setActiveWindow(&w2);
5023 QVERIFY(QTest::qWaitForWindowActive(&w2));
5024 QCOMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&w2));
5025 QTest::mouseClick(&w2, Qt::LeftButton);
5026 QTRY_COMPARE(QApplication::focusWidget(), (QWidget *)0);
5029 class FocusWidget: public QWidget
5032 virtual bool event(QEvent *ev)
5034 if (ev->type() == QEvent::FocusAboutToChange)
5035 widgetDuringFocusAboutToChange = qApp->focusWidget();
5036 return QWidget::event(ev);
5038 virtual void focusOutEvent(QFocusEvent *)
5040 widgetDuringFocusOut = qApp->focusWidget();
5044 FocusWidget(QWidget *parent) : QWidget(parent), widgetDuringFocusAboutToChange(0), widgetDuringFocusOut(0) {}
5046 QWidget *widgetDuringFocusAboutToChange;
5047 QWidget *widgetDuringFocusOut;
5050 void tst_QWidget::setFocus()
5053 // move focus to another window
5054 testWidget->activateWindow();
5055 QApplication::setActiveWindow(testWidget);
5056 if (testWidget->focusWidget())
5057 testWidget->focusWidget()->clearFocus();
5059 testWidget->clearFocus();
5061 // window and children never shown, nobody gets focus
5063 window.resize(200, 200);
5065 QWidget child1(&window);
5066 child1.setFocusPolicy(Qt::StrongFocus);
5068 QWidget child2(&window);
5069 child2.setFocusPolicy(Qt::StrongFocus);
5072 QVERIFY(!child1.hasFocus());
5073 QCOMPARE(window.focusWidget(), &child1);
5074 QCOMPARE(QApplication::focusWidget(), static_cast<QWidget *>(0));
5077 QVERIFY(!child2.hasFocus());
5078 QCOMPARE(window.focusWidget(), &child2);
5079 QCOMPARE(QApplication::focusWidget(), static_cast<QWidget *>(0));
5083 // window and children show, but window not active, nobody gets focus
5085 window.resize(200, 200);
5087 QWidget child1(&window);
5088 child1.setFocusPolicy(Qt::StrongFocus);
5090 QWidget child2(&window);
5091 child2.setFocusPolicy(Qt::StrongFocus);
5095 // note: window may be active, but we don't want it to be
5096 testWidget->activateWindow();
5097 QApplication::setActiveWindow(testWidget);
5098 if (testWidget->focusWidget())
5099 testWidget->focusWidget()->clearFocus();
5101 testWidget->clearFocus();
5104 QVERIFY(!child1.hasFocus());
5105 QCOMPARE(window.focusWidget(), &child1);
5106 QCOMPARE(QApplication::focusWidget(), static_cast<QWidget *>(0));
5109 QVERIFY(!child2.hasFocus());
5110 QCOMPARE(window.focusWidget(), &child2);
5111 QCOMPARE(QApplication::focusWidget(), static_cast<QWidget *>(0));
5115 // window and children show, but window *is* active, children get focus
5117 window.resize(200, 200);
5119 FocusWidget child1(&window);
5120 child1.setFocusPolicy(Qt::StrongFocus);
5122 QWidget child2(&window);
5123 child2.setFocusPolicy(Qt::StrongFocus);
5126 window.activateWindow();
5127 QVERIFY(QTest::qWaitForWindowExposed(&window));
5128 QTRY_VERIFY(qGuiApp->focusWindow());
5131 QTRY_VERIFY(child1.hasFocus());
5132 QCOMPARE(window.focusWidget(), &child1);
5133 QCOMPARE(QApplication::focusWidget(), &child1);
5136 QVERIFY(child2.hasFocus());
5137 QCOMPARE(window.focusWidget(), &child2);
5138 QCOMPARE(QApplication::focusWidget(), &child2);
5140 // focus changed in between the events
5141 QCOMPARE(child1.widgetDuringFocusAboutToChange, &child1);
5142 QCOMPARE(child1.widgetDuringFocusOut, &child2);
5146 // window shown and active, children created, don't get focus, but get focus when shown
5148 window.resize(200, 200);
5151 window.activateWindow();
5152 QVERIFY(QTest::qWaitForWindowExposed(&window));
5153 QTRY_VERIFY(qGuiApp->focusWindow());
5155 QWidget child1(&window);
5156 child1.setFocusPolicy(Qt::StrongFocus);
5158 QWidget child2(&window);
5159 child2.setFocusPolicy(Qt::StrongFocus);
5162 QVERIFY(!child1.hasFocus());
5163 QCOMPARE(window.focusWidget(), static_cast<QWidget *>(0));
5164 QCOMPARE(QApplication::focusWidget(), static_cast<QWidget *>(0));
5167 QApplication::processEvents();
5168 QTRY_VERIFY(child1.hasFocus());
5169 QCOMPARE(window.focusWidget(), &child1);
5170 QCOMPARE(QApplication::focusWidget(), &child1);
5173 QVERIFY(!child2.hasFocus());
5174 QCOMPARE(window.focusWidget(), &child1);
5175 QCOMPARE(QApplication::focusWidget(), &child1);
5178 QVERIFY(child2.hasFocus());
5179 QCOMPARE(window.focusWidget(), &child2);
5180 QCOMPARE(QApplication::focusWidget(), &child2);
5184 // window shown and active, children created, don't get focus,
5185 // even after setFocus(), hide(), then show()
5187 window.resize(200, 200);
5190 window.activateWindow();
5191 QVERIFY(QTest::qWaitForWindowExposed(&window));
5192 QTRY_VERIFY(qGuiApp->focusWindow());
5194 QWidget child1(&window);
5195 child1.setFocusPolicy(Qt::StrongFocus);
5197 QWidget child2(&window);
5198 child2.setFocusPolicy(Qt::StrongFocus);
5201 QVERIFY(!child1.hasFocus());
5202 QCOMPARE(window.focusWidget(), static_cast<QWidget *>(0));
5203 QCOMPARE(QApplication::focusWidget(), static_cast<QWidget *>(0));
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(!child2.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));
5232 class EventSpy : public QObject
5235 EventSpy(QWidget *widget, QEvent::Type event)
5236 : m_widget(widget), eventToSpy(event), m_count(0)
5239 m_widget->installEventFilter(this);
5242 QWidget *widget() const { return m_widget; }
5243 int count() const { return m_count; }
5244 void clear() { m_count = 0; }
5247 bool eventFilter(QObject *object, QEvent *event)
5249 if (event->type() == eventToSpy)
5251 return QObject::eventFilter(object, event);
5256 QEvent::Type eventToSpy;
5260 void tst_QWidget::setCursor()
5262 #ifndef QT_NO_CURSOR
5265 window.resize(200, 200);
5266 QWidget child(&window);
5268 QVERIFY(!window.testAttribute(Qt::WA_SetCursor));
5269 QVERIFY(!child.testAttribute(Qt::WA_SetCursor));
5271 window.setCursor(window.cursor());
5272 QVERIFY(window.testAttribute(Qt::WA_SetCursor));
5273 QVERIFY(!child.testAttribute(Qt::WA_SetCursor));
5274 QCOMPARE(child.cursor().shape(), window.cursor().shape());
5277 // do it again, but with window show()n
5280 window.resize(200, 200);
5281 QWidget child(&window);
5284 QVERIFY(!window.testAttribute(Qt::WA_SetCursor));
5285 QVERIFY(!child.testAttribute(Qt::WA_SetCursor));
5287 window.setCursor(window.cursor());
5288 QVERIFY(window.testAttribute(Qt::WA_SetCursor));
5289 QVERIFY(!child.testAttribute(Qt::WA_SetCursor));
5290 QCOMPARE(child.cursor().shape(), window.cursor().shape());
5296 window.resize(200, 200);
5297 QWidget child(&window);
5299 window.setCursor(Qt::WaitCursor);
5300 QVERIFY(window.testAttribute(Qt::WA_SetCursor));
5301 QVERIFY(!child.testAttribute(Qt::WA_SetCursor));
5302 QCOMPARE(child.cursor().shape(), window.cursor().shape());
5305 // same thing again, just with window show()n
5308 window.resize(200, 200);
5309 QWidget child(&window);
5312 window.setCursor(Qt::WaitCursor);
5313 QVERIFY(window.testAttribute(Qt::WA_SetCursor));
5314 QVERIFY(!child.testAttribute(Qt::WA_SetCursor));
5315 QCOMPARE(child.cursor().shape(), window.cursor().shape());
5318 // reparenting child should not cause the WA_SetCursor to become set
5321 window.resize(200, 200);
5323 window2.resize(200, 200);
5324 QWidget child(&window);
5326 window.setCursor(Qt::WaitCursor);
5329 QVERIFY(!child.testAttribute(Qt::WA_SetCursor));
5330 QCOMPARE(child.cursor().shape(), QCursor().shape());
5332 child.setParent(&window2);
5333 QVERIFY(!child.testAttribute(Qt::WA_SetCursor));
5334 QCOMPARE(child.cursor().shape(), window2.cursor().shape());
5336 window2.setCursor(Qt::WaitCursor);
5337 QVERIFY(!child.testAttribute(Qt::WA_SetCursor));
5338 QCOMPARE(child.cursor().shape(), window2.cursor().shape());
5341 // again, with windows show()n
5344 window.resize(200, 200);
5346 window2.resize(200, 200);
5347 QWidget child(&window);
5349 window.setCursor(Qt::WaitCursor);
5353 QVERIFY(!child.testAttribute(Qt::WA_SetCursor));
5354 QCOMPARE(child.cursor().shape(), QCursor().shape());
5356 child.setParent(&window2);
5357 QVERIFY(!child.testAttribute(Qt::WA_SetCursor));
5358 QCOMPARE(child.cursor().shape(), window2.cursor().shape());
5361 window2.setCursor(Qt::WaitCursor);
5362 QVERIFY(!child.testAttribute(Qt::WA_SetCursor));
5363 QCOMPARE(child.cursor().shape(), window2.cursor().shape());
5366 // test if CursorChange is sent
5369 EventSpy spy(&widget, QEvent::CursorChange);
5370 QCOMPARE(spy.count(), 0);
5371 widget.setCursor(QCursor(Qt::WaitCursor));
5372 QCOMPARE(spy.count(), 1);
5373 widget.unsetCursor();
5374 QCOMPARE(spy.count(), 2);
5379 void tst_QWidget::setToolTip()
5382 EventSpy spy(&widget, QEvent::ToolTipChange);
5383 QCOMPARE(spy.count(), 0);
5385 QCOMPARE(widget.toolTip(), QString());
5386 widget.setToolTip(QString("Hello"));
5387 QCOMPARE(widget.toolTip(), QString("Hello"));
5388 QCOMPARE(spy.count(), 1);
5389 widget.setToolTip(QString());
5390 QCOMPARE(widget.toolTip(), QString());
5391 QCOMPARE(spy.count(), 2);
5393 // Mouse over doesn't work on Windows mobile, so skip the rest of the test for that platform.
5394 #ifndef Q_OS_WINCE_WM
5395 for (int pass = 0; pass < 2; ++pass) {
5396 QScopedPointer<QWidget> popup(new QWidget(0, Qt::Popup));
5397 popup->resize(150, 50);
5398 QFrame *frame = new QFrame(popup.data());
5399 frame->setGeometry(0, 0, 50, 50);
5400 frame->setFrameStyle(QFrame::Box | QFrame::Plain);
5401 EventSpy spy1(frame, QEvent::ToolTip);
5402 EventSpy spy2(popup.data(), QEvent::ToolTip);
5403 frame->setMouseTracking(pass == 0 ? false : true);
5404 frame->setToolTip(QLatin1String("TOOLTIP FRAME"));
5405 popup->setToolTip(QLatin1String("TOOLTIP POPUP"));
5407 QVERIFY(QTest::qWaitForWindowExposed(popup.data()));
5409 QTest::mouseMove(frame);
5410 QTest::qWait(900); // delay is 700
5412 if (m_platform == QStringLiteral("xcb"))
5413 QSKIP("QTBUG-26424");
5414 QCOMPARE(spy1.count(), 1);
5415 QCOMPARE(spy2.count(), 0);
5417 QTest::qWait(2200); // delay is 2000
5418 QTest::mouseMove(popup.data());
5423 void tst_QWidget::testWindowIconChangeEventPropagation()
5425 typedef QSharedPointer<EventSpy> EventSpyPtr;
5426 // Create widget hierarchy.
5427 QWidget topLevelWidget;
5428 QWidget topLevelChild(&topLevelWidget);
5430 QDialog dialog(&topLevelWidget);
5431 QWidget dialogChild(&dialog);
5433 QWidgetList widgets;
5434 widgets << &topLevelWidget << &topLevelChild
5435 << &dialog << &dialogChild;
5436 QCOMPARE(widgets.count(), 4);
5438 // Create spy lists.
5439 QList <EventSpyPtr> applicationEventSpies;
5440 QList <EventSpyPtr> widgetEventSpies;
5441 foreach (QWidget *widget, widgets) {
5442 applicationEventSpies.append(EventSpyPtr(new EventSpy(widget, QEvent::ApplicationWindowIconChange)));
5443 widgetEventSpies.append(EventSpyPtr(new EventSpy(widget, QEvent::WindowIconChange)));
5446 // QApplication::setWindowIcon
5447 const QIcon windowIcon = qApp->style()->standardIcon(QStyle::SP_TitleBarMenuButton);
5448 qApp->setWindowIcon(windowIcon);
5450 for (int i = 0; i < widgets.count(); ++i) {
5451 // Check QEvent::ApplicationWindowIconChange
5452 EventSpyPtr spy = applicationEventSpies.at(i);
5453 QWidget *widget = spy->widget();
5454 if (widget->isWindow()) {
5455 QCOMPARE(spy->count(), 1);
5456 QCOMPARE(widget->windowIcon(), windowIcon);
5458 QCOMPARE(spy->count(), 0);
5462 // Check QEvent::WindowIconChange
5463 spy = widgetEventSpies.at(i);
5464 QCOMPARE(spy->count(), 1);
5468 // Set icon on a top-level widget.
5469 topLevelWidget.setWindowIcon(QIcon());
5471 for (int i = 0; i < widgets.count(); ++i) {
5472 // Check QEvent::ApplicationWindowIconChange
5473 EventSpyPtr spy = applicationEventSpies.at(i);
5474 QCOMPARE(spy->count(), 0);
5477 // Check QEvent::WindowIconChange
5478 spy = widgetEventSpies.at(i);
5479 QWidget *widget = spy->widget();
5480 if (widget == &topLevelWidget) {
5481 QCOMPARE(widget->windowIcon(), QIcon());
5482 QCOMPARE(spy->count(), 1);
5483 } else if (topLevelWidget.isAncestorOf(widget)) {
5484 QCOMPARE(spy->count(), 1);
5486 QCOMPARE(spy->count(), 0);
5492 qApp->setWindowIcon(QIcon());
5495 void tst_QWidget::minAndMaxSizeWithX11BypassWindowManagerHint()
5497 if (m_platform != QStringLiteral("xcb"))
5498 QSKIP("This test is for X11 only.");
5499 // Same size as in QWidget::create_sys().
5500 const QSize desktopSize = QApplication::desktop()->size();
5501 const QSize originalSize(desktopSize.width() / 2, desktopSize.height() * 4 / 10);
5504 QWidget widget(0, Qt::X11BypassWindowManagerHint);
5506 const QSize newMaximumSize = widget.size().boundedTo(originalSize) - QSize(10, 10);
5507 widget.setMaximumSize(newMaximumSize);
5508 QCOMPARE(widget.size(), newMaximumSize);
5511 QVERIFY(QTest::qWaitForWindowExposed(&widget));
5512 QCOMPARE(widget.size(), newMaximumSize);
5516 QWidget widget(0, Qt::X11BypassWindowManagerHint);
5518 const QSize newMinimumSize = widget.size().expandedTo(originalSize) + QSize(10, 10);
5519 widget.setMinimumSize(newMinimumSize);
5520 QCOMPARE(widget.size(), newMinimumSize);
5523 QVERIFY(QTest::qWaitForWindowExposed(&widget));
5524 QCOMPARE(widget.size(), newMinimumSize);
5528 class ShowHideShowWidget : public QWidget, public QAbstractNativeEventFilter
5534 bool gotExpectedMapNotify;
5535 bool gotExpectedGlobalEvent;
5537 ShowHideShowWidget()
5538 : state(0), gotExpectedMapNotify(false), gotExpectedGlobalEvent(false)
5543 void timerEvent(QTimerEvent *)
5555 bool isMapNotify(const QByteArray &eventType, void *message)
5557 enum { XCB_MAP_NOTIFY = 19 };
5558 if (state == 1 && eventType == QByteArrayLiteral("xcb_generic_event_t")) {
5559 // XCB events have a uint8 response_type member at the beginning.
5560 const unsigned char responseType = *(const unsigned char *)(message);
5561 return ((responseType & ~0x80) == XCB_MAP_NOTIFY);
5566 bool nativeEvent(const QByteArray &eventType, void *message, long *)
5568 if (isMapNotify(eventType, message))
5569 gotExpectedMapNotify = true;
5573 // QAbstractNativeEventFilter interface
5574 virtual bool nativeEventFilter(const QByteArray &eventType, void *message, long *) Q_DECL_OVERRIDE
5576 if (isMapNotify(eventType, message))
5577 gotExpectedGlobalEvent = true;
5585 void tst_QWidget::showHideShowX11()
5587 if (m_platform != QStringLiteral("xcb"))
5588 QSKIP("This test is for X11 only.");
5590 ShowHideShowWidget w;
5591 qApp->installNativeEventFilter(&w);
5596 QEventLoop eventLoop;
5597 connect(&w, SIGNAL(done()), &eventLoop, SLOT(quit()));
5600 QVERIFY(w.gotExpectedGlobalEvent);
5601 QVERIFY(w.gotExpectedMapNotify);
5604 void tst_QWidget::clean_qt_x11_enforce_cursor()
5606 if (m_platform != QStringLiteral("xcb"))
5607 QSKIP("This test is for X11 only.");
5611 QWidget *w = new QWidget(&window);
5612 QWidget *child = new QWidget(w);
5613 child->setAttribute(Qt::WA_SetCursor, true);
5616 QApplication::setActiveWindow(&window);
5617 QVERIFY(QTest::qWaitForWindowActive(&window));
5619 QCursor::setPos(window.geometry().center());
5623 QApplication::processEvents();
5629 QGraphicsScene scene;
5630 QLineEdit *edit = new QLineEdit;
5631 scene.addWidget(edit);
5633 // If the test didn't crash, then it passed.
5636 class EventRecorder : public QObject
5641 typedef QPair<QWidget *, QEvent::Type> WidgetEventTypePair;
5642 typedef QList<WidgetEventTypePair> EventList;
5644 EventRecorder(QObject *parent = 0)
5648 EventList eventList()
5658 bool eventFilter(QObject *object, QEvent *event)
5660 QWidget *widget = qobject_cast<QWidget *>(object);
5661 if (widget && !event->spontaneous())
5662 events.append(qMakePair(widget, event->type()));
5666 static QByteArray msgEventListMismatch(const EventList &expected, const EventList &actual);
5667 static QByteArray msgExpectFailQtBug26424(const EventList &expected, const EventList &actual)
5668 { return QByteArrayLiteral("QTBUG-26424: ") + msgEventListMismatch(expected, actual); }
5671 static inline void formatEventList(const EventList &l, QDebug &d);
5676 void EventRecorder::formatEventList(const EventList &l, QDebug &d)
5678 QWidget *lastWidget = 0;
5679 foreach (const WidgetEventTypePair &p, l) {
5680 if (p.first != lastWidget) {
5681 d << p.first << ':';
5682 lastWidget = p.first;
5684 d << p.second << ' ';
5688 QByteArray EventRecorder::msgEventListMismatch(const EventList &expected, const EventList &actual)
5691 QDebug d = QDebug(&result).nospace();
5692 d << "Event list mismatch, expected " << expected.size() << " (";
5693 EventRecorder::formatEventList(expected, d);
5694 d << "), actual " << actual.size() << " (";
5695 EventRecorder::formatEventList(actual, d);
5697 return result.toLocal8Bit();
5700 void tst_QWidget::childEvents()
5702 EventRecorder::EventList expected;
5704 // Move away the cursor; otherwise it might result in an enter event if it's
5705 // inside the widget when the widget is shown.
5706 QCursor::setPos(qApp->desktop()->availableGeometry().bottomRight());
5710 // no children created, not shown
5713 widget.installEventFilter(&spy);
5715 QCoreApplication::postEvent(&widget, new QEvent(QEvent::Type(QEvent::User + 1)));
5717 QCoreApplication::sendPostedEvents();
5720 EventRecorder::EventList()
5721 << qMakePair(&widget, QEvent::PolishRequest)
5722 << qMakePair(&widget, QEvent::Polish)
5723 << qMakePair(&widget, QEvent::Type(QEvent::User + 1));
5724 QVERIFY2(spy.eventList() == expected,
5725 EventRecorder::msgEventListMismatch(expected, spy.eventList()).constData());
5729 // no children, shown
5732 widget.installEventFilter(&spy);
5734 QCoreApplication::postEvent(&widget, new QEvent(QEvent::Type(QEvent::User + 1)));
5738 EventRecorder::EventList()
5739 << qMakePair(&widget, QEvent::WinIdChange)
5740 << qMakePair(&widget, QEvent::Polish)
5741 << qMakePair(&widget, QEvent::Move)
5742 << qMakePair(&widget, QEvent::Resize)
5743 << qMakePair(&widget, QEvent::Show);
5745 expected << qMakePair(&widget, QEvent::ShowToParent);
5747 QVERIFY2(spy.eventList() == expected,
5748 EventRecorder::msgEventListMismatch(expected, spy.eventList()).constData());
5751 QCoreApplication::sendPostedEvents();
5753 EventRecorder::EventList()
5754 << qMakePair(&widget, QEvent::PolishRequest)
5755 << qMakePair(&widget, QEvent::Type(QEvent::User + 1));
5758 expected << qMakePair(&widget, QEvent::UpdateLater);
5760 expected << qMakePair(&widget, QEvent::UpdateRequest);
5762 if (m_platform == QStringLiteral("windows") || m_platform == QStringLiteral("xcb"))
5763 QEXPECT_FAIL("", EventRecorder::msgExpectFailQtBug26424(expected, spy.eventList()).constData(), Continue);
5764 QVERIFY2(spy.eventList() == expected,
5765 EventRecorder::msgEventListMismatch(expected, spy.eventList()).constData());
5769 // 2 children, not shown
5772 widget.installEventFilter(&spy);
5774 QCoreApplication::postEvent(&widget, new QEvent(QEvent::Type(QEvent::User + 1)));
5776 QWidget child1(&widget);
5778 child2.setParent(&widget);
5780 QCoreApplication::postEvent(&widget, new QEvent(QEvent::Type(QEvent::User + 2)));
5783 EventRecorder::EventList()
5784 << qMakePair(&widget, QEvent::ChildAdded)
5785 << qMakePair(&widget, QEvent::ChildAdded);
5786 QVERIFY2(spy.eventList() == expected,
5787 EventRecorder::msgEventListMismatch(expected, spy.eventList()).constData());
5790 QCoreApplication::sendPostedEvents();
5792 EventRecorder::EventList()
5793 << qMakePair(&widget, QEvent::PolishRequest)
5794 << qMakePair(&widget, QEvent::Polish)
5795 << qMakePair(&widget, QEvent::ChildPolished)
5796 << qMakePair(&widget, QEvent::ChildPolished)
5797 << qMakePair(&widget, QEvent::Type(QEvent::User + 1))
5798 << qMakePair(&widget, QEvent::Type(QEvent::User + 2));
5799 QVERIFY2(spy.eventList() == expected,
5800 EventRecorder::msgEventListMismatch(expected, spy.eventList()).constData());
5804 // 2 children, widget shown
5807 widget.installEventFilter(&spy);
5809 QCoreApplication::postEvent(&widget, new QEvent(QEvent::Type(QEvent::User + 1)));
5811 QWidget child1(&widget);
5813 child2.setParent(&widget);
5815 QCoreApplication::postEvent(&widget, new QEvent(QEvent::Type(QEvent::User + 2)));
5818 EventRecorder::EventList()
5819 << qMakePair(&widget, QEvent::ChildAdded)
5820 << qMakePair(&widget, QEvent::ChildAdded);
5821 QCOMPARE(spy.eventList(), expected);
5826 EventRecorder::EventList()
5827 << qMakePair(&widget, QEvent::WinIdChange)
5828 << qMakePair(&widget, QEvent::Polish)
5829 << qMakePair(&widget, QEvent::ChildPolished)
5830 << qMakePair(&widget, QEvent::ChildPolished)
5831 << qMakePair(&widget, QEvent::Move)
5832 << qMakePair(&widget, QEvent::Resize)
5833 << qMakePair(&widget, QEvent::Show);
5835 expected << qMakePair(&widget, QEvent::ShowToParent);
5837 QVERIFY2(spy.eventList() == expected,
5838 EventRecorder::msgEventListMismatch(expected, spy.eventList()).constData());
5841 QCoreApplication::sendPostedEvents();
5843 EventRecorder::EventList()
5844 << qMakePair(&widget, QEvent::PolishRequest)
5845 << qMakePair(&widget, QEvent::Type(QEvent::User + 1))
5846 << qMakePair(&widget, QEvent::Type(QEvent::User + 2));
5849 expected << qMakePair(&widget, QEvent::UpdateLater);
5851 expected << qMakePair(&widget, QEvent::UpdateRequest);
5853 if (m_platform == QStringLiteral("windows") || m_platform == QStringLiteral("xcb"))
5854 QEXPECT_FAIL("", EventRecorder::msgExpectFailQtBug26424(expected, spy.eventList()).constData(), Continue);
5855 QVERIFY2(spy.eventList() == expected,
5856 EventRecorder::msgEventListMismatch(expected, spy.eventList()).constData());
5860 // 2 children, but one is reparented away, not shown
5863 widget.installEventFilter(&spy);
5865 QCoreApplication::postEvent(&widget, new QEvent(QEvent::Type(QEvent::User + 1)));
5867 QWidget child1(&widget);
5869 child2.setParent(&widget);
5870 child2.setParent(0);
5872 QCoreApplication::postEvent(&widget, new QEvent(QEvent::Type(QEvent::User + 2)));
5875 EventRecorder::EventList()
5876 << qMakePair(&widget, QEvent::ChildAdded)
5877 << qMakePair(&widget, QEvent::ChildAdded)
5878 << qMakePair(&widget, QEvent::ChildRemoved);
5879 QCOMPARE(spy.eventList(), expected);
5882 QCoreApplication::sendPostedEvents();
5884 EventRecorder::EventList()
5885 << qMakePair(&widget, QEvent::PolishRequest)
5886 << qMakePair(&widget, QEvent::Polish)
5887 << qMakePair(&widget, QEvent::ChildPolished)
5888 << qMakePair(&widget, QEvent::Type(QEvent::User + 1))
5889 << qMakePair(&widget, QEvent::Type(QEvent::User + 2));
5891 QVERIFY2(spy.eventList() == expected,
5892 EventRecorder::msgEventListMismatch(expected, spy.eventList()).constData());
5896 // 2 children, but one is reparented away, then widget is shown
5899 widget.installEventFilter(&spy);
5901 QCoreApplication::postEvent(&widget, new QEvent(QEvent::Type(QEvent::User + 1)));
5903 QWidget child1(&widget);
5905 child2.setParent(&widget);
5906 child2.setParent(0);
5908 QCoreApplication::postEvent(&widget, new QEvent(QEvent::Type(QEvent::User + 2)));
5911 EventRecorder::EventList()
5912 << qMakePair(&widget, QEvent::ChildAdded)
5913 << qMakePair(&widget, QEvent::ChildAdded)
5914 << qMakePair(&widget, QEvent::ChildRemoved);
5915 QCOMPARE(spy.eventList(), expected);
5920 EventRecorder::EventList()
5921 << qMakePair(&widget, QEvent::WinIdChange)
5922 << qMakePair(&widget, QEvent::Polish)
5923 << qMakePair(&widget, QEvent::ChildPolished)
5924 << qMakePair(&widget, QEvent::Move)
5925 << qMakePair(&widget, QEvent::Resize)
5926 << qMakePair(&widget, QEvent::Show);
5928 expected << qMakePair(&widget, QEvent::ShowToParent);
5929 QVERIFY2(spy.eventList() == expected,
5930 EventRecorder::msgEventListMismatch(expected, spy.eventList()).constData());
5933 QCoreApplication::sendPostedEvents();
5935 EventRecorder::EventList()
5936 << qMakePair(&widget, QEvent::PolishRequest)
5937 << qMakePair(&widget, QEvent::Type(QEvent::User + 1))
5938 << qMakePair(&widget, QEvent::Type(QEvent::User + 2));
5941 expected << qMakePair(&widget, QEvent::UpdateLater);
5943 expected << qMakePair(&widget, QEvent::UpdateRequest);
5945 if (m_platform == QStringLiteral("windows") || m_platform == QStringLiteral("xcb"))
5946 QEXPECT_FAIL("", EventRecorder::msgExpectFailQtBug26424(expected, spy.eventList()).constData(), Continue);
5947 QVERIFY2(spy.eventList() == expected,
5948 EventRecorder::msgEventListMismatch(expected, spy.eventList()).constData());
5952 class RenderWidget : public QWidget
5955 RenderWidget(QWidget *source)
5956 : source(source), ellipse(false) {}
5958 void setEllipseEnabled(bool enable = true)
5965 void paintEvent(QPaintEvent *)
5968 QPainter painter(this);
5969 painter.fillRect(rect(), Qt::red);
5971 QRegion regionToRender = QRegion(0, 0, source->width(), source->height() / 2,
5973 source->render(this, QPoint(0, 30), regionToRender);
5975 source->render(this);
5984 void tst_QWidget::render()
5987 QCalendarWidget source;
5988 // disable anti-aliasing to eliminate potential differences when subpixel antialiasing
5989 // is enabled on the screen
5991 f.setStyleStrategy(QFont::NoAntialias);
5994 QVERIFY(QTest::qWaitForWindowExposed(&source));
5996 // Render the entire source into target.
5997 RenderWidget target(&source);
5998 target.resize(source.size());
6001 qApp->processEvents();
6002 qApp->sendPostedEvents();
6005 const QImage sourceImage = source.grab(QRect(QPoint(0, 0), QSize(-1, -1))).toImage();
6006 qApp->processEvents();
6007 QImage targetImage = target.grab(QRect(QPoint(0, 0), QSize(-1, -1))).toImage();
6008 qApp->processEvents();
6009 QCOMPARE(sourceImage, targetImage);
6011 // Fill target.rect() will Qt::red and render
6012 // QRegion(0, 0, source->width(), source->height() / 2, QRegion::Ellipse)
6013 // of source into target with offset (0, 30).
6014 target.setEllipseEnabled();
6015 qApp->processEvents();
6016 qApp->sendPostedEvents();
6018 targetImage = target.grab(QRect(QPoint(0, 0), QSize(-1, -1))).toImage();
6019 QVERIFY(sourceImage != targetImage);
6021 QCOMPARE(targetImage.pixel(target.width() / 2, 29), QColor(Qt::red).rgb());
6022 QCOMPARE(targetImage.pixel(target.width() / 2, 30), sourceImage.pixel(source.width() / 2, 0));
6024 // Test that a child widget properly fills its background
6027 window.resize(100, 100);
6028 // prevent custom styles
6029 window.setStyle(new QWindowsStyle);
6031 QVERIFY(QTest::qWaitForWindowExposed(&window));
6032 QWidget child(&window);
6033 child.resize(window.size());
6036 qApp->processEvents();
6037 const QPixmap childPixmap = child.grab(QRect(QPoint(0, 0), QSize(-1, -1)));
6038 const QPixmap windowPixmap = window.grab(QRect(QPoint(0, 0), QSize(-1, -1)));
6039 QCOMPARE(childPixmap, windowPixmap);
6042 { // Check that the target offset is correct.
6044 widget.resize(200, 200);
6045 widget.setAutoFillBackground(true);
6046 widget.setPalette(Qt::red);
6047 // prevent custom styles
6048 widget.setStyle(new QWindowsStyle);
6050 QVERIFY(QTest::qWaitForWindowExposed(&widget));
6051 QImage image(widget.size(), QImage::Format_RGB32);
6052 image.fill(QColor(Qt::blue).rgb());
6054 // Target offset (0, 0)
6055 widget.render(&image, QPoint(), QRect(20, 20, 100, 100));
6056 QCOMPARE(image.pixel(0, 0), QColor(Qt::red).rgb());
6057 QCOMPARE(image.pixel(99, 99), QColor(Qt::red).rgb());
6058 QCOMPARE(image.pixel(100, 100), QColor(Qt::blue).rgb());
6060 // Target offset (20, 20).
6061 image.fill(QColor(Qt::blue).rgb());
6062 widget.render(&image, QPoint(20, 20), QRect(20, 20, 100, 100));
6063 QCOMPARE(image.pixel(0, 0), QColor(Qt::blue).rgb());
6064 QCOMPARE(image.pixel(19, 19), QColor(Qt::blue).rgb());
6065 QCOMPARE(image.pixel(20, 20), QColor(Qt::red).rgb());
6066 QCOMPARE(image.pixel(119, 119), QColor(Qt::red).rgb());
6067 QCOMPARE(image.pixel(120, 120), QColor(Qt::blue).rgb());
6071 // On Windows the active palette is used instead of the inactive palette even
6072 // though the widget is invisible. This is probably related to task 178507/168682,
6073 // but for the renderInvisible test it doesn't matter, we're mostly interested
6074 // in testing the geometry so just workaround the palette issue for now.
6075 static void workaroundPaletteIssue(QWidget *widget)
6083 QWidget *navigationBar = qFindChild<QWidget *>(widget, QLatin1String("qt_calendar_navigationbar"));
6084 QVERIFY(navigationBar);
6086 QPalette palette = navigationBar->palette();
6087 const QColor background = palette.color(QPalette::Inactive, navigationBar->backgroundRole());
6088 const QColor highlightedText = palette.color(QPalette::Inactive, QPalette::HighlightedText);
6089 palette.setColor(QPalette::Active, navigationBar->backgroundRole(), background);
6090 palette.setColor(QPalette::Active, QPalette::HighlightedText, highlightedText);
6091 navigationBar->setPalette(palette);
6094 //#define RENDER_DEBUG
6095 void tst_QWidget::renderInvisible()
6097 if (m_platform == QStringLiteral("xcb"))
6098 QSKIP("QTBUG-26424");
6100 QScopedPointer<QCalendarWidget> calendar(new QCalendarWidget);
6101 // disable anti-aliasing to eliminate potential differences when subpixel antialiasing
6102 // is enabled on the screen
6104 f.setStyleStrategy(QFont::NoAntialias);
6105 calendar->setFont(f);
6107 QVERIFY(QTest::qWaitForWindowExposed(calendar.data()));
6109 // Create a dummy focus widget to get rid of focus rect in reference image.
6110 QLineEdit dummyFocusWidget;
6111 dummyFocusWidget.show();
6112 QVERIFY(QTest::qWaitForWindowExposed(&dummyFocusWidget));
6113 qApp->processEvents();
6116 // Create normal reference image.
6117 const QSize calendarSize = calendar->size();
6118 QImage referenceImage(calendarSize, QImage::Format_ARGB32);
6119 calendar->render(&referenceImage);
6121 referenceImage.save("referenceImage.png");
6123 QVERIFY(!referenceImage.isNull());
6125 // Create resized reference image.
6126 const QSize calendarSizeResized = calendar->size() + QSize(50, 50);
6127 calendar->resize(calendarSizeResized);
6128 qApp->processEvents();
6130 QImage referenceImageResized(calendarSizeResized, QImage::Format_ARGB32);
6131 calendar->render(&referenceImageResized);
6133 referenceImageResized.save("referenceImageResized.png");
6135 QVERIFY(!referenceImageResized.isNull());
6137 // Explicitly hide the calendar.
6139 qApp->processEvents();
6141 workaroundPaletteIssue(calendar.data());
6143 { // Make sure we get the same image when the calendar is explicitly hidden.
6144 QImage testImage(calendarSizeResized, QImage::Format_ARGB32);
6145 calendar->render(&testImage);
6147 testImage.save("explicitlyHiddenCalendarResized.png");
6149 QCOMPARE(testImage, referenceImageResized);
6152 // Now that we have reference images we can delete the source and re-create
6153 // the calendar and check that we get the same images from a calendar which has never
6154 // been visible, laid out or created (Qt::WA_WState_Created).
6155 calendar.reset(new QCalendarWidget);
6156 calendar->setFont(f);
6157 workaroundPaletteIssue(calendar.data());
6159 { // Never been visible, created or laid out.
6160 QImage testImage(calendarSize, QImage::Format_ARGB32);
6161 calendar->render(&testImage);
6163 testImage.save("neverBeenVisibleCreatedOrLaidOut.png");
6165 QCOMPARE(testImage, referenceImage);
6169 qApp->processEvents();
6172 { // Calendar explicitly hidden.
6173 QImage testImage(calendarSize, QImage::Format_ARGB32);
6174 calendar->render(&testImage);
6176 testImage.save("explicitlyHiddenCalendar.png");
6178 QCOMPARE(testImage, referenceImage);
6181 // Get navigation bar and explicitly hide it.
6182 QWidget *navigationBar = qFindChild<QWidget *>(calendar.data(), QLatin1String("qt_calendar_navigationbar"));
6183 QVERIFY(navigationBar);
6184 navigationBar->hide();
6186 { // Check that the navigation bar isn't drawn when rendering the entire calendar.
6187 QImage testImage(calendarSize, QImage::Format_ARGB32);
6188 calendar->render(&testImage);
6190 testImage.save("calendarWithoutNavigationBar.png");
6192 QVERIFY(testImage != referenceImage);
6195 { // Make sure the navigation bar renders correctly even though it's hidden.
6196 QImage testImage(navigationBar->size(), QImage::Format_ARGB32);
6197 navigationBar->render(&testImage);
6199 testImage.save("explicitlyHiddenNavigationBar.png");
6201 QCOMPARE(testImage, referenceImage.copy(navigationBar->rect()));
6204 // Get next month button.
6205 QWidget *nextMonthButton = qFindChild<QWidget *>(navigationBar, QLatin1String("qt_calendar_nextmonth"));
6206 QVERIFY(nextMonthButton);
6208 { // Render next month button.
6209 // Fill test image with correct background color.
6210 QImage testImage(nextMonthButton->size(), QImage::Format_ARGB32);
6211 navigationBar->render(&testImage, QPoint(), QRegion(), QWidget::RenderFlags());
6213 testImage.save("nextMonthButtonBackground.png");
6216 // Set the button's background color to Qt::transparent; otherwise it will fill the
6217 // background with QPalette::Window.
6218 const QPalette originalPalette = nextMonthButton->palette();
6219 QPalette palette = originalPalette;
6220 palette.setColor(QPalette::Window, Qt::transparent);
6221 nextMonthButton->setPalette(palette);
6223 // Render the button on top of the background.
6224 nextMonthButton->render(&testImage);
6226 testImage.save("nextMonthButton.png");
6228 const QRect buttonRect(nextMonthButton->mapTo(calendar.data(), QPoint()), nextMonthButton->size());
6229 QCOMPARE(testImage, referenceImage.copy(buttonRect));
6232 nextMonthButton->setPalette(originalPalette);
6235 // Navigation bar isn't explicitly hidden anymore.
6236 navigationBar->show();
6237 qApp->processEvents();
6239 QVERIFY(!calendar->isVisible());
6241 // Now, completely mess up the layout. This will trigger an update on the layout
6242 // when the calendar is visible or shown, but it's not. QWidget::render must therefore
6243 // make sure the layout is activated before rendering.
6244 QVERIFY(!calendar->isVisible());
6245 calendar->resize(calendarSizeResized);
6246 qApp->processEvents();
6248 { // Make sure we get an image equal to the resized reference image.
6249 QImage testImage(calendarSizeResized, QImage::Format_ARGB32);
6250 calendar->render(&testImage);
6252 testImage.save("calendarResized.png");
6254 QCOMPARE(testImage, referenceImageResized);
6257 { // Make sure we lay out the widget correctly the first time it's rendered.
6258 QCalendarWidget calendar;
6259 const QSize calendarSize = calendar.sizeHint();
6261 QImage image(2 * calendarSize, QImage::Format_ARGB32);
6262 image.fill(QColor(Qt::red).rgb());
6263 calendar.render(&image);
6265 for (int i = calendarSize.height(); i < 2 * calendarSize.height(); ++i)
6266 for (int j = calendarSize.width(); j < 2 * calendarSize.width(); ++j)
6267 QCOMPARE(image.pixel(j, i), QColor(Qt::red).rgb());
6270 { // Ensure that we don't call adjustSize() on invisible top-levels if render() is called
6271 // right after widgets have been added/removed to/from its layout.
6273 topLevel.setLayout(new QVBoxLayout);
6275 QWidget *widget = new QLineEdit;
6276 topLevel.layout()->addWidget(widget);
6278 const QSize initialSize = topLevel.size();
6279 QPixmap pixmap(topLevel.sizeHint());
6280 topLevel.render(&pixmap); // triggers adjustSize()
6281 const QSize finalSize = topLevel.size();
6282 QVERIFY(finalSize != initialSize);
6284 topLevel.layout()->removeWidget(widget);
6285 QCOMPARE(topLevel.size(), finalSize);
6286 topLevel.render(&pixmap);
6287 QCOMPARE(topLevel.size(), finalSize);
6289 topLevel.layout()->addWidget(widget);
6290 QCOMPARE(topLevel.size(), finalSize);
6291 topLevel.render(&pixmap);
6292 QCOMPARE(topLevel.size(), finalSize);
6296 void tst_QWidget::renderWithPainter()
6298 QWidget widget(0, Qt::Tool);
6299 // prevent custom styles
6300 widget.setStyle(new QWindowsStyle);
6302 widget.resize(70, 50);
6303 widget.setAutoFillBackground(true);
6304 widget.setPalette(Qt::black);
6306 // Render the entire widget onto the image.
6307 QImage image(QSize(70, 50), QImage::Format_ARGB32);
6308 image.fill(QColor(Qt::red).rgb());
6309 QPainter painter(&image);
6310 widget.render(&painter);
6312 for (int i = 0; i < image.height(); ++i) {
6313 for (int j = 0; j < image.width(); ++j)
6314 QCOMPARE(image.pixel(j, i), QColor(Qt::black).rgb());
6317 // Translate painter (10, 10).
6319 image.fill(QColor(Qt::red).rgb());
6320 painter.translate(10, 10);
6321 widget.render(&painter);
6324 for (int i = 0; i < image.height(); ++i) {
6325 for (int j = 0; j < image.width(); ++j) {
6326 if (i < 10 || j < 10)
6327 QCOMPARE(image.pixel(j, i), QColor(Qt::red).rgb());
6329 QCOMPARE(image.pixel(j, i), QColor(Qt::black).rgb());
6333 // Pass target offset (10, 10) (the same as QPainter::translate).
6334 image.fill(QColor(Qt::red).rgb());
6335 widget.render(&painter, QPoint(10, 10));
6337 for (int i = 0; i < image.height(); ++i) {
6338 for (int j = 0; j < image.width(); ++j) {
6339 if (i < 10 || j < 10)
6340 QCOMPARE(image.pixel(j, i), QColor(Qt::red).rgb());
6342 QCOMPARE(image.pixel(j, i), QColor(Qt::black).rgb());
6346 // Translate (10, 10) and pass target offset (10, 10).
6348 image.fill(QColor(Qt::red).rgb());
6349 painter.translate(10, 10);
6350 widget.render(&painter, QPoint(10, 10));
6353 for (int i = 0; i < image.height(); ++i) {
6354 for (int j = 0; j < image.width(); ++j) {
6355 if (i < 20 || j < 20)
6356 QCOMPARE(image.pixel(j, i), QColor(Qt::red).rgb());
6358 QCOMPARE(image.pixel(j, i), QColor(Qt::black).rgb());
6362 // Rotate painter 90 degrees.
6364 image.fill(QColor(Qt::red).rgb());
6366 widget.render(&painter);
6369 for (int i = 0; i < image.height(); ++i) {
6370 for (int j = 0; j < image.width(); ++j)
6371 QCOMPARE(image.pixel(j, i), QColor(Qt::red).rgb());
6374 // Translate and rotate.
6375 image.fill(QColor(Qt::red).rgb());
6376 widget.resize(40, 10);
6377 painter.translate(10, 10);
6379 widget.render(&painter);
6381 for (int i = 0; i < image.height(); ++i) {
6382 for (int j = 0; j < image.width(); ++j) {
6383 if (i >= 10 && j >= 0 && j < 10)
6384 QCOMPARE(image.pixel(j, i), QColor(Qt::black).rgb());
6386 QCOMPARE(image.pixel(j, i), QColor(Qt::red).rgb());
6390 // Make sure QWidget::render does not modify the render hints set on the painter.
6391 painter.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform
6392 | QPainter::NonCosmeticDefaultPen | QPainter::TextAntialiasing);
6393 QPainter::RenderHints oldRenderHints = painter.renderHints();
6394 widget.render(&painter);
6395 QCOMPARE(painter.renderHints(), oldRenderHints);
6398 void tst_QWidget::render_task188133()
6400 QMainWindow mainWindow;
6402 // Make sure QWidget::render does not trigger QWidget::repaint/update
6403 // and asserts for Qt::WA_WState_Created.
6404 const QPixmap pixmap = mainWindow.grab(QRect(QPoint(0, 0), QSize(-1, -1)));
6408 void tst_QWidget::render_task211796()
6410 class MyWidget : public QWidget
6412 void resizeEvent(QResizeEvent *)
6414 QPixmap pixmap(size());
6419 { // Please don't die in a resize recursion.
6421 widget.resize(200, 200);
6425 { // Same check with a deeper hierarchy.
6428 QWidget child(&widget);
6429 MyWidget grandChild;
6430 grandChild.setParent(&child);
6431 grandChild.resize(100, 100);
6436 void tst_QWidget::render_task217815()
6438 // Make sure we don't change the size of the widget when calling
6439 // render() and the widget has an explicit size set.
6440 // This was a problem on Windows because we called createWinId(),
6441 // which in turn enforced the size to be bigger than the smallest
6442 // possible native window size (which is (115,something) on WinXP).
6444 const QSize explicitSize(80, 20);
6445 widget.resize(explicitSize);
6446 QCOMPARE(widget.size(), explicitSize);
6448 QPixmap pixmap(explicitSize);
6449 widget.render(&pixmap);
6451 QCOMPARE(widget.size(), explicitSize);
6454 // Window Opacity is not supported on Windows CE.
6456 void tst_QWidget::render_windowOpacity()
6458 const qreal opacity = 0.5;
6460 { // Check that the painter opacity effects the widget drawing.
6462 QWidget child(&topLevel);
6463 child.resize(50, 50);
6464 child.setPalette(Qt::red);
6465 child.setAutoFillBackground(true);
6467 QPixmap expected(child.size());
6469 if (m_platform == QStringLiteral("xcb") && expected.depth() < 24)
6470 QSKIP("This test won't give correct results with dithered pixmaps");
6472 expected.fill(Qt::green);
6473 QPainter painter(&expected);
6474 painter.setOpacity(opacity);
6475 painter.fillRect(QRect(QPoint(0, 0), child.size()), Qt::red);
6478 QPixmap result(child.size());
6479 result.fill(Qt::green);
6480 painter.begin(&result);
6481 painter.setOpacity(opacity);
6482 child.render(&painter);
6484 QCOMPARE(result, expected);
6487 { // Combine the opacity set on the painter with the widget opacity.
6488 class MyWidget : public QWidget
6491 void paintEvent(QPaintEvent *)
6493 QPainter painter(this);
6494 painter.setOpacity(opacity);
6495 QCOMPARE(painter.opacity(), opacity);
6496 painter.fillRect(rect(), Qt::red);
6502 widget.resize(50, 50);
6503 widget.opacity = opacity;
6504 widget.setPalette(Qt::blue);
6505 widget.setAutoFillBackground(true);
6507 QPixmap expected(widget.size());
6508 expected.fill(Qt::green);
6509 QPainter painter(&expected);
6510 painter.setOpacity(opacity);
6511 QPixmap pixmap(widget.size());
6512 pixmap.fill(Qt::blue);
6513 QPainter pixmapPainter(&pixmap);
6514 pixmapPainter.setOpacity(opacity);
6515 pixmapPainter.fillRect(QRect(QPoint(), widget.size()), Qt::red);
6516 painter.drawPixmap(QPoint(), pixmap);
6519 QPixmap result(widget.size());
6520 result.fill(Qt::green);
6521 painter.begin(&result);
6522 painter.setOpacity(opacity);
6523 widget.render(&painter);
6525 QCOMPARE(result, expected);
6530 void tst_QWidget::render_systemClip()
6533 widget.setPalette(Qt::blue);
6534 widget.resize(100, 100);
6536 QImage image(widget.size(), QImage::Format_RGB32);
6537 image.fill(QColor(Qt::red).rgb());
6539 QPaintEngine *paintEngine = image.paintEngine();
6540 QVERIFY(paintEngine);
6541 paintEngine->setSystemClip(QRegion(0, 0, 50, 50));
6543 QPainter painter(&image);
6544 // Make sure we're using the same paint engine and has the right clip set.
6545 QCOMPARE(painter.paintEngine(), paintEngine);
6546 QCOMPARE(paintEngine->systemClip(), QRegion(0, 0, 50, 50));
6548 // Translate painter outside system clip.
6549 painter.translate(50, 0);
6550 widget.render(&painter);
6553 image.save("outside_systemclip.png");
6556 // All pixels should be red.
6557 for (int i = 0; i < image.height(); ++i) {
6558 for (int j = 0; j < image.width(); ++j)
6559 QCOMPARE(image.pixel(j, i), QColor(Qt::red).rgb());
6562 // Restore painter and refill image with red.
6563 image.fill(QColor(Qt::red).rgb());
6564 painter.translate(-50, 0);
6566 // Set transform on the painter.
6567 QTransform transform;
6568 transform.shear(0, 1);
6569 painter.setTransform(transform);
6570 widget.render(&painter);
6573 image.save("blue_triangle.png");
6576 // We should now have a blue triangle starting at scan line 1, and the rest should be red.
6586 for (int i = 0; i < image.height(); ++i) {
6587 for (int j = 0; j < image.width(); ++j) {
6588 if (i < 50 && j < i)
6589 QCOMPARE(image.pixel(j, i), QColor(Qt::blue).rgb());
6591 QCOMPARE(image.pixel(j, i), QColor(Qt::red).rgb());
6595 // We don't paint directly on the image on the Mac, so we cannot do the pixel comparison
6596 // as above due to QPainter::SmoothPixmapTransform. We therefore need to generate an
6597 // expected image by first painting on a pixmap, and then draw the pixmap onto
6598 // the image using QPainter::SmoothPixmapTransform. Then we can compare pixels :)
6599 // The check is basically the same, except that it takes the smoothening into account.
6600 QPixmap pixmap(50, 50);
6601 const QRegion sysClip(0, 0, 50, 50);
6602 widget.render(&pixmap, QPoint(), sysClip);
6604 QImage expectedImage(widget.size(), QImage::Format_RGB32);
6605 expectedImage.fill(QColor(Qt::red).rgb());
6606 expectedImage.paintEngine()->setSystemClip(sysClip);
6608 QPainter expectedImagePainter(&expectedImage);
6609 expectedImagePainter.setTransform(QTransform().shear(0, 1));
6610 // NB! This is the important part (SmoothPixmapTransform).
6611 expectedImagePainter.setRenderHints(QPainter::SmoothPixmapTransform);
6612 expectedImagePainter.drawPixmap(QPoint(0, 0), pixmap);
6613 expectedImagePainter.end();
6615 QCOMPARE(image, expectedImage);
6619 void tst_QWidget::render_systemClip2_data()
6621 QTest::addColumn<bool>("autoFillBackground");
6622 QTest::addColumn<bool>("usePaintEvent");
6623 QTest::addColumn<QColor>("expectedColor");
6625 QTest::newRow("Only auto-fill background") << true << false << QColor(Qt::blue);
6626 QTest::newRow("Only draw in paintEvent") << false << true << QColor(Qt::green);
6627 QTest::newRow("Auto-fill background and draw in paintEvent") << true << true << QColor(Qt::green);
6630 void tst_QWidget::render_systemClip2()
6632 QFETCH(bool, autoFillBackground);
6633 QFETCH(bool, usePaintEvent);
6634 QFETCH(QColor, expectedColor);
6636 QVERIFY2(expectedColor != QColor(Qt::red), "Qt::red is the reference color for the image, pick another color");
6638 class MyWidget : public QWidget
6642 void paintEvent(QPaintEvent *)
6645 QPainter(this).fillRect(rect(), Qt::green);
6650 widget.usePaintEvent = usePaintEvent;
6651 widget.setPalette(Qt::blue);
6652 // NB! widget.setAutoFillBackground(autoFillBackground) won't do the
6653 // trick here since the widget is a top-level. The background is filled
6654 // regardless, unless Qt::WA_OpaquePaintEvent or Qt::WA_NoSystemBackground
6655 // is set. We therefore use the opaque attribute to turn off auto-fill.
6656 if (!autoFillBackground)
6657 widget.setAttribute(Qt::WA_OpaquePaintEvent);
6658 widget.resize(100, 100);
6660 QImage image(widget.size(), QImage::Format_RGB32);
6661 image.fill(QColor(Qt::red).rgb());
6663 QPaintEngine *paintEngine = image.paintEngine();
6664 QVERIFY(paintEngine);
6666 QRegion systemClip(QRegion(50, 0, 50, 10));
6667 systemClip += QRegion(90, 10, 10, 40);
6668 paintEngine->setSystemClip(systemClip);
6670 // Render entire widget directly onto device.
6671 widget.render(&image);
6674 image.save("systemclip_with_device.png");
6676 // All pixels within the system clip should now be
6677 // the expectedColor, and the rest should be red.
6678 for (int i = 0; i < image.height(); ++i) {
6679 for (int j = 0; j < image.width(); ++j) {
6680 if (systemClip.contains(QPoint(j, i)))
6681 QCOMPARE(image.pixel(j, i), expectedColor.rgb());
6683 QCOMPARE(image.pixel(j, i), QColor(Qt::red).rgb());
6687 // Refill image with red.
6688 image.fill(QColor(Qt::red).rgb());
6689 paintEngine->setSystemClip(systemClip);
6691 // Do the same with an untransformed painter.
6692 QPainter painter(&image);
6693 //Make sure we're using the same paint engine and has the right clip set.
6694 QCOMPARE(painter.paintEngine(), paintEngine);
6695 QCOMPARE(paintEngine->systemClip(), systemClip);
6697 widget.render(&painter);
6700 image.save("systemclip_with_untransformed_painter.png");
6702 // All pixels within the system clip should now be
6703 // the expectedColor, and the rest should be red.
6704 for (int i = 0; i < image.height(); ++i) {
6705 for (int j = 0; j < image.width(); ++j) {
6706 if (systemClip.contains(QPoint(j, i)))
6707 QCOMPARE(image.pixel(j, i), expectedColor.rgb());
6709 QCOMPARE(image.pixel(j, i), QColor(Qt::red).rgb());
6714 void tst_QWidget::render_systemClip3_data()
6716 QTest::addColumn<QSize>("size");
6717 QTest::addColumn<bool>("useSystemClip");
6719 // Reference: http://en.wikipedia.org/wiki/Flag_of_Norway
6720 QTest::newRow("Norwegian Civil Flag") << QSize(220, 160) << false;
6721 QTest::newRow("Norwegian War Flag") << QSize(270, 160) << true;
6724 // This test ensures that the current engine clip (systemClip + painter clip)
6725 // is preserved after QPainter::setClipRegion(..., Qt::ReplaceClip);
6726 void tst_QWidget::render_systemClip3()
6728 QFETCH(QSize, size);
6729 QFETCH(bool, useSystemClip);
6731 // Calculate the inner/outer cross of the flag.
6732 QRegion outerCross(0, 0, size.width(), size.height());
6733 outerCross -= QRect(0, 0, 60, 60);
6734 outerCross -= QRect(100, 0, size.width() - 100, 60);
6735 outerCross -= QRect(0, 100, 60, 60);
6736 outerCross -= QRect(100, 100, size.width() - 100, 60);
6738 QRegion innerCross(0, 0, size.width(), size.height());
6739 innerCross -= QRect(0, 0, 70, 70);
6740 innerCross -= QRect(90, 0, size.width() - 90, 70);
6741 innerCross -= QRect(0, 90, 70, 70);
6742 innerCross -= QRect(90, 90, size.width() - 90, 70);
6744 const QRegion redArea(QRegion(0, 0, size.width(), size.height()) - outerCross);
6745 const QRegion whiteArea(outerCross - innerCross);
6746 const QRegion blueArea(innerCross);
6749 // Okay, here's the image that should look like a Norwegian civil/war flag in the end.
6750 QImage flag(size, QImage::Format_ARGB32);
6751 flag.fill(QColor(Qt::transparent).rgba());
6753 if (useSystemClip) {
6754 QPainterPath warClip(QPoint(size.width(), 0));
6755 warClip.lineTo(size.width() - 110, 60);
6756 warClip.lineTo(size.width(), 80);
6757 warClip.lineTo(size.width() - 110, 100);
6758 warClip.lineTo(size.width(), 160);
6759 warClip.closeSubpath();
6760 systemClip = QRegion(0, 0, size.width(), size.height()) - QRegion(warClip.toFillPolygon().toPolygon());
6761 flag.paintEngine()->setSystemClip(systemClip);
6764 QPainter painter(&flag);
6765 painter.fillRect(QRect(QPoint(), size), Qt::red); // Fill image background with red.
6766 painter.setClipRegion(outerCross); // Limit widget painting to inside the outer cross.
6768 // Here's the widget that's supposed to draw the inner/outer cross of the flag.
6769 // The outer cross (white) should be drawn when the background is auto-filled, and
6770 // the inner cross (blue) should be drawn in the paintEvent.
6771 class MyWidget : public QWidget
6773 void paintEvent(QPaintEvent *)
6775 QPainter painter(this);
6776 // Be evil and try to paint outside the outer cross. This should not be
6777 // possible since the shared painter is clipped to the outer cross.
6778 painter.setClipRect(0, 0, 60, 60, Qt::ReplaceClip);
6779 painter.fillRect(rect(), Qt::green);
6780 painter.setClipRegion(clip, Qt::ReplaceClip);
6781 painter.fillRect(rect(), Qt::blue);
6787 widget.clip = innerCross;
6788 widget.setFixedSize(size);
6789 widget.setPalette(Qt::white);
6790 widget.setAutoFillBackground(true);
6791 widget.render(&painter);
6794 flag.save("flag.png");
6797 // Let's make sure we got a Norwegian flag.
6798 for (int i = 0; i < flag.height(); ++i) {
6799 for (int j = 0; j < flag.width(); ++j) {
6800 const QPoint pixel(j, i);
6801 const QRgb pixelValue = flag.pixel(pixel);
6802 if (useSystemClip && !systemClip.contains(pixel))
6803 QCOMPARE(pixelValue, QColor(Qt::transparent).rgba());
6804 else if (redArea.contains(pixel))
6805 QCOMPARE(pixelValue, QColor(Qt::red).rgba());
6806 else if (whiteArea.contains(pixel))
6807 QCOMPARE(pixelValue, QColor(Qt::white).rgba());
6809 QCOMPARE(pixelValue, QColor(Qt::blue).rgba());
6814 void tst_QWidget::render_task252837()
6817 widget.resize(200, 200);
6819 QPixmap pixmap(widget.size());
6820 QPainter painter(&pixmap);
6821 // Please do not crash.
6822 widget.render(&painter);
6825 void tst_QWidget::render_worldTransform()
6827 class MyWidget : public QWidget
6829 void paintEvent(QPaintEvent *)
6831 QPainter painter(this);
6832 // Make sure world transform is identity.
6833 QCOMPARE(painter.worldTransform(), QTransform());
6835 // Make sure device transform is correct.
6836 const QPoint widgetOffset = geometry().topLeft();
6837 QTransform expectedDeviceTransform = QTransform::fromTranslate(105, 5);
6838 expectedDeviceTransform.rotate(90);
6839 expectedDeviceTransform.translate(widgetOffset.x(), widgetOffset.y());
6840 QCOMPARE(painter.deviceTransform(), expectedDeviceTransform);
6842 // Set new world transform.
6843 QTransform newWorldTransform = QTransform::fromTranslate(10, 10);
6844 newWorldTransform.rotate(90);
6845 painter.setWorldTransform(newWorldTransform);
6846 QCOMPARE(painter.worldTransform(), newWorldTransform);
6848 // Again, check device transform.
6849 expectedDeviceTransform.translate(10, 10);
6850 expectedDeviceTransform.rotate(90);
6851 QCOMPARE(painter.deviceTransform(), expectedDeviceTransform);
6853 painter.fillRect(QRect(0, 0, 20, 10), Qt::green);
6858 widget.setFixedSize(100, 100);
6859 widget.setPalette(Qt::red);
6860 widget.setAutoFillBackground(true);
6863 child.setParent(&widget);
6865 child.setFixedSize(50, 50);
6866 child.setPalette(Qt::blue);
6867 child.setAutoFillBackground(true);
6869 QImage image(QSize(110, 110), QImage::Format_RGB32);
6870 image.fill(QColor(Qt::black).rgb());
6872 QPainter painter(&image);
6873 painter.translate(105, 5);
6876 // Render widgets onto image.
6877 widget.render(&painter);
6879 image.save("render_worldTransform_image.png");
6882 // Ensure the transforms are unchanged after render.
6883 QCOMPARE(painter.worldTransform(), painter.worldTransform());
6884 QCOMPARE(painter.deviceTransform(), painter.deviceTransform());
6887 // Paint expected image.
6888 QImage expected(QSize(110, 110), QImage::Format_RGB32);
6889 expected.fill(QColor(Qt::black).rgb());
6891 QPainter expectedPainter(&expected);
6892 expectedPainter.translate(105, 5);
6893 expectedPainter.rotate(90);
6894 expectedPainter.save();
6895 expectedPainter.fillRect(widget.rect(),Qt::red);
6896 expectedPainter.translate(10, 10);
6897 expectedPainter.rotate(90);
6898 expectedPainter.fillRect(QRect(0, 0, 20, 10), Qt::green);
6899 expectedPainter.restore();
6900 expectedPainter.translate(50, 50);
6901 expectedPainter.fillRect(child.rect(),Qt::blue);
6902 expectedPainter.translate(10, 10);
6903 expectedPainter.rotate(90);
6904 expectedPainter.fillRect(QRect(0, 0, 20, 10), Qt::green);
6905 expectedPainter.end();
6908 expected.save("render_worldTransform_expected.png");
6911 QCOMPARE(image, expected);
6914 void tst_QWidget::setContentsMargins()
6916 QLabel label("why does it always rain on me?");
6917 QSize oldSize = label.sizeHint();
6918 label.setFrameStyle(QFrame::Sunken | QFrame::Box);
6919 QSize newSize = label.sizeHint();
6920 QVERIFY(oldSize != newSize);
6922 QLabel label2("why does it always rain on me?");
6924 label2.setFrameStyle(QFrame::Sunken | QFrame::Box);
6925 QCOMPARE(newSize, label2.sizeHint());
6927 QLabel label3("why does it always rain on me?");
6928 label3.setFrameStyle(QFrame::Sunken | QFrame::Box);
6929 QCOMPARE(newSize, label3.sizeHint());
6932 void tst_QWidget::moveWindowInShowEvent_data()
6934 QTest::addColumn<QPoint>("initial");
6935 QTest::addColumn<QPoint>("position");
6937 QPoint p = QApplication::desktop()->availableGeometry().topLeft();
6939 QTest::newRow("1") << p << (p + QPoint(10, 10));
6940 QTest::newRow("2") << (p + QPoint(10,10)) << p;
6943 void tst_QWidget::moveWindowInShowEvent()
6945 if (m_platform == QStringLiteral("xcb"))
6946 QSKIP("QTBUG-26424");
6948 QFETCH(QPoint, initial);
6949 QFETCH(QPoint, position);
6951 class MoveWindowInShowEventWidget : public QWidget
6955 void showEvent(QShowEvent *)
6961 MoveWindowInShowEventWidget widget;
6962 widget.resize(QSize(qApp->desktop()->availableGeometry().size() / 3).expandedTo(QSize(1, 1)));
6963 // move to this position in showEvent()
6964 widget.position = position;
6966 // put the widget in it's starting position
6967 widget.move(initial);
6968 QCOMPARE(widget.pos(), initial);
6972 QVERIFY(QTest::qWaitForWindowShown(&widget));
6974 // it should have moved
6975 QCOMPARE(widget.pos(), position);
6978 void tst_QWidget::repaintWhenChildDeleted()
6981 if (QSysInfo::WindowsVersion & QSysInfo::WV_VISTA) {
6985 ColorWidget w(0, Qt::red);
6986 #if !defined(Q_OS_WINCE)
6987 QPoint startPoint = QApplication::desktop()->availableGeometry(&w).topLeft();
6988 startPoint.rx() += 50;
6989 startPoint.ry() += 50;
6990 w.setGeometry(QRect(startPoint, QSize(100, 100)));
6992 w.setGeometry(60, 60, 110, 110);
6995 QVERIFY(QTest::qWaitForWindowExposed(&w));
6997 QTRY_COMPARE(w.r, QRegion(w.rect()));
7001 ColorWidget child(&w, Qt::blue);
7002 child.setGeometry(10, 10, 10, 10);
7005 QTRY_COMPARE(child.r, QRegion(child.rect()));
7010 QTRY_COMPARE(w.r, QRegion(10, 10, 10, 10));
7014 void tst_QWidget::hideOpaqueChildWhileHidden()
7016 ColorWidget w(0, Qt::red);
7017 #if !defined(Q_OS_WINCE)
7018 QPoint startPoint = QApplication::desktop()->availableGeometry(&w).topLeft();
7019 startPoint.rx() += 50;
7020 startPoint.ry() += 50;
7021 w.setGeometry(QRect(startPoint, QSize(100, 100)));
7023 w.setGeometry(60, 60, 110, 110);
7026 ColorWidget child(&w, Qt::blue);
7027 child.setGeometry(10, 10, 80, 80);
7029 ColorWidget child2(&child, Qt::white);
7030 child2.setGeometry(10, 10, 60, 60);
7033 QVERIFY(QTest::qWaitForWindowExposed(&w));
7035 QTRY_COMPARE(child2.r, QRegion(child2.rect()));
7036 child.r = QRegion();
7037 child2.r = QRegion();
7044 QCOMPARE(w.r, QRegion(child.geometry()));
7048 QCOMPARE(child.r, QRegion(child.rect()));
7049 QCOMPARE(child2.r, QRegion());
7052 // This test doesn't make sense without support for showMinimized().
7053 #if !defined(Q_OS_WINCE)
7054 void tst_QWidget::updateWhileMinimized()
7056 UpdateWidget widget;
7057 // Filter out activation change and focus events to avoid update() calls in QWidget.
7058 widget.updateOnActivationChangeAndFocusIn = false;
7061 QVERIFY(QTest::qWaitForWindowExposed(&widget));
7062 QApplication::processEvents();
7063 QTRY_VERIFY(widget.numPaintEvents > 0);
7067 widget.showMinimized();
7072 // The widget is not visible on the screen (but isVisible() still returns true).
7073 // Make sure update requests are discarded until the widget is shown again.
7074 widget.update(0, 0, 50, 50);
7076 if (m_platform == QStringLiteral("windows"))
7077 QEXPECT_FAIL("", "QTBUG-26424", Continue);
7078 QCOMPARE(widget.numPaintEvents, 0);
7081 widget.showNormal();
7083 if (m_platform == QStringLiteral("xcb"))
7084 QSKIP("QTBUG-26424");
7085 QTRY_COMPARE(widget.numPaintEvents, 1);
7086 QCOMPARE(widget.paintedRegion, QRegion(0, 0, 50, 50));
7090 class PaintOnScreenWidget: public QWidget
7093 PaintOnScreenWidget(QWidget *parent = 0, Qt::WindowFlags f = 0)
7097 #if defined(Q_OS_WIN)
7098 // This is the only way to enable PaintOnScreen on Windows.
7099 QPaintEngine * paintEngine () const {return 0;}
7103 void tst_QWidget::alienWidgets()
7105 if (m_platform != QStringLiteral("xcb") && m_platform != QStringLiteral("windows"))
7106 QSKIP("This test is only for X11/Windows.");
7108 qApp->setAttribute(Qt::AA_DontCreateNativeWidgetSiblings);
7110 parent.resize(200, 200);
7111 QWidget child(&parent);
7112 QWidget grandChild(&child);
7113 QWidget greatGrandChild(&grandChild);
7116 QVERIFY(QTest::qWaitForWindowExposed(&parent));
7118 // Verify that the WA_WState_Created attribute is set
7119 // and the top-level is the only native window.
7120 QVERIFY(parent.testAttribute(Qt::WA_WState_Created));
7121 QVERIFY(parent.internalWinId());
7123 QVERIFY(child.testAttribute(Qt::WA_WState_Created));
7124 QVERIFY(!child.internalWinId());
7126 QVERIFY(grandChild.testAttribute(Qt::WA_WState_Created));
7127 QVERIFY(!grandChild.internalWinId());
7129 QVERIFY(greatGrandChild.testAttribute(Qt::WA_WState_Created));
7130 QVERIFY(!greatGrandChild.internalWinId());
7132 // Enforce native windows all the way up in the parent hierarchy
7133 // if not WA_DontCreateNativeAncestors is set.
7134 grandChild.setAttribute(Qt::WA_DontCreateNativeAncestors);
7135 greatGrandChild.setAttribute(Qt::WA_NativeWindow);
7136 QVERIFY(greatGrandChild.internalWinId());
7137 QVERIFY(grandChild.internalWinId());
7138 QVERIFY(!child.internalWinId());
7141 // Ensure that hide() on an ancestor of a widget with
7142 // Qt::WA_DontCreateNativeAncestors still gets unmapped
7144 window.resize(200, 200);
7145 QWidget widget(&window);
7146 QWidget child(&widget);
7147 child.setAttribute(Qt::WA_NativeWindow);
7148 child.setAttribute(Qt::WA_DontCreateNativeAncestors);
7150 QVERIFY(QTest::qWaitForWindowExposed(&window));
7151 QVERIFY(child.testAttribute(Qt::WA_Mapped));
7153 QTRY_VERIFY(!child.testAttribute(Qt::WA_Mapped));
7156 // Enforce a native window when calling QWidget::winId.
7157 QVERIFY(child.winId());
7158 QVERIFY(child.internalWinId());
7160 // Check that paint on screen widgets (incl. children) are native.
7161 PaintOnScreenWidget paintOnScreen(&parent);
7162 QWidget paintOnScreenChild(&paintOnScreen);
7163 paintOnScreen.show();
7164 QVERIFY(paintOnScreen.testAttribute(Qt::WA_WState_Created));
7165 QVERIFY(!paintOnScreen.testAttribute(Qt::WA_NativeWindow));
7166 QVERIFY(!paintOnScreen.internalWinId());
7167 QVERIFY(!paintOnScreenChild.testAttribute(Qt::WA_NativeWindow));
7168 QVERIFY(!paintOnScreenChild.internalWinId());
7170 paintOnScreen.setAttribute(Qt::WA_PaintOnScreen);
7171 if (m_platform == QStringLiteral("xcb") || m_platform == QStringLiteral("windows"))
7172 QEXPECT_FAIL("", "QTBUG-26424", Continue);
7173 QVERIFY(paintOnScreen.testAttribute(Qt::WA_NativeWindow));
7174 if (m_platform == QStringLiteral("xcb") || m_platform == QStringLiteral("windows"))
7175 QEXPECT_FAIL("", "QTBUG-26424", Continue);
7176 QVERIFY(paintOnScreen.internalWinId());
7177 if (m_platform == QStringLiteral("xcb") || m_platform == QStringLiteral("windows"))
7178 QEXPECT_FAIL("", "QTBUG-26424", Continue);
7179 QVERIFY(paintOnScreenChild.testAttribute(Qt::WA_NativeWindow));
7180 if (m_platform == QStringLiteral("xcb") || m_platform == QStringLiteral("windows"))
7181 QEXPECT_FAIL("", "QTBUG-26424", Continue);
7182 QVERIFY(paintOnScreenChild.internalWinId());
7184 // Check that widgets with the Qt::MSWindowsOwnDC attribute set
7186 QWidget msWindowsOwnDC(&parent, Qt::MSWindowsOwnDC);
7187 msWindowsOwnDC.show();
7188 QVERIFY(msWindowsOwnDC.testAttribute(Qt::WA_WState_Created));
7189 QVERIFY(msWindowsOwnDC.testAttribute(Qt::WA_NativeWindow));
7190 QVERIFY(msWindowsOwnDC.internalWinId());
7192 { // Enforce a native window when calling QWidget::handle() (on X11) or QWidget::getDC() (on Windows).
7193 QWidget widget(&parent);
7195 QVERIFY(widget.testAttribute(Qt::WA_WState_Created));
7196 QVERIFY(!widget.internalWinId());
7199 QVERIFY(widget.internalWinId());
7202 if (m_platform == QStringLiteral("xcb")) {
7203 // Make sure we don't create native windows when setting Qt::WA_X11NetWmWindowType attributes
7204 // on alien widgets (see task 194231).
7206 dummy.resize(200, 200);
7207 QVERIFY(dummy.winId());
7208 QWidget widget(&dummy);
7209 widget.setAttribute(Qt::WA_X11NetWmWindowTypeToolBar);
7210 QVERIFY(!widget.internalWinId());
7213 { // Make sure we create native ancestors when setting Qt::WA_PaintOnScreen before show().
7215 topLevel.resize(200, 200);
7216 QWidget child(&topLevel);
7217 QWidget grandChild(&child);
7218 PaintOnScreenWidget greatGrandChild(&grandChild);
7220 greatGrandChild.setAttribute(Qt::WA_PaintOnScreen);
7221 QVERIFY(!child.internalWinId());
7222 QVERIFY(!grandChild.internalWinId());
7223 QVERIFY(!greatGrandChild.internalWinId());
7226 if (m_platform == QStringLiteral("xcb") || m_platform == QStringLiteral("windows"))
7227 QEXPECT_FAIL("", "QTBUG-26424", Continue);
7228 QVERIFY(child.internalWinId());
7229 if (m_platform == QStringLiteral("xcb") || m_platform == QStringLiteral("windows"))
7230 QEXPECT_FAIL("", "QTBUG-26424", Continue);
7231 QVERIFY(grandChild.internalWinId());
7232 if (m_platform == QStringLiteral("xcb") || m_platform == QStringLiteral("windows"))
7233 QEXPECT_FAIL("", "QTBUG-26424", Continue);
7234 QVERIFY(greatGrandChild.internalWinId());
7237 { // Ensure that widgets reparented into Qt::WA_PaintOnScreen widgets become native.
7239 topLevel.resize(200, 200);
7240 QWidget *widget = new PaintOnScreenWidget(&topLevel);
7241 widget->setAttribute(Qt::WA_PaintOnScreen);
7242 QWidget *child = new QWidget;
7243 QWidget *dummy = new QWidget(child);
7244 QWidget *grandChild = new QWidget(child);
7245 QWidget *dummy2 = new QWidget(grandChild);
7247 child->setParent(widget);
7249 QVERIFY(!topLevel.internalWinId());
7250 QVERIFY(!child->internalWinId());
7251 QVERIFY(!dummy->internalWinId());
7252 QVERIFY(!grandChild->internalWinId());
7253 QVERIFY(!dummy2->internalWinId());
7256 QVERIFY(topLevel.internalWinId());
7257 QVERIFY(widget->testAttribute(Qt::WA_NativeWindow));
7258 QVERIFY(child->internalWinId());
7259 QVERIFY(child->testAttribute(Qt::WA_NativeWindow));
7260 QVERIFY(!child->testAttribute(Qt::WA_PaintOnScreen));
7261 QVERIFY(!dummy->internalWinId());
7262 QVERIFY(!dummy->testAttribute(Qt::WA_NativeWindow));
7263 QVERIFY(!grandChild->internalWinId());
7264 QVERIFY(!grandChild->testAttribute(Qt::WA_NativeWindow));
7265 QVERIFY(!dummy2->internalWinId());
7266 QVERIFY(!dummy2->testAttribute(Qt::WA_NativeWindow));
7269 { // Ensure that ancestors of a Qt::WA_PaintOnScreen widget stay native
7270 // if they are re-created (typically in QWidgetPrivate::setParent_sys) (task 210822).
7272 window.resize(200, 200);
7273 QWidget child(&window);
7276 grandChild.setWindowTitle("This causes the widget to be created");
7278 PaintOnScreenWidget paintOnScreenWidget;
7279 paintOnScreenWidget.setAttribute(Qt::WA_PaintOnScreen);
7280 paintOnScreenWidget.setParent(&grandChild);
7282 grandChild.setParent(&child);
7286 QVERIFY(window.internalWinId());
7287 if (m_platform == QStringLiteral("xcb") || m_platform == QStringLiteral("windows"))
7288 QEXPECT_FAIL("", "QTBUG-26424", Continue);
7289 QVERIFY(child.internalWinId());
7290 if (m_platform == QStringLiteral("xcb") || m_platform == QStringLiteral("windows"))
7291 QEXPECT_FAIL("", "QTBUG-26424", Continue);
7292 QVERIFY(child.testAttribute(Qt::WA_NativeWindow));
7293 if (m_platform == QStringLiteral("xcb") || m_platform == QStringLiteral("windows"))
7294 QEXPECT_FAIL("", "QTBUG-26424", Continue);
7295 QVERIFY(grandChild.internalWinId());
7296 if (m_platform == QStringLiteral("xcb") || m_platform == QStringLiteral("windows"))
7297 QEXPECT_FAIL("", "QTBUG-26424", Continue);
7298 QVERIFY(grandChild.testAttribute(Qt::WA_NativeWindow));
7299 if (m_platform == QStringLiteral("xcb") || m_platform == QStringLiteral("windows"))
7300 QEXPECT_FAIL("", "QTBUG-26424", Continue);
7301 QVERIFY(paintOnScreenWidget.internalWinId());
7302 if (m_platform == QStringLiteral("xcb") || m_platform == QStringLiteral("windows"))
7303 QEXPECT_FAIL("", "QTBUG-26424", Continue);
7304 QVERIFY(paintOnScreenWidget.testAttribute(Qt::WA_NativeWindow));
7307 { // Ensure that all siblings are native unless Qt::AA_DontCreateNativeWidgetSiblings is set.
7308 qApp->setAttribute(Qt::AA_DontCreateNativeWidgetSiblings, false);
7310 QWidget *toolBar = new QWidget(&mainWindow);
7311 QWidget *dockWidget = new QWidget(&mainWindow);
7312 QWidget *centralWidget = new QWidget(&mainWindow);
7314 QWidget *button = new QWidget(centralWidget);
7315 QWidget *mdiArea = new QWidget(centralWidget);
7317 QWidget *horizontalScroll = new QWidget(mdiArea);
7318 QWidget *verticalScroll = new QWidget(mdiArea);
7319 QWidget *viewport = new QWidget(mdiArea);
7321 viewport->setAttribute(Qt::WA_NativeWindow);
7324 // Ensure that the viewport and its siblings are native:
7325 QVERIFY(verticalScroll->testAttribute(Qt::WA_NativeWindow));
7326 QVERIFY(verticalScroll->testAttribute(Qt::WA_NativeWindow));
7327 QVERIFY(horizontalScroll->testAttribute(Qt::WA_NativeWindow));
7329 // Ensure that the mdi area and its siblings are native:
7330 QVERIFY(mdiArea->testAttribute(Qt::WA_NativeWindow));
7331 QVERIFY(button->testAttribute(Qt::WA_NativeWindow));
7333 // Ensure that the central widget and its siblings are native:
7334 QVERIFY(centralWidget->testAttribute(Qt::WA_NativeWindow));
7335 QVERIFY(dockWidget->testAttribute(Qt::WA_NativeWindow));
7336 QVERIFY(toolBar->testAttribute(Qt::WA_NativeWindow));
7340 class ASWidget : public QWidget
7343 ASWidget(QSize sizeHint, QSizePolicy sizePolicy, bool layout, bool hfwLayout, QWidget *parent = 0)
7344 : QWidget(parent), mySizeHint(sizeHint)
7346 setObjectName(QStringLiteral("ASWidget"));
7347 setWindowTitle(objectName());
7348 setSizePolicy(sizePolicy);
7350 QSizePolicy sp = QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
7351 sp.setHeightForWidth(hfwLayout);
7353 QVBoxLayout *vbox = new QVBoxLayout;
7355 vbox->addWidget(new ASWidget(sizeHint + QSize(30, 20), sp, false, false));
7360 QSize sizeHint() const {
7362 return layout()->totalSizeHint();
7365 int heightForWidth(int width) const {
7366 if (sizePolicy().hasHeightForWidth()) {
7376 void tst_QWidget::adjustSize_data()
7378 const int MagicW = 200;
7379 const int MagicH = 100;
7381 QTest::addColumn<QSize>("sizeHint");
7382 QTest::addColumn<int>("hPolicy");
7383 QTest::addColumn<int>("vPolicy");
7384 QTest::addColumn<bool>("hfwSP");
7385 QTest::addColumn<bool>("layout");
7386 QTest::addColumn<bool>("hfwLayout");
7387 QTest::addColumn<bool>("haveParent");
7388 QTest::addColumn<QSize>("expectedSize");
7390 QTest::newRow("1") << QSize(5, 6) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
7391 << false << false << false << false << QSize(5, qMax(6, MagicH));
7392 QTest::newRow("2") << QSize(5, 6) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
7393 << true << false << false << false << QSize(5, qMax(10, MagicH));
7394 QTest::newRow("3") << QSize(5, 6) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
7395 << false << true << false << false << QSize(35, 26);
7396 QTest::newRow("4") << QSize(5, 6) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
7397 << false << true << true << false << QSize(35, 70);
7398 QTest::newRow("5") << QSize(40001, 30001) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
7399 << false << false << false << false << QSize(100000, 100000);
7400 QTest::newRow("6") << QSize(40001, 30001) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
7401 << true << false << false << false << QSize(100000, 100000);
7402 QTest::newRow("7") << QSize(40001, 30001) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
7403 << false << true << false << false << QSize(100000, 100000);
7404 QTest::newRow("8") << QSize(40001, 30001) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
7405 << false << true << true << false << QSize(100000, 100000);
7406 QTest::newRow("9") << QSize(5, 6) << int(QSizePolicy::Expanding) << int(QSizePolicy::Minimum)
7407 << true << false << false << false << QSize(qMax(5, MagicW), 10);
7409 QTest::newRow("1c") << QSize(5, 6) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
7410 << false << false << false << true << QSize(5, 6);
7411 QTest::newRow("2c") << QSize(5, 6) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
7412 << true << false << false << true << QSize(5, 6 /* or 10 would be OK too, since hfw contradicts sizeHint() */);
7413 QTest::newRow("3c") << QSize(5, 6) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
7414 << false << true << false << true << QSize(35, 26);
7415 QTest::newRow("4c") << QSize(5, 6) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
7416 << false << true << true << true << QSize(35, 70);
7417 QTest::newRow("5c") << QSize(40001, 30001) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
7418 << false << false << false << true << QSize(40001, 30001);
7419 QTest::newRow("6c") << QSize(40001, 30001) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
7420 << true << false << false << true << QSize(40001, 30001 /* or 80002 would be OK too, since hfw contradicts sizeHint() */);
7421 QTest::newRow("7c") << QSize(40001, 30001) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
7422 << false << true << false << true << QSize(40001 + 30, 30001 + 20);
7423 QTest::newRow("8c") << QSize(40001, 30001) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
7424 << false << true << true << true << QSize(40001 + 30, 80002 + 60);
7425 QTest::newRow("9c") << QSize(5, 6) << int(QSizePolicy::Expanding) << int(QSizePolicy::Minimum)
7426 << true << false << false << true << QSize(5, 6);
7429 void tst_QWidget::adjustSize()
7431 QFETCH(QSize, sizeHint);
7432 QFETCH(int, hPolicy);
7433 QFETCH(int, vPolicy);
7434 QFETCH(bool, hfwSP);
7435 QFETCH(bool, layout);
7436 QFETCH(bool, hfwLayout);
7437 QFETCH(bool, haveParent);
7438 QFETCH(QSize, expectedSize);
7440 QScopedPointer<QWidget> parent(new QWidget);
7442 QSizePolicy sp = QSizePolicy(QSizePolicy::Policy(hPolicy), QSizePolicy::Policy(vPolicy));
7443 sp.setHeightForWidth(hfwSP);
7445 QWidget *child = new ASWidget(sizeHint, sp, layout, hfwLayout, haveParent ? parent.data() : 0);
7446 child->resize(123, 456);
7447 child->adjustSize();
7448 if (expectedSize == QSize(100000, 100000)) {
7449 QVERIFY(child->size().width() < sizeHint.width());
7450 QVERIFY(child->size().height() < sizeHint.height());
7452 #if defined (Q_OS_WINCE)
7454 const QRect& desktopRect = qApp->desktop()->availableGeometry();
7455 expectedSize.setWidth(qMin(expectedSize.width(), desktopRect.width()));
7456 expectedSize.setHeight(qMin(expectedSize.height(), desktopRect.height()));
7459 QCOMPARE(child->size(), expectedSize);
7465 class TestLayout : public QVBoxLayout
7469 TestLayout(QWidget *w = 0) : QVBoxLayout(w)
7471 invalidated = false;
7482 void tst_QWidget::updateGeometry_data()
7484 QTest::addColumn<QSize>("minSize");
7485 QTest::addColumn<bool>("shouldInvalidate");
7486 QTest::addColumn<QSize>("maxSize");
7487 QTest::addColumn<bool>("shouldInvalidate2");
7488 QTest::addColumn<int>("verticalSizePolicy");
7489 QTest::addColumn<bool>("shouldInvalidate3");
7490 QTest::addColumn<bool>("setVisible");
7491 QTest::addColumn<bool>("shouldInvalidate4");
7493 QTest::newRow("setMinimumSize")
7494 << QSize(100, 100) << true
7496 << int(QSizePolicy::Preferred) << false
7498 QTest::newRow("setMaximumSize")
7500 << QSize(100, 100) << true
7501 << int(QSizePolicy::Preferred) << false
7503 QTest::newRow("setMinimumSize, then maximumSize to a different size")
7504 << QSize(100, 100) << true
7505 << QSize(300, 300) << true
7506 << int(QSizePolicy::Preferred) << false
7508 QTest::newRow("setMinimumSize, then maximumSize to the same size")
7509 << QSize(100, 100) << true
7510 << QSize(100, 100) << true
7511 << int(QSizePolicy::Preferred) << false
7513 QTest::newRow("setMinimumSize, then maximumSize to the same size and then hide it")
7514 << QSize(100, 100) << true
7515 << QSize(100, 100) << true
7516 << int(QSizePolicy::Preferred) << false
7518 QTest::newRow("Change sizePolicy")
7521 << int(QSizePolicy::Minimum) << true
7526 void tst_QWidget::updateGeometry()
7528 QFETCH(QSize, minSize);
7529 QFETCH(bool, shouldInvalidate);
7530 QFETCH(QSize, maxSize);
7531 QFETCH(bool, shouldInvalidate2);
7532 QFETCH(int, verticalSizePolicy);
7533 QFETCH(bool, shouldInvalidate3);
7534 QFETCH(bool, setVisible);
7535 QFETCH(bool, shouldInvalidate4);
7537 parent.resize(200, 200);
7538 TestLayout *lout = new TestLayout();
7539 parent.setLayout(lout);
7540 QWidget *child = new QWidget(&parent);
7541 lout->addWidget(child);
7543 QApplication::processEvents();
7545 lout->invalidated = false;
7546 if (minSize.isValid())
7547 child->setMinimumSize(minSize);
7548 QCOMPARE(lout->invalidated, shouldInvalidate);
7550 lout->invalidated = false;
7551 if (maxSize.isValid())
7552 child->setMaximumSize(maxSize);
7553 QCOMPARE(lout->invalidated, shouldInvalidate2);
7555 lout->invalidated = false;
7556 child->setSizePolicy(QSizePolicy(QSizePolicy::Preferred, (QSizePolicy::Policy)verticalSizePolicy));
7557 if (shouldInvalidate3)
7558 QCOMPARE(lout->invalidated, true);
7560 lout->invalidated = false;
7562 child->setVisible(false);
7563 QCOMPARE(lout->invalidated, shouldInvalidate4);
7566 void tst_QWidget::sendUpdateRequestImmediately()
7568 UpdateWidget updateWidget;
7569 updateWidget.show();
7571 QVERIFY(QTest::qWaitForWindowExposed(&updateWidget));
7573 qApp->processEvents();
7574 updateWidget.reset();
7576 QCOMPARE(updateWidget.numUpdateRequestEvents, 0);
7577 updateWidget.repaint();
7578 QCOMPARE(updateWidget.numUpdateRequestEvents, 1);
7581 void tst_QWidget::doubleRepaint()
7583 #if defined(Q_OS_MAC)
7584 if (!macHasAccessToWindowsServer())
7585 QSKIP("Not having window server access causes the wrong number of repaints to be issues");
7587 UpdateWidget widget;
7588 widget.setFocusPolicy(Qt::StrongFocus);
7589 // Filter out activation change and focus events to avoid update() calls in QWidget.
7590 widget.updateOnActivationChangeAndFocusIn = false;
7593 int expectedRepaints = 1;
7595 QVERIFY(QTest::qWaitForWindowExposed(&widget));
7597 if (m_platform == QStringLiteral("windows"))
7598 QEXPECT_FAIL("", "QTBUG-26424", Continue);
7599 QTRY_COMPARE(widget.numPaintEvents, expectedRepaints);
7600 widget.numPaintEvents = 0;
7602 // Minmize: Should not trigger a repaint.
7603 widget.showMinimized();
7605 QCOMPARE(widget.numPaintEvents, 0);
7606 widget.numPaintEvents = 0;
7608 // Restore: Should not trigger a repaint.
7609 widget.showNormal();
7610 QVERIFY(QTest::qWaitForWindowExposed(&widget));
7612 QCOMPARE(widget.numPaintEvents, 0);
7615 void tst_QWidget::resizeInPaintEvent()
7618 UpdateWidget widget(&window);
7619 window.resize(200, 200);
7621 qApp->setActiveWindow(&window);
7622 QVERIFY(QTest::qWaitForWindowActive(&window));
7623 QTRY_VERIFY(widget.numPaintEvents > 0);
7626 QCOMPARE(widget.numPaintEvents, 0);
7628 widget.resizeInPaintEvent = true;
7629 // This will call resize in the paintEvent, which in turn will call
7630 // invalidateBuffer() and a new update request should be posted.
7632 QCOMPARE(widget.numPaintEvents, 1);
7633 widget.numPaintEvents = 0;
7636 // Make sure the resize triggers another update.
7637 QTRY_COMPARE(widget.numPaintEvents, 1);
7640 void tst_QWidget::opaqueChildren()
7643 widget.resize(200, 200);
7645 QWidget child(&widget);
7646 child.setGeometry(-700, -700, 200, 200);
7648 QWidget grandChild(&child);
7649 grandChild.resize(200, 200);
7651 QWidget greatGrandChild(&grandChild);
7652 greatGrandChild.setGeometry(50, 50, 200, 200);
7653 greatGrandChild.setPalette(Qt::red);
7654 greatGrandChild.setAutoFillBackground(true); // Opaque child widget.
7657 QVERIFY(QTest::qWaitForWindowExposed(&widget));
7660 // Child, grandChild and greatGrandChild are outside the ancestor clip.
7661 QRegion expectedOpaqueRegion(50, 50, 150, 150);
7662 QCOMPARE(qt_widget_private(&grandChild)->getOpaqueChildren(), expectedOpaqueRegion);
7664 // Now they are all inside the ancestor clip.
7665 child.setGeometry(50, 50, 150, 150);
7666 QCOMPARE(qt_widget_private(&grandChild)->getOpaqueChildren(), expectedOpaqueRegion);
7668 // Set mask on greatGrandChild.
7669 const QRegion mask(10, 10, 50, 50);
7670 greatGrandChild.setMask(mask);
7671 expectedOpaqueRegion &= mask.translated(50, 50);
7672 QCOMPARE(qt_widget_private(&grandChild)->getOpaqueChildren(), expectedOpaqueRegion);
7674 // Make greatGrandChild "transparent".
7675 greatGrandChild.setAutoFillBackground(false);
7676 QCOMPARE(qt_widget_private(&grandChild)->getOpaqueChildren(), QRegion());
7680 class MaskSetWidget : public QWidget
7684 MaskSetWidget(QWidget* p =0)
7687 void paintEvent(QPaintEvent* event) {
7690 paintedRegion += event->region();
7691 foreach(QRect r, event->region().rects())
7692 p.fillRect(r, Qt::red);
7695 void resizeEvent(QResizeEvent*) {
7696 setMask(QRegion(QRect(0, 0, width(), 10).normalized()));
7699 QRegion paintedRegion;
7703 setGeometry(QRect(0, 50, 50, 50));
7707 setGeometry(QRect(0, 50, 150, 50));
7712 void tst_QWidget::setMaskInResizeEvent()
7717 w.setWindowFlags(Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint);
7720 MaskSetWidget testWidget(&w);
7721 testWidget.setGeometry(0, 0, 100, 100);
7722 testWidget.setMask(QRegion(QRect(0,0,100,10)));
7725 QVERIFY(QTest::qWaitForWindowExposed(&w));
7727 QTRY_VERIFY(w.numPaintEvents > 0);
7730 testWidget.paintedRegion = QRegion();
7731 QTimer::singleShot(0, &testWidget, SLOT(resizeDown()));
7734 QRegion expectedParentUpdate(0, 0, 100, 10); // Old testWidget area.
7735 expectedParentUpdate += testWidget.geometry(); // New testWidget area.
7736 QCOMPARE(w.paintedRegion, expectedParentUpdate);
7737 QCOMPARE(testWidget.paintedRegion, testWidget.mask());
7739 testWidget.paintedRegion = QRegion();
7740 // Now resize the widget again, but in the oposite direction
7741 QTimer::singleShot(0, &testWidget, SLOT(resizeUp()));
7744 QTRY_COMPARE(testWidget.paintedRegion, testWidget.mask());
7747 class MoveInResizeWidget : public QWidget
7751 MoveInResizeWidget(QWidget* p = 0)
7754 setWindowFlags(Qt::FramelessWindowHint);
7757 void resizeEvent(QResizeEvent*) {
7759 move(QPoint(100,100));
7761 static bool firstTime = true;
7763 QTimer::singleShot(250, this, SLOT(resizeMe()));
7774 void tst_QWidget::moveInResizeEvent()
7776 MoveInResizeWidget testWidget;
7777 testWidget.setGeometry(50, 50, 200, 200);
7779 QVERIFY(QTest::qWaitForWindowExposed(&testWidget));
7782 QRect expectedGeometry(100,100, 100, 100);
7783 QTRY_COMPARE(testWidget.geometry(), expectedGeometry);
7786 void tst_QWidget::immediateRepaintAfterShow()
7788 if (m_platform == QStringLiteral("xcb"))
7789 QSKIP("QTBUG-26424");
7790 if (m_platform != QStringLiteral("xcb") && m_platform != QStringLiteral("windows"))
7791 QSKIP("We don't support immediate repaint right after show on other platforms.");
7793 UpdateWidget widget;
7795 qApp->processEvents();
7796 // On X11 in particular, we are now waiting for a MapNotify event before
7797 // syncing the backing store. However, if someone request a repaint()
7798 // we must repaint immediately regardless of the current state.
7799 widget.numPaintEvents = 0;
7801 QCOMPARE(widget.numPaintEvents, 1);
7804 void tst_QWidget::immediateRepaintAfterInvalidateBuffer()
7806 if (m_platform != QStringLiteral("xcb") && m_platform != QStringLiteral("windows"))
7807 QSKIP("We don't support immediate repaint right after show on other platforms.");
7809 QScopedPointer<UpdateWidget> widget(new UpdateWidget);
7811 QVERIFY(QTest::qWaitForWindowExposed(widget.data()));
7814 widget->numPaintEvents = 0;
7816 // Marks the area covered by the widget as dirty in the backing store and
7817 // posts an UpdateRequest event.
7818 qt_widget_private(widget.data())->invalidateBuffer(widget->rect());
7819 QCOMPARE(widget->numPaintEvents, 0);
7821 // The entire widget is already dirty, but this time we want to update immediately
7822 // by calling repaint(), and thus we have to repaint the widget and not wait for
7823 // the UpdateRequest to be sent when we get back to the event loop.
7825 QCOMPARE(widget->numPaintEvents, 1);
7828 void tst_QWidget::effectiveWinId()
7831 QWidget child(&parent);
7834 QVERIFY(!parent.effectiveWinId());
7835 QVERIFY(!child.effectiveWinId());
7839 QVERIFY(parent.effectiveWinId());
7840 QVERIFY(child.effectiveWinId());
7843 void tst_QWidget::effectiveWinId2()
7847 class MyWidget : public QWidget {
7848 bool event(QEvent *e)
7850 if (e->type() == QEvent::WinIdChange) {
7855 return QWidget::event(e);
7860 child.setParent(&parent);
7864 child.setParent(&parent);
7867 class CustomWidget : public QWidget
7870 mutable int metricCallCount;
7872 CustomWidget(QWidget *parent = 0) : QWidget(parent), metricCallCount(0) {}
7874 virtual int metric(PaintDeviceMetric metric) const {
7876 return QWidget::metric(metric);
7880 void tst_QWidget::customDpi()
7882 QScopedPointer<QWidget> topLevel(new QWidget);
7883 CustomWidget *custom = new CustomWidget(topLevel.data());
7884 QWidget *child = new QWidget(custom);
7886 custom->metricCallCount = 0;
7887 topLevel->logicalDpiX();
7888 QCOMPARE(custom->metricCallCount, 0);
7889 custom->logicalDpiX();
7890 QCOMPARE(custom->metricCallCount, 1);
7891 child->logicalDpiX();
7892 QCOMPARE(custom->metricCallCount, 2);
7895 void tst_QWidget::customDpiProperty()
7897 QScopedPointer<QWidget> topLevel(new QWidget);
7898 QWidget *middle = new CustomWidget(topLevel.data());
7899 QWidget *child = new QWidget(middle);
7901 const int initialDpiX = topLevel->logicalDpiX();
7902 const int initialDpiY = topLevel->logicalDpiY();
7904 middle->setProperty("_q_customDpiX", 300);
7905 middle->setProperty("_q_customDpiY", 400);
7907 QCOMPARE(topLevel->logicalDpiX(), initialDpiX);
7908 QCOMPARE(topLevel->logicalDpiY(), initialDpiY);
7910 QCOMPARE(middle->logicalDpiX(), 300);
7911 QCOMPARE(middle->logicalDpiY(), 400);
7913 QCOMPARE(child->logicalDpiX(), 300);
7914 QCOMPARE(child->logicalDpiY(), 400);
7916 middle->setProperty("_q_customDpiX", QVariant());
7917 middle->setProperty("_q_customDpiY", QVariant());
7919 QCOMPARE(topLevel->logicalDpiX(), initialDpiX);
7920 QCOMPARE(topLevel->logicalDpiY(), initialDpiY);
7922 QCOMPARE(middle->logicalDpiX(), initialDpiX);
7923 QCOMPARE(middle->logicalDpiY(), initialDpiY);
7925 QCOMPARE(child->logicalDpiX(), initialDpiX);
7926 QCOMPARE(child->logicalDpiY(), initialDpiY);
7929 void tst_QWidget::quitOnCloseAttribute()
7932 QCOMPARE(w.testAttribute(Qt::WA_QuitOnClose), true);
7933 w.setAttribute(Qt::WA_QuitOnClose, false);
7934 QCOMPARE(w.testAttribute(Qt::WA_QuitOnClose), false);
7936 w.setAttribute(Qt::WA_QuitOnClose);
7937 w.setWindowFlags(Qt::Tool);
7938 QCOMPARE(w.testAttribute(Qt::WA_QuitOnClose), false);
7940 w.setAttribute(Qt::WA_QuitOnClose);
7941 w.setWindowFlags(Qt::Popup);
7942 QCOMPARE(w.testAttribute(Qt::WA_QuitOnClose), false);
7944 w.setAttribute(Qt::WA_QuitOnClose);
7945 w.setWindowFlags(Qt::ToolTip);
7946 QCOMPARE(w.testAttribute(Qt::WA_QuitOnClose), false);
7948 w.setAttribute(Qt::WA_QuitOnClose);
7949 w.setWindowFlags(Qt::SplashScreen);
7950 QCOMPARE(w.testAttribute(Qt::WA_QuitOnClose), false);
7952 w.setAttribute(Qt::WA_QuitOnClose);
7953 w.setWindowFlags(Qt::SubWindow);
7954 QCOMPARE(w.testAttribute(Qt::WA_QuitOnClose), false);
7956 w.setAttribute(Qt::WA_QuitOnClose);
7957 w.setWindowFlags(Qt::Dialog);
7958 QCOMPARE(w.testAttribute(Qt::WA_QuitOnClose), true);
7960 QCOMPARE(w.testAttribute(Qt::WA_QuitOnClose), true);
7961 w.setWindowFlags(Qt::Tool);
7962 QCOMPARE(w.testAttribute(Qt::WA_QuitOnClose), false);
7965 void tst_QWidget::moveRect()
7968 widget.resize(200, 200);
7969 widget.setUpdatesEnabled(false);
7970 QWidget child(&widget);
7971 child.setUpdatesEnabled(false);
7972 child.setAttribute(Qt::WA_OpaquePaintEvent);
7975 child.move(10, 10); // Don't crash.
7979 class GDIWidget : public QDialog
7984 setAttribute(Qt::WA_PaintOnScreen);
7985 timer.setSingleShot(true);
7986 timer.setInterval(0);
7988 QPaintEngine *paintEngine() const { return 0; }
7990 void paintEvent(QPaintEvent *) {
7991 QPlatformNativeInterface *ni = QGuiApplication::platformNativeInterface();
7992 const HDC hdc = (HDC)ni->nativeResourceForWindow(QByteArrayLiteral("getDC"), windowHandle());
7994 const HBRUSH brush = CreateSolidBrush(RGB(255, 0, 0));
7995 SelectObject(hdc, brush);
7996 Rectangle(hdc, 0, 0, 10, 10);
7997 DeleteObject(brush);
7998 ni->nativeResourceForWindow(QByteArrayLiteral("releaseDC"), windowHandle());
8000 qWarning("%s: Unable to obtain native DC.", Q_FUNC_INFO);
8002 if (!timer.isActive()) {
8003 connect(&timer, &QTimer::timeout, this,
8004 hdc ? &GDIWidget::slotTimer : &QDialog::reject);
8009 QSize sizeHint() const {
8010 return QSize(400, 300);
8015 QScreen *screen = windowHandle()->screen();
8016 const QImage im = screen->grabWindow(internalWinId(), 0, 0, -1, -1).toImage();
8017 color = im.pixel(1, 1);
8026 void tst_QWidget::gdiPainting()
8031 QCOMPARE(w.color, QColor(255, 0, 0));
8035 void tst_QWidget::paintOnScreenPossible()
8038 w1.setAttribute(Qt::WA_PaintOnScreen);
8039 QVERIFY(!w1.testAttribute(Qt::WA_PaintOnScreen));
8042 w2.setAttribute(Qt::WA_PaintOnScreen);
8043 QVERIFY(w2.testAttribute(Qt::WA_PaintOnScreen));
8047 void tst_QWidget::reparentStaticWidget()
8051 QWidget *child = new QWidget(&window1);
8052 child->setPalette(Qt::red);
8053 child->setAutoFillBackground(true);
8054 child->setAttribute(Qt::WA_StaticContents);
8055 child->resize(160, 160);
8057 QWidget *grandChild = new QWidget(child);
8058 grandChild->setPalette(Qt::blue);
8059 grandChild->setAutoFillBackground(true);
8060 grandChild->resize(50, 50);
8061 grandChild->setAttribute(Qt::WA_StaticContents);
8063 QVERIFY(QTest::qWaitForWindowExposed(&window1));
8067 QVERIFY(QTest::qWaitForWindowExposed(&window2));
8070 // Reparent into another top-level.
8071 child->setParent(&window2);
8074 // Please don't crash.
8075 window1.resize(window1.size() + QSize(2, 2));
8078 // Make sure we move all static children even though
8079 // the reparented widget itself is non-static.
8080 child->setAttribute(Qt::WA_StaticContents, false);
8081 child->setParent(&window1);
8084 // Please don't crash.
8085 window2.resize(window2.size() + QSize(2, 2));
8088 child->setParent(0);
8092 // Please don't crash.
8093 child->resize(child->size() + QSize(2, 2));
8094 window2.resize(window2.size() + QSize(2, 2));
8097 QWidget *siblingOfGrandChild = new QWidget(child);
8098 siblingOfGrandChild->show();
8101 // Nothing should happen when reparenting within the same top-level.
8102 grandChild->setParent(siblingOfGrandChild);
8106 QWidget paintOnScreen;
8107 paintOnScreen.setAttribute(Qt::WA_PaintOnScreen);
8108 paintOnScreen.show();
8109 QVERIFY(QTest::qWaitForWindowExposed(&paintOnScreen));
8112 child->setParent(&paintOnScreen);
8116 // Please don't crash.
8117 paintOnScreen.resize(paintOnScreen.size() + QSize(2, 2));
8122 void tst_QWidget::QTBUG6883_reparentStaticWidget2()
8125 QDockWidget *one = new QDockWidget("one", &mw);
8126 mw.addDockWidget(Qt::LeftDockWidgetArea, one , Qt::Vertical);
8128 QWidget *child = new QWidget();
8129 child->setPalette(Qt::red);
8130 child->setAutoFillBackground(true);
8131 child->setAttribute(Qt::WA_StaticContents);
8132 child->resize(100, 100);
8133 one->setWidget(child);
8135 QToolBar *mainTools = mw.addToolBar("Main Tools");
8136 mainTools->addWidget(new QLineEdit);
8139 QVERIFY(QTest::qWaitForWindowExposed(&mw));
8141 one->setFloating(true);
8146 class ColorRedWidget : public QWidget
8149 ColorRedWidget(QWidget *parent = 0)
8150 : QWidget(parent, Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint | Qt::ToolTip)
8154 void paintEvent(QPaintEvent *) {
8156 p.fillRect(rect(),Qt::red);
8160 void tst_QWidget::translucentWidget()
8164 ColorRedWidget label;
8165 label.setFixedSize(16,16);
8166 label.setAttribute(Qt::WA_TranslucentBackground);
8167 const QPoint labelPos = qApp->desktop()->availableGeometry().topLeft();
8168 label.move(labelPos);
8170 QVERIFY(QTest::qWaitForWindowExposed(&label));
8173 QPixmap widgetSnapshot;
8176 QWidget *desktopWidget = QApplication::desktop()->screen(0);
8177 if (QSysInfo::windowsVersion() >= QSysInfo::WV_VISTA)
8178 widgetSnapshot = qApp->primaryScreen()->grabWindow(desktopWidget->winId(), labelPos.x(), labelPos.y(), label.width(), label.height());
8181 widgetSnapshot = label.grab(QRect(QPoint(0, 0), label.size()));
8182 QImage actual = widgetSnapshot.toImage().convertToFormat(QImage::Format_RGB32);
8183 QImage expected = pm.toImage().convertToFormat(QImage::Format_RGB32);
8184 QCOMPARE(actual.size(),expected.size());
8185 QCOMPARE(actual,expected);
8188 class MaskResizeTestWidget : public QWidget
8192 MaskResizeTestWidget(QWidget* p =0)
8194 setMask(QRegion(QRect(0, 0, 100, 100).normalized()));
8197 void paintEvent(QPaintEvent* event) {
8200 paintedRegion += event->region();
8201 foreach(QRect r, event->region().rects())
8202 p.fillRect(r, Qt::red);
8205 QRegion paintedRegion;
8208 void enlargeMask() {
8209 QRegion newMask(QRect(0, 0, 150, 150).normalized());
8214 QRegion newMask(QRect(0, 0, 50, 50).normalized());
8220 void tst_QWidget::setClearAndResizeMask()
8222 UpdateWidget topLevel;
8223 topLevel.resize(160, 160);
8225 qApp->setActiveWindow(&topLevel);
8226 QVERIFY(QTest::qWaitForWindowActive(&topLevel));
8227 QTRY_VERIFY(topLevel.numPaintEvents > 0);
8230 // Mask top-level widget
8231 const QRegion topLevelMask(0, 0, 100, 100, QRegion::Ellipse);
8232 topLevel.setMask(topLevelMask);
8233 QCOMPARE(topLevel.mask(), topLevelMask);
8234 // Ensure that the top-level doesn't get any update.
8235 // We don't control what's happening on platforms other than X11, Windows
8236 if (m_platform == QStringLiteral("xcb") || m_platform == QStringLiteral("windows"))
8237 QCOMPARE(topLevel.numPaintEvents, 0);
8241 // Clear top-level mask
8242 topLevel.clearMask();
8243 QCOMPARE(topLevel.mask(), QRegion());
8245 QRegion outsideOldMask(topLevel.rect());
8246 outsideOldMask -= topLevelMask;
8247 // Ensure that the top-level gets an update for the area outside the old mask.
8248 // We don't control what's happening on platforms other than X11, Windows
8249 if (m_platform == QStringLiteral("xcb") || m_platform == QStringLiteral("windows")) {
8250 QTRY_VERIFY(topLevel.numPaintEvents > 0);
8251 QTRY_COMPARE(topLevel.paintedRegion, outsideOldMask);
8254 UpdateWidget child(&topLevel);
8255 child.setAutoFillBackground(true); // NB! Opaque child.
8256 child.setPalette(Qt::red);
8257 child.resize(100, 100);
8264 // Mask child widget with a mask that is smaller than the rect
8265 const QRegion childMask(0, 0, 50, 50);
8266 child.setMask(childMask);
8267 QTRY_COMPARE(child.mask(), childMask);
8269 // and ensure that the child widget doesn't get any update.
8271 // Mac always issues a full update when calling setMask, and we cannot force it to not do so.
8272 if (child.internalWinId())
8273 QCOMPARE(child.numPaintEvents, 1);
8276 QCOMPARE(child.numPaintEvents, 0);
8277 // and the parent widget gets an update for the newly exposed area.
8278 QTRY_COMPARE(topLevel.numPaintEvents, 1);
8279 QRegion expectedParentExpose(child.rect());
8280 expectedParentExpose -= childMask;
8281 QCOMPARE(topLevel.paintedRegion, expectedParentExpose);
8286 // Clear child widget mask
8288 QTRY_COMPARE(child.mask(), QRegion());
8290 // and ensure that that the child widget gets an update for the area outside the old mask.
8291 QTRY_COMPARE(child.numPaintEvents, 1);
8292 outsideOldMask = child.rect();
8294 // Mac always issues a full update when calling setMask, and we cannot force it to not do so.
8295 if (!child.internalWinId())
8297 outsideOldMask -= childMask;
8298 QCOMPARE(child.paintedRegion, outsideOldMask);
8299 // and the parent widget doesn't get any update.
8300 QCOMPARE(topLevel.numPaintEvents, 0);
8305 // Mask child widget with a mask that is bigger than the rect
8306 child.setMask(QRegion(0, 0, 1000, 1000));
8309 // Mac always issues a full update when calling setMask, and we cannot force it to not do so.
8310 if (child.internalWinId())
8311 QTRY_COMPARE(child.numPaintEvents, 1);
8314 // and ensure that we don't get any updates at all.
8315 QTRY_COMPARE(child.numPaintEvents, 0);
8316 QCOMPARE(topLevel.numPaintEvents, 0);
8318 // ...and the same applies when clearing the mask.
8322 // Mac always issues a full update when calling setMask, and we cannot force it to not do so.
8323 if (child.internalWinId())
8324 QTRY_VERIFY(child.numPaintEvents > 0);
8327 QCOMPARE(child.numPaintEvents, 0);
8328 QCOMPARE(topLevel.numPaintEvents, 0);
8330 QWidget resizeParent;
8331 MaskResizeTestWidget resizeChild(&resizeParent);
8333 resizeParent.resize(300,300);
8334 resizeParent.raise();
8335 resizeParent.setWindowFlags(Qt::WindowStaysOnTopHint);
8336 resizeChild.setGeometry(50,50,200,200);
8337 QPalette pal = resizeParent.palette();
8338 pal.setColor(QPalette::Window, QColor(Qt::white));
8339 resizeParent.setPalette(pal);
8341 resizeParent.show();
8342 QVERIFY(QTest::qWaitForWindowExposed(&resizeParent));
8343 // Disable the size grip on the Mac; otherwise it'll be included when grabbing the window.
8344 resizeParent.setFixedSize(resizeParent.size());
8347 resizeChild.paintedRegion = QRegion();
8349 QTimer::singleShot(100, &resizeChild, SLOT(shrinkMask()));
8352 // Mac always issues a full update when calling setMask, and we cannot force it to not do so.
8353 if (child.internalWinId())
8354 QTRY_COMPARE(resizeChild.paintedRegion, resizeChild.mask());
8357 QTRY_COMPARE(resizeChild.paintedRegion, QRegion());
8359 resizeChild.paintedRegion = QRegion();
8360 const QRegion oldMask = resizeChild.mask();
8361 QTimer::singleShot(0, &resizeChild, SLOT(enlargeMask()));
8364 // Mac always issues a full update when calling setMask, and we cannot force it to not do so.
8365 if (child.internalWinId())
8366 QTRY_COMPARE(resizeChild.paintedRegion, resizeChild.mask());
8369 QTRY_COMPARE(resizeChild.paintedRegion, resizeChild.mask() - oldMask);
8372 void tst_QWidget::maskedUpdate()
8374 UpdateWidget topLevel;
8375 topLevel.resize(200, 200);
8376 const QRegion topLevelMask(50, 50, 70, 70);
8377 topLevel.setMask(topLevelMask);
8379 UpdateWidget child(&topLevel);
8380 child.setGeometry(20, 20, 180, 180);
8381 const QRegion childMask(60, 60, 30, 30);
8382 child.setMask(childMask);
8384 UpdateWidget grandChild(&child);
8385 grandChild.setGeometry(50, 50, 100, 100);
8386 const QRegion grandChildMask(20, 20, 10, 10);
8387 grandChild.setMask(grandChildMask);
8390 QVERIFY(QTest::qWaitForWindowExposed(&topLevel));
8391 QTRY_VERIFY(topLevel.numPaintEvents > 0);
8394 #define RESET_WIDGETS \
8399 #define CLEAR_MASK(widget) \
8400 widget.clearMask(); \
8401 QTest::qWait(100); \
8404 // All widgets are transparent at this point, so any call to update() will result
8405 // in composition, i.e. the update propagates to ancestors and children.
8412 QTRY_COMPARE(topLevel.paintedRegion, topLevelMask);
8413 QTRY_COMPARE(child.paintedRegion, childMask);
8414 QTRY_COMPARE(grandChild.paintedRegion, grandChildMask);
8421 QTRY_COMPARE(topLevel.paintedRegion, childMask.translated(child.pos()));
8422 QTRY_COMPARE(child.paintedRegion, childMask);
8423 QTRY_COMPARE(grandChild.paintedRegion, grandChildMask);
8425 // GrandChild update.
8427 grandChild.update();
8430 QTRY_COMPARE(topLevel.paintedRegion, grandChildMask.translated(grandChild.mapTo(&topLevel, QPoint())));
8431 QTRY_COMPARE(child.paintedRegion, grandChildMask.translated(grandChild.pos()));
8432 QTRY_COMPARE(grandChild.paintedRegion, grandChildMask);
8434 topLevel.setAttribute(Qt::WA_OpaquePaintEvent);
8435 child.setAttribute(Qt::WA_OpaquePaintEvent);
8436 grandChild.setAttribute(Qt::WA_OpaquePaintEvent);
8438 // All widgets are now opaque, which means no composition, i.e.
8439 // the update does not propate to ancestors and children.
8446 QRegion expectedTopLevelUpdate = topLevelMask;
8447 expectedTopLevelUpdate -= childMask.translated(child.pos()); // Subtract opaque children.
8448 QTRY_COMPARE(topLevel.paintedRegion, expectedTopLevelUpdate);
8449 QTRY_COMPARE(child.paintedRegion, QRegion());
8450 QTRY_COMPARE(grandChild.paintedRegion, QRegion());
8457 QTRY_COMPARE(topLevel.paintedRegion, QRegion());
8458 QRegion expectedChildUpdate = childMask;
8459 expectedChildUpdate -= grandChildMask.translated(grandChild.pos()); // Subtract oapque children.
8460 QTRY_COMPARE(child.paintedRegion, expectedChildUpdate);
8461 QTRY_COMPARE(grandChild.paintedRegion, QRegion());
8463 // GrandChild update.
8465 grandChild.update();
8468 QTRY_COMPARE(topLevel.paintedRegion, QRegion());
8469 QTRY_COMPARE(child.paintedRegion, QRegion());
8470 QTRY_COMPARE(grandChild.paintedRegion, grandChildMask);
8472 // GrandChild update.
8473 CLEAR_MASK(grandChild);
8474 grandChild.update();
8477 QTRY_COMPARE(topLevel.paintedRegion, QRegion());
8478 QTRY_COMPARE(child.paintedRegion, QRegion());
8479 QRegion expectedGrandChildUpdate = grandChild.rect();
8480 // Clip with parent's mask.
8481 expectedGrandChildUpdate &= childMask.translated(-grandChild.pos());
8482 QCOMPARE(grandChild.paintedRegion, expectedGrandChildUpdate);
8484 // GrandChild update.
8486 grandChild.update();
8489 QTRY_COMPARE(topLevel.paintedRegion, QRegion());
8490 QTRY_COMPARE(child.paintedRegion, QRegion());
8491 expectedGrandChildUpdate = grandChild.rect();
8492 // Clip with parent's mask.
8493 expectedGrandChildUpdate &= topLevelMask.translated(-grandChild.mapTo(&topLevel, QPoint()));
8494 QTRY_COMPARE(grandChild.paintedRegion, expectedGrandChildUpdate);
8501 QTRY_COMPARE(topLevel.paintedRegion, QRegion());
8502 expectedChildUpdate = child.rect();
8503 // Clip with parent's mask.
8504 expectedChildUpdate &= topLevelMask.translated(-child.pos());
8505 expectedChildUpdate -= grandChild.geometry(); // Subtract opaque children.
8506 QTRY_COMPARE(child.paintedRegion, expectedChildUpdate);
8507 QTRY_COMPARE(grandChild.paintedRegion, QRegion());
8509 // GrandChild update.
8510 CLEAR_MASK(topLevel);
8511 grandChild.update();
8514 QTRY_COMPARE(topLevel.paintedRegion, QRegion());
8515 QTRY_COMPARE(child.paintedRegion, QRegion());
8516 QTRY_COMPARE(grandChild.paintedRegion, QRegion(grandChild.rect())); // Full update.
8519 // Windows Mobile has no proper cursor support, so skip this test on that platform.
8520 #if !defined(Q_OS_WINCE_WM)
8521 void tst_QWidget::syntheticEnterLeave()
8523 class MyWidget : public QWidget
8526 MyWidget(QWidget *parent = 0) : QWidget(parent), numEnterEvents(0), numLeaveEvents(0) {}
8527 void enterEvent(QEvent *) { ++numEnterEvents; }
8528 void leaveEvent(QEvent *) { ++numLeaveEvents; }
8533 QCursor::setPos(QPoint(0,0));
8536 window.setWindowFlags(Qt::WindowStaysOnTopHint);
8537 window.resize(200, 200);
8539 MyWidget *child1 = new MyWidget(&window);
8540 child1->setPalette(Qt::blue);
8541 child1->setAutoFillBackground(true);
8542 child1->resize(200, 200);
8543 child1->setCursor(Qt::OpenHandCursor);
8545 MyWidget *child2 = new MyWidget(&window);
8546 child2->resize(200, 200);
8548 MyWidget *grandChild = new MyWidget(child2);
8549 grandChild->setPalette(Qt::red);
8550 grandChild->setAutoFillBackground(true);
8551 grandChild->resize(200, 200);
8552 grandChild->setCursor(Qt::WaitCursor);
8557 QVERIFY(QTest::qWaitForWindowExposed(&window));
8560 #define RESET_EVENT_COUNTS \
8561 window.numEnterEvents = 0; \
8562 window.numLeaveEvents = 0; \
8563 child1->numEnterEvents = 0; \
8564 child1->numLeaveEvents = 0; \
8565 child2->numEnterEvents = 0; \
8566 child2->numLeaveEvents = 0; \
8567 grandChild->numEnterEvents = 0; \
8568 grandChild->numLeaveEvents = 0;
8570 // Position the cursor in the middle of the window.
8571 const QPoint globalPos = window.mapToGlobal(QPoint(100, 100));
8572 QCursor::setPos(globalPos); // Enter child2 and grandChild.
8575 QCOMPARE(window.numLeaveEvents, 0);
8576 QCOMPARE(child2->numLeaveEvents, 0);
8577 QCOMPARE(grandChild->numLeaveEvents, 0);
8578 QCOMPARE(child1->numLeaveEvents, 0);
8580 // This event arrives asynchronously
8581 QTRY_COMPARE(window.numEnterEvents, 1);
8582 QCOMPARE(child2->numEnterEvents, 1);
8583 QCOMPARE(grandChild->numEnterEvents, 1);
8584 QCOMPARE(child1->numEnterEvents, 0);
8587 child2->hide(); // Leave child2 and grandChild, enter child1.
8589 QCOMPARE(window.numLeaveEvents, 0);
8590 QCOMPARE(child2->numLeaveEvents, 1);
8591 QCOMPARE(grandChild->numLeaveEvents, 1);
8592 QCOMPARE(child1->numLeaveEvents, 0);
8594 QCOMPARE(window.numEnterEvents, 0);
8595 QCOMPARE(child2->numEnterEvents, 0);
8596 QCOMPARE(grandChild->numEnterEvents, 0);
8597 QCOMPARE(child1->numEnterEvents, 1);
8600 child2->show(); // Leave child1, enter child2 and grandChild.
8602 QCOMPARE(window.numLeaveEvents, 0);
8603 QCOMPARE(child2->numLeaveEvents, 0);
8604 QCOMPARE(grandChild->numLeaveEvents, 0);
8605 QCOMPARE(child1->numLeaveEvents, 1);
8607 QCOMPARE(window.numEnterEvents, 0);
8608 QCOMPARE(child2->numEnterEvents, 1);
8609 QCOMPARE(grandChild->numEnterEvents, 1);
8610 QCOMPARE(child1->numEnterEvents, 0);
8613 delete child2; // Enter child1 (and do not send leave events to child2 and grandChild).
8615 QCOMPARE(window.numLeaveEvents, 0);
8616 QCOMPARE(child1->numLeaveEvents, 0);
8618 QCOMPARE(window.numEnterEvents, 0);
8619 QCOMPARE(child1->numEnterEvents, 1);
8623 // Windows Mobile has no proper cursor support, so skip this test on that platform.
8624 #if !defined(Q_OS_WINCE_WM)
8625 void tst_QWidget::taskQTBUG_4055_sendSyntheticEnterLeave()
8627 if (m_platform == QStringLiteral("windows") || m_platform == QStringLiteral("xcb"))
8628 QSKIP("QTBUG-26424");
8629 class SELParent : public QWidget
8632 SELParent(QWidget *parent = 0): QWidget(parent) { }
8634 void mousePressEvent(QMouseEvent *) { child->show(); }
8638 class SELChild : public QWidget
8641 SELChild(QWidget *parent = 0) : QWidget(parent), numEnterEvents(0), numMouseMoveEvents(0) {}
8642 void enterEvent(QEvent *) { ++numEnterEvents; }
8643 void mouseMoveEvent(QMouseEvent *event)
8645 QCOMPARE(event->button(), Qt::NoButton);
8646 QCOMPARE(event->buttons(), Qt::MouseButtons(Qt::NoButton));
8647 ++numMouseMoveEvents;
8649 void reset() { numEnterEvents = numMouseMoveEvents = 0; }
8650 int numEnterEvents, numMouseMoveEvents;
8653 QCursor::setPos(QPoint(0,0));
8656 parent.resize(200, 200);
8657 SELChild child(&parent);
8658 child.resize(200, 200);
8660 QVERIFY(QTest::qWaitForWindowExposed(&parent));
8663 QCursor::setPos(child.mapToGlobal(QPoint(100, 100)));
8664 // Make sure the cursor has entered the child.
8665 QTRY_VERIFY(child.numEnterEvents > 0);
8671 // Make sure the child gets enter event and no mouse move event.
8672 QTRY_COMPARE(child.numEnterEvents, 1);
8673 QCOMPARE(child.numMouseMoveEvents, 0);
8677 child.setMouseTracking(true);
8680 // Make sure the child gets enter event and mouse move event.
8681 // Note that we verify event->button() and event->buttons()
8682 // in SELChild::mouseMoveEvent().
8683 QTRY_COMPARE(child.numEnterEvents, 1);
8684 QCOMPARE(child.numMouseMoveEvents, 1);
8686 // Sending synthetic enter/leave trough the parent's mousePressEvent handler.
8687 parent.child = &child;
8691 QTest::mouseClick(&parent, Qt::LeftButton);
8693 // Make sure the child gets enter event and one mouse move event.
8694 QTRY_COMPARE(child.numEnterEvents, 1);
8695 QCOMPARE(child.numMouseMoveEvents, 1);
8699 child.setMouseTracking(false);
8700 QTest::mouseClick(&parent, Qt::LeftButton);
8702 // Make sure the child gets enter event and no mouse move event.
8703 QTRY_COMPARE(child.numEnterEvents, 1);
8704 QCOMPARE(child.numMouseMoveEvents, 0);
8708 void tst_QWidget::windowFlags()
8711 w.setWindowFlags(w.windowFlags() | Qt::FramelessWindowHint);
8712 QVERIFY(w.windowFlags() & Qt::FramelessWindowHint);
8715 void tst_QWidget::initialPosForDontShowOnScreenWidgets()
8717 { // Check default position.
8718 const QPoint expectedPos(0, 0);
8720 widget.setAttribute(Qt::WA_DontShowOnScreen);
8721 widget.winId(); // Make sure create_sys is called.
8722 QCOMPARE(widget.pos(), expectedPos);
8723 QCOMPARE(widget.geometry().topLeft(), expectedPos);
8726 { // Explicitly move to a position.
8727 const QPoint expectedPos(100, 100);
8729 widget.setAttribute(Qt::WA_DontShowOnScreen);
8730 widget.move(expectedPos);
8731 widget.winId(); // Make sure create_sys is called.
8732 QCOMPARE(widget.pos(), expectedPos);
8733 QCOMPARE(widget.geometry().topLeft(), expectedPos);
8737 class MyEvilObject : public QObject
8741 MyEvilObject(QWidget *widgetToCrash) : QObject(), widget(widgetToCrash)
8743 connect(widget, SIGNAL(destroyed(QObject *)), this, SLOT(beEvil(QObject *)));
8749 void beEvil(QObject *) { widget->update(0, 0, 150, 150); }
8752 void tst_QWidget::updateOnDestroyedSignal()
8756 QWidget *child = new QWidget(&widget);
8757 child->resize(200, 200);
8758 child->setAutoFillBackground(true);
8759 child->setPalette(Qt::red);
8762 QVERIFY(QTest::qWaitForWindowExposed(&widget));
8765 // Please do not crash.
8766 MyEvilObject evil(child);
8770 void tst_QWidget::toplevelLineEditFocus()
8776 QVERIFY(QTest::qWaitForWindowExposed(&w));
8779 QTRY_COMPARE(QApplication::activeWindow(), (QWidget*)&w);
8780 QTRY_COMPARE(QApplication::focusWidget(), (QWidget*)&w);
8783 void tst_QWidget::focusWidget_task254563()
8785 //having different visibility for widget is important
8788 QWidget container(&top);
8789 QWidget *widget = new QWidget(&container);
8792 widget->setFocus(); //set focus (will set the focus widget up to the toplevel to be 'widget')
8793 container.setFocus();
8794 delete widget; // will call clearFocus but that doesn't help
8795 QVERIFY(top.focusWidget() != widget); //dangling pointer
8798 // This test case relies on developer build (AUTOTEST_EXPORT).
8799 #ifdef QT_BUILD_INTERNAL
8800 void tst_QWidget::destroyBackingStore()
8806 QVERIFY(QTest::qWaitForWindowExposed(&w));
8807 QApplication::processEvents();
8808 QTRY_VERIFY(w.numPaintEvents > 0);
8811 qt_widget_private(&w)->topData()->backingStoreTracker.create(&w);
8814 QApplication::processEvents();
8816 QCOMPARE(w.numPaintEvents, 1);
8818 // Check one more time, because the second time around does more caching.
8820 QApplication::processEvents();
8821 QCOMPARE(w.numPaintEvents, 2);
8823 #endif // QT_BUILD_INTERNAL
8826 QWidgetBackingStore* backingStore(QWidget &widget)
8828 QWidgetBackingStore *backingStore = 0;
8829 #ifdef QT_BUILD_INTERNAL
8830 if (QTLWExtra *topExtra = qt_widget_private(&widget)->maybeTopData())
8831 backingStore = topExtra->backingStoreTracker.data();
8833 return backingStore;
8836 // Tables of 5000 elements do not make sense on Windows Mobile.
8837 #ifndef Q_OS_WINCE_WM
8838 void tst_QWidget::rectOutsideCoordinatesLimit_task144779()
8840 QApplication::setOverrideCursor(Qt::BlankCursor); //keep the cursor out of screen grabs
8841 QWidget main(0,Qt::FramelessWindowHint); //don't get confused by the size of the window frame
8843 palette.setColor(QPalette::Window, Qt::red);
8844 main.setPalette(palette);
8846 QDesktopWidget desktop;
8847 QRect desktopDimensions = desktop.availableGeometry(&main);
8848 QSize mainSize(400, 400);
8849 mainSize = mainSize.boundedTo(desktopDimensions.size());
8850 main.resize(mainSize);
8852 QWidget *offsetWidget = new QWidget(&main);
8853 offsetWidget->setGeometry(0, -(15000 - mainSize.height()), mainSize.width(), 15000);
8855 // big widget is too big for the coordinates, it must be limited by wrect
8856 // if wrect is not at the right position because of offsetWidget, bigwidget
8857 // is not painted correctly
8858 QWidget *bigWidget = new QWidget(offsetWidget);
8859 bigWidget->setGeometry(0, 0, mainSize.width(), 50000);
8860 palette.setColor(QPalette::Window, Qt::green);
8861 bigWidget->setPalette(palette);
8862 bigWidget->setAutoFillBackground(true);
8865 QVERIFY(QTest::qWaitForWindowExposed(&main));
8867 QPixmap correct(main.size());
8868 correct.fill(Qt::green);
8869 const QPixmap mainPixmap = main.grab(QRect(QPoint(0, 0), QSize(-1, -1)));
8871 QTRY_COMPARE(mainPixmap.toImage().convertToFormat(QImage::Format_RGB32),
8872 correct.toImage().convertToFormat(QImage::Format_RGB32));
8873 QApplication::restoreOverrideCursor();
8877 void tst_QWidget::inputFocus_task257832()
8879 QScopedPointer<QLineEdit> widget(new QLineEdit);
8881 widget->winId(); // make sure, widget has been created
8883 QTRY_VERIFY(widget->hasFocus());
8884 QCOMPARE(qApp->inputMethod()->inputItem(), widget.data());
8885 widget->setReadOnly(true);
8886 QVERIFY(!qApp->inputMethod()->inputItem());
8889 void tst_QWidget::setGraphicsEffect()
8891 // Check that we don't have any effect by default.
8892 QScopedPointer<QWidget> widget(new QWidget);
8893 QVERIFY(!widget->graphicsEffect());
8896 QPointer<QGraphicsEffect> blurEffect = new QGraphicsBlurEffect;
8897 widget->setGraphicsEffect(blurEffect);
8898 QCOMPARE(widget->graphicsEffect(), static_cast<QGraphicsEffect *>(blurEffect));
8900 // Ensure the existing effect is deleted when setting a new one.
8901 QPointer<QGraphicsEffect> shadowEffect = new QGraphicsDropShadowEffect;
8902 widget->setGraphicsEffect(shadowEffect);
8903 QVERIFY(!blurEffect);
8904 QCOMPARE(widget->graphicsEffect(), static_cast<QGraphicsEffect *>(shadowEffect));
8905 blurEffect = new QGraphicsBlurEffect;
8907 // Ensure the effect is uninstalled when setting it on a new target.
8908 QScopedPointer<QWidget> anotherWidget(new QWidget);
8909 anotherWidget->setGraphicsEffect(blurEffect);
8910 widget->setGraphicsEffect(blurEffect);
8911 QVERIFY(!anotherWidget->graphicsEffect());
8912 QVERIFY(!shadowEffect);
8914 // Ensure the existing effect is deleted when deleting the widget.
8916 QVERIFY(!blurEffect);
8917 anotherWidget.reset();
8919 // Ensure the effect is uninstalled when deleting it
8920 widget.reset(new QWidget);
8921 blurEffect = new QGraphicsBlurEffect;
8922 widget->setGraphicsEffect(blurEffect);
8924 QVERIFY(!widget->graphicsEffect());
8926 // Ensure the existing effect is uninstalled and deleted when setting a null effect
8927 blurEffect = new QGraphicsBlurEffect;
8928 widget->setGraphicsEffect(blurEffect);
8929 widget->setGraphicsEffect(0);
8930 QVERIFY(!widget->graphicsEffect());
8931 QVERIFY(!blurEffect);
8934 void tst_QWidget::activateWindow()
8936 // Test case for task 260685
8938 // Create first mainwindow and set it active
8939 QScopedPointer<QMainWindow> mainwindow(new QMainWindow);
8940 QLabel* label = new QLabel(mainwindow.data());
8941 mainwindow->setCentralWidget(label);
8942 mainwindow->setVisible(true);
8943 mainwindow->activateWindow();
8944 QVERIFY(QTest::qWaitForWindowActive(mainwindow.data()));
8945 QVERIFY(mainwindow->isActiveWindow());
8947 // Create second mainwindow and set it active
8948 QScopedPointer<QMainWindow> mainwindow2(new QMainWindow);
8949 QLabel* label2 = new QLabel(mainwindow2.data());
8950 mainwindow2->setCentralWidget(label2);
8951 mainwindow2->setVisible(true);
8952 mainwindow2->activateWindow();
8953 qApp->processEvents();
8955 QTRY_VERIFY(!mainwindow->isActiveWindow());
8956 QTRY_VERIFY(mainwindow2->isActiveWindow());
8958 // Revert first mainwindow back to visible active
8959 mainwindow->setVisible(true);
8960 mainwindow->activateWindow();
8961 qApp->processEvents();
8963 QTRY_VERIFY(mainwindow->isActiveWindow());
8964 QTRY_VERIFY(!mainwindow2->isActiveWindow());
8967 void tst_QWidget::openModal_taskQTBUG_5804()
8969 class Widget : public QWidget
8972 Widget(QWidget *parent) : QWidget(parent)
8979 QTimer::singleShot(10, &msgbox, SLOT(accept()));
8980 msgbox.exec(); //open a modal dialog
8984 QScopedPointer<QWidget> win(new QWidget);
8985 new Widget(win.data());
8987 QVERIFY(QTest::qWaitForWindowExposed(win.data()));
8990 void tst_QWidget::focusProxyAndInputMethods()
8992 QScopedPointer<QWidget> toplevel(new QWidget(0, Qt::X11BypassWindowManagerHint));
8993 toplevel->resize(200, 200);
8994 toplevel->setAttribute(Qt::WA_InputMethodEnabled, true);
8996 QWidget *child = new QWidget(toplevel.data());
8997 child->setFocusProxy(toplevel.data());
8998 child->setAttribute(Qt::WA_InputMethodEnabled, true);
9000 toplevel->setFocusPolicy(Qt::WheelFocus);
9001 child->setFocusPolicy(Qt::WheelFocus);
9003 QVERIFY(!child->hasFocus());
9004 QVERIFY(!toplevel->hasFocus());
9007 QVERIFY(QTest::qWaitForWindowExposed(toplevel.data()));
9008 QApplication::setActiveWindow(toplevel.data());
9009 QVERIFY(QTest::qWaitForWindowActive(toplevel.data()));
9010 QVERIFY(toplevel->hasFocus());
9011 QVERIFY(child->hasFocus());
9013 // verify that toggling input methods on the child widget
9014 // correctly propagate to the focus proxy's input method
9015 // and that the input method gets the focus proxy passed
9016 // as the focus widget instead of the child widget.
9017 // otherwise input method queries go to the wrong widget
9018 QCOMPARE(qApp->inputPanel()->inputItem(), toplevel.data());
9020 toplevel->setAttribute(Qt::WA_InputMethodEnabled, false);
9021 QVERIFY(!qApp->inputPanel()->inputItem());
9023 toplevel->setAttribute(Qt::WA_InputMethodEnabled, true);
9024 QCOMPARE(qApp->inputPanel()->inputItem(), toplevel.data());
9027 #ifdef QT_BUILD_INTERNAL
9028 class scrollWidgetWBS : public QWidget
9031 void deleteBackingStore()
9033 static_cast<QWidgetPrivate*>(d_ptr.data())->topData()->backingStoreTracker.destroy();
9035 void enableBackingStore()
9037 if (!static_cast<QWidgetPrivate*>(d_ptr.data())->maybeBackingStore()) {
9038 static_cast<QWidgetPrivate*>(d_ptr.data())->topData()->backingStoreTracker.create(this);
9039 static_cast<QWidgetPrivate*>(d_ptr.data())->invalidateBuffer(this->rect());
9046 // Test case relies on developer build (AUTOTEST_EXPORT).
9047 #ifdef QT_BUILD_INTERNAL
9048 void tst_QWidget::scrollWithoutBackingStore()
9050 scrollWidgetWBS scrollable;
9051 scrollable.resize(200, 200);
9052 QLabel child(QString("@"),&scrollable);
9053 child.resize(50,50);
9055 QVERIFY(QTest::qWaitForWindowExposed(&scrollable));
9056 scrollable.scroll(50,50);
9057 QCOMPARE(child.pos(),QPoint(50,50));
9058 scrollable.deleteBackingStore();
9059 scrollable.scroll(-25,-25);
9060 QCOMPARE(child.pos(),QPoint(25,25));
9061 scrollable.enableBackingStore();
9062 QCOMPARE(child.pos(),QPoint(25,25));
9066 void tst_QWidget::taskQTBUG_7532_tabOrderWithFocusProxy()
9069 w.setFocusPolicy(Qt::TabFocus);
9070 QWidget *fp = new QWidget(&w);
9071 fp->setFocusPolicy(Qt::TabFocus);
9072 w.setFocusProxy(fp);
9073 QWidget::setTabOrder(&w, fp);
9075 // In debug mode, no assertion failure means it's alright.
9078 void tst_QWidget::movedAndResizedAttributes()
9080 #if defined (Q_OS_MAC)
9081 QEXPECT_FAIL("", "FixMe, QTBUG-8941 and QTBUG-8977", Abort);
9084 // Use Qt::Tool as fully decorated windows have a minimum width of 160 on
9085 QWidget w(0, Qt::Tool);
9088 QVERIFY(!w.testAttribute(Qt::WA_Moved));
9089 QVERIFY(!w.testAttribute(Qt::WA_Resized));
9091 w.setWindowState(Qt::WindowFullScreen);
9093 QVERIFY(!w.testAttribute(Qt::WA_Moved));
9094 QVERIFY(!w.testAttribute(Qt::WA_Resized));
9096 w.setWindowState(Qt::WindowMaximized);
9098 QVERIFY(!w.testAttribute(Qt::WA_Moved));
9099 QVERIFY(!w.testAttribute(Qt::WA_Resized));
9101 w.setWindowState(Qt::WindowMinimized);
9103 QVERIFY(!w.testAttribute(Qt::WA_Moved));
9104 QVERIFY(!w.testAttribute(Qt::WA_Resized));
9108 QVERIFY(!w.testAttribute(Qt::WA_Moved));
9109 QVERIFY(!w.testAttribute(Qt::WA_Resized));
9113 QVERIFY(!w.testAttribute(Qt::WA_Moved));
9114 QVERIFY(!w.testAttribute(Qt::WA_Resized));
9118 QVERIFY(!w.testAttribute(Qt::WA_Moved));
9119 QVERIFY(!w.testAttribute(Qt::WA_Resized));
9123 QVERIFY(w.testAttribute(Qt::WA_Moved));
9124 QVERIFY(!w.testAttribute(Qt::WA_Resized));
9127 QVERIFY(w.testAttribute(Qt::WA_Moved));
9128 QVERIFY(w.testAttribute(Qt::WA_Resized));
9132 void tst_QWidget::childAt()
9134 QWidget parent(0, Qt::FramelessWindowHint);
9135 parent.resize(200, 200);
9137 QWidget *child = new QWidget(&parent);
9138 child->setPalette(Qt::red);
9139 child->setAutoFillBackground(true);
9140 child->setGeometry(20, 20, 160, 160);
9142 QWidget *grandChild = new QWidget(child);
9143 grandChild->setPalette(Qt::blue);
9144 grandChild->setAutoFillBackground(true);
9145 grandChild->setGeometry(-20, -20, 220, 220);
9147 QVERIFY(!parent.childAt(19, 19));
9148 QVERIFY(!parent.childAt(180, 180));
9149 QCOMPARE(parent.childAt(20, 20), grandChild);
9150 QCOMPARE(parent.childAt(179, 179), grandChild);
9152 grandChild->setAttribute(Qt::WA_TransparentForMouseEvents);
9153 QCOMPARE(parent.childAt(20, 20), child);
9154 QCOMPARE(parent.childAt(179, 179), child);
9155 grandChild->setAttribute(Qt::WA_TransparentForMouseEvents, false);
9157 child->setMask(QRect(50, 50, 60, 60));
9159 QVERIFY(!parent.childAt(69, 69));
9160 QVERIFY(!parent.childAt(130, 130));
9161 QCOMPARE(parent.childAt(70, 70), grandChild);
9162 QCOMPARE(parent.childAt(129, 129), grandChild);
9164 child->setAttribute(Qt::WA_MouseNoMask);
9165 QCOMPARE(parent.childAt(69, 69), grandChild);
9166 QCOMPARE(parent.childAt(130, 130), grandChild);
9167 child->setAttribute(Qt::WA_MouseNoMask, false);
9169 grandChild->setAttribute(Qt::WA_TransparentForMouseEvents);
9170 QCOMPARE(parent.childAt(70, 70), child);
9171 QCOMPARE(parent.childAt(129, 129), child);
9172 grandChild->setAttribute(Qt::WA_TransparentForMouseEvents, false);
9174 grandChild->setMask(QRect(80, 80, 40, 40));
9176 QCOMPARE(parent.childAt(79, 79), child);
9177 QCOMPARE(parent.childAt(120, 120), child);
9178 QCOMPARE(parent.childAt(80, 80), grandChild);
9179 QCOMPARE(parent.childAt(119, 119), grandChild);
9181 grandChild->setAttribute(Qt::WA_MouseNoMask);
9183 QCOMPARE(parent.childAt(79, 79), grandChild);
9184 QCOMPARE(parent.childAt(120, 120), grandChild);
9188 void tst_QWidget::childAt_unifiedToolBar()
9190 QLabel *label = new QLabel(QLatin1String("foo"));
9191 QToolBar *toolBar = new QToolBar;
9192 toolBar->addWidget(new QLabel("dummy"));
9193 toolBar->addWidget(label);
9195 QMainWindow mainWindow;
9196 mainWindow.addToolBar(toolBar);
9199 // Calculate the top-left corner of the tool bar and the label (in mainWindow's coordinates).
9200 QPoint labelTopLeft = label->mapTo(&mainWindow, QPoint());
9201 QPoint toolBarTopLeft = toolBar->mapTo(&mainWindow, QPoint());
9203 QCOMPARE(mainWindow.childAt(toolBarTopLeft), static_cast<QWidget *>(toolBar));
9204 QCOMPARE(mainWindow.childAt(labelTopLeft), static_cast<QWidget *>(label));
9206 // Enable unified tool bars.
9207 mainWindow.setUnifiedTitleAndToolBarOnMac(true);
9210 // The tool bar is now in the "non-client" area of QMainWindow, i.e.
9211 // outside the mainWindow's rect(), and since mapTo et al. doesn't work
9212 // in that case (see commit 35667fd45ada49269a5987c235fdedfc43e92bb8),
9213 // we use mapToGlobal/mapFromGlobal to re-calculate the corners.
9214 QPoint oldToolBarTopLeft = toolBarTopLeft;
9215 toolBarTopLeft = mainWindow.mapFromGlobal(toolBar->mapToGlobal(QPoint()));
9216 QVERIFY(toolBarTopLeft != oldToolBarTopLeft);
9217 QVERIFY(toolBarTopLeft.y() < 0);
9218 labelTopLeft = mainWindow.mapFromGlobal(label->mapToGlobal(QPoint()));
9220 QCOMPARE(mainWindow.childAt(toolBarTopLeft), static_cast<QWidget *>(toolBar));
9221 QCOMPARE(mainWindow.childAt(labelTopLeft), static_cast<QWidget *>(label));
9224 void tst_QWidget::taskQTBUG_11373()
9226 QScopedPointer<QMainWindow> myWindow(new QMainWindow);
9227 QWidget * center = new QWidget();
9228 myWindow -> setCentralWidget(center);
9229 QWidget * drawer = new QWidget(myWindow.data(), Qt::Drawer);
9231 QCOMPARE(drawer->isVisible(), false);
9233 myWindow -> raise();
9234 // The drawer shouldn't be visible now.
9235 QCOMPARE(drawer->isVisible(), false);
9236 myWindow -> setWindowState(Qt::WindowFullScreen);
9237 myWindow -> setWindowState(Qt::WindowNoState);
9238 // The drawer should still not be visible, since we haven't shown it.
9239 QCOMPARE(drawer->isVisible(), false);
9243 void tst_QWidget::taskQTBUG_17333_ResizeInfiniteRecursion()
9246 const char *s = "border: 1px solid;";
9247 tb.setStyleSheet(s);
9250 QVERIFY(QTest::qWaitForWindowExposed(&tb));
9251 tb.setGeometry(QRect(100, 100, 0, 100));
9252 // No crash, it works.
9255 void tst_QWidget::nativeChildFocus()
9258 QLayout *layout = new QVBoxLayout;
9259 w.setLayout(layout);
9260 QLineEdit *p1 = new QLineEdit;
9261 QLineEdit *p2 = new QLineEdit;
9262 layout->addWidget(p1);
9263 layout->addWidget(p2);
9264 p1->setObjectName("p1");
9265 p2->setObjectName("p2");
9269 p1->setAttribute(Qt::WA_NativeWindow);
9270 p2->setAttribute(Qt::WA_NativeWindow);
9271 QApplication::processEvents();
9272 QVERIFY(QTest::qWaitForWindowExposed(&w));
9275 QCOMPARE(QApplication::activeWindow(), &w);
9276 QCOMPARE(QApplication::focusWidget(), static_cast<QWidget*>(p1));
9281 static bool lenientCompare(const QPixmap &actual, const QPixmap &expected)
9283 QImage expectedImage = expected.toImage().convertToFormat(QImage::Format_RGB32);
9284 QImage actualImage = actual.toImage().convertToFormat(QImage::Format_RGB32);
9286 if (expectedImage.size() != actualImage.size()) {
9287 qWarning("Image size comparison failed: expected: %dx%d, got %dx%d",
9288 expectedImage.size().width(), expectedImage.size().height(),
9289 actualImage.size().width(), actualImage.size().height());
9293 const int size = actual.width() * actual.height();
9294 const int threshold = QPixmap::defaultDepth() == 16 ? 10 : 2;
9296 QRgb *a = (QRgb *)actualImage.bits();
9297 QRgb *e = (QRgb *)expectedImage.bits();
9298 for (int i = 0; i < size; ++i) {
9299 const QColor ca(a[i]);
9300 const QColor ce(e[i]);
9301 if (qAbs(ca.red() - ce.red()) > threshold
9302 || qAbs(ca.green() - ce.green()) > threshold
9303 || qAbs(ca.blue() - ce.blue()) > threshold) {
9304 qWarning("Color mismatch at pixel #%d: Expected: %d,%d,%d, got %d,%d,%d",
9305 i, ce.red(), ce.green(), ce.blue(), ca.red(), ca.green(), ca.blue());
9313 void tst_QWidget::grab()
9315 for (int opaque = 0; opaque < 2; ++opaque) {
9317 QImage image(128, 128, opaque ? QImage::Format_RGB32 : QImage::Format_ARGB32_Premultiplied);
9318 for (int row = 0; row < image.height(); ++row) {
9319 QRgb *line = reinterpret_cast<QRgb *>(image.scanLine(row));
9320 for (int col = 0; col < image.width(); ++col)
9321 line[col] = qRgba(rand() & 255, row, col, opaque ? 255 : 127);
9324 QPalette pal = widget.palette();
9325 pal.setBrush(QPalette::Window, QBrush(image));
9326 widget.setPalette(pal);
9327 widget.resize(128, 128);
9329 QPixmap expected(64, 64);
9331 expected.fill(Qt::transparent);
9333 QPainter p(&expected);
9334 p.translate(-64, -64);
9335 p.drawTiledPixmap(0, 0, 128, 128, pal.brush(QPalette::Window).texture(), 0, 0);
9338 QPixmap actual = widget.grab(QRect(64, 64, 64, 64));
9339 QVERIFY(lenientCompare(actual, expected));
9341 actual = widget.grab(QRect(64, 64, -1, -1));
9342 QVERIFY(lenientCompare(actual, expected));
9344 // Make sure a widget that is not yet shown is grabbed correctly.
9345 QTreeWidget widget2;
9346 actual = widget2.grab(QRect());
9348 expected = widget2.grab(QRect());
9350 QVERIFY(lenientCompare(actual, expected));
9354 class TouchMouseWidget : public QWidget {
9356 explicit TouchMouseWidget(QWidget *parent = 0)
9358 m_touchEventCount(0),
9359 m_acceptTouch(false),
9360 m_mouseEventCount(0),
9366 void setAcceptTouch(bool accept)
9368 m_acceptTouch = accept;
9369 setAttribute(Qt::WA_AcceptTouchEvents, accept);
9372 void setAcceptMouse(bool accept)
9374 m_acceptMouse = accept;
9378 bool event(QEvent *e)
9380 switch (e->type()) {
9381 case QEvent::TouchBegin:
9382 case QEvent::TouchUpdate:
9383 case QEvent::TouchEnd:
9384 ++m_touchEventCount;
9391 case QEvent::MouseButtonPress:
9392 case QEvent::MouseMove:
9393 case QEvent::MouseButtonRelease:
9394 ++m_mouseEventCount;
9395 m_lastMouseEventPos = static_cast<QMouseEvent *>(e)->localPos();
9403 return QWidget::event(e);
9408 int m_touchEventCount;
9410 int m_mouseEventCount;
9412 QPointF m_lastMouseEventPos;
9415 void tst_QWidget::touchEventSynthesizedMouseEvent()
9418 // Simple case, we ignore the touch events, we get mouse events instead
9419 QTouchDevice *device = new QTouchDevice;
9420 device->setType(QTouchDevice::TouchScreen);
9421 QWindowSystemInterface::registerTouchDevice(device);
9423 TouchMouseWidget widget;
9425 QVERIFY(QTest::qWaitForWindowExposed(widget.windowHandle()));
9426 QCOMPARE(widget.m_touchEventCount, 0);
9427 QCOMPARE(widget.m_mouseEventCount, 0);
9429 QTest::touchEvent(&widget, device).press(0, QPoint(10, 10), &widget);
9430 QCOMPARE(widget.m_touchEventCount, 0);
9431 QCOMPARE(widget.m_mouseEventCount, 1);
9432 QCOMPARE(widget.m_lastMouseEventPos, QPointF(10, 10));
9433 QTest::touchEvent(&widget, device).move(0, QPoint(15, 15), &widget);
9434 QCOMPARE(widget.m_touchEventCount, 0);
9435 QCOMPARE(widget.m_mouseEventCount, 2);
9436 QCOMPARE(widget.m_lastMouseEventPos, QPointF(15, 15));
9437 QTest::touchEvent(&widget, device).release(0, QPoint(20, 20), &widget);
9438 QCOMPARE(widget.m_touchEventCount, 0);
9439 QCOMPARE(widget.m_mouseEventCount, 3);
9440 QCOMPARE(widget.m_lastMouseEventPos, QPointF(20, 20));
9444 // We accept the touch events, no mouse event is generated
9445 QTouchDevice *device = new QTouchDevice;
9446 device->setType(QTouchDevice::TouchScreen);
9447 QWindowSystemInterface::registerTouchDevice(device);
9449 TouchMouseWidget widget;
9450 widget.setAcceptTouch(true);
9452 QVERIFY(QTest::qWaitForWindowExposed(widget.windowHandle()));
9453 QCOMPARE(widget.m_touchEventCount, 0);
9454 QCOMPARE(widget.m_mouseEventCount, 0);
9456 QTest::touchEvent(&widget, device).press(0, QPoint(10, 10), &widget);
9457 QCOMPARE(widget.m_touchEventCount, 1);
9458 QCOMPARE(widget.m_mouseEventCount, 0);
9459 QTest::touchEvent(&widget, device).move(0, QPoint(15, 15), &widget);
9460 QCOMPARE(widget.m_touchEventCount, 2);
9461 QCOMPARE(widget.m_mouseEventCount, 0);
9462 QTest::touchEvent(&widget, device).release(0, QPoint(20, 20), &widget);
9463 QCOMPARE(widget.m_touchEventCount, 3);
9464 QCOMPARE(widget.m_mouseEventCount, 0);
9468 // Parent accepts touch events, child ignore both mouse and touch
9469 // We should see propagation of the TouchBegin
9470 QTouchDevice *device = new QTouchDevice;
9471 device->setType(QTouchDevice::TouchScreen);
9472 QWindowSystemInterface::registerTouchDevice(device);
9474 TouchMouseWidget parent;
9475 parent.setAcceptTouch(true);
9476 TouchMouseWidget child(&parent);
9478 child.setAcceptMouse(false);
9480 QVERIFY(QTest::qWaitForWindowExposed(parent.windowHandle()));
9481 QCOMPARE(parent.m_touchEventCount, 0);
9482 QCOMPARE(parent.m_mouseEventCount, 0);
9483 QCOMPARE(child.m_touchEventCount, 0);
9484 QCOMPARE(child.m_mouseEventCount, 0);
9486 QTest::touchEvent(parent.window(), device).press(0, QPoint(10, 10), &child);
9487 QCOMPARE(parent.m_touchEventCount, 1);
9488 QCOMPARE(parent.m_mouseEventCount, 0);
9489 QCOMPARE(child.m_touchEventCount, 0);
9490 QCOMPARE(child.m_mouseEventCount, 1); // Attempt at mouse event before propagation
9491 QCOMPARE(child.m_lastMouseEventPos, QPointF(10, 10));
9495 // Parent accepts mouse events, child ignore both mouse and touch
9496 // We should see propagation of the TouchBegin into a MouseButtonPress
9497 QTouchDevice *device = new QTouchDevice;
9498 device->setType(QTouchDevice::TouchScreen);
9499 QWindowSystemInterface::registerTouchDevice(device);
9501 TouchMouseWidget parent;
9502 TouchMouseWidget child(&parent);
9504 child.setAcceptMouse(false);
9506 QVERIFY(QTest::qWaitForWindowExposed(parent.windowHandle()));
9507 QCOMPARE(parent.m_touchEventCount, 0);
9508 QCOMPARE(parent.m_mouseEventCount, 0);
9509 QCOMPARE(child.m_touchEventCount, 0);
9510 QCOMPARE(child.m_mouseEventCount, 0);
9512 QTest::touchEvent(parent.window(), device).press(0, QPoint(10, 10), &child);
9513 QCOMPARE(parent.m_touchEventCount, 0);
9514 QCOMPARE(parent.m_mouseEventCount, 1);
9515 QCOMPARE(parent.m_lastMouseEventPos, QPointF(15, 15));
9516 QCOMPARE(child.m_touchEventCount, 0);
9517 QCOMPARE(child.m_mouseEventCount, 1); // Attempt at mouse event before propagation
9518 QCOMPARE(child.m_lastMouseEventPos, QPointF(10, 10));
9522 QTEST_MAIN(tst_QWidget)
9523 #include "tst_qwidget.moc"