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>
75 #include <QtWidgets/QGraphicsView>
76 #include <QtWidgets/QGraphicsProxyWidget>
79 #include "tst_qwidget_mac_helpers.h" // Abstract the ObjC stuff out so not everyone must run an ObjC++ compile.
82 #include <QtTest/QtTest>
85 # include <QtCore/qt_windows.h>
86 # include <QtGui/private/qguiapplication_p.h>
87 #include <qpa/qplatformnativeinterface.h>
88 #include <qpa/qplatformintegration.h>
90 static HWND winHandleOf(const QWidget *w)
92 static QPlatformNativeInterface *nativeInterface
93 = QGuiApplicationPrivate::instance()->platformIntegration()->nativeInterface();
94 if (void *handle = nativeInterface->nativeResourceForWindow("handle", w->window()->windowHandle()))
95 return reinterpret_cast<HWND>(handle);
96 qWarning() << "Cannot obtain native handle for " << w;
101 # define Q_CHECK_PAINTEVENTS
102 # ifdef Q_OS_WINCE_WM
103 # include <qguifunctions_wince.h>
104 // taken from qguifunctions_wce.cpp
105 # define SPI_GETPLATFORMTYPE 257
106 static bool qt_wince_is_platform(const QString &platformString) {
107 wchar_t tszPlatform[64];
108 if (SystemParametersInfo(SPI_GETPLATFORMTYPE,
109 sizeof(tszPlatform)/sizeof(*tszPlatform),tszPlatform,0))
110 if (0 == _tcsicmp(reinterpret_cast<const wchar_t *> (platformString.utf16()), tszPlatform))
114 static inline bool qt_wince_is_smartphone() { return qt_wince_is_platform(QString::fromLatin1("Smartphone")); }
115 # endif // Q_OS_WINCE_WM
117 # define Q_CHECK_PAINTEVENTS \
118 if (::SwitchDesktop(::GetThreadDesktop(::GetCurrentThreadId())) == 0) \
119 QSKIP("desktop is not visible, this test would fail");
120 # endif // !Q_OS_WINCE
122 # define Q_CHECK_PAINTEVENTS
123 #endif // else Q_OS_WIN
126 #if defined(Q_OS_WINCE_WM)
127 #include <qguifunctions_wince.h>
128 // taken from qguifunctions_wce.cpp
129 #define SPI_GETPLATFORMTYPE 257
130 bool qt_wince_is_platform(const QString &platformString) {
131 wchar_t tszPlatform[64];
132 if (SystemParametersInfo(SPI_GETPLATFORMTYPE,
133 sizeof(tszPlatform)/sizeof(*tszPlatform),tszPlatform,0))
134 if (0 == _tcsicmp(reinterpret_cast<const wchar_t *> (platformString.utf16()), tszPlatform))
138 bool qt_wince_is_smartphone() {
139 return qt_wince_is_platform(QString::fromLatin1("Smartphone"));
144 #include <Security/AuthSession.h>
145 bool macHasAccessToWindowsServer()
147 SecuritySessionId mySession;
148 SessionAttributeBits sessionInfo;
149 SessionGetInfo(callerSecuritySession, &mySession, &sessionInfo);
150 return (sessionInfo & sessionHasGraphicAccess);
154 class tst_QWidget : public QObject
160 virtual ~tst_QWidget();
164 void cleanupTestCase();
169 void fontPropagation();
170 void fontPropagation2();
171 void palettePropagation();
172 void palettePropagation2();
173 void enabledPropagation();
174 void popupEnterLeave();
175 #ifndef QT_NO_DRAGANDDROP
176 void acceptDropsPropagation();
180 void visible_setWindowOpacity();
184 void mapFromAndTo_data();
186 void focusChainOnHide();
187 void focusChainOnReparent();
194 void showMaximized();
195 void showFullScreen();
196 void showMinimized();
197 void showMinimizedKeepsFocus();
199 void hideWhenFocusWidgetIsChild();
200 void normalGeometry();
203 void windowOpacity();
207 #ifndef QT_MAC_USE_COCOA
210 void testContentsPropagation();
211 void saveRestoreGeometry();
212 void restoreVersion1Geometry_data();
213 void restoreVersion1Geometry();
220 void optimizedResizeMove();
221 void optimizedResize_topLevel();
225 void testDeletionInEventHandlers();
227 void childDeletesItsSibling();
229 void setMinimumSize();
230 void setMaximumSize();
233 void ensureCreated();
234 void winIdChangeEvent();
235 void persistentWinId();
236 void showNativeChild();
237 void qobject_castInDestroyedSlot();
239 void showHideEvent_data();
240 void showHideEvent();
242 void lostUpdatesOnHide();
251 // tests QWidget::setGeometry()
252 void setWindowGeometry_data();
253 void setWindowGeometry();
255 // tests QWidget::move() and resize()
256 void windowMoveResize_data();
257 void windowMoveResize();
259 void moveChild_data();
261 void showAndMoveChild();
263 #ifndef QT_MAC_USE_COCOA
264 void subtractOpaqueSiblings();
267 #if defined (Q_OS_WIN) && !defined(Q_OS_WINCE)
268 void setGeometry_win();
273 void multipleToplevelFocusCheck();
277 void testWindowIconChangeEventPropagation();
279 void minAndMaxSizeWithX11BypassWindowManagerHint();
280 void showHideShowX11();
281 void clean_qt_x11_enforce_cursor();
285 void renderInvisible();
286 void renderWithPainter();
287 void render_task188133();
288 void render_task211796();
289 void render_task217815();
291 void render_windowOpacity();
293 void render_systemClip();
294 void render_systemClip2_data();
295 void render_systemClip2();
296 void render_systemClip3_data();
297 void render_systemClip3();
298 void render_task252837();
299 void render_worldTransform();
301 void setContentsMargins();
303 void moveWindowInShowEvent_data();
304 void moveWindowInShowEvent();
306 void repaintWhenChildDeleted();
307 void hideOpaqueChildWhileHidden();
308 #if !defined(Q_OS_WINCE)
309 void updateWhileMinimized();
313 void adjustSize_data();
314 void updateGeometry();
315 void updateGeometry_data();
316 void sendUpdateRequestImmediately();
317 void doubleRepaint();
318 void resizeInPaintEvent();
319 void opaqueChildren();
321 void setMaskInResizeEvent();
322 void moveInResizeEvent();
324 void immediateRepaintAfterShow();
325 void immediateRepaintAfterInvalidateBuffer();
327 void effectiveWinId();
328 void effectiveWinId2();
330 void customDpiProperty();
332 void quitOnCloseAttribute();
335 #if defined (Q_OS_WIN)
337 void paintOnScreenPossible();
339 void reparentStaticWidget();
340 void QTBUG6883_reparentStaticWidget2();
342 void translucentWidget();
344 void setClearAndResizeMask();
346 #if !defined(Q_OS_WINCE_WM)
347 void syntheticEnterLeave();
348 void taskQTBUG_4055_sendSyntheticEnterLeave();
351 void initialPosForDontShowOnScreenWidgets();
352 void updateOnDestroyedSignal();
353 void toplevelLineEditFocus();
354 void inputFocus_task257832();
356 void focusWidget_task254563();
357 #ifndef Q_OS_WINCE_WM
358 void rectOutsideCoordinatesLimit_task144779();
360 void setGraphicsEffect();
362 #ifdef QT_BUILD_INTERNAL
363 void destroyBackingStore();
366 void activateWindow();
368 void openModal_taskQTBUG_5804();
370 void focusProxyAndInputMethods();
371 #ifdef QT_BUILD_INTERNAL
372 void scrollWithoutBackingStore();
375 void taskQTBUG_7532_tabOrderWithFocusProxy();
376 void movedAndResizedAttributes();
379 void childAt_unifiedToolBar();
380 void taskQTBUG_11373();
382 void taskQTBUG_17333_ResizeInfiniteRecursion();
384 void nativeChildFocus();
388 bool ensureScreenSize(int width, int height);
391 const QString m_platform;
394 bool tst_QWidget::ensureScreenSize(int width, int height)
397 available = QDesktopWidget().availableGeometry().size();
398 return (available.width() >= width && available.height() >= height);
401 // Testing get/set functions
402 void tst_QWidget::getSetCheck()
405 QWidget child1(&obj1);
406 // QStyle * QWidget::style()
407 // void QWidget::setStyle(QStyle *)
408 QWindowsStyle *var1 = new QWindowsStyle;
410 QCOMPARE(static_cast<QStyle *>(var1), obj1.style());
411 obj1.setStyle((QStyle *)0);
412 QVERIFY(var1 != obj1.style());
413 QVERIFY(0 != obj1.style()); // style can never be 0 for a widget
415 // int QWidget::minimumWidth()
416 // void QWidget::setMinimumWidth(int)
417 obj1.setMinimumWidth(0);
418 QCOMPARE(obj1.minimumWidth(), 0);
419 obj1.setMinimumWidth(INT_MIN);
420 QCOMPARE(obj1.minimumWidth(), 0); // A widgets width can never be less than 0
421 obj1.setMinimumWidth(INT_MAX);
423 child1.setMinimumWidth(0);
424 QCOMPARE(child1.minimumWidth(), 0);
425 child1.setMinimumWidth(INT_MIN);
426 QCOMPARE(child1.minimumWidth(), 0); // A widgets width can never be less than 0
427 child1.setMinimumWidth(INT_MAX);
428 QCOMPARE(child1.minimumWidth(), QWIDGETSIZE_MAX); // The largest minimum size should only be as big as the maximium
430 // int QWidget::minimumHeight()
431 // void QWidget::setMinimumHeight(int)
432 obj1.setMinimumHeight(0);
433 QCOMPARE(obj1.minimumHeight(), 0);
434 obj1.setMinimumHeight(INT_MIN);
435 QCOMPARE(obj1.minimumHeight(), 0); // A widgets height can never be less than 0
436 obj1.setMinimumHeight(INT_MAX);
438 child1.setMinimumHeight(0);
439 QCOMPARE(child1.minimumHeight(), 0);
440 child1.setMinimumHeight(INT_MIN);
441 QCOMPARE(child1.minimumHeight(), 0); // A widgets height can never be less than 0
442 child1.setMinimumHeight(INT_MAX);
443 QCOMPARE(child1.minimumHeight(), QWIDGETSIZE_MAX); // The largest minimum size should only be as big as the maximium
445 // int QWidget::maximumWidth()
446 // void QWidget::setMaximumWidth(int)
447 obj1.setMaximumWidth(0);
448 QCOMPARE(obj1.maximumWidth(), 0);
449 obj1.setMaximumWidth(INT_MIN);
450 QCOMPARE(obj1.maximumWidth(), 0); // A widgets width can never be less than 0
451 obj1.setMaximumWidth(INT_MAX);
452 QCOMPARE(obj1.maximumWidth(), QWIDGETSIZE_MAX); // QWIDGETSIZE_MAX is the abs max, not INT_MAX
454 // int QWidget::maximumHeight()
455 // void QWidget::setMaximumHeight(int)
456 obj1.setMaximumHeight(0);
457 QCOMPARE(obj1.maximumHeight(), 0);
458 obj1.setMaximumHeight(INT_MIN);
459 QCOMPARE(obj1.maximumHeight(), 0); // A widgets height can never be less than 0
460 obj1.setMaximumHeight(INT_MAX);
461 QCOMPARE(obj1.maximumHeight(), QWIDGETSIZE_MAX); // QWIDGETSIZE_MAX is the abs max, not INT_MAX
464 obj1.setMinimumWidth(0);
465 obj1.setMinimumHeight(0);
466 obj1.setMaximumWidth(QWIDGETSIZE_MAX);
467 obj1.setMaximumHeight(QWIDGETSIZE_MAX);
469 // const QPalette & QWidget::palette()
470 // void QWidget::setPalette(const QPalette &)
472 obj1.setPalette(var6);
473 QCOMPARE(var6, obj1.palette());
474 obj1.setPalette(QPalette());
475 QCOMPARE(QPalette(), obj1.palette());
477 // const QFont & QWidget::font()
478 // void QWidget::setFont(const QFont &)
481 QCOMPARE(var7, obj1.font());
482 obj1.setFont(QFont());
483 QCOMPARE(QFont(), obj1.font());
485 // qreal QWidget::windowOpacity()
486 // void QWidget::setWindowOpacity(qreal)
487 obj1.setWindowOpacity(0.0);
488 QCOMPARE(0.0, obj1.windowOpacity());
489 obj1.setWindowOpacity(1.1f);
490 QCOMPARE(1.0, obj1.windowOpacity()); // 1.0 is the fullest opacity possible
492 // QWidget * QWidget::focusProxy()
493 // void QWidget::setFocusProxy(QWidget *)
494 QWidget *var9 = new QWidget();
495 obj1.setFocusProxy(var9);
496 QCOMPARE(var9, obj1.focusProxy());
497 obj1.setFocusProxy((QWidget *)0);
498 QCOMPARE((QWidget *)0, obj1.focusProxy());
501 // const QRect & QWidget::geometry()
502 // void QWidget::setGeometry(const QRect &)
503 qApp->processEvents();
504 QRect var10(10, 10, 100, 100);
505 obj1.setGeometry(var10);
506 qApp->processEvents();
507 qDebug() << obj1.geometry();
508 QCOMPARE(var10, obj1.geometry());
509 obj1.setGeometry(QRect(0,0,0,0));
510 qDebug() << obj1.geometry();
511 QCOMPARE(QRect(0,0,0,0), obj1.geometry());
513 // QLayout * QWidget::layout()
514 // void QWidget::setLayout(QLayout *)
515 QBoxLayout *var11 = new QBoxLayout(QBoxLayout::LeftToRight);
516 obj1.setLayout(var11);
517 QCOMPARE(static_cast<QLayout *>(var11), obj1.layout());
518 obj1.setLayout((QLayout *)0);
519 QCOMPARE(static_cast<QLayout *>(var11), obj1.layout()); // You cannot set a 0-pointer layout, that keeps the current
520 delete var11; // This will remove the layout from the widget
521 QCOMPARE((QLayout *)0, obj1.layout());
523 // bool QWidget::acceptDrops()
524 // void QWidget::setAcceptDrops(bool)
525 obj1.setAcceptDrops(false);
526 QCOMPARE(false, obj1.acceptDrops());
527 obj1.setAcceptDrops(true);
528 QCOMPARE(true, obj1.acceptDrops());
530 // bool QWidget::autoFillBackground()
531 // void QWidget::setAutoFillBackground(bool)
532 obj1.setAutoFillBackground(false);
533 QCOMPARE(false, obj1.autoFillBackground());
534 obj1.setAutoFillBackground(true);
535 QCOMPARE(true, obj1.autoFillBackground());
538 #if defined (Q_OS_WIN) && !defined(Q_OS_WINCE)
539 obj1.setWindowFlags(Qt::FramelessWindowHint | Qt::WindowSystemMenuHint);
540 const HWND handle = reinterpret_cast<HWND>(obj1.winId()); // explicitly create window handle
541 QVERIFY(GetWindowLong(handle, GWL_STYLE) & WS_POPUP);
545 tst_QWidget::tst_QWidget() : m_platform(qApp->platformName().toLower())
549 font.setPointSize(42);
550 qApp->setFont(font, "QPropagationTestWidget");
553 palette.setColor(QPalette::ToolTipBase, QColor(12, 13, 14));
554 palette.setColor(QPalette::Text, QColor(21, 22, 23));
555 qApp->setPalette(palette, "QPropagationTestWidget");
560 tst_QWidget::~tst_QWidget()
564 class BezierViewer : public QWidget {
566 BezierViewer( QWidget* parent=0, const char* name=0 );
567 void paintEvent( QPaintEvent* );
568 void setPoints( const QPolygonF& poly );
574 void tst_QWidget::initTestCase()
576 #ifdef Q_OS_WINCE //disable magic for WindowsCE
577 qApp->setAutoMaximizeThreshold(-1);
579 // Create the test class
580 testWidget = new BezierViewer( 0, "testObject");
581 testWidget->resize(200,200);
583 QTest::qWaitForWindowShown(testWidget);
587 void tst_QWidget::cleanupTestCase()
593 void tst_QWidget::init()
595 // TODO: Add initialization code here.
596 // This will be executed immediately before each test is run.
597 testWidget->setFont(QFont());
598 testWidget->setPalette(QPalette());
601 void tst_QWidget::cleanup()
607 BezierViewer::BezierViewer( QWidget* parent, const char* name )
612 pal.setColor(backgroundRole(), Qt::white);
617 void BezierViewer::setPoints( const QPolygonF& a )
622 #include "private/qbezier_p.h"
623 void BezierViewer::paintEvent( QPaintEvent* )
625 if ( points.size() != 4 ) {
626 #if defined(QT_CHECK_RANGE)
627 qWarning( "QPolygon::bezier: The array must have 4 control points" );
632 /* Calculate Bezier curve */
633 QPolygonF bezier = QBezier::fromPoints(points.at(0),points.at(1),points.at(2),points.at(3)).toPolygon();
635 QPainter painter( this );
637 /* Calculate scale to fit in window */
638 QRectF br = bezier.boundingRect() | points.boundingRect();
640 int scl = qMax( qMin(pr.width()/br.width(), pr.height()/br.height()), qreal(1.) );
643 /* Scale Bezier curve vertices */
644 for ( QPolygonF::Iterator it = bezier.begin(); it != bezier.end(); ++it ) {
645 it->setX( (it->x()-br.x()) * scl + border );
646 it->setY( (it->y()-br.y()) * scl + border );
650 painter.setPen( Qt::lightGray );
652 for ( i = border; i <= pr.width(); i += scl ) {
653 painter.drawLine( i, 0, i, pr.height() );
655 for ( int j = border; j <= pr.height(); j += scl ) {
656 painter.drawLine( 0, j, pr.width(), j );
659 /* Write number of vertices */
660 painter.setPen( Qt::red );
661 painter.setFont( QFont("Helvetica", 14, QFont::DemiBold, true ) );
663 caption.setNum( bezier.size() );
664 caption += QString::fromLatin1( " vertices" );
665 painter.drawText( 10, pr.height()-10, caption );
667 /* Draw Bezier curve */
668 painter.setPen( Qt::black );
669 painter.drawPolyline( bezier );
671 /* Scale and draw control points */
672 painter.setPen( Qt::darkGreen );
673 for ( QPolygonF::Iterator p1 = points.begin(); p1 != points.end(); ++p1 ) {
674 int x = (p1->x()-br.x()) * scl + border;
675 int y = (p1->y()-br.y()) * scl + border;
676 painter.drawLine( x-4, y-4, x+4, y+4 );
677 painter.drawLine( x+4, y-4, x-4, y+4 );
681 painter.setPen( Qt::red );
682 painter.setBrush( Qt::red );
683 for ( QPolygonF::Iterator p2 = bezier.begin(); p2 != bezier.end(); ++p2 )
684 painter.drawEllipse( p2->x()-1, p2->y()-1, 3, 3 );
687 void tst_QWidget::fontPropagation()
689 QFont font = testWidget->font();
690 QWidget* childWidget = new QWidget( testWidget );
692 QCOMPARE( font, childWidget->font() );
694 font.setBold( true );
695 testWidget->setFont( font );
696 QCOMPARE( font, testWidget->font() );
697 QCOMPARE( font, childWidget->font() );
699 QFont newFont = font;
700 newFont.setItalic( true );
701 childWidget->setFont( newFont );
702 QWidget* grandChildWidget = new QWidget( childWidget );
703 QCOMPARE( font, testWidget->font() );
704 QCOMPARE( newFont, grandChildWidget->font() );
706 font.setUnderline( true );
707 testWidget->setFont( font );
709 // the child and grand child should now have merged bold and
711 newFont.setUnderline( true );
713 QCOMPARE( newFont, childWidget->font() );
714 QCOMPARE( newFont, grandChildWidget->font() );
716 // make sure font propagation continues working after reparenting
717 font = testWidget->font();
718 font.setPointSize(font.pointSize() + 2);
719 testWidget->setFont(font);
721 QWidget *one = new QWidget(testWidget);
722 QWidget *two = new QWidget(one);
723 QWidget *three = new QWidget(two);
724 QWidget *four = new QWidget(two);
726 four->setParent(three);
727 four->move(QPoint(0,0));
729 font.setPointSize(font.pointSize() + 2);
730 testWidget->setFont(font);
732 QCOMPARE(testWidget->font(), one->font());
733 QCOMPARE(one->font(), two->font());
734 QCOMPARE(two->font(), three->font());
735 QCOMPARE(three->font(), four->font());
737 QVERIFY(testWidget->testAttribute(Qt::WA_SetFont));
738 QVERIFY(! one->testAttribute(Qt::WA_SetFont));
739 QVERIFY(! two->testAttribute(Qt::WA_SetFont));
740 QVERIFY(! three->testAttribute(Qt::WA_SetFont));
741 QVERIFY(! four->testAttribute(Qt::WA_SetFont));
743 font.setPointSize(font.pointSize() + 2);
746 QCOMPARE(one->font(), two->font());
747 QCOMPARE(two->font(), three->font());
748 QCOMPARE(three->font(), four->font());
750 QVERIFY(one->testAttribute(Qt::WA_SetFont));
751 QVERIFY(! two->testAttribute(Qt::WA_SetFont));
752 QVERIFY(! three->testAttribute(Qt::WA_SetFont));
753 QVERIFY(! four->testAttribute(Qt::WA_SetFont));
755 font.setPointSize(font.pointSize() + 2);
758 QCOMPARE(two->font(), three->font());
759 QCOMPARE(three->font(), four->font());
761 QVERIFY(two->testAttribute(Qt::WA_SetFont));
762 QVERIFY(! three->testAttribute(Qt::WA_SetFont));
763 QVERIFY(! four->testAttribute(Qt::WA_SetFont));
765 font.setPointSize(font.pointSize() + 2);
766 three->setFont(font);
768 QCOMPARE(three->font(), four->font());
770 QVERIFY(three->testAttribute(Qt::WA_SetFont));
771 QVERIFY(! four->testAttribute(Qt::WA_SetFont));
773 font.setPointSize(font.pointSize() + 2);
776 QVERIFY(four->testAttribute(Qt::WA_SetFont));
779 class QPropagationTestWidget : public QWidget
783 QPropagationTestWidget(QWidget *parent = 0)
788 void tst_QWidget::fontPropagation2()
790 // ! Note, the code below is executed in tst_QWidget's constructor.
792 // font.setBold(true);
793 // font.setPointSize(42);
794 // qApp->setFont(font, "QPropagationTestWidget");
796 QWidget *root = new QWidget;
797 QWidget *child0 = new QWidget(root);
798 QWidget *child1 = new QWidget(child0);
799 QWidget *child2 = new QPropagationTestWidget(child1);
800 QWidget *child3 = new QWidget(child2);
801 QWidget *child4 = new QWidget(child3);
802 QWidget *child5 = new QWidget(child4);
805 // Check that only the application fonts apply.
806 QCOMPARE(root->font(), QApplication::font());
807 QCOMPARE(child0->font(), QApplication::font());
808 QCOMPARE(child1->font(), QApplication::font());
809 QCOMPARE(child2->font().pointSize(), 42);
810 QVERIFY(child2->font().bold());
811 QCOMPARE(child3->font().pointSize(), 42);
812 QVERIFY(child3->font().bold());
813 QCOMPARE(child4->font().pointSize(), 42);
814 QVERIFY(child4->font().bold());
815 QCOMPARE(child5->font().pointSize(), 42);
816 QVERIFY(child5->font().bold());
818 // Set child0's font size to 15, and remove bold on child4.
820 font.setPointSize(15);
821 child0->setFont(font);
823 unboldFont.setBold(false);
824 child4->setFont(unboldFont);
826 // Check that the above settings propagate correctly.
827 QCOMPARE(root->font(), QApplication::font());
828 QCOMPARE(child0->font().pointSize(), 15);
829 QVERIFY(!child0->font().bold());
830 QCOMPARE(child1->font().pointSize(), 15);
831 QVERIFY(!child1->font().bold());
832 QCOMPARE(child2->font().pointSize(), 15);
833 QVERIFY(child2->font().bold());
834 QCOMPARE(child3->font().pointSize(), 15);
835 QVERIFY(child3->font().bold());
836 QCOMPARE(child4->font().pointSize(), 15);
837 QVERIFY(!child4->font().bold());
838 QCOMPARE(child5->font().pointSize(), 15);
839 QVERIFY(!child5->font().bold());
841 // Replace the app font for child2. Italic should propagate
842 // but the size should still be ignored. The previous bold
844 QFont italicSizeFont;
845 italicSizeFont.setItalic(true);
846 italicSizeFont.setPointSize(33);
847 qApp->setFont(italicSizeFont, "QPropagationTestWidget");
849 // Check that this propagates correctly.
850 QCOMPARE(root->font(), QApplication::font());
851 QCOMPARE(child0->font().pointSize(), 15);
852 QVERIFY(!child0->font().bold());
853 QVERIFY(!child0->font().italic());
854 QCOMPARE(child1->font().pointSize(), 15);
855 QVERIFY(!child1->font().bold());
856 QVERIFY(!child1->font().italic());
857 QCOMPARE(child2->font().pointSize(), 15);
858 QVERIFY(!child2->font().bold());
859 QVERIFY(child2->font().italic());
860 QCOMPARE(child3->font().pointSize(), 15);
861 QVERIFY(!child3->font().bold());
862 QVERIFY(child3->font().italic());
863 QCOMPARE(child4->font().pointSize(), 15);
864 QVERIFY(!child4->font().bold());
865 QVERIFY(child4->font().italic());
866 QCOMPARE(child5->font().pointSize(), 15);
867 QVERIFY(!child5->font().bold());
868 QVERIFY(child5->font().italic());
871 void tst_QWidget::palettePropagation()
873 QPalette palette = testWidget->palette();
874 QWidget* childWidget = new QWidget( testWidget );
876 QCOMPARE( palette, childWidget->palette() );
878 palette.setColor( QPalette::Base, Qt::red );
879 testWidget->setPalette( palette );
880 QCOMPARE( palette, testWidget->palette() );
881 QCOMPARE( palette, childWidget->palette() );
883 QPalette newPalette = palette;
884 newPalette.setColor( QPalette::Highlight, Qt::green );
885 childWidget->setPalette( newPalette );
886 QWidget* grandChildWidget = new QWidget( childWidget );
887 QCOMPARE( palette, testWidget->palette() );
888 QCOMPARE( newPalette, grandChildWidget->palette() );
890 palette.setColor( QPalette::Text, Qt::blue );
891 testWidget->setPalette( palette );
893 // the child and grand child should now have merged green
894 // highlight and blue text
895 newPalette.setColor( QPalette::Text, Qt::blue);
897 QCOMPARE( newPalette, childWidget->palette() );
898 QCOMPARE( newPalette, grandChildWidget->palette() );
901 void tst_QWidget::palettePropagation2()
903 // ! Note, the code below is executed in tst_QWidget's constructor.
905 // font.setColor(QPalette::ToolTipBase, QColor(12, 13, 14));
906 // font.setColor(QPalette::Text, QColor(21, 22, 23));
907 // qApp->setPalette(palette, "QPropagationTestWidget");
909 QWidget *root = new QWidget;
910 QWidget *child0 = new QWidget(root);
911 QWidget *child1 = new QWidget(child0);
912 QWidget *child2 = new QPropagationTestWidget(child1);
913 QWidget *child3 = new QWidget(child2);
914 QWidget *child4 = new QWidget(child3);
915 QWidget *child5 = new QWidget(child4);
919 // These colors are unlikely to be imposed on the default palette of
921 QColor sysPalText(21, 22, 23);
922 QColor sysPalToolTipBase(12, 13, 14);
923 QColor overridePalText(42, 43, 44);
924 QColor overridePalToolTipBase(45, 46, 47);
925 QColor sysPalButton(99, 98, 97);
927 // Check that only the application fonts apply.
928 QPalette appPal = QApplication::palette();
929 QCOMPARE(root->palette(), appPal);
930 QCOMPARE(child0->palette(), appPal);
931 QCOMPARE(child1->palette(), appPal);
932 QCOMPARE(child2->palette().color(QPalette::ToolTipBase), sysPalToolTipBase);
933 QCOMPARE(child2->palette().color(QPalette::Text), sysPalText);
934 QCOMPARE(child2->palette().color(QPalette::ToolTipText), appPal.color(QPalette::ToolTipText));
935 QCOMPARE(child3->palette().color(QPalette::ToolTipBase), sysPalToolTipBase);
936 QCOMPARE(child3->palette().color(QPalette::Text), sysPalText);
937 QCOMPARE(child3->palette().color(QPalette::ToolTipText), appPal.color(QPalette::ToolTipText));
938 QCOMPARE(child4->palette().color(QPalette::ToolTipBase), sysPalToolTipBase);
939 QCOMPARE(child4->palette().color(QPalette::Text), sysPalText);
940 QCOMPARE(child4->palette().color(QPalette::ToolTipText), appPal.color(QPalette::ToolTipText));
941 QCOMPARE(child5->palette().color(QPalette::ToolTipBase), sysPalToolTipBase);
942 QCOMPARE(child5->palette().color(QPalette::Text), sysPalText);
943 QCOMPARE(child5->palette().color(QPalette::ToolTipText), appPal.color(QPalette::ToolTipText));
945 // Set child0's Text, and set ToolTipBase on child4.
946 QPalette textPalette;
947 textPalette.setColor(QPalette::Text, overridePalText);
948 child0->setPalette(textPalette);
949 QPalette toolTipPalette;
950 toolTipPalette.setColor(QPalette::ToolTipBase, overridePalToolTipBase);
951 child4->setPalette(toolTipPalette);
953 // Check that the above settings propagate correctly.
954 QCOMPARE(root->palette(), appPal);
955 QCOMPARE(child0->palette().color(QPalette::Text), overridePalText);
956 QCOMPARE(child0->palette().color(QPalette::ToolTipBase), appPal.color(QPalette::ToolTipBase));
957 QCOMPARE(child0->palette().color(QPalette::ToolTipText), appPal.color(QPalette::ToolTipText));
958 QCOMPARE(child1->palette().color(QPalette::Text), overridePalText);
959 QCOMPARE(child1->palette().color(QPalette::ToolTipBase), appPal.color(QPalette::ToolTipBase));
960 QCOMPARE(child1->palette().color(QPalette::ToolTipText), appPal.color(QPalette::ToolTipText));
961 QCOMPARE(child2->palette().color(QPalette::Text), overridePalText);
962 QCOMPARE(child2->palette().color(QPalette::ToolTipBase), sysPalToolTipBase);
963 QCOMPARE(child2->palette().color(QPalette::ToolTipText), appPal.color(QPalette::ToolTipText));
964 QCOMPARE(child3->palette().color(QPalette::Text), overridePalText);
965 QCOMPARE(child3->palette().color(QPalette::ToolTipBase), sysPalToolTipBase);
966 QCOMPARE(child3->palette().color(QPalette::ToolTipText), appPal.color(QPalette::ToolTipText));
967 QCOMPARE(child4->palette().color(QPalette::Text), overridePalText);
968 QCOMPARE(child4->palette().color(QPalette::ToolTipBase), overridePalToolTipBase);
969 QCOMPARE(child4->palette().color(QPalette::ToolTipText), appPal.color(QPalette::ToolTipText));
970 QCOMPARE(child5->palette().color(QPalette::Text), overridePalText);
971 QCOMPARE(child5->palette().color(QPalette::ToolTipBase), overridePalToolTipBase);
972 QCOMPARE(child5->palette().color(QPalette::ToolTipText), appPal.color(QPalette::ToolTipText));
974 // Replace the app palette for child2. Button should propagate but Text
975 // should still be ignored. The previous ToolTipBase setting is gone.
976 QPalette buttonPalette;
977 buttonPalette.setColor(QPalette::ToolTipText, sysPalButton);
978 qApp->setPalette(buttonPalette, "QPropagationTestWidget");
980 // Check that the above settings propagate correctly.
981 QCOMPARE(root->palette(), appPal);
982 QCOMPARE(child0->palette().color(QPalette::Text), overridePalText);
983 QCOMPARE(child0->palette().color(QPalette::ToolTipBase), appPal.color(QPalette::ToolTipBase));
984 QCOMPARE(child0->palette().color(QPalette::ToolTipText), appPal.color(QPalette::ToolTipText));
985 QCOMPARE(child1->palette().color(QPalette::Text), overridePalText);
986 QCOMPARE(child1->palette().color(QPalette::ToolTipBase), appPal.color(QPalette::ToolTipBase));
987 QCOMPARE(child1->palette().color(QPalette::ToolTipText), appPal.color(QPalette::ToolTipText));
988 QCOMPARE(child2->palette().color(QPalette::Text), overridePalText);
989 QCOMPARE(child2->palette().color(QPalette::ToolTipBase), appPal.color(QPalette::ToolTipBase));
990 QCOMPARE(child2->palette().color(QPalette::ToolTipText), sysPalButton);
991 QCOMPARE(child3->palette().color(QPalette::Text), overridePalText);
992 QCOMPARE(child3->palette().color(QPalette::ToolTipBase), appPal.color(QPalette::ToolTipBase));
993 QCOMPARE(child3->palette().color(QPalette::ToolTipText), sysPalButton);
994 QCOMPARE(child4->palette().color(QPalette::Text), overridePalText);
995 QCOMPARE(child4->palette().color(QPalette::ToolTipBase), overridePalToolTipBase);
996 QCOMPARE(child4->palette().color(QPalette::ToolTipText), sysPalButton);
997 QCOMPARE(child5->palette().color(QPalette::Text), overridePalText);
998 QCOMPARE(child5->palette().color(QPalette::ToolTipBase), overridePalToolTipBase);
999 QCOMPARE(child5->palette().color(QPalette::ToolTipText), sysPalButton);
1002 void tst_QWidget::enabledPropagation()
1004 QWidget* childWidget = new QWidget( testWidget );
1005 childWidget->show();
1006 QVERIFY( testWidget->isEnabled() );
1007 QVERIFY( childWidget->isEnabled() );
1009 testWidget->setEnabled( false );
1010 QVERIFY( !testWidget->isEnabled() );
1011 QVERIFY( !childWidget->isEnabled() );
1013 testWidget->setDisabled( false );
1014 QVERIFY( testWidget->isEnabled() );
1015 QVERIFY( childWidget->isEnabled() );
1017 QWidget* grandChildWidget = new QWidget( childWidget );
1018 QVERIFY( grandChildWidget->isEnabled() );
1020 testWidget->setDisabled( true );
1021 QVERIFY( !testWidget->isEnabled() );
1022 QVERIFY( !childWidget->isEnabled() );
1023 QVERIFY( !grandChildWidget->isEnabled() );
1025 grandChildWidget->setEnabled( false );
1026 testWidget->setEnabled( true );
1027 QVERIFY( testWidget->isEnabled() );
1028 QVERIFY( childWidget->isEnabled() );
1029 QVERIFY( !grandChildWidget->isEnabled() );
1031 grandChildWidget->setEnabled( true );
1032 testWidget->setEnabled( false );
1033 childWidget->setDisabled( true );
1034 testWidget->setEnabled( true );
1035 QVERIFY( testWidget->isEnabled() );
1036 QVERIFY( !childWidget->isEnabled() );
1037 QVERIFY( !grandChildWidget->isEnabled() );
1040 // Drag'n drop disabled in this build.
1041 #ifndef QT_NO_DRAGANDDROP
1042 void tst_QWidget::acceptDropsPropagation()
1044 QWidget *childWidget = new QWidget(testWidget);
1045 childWidget->show();
1046 QVERIFY(!testWidget->acceptDrops());
1047 QVERIFY(!childWidget->acceptDrops());
1049 testWidget->setAcceptDrops(true);
1050 QVERIFY(testWidget->acceptDrops());
1051 QVERIFY(!childWidget->acceptDrops());
1052 QVERIFY(childWidget->testAttribute(Qt::WA_DropSiteRegistered));
1054 testWidget->setAcceptDrops(false);
1055 QVERIFY(!testWidget->acceptDrops());
1056 QVERIFY(!childWidget->acceptDrops());
1057 QVERIFY(!childWidget->testAttribute(Qt::WA_DropSiteRegistered));
1059 QWidget *grandChildWidget = new QWidget(childWidget);
1060 QVERIFY(!grandChildWidget->acceptDrops());
1061 QVERIFY(!grandChildWidget->testAttribute(Qt::WA_DropSiteRegistered));
1063 testWidget->setAcceptDrops(true);
1064 QVERIFY(testWidget->acceptDrops());
1065 QVERIFY(!childWidget->acceptDrops());
1066 QVERIFY(childWidget->testAttribute(Qt::WA_DropSiteRegistered));
1067 QVERIFY(!grandChildWidget->acceptDrops());
1068 QVERIFY(grandChildWidget->testAttribute(Qt::WA_DropSiteRegistered));
1070 grandChildWidget->setAcceptDrops(true);
1071 testWidget->setAcceptDrops(false);
1072 QVERIFY(!testWidget->acceptDrops());
1073 QVERIFY(!childWidget->acceptDrops());
1074 QVERIFY(grandChildWidget->acceptDrops());
1075 QVERIFY(grandChildWidget->testAttribute(Qt::WA_DropSiteRegistered));
1077 grandChildWidget->setAcceptDrops(false);
1078 QVERIFY(!grandChildWidget->testAttribute(Qt::WA_DropSiteRegistered));
1079 testWidget->setAcceptDrops(true);
1080 childWidget->setAcceptDrops(true);
1081 testWidget->setAcceptDrops(false);
1082 QVERIFY(!testWidget->acceptDrops());
1083 QVERIFY(childWidget->acceptDrops());
1084 QVERIFY(!grandChildWidget->acceptDrops());
1085 QVERIFY(grandChildWidget->testAttribute(Qt::WA_DropSiteRegistered));
1089 void tst_QWidget::isEnabledTo()
1091 QWidget* childWidget = new QWidget( testWidget );
1092 QWidget* grandChildWidget = new QWidget( childWidget );
1094 QVERIFY( childWidget->isEnabledTo( testWidget ) );
1095 QVERIFY( grandChildWidget->isEnabledTo( testWidget ) );
1097 childWidget->setEnabled( false );
1098 QVERIFY( !childWidget->isEnabledTo( testWidget ) );
1099 QVERIFY( grandChildWidget->isEnabledTo( childWidget ) );
1100 QVERIFY( !grandChildWidget->isEnabledTo( testWidget ) );
1103 void tst_QWidget::visible()
1105 // Ensure that the testWidget is hidden for this test at the
1109 QVERIFY( !testWidget->isVisible() );
1110 QWidget* childWidget = new QWidget( testWidget );
1111 QVERIFY( !childWidget->isVisible() );
1114 QVERIFY( testWidget->isVisible() );
1115 QVERIFY( childWidget->isVisible() );
1117 QWidget* grandChildWidget = new QWidget( childWidget );
1118 QVERIFY( !grandChildWidget->isVisible() );
1119 grandChildWidget->show();
1120 QVERIFY( grandChildWidget->isVisible() );
1122 grandChildWidget->hide();
1125 QVERIFY( !grandChildWidget->isVisible() );
1126 QVERIFY( testWidget->isVisible() );
1127 QVERIFY( childWidget->isVisible() );
1129 grandChildWidget->show();
1130 childWidget->hide();
1133 QVERIFY( testWidget->isVisible() );
1134 QVERIFY( !childWidget->isVisible() );
1135 QVERIFY( !grandChildWidget->isVisible() );
1137 grandChildWidget->show();
1138 QVERIFY( !grandChildWidget->isVisible() );
1141 void tst_QWidget::setLocale()
1144 QCOMPARE(w.locale(), QLocale());
1146 w.setLocale(QLocale::Italian);
1147 QCOMPARE(w.locale(), QLocale(QLocale::Italian));
1150 QCOMPARE(child1.locale(), QLocale(QLocale::Italian));
1153 QCOMPARE(w.locale(), QLocale());
1154 QCOMPARE(child1.locale(), QLocale());
1156 w.setLocale(QLocale::French);
1157 QCOMPARE(w.locale(), QLocale(QLocale::French));
1158 QCOMPARE(child1.locale(), QLocale(QLocale::French));
1160 child1.setLocale(QLocale::Italian);
1161 QCOMPARE(w.locale(), QLocale(QLocale::French));
1162 QCOMPARE(child1.locale(), QLocale(QLocale::Italian));
1164 child1.unsetLocale();
1165 QCOMPARE(w.locale(), QLocale(QLocale::French));
1166 QCOMPARE(child1.locale(), QLocale(QLocale::French));
1169 QCOMPARE(child2.locale(), QLocale());
1170 child2.setParent(&w);
1171 QCOMPARE(child2.locale(), QLocale(QLocale::French));
1174 void tst_QWidget::visible_setWindowOpacity()
1177 QVERIFY( !testWidget->isVisible() );
1178 testWidget->setWindowOpacity(0.5);
1180 QVERIFY(!::IsWindowVisible(winHandleOf(testWidget)));
1182 testWidget->setWindowOpacity(1.0);
1185 void tst_QWidget::isVisibleTo()
1187 // Ensure that the testWidget is hidden for this test at the
1191 QWidget* childWidget = new QWidget( testWidget );
1192 QVERIFY( childWidget->isVisibleTo( testWidget ) );
1193 childWidget->hide();
1194 QVERIFY( !childWidget->isVisibleTo( testWidget ) );
1196 QWidget* grandChildWidget = new QWidget( childWidget );
1197 QVERIFY( !grandChildWidget->isVisibleTo( testWidget ) );
1198 QVERIFY( grandChildWidget->isVisibleTo( childWidget ) );
1201 childWidget->show();
1203 QVERIFY( childWidget->isVisibleTo( testWidget ) );
1204 grandChildWidget->hide();
1205 QVERIFY( !grandChildWidget->isVisibleTo( childWidget ) );
1206 QVERIFY( !grandChildWidget->isVisibleTo( testWidget ) );
1210 void tst_QWidget::isHidden()
1212 // Ensure that the testWidget is hidden for this test at the
1216 QVERIFY( testWidget->isHidden() );
1217 QWidget* childWidget = new QWidget( testWidget );
1218 QVERIFY( !childWidget->isHidden() );
1221 QVERIFY( !testWidget->isHidden() );
1222 QVERIFY( !childWidget->isHidden() );
1224 QWidget* grandChildWidget = new QWidget( childWidget );
1225 QVERIFY( grandChildWidget->isHidden() );
1226 grandChildWidget->show();
1227 QVERIFY( !grandChildWidget->isHidden() );
1229 grandChildWidget->hide();
1232 QVERIFY( grandChildWidget->isHidden() );
1233 QVERIFY( !testWidget->isHidden() );
1234 QVERIFY( !childWidget->isHidden() );
1236 grandChildWidget->show();
1237 childWidget->hide();
1240 QVERIFY( !testWidget->isHidden() );
1241 QVERIFY( childWidget->isHidden() );
1242 QVERIFY( !grandChildWidget->isHidden() );
1244 grandChildWidget->show();
1245 QVERIFY( !grandChildWidget->isHidden() );
1248 void tst_QWidget::fonts()
1250 // Tests setFont(), ownFont() and unsetFont()
1251 QWidget* cleanTestWidget = new QWidget( testWidget );
1252 QFont originalFont = cleanTestWidget->font();
1254 QVERIFY( !cleanTestWidget->testAttribute(Qt::WA_SetFont) );
1255 cleanTestWidget->setFont(QFont());
1256 QVERIFY( !cleanTestWidget->testAttribute(Qt::WA_SetFont) );
1258 QFont newFont( "times", 18 );
1259 cleanTestWidget->setFont( newFont );
1260 newFont = newFont.resolve( testWidget->font() );
1262 QVERIFY( cleanTestWidget->testAttribute(Qt::WA_SetFont) );
1263 QVERIFY( cleanTestWidget->font() == newFont );
1265 cleanTestWidget->setFont(QFont());
1266 QVERIFY( !cleanTestWidget->testAttribute(Qt::WA_SetFont) );
1267 QVERIFY( cleanTestWidget->font() == originalFont );
1270 void tst_QWidget::mapFromAndTo_data()
1272 QTest::addColumn<bool>("windowHidden");
1273 QTest::addColumn<bool>("subWindow1Hidden");
1274 QTest::addColumn<bool>("subWindow2Hidden");
1275 QTest::addColumn<bool>("subSubWindowHidden");
1276 QTest::addColumn<bool>("windowMinimized");
1277 QTest::addColumn<bool>("subWindow1Minimized");
1279 QTest::newRow("window 1 sub1 1 sub2 1 subsub 1") << false << false << false << false << false << false;
1280 QTest::newRow("window 0 sub1 1 sub2 1 subsub 1") << true << false << false << false << false << false;
1281 QTest::newRow("window 1 sub1 0 sub2 1 subsub 1") << false << true << false << false << false << false;
1282 QTest::newRow("window 0 sub1 0 sub2 1 subsub 1") << true << true << false << false << false << false;
1283 QTest::newRow("window 1 sub1 1 sub2 0 subsub 1") << false << false << true << false << false << false;
1284 QTest::newRow("window 0 sub1 1 sub2 0 subsub 1") << true << false << true << false << false << false;
1285 QTest::newRow("window 1 sub1 0 sub2 0 subsub 1") << false << true << true << false << false << false;
1286 QTest::newRow("window 0 sub1 0 sub2 0 subsub 1") << true << true << true << false << false << false;
1287 QTest::newRow("window 1 sub1 1 sub2 1 subsub 0") << false << false << false << true << false << false;
1288 QTest::newRow("window 0 sub1 1 sub2 1 subsub 0") << true << false << false << true << false << false;
1289 QTest::newRow("window 1 sub1 0 sub2 1 subsub 0") << false << true << false << true << false << false;
1290 QTest::newRow("window 0 sub1 0 sub2 1 subsub 0") << true << true << false << true << false << false;
1291 QTest::newRow("window 1 sub1 1 sub2 0 subsub 0") << false << false << true << true << false << false;
1292 QTest::newRow("window 0 sub1 1 sub2 0 subsub 0") << true << false << true << true << false << false;
1293 QTest::newRow("window 1 sub1 0 sub2 0 subsub 0") << false << true << true << true << false << false;
1294 QTest::newRow("window 0 sub1 0 sub2 0 subsub 0") << true << true << true << true << false << false;
1295 QTest::newRow("window 1 sub1 1 sub2 1 subsub 1 windowMinimized") << false << false << false << false << true << false;
1296 QTest::newRow("window 0 sub1 1 sub2 1 subsub 1 windowMinimized") << true << false << false << false << true << false;
1297 QTest::newRow("window 1 sub1 0 sub2 1 subsub 1 windowMinimized") << false << true << false << false << true << false;
1298 QTest::newRow("window 0 sub1 0 sub2 1 subsub 1 windowMinimized") << true << true << false << false << true << false;
1299 QTest::newRow("window 1 sub1 1 sub2 0 subsub 1 windowMinimized") << false << false << true << false << true << false;
1300 QTest::newRow("window 0 sub1 1 sub2 0 subsub 1 windowMinimized") << true << false << true << false << true << false;
1301 QTest::newRow("window 1 sub1 0 sub2 0 subsub 1 windowMinimized") << false << true << true << false << true << false;
1302 QTest::newRow("window 0 sub1 0 sub2 0 subsub 1 windowMinimized") << true << true << true << false << true << false;
1303 QTest::newRow("window 1 sub1 1 sub2 1 subsub 0 windowMinimized") << false << false << false << true << true << false;
1304 QTest::newRow("window 0 sub1 1 sub2 1 subsub 0 windowMinimized") << true << false << false << true << true << false;
1305 QTest::newRow("window 1 sub1 0 sub2 1 subsub 0 windowMinimized") << false << true << false << true << true << false;
1306 QTest::newRow("window 0 sub1 0 sub2 1 subsub 0 windowMinimized") << true << true << false << true << true << false;
1307 QTest::newRow("window 1 sub1 1 sub2 0 subsub 0 windowMinimized") << false << false << true << true << true << false;
1308 QTest::newRow("window 0 sub1 1 sub2 0 subsub 0 windowMinimized") << true << false << true << true << true << false;
1309 QTest::newRow("window 1 sub1 0 sub2 0 subsub 0 windowMinimized") << false << true << true << true << true << false;
1310 QTest::newRow("window 0 sub1 0 sub2 0 subsub 0 windowMinimized") << true << true << true << true << true << false;
1311 QTest::newRow("window 1 sub1 1 sub2 1 subsub 1 subWindow1Minimized") << false << false << false << false << false << true;
1312 QTest::newRow("window 0 sub1 1 sub2 1 subsub 1 subWindow1Minimized") << true << false << false << false << false << true;
1313 QTest::newRow("window 1 sub1 0 sub2 1 subsub 1 subWindow1Minimized") << false << true << false << false << false << true;
1314 QTest::newRow("window 0 sub1 0 sub2 1 subsub 1 subWindow1Minimized") << true << true << false << false << false << true;
1315 QTest::newRow("window 1 sub1 1 sub2 0 subsub 1 subWindow1Minimized") << false << false << true << false << false << true;
1316 QTest::newRow("window 0 sub1 1 sub2 0 subsub 1 subWindow1Minimized") << true << false << true << false << false << true;
1317 QTest::newRow("window 1 sub1 0 sub2 0 subsub 1 subWindow1Minimized") << false << true << true << false << false << true;
1318 QTest::newRow("window 0 sub1 0 sub2 0 subsub 1 subWindow1Minimized") << true << true << true << false << false << true;
1319 QTest::newRow("window 1 sub1 1 sub2 1 subsub 0 subWindow1Minimized") << false << false << false << true << false << true;
1320 QTest::newRow("window 0 sub1 1 sub2 1 subsub 0 subWindow1Minimized") << true << false << false << true << false << true;
1321 QTest::newRow("window 1 sub1 0 sub2 1 subsub 0 subWindow1Minimized") << false << true << false << true << false << true;
1322 QTest::newRow("window 0 sub1 0 sub2 1 subsub 0 subWindow1Minimized") << true << true << false << true << false << true;
1323 QTest::newRow("window 1 sub1 1 sub2 0 subsub 0 subWindow1Minimized") << false << false << true << true << false << true;
1324 QTest::newRow("window 0 sub1 1 sub2 0 subsub 0 subWindow1Minimized") << true << false << true << true << false << true;
1325 QTest::newRow("window 1 sub1 0 sub2 0 subsub 0 subWindow1Minimized") << false << true << true << true << false << true;
1326 QTest::newRow("window 0 sub1 0 sub2 0 subsub 0 subWindow1Minimized") << true << true << true << true << false << true;
1331 void tst_QWidget::mapFromAndTo()
1333 QFETCH(bool, windowHidden);
1334 QFETCH(bool, subWindow1Hidden);
1335 QFETCH(bool, subWindow2Hidden);
1336 QFETCH(bool, subSubWindowHidden);
1337 QFETCH(bool, windowMinimized);
1338 QFETCH(bool, subWindow1Minimized);
1340 // create a toplevel and two overlapping siblings
1342 window.setWindowFlags(window.windowFlags() | Qt::X11BypassWindowManagerHint);
1343 QWidget *subWindow1 = new QWidget(&window);
1344 QWidget *subWindow2 = new QWidget(&window);
1345 QWidget *subSubWindow = new QWidget(subWindow1);
1347 // set their geometries
1348 window.setGeometry(100, 100, 100, 100);
1349 subWindow1->setGeometry(50, 50, 100, 100);
1350 subWindow2->setGeometry(75, 75, 100, 100);
1351 subSubWindow->setGeometry(10, 10, 10, 10);
1353 #if !defined (Q_OS_WINCE) //still no proper minimizing
1355 if (windowMinimized) {
1356 if (!windowHidden) {
1357 window.showMinimized();
1358 QVERIFY(window.isMinimized());
1361 window.setVisible(!windowHidden);
1363 if (subWindow1Minimized) {
1365 subWindow1->showMinimized();
1366 QVERIFY(subWindow1->isMinimized());
1368 subWindow1->setVisible(!subWindow1Hidden);
1371 Q_UNUSED(windowHidden);
1372 Q_UNUSED(subWindow1Hidden);
1373 Q_UNUSED(windowMinimized);
1374 Q_UNUSED(subWindow1Minimized);
1377 subWindow2->setVisible(!subWindow2Hidden);
1378 subSubWindow->setVisible(!subSubWindowHidden);
1381 QCOMPARE(window.mapToGlobal(QPoint(0, 0)), QPoint(100, 100));
1382 QCOMPARE(window.mapToGlobal(QPoint(10, 0)), QPoint(110, 100));
1383 QCOMPARE(window.mapToGlobal(QPoint(0, 10)), QPoint(100, 110));
1384 QCOMPARE(window.mapToGlobal(QPoint(-10, 0)), QPoint(90, 100));
1385 QCOMPARE(window.mapToGlobal(QPoint(0, -10)), QPoint(100, 90));
1386 QCOMPARE(window.mapToGlobal(QPoint(100, 100)), QPoint(200, 200));
1387 QCOMPARE(window.mapToGlobal(QPoint(110, 100)), QPoint(210, 200));
1388 QCOMPARE(window.mapToGlobal(QPoint(100, 110)), QPoint(200, 210));
1389 QCOMPARE(window.mapFromGlobal(QPoint(100, 100)), QPoint(0, 0));
1390 QCOMPARE(window.mapFromGlobal(QPoint(110, 100)), QPoint(10, 0));
1391 QCOMPARE(window.mapFromGlobal(QPoint(100, 110)), QPoint(0, 10));
1392 QCOMPARE(window.mapFromGlobal(QPoint(90, 100)), QPoint(-10, 0));
1393 QCOMPARE(window.mapFromGlobal(QPoint(100, 90)), QPoint(0, -10));
1394 QCOMPARE(window.mapFromGlobal(QPoint(200, 200)), QPoint(100, 100));
1395 QCOMPARE(window.mapFromGlobal(QPoint(210, 200)), QPoint(110, 100));
1396 QCOMPARE(window.mapFromGlobal(QPoint(200, 210)), QPoint(100, 110));
1397 QCOMPARE(window.mapToParent(QPoint(0, 0)), QPoint(100, 100));
1398 QCOMPARE(window.mapToParent(QPoint(10, 0)), QPoint(110, 100));
1399 QCOMPARE(window.mapToParent(QPoint(0, 10)), QPoint(100, 110));
1400 QCOMPARE(window.mapToParent(QPoint(-10, 0)), QPoint(90, 100));
1401 QCOMPARE(window.mapToParent(QPoint(0, -10)), QPoint(100, 90));
1402 QCOMPARE(window.mapToParent(QPoint(100, 100)), QPoint(200, 200));
1403 QCOMPARE(window.mapToParent(QPoint(110, 100)), QPoint(210, 200));
1404 QCOMPARE(window.mapToParent(QPoint(100, 110)), QPoint(200, 210));
1405 QCOMPARE(window.mapFromParent(QPoint(100, 100)), QPoint(0, 0));
1406 QCOMPARE(window.mapFromParent(QPoint(110, 100)), QPoint(10, 0));
1407 QCOMPARE(window.mapFromParent(QPoint(100, 110)), QPoint(0, 10));
1408 QCOMPARE(window.mapFromParent(QPoint(90, 100)), QPoint(-10, 0));
1409 QCOMPARE(window.mapFromParent(QPoint(100, 90)), QPoint(0, -10));
1410 QCOMPARE(window.mapFromParent(QPoint(200, 200)), QPoint(100, 100));
1411 QCOMPARE(window.mapFromParent(QPoint(210, 200)), QPoint(110, 100));
1412 QCOMPARE(window.mapFromParent(QPoint(200, 210)), QPoint(100, 110));
1415 QCOMPARE(subWindow1->mapToGlobal(QPoint(0, 0)), QPoint(150, 150));
1416 QCOMPARE(subWindow1->mapToGlobal(QPoint(10, 0)), QPoint(160, 150));
1417 QCOMPARE(subWindow1->mapToGlobal(QPoint(0, 10)), QPoint(150, 160));
1418 QCOMPARE(subWindow1->mapToGlobal(QPoint(-10, 0)), QPoint(140, 150));
1419 QCOMPARE(subWindow1->mapToGlobal(QPoint(0, -10)), QPoint(150, 140));
1420 QCOMPARE(subWindow1->mapToGlobal(QPoint(100, 100)), QPoint(250, 250));
1421 QCOMPARE(subWindow1->mapToGlobal(QPoint(110, 100)), QPoint(260, 250));
1422 QCOMPARE(subWindow1->mapToGlobal(QPoint(100, 110)), QPoint(250, 260));
1423 QCOMPARE(subWindow1->mapFromGlobal(QPoint(150, 150)), QPoint(0, 0));
1424 QCOMPARE(subWindow1->mapFromGlobal(QPoint(160, 150)), QPoint(10, 0));
1425 QCOMPARE(subWindow1->mapFromGlobal(QPoint(150, 160)), QPoint(0, 10));
1426 QCOMPARE(subWindow1->mapFromGlobal(QPoint(140, 150)), QPoint(-10, 0));
1427 QCOMPARE(subWindow1->mapFromGlobal(QPoint(150, 140)), QPoint(0, -10));
1428 QCOMPARE(subWindow1->mapFromGlobal(QPoint(250, 250)), QPoint(100, 100));
1429 QCOMPARE(subWindow1->mapFromGlobal(QPoint(260, 250)), QPoint(110, 100));
1430 QCOMPARE(subWindow1->mapFromGlobal(QPoint(250, 260)), QPoint(100, 110));
1431 QCOMPARE(subWindow1->mapToParent(QPoint(0, 0)), QPoint(50, 50));
1432 QCOMPARE(subWindow1->mapToParent(QPoint(10, 0)), QPoint(60, 50));
1433 QCOMPARE(subWindow1->mapToParent(QPoint(0, 10)), QPoint(50, 60));
1434 QCOMPARE(subWindow1->mapToParent(QPoint(-10, 0)), QPoint(40, 50));
1435 QCOMPARE(subWindow1->mapToParent(QPoint(0, -10)), QPoint(50, 40));
1436 QCOMPARE(subWindow1->mapToParent(QPoint(100, 100)), QPoint(150, 150));
1437 QCOMPARE(subWindow1->mapToParent(QPoint(110, 100)), QPoint(160, 150));
1438 QCOMPARE(subWindow1->mapToParent(QPoint(100, 110)), QPoint(150, 160));
1439 QCOMPARE(subWindow1->mapFromParent(QPoint(50, 50)), QPoint(0, 0));
1440 QCOMPARE(subWindow1->mapFromParent(QPoint(60, 50)), QPoint(10, 0));
1441 QCOMPARE(subWindow1->mapFromParent(QPoint(50, 60)), QPoint(0, 10));
1442 QCOMPARE(subWindow1->mapFromParent(QPoint(40, 50)), QPoint(-10, 0));
1443 QCOMPARE(subWindow1->mapFromParent(QPoint(50, 40)), QPoint(0, -10));
1444 QCOMPARE(subWindow1->mapFromParent(QPoint(150, 150)), QPoint(100, 100));
1445 QCOMPARE(subWindow1->mapFromParent(QPoint(160, 150)), QPoint(110, 100));
1446 QCOMPARE(subWindow1->mapFromParent(QPoint(150, 160)), QPoint(100, 110));
1449 QCOMPARE(subSubWindow->mapToGlobal(QPoint(0, 0)), QPoint(160, 160));
1450 QCOMPARE(subSubWindow->mapToGlobal(QPoint(10, 0)), QPoint(170, 160));
1451 QCOMPARE(subSubWindow->mapToGlobal(QPoint(0, 10)), QPoint(160, 170));
1452 QCOMPARE(subSubWindow->mapToGlobal(QPoint(-10, 0)), QPoint(150, 160));
1453 QCOMPARE(subSubWindow->mapToGlobal(QPoint(0, -10)), QPoint(160, 150));
1454 QCOMPARE(subSubWindow->mapToGlobal(QPoint(100, 100)), QPoint(260, 260));
1455 QCOMPARE(subSubWindow->mapToGlobal(QPoint(110, 100)), QPoint(270, 260));
1456 QCOMPARE(subSubWindow->mapToGlobal(QPoint(100, 110)), QPoint(260, 270));
1457 QCOMPARE(subSubWindow->mapFromGlobal(QPoint(160, 160)), QPoint(0, 0));
1458 QCOMPARE(subSubWindow->mapFromGlobal(QPoint(170, 160)), QPoint(10, 0));
1459 QCOMPARE(subSubWindow->mapFromGlobal(QPoint(160, 170)), QPoint(0, 10));
1460 QCOMPARE(subSubWindow->mapFromGlobal(QPoint(150, 160)), QPoint(-10, 0));
1461 QCOMPARE(subSubWindow->mapFromGlobal(QPoint(160, 150)), QPoint(0, -10));
1462 QCOMPARE(subSubWindow->mapFromGlobal(QPoint(260, 260)), QPoint(100, 100));
1463 QCOMPARE(subSubWindow->mapFromGlobal(QPoint(270, 260)), QPoint(110, 100));
1464 QCOMPARE(subSubWindow->mapFromGlobal(QPoint(260, 270)), QPoint(100, 110));
1465 QCOMPARE(subSubWindow->mapToParent(QPoint(0, 0)), QPoint(10, 10));
1466 QCOMPARE(subSubWindow->mapToParent(QPoint(10, 0)), QPoint(20, 10));
1467 QCOMPARE(subSubWindow->mapToParent(QPoint(0, 10)), QPoint(10, 20));
1468 QCOMPARE(subSubWindow->mapToParent(QPoint(-10, 0)), QPoint(0, 10));
1469 QCOMPARE(subSubWindow->mapToParent(QPoint(0, -10)), QPoint(10, 0));
1470 QCOMPARE(subSubWindow->mapToParent(QPoint(100, 100)), QPoint(110, 110));
1471 QCOMPARE(subSubWindow->mapToParent(QPoint(110, 100)), QPoint(120, 110));
1472 QCOMPARE(subSubWindow->mapToParent(QPoint(100, 110)), QPoint(110, 120));
1473 QCOMPARE(subSubWindow->mapFromParent(QPoint(10, 10)), QPoint(0, 0));
1474 QCOMPARE(subSubWindow->mapFromParent(QPoint(20, 10)), QPoint(10, 0));
1475 QCOMPARE(subSubWindow->mapFromParent(QPoint(10, 20)), QPoint(0, 10));
1476 QCOMPARE(subSubWindow->mapFromParent(QPoint(0, 10)), QPoint(-10, 0));
1477 QCOMPARE(subSubWindow->mapFromParent(QPoint(10, 0)), QPoint(0, -10));
1478 QCOMPARE(subSubWindow->mapFromParent(QPoint(110, 110)), QPoint(100, 100));
1479 QCOMPARE(subSubWindow->mapFromParent(QPoint(120, 110)), QPoint(110, 100));
1480 QCOMPARE(subSubWindow->mapFromParent(QPoint(110, 120)), QPoint(100, 110));
1483 void tst_QWidget::focusChainOnReparent()
1486 QWidget *child1 = new QWidget(&window);
1487 QWidget *child2 = new QWidget(&window);
1488 QWidget *child3 = new QWidget(&window);
1489 QWidget *child21 = new QWidget(child2);
1490 QWidget *child22 = new QWidget(child2);
1491 QWidget *child4 = new QWidget(&window);
1493 QWidget *expectedOriginalChain[8] = {&window, child1, child2, child3, child21, child22, child4, &window};
1494 QWidget *w = &window;
1495 for (int i = 0; i <8; ++i) {
1496 QCOMPARE(w, expectedOriginalChain[i]);
1497 w = w->nextInFocusChain();
1499 for (int i = 7; i >= 0; --i) {
1500 w = w->previousInFocusChain();
1501 QCOMPARE(w, expectedOriginalChain[i]);
1505 child2->setParent(&window2);
1507 QWidget *expectedNewChain[5] = {&window2, child2, child21, child22, &window2};
1509 for (int i = 0; i <5; ++i) {
1510 QCOMPARE(w, expectedNewChain[i]);
1511 w = w->nextInFocusChain();
1513 for (int i = 4; i >= 0; --i) {
1514 w = w->previousInFocusChain();
1515 QCOMPARE(w, expectedNewChain[i]);
1518 QWidget *expectedOldChain[5] = {&window, child1, child3, child4, &window};
1520 for (int i = 0; i <5; ++i) {
1521 QCOMPARE(w, expectedOldChain[i]);
1522 w = w->nextInFocusChain();
1524 for (int i = 4; i >= 0; --i) {
1525 w = w->previousInFocusChain();
1526 QCOMPARE(w, expectedOldChain[i]);
1531 void tst_QWidget::focusChainOnHide()
1533 testWidget->hide(); // We do not want to get disturbed by other widgets
1534 // focus should move to the next widget in the focus chain when we hide it.
1535 QWidget *parent = new QWidget();
1536 parent->setObjectName(QLatin1String("Parent"));
1537 parent->setFocusPolicy(Qt::StrongFocus);
1538 QWidget *child = new QWidget(parent);
1539 child->setObjectName(QLatin1String("child"));
1540 child->setFocusPolicy(Qt::StrongFocus);
1541 QWidget::setTabOrder(child, parent);
1544 qApp->setActiveWindow(parent->window());
1545 child->activateWindow();
1547 qApp->processEvents();
1549 QTRY_COMPARE(child->hasFocus(), true);
1551 qApp->processEvents();
1553 QTRY_COMPARE(parent->hasFocus(), true);
1554 QCOMPARE(parent, qApp->focusWidget());
1557 testWidget->show(); //don't disturb later tests
1560 class Container : public QWidget
1567 box = new QVBoxLayout(this);
1568 //(new QVBoxLayout(this))->setAutoAdd(true);
1573 focusNextPrevChild(true);
1578 focusNextPrevChild(false);
1582 class Composite : public QFrame
1585 Composite(QWidget* parent = 0, const char* name = 0)
1588 setObjectName(name);
1589 //QHBoxLayout* hbox = new QHBoxLayout(this, 2, 0);
1590 //hbox->setAutoAdd(true);
1591 QHBoxLayout* hbox = new QHBoxLayout(this);
1593 lineEdit = new QLineEdit(this);
1594 hbox->addWidget(lineEdit);
1596 button = new QPushButton(this);
1597 hbox->addWidget(button);
1598 button->setFocusPolicy( Qt::NoFocus );
1600 setFocusProxy( lineEdit );
1601 setFocusPolicy( Qt::StrongFocus );
1603 setTabOrder(lineEdit, button);
1607 QLineEdit* lineEdit;
1608 QPushButton* button;
1611 #define NUM_WIDGETS 4
1613 void tst_QWidget::setTabOrder()
1617 Container container;
1619 Composite* comp[NUM_WIDGETS];
1621 QLineEdit *firstEdit = new QLineEdit(&container);
1622 container.box->addWidget(firstEdit);
1625 for(i = 0; i < NUM_WIDGETS; i++) {
1626 comp[i] = new Composite(&container);
1627 container.box->addWidget(comp[i]);
1630 QLineEdit *lastEdit = new QLineEdit(&container);
1631 container.box->addWidget(lastEdit);
1633 container.setTabOrder(lastEdit, comp[NUM_WIDGETS-1]);
1634 for(i = NUM_WIDGETS-1; i > 0; i--) {
1635 container.setTabOrder(comp[i], comp[i-1]);
1637 container.setTabOrder(comp[0], firstEdit);
1639 int current = NUM_WIDGETS-1;
1640 lastEdit->setFocus();
1643 container.activateWindow();
1644 qApp->setActiveWindow(&container);
1645 QTest::qWaitForWindowShown(container.windowHandle());
1648 QTRY_VERIFY(lastEdit->hasFocus());
1651 QVERIFY(comp[current]->focusProxy()->hasFocus());
1654 } while (current >= 0);
1656 QVERIFY(firstEdit->hasFocus());
1660 void tst_QWidget::activation()
1664 #if defined(Q_OS_WINCE)
1665 int waitTime = 1000;
1671 qApp->processEvents();
1674 widget1.setWindowTitle("Widget1");
1677 widget2.setWindowTitle("Widget2");
1682 QTest::qWait(waitTime);
1683 QVERIFY(qApp->activeWindow() == &widget2);
1684 widget2.showMinimized();
1685 QTest::qWait(waitTime);
1687 QEXPECT_FAIL("", "QTBUG-26418", Continue);
1688 QVERIFY(qApp->activeWindow() == &widget1);
1689 widget2.showMaximized();
1690 QTest::qWait(waitTime);
1691 QVERIFY(qApp->activeWindow() == &widget2);
1692 widget2.showMinimized();
1693 QTest::qWait(waitTime);
1694 QEXPECT_FAIL("", "QTBUG-26418", Continue);
1695 QVERIFY(qApp->activeWindow() == &widget1);
1696 widget2.showNormal();
1697 QTest::qWait(waitTime);
1698 #if 0 // QTBUG-26418, widget2 is always set to active
1700 if (QSysInfo::WindowsVersion >= QSysInfo::WV_VISTA)
1701 QEXPECT_FAIL("", "MS introduced new behavior after XP", Continue);
1704 QTest::qWait(waitTime);
1705 QVERIFY(qApp->activeWindow() == &widget2);
1707 QTest::qWait(waitTime);
1708 QVERIFY(qApp->activeWindow() == &widget1);
1712 void tst_QWidget::windowState()
1714 if (m_platform == QStringLiteral("xcb"))
1715 QSKIP("X11: Many window managers do not support window state properly, which causes this test to fail.");
1716 #ifdef Q_OS_WINCE_WM
1717 QPoint pos(500, 500);
1718 QSize size(200, 200);
1719 if (qt_wince_is_smartphone()) { //small screen
1720 pos = QPoint(10,10);
1721 size = QSize(100,100);
1724 const QPoint pos(500, 500);
1725 const QSize size(200, 200);
1730 widget1.resize(size);
1731 QCOMPARE(widget1.pos(), pos);
1732 QCOMPARE(widget1.size(), size);
1734 widget1.setWindowTitle("Widget1");
1735 QCOMPARE(widget1.pos(), pos);
1736 QCOMPARE(widget1.size(), size);
1738 #define VERIFY_STATE(s) QCOMPARE(int(widget1.windowState() & stateMask), int(s))
1740 const int stateMask = Qt::WindowMaximized|Qt::WindowMinimized|Qt::WindowFullScreen;
1742 widget1.setWindowState(Qt::WindowMaximized);
1744 VERIFY_STATE(Qt::WindowMaximized);
1745 QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowMaximized);
1749 VERIFY_STATE(Qt::WindowMaximized);
1750 QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowMaximized);
1752 widget1.setWindowState(widget1.windowState() ^ Qt::WindowMaximized);
1754 QVERIFY(!(widget1.windowState() & Qt::WindowMaximized));
1755 QTRY_COMPARE(widget1.pos(), pos);
1756 QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowNoState);
1758 widget1.setWindowState(Qt::WindowMinimized);
1760 VERIFY_STATE(Qt::WindowMinimized);
1761 QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowMinimized);
1763 widget1.setWindowState(widget1.windowState() | Qt::WindowMaximized);
1765 VERIFY_STATE((Qt::WindowMinimized|Qt::WindowMaximized));
1766 QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowMinimized);
1768 widget1.setWindowState(widget1.windowState() ^ Qt::WindowMinimized);
1770 VERIFY_STATE(Qt::WindowMaximized);
1771 QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowMaximized);
1773 widget1.setWindowState(widget1.windowState() ^ Qt::WindowMaximized);
1775 QVERIFY(!(widget1.windowState() & (Qt::WindowMinimized|Qt::WindowMaximized)));
1776 QTRY_COMPARE(widget1.pos(), pos);
1777 QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowNoState);
1779 widget1.setWindowState(Qt::WindowFullScreen);
1781 VERIFY_STATE(Qt::WindowFullScreen);
1782 QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowFullScreen);
1784 widget1.setWindowState(widget1.windowState() ^ Qt::WindowMinimized);
1787 QEXPECT_FAIL("", "QTBUG-26420", Continue);
1789 VERIFY_STATE((Qt::WindowFullScreen|Qt::WindowMinimized));
1790 QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowMinimized);
1792 widget1.setWindowState(widget1.windowState() ^ Qt::WindowMinimized);
1795 QEXPECT_FAIL("", "QTBUG-26420", Continue);
1797 VERIFY_STATE(Qt::WindowFullScreen);
1799 QEXPECT_FAIL("", "QTBUG-26420", Continue);
1801 QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowFullScreen);
1803 widget1.setWindowState(Qt::WindowNoState);
1805 VERIFY_STATE(Qt::WindowNoState);
1806 QTRY_COMPARE(widget1.pos(), pos);
1807 QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowNoState);
1809 widget1.setWindowState(Qt::WindowFullScreen);
1811 VERIFY_STATE(Qt::WindowFullScreen);
1812 QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowFullScreen);
1814 widget1.setWindowState(widget1.windowState() ^ Qt::WindowMaximized);
1816 VERIFY_STATE((Qt::WindowFullScreen|Qt::WindowMaximized));
1817 QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowFullScreen);
1820 QSKIP("QTBUG-26420");
1823 widget1.setWindowState(widget1.windowState() ^ Qt::WindowMinimized);
1825 VERIFY_STATE((Qt::WindowFullScreen|Qt::WindowMaximized|Qt::WindowMinimized));
1826 QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowMinimized);
1828 widget1.setWindowState(widget1.windowState() ^ Qt::WindowMinimized);
1830 VERIFY_STATE((Qt::WindowFullScreen|Qt::WindowMaximized));
1831 QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowFullScreen);
1833 widget1.setWindowState(widget1.windowState() ^ Qt::WindowFullScreen);
1835 VERIFY_STATE(Qt::WindowMaximized);
1836 QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowMaximized);
1838 widget1.setWindowState(widget1.windowState() ^ Qt::WindowMaximized);
1840 QVERIFY(!(widget1.windowState() & stateMask));
1841 QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowNoState);
1843 QTRY_COMPARE(widget1.pos(), pos);
1844 QTRY_COMPARE(widget1.size(), size);
1847 void tst_QWidget::showMaximized()
1850 QHBoxLayout *layout;
1851 layout = new QHBoxLayout;
1857 layout->addWidget(&le);
1858 layout->addWidget(&le2);
1859 layout->addWidget(&le3);
1861 layouted.setLayout(layout);
1863 plain.showMaximized();
1864 QVERIFY(plain.windowState() & Qt::WindowMaximized);
1867 QVERIFY(!(plain.windowState() & Qt::WindowMaximized));
1869 layouted.showMaximized();
1870 QVERIFY(layouted.windowState() & Qt::WindowMaximized);
1872 layouted.showNormal();
1873 QVERIFY(!(layouted.windowState() & Qt::WindowMaximized));
1875 // ### fixme: embedded may choose a different size to fit on the screen.
1876 if (layouted.size() != layouted.sizeHint())
1877 QEXPECT_FAIL("", "QTBUG-22326", Continue);
1878 QCOMPARE(layouted.size(), layouted.sizeHint());
1880 layouted.showMaximized();
1881 QVERIFY(layouted.isMaximized());
1882 QVERIFY(layouted.isVisible());
1885 QVERIFY(layouted.isMaximized());
1886 QVERIFY(!layouted.isVisible());
1888 layouted.showMaximized();
1889 QVERIFY(layouted.isMaximized());
1890 QVERIFY(layouted.isVisible());
1892 layouted.showMinimized();
1893 QVERIFY(layouted.isMinimized());
1894 QVERIFY(layouted.isMaximized());
1896 layouted.showMaximized();
1897 QVERIFY(!layouted.isMinimized());
1898 QVERIFY(layouted.isMaximized());
1899 QVERIFY(layouted.isVisible());
1901 layouted.showMinimized();
1902 QVERIFY(layouted.isMinimized());
1903 QVERIFY(layouted.isMaximized());
1905 layouted.showMaximized();
1906 QVERIFY(!layouted.isMinimized());
1907 QVERIFY(layouted.isMaximized());
1908 QVERIFY(layouted.isVisible());
1912 QWidget widget(&frame);
1913 widget.showMaximized();
1914 QVERIFY(widget.isMaximized());
1919 widget.setGeometry(0, 0, 10, 10);
1920 widget.showMaximized();
1921 QTRY_VERIFY(widget.size().width() > 20 && widget.size().height() > 20);
1925 void tst_QWidget::showFullScreen()
1928 QHBoxLayout *layout;
1933 layout = new QHBoxLayout;
1935 layout->addWidget(&le);
1936 layout->addWidget(&le2);
1937 layout->addWidget(&le3);
1939 layouted.setLayout(layout);
1941 plain.showFullScreen();
1942 QVERIFY(plain.windowState() & Qt::WindowFullScreen);
1945 QVERIFY(!(plain.windowState() & Qt::WindowFullScreen));
1947 layouted.showFullScreen();
1948 QVERIFY(layouted.windowState() & Qt::WindowFullScreen);
1950 layouted.showNormal();
1951 QVERIFY(!(layouted.windowState() & Qt::WindowFullScreen));
1953 // ### fixme: embedded may choose a different size to fit on the screen.
1954 if (layouted.size() != layouted.sizeHint())
1955 QEXPECT_FAIL("", "QTBUG-22326", Continue);
1956 QCOMPARE(layouted.size(), layouted.sizeHint());
1958 layouted.showFullScreen();
1959 QVERIFY(layouted.isFullScreen());
1960 QVERIFY(layouted.isVisible());
1963 QVERIFY(layouted.isFullScreen());
1964 QVERIFY(!layouted.isVisible());
1966 layouted.showFullScreen();
1967 QVERIFY(layouted.isFullScreen());
1968 QVERIFY(layouted.isVisible());
1970 layouted.showMinimized();
1971 QVERIFY(layouted.isMinimized());
1972 QVERIFY(layouted.isFullScreen());
1974 layouted.showFullScreen();
1975 QVERIFY(!layouted.isMinimized());
1976 QVERIFY(layouted.isFullScreen());
1977 QVERIFY(layouted.isVisible());
1979 layouted.showMinimized();
1980 QVERIFY(layouted.isMinimized());
1981 QVERIFY(layouted.isFullScreen());
1983 layouted.showFullScreen();
1984 QVERIFY(!layouted.isMinimized());
1985 QVERIFY(layouted.isFullScreen());
1986 QVERIFY(layouted.isVisible());
1990 QWidget widget(&frame);
1991 widget.showFullScreen();
1992 QVERIFY(widget.isFullScreen());
1996 class ResizeWidget : public QWidget {
1998 ResizeWidget(QWidget *p = 0) : QWidget(p)
2000 m_resizeEventCount = 0;
2003 void resizeEvent(QResizeEvent *e){
2004 QCOMPARE(size(), e->size());
2005 ++m_resizeEventCount;
2009 int m_resizeEventCount;
2012 void tst_QWidget::resizeEvent()
2016 ResizeWidget wChild(&wParent);
2018 QCOMPARE (wChild.m_resizeEventCount, 1); // initial resize event before paint
2020 QSize safeSize(640,480);
2021 if (wChild.size() == safeSize)
2022 safeSize.setWidth(639);
2023 wChild.resize(safeSize);
2024 QCOMPARE (wChild.m_resizeEventCount, 1);
2026 QCOMPARE (wChild.m_resizeEventCount, 2);
2030 ResizeWidget wTopLevel;
2032 if (m_platform == QStringLiteral("windows"))
2033 QSKIP("QTBUG-26424");
2034 QCOMPARE (wTopLevel.m_resizeEventCount, 1); // initial resize event before paint for toplevels
2036 QSize safeSize(640,480);
2037 if (wTopLevel.size() == safeSize)
2038 safeSize.setWidth(639);
2039 wTopLevel.resize(safeSize);
2040 QCOMPARE (wTopLevel.m_resizeEventCount, 1);
2042 QCOMPARE (wTopLevel.m_resizeEventCount, 2);
2046 void tst_QWidget::showMinimized()
2049 plain.move(100, 100);
2050 plain.resize(200, 200);
2051 QPoint pos = plain.pos();
2053 plain.showMinimized();
2054 QVERIFY(plain.isMinimized());
2055 QVERIFY(plain.isVisible());
2056 QCOMPARE(plain.pos(), pos);
2059 QVERIFY(!plain.isMinimized());
2060 QVERIFY(plain.isVisible());
2061 QCOMPARE(plain.pos(), pos);
2063 plain.showMinimized();
2064 QVERIFY(plain.isMinimized());
2065 QVERIFY(plain.isVisible());
2066 QCOMPARE(plain.pos(), pos);
2069 QVERIFY(plain.isMinimized());
2070 QVERIFY(!plain.isVisible());
2072 plain.showMinimized();
2073 QVERIFY(plain.isMinimized());
2074 QVERIFY(plain.isVisible());
2076 plain.setGeometry(200, 200, 300, 300);
2078 QCOMPARE(plain.geometry(), QRect(200, 200, 300, 300));
2082 QWidget widget(&frame);
2083 widget.showMinimized();
2084 QVERIFY(widget.isMinimized());
2088 void tst_QWidget::showMinimizedKeepsFocus()
2090 if (m_platform == QStringLiteral("xcb"))
2091 QSKIP("QTBUG-26424");
2093 //here we test that minimizing a widget and restoring it doesn't change the focus inside of it
2096 QWidget child1(&window), child2(&window);
2097 child1.setFocusPolicy(Qt::StrongFocus);
2098 child2.setFocusPolicy(Qt::StrongFocus);
2100 qApp->setActiveWindow(&window);
2101 QTest::qWaitForWindowShown(&window);
2105 QTRY_COMPARE(window.focusWidget(), &child2);
2106 QTRY_COMPARE(qApp->focusWidget(), &child2);
2108 window.showMinimized();
2110 QTRY_VERIFY(window.isMinimized());
2111 QTRY_COMPARE(window.focusWidget(), &child2);
2113 window.showNormal();
2115 QTRY_COMPARE(window.focusWidget(), &child2);
2118 //testing deletion of the focusWidget
2121 QWidget *child = new QWidget(&window);
2122 child->setFocusPolicy(Qt::StrongFocus);
2124 qApp->setActiveWindow(&window);
2125 QTest::qWaitForWindowShown(&window);
2128 QTRY_COMPARE(window.focusWidget(), child);
2129 QTRY_COMPARE(qApp->focusWidget(), child);
2132 QCOMPARE(window.focusWidget(), static_cast<QWidget*>(0));
2133 QCOMPARE(qApp->focusWidget(), static_cast<QWidget*>(0));
2136 //testing reparenting the focus widget
2139 QWidget *child = new QWidget(&window);
2140 child->setFocusPolicy(Qt::StrongFocus);
2142 qApp->setActiveWindow(&window);
2143 QTest::qWaitForWindowShown(&window);
2146 QTRY_COMPARE(window.focusWidget(), child);
2147 QTRY_COMPARE(qApp->focusWidget(), child);
2149 child->setParent(0);
2150 QCOMPARE(window.focusWidget(), static_cast<QWidget*>(0));
2151 QCOMPARE(qApp->focusWidget(), static_cast<QWidget*>(0));
2154 //testing setEnabled(false)
2157 QWidget *child = new QWidget(&window);
2158 child->setFocusPolicy(Qt::StrongFocus);
2160 qApp->setActiveWindow(&window);
2161 QTest::qWaitForWindowShown(&window);
2164 QTRY_COMPARE(window.focusWidget(), child);
2165 QTRY_COMPARE(qApp->focusWidget(), child);
2167 child->setEnabled(false);
2168 QCOMPARE(window.focusWidget(), static_cast<QWidget*>(0));
2169 QCOMPARE(qApp->focusWidget(), static_cast<QWidget*>(0));
2172 //testing clearFocus
2175 QWidget *firstchild = new QWidget(&window);
2176 firstchild->setFocusPolicy(Qt::StrongFocus);
2177 QWidget *child = new QWidget(&window);
2178 child->setFocusPolicy(Qt::StrongFocus);
2180 qApp->setActiveWindow(&window);
2181 QTest::qWaitForWindowShown(&window);
2184 QTRY_COMPARE(window.focusWidget(), child);
2185 QTRY_COMPARE(qApp->focusWidget(), child);
2187 child->clearFocus();
2188 QCOMPARE(window.focusWidget(), static_cast<QWidget*>(0));
2189 QCOMPARE(qApp->focusWidget(), static_cast<QWidget*>(0));
2191 window.showMinimized();
2193 QTRY_VERIFY(window.isMinimized());
2194 QCOMPARE(window.focusWidget(), static_cast<QWidget*>(0));
2195 QTRY_COMPARE(qApp->focusWidget(), static_cast<QWidget*>(0));
2197 window.showNormal();
2198 qApp->setActiveWindow(&window);
2199 QTest::qWaitForWindowShown(&window);
2202 if (!macHasAccessToWindowsServer())
2203 QEXPECT_FAIL("", "When not having WindowServer access, we lose focus.", Continue);
2205 QTRY_COMPARE(window.focusWidget(), firstchild);
2207 if (!macHasAccessToWindowsServer())
2208 QEXPECT_FAIL("", "When not having WindowServer access, we lose focus.", Continue);
2210 QTRY_COMPARE(qApp->focusWidget(), firstchild);
2215 void tst_QWidget::reparent()
2218 parent.setWindowTitle("Toplevel");
2219 parent.setGeometry(300, 300, 200, 150);
2222 child.setObjectName("child");
2223 child.setGeometry(10, 10, 180, 130);
2225 pal1.setColor(child.backgroundRole(), Qt::white);
2226 child.setPalette(pal1);
2228 QWidget childTLW(&child, Qt::Window);
2229 childTLW.setObjectName("childTLW");
2230 childTLW.setGeometry(100, 100, 50, 50);
2232 pal2.setColor(childTLW.backgroundRole(), Qt::yellow);
2233 childTLW.setPalette(pal2);
2237 QTest::qWaitForWindowShown(&parent);
2240 parent.move(50, 50);
2242 parent.move(300, 300);
2245 QPoint childPos = parent.mapToGlobal(child.pos());
2246 QPoint tlwPos = childTLW.pos();
2248 child.setParent(0, child.windowFlags() & ~Qt::WindowType_Mask);
2249 child.setGeometry(childPos.x(), childPos.y(), child.width(), child.height());
2252 #if 0 // QTBUG-26424
2253 if (m_platform == QStringLiteral("xcb"))
2254 QEXPECT_FAIL("", "On X11, the window manager will apply NorthWestGravity rules to 'child', which"
2255 " means the top-left corner of the window frame will be placed at 'childPos'"
2256 " causing this test to fail.", Continue);
2259 QCOMPARE(child.geometry().topLeft(), childPos);
2260 QTRY_COMPARE(childTLW.pos(), tlwPos);
2263 // Qt/Embedded does it differently.
2264 void tst_QWidget::icon()
2268 testWidget->setWindowIcon(p);
2270 QVERIFY(!testWidget->windowIcon().isNull());
2272 QVERIFY(!testWidget->windowIcon().isNull());
2273 testWidget->showFullScreen();
2274 QVERIFY(!testWidget->windowIcon().isNull());
2275 testWidget->showNormal();
2276 QVERIFY(!testWidget->windowIcon().isNull());
2279 void tst_QWidget::hideWhenFocusWidgetIsChild()
2281 testWidget->activateWindow();
2282 QWidget *parentWidget = new QWidget(testWidget);
2283 parentWidget->setObjectName("parentWidget");
2284 parentWidget->setGeometry(0, 0, 100, 100);
2285 QLineEdit *edit = new QLineEdit(parentWidget);
2286 edit->setObjectName("edit1");
2287 QLineEdit *edit3 = new QLineEdit(parentWidget);
2288 edit3->setObjectName("edit3");
2290 parentWidget->show();
2291 QLineEdit *edit2 = new QLineEdit(testWidget);
2292 edit2->setObjectName("edit2");
2294 edit2->move(110, 100);
2296 qApp->processEvents();
2297 QString actualFocusWidget, expectedFocusWidget;
2298 if (!qApp->focusWidget() && m_platform == QStringLiteral("xcb"))
2299 QSKIP("X11: Your window manager is too broken for this test");
2301 QVERIFY(qApp->focusWidget());
2302 actualFocusWidget.sprintf("%p %s %s", qApp->focusWidget(), qApp->focusWidget()->objectName().toLatin1().constData(), qApp->focusWidget()->metaObject()->className());
2303 expectedFocusWidget.sprintf("%p %s %s", edit, edit->objectName().toLatin1().constData(), edit->metaObject()->className());
2304 QCOMPARE(actualFocusWidget, expectedFocusWidget);
2306 parentWidget->hide();
2307 qApp->processEvents();
2308 actualFocusWidget.sprintf("%p %s %s", qApp->focusWidget(), qApp->focusWidget()->objectName().toLatin1().constData(), qApp->focusWidget()->metaObject()->className());
2309 expectedFocusWidget.sprintf("%p %s %s", edit2, edit2->objectName().toLatin1().constData(), edit2->metaObject()->className());
2310 QCOMPARE(actualFocusWidget, expectedFocusWidget);
2313 delete parentWidget;
2316 void tst_QWidget::normalGeometry()
2319 parent.setWindowTitle("NormalGeometry parent");
2320 QWidget *child = new QWidget(&parent);
2322 QCOMPARE(parent.normalGeometry(), parent.geometry());
2323 QCOMPARE(child->normalGeometry(), QRect());
2325 parent.setGeometry(100, 100, 200, 200);
2327 QTest::qWaitForWindowShown(&parent);
2328 QApplication::processEvents();
2330 QRect geom = parent.geometry();
2331 // ### the window manager places the top-left corner at
2332 // ### 100,100... making geom something like 102,124 (offset by
2333 // ### the frame/frame)... this indicates a rather large different
2334 // ### between how X11 and Windows works
2335 // QCOMPARE(geom, QRect(100, 100, 200, 200));
2336 QCOMPARE(parent.normalGeometry(), geom);
2338 parent.setWindowState(parent.windowState() ^ Qt::WindowMaximized);
2340 QTRY_VERIFY(parent.windowState() & Qt::WindowMaximized);
2341 QTRY_VERIFY(parent.geometry() != geom);
2342 QTRY_COMPARE(parent.normalGeometry(), geom);
2344 parent.setWindowState(parent.windowState() ^ Qt::WindowMaximized);
2346 QTRY_VERIFY(!(parent.windowState() & Qt::WindowMaximized));
2347 QTRY_COMPARE(parent.geometry(), geom);
2348 QTRY_COMPARE(parent.normalGeometry(), geom);
2350 parent.showMaximized();
2352 QTRY_VERIFY(parent.windowState() & Qt::WindowMaximized);
2353 QTRY_VERIFY(parent.geometry() != geom);
2354 QCOMPARE(parent.normalGeometry(), geom);
2356 parent.showNormal();
2358 QTRY_VERIFY(!(parent.windowState() & Qt::WindowMaximized));
2359 QTRY_COMPARE(parent.geometry(), geom);
2360 QCOMPARE(parent.normalGeometry(), geom);
2362 parent.setWindowState(parent.windowState() ^ Qt::WindowMinimized);
2364 parent.setWindowState(parent.windowState() ^ Qt::WindowMaximized);
2366 if (m_platform == QStringLiteral("xcb"))
2367 QSKIP("QTBUG-26424");
2368 QTRY_VERIFY(parent.windowState() & (Qt::WindowMinimized|Qt::WindowMaximized));
2369 // ### when minimized and maximized at the same time, the geometry
2370 // ### does *NOT* have to be the normal geometry, it could be the
2371 // ### maximized geometry.
2372 // QCOMPARE(parent.geometry(), geom);
2373 QTRY_COMPARE(parent.normalGeometry(), geom);
2375 parent.setWindowState(parent.windowState() ^ Qt::WindowMinimized);
2377 QTRY_VERIFY(!(parent.windowState() & Qt::WindowMinimized));
2378 QTRY_VERIFY(parent.windowState() & Qt::WindowMaximized);
2379 QTRY_VERIFY(parent.geometry() != geom);
2380 QTRY_COMPARE(parent.normalGeometry(), geom);
2382 parent.setWindowState(parent.windowState() ^ Qt::WindowMaximized);
2384 QTRY_VERIFY(!(parent.windowState() & Qt::WindowMaximized));
2385 QTRY_COMPARE(parent.geometry(), geom);
2386 QTRY_COMPARE(parent.normalGeometry(), geom);
2388 parent.setWindowState(parent.windowState() ^ Qt::WindowFullScreen);
2390 QTRY_VERIFY(parent.windowState() & Qt::WindowFullScreen);
2391 QTRY_VERIFY(parent.geometry() != geom);
2392 QTRY_COMPARE(parent.normalGeometry(), geom);
2394 parent.setWindowState(parent.windowState() ^ Qt::WindowFullScreen);
2396 QVERIFY(!(parent.windowState() & Qt::WindowFullScreen));
2397 QTRY_COMPARE(parent.geometry(), geom);
2398 QTRY_COMPARE(parent.normalGeometry(), geom);
2400 parent.showFullScreen();
2402 QTRY_VERIFY(parent.windowState() & Qt::WindowFullScreen);
2403 QTRY_VERIFY(parent.geometry() != geom);
2404 QTRY_COMPARE(parent.normalGeometry(), geom);
2406 parent.showNormal();
2408 QTRY_VERIFY(!(parent.windowState() & Qt::WindowFullScreen));
2409 QTRY_COMPARE(parent.geometry(), geom);
2410 QTRY_COMPARE(parent.normalGeometry(), geom);
2412 QSKIP("QTBUG-26420");
2413 parent.showNormal();
2414 parent.setWindowState(Qt:: WindowFullScreen | Qt::WindowMaximized);
2415 parent.setWindowState(Qt::WindowMinimized | Qt:: WindowFullScreen | Qt::WindowMaximized);
2416 parent.setWindowState(Qt:: WindowFullScreen | Qt::WindowMaximized);
2418 QTRY_COMPARE(parent.normalGeometry(), geom);
2421 void tst_QWidget::setGeometry()
2424 QWidget child(&tlw);
2426 QRect tr(100,100,200,200);
2427 QRect cr(50,50,50,50);
2428 tlw.setGeometry(tr);
2429 child.setGeometry(cr);
2432 QCOMPARE(tlw.geometry().size(), tr.size());
2433 QCOMPARE(child.geometry(), cr);
2435 tlw.setParent(0, Qt::Window|Qt::FramelessWindowHint);
2436 tr = QRect(0,0,100,100);
2437 tr.moveTopLeft(QApplication::desktop()->availableGeometry().topLeft());
2438 tlw.setGeometry(tr);
2439 QCOMPARE(tlw.geometry(), tr);
2442 if (tlw.frameGeometry() != tlw.geometry())
2443 QSKIP("Your window manager is too broken for this test");
2444 if (m_platform == QStringLiteral("xcb"))
2445 QSKIP("QTBUG-26424");
2446 QCOMPARE(tlw.geometry(), tr);
2449 // Windows CE does not support windowOpacity.
2451 void tst_QWidget::windowOpacity()
2454 QWidget child(&widget);
2456 // Initial value should be 1.0
2457 QCOMPARE(widget.windowOpacity(), 1.0);
2458 // children should always return 1.0
2459 QCOMPARE(child.windowOpacity(), 1.0);
2461 widget.setWindowOpacity(0.0);
2462 QCOMPARE(widget.windowOpacity(), 0.0);
2463 child.setWindowOpacity(0.0);
2464 QCOMPARE(child.windowOpacity(), 1.0);
2466 widget.setWindowOpacity(1.0);
2467 QCOMPARE(widget.windowOpacity(), 1.0);
2468 child.setWindowOpacity(1.0);
2469 QCOMPARE(child.windowOpacity(), 1.0);
2471 widget.setWindowOpacity(2.0);
2472 QCOMPARE(widget.windowOpacity(), 1.0);
2473 child.setWindowOpacity(2.0);
2474 QCOMPARE(child.windowOpacity(), 1.0);
2476 widget.setWindowOpacity(-1.0);
2477 QCOMPARE(widget.windowOpacity(), 0.0);
2478 child.setWindowOpacity(-1.0);
2479 QCOMPARE(child.windowOpacity(), 1.0);
2483 class UpdateWidget : public QWidget
2486 UpdateWidget(QWidget *parent = 0) : QWidget(parent) {
2490 void paintEvent(QPaintEvent *e) {
2491 paintedRegion += e->region();
2493 if (resizeInPaintEvent) {
2494 resizeInPaintEvent = false;
2495 resize(size() + QSize(2, 2));
2499 bool event(QEvent *event)
2501 switch (event->type()) {
2502 case QEvent::ZOrderChange:
2503 ++numZOrderChangeEvents;
2505 case QEvent::UpdateRequest:
2506 ++numUpdateRequestEvents;
2508 case QEvent::ActivationChange:
2509 case QEvent::FocusIn:
2510 case QEvent::FocusOut:
2511 case QEvent::WindowActivate:
2512 case QEvent::WindowDeactivate:
2513 if (!updateOnActivationChangeAndFocusIn)
2514 return true; // Filter out to avoid update() calls in QWidget.
2519 return QWidget::event(event);
2524 numZOrderChangeEvents = 0;
2525 numUpdateRequestEvents = 0;
2526 updateOnActivationChangeAndFocusIn = false;
2527 resizeInPaintEvent = false;
2528 paintedRegion = QRegion();
2532 int numZOrderChangeEvents;
2533 int numUpdateRequestEvents;
2534 bool updateOnActivationChangeAndFocusIn;
2535 bool resizeInPaintEvent;
2536 QRegion paintedRegion;
2539 void tst_QWidget::lostUpdatesOnHide()
2542 UpdateWidget widget;
2543 widget.setAttribute(Qt::WA_DontShowOnScreen);
2550 QCOMPARE(widget.numPaintEvents, 1);
2554 void tst_QWidget::raise()
2557 QWidget *parent = new QWidget(0);
2558 QList<UpdateWidget *> allChildren;
2560 UpdateWidget *child1 = new UpdateWidget(parent);
2561 child1->setAutoFillBackground(true);
2562 allChildren.append(child1);
2564 UpdateWidget *child2 = new UpdateWidget(parent);
2565 child2->setAutoFillBackground(true);
2566 allChildren.append(child2);
2568 UpdateWidget *child3 = new UpdateWidget(parent);
2569 child3->setAutoFillBackground(true);
2570 allChildren.append(child3);
2572 UpdateWidget *child4 = new UpdateWidget(parent);
2573 child4->setAutoFillBackground(true);
2574 allChildren.append(child4);
2577 QTest::qWaitForWindowShown(parent);
2581 if (child1->internalWinId()) {
2582 QSKIP("Cocoa has no Z-Order for views, we hack it, but it results in paint events.");
2586 QList<QObject *> list1;
2587 list1 << child1 << child2 << child3 << child4;
2588 QVERIFY(parent->children() == list1);
2589 QCOMPARE(allChildren.count(), list1.count());
2591 foreach (UpdateWidget *child, allChildren) {
2592 int expectedPaintEvents = child == child4 ? 1 : 0;
2593 if (expectedPaintEvents == 0) {
2594 QVERIFY(child->numPaintEvents == 0);
2596 // show() issues multiple paint events on some window managers
2597 QTRY_VERIFY(child->numPaintEvents >= expectedPaintEvents);
2599 QCOMPARE(child->numZOrderChangeEvents, 0);
2603 for (int i = 0; i < 5; ++i)
2607 foreach (UpdateWidget *child, allChildren) {
2608 int expectedPaintEvents = child == child2 ? 1 : 0;
2609 int expectedZOrderChangeEvents = child == child2 ? 1 : 0;
2611 QSKIP("Not yet sure why this fails.");
2613 QTRY_COMPARE(child->numPaintEvents, expectedPaintEvents);
2614 QCOMPARE(child->numZOrderChangeEvents, expectedZOrderChangeEvents);
2618 QList<QObject *> list2;
2619 list2 << child1 << child3 << child4 << child2;
2620 QVERIFY(parent->children() == list2);
2622 // Creates a widget on top of all the children and checks that raising one of
2623 // the children underneath doesn't trigger a repaint on the covering widget.
2625 parent->setParent(&topLevel);
2627 QTest::qWaitForWindowShown(&topLevel);
2630 UpdateWidget *onTop = new UpdateWidget(&topLevel);
2632 onTop->resize(topLevel.size());
2633 onTop->setAutoFillBackground(true);
2636 QTRY_VERIFY(onTop->numPaintEvents > 0);
2639 // Reset all the children.
2640 foreach (UpdateWidget *child, allChildren)
2643 for (int i = 0; i < 5; ++i)
2647 QCOMPARE(onTop->numPaintEvents, 0);
2648 QCOMPARE(onTop->numZOrderChangeEvents, 0);
2650 QList<QObject *> list3;
2651 list3 << child1 << child4 << child2 << child3;
2652 QVERIFY(parent->children() == list3);
2654 foreach (UpdateWidget *child, allChildren) {
2655 int expectedPaintEvents = 0;
2656 int expectedZOrderChangeEvents = child == child3 ? 1 : 0;
2657 QTRY_COMPARE(child->numPaintEvents, expectedPaintEvents);
2658 QCOMPARE(child->numZOrderChangeEvents, expectedZOrderChangeEvents);
2663 // Cocoa has no Z-Order for views, we hack it, but it results in paint events.
2665 void tst_QWidget::lower()
2667 QWidget *parent = new QWidget(0);
2668 QList<UpdateWidget *> allChildren;
2670 UpdateWidget *child1 = new UpdateWidget(parent);
2671 child1->setAutoFillBackground(true);
2672 allChildren.append(child1);
2674 UpdateWidget *child2 = new UpdateWidget(parent);
2675 child2->setAutoFillBackground(true);
2676 allChildren.append(child2);
2678 UpdateWidget *child3 = new UpdateWidget(parent);
2679 child3->setAutoFillBackground(true);
2680 allChildren.append(child3);
2682 UpdateWidget *child4 = new UpdateWidget(parent);
2683 child4->setAutoFillBackground(true);
2684 allChildren.append(child4);
2687 QTest::qWaitForWindowShown(parent);
2690 QList<QObject *> list1;
2691 list1 << child1 << child2 << child3 << child4;
2692 QVERIFY(parent->children() == list1);
2693 QCOMPARE(allChildren.count(), list1.count());
2695 foreach (UpdateWidget *child, allChildren) {
2696 int expectedPaintEvents = child == child4 ? 1 : 0;
2697 if (expectedPaintEvents == 0) {
2698 QVERIFY(child->numPaintEvents == 0);
2700 // show() issues multiple paint events on some window managers
2701 QTRY_VERIFY(child->numPaintEvents >= expectedPaintEvents);
2703 QCOMPARE(child->numZOrderChangeEvents, 0);
2707 for (int i = 0; i < 5; ++i)
2712 foreach (UpdateWidget *child, allChildren) {
2713 int expectedPaintEvents = child == child3 ? 1 : 0;
2714 int expectedZOrderChangeEvents = child == child4 ? 1 : 0;
2715 QTRY_COMPARE(child->numZOrderChangeEvents, expectedZOrderChangeEvents);
2716 QTRY_COMPARE(child->numPaintEvents, expectedPaintEvents);
2720 QList<QObject *> list2;
2721 list2 << child4 << child1 << child2 << child3;
2722 QVERIFY(parent->children() == list2);
2728 // Cocoa has no Z-Order for views, we hack it, but it results in paint events.
2730 void tst_QWidget::stackUnder()
2733 QWidget *parent = new QWidget(0);
2734 QList<UpdateWidget *> allChildren;
2736 UpdateWidget *child1 = new UpdateWidget(parent);
2737 child1->setAutoFillBackground(true);
2738 allChildren.append(child1);
2740 UpdateWidget *child2 = new UpdateWidget(parent);
2741 child2->setAutoFillBackground(true);
2742 allChildren.append(child2);
2744 UpdateWidget *child3 = new UpdateWidget(parent);
2745 child3->setAutoFillBackground(true);
2746 allChildren.append(child3);
2748 UpdateWidget *child4 = new UpdateWidget(parent);
2749 child4->setAutoFillBackground(true);
2750 allChildren.append(child4);
2753 QTest::qWaitForWindowShown(parent);
2755 QList<QObject *> list1;
2756 list1 << child1 << child2 << child3 << child4;
2757 QVERIFY(parent->children() == list1);
2759 foreach (UpdateWidget *child, allChildren) {
2760 int expectedPaintEvents = child == child4 ? 1 : 0;
2761 #if defined(Q_OS_WIN) || defined(Q_OS_MAC)
2762 if (expectedPaintEvents == 1 && child->numPaintEvents == 2)
2763 QEXPECT_FAIL(0, "Mac and Windows issues double repaints for Z-Order change", Continue);
2765 QTRY_COMPARE(child->numPaintEvents, expectedPaintEvents);
2766 QCOMPARE(child->numZOrderChangeEvents, 0);
2770 for (int i = 0; i < 5; ++i)
2771 child4->stackUnder(child2);
2774 QList<QObject *> list2;
2775 list2 << child1 << child4 << child2 << child3;
2776 QVERIFY(parent->children() == list2);
2778 foreach (UpdateWidget *child, allChildren) {
2779 int expectedPaintEvents = child == child3 ? 1 : 0;
2780 int expectedZOrderChangeEvents = child == child4 ? 1 : 0;
2781 QTRY_COMPARE(child->numPaintEvents, expectedPaintEvents);
2782 QTRY_COMPARE(child->numZOrderChangeEvents, expectedZOrderChangeEvents);
2786 for (int i = 0; i < 5; ++i)
2787 child1->stackUnder(child3);
2790 QList<QObject *> list3;
2791 list3 << child4 << child2 << child1 << child3;
2792 QVERIFY(parent->children() == list3);
2794 foreach (UpdateWidget *child, allChildren) {
2795 int expectedZOrderChangeEvents = child == child1 ? 1 : 0;
2796 if (child == child3) {
2798 qApp->processEvents();
2801 QEXPECT_FAIL(0, "See QTBUG-493", Continue);
2803 QCOMPARE(child->numPaintEvents, 0);
2805 QCOMPARE(child->numPaintEvents, 0);
2807 QTRY_COMPARE(child->numZOrderChangeEvents, expectedZOrderChangeEvents);
2815 void drawPolygon(QPaintDevice *dev, int w, int h)
2818 p.fillRect(0, 0, w, h, Qt::white);
2821 a << QPoint(0, 0) << QPoint(w/2, h/2) << QPoint(w, 0)
2822 << QPoint(w/2, h) << QPoint(0, 0);
2824 p.setPen(QPen(Qt::black, 1));
2825 p.setBrush(Qt::DiagCrossPattern);
2829 class ContentsPropagationWidget : public QWidget
2833 ContentsPropagationWidget(QWidget *parent = 0) : QWidget(parent)
2835 QWidget *child = this;
2836 for (int i=0; i<32; ++i) {
2837 child = new QWidget(child);
2838 child->setGeometry(i, i, 400 - i*2, 400 - i*2);
2842 void setContentsPropagation(bool enable) {
2843 foreach (QObject *child, children())
2844 qobject_cast<QWidget *>(child)->setAutoFillBackground(!enable);
2848 void paintEvent(QPaintEvent *)
2850 int w = width(), h = height();
2851 drawPolygon(this, w, h);
2854 QSize sizeHint() const { return QSize(500, 500); }
2857 void tst_QWidget::testContentsPropagation()
2859 ContentsPropagationWidget widget;
2860 widget.setFixedSize(500, 500);
2861 widget.setContentsPropagation(false);
2862 QPixmap widgetSnapshot = widget.grab(QRect(QPoint(0, 0), QSize(-1, -1)));
2864 QPixmap correct(500, 500);
2865 drawPolygon(&correct, 500, 500);
2866 //correct.save("correct.png", "PNG");
2868 //widgetSnapshot.save("snap1.png", "PNG");
2869 QVERIFY(widgetSnapshot.toImage() != correct.toImage());
2871 widget.setContentsPropagation(true);
2872 widgetSnapshot = widgetSnapshot = widget.grab(QRect(QPoint(0, 0), QSize(-1, -1)));
2873 //widgetSnapshot.save("snap2.png", "PNG");
2875 QCOMPARE(widgetSnapshot, correct);
2879 Test that saving and restoring window geometry with
2880 saveGeometry() and restoreGeometry() works.
2883 void tst_QWidget::saveRestoreGeometry()
2885 const QPoint position(100, 100);
2886 const QSize size(200, 200);
2888 QByteArray savedGeometry;
2892 widget.move(position);
2893 widget.resize(size);
2895 QTest::qWaitForWindowShown(&widget);
2896 QApplication::processEvents();
2898 QTRY_COMPARE(widget.pos(), position);
2899 QCOMPARE(widget.size(), size);
2900 savedGeometry = widget.saveGeometry();
2906 const QByteArray empty;
2907 const QByteArray one("a");
2908 const QByteArray two("ab");
2909 const QByteArray three("abc");
2910 const QByteArray four("abca");
2911 const QByteArray garbage("abcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabc");
2913 QVERIFY(widget.restoreGeometry(empty) == false);
2914 QVERIFY(widget.restoreGeometry(one) == false);
2915 QVERIFY(widget.restoreGeometry(two) == false);
2916 QVERIFY(widget.restoreGeometry(three) == false);
2917 QVERIFY(widget.restoreGeometry(four) == false);
2918 QVERIFY(widget.restoreGeometry(garbage) == false);
2920 QVERIFY(widget.restoreGeometry(savedGeometry));
2922 QTest::qWaitForWindowShown(&widget);
2923 QApplication::processEvents();
2925 QTRY_COMPARE(widget.pos(), position);
2926 QCOMPARE(widget.size(), size);
2928 QCOMPARE(widget.pos(), position);
2929 QCOMPARE(widget.size(), size);
2934 widget.move(position);
2935 widget.resize(size);
2937 QTest::qWaitForWindowShown(&widget);
2939 QTRY_COMPARE(widget.geometry().size(), size);
2943 //Restore from Full screen
2944 savedGeometry = widget.saveGeometry();
2945 geom = widget.geometry();
2946 widget.setWindowState(widget.windowState() | Qt::WindowFullScreen);
2947 QTRY_VERIFY((widget.windowState() & Qt::WindowFullScreen));
2949 QVERIFY(widget.restoreGeometry(savedGeometry));
2951 QTRY_VERIFY(!(widget.windowState() & Qt::WindowFullScreen));
2953 QEXPECT_FAIL("", "QTBUG-26421", Continue);
2955 QTRY_COMPARE(widget.geometry(), geom);
2957 //Restore to full screen
2958 widget.setWindowState(widget.windowState() | Qt::WindowFullScreen);
2960 QTRY_VERIFY((widget.windowState() & Qt::WindowFullScreen));
2962 savedGeometry = widget.saveGeometry();
2963 geom = widget.geometry();
2964 widget.setWindowState(widget.windowState() ^ Qt::WindowFullScreen);
2966 QTRY_VERIFY(!(widget.windowState() & Qt::WindowFullScreen));
2968 QVERIFY(widget.restoreGeometry(savedGeometry));
2970 QTRY_VERIFY((widget.windowState() & Qt::WindowFullScreen));
2971 QTRY_COMPARE(widget.geometry(), geom);
2972 QVERIFY((widget.windowState() & Qt::WindowFullScreen));
2973 widget.setWindowState(widget.windowState() ^ Qt::WindowFullScreen);
2975 QTRY_VERIFY(!(widget.windowState() & Qt::WindowFullScreen));
2978 //Restore from Maximised
2979 widget.move(position);
2980 widget.resize(size);
2982 QTRY_COMPARE(widget.size(), size);
2984 savedGeometry = widget.saveGeometry();
2985 geom = widget.geometry();
2986 widget.setWindowState(widget.windowState() | Qt::WindowMaximized);
2988 QTRY_VERIFY((widget.windowState() & Qt::WindowMaximized));
2989 QTRY_VERIFY(widget.geometry() != geom);
2991 QVERIFY(widget.restoreGeometry(savedGeometry));
2993 QTRY_COMPARE(widget.geometry(), geom);
2995 QVERIFY(!(widget.windowState() & Qt::WindowMaximized));
2997 //Restore to maximised
2998 widget.setWindowState(widget.windowState() | Qt::WindowMaximized);
3000 QTRY_VERIFY((widget.windowState() & Qt::WindowMaximized));
3002 geom = widget.geometry();
3003 savedGeometry = widget.saveGeometry();
3004 widget.setWindowState(widget.windowState() ^ Qt::WindowMaximized);
3006 QTRY_VERIFY(!(widget.windowState() & Qt::WindowMaximized));
3008 QVERIFY(widget.restoreGeometry(savedGeometry));
3010 QTRY_VERIFY((widget.windowState() & Qt::WindowMaximized));
3011 QTRY_COMPARE(widget.geometry(), geom);
3015 void tst_QWidget::restoreVersion1Geometry_data()
3017 QTest::addColumn<QString>("fileName");
3018 QTest::addColumn<uint>("expectedWindowState");
3019 QTest::addColumn<QPoint>("expectedPosition");
3020 QTest::addColumn<QSize>("expectedSize");
3021 QTest::addColumn<QRect>("expectedNormalGeometry");
3022 const QPoint position(100, 100);
3023 const QSize size(200, 200);
3024 const QRect normalGeometry(102, 124, 200, 200);
3026 QTest::newRow("geometry.dat") << ":geometry.dat" << uint(Qt::WindowNoState) << position << size << normalGeometry;
3027 QTest::newRow("geometry-maximized.dat") << ":geometry-maximized.dat" << uint(Qt::WindowMaximized) << position << size << normalGeometry;
3028 QTest::newRow("geometry-fullscreen.dat") << ":geometry-fullscreen.dat" << uint(Qt::WindowFullScreen) << position << size << normalGeometry;
3032 Test that the current version of restoreGeometry() can restore geometry
3033 saved width saveGeometry() version 1.0.
3035 void tst_QWidget::restoreVersion1Geometry()
3037 QFETCH(QString, fileName);
3038 QFETCH(uint, expectedWindowState);
3039 QFETCH(QPoint, expectedPosition);
3040 QFETCH(QSize, expectedSize);
3041 QFETCH(QRect, expectedNormalGeometry);
3043 // WindowActive is uninteresting for this test
3044 const uint WindowStateMask = Qt::WindowFullScreen | Qt::WindowMaximized | Qt::WindowMinimized;
3047 QVERIFY(f.exists());
3048 f.open(QIODevice::ReadOnly);
3049 const QByteArray savedGeometry = f.readAll();
3050 QCOMPARE(savedGeometry.count(), 46);
3055 QVERIFY(widget.restoreGeometry(savedGeometry));
3057 QCOMPARE(uint(widget.windowState() & WindowStateMask), expectedWindowState);
3058 if (expectedWindowState == Qt::WindowNoState) {
3059 QCOMPARE(widget.pos(), expectedPosition);
3060 QCOMPARE(widget.size(), expectedSize);
3063 QTest::qWaitForWindowShown(&widget);
3066 if (expectedWindowState == Qt::WindowNoState) {
3067 QTRY_COMPARE(widget.pos(), expectedPosition);
3068 QTRY_COMPARE(widget.size(), expectedSize);
3071 widget.showNormal();
3074 if (m_platform == QStringLiteral("xcb") || m_platform == QStringLiteral("windows"))
3075 QSKIP("QTBUG-26421");
3077 if (expectedWindowState != Qt::WindowNoState) {
3078 // restoring from maximized or fullscreen, we can only restore to the normal geometry
3079 QTRY_COMPARE(widget.geometry(), expectedNormalGeometry);
3081 QTRY_COMPARE(widget.pos(), expectedPosition);
3082 QTRY_COMPARE(widget.size(), expectedSize);
3086 // Code for saving a new geometry*.dat files
3088 QWidget widgetToSave;
3089 widgetToSave.move(expectedPosition);
3090 widgetToSave.resize(expectedSize);
3091 widgetToSave.show();
3092 QTest::qWaitForWindowShown(widget.windowHandle());
3093 QTest::qWait(500); // stabilize
3094 widgetToSave.setWindowState(Qt::WindowStates(expectedWindowState));
3095 QTest::qWait(500); // stabilize
3097 QByteArray geometryToSave = widgetToSave.saveGeometry();
3099 // Code for saving a new geometry.dat file.
3100 f.setFileName(fileName.mid(1));
3101 QVERIFY(f.open(QIODevice::WriteOnly)); // did you forget to 'p4 edit *.dat'? :)
3102 f.write(geometryToSave);
3108 void tst_QWidget::widgetAt()
3112 QWidget *w1 = new QWidget(0, Qt::X11BypassWindowManagerHint);
3113 w1->setGeometry(0,0,150,150);
3114 w1->setObjectName("w1");
3116 QWidget *w2 = new QWidget(0, Qt::X11BypassWindowManagerHint | Qt::FramelessWindowHint);
3117 w2->setGeometry(50,50,100,100);
3118 w2->setObjectName("w2");
3120 QTest::qWaitForWindowShown(w1);
3121 qApp->processEvents();
3123 QTRY_VERIFY((wr = QApplication::widgetAt(100, 100)));
3124 QCOMPARE(wr->objectName(), QString("w1"));
3127 QTest::qWaitForWindowShown(w2);
3128 qApp->processEvents();
3129 qApp->processEvents();
3130 qApp->processEvents();
3131 QTRY_VERIFY((wr = QApplication::widgetAt(100, 100)));
3132 QCOMPARE(wr->objectName(), QString("w2"));
3135 qApp->processEvents();
3136 QTRY_VERIFY((wr = QApplication::widgetAt(100, 100)) && wr->objectName() == QString("w1"));
3139 qApp->processEvents();
3140 QTRY_VERIFY((wr = QApplication::widgetAt(100, 100)) && wr->objectName() == QString("w2"));
3142 QWidget *w3 = new QWidget(w2);
3143 w3->setGeometry(10,10,50,50);
3144 w3->setObjectName("w3");
3146 qApp->processEvents();
3147 QTRY_VERIFY((wr = QApplication::widgetAt(100,100)) && wr->objectName() == QString("w3"));
3149 w3->setAttribute(Qt::WA_TransparentForMouseEvents);
3150 qApp->processEvents();
3151 QTRY_VERIFY((wr = QApplication::widgetAt(100, 100)) && wr->objectName() == QString("w2"));
3153 QRegion rgn = QRect(QPoint(0,0), w2->size());
3154 QPoint point = w2->mapFromGlobal(QPoint(100,100));
3155 rgn -= QRect(point, QSize(1,1));
3157 qApp->processEvents();
3159 #if defined(Q_OS_WINCE)
3160 QEXPECT_FAIL("", "Windows CE does only support rectangular regions", Continue); //See also task 147191
3162 if (!QGuiApplication::platformName().compare(QLatin1String("cocoa"), Qt::CaseInsensitive))
3163 QEXPECT_FAIL("", "Window mask not implemented on Mac QTBUG-22326", Continue);
3165 QTRY_VERIFY((wr = QApplication::widgetAt(100,100)));
3166 QTRY_COMPARE(wr->objectName(), w1->objectName());
3167 QTRY_VERIFY((wr = QApplication::widgetAt(101,101)));
3168 QTRY_COMPARE(wr->objectName(), w2->objectName());
3170 QBitmap bitmap(w2->size());
3171 QPainter p(&bitmap);
3172 p.fillRect(bitmap.rect(), Qt::color1);
3173 p.setPen(Qt::color0);
3174 p.drawPoint(w2->mapFromGlobal(QPoint(100,100)));
3176 w2->setMask(bitmap);
3177 qApp->processEvents();
3179 #if defined(Q_OS_WINCE)
3180 QEXPECT_FAIL("", "Windows CE does only support rectangular regions", Continue); //See also task 147191
3182 if (!QGuiApplication::platformName().compare(QLatin1String("cocoa"), Qt::CaseInsensitive))
3183 QEXPECT_FAIL("", "Window mask not implemented on Mac QTBUG-22326", Continue);
3184 QTRY_VERIFY(QApplication::widgetAt(100,100) == w1);
3185 QTRY_VERIFY(QApplication::widgetAt(101,101) == w2);
3191 void tst_QWidget::task110173()
3195 QPushButton *pb1 = new QPushButton("click", &w);
3196 pb1->setFocusPolicy(Qt::ClickFocus);
3197 pb1->move(100, 100);
3199 QPushButton *pb2 = new QPushButton("push", &w);
3200 pb2->setFocusPolicy(Qt::ClickFocus);
3201 pb2->move(300, 300);
3203 QTest::keyClick( &w, Qt::Key_Tab );
3205 QTest::qWaitForWindowShown(&w);
3209 class Widget : public QWidget
3212 Widget() : deleteThis(false) { setFocusPolicy(Qt::StrongFocus); }
3213 void actionEvent(QActionEvent *) { if (deleteThis) delete this; }
3214 void changeEvent(QEvent *) { if (deleteThis) delete this; }
3215 void closeEvent(QCloseEvent *) { if (deleteThis) delete this; }
3216 void hideEvent(QHideEvent *) { if (deleteThis) delete this; }
3217 void focusOutEvent(QFocusEvent *) { if (deleteThis) delete this; }
3218 void keyPressEvent(QKeyEvent *) { if (deleteThis) delete this; }
3219 void keyReleaseEvent(QKeyEvent *) { if (deleteThis) delete this; }
3220 void mouseDoubleClickEvent(QMouseEvent *) { if (deleteThis) delete this; }
3221 void mousePressEvent(QMouseEvent *) { if (deleteThis) delete this; }
3222 void mouseReleaseEvent(QMouseEvent *) { if (deleteThis) delete this; }
3223 void mouseMoveEvent(QMouseEvent *) { if (deleteThis) delete this; }
3228 void tst_QWidget::testDeletionInEventHandlers()
3231 QPointer<Widget> w = new Widget;
3232 w->deleteThis = true;
3237 // focusOut (crashes)
3241 //QVERIFY(qApp->focusWidget() == w);
3242 //w->deleteThis = true;
3249 w->deleteThis = true;
3250 QTest::keyPress(w, Qt::Key_A);
3257 w->deleteThis = true;
3258 QTest::keyRelease(w, Qt::Key_A);
3265 w->deleteThis = true;
3266 QTest::mousePress(w, Qt::LeftButton);
3273 w->deleteThis = true;
3274 QTest::mouseRelease(w, Qt::LeftButton);
3278 // mouse double click
3281 w->deleteThis = true;
3282 QTest::mouseDClick(w, Qt::LeftButton);
3286 // hide event (crashes)
3289 //w->deleteThis = true;
3295 w->deleteThis = true;
3296 w->addAction(new QAction(w));
3303 w->deleteThis = true;
3304 w->setMouseTracking(true);
3309 w->setMouseTracking(true);
3311 w->deleteThis = true;
3312 QMouseEvent me(QEvent::MouseMove, QPoint(0, 0), Qt::NoButton, Qt::NoButton, Qt::NoModifier);
3313 QApplication::sendEvent(w, &me);
3319 void tst_QWidget::sheetOpacity()
3322 QWidget sheet(&tmpWindow, Qt::Sheet);
3325 QCOMPARE(int(sheet.windowOpacity() * 255), 242); // 95%
3326 sheet.setParent(0, Qt::Dialog);
3327 QCOMPARE(int(sheet.windowOpacity() * 255), 255);
3330 class MaskedPainter : public QWidget
3336 : mask(20, 20, 50, 50)
3341 void paintEvent(QPaintEvent *)
3344 p.fillRect(mask, QColor(Qt::red));
3349 Verifies that the entire area inside the mask is painted red.
3351 bool verifyWidgetMask(QWidget *widget, QRect mask)
3353 const QImage image = widget->grab(QRect(QPoint(0, 0), widget->size())).toImage();
3355 const QImage masked = image.copy(mask);
3357 red.fill(QColor(Qt::red).rgb());
3359 return (masked == red);
3362 void tst_QWidget::setMask()
3364 testWidget->hide(); // get this out of the way.
3371 QVERIFY(verifyWidgetMask(&w, w.mask));
3376 w.setWindowFlags(w.windowFlags() | Qt::FramelessWindowHint);
3379 QRect mask = w.mask;
3381 QVERIFY(verifyWidgetMask(&w, mask));
3386 class StaticWidget : public QWidget
3392 QRegion paintedRegion;
3394 StaticWidget(QWidget *parent = 0)
3397 setAttribute(Qt::WA_StaticContents);
3398 setAttribute(Qt::WA_OpaquePaintEvent);
3399 setPalette(Qt::red); // Make sure we have an opaque palette.
3400 setAutoFillBackground(true);
3401 gotPaintEvent = false;
3404 void paintEvent(QPaintEvent *e)
3406 paintedRegion += e->region();
3407 gotPaintEvent = true;
3408 // qDebug() << "paint" << e->region();
3409 // Look for a full update, set partial to false if found.
3410 foreach(QRect r, e->region().rects()) {
3411 partial = (r != rect());
3412 if (partial == false)
3419 Test that widget resizes and moves can be done with minimal repaints when WA_StaticContents
3420 and WA_OpaquePaintEvent is set. Test is mac-only for now.
3422 void tst_QWidget::optimizedResizeMove()
3425 parent.resize(400, 400);
3427 StaticWidget staticWidget(&parent);
3428 staticWidget.gotPaintEvent = false;
3429 staticWidget.move(150, 150);
3430 staticWidget.resize(150, 150);
3432 QTest::qWaitForWindowShown(&parent);
3434 QTRY_COMPARE(staticWidget.gotPaintEvent, true);
3436 staticWidget.gotPaintEvent = false;
3437 staticWidget.move(staticWidget.pos() + QPoint(10, 10));
3439 QCOMPARE(staticWidget.gotPaintEvent, false);
3441 staticWidget.gotPaintEvent = false;
3442 staticWidget.move(staticWidget.pos() + QPoint(-10, -10));
3444 QCOMPARE(staticWidget.gotPaintEvent, false);
3446 staticWidget.gotPaintEvent = false;
3447 staticWidget.move(staticWidget.pos() + QPoint(-10, 10));
3449 QCOMPARE(staticWidget.gotPaintEvent, false);
3451 staticWidget.gotPaintEvent = false;
3452 staticWidget.resize(staticWidget.size() + QSize(10, 10));
3454 QCOMPARE(staticWidget.gotPaintEvent, true);
3455 QCOMPARE(staticWidget.partial, true);
3457 staticWidget.gotPaintEvent = false;
3458 staticWidget.resize(staticWidget.size() + QSize(-10, -10));
3460 QCOMPARE(staticWidget.gotPaintEvent, false);
3462 staticWidget.gotPaintEvent = false;
3463 staticWidget.resize(staticWidget.size() + QSize(10, -10));
3465 QCOMPARE(staticWidget.gotPaintEvent, true);
3466 QCOMPARE(staticWidget.partial, true);
3468 staticWidget.gotPaintEvent = false;
3469 staticWidget.move(staticWidget.pos() + QPoint(10, 10));
3470 staticWidget.resize(staticWidget.size() + QSize(-10, -10));
3472 QCOMPARE(staticWidget.gotPaintEvent, false);
3474 staticWidget.gotPaintEvent = false;
3475 staticWidget.move(staticWidget.pos() + QPoint(10, 10));
3476 staticWidget.resize(staticWidget.size() + QSize(10, 10));
3478 QCOMPARE(staticWidget.gotPaintEvent, true);
3479 QCOMPARE(staticWidget.partial, true);
3481 staticWidget.gotPaintEvent = false;
3482 staticWidget.move(staticWidget.pos() + QPoint(-10, -10));
3483 staticWidget.resize(staticWidget.size() + QSize(-10, -10));
3485 QCOMPARE(staticWidget.gotPaintEvent, false);
3487 staticWidget.setAttribute(Qt::WA_StaticContents, false);
3488 staticWidget.gotPaintEvent = false;
3489 staticWidget.move(staticWidget.pos() + QPoint(-10, -10));
3490 staticWidget.resize(staticWidget.size() + QSize(-10, -10));
3492 QCOMPARE(staticWidget.gotPaintEvent, true);
3493 QCOMPARE(staticWidget.partial, false);
3494 staticWidget.setAttribute(Qt::WA_StaticContents, true);
3496 staticWidget.setAttribute(Qt::WA_StaticContents, false);
3497 staticWidget.gotPaintEvent = false;
3498 staticWidget.move(staticWidget.pos() + QPoint(10, 10));
3500 QCOMPARE(staticWidget.gotPaintEvent, false);
3501 staticWidget.setAttribute(Qt::WA_StaticContents, true);
3504 void tst_QWidget::optimizedResize_topLevel()
3506 #if defined(Q_OS_MAC)
3507 QSKIP("We do not yet have static contents support for *top-levels* on this platform");
3510 StaticWidget topLevel;
3511 topLevel.gotPaintEvent = false;
3513 QTest::qWaitForWindowShown(&topLevel);
3515 QTRY_COMPARE(topLevel.gotPaintEvent, true);
3517 topLevel.gotPaintEvent = false;
3518 topLevel.partial = false;
3519 topLevel.paintedRegion = QRegion();
3522 topLevel.resize(topLevel.size() + QSize(10, 10));
3524 // Static contents does not work when programmatically resizing
3525 // top-levels with QWidget::resize. We do some funky stuff in
3526 // setGeometry_sys. However, resizing it with the mouse or with
3527 // a native function call works (it basically has to go through
3528 // WM_RESIZE in QApplication). This is a corner case, though.
3530 const QRect frame = topLevel.frameGeometry();
3531 MoveWindow(winHandleOf(&topLevel), frame.x(), frame.y(),
3532 frame.width() + 10, frame.height() + 10,
3538 // Expected update region: New rect - old rect.
3539 QRegion expectedUpdateRegion(topLevel.rect());
3540 expectedUpdateRegion -= QRect(QPoint(), topLevel.size() - QSize(10, 10));
3542 QTRY_COMPARE(topLevel.gotPaintEvent, true);
3543 if (m_platform == QStringLiteral("xcb"))
3544 QSKIP("QTBUG-26424");
3545 QCOMPARE(topLevel.partial, true);
3546 QCOMPARE(topLevel.paintedRegion, expectedUpdateRegion);
3549 class SiblingDeleter : public QWidget
3552 inline SiblingDeleter(QWidget *sibling, QWidget *parent)
3553 : QWidget(parent), sibling(sibling) {}
3554 inline virtual ~SiblingDeleter() { delete sibling; }
3557 QPointer<QWidget> sibling;
3561 void tst_QWidget::childDeletesItsSibling()
3563 QWidget *commonParent = new QWidget(0);
3564 QPointer<QWidget> child = new QWidget(0);
3565 QPointer<QWidget> siblingDeleter = new SiblingDeleter(child, commonParent);
3566 child->setParent(commonParent);
3567 delete commonParent; // don't crash
3569 QVERIFY(!siblingDeleter);
3573 void tst_QWidget::setMinimumSize()
3576 QSize defaultSize = w.size();
3578 w.setMinimumSize(defaultSize + QSize(100, 100));
3579 QCOMPARE(w.size(), defaultSize + QSize(100, 100));
3580 QVERIFY(!w.testAttribute(Qt::WA_Resized));
3582 w.setMinimumSize(defaultSize + QSize(50, 50));
3583 QCOMPARE(w.size(), defaultSize + QSize(100, 100));
3584 QVERIFY(!w.testAttribute(Qt::WA_Resized));
3586 w.setMinimumSize(defaultSize + QSize(200, 200));
3587 QCOMPARE(w.size(), defaultSize + QSize(200, 200));
3588 QVERIFY(!w.testAttribute(Qt::WA_Resized));
3590 // Setting a minimum size larger than the desktop does not work on WinCE,
3591 // so skip this part of the test.
3593 QSize nonDefaultSize = defaultSize + QSize(5,5);
3594 w.setMinimumSize(nonDefaultSize);
3597 QVERIFY(w.height() >= nonDefaultSize.height());
3598 QVERIFY(w.width() >= nonDefaultSize.width());
3602 void tst_QWidget::setMaximumSize()
3605 QSize defaultSize = w.size();
3607 w.setMinimumSize(defaultSize + QSize(100, 100));
3608 QCOMPARE(w.size(), defaultSize + QSize(100, 100));
3609 QVERIFY(!w.testAttribute(Qt::WA_Resized));
3610 w.setMinimumSize(defaultSize);
3612 w.setMaximumSize(defaultSize + QSize(200, 200));
3613 QCOMPARE(w.size(), defaultSize + QSize(100, 100));
3614 QVERIFY(!w.testAttribute(Qt::WA_Resized));
3616 w.setMaximumSize(defaultSize + QSize(50, 50));
3617 QCOMPARE(w.size(), defaultSize + QSize(50, 50));
3618 QVERIFY(!w.testAttribute(Qt::WA_Resized));
3621 void tst_QWidget::setFixedSize()
3624 QSize defaultSize = w.size();
3626 w.setFixedSize(defaultSize + QSize(100, 100));
3627 QCOMPARE(w.size(), defaultSize + QSize(100, 100));
3628 QVERIFY(w.testAttribute(Qt::WA_Resized));
3630 w.setFixedSize(defaultSize + QSize(200, 200));
3632 QCOMPARE(w.minimumSize(), defaultSize + QSize(200,200));
3633 QCOMPARE(w.maximumSize(), defaultSize + QSize(200,200));
3634 QCOMPARE(w.size(), defaultSize + QSize(200, 200));
3635 QVERIFY(w.testAttribute(Qt::WA_Resized));
3637 w.setFixedSize(defaultSize + QSize(50, 50));
3638 QCOMPARE(w.size(), defaultSize + QSize(50, 50));
3639 QVERIFY(w.testAttribute(Qt::WA_Resized));
3641 w.setAttribute(Qt::WA_Resized, false);
3642 w.setFixedSize(defaultSize + QSize(50, 50));
3643 QVERIFY(!w.testAttribute(Qt::WA_Resized));
3645 w.setFixedSize(defaultSize + QSize(150, 150));
3648 if (m_platform == QStringLiteral("xcb"))
3649 QSKIP("QTBUG-26424");
3650 QVERIFY(w.size() == defaultSize + QSize(150,150));
3653 void tst_QWidget::ensureCreated()
3657 WId widgetWinId = widget.winId();
3658 Q_UNUSED(widgetWinId);
3659 QVERIFY(widget.testAttribute(Qt::WA_WState_Created));
3665 QDialog dialog(&window);
3666 dialog.setWindowModality(Qt::NonModal);
3668 WId dialogWinId = dialog.winId();
3669 Q_UNUSED(dialogWinId);
3670 QVERIFY(dialog.testAttribute(Qt::WA_WState_Created));
3671 QVERIFY(window.testAttribute(Qt::WA_WState_Created));
3677 QDialog dialog(&window);
3678 dialog.setWindowModality(Qt::WindowModal);
3680 WId dialogWinId = dialog.winId();
3681 Q_UNUSED(dialogWinId);
3682 QVERIFY(dialog.testAttribute(Qt::WA_WState_Created));
3683 QVERIFY(window.testAttribute(Qt::WA_WState_Created));
3689 QDialog dialog(&window);
3690 dialog.setWindowModality(Qt::ApplicationModal);
3692 WId dialogWinId = dialog.winId();
3693 Q_UNUSED(dialogWinId);
3694 QVERIFY(dialog.testAttribute(Qt::WA_WState_Created));
3695 QVERIFY(window.testAttribute(Qt::WA_WState_Created));
3699 class WinIdChangeWidget : public QWidget {
3701 WinIdChangeWidget(QWidget *p = 0)
3707 bool event(QEvent *e)
3709 if (e->type() == QEvent::WinIdChange) {
3710 m_winIdList.append(internalWinId());
3713 return QWidget::event(e);
3716 QList<WId> m_winIdList;
3717 int winIdChangeEventCount() const { return m_winIdList.count(); }
3720 void tst_QWidget::winIdChangeEvent()
3723 // Transforming an alien widget into a native widget
3724 WinIdChangeWidget widget;
3725 const WId winIdBefore = widget.internalWinId();
3726 const WId winIdAfter = widget.winId();
3727 QVERIFY(winIdBefore != winIdAfter);
3728 QCOMPARE(widget.winIdChangeEventCount(), 1);
3732 // Changing parent of a native widget
3733 // Should cause winId of child to change, on all platforms
3734 QWidget parent1, parent2;
3735 WinIdChangeWidget child(&parent1);
3736 const WId winIdBefore = child.winId();
3737 QCOMPARE(child.winIdChangeEventCount(), 1);
3738 child.setParent(&parent2);
3739 const WId winIdAfter = child.internalWinId();
3740 if (m_platform == QStringLiteral("windows"))
3741 QEXPECT_FAIL("", "QTBUG-26424", Continue);
3742 QVERIFY(winIdBefore != winIdAfter);
3743 QCOMPARE(child.winIdChangeEventCount(), 3);
3744 // winId is set to zero during reparenting
3745 QVERIFY(0 == child.m_winIdList[1]);
3749 // Changing grandparent of a native widget
3750 QWidget grandparent1, grandparent2;
3751 QWidget parent(&grandparent1);
3752 WinIdChangeWidget child(&parent);
3753 const WId winIdBefore = child.winId();
3754 QCOMPARE(child.winIdChangeEventCount(), 1);
3755 parent.setParent(&grandparent2);
3756 const WId winIdAfter = child.internalWinId();
3757 QCOMPARE(winIdBefore, winIdAfter);
3758 QCOMPARE(child.winIdChangeEventCount(), 1);
3762 // Changing parent of an alien widget
3763 QWidget parent1, parent2;
3764 WinIdChangeWidget child(&parent1);
3765 const WId winIdBefore = child.internalWinId();
3766 child.setParent(&parent2);
3767 const WId winIdAfter = child.internalWinId();
3768 QCOMPARE(winIdBefore, winIdAfter);
3769 QCOMPARE(child.winIdChangeEventCount(), 0);
3773 // Making native child widget into a top-level window
3775 WinIdChangeWidget child(&parent);
3777 const WId winIdBefore = child.internalWinId();
3778 QCOMPARE(child.winIdChangeEventCount(), 1);
3779 const Qt::WindowFlags flags = child.windowFlags();
3780 child.setWindowFlags(flags | Qt::Window);
3781 const WId winIdAfter = child.internalWinId();
3782 if (m_platform == QStringLiteral("windows"))
3783 QEXPECT_FAIL("", "QTBUG-26424", Continue);
3784 QVERIFY(winIdBefore != winIdAfter);
3785 QCOMPARE(child.winIdChangeEventCount(), 3);
3786 // winId is set to zero during reparenting
3787 QVERIFY(0 == child.m_winIdList[1]);
3791 void tst_QWidget::persistentWinId()
3793 QWidget *parent = new QWidget;
3794 QWidget *w1 = new QWidget;
3795 QWidget *w2 = new QWidget;
3796 QWidget *w3 = new QWidget;
3797 w1->setParent(parent);
3801 WId winId1 = w1->winId();
3802 WId winId2 = w2->winId();
3803 WId winId3 = w3->winId();
3805 // reparenting should change the winId of the widget being reparented, but not of its children
3807 if (m_platform == QStringLiteral("windows"))
3808 QEXPECT_FAIL("", "QTBUG-26424", Continue);
3809 QVERIFY(w1->winId() != winId1);
3810 winId1 = w1->winId();
3811 QCOMPARE(w2->winId(), winId2);
3812 QCOMPARE(w3->winId(), winId3);
3814 w1->setParent(parent);
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);
3823 if (m_platform == QStringLiteral("windows"))
3824 QEXPECT_FAIL("", "QTBUG-26424", Continue);
3825 QVERIFY(w2->winId() != winId2);
3826 winId2 = w2->winId();
3827 QCOMPARE(w3->winId(), winId3);
3829 w2->setParent(parent);
3830 if (m_platform == QStringLiteral("windows"))
3831 QEXPECT_FAIL("", "QTBUG-26424", Continue);
3832 QVERIFY(w2->winId() != winId2);
3833 winId2 = w2->winId();
3834 QCOMPARE(w3->winId(), winId3);
3837 if (m_platform == QStringLiteral("windows"))
3838 QEXPECT_FAIL("", "QTBUG-26424", Continue);
3839 QVERIFY(w2->winId() != winId2);
3840 winId2 = w2->winId();
3841 QCOMPARE(w3->winId(), winId3);
3844 if (m_platform == QStringLiteral("windows"))
3845 QEXPECT_FAIL("", "QTBUG-26424", Continue);
3846 QVERIFY(w3->winId() != winId3);
3847 winId3 = w3->winId();
3850 if (m_platform == QStringLiteral("windows"))
3851 QEXPECT_FAIL("", "QTBUG-26424", Continue);
3852 QVERIFY(w3->winId() != winId3);
3853 winId3 = w3->winId();
3856 if (m_platform == QStringLiteral("windows"))
3857 QEXPECT_FAIL("", "QTBUG-26424", Continue);
3858 QVERIFY(w3->winId() != winId3);
3859 winId3 = w3->winId();
3864 void tst_QWidget::showNativeChild()
3867 topLevel.setGeometry(0, 0, 100, 100);
3868 QWidget child(&topLevel);
3871 QTest::qWaitForWindowShown(&topLevel);
3874 class ShowHideEventWidget : public QWidget
3877 int numberOfShowEvents, numberOfHideEvents;
3879 ShowHideEventWidget(QWidget *parent = 0)
3880 : QWidget(parent), numberOfShowEvents(0), numberOfHideEvents(0)
3884 { QWidget::create(); }
3886 void showEvent(QShowEvent *)
3887 { ++numberOfShowEvents; }
3889 void hideEvent(QHideEvent *)
3890 { ++numberOfHideEvents; }
3893 void tst_QWidget::showHideEvent_data()
3895 QTest::addColumn<bool>("show");
3896 QTest::addColumn<bool>("hide");
3897 QTest::addColumn<bool>("create");
3898 QTest::addColumn<int>("expectedShowEvents");
3899 QTest::addColumn<int>("expectedHideEvents");
3901 QTest::newRow("window: only show")
3907 QTest::newRow("window: show/hide")
3913 QTest::newRow("window: show/hide/create")
3919 QTest::newRow("window: hide/create")
3925 QTest::newRow("window: only hide")
3931 QTest::newRow("window: nothing")
3939 void tst_QWidget::showHideEvent()
3943 QFETCH(bool, create);
3944 QFETCH(int, expectedShowEvents);
3945 QFETCH(int, expectedHideEvents);
3947 ShowHideEventWidget widget;
3952 if (create && !widget.testAttribute(Qt::WA_WState_Created))
3955 if (m_platform == QStringLiteral("windows") || m_platform == QStringLiteral("xcb")) {
3956 QEXPECT_FAIL("window: only show", "QTBUG-26424", Continue);
3957 QEXPECT_FAIL("window: show/hide", "QTBUG-26424", Continue);
3958 QEXPECT_FAIL("window: show/hide/create", "QTBUG-26424", Continue);
3960 QCOMPARE(widget.numberOfShowEvents, expectedShowEvents);
3961 if (m_platform == QStringLiteral("windows") || m_platform == QStringLiteral("xcb")) {
3962 QEXPECT_FAIL("window: show/hide", "QTBUG-26424", Continue);
3963 QEXPECT_FAIL("window: show/hide/create", "QTBUG-26424", Continue);
3965 QCOMPARE(widget.numberOfHideEvents, expectedHideEvents);
3968 void tst_QWidget::update()
3970 QTest::qWait(10); // Wait for the initStuff to do it's stuff.
3974 w.setGeometry(50, 50, 100, 100);
3976 QTest::qWaitForWindowShown(&w);
3978 QApplication::processEvents();
3979 QApplication::processEvents();
3982 QEXPECT_FAIL(0, "Cocoa compositor says to paint this twice.", Continue);
3984 if (m_platform == QStringLiteral("windows"))
3985 QEXPECT_FAIL("", "QTBUG-26424", Continue);
3986 QTRY_COMPARE(w.numPaintEvents, 1);
3988 QCOMPARE(w.visibleRegion(), QRegion(w.rect()));
3989 QCOMPARE(w.paintedRegion, w.visibleRegion());
3992 UpdateWidget child(&w);
3993 child.setGeometry(10, 10, 80, 80);
3996 QPoint childOffset = child.mapToParent(QPoint());
3998 // widgets are transparent by default, so both should get repaints
4000 QApplication::processEvents();
4001 QApplication::processEvents();
4002 QCOMPARE(child.numPaintEvents, 1);
4003 QCOMPARE(child.visibleRegion(), QRegion(child.rect()));
4004 QCOMPARE(child.paintedRegion, child.visibleRegion());
4005 QCOMPARE(w.numPaintEvents, 1);
4006 QCOMPARE(w.visibleRegion(), QRegion(w.rect()));
4007 QCOMPARE(w.paintedRegion, child.visibleRegion().translated(childOffset));
4013 QApplication::processEvents();
4014 QApplication::processEvents();
4015 QCOMPARE(child.numPaintEvents, 1);
4016 QCOMPARE(child.visibleRegion(), QRegion(child.rect()));
4017 QCOMPARE(child.paintedRegion, child.visibleRegion());
4018 QCOMPARE(w.numPaintEvents, 1);
4019 QCOMPARE(w.visibleRegion(), QRegion(w.rect()));
4020 QCOMPARE(w.paintedRegion, w.visibleRegion());
4023 QPalette opaquePalette = child.palette();
4024 opaquePalette.setColor(child.backgroundRole(), QColor(Qt::red));
4026 // setting an opaque background on the child should prevent paint-events
4027 // for the parent in the child area
4029 child.setPalette(opaquePalette);
4030 child.setAutoFillBackground(true);
4031 QApplication::processEvents();
4037 QApplication::processEvents();
4038 QApplication::processEvents();
4040 QCOMPARE(w.numPaintEvents, 1);
4041 QRegion expectedVisible = QRegion(w.rect())
4042 - child.visibleRegion().translated(childOffset);
4043 QCOMPARE(w.visibleRegion(), expectedVisible);
4044 QCOMPARE(w.paintedRegion, expectedVisible);
4045 QCOMPARE(child.numPaintEvents, 0);
4051 QApplication::processEvents();
4052 QApplication::processEvents();
4054 QCOMPARE(w.numPaintEvents, 0);
4055 QCOMPARE(child.numPaintEvents, 1);
4056 QCOMPARE(child.paintedRegion, child.visibleRegion());
4062 // overlapping sibling
4063 UpdateWidget sibling(&w);
4064 child.setGeometry(10, 10, 20, 20);
4065 sibling.setGeometry(15, 15, 20, 20);
4068 QApplication::processEvents();
4073 const QPoint siblingOffset = sibling.mapToParent(QPoint());
4076 QApplication::processEvents();
4077 QApplication::processEvents();
4079 // child is opaque, sibling transparent
4081 QCOMPARE(sibling.numPaintEvents, 1);
4082 QCOMPARE(sibling.paintedRegion, sibling.visibleRegion());
4084 QCOMPARE(child.numPaintEvents, 1);
4085 QCOMPARE(child.paintedRegion.translated(childOffset),
4086 child.visibleRegion().translated(childOffset)
4087 & sibling.visibleRegion().translated(siblingOffset));
4089 QCOMPARE(w.numPaintEvents, 1);
4090 QCOMPARE(w.paintedRegion,
4091 w.visibleRegion() & sibling.visibleRegion().translated(siblingOffset));
4092 QCOMPARE(w.paintedRegion,
4093 (w.visibleRegion() - child.visibleRegion().translated(childOffset))
4094 & sibling.visibleRegion().translated(siblingOffset));
4101 sibling.setPalette(opaquePalette);
4102 sibling.setAutoFillBackground(true);
4105 QApplication::processEvents();
4106 QApplication::processEvents();
4108 // child opaque, sibling opaque
4110 QCOMPARE(sibling.numPaintEvents, 1);
4111 QCOMPARE(sibling.paintedRegion, sibling.visibleRegion());
4114 if (child.internalWinId()) // child is native
4115 QEXPECT_FAIL(0, "Cocoa compositor paints child and sibling", Continue);
4117 QCOMPARE(child.numPaintEvents, 0);
4118 QCOMPARE(child.visibleRegion(),
4119 QRegion(child.rect())
4120 - sibling.visibleRegion().translated(siblingOffset - childOffset));
4122 QCOMPARE(w.numPaintEvents, 0);
4123 QCOMPARE(w.visibleRegion(),
4125 - child.visibleRegion().translated(childOffset)
4126 - sibling.visibleRegion().translated(siblingOffset));
4130 static inline bool isOpaque(QWidget *widget)
4134 return qt_widget_private(widget)->isOpaque;
4137 void tst_QWidget::isOpaque()
4141 QVERIFY(::isOpaque(&w));
4144 QVERIFY(!::isOpaque(&child));
4146 child.setAutoFillBackground(true);
4147 QVERIFY(::isOpaque(&child));
4153 palette = child.palette();
4154 palette.setColor(child.backgroundRole(), QColor(255, 0, 0, 127));
4155 child.setPalette(palette);
4156 QVERIFY(!::isOpaque(&child));
4158 palette.setColor(child.backgroundRole(), QColor(255, 0, 0, 255));
4159 child.setPalette(palette);
4160 QVERIFY(::isOpaque(&child));
4162 palette.setColor(QPalette::Window, QColor(0, 0, 255, 127));
4163 w.setPalette(palette);
4165 QVERIFY(!::isOpaque(&w));
4167 child.setAutoFillBackground(false);
4168 QVERIFY(!::isOpaque(&child));
4170 // Qt::WA_OpaquePaintEvent
4172 child.setAttribute(Qt::WA_OpaquePaintEvent);
4173 QVERIFY(::isOpaque(&child));
4175 child.setAttribute(Qt::WA_OpaquePaintEvent, false);
4176 QVERIFY(!::isOpaque(&child));
4178 // Qt::WA_NoSystemBackground
4180 child.setAttribute(Qt::WA_NoSystemBackground);
4181 QVERIFY(!::isOpaque(&child));
4183 child.setAttribute(Qt::WA_NoSystemBackground, false);
4184 QVERIFY(!::isOpaque(&child));
4186 palette.setColor(QPalette::Window, QColor(0, 0, 255, 255));
4187 w.setPalette(palette);
4188 QVERIFY(::isOpaque(&w));
4190 w.setAttribute(Qt::WA_NoSystemBackground);
4191 QVERIFY(!::isOpaque(&w));
4193 w.setAttribute(Qt::WA_NoSystemBackground, false);
4194 QVERIFY(::isOpaque(&w));
4197 QPalette palette = QApplication::palette();
4198 QPalette old = palette;
4199 palette.setColor(QPalette::Window, Qt::transparent);
4200 QApplication::setPalette(palette);
4203 QVERIFY(!::isOpaque(&widget));
4205 QApplication::setPalette(old);
4206 QCOMPARE(::isOpaque(&widget), old.color(QPalette::Window).alpha() == 255);
4213 Test that scrolling of a widget invalidates the correct regions
4215 void tst_QWidget::scroll()
4217 UpdateWidget updateWidget;
4218 updateWidget.resize(500, 500);
4219 updateWidget.reset();
4220 updateWidget.show();
4221 QTest::qWaitForWindowShown(&updateWidget);
4223 qApp->processEvents();
4224 QTRY_VERIFY(updateWidget.numPaintEvents > 0);
4227 updateWidget.reset();
4228 updateWidget.scroll(10, 10);
4229 qApp->processEvents();
4230 QRegion dirty(QRect(0, 0, 500, 10));
4231 dirty += QRegion(QRect(0, 10, 10, 490));
4232 QCOMPARE(updateWidget.paintedRegion, dirty);
4236 updateWidget.reset();
4237 updateWidget.update(0, 0, 10, 10);
4238 updateWidget.scroll(0, 10);
4239 qApp->processEvents();
4240 QRegion dirty(QRect(0, 0, 500, 10));
4241 dirty += QRegion(QRect(0, 10, 10, 10));
4242 QCOMPARE(updateWidget.paintedRegion, dirty);
4246 updateWidget.reset();
4247 updateWidget.update(0, 0, 100, 100);
4248 updateWidget.scroll(10, 10, QRect(50, 50, 100, 100));
4249 qApp->processEvents();
4250 QRegion dirty(QRect(0, 0, 100, 50));
4251 dirty += QRegion(QRect(0, 50, 150, 10));
4252 dirty += QRegion(QRect(0, 60, 110, 40));
4253 dirty += QRegion(QRect(50, 100, 60, 10));
4254 dirty += QRegion(QRect(50, 110, 10, 40));
4255 QCOMPARE(updateWidget.paintedRegion, dirty);
4259 updateWidget.reset();
4260 updateWidget.update(0, 0, 100, 100);
4261 updateWidget.scroll(10, 10, QRect(100, 100, 100, 100));
4262 qApp->processEvents();
4263 QRegion dirty(QRect(0, 0, 100, 100));
4264 dirty += QRegion(QRect(100, 100, 100, 10));
4265 dirty += QRegion(QRect(100, 110, 10, 90));
4266 QCOMPARE(updateWidget.paintedRegion, dirty);
4271 class DestroyedSlotChecker : public QObject
4278 DestroyedSlotChecker()
4284 void destroyedSlot(QObject *object)
4286 wasQWidget = (qobject_cast<QWidget *>(object) != 0 || object->isWidgetType());
4291 Test that qobject_cast<QWidget*> returns 0 in a slot
4292 connected to QObject::destroyed.
4294 void tst_QWidget::qobject_castInDestroyedSlot()
4296 DestroyedSlotChecker checker;
4297 QWidget *widget = new QWidget();
4299 QObject::connect(widget, SIGNAL(destroyed(QObject *)), &checker, SLOT(destroyedSlot(QObject *)));
4302 QVERIFY(checker.wasQWidget == true);
4305 Q_DECLARE_METATYPE(QList<QRect>)
4307 // Since X11 WindowManager operations are all async, and we have no way to know if the window
4308 // manager has finished playing with the window geometry, this test can't be reliable on X11.
4310 void tst_QWidget::setWindowGeometry_data()
4312 QTest::addColumn<QList<QRect> >("rects");
4313 QTest::addColumn<int>("windowFlags");
4315 QList<QList<QRect> > rects;
4316 rects << (QList<QRect>()
4317 << QRect(100, 100, 200, 200)
4318 << QApplication::desktop()->availableGeometry().adjusted(100, 100, -100, -100)
4319 << QRect(130, 100, 0, 200)
4320 << QRect(100, 50, 200, 0)
4321 << QRect(130, 50, 0, 0))
4323 << QApplication::desktop()->availableGeometry().adjusted(100, 100, -100, -100)
4324 << QRect(130, 100, 0, 200)
4325 << QRect(100, 50, 200, 0)
4326 << QRect(130, 50, 0, 0)
4327 << QRect(100, 100, 200, 200))
4329 << QRect(130, 100, 0, 200)
4330 << QRect(100, 50, 200, 0)
4331 << QRect(130, 50, 0, 0)
4332 << QRect(100, 100, 200, 200)
4333 << QApplication::desktop()->availableGeometry().adjusted(100, 100, -100, -100))
4335 << QRect(100, 50, 200, 0)
4336 << QRect(130, 50, 0, 0)
4337 << QRect(100, 100, 200, 200)
4338 << QApplication::desktop()->availableGeometry().adjusted(100, 100, -100, -100)
4339 << QRect(130, 100, 0, 200))
4341 << QRect(130, 50, 0, 0)
4342 << QRect(100, 100, 200, 200)
4343 << QApplication::desktop()->availableGeometry().adjusted(100, 100, -100, -100)
4344 << QRect(130, 100, 0, 200)
4345 << QRect(100, 50, 200, 0));
4347 QList<int> windowFlags;
4348 windowFlags << 0 << Qt::FramelessWindowHint;
4350 foreach (QList<QRect> l, rects) {
4351 QRect rect = l.first();
4352 foreach (int windowFlag, windowFlags) {
4353 QTest::newRow(QString("%1,%2 %3x%4, flags %5")
4358 .arg(windowFlag, 0, 16).toLatin1())
4365 void tst_QWidget::setWindowGeometry()
4367 if (m_platform == QStringLiteral("xcb"))
4368 QSKIP("X11: Skip this test due to Window manager positioning issues.");
4370 QFETCH(QList<QRect>, rects);
4371 QFETCH(int, windowFlags);
4372 QRect rect = rects.takeFirst();
4375 // test setGeometry() without actually showing the window
4377 if (windowFlags != 0)
4378 widget.setWindowFlags(Qt::WindowFlags(windowFlags));
4380 widget.setGeometry(rect);
4382 QCOMPARE(widget.geometry(), rect);
4384 // setGeometry() without showing
4385 foreach (QRect r, rects) {
4386 widget.setGeometry(r);
4388 QCOMPARE(widget.geometry(), r);
4393 // setGeometry() first, then show()
4395 if (windowFlags != 0)
4396 widget.setWindowFlags(Qt::WindowFlags(windowFlags));
4398 widget.setGeometry(rect);
4400 QTest::qWaitForWindowShown(&widget);
4402 if (m_platform == QStringLiteral("windows")) {
4403 QEXPECT_FAIL("130,100 0x200, flags 0", "QTBUG-26424", Continue);
4404 QEXPECT_FAIL("130,50 0x0, flags 0", "QTBUG-26424", Continue);
4406 QTRY_COMPARE(widget.geometry(), rect);
4408 // setGeometry() while shown
4409 foreach (QRect r, rects) {
4410 widget.setGeometry(r);
4412 QTRY_COMPARE(widget.geometry(), r);
4414 widget.setGeometry(rect);
4416 QTRY_COMPARE(widget.geometry(), rect);
4421 QTRY_COMPARE(widget.geometry(), rect);
4423 // setGeometry() after hide()
4424 foreach (QRect r, rects) {
4425 widget.setGeometry(r);
4427 QTRY_COMPARE(widget.geometry(), r);
4429 widget.setGeometry(rect);
4431 QTRY_COMPARE(widget.geometry(), rect);
4433 // show() again, geometry() should still be the same
4435 QTest::qWaitForWindowShown(&widget);
4437 QTRY_COMPARE(widget.geometry(), rect);
4439 // final hide(), again geometry() should be unchanged
4442 QTRY_COMPARE(widget.geometry(), rect);
4446 // show() first, then setGeometry()
4448 if (windowFlags != 0)
4449 widget.setWindowFlags(Qt::WindowFlags(windowFlags));
4452 QTest::qWaitForWindowShown(&widget);
4453 widget.setGeometry(rect);
4455 QTRY_COMPARE(widget.geometry(), rect);
4457 // setGeometry() while shown
4458 foreach (QRect r, rects) {
4459 widget.setGeometry(r);
4461 QTRY_COMPARE(widget.geometry(), r);
4463 widget.setGeometry(rect);
4465 QTRY_COMPARE(widget.geometry(), rect);
4470 QTRY_COMPARE(widget.geometry(), rect);
4472 // setGeometry() after hide()
4473 foreach (QRect r, rects) {
4474 widget.setGeometry(r);
4476 QTRY_COMPARE(widget.geometry(), r);
4478 widget.setGeometry(rect);
4480 QTRY_COMPARE(widget.geometry(), rect);
4482 // show() again, geometry() should still be the same
4484 QTest::qWaitForWindowShown(&widget);
4486 QTRY_COMPARE(widget.geometry(), rect);
4488 // final hide(), again geometry() should be unchanged
4491 QTRY_COMPARE(widget.geometry(), rect);
4495 #if defined (Q_OS_WIN) && !defined(Q_OS_WINCE)
4496 void tst_QWidget::setGeometry_win()
4499 widget.setGeometry(0, 600, 100,100);
4501 widget.setWindowState(widget.windowState() | Qt::WindowMaximized);
4502 QRect geom = widget.normalGeometry();
4504 widget.setGeometry(geom);
4505 widget.setWindowState(widget.windowState() | Qt::WindowMaximized);
4508 ::GetWindowRect(winHandleOf(&widget), &rt);
4509 QVERIFY(rt.left <= 0);
4510 QEXPECT_FAIL("", "QTBUG-26424", Continue);
4511 QVERIFY(rt.top <= 0);
4513 #endif // defined (Q_OS_WIN) && !defined(Q_OS_WINCE)
4515 // Since X11 WindowManager operation are all async, and we have no way to know if the window
4516 // manager has finished playing with the window geometry, this test can't be reliable on X11.
4518 void tst_QWidget::windowMoveResize_data()
4520 setWindowGeometry_data();
4523 void tst_QWidget::windowMoveResize()
4525 if (m_platform == QStringLiteral("xcb"))
4526 QSKIP("X11: Skip this test due to Window manager positioning issues.");
4528 QFETCH(QList<QRect>, rects);
4529 QFETCH(int, windowFlags);
4531 QRect rect = rects.takeFirst();
4534 // test setGeometry() without actually showing the window
4536 if (windowFlags != 0)
4537 widget.setWindowFlags(Qt::WindowFlags(windowFlags));
4539 widget.move(rect.topLeft());
4540 widget.resize(rect.size());
4542 QTRY_COMPARE(widget.pos(), rect.topLeft());
4543 QTRY_COMPARE(widget.size(), rect.size());
4545 // move() without showing
4546 foreach (QRect r, rects) {
4547 widget.move(r.topLeft());
4548 widget.resize(r.size());
4549 QApplication::processEvents();
4550 QTRY_COMPARE(widget.pos(), r.topLeft());
4551 QTRY_COMPARE(widget.size(), r.size());
4556 // move() first, then show()
4558 if (windowFlags != 0)
4559 widget.setWindowFlags(Qt::WindowFlags(windowFlags));
4561 widget.move(rect.topLeft());
4562 widget.resize(rect.size());
4566 QTRY_COMPARE(widget.pos(), rect.topLeft());
4567 if (m_platform == QStringLiteral("windows")) {
4568 QEXPECT_FAIL("130,100 0x200, flags 0", "QTBUG-26424", Continue);
4569 QEXPECT_FAIL("130,50 0x0, flags 0", "QTBUG-26424", Continue);
4571 QTRY_COMPARE(widget.size(), rect.size());
4573 // move() while shown
4574 foreach (const QRect &r, rects) {
4575 if (m_platform == QStringLiteral("xcb")
4576 && ((widget.width() == 0 || widget.height() == 0) && r.width() != 0 && r.height() != 0)) {
4577 QEXPECT_FAIL("130,100 0x200, flags 0",
4578 "First resize after show of zero-sized gets wrong win_gravity.",
4580 QEXPECT_FAIL("100,50 200x0, flags 0",
4581 "First resize after show of zero-sized gets wrong win_gravity.",
4583 QEXPECT_FAIL("130,50 0x0, flags 0",
4584 "First resize after show of zero-sized gets wrong win_gravity.",
4588 widget.move(r.topLeft());
4589 widget.resize(r.size());
4590 QApplication::processEvents();
4591 QTRY_COMPARE(widget.pos(), r.topLeft());
4592 QTRY_COMPARE(widget.size(), r.size());
4594 widget.move(rect.topLeft());
4595 widget.resize(rect.size());
4596 QApplication::processEvents();
4597 QTRY_COMPARE(widget.pos(), rect.topLeft());
4598 QTRY_COMPARE(widget.size(), rect.size());
4603 QTRY_COMPARE(widget.pos(), rect.topLeft());
4604 QTRY_COMPARE(widget.size(), rect.size());
4606 // move() after hide()
4607 foreach (QRect r, rects) {
4608 widget.move(r.topLeft());
4609 widget.resize(r.size());
4610 QApplication::processEvents();
4611 #if defined(Q_OS_MAC)
4612 if (r.width() == 0 && r.height() > 0) {
4613 widget.move(r.topLeft());
4614 widget.resize(r.size());
4617 QTRY_COMPARE(widget.pos(), r.topLeft());
4618 QTRY_COMPARE(widget.size(), r.size());
4620 widget.move(rect.topLeft());
4621 widget.resize(rect.size());
4623 QTRY_COMPARE(widget.pos(), rect.topLeft());
4624 QTRY_COMPARE(widget.size(), rect.size());
4626 // show() again, pos() should be the same
4628 QTest::qWaitForWindowShown(&widget);
4629 QApplication::processEvents();
4630 QTRY_COMPARE(widget.pos(), rect.topLeft());
4631 QTRY_COMPARE(widget.size(), rect.size());
4633 // final hide(), again pos() should be unchanged
4635 QApplication::processEvents();
4636 QTRY_COMPARE(widget.pos(), rect.topLeft());
4637 QTRY_COMPARE(widget.size(), rect.size());
4641 // show() first, then move()
4643 if (windowFlags != 0)
4644 widget.setWindowFlags(Qt::WindowFlags(windowFlags));
4647 QTest::qWaitForWindowShown(&widget);
4648 QApplication::processEvents();
4649 widget.move(rect.topLeft());
4650 widget.resize(rect.size());
4651 QApplication::processEvents();
4652 QTRY_COMPARE(widget.pos(), rect.topLeft());
4653 QTRY_COMPARE(widget.size(), rect.size());
4655 // move() while shown
4656 foreach (QRect r, rects) {
4657 widget.move(r.topLeft());
4658 widget.resize(r.size());
4659 QApplication::processEvents();
4660 QTRY_COMPARE(widget.pos(), r.topLeft());
4661 QTRY_COMPARE(widget.size(), r.size());
4663 widget.move(rect.topLeft());
4664 widget.resize(rect.size());
4665 QApplication::processEvents();
4666 QTRY_COMPARE(widget.pos(), rect.topLeft());
4667 QTRY_COMPARE(widget.size(), rect.size());
4671 QApplication::processEvents();
4672 QTRY_COMPARE(widget.pos(), rect.topLeft());
4673 QTRY_COMPARE(widget.size(), rect.size());
4675 // move() after hide()
4676 foreach (QRect r, rects) {
4677 widget.move(r.topLeft());
4678 widget.resize(r.size());
4679 QApplication::processEvents();
4680 #if defined(Q_OS_MAC)
4681 if (r.width() == 0 && r.height() > 0) {
4682 widget.move(r.topLeft());
4683 widget.resize(r.size());
4686 QTRY_COMPARE(widget.pos(), r.topLeft());
4687 QTRY_COMPARE(widget.size(), r.size());
4689 widget.move(rect.topLeft());
4690 widget.resize(rect.size());
4691 QApplication::processEvents();
4692 QTRY_COMPARE(widget.pos(), rect.topLeft());
4693 QTRY_COMPARE(widget.size(), rect.size());
4695 // show() again, pos() should be the same
4697 QTest::qWaitForWindowShown(&widget);
4699 QTRY_COMPARE(widget.pos(), rect.topLeft());
4700 QTRY_COMPARE(widget.size(), rect.size());
4702 // final hide(), again pos() should be unchanged
4705 QTRY_COMPARE(widget.pos(), rect.topLeft());
4706 QTRY_COMPARE(widget.size(), rect.size());
4710 class ColorWidget : public QWidget
4713 ColorWidget(QWidget *parent = 0, const QColor &c = QColor(Qt::red))
4714 : QWidget(parent, Qt::FramelessWindowHint), color(c)
4716 QPalette opaquePalette = palette();
4717 opaquePalette.setColor(backgroundRole(), color);
4718 setPalette(opaquePalette);
4719 setAutoFillBackground(true);
4722 void paintEvent(QPaintEvent *e) {
4734 #define VERIFY_COLOR(region, color) { \
4735 const QRegion r = QRegion(region); \
4736 QScreen *screen = qApp->primaryScreen(); \
4737 const WId desktopWinId = QDesktopWidget().winId(); \
4738 for (int i = 0; i < r.rects().size(); ++i) { \
4739 const QRect rect = r.rects().at(i); \
4740 for (int t = 0; t < 5; t++) { \
4741 const QPixmap pixmap = screen->grabWindow(desktopWinId, \
4742 rect.left(), rect.top(), \
4743 rect.width(), rect.height()); \
4744 QCOMPARE(pixmap.size(), rect.size()); \
4745 QPixmap expectedPixmap(pixmap); /* ensure equal formats */ \
4746 expectedPixmap.detach(); \
4747 expectedPixmap.fill(color); \
4748 QImage image = pixmap.toImage(); \
4749 uint alphaCorrection = image.format() == QImage::Format_RGB32 ? 0xff000000 : 0; \
4750 uint firstPixel = image.pixel(0,0) | alphaCorrection; \
4751 if ( firstPixel != QColor(color).rgb() && t < 4 ) \
4752 { QTest::qWait(200); continue; } \
4753 QCOMPARE(firstPixel, QColor(color).rgb()); \
4754 QCOMPARE(pixmap, expectedPixmap); \
4760 void tst_QWidget::popupEnterLeave()
4762 if (m_platform == QStringLiteral("windows"))
4763 QSKIP("QTBUG-26424");
4766 parent.setWindowFlags(Qt::FramelessWindowHint);
4767 parent.setGeometry(10, 10, 200, 100);
4769 ColorWidget alien(&parent, Qt::black);
4770 alien.setGeometry(0, 0, 10, 10);
4775 QTest::qWaitForWindowShown(parent.windowHandle());
4777 QWindowSystemInterface::handleMouseEvent(parent.windowHandle(), QPointF(5, 5), QPointF(), Qt::LeftButton, Qt::NoModifier);
4779 QWindowSystemInterface::handleMouseEvent(parent.windowHandle(), QPointF(5, 5), QPointF(), Qt::NoButton, Qt::NoModifier);
4782 QStringList wordList;
4783 wordList << "alpha" << "omega" << "omicron" << "zeta";
4785 QLineEdit popup(&parent);
4787 QCompleter completer(wordList);
4788 completer.setCaseSensitivity(Qt::CaseInsensitive);
4789 popup.setCompleter(&completer);
4790 popup.setWindowFlags(Qt::Popup);
4791 popup.setGeometry(20, 20, 80, 20);
4795 QTest::qWaitForWindowShown(popup.windowHandle());
4799 QWindowSystemInterface::handleMouseEvent(popup.windowHandle(), QPointF(-5, -5), QPointF(), Qt::LeftButton, Qt::NoModifier);
4801 QWindowSystemInterface::handleMouseEvent(popup.windowHandle(), QPointF(-5, -5), QPointF(), Qt::NoButton, Qt::NoModifier);
4805 QVERIFY(!popup.underMouse());
4808 void tst_QWidget::moveChild_data()
4810 QTest::addColumn<QPoint>("offset");
4812 QTest::newRow("right") << QPoint(20, 0);
4813 QTest::newRow("down") << QPoint(0, 20);
4814 QTest::newRow("left") << QPoint(-20, 0);
4815 QTest::newRow("up") << QPoint(0, -20);
4818 void tst_QWidget::moveChild()
4820 QFETCH(QPoint, offset);
4823 // prevent custom styles
4824 parent.setStyle(new QWindowsStyle);
4825 ColorWidget child(&parent, Qt::blue);
4828 parent.setGeometry(QRect(QPoint(QApplication::desktop()->availableGeometry(&parent).topLeft()),
4831 parent.setGeometry(60, 60, 150, 150);
4833 child.setGeometry(25, 25, 50, 50);
4835 QTest::qWaitForWindowShown(&parent);
4837 const QPoint tlwOffset = parent.geometry().topLeft();
4839 QTRY_COMPARE(parent.r, QRegion(parent.rect()) - child.geometry());
4840 QTRY_COMPARE(child.r, QRegion(child.rect()));
4841 VERIFY_COLOR(child.geometry().translated(tlwOffset),
4843 VERIFY_COLOR(QRegion(parent.geometry()) - child.geometry().translated(tlwOffset),
4850 const QRect oldGeometry = child.geometry();
4852 QPoint pos = child.pos() + offset;
4855 QTRY_COMPARE(pos, child.pos());
4857 QCOMPARE(parent.r, QRegion(oldGeometry) - child.geometry());
4858 #if !defined(Q_OS_MAC)
4859 // should be scrolled in backingstore
4860 QCOMPARE(child.r, QRegion());
4862 VERIFY_COLOR(child.geometry().translated(tlwOffset),
4864 VERIFY_COLOR(QRegion(parent.geometry()) - child.geometry().translated(tlwOffset),
4868 void tst_QWidget::showAndMoveChild()
4870 if (m_platform == QStringLiteral("windows"))
4871 QSKIP("QTBUG-26424");
4873 QWidget parent(0, Qt::FramelessWindowHint);
4874 // prevent custom styles
4875 parent.setStyle(new QWindowsStyle);
4877 QDesktopWidget desktop;
4878 QRect desktopDimensions = desktop.availableGeometry(&parent);
4879 desktopDimensions = desktopDimensions.adjusted(64, 64, -64, -64);
4881 parent.setGeometry(desktopDimensions);
4882 parent.setPalette(Qt::red);
4884 QTest::qWaitForWindowShown(&parent);
4887 const QPoint tlwOffset = parent.geometry().topLeft();
4888 QWidget child(&parent);
4889 child.resize(desktopDimensions.width()/2, desktopDimensions.height()/2);
4890 child.setPalette(Qt::blue);
4891 child.setAutoFillBackground(true);
4893 // Ensure that the child is repainted correctly when moved right after show.
4894 // NB! Do NOT processEvents() (or qWait()) in between show() and move().
4896 child.move(desktopDimensions.width()/2, desktopDimensions.height()/2);
4897 qApp->processEvents();
4899 VERIFY_COLOR(child.geometry().translated(tlwOffset), Qt::blue);
4900 VERIFY_COLOR(QRegion(parent.geometry()) - child.geometry().translated(tlwOffset), Qt::red);
4903 // Cocoa only has rect granularity.
4905 void tst_QWidget::subtractOpaqueSiblings()
4908 w.setGeometry(50, 50, 300, 300);
4910 ColorWidget *large = new ColorWidget(&w, Qt::red);
4911 large->setGeometry(50, 50, 200, 200);
4913 ColorWidget *medium = new ColorWidget(large, Qt::gray);
4914 medium->setGeometry(50, 50, 100, 100);
4916 ColorWidget *tall = new ColorWidget(&w, Qt::blue);
4917 tall->setGeometry(100, 30, 50, 100);
4920 QTest::qWaitForWindowShown(&w);
4930 // QWidgetPrivate::subtractOpaqueSiblings() should prevent parts of medium
4931 // to be repainted and tall from be repainted at all.
4933 QTRY_COMPARE(large->r, QRegion());
4934 QTRY_COMPARE(tall->r, QRegion());
4935 QTRY_COMPARE(medium->r.translated(medium->mapTo(&w, QPoint())),
4936 QRegion(medium->geometry().translated(large->pos()))
4937 - tall->geometry());
4941 void tst_QWidget::deleteStyle()
4944 widget.setStyle(new QWindowsStyle);
4946 delete widget.style();
4947 qApp->processEvents();
4950 class TopLevelFocusCheck: public QWidget
4955 TopLevelFocusCheck(QWidget* parent = 0) : QWidget(parent)
4957 edit = new QLineEdit(this);
4959 edit->installEventFilter(this);
4963 void mouseDoubleClickEvent ( QMouseEvent * /*event*/ )
4966 edit->setFocus(Qt::OtherFocusReason);
4967 qApp->processEvents();
4969 bool eventFilter(QObject *obj, QEvent *event)
4971 if (obj == edit && event->type()== QEvent::FocusOut) {
4979 void tst_QWidget::multipleToplevelFocusCheck()
4981 TopLevelFocusCheck w1;
4982 TopLevelFocusCheck w2;
4984 w1.resize(200, 200);
4986 QTest::qWaitForWindowShown(&w1);
4989 QTest::qWaitForWindowShown(&w2);
4993 QApplication::setActiveWindow(&w1);
4994 w1.activateWindow();
4995 QApplication::processEvents();
4996 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&w1));
4998 QTest::mouseDClick(&w1, Qt::LeftButton);
4999 QTRY_COMPARE(QApplication::focusWidget(), static_cast<QWidget *>(w1.edit));
5001 w2.activateWindow();
5002 QApplication::setActiveWindow(&w2);
5003 QApplication::processEvents();
5004 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&w2));
5005 QTest::mouseClick(&w2, Qt::LeftButton);
5006 QTRY_COMPARE(QApplication::focusWidget(), (QWidget *)0);
5008 QTest::mouseDClick(&w2, Qt::LeftButton);
5009 QTRY_COMPARE(QApplication::focusWidget(), static_cast<QWidget *>(w2.edit));
5011 w1.activateWindow();
5012 QApplication::setActiveWindow(&w1);
5013 QApplication::processEvents();
5014 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&w1));
5015 QTest::mouseDClick(&w1, Qt::LeftButton);
5016 QTRY_COMPARE(QApplication::focusWidget(), static_cast<QWidget *>(w1.edit));
5018 w2.activateWindow();
5019 QApplication::setActiveWindow(&w2);
5020 QApplication::processEvents();
5021 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&w2));
5022 QTest::mouseClick(&w2, Qt::LeftButton);
5023 QTRY_COMPARE(QApplication::focusWidget(), (QWidget *)0);
5026 class FocusWidget: public QWidget
5029 virtual bool event(QEvent *ev)
5031 if (ev->type() == QEvent::FocusAboutToChange)
5032 widgetDuringFocusAboutToChange = qApp->focusWidget();
5033 return QWidget::event(ev);
5035 virtual void focusOutEvent(QFocusEvent *)
5037 widgetDuringFocusOut = qApp->focusWidget();
5041 FocusWidget(QWidget *parent) : QWidget(parent), widgetDuringFocusAboutToChange(0), widgetDuringFocusOut(0) {}
5043 QWidget *widgetDuringFocusAboutToChange;
5044 QWidget *widgetDuringFocusOut;
5047 void tst_QWidget::setFocus()
5050 // move focus to another window
5051 testWidget->activateWindow();
5052 QApplication::setActiveWindow(testWidget);
5053 if (testWidget->focusWidget())
5054 testWidget->focusWidget()->clearFocus();
5056 testWidget->clearFocus();
5058 // window and children never shown, nobody gets focus
5061 QWidget child1(&window);
5062 child1.setFocusPolicy(Qt::StrongFocus);
5064 QWidget child2(&window);
5065 child2.setFocusPolicy(Qt::StrongFocus);
5068 QVERIFY(!child1.hasFocus());
5069 QCOMPARE(window.focusWidget(), &child1);
5070 QCOMPARE(QApplication::focusWidget(), static_cast<QWidget *>(0));
5073 QVERIFY(!child2.hasFocus());
5074 QCOMPARE(window.focusWidget(), &child2);
5075 QCOMPARE(QApplication::focusWidget(), static_cast<QWidget *>(0));
5079 // window and children show, but window not active, nobody gets focus
5082 QWidget child1(&window);
5083 child1.setFocusPolicy(Qt::StrongFocus);
5085 QWidget child2(&window);
5086 child2.setFocusPolicy(Qt::StrongFocus);
5090 // note: window may be active, but we don't want it to be
5091 testWidget->activateWindow();
5092 QApplication::setActiveWindow(testWidget);
5093 if (testWidget->focusWidget())
5094 testWidget->focusWidget()->clearFocus();
5096 testWidget->clearFocus();
5099 QVERIFY(!child1.hasFocus());
5100 QCOMPARE(window.focusWidget(), &child1);
5101 QCOMPARE(QApplication::focusWidget(), static_cast<QWidget *>(0));
5104 QVERIFY(!child2.hasFocus());
5105 QCOMPARE(window.focusWidget(), &child2);
5106 QCOMPARE(QApplication::focusWidget(), static_cast<QWidget *>(0));
5110 // window and children show, but window *is* active, children get focus
5113 FocusWidget child1(&window);
5114 child1.setFocusPolicy(Qt::StrongFocus);
5116 QWidget child2(&window);
5117 child2.setFocusPolicy(Qt::StrongFocus);
5120 window.activateWindow();
5121 QTest::qWaitForWindowShown(&window);
5122 QTRY_VERIFY(qGuiApp->focusWindow());
5125 QTRY_VERIFY(child1.hasFocus());
5126 QCOMPARE(window.focusWidget(), &child1);
5127 QCOMPARE(QApplication::focusWidget(), &child1);
5130 QVERIFY(child2.hasFocus());
5131 QCOMPARE(window.focusWidget(), &child2);
5132 QCOMPARE(QApplication::focusWidget(), &child2);
5134 // focus changed in between the events
5135 QCOMPARE(child1.widgetDuringFocusAboutToChange, &child1);
5136 QCOMPARE(child1.widgetDuringFocusOut, &child2);
5140 // window shown and active, children created, don't get focus, but get focus when shown
5144 window.activateWindow();
5145 QTest::qWaitForWindowShown(&window);
5146 QTRY_VERIFY(qGuiApp->focusWindow());
5148 QWidget child1(&window);
5149 child1.setFocusPolicy(Qt::StrongFocus);
5151 QWidget child2(&window);
5152 child2.setFocusPolicy(Qt::StrongFocus);
5155 QVERIFY(!child1.hasFocus());
5156 QCOMPARE(window.focusWidget(), static_cast<QWidget *>(0));
5157 QCOMPARE(QApplication::focusWidget(), static_cast<QWidget *>(0));
5160 QApplication::processEvents();
5161 QTRY_VERIFY(child1.hasFocus());
5162 QCOMPARE(window.focusWidget(), &child1);
5163 QCOMPARE(QApplication::focusWidget(), &child1);
5166 QVERIFY(!child2.hasFocus());
5167 QCOMPARE(window.focusWidget(), &child1);
5168 QCOMPARE(QApplication::focusWidget(), &child1);
5171 QVERIFY(child2.hasFocus());
5172 QCOMPARE(window.focusWidget(), &child2);
5173 QCOMPARE(QApplication::focusWidget(), &child2);
5177 // window shown and active, children created, don't get focus,
5178 // even after setFocus(), hide(), then show()
5182 window.activateWindow();
5183 QTest::qWaitForWindowShown(&window);
5184 QTRY_VERIFY(qGuiApp->focusWindow());
5186 QWidget child1(&window);
5187 child1.setFocusPolicy(Qt::StrongFocus);
5189 QWidget child2(&window);
5190 child2.setFocusPolicy(Qt::StrongFocus);
5193 QVERIFY(!child1.hasFocus());
5194 QCOMPARE(window.focusWidget(), static_cast<QWidget *>(0));
5195 QCOMPARE(QApplication::focusWidget(), static_cast<QWidget *>(0));
5198 QVERIFY(!child1.hasFocus());
5199 QCOMPARE(window.focusWidget(), static_cast<QWidget *>(0));
5200 QCOMPARE(QApplication::focusWidget(), static_cast<QWidget *>(0));
5203 QVERIFY(!child1.hasFocus());
5204 QCOMPARE(window.focusWidget(), static_cast<QWidget *>(0));
5205 QCOMPARE(QApplication::focusWidget(), static_cast<QWidget *>(0));
5208 QVERIFY(!child2.hasFocus());
5209 QCOMPARE(window.focusWidget(), static_cast<QWidget *>(0));
5210 QCOMPARE(QApplication::focusWidget(), static_cast<QWidget *>(0));
5213 QVERIFY(!child2.hasFocus());
5214 QCOMPARE(window.focusWidget(), static_cast<QWidget *>(0));
5215 QCOMPARE(QApplication::focusWidget(), static_cast<QWidget *>(0));
5218 QVERIFY(!child2.hasFocus());
5219 QCOMPARE(window.focusWidget(), static_cast<QWidget *>(0));
5220 QCOMPARE(QApplication::focusWidget(), static_cast<QWidget *>(0));
5224 class EventSpy : public QObject
5227 EventSpy(QWidget *widget, QEvent::Type event)
5228 : m_widget(widget), eventToSpy(event), m_count(0)
5231 m_widget->installEventFilter(this);
5234 QWidget *widget() const { return m_widget; }
5235 int count() const { return m_count; }
5236 void clear() { m_count = 0; }
5239 bool eventFilter(QObject *object, QEvent *event)
5241 if (event->type() == eventToSpy)
5243 return QObject::eventFilter(object, event);
5248 QEvent::Type eventToSpy;
5252 void tst_QWidget::setCursor()
5254 #ifndef QT_NO_CURSOR
5257 QWidget child(&window);
5259 QVERIFY(!window.testAttribute(Qt::WA_SetCursor));
5260 QVERIFY(!child.testAttribute(Qt::WA_SetCursor));
5262 window.setCursor(window.cursor());
5263 QVERIFY(window.testAttribute(Qt::WA_SetCursor));
5264 QVERIFY(!child.testAttribute(Qt::WA_SetCursor));
5265 QCOMPARE(child.cursor().shape(), window.cursor().shape());
5268 // do it again, but with window show()n
5271 QWidget child(&window);
5274 QVERIFY(!window.testAttribute(Qt::WA_SetCursor));
5275 QVERIFY(!child.testAttribute(Qt::WA_SetCursor));
5277 window.setCursor(window.cursor());
5278 QVERIFY(window.testAttribute(Qt::WA_SetCursor));
5279 QVERIFY(!child.testAttribute(Qt::WA_SetCursor));
5280 QCOMPARE(child.cursor().shape(), window.cursor().shape());
5286 QWidget child(&window);
5288 window.setCursor(Qt::WaitCursor);
5289 QVERIFY(window.testAttribute(Qt::WA_SetCursor));
5290 QVERIFY(!child.testAttribute(Qt::WA_SetCursor));
5291 QCOMPARE(child.cursor().shape(), window.cursor().shape());
5294 // same thing again, just with window show()n
5297 QWidget child(&window);
5300 window.setCursor(Qt::WaitCursor);
5301 QVERIFY(window.testAttribute(Qt::WA_SetCursor));
5302 QVERIFY(!child.testAttribute(Qt::WA_SetCursor));
5303 QCOMPARE(child.cursor().shape(), window.cursor().shape());
5306 // reparenting child should not cause the WA_SetCursor to become set
5310 QWidget child(&window);
5312 window.setCursor(Qt::WaitCursor);
5315 QVERIFY(!child.testAttribute(Qt::WA_SetCursor));
5316 QCOMPARE(child.cursor().shape(), QCursor().shape());
5318 child.setParent(&window2);
5319 QVERIFY(!child.testAttribute(Qt::WA_SetCursor));
5320 QCOMPARE(child.cursor().shape(), window2.cursor().shape());
5322 window2.setCursor(Qt::WaitCursor);
5323 QVERIFY(!child.testAttribute(Qt::WA_SetCursor));
5324 QCOMPARE(child.cursor().shape(), window2.cursor().shape());
5327 // again, with windows show()n
5331 QWidget child(&window);
5333 window.setCursor(Qt::WaitCursor);
5337 QVERIFY(!child.testAttribute(Qt::WA_SetCursor));
5338 QCOMPARE(child.cursor().shape(), QCursor().shape());
5340 child.setParent(&window2);
5341 QVERIFY(!child.testAttribute(Qt::WA_SetCursor));
5342 QCOMPARE(child.cursor().shape(), window2.cursor().shape());
5345 window2.setCursor(Qt::WaitCursor);
5346 QVERIFY(!child.testAttribute(Qt::WA_SetCursor));
5347 QCOMPARE(child.cursor().shape(), window2.cursor().shape());
5350 // test if CursorChange is sent
5353 EventSpy spy(&widget, QEvent::CursorChange);
5354 QCOMPARE(spy.count(), 0);
5355 widget.setCursor(QCursor(Qt::WaitCursor));
5356 QCOMPARE(spy.count(), 1);
5357 widget.unsetCursor();
5358 QCOMPARE(spy.count(), 2);
5363 void tst_QWidget::setToolTip()
5366 EventSpy spy(&widget, QEvent::ToolTipChange);
5367 QCOMPARE(spy.count(), 0);
5369 QCOMPARE(widget.toolTip(), QString());
5370 widget.setToolTip(QString("Hello"));
5371 QCOMPARE(widget.toolTip(), QString("Hello"));
5372 QCOMPARE(spy.count(), 1);
5373 widget.setToolTip(QString());
5374 QCOMPARE(widget.toolTip(), QString());
5375 QCOMPARE(spy.count(), 2);
5377 // Mouse over doesn't work on Windows mobile, so skip the rest of the test for that platform.
5378 #ifndef Q_OS_WINCE_WM
5379 for (int pass = 0; pass < 2; ++pass) {
5380 QWidget *popup = new QWidget(0, Qt::Popup);
5381 popup->resize(150, 50);
5382 QFrame *frame = new QFrame(popup);
5383 frame->setGeometry(0, 0, 50, 50);
5384 frame->setFrameStyle(QFrame::Box | QFrame::Plain);
5385 EventSpy spy1(frame, QEvent::ToolTip);
5386 EventSpy spy2(popup, QEvent::ToolTip);
5387 frame->setMouseTracking(pass == 0 ? false : true);
5388 frame->setToolTip(QLatin1String("TOOLTIP FRAME"));
5389 popup->setToolTip(QLatin1String("TOOLTIP POPUP"));
5391 QTest::qWaitForWindowShown(popup);
5393 QTest::mouseMove(frame);
5394 QTest::qWait(900); // delay is 700
5396 if (m_platform == QStringLiteral("xcb"))
5397 QSKIP("QTBUG-26424");
5398 QCOMPARE(spy1.count(), 1);
5399 QCOMPARE(spy2.count(), 0);
5401 QTest::qWait(2200); // delay is 2000
5402 QTest::mouseMove(popup);
5408 void tst_QWidget::testWindowIconChangeEventPropagation()
5410 // Create widget hierarchy.
5411 QWidget topLevelWidget;
5412 QWidget topLevelChild(&topLevelWidget);
5414 QDialog dialog(&topLevelWidget);
5415 QWidget dialogChild(&dialog);
5417 QWidgetList widgets;
5418 widgets << &topLevelWidget << &topLevelChild
5419 << &dialog << &dialogChild;
5420 QCOMPARE(widgets.count(), 4);
5422 // Create spy lists.
5423 QList <EventSpy *> applicationEventSpies;
5424 QList <EventSpy *> widgetEventSpies;
5425 foreach (QWidget *widget, widgets) {
5426 applicationEventSpies.append(new EventSpy(widget, QEvent::ApplicationWindowIconChange));
5427 widgetEventSpies.append(new EventSpy(widget, QEvent::WindowIconChange));
5430 // QApplication::setWindowIcon
5431 const QIcon windowIcon = qApp->style()->standardIcon(QStyle::SP_TitleBarMenuButton);
5432 qApp->setWindowIcon(windowIcon);
5434 for (int i = 0; i < widgets.count(); ++i) {
5435 // Check QEvent::ApplicationWindowIconChange
5436 EventSpy *spy = applicationEventSpies.at(i);
5437 QWidget *widget = spy->widget();
5438 if (widget->isWindow()) {
5439 QCOMPARE(spy->count(), 1);
5440 QCOMPARE(widget->windowIcon(), windowIcon);
5442 QCOMPARE(spy->count(), 0);
5446 // Check QEvent::WindowIconChange
5447 spy = widgetEventSpies.at(i);
5448 QCOMPARE(spy->count(), 1);
5452 // Set icon on a top-level widget.
5453 topLevelWidget.setWindowIcon(*new QIcon);
5455 for (int i = 0; i < widgets.count(); ++i) {
5456 // Check QEvent::ApplicationWindowIconChange
5457 EventSpy *spy = applicationEventSpies.at(i);
5458 QCOMPARE(spy->count(), 0);
5461 // Check QEvent::WindowIconChange
5462 spy = widgetEventSpies.at(i);
5463 QWidget *widget = spy->widget();
5464 if (widget == &topLevelWidget) {
5465 QCOMPARE(widget->windowIcon(), QIcon());
5466 QCOMPARE(spy->count(), 1);
5467 } else if (topLevelWidget.isAncestorOf(widget)) {
5468 QCOMPARE(spy->count(), 1);
5470 QCOMPARE(spy->count(), 0);
5476 for (int i = 0; i < widgets.count(); ++i) {
5477 delete applicationEventSpies.at(i);
5478 delete widgetEventSpies.at(i);
5480 qApp->setWindowIcon(QIcon());
5483 void tst_QWidget::minAndMaxSizeWithX11BypassWindowManagerHint()
5485 if (m_platform != QStringLiteral("xcb"))
5486 QSKIP("This test is for X11 only.");
5487 // Same size as in QWidget::create_sys().
5488 const QSize desktopSize = QApplication::desktop()->size();
5489 const QSize originalSize(desktopSize.width() / 2, desktopSize.height() * 4 / 10);
5492 QWidget widget(0, Qt::X11BypassWindowManagerHint);
5494 const QSize newMaximumSize = widget.size().boundedTo(originalSize) - QSize(10, 10);
5495 widget.setMaximumSize(newMaximumSize);
5496 QCOMPARE(widget.size(), newMaximumSize);
5499 QTest::qWaitForWindowShown(widget.windowHandle());
5500 QCOMPARE(widget.size(), newMaximumSize);
5504 QWidget widget(0, Qt::X11BypassWindowManagerHint);
5506 const QSize newMinimumSize = widget.size().expandedTo(originalSize) + QSize(10, 10);
5507 widget.setMinimumSize(newMinimumSize);
5508 QCOMPARE(widget.size(), newMinimumSize);
5511 QTest::qWaitForWindowShown(widget.windowHandle());
5512 QCOMPARE(widget.size(), newMinimumSize);
5516 class ShowHideShowWidget : public QWidget
5522 bool gotExpectedMapNotify;
5524 ShowHideShowWidget()
5525 : state(0), gotExpectedMapNotify(false)
5530 void timerEvent(QTimerEvent *)
5542 bool nativeEvent(const QByteArray &eventType, void *message, long *)
5544 enum { XCB_MAP_NOTIFY = 19 };
5546 if (state == 1 && eventType == QByteArrayLiteral("xcb_generic_event_t")) {
5547 // XCB events have a uint8 response_type member at the beginning.
5548 const unsigned char responseType = *(const unsigned char *)(message);
5549 if ((responseType & ~0x80) == XCB_MAP_NOTIFY)
5550 gotExpectedMapNotify = true;
5559 void tst_QWidget::showHideShowX11()
5561 if (m_platform != QStringLiteral("xcb"))
5562 QSKIP("This test is for X11 only.");
5564 ShowHideShowWidget w;
5568 QEventLoop eventLoop;
5569 connect(&w, SIGNAL(done()), &eventLoop, SLOT(quit()));
5572 QVERIFY(w.gotExpectedMapNotify);
5575 void tst_QWidget::clean_qt_x11_enforce_cursor()
5577 if (m_platform != QStringLiteral("xcb"))
5578 QSKIP("This test is for X11 only.");
5582 QWidget *w = new QWidget(&window);
5583 QWidget *child = new QWidget(w);
5584 child->setAttribute(Qt::WA_SetCursor, true);
5587 QApplication::setActiveWindow(&window);
5588 QTest::qWaitForWindowShown(&window);
5590 QCursor::setPos(window.geometry().center());
5594 QApplication::processEvents();
5600 QGraphicsScene scene;
5601 QLineEdit *edit = new QLineEdit;
5602 scene.addWidget(edit);
5604 // If the test didn't crash, then it passed.
5607 class EventRecorder : public QObject
5612 typedef QList<QPair<QWidget *, QEvent::Type> > EventList;
5614 EventRecorder(QObject *parent = 0)
5618 EventList eventList()
5628 bool eventFilter(QObject *object, QEvent *event)
5630 QWidget *widget = qobject_cast<QWidget *>(object);
5631 if (widget && !event->spontaneous())
5632 events.append(qMakePair(widget, event->type()));
5640 void tst_QWidget::childEvents()
5642 EventRecorder::EventList expected;
5644 // Move away the cursor; otherwise it might result in an enter event if it's
5645 // inside the widget when the widget is shown.
5646 QCursor::setPos(qApp->desktop()->availableGeometry().bottomRight());
5650 // no children created, not shown
5653 widget.installEventFilter(&spy);
5655 QCoreApplication::postEvent(&widget, new QEvent(QEvent::Type(QEvent::User + 1)));
5657 QCoreApplication::sendPostedEvents();
5660 EventRecorder::EventList()
5661 << qMakePair(&widget, QEvent::PolishRequest)
5662 << qMakePair(&widget, QEvent::Polish)
5663 << qMakePair(&widget, QEvent::Type(QEvent::User + 1));
5664 QCOMPARE(spy.eventList(), expected);
5668 // no children, shown
5671 widget.installEventFilter(&spy);
5673 QCoreApplication::postEvent(&widget, new QEvent(QEvent::Type(QEvent::User + 1)));
5677 EventRecorder::EventList()
5678 << qMakePair(&widget, QEvent::WinIdChange)
5679 << qMakePair(&widget, QEvent::Polish)
5680 << qMakePair(&widget, QEvent::Move)
5681 << qMakePair(&widget, QEvent::Resize)
5682 << qMakePair(&widget, QEvent::Show);
5684 expected << qMakePair(&widget, QEvent::ShowToParent);
5685 QCOMPARE(spy.eventList(), expected);
5688 QCoreApplication::sendPostedEvents();
5690 EventRecorder::EventList()
5691 << qMakePair(&widget, QEvent::PolishRequest)
5692 << qMakePair(&widget, QEvent::Type(QEvent::User + 1));
5695 expected << qMakePair(&widget, QEvent::UpdateLater);
5697 expected << qMakePair(&widget, QEvent::UpdateRequest);
5699 if (m_platform == QStringLiteral("windows") || m_platform == QStringLiteral("xcb"))
5700 QEXPECT_FAIL("", "QTBUG-26424", Continue);
5701 QCOMPARE(spy.eventList(), expected);
5705 // 2 children, not shown
5708 widget.installEventFilter(&spy);
5710 QCoreApplication::postEvent(&widget, new QEvent(QEvent::Type(QEvent::User + 1)));
5712 QWidget child1(&widget);
5714 child2.setParent(&widget);
5716 QCoreApplication::postEvent(&widget, new QEvent(QEvent::Type(QEvent::User + 2)));
5719 EventRecorder::EventList()
5720 << qMakePair(&widget, QEvent::ChildAdded)
5721 << qMakePair(&widget, QEvent::ChildAdded);
5722 QCOMPARE(spy.eventList(), expected);
5725 QCoreApplication::sendPostedEvents();
5727 EventRecorder::EventList()
5728 << qMakePair(&widget, QEvent::PolishRequest)
5729 << qMakePair(&widget, QEvent::Polish)
5730 << qMakePair(&widget, QEvent::ChildPolished)
5731 << qMakePair(&widget, QEvent::ChildPolished)
5732 << qMakePair(&widget, QEvent::Type(QEvent::User + 1))
5733 << qMakePair(&widget, QEvent::Type(QEvent::User + 2));
5734 QCOMPARE(spy.eventList(), expected);
5738 // 2 children, widget shown
5741 widget.installEventFilter(&spy);
5743 QCoreApplication::postEvent(&widget, new QEvent(QEvent::Type(QEvent::User + 1)));
5745 QWidget child1(&widget);
5747 child2.setParent(&widget);
5749 QCoreApplication::postEvent(&widget, new QEvent(QEvent::Type(QEvent::User + 2)));
5752 EventRecorder::EventList()
5753 << qMakePair(&widget, QEvent::ChildAdded)
5754 << qMakePair(&widget, QEvent::ChildAdded);
5755 QCOMPARE(spy.eventList(), expected);
5760 EventRecorder::EventList()
5761 << qMakePair(&widget, QEvent::WinIdChange)
5762 << qMakePair(&widget, QEvent::Polish)
5763 << qMakePair(&widget, QEvent::ChildPolished)
5764 << qMakePair(&widget, QEvent::ChildPolished)
5765 << qMakePair(&widget, QEvent::Move)
5766 << qMakePair(&widget, QEvent::Resize)
5767 << qMakePair(&widget, QEvent::Show);
5769 expected << qMakePair(&widget, QEvent::ShowToParent);
5770 QCOMPARE(spy.eventList(), expected);
5773 QCoreApplication::sendPostedEvents();
5775 EventRecorder::EventList()
5776 << qMakePair(&widget, QEvent::PolishRequest)
5777 << qMakePair(&widget, QEvent::Type(QEvent::User + 1))
5778 << qMakePair(&widget, QEvent::Type(QEvent::User + 2));
5781 expected << qMakePair(&widget, QEvent::UpdateLater);
5783 expected << qMakePair(&widget, QEvent::UpdateRequest);
5785 if (m_platform == QStringLiteral("windows") || m_platform == QStringLiteral("xcb"))
5786 QEXPECT_FAIL("", "QTBUG-26424", Continue);
5787 QCOMPARE(spy.eventList(), expected);
5791 // 2 children, but one is reparented away, not shown
5794 widget.installEventFilter(&spy);
5796 QCoreApplication::postEvent(&widget, new QEvent(QEvent::Type(QEvent::User + 1)));
5798 QWidget child1(&widget);
5800 child2.setParent(&widget);
5801 child2.setParent(0);
5803 QCoreApplication::postEvent(&widget, new QEvent(QEvent::Type(QEvent::User + 2)));
5806 EventRecorder::EventList()
5807 << qMakePair(&widget, QEvent::ChildAdded)
5808 << qMakePair(&widget, QEvent::ChildAdded)
5809 << qMakePair(&widget, QEvent::ChildRemoved);
5810 QCOMPARE(spy.eventList(), expected);
5813 QCoreApplication::sendPostedEvents();
5815 EventRecorder::EventList()
5816 << qMakePair(&widget, QEvent::PolishRequest)
5817 << qMakePair(&widget, QEvent::Polish)
5818 << qMakePair(&widget, QEvent::ChildPolished)
5819 << qMakePair(&widget, QEvent::Type(QEvent::User + 1))
5820 << qMakePair(&widget, QEvent::Type(QEvent::User + 2));
5821 QCOMPARE(spy.eventList(), expected);
5825 // 2 children, but one is reparented away, then widget is shown
5828 widget.installEventFilter(&spy);
5830 QCoreApplication::postEvent(&widget, new QEvent(QEvent::Type(QEvent::User + 1)));
5832 QWidget child1(&widget);
5834 child2.setParent(&widget);
5835 child2.setParent(0);
5837 QCoreApplication::postEvent(&widget, new QEvent(QEvent::Type(QEvent::User + 2)));
5840 EventRecorder::EventList()
5841 << qMakePair(&widget, QEvent::ChildAdded)
5842 << qMakePair(&widget, QEvent::ChildAdded)
5843 << qMakePair(&widget, QEvent::ChildRemoved);
5844 QCOMPARE(spy.eventList(), expected);
5849 EventRecorder::EventList()
5850 << qMakePair(&widget, QEvent::WinIdChange)
5851 << qMakePair(&widget, QEvent::Polish)
5852 << qMakePair(&widget, QEvent::ChildPolished)
5853 << qMakePair(&widget, QEvent::Move)
5854 << qMakePair(&widget, QEvent::Resize)
5855 << qMakePair(&widget, QEvent::Show);
5857 expected << qMakePair(&widget, QEvent::ShowToParent);
5858 QCOMPARE(spy.eventList(), expected);
5861 QCoreApplication::sendPostedEvents();
5863 EventRecorder::EventList()
5864 << qMakePair(&widget, QEvent::PolishRequest)
5865 << qMakePair(&widget, QEvent::Type(QEvent::User + 1))
5866 << qMakePair(&widget, QEvent::Type(QEvent::User + 2));
5869 expected << qMakePair(&widget, QEvent::UpdateLater);
5871 expected << qMakePair(&widget, QEvent::UpdateRequest);
5873 if (m_platform == QStringLiteral("windows") || m_platform == QStringLiteral("xcb"))
5874 QEXPECT_FAIL("", "QTBUG-26424", Continue);
5875 QCOMPARE(spy.eventList(), expected);
5879 class RenderWidget : public QWidget
5882 RenderWidget(QWidget *source)
5883 : source(source), ellipse(false) {}
5885 void setEllipseEnabled(bool enable = true)
5892 void paintEvent(QPaintEvent *)
5895 QPainter painter(this);
5896 painter.fillRect(rect(), Qt::red);
5898 QRegion regionToRender = QRegion(0, 0, source->width(), source->height() / 2,
5900 source->render(this, QPoint(0, 30), regionToRender);
5902 source->render(this);
5911 void tst_QWidget::render()
5914 QCalendarWidget source;
5915 // disable anti-aliasing to eliminate potential differences when subpixel antialiasing
5916 // is enabled on the screen
5918 f.setStyleStrategy(QFont::NoAntialias);
5921 QTest::qWaitForWindowShown(&source);
5923 // Render the entire source into target.
5924 RenderWidget target(&source);
5925 target.resize(source.size());
5928 qApp->processEvents();
5929 qApp->sendPostedEvents();
5932 const QImage sourceImage = source.grab(QRect(QPoint(0, 0), QSize(-1, -1))).toImage();
5933 qApp->processEvents();
5934 QImage targetImage = target.grab(QRect(QPoint(0, 0), QSize(-1, -1))).toImage();
5935 qApp->processEvents();
5936 QCOMPARE(sourceImage, targetImage);
5938 // Fill target.rect() will Qt::red and render
5939 // QRegion(0, 0, source->width(), source->height() / 2, QRegion::Ellipse)
5940 // of source into target with offset (0, 30).
5941 target.setEllipseEnabled();
5942 qApp->processEvents();
5943 qApp->sendPostedEvents();
5945 targetImage = target.grab(QRect(QPoint(0, 0), QSize(-1, -1))).toImage();
5946 QVERIFY(sourceImage != targetImage);
5948 QCOMPARE(targetImage.pixel(target.width() / 2, 29), QColor(Qt::red).rgb());
5949 QCOMPARE(targetImage.pixel(target.width() / 2, 30), sourceImage.pixel(source.width() / 2, 0));
5951 // Test that a child widget properly fills its background
5954 window.resize(100, 100);
5955 // prevent custom styles
5956 window.setStyle(new QWindowsStyle);
5958 QTest::qWaitForWindowShown(&window);
5959 QWidget child(&window);
5960 child.resize(window.size());
5963 qApp->processEvents();
5964 const QPixmap childPixmap = child.grab(QRect(QPoint(0, 0), QSize(-1, -1)));
5965 const QPixmap windowPixmap = window.grab(QRect(QPoint(0, 0), QSize(-1, -1)));
5966 QCOMPARE(childPixmap, windowPixmap);
5969 { // Check that the target offset is correct.
5971 widget.resize(200, 200);
5972 widget.setAutoFillBackground(true);
5973 widget.setPalette(Qt::red);
5974 // prevent custom styles
5975 widget.setStyle(new QWindowsStyle);
5977 QTest::qWaitForWindowShown(&widget);
5978 QImage image(widget.size(), QImage::Format_RGB32);
5979 image.fill(QColor(Qt::blue).rgb());
5981 // Target offset (0, 0)
5982 widget.render(&image, QPoint(), QRect(20, 20, 100, 100));
5983 QCOMPARE(image.pixel(0, 0), QColor(Qt::red).rgb());
5984 QCOMPARE(image.pixel(99, 99), QColor(Qt::red).rgb());
5985 QCOMPARE(image.pixel(100, 100), QColor(Qt::blue).rgb());
5987 // Target offset (20, 20).
5988 image.fill(QColor(Qt::blue).rgb());
5989 widget.render(&image, QPoint(20, 20), QRect(20, 20, 100, 100));
5990 QCOMPARE(image.pixel(0, 0), QColor(Qt::blue).rgb());
5991 QCOMPARE(image.pixel(19, 19), QColor(Qt::blue).rgb());
5992 QCOMPARE(image.pixel(20, 20), QColor(Qt::red).rgb());
5993 QCOMPARE(image.pixel(119, 119), QColor(Qt::red).rgb());
5994 QCOMPARE(image.pixel(120, 120), QColor(Qt::blue).rgb());
5998 // On Windows the active palette is used instead of the inactive palette even
5999 // though the widget is invisible. This is probably related to task 178507/168682,
6000 // but for the renderInvisible test it doesn't matter, we're mostly interested
6001 // in testing the geometry so just workaround the palette issue for now.
6002 static void workaroundPaletteIssue(QWidget *widget)
6010 QWidget *navigationBar = qFindChild<QWidget *>(widget, QLatin1String("qt_calendar_navigationbar"));
6011 QVERIFY(navigationBar);
6013 QPalette palette = navigationBar->palette();
6014 const QColor background = palette.color(QPalette::Inactive, navigationBar->backgroundRole());
6015 const QColor highlightedText = palette.color(QPalette::Inactive, QPalette::HighlightedText);
6016 palette.setColor(QPalette::Active, navigationBar->backgroundRole(), background);
6017 palette.setColor(QPalette::Active, QPalette::HighlightedText, highlightedText);
6018 navigationBar->setPalette(palette);
6021 //#define RENDER_DEBUG
6022 void tst_QWidget::renderInvisible()
6024 if (m_platform == QStringLiteral("xcb"))
6025 QSKIP("QTBUG-26424");
6027 QCalendarWidget *calendar = new QCalendarWidget;
6028 // disable anti-aliasing to eliminate potential differences when subpixel antialiasing
6029 // is enabled on the screen
6031 f.setStyleStrategy(QFont::NoAntialias);
6032 calendar->setFont(f);
6034 QTest::qWaitForWindowShown(calendar);
6036 // Create a dummy focus widget to get rid of focus rect in reference image.
6037 QLineEdit dummyFocusWidget;
6038 dummyFocusWidget.show();
6039 QTest::qWaitForWindowShown(&dummyFocusWidget);
6040 qApp->processEvents();
6043 // Create normal reference image.
6044 const QSize calendarSize = calendar->size();
6045 QImage referenceImage(calendarSize, QImage::Format_ARGB32);
6046 calendar->render(&referenceImage);
6048 referenceImage.save("referenceImage.png");
6050 QVERIFY(!referenceImage.isNull());
6052 // Create resized reference image.
6053 const QSize calendarSizeResized = calendar->size() + QSize(50, 50);
6054 calendar->resize(calendarSizeResized);
6055 qApp->processEvents();
6057 QImage referenceImageResized(calendarSizeResized, QImage::Format_ARGB32);
6058 calendar->render(&referenceImageResized);
6060 referenceImageResized.save("referenceImageResized.png");
6062 QVERIFY(!referenceImageResized.isNull());
6064 // Explicitly hide the calendar.
6066 qApp->processEvents();
6068 workaroundPaletteIssue(calendar);
6070 { // Make sure we get the same image when the calendar is explicitly hidden.
6071 QImage testImage(calendarSizeResized, QImage::Format_ARGB32);
6072 calendar->render(&testImage);
6074 testImage.save("explicitlyHiddenCalendarResized.png");
6076 QCOMPARE(testImage, referenceImageResized);
6079 // Now that we have reference images we can delete the source and re-create
6080 // the calendar and check that we get the same images from a calendar which has never
6081 // been visible, laid out or created (Qt::WA_WState_Created).
6083 calendar = new QCalendarWidget;
6084 calendar->setFont(f);
6085 workaroundPaletteIssue(calendar);
6087 { // Never been visible, created or laid out.
6088 QImage testImage(calendarSize, QImage::Format_ARGB32);
6089 calendar->render(&testImage);
6091 testImage.save("neverBeenVisibleCreatedOrLaidOut.png");
6093 QCOMPARE(testImage, referenceImage);
6097 qApp->processEvents();
6100 { // Calendar explicitly hidden.
6101 QImage testImage(calendarSize, QImage::Format_ARGB32);
6102 calendar->render(&testImage);
6104 testImage.save("explicitlyHiddenCalendar.png");
6106 QCOMPARE(testImage, referenceImage);
6109 // Get navigation bar and explicitly hide it.
6110 QWidget *navigationBar = qFindChild<QWidget *>(calendar, QLatin1String("qt_calendar_navigationbar"));
6111 QVERIFY(navigationBar);
6112 navigationBar->hide();
6114 { // Check that the navigation bar isn't drawn when rendering the entire calendar.
6115 QImage testImage(calendarSize, QImage::Format_ARGB32);
6116 calendar->render(&testImage);
6118 testImage.save("calendarWithoutNavigationBar.png");
6120 QVERIFY(testImage != referenceImage);
6123 { // Make sure the navigation bar renders correctly even though it's hidden.
6124 QImage testImage(navigationBar->size(), QImage::Format_ARGB32);
6125 navigationBar->render(&testImage);
6127 testImage.save("explicitlyHiddenNavigationBar.png");
6129 QCOMPARE(testImage, referenceImage.copy(navigationBar->rect()));
6132 // Get next month button.
6133 QWidget *nextMonthButton = qFindChild<QWidget *>(navigationBar, QLatin1String("qt_calendar_nextmonth"));
6134 QVERIFY(nextMonthButton);
6136 { // Render next month button.
6137 // Fill test image with correct background color.
6138 QImage testImage(nextMonthButton->size(), QImage::Format_ARGB32);
6139 navigationBar->render(&testImage, QPoint(), QRegion(), QWidget::RenderFlags());
6141 testImage.save("nextMonthButtonBackground.png");
6144 // Set the button's background color to Qt::transparent; otherwise it will fill the
6145 // background with QPalette::Window.
6146 const QPalette originalPalette = nextMonthButton->palette();
6147 QPalette palette = originalPalette;
6148 palette.setColor(QPalette::Window, Qt::transparent);
6149 nextMonthButton->setPalette(palette);
6151 // Render the button on top of the background.
6152 nextMonthButton->render(&testImage);
6154 testImage.save("nextMonthButton.png");
6156 const QRect buttonRect(nextMonthButton->mapTo(calendar, QPoint()), nextMonthButton->size());
6157 QCOMPARE(testImage, referenceImage.copy(buttonRect));
6160 nextMonthButton->setPalette(originalPalette);
6163 // Navigation bar isn't explicitly hidden anymore.
6164 navigationBar->show();
6165 qApp->processEvents();
6167 QVERIFY(!calendar->isVisible());
6169 // Now, completely mess up the layout. This will trigger an update on the layout
6170 // when the calendar is visible or shown, but it's not. QWidget::render must therefore
6171 // make sure the layout is activated before rendering.
6172 QVERIFY(!calendar->isVisible());
6173 calendar->resize(calendarSizeResized);
6174 qApp->processEvents();
6176 { // Make sure we get an image equal to the resized reference image.
6177 QImage testImage(calendarSizeResized, QImage::Format_ARGB32);
6178 calendar->render(&testImage);
6180 testImage.save("calendarResized.png");
6182 QCOMPARE(testImage, referenceImageResized);
6185 { // Make sure we lay out the widget correctly the first time it's rendered.
6186 QCalendarWidget calendar;
6187 const QSize calendarSize = calendar.sizeHint();
6189 QImage image(2 * calendarSize, QImage::Format_ARGB32);
6190 image.fill(QColor(Qt::red).rgb());
6191 calendar.render(&image);
6193 for (int i = calendarSize.height(); i < 2 * calendarSize.height(); ++i)
6194 for (int j = calendarSize.width(); j < 2 * calendarSize.width(); ++j)
6195 QCOMPARE(image.pixel(j, i), QColor(Qt::red).rgb());
6198 { // Ensure that we don't call adjustSize() on invisible top-levels if render() is called
6199 // right after widgets have been added/removed to/from its layout.
6201 topLevel.setLayout(new QVBoxLayout);
6203 QWidget *widget = new QLineEdit;
6204 topLevel.layout()->addWidget(widget);
6206 const QSize initialSize = topLevel.size();
6207 QPixmap pixmap(topLevel.sizeHint());
6208 topLevel.render(&pixmap); // triggers adjustSize()
6209 const QSize finalSize = topLevel.size();
6210 QVERIFY(finalSize != initialSize);
6212 topLevel.layout()->removeWidget(widget);
6213 QCOMPARE(topLevel.size(), finalSize);
6214 topLevel.render(&pixmap);
6215 QCOMPARE(topLevel.size(), finalSize);
6217 topLevel.layout()->addWidget(widget);
6218 QCOMPARE(topLevel.size(), finalSize);
6219 topLevel.render(&pixmap);
6220 QCOMPARE(topLevel.size(), finalSize);
6224 void tst_QWidget::renderWithPainter()
6227 // prevent custom styles
6228 widget.setStyle(new QWindowsStyle);
6230 widget.resize(70, 50);
6231 widget.setAutoFillBackground(true);
6232 widget.setPalette(Qt::black);
6234 // Render the entire widget onto the image.
6235 QImage image(QSize(70, 50), QImage::Format_ARGB32);
6236 image.fill(QColor(Qt::red).rgb());
6237 QPainter painter(&image);
6238 widget.render(&painter);
6240 for (int i = 0; i < image.height(); ++i) {
6241 for (int j = 0; j < image.width(); ++j)
6242 QCOMPARE(image.pixel(j, i), QColor(Qt::black).rgb());
6245 // Translate painter (10, 10).
6247 image.fill(QColor(Qt::red).rgb());
6248 painter.translate(10, 10);
6249 widget.render(&painter);
6252 for (int i = 0; i < image.height(); ++i) {
6253 for (int j = 0; j < image.width(); ++j) {
6254 if (i < 10 || j < 10)
6255 QCOMPARE(image.pixel(j, i), QColor(Qt::red).rgb());
6257 QCOMPARE(image.pixel(j, i), QColor(Qt::black).rgb());
6261 // Pass target offset (10, 10) (the same as QPainter::translate).
6262 image.fill(QColor(Qt::red).rgb());
6263 widget.render(&painter, QPoint(10, 10));
6265 for (int i = 0; i < image.height(); ++i) {
6266 for (int j = 0; j < image.width(); ++j) {
6267 if (i < 10 || j < 10)
6268 QCOMPARE(image.pixel(j, i), QColor(Qt::red).rgb());
6270 QCOMPARE(image.pixel(j, i), QColor(Qt::black).rgb());
6274 // Translate (10, 10) and pass target offset (10, 10).
6276 image.fill(QColor(Qt::red).rgb());
6277 painter.translate(10, 10);
6278 widget.render(&painter, QPoint(10, 10));
6281 for (int i = 0; i < image.height(); ++i) {
6282 for (int j = 0; j < image.width(); ++j) {
6283 if (i < 20 || j < 20)
6284 QCOMPARE(image.pixel(j, i), QColor(Qt::red).rgb());
6286 QCOMPARE(image.pixel(j, i), QColor(Qt::black).rgb());
6290 // Rotate painter 90 degrees.
6292 image.fill(QColor(Qt::red).rgb());
6294 widget.render(&painter);
6297 for (int i = 0; i < image.height(); ++i) {
6298 for (int j = 0; j < image.width(); ++j)
6299 QCOMPARE(image.pixel(j, i), QColor(Qt::red).rgb());
6302 // Translate and rotate.
6303 image.fill(QColor(Qt::red).rgb());
6304 widget.resize(40, 10);
6305 painter.translate(10, 10);
6307 widget.render(&painter);
6309 for (int i = 0; i < image.height(); ++i) {
6310 for (int j = 0; j < image.width(); ++j) {
6311 if (i >= 10 && j >= 0 && j < 10)
6312 QCOMPARE(image.pixel(j, i), QColor(Qt::black).rgb());
6314 QCOMPARE(image.pixel(j, i), QColor(Qt::red).rgb());
6318 // Make sure QWidget::render does not modify the render hints set on the painter.
6319 painter.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform
6320 | QPainter::NonCosmeticDefaultPen | QPainter::TextAntialiasing);
6321 QPainter::RenderHints oldRenderHints = painter.renderHints();
6322 widget.render(&painter);
6323 QCOMPARE(painter.renderHints(), oldRenderHints);
6326 void tst_QWidget::render_task188133()
6328 QMainWindow mainWindow;
6330 // Make sure QWidget::render does not trigger QWidget::repaint/update
6331 // and asserts for Qt::WA_WState_Created.
6332 const QPixmap pixmap = mainWindow.grab(QRect(QPoint(0, 0), QSize(-1, -1)));
6336 void tst_QWidget::render_task211796()
6338 class MyWidget : public QWidget
6340 void resizeEvent(QResizeEvent *)
6342 QPixmap pixmap(size());
6347 { // Please don't die in a resize recursion.
6349 widget.resize(200, 200);
6353 { // Same check with a deeper hierarchy.
6356 QWidget child(&widget);
6357 MyWidget grandChild;
6358 grandChild.setParent(&child);
6359 grandChild.resize(100, 100);
6364 void tst_QWidget::render_task217815()
6366 // Make sure we don't change the size of the widget when calling
6367 // render() and the widget has an explicit size set.
6368 // This was a problem on Windows because we called createWinId(),
6369 // which in turn enforced the size to be bigger than the smallest
6370 // possible native window size (which is (115,something) on WinXP).
6372 const QSize explicitSize(80, 20);
6373 widget.resize(explicitSize);
6374 QCOMPARE(widget.size(), explicitSize);
6376 QPixmap pixmap(explicitSize);
6377 widget.render(&pixmap);
6379 QCOMPARE(widget.size(), explicitSize);
6382 // Window Opacity is not supported on Windows CE.
6384 void tst_QWidget::render_windowOpacity()
6386 const qreal opacity = 0.5;
6388 { // Check that the painter opacity effects the widget drawing.
6390 QWidget child(&topLevel);
6391 child.resize(50, 50);
6392 child.setPalette(Qt::red);
6393 child.setAutoFillBackground(true);
6395 QPixmap expected(child.size());
6397 if (m_platform == QStringLiteral("xcb") && expected.depth() < 24)
6398 QSKIP("This test won't give correct results with dithered pixmaps");
6400 expected.fill(Qt::green);
6401 QPainter painter(&expected);
6402 painter.setOpacity(opacity);
6403 painter.fillRect(QRect(QPoint(0, 0), child.size()), Qt::red);
6406 QPixmap result(child.size());
6407 result.fill(Qt::green);
6408 painter.begin(&result);
6409 painter.setOpacity(opacity);
6410 child.render(&painter);
6412 QCOMPARE(result, expected);
6415 { // Combine the opacity set on the painter with the widget opacity.
6416 class MyWidget : public QWidget
6419 void paintEvent(QPaintEvent *)
6421 QPainter painter(this);
6422 painter.setOpacity(opacity);
6423 QCOMPARE(painter.opacity(), opacity);
6424 painter.fillRect(rect(), Qt::red);
6430 widget.resize(50, 50);
6431 widget.opacity = opacity;
6432 widget.setPalette(Qt::blue);
6433 widget.setAutoFillBackground(true);
6435 QPixmap expected(widget.size());
6436 expected.fill(Qt::green);
6437 QPainter painter(&expected);
6438 painter.setOpacity(opacity);
6439 QPixmap pixmap(widget.size());
6440 pixmap.fill(Qt::blue);
6441 QPainter pixmapPainter(&pixmap);
6442 pixmapPainter.setOpacity(opacity);
6443 pixmapPainter.fillRect(QRect(QPoint(), widget.size()), Qt::red);
6444 painter.drawPixmap(QPoint(), pixmap);
6447 QPixmap result(widget.size());
6448 result.fill(Qt::green);
6449 painter.begin(&result);
6450 painter.setOpacity(opacity);
6451 widget.render(&painter);
6453 QCOMPARE(result, expected);
6458 void tst_QWidget::render_systemClip()
6461 widget.setPalette(Qt::blue);
6462 widget.resize(100, 100);
6464 QImage image(widget.size(), QImage::Format_RGB32);
6465 image.fill(QColor(Qt::red).rgb());
6467 QPaintEngine *paintEngine = image.paintEngine();
6468 QVERIFY(paintEngine);
6469 paintEngine->setSystemClip(QRegion(0, 0, 50, 50));
6471 QPainter painter(&image);
6472 // Make sure we're using the same paint engine and has the right clip set.
6473 QCOMPARE(painter.paintEngine(), paintEngine);
6474 QCOMPARE(paintEngine->systemClip(), QRegion(0, 0, 50, 50));
6476 // Translate painter outside system clip.
6477 painter.translate(50, 0);
6478 widget.render(&painter);
6481 image.save("outside_systemclip.png");
6484 // All pixels should be red.
6485 for (int i = 0; i < image.height(); ++i) {
6486 for (int j = 0; j < image.width(); ++j)
6487 QCOMPARE(image.pixel(j, i), QColor(Qt::red).rgb());
6490 // Restore painter and refill image with red.
6491 image.fill(QColor(Qt::red).rgb());
6492 painter.translate(-50, 0);
6494 // Set transform on the painter.
6495 QTransform transform;
6496 transform.shear(0, 1);
6497 painter.setTransform(transform);
6498 widget.render(&painter);
6501 image.save("blue_triangle.png");
6504 // We should now have a blue triangle starting at scan line 1, and the rest should be red.
6514 for (int i = 0; i < image.height(); ++i) {
6515 for (int j = 0; j < image.width(); ++j) {
6516 if (i < 50 && j < i)
6517 QCOMPARE(image.pixel(j, i), QColor(Qt::blue).rgb());
6519 QCOMPARE(image.pixel(j, i), QColor(Qt::red).rgb());
6523 // We don't paint directly on the image on the Mac, so we cannot do the pixel comparison
6524 // as above due to QPainter::SmoothPixmapTransform. We therefore need to generate an
6525 // expected image by first painting on a pixmap, and then draw the pixmap onto
6526 // the image using QPainter::SmoothPixmapTransform. Then we can compare pixels :)
6527 // The check is basically the same, except that it takes the smoothening into account.
6528 QPixmap pixmap(50, 50);
6529 const QRegion sysClip(0, 0, 50, 50);
6530 widget.render(&pixmap, QPoint(), sysClip);
6532 QImage expectedImage(widget.size(), QImage::Format_RGB32);
6533 expectedImage.fill(QColor(Qt::red).rgb());
6534 expectedImage.paintEngine()->setSystemClip(sysClip);
6536 QPainter expectedImagePainter(&expectedImage);
6537 expectedImagePainter.setTransform(QTransform().shear(0, 1));
6538 // NB! This is the important part (SmoothPixmapTransform).
6539 expectedImagePainter.setRenderHints(QPainter::SmoothPixmapTransform);
6540 expectedImagePainter.drawPixmap(QPoint(0, 0), pixmap);
6541 expectedImagePainter.end();
6543 QCOMPARE(image, expectedImage);
6547 void tst_QWidget::render_systemClip2_data()
6549 QTest::addColumn<bool>("autoFillBackground");
6550 QTest::addColumn<bool>("usePaintEvent");
6551 QTest::addColumn<QColor>("expectedColor");
6553 QTest::newRow("Only auto-fill background") << true << false << QColor(Qt::blue);
6554 QTest::newRow("Only draw in paintEvent") << false << true << QColor(Qt::green);
6555 QTest::newRow("Auto-fill background and draw in paintEvent") << true << true << QColor(Qt::green);
6558 void tst_QWidget::render_systemClip2()
6560 QFETCH(bool, autoFillBackground);
6561 QFETCH(bool, usePaintEvent);
6562 QFETCH(QColor, expectedColor);
6564 QVERIFY2(expectedColor != QColor(Qt::red), "Qt::red is the reference color for the image, pick another color");
6566 class MyWidget : public QWidget
6570 void paintEvent(QPaintEvent *)
6573 QPainter(this).fillRect(rect(), Qt::green);
6578 widget.usePaintEvent = usePaintEvent;
6579 widget.setPalette(Qt::blue);
6580 // NB! widget.setAutoFillBackground(autoFillBackground) won't do the
6581 // trick here since the widget is a top-level. The background is filled
6582 // regardless, unless Qt::WA_OpaquePaintEvent or Qt::WA_NoSystemBackground
6583 // is set. We therefore use the opaque attribute to turn off auto-fill.
6584 if (!autoFillBackground)
6585 widget.setAttribute(Qt::WA_OpaquePaintEvent);
6586 widget.resize(100, 100);
6588 QImage image(widget.size(), QImage::Format_RGB32);
6589 image.fill(QColor(Qt::red).rgb());
6591 QPaintEngine *paintEngine = image.paintEngine();
6592 QVERIFY(paintEngine);
6594 QRegion systemClip(QRegion(50, 0, 50, 10));
6595 systemClip += QRegion(90, 10, 10, 40);
6596 paintEngine->setSystemClip(systemClip);
6598 // Render entire widget directly onto device.
6599 widget.render(&image);
6602 image.save("systemclip_with_device.png");
6604 // All pixels within the system clip should now be
6605 // the expectedColor, and the rest should be red.
6606 for (int i = 0; i < image.height(); ++i) {
6607 for (int j = 0; j < image.width(); ++j) {
6608 if (systemClip.contains(QPoint(j, i)))
6609 QCOMPARE(image.pixel(j, i), expectedColor.rgb());
6611 QCOMPARE(image.pixel(j, i), QColor(Qt::red).rgb());
6615 // Refill image with red.
6616 image.fill(QColor(Qt::red).rgb());
6617 paintEngine->setSystemClip(systemClip);
6619 // Do the same with an untransformed painter.
6620 QPainter painter(&image);
6621 //Make sure we're using the same paint engine and has the right clip set.
6622 QCOMPARE(painter.paintEngine(), paintEngine);
6623 QCOMPARE(paintEngine->systemClip(), systemClip);
6625 widget.render(&painter);
6628 image.save("systemclip_with_untransformed_painter.png");
6630 // All pixels within the system clip should now be
6631 // the expectedColor, and the rest should be red.
6632 for (int i = 0; i < image.height(); ++i) {
6633 for (int j = 0; j < image.width(); ++j) {
6634 if (systemClip.contains(QPoint(j, i)))
6635 QCOMPARE(image.pixel(j, i), expectedColor.rgb());
6637 QCOMPARE(image.pixel(j, i), QColor(Qt::red).rgb());
6642 void tst_QWidget::render_systemClip3_data()
6644 QTest::addColumn<QSize>("size");
6645 QTest::addColumn<bool>("useSystemClip");
6647 // Reference: http://en.wikipedia.org/wiki/Flag_of_Norway
6648 QTest::newRow("Norwegian Civil Flag") << QSize(220, 160) << false;
6649 QTest::newRow("Norwegian War Flag") << QSize(270, 160) << true;
6652 // This test ensures that the current engine clip (systemClip + painter clip)
6653 // is preserved after QPainter::setClipRegion(..., Qt::ReplaceClip);
6654 void tst_QWidget::render_systemClip3()
6656 QFETCH(QSize, size);
6657 QFETCH(bool, useSystemClip);
6659 // Calculate the inner/outer cross of the flag.
6660 QRegion outerCross(0, 0, size.width(), size.height());
6661 outerCross -= QRect(0, 0, 60, 60);
6662 outerCross -= QRect(100, 0, size.width() - 100, 60);
6663 outerCross -= QRect(0, 100, 60, 60);
6664 outerCross -= QRect(100, 100, size.width() - 100, 60);
6666 QRegion innerCross(0, 0, size.width(), size.height());
6667 innerCross -= QRect(0, 0, 70, 70);
6668 innerCross -= QRect(90, 0, size.width() - 90, 70);
6669 innerCross -= QRect(0, 90, 70, 70);
6670 innerCross -= QRect(90, 90, size.width() - 90, 70);
6672 const QRegion redArea(QRegion(0, 0, size.width(), size.height()) - outerCross);
6673 const QRegion whiteArea(outerCross - innerCross);
6674 const QRegion blueArea(innerCross);
6677 // Okay, here's the image that should look like a Norwegian civil/war flag in the end.
6678 QImage flag(size, QImage::Format_ARGB32);
6679 flag.fill(QColor(Qt::transparent).rgba());
6681 if (useSystemClip) {
6682 QPainterPath warClip(QPoint(size.width(), 0));
6683 warClip.lineTo(size.width() - 110, 60);
6684 warClip.lineTo(size.width(), 80);
6685 warClip.lineTo(size.width() - 110, 100);
6686 warClip.lineTo(size.width(), 160);
6687 warClip.closeSubpath();
6688 systemClip = QRegion(0, 0, size.width(), size.height()) - QRegion(warClip.toFillPolygon().toPolygon());
6689 flag.paintEngine()->setSystemClip(systemClip);
6692 QPainter painter(&flag);
6693 painter.fillRect(QRect(QPoint(), size), Qt::red); // Fill image background with red.
6694 painter.setClipRegion(outerCross); // Limit widget painting to inside the outer cross.
6696 // Here's the widget that's supposed to draw the inner/outer cross of the flag.
6697 // The outer cross (white) should be drawn when the background is auto-filled, and
6698 // the inner cross (blue) should be drawn in the paintEvent.
6699 class MyWidget : public QWidget
6701 void paintEvent(QPaintEvent *)
6703 QPainter painter(this);
6704 // Be evil and try to paint outside the outer cross. This should not be
6705 // possible since the shared painter is clipped to the outer cross.
6706 painter.setClipRect(0, 0, 60, 60, Qt::ReplaceClip);
6707 painter.fillRect(rect(), Qt::green);
6708 painter.setClipRegion(clip, Qt::ReplaceClip);
6709 painter.fillRect(rect(), Qt::blue);
6715 widget.clip = innerCross;
6716 widget.setFixedSize(size);
6717 widget.setPalette(Qt::white);
6718 widget.setAutoFillBackground(true);
6719 widget.render(&painter);
6722 flag.save("flag.png");
6725 // Let's make sure we got a Norwegian flag.
6726 for (int i = 0; i < flag.height(); ++i) {
6727 for (int j = 0; j < flag.width(); ++j) {
6728 const QPoint pixel(j, i);
6729 const QRgb pixelValue = flag.pixel(pixel);
6730 if (useSystemClip && !systemClip.contains(pixel))
6731 QCOMPARE(pixelValue, QColor(Qt::transparent).rgba());
6732 else if (redArea.contains(pixel))
6733 QCOMPARE(pixelValue, QColor(Qt::red).rgba());
6734 else if (whiteArea.contains(pixel))
6735 QCOMPARE(pixelValue, QColor(Qt::white).rgba());
6737 QCOMPARE(pixelValue, QColor(Qt::blue).rgba());
6742 void tst_QWidget::render_task252837()
6745 widget.resize(200, 200);
6747 QPixmap pixmap(widget.size());
6748 QPainter painter(&pixmap);
6749 // Please do not crash.
6750 widget.render(&painter);
6753 void tst_QWidget::render_worldTransform()
6755 class MyWidget : public QWidget
6757 void paintEvent(QPaintEvent *)
6759 QPainter painter(this);
6760 // Make sure world transform is identity.
6761 QCOMPARE(painter.worldTransform(), QTransform());
6763 // Make sure device transform is correct.
6764 const QPoint widgetOffset = geometry().topLeft();
6765 QTransform expectedDeviceTransform = QTransform::fromTranslate(105, 5);
6766 expectedDeviceTransform.rotate(90);
6767 expectedDeviceTransform.translate(widgetOffset.x(), widgetOffset.y());
6768 QCOMPARE(painter.deviceTransform(), expectedDeviceTransform);
6770 // Set new world transform.
6771 QTransform newWorldTransform = QTransform::fromTranslate(10, 10);
6772 newWorldTransform.rotate(90);
6773 painter.setWorldTransform(newWorldTransform);
6774 QCOMPARE(painter.worldTransform(), newWorldTransform);
6776 // Again, check device transform.
6777 expectedDeviceTransform.translate(10, 10);
6778 expectedDeviceTransform.rotate(90);
6779 QCOMPARE(painter.deviceTransform(), expectedDeviceTransform);
6781 painter.fillRect(QRect(0, 0, 20, 10), Qt::green);
6786 widget.setFixedSize(100, 100);
6787 widget.setPalette(Qt::red);
6788 widget.setAutoFillBackground(true);
6791 child.setParent(&widget);
6793 child.setFixedSize(50, 50);
6794 child.setPalette(Qt::blue);
6795 child.setAutoFillBackground(true);
6797 QImage image(QSize(110, 110), QImage::Format_RGB32);
6798 image.fill(QColor(Qt::black).rgb());
6800 QPainter painter(&image);
6801 painter.translate(105, 5);
6804 // Render widgets onto image.
6805 widget.render(&painter);
6807 image.save("render_worldTransform_image.png");
6810 // Ensure the transforms are unchanged after render.
6811 QCOMPARE(painter.worldTransform(), painter.worldTransform());
6812 QCOMPARE(painter.deviceTransform(), painter.deviceTransform());
6815 // Paint expected image.
6816 QImage expected(QSize(110, 110), QImage::Format_RGB32);
6817 expected.fill(QColor(Qt::black).rgb());
6819 QPainter expectedPainter(&expected);
6820 expectedPainter.translate(105, 5);
6821 expectedPainter.rotate(90);
6822 expectedPainter.save();
6823 expectedPainter.fillRect(widget.rect(),Qt::red);
6824 expectedPainter.translate(10, 10);
6825 expectedPainter.rotate(90);
6826 expectedPainter.fillRect(QRect(0, 0, 20, 10), Qt::green);
6827 expectedPainter.restore();
6828 expectedPainter.translate(50, 50);
6829 expectedPainter.fillRect(child.rect(),Qt::blue);
6830 expectedPainter.translate(10, 10);
6831 expectedPainter.rotate(90);
6832 expectedPainter.fillRect(QRect(0, 0, 20, 10), Qt::green);
6833 expectedPainter.end();
6836 expected.save("render_worldTransform_expected.png");
6839 QCOMPARE(image, expected);
6842 void tst_QWidget::setContentsMargins()
6844 QLabel label("why does it always rain on me?");
6845 QSize oldSize = label.sizeHint();
6846 label.setFrameStyle(QFrame::Sunken | QFrame::Box);
6847 QSize newSize = label.sizeHint();
6848 QVERIFY(oldSize != newSize);
6850 QLabel label2("why does it always rain on me?");
6852 label2.setFrameStyle(QFrame::Sunken | QFrame::Box);
6853 QCOMPARE(newSize, label2.sizeHint());
6855 QLabel label3("why does it always rain on me?");
6856 label3.setFrameStyle(QFrame::Sunken | QFrame::Box);
6857 QCOMPARE(newSize, label3.sizeHint());
6860 void tst_QWidget::moveWindowInShowEvent_data()
6862 QTest::addColumn<QPoint>("initial");
6863 QTest::addColumn<QPoint>("position");
6865 QPoint p = QApplication::desktop()->availableGeometry().topLeft();
6867 QTest::newRow("1") << p << (p + QPoint(10, 10));
6868 QTest::newRow("2") << (p + QPoint(10,10)) << p;
6871 void tst_QWidget::moveWindowInShowEvent()
6873 if (m_platform == QStringLiteral("xcb"))
6874 QSKIP("QTBUG-26424");
6876 QFETCH(QPoint, initial);
6877 QFETCH(QPoint, position);
6879 class MoveWindowInShowEventWidget : public QWidget
6883 void showEvent(QShowEvent *)
6889 MoveWindowInShowEventWidget widget;
6890 widget.resize(QSize(qApp->desktop()->availableGeometry().size() / 3).expandedTo(QSize(1, 1)));
6891 // move to this position in showEvent()
6892 widget.position = position;
6894 // put the widget in it's starting position
6895 widget.move(initial);
6896 QCOMPARE(widget.pos(), initial);
6900 QTest::qWaitForWindowShown(widget.windowHandle());
6902 // it should have moved
6903 QCOMPARE(widget.pos(), position);
6906 void tst_QWidget::repaintWhenChildDeleted()
6909 if (QSysInfo::WindowsVersion & QSysInfo::WV_VISTA) {
6913 ColorWidget w(0, Qt::red);
6914 #if !defined(Q_OS_WINCE)
6915 QPoint startPoint = QApplication::desktop()->availableGeometry(&w).topLeft();
6916 startPoint.rx() += 50;
6917 startPoint.ry() += 50;
6918 w.setGeometry(QRect(startPoint, QSize(100, 100)));
6920 w.setGeometry(60, 60, 110, 110);
6923 QTest::qWaitForWindowShown(&w);
6925 QTRY_COMPARE(w.r, QRegion(w.rect()));
6929 ColorWidget child(&w, Qt::blue);
6930 child.setGeometry(10, 10, 10, 10);
6933 QTRY_COMPARE(child.r, QRegion(child.rect()));
6938 QTRY_COMPARE(w.r, QRegion(10, 10, 10, 10));
6942 void tst_QWidget::hideOpaqueChildWhileHidden()
6944 ColorWidget w(0, Qt::red);
6945 #if !defined(Q_OS_WINCE)
6946 QPoint startPoint = QApplication::desktop()->availableGeometry(&w).topLeft();
6947 startPoint.rx() += 50;
6948 startPoint.ry() += 50;
6949 w.setGeometry(QRect(startPoint, QSize(100, 100)));
6951 w.setGeometry(60, 60, 110, 110);
6954 ColorWidget child(&w, Qt::blue);
6955 child.setGeometry(10, 10, 80, 80);
6957 ColorWidget child2(&child, Qt::white);
6958 child2.setGeometry(10, 10, 60, 60);
6961 QTest::qWaitForWindowShown(&w);
6963 QTRY_COMPARE(child2.r, QRegion(child2.rect()));
6964 child.r = QRegion();
6965 child2.r = QRegion();
6972 QCOMPARE(w.r, QRegion(child.geometry()));
6976 QCOMPARE(child.r, QRegion(child.rect()));
6977 QCOMPARE(child2.r, QRegion());
6980 // This test doesn't make sense without support for showMinimized().
6981 #if !defined(Q_OS_WINCE)
6982 void tst_QWidget::updateWhileMinimized()
6984 UpdateWidget widget;
6985 // Filter out activation change and focus events to avoid update() calls in QWidget.
6986 widget.updateOnActivationChangeAndFocusIn = false;
6989 QTest::qWaitForWindowShown(&widget);
6990 QApplication::processEvents();
6991 QTRY_VERIFY(widget.numPaintEvents > 0);
6995 widget.showMinimized();
7000 // The widget is not visible on the screen (but isVisible() still returns true).
7001 // Make sure update requests are discarded until the widget is shown again.
7002 widget.update(0, 0, 50, 50);
7004 if (m_platform == QStringLiteral("windows"))
7005 QEXPECT_FAIL("", "QTBUG-26424", Continue);
7006 QCOMPARE(widget.numPaintEvents, 0);
7009 widget.showNormal();
7011 if (m_platform == QStringLiteral("xcb"))
7012 QSKIP("QTBUG-26424");
7013 QTRY_COMPARE(widget.numPaintEvents, 1);
7014 QCOMPARE(widget.paintedRegion, QRegion(0, 0, 50, 50));
7018 class PaintOnScreenWidget: public QWidget
7021 PaintOnScreenWidget(QWidget *parent = 0, Qt::WindowFlags f = 0)
7025 #if defined(Q_OS_WIN)
7026 // This is the only way to enable PaintOnScreen on Windows.
7027 QPaintEngine * paintEngine () const {return 0;}
7031 void tst_QWidget::alienWidgets()
7033 if (m_platform != QStringLiteral("xcb") && m_platform != QStringLiteral("windows"))
7034 QSKIP("This test is only for X11/Windows.");
7036 qApp->setAttribute(Qt::AA_DontCreateNativeWidgetSiblings);
7038 QWidget child(&parent);
7039 QWidget grandChild(&child);
7040 QWidget greatGrandChild(&grandChild);
7043 QTest::qWaitForWindowShown(parent.windowHandle());
7045 // Verify that the WA_WState_Created attribute is set
7046 // and the top-level is the only native window.
7047 QVERIFY(parent.testAttribute(Qt::WA_WState_Created));
7048 QVERIFY(parent.internalWinId());
7050 QVERIFY(child.testAttribute(Qt::WA_WState_Created));
7051 QVERIFY(!child.internalWinId());
7053 QVERIFY(grandChild.testAttribute(Qt::WA_WState_Created));
7054 QVERIFY(!grandChild.internalWinId());
7056 QVERIFY(greatGrandChild.testAttribute(Qt::WA_WState_Created));
7057 QVERIFY(!greatGrandChild.internalWinId());
7059 // Enforce native windows all the way up in the parent hierarchy
7060 // if not WA_DontCreateNativeAncestors is set.
7061 grandChild.setAttribute(Qt::WA_DontCreateNativeAncestors);
7062 greatGrandChild.setAttribute(Qt::WA_NativeWindow);
7063 QVERIFY(greatGrandChild.internalWinId());
7064 QVERIFY(grandChild.internalWinId());
7065 QVERIFY(!child.internalWinId());
7068 // Ensure that hide() on an ancestor of a widget with
7069 // Qt::WA_DontCreateNativeAncestors still gets unmapped
7071 QWidget widget(&window);
7072 QWidget child(&widget);
7073 child.setAttribute(Qt::WA_NativeWindow);
7074 child.setAttribute(Qt::WA_DontCreateNativeAncestors);
7076 if (m_platform == QStringLiteral("xcb"))
7077 QEXPECT_FAIL("", "QTBUG-26424", Continue);
7078 QVERIFY(child.testAttribute(Qt::WA_Mapped));
7080 QVERIFY(!child.testAttribute(Qt::WA_Mapped));
7083 // Enforce a native window when calling QWidget::winId.
7084 QVERIFY(child.winId());
7085 QVERIFY(child.internalWinId());
7087 // Check that paint on screen widgets (incl. children) are native.
7088 PaintOnScreenWidget paintOnScreen(&parent);
7089 QWidget paintOnScreenChild(&paintOnScreen);
7090 paintOnScreen.show();
7091 QVERIFY(paintOnScreen.testAttribute(Qt::WA_WState_Created));
7092 QVERIFY(!paintOnScreen.testAttribute(Qt::WA_NativeWindow));
7093 QVERIFY(!paintOnScreen.internalWinId());
7094 QVERIFY(!paintOnScreenChild.testAttribute(Qt::WA_NativeWindow));
7095 QVERIFY(!paintOnScreenChild.internalWinId());
7097 paintOnScreen.setAttribute(Qt::WA_PaintOnScreen);
7098 if (m_platform == QStringLiteral("xcb") || m_platform == QStringLiteral("windows"))
7099 QEXPECT_FAIL("", "QTBUG-26424", Continue);
7100 QVERIFY(paintOnScreen.testAttribute(Qt::WA_NativeWindow));
7101 if (m_platform == QStringLiteral("xcb") || m_platform == QStringLiteral("windows"))
7102 QEXPECT_FAIL("", "QTBUG-26424", Continue);
7103 QVERIFY(paintOnScreen.internalWinId());
7104 if (m_platform == QStringLiteral("xcb") || m_platform == QStringLiteral("windows"))
7105 QEXPECT_FAIL("", "QTBUG-26424", Continue);
7106 QVERIFY(paintOnScreenChild.testAttribute(Qt::WA_NativeWindow));
7107 if (m_platform == QStringLiteral("xcb") || m_platform == QStringLiteral("windows"))
7108 QEXPECT_FAIL("", "QTBUG-26424", Continue);
7109 QVERIFY(paintOnScreenChild.internalWinId());
7111 // Check that widgets with the Qt::MSWindowsOwnDC attribute set
7113 QWidget msWindowsOwnDC(&parent, Qt::MSWindowsOwnDC);
7114 msWindowsOwnDC.show();
7115 QVERIFY(msWindowsOwnDC.testAttribute(Qt::WA_WState_Created));
7116 QVERIFY(msWindowsOwnDC.testAttribute(Qt::WA_NativeWindow));
7117 QVERIFY(msWindowsOwnDC.internalWinId());
7119 { // Enforce a native window when calling QWidget::handle() (on X11) or QWidget::getDC() (on Windows).
7120 QWidget widget(&parent);
7122 QVERIFY(widget.testAttribute(Qt::WA_WState_Created));
7123 QVERIFY(!widget.internalWinId());
7126 QVERIFY(widget.internalWinId());
7129 if (m_platform == QStringLiteral("xcb")) {
7130 // Make sure we don't create native windows when setting Qt::WA_X11NetWmWindowType attributes
7131 // on alien widgets (see task 194231).
7133 QVERIFY(dummy.winId());
7134 QWidget widget(&dummy);
7135 widget.setAttribute(Qt::WA_X11NetWmWindowTypeToolBar);
7136 QVERIFY(!widget.internalWinId());
7139 { // Make sure we create native ancestors when setting Qt::WA_PaintOnScreen before show().
7141 QWidget child(&topLevel);
7142 QWidget grandChild(&child);
7143 PaintOnScreenWidget greatGrandChild(&grandChild);
7145 greatGrandChild.setAttribute(Qt::WA_PaintOnScreen);
7146 QVERIFY(!child.internalWinId());
7147 QVERIFY(!grandChild.internalWinId());
7148 QVERIFY(!greatGrandChild.internalWinId());
7151 if (m_platform == QStringLiteral("xcb") || m_platform == QStringLiteral("windows"))
7152 QEXPECT_FAIL("", "QTBUG-26424", Continue);
7153 QVERIFY(child.internalWinId());
7154 if (m_platform == QStringLiteral("xcb") || m_platform == QStringLiteral("windows"))
7155 QEXPECT_FAIL("", "QTBUG-26424", Continue);
7156 QVERIFY(grandChild.internalWinId());
7157 if (m_platform == QStringLiteral("xcb") || m_platform == QStringLiteral("windows"))
7158 QEXPECT_FAIL("", "QTBUG-26424", Continue);
7159 QVERIFY(greatGrandChild.internalWinId());
7162 { // Ensure that widgets reparented into Qt::WA_PaintOnScreen widgets become native.
7164 QWidget *widget = new PaintOnScreenWidget(&topLevel);
7165 widget->setAttribute(Qt::WA_PaintOnScreen);
7166 QWidget *child = new QWidget;
7167 QWidget *dummy = new QWidget(child);
7168 QWidget *grandChild = new QWidget(child);
7169 QWidget *dummy2 = new QWidget(grandChild);
7171 child->setParent(widget);
7173 QVERIFY(!topLevel.internalWinId());
7174 QVERIFY(!child->internalWinId());
7175 QVERIFY(!dummy->internalWinId());
7176 QVERIFY(!grandChild->internalWinId());
7177 QVERIFY(!dummy2->internalWinId());
7180 QVERIFY(topLevel.internalWinId());
7181 if (m_platform == QStringLiteral("xcb") || m_platform == QStringLiteral("windows"))
7182 QEXPECT_FAIL("", "QTBUG-26424", Continue);
7183 QVERIFY(widget->testAttribute(Qt::WA_NativeWindow));
7184 if (m_platform == QStringLiteral("xcb") || m_platform == QStringLiteral("windows"))
7185 QEXPECT_FAIL("", "QTBUG-26424", Continue);
7186 QVERIFY(child->internalWinId());
7187 if (m_platform == QStringLiteral("xcb") || m_platform == QStringLiteral("windows"))
7188 QEXPECT_FAIL("", "QTBUG-26424", Continue);
7189 QVERIFY(child->testAttribute(Qt::WA_NativeWindow));
7190 QVERIFY(!child->testAttribute(Qt::WA_PaintOnScreen));
7191 QVERIFY(!dummy->internalWinId());
7192 QVERIFY(!dummy->testAttribute(Qt::WA_NativeWindow));
7193 QVERIFY(!grandChild->internalWinId());
7194 QVERIFY(!grandChild->testAttribute(Qt::WA_NativeWindow));
7195 QVERIFY(!dummy2->internalWinId());
7196 QVERIFY(!dummy2->testAttribute(Qt::WA_NativeWindow));
7199 { // Ensure that ancestors of a Qt::WA_PaintOnScreen widget stay native
7200 // if they are re-created (typically in QWidgetPrivate::setParent_sys) (task 210822).
7202 QWidget child(&window);
7205 grandChild.setWindowTitle("This causes the widget to be created");
7207 PaintOnScreenWidget paintOnScreenWidget;
7208 paintOnScreenWidget.setAttribute(Qt::WA_PaintOnScreen);
7209 paintOnScreenWidget.setParent(&grandChild);
7211 grandChild.setParent(&child);
7215 QVERIFY(window.internalWinId());
7216 if (m_platform == QStringLiteral("xcb") || m_platform == QStringLiteral("windows"))
7217 QEXPECT_FAIL("", "QTBUG-26424", Continue);
7218 QVERIFY(child.internalWinId());
7219 if (m_platform == QStringLiteral("xcb") || m_platform == QStringLiteral("windows"))
7220 QEXPECT_FAIL("", "QTBUG-26424", Continue);
7221 QVERIFY(child.testAttribute(Qt::WA_NativeWindow));
7222 if (m_platform == QStringLiteral("xcb") || m_platform == QStringLiteral("windows"))
7223 QEXPECT_FAIL("", "QTBUG-26424", Continue);
7224 QVERIFY(grandChild.internalWinId());
7225 if (m_platform == QStringLiteral("xcb") || m_platform == QStringLiteral("windows"))
7226 QEXPECT_FAIL("", "QTBUG-26424", Continue);
7227 QVERIFY(grandChild.testAttribute(Qt::WA_NativeWindow));
7228 if (m_platform == QStringLiteral("xcb") || m_platform == QStringLiteral("windows"))
7229 QEXPECT_FAIL("", "QTBUG-26424", Continue);
7230 QVERIFY(paintOnScreenWidget.internalWinId());
7231 if (m_platform == QStringLiteral("xcb") || m_platform == QStringLiteral("windows"))
7232 QEXPECT_FAIL("", "QTBUG-26424", Continue);
7233 QVERIFY(paintOnScreenWidget.testAttribute(Qt::WA_NativeWindow));
7236 { // Ensure that all siblings are native unless Qt::AA_DontCreateNativeWidgetSiblings is set.
7237 qApp->setAttribute(Qt::AA_DontCreateNativeWidgetSiblings, false);
7239 QWidget *toolBar = new QWidget(&mainWindow);
7240 QWidget *dockWidget = new QWidget(&mainWindow);
7241 QWidget *centralWidget = new QWidget(&mainWindow);
7243 QWidget *button = new QWidget(centralWidget);
7244 QWidget *mdiArea = new QWidget(centralWidget);
7246 QWidget *horizontalScroll = new QWidget(mdiArea);
7247 QWidget *verticalScroll = new QWidget(mdiArea);
7248 QWidget *viewport = new QWidget(mdiArea);
7250 viewport->setAttribute(Qt::WA_NativeWindow);
7253 // Ensure that the viewport and its siblings are native:
7254 QVERIFY(verticalScroll->testAttribute(Qt::WA_NativeWindow));
7255 QVERIFY(verticalScroll->testAttribute(Qt::WA_NativeWindow));
7256 QVERIFY(horizontalScroll->testAttribute(Qt::WA_NativeWindow));
7258 // Ensure that the mdi area and its siblings are native:
7259 QVERIFY(mdiArea->testAttribute(Qt::WA_NativeWindow));
7260 QVERIFY(button->testAttribute(Qt::WA_NativeWindow));
7262 // Ensure that the central widget and its siblings are native:
7263 QVERIFY(centralWidget->testAttribute(Qt::WA_NativeWindow));
7264 QVERIFY(dockWidget->testAttribute(Qt::WA_NativeWindow));
7265 QVERIFY(toolBar->testAttribute(Qt::WA_NativeWindow));
7269 class ASWidget : public QWidget
7272 ASWidget(QSize sizeHint, QSizePolicy sizePolicy, bool layout, bool hfwLayout, QWidget *parent = 0)
7273 : QWidget(parent), mySizeHint(sizeHint)
7275 setSizePolicy(sizePolicy);
7277 QSizePolicy sp = QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
7278 sp.setHeightForWidth(hfwLayout);
7280 QVBoxLayout *vbox = new QVBoxLayout;
7282 vbox->addWidget(new ASWidget(sizeHint + QSize(30, 20), sp, false, false));
7287 QSize sizeHint() const {
7289 return layout()->totalSizeHint();
7292 int heightForWidth(int width) const {
7293 if (sizePolicy().hasHeightForWidth()) {
7303 void tst_QWidget::adjustSize_data()
7305 const int MagicW = 200;
7306 const int MagicH = 100;
7308 QTest::addColumn<QSize>("sizeHint");
7309 QTest::addColumn<int>("hPolicy");
7310 QTest::addColumn<int>("vPolicy");
7311 QTest::addColumn<bool>("hfwSP");
7312 QTest::addColumn<bool>("layout");
7313 QTest::addColumn<bool>("hfwLayout");
7314 QTest::addColumn<bool>("haveParent");
7315 QTest::addColumn<QSize>("expectedSize");
7317 QTest::newRow("1") << QSize(5, 6) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
7318 << false << false << false << false << QSize(5, qMax(6, MagicH));
7319 QTest::newRow("2") << QSize(5, 6) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
7320 << true << false << false << false << QSize(5, qMax(10, MagicH));
7321 QTest::newRow("3") << QSize(5, 6) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
7322 << false << true << false << false << QSize(35, 26);
7323 QTest::newRow("4") << QSize(5, 6) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
7324 << false << true << true << false << QSize(35, 70);
7325 QTest::newRow("5") << QSize(40001, 30001) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
7326 << false << false << false << false << QSize(100000, 100000);
7327 QTest::newRow("6") << QSize(40001, 30001) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
7328 << true << false << false << false << QSize(100000, 100000);
7329 QTest::newRow("7") << QSize(40001, 30001) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
7330 << false << true << false << false << QSize(100000, 100000);
7331 QTest::newRow("8") << QSize(40001, 30001) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
7332 << false << true << true << false << QSize(100000, 100000);
7333 QTest::newRow("9") << QSize(5, 6) << int(QSizePolicy::Expanding) << int(QSizePolicy::Minimum)
7334 << true << false << false << false << QSize(qMax(5, MagicW), 10);
7336 QTest::newRow("1c") << QSize(5, 6) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
7337 << false << false << false << true << QSize(5, 6);
7338 QTest::newRow("2c") << QSize(5, 6) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
7339 << true << false << false << true << QSize(5, 6 /* or 10 would be OK too, since hfw contradicts sizeHint() */);
7340 QTest::newRow("3c") << QSize(5, 6) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
7341 << false << true << false << true << QSize(35, 26);
7342 QTest::newRow("4c") << QSize(5, 6) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
7343 << false << true << true << true << QSize(35, 70);
7344 QTest::newRow("5c") << QSize(40001, 30001) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
7345 << false << false << false << true << QSize(40001, 30001);
7346 QTest::newRow("6c") << QSize(40001, 30001) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
7347 << true << false << false << true << QSize(40001, 30001 /* or 80002 would be OK too, since hfw contradicts sizeHint() */);
7348 QTest::newRow("7c") << QSize(40001, 30001) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
7349 << false << true << false << true << QSize(40001 + 30, 30001 + 20);
7350 QTest::newRow("8c") << QSize(40001, 30001) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
7351 << false << true << true << true << QSize(40001 + 30, 80002 + 60);
7352 QTest::newRow("9c") << QSize(5, 6) << int(QSizePolicy::Expanding) << int(QSizePolicy::Minimum)
7353 << true << false << false << true << QSize(5, 6);
7356 void tst_QWidget::adjustSize()
7358 QFETCH(QSize, sizeHint);
7359 QFETCH(int, hPolicy);
7360 QFETCH(int, vPolicy);
7361 QFETCH(bool, hfwSP);
7362 QFETCH(bool, layout);
7363 QFETCH(bool, hfwLayout);
7364 QFETCH(bool, haveParent);
7365 QFETCH(QSize, expectedSize);
7367 QWidget *parent = new QWidget;
7369 QSizePolicy sp = QSizePolicy(QSizePolicy::Policy(hPolicy), QSizePolicy::Policy(vPolicy));
7370 sp.setHeightForWidth(hfwSP);
7372 QWidget *child = new ASWidget(sizeHint, sp, layout, hfwLayout, haveParent ? parent : 0);
7373 child->resize(123, 456);
7374 child->adjustSize();
7375 if (expectedSize == QSize(100000, 100000)) {
7376 QVERIFY(child->size().width() < sizeHint.width());
7377 QVERIFY(child->size().height() < sizeHint.height());
7379 #if defined (Q_OS_WINCE)
7381 const QRect& desktopRect = qApp->desktop()->availableGeometry();
7382 expectedSize.setWidth(qMin(expectedSize.width(), desktopRect.width()));
7383 expectedSize.setHeight(qMin(expectedSize.height(), desktopRect.height()));
7386 QCOMPARE(child->size(), expectedSize);
7392 class TestLayout : public QVBoxLayout
7396 TestLayout(QWidget *w = 0) : QVBoxLayout(w)
7398 invalidated = false;
7409 void tst_QWidget::updateGeometry_data()
7411 QTest::addColumn<QSize>("minSize");
7412 QTest::addColumn<bool>("shouldInvalidate");
7413 QTest::addColumn<QSize>("maxSize");
7414 QTest::addColumn<bool>("shouldInvalidate2");
7415 QTest::addColumn<int>("verticalSizePolicy");
7416 QTest::addColumn<bool>("shouldInvalidate3");
7417 QTest::addColumn<bool>("setVisible");
7418 QTest::addColumn<bool>("shouldInvalidate4");
7420 QTest::newRow("setMinimumSize")
7421 << QSize(100, 100) << true
7423 << int(QSizePolicy::Preferred) << false
7425 QTest::newRow("setMaximumSize")
7427 << QSize(100, 100) << true
7428 << int(QSizePolicy::Preferred) << false
7430 QTest::newRow("setMinimumSize, then maximumSize to a different size")
7431 << QSize(100, 100) << true
7432 << QSize(300, 300) << true
7433 << int(QSizePolicy::Preferred) << false
7435 QTest::newRow("setMinimumSize, then maximumSize to the same size")
7436 << QSize(100, 100) << true
7437 << QSize(100, 100) << true
7438 << int(QSizePolicy::Preferred) << false
7440 QTest::newRow("setMinimumSize, then maximumSize to the same size and then hide it")
7441 << QSize(100, 100) << true
7442 << QSize(100, 100) << true
7443 << int(QSizePolicy::Preferred) << false
7445 QTest::newRow("Change sizePolicy")
7448 << int(QSizePolicy::Minimum) << true
7453 void tst_QWidget::updateGeometry()
7455 QFETCH(QSize, minSize);
7456 QFETCH(bool, shouldInvalidate);
7457 QFETCH(QSize, maxSize);
7458 QFETCH(bool, shouldInvalidate2);
7459 QFETCH(int, verticalSizePolicy);
7460 QFETCH(bool, shouldInvalidate3);
7461 QFETCH(bool, setVisible);
7462 QFETCH(bool, shouldInvalidate4);
7464 parent.resize(200, 200);
7465 TestLayout *lout = new TestLayout();
7466 parent.setLayout(lout);
7467 QWidget *child = new QWidget(&parent);
7468 lout->addWidget(child);
7470 QApplication::processEvents();
7472 lout->invalidated = false;
7473 if (minSize.isValid())
7474 child->setMinimumSize(minSize);
7475 QCOMPARE(lout->invalidated, shouldInvalidate);
7477 lout->invalidated = false;
7478 if (maxSize.isValid())
7479 child->setMaximumSize(maxSize);
7480 QCOMPARE(lout->invalidated, shouldInvalidate2);
7482 lout->invalidated = false;
7483 child->setSizePolicy(QSizePolicy(QSizePolicy::Preferred, (QSizePolicy::Policy)verticalSizePolicy));
7484 if (shouldInvalidate3)
7485 QCOMPARE(lout->invalidated, true);
7487 lout->invalidated = false;
7489 child->setVisible(false);
7490 QCOMPARE(lout->invalidated, shouldInvalidate4);
7493 void tst_QWidget::sendUpdateRequestImmediately()
7495 UpdateWidget updateWidget;
7496 updateWidget.show();
7498 QTest::qWaitForWindowShown(updateWidget.windowHandle());
7500 qApp->processEvents();
7501 updateWidget.reset();
7503 QCOMPARE(updateWidget.numUpdateRequestEvents, 0);
7504 updateWidget.repaint();
7505 QCOMPARE(updateWidget.numUpdateRequestEvents, 1);
7508 void tst_QWidget::doubleRepaint()
7510 #if defined(Q_OS_MAC)
7511 if (!macHasAccessToWindowsServer())
7512 QSKIP("Not having window server access causes the wrong number of repaints to be issues");
7514 UpdateWidget widget;
7515 widget.setFocusPolicy(Qt::StrongFocus);
7516 // Filter out activation change and focus events to avoid update() calls in QWidget.
7517 widget.updateOnActivationChangeAndFocusIn = false;
7520 int expectedRepaints = 1;
7522 QTest::qWaitForWindowShown(&widget);
7524 if (m_platform == QStringLiteral("windows"))
7525 QEXPECT_FAIL("", "QTBUG-26424", Continue);
7526 QTRY_COMPARE(widget.numPaintEvents, expectedRepaints);
7527 widget.numPaintEvents = 0;
7529 // Minmize: Should not trigger a repaint.
7530 widget.showMinimized();
7532 QCOMPARE(widget.numPaintEvents, 0);
7533 widget.numPaintEvents = 0;
7535 // Restore: Should not trigger a repaint.
7536 widget.showNormal();
7537 QTest::qWaitForWindowShown(&widget);
7539 QCOMPARE(widget.numPaintEvents, 0);
7542 void tst_QWidget::resizeInPaintEvent()
7545 UpdateWidget widget(&window);
7547 QTest::qWaitForWindowShown(&window);
7548 QTRY_VERIFY(widget.numPaintEvents > 0);
7551 QCOMPARE(widget.numPaintEvents, 0);
7553 widget.resizeInPaintEvent = true;
7554 // This will call resize in the paintEvent, which in turn will call
7555 // invalidateBuffer() and a new update request should be posted.
7557 QCOMPARE(widget.numPaintEvents, 1);
7558 widget.numPaintEvents = 0;
7561 // Make sure the resize triggers another update.
7562 QTRY_COMPARE(widget.numPaintEvents, 1);
7565 void tst_QWidget::opaqueChildren()
7568 widget.resize(200, 200);
7570 QWidget child(&widget);
7571 child.setGeometry(-700, -700, 200, 200);
7573 QWidget grandChild(&child);
7574 grandChild.resize(200, 200);
7576 QWidget greatGrandChild(&grandChild);
7577 greatGrandChild.setGeometry(50, 50, 200, 200);
7578 greatGrandChild.setPalette(Qt::red);
7579 greatGrandChild.setAutoFillBackground(true); // Opaque child widget.
7582 QTest::qWaitForWindowShown(widget.windowHandle());
7585 // Child, grandChild and greatGrandChild are outside the ancestor clip.
7586 QRegion expectedOpaqueRegion(50, 50, 150, 150);
7587 QCOMPARE(qt_widget_private(&grandChild)->getOpaqueChildren(), expectedOpaqueRegion);
7589 // Now they are all inside the ancestor clip.
7590 child.setGeometry(50, 50, 150, 150);
7591 QCOMPARE(qt_widget_private(&grandChild)->getOpaqueChildren(), expectedOpaqueRegion);
7593 // Set mask on greatGrandChild.
7594 const QRegion mask(10, 10, 50, 50);
7595 greatGrandChild.setMask(mask);
7596 expectedOpaqueRegion &= mask.translated(50, 50);
7597 QCOMPARE(qt_widget_private(&grandChild)->getOpaqueChildren(), expectedOpaqueRegion);
7599 // Make greatGrandChild "transparent".
7600 greatGrandChild.setAutoFillBackground(false);
7601 QCOMPARE(qt_widget_private(&grandChild)->getOpaqueChildren(), QRegion());
7605 class MaskSetWidget : public QWidget
7609 MaskSetWidget(QWidget* p =0)
7612 void paintEvent(QPaintEvent* event) {
7615 paintedRegion += event->region();
7616 foreach(QRect r, event->region().rects())
7617 p.fillRect(r, Qt::red);
7620 void resizeEvent(QResizeEvent*) {
7621 setMask(QRegion(QRect(0, 0, width(), 10).normalized()));
7624 QRegion paintedRegion;
7628 setGeometry(QRect(0, 50, 50, 50));
7632 setGeometry(QRect(0, 50, 150, 50));
7637 void tst_QWidget::setMaskInResizeEvent()
7642 w.setWindowFlags(Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint);
7645 MaskSetWidget testWidget(&w);
7646 testWidget.setGeometry(0, 0, 100, 100);
7647 testWidget.setMask(QRegion(QRect(0,0,100,10)));
7650 QTest::qWaitForWindowShown(&w);
7652 QTRY_VERIFY(w.numPaintEvents > 0);
7655 testWidget.paintedRegion = QRegion();
7656 QTimer::singleShot(0, &testWidget, SLOT(resizeDown()));
7659 QRegion expectedParentUpdate(0, 0, 100, 10); // Old testWidget area.
7660 expectedParentUpdate += testWidget.geometry(); // New testWidget area.
7661 QCOMPARE(w.paintedRegion, expectedParentUpdate);
7662 QCOMPARE(testWidget.paintedRegion, testWidget.mask());
7664 testWidget.paintedRegion = QRegion();
7665 // Now resize the widget again, but in the oposite direction
7666 QTimer::singleShot(0, &testWidget, SLOT(resizeUp()));
7669 QTRY_COMPARE(testWidget.paintedRegion, testWidget.mask());
7672 class MoveInResizeWidget : public QWidget
7676 MoveInResizeWidget(QWidget* p = 0)
7679 setWindowFlags(Qt::FramelessWindowHint);
7682 void resizeEvent(QResizeEvent*) {
7684 move(QPoint(100,100));
7686 static bool firstTime = true;
7688 QTimer::singleShot(250, this, SLOT(resizeMe()));
7699 void tst_QWidget::moveInResizeEvent()
7701 MoveInResizeWidget testWidget;
7702 testWidget.setGeometry(50, 50, 200, 200);
7704 QTest::qWaitForWindowShown(&testWidget);
7707 QRect expectedGeometry(100,100, 100, 100);
7708 QTRY_COMPARE(testWidget.geometry(), expectedGeometry);
7711 void tst_QWidget::immediateRepaintAfterShow()
7713 if (m_platform == QStringLiteral("xcb"))
7714 QSKIP("QTBUG-26424");
7715 if (m_platform != QStringLiteral("xcb") && m_platform != QStringLiteral("windows"))
7716 QSKIP("We don't support immediate repaint right after show on other platforms.");
7718 UpdateWidget widget;
7720 qApp->processEvents();
7721 // On X11 in particular, we are now waiting for a MapNotify event before
7722 // syncing the backing store. However, if someone request a repaint()
7723 // we must repaint immediately regardless of the current state.
7724 widget.numPaintEvents = 0;
7726 QCOMPARE(widget.numPaintEvents, 1);
7729 void tst_QWidget::immediateRepaintAfterInvalidateBuffer()
7731 if (m_platform != QStringLiteral("xcb") && m_platform != QStringLiteral("windows"))
7732 QSKIP("We don't support immediate repaint right after show on other platforms.");
7734 QWidget *widget = new UpdateWidget;
7736 QTest::qWaitForWindowShown(widget->windowHandle());
7739 static_cast<UpdateWidget *>(widget)->numPaintEvents = 0;
7741 // Marks the area covered by the widget as dirty in the backing store and
7742 // posts an UpdateRequest event.
7743 qt_widget_private(widget)->invalidateBuffer(widget->rect());
7744 QCOMPARE(static_cast<UpdateWidget *>(widget)->numPaintEvents, 0);
7746 // The entire widget is already dirty, but this time we want to update immediately
7747 // by calling repaint(), and thus we have to repaint the widget and not wait for
7748 // the UpdateRequest to be sent when we get back to the event loop.
7750 QCOMPARE(static_cast<UpdateWidget *>(widget)->numPaintEvents, 1);
7755 void tst_QWidget::effectiveWinId()
7758 QWidget child(&parent);
7761 QVERIFY(!parent.effectiveWinId());
7762 QVERIFY(!child.effectiveWinId());
7766 QVERIFY(parent.effectiveWinId());
7767 QVERIFY(child.effectiveWinId());
7770 void tst_QWidget::effectiveWinId2()
7774 class MyWidget : public QWidget {
7775 bool event(QEvent *e)
7777 if (e->type() == QEvent::WinIdChange) {
7782 return QWidget::event(e);
7787 child.setParent(&parent);
7791 child.setParent(&parent);
7794 class CustomWidget : public QWidget
7797 mutable int metricCallCount;
7799 CustomWidget(QWidget *parent = 0) : QWidget(parent), metricCallCount(0) {}
7801 virtual int metric(PaintDeviceMetric metric) const {
7803 return QWidget::metric(metric);
7807 void tst_QWidget::customDpi()
7809 QWidget *topLevel = new QWidget;
7810 CustomWidget *custom = new CustomWidget(topLevel);
7811 QWidget *child = new QWidget(custom);
7813 custom->metricCallCount = 0;
7814 topLevel->logicalDpiX();
7815 QCOMPARE(custom->metricCallCount, 0);
7816 custom->logicalDpiX();
7817 QCOMPARE(custom->metricCallCount, 1);
7818 child->logicalDpiX();
7819 QCOMPARE(custom->metricCallCount, 2);
7824 void tst_QWidget::customDpiProperty()
7826 QWidget *topLevel = new QWidget;
7827 QWidget *middle = new CustomWidget(topLevel);
7828 QWidget *child = new QWidget(middle);
7830 const int initialDpiX = topLevel->logicalDpiX();
7831 const int initialDpiY = topLevel->logicalDpiY();
7833 middle->setProperty("_q_customDpiX", 300);
7834 middle->setProperty("_q_customDpiY", 400);
7836 QCOMPARE(topLevel->logicalDpiX(), initialDpiX);
7837 QCOMPARE(topLevel->logicalDpiY(), initialDpiY);
7839 QCOMPARE(middle->logicalDpiX(), 300);
7840 QCOMPARE(middle->logicalDpiY(), 400);
7842 QCOMPARE(child->logicalDpiX(), 300);
7843 QCOMPARE(child->logicalDpiY(), 400);
7845 middle->setProperty("_q_customDpiX", QVariant());
7846 middle->setProperty("_q_customDpiY", QVariant());
7848 QCOMPARE(topLevel->logicalDpiX(), initialDpiX);
7849 QCOMPARE(topLevel->logicalDpiY(), initialDpiY);
7851 QCOMPARE(middle->logicalDpiX(), initialDpiX);
7852 QCOMPARE(middle->logicalDpiY(), initialDpiY);
7854 QCOMPARE(child->logicalDpiX(), initialDpiX);
7855 QCOMPARE(child->logicalDpiY(), initialDpiY);
7860 void tst_QWidget::quitOnCloseAttribute()
7863 QCOMPARE(w.testAttribute(Qt::WA_QuitOnClose), true);
7864 w.setAttribute(Qt::WA_QuitOnClose, false);
7865 QCOMPARE(w.testAttribute(Qt::WA_QuitOnClose), false);
7867 w.setAttribute(Qt::WA_QuitOnClose);
7868 w.setWindowFlags(Qt::Tool);
7869 QCOMPARE(w.testAttribute(Qt::WA_QuitOnClose), false);
7871 w.setAttribute(Qt::WA_QuitOnClose);
7872 w.setWindowFlags(Qt::Popup);
7873 QCOMPARE(w.testAttribute(Qt::WA_QuitOnClose), false);
7875 w.setAttribute(Qt::WA_QuitOnClose);
7876 w.setWindowFlags(Qt::ToolTip);
7877 QCOMPARE(w.testAttribute(Qt::WA_QuitOnClose), false);
7879 w.setAttribute(Qt::WA_QuitOnClose);
7880 w.setWindowFlags(Qt::SplashScreen);
7881 QCOMPARE(w.testAttribute(Qt::WA_QuitOnClose), false);
7883 w.setAttribute(Qt::WA_QuitOnClose);
7884 w.setWindowFlags(Qt::SubWindow);
7885 QCOMPARE(w.testAttribute(Qt::WA_QuitOnClose), false);
7887 w.setAttribute(Qt::WA_QuitOnClose);
7888 w.setWindowFlags(Qt::Dialog);
7889 QCOMPARE(w.testAttribute(Qt::WA_QuitOnClose), true);
7891 QCOMPARE(w.testAttribute(Qt::WA_QuitOnClose), true);
7892 w.setWindowFlags(Qt::Tool);
7893 QCOMPARE(w.testAttribute(Qt::WA_QuitOnClose), false);
7896 void tst_QWidget::moveRect()
7899 widget.setUpdatesEnabled(false);
7900 QWidget child(&widget);
7901 child.setUpdatesEnabled(false);
7902 child.setAttribute(Qt::WA_OpaquePaintEvent);
7905 child.move(10, 10); // Don't crash.
7909 class GDIWidget : public QDialog
7913 GDIWidget() { setAttribute(Qt::WA_PaintOnScreen); }
7914 QPaintEngine *paintEngine() const { return 0; }
7917 void paintEvent(QPaintEvent *) {
7918 QPlatformNativeInterface *ni = QGuiApplication::platformNativeInterface();
7919 const HDC hdc = (HDC)ni->nativeResourceForWindow(QByteArrayLiteral("getDC"), windowHandle());
7921 qWarning("%s: Unable to obtain native DC.", Q_FUNC_INFO);
7922 QTimer::singleShot(0, this, SLOT(reject()));
7925 SelectObject(hdc, CreateSolidBrush(RGB(255, 0, 0)));
7926 Rectangle(hdc, 0, 0, 10, 10);
7928 ni->nativeResourceForWindow(QByteArrayLiteral("releaseDC"), windowHandle());
7930 QTimer::singleShot(0, this, SLOT(slotTimer()));
7933 QSize sizeHint() const {
7934 return QSize(400, 300);
7939 QScreen *screen = windowHandle()->screen();
7940 const QImage im = screen->grabWindow(internalWinId(), 0, 0, -1, -1).toImage();
7941 color = im.pixel(1, 1);
7949 void tst_QWidget::gdiPainting()
7954 QCOMPARE(w.color, QColor(255, 0, 0));
7958 void tst_QWidget::paintOnScreenPossible()
7961 w1.setAttribute(Qt::WA_PaintOnScreen);
7962 QVERIFY(!w1.testAttribute(Qt::WA_PaintOnScreen));
7965 w2.setAttribute(Qt::WA_PaintOnScreen);
7966 QVERIFY(w2.testAttribute(Qt::WA_PaintOnScreen));
7970 void tst_QWidget::reparentStaticWidget()
7974 QWidget *child = new QWidget(&window1);
7975 child->setPalette(Qt::red);
7976 child->setAutoFillBackground(true);
7977 child->setAttribute(Qt::WA_StaticContents);
7978 child->resize(100, 100);
7980 QWidget *grandChild = new QWidget(child);
7981 grandChild->setPalette(Qt::blue);
7982 grandChild->setAutoFillBackground(true);
7983 grandChild->resize(50, 50);
7984 grandChild->setAttribute(Qt::WA_StaticContents);
7986 QTest::qWaitForWindowShown(&window1);
7990 QTest::qWaitForWindowShown(&window2);
7993 // Reparent into another top-level.
7994 child->setParent(&window2);
7997 // Please don't crash.
7998 window1.resize(window1.size() + QSize(2, 2));
8001 // Make sure we move all static children even though
8002 // the reparented widget itself is non-static.
8003 child->setAttribute(Qt::WA_StaticContents, false);
8004 child->setParent(&window1);
8007 // Please don't crash.
8008 window2.resize(window2.size() + QSize(2, 2));
8011 child->setParent(0);
8015 // Please don't crash.
8016 child->resize(child->size() + QSize(2, 2));
8017 window2.resize(window2.size() + QSize(2, 2));
8020 QWidget *siblingOfGrandChild = new QWidget(child);
8021 siblingOfGrandChild->show();
8024 // Nothing should happen when reparenting within the same top-level.
8025 grandChild->setParent(siblingOfGrandChild);
8029 QWidget paintOnScreen;
8030 paintOnScreen.setAttribute(Qt::WA_PaintOnScreen);
8031 paintOnScreen.show();
8032 QTest::qWaitForWindowShown(&paintOnScreen);
8035 child->setParent(&paintOnScreen);
8039 // Please don't crash.
8040 paintOnScreen.resize(paintOnScreen.size() + QSize(2, 2));
8045 void tst_QWidget::QTBUG6883_reparentStaticWidget2()
8048 QDockWidget *one = new QDockWidget("one", &mw);
8049 mw.addDockWidget(Qt::LeftDockWidgetArea, one , Qt::Vertical);
8051 QWidget *child = new QWidget();
8052 child->setPalette(Qt::red);
8053 child->setAutoFillBackground(true);
8054 child->setAttribute(Qt::WA_StaticContents);
8055 child->resize(100, 100);
8056 one->setWidget(child);
8058 QToolBar *mainTools = mw.addToolBar("Main Tools");
8059 mainTools->addWidget(new QLineEdit);
8062 QTest::qWaitForWindowShown(&mw);
8064 one->setFloating(true);
8069 class ColorRedWidget : public QWidget
8072 ColorRedWidget(QWidget *parent = 0)
8073 : QWidget(parent, Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint | Qt::ToolTip)
8077 void paintEvent(QPaintEvent *) {
8079 p.fillRect(rect(),Qt::red);
8083 void tst_QWidget::translucentWidget()
8087 ColorRedWidget label;
8088 label.setFixedSize(16,16);
8089 label.setAttribute(Qt::WA_TranslucentBackground);
8090 const QPoint labelPos = qApp->desktop()->availableGeometry().topLeft();
8091 label.move(labelPos);
8093 QTest::qWaitForWindowShown(label.windowHandle());
8096 QPixmap widgetSnapshot;
8099 QWidget *desktopWidget = QApplication::desktop()->screen(0);
8100 if (QSysInfo::windowsVersion() >= QSysInfo::WV_VISTA)
8101 widgetSnapshot = qApp->primaryScreen()->grabWindow(desktopWidget->winId(), labelPos.x(), labelPos.y(), label.width(), label.height());
8104 widgetSnapshot = label.grab(QRect(QPoint(0, 0), label.size()));
8105 QImage actual = widgetSnapshot.toImage().convertToFormat(QImage::Format_RGB32);
8106 QImage expected = pm.toImage().convertToFormat(QImage::Format_RGB32);
8107 QCOMPARE(actual.size(),expected.size());
8108 QCOMPARE(actual,expected);
8111 class MaskResizeTestWidget : public QWidget
8115 MaskResizeTestWidget(QWidget* p =0)
8117 setMask(QRegion(QRect(0, 0, 100, 100).normalized()));
8120 void paintEvent(QPaintEvent* event) {
8123 paintedRegion += event->region();
8124 foreach(QRect r, event->region().rects())
8125 p.fillRect(r, Qt::red);
8128 QRegion paintedRegion;
8131 void enlargeMask() {
8132 QRegion newMask(QRect(0, 0, 150, 150).normalized());
8137 QRegion newMask(QRect(0, 0, 50, 50).normalized());
8143 void tst_QWidget::setClearAndResizeMask()
8145 UpdateWidget topLevel;
8146 topLevel.resize(150, 150);
8148 QTest::qWaitForWindowShown(&topLevel);
8149 QTRY_VERIFY(topLevel.numPaintEvents > 0);
8152 // Mask top-level widget
8153 const QRegion topLevelMask(0, 0, 100, 100, QRegion::Ellipse);
8154 topLevel.setMask(topLevelMask);
8155 QCOMPARE(topLevel.mask(), topLevelMask);
8156 // Ensure that the top-level doesn't get any update.
8157 // We don't control what's happening on platforms other than X11, Windows
8158 if (m_platform == QStringLiteral("xcb") || m_platform == QStringLiteral("windows"))
8159 QCOMPARE(topLevel.numPaintEvents, 0);
8163 // Clear top-level mask
8164 topLevel.clearMask();
8165 QCOMPARE(topLevel.mask(), QRegion());
8167 QRegion outsideOldMask(topLevel.rect());
8168 outsideOldMask -= topLevelMask;
8169 // Ensure that the top-level gets an update for the area outside the old mask.
8170 // We don't control what's happening on platforms other than X11, Windows
8171 if (m_platform == QStringLiteral("xcb") || m_platform == QStringLiteral("windows")) {
8172 QTRY_VERIFY(topLevel.numPaintEvents > 0);
8173 QTRY_COMPARE(topLevel.paintedRegion, outsideOldMask);
8176 UpdateWidget child(&topLevel);
8177 child.setAutoFillBackground(true); // NB! Opaque child.
8178 child.setPalette(Qt::red);
8179 child.resize(100, 100);
8186 // Mask child widget with a mask that is smaller than the rect
8187 const QRegion childMask(0, 0, 50, 50);
8188 child.setMask(childMask);
8189 QTRY_COMPARE(child.mask(), childMask);
8191 // and ensure that the child widget doesn't get any update.
8193 // Mac always issues a full update when calling setMask, and we cannot force it to not do so.
8194 if (child.internalWinId())
8195 QCOMPARE(child.numPaintEvents, 1);
8198 QCOMPARE(child.numPaintEvents, 0);
8199 // and the parent widget gets an update for the newly exposed area.
8200 QTRY_COMPARE(topLevel.numPaintEvents, 1);
8201 QRegion expectedParentExpose(child.rect());
8202 expectedParentExpose -= childMask;
8203 QCOMPARE(topLevel.paintedRegion, expectedParentExpose);
8208 // Clear child widget mask
8210 QTRY_COMPARE(child.mask(), QRegion());
8212 // and ensure that that the child widget gets an update for the area outside the old mask.
8213 QTRY_COMPARE(child.numPaintEvents, 1);
8214 outsideOldMask = child.rect();
8216 // Mac always issues a full update when calling setMask, and we cannot force it to not do so.
8217 if (!child.internalWinId())
8219 outsideOldMask -= childMask;
8220 QCOMPARE(child.paintedRegion, outsideOldMask);
8221 // and the parent widget doesn't get any update.
8222 QCOMPARE(topLevel.numPaintEvents, 0);
8227 // Mask child widget with a mask that is bigger than the rect
8228 child.setMask(QRegion(0, 0, 1000, 1000));
8231 // Mac always issues a full update when calling setMask, and we cannot force it to not do so.
8232 if (child.internalWinId())
8233 QTRY_COMPARE(child.numPaintEvents, 1);
8236 // and ensure that we don't get any updates at all.
8237 QTRY_COMPARE(child.numPaintEvents, 0);
8238 QCOMPARE(topLevel.numPaintEvents, 0);
8240 // ...and the same applies when clearing the mask.
8244 // Mac always issues a full update when calling setMask, and we cannot force it to not do so.
8245 if (child.internalWinId())
8246 QTRY_VERIFY(child.numPaintEvents > 0);
8249 QCOMPARE(child.numPaintEvents, 0);
8250 QCOMPARE(topLevel.numPaintEvents, 0);
8252 QWidget resizeParent;
8253 MaskResizeTestWidget resizeChild(&resizeParent);
8255 resizeParent.resize(300,300);
8256 resizeParent.raise();
8257 resizeParent.setWindowFlags(Qt::WindowStaysOnTopHint);
8258 resizeChild.setGeometry(50,50,200,200);
8259 QPalette pal = resizeParent.palette();
8260 pal.setColor(QPalette::Window, QColor(Qt::white));
8261 resizeParent.setPalette(pal);
8263 resizeParent.show();
8264 QTest::qWaitForWindowShown(&resizeParent);
8265 // Disable the size grip on the Mac; otherwise it'll be included when grabbing the window.
8266 resizeParent.setFixedSize(resizeParent.size());
8269 resizeChild.paintedRegion = QRegion();
8271 QTimer::singleShot(100, &resizeChild, SLOT(shrinkMask()));
8274 // Mac always issues a full update when calling setMask, and we cannot force it to not do so.
8275 if (child.internalWinId())
8276 QTRY_COMPARE(resizeChild.paintedRegion, resizeChild.mask());
8279 QTRY_COMPARE(resizeChild.paintedRegion, QRegion());
8281 resizeChild.paintedRegion = QRegion();
8282 const QRegion oldMask = resizeChild.mask();
8283 QTimer::singleShot(0, &resizeChild, SLOT(enlargeMask()));
8286 // Mac always issues a full update when calling setMask, and we cannot force it to not do so.
8287 if (child.internalWinId())
8288 QTRY_COMPARE(resizeChild.paintedRegion, resizeChild.mask());
8291 QTRY_COMPARE(resizeChild.paintedRegion, resizeChild.mask() - oldMask);
8294 void tst_QWidget::maskedUpdate()
8296 UpdateWidget topLevel;
8297 topLevel.resize(200, 200);
8298 const QRegion topLevelMask(50, 50, 70, 70);
8299 topLevel.setMask(topLevelMask);
8301 UpdateWidget child(&topLevel);
8302 child.setGeometry(20, 20, 180, 180);
8303 const QRegion childMask(60, 60, 30, 30);
8304 child.setMask(childMask);
8306 UpdateWidget grandChild(&child);
8307 grandChild.setGeometry(50, 50, 100, 100);
8308 const QRegion grandChildMask(20, 20, 10, 10);
8309 grandChild.setMask(grandChildMask);
8312 QTest::qWaitForWindowShown(&topLevel);
8313 QTRY_VERIFY(topLevel.numPaintEvents > 0);
8316 #define RESET_WIDGETS \
8321 #define CLEAR_MASK(widget) \
8322 widget.clearMask(); \
8323 QTest::qWait(100); \
8326 // All widgets are transparent at this point, so any call to update() will result
8327 // in composition, i.e. the update propagates to ancestors and children.
8334 QTRY_COMPARE(topLevel.paintedRegion, topLevelMask);
8335 QTRY_COMPARE(child.paintedRegion, childMask);
8336 QTRY_COMPARE(grandChild.paintedRegion, grandChildMask);
8343 QTRY_COMPARE(topLevel.paintedRegion, childMask.translated(child.pos()));
8344 QTRY_COMPARE(child.paintedRegion, childMask);
8345 QTRY_COMPARE(grandChild.paintedRegion, grandChildMask);
8347 // GrandChild update.
8349 grandChild.update();
8352 QTRY_COMPARE(topLevel.paintedRegion, grandChildMask.translated(grandChild.mapTo(&topLevel, QPoint())));
8353 QTRY_COMPARE(child.paintedRegion, grandChildMask.translated(grandChild.pos()));
8354 QTRY_COMPARE(grandChild.paintedRegion, grandChildMask);
8356 topLevel.setAttribute(Qt::WA_OpaquePaintEvent);
8357 child.setAttribute(Qt::WA_OpaquePaintEvent);
8358 grandChild.setAttribute(Qt::WA_OpaquePaintEvent);
8360 // All widgets are now opaque, which means no composition, i.e.
8361 // the update does not propate to ancestors and children.
8368 QRegion expectedTopLevelUpdate = topLevelMask;
8369 expectedTopLevelUpdate -= childMask.translated(child.pos()); // Subtract opaque children.
8370 QTRY_COMPARE(topLevel.paintedRegion, expectedTopLevelUpdate);
8371 QTRY_COMPARE(child.paintedRegion, QRegion());
8372 QTRY_COMPARE(grandChild.paintedRegion, QRegion());
8379 QTRY_COMPARE(topLevel.paintedRegion, QRegion());
8380 QRegion expectedChildUpdate = childMask;
8381 expectedChildUpdate -= grandChildMask.translated(grandChild.pos()); // Subtract oapque children.
8382 QTRY_COMPARE(child.paintedRegion, expectedChildUpdate);
8383 QTRY_COMPARE(grandChild.paintedRegion, QRegion());
8385 // GrandChild update.
8387 grandChild.update();
8390 QTRY_COMPARE(topLevel.paintedRegion, QRegion());
8391 QTRY_COMPARE(child.paintedRegion, QRegion());
8392 QTRY_COMPARE(grandChild.paintedRegion, grandChildMask);
8394 // GrandChild update.
8395 CLEAR_MASK(grandChild);
8396 grandChild.update();
8399 QTRY_COMPARE(topLevel.paintedRegion, QRegion());
8400 QTRY_COMPARE(child.paintedRegion, QRegion());
8401 QRegion expectedGrandChildUpdate = grandChild.rect();
8402 // Clip with parent's mask.
8403 expectedGrandChildUpdate &= childMask.translated(-grandChild.pos());
8404 QCOMPARE(grandChild.paintedRegion, expectedGrandChildUpdate);
8406 // GrandChild update.
8408 grandChild.update();
8411 QTRY_COMPARE(topLevel.paintedRegion, QRegion());
8412 QTRY_COMPARE(child.paintedRegion, QRegion());
8413 expectedGrandChildUpdate = grandChild.rect();
8414 // Clip with parent's mask.
8415 expectedGrandChildUpdate &= topLevelMask.translated(-grandChild.mapTo(&topLevel, QPoint()));
8416 QTRY_COMPARE(grandChild.paintedRegion, expectedGrandChildUpdate);
8423 QTRY_COMPARE(topLevel.paintedRegion, QRegion());
8424 expectedChildUpdate = child.rect();
8425 // Clip with parent's mask.
8426 expectedChildUpdate &= topLevelMask.translated(-child.pos());
8427 expectedChildUpdate -= grandChild.geometry(); // Subtract opaque children.
8428 QTRY_COMPARE(child.paintedRegion, expectedChildUpdate);
8429 QTRY_COMPARE(grandChild.paintedRegion, QRegion());
8431 // GrandChild update.
8432 CLEAR_MASK(topLevel);
8433 grandChild.update();
8436 QTRY_COMPARE(topLevel.paintedRegion, QRegion());
8437 QTRY_COMPARE(child.paintedRegion, QRegion());
8438 QTRY_COMPARE(grandChild.paintedRegion, QRegion(grandChild.rect())); // Full update.
8441 // Windows Mobile has no proper cursor support, so skip this test on that platform.
8442 #if !defined(Q_OS_WINCE_WM)
8443 void tst_QWidget::syntheticEnterLeave()
8445 class MyWidget : public QWidget
8448 MyWidget(QWidget *parent = 0) : QWidget(parent), numEnterEvents(0), numLeaveEvents(0) {}
8449 void enterEvent(QEvent *) { ++numEnterEvents; }
8450 void leaveEvent(QEvent *) { ++numLeaveEvents; }
8455 QCursor::setPos(QPoint(0,0));
8458 window.setWindowFlags(Qt::WindowStaysOnTopHint);
8459 window.resize(200, 200);
8461 MyWidget *child1 = new MyWidget(&window);
8462 child1->setPalette(Qt::blue);
8463 child1->setAutoFillBackground(true);
8464 child1->resize(200, 200);
8465 child1->setCursor(Qt::OpenHandCursor);
8467 MyWidget *child2 = new MyWidget(&window);
8468 child2->resize(200, 200);
8470 MyWidget *grandChild = new MyWidget(child2);
8471 grandChild->setPalette(Qt::red);
8472 grandChild->setAutoFillBackground(true);
8473 grandChild->resize(200, 200);
8474 grandChild->setCursor(Qt::WaitCursor);
8479 QTest::qWaitForWindowShown(window.windowHandle());
8482 #define RESET_EVENT_COUNTS \
8483 window.numEnterEvents = 0; \
8484 window.numLeaveEvents = 0; \
8485 child1->numEnterEvents = 0; \
8486 child1->numLeaveEvents = 0; \
8487 child2->numEnterEvents = 0; \
8488 child2->numLeaveEvents = 0; \
8489 grandChild->numEnterEvents = 0; \
8490 grandChild->numLeaveEvents = 0;
8492 // Position the cursor in the middle of the window.
8493 const QPoint globalPos = window.mapToGlobal(QPoint(100, 100));
8494 QCursor::setPos(globalPos); // Enter child2 and grandChild.
8497 QCOMPARE(window.numLeaveEvents, 0);
8498 QCOMPARE(child2->numLeaveEvents, 0);
8499 QCOMPARE(grandChild->numLeaveEvents, 0);
8500 QCOMPARE(child1->numLeaveEvents, 0);
8502 // This event arrives asynchronously
8503 QTRY_COMPARE(window.numEnterEvents, 1);
8504 QCOMPARE(child2->numEnterEvents, 1);
8505 QCOMPARE(grandChild->numEnterEvents, 1);
8506 QCOMPARE(child1->numEnterEvents, 0);
8509 child2->hide(); // Leave child2 and grandChild, enter child1.
8511 QCOMPARE(window.numLeaveEvents, 0);
8512 QCOMPARE(child2->numLeaveEvents, 1);
8513 QCOMPARE(grandChild->numLeaveEvents, 1);
8514 QCOMPARE(child1->numLeaveEvents, 0);
8516 QCOMPARE(window.numEnterEvents, 0);
8517 QCOMPARE(child2->numEnterEvents, 0);
8518 QCOMPARE(grandChild->numEnterEvents, 0);
8519 QCOMPARE(child1->numEnterEvents, 1);
8522 child2->show(); // Leave child1, enter child2 and grandChild.
8524 QCOMPARE(window.numLeaveEvents, 0);
8525 QCOMPARE(child2->numLeaveEvents, 0);
8526 QCOMPARE(grandChild->numLeaveEvents, 0);
8527 QCOMPARE(child1->numLeaveEvents, 1);
8529 QCOMPARE(window.numEnterEvents, 0);
8530 QCOMPARE(child2->numEnterEvents, 1);
8531 QCOMPARE(grandChild->numEnterEvents, 1);
8532 QCOMPARE(child1->numEnterEvents, 0);
8535 delete child2; // Enter child1 (and do not send leave events to child2 and grandChild).
8537 QCOMPARE(window.numLeaveEvents, 0);
8538 QCOMPARE(child1->numLeaveEvents, 0);
8540 QCOMPARE(window.numEnterEvents, 0);
8541 QCOMPARE(child1->numEnterEvents, 1);
8545 // Windows Mobile has no proper cursor support, so skip this test on that platform.
8546 #if !defined(Q_OS_WINCE_WM)
8547 void tst_QWidget::taskQTBUG_4055_sendSyntheticEnterLeave()
8549 if (m_platform == QStringLiteral("windows") || m_platform == QStringLiteral("xcb"))
8550 QSKIP("QTBUG-26424");
8551 class SELParent : public QWidget
8554 SELParent(QWidget *parent = 0): QWidget(parent) { }
8556 void mousePressEvent(QMouseEvent *) { child->show(); }
8560 class SELChild : public QWidget
8563 SELChild(QWidget *parent = 0) : QWidget(parent), numEnterEvents(0), numMouseMoveEvents(0) {}
8564 void enterEvent(QEvent *) { ++numEnterEvents; }
8565 void mouseMoveEvent(QMouseEvent *event)
8567 QCOMPARE(event->button(), Qt::NoButton);
8568 QCOMPARE(event->buttons(), Qt::MouseButtons(Qt::NoButton));
8569 ++numMouseMoveEvents;
8571 void reset() { numEnterEvents = numMouseMoveEvents = 0; }
8572 int numEnterEvents, numMouseMoveEvents;
8575 QCursor::setPos(QPoint(0,0));
8578 parent.resize(200, 200);
8579 SELChild child(&parent);
8580 child.resize(200, 200);
8582 QTest::qWaitForWindowShown(parent.windowHandle());
8585 QCursor::setPos(child.mapToGlobal(QPoint(100, 100)));
8586 // Make sure the cursor has entered the child.
8587 QTRY_VERIFY(child.numEnterEvents > 0);
8593 // Make sure the child gets enter event and no mouse move event.
8594 QTRY_COMPARE(child.numEnterEvents, 1);
8595 QCOMPARE(child.numMouseMoveEvents, 0);
8599 child.setMouseTracking(true);
8602 // Make sure the child gets enter event and mouse move event.
8603 // Note that we verify event->button() and event->buttons()
8604 // in SELChild::mouseMoveEvent().
8605 QTRY_COMPARE(child.numEnterEvents, 1);
8606 QCOMPARE(child.numMouseMoveEvents, 1);
8608 // Sending synthetic enter/leave trough the parent's mousePressEvent handler.
8609 parent.child = &child;
8613 QTest::mouseClick(&parent, Qt::LeftButton);
8615 // Make sure the child gets enter event and one mouse move event.
8616 QTRY_COMPARE(child.numEnterEvents, 1);
8617 QCOMPARE(child.numMouseMoveEvents, 1);
8621 child.setMouseTracking(false);
8622 QTest::mouseClick(&parent, Qt::LeftButton);
8624 // Make sure the child gets enter event and no mouse move event.
8625 QTRY_COMPARE(child.numEnterEvents, 1);
8626 QCOMPARE(child.numMouseMoveEvents, 0);
8630 void tst_QWidget::windowFlags()
8633 w.setWindowFlags(w.windowFlags() | Qt::FramelessWindowHint);
8634 QVERIFY(w.windowFlags() & Qt::FramelessWindowHint);
8637 void tst_QWidget::initialPosForDontShowOnScreenWidgets()
8639 { // Check default position.
8640 const QPoint expectedPos(0, 0);
8642 widget.setAttribute(Qt::WA_DontShowOnScreen);
8643 widget.winId(); // Make sure create_sys is called.
8644 QCOMPARE(widget.pos(), expectedPos);
8645 QCOMPARE(widget.geometry().topLeft(), expectedPos);
8648 { // Explicitly move to a position.
8649 const QPoint expectedPos(100, 100);
8651 widget.setAttribute(Qt::WA_DontShowOnScreen);
8652 widget.move(expectedPos);
8653 widget.winId(); // Make sure create_sys is called.
8654 QCOMPARE(widget.pos(), expectedPos);
8655 QCOMPARE(widget.geometry().topLeft(), expectedPos);
8659 class MyEvilObject : public QObject
8663 MyEvilObject(QWidget *widgetToCrash) : QObject(), widget(widgetToCrash)
8665 connect(widget, SIGNAL(destroyed(QObject *)), this, SLOT(beEvil(QObject *)));
8671 void beEvil(QObject *) { widget->update(0, 0, 150, 150); }
8674 void tst_QWidget::updateOnDestroyedSignal()
8678 QWidget *child = new QWidget(&widget);
8679 child->resize(100, 100);
8680 child->setAutoFillBackground(true);
8681 child->setPalette(Qt::red);
8684 QTest::qWaitForWindowShown(widget.windowHandle());
8687 // Please do not crash.
8688 MyEvilObject evil(child);
8692 void tst_QWidget::toplevelLineEditFocus()
8698 QTest::qWaitForWindowShown(&w);
8701 QTRY_COMPARE(QApplication::activeWindow(), (QWidget*)&w);
8702 QTRY_COMPARE(QApplication::focusWidget(), (QWidget*)&w);
8705 void tst_QWidget::focusWidget_task254563()
8707 //having different visibility for widget is important
8710 QWidget container(&top);
8711 QWidget *widget = new QWidget(&container);
8714 widget->setFocus(); //set focus (will set the focus widget up to the toplevel to be 'widget')
8715 container.setFocus();
8716 delete widget; // will call clearFocus but that doesn't help
8717 QVERIFY(top.focusWidget() != widget); //dangling pointer
8720 // This test case relies on developer build (AUTOTEST_EXPORT).
8721 #ifdef QT_BUILD_INTERNAL
8722 void tst_QWidget::destroyBackingStore()
8728 QTest::qWaitForWindowShown(&w);
8729 QApplication::processEvents();
8730 QTRY_VERIFY(w.numPaintEvents > 0);
8733 qt_widget_private(&w)->topData()->backingStoreTracker.create(&w);
8736 QApplication::processEvents();
8738 QCOMPARE(w.numPaintEvents, 1);
8740 // Check one more time, because the second time around does more caching.
8742 QApplication::processEvents();
8743 QCOMPARE(w.numPaintEvents, 2);
8745 #endif // QT_BUILD_INTERNAL
8748 QWidgetBackingStore* backingStore(QWidget &widget)
8750 QWidgetBackingStore *backingStore = 0;
8751 #ifdef QT_BUILD_INTERNAL
8752 if (QTLWExtra *topExtra = qt_widget_private(&widget)->maybeTopData())
8753 backingStore = topExtra->backingStoreTracker.data();
8755 return backingStore;
8758 // Tables of 5000 elements do not make sense on Windows Mobile.
8759 #ifndef Q_OS_WINCE_WM
8760 void tst_QWidget::rectOutsideCoordinatesLimit_task144779()
8762 QApplication::setOverrideCursor(Qt::BlankCursor); //keep the cursor out of screen grabs
8763 QWidget main(0,Qt::FramelessWindowHint); //don't get confused by the size of the window frame
8765 palette.setColor(QPalette::Window, Qt::red);
8766 main.setPalette(palette);
8768 QDesktopWidget desktop;
8769 QRect desktopDimensions = desktop.availableGeometry(&main);
8770 QSize mainSize(400, 400);
8771 mainSize = mainSize.boundedTo(desktopDimensions.size());
8772 main.resize(mainSize);
8774 QWidget *offsetWidget = new QWidget(&main);
8775 offsetWidget->setGeometry(0, -(15000 - mainSize.height()), mainSize.width(), 15000);
8777 // big widget is too big for the coordinates, it must be limited by wrect
8778 // if wrect is not at the right position because of offsetWidget, bigwidget
8779 // is not painted correctly
8780 QWidget *bigWidget = new QWidget(offsetWidget);
8781 bigWidget->setGeometry(0, 0, mainSize.width(), 50000);
8782 palette.setColor(QPalette::Window, Qt::green);
8783 bigWidget->setPalette(palette);
8784 bigWidget->setAutoFillBackground(true);
8787 QTest::qWaitForWindowShown(&main);
8789 QPixmap correct(main.size());
8790 correct.fill(Qt::green);
8791 const QPixmap mainPixmap = main.grab(QRect(QPoint(0, 0), QSize(-1, -1)));
8793 QTRY_COMPARE(mainPixmap.toImage().convertToFormat(QImage::Format_RGB32),
8794 correct.toImage().convertToFormat(QImage::Format_RGB32));
8795 QApplication::restoreOverrideCursor();
8799 void tst_QWidget::inputFocus_task257832()
8801 QLineEdit *widget = new QLineEdit;
8803 widget->winId(); // make sure, widget has been created
8805 QTRY_VERIFY(widget->hasFocus());
8806 QCOMPARE(qApp->inputMethod()->inputItem(), static_cast<QWidget*>(widget));
8807 widget->setReadOnly(true);
8808 QVERIFY(!qApp->inputMethod()->inputItem());
8812 void tst_QWidget::setGraphicsEffect()
8814 // Check that we don't have any effect by default.
8815 QWidget *widget = new QWidget;
8816 QVERIFY(!widget->graphicsEffect());
8819 QPointer<QGraphicsEffect> blurEffect = new QGraphicsBlurEffect;
8820 widget->setGraphicsEffect(blurEffect);
8821 QCOMPARE(widget->graphicsEffect(), static_cast<QGraphicsEffect *>(blurEffect));
8823 // Ensure the existing effect is deleted when setting a new one.
8824 QPointer<QGraphicsEffect> shadowEffect = new QGraphicsDropShadowEffect;
8825 widget->setGraphicsEffect(shadowEffect);
8826 QVERIFY(!blurEffect);
8827 QCOMPARE(widget->graphicsEffect(), static_cast<QGraphicsEffect *>(shadowEffect));
8828 blurEffect = new QGraphicsBlurEffect;
8830 // Ensure the effect is uninstalled when setting it on a new target.
8831 QWidget *anotherWidget = new QWidget;
8832 anotherWidget->setGraphicsEffect(blurEffect);
8833 widget->setGraphicsEffect(blurEffect);
8834 QVERIFY(!anotherWidget->graphicsEffect());
8835 QVERIFY(!shadowEffect);
8837 // Ensure the existing effect is deleted when deleting the widget.
8839 QVERIFY(!blurEffect);
8840 delete anotherWidget;
8842 // Ensure the effect is uninstalled when deleting it
8843 widget = new QWidget;
8844 blurEffect = new QGraphicsBlurEffect;
8845 widget->setGraphicsEffect(blurEffect);
8847 QVERIFY(!widget->graphicsEffect());
8849 // Ensure the existing effect is uninstalled and deleted when setting a null effect
8850 blurEffect = new QGraphicsBlurEffect;
8851 widget->setGraphicsEffect(blurEffect);
8852 widget->setGraphicsEffect(0);
8853 QVERIFY(!widget->graphicsEffect());
8854 QVERIFY(!blurEffect);
8859 void tst_QWidget::activateWindow()
8861 // Test case for task 260685
8863 // Create first mainwindow and set it active
8864 QMainWindow* mainwindow = new QMainWindow();
8865 QLabel* label = new QLabel(mainwindow);
8866 mainwindow->setCentralWidget(label);
8867 mainwindow->setVisible(true);
8868 mainwindow->activateWindow();
8869 QTest::qWaitForWindowShown(mainwindow);
8870 qApp->processEvents();
8872 QTRY_VERIFY(mainwindow->isActiveWindow());
8874 // Create second mainwindow and set it active
8875 QMainWindow* mainwindow2 = new QMainWindow();
8876 QLabel* label2 = new QLabel(mainwindow2);
8877 mainwindow2->setCentralWidget(label2);
8878 mainwindow2->setVisible(true);
8879 mainwindow2->activateWindow();
8880 qApp->processEvents();
8882 QTRY_VERIFY(!mainwindow->isActiveWindow());
8883 QTRY_VERIFY(mainwindow2->isActiveWindow());
8885 // Revert first mainwindow back to visible active
8886 mainwindow->setVisible(true);
8887 mainwindow->activateWindow();
8888 qApp->processEvents();
8890 QTRY_VERIFY(mainwindow->isActiveWindow());
8891 QTRY_VERIFY(!mainwindow2->isActiveWindow());
8894 void tst_QWidget::openModal_taskQTBUG_5804()
8896 class Widget : public QWidget
8899 Widget(QWidget *parent) : QWidget(parent)
8905 QTimer::singleShot(10, &msgbox, SLOT(accept()));
8906 msgbox.exec(); //open a modal dialog
8910 QWidget *win = new QWidget;
8913 QTest::qWaitForWindowShown(win);
8917 void tst_QWidget::focusProxyAndInputMethods()
8919 QWidget *toplevel = new QWidget(0, Qt::X11BypassWindowManagerHint);
8920 toplevel->setAttribute(Qt::WA_InputMethodEnabled, true);
8922 QWidget *child = new QWidget(toplevel);
8923 child->setFocusProxy(toplevel);
8924 child->setAttribute(Qt::WA_InputMethodEnabled, true);
8926 toplevel->setFocusPolicy(Qt::WheelFocus);
8927 child->setFocusPolicy(Qt::WheelFocus);
8929 QVERIFY(!child->hasFocus());
8930 QVERIFY(!toplevel->hasFocus());
8933 QTest::qWaitForWindowShown(toplevel);
8934 QApplication::setActiveWindow(toplevel);
8935 QVERIFY(toplevel->hasFocus());
8936 QVERIFY(child->hasFocus());
8938 // verify that toggling input methods on the child widget
8939 // correctly propagate to the focus proxy's input method
8940 // and that the input method gets the focus proxy passed
8941 // as the focus widget instead of the child widget.
8942 // otherwise input method queries go to the wrong widget
8943 QCOMPARE(qApp->inputPanel()->inputItem(), toplevel);
8945 toplevel->setAttribute(Qt::WA_InputMethodEnabled, false);
8946 QVERIFY(!qApp->inputPanel()->inputItem());
8948 toplevel->setAttribute(Qt::WA_InputMethodEnabled, true);
8949 QCOMPARE(qApp->inputPanel()->inputItem(), toplevel);
8954 #ifdef QT_BUILD_INTERNAL
8955 class scrollWidgetWBS : public QWidget
8958 void deleteBackingStore()
8960 static_cast<QWidgetPrivate*>(d_ptr.data())->topData()->backingStoreTracker.destroy();
8962 void enableBackingStore()
8964 if (!static_cast<QWidgetPrivate*>(d_ptr.data())->maybeBackingStore()) {
8965 static_cast<QWidgetPrivate*>(d_ptr.data())->topData()->backingStoreTracker.create(this);
8966 static_cast<QWidgetPrivate*>(d_ptr.data())->invalidateBuffer(this->rect());
8973 // Test case relies on developer build (AUTOTEST_EXPORT).
8974 #ifdef QT_BUILD_INTERNAL
8975 void tst_QWidget::scrollWithoutBackingStore()
8977 scrollWidgetWBS scrollable;
8978 scrollable.resize(100,100);
8979 QLabel child(QString("@"),&scrollable);
8980 child.resize(50,50);
8982 QTest::qWaitForWindowShown(&scrollable);
8983 scrollable.scroll(50,50);
8984 QCOMPARE(child.pos(),QPoint(50,50));
8985 scrollable.deleteBackingStore();
8986 scrollable.scroll(-25,-25);
8987 QCOMPARE(child.pos(),QPoint(25,25));
8988 scrollable.enableBackingStore();
8989 QCOMPARE(child.pos(),QPoint(25,25));
8993 void tst_QWidget::taskQTBUG_7532_tabOrderWithFocusProxy()
8996 w.setFocusPolicy(Qt::TabFocus);
8997 QWidget *fp = new QWidget(&w);
8998 fp->setFocusPolicy(Qt::TabFocus);
8999 w.setFocusProxy(fp);
9000 QWidget::setTabOrder(&w, fp);
9002 // In debug mode, no assertion failure means it's alright.
9005 void tst_QWidget::movedAndResizedAttributes()
9007 #if defined (Q_OS_MAC)
9008 QEXPECT_FAIL("", "FixMe, QTBUG-8941 and QTBUG-8977", Abort);
9014 QVERIFY(!w.testAttribute(Qt::WA_Moved));
9015 QVERIFY(!w.testAttribute(Qt::WA_Resized));
9017 w.setWindowState(Qt::WindowFullScreen);
9019 QVERIFY(!w.testAttribute(Qt::WA_Moved));
9020 QVERIFY(!w.testAttribute(Qt::WA_Resized));
9022 w.setWindowState(Qt::WindowMaximized);
9024 QVERIFY(!w.testAttribute(Qt::WA_Moved));
9025 QVERIFY(!w.testAttribute(Qt::WA_Resized));
9027 w.setWindowState(Qt::WindowMinimized);
9029 QVERIFY(!w.testAttribute(Qt::WA_Moved));
9030 QVERIFY(!w.testAttribute(Qt::WA_Resized));
9034 QVERIFY(!w.testAttribute(Qt::WA_Moved));
9035 QVERIFY(!w.testAttribute(Qt::WA_Resized));
9039 QVERIFY(!w.testAttribute(Qt::WA_Moved));
9040 QVERIFY(!w.testAttribute(Qt::WA_Resized));
9044 QVERIFY(!w.testAttribute(Qt::WA_Moved));
9045 QVERIFY(!w.testAttribute(Qt::WA_Resized));
9049 QVERIFY(w.testAttribute(Qt::WA_Moved));
9050 QVERIFY(!w.testAttribute(Qt::WA_Resized));
9053 QVERIFY(w.testAttribute(Qt::WA_Moved));
9054 QVERIFY(w.testAttribute(Qt::WA_Resized));
9058 void tst_QWidget::childAt()
9060 QWidget parent(0, Qt::FramelessWindowHint);
9061 parent.resize(200, 200);
9063 QWidget *child = new QWidget(&parent);
9064 child->setPalette(Qt::red);
9065 child->setAutoFillBackground(true);
9066 child->setGeometry(20, 20, 160, 160);
9068 QWidget *grandChild = new QWidget(child);
9069 grandChild->setPalette(Qt::blue);
9070 grandChild->setAutoFillBackground(true);
9071 grandChild->setGeometry(-20, -20, 220, 220);
9073 QVERIFY(!parent.childAt(19, 19));
9074 QVERIFY(!parent.childAt(180, 180));
9075 QCOMPARE(parent.childAt(20, 20), grandChild);
9076 QCOMPARE(parent.childAt(179, 179), grandChild);
9078 grandChild->setAttribute(Qt::WA_TransparentForMouseEvents);
9079 QCOMPARE(parent.childAt(20, 20), child);
9080 QCOMPARE(parent.childAt(179, 179), child);
9081 grandChild->setAttribute(Qt::WA_TransparentForMouseEvents, false);
9083 child->setMask(QRect(50, 50, 60, 60));
9085 QVERIFY(!parent.childAt(69, 69));
9086 QVERIFY(!parent.childAt(130, 130));
9087 QCOMPARE(parent.childAt(70, 70), grandChild);
9088 QCOMPARE(parent.childAt(129, 129), grandChild);
9090 child->setAttribute(Qt::WA_MouseNoMask);
9091 QCOMPARE(parent.childAt(69, 69), grandChild);
9092 QCOMPARE(parent.childAt(130, 130), grandChild);
9093 child->setAttribute(Qt::WA_MouseNoMask, false);
9095 grandChild->setAttribute(Qt::WA_TransparentForMouseEvents);
9096 QCOMPARE(parent.childAt(70, 70), child);
9097 QCOMPARE(parent.childAt(129, 129), child);
9098 grandChild->setAttribute(Qt::WA_TransparentForMouseEvents, false);
9100 grandChild->setMask(QRect(80, 80, 40, 40));
9102 QCOMPARE(parent.childAt(79, 79), child);
9103 QCOMPARE(parent.childAt(120, 120), child);
9104 QCOMPARE(parent.childAt(80, 80), grandChild);
9105 QCOMPARE(parent.childAt(119, 119), grandChild);
9107 grandChild->setAttribute(Qt::WA_MouseNoMask);
9109 QCOMPARE(parent.childAt(79, 79), grandChild);
9110 QCOMPARE(parent.childAt(120, 120), grandChild);
9114 void tst_QWidget::childAt_unifiedToolBar()
9116 QLabel *label = new QLabel(QLatin1String("foo"));
9117 QToolBar *toolBar = new QToolBar;
9118 toolBar->addWidget(new QLabel("dummy"));
9119 toolBar->addWidget(label);
9121 QMainWindow mainWindow;
9122 mainWindow.addToolBar(toolBar);
9125 // Calculate the top-left corner of the tool bar and the label (in mainWindow's coordinates).
9126 QPoint labelTopLeft = label->mapTo(&mainWindow, QPoint());
9127 QPoint toolBarTopLeft = toolBar->mapTo(&mainWindow, QPoint());
9129 QCOMPARE(mainWindow.childAt(toolBarTopLeft), static_cast<QWidget *>(toolBar));
9130 QCOMPARE(mainWindow.childAt(labelTopLeft), static_cast<QWidget *>(label));
9132 // Enable unified tool bars.
9133 mainWindow.setUnifiedTitleAndToolBarOnMac(true);
9136 // The tool bar is now in the "non-client" area of QMainWindow, i.e.
9137 // outside the mainWindow's rect(), and since mapTo et al. doesn't work
9138 // in that case (see commit 35667fd45ada49269a5987c235fdedfc43e92bb8),
9139 // we use mapToGlobal/mapFromGlobal to re-calculate the corners.
9140 QPoint oldToolBarTopLeft = toolBarTopLeft;
9141 toolBarTopLeft = mainWindow.mapFromGlobal(toolBar->mapToGlobal(QPoint()));
9142 QVERIFY(toolBarTopLeft != oldToolBarTopLeft);
9143 QVERIFY(toolBarTopLeft.y() < 0);
9144 labelTopLeft = mainWindow.mapFromGlobal(label->mapToGlobal(QPoint()));
9146 QCOMPARE(mainWindow.childAt(toolBarTopLeft), static_cast<QWidget *>(toolBar));
9147 QCOMPARE(mainWindow.childAt(labelTopLeft), static_cast<QWidget *>(label));
9150 void tst_QWidget::taskQTBUG_11373()
9152 QMainWindow * myWindow = new QMainWindow();
9153 QWidget * center = new QWidget();
9154 myWindow -> setCentralWidget(center);
9155 QWidget * drawer = new QWidget(myWindow, Qt::Drawer);
9157 QCOMPARE(drawer->isVisible(), false);
9159 myWindow -> raise();
9160 // The drawer shouldn't be visible now.
9161 QCOMPARE(drawer->isVisible(), false);
9162 myWindow -> setWindowState(Qt::WindowFullScreen);
9163 myWindow -> setWindowState(Qt::WindowNoState);
9164 // The drawer should still not be visible, since we haven't shown it.
9165 QCOMPARE(drawer->isVisible(), false);
9169 void tst_QWidget::taskQTBUG_17333_ResizeInfiniteRecursion()
9172 const char *s = "border: 1px solid;";
9173 tb.setStyleSheet(s);
9176 QTest::qWaitForWindowShown(&tb);
9177 tb.setGeometry(QRect(100, 100, 0, 100));
9178 // No crash, it works.
9181 void tst_QWidget::nativeChildFocus()
9184 QLayout *layout = new QVBoxLayout;
9185 w.setLayout(layout);
9186 QLineEdit *p1 = new QLineEdit;
9187 QLineEdit *p2 = new QLineEdit;
9188 layout->addWidget(p1);
9189 layout->addWidget(p2);
9190 p1->setObjectName("p1");
9191 p2->setObjectName("p2");
9195 p1->setAttribute(Qt::WA_NativeWindow);
9196 p2->setAttribute(Qt::WA_NativeWindow);
9197 QApplication::processEvents();
9198 QTest::qWaitForWindowShown(&w);
9201 QCOMPARE(QApplication::activeWindow(), &w);
9202 QCOMPARE(QApplication::focusWidget(), static_cast<QWidget*>(p1));
9207 static bool lenientCompare(const QPixmap &actual, const QPixmap &expected)
9209 QImage expectedImage = expected.toImage().convertToFormat(QImage::Format_RGB32);
9210 QImage actualImage = actual.toImage().convertToFormat(QImage::Format_RGB32);
9212 if (expectedImage.size() != actualImage.size()) {
9213 qWarning("Image size comparison failed: expected: %dx%d, got %dx%d",
9214 expectedImage.size().width(), expectedImage.size().height(),
9215 actualImage.size().width(), actualImage.size().height());
9219 const int size = actual.width() * actual.height();
9220 const int threshold = QPixmap::defaultDepth() == 16 ? 10 : 2;
9222 QRgb *a = (QRgb *)actualImage.bits();
9223 QRgb *e = (QRgb *)expectedImage.bits();
9224 for (int i = 0; i < size; ++i) {
9225 const QColor ca(a[i]);
9226 const QColor ce(e[i]);
9227 if (qAbs(ca.red() - ce.red()) > threshold
9228 || qAbs(ca.green() - ce.green()) > threshold
9229 || qAbs(ca.blue() - ce.blue()) > threshold) {
9230 qWarning("Color mismatch at pixel #%d: Expected: %d,%d,%d, got %d,%d,%d",
9231 i, ce.red(), ce.green(), ce.blue(), ca.red(), ca.green(), ca.blue());
9239 void tst_QWidget::grab()
9241 for (int opaque = 0; opaque < 2; ++opaque) {
9243 QImage image(128, 128, opaque ? QImage::Format_RGB32 : QImage::Format_ARGB32_Premultiplied);
9244 for (int row = 0; row < image.height(); ++row) {
9245 QRgb *line = reinterpret_cast<QRgb *>(image.scanLine(row));
9246 for (int col = 0; col < image.width(); ++col)
9247 line[col] = qRgba(rand() & 255, row, col, opaque ? 255 : 127);
9250 QPalette pal = widget.palette();
9251 pal.setBrush(QPalette::Window, QBrush(image));
9252 widget.setPalette(pal);
9253 widget.resize(128, 128);
9255 QPixmap expected(64, 64);
9257 expected.fill(Qt::transparent);
9259 QPainter p(&expected);
9260 p.translate(-64, -64);
9261 p.drawTiledPixmap(0, 0, 128, 128, pal.brush(QPalette::Window).texture(), 0, 0);
9264 QPixmap actual = widget.grab(QRect(64, 64, 64, 64));
9265 QVERIFY(lenientCompare(actual, expected));
9267 actual = widget.grab(QRect(64, 64, -1, -1));
9268 QVERIFY(lenientCompare(actual, expected));
9270 // Make sure a widget that is not yet shown is grabbed correctly.
9271 QTreeWidget widget2;
9272 actual = widget2.grab(QRect());
9274 expected = widget2.grab(QRect());
9276 QVERIFY(lenientCompare(actual, expected));
9280 QTEST_MAIN(tst_QWidget)
9281 #include "tst_qwidget.moc"