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 QVERIFY(qApp->activeWindow() == &widget1);
1688 widget2.showMaximized();
1689 QTest::qWait(waitTime);
1690 QVERIFY(qApp->activeWindow() == &widget2);
1691 widget2.showMinimized();
1692 QTest::qWait(waitTime);
1693 QVERIFY(qApp->activeWindow() == &widget1);
1694 widget2.showNormal();
1695 QTest::qWait(waitTime);
1697 if (QSysInfo::WindowsVersion >= QSysInfo::WV_VISTA)
1698 QEXPECT_FAIL("", "MS introduced new behavior after XP", Continue);
1700 QTest::qWait(waitTime);
1701 QVERIFY(qApp->activeWindow() == &widget2);
1703 QTest::qWait(waitTime);
1704 QVERIFY(qApp->activeWindow() == &widget1);
1708 void tst_QWidget::windowState()
1710 if (m_platform == QStringLiteral("xcb"))
1711 QSKIP("X11: Many window managers do not support window state properly, which causes this test to fail.");
1712 #ifdef Q_OS_WINCE_WM
1713 QPoint pos(500, 500);
1714 QSize size(200, 200);
1715 if (qt_wince_is_smartphone()) { //small screen
1716 pos = QPoint(10,10);
1717 size = QSize(100,100);
1720 const QPoint pos(500, 500);
1721 const QSize size(200, 200);
1726 widget1.resize(size);
1727 QCOMPARE(widget1.pos(), pos);
1728 QCOMPARE(widget1.size(), size);
1730 widget1.setWindowTitle("Widget1");
1731 QCOMPARE(widget1.pos(), pos);
1732 QCOMPARE(widget1.size(), size);
1734 #define VERIFY_STATE(s) QCOMPARE(int(widget1.windowState() & stateMask), int(s))
1736 const int stateMask = Qt::WindowMaximized|Qt::WindowMinimized|Qt::WindowFullScreen;
1738 widget1.setWindowState(Qt::WindowMaximized);
1740 VERIFY_STATE(Qt::WindowMaximized);
1741 QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowMaximized);
1745 VERIFY_STATE(Qt::WindowMaximized);
1746 QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowMaximized);
1748 widget1.setWindowState(widget1.windowState() ^ Qt::WindowMaximized);
1750 QVERIFY(!(widget1.windowState() & Qt::WindowMaximized));
1751 QTRY_COMPARE(widget1.pos(), pos);
1752 QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowNoState);
1754 widget1.setWindowState(Qt::WindowMinimized);
1756 VERIFY_STATE(Qt::WindowMinimized);
1757 QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowMinimized);
1759 widget1.setWindowState(widget1.windowState() | Qt::WindowMaximized);
1761 VERIFY_STATE((Qt::WindowMinimized|Qt::WindowMaximized));
1762 QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowMinimized);
1764 widget1.setWindowState(widget1.windowState() ^ Qt::WindowMinimized);
1766 VERIFY_STATE(Qt::WindowMaximized);
1767 QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowMaximized);
1769 widget1.setWindowState(widget1.windowState() ^ Qt::WindowMaximized);
1771 QVERIFY(!(widget1.windowState() & (Qt::WindowMinimized|Qt::WindowMaximized)));
1772 QTRY_COMPARE(widget1.pos(), pos);
1773 QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowNoState);
1775 widget1.setWindowState(Qt::WindowFullScreen);
1777 VERIFY_STATE(Qt::WindowFullScreen);
1778 QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowFullScreen);
1780 widget1.setWindowState(widget1.windowState() ^ Qt::WindowMinimized);
1782 VERIFY_STATE((Qt::WindowFullScreen|Qt::WindowMinimized));
1783 QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowMinimized);
1785 widget1.setWindowState(widget1.windowState() ^ Qt::WindowMinimized);
1787 VERIFY_STATE(Qt::WindowFullScreen);
1788 QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowFullScreen);
1790 widget1.setWindowState(Qt::WindowNoState);
1792 VERIFY_STATE(Qt::WindowNoState);
1793 QTRY_COMPARE(widget1.pos(), pos);
1794 QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowNoState);
1796 widget1.setWindowState(Qt::WindowFullScreen);
1798 VERIFY_STATE(Qt::WindowFullScreen);
1799 QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowFullScreen);
1801 widget1.setWindowState(widget1.windowState() ^ Qt::WindowMaximized);
1803 VERIFY_STATE((Qt::WindowFullScreen|Qt::WindowMaximized));
1804 QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowFullScreen);
1806 widget1.setWindowState(widget1.windowState() ^ Qt::WindowMinimized);
1808 VERIFY_STATE((Qt::WindowFullScreen|Qt::WindowMaximized|Qt::WindowMinimized));
1809 QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowMinimized);
1811 widget1.setWindowState(widget1.windowState() ^ Qt::WindowMinimized);
1813 VERIFY_STATE((Qt::WindowFullScreen|Qt::WindowMaximized));
1814 QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowFullScreen);
1816 widget1.setWindowState(widget1.windowState() ^ Qt::WindowFullScreen);
1818 VERIFY_STATE(Qt::WindowMaximized);
1819 QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowMaximized);
1821 widget1.setWindowState(widget1.windowState() ^ Qt::WindowMaximized);
1823 QVERIFY(!(widget1.windowState() & stateMask));
1824 QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowNoState);
1826 QTRY_COMPARE(widget1.pos(), pos);
1827 QTRY_COMPARE(widget1.size(), size);
1830 void tst_QWidget::showMaximized()
1833 QHBoxLayout *layout;
1834 layout = new QHBoxLayout;
1840 layout->addWidget(&le);
1841 layout->addWidget(&le2);
1842 layout->addWidget(&le3);
1844 layouted.setLayout(layout);
1846 plain.showMaximized();
1847 QVERIFY(plain.windowState() & Qt::WindowMaximized);
1850 QVERIFY(!(plain.windowState() & Qt::WindowMaximized));
1852 layouted.showMaximized();
1853 QVERIFY(layouted.windowState() & Qt::WindowMaximized);
1855 layouted.showNormal();
1856 QVERIFY(!(layouted.windowState() & Qt::WindowMaximized));
1858 // ### fixme: embedded may choose a different size to fit on the screen.
1859 if (layouted.size() != layouted.sizeHint())
1860 QEXPECT_FAIL("", "QTBUG-22326", Continue);
1861 QCOMPARE(layouted.size(), layouted.sizeHint());
1863 layouted.showMaximized();
1864 QVERIFY(layouted.isMaximized());
1865 QVERIFY(layouted.isVisible());
1868 QVERIFY(layouted.isMaximized());
1869 QVERIFY(!layouted.isVisible());
1871 layouted.showMaximized();
1872 QVERIFY(layouted.isMaximized());
1873 QVERIFY(layouted.isVisible());
1875 layouted.showMinimized();
1876 QVERIFY(layouted.isMinimized());
1877 QVERIFY(layouted.isMaximized());
1879 layouted.showMaximized();
1880 QVERIFY(!layouted.isMinimized());
1881 QVERIFY(layouted.isMaximized());
1882 QVERIFY(layouted.isVisible());
1884 layouted.showMinimized();
1885 QVERIFY(layouted.isMinimized());
1886 QVERIFY(layouted.isMaximized());
1888 layouted.showMaximized();
1889 QVERIFY(!layouted.isMinimized());
1890 QVERIFY(layouted.isMaximized());
1891 QVERIFY(layouted.isVisible());
1895 QWidget widget(&frame);
1896 widget.showMaximized();
1897 QVERIFY(widget.isMaximized());
1902 widget.setGeometry(0, 0, 10, 10);
1903 widget.showMaximized();
1904 QTRY_VERIFY(widget.size().width() > 20 && widget.size().height() > 20);
1908 void tst_QWidget::showFullScreen()
1911 QHBoxLayout *layout;
1916 layout = new QHBoxLayout;
1918 layout->addWidget(&le);
1919 layout->addWidget(&le2);
1920 layout->addWidget(&le3);
1922 layouted.setLayout(layout);
1924 plain.showFullScreen();
1925 QVERIFY(plain.windowState() & Qt::WindowFullScreen);
1928 QVERIFY(!(plain.windowState() & Qt::WindowFullScreen));
1930 layouted.showFullScreen();
1931 QVERIFY(layouted.windowState() & Qt::WindowFullScreen);
1933 layouted.showNormal();
1934 QVERIFY(!(layouted.windowState() & Qt::WindowFullScreen));
1936 // ### fixme: embedded may choose a different size to fit on the screen.
1937 if (layouted.size() != layouted.sizeHint())
1938 QEXPECT_FAIL("", "QTBUG-22326", Continue);
1939 QCOMPARE(layouted.size(), layouted.sizeHint());
1941 layouted.showFullScreen();
1942 QVERIFY(layouted.isFullScreen());
1943 QVERIFY(layouted.isVisible());
1946 QVERIFY(layouted.isFullScreen());
1947 QVERIFY(!layouted.isVisible());
1949 layouted.showFullScreen();
1950 QVERIFY(layouted.isFullScreen());
1951 QVERIFY(layouted.isVisible());
1953 layouted.showMinimized();
1954 QVERIFY(layouted.isMinimized());
1955 QVERIFY(layouted.isFullScreen());
1957 layouted.showFullScreen();
1958 QVERIFY(!layouted.isMinimized());
1959 QVERIFY(layouted.isFullScreen());
1960 QVERIFY(layouted.isVisible());
1962 layouted.showMinimized();
1963 QVERIFY(layouted.isMinimized());
1964 QVERIFY(layouted.isFullScreen());
1966 layouted.showFullScreen();
1967 QVERIFY(!layouted.isMinimized());
1968 QVERIFY(layouted.isFullScreen());
1969 QVERIFY(layouted.isVisible());
1973 QWidget widget(&frame);
1974 widget.showFullScreen();
1975 QVERIFY(widget.isFullScreen());
1979 class ResizeWidget : public QWidget {
1981 ResizeWidget(QWidget *p = 0) : QWidget(p)
1983 m_resizeEventCount = 0;
1986 void resizeEvent(QResizeEvent *e){
1987 QCOMPARE(size(), e->size());
1988 ++m_resizeEventCount;
1992 int m_resizeEventCount;
1995 void tst_QWidget::resizeEvent()
1999 ResizeWidget wChild(&wParent);
2001 QCOMPARE (wChild.m_resizeEventCount, 1); // initial resize event before paint
2003 QSize safeSize(640,480);
2004 if (wChild.size() == safeSize)
2005 safeSize.setWidth(639);
2006 wChild.resize(safeSize);
2007 QCOMPARE (wChild.m_resizeEventCount, 1);
2009 QCOMPARE (wChild.m_resizeEventCount, 2);
2013 ResizeWidget wTopLevel;
2015 QCOMPARE (wTopLevel.m_resizeEventCount, 1); // initial resize event before paint for toplevels
2017 QSize safeSize(640,480);
2018 if (wTopLevel.size() == safeSize)
2019 safeSize.setWidth(639);
2020 wTopLevel.resize(safeSize);
2021 QCOMPARE (wTopLevel.m_resizeEventCount, 1);
2023 QCOMPARE (wTopLevel.m_resizeEventCount, 2);
2027 void tst_QWidget::showMinimized()
2030 plain.move(100, 100);
2031 plain.resize(200, 200);
2032 QPoint pos = plain.pos();
2034 plain.showMinimized();
2035 QVERIFY(plain.isMinimized());
2036 QVERIFY(plain.isVisible());
2037 QCOMPARE(plain.pos(), pos);
2040 QVERIFY(!plain.isMinimized());
2041 QVERIFY(plain.isVisible());
2042 QCOMPARE(plain.pos(), pos);
2044 plain.showMinimized();
2045 QVERIFY(plain.isMinimized());
2046 QVERIFY(plain.isVisible());
2047 QCOMPARE(plain.pos(), pos);
2050 QVERIFY(plain.isMinimized());
2051 QVERIFY(!plain.isVisible());
2053 plain.showMinimized();
2054 QVERIFY(plain.isMinimized());
2055 QVERIFY(plain.isVisible());
2057 plain.setGeometry(200, 200, 300, 300);
2059 QCOMPARE(plain.geometry(), QRect(200, 200, 300, 300));
2063 QWidget widget(&frame);
2064 widget.showMinimized();
2065 QVERIFY(widget.isMinimized());
2069 void tst_QWidget::showMinimizedKeepsFocus()
2071 //here we test that minimizing a widget and restoring it doesn't change the focus inside of it
2074 QWidget child1(&window), child2(&window);
2075 child1.setFocusPolicy(Qt::StrongFocus);
2076 child2.setFocusPolicy(Qt::StrongFocus);
2078 qApp->setActiveWindow(&window);
2079 QTest::qWaitForWindowShown(&window);
2083 QTRY_COMPARE(window.focusWidget(), &child2);
2084 QTRY_COMPARE(qApp->focusWidget(), &child2);
2086 window.showMinimized();
2088 QTRY_VERIFY(window.isMinimized());
2089 QTRY_COMPARE(window.focusWidget(), &child2);
2091 window.showNormal();
2093 QTRY_COMPARE(window.focusWidget(), &child2);
2096 //testing deletion of the focusWidget
2099 QWidget *child = new QWidget(&window);
2100 child->setFocusPolicy(Qt::StrongFocus);
2102 qApp->setActiveWindow(&window);
2103 QTest::qWaitForWindowShown(&window);
2106 QTRY_COMPARE(window.focusWidget(), child);
2107 QTRY_COMPARE(qApp->focusWidget(), child);
2110 QCOMPARE(window.focusWidget(), static_cast<QWidget*>(0));
2111 QCOMPARE(qApp->focusWidget(), static_cast<QWidget*>(0));
2114 //testing reparenting the focus widget
2117 QWidget *child = new QWidget(&window);
2118 child->setFocusPolicy(Qt::StrongFocus);
2120 qApp->setActiveWindow(&window);
2121 QTest::qWaitForWindowShown(&window);
2124 QTRY_COMPARE(window.focusWidget(), child);
2125 QTRY_COMPARE(qApp->focusWidget(), child);
2127 child->setParent(0);
2128 QCOMPARE(window.focusWidget(), static_cast<QWidget*>(0));
2129 QCOMPARE(qApp->focusWidget(), static_cast<QWidget*>(0));
2132 //testing setEnabled(false)
2135 QWidget *child = new QWidget(&window);
2136 child->setFocusPolicy(Qt::StrongFocus);
2138 qApp->setActiveWindow(&window);
2139 QTest::qWaitForWindowShown(&window);
2142 QTRY_COMPARE(window.focusWidget(), child);
2143 QTRY_COMPARE(qApp->focusWidget(), child);
2145 child->setEnabled(false);
2146 QCOMPARE(window.focusWidget(), static_cast<QWidget*>(0));
2147 QCOMPARE(qApp->focusWidget(), static_cast<QWidget*>(0));
2150 //testing clearFocus
2153 QWidget *firstchild = new QWidget(&window);
2154 firstchild->setFocusPolicy(Qt::StrongFocus);
2155 QWidget *child = new QWidget(&window);
2156 child->setFocusPolicy(Qt::StrongFocus);
2158 qApp->setActiveWindow(&window);
2159 QTest::qWaitForWindowShown(&window);
2162 QTRY_COMPARE(window.focusWidget(), child);
2163 QTRY_COMPARE(qApp->focusWidget(), child);
2165 child->clearFocus();
2166 QCOMPARE(window.focusWidget(), static_cast<QWidget*>(0));
2167 QCOMPARE(qApp->focusWidget(), static_cast<QWidget*>(0));
2169 window.showMinimized();
2171 QTRY_VERIFY(window.isMinimized());
2172 QCOMPARE(window.focusWidget(), static_cast<QWidget*>(0));
2173 QTRY_COMPARE(qApp->focusWidget(), static_cast<QWidget*>(0));
2175 window.showNormal();
2176 qApp->setActiveWindow(&window);
2177 QTest::qWaitForWindowShown(&window);
2180 if (!macHasAccessToWindowsServer())
2181 QEXPECT_FAIL("", "When not having WindowServer access, we lose focus.", Continue);
2183 QTRY_COMPARE(window.focusWidget(), firstchild);
2185 if (!macHasAccessToWindowsServer())
2186 QEXPECT_FAIL("", "When not having WindowServer access, we lose focus.", Continue);
2188 QTRY_COMPARE(qApp->focusWidget(), firstchild);
2193 void tst_QWidget::reparent()
2196 parent.setWindowTitle("Toplevel");
2197 parent.setGeometry(300, 300, 200, 150);
2200 child.setObjectName("child");
2201 child.setGeometry(10, 10, 180, 130);
2203 pal1.setColor(child.backgroundRole(), Qt::white);
2204 child.setPalette(pal1);
2206 QWidget childTLW(&child, Qt::Window);
2207 childTLW.setObjectName("childTLW");
2208 childTLW.setGeometry(100, 100, 50, 50);
2210 pal2.setColor(childTLW.backgroundRole(), Qt::yellow);
2211 childTLW.setPalette(pal2);
2215 QTest::qWaitForWindowShown(&parent);
2218 parent.move(50, 50);
2220 parent.move(300, 300);
2223 QPoint childPos = parent.mapToGlobal(child.pos());
2224 QPoint tlwPos = childTLW.pos();
2226 child.setParent(0, child.windowFlags() & ~Qt::WindowType_Mask);
2227 child.setGeometry(childPos.x(), childPos.y(), child.width(), child.height());
2230 if (m_platform == QStringLiteral("xcb"))
2231 QEXPECT_FAIL("", "On X11, the window manager will apply NorthWestGravity rules to 'child', which"
2232 " means the top-left corner of the window frame will be placed at 'childPos'"
2233 " causing this test to fail.", Continue);
2235 QCOMPARE(child.geometry().topLeft(), childPos);
2236 QTRY_COMPARE(childTLW.pos(), tlwPos);
2239 // Qt/Embedded does it differently.
2240 void tst_QWidget::icon()
2244 testWidget->setWindowIcon(p);
2246 QVERIFY(!testWidget->windowIcon().isNull());
2248 QVERIFY(!testWidget->windowIcon().isNull());
2249 testWidget->showFullScreen();
2250 QVERIFY(!testWidget->windowIcon().isNull());
2251 testWidget->showNormal();
2252 QVERIFY(!testWidget->windowIcon().isNull());
2255 void tst_QWidget::hideWhenFocusWidgetIsChild()
2257 testWidget->activateWindow();
2258 QWidget *parentWidget = new QWidget(testWidget);
2259 parentWidget->setObjectName("parentWidget");
2260 parentWidget->setGeometry(0, 0, 100, 100);
2261 QLineEdit *edit = new QLineEdit(parentWidget);
2262 edit->setObjectName("edit1");
2263 QLineEdit *edit3 = new QLineEdit(parentWidget);
2264 edit3->setObjectName("edit3");
2266 parentWidget->show();
2267 QLineEdit *edit2 = new QLineEdit(testWidget);
2268 edit2->setObjectName("edit2");
2270 edit2->move(110, 100);
2272 qApp->processEvents();
2273 QString actualFocusWidget, expectedFocusWidget;
2274 if (!qApp->focusWidget() && m_platform == QStringLiteral("xcb"))
2275 QSKIP("X11: Your window manager is too broken for this test");
2277 QVERIFY(qApp->focusWidget());
2278 actualFocusWidget.sprintf("%p %s %s", qApp->focusWidget(), qApp->focusWidget()->objectName().toLatin1().constData(), qApp->focusWidget()->metaObject()->className());
2279 expectedFocusWidget.sprintf("%p %s %s", edit, edit->objectName().toLatin1().constData(), edit->metaObject()->className());
2280 QCOMPARE(actualFocusWidget, expectedFocusWidget);
2282 parentWidget->hide();
2283 qApp->processEvents();
2284 actualFocusWidget.sprintf("%p %s %s", qApp->focusWidget(), qApp->focusWidget()->objectName().toLatin1().constData(), qApp->focusWidget()->metaObject()->className());
2285 expectedFocusWidget.sprintf("%p %s %s", edit2, edit2->objectName().toLatin1().constData(), edit2->metaObject()->className());
2286 QCOMPARE(actualFocusWidget, expectedFocusWidget);
2289 delete parentWidget;
2292 void tst_QWidget::normalGeometry()
2295 parent.setWindowTitle("NormalGeometry parent");
2296 QWidget *child = new QWidget(&parent);
2298 QCOMPARE(parent.normalGeometry(), parent.geometry());
2299 QCOMPARE(child->normalGeometry(), QRect());
2301 parent.setGeometry(100, 100, 200, 200);
2303 QTest::qWaitForWindowShown(&parent);
2304 QApplication::processEvents();
2306 QRect geom = parent.geometry();
2307 // ### the window manager places the top-left corner at
2308 // ### 100,100... making geom something like 102,124 (offset by
2309 // ### the frame/frame)... this indicates a rather large different
2310 // ### between how X11 and Windows works
2311 // QCOMPARE(geom, QRect(100, 100, 200, 200));
2312 QCOMPARE(parent.normalGeometry(), geom);
2314 parent.setWindowState(parent.windowState() ^ Qt::WindowMaximized);
2316 QTRY_VERIFY(parent.windowState() & Qt::WindowMaximized);
2317 QTRY_VERIFY(parent.geometry() != geom);
2318 QTRY_COMPARE(parent.normalGeometry(), geom);
2320 parent.setWindowState(parent.windowState() ^ Qt::WindowMaximized);
2322 QTRY_VERIFY(!(parent.windowState() & Qt::WindowMaximized));
2323 QTRY_COMPARE(parent.geometry(), geom);
2324 QTRY_COMPARE(parent.normalGeometry(), geom);
2326 parent.showMaximized();
2328 QTRY_VERIFY(parent.windowState() & Qt::WindowMaximized);
2329 QTRY_VERIFY(parent.geometry() != geom);
2330 QCOMPARE(parent.normalGeometry(), geom);
2332 parent.showNormal();
2334 QTRY_VERIFY(!(parent.windowState() & Qt::WindowMaximized));
2335 QTRY_COMPARE(parent.geometry(), geom);
2336 QCOMPARE(parent.normalGeometry(), geom);
2338 parent.setWindowState(parent.windowState() ^ Qt::WindowMinimized);
2340 parent.setWindowState(parent.windowState() ^ Qt::WindowMaximized);
2342 QTRY_VERIFY(parent.windowState() & (Qt::WindowMinimized|Qt::WindowMaximized));
2343 // ### when minimized and maximized at the same time, the geometry
2344 // ### does *NOT* have to be the normal geometry, it could be the
2345 // ### maximized geometry.
2346 // QCOMPARE(parent.geometry(), geom);
2347 QTRY_COMPARE(parent.normalGeometry(), geom);
2349 parent.setWindowState(parent.windowState() ^ Qt::WindowMinimized);
2351 QTRY_VERIFY(!(parent.windowState() & Qt::WindowMinimized));
2352 QTRY_VERIFY(parent.windowState() & Qt::WindowMaximized);
2353 QTRY_VERIFY(parent.geometry() != geom);
2354 QTRY_COMPARE(parent.normalGeometry(), geom);
2356 parent.setWindowState(parent.windowState() ^ Qt::WindowMaximized);
2358 QTRY_VERIFY(!(parent.windowState() & Qt::WindowMaximized));
2359 QTRY_COMPARE(parent.geometry(), geom);
2360 QTRY_COMPARE(parent.normalGeometry(), geom);
2362 parent.setWindowState(parent.windowState() ^ Qt::WindowFullScreen);
2364 QTRY_VERIFY(parent.windowState() & Qt::WindowFullScreen);
2365 QTRY_VERIFY(parent.geometry() != geom);
2366 QTRY_COMPARE(parent.normalGeometry(), geom);
2368 parent.setWindowState(parent.windowState() ^ Qt::WindowFullScreen);
2370 QVERIFY(!(parent.windowState() & Qt::WindowFullScreen));
2371 QTRY_COMPARE(parent.geometry(), geom);
2372 QTRY_COMPARE(parent.normalGeometry(), geom);
2374 parent.showFullScreen();
2376 QTRY_VERIFY(parent.windowState() & Qt::WindowFullScreen);
2377 QTRY_VERIFY(parent.geometry() != geom);
2378 QTRY_COMPARE(parent.normalGeometry(), geom);
2380 parent.showNormal();
2382 QTRY_VERIFY(!(parent.windowState() & Qt::WindowFullScreen));
2383 QTRY_COMPARE(parent.geometry(), geom);
2384 QTRY_COMPARE(parent.normalGeometry(), geom);
2386 parent.showNormal();
2387 parent.setWindowState(Qt:: WindowFullScreen | Qt::WindowMaximized);
2388 parent.setWindowState(Qt::WindowMinimized | Qt:: WindowFullScreen | Qt::WindowMaximized);
2389 parent.setWindowState(Qt:: WindowFullScreen | Qt::WindowMaximized);
2391 QTRY_COMPARE(parent.normalGeometry(), geom);
2394 void tst_QWidget::setGeometry()
2397 QWidget child(&tlw);
2399 QRect tr(100,100,200,200);
2400 QRect cr(50,50,50,50);
2401 tlw.setGeometry(tr);
2402 child.setGeometry(cr);
2405 QCOMPARE(tlw.geometry().size(), tr.size());
2406 QCOMPARE(child.geometry(), cr);
2408 tlw.setParent(0, Qt::Window|Qt::FramelessWindowHint);
2409 tr = QRect(0,0,100,100);
2410 tr.moveTopLeft(QApplication::desktop()->availableGeometry().topLeft());
2411 tlw.setGeometry(tr);
2412 QCOMPARE(tlw.geometry(), tr);
2415 if (tlw.frameGeometry() != tlw.geometry())
2416 QSKIP("Your window manager is too broken for this test");
2417 QCOMPARE(tlw.geometry(), tr);
2421 // Windows CE does not support windowOpacity.
2423 void tst_QWidget::windowOpacity()
2426 QWidget child(&widget);
2428 // Initial value should be 1.0
2429 QCOMPARE(widget.windowOpacity(), 1.0);
2430 // children should always return 1.0
2431 QCOMPARE(child.windowOpacity(), 1.0);
2433 widget.setWindowOpacity(0.0);
2434 QCOMPARE(widget.windowOpacity(), 0.0);
2435 child.setWindowOpacity(0.0);
2436 QCOMPARE(child.windowOpacity(), 1.0);
2438 widget.setWindowOpacity(1.0);
2439 QCOMPARE(widget.windowOpacity(), 1.0);
2440 child.setWindowOpacity(1.0);
2441 QCOMPARE(child.windowOpacity(), 1.0);
2443 widget.setWindowOpacity(2.0);
2444 QCOMPARE(widget.windowOpacity(), 1.0);
2445 child.setWindowOpacity(2.0);
2446 QCOMPARE(child.windowOpacity(), 1.0);
2448 widget.setWindowOpacity(-1.0);
2449 QCOMPARE(widget.windowOpacity(), 0.0);
2450 child.setWindowOpacity(-1.0);
2451 QCOMPARE(child.windowOpacity(), 1.0);
2455 class UpdateWidget : public QWidget
2458 UpdateWidget(QWidget *parent = 0) : QWidget(parent) {
2462 void paintEvent(QPaintEvent *e) {
2463 paintedRegion += e->region();
2465 if (resizeInPaintEvent) {
2466 resizeInPaintEvent = false;
2467 resize(size() + QSize(2, 2));
2471 bool event(QEvent *event)
2473 switch (event->type()) {
2474 case QEvent::ZOrderChange:
2475 ++numZOrderChangeEvents;
2477 case QEvent::UpdateRequest:
2478 ++numUpdateRequestEvents;
2480 case QEvent::ActivationChange:
2481 case QEvent::FocusIn:
2482 case QEvent::FocusOut:
2483 case QEvent::WindowActivate:
2484 case QEvent::WindowDeactivate:
2485 if (!updateOnActivationChangeAndFocusIn)
2486 return true; // Filter out to avoid update() calls in QWidget.
2491 return QWidget::event(event);
2496 numZOrderChangeEvents = 0;
2497 numUpdateRequestEvents = 0;
2498 updateOnActivationChangeAndFocusIn = false;
2499 resizeInPaintEvent = false;
2500 paintedRegion = QRegion();
2504 int numZOrderChangeEvents;
2505 int numUpdateRequestEvents;
2506 bool updateOnActivationChangeAndFocusIn;
2507 bool resizeInPaintEvent;
2508 QRegion paintedRegion;
2511 void tst_QWidget::lostUpdatesOnHide()
2514 UpdateWidget widget;
2515 widget.setAttribute(Qt::WA_DontShowOnScreen);
2522 QCOMPARE(widget.numPaintEvents, 1);
2526 void tst_QWidget::raise()
2529 QWidget *parent = new QWidget(0);
2530 QList<UpdateWidget *> allChildren;
2532 UpdateWidget *child1 = new UpdateWidget(parent);
2533 child1->setAutoFillBackground(true);
2534 allChildren.append(child1);
2536 UpdateWidget *child2 = new UpdateWidget(parent);
2537 child2->setAutoFillBackground(true);
2538 allChildren.append(child2);
2540 UpdateWidget *child3 = new UpdateWidget(parent);
2541 child3->setAutoFillBackground(true);
2542 allChildren.append(child3);
2544 UpdateWidget *child4 = new UpdateWidget(parent);
2545 child4->setAutoFillBackground(true);
2546 allChildren.append(child4);
2549 QTest::qWaitForWindowShown(parent);
2553 if (child1->internalWinId()) {
2554 QSKIP("Cocoa has no Z-Order for views, we hack it, but it results in paint events.");
2558 QList<QObject *> list1;
2559 list1 << child1 << child2 << child3 << child4;
2560 QVERIFY(parent->children() == list1);
2561 QCOMPARE(allChildren.count(), list1.count());
2563 foreach (UpdateWidget *child, allChildren) {
2564 int expectedPaintEvents = child == child4 ? 1 : 0;
2565 if (expectedPaintEvents == 0) {
2566 QVERIFY(child->numPaintEvents == 0);
2568 // show() issues multiple paint events on some window managers
2569 QTRY_VERIFY(child->numPaintEvents >= expectedPaintEvents);
2571 QCOMPARE(child->numZOrderChangeEvents, 0);
2575 for (int i = 0; i < 5; ++i)
2579 foreach (UpdateWidget *child, allChildren) {
2580 int expectedPaintEvents = child == child2 ? 1 : 0;
2581 int expectedZOrderChangeEvents = child == child2 ? 1 : 0;
2583 QSKIP("Not yet sure why this fails.");
2585 QTRY_COMPARE(child->numPaintEvents, expectedPaintEvents);
2586 QCOMPARE(child->numZOrderChangeEvents, expectedZOrderChangeEvents);
2590 QList<QObject *> list2;
2591 list2 << child1 << child3 << child4 << child2;
2592 QVERIFY(parent->children() == list2);
2594 // Creates a widget on top of all the children and checks that raising one of
2595 // the children underneath doesn't trigger a repaint on the covering widget.
2597 parent->setParent(&topLevel);
2599 QTest::qWaitForWindowShown(&topLevel);
2602 UpdateWidget *onTop = new UpdateWidget(&topLevel);
2604 onTop->resize(topLevel.size());
2605 onTop->setAutoFillBackground(true);
2608 QTRY_VERIFY(onTop->numPaintEvents > 0);
2611 // Reset all the children.
2612 foreach (UpdateWidget *child, allChildren)
2615 for (int i = 0; i < 5; ++i)
2619 QCOMPARE(onTop->numPaintEvents, 0);
2620 QCOMPARE(onTop->numZOrderChangeEvents, 0);
2622 QList<QObject *> list3;
2623 list3 << child1 << child4 << child2 << child3;
2624 QVERIFY(parent->children() == list3);
2626 foreach (UpdateWidget *child, allChildren) {
2627 int expectedPaintEvents = 0;
2628 int expectedZOrderChangeEvents = child == child3 ? 1 : 0;
2629 QTRY_COMPARE(child->numPaintEvents, expectedPaintEvents);
2630 QCOMPARE(child->numZOrderChangeEvents, expectedZOrderChangeEvents);
2635 // Cocoa has no Z-Order for views, we hack it, but it results in paint events.
2637 void tst_QWidget::lower()
2639 QWidget *parent = new QWidget(0);
2640 QList<UpdateWidget *> allChildren;
2642 UpdateWidget *child1 = new UpdateWidget(parent);
2643 child1->setAutoFillBackground(true);
2644 allChildren.append(child1);
2646 UpdateWidget *child2 = new UpdateWidget(parent);
2647 child2->setAutoFillBackground(true);
2648 allChildren.append(child2);
2650 UpdateWidget *child3 = new UpdateWidget(parent);
2651 child3->setAutoFillBackground(true);
2652 allChildren.append(child3);
2654 UpdateWidget *child4 = new UpdateWidget(parent);
2655 child4->setAutoFillBackground(true);
2656 allChildren.append(child4);
2659 QTest::qWaitForWindowShown(parent);
2662 QList<QObject *> list1;
2663 list1 << child1 << child2 << child3 << child4;
2664 QVERIFY(parent->children() == list1);
2665 QCOMPARE(allChildren.count(), list1.count());
2667 foreach (UpdateWidget *child, allChildren) {
2668 int expectedPaintEvents = child == child4 ? 1 : 0;
2669 if (expectedPaintEvents == 0) {
2670 QVERIFY(child->numPaintEvents == 0);
2672 // show() issues multiple paint events on some window managers
2673 QTRY_VERIFY(child->numPaintEvents >= expectedPaintEvents);
2675 QCOMPARE(child->numZOrderChangeEvents, 0);
2679 for (int i = 0; i < 5; ++i)
2684 foreach (UpdateWidget *child, allChildren) {
2685 int expectedPaintEvents = child == child3 ? 1 : 0;
2686 int expectedZOrderChangeEvents = child == child4 ? 1 : 0;
2687 QTRY_COMPARE(child->numZOrderChangeEvents, expectedZOrderChangeEvents);
2688 QTRY_COMPARE(child->numPaintEvents, expectedPaintEvents);
2692 QList<QObject *> list2;
2693 list2 << child4 << child1 << child2 << child3;
2694 QVERIFY(parent->children() == list2);
2700 // Cocoa has no Z-Order for views, we hack it, but it results in paint events.
2702 void tst_QWidget::stackUnder()
2705 QWidget *parent = new QWidget(0);
2706 QList<UpdateWidget *> allChildren;
2708 UpdateWidget *child1 = new UpdateWidget(parent);
2709 child1->setAutoFillBackground(true);
2710 allChildren.append(child1);
2712 UpdateWidget *child2 = new UpdateWidget(parent);
2713 child2->setAutoFillBackground(true);
2714 allChildren.append(child2);
2716 UpdateWidget *child3 = new UpdateWidget(parent);
2717 child3->setAutoFillBackground(true);
2718 allChildren.append(child3);
2720 UpdateWidget *child4 = new UpdateWidget(parent);
2721 child4->setAutoFillBackground(true);
2722 allChildren.append(child4);
2725 QTest::qWaitForWindowShown(parent);
2727 QList<QObject *> list1;
2728 list1 << child1 << child2 << child3 << child4;
2729 QVERIFY(parent->children() == list1);
2731 foreach (UpdateWidget *child, allChildren) {
2732 int expectedPaintEvents = child == child4 ? 1 : 0;
2733 #if defined(Q_OS_WIN) || defined(Q_OS_MAC)
2734 if (expectedPaintEvents == 1 && child->numPaintEvents == 2)
2735 QEXPECT_FAIL(0, "Mac and Windows issues double repaints for Z-Order change", Continue);
2737 QTRY_COMPARE(child->numPaintEvents, expectedPaintEvents);
2738 QCOMPARE(child->numZOrderChangeEvents, 0);
2742 for (int i = 0; i < 5; ++i)
2743 child4->stackUnder(child2);
2746 QList<QObject *> list2;
2747 list2 << child1 << child4 << child2 << child3;
2748 QVERIFY(parent->children() == list2);
2750 foreach (UpdateWidget *child, allChildren) {
2751 int expectedPaintEvents = child == child3 ? 1 : 0;
2752 int expectedZOrderChangeEvents = child == child4 ? 1 : 0;
2753 QTRY_COMPARE(child->numPaintEvents, expectedPaintEvents);
2754 QTRY_COMPARE(child->numZOrderChangeEvents, expectedZOrderChangeEvents);
2758 for (int i = 0; i < 5; ++i)
2759 child1->stackUnder(child3);
2762 QList<QObject *> list3;
2763 list3 << child4 << child2 << child1 << child3;
2764 QVERIFY(parent->children() == list3);
2766 foreach (UpdateWidget *child, allChildren) {
2767 int expectedZOrderChangeEvents = child == child1 ? 1 : 0;
2768 if (child == child3) {
2770 qApp->processEvents();
2773 QEXPECT_FAIL(0, "See QTBUG-493", Continue);
2775 QCOMPARE(child->numPaintEvents, 0);
2777 QCOMPARE(child->numPaintEvents, 0);
2779 QTRY_COMPARE(child->numZOrderChangeEvents, expectedZOrderChangeEvents);
2787 void drawPolygon(QPaintDevice *dev, int w, int h)
2790 p.fillRect(0, 0, w, h, Qt::white);
2793 a << QPoint(0, 0) << QPoint(w/2, h/2) << QPoint(w, 0)
2794 << QPoint(w/2, h) << QPoint(0, 0);
2796 p.setPen(QPen(Qt::black, 1));
2797 p.setBrush(Qt::DiagCrossPattern);
2801 class ContentsPropagationWidget : public QWidget
2805 ContentsPropagationWidget(QWidget *parent = 0) : QWidget(parent)
2807 QWidget *child = this;
2808 for (int i=0; i<32; ++i) {
2809 child = new QWidget(child);
2810 child->setGeometry(i, i, 400 - i*2, 400 - i*2);
2814 void setContentsPropagation(bool enable) {
2815 foreach (QObject *child, children())
2816 qobject_cast<QWidget *>(child)->setAutoFillBackground(!enable);
2820 void paintEvent(QPaintEvent *)
2822 int w = width(), h = height();
2823 drawPolygon(this, w, h);
2826 QSize sizeHint() const { return QSize(500, 500); }
2829 void tst_QWidget::testContentsPropagation()
2831 ContentsPropagationWidget widget;
2832 widget.setFixedSize(500, 500);
2833 widget.setContentsPropagation(false);
2834 QPixmap widgetSnapshot = widget.grab(QRect(QPoint(0, 0), QSize(-1, -1)));
2836 QPixmap correct(500, 500);
2837 drawPolygon(&correct, 500, 500);
2838 //correct.save("correct.png", "PNG");
2840 //widgetSnapshot.save("snap1.png", "PNG");
2841 QVERIFY(widgetSnapshot.toImage() != correct.toImage());
2843 widget.setContentsPropagation(true);
2844 widgetSnapshot = widgetSnapshot = widget.grab(QRect(QPoint(0, 0), QSize(-1, -1)));
2845 //widgetSnapshot.save("snap2.png", "PNG");
2847 QCOMPARE(widgetSnapshot, correct);
2851 Test that saving and restoring window geometry with
2852 saveGeometry() and restoreGeometry() works.
2855 void tst_QWidget::saveRestoreGeometry()
2857 const QPoint position(100, 100);
2858 const QSize size(200, 200);
2860 QByteArray savedGeometry;
2864 widget.move(position);
2865 widget.resize(size);
2867 QTest::qWaitForWindowShown(&widget);
2868 QApplication::processEvents();
2870 QTRY_COMPARE(widget.pos(), position);
2871 QCOMPARE(widget.size(), size);
2872 savedGeometry = widget.saveGeometry();
2878 const QByteArray empty;
2879 const QByteArray one("a");
2880 const QByteArray two("ab");
2881 const QByteArray three("abc");
2882 const QByteArray four("abca");
2883 const QByteArray garbage("abcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabc");
2885 QVERIFY(widget.restoreGeometry(empty) == false);
2886 QVERIFY(widget.restoreGeometry(one) == false);
2887 QVERIFY(widget.restoreGeometry(two) == false);
2888 QVERIFY(widget.restoreGeometry(three) == false);
2889 QVERIFY(widget.restoreGeometry(four) == false);
2890 QVERIFY(widget.restoreGeometry(garbage) == false);
2892 QVERIFY(widget.restoreGeometry(savedGeometry));
2894 QTest::qWaitForWindowShown(&widget);
2895 QApplication::processEvents();
2897 QTRY_COMPARE(widget.pos(), position);
2898 QCOMPARE(widget.size(), size);
2900 QCOMPARE(widget.pos(), position);
2901 QCOMPARE(widget.size(), size);
2906 widget.move(position);
2907 widget.resize(size);
2909 QTest::qWaitForWindowShown(&widget);
2911 QTRY_COMPARE(widget.geometry().size(), size);
2915 //Restore from Full screen
2916 savedGeometry = widget.saveGeometry();
2917 geom = widget.geometry();
2918 widget.setWindowState(widget.windowState() | Qt::WindowFullScreen);
2919 QTRY_VERIFY((widget.windowState() & Qt::WindowFullScreen));
2921 QVERIFY(widget.restoreGeometry(savedGeometry));
2923 QTRY_VERIFY(!(widget.windowState() & Qt::WindowFullScreen));
2924 QTRY_COMPARE(widget.geometry(), geom);
2926 //Restore to full screen
2927 widget.setWindowState(widget.windowState() | Qt::WindowFullScreen);
2929 QTRY_VERIFY((widget.windowState() & Qt::WindowFullScreen));
2931 savedGeometry = widget.saveGeometry();
2932 geom = widget.geometry();
2933 widget.setWindowState(widget.windowState() ^ Qt::WindowFullScreen);
2935 QTRY_VERIFY(!(widget.windowState() & Qt::WindowFullScreen));
2937 QVERIFY(widget.restoreGeometry(savedGeometry));
2939 QTRY_VERIFY((widget.windowState() & Qt::WindowFullScreen));
2940 QTRY_COMPARE(widget.geometry(), geom);
2941 QVERIFY((widget.windowState() & Qt::WindowFullScreen));
2942 widget.setWindowState(widget.windowState() ^ Qt::WindowFullScreen);
2944 QTRY_VERIFY(!(widget.windowState() & Qt::WindowFullScreen));
2947 //Restore from Maximised
2948 widget.move(position);
2949 widget.resize(size);
2951 QTRY_COMPARE(widget.size(), size);
2953 savedGeometry = widget.saveGeometry();
2954 geom = widget.geometry();
2955 widget.setWindowState(widget.windowState() | Qt::WindowMaximized);
2957 QTRY_VERIFY((widget.windowState() & Qt::WindowMaximized));
2958 QTRY_VERIFY(widget.geometry() != geom);
2960 QVERIFY(widget.restoreGeometry(savedGeometry));
2962 QTRY_COMPARE(widget.geometry(), geom);
2964 QVERIFY(!(widget.windowState() & Qt::WindowMaximized));
2966 //Restore to maximised
2967 widget.setWindowState(widget.windowState() | Qt::WindowMaximized);
2969 QTRY_VERIFY((widget.windowState() & Qt::WindowMaximized));
2971 geom = widget.geometry();
2972 savedGeometry = widget.saveGeometry();
2973 widget.setWindowState(widget.windowState() ^ Qt::WindowMaximized);
2975 QTRY_VERIFY(!(widget.windowState() & Qt::WindowMaximized));
2977 QVERIFY(widget.restoreGeometry(savedGeometry));
2979 QTRY_VERIFY((widget.windowState() & Qt::WindowMaximized));
2980 QTRY_COMPARE(widget.geometry(), geom);
2984 void tst_QWidget::restoreVersion1Geometry_data()
2986 QTest::addColumn<QString>("fileName");
2987 QTest::addColumn<uint>("expectedWindowState");
2988 QTest::addColumn<QPoint>("expectedPosition");
2989 QTest::addColumn<QSize>("expectedSize");
2990 QTest::addColumn<QRect>("expectedNormalGeometry");
2991 const QPoint position(100, 100);
2992 const QSize size(200, 200);
2993 const QRect normalGeometry(102, 124, 200, 200);
2995 QTest::newRow("geometry.dat") << ":geometry.dat" << uint(Qt::WindowNoState) << position << size << normalGeometry;
2996 QTest::newRow("geometry-maximized.dat") << ":geometry-maximized.dat" << uint(Qt::WindowMaximized) << position << size << normalGeometry;
2997 QTest::newRow("geometry-fullscreen.dat") << ":geometry-fullscreen.dat" << uint(Qt::WindowFullScreen) << position << size << normalGeometry;
3001 Test that the current version of restoreGeometry() can restore geometry
3002 saved width saveGeometry() version 1.0.
3004 void tst_QWidget::restoreVersion1Geometry()
3006 QFETCH(QString, fileName);
3007 QFETCH(uint, expectedWindowState);
3008 QFETCH(QPoint, expectedPosition);
3009 QFETCH(QSize, expectedSize);
3010 QFETCH(QRect, expectedNormalGeometry);
3012 // WindowActive is uninteresting for this test
3013 const uint WindowStateMask = Qt::WindowFullScreen | Qt::WindowMaximized | Qt::WindowMinimized;
3016 QVERIFY(f.exists());
3017 f.open(QIODevice::ReadOnly);
3018 const QByteArray savedGeometry = f.readAll();
3019 QCOMPARE(savedGeometry.count(), 46);
3024 QVERIFY(widget.restoreGeometry(savedGeometry));
3026 QCOMPARE(uint(widget.windowState() & WindowStateMask), expectedWindowState);
3027 if (expectedWindowState == Qt::WindowNoState) {
3028 QCOMPARE(widget.pos(), expectedPosition);
3029 QCOMPARE(widget.size(), expectedSize);
3032 QTest::qWaitForWindowShown(&widget);
3035 if (expectedWindowState == Qt::WindowNoState) {
3036 QTRY_COMPARE(widget.pos(), expectedPosition);
3037 QTRY_COMPARE(widget.size(), expectedSize);
3040 widget.showNormal();
3043 if (expectedWindowState != Qt::WindowNoState) {
3044 // restoring from maximized or fullscreen, we can only restore to the normal geometry
3045 QTRY_COMPARE(widget.geometry(), expectedNormalGeometry);
3047 QTRY_COMPARE(widget.pos(), expectedPosition);
3048 QTRY_COMPARE(widget.size(), expectedSize);
3052 // Code for saving a new geometry*.dat files
3054 QWidget widgetToSave;
3055 widgetToSave.move(expectedPosition);
3056 widgetToSave.resize(expectedSize);
3057 widgetToSave.show();
3058 QTest::qWaitForWindowShown(widget.windowHandle());
3059 QTest::qWait(500); // stabilize
3060 widgetToSave.setWindowState(Qt::WindowStates(expectedWindowState));
3061 QTest::qWait(500); // stabilize
3063 QByteArray geometryToSave = widgetToSave.saveGeometry();
3065 // Code for saving a new geometry.dat file.
3066 f.setFileName(fileName.mid(1));
3067 QVERIFY(f.open(QIODevice::WriteOnly)); // did you forget to 'p4 edit *.dat'? :)
3068 f.write(geometryToSave);
3074 void tst_QWidget::widgetAt()
3078 QWidget *w1 = new QWidget(0, Qt::X11BypassWindowManagerHint);
3079 w1->setGeometry(0,0,150,150);
3080 w1->setObjectName("w1");
3082 QWidget *w2 = new QWidget(0, Qt::X11BypassWindowManagerHint | Qt::FramelessWindowHint);
3083 w2->setGeometry(50,50,100,100);
3084 w2->setObjectName("w2");
3086 QTest::qWaitForWindowShown(w1);
3087 qApp->processEvents();
3089 QTRY_VERIFY((wr = QApplication::widgetAt(100, 100)));
3090 QCOMPARE(wr->objectName(), QString("w1"));
3093 QTest::qWaitForWindowShown(w2);
3094 qApp->processEvents();
3095 qApp->processEvents();
3096 qApp->processEvents();
3097 QTRY_VERIFY((wr = QApplication::widgetAt(100, 100)));
3098 QCOMPARE(wr->objectName(), QString("w2"));
3101 qApp->processEvents();
3102 QTRY_VERIFY((wr = QApplication::widgetAt(100, 100)) && wr->objectName() == QString("w1"));
3105 qApp->processEvents();
3106 QTRY_VERIFY((wr = QApplication::widgetAt(100, 100)) && wr->objectName() == QString("w2"));
3108 QWidget *w3 = new QWidget(w2);
3109 w3->setGeometry(10,10,50,50);
3110 w3->setObjectName("w3");
3112 qApp->processEvents();
3113 QTRY_VERIFY((wr = QApplication::widgetAt(100,100)) && wr->objectName() == QString("w3"));
3115 w3->setAttribute(Qt::WA_TransparentForMouseEvents);
3116 qApp->processEvents();
3117 QTRY_VERIFY((wr = QApplication::widgetAt(100, 100)) && wr->objectName() == QString("w2"));
3119 QRegion rgn = QRect(QPoint(0,0), w2->size());
3120 QPoint point = w2->mapFromGlobal(QPoint(100,100));
3121 rgn -= QRect(point, QSize(1,1));
3123 qApp->processEvents();
3125 #if defined(Q_OS_WINCE)
3126 QEXPECT_FAIL("", "Windows CE does only support rectangular regions", Continue); //See also task 147191
3128 if (!QGuiApplication::platformName().compare(QLatin1String("cocoa"), Qt::CaseInsensitive))
3129 QEXPECT_FAIL("", "Window mask not implemented on Mac QTBUG-22326", Continue);
3131 QTRY_VERIFY((wr = QApplication::widgetAt(100,100)));
3132 QTRY_COMPARE(wr->objectName(), w1->objectName());
3133 QTRY_VERIFY((wr = QApplication::widgetAt(101,101)));
3134 QTRY_COMPARE(wr->objectName(), w2->objectName());
3136 QBitmap bitmap(w2->size());
3137 QPainter p(&bitmap);
3138 p.fillRect(bitmap.rect(), Qt::color1);
3139 p.setPen(Qt::color0);
3140 p.drawPoint(w2->mapFromGlobal(QPoint(100,100)));
3142 w2->setMask(bitmap);
3143 qApp->processEvents();
3145 #if defined(Q_OS_WINCE)
3146 QEXPECT_FAIL("", "Windows CE does only support rectangular regions", Continue); //See also task 147191
3148 if (!QGuiApplication::platformName().compare(QLatin1String("cocoa"), Qt::CaseInsensitive))
3149 QEXPECT_FAIL("", "Window mask not implemented on Mac QTBUG-22326", Continue);
3150 QTRY_VERIFY(QApplication::widgetAt(100,100) == w1);
3151 QTRY_VERIFY(QApplication::widgetAt(101,101) == w2);
3157 void tst_QWidget::task110173()
3161 QPushButton *pb1 = new QPushButton("click", &w);
3162 pb1->setFocusPolicy(Qt::ClickFocus);
3163 pb1->move(100, 100);
3165 QPushButton *pb2 = new QPushButton("push", &w);
3166 pb2->setFocusPolicy(Qt::ClickFocus);
3167 pb2->move(300, 300);
3169 QTest::keyClick( &w, Qt::Key_Tab );
3171 QTest::qWaitForWindowShown(&w);
3175 class Widget : public QWidget
3178 Widget() : deleteThis(false) { setFocusPolicy(Qt::StrongFocus); }
3179 void actionEvent(QActionEvent *) { if (deleteThis) delete this; }
3180 void changeEvent(QEvent *) { if (deleteThis) delete this; }
3181 void closeEvent(QCloseEvent *) { if (deleteThis) delete this; }
3182 void hideEvent(QHideEvent *) { if (deleteThis) delete this; }
3183 void focusOutEvent(QFocusEvent *) { if (deleteThis) delete this; }
3184 void keyPressEvent(QKeyEvent *) { if (deleteThis) delete this; }
3185 void keyReleaseEvent(QKeyEvent *) { if (deleteThis) delete this; }
3186 void mouseDoubleClickEvent(QMouseEvent *) { if (deleteThis) delete this; }
3187 void mousePressEvent(QMouseEvent *) { if (deleteThis) delete this; }
3188 void mouseReleaseEvent(QMouseEvent *) { if (deleteThis) delete this; }
3189 void mouseMoveEvent(QMouseEvent *) { if (deleteThis) delete this; }
3194 void tst_QWidget::testDeletionInEventHandlers()
3197 QPointer<Widget> w = new Widget;
3198 w->deleteThis = true;
3203 // focusOut (crashes)
3207 //QVERIFY(qApp->focusWidget() == w);
3208 //w->deleteThis = true;
3215 w->deleteThis = true;
3216 QTest::keyPress(w, Qt::Key_A);
3223 w->deleteThis = true;
3224 QTest::keyRelease(w, Qt::Key_A);
3231 w->deleteThis = true;
3232 QTest::mousePress(w, Qt::LeftButton);
3239 w->deleteThis = true;
3240 QTest::mouseRelease(w, Qt::LeftButton);
3244 // mouse double click
3247 w->deleteThis = true;
3248 QTest::mouseDClick(w, Qt::LeftButton);
3252 // hide event (crashes)
3255 //w->deleteThis = true;
3261 w->deleteThis = true;
3262 w->addAction(new QAction(w));
3269 w->deleteThis = true;
3270 w->setMouseTracking(true);
3275 w->setMouseTracking(true);
3277 w->deleteThis = true;
3278 QMouseEvent me(QEvent::MouseMove, QPoint(0, 0), Qt::NoButton, Qt::NoButton, Qt::NoModifier);
3279 QApplication::sendEvent(w, &me);
3285 void tst_QWidget::sheetOpacity()
3288 QWidget sheet(&tmpWindow, Qt::Sheet);
3291 QCOMPARE(int(sheet.windowOpacity() * 255), 242); // 95%
3292 sheet.setParent(0, Qt::Dialog);
3293 QCOMPARE(int(sheet.windowOpacity() * 255), 255);
3296 class MaskedPainter : public QWidget
3302 : mask(20, 20, 50, 50)
3307 void paintEvent(QPaintEvent *)
3310 p.fillRect(mask, QColor(Qt::red));
3315 Verifies that the entire area inside the mask is painted red.
3317 bool verifyWidgetMask(QWidget *widget, QRect mask)
3319 const QImage image = widget->grab(QRect(QPoint(0, 0), widget->size())).toImage();
3321 const QImage masked = image.copy(mask);
3323 red.fill(QColor(Qt::red).rgb());
3325 return (masked == red);
3328 void tst_QWidget::setMask()
3330 testWidget->hide(); // get this out of the way.
3337 QVERIFY(verifyWidgetMask(&w, w.mask));
3342 w.setWindowFlags(w.windowFlags() | Qt::FramelessWindowHint);
3345 QRect mask = w.mask;
3347 QVERIFY(verifyWidgetMask(&w, mask));
3352 class StaticWidget : public QWidget
3358 QRegion paintedRegion;
3360 StaticWidget(QWidget *parent = 0)
3363 setAttribute(Qt::WA_StaticContents);
3364 setAttribute(Qt::WA_OpaquePaintEvent);
3365 setPalette(Qt::red); // Make sure we have an opaque palette.
3366 setAutoFillBackground(true);
3367 gotPaintEvent = false;
3370 void paintEvent(QPaintEvent *e)
3372 paintedRegion += e->region();
3373 gotPaintEvent = true;
3374 // qDebug() << "paint" << e->region();
3375 // Look for a full update, set partial to false if found.
3376 foreach(QRect r, e->region().rects()) {
3377 partial = (r != rect());
3378 if (partial == false)
3385 Test that widget resizes and moves can be done with minimal repaints when WA_StaticContents
3386 and WA_OpaquePaintEvent is set. Test is mac-only for now.
3388 void tst_QWidget::optimizedResizeMove()
3391 parent.resize(400, 400);
3393 StaticWidget staticWidget(&parent);
3394 staticWidget.gotPaintEvent = false;
3395 staticWidget.move(150, 150);
3396 staticWidget.resize(150, 150);
3398 QTest::qWaitForWindowShown(&parent);
3400 QTRY_COMPARE(staticWidget.gotPaintEvent, true);
3402 staticWidget.gotPaintEvent = false;
3403 staticWidget.move(staticWidget.pos() + QPoint(10, 10));
3405 QCOMPARE(staticWidget.gotPaintEvent, false);
3407 staticWidget.gotPaintEvent = false;
3408 staticWidget.move(staticWidget.pos() + QPoint(-10, -10));
3410 QCOMPARE(staticWidget.gotPaintEvent, false);
3412 staticWidget.gotPaintEvent = false;
3413 staticWidget.move(staticWidget.pos() + QPoint(-10, 10));
3415 QCOMPARE(staticWidget.gotPaintEvent, false);
3417 staticWidget.gotPaintEvent = false;
3418 staticWidget.resize(staticWidget.size() + QSize(10, 10));
3420 QCOMPARE(staticWidget.gotPaintEvent, true);
3421 QCOMPARE(staticWidget.partial, true);
3423 staticWidget.gotPaintEvent = false;
3424 staticWidget.resize(staticWidget.size() + QSize(-10, -10));
3426 QCOMPARE(staticWidget.gotPaintEvent, false);
3428 staticWidget.gotPaintEvent = false;
3429 staticWidget.resize(staticWidget.size() + QSize(10, -10));
3431 QCOMPARE(staticWidget.gotPaintEvent, true);
3432 QCOMPARE(staticWidget.partial, true);
3434 staticWidget.gotPaintEvent = false;
3435 staticWidget.move(staticWidget.pos() + QPoint(10, 10));
3436 staticWidget.resize(staticWidget.size() + QSize(-10, -10));
3438 QCOMPARE(staticWidget.gotPaintEvent, false);
3440 staticWidget.gotPaintEvent = false;
3441 staticWidget.move(staticWidget.pos() + QPoint(10, 10));
3442 staticWidget.resize(staticWidget.size() + QSize(10, 10));
3444 QCOMPARE(staticWidget.gotPaintEvent, true);
3445 QCOMPARE(staticWidget.partial, true);
3447 staticWidget.gotPaintEvent = false;
3448 staticWidget.move(staticWidget.pos() + QPoint(-10, -10));
3449 staticWidget.resize(staticWidget.size() + QSize(-10, -10));
3451 QCOMPARE(staticWidget.gotPaintEvent, false);
3453 staticWidget.setAttribute(Qt::WA_StaticContents, false);
3454 staticWidget.gotPaintEvent = false;
3455 staticWidget.move(staticWidget.pos() + QPoint(-10, -10));
3456 staticWidget.resize(staticWidget.size() + QSize(-10, -10));
3458 QCOMPARE(staticWidget.gotPaintEvent, true);
3459 QCOMPARE(staticWidget.partial, false);
3460 staticWidget.setAttribute(Qt::WA_StaticContents, true);
3462 staticWidget.setAttribute(Qt::WA_StaticContents, false);
3463 staticWidget.gotPaintEvent = false;
3464 staticWidget.move(staticWidget.pos() + QPoint(10, 10));
3466 QCOMPARE(staticWidget.gotPaintEvent, false);
3467 staticWidget.setAttribute(Qt::WA_StaticContents, true);
3470 void tst_QWidget::optimizedResize_topLevel()
3472 #if defined(Q_OS_MAC)
3473 QSKIP("We do not yet have static contents support for *top-levels* on this platform");
3476 StaticWidget topLevel;
3477 topLevel.gotPaintEvent = false;
3479 QTest::qWaitForWindowShown(&topLevel);
3481 QTRY_COMPARE(topLevel.gotPaintEvent, true);
3483 topLevel.gotPaintEvent = false;
3484 topLevel.partial = false;
3485 topLevel.paintedRegion = QRegion();
3488 topLevel.resize(topLevel.size() + QSize(10, 10));
3490 // Static contents does not work when programmatically resizing
3491 // top-levels with QWidget::resize. We do some funky stuff in
3492 // setGeometry_sys. However, resizing it with the mouse or with
3493 // a native function call works (it basically has to go through
3494 // WM_RESIZE in QApplication). This is a corner case, though.
3496 const QRect frame = topLevel.frameGeometry();
3497 MoveWindow(winHandleOf(&topLevel), frame.x(), frame.y(),
3498 frame.width() + 10, frame.height() + 10,
3504 // Expected update region: New rect - old rect.
3505 QRegion expectedUpdateRegion(topLevel.rect());
3506 expectedUpdateRegion -= QRect(QPoint(), topLevel.size() - QSize(10, 10));
3508 QTRY_COMPARE(topLevel.gotPaintEvent, true);
3509 QCOMPARE(topLevel.partial, true);
3510 QCOMPARE(topLevel.paintedRegion, expectedUpdateRegion);
3513 class SiblingDeleter : public QWidget
3516 inline SiblingDeleter(QWidget *sibling, QWidget *parent)
3517 : QWidget(parent), sibling(sibling) {}
3518 inline virtual ~SiblingDeleter() { delete sibling; }
3521 QPointer<QWidget> sibling;
3525 void tst_QWidget::childDeletesItsSibling()
3527 QWidget *commonParent = new QWidget(0);
3528 QPointer<QWidget> child = new QWidget(0);
3529 QPointer<QWidget> siblingDeleter = new SiblingDeleter(child, commonParent);
3530 child->setParent(commonParent);
3531 delete commonParent; // don't crash
3533 QVERIFY(!siblingDeleter);
3537 void tst_QWidget::setMinimumSize()
3540 QSize defaultSize = w.size();
3542 w.setMinimumSize(defaultSize + QSize(100, 100));
3543 QCOMPARE(w.size(), defaultSize + QSize(100, 100));
3544 QVERIFY(!w.testAttribute(Qt::WA_Resized));
3546 w.setMinimumSize(defaultSize + QSize(50, 50));
3547 QCOMPARE(w.size(), defaultSize + QSize(100, 100));
3548 QVERIFY(!w.testAttribute(Qt::WA_Resized));
3550 w.setMinimumSize(defaultSize + QSize(200, 200));
3551 QCOMPARE(w.size(), defaultSize + QSize(200, 200));
3552 QVERIFY(!w.testAttribute(Qt::WA_Resized));
3554 // Setting a minimum size larger than the desktop does not work on WinCE,
3555 // so skip this part of the test.
3557 QSize nonDefaultSize = defaultSize + QSize(5,5);
3558 w.setMinimumSize(nonDefaultSize);
3561 QVERIFY(w.height() >= nonDefaultSize.height());
3562 QVERIFY(w.width() >= nonDefaultSize.width());
3566 void tst_QWidget::setMaximumSize()
3569 QSize defaultSize = w.size();
3571 w.setMinimumSize(defaultSize + QSize(100, 100));
3572 QCOMPARE(w.size(), defaultSize + QSize(100, 100));
3573 QVERIFY(!w.testAttribute(Qt::WA_Resized));
3574 w.setMinimumSize(defaultSize);
3576 w.setMaximumSize(defaultSize + QSize(200, 200));
3577 QCOMPARE(w.size(), defaultSize + QSize(100, 100));
3578 QVERIFY(!w.testAttribute(Qt::WA_Resized));
3580 w.setMaximumSize(defaultSize + QSize(50, 50));
3581 QCOMPARE(w.size(), defaultSize + QSize(50, 50));
3582 QVERIFY(!w.testAttribute(Qt::WA_Resized));
3585 void tst_QWidget::setFixedSize()
3588 QSize defaultSize = w.size();
3590 w.setFixedSize(defaultSize + QSize(100, 100));
3591 QCOMPARE(w.size(), defaultSize + QSize(100, 100));
3592 QVERIFY(w.testAttribute(Qt::WA_Resized));
3594 w.setFixedSize(defaultSize + QSize(200, 200));
3596 QCOMPARE(w.minimumSize(), defaultSize + QSize(200,200));
3597 QCOMPARE(w.maximumSize(), defaultSize + QSize(200,200));
3598 QCOMPARE(w.size(), defaultSize + QSize(200, 200));
3599 QVERIFY(w.testAttribute(Qt::WA_Resized));
3601 w.setFixedSize(defaultSize + QSize(50, 50));
3602 QCOMPARE(w.size(), defaultSize + QSize(50, 50));
3603 QVERIFY(w.testAttribute(Qt::WA_Resized));
3605 w.setAttribute(Qt::WA_Resized, false);
3606 w.setFixedSize(defaultSize + QSize(50, 50));
3607 QVERIFY(!w.testAttribute(Qt::WA_Resized));
3609 w.setFixedSize(defaultSize + QSize(150, 150));
3612 QVERIFY(w.size() == defaultSize + QSize(150,150));
3615 void tst_QWidget::ensureCreated()
3619 WId widgetWinId = widget.winId();
3620 Q_UNUSED(widgetWinId);
3621 QVERIFY(widget.testAttribute(Qt::WA_WState_Created));
3627 QDialog dialog(&window);
3628 dialog.setWindowModality(Qt::NonModal);
3630 WId dialogWinId = dialog.winId();
3631 Q_UNUSED(dialogWinId);
3632 QVERIFY(dialog.testAttribute(Qt::WA_WState_Created));
3633 QVERIFY(window.testAttribute(Qt::WA_WState_Created));
3639 QDialog dialog(&window);
3640 dialog.setWindowModality(Qt::WindowModal);
3642 WId dialogWinId = dialog.winId();
3643 Q_UNUSED(dialogWinId);
3644 QVERIFY(dialog.testAttribute(Qt::WA_WState_Created));
3645 QVERIFY(window.testAttribute(Qt::WA_WState_Created));
3651 QDialog dialog(&window);
3652 dialog.setWindowModality(Qt::ApplicationModal);
3654 WId dialogWinId = dialog.winId();
3655 Q_UNUSED(dialogWinId);
3656 QVERIFY(dialog.testAttribute(Qt::WA_WState_Created));
3657 QVERIFY(window.testAttribute(Qt::WA_WState_Created));
3661 class WinIdChangeWidget : public QWidget {
3663 WinIdChangeWidget(QWidget *p = 0)
3669 bool event(QEvent *e)
3671 if (e->type() == QEvent::WinIdChange) {
3672 m_winIdList.append(internalWinId());
3675 return QWidget::event(e);
3678 QList<WId> m_winIdList;
3679 int winIdChangeEventCount() const { return m_winIdList.count(); }
3682 void tst_QWidget::winIdChangeEvent()
3685 // Transforming an alien widget into a native widget
3686 WinIdChangeWidget widget;
3687 const WId winIdBefore = widget.internalWinId();
3688 const WId winIdAfter = widget.winId();
3689 QVERIFY(winIdBefore != winIdAfter);
3690 QCOMPARE(widget.winIdChangeEventCount(), 1);
3694 // Changing parent of a native widget
3695 // Should cause winId of child to change, on all platforms
3696 QWidget parent1, parent2;
3697 WinIdChangeWidget child(&parent1);
3698 const WId winIdBefore = child.winId();
3699 QCOMPARE(child.winIdChangeEventCount(), 1);
3700 child.setParent(&parent2);
3701 const WId winIdAfter = child.internalWinId();
3702 QVERIFY(winIdBefore != winIdAfter);
3703 QCOMPARE(child.winIdChangeEventCount(), 3);
3704 // winId is set to zero during reparenting
3705 QVERIFY(0 == child.m_winIdList[1]);
3709 // Changing grandparent of a native widget
3710 QWidget grandparent1, grandparent2;
3711 QWidget parent(&grandparent1);
3712 WinIdChangeWidget child(&parent);
3713 const WId winIdBefore = child.winId();
3714 QCOMPARE(child.winIdChangeEventCount(), 1);
3715 parent.setParent(&grandparent2);
3716 const WId winIdAfter = child.internalWinId();
3717 QCOMPARE(winIdBefore, winIdAfter);
3718 QCOMPARE(child.winIdChangeEventCount(), 1);
3722 // Changing parent of an alien widget
3723 QWidget parent1, parent2;
3724 WinIdChangeWidget child(&parent1);
3725 const WId winIdBefore = child.internalWinId();
3726 child.setParent(&parent2);
3727 const WId winIdAfter = child.internalWinId();
3728 QCOMPARE(winIdBefore, winIdAfter);
3729 QCOMPARE(child.winIdChangeEventCount(), 0);
3733 // Making native child widget into a top-level window
3735 WinIdChangeWidget child(&parent);
3737 const WId winIdBefore = child.internalWinId();
3738 QCOMPARE(child.winIdChangeEventCount(), 1);
3739 const Qt::WindowFlags flags = child.windowFlags();
3740 child.setWindowFlags(flags | Qt::Window);
3741 const WId winIdAfter = child.internalWinId();
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 void tst_QWidget::persistentWinId()
3751 QWidget *parent = new QWidget;
3752 QWidget *w1 = new QWidget;
3753 QWidget *w2 = new QWidget;
3754 QWidget *w3 = new QWidget;
3755 w1->setParent(parent);
3759 WId winId1 = w1->winId();
3760 WId winId2 = w2->winId();
3761 WId winId3 = w3->winId();
3763 // reparenting should change the winId of the widget being reparented, but not of its children
3765 QVERIFY(w1->winId() != winId1);
3766 winId1 = w1->winId();
3767 QCOMPARE(w2->winId(), winId2);
3768 QCOMPARE(w3->winId(), winId3);
3770 w1->setParent(parent);
3771 QVERIFY(w1->winId() != winId1);
3772 winId1 = w1->winId();
3773 QCOMPARE(w2->winId(), winId2);
3774 QCOMPARE(w3->winId(), winId3);
3777 QVERIFY(w2->winId() != winId2);
3778 winId2 = w2->winId();
3779 QCOMPARE(w3->winId(), winId3);
3781 w2->setParent(parent);
3782 QVERIFY(w2->winId() != winId2);
3783 winId2 = w2->winId();
3784 QCOMPARE(w3->winId(), winId3);
3787 QVERIFY(w2->winId() != winId2);
3788 winId2 = w2->winId();
3789 QCOMPARE(w3->winId(), winId3);
3792 QVERIFY(w3->winId() != winId3);
3793 winId3 = w3->winId();
3796 QVERIFY(w3->winId() != winId3);
3797 winId3 = w3->winId();
3800 QVERIFY(w3->winId() != winId3);
3801 winId3 = w3->winId();
3806 void tst_QWidget::showNativeChild()
3809 topLevel.setGeometry(0, 0, 100, 100);
3810 QWidget child(&topLevel);
3813 QTest::qWaitForWindowShown(&topLevel);
3816 class ShowHideEventWidget : public QWidget
3819 int numberOfShowEvents, numberOfHideEvents;
3821 ShowHideEventWidget(QWidget *parent = 0)
3822 : QWidget(parent), numberOfShowEvents(0), numberOfHideEvents(0)
3826 { QWidget::create(); }
3828 void showEvent(QShowEvent *)
3829 { ++numberOfShowEvents; }
3831 void hideEvent(QHideEvent *)
3832 { ++numberOfHideEvents; }
3835 void tst_QWidget::showHideEvent_data()
3837 QTest::addColumn<bool>("show");
3838 QTest::addColumn<bool>("hide");
3839 QTest::addColumn<bool>("create");
3840 QTest::addColumn<int>("expectedShowEvents");
3841 QTest::addColumn<int>("expectedHideEvents");
3843 QTest::newRow("window: only show")
3849 QTest::newRow("window: show/hide")
3855 QTest::newRow("window: show/hide/create")
3861 QTest::newRow("window: hide/create")
3867 QTest::newRow("window: only hide")
3873 QTest::newRow("window: nothing")
3881 void tst_QWidget::showHideEvent()
3885 QFETCH(bool, create);
3886 QFETCH(int, expectedShowEvents);
3887 QFETCH(int, expectedHideEvents);
3889 ShowHideEventWidget widget;
3894 if (create && !widget.testAttribute(Qt::WA_WState_Created))
3897 QCOMPARE(widget.numberOfShowEvents, expectedShowEvents);
3898 QCOMPARE(widget.numberOfHideEvents, expectedHideEvents);
3901 void tst_QWidget::update()
3903 QTest::qWait(10); // Wait for the initStuff to do it's stuff.
3907 w.setGeometry(50, 50, 100, 100);
3909 QTest::qWaitForWindowShown(&w);
3911 QApplication::processEvents();
3912 QApplication::processEvents();
3915 QEXPECT_FAIL(0, "Cocoa compositor says to paint this twice.", Continue);
3917 QTRY_COMPARE(w.numPaintEvents, 1);
3919 QCOMPARE(w.visibleRegion(), QRegion(w.rect()));
3920 QCOMPARE(w.paintedRegion, w.visibleRegion());
3923 UpdateWidget child(&w);
3924 child.setGeometry(10, 10, 80, 80);
3927 QPoint childOffset = child.mapToParent(QPoint());
3929 // widgets are transparent by default, so both should get repaints
3931 QApplication::processEvents();
3932 QApplication::processEvents();
3933 QCOMPARE(child.numPaintEvents, 1);
3934 QCOMPARE(child.visibleRegion(), QRegion(child.rect()));
3935 QCOMPARE(child.paintedRegion, child.visibleRegion());
3936 QCOMPARE(w.numPaintEvents, 1);
3937 QCOMPARE(w.visibleRegion(), QRegion(w.rect()));
3938 QCOMPARE(w.paintedRegion, child.visibleRegion().translated(childOffset));
3944 QApplication::processEvents();
3945 QApplication::processEvents();
3946 QCOMPARE(child.numPaintEvents, 1);
3947 QCOMPARE(child.visibleRegion(), QRegion(child.rect()));
3948 QCOMPARE(child.paintedRegion, child.visibleRegion());
3949 QCOMPARE(w.numPaintEvents, 1);
3950 QCOMPARE(w.visibleRegion(), QRegion(w.rect()));
3951 QCOMPARE(w.paintedRegion, w.visibleRegion());
3954 QPalette opaquePalette = child.palette();
3955 opaquePalette.setColor(child.backgroundRole(), QColor(Qt::red));
3957 // setting an opaque background on the child should prevent paint-events
3958 // for the parent in the child area
3960 child.setPalette(opaquePalette);
3961 child.setAutoFillBackground(true);
3962 QApplication::processEvents();
3968 QApplication::processEvents();
3969 QApplication::processEvents();
3971 QCOMPARE(w.numPaintEvents, 1);
3972 QRegion expectedVisible = QRegion(w.rect())
3973 - child.visibleRegion().translated(childOffset);
3974 QCOMPARE(w.visibleRegion(), expectedVisible);
3975 QCOMPARE(w.paintedRegion, expectedVisible);
3976 QCOMPARE(child.numPaintEvents, 0);
3982 QApplication::processEvents();
3983 QApplication::processEvents();
3985 QCOMPARE(w.numPaintEvents, 0);
3986 QCOMPARE(child.numPaintEvents, 1);
3987 QCOMPARE(child.paintedRegion, child.visibleRegion());
3993 // overlapping sibling
3994 UpdateWidget sibling(&w);
3995 child.setGeometry(10, 10, 20, 20);
3996 sibling.setGeometry(15, 15, 20, 20);
3999 QApplication::processEvents();
4004 const QPoint siblingOffset = sibling.mapToParent(QPoint());
4007 QApplication::processEvents();
4008 QApplication::processEvents();
4010 // child is opaque, sibling transparent
4012 QCOMPARE(sibling.numPaintEvents, 1);
4013 QCOMPARE(sibling.paintedRegion, sibling.visibleRegion());
4015 QCOMPARE(child.numPaintEvents, 1);
4016 QCOMPARE(child.paintedRegion.translated(childOffset),
4017 child.visibleRegion().translated(childOffset)
4018 & sibling.visibleRegion().translated(siblingOffset));
4020 QCOMPARE(w.numPaintEvents, 1);
4021 QCOMPARE(w.paintedRegion,
4022 w.visibleRegion() & sibling.visibleRegion().translated(siblingOffset));
4023 QCOMPARE(w.paintedRegion,
4024 (w.visibleRegion() - child.visibleRegion().translated(childOffset))
4025 & sibling.visibleRegion().translated(siblingOffset));
4032 sibling.setPalette(opaquePalette);
4033 sibling.setAutoFillBackground(true);
4036 QApplication::processEvents();
4037 QApplication::processEvents();
4039 // child opaque, sibling opaque
4041 QCOMPARE(sibling.numPaintEvents, 1);
4042 QCOMPARE(sibling.paintedRegion, sibling.visibleRegion());
4045 if (child.internalWinId()) // child is native
4046 QEXPECT_FAIL(0, "Cocoa compositor paints child and sibling", Continue);
4048 QCOMPARE(child.numPaintEvents, 0);
4049 QCOMPARE(child.visibleRegion(),
4050 QRegion(child.rect())
4051 - sibling.visibleRegion().translated(siblingOffset - childOffset));
4053 QCOMPARE(w.numPaintEvents, 0);
4054 QCOMPARE(w.visibleRegion(),
4056 - child.visibleRegion().translated(childOffset)
4057 - sibling.visibleRegion().translated(siblingOffset));
4061 static inline bool isOpaque(QWidget *widget)
4065 return qt_widget_private(widget)->isOpaque;
4068 void tst_QWidget::isOpaque()
4072 QVERIFY(::isOpaque(&w));
4075 QVERIFY(!::isOpaque(&child));
4077 child.setAutoFillBackground(true);
4078 QVERIFY(::isOpaque(&child));
4084 palette = child.palette();
4085 palette.setColor(child.backgroundRole(), QColor(255, 0, 0, 127));
4086 child.setPalette(palette);
4087 QVERIFY(!::isOpaque(&child));
4089 palette.setColor(child.backgroundRole(), QColor(255, 0, 0, 255));
4090 child.setPalette(palette);
4091 QVERIFY(::isOpaque(&child));
4093 palette.setColor(QPalette::Window, QColor(0, 0, 255, 127));
4094 w.setPalette(palette);
4096 QVERIFY(!::isOpaque(&w));
4098 child.setAutoFillBackground(false);
4099 QVERIFY(!::isOpaque(&child));
4101 // Qt::WA_OpaquePaintEvent
4103 child.setAttribute(Qt::WA_OpaquePaintEvent);
4104 QVERIFY(::isOpaque(&child));
4106 child.setAttribute(Qt::WA_OpaquePaintEvent, false);
4107 QVERIFY(!::isOpaque(&child));
4109 // Qt::WA_NoSystemBackground
4111 child.setAttribute(Qt::WA_NoSystemBackground);
4112 QVERIFY(!::isOpaque(&child));
4114 child.setAttribute(Qt::WA_NoSystemBackground, false);
4115 QVERIFY(!::isOpaque(&child));
4117 palette.setColor(QPalette::Window, QColor(0, 0, 255, 255));
4118 w.setPalette(palette);
4119 QVERIFY(::isOpaque(&w));
4121 w.setAttribute(Qt::WA_NoSystemBackground);
4122 QVERIFY(!::isOpaque(&w));
4124 w.setAttribute(Qt::WA_NoSystemBackground, false);
4125 QVERIFY(::isOpaque(&w));
4128 QPalette palette = QApplication::palette();
4129 QPalette old = palette;
4130 palette.setColor(QPalette::Window, Qt::transparent);
4131 QApplication::setPalette(palette);
4134 QVERIFY(!::isOpaque(&widget));
4136 QApplication::setPalette(old);
4137 QCOMPARE(::isOpaque(&widget), old.color(QPalette::Window).alpha() == 255);
4144 Test that scrolling of a widget invalidates the correct regions
4146 void tst_QWidget::scroll()
4148 UpdateWidget updateWidget;
4149 updateWidget.resize(500, 500);
4150 updateWidget.reset();
4151 updateWidget.show();
4152 QTest::qWaitForWindowShown(&updateWidget);
4154 qApp->processEvents();
4155 QTRY_VERIFY(updateWidget.numPaintEvents > 0);
4158 updateWidget.reset();
4159 updateWidget.scroll(10, 10);
4160 qApp->processEvents();
4161 QRegion dirty(QRect(0, 0, 500, 10));
4162 dirty += QRegion(QRect(0, 10, 10, 490));
4163 QCOMPARE(updateWidget.paintedRegion, dirty);
4167 updateWidget.reset();
4168 updateWidget.update(0, 0, 10, 10);
4169 updateWidget.scroll(0, 10);
4170 qApp->processEvents();
4171 QRegion dirty(QRect(0, 0, 500, 10));
4172 dirty += QRegion(QRect(0, 10, 10, 10));
4173 QCOMPARE(updateWidget.paintedRegion, dirty);
4177 updateWidget.reset();
4178 updateWidget.update(0, 0, 100, 100);
4179 updateWidget.scroll(10, 10, QRect(50, 50, 100, 100));
4180 qApp->processEvents();
4181 QRegion dirty(QRect(0, 0, 100, 50));
4182 dirty += QRegion(QRect(0, 50, 150, 10));
4183 dirty += QRegion(QRect(0, 60, 110, 40));
4184 dirty += QRegion(QRect(50, 100, 60, 10));
4185 dirty += QRegion(QRect(50, 110, 10, 40));
4186 QCOMPARE(updateWidget.paintedRegion, dirty);
4190 updateWidget.reset();
4191 updateWidget.update(0, 0, 100, 100);
4192 updateWidget.scroll(10, 10, QRect(100, 100, 100, 100));
4193 qApp->processEvents();
4194 QRegion dirty(QRect(0, 0, 100, 100));
4195 dirty += QRegion(QRect(100, 100, 100, 10));
4196 dirty += QRegion(QRect(100, 110, 10, 90));
4197 QCOMPARE(updateWidget.paintedRegion, dirty);
4202 class DestroyedSlotChecker : public QObject
4209 DestroyedSlotChecker()
4215 void destroyedSlot(QObject *object)
4217 wasQWidget = (qobject_cast<QWidget *>(object) != 0 || object->isWidgetType());
4222 Test that qobject_cast<QWidget*> returns 0 in a slot
4223 connected to QObject::destroyed.
4225 void tst_QWidget::qobject_castInDestroyedSlot()
4227 DestroyedSlotChecker checker;
4228 QWidget *widget = new QWidget();
4230 QObject::connect(widget, SIGNAL(destroyed(QObject *)), &checker, SLOT(destroyedSlot(QObject *)));
4233 QVERIFY(checker.wasQWidget == true);
4236 Q_DECLARE_METATYPE(QList<QRect>)
4238 // Since X11 WindowManager operations are all async, and we have no way to know if the window
4239 // manager has finished playing with the window geometry, this test can't be reliable on X11.
4241 void tst_QWidget::setWindowGeometry_data()
4243 QTest::addColumn<QList<QRect> >("rects");
4244 QTest::addColumn<int>("windowFlags");
4246 QList<QList<QRect> > rects;
4247 rects << (QList<QRect>()
4248 << QRect(100, 100, 200, 200)
4249 << QApplication::desktop()->availableGeometry().adjusted(100, 100, -100, -100)
4250 << QRect(130, 100, 0, 200)
4251 << QRect(100, 50, 200, 0)
4252 << QRect(130, 50, 0, 0))
4254 << QApplication::desktop()->availableGeometry().adjusted(100, 100, -100, -100)
4255 << QRect(130, 100, 0, 200)
4256 << QRect(100, 50, 200, 0)
4257 << QRect(130, 50, 0, 0)
4258 << QRect(100, 100, 200, 200))
4260 << QRect(130, 100, 0, 200)
4261 << QRect(100, 50, 200, 0)
4262 << QRect(130, 50, 0, 0)
4263 << QRect(100, 100, 200, 200)
4264 << QApplication::desktop()->availableGeometry().adjusted(100, 100, -100, -100))
4266 << QRect(100, 50, 200, 0)
4267 << QRect(130, 50, 0, 0)
4268 << QRect(100, 100, 200, 200)
4269 << QApplication::desktop()->availableGeometry().adjusted(100, 100, -100, -100)
4270 << QRect(130, 100, 0, 200))
4272 << QRect(130, 50, 0, 0)
4273 << QRect(100, 100, 200, 200)
4274 << QApplication::desktop()->availableGeometry().adjusted(100, 100, -100, -100)
4275 << QRect(130, 100, 0, 200)
4276 << QRect(100, 50, 200, 0));
4278 QList<int> windowFlags;
4279 windowFlags << 0 << Qt::FramelessWindowHint;
4281 foreach (QList<QRect> l, rects) {
4282 QRect rect = l.first();
4283 foreach (int windowFlag, windowFlags) {
4284 QTest::newRow(QString("%1,%2 %3x%4, flags %5")
4289 .arg(windowFlag, 0, 16).toLatin1())
4296 void tst_QWidget::setWindowGeometry()
4298 if (m_platform == QStringLiteral("xcb"))
4299 QSKIP("X11: Skip this test due to Window manager positioning issues.");
4301 QFETCH(QList<QRect>, rects);
4302 QFETCH(int, windowFlags);
4303 QRect rect = rects.takeFirst();
4306 // test setGeometry() without actually showing the window
4308 if (windowFlags != 0)
4309 widget.setWindowFlags(Qt::WindowFlags(windowFlags));
4311 widget.setGeometry(rect);
4313 QCOMPARE(widget.geometry(), rect);
4315 // setGeometry() without showing
4316 foreach (QRect r, rects) {
4317 widget.setGeometry(r);
4319 QCOMPARE(widget.geometry(), r);
4324 // setGeometry() first, then show()
4326 if (windowFlags != 0)
4327 widget.setWindowFlags(Qt::WindowFlags(windowFlags));
4329 widget.setGeometry(rect);
4331 QTest::qWaitForWindowShown(&widget);
4333 QTRY_COMPARE(widget.geometry(), rect);
4335 // setGeometry() while shown
4336 foreach (QRect r, rects) {
4337 widget.setGeometry(r);
4339 QTRY_COMPARE(widget.geometry(), r);
4341 widget.setGeometry(rect);
4343 QTRY_COMPARE(widget.geometry(), rect);
4348 QTRY_COMPARE(widget.geometry(), rect);
4350 // setGeometry() after hide()
4351 foreach (QRect r, rects) {
4352 widget.setGeometry(r);
4354 QTRY_COMPARE(widget.geometry(), r);
4356 widget.setGeometry(rect);
4358 QTRY_COMPARE(widget.geometry(), rect);
4360 // show() again, geometry() should still be the same
4362 QTest::qWaitForWindowShown(&widget);
4364 QTRY_COMPARE(widget.geometry(), rect);
4366 // final hide(), again geometry() should be unchanged
4369 QTRY_COMPARE(widget.geometry(), rect);
4373 // show() first, then setGeometry()
4375 if (windowFlags != 0)
4376 widget.setWindowFlags(Qt::WindowFlags(windowFlags));
4379 QTest::qWaitForWindowShown(&widget);
4380 widget.setGeometry(rect);
4382 QTRY_COMPARE(widget.geometry(), rect);
4384 // setGeometry() while shown
4385 foreach (QRect r, rects) {
4386 widget.setGeometry(r);
4388 QTRY_COMPARE(widget.geometry(), r);
4390 widget.setGeometry(rect);
4392 QTRY_COMPARE(widget.geometry(), rect);
4397 QTRY_COMPARE(widget.geometry(), rect);
4399 // setGeometry() after hide()
4400 foreach (QRect r, rects) {
4401 widget.setGeometry(r);
4403 QTRY_COMPARE(widget.geometry(), r);
4405 widget.setGeometry(rect);
4407 QTRY_COMPARE(widget.geometry(), rect);
4409 // show() again, geometry() should still be the same
4411 QTest::qWaitForWindowShown(&widget);
4413 QTRY_COMPARE(widget.geometry(), rect);
4415 // final hide(), again geometry() should be unchanged
4418 QTRY_COMPARE(widget.geometry(), rect);
4422 #if defined (Q_OS_WIN) && !defined(Q_OS_WINCE)
4423 void tst_QWidget::setGeometry_win()
4426 widget.setGeometry(0, 600, 100,100);
4428 widget.setWindowState(widget.windowState() | Qt::WindowMaximized);
4429 QRect geom = widget.normalGeometry();
4431 widget.setGeometry(geom);
4432 widget.setWindowState(widget.windowState() | Qt::WindowMaximized);
4435 ::GetWindowRect(winHandleOf(&widget), &rt);
4436 QVERIFY(rt.left <= 0);
4437 QVERIFY(rt.top <= 0);
4439 #endif // defined (Q_OS_WIN) && !defined(Q_OS_WINCE)
4441 // Since X11 WindowManager operation are all async, and we have no way to know if the window
4442 // manager has finished playing with the window geometry, this test can't be reliable on X11.
4444 void tst_QWidget::windowMoveResize_data()
4446 setWindowGeometry_data();
4449 void tst_QWidget::windowMoveResize()
4451 if (m_platform == QStringLiteral("xcb"))
4452 QSKIP("X11: Skip this test due to Window manager positioning issues.");
4454 QFETCH(QList<QRect>, rects);
4455 QFETCH(int, windowFlags);
4457 QRect rect = rects.takeFirst();
4460 // test setGeometry() without actually showing the window
4462 if (windowFlags != 0)
4463 widget.setWindowFlags(Qt::WindowFlags(windowFlags));
4465 widget.move(rect.topLeft());
4466 widget.resize(rect.size());
4468 QTRY_COMPARE(widget.pos(), rect.topLeft());
4469 QTRY_COMPARE(widget.size(), rect.size());
4471 // move() without showing
4472 foreach (QRect r, rects) {
4473 widget.move(r.topLeft());
4474 widget.resize(r.size());
4475 QApplication::processEvents();
4476 QTRY_COMPARE(widget.pos(), r.topLeft());
4477 QTRY_COMPARE(widget.size(), r.size());
4482 // move() first, then show()
4484 if (windowFlags != 0)
4485 widget.setWindowFlags(Qt::WindowFlags(windowFlags));
4487 widget.move(rect.topLeft());
4488 widget.resize(rect.size());
4492 QTRY_COMPARE(widget.pos(), rect.topLeft());
4493 QTRY_COMPARE(widget.size(), rect.size());
4495 // move() while shown
4496 foreach (const QRect &r, rects) {
4497 if (m_platform == QStringLiteral("xcb")
4498 && ((widget.width() == 0 || widget.height() == 0) && r.width() != 0 && r.height() != 0)) {
4499 QEXPECT_FAIL("130,100 0x200, flags 0",
4500 "First resize after show of zero-sized gets wrong win_gravity.",
4502 QEXPECT_FAIL("100,50 200x0, flags 0",
4503 "First resize after show of zero-sized gets wrong win_gravity.",
4505 QEXPECT_FAIL("130,50 0x0, flags 0",
4506 "First resize after show of zero-sized gets wrong win_gravity.",
4510 widget.move(r.topLeft());
4511 widget.resize(r.size());
4512 QApplication::processEvents();
4513 QTRY_COMPARE(widget.pos(), r.topLeft());
4514 QTRY_COMPARE(widget.size(), r.size());
4516 widget.move(rect.topLeft());
4517 widget.resize(rect.size());
4518 QApplication::processEvents();
4519 QTRY_COMPARE(widget.pos(), rect.topLeft());
4520 QTRY_COMPARE(widget.size(), rect.size());
4525 QTRY_COMPARE(widget.pos(), rect.topLeft());
4526 QTRY_COMPARE(widget.size(), rect.size());
4528 // move() after hide()
4529 foreach (QRect r, rects) {
4530 widget.move(r.topLeft());
4531 widget.resize(r.size());
4532 QApplication::processEvents();
4533 #if defined(Q_OS_MAC)
4534 if (r.width() == 0 && r.height() > 0) {
4535 widget.move(r.topLeft());
4536 widget.resize(r.size());
4539 QTRY_COMPARE(widget.pos(), r.topLeft());
4540 QTRY_COMPARE(widget.size(), r.size());
4542 widget.move(rect.topLeft());
4543 widget.resize(rect.size());
4545 QTRY_COMPARE(widget.pos(), rect.topLeft());
4546 QTRY_COMPARE(widget.size(), rect.size());
4548 // show() again, pos() should be the same
4550 QTest::qWaitForWindowShown(&widget);
4551 QApplication::processEvents();
4552 QTRY_COMPARE(widget.pos(), rect.topLeft());
4553 QTRY_COMPARE(widget.size(), rect.size());
4555 // final hide(), again pos() should be unchanged
4557 QApplication::processEvents();
4558 QTRY_COMPARE(widget.pos(), rect.topLeft());
4559 QTRY_COMPARE(widget.size(), rect.size());
4563 // show() first, then move()
4565 if (windowFlags != 0)
4566 widget.setWindowFlags(Qt::WindowFlags(windowFlags));
4569 QTest::qWaitForWindowShown(&widget);
4570 QApplication::processEvents();
4571 widget.move(rect.topLeft());
4572 widget.resize(rect.size());
4573 QApplication::processEvents();
4574 QTRY_COMPARE(widget.pos(), rect.topLeft());
4575 QTRY_COMPARE(widget.size(), rect.size());
4577 // move() while shown
4578 foreach (QRect r, rects) {
4579 widget.move(r.topLeft());
4580 widget.resize(r.size());
4581 QApplication::processEvents();
4582 QTRY_COMPARE(widget.pos(), r.topLeft());
4583 QTRY_COMPARE(widget.size(), r.size());
4585 widget.move(rect.topLeft());
4586 widget.resize(rect.size());
4587 QApplication::processEvents();
4588 QTRY_COMPARE(widget.pos(), rect.topLeft());
4589 QTRY_COMPARE(widget.size(), rect.size());
4593 QApplication::processEvents();
4594 QTRY_COMPARE(widget.pos(), rect.topLeft());
4595 QTRY_COMPARE(widget.size(), rect.size());
4597 // move() after hide()
4598 foreach (QRect r, rects) {
4599 widget.move(r.topLeft());
4600 widget.resize(r.size());
4601 QApplication::processEvents();
4602 #if defined(Q_OS_MAC)
4603 if (r.width() == 0 && r.height() > 0) {
4604 widget.move(r.topLeft());
4605 widget.resize(r.size());
4608 QTRY_COMPARE(widget.pos(), r.topLeft());
4609 QTRY_COMPARE(widget.size(), r.size());
4611 widget.move(rect.topLeft());
4612 widget.resize(rect.size());
4613 QApplication::processEvents();
4614 QTRY_COMPARE(widget.pos(), rect.topLeft());
4615 QTRY_COMPARE(widget.size(), rect.size());
4617 // show() again, pos() should be the same
4619 QTest::qWaitForWindowShown(&widget);
4621 QTRY_COMPARE(widget.pos(), rect.topLeft());
4622 QTRY_COMPARE(widget.size(), rect.size());
4624 // final hide(), again pos() should be unchanged
4627 QTRY_COMPARE(widget.pos(), rect.topLeft());
4628 QTRY_COMPARE(widget.size(), rect.size());
4632 class ColorWidget : public QWidget
4635 ColorWidget(QWidget *parent = 0, const QColor &c = QColor(Qt::red))
4636 : QWidget(parent, Qt::FramelessWindowHint), color(c)
4638 QPalette opaquePalette = palette();
4639 opaquePalette.setColor(backgroundRole(), color);
4640 setPalette(opaquePalette);
4641 setAutoFillBackground(true);
4644 void paintEvent(QPaintEvent *e) {
4656 #define VERIFY_COLOR(region, color) { \
4657 const QRegion r = QRegion(region); \
4658 QScreen *screen = qApp->primaryScreen(); \
4659 const WId desktopWinId = QDesktopWidget().winId(); \
4660 for (int i = 0; i < r.rects().size(); ++i) { \
4661 const QRect rect = r.rects().at(i); \
4662 for (int t = 0; t < 5; t++) { \
4663 const QPixmap pixmap = screen->grabWindow(desktopWinId, \
4664 rect.left(), rect.top(), \
4665 rect.width(), rect.height()); \
4666 QCOMPARE(pixmap.size(), rect.size()); \
4667 QPixmap expectedPixmap(pixmap); /* ensure equal formats */ \
4668 expectedPixmap.detach(); \
4669 expectedPixmap.fill(color); \
4670 QImage image = pixmap.toImage(); \
4671 uint alphaCorrection = image.format() == QImage::Format_RGB32 ? 0xff000000 : 0; \
4672 uint firstPixel = image.pixel(0,0) | alphaCorrection; \
4673 if ( firstPixel != QColor(color).rgb() && t < 4 ) \
4674 { QTest::qWait(200); continue; } \
4675 QCOMPARE(firstPixel, QColor(color).rgb()); \
4676 QCOMPARE(pixmap, expectedPixmap); \
4682 void tst_QWidget::popupEnterLeave()
4685 parent.setWindowFlags(Qt::FramelessWindowHint);
4686 parent.setGeometry(10, 10, 200, 100);
4688 ColorWidget alien(&parent, Qt::black);
4689 alien.setGeometry(0, 0, 10, 10);
4694 QTest::qWaitForWindowShown(parent.windowHandle());
4696 QWindowSystemInterface::handleMouseEvent(parent.windowHandle(), QPointF(5, 5), QPointF(), Qt::LeftButton, Qt::NoModifier);
4698 QWindowSystemInterface::handleMouseEvent(parent.windowHandle(), QPointF(5, 5), QPointF(), Qt::NoButton, Qt::NoModifier);
4701 QStringList wordList;
4702 wordList << "alpha" << "omega" << "omicron" << "zeta";
4704 QLineEdit popup(&parent);
4706 QCompleter completer(wordList);
4707 completer.setCaseSensitivity(Qt::CaseInsensitive);
4708 popup.setCompleter(&completer);
4709 popup.setWindowFlags(Qt::Popup);
4710 popup.setGeometry(20, 20, 80, 20);
4714 QTest::qWaitForWindowShown(popup.windowHandle());
4718 QWindowSystemInterface::handleMouseEvent(popup.windowHandle(), QPointF(-5, -5), QPointF(), Qt::LeftButton, Qt::NoModifier);
4720 QWindowSystemInterface::handleMouseEvent(popup.windowHandle(), QPointF(-5, -5), QPointF(), Qt::NoButton, Qt::NoModifier);
4724 QVERIFY(!popup.underMouse());
4727 void tst_QWidget::moveChild_data()
4729 QTest::addColumn<QPoint>("offset");
4731 QTest::newRow("right") << QPoint(20, 0);
4732 QTest::newRow("down") << QPoint(0, 20);
4733 QTest::newRow("left") << QPoint(-20, 0);
4734 QTest::newRow("up") << QPoint(0, -20);
4737 void tst_QWidget::moveChild()
4739 QFETCH(QPoint, offset);
4742 // prevent custom styles
4743 parent.setStyle(new QWindowsStyle);
4744 ColorWidget child(&parent, Qt::blue);
4747 parent.setGeometry(QRect(QPoint(QApplication::desktop()->availableGeometry(&parent).topLeft()),
4750 parent.setGeometry(60, 60, 150, 150);
4752 child.setGeometry(25, 25, 50, 50);
4754 QTest::qWaitForWindowShown(&parent);
4756 const QPoint tlwOffset = parent.geometry().topLeft();
4758 QTRY_COMPARE(parent.r, QRegion(parent.rect()) - child.geometry());
4759 QTRY_COMPARE(child.r, QRegion(child.rect()));
4760 VERIFY_COLOR(child.geometry().translated(tlwOffset),
4762 VERIFY_COLOR(QRegion(parent.geometry()) - child.geometry().translated(tlwOffset),
4769 const QRect oldGeometry = child.geometry();
4771 QPoint pos = child.pos() + offset;
4774 QTRY_COMPARE(pos, child.pos());
4776 QCOMPARE(parent.r, QRegion(oldGeometry) - child.geometry());
4777 #if !defined(Q_OS_MAC)
4778 // should be scrolled in backingstore
4779 QCOMPARE(child.r, QRegion());
4781 VERIFY_COLOR(child.geometry().translated(tlwOffset),
4783 VERIFY_COLOR(QRegion(parent.geometry()) - child.geometry().translated(tlwOffset),
4787 void tst_QWidget::showAndMoveChild()
4789 QWidget parent(0, Qt::FramelessWindowHint);
4790 // prevent custom styles
4791 parent.setStyle(new QWindowsStyle);
4793 QDesktopWidget desktop;
4794 QRect desktopDimensions = desktop.availableGeometry(&parent);
4795 desktopDimensions = desktopDimensions.adjusted(64, 64, -64, -64);
4797 parent.setGeometry(desktopDimensions);
4798 parent.setPalette(Qt::red);
4800 QTest::qWaitForWindowShown(&parent);
4803 const QPoint tlwOffset = parent.geometry().topLeft();
4804 QWidget child(&parent);
4805 child.resize(desktopDimensions.width()/2, desktopDimensions.height()/2);
4806 child.setPalette(Qt::blue);
4807 child.setAutoFillBackground(true);
4809 // Ensure that the child is repainted correctly when moved right after show.
4810 // NB! Do NOT processEvents() (or qWait()) in between show() and move().
4812 child.move(desktopDimensions.width()/2, desktopDimensions.height()/2);
4813 qApp->processEvents();
4815 VERIFY_COLOR(child.geometry().translated(tlwOffset), Qt::blue);
4816 VERIFY_COLOR(QRegion(parent.geometry()) - child.geometry().translated(tlwOffset), Qt::red);
4819 // Cocoa only has rect granularity.
4821 void tst_QWidget::subtractOpaqueSiblings()
4824 w.setGeometry(50, 50, 300, 300);
4826 ColorWidget *large = new ColorWidget(&w, Qt::red);
4827 large->setGeometry(50, 50, 200, 200);
4829 ColorWidget *medium = new ColorWidget(large, Qt::gray);
4830 medium->setGeometry(50, 50, 100, 100);
4832 ColorWidget *tall = new ColorWidget(&w, Qt::blue);
4833 tall->setGeometry(100, 30, 50, 100);
4836 QTest::qWaitForWindowShown(&w);
4846 // QWidgetPrivate::subtractOpaqueSiblings() should prevent parts of medium
4847 // to be repainted and tall from be repainted at all.
4849 QTRY_COMPARE(large->r, QRegion());
4850 QTRY_COMPARE(tall->r, QRegion());
4851 QTRY_COMPARE(medium->r.translated(medium->mapTo(&w, QPoint())),
4852 QRegion(medium->geometry().translated(large->pos()))
4853 - tall->geometry());
4857 void tst_QWidget::deleteStyle()
4860 widget.setStyle(new QWindowsStyle);
4862 delete widget.style();
4863 qApp->processEvents();
4866 class TopLevelFocusCheck: public QWidget
4871 TopLevelFocusCheck(QWidget* parent = 0) : QWidget(parent)
4873 edit = new QLineEdit(this);
4875 edit->installEventFilter(this);
4879 void mouseDoubleClickEvent ( QMouseEvent * /*event*/ )
4882 edit->setFocus(Qt::OtherFocusReason);
4883 qApp->processEvents();
4885 bool eventFilter(QObject *obj, QEvent *event)
4887 if (obj == edit && event->type()== QEvent::FocusOut) {
4895 void tst_QWidget::multipleToplevelFocusCheck()
4897 TopLevelFocusCheck w1;
4898 TopLevelFocusCheck w2;
4900 w1.resize(200, 200);
4902 QTest::qWaitForWindowShown(&w1);
4905 QTest::qWaitForWindowShown(&w2);
4909 QApplication::setActiveWindow(&w1);
4910 w1.activateWindow();
4911 QApplication::processEvents();
4912 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&w1));
4914 QTest::mouseDClick(&w1, Qt::LeftButton);
4915 QTRY_COMPARE(QApplication::focusWidget(), static_cast<QWidget *>(w1.edit));
4917 w2.activateWindow();
4918 QApplication::setActiveWindow(&w2);
4919 QApplication::processEvents();
4920 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&w2));
4921 QTest::mouseClick(&w2, Qt::LeftButton);
4922 QTRY_COMPARE(QApplication::focusWidget(), (QWidget *)0);
4924 QTest::mouseDClick(&w2, Qt::LeftButton);
4925 QTRY_COMPARE(QApplication::focusWidget(), static_cast<QWidget *>(w2.edit));
4927 w1.activateWindow();
4928 QApplication::setActiveWindow(&w1);
4929 QApplication::processEvents();
4930 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&w1));
4931 QTest::mouseDClick(&w1, Qt::LeftButton);
4932 QTRY_COMPARE(QApplication::focusWidget(), static_cast<QWidget *>(w1.edit));
4934 w2.activateWindow();
4935 QApplication::setActiveWindow(&w2);
4936 QApplication::processEvents();
4937 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&w2));
4938 QTest::mouseClick(&w2, Qt::LeftButton);
4939 QTRY_COMPARE(QApplication::focusWidget(), (QWidget *)0);
4942 class FocusWidget: public QWidget
4945 virtual bool event(QEvent *ev)
4947 if (ev->type() == QEvent::FocusAboutToChange)
4948 widgetDuringFocusAboutToChange = qApp->focusWidget();
4949 return QWidget::event(ev);
4951 virtual void focusOutEvent(QFocusEvent *)
4953 widgetDuringFocusOut = qApp->focusWidget();
4957 FocusWidget(QWidget *parent) : QWidget(parent), widgetDuringFocusAboutToChange(0), widgetDuringFocusOut(0) {}
4959 QWidget *widgetDuringFocusAboutToChange;
4960 QWidget *widgetDuringFocusOut;
4963 void tst_QWidget::setFocus()
4966 // move focus to another window
4967 testWidget->activateWindow();
4968 QApplication::setActiveWindow(testWidget);
4969 if (testWidget->focusWidget())
4970 testWidget->focusWidget()->clearFocus();
4972 testWidget->clearFocus();
4974 // window and children never shown, nobody gets focus
4977 QWidget child1(&window);
4978 child1.setFocusPolicy(Qt::StrongFocus);
4980 QWidget child2(&window);
4981 child2.setFocusPolicy(Qt::StrongFocus);
4984 QVERIFY(!child1.hasFocus());
4985 QCOMPARE(window.focusWidget(), &child1);
4986 QCOMPARE(QApplication::focusWidget(), static_cast<QWidget *>(0));
4989 QVERIFY(!child2.hasFocus());
4990 QCOMPARE(window.focusWidget(), &child2);
4991 QCOMPARE(QApplication::focusWidget(), static_cast<QWidget *>(0));
4995 // window and children show, but window not active, nobody gets focus
4998 QWidget child1(&window);
4999 child1.setFocusPolicy(Qt::StrongFocus);
5001 QWidget child2(&window);
5002 child2.setFocusPolicy(Qt::StrongFocus);
5006 // note: window may be active, but we don't want it to be
5007 testWidget->activateWindow();
5008 QApplication::setActiveWindow(testWidget);
5009 if (testWidget->focusWidget())
5010 testWidget->focusWidget()->clearFocus();
5012 testWidget->clearFocus();
5015 QVERIFY(!child1.hasFocus());
5016 QCOMPARE(window.focusWidget(), &child1);
5017 QCOMPARE(QApplication::focusWidget(), static_cast<QWidget *>(0));
5020 QVERIFY(!child2.hasFocus());
5021 QCOMPARE(window.focusWidget(), &child2);
5022 QCOMPARE(QApplication::focusWidget(), static_cast<QWidget *>(0));
5026 // window and children show, but window *is* active, children get focus
5029 FocusWidget child1(&window);
5030 child1.setFocusPolicy(Qt::StrongFocus);
5032 QWidget child2(&window);
5033 child2.setFocusPolicy(Qt::StrongFocus);
5036 window.activateWindow();
5037 QTest::qWaitForWindowShown(&window);
5038 QTRY_VERIFY(qGuiApp->focusWindow());
5041 QTRY_VERIFY(child1.hasFocus());
5042 QCOMPARE(window.focusWidget(), &child1);
5043 QCOMPARE(QApplication::focusWidget(), &child1);
5046 QVERIFY(child2.hasFocus());
5047 QCOMPARE(window.focusWidget(), &child2);
5048 QCOMPARE(QApplication::focusWidget(), &child2);
5050 // focus changed in between the events
5051 QCOMPARE(child1.widgetDuringFocusAboutToChange, &child1);
5052 QCOMPARE(child1.widgetDuringFocusOut, &child2);
5056 // window shown and active, children created, don't get focus, but get focus when shown
5060 window.activateWindow();
5061 QTest::qWaitForWindowShown(&window);
5062 QTRY_VERIFY(qGuiApp->focusWindow());
5064 QWidget child1(&window);
5065 child1.setFocusPolicy(Qt::StrongFocus);
5067 QWidget child2(&window);
5068 child2.setFocusPolicy(Qt::StrongFocus);
5071 QVERIFY(!child1.hasFocus());
5072 QCOMPARE(window.focusWidget(), static_cast<QWidget *>(0));
5073 QCOMPARE(QApplication::focusWidget(), static_cast<QWidget *>(0));
5076 QApplication::processEvents();
5077 QTRY_VERIFY(child1.hasFocus());
5078 QCOMPARE(window.focusWidget(), &child1);
5079 QCOMPARE(QApplication::focusWidget(), &child1);
5082 QVERIFY(!child2.hasFocus());
5083 QCOMPARE(window.focusWidget(), &child1);
5084 QCOMPARE(QApplication::focusWidget(), &child1);
5087 QVERIFY(child2.hasFocus());
5088 QCOMPARE(window.focusWidget(), &child2);
5089 QCOMPARE(QApplication::focusWidget(), &child2);
5093 // window shown and active, children created, don't get focus,
5094 // even after setFocus(), hide(), then show()
5098 window.activateWindow();
5099 QTest::qWaitForWindowShown(&window);
5100 QTRY_VERIFY(qGuiApp->focusWindow());
5102 QWidget child1(&window);
5103 child1.setFocusPolicy(Qt::StrongFocus);
5105 QWidget child2(&window);
5106 child2.setFocusPolicy(Qt::StrongFocus);
5109 QVERIFY(!child1.hasFocus());
5110 QCOMPARE(window.focusWidget(), static_cast<QWidget *>(0));
5111 QCOMPARE(QApplication::focusWidget(), static_cast<QWidget *>(0));
5114 QVERIFY(!child1.hasFocus());
5115 QCOMPARE(window.focusWidget(), static_cast<QWidget *>(0));
5116 QCOMPARE(QApplication::focusWidget(), static_cast<QWidget *>(0));
5119 QVERIFY(!child1.hasFocus());
5120 QCOMPARE(window.focusWidget(), static_cast<QWidget *>(0));
5121 QCOMPARE(QApplication::focusWidget(), static_cast<QWidget *>(0));
5124 QVERIFY(!child2.hasFocus());
5125 QCOMPARE(window.focusWidget(), static_cast<QWidget *>(0));
5126 QCOMPARE(QApplication::focusWidget(), static_cast<QWidget *>(0));
5129 QVERIFY(!child2.hasFocus());
5130 QCOMPARE(window.focusWidget(), static_cast<QWidget *>(0));
5131 QCOMPARE(QApplication::focusWidget(), static_cast<QWidget *>(0));
5134 QVERIFY(!child2.hasFocus());
5135 QCOMPARE(window.focusWidget(), static_cast<QWidget *>(0));
5136 QCOMPARE(QApplication::focusWidget(), static_cast<QWidget *>(0));
5140 class EventSpy : public QObject
5143 EventSpy(QWidget *widget, QEvent::Type event)
5144 : m_widget(widget), eventToSpy(event), m_count(0)
5147 m_widget->installEventFilter(this);
5150 QWidget *widget() const { return m_widget; }
5151 int count() const { return m_count; }
5152 void clear() { m_count = 0; }
5155 bool eventFilter(QObject *object, QEvent *event)
5157 if (event->type() == eventToSpy)
5159 return QObject::eventFilter(object, event);
5164 QEvent::Type eventToSpy;
5168 void tst_QWidget::setCursor()
5170 #ifndef QT_NO_CURSOR
5173 QWidget child(&window);
5175 QVERIFY(!window.testAttribute(Qt::WA_SetCursor));
5176 QVERIFY(!child.testAttribute(Qt::WA_SetCursor));
5178 window.setCursor(window.cursor());
5179 QVERIFY(window.testAttribute(Qt::WA_SetCursor));
5180 QVERIFY(!child.testAttribute(Qt::WA_SetCursor));
5181 QCOMPARE(child.cursor().shape(), window.cursor().shape());
5184 // do it again, but with window show()n
5187 QWidget child(&window);
5190 QVERIFY(!window.testAttribute(Qt::WA_SetCursor));
5191 QVERIFY(!child.testAttribute(Qt::WA_SetCursor));
5193 window.setCursor(window.cursor());
5194 QVERIFY(window.testAttribute(Qt::WA_SetCursor));
5195 QVERIFY(!child.testAttribute(Qt::WA_SetCursor));
5196 QCOMPARE(child.cursor().shape(), window.cursor().shape());
5202 QWidget child(&window);
5204 window.setCursor(Qt::WaitCursor);
5205 QVERIFY(window.testAttribute(Qt::WA_SetCursor));
5206 QVERIFY(!child.testAttribute(Qt::WA_SetCursor));
5207 QCOMPARE(child.cursor().shape(), window.cursor().shape());
5210 // same thing again, just with window show()n
5213 QWidget child(&window);
5216 window.setCursor(Qt::WaitCursor);
5217 QVERIFY(window.testAttribute(Qt::WA_SetCursor));
5218 QVERIFY(!child.testAttribute(Qt::WA_SetCursor));
5219 QCOMPARE(child.cursor().shape(), window.cursor().shape());
5222 // reparenting child should not cause the WA_SetCursor to become set
5226 QWidget child(&window);
5228 window.setCursor(Qt::WaitCursor);
5231 QVERIFY(!child.testAttribute(Qt::WA_SetCursor));
5232 QCOMPARE(child.cursor().shape(), QCursor().shape());
5234 child.setParent(&window2);
5235 QVERIFY(!child.testAttribute(Qt::WA_SetCursor));
5236 QCOMPARE(child.cursor().shape(), window2.cursor().shape());
5238 window2.setCursor(Qt::WaitCursor);
5239 QVERIFY(!child.testAttribute(Qt::WA_SetCursor));
5240 QCOMPARE(child.cursor().shape(), window2.cursor().shape());
5243 // again, with windows show()n
5247 QWidget child(&window);
5249 window.setCursor(Qt::WaitCursor);
5253 QVERIFY(!child.testAttribute(Qt::WA_SetCursor));
5254 QCOMPARE(child.cursor().shape(), QCursor().shape());
5256 child.setParent(&window2);
5257 QVERIFY(!child.testAttribute(Qt::WA_SetCursor));
5258 QCOMPARE(child.cursor().shape(), window2.cursor().shape());
5261 window2.setCursor(Qt::WaitCursor);
5262 QVERIFY(!child.testAttribute(Qt::WA_SetCursor));
5263 QCOMPARE(child.cursor().shape(), window2.cursor().shape());
5266 // test if CursorChange is sent
5269 EventSpy spy(&widget, QEvent::CursorChange);
5270 QCOMPARE(spy.count(), 0);
5271 widget.setCursor(QCursor(Qt::WaitCursor));
5272 QCOMPARE(spy.count(), 1);
5273 widget.unsetCursor();
5274 QCOMPARE(spy.count(), 2);
5279 void tst_QWidget::setToolTip()
5282 EventSpy spy(&widget, QEvent::ToolTipChange);
5283 QCOMPARE(spy.count(), 0);
5285 QCOMPARE(widget.toolTip(), QString());
5286 widget.setToolTip(QString("Hello"));
5287 QCOMPARE(widget.toolTip(), QString("Hello"));
5288 QCOMPARE(spy.count(), 1);
5289 widget.setToolTip(QString());
5290 QCOMPARE(widget.toolTip(), QString());
5291 QCOMPARE(spy.count(), 2);
5293 // Mouse over doesn't work on Windows mobile, so skip the rest of the test for that platform.
5294 #ifndef Q_OS_WINCE_WM
5295 for (int pass = 0; pass < 2; ++pass) {
5296 QWidget *popup = new QWidget(0, Qt::Popup);
5297 popup->resize(150, 50);
5298 QFrame *frame = new QFrame(popup);
5299 frame->setGeometry(0, 0, 50, 50);
5300 frame->setFrameStyle(QFrame::Box | QFrame::Plain);
5301 EventSpy spy1(frame, QEvent::ToolTip);
5302 EventSpy spy2(popup, QEvent::ToolTip);
5303 frame->setMouseTracking(pass == 0 ? false : true);
5304 frame->setToolTip(QLatin1String("TOOLTIP FRAME"));
5305 popup->setToolTip(QLatin1String("TOOLTIP POPUP"));
5307 QTest::qWaitForWindowShown(popup);
5309 QTest::mouseMove(frame);
5310 QTest::qWait(900); // delay is 700
5312 QCOMPARE(spy1.count(), 1);
5313 QCOMPARE(spy2.count(), 0);
5315 QTest::qWait(2200); // delay is 2000
5316 QTest::mouseMove(popup);
5322 void tst_QWidget::testWindowIconChangeEventPropagation()
5324 // Create widget hierarchy.
5325 QWidget topLevelWidget;
5326 QWidget topLevelChild(&topLevelWidget);
5328 QDialog dialog(&topLevelWidget);
5329 QWidget dialogChild(&dialog);
5331 QWidgetList widgets;
5332 widgets << &topLevelWidget << &topLevelChild
5333 << &dialog << &dialogChild;
5334 QCOMPARE(widgets.count(), 4);
5336 // Create spy lists.
5337 QList <EventSpy *> applicationEventSpies;
5338 QList <EventSpy *> widgetEventSpies;
5339 foreach (QWidget *widget, widgets) {
5340 applicationEventSpies.append(new EventSpy(widget, QEvent::ApplicationWindowIconChange));
5341 widgetEventSpies.append(new EventSpy(widget, QEvent::WindowIconChange));
5344 // QApplication::setWindowIcon
5345 const QIcon windowIcon = qApp->style()->standardIcon(QStyle::SP_TitleBarMenuButton);
5346 qApp->setWindowIcon(windowIcon);
5348 for (int i = 0; i < widgets.count(); ++i) {
5349 // Check QEvent::ApplicationWindowIconChange
5350 EventSpy *spy = applicationEventSpies.at(i);
5351 QWidget *widget = spy->widget();
5352 if (widget->isWindow()) {
5353 QCOMPARE(spy->count(), 1);
5354 QCOMPARE(widget->windowIcon(), windowIcon);
5356 QCOMPARE(spy->count(), 0);
5360 // Check QEvent::WindowIconChange
5361 spy = widgetEventSpies.at(i);
5362 QCOMPARE(spy->count(), 1);
5366 // Set icon on a top-level widget.
5367 topLevelWidget.setWindowIcon(*new QIcon);
5369 for (int i = 0; i < widgets.count(); ++i) {
5370 // Check QEvent::ApplicationWindowIconChange
5371 EventSpy *spy = applicationEventSpies.at(i);
5372 QCOMPARE(spy->count(), 0);
5375 // Check QEvent::WindowIconChange
5376 spy = widgetEventSpies.at(i);
5377 QWidget *widget = spy->widget();
5378 if (widget == &topLevelWidget) {
5379 QCOMPARE(widget->windowIcon(), QIcon());
5380 QCOMPARE(spy->count(), 1);
5381 } else if (topLevelWidget.isAncestorOf(widget)) {
5382 QCOMPARE(spy->count(), 1);
5384 QCOMPARE(spy->count(), 0);
5390 for (int i = 0; i < widgets.count(); ++i) {
5391 delete applicationEventSpies.at(i);
5392 delete widgetEventSpies.at(i);
5394 qApp->setWindowIcon(QIcon());
5397 void tst_QWidget::minAndMaxSizeWithX11BypassWindowManagerHint()
5399 if (m_platform != QStringLiteral("xcb"))
5400 QSKIP("This test is for X11 only.");
5401 // Same size as in QWidget::create_sys().
5402 const QSize desktopSize = QApplication::desktop()->size();
5403 const QSize originalSize(desktopSize.width() / 2, desktopSize.height() * 4 / 10);
5406 QWidget widget(0, Qt::X11BypassWindowManagerHint);
5408 const QSize newMaximumSize = widget.size().boundedTo(originalSize) - QSize(10, 10);
5409 widget.setMaximumSize(newMaximumSize);
5410 QCOMPARE(widget.size(), newMaximumSize);
5413 QTest::qWaitForWindowShown(widget.windowHandle());
5414 QCOMPARE(widget.size(), newMaximumSize);
5418 QWidget widget(0, Qt::X11BypassWindowManagerHint);
5420 const QSize newMinimumSize = widget.size().expandedTo(originalSize) + QSize(10, 10);
5421 widget.setMinimumSize(newMinimumSize);
5422 QCOMPARE(widget.size(), newMinimumSize);
5425 QTest::qWaitForWindowShown(widget.windowHandle());
5426 QCOMPARE(widget.size(), newMinimumSize);
5430 class ShowHideShowWidget : public QWidget
5436 bool gotExpectedMapNotify;
5438 ShowHideShowWidget()
5439 : state(0), gotExpectedMapNotify(false)
5444 void timerEvent(QTimerEvent *)
5456 bool nativeEvent(const QByteArray &eventType, void *message, long *)
5458 enum { XCB_MAP_NOTIFY = 19 };
5460 if (state == 1 && eventType == QByteArrayLiteral("xcb_generic_event_t")) {
5461 // XCB events have a uint8 response_type member at the beginning.
5462 const unsigned char responseType = *(const unsigned char *)(message);
5463 if ((responseType & ~0x80) == XCB_MAP_NOTIFY)
5464 gotExpectedMapNotify = true;
5473 void tst_QWidget::showHideShowX11()
5475 if (m_platform != QStringLiteral("xcb"))
5476 QSKIP("This test is for X11 only.");
5478 ShowHideShowWidget w;
5482 QEventLoop eventLoop;
5483 connect(&w, SIGNAL(done()), &eventLoop, SLOT(quit()));
5486 QVERIFY(w.gotExpectedMapNotify);
5489 void tst_QWidget::clean_qt_x11_enforce_cursor()
5491 if (m_platform != QStringLiteral("xcb"))
5492 QSKIP("This test is for X11 only.");
5496 QWidget *w = new QWidget(&window);
5497 QWidget *child = new QWidget(w);
5498 child->setAttribute(Qt::WA_SetCursor, true);
5501 QApplication::setActiveWindow(&window);
5502 QTest::qWaitForWindowShown(&window);
5504 QCursor::setPos(window.geometry().center());
5508 QApplication::processEvents();
5514 QGraphicsScene scene;
5515 QLineEdit *edit = new QLineEdit;
5516 scene.addWidget(edit);
5518 // If the test didn't crash, then it passed.
5521 class EventRecorder : public QObject
5526 typedef QList<QPair<QWidget *, QEvent::Type> > EventList;
5528 EventRecorder(QObject *parent = 0)
5532 EventList eventList()
5542 bool eventFilter(QObject *object, QEvent *event)
5544 QWidget *widget = qobject_cast<QWidget *>(object);
5545 if (widget && !event->spontaneous())
5546 events.append(qMakePair(widget, event->type()));
5554 void tst_QWidget::childEvents()
5556 EventRecorder::EventList expected;
5558 // Move away the cursor; otherwise it might result in an enter event if it's
5559 // inside the widget when the widget is shown.
5560 QCursor::setPos(qApp->desktop()->availableGeometry().bottomRight());
5564 // no children created, not shown
5567 widget.installEventFilter(&spy);
5569 QCoreApplication::postEvent(&widget, new QEvent(QEvent::Type(QEvent::User + 1)));
5571 QCoreApplication::sendPostedEvents();
5574 EventRecorder::EventList()
5575 << qMakePair(&widget, QEvent::PolishRequest)
5576 << qMakePair(&widget, QEvent::Polish)
5577 << qMakePair(&widget, QEvent::Type(QEvent::User + 1));
5578 QCOMPARE(spy.eventList(), expected);
5582 // no children, shown
5585 widget.installEventFilter(&spy);
5587 QCoreApplication::postEvent(&widget, new QEvent(QEvent::Type(QEvent::User + 1)));
5591 EventRecorder::EventList()
5592 << qMakePair(&widget, QEvent::WinIdChange)
5593 << qMakePair(&widget, QEvent::Polish)
5594 << qMakePair(&widget, QEvent::Move)
5595 << qMakePair(&widget, QEvent::Resize)
5596 << qMakePair(&widget, QEvent::Show);
5598 expected << qMakePair(&widget, QEvent::ShowToParent);
5599 QCOMPARE(spy.eventList(), expected);
5602 QCoreApplication::sendPostedEvents();
5604 EventRecorder::EventList()
5605 << qMakePair(&widget, QEvent::PolishRequest)
5606 << qMakePair(&widget, QEvent::Type(QEvent::User + 1));
5609 expected << qMakePair(&widget, QEvent::UpdateLater);
5611 expected << qMakePair(&widget, QEvent::UpdateRequest);
5613 QCOMPARE(spy.eventList(), expected);
5617 // 2 children, not shown
5620 widget.installEventFilter(&spy);
5622 QCoreApplication::postEvent(&widget, new QEvent(QEvent::Type(QEvent::User + 1)));
5624 QWidget child1(&widget);
5626 child2.setParent(&widget);
5628 QCoreApplication::postEvent(&widget, new QEvent(QEvent::Type(QEvent::User + 2)));
5631 EventRecorder::EventList()
5632 << qMakePair(&widget, QEvent::ChildAdded)
5633 << qMakePair(&widget, QEvent::ChildAdded);
5634 QCOMPARE(spy.eventList(), expected);
5637 QCoreApplication::sendPostedEvents();
5639 EventRecorder::EventList()
5640 << qMakePair(&widget, QEvent::PolishRequest)
5641 << qMakePair(&widget, QEvent::Polish)
5642 << qMakePair(&widget, QEvent::ChildPolished)
5643 << qMakePair(&widget, QEvent::ChildPolished)
5644 << qMakePair(&widget, QEvent::Type(QEvent::User + 1))
5645 << qMakePair(&widget, QEvent::Type(QEvent::User + 2));
5646 QCOMPARE(spy.eventList(), expected);
5650 // 2 children, widget shown
5653 widget.installEventFilter(&spy);
5655 QCoreApplication::postEvent(&widget, new QEvent(QEvent::Type(QEvent::User + 1)));
5657 QWidget child1(&widget);
5659 child2.setParent(&widget);
5661 QCoreApplication::postEvent(&widget, new QEvent(QEvent::Type(QEvent::User + 2)));
5664 EventRecorder::EventList()
5665 << qMakePair(&widget, QEvent::ChildAdded)
5666 << qMakePair(&widget, QEvent::ChildAdded);
5667 QCOMPARE(spy.eventList(), expected);
5672 EventRecorder::EventList()
5673 << qMakePair(&widget, QEvent::WinIdChange)
5674 << qMakePair(&widget, QEvent::Polish)
5675 << qMakePair(&widget, QEvent::ChildPolished)
5676 << qMakePair(&widget, QEvent::ChildPolished)
5677 << qMakePair(&widget, QEvent::Move)
5678 << qMakePair(&widget, QEvent::Resize)
5679 << qMakePair(&widget, QEvent::Show);
5681 expected << qMakePair(&widget, QEvent::ShowToParent);
5682 QCOMPARE(spy.eventList(), expected);
5685 QCoreApplication::sendPostedEvents();
5687 EventRecorder::EventList()
5688 << qMakePair(&widget, QEvent::PolishRequest)
5689 << qMakePair(&widget, QEvent::Type(QEvent::User + 1))
5690 << qMakePair(&widget, QEvent::Type(QEvent::User + 2));
5693 expected << qMakePair(&widget, QEvent::UpdateLater);
5695 expected << qMakePair(&widget, QEvent::UpdateRequest);
5697 QCOMPARE(spy.eventList(), expected);
5701 // 2 children, but one is reparented away, not shown
5704 widget.installEventFilter(&spy);
5706 QCoreApplication::postEvent(&widget, new QEvent(QEvent::Type(QEvent::User + 1)));
5708 QWidget child1(&widget);
5710 child2.setParent(&widget);
5711 child2.setParent(0);
5713 QCoreApplication::postEvent(&widget, new QEvent(QEvent::Type(QEvent::User + 2)));
5716 EventRecorder::EventList()
5717 << qMakePair(&widget, QEvent::ChildAdded)
5718 << qMakePair(&widget, QEvent::ChildAdded)
5719 << qMakePair(&widget, QEvent::ChildRemoved);
5720 QCOMPARE(spy.eventList(), expected);
5723 QCoreApplication::sendPostedEvents();
5725 EventRecorder::EventList()
5726 << qMakePair(&widget, QEvent::PolishRequest)
5727 << qMakePair(&widget, QEvent::Polish)
5728 << qMakePair(&widget, QEvent::ChildPolished)
5729 << qMakePair(&widget, QEvent::Type(QEvent::User + 1))
5730 << qMakePair(&widget, QEvent::Type(QEvent::User + 2));
5731 QCOMPARE(spy.eventList(), expected);
5735 // 2 children, but one is reparented away, then widget is shown
5738 widget.installEventFilter(&spy);
5740 QCoreApplication::postEvent(&widget, new QEvent(QEvent::Type(QEvent::User + 1)));
5742 QWidget child1(&widget);
5744 child2.setParent(&widget);
5745 child2.setParent(0);
5747 QCoreApplication::postEvent(&widget, new QEvent(QEvent::Type(QEvent::User + 2)));
5750 EventRecorder::EventList()
5751 << qMakePair(&widget, QEvent::ChildAdded)
5752 << qMakePair(&widget, QEvent::ChildAdded)
5753 << qMakePair(&widget, QEvent::ChildRemoved);
5754 QCOMPARE(spy.eventList(), expected);
5759 EventRecorder::EventList()
5760 << qMakePair(&widget, QEvent::WinIdChange)
5761 << qMakePair(&widget, QEvent::Polish)
5762 << qMakePair(&widget, QEvent::ChildPolished)
5763 << qMakePair(&widget, QEvent::Move)
5764 << qMakePair(&widget, QEvent::Resize)
5765 << qMakePair(&widget, QEvent::Show);
5767 expected << qMakePair(&widget, QEvent::ShowToParent);
5768 QCOMPARE(spy.eventList(), expected);
5771 QCoreApplication::sendPostedEvents();
5773 EventRecorder::EventList()
5774 << qMakePair(&widget, QEvent::PolishRequest)
5775 << qMakePair(&widget, QEvent::Type(QEvent::User + 1))
5776 << qMakePair(&widget, QEvent::Type(QEvent::User + 2));
5779 expected << qMakePair(&widget, QEvent::UpdateLater);
5781 expected << qMakePair(&widget, QEvent::UpdateRequest);
5783 QCOMPARE(spy.eventList(), expected);
5787 class RenderWidget : public QWidget
5790 RenderWidget(QWidget *source)
5791 : source(source), ellipse(false) {}
5793 void setEllipseEnabled(bool enable = true)
5800 void paintEvent(QPaintEvent *)
5803 QPainter painter(this);
5804 painter.fillRect(rect(), Qt::red);
5806 QRegion regionToRender = QRegion(0, 0, source->width(), source->height() / 2,
5808 source->render(this, QPoint(0, 30), regionToRender);
5810 source->render(this);
5819 void tst_QWidget::render()
5822 QCalendarWidget source;
5823 // disable anti-aliasing to eliminate potential differences when subpixel antialiasing
5824 // is enabled on the screen
5826 f.setStyleStrategy(QFont::NoAntialias);
5829 QTest::qWaitForWindowShown(&source);
5831 // Render the entire source into target.
5832 RenderWidget target(&source);
5833 target.resize(source.size());
5836 qApp->processEvents();
5837 qApp->sendPostedEvents();
5840 const QImage sourceImage = source.grab(QRect(QPoint(0, 0), QSize(-1, -1))).toImage();
5841 qApp->processEvents();
5842 QImage targetImage = target.grab(QRect(QPoint(0, 0), QSize(-1, -1))).toImage();
5843 qApp->processEvents();
5844 QCOMPARE(sourceImage, targetImage);
5846 // Fill target.rect() will Qt::red and render
5847 // QRegion(0, 0, source->width(), source->height() / 2, QRegion::Ellipse)
5848 // of source into target with offset (0, 30).
5849 target.setEllipseEnabled();
5850 qApp->processEvents();
5851 qApp->sendPostedEvents();
5853 targetImage = target.grab(QRect(QPoint(0, 0), QSize(-1, -1))).toImage();
5854 QVERIFY(sourceImage != targetImage);
5856 QCOMPARE(targetImage.pixel(target.width() / 2, 29), QColor(Qt::red).rgb());
5857 QCOMPARE(targetImage.pixel(target.width() / 2, 30), sourceImage.pixel(source.width() / 2, 0));
5859 // Test that a child widget properly fills its background
5862 window.resize(100, 100);
5863 // prevent custom styles
5864 window.setStyle(new QWindowsStyle);
5866 QTest::qWaitForWindowShown(&window);
5867 QWidget child(&window);
5868 child.resize(window.size());
5871 qApp->processEvents();
5872 const QPixmap childPixmap = child.grab(QRect(QPoint(0, 0), QSize(-1, -1)));
5873 const QPixmap windowPixmap = window.grab(QRect(QPoint(0, 0), QSize(-1, -1)));
5874 QCOMPARE(childPixmap, windowPixmap);
5877 { // Check that the target offset is correct.
5879 widget.resize(200, 200);
5880 widget.setAutoFillBackground(true);
5881 widget.setPalette(Qt::red);
5882 // prevent custom styles
5883 widget.setStyle(new QWindowsStyle);
5885 QTest::qWaitForWindowShown(&widget);
5886 QImage image(widget.size(), QImage::Format_RGB32);
5887 image.fill(QColor(Qt::blue).rgb());
5889 // Target offset (0, 0)
5890 widget.render(&image, QPoint(), QRect(20, 20, 100, 100));
5891 QCOMPARE(image.pixel(0, 0), QColor(Qt::red).rgb());
5892 QCOMPARE(image.pixel(99, 99), QColor(Qt::red).rgb());
5893 QCOMPARE(image.pixel(100, 100), QColor(Qt::blue).rgb());
5895 // Target offset (20, 20).
5896 image.fill(QColor(Qt::blue).rgb());
5897 widget.render(&image, QPoint(20, 20), QRect(20, 20, 100, 100));
5898 QCOMPARE(image.pixel(0, 0), QColor(Qt::blue).rgb());
5899 QCOMPARE(image.pixel(19, 19), QColor(Qt::blue).rgb());
5900 QCOMPARE(image.pixel(20, 20), QColor(Qt::red).rgb());
5901 QCOMPARE(image.pixel(119, 119), QColor(Qt::red).rgb());
5902 QCOMPARE(image.pixel(120, 120), QColor(Qt::blue).rgb());
5906 // On Windows the active palette is used instead of the inactive palette even
5907 // though the widget is invisible. This is probably related to task 178507/168682,
5908 // but for the renderInvisible test it doesn't matter, we're mostly interested
5909 // in testing the geometry so just workaround the palette issue for now.
5910 static void workaroundPaletteIssue(QWidget *widget)
5918 QWidget *navigationBar = qFindChild<QWidget *>(widget, QLatin1String("qt_calendar_navigationbar"));
5919 QVERIFY(navigationBar);
5921 QPalette palette = navigationBar->palette();
5922 const QColor background = palette.color(QPalette::Inactive, navigationBar->backgroundRole());
5923 const QColor highlightedText = palette.color(QPalette::Inactive, QPalette::HighlightedText);
5924 palette.setColor(QPalette::Active, navigationBar->backgroundRole(), background);
5925 palette.setColor(QPalette::Active, QPalette::HighlightedText, highlightedText);
5926 navigationBar->setPalette(palette);
5929 //#define RENDER_DEBUG
5930 void tst_QWidget::renderInvisible()
5932 QCalendarWidget *calendar = new QCalendarWidget;
5933 // disable anti-aliasing to eliminate potential differences when subpixel antialiasing
5934 // is enabled on the screen
5936 f.setStyleStrategy(QFont::NoAntialias);
5937 calendar->setFont(f);
5939 QTest::qWaitForWindowShown(calendar);
5941 // Create a dummy focus widget to get rid of focus rect in reference image.
5942 QLineEdit dummyFocusWidget;
5943 dummyFocusWidget.show();
5944 QTest::qWaitForWindowShown(&dummyFocusWidget);
5945 qApp->processEvents();
5948 // Create normal reference image.
5949 const QSize calendarSize = calendar->size();
5950 QImage referenceImage(calendarSize, QImage::Format_ARGB32);
5951 calendar->render(&referenceImage);
5953 referenceImage.save("referenceImage.png");
5955 QVERIFY(!referenceImage.isNull());
5957 // Create resized reference image.
5958 const QSize calendarSizeResized = calendar->size() + QSize(50, 50);
5959 calendar->resize(calendarSizeResized);
5960 qApp->processEvents();
5962 QImage referenceImageResized(calendarSizeResized, QImage::Format_ARGB32);
5963 calendar->render(&referenceImageResized);
5965 referenceImageResized.save("referenceImageResized.png");
5967 QVERIFY(!referenceImageResized.isNull());
5969 // Explicitly hide the calendar.
5971 qApp->processEvents();
5973 workaroundPaletteIssue(calendar);
5975 { // Make sure we get the same image when the calendar is explicitly hidden.
5976 QImage testImage(calendarSizeResized, QImage::Format_ARGB32);
5977 calendar->render(&testImage);
5979 testImage.save("explicitlyHiddenCalendarResized.png");
5981 QCOMPARE(testImage, referenceImageResized);
5984 // Now that we have reference images we can delete the source and re-create
5985 // the calendar and check that we get the same images from a calendar which has never
5986 // been visible, laid out or created (Qt::WA_WState_Created).
5988 calendar = new QCalendarWidget;
5989 calendar->setFont(f);
5990 workaroundPaletteIssue(calendar);
5992 { // Never been visible, created or laid out.
5993 QImage testImage(calendarSize, QImage::Format_ARGB32);
5994 calendar->render(&testImage);
5996 testImage.save("neverBeenVisibleCreatedOrLaidOut.png");
5998 QCOMPARE(testImage, referenceImage);
6002 qApp->processEvents();
6005 { // Calendar explicitly hidden.
6006 QImage testImage(calendarSize, QImage::Format_ARGB32);
6007 calendar->render(&testImage);
6009 testImage.save("explicitlyHiddenCalendar.png");
6011 QCOMPARE(testImage, referenceImage);
6014 // Get navigation bar and explicitly hide it.
6015 QWidget *navigationBar = qFindChild<QWidget *>(calendar, QLatin1String("qt_calendar_navigationbar"));
6016 QVERIFY(navigationBar);
6017 navigationBar->hide();
6019 { // Check that the navigation bar isn't drawn when rendering the entire calendar.
6020 QImage testImage(calendarSize, QImage::Format_ARGB32);
6021 calendar->render(&testImage);
6023 testImage.save("calendarWithoutNavigationBar.png");
6025 QVERIFY(testImage != referenceImage);
6028 { // Make sure the navigation bar renders correctly even though it's hidden.
6029 QImage testImage(navigationBar->size(), QImage::Format_ARGB32);
6030 navigationBar->render(&testImage);
6032 testImage.save("explicitlyHiddenNavigationBar.png");
6034 QCOMPARE(testImage, referenceImage.copy(navigationBar->rect()));
6037 // Get next month button.
6038 QWidget *nextMonthButton = qFindChild<QWidget *>(navigationBar, QLatin1String("qt_calendar_nextmonth"));
6039 QVERIFY(nextMonthButton);
6041 { // Render next month button.
6042 // Fill test image with correct background color.
6043 QImage testImage(nextMonthButton->size(), QImage::Format_ARGB32);
6044 navigationBar->render(&testImage, QPoint(), QRegion(), QWidget::RenderFlags());
6046 testImage.save("nextMonthButtonBackground.png");
6049 // Set the button's background color to Qt::transparent; otherwise it will fill the
6050 // background with QPalette::Window.
6051 const QPalette originalPalette = nextMonthButton->palette();
6052 QPalette palette = originalPalette;
6053 palette.setColor(QPalette::Window, Qt::transparent);
6054 nextMonthButton->setPalette(palette);
6056 // Render the button on top of the background.
6057 nextMonthButton->render(&testImage);
6059 testImage.save("nextMonthButton.png");
6061 const QRect buttonRect(nextMonthButton->mapTo(calendar, QPoint()), nextMonthButton->size());
6062 QCOMPARE(testImage, referenceImage.copy(buttonRect));
6065 nextMonthButton->setPalette(originalPalette);
6068 // Navigation bar isn't explicitly hidden anymore.
6069 navigationBar->show();
6070 qApp->processEvents();
6072 QVERIFY(!calendar->isVisible());
6074 // Now, completely mess up the layout. This will trigger an update on the layout
6075 // when the calendar is visible or shown, but it's not. QWidget::render must therefore
6076 // make sure the layout is activated before rendering.
6077 QVERIFY(!calendar->isVisible());
6078 calendar->resize(calendarSizeResized);
6079 qApp->processEvents();
6081 { // Make sure we get an image equal to the resized reference image.
6082 QImage testImage(calendarSizeResized, QImage::Format_ARGB32);
6083 calendar->render(&testImage);
6085 testImage.save("calendarResized.png");
6087 QCOMPARE(testImage, referenceImageResized);
6090 { // Make sure we lay out the widget correctly the first time it's rendered.
6091 QCalendarWidget calendar;
6092 const QSize calendarSize = calendar.sizeHint();
6094 QImage image(2 * calendarSize, QImage::Format_ARGB32);
6095 image.fill(QColor(Qt::red).rgb());
6096 calendar.render(&image);
6098 for (int i = calendarSize.height(); i < 2 * calendarSize.height(); ++i)
6099 for (int j = calendarSize.width(); j < 2 * calendarSize.width(); ++j)
6100 QCOMPARE(image.pixel(j, i), QColor(Qt::red).rgb());
6103 { // Ensure that we don't call adjustSize() on invisible top-levels if render() is called
6104 // right after widgets have been added/removed to/from its layout.
6106 topLevel.setLayout(new QVBoxLayout);
6108 QWidget *widget = new QLineEdit;
6109 topLevel.layout()->addWidget(widget);
6111 const QSize initialSize = topLevel.size();
6112 QPixmap pixmap(topLevel.sizeHint());
6113 topLevel.render(&pixmap); // triggers adjustSize()
6114 const QSize finalSize = topLevel.size();
6115 QVERIFY(finalSize != initialSize);
6117 topLevel.layout()->removeWidget(widget);
6118 QCOMPARE(topLevel.size(), finalSize);
6119 topLevel.render(&pixmap);
6120 QCOMPARE(topLevel.size(), finalSize);
6122 topLevel.layout()->addWidget(widget);
6123 QCOMPARE(topLevel.size(), finalSize);
6124 topLevel.render(&pixmap);
6125 QCOMPARE(topLevel.size(), finalSize);
6129 void tst_QWidget::renderWithPainter()
6132 // prevent custom styles
6133 widget.setStyle(new QWindowsStyle);
6135 widget.resize(70, 50);
6136 widget.setAutoFillBackground(true);
6137 widget.setPalette(Qt::black);
6139 // Render the entire widget onto the image.
6140 QImage image(QSize(70, 50), QImage::Format_ARGB32);
6141 image.fill(QColor(Qt::red).rgb());
6142 QPainter painter(&image);
6143 widget.render(&painter);
6145 for (int i = 0; i < image.height(); ++i) {
6146 for (int j = 0; j < image.width(); ++j)
6147 QCOMPARE(image.pixel(j, i), QColor(Qt::black).rgb());
6150 // Translate painter (10, 10).
6152 image.fill(QColor(Qt::red).rgb());
6153 painter.translate(10, 10);
6154 widget.render(&painter);
6157 for (int i = 0; i < image.height(); ++i) {
6158 for (int j = 0; j < image.width(); ++j) {
6159 if (i < 10 || j < 10)
6160 QCOMPARE(image.pixel(j, i), QColor(Qt::red).rgb());
6162 QCOMPARE(image.pixel(j, i), QColor(Qt::black).rgb());
6166 // Pass target offset (10, 10) (the same as QPainter::translate).
6167 image.fill(QColor(Qt::red).rgb());
6168 widget.render(&painter, QPoint(10, 10));
6170 for (int i = 0; i < image.height(); ++i) {
6171 for (int j = 0; j < image.width(); ++j) {
6172 if (i < 10 || j < 10)
6173 QCOMPARE(image.pixel(j, i), QColor(Qt::red).rgb());
6175 QCOMPARE(image.pixel(j, i), QColor(Qt::black).rgb());
6179 // Translate (10, 10) and pass target offset (10, 10).
6181 image.fill(QColor(Qt::red).rgb());
6182 painter.translate(10, 10);
6183 widget.render(&painter, QPoint(10, 10));
6186 for (int i = 0; i < image.height(); ++i) {
6187 for (int j = 0; j < image.width(); ++j) {
6188 if (i < 20 || j < 20)
6189 QCOMPARE(image.pixel(j, i), QColor(Qt::red).rgb());
6191 QCOMPARE(image.pixel(j, i), QColor(Qt::black).rgb());
6195 // Rotate painter 90 degrees.
6197 image.fill(QColor(Qt::red).rgb());
6199 widget.render(&painter);
6202 for (int i = 0; i < image.height(); ++i) {
6203 for (int j = 0; j < image.width(); ++j)
6204 QCOMPARE(image.pixel(j, i), QColor(Qt::red).rgb());
6207 // Translate and rotate.
6208 image.fill(QColor(Qt::red).rgb());
6209 widget.resize(40, 10);
6210 painter.translate(10, 10);
6212 widget.render(&painter);
6214 for (int i = 0; i < image.height(); ++i) {
6215 for (int j = 0; j < image.width(); ++j) {
6216 if (i >= 10 && j >= 0 && j < 10)
6217 QCOMPARE(image.pixel(j, i), QColor(Qt::black).rgb());
6219 QCOMPARE(image.pixel(j, i), QColor(Qt::red).rgb());
6223 // Make sure QWidget::render does not modify the render hints set on the painter.
6224 painter.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform
6225 | QPainter::NonCosmeticDefaultPen | QPainter::TextAntialiasing);
6226 QPainter::RenderHints oldRenderHints = painter.renderHints();
6227 widget.render(&painter);
6228 QCOMPARE(painter.renderHints(), oldRenderHints);
6231 void tst_QWidget::render_task188133()
6233 QMainWindow mainWindow;
6235 // Make sure QWidget::render does not trigger QWidget::repaint/update
6236 // and asserts for Qt::WA_WState_Created.
6237 const QPixmap pixmap = mainWindow.grab(QRect(QPoint(0, 0), QSize(-1, -1)));
6241 void tst_QWidget::render_task211796()
6243 class MyWidget : public QWidget
6245 void resizeEvent(QResizeEvent *)
6247 QPixmap pixmap(size());
6252 { // Please don't die in a resize recursion.
6254 widget.resize(200, 200);
6258 { // Same check with a deeper hierarchy.
6261 QWidget child(&widget);
6262 MyWidget grandChild;
6263 grandChild.setParent(&child);
6264 grandChild.resize(100, 100);
6269 void tst_QWidget::render_task217815()
6271 // Make sure we don't change the size of the widget when calling
6272 // render() and the widget has an explicit size set.
6273 // This was a problem on Windows because we called createWinId(),
6274 // which in turn enforced the size to be bigger than the smallest
6275 // possible native window size (which is (115,something) on WinXP).
6277 const QSize explicitSize(80, 20);
6278 widget.resize(explicitSize);
6279 QCOMPARE(widget.size(), explicitSize);
6281 QPixmap pixmap(explicitSize);
6282 widget.render(&pixmap);
6284 QCOMPARE(widget.size(), explicitSize);
6287 // Window Opacity is not supported on Windows CE.
6289 void tst_QWidget::render_windowOpacity()
6291 const qreal opacity = 0.5;
6293 { // Check that the painter opacity effects the widget drawing.
6295 QWidget child(&topLevel);
6296 child.resize(50, 50);
6297 child.setPalette(Qt::red);
6298 child.setAutoFillBackground(true);
6300 QPixmap expected(child.size());
6302 if (m_platform == QStringLiteral("xcb") && expected.depth() < 24)
6303 QSKIP("This test won't give correct results with dithered pixmaps");
6305 expected.fill(Qt::green);
6306 QPainter painter(&expected);
6307 painter.setOpacity(opacity);
6308 painter.fillRect(QRect(QPoint(0, 0), child.size()), Qt::red);
6311 QPixmap result(child.size());
6312 result.fill(Qt::green);
6313 painter.begin(&result);
6314 painter.setOpacity(opacity);
6315 child.render(&painter);
6317 QCOMPARE(result, expected);
6320 { // Combine the opacity set on the painter with the widget opacity.
6321 class MyWidget : public QWidget
6324 void paintEvent(QPaintEvent *)
6326 QPainter painter(this);
6327 painter.setOpacity(opacity);
6328 QCOMPARE(painter.opacity(), opacity);
6329 painter.fillRect(rect(), Qt::red);
6335 widget.resize(50, 50);
6336 widget.opacity = opacity;
6337 widget.setPalette(Qt::blue);
6338 widget.setAutoFillBackground(true);
6340 QPixmap expected(widget.size());
6341 expected.fill(Qt::green);
6342 QPainter painter(&expected);
6343 painter.setOpacity(opacity);
6344 QPixmap pixmap(widget.size());
6345 pixmap.fill(Qt::blue);
6346 QPainter pixmapPainter(&pixmap);
6347 pixmapPainter.setOpacity(opacity);
6348 pixmapPainter.fillRect(QRect(QPoint(), widget.size()), Qt::red);
6349 painter.drawPixmap(QPoint(), pixmap);
6352 QPixmap result(widget.size());
6353 result.fill(Qt::green);
6354 painter.begin(&result);
6355 painter.setOpacity(opacity);
6356 widget.render(&painter);
6358 QCOMPARE(result, expected);
6363 void tst_QWidget::render_systemClip()
6366 widget.setPalette(Qt::blue);
6367 widget.resize(100, 100);
6369 QImage image(widget.size(), QImage::Format_RGB32);
6370 image.fill(QColor(Qt::red).rgb());
6372 QPaintEngine *paintEngine = image.paintEngine();
6373 QVERIFY(paintEngine);
6374 paintEngine->setSystemClip(QRegion(0, 0, 50, 50));
6376 QPainter painter(&image);
6377 // Make sure we're using the same paint engine and has the right clip set.
6378 QCOMPARE(painter.paintEngine(), paintEngine);
6379 QCOMPARE(paintEngine->systemClip(), QRegion(0, 0, 50, 50));
6381 // Translate painter outside system clip.
6382 painter.translate(50, 0);
6383 widget.render(&painter);
6386 image.save("outside_systemclip.png");
6389 // All pixels should be red.
6390 for (int i = 0; i < image.height(); ++i) {
6391 for (int j = 0; j < image.width(); ++j)
6392 QCOMPARE(image.pixel(j, i), QColor(Qt::red).rgb());
6395 // Restore painter and refill image with red.
6396 image.fill(QColor(Qt::red).rgb());
6397 painter.translate(-50, 0);
6399 // Set transform on the painter.
6400 QTransform transform;
6401 transform.shear(0, 1);
6402 painter.setTransform(transform);
6403 widget.render(&painter);
6406 image.save("blue_triangle.png");
6409 // We should now have a blue triangle starting at scan line 1, and the rest should be red.
6419 for (int i = 0; i < image.height(); ++i) {
6420 for (int j = 0; j < image.width(); ++j) {
6421 if (i < 50 && j < i)
6422 QCOMPARE(image.pixel(j, i), QColor(Qt::blue).rgb());
6424 QCOMPARE(image.pixel(j, i), QColor(Qt::red).rgb());
6428 // We don't paint directly on the image on the Mac, so we cannot do the pixel comparison
6429 // as above due to QPainter::SmoothPixmapTransform. We therefore need to generate an
6430 // expected image by first painting on a pixmap, and then draw the pixmap onto
6431 // the image using QPainter::SmoothPixmapTransform. Then we can compare pixels :)
6432 // The check is basically the same, except that it takes the smoothening into account.
6433 QPixmap pixmap(50, 50);
6434 const QRegion sysClip(0, 0, 50, 50);
6435 widget.render(&pixmap, QPoint(), sysClip);
6437 QImage expectedImage(widget.size(), QImage::Format_RGB32);
6438 expectedImage.fill(QColor(Qt::red).rgb());
6439 expectedImage.paintEngine()->setSystemClip(sysClip);
6441 QPainter expectedImagePainter(&expectedImage);
6442 expectedImagePainter.setTransform(QTransform().shear(0, 1));
6443 // NB! This is the important part (SmoothPixmapTransform).
6444 expectedImagePainter.setRenderHints(QPainter::SmoothPixmapTransform);
6445 expectedImagePainter.drawPixmap(QPoint(0, 0), pixmap);
6446 expectedImagePainter.end();
6448 QCOMPARE(image, expectedImage);
6452 void tst_QWidget::render_systemClip2_data()
6454 QTest::addColumn<bool>("autoFillBackground");
6455 QTest::addColumn<bool>("usePaintEvent");
6456 QTest::addColumn<QColor>("expectedColor");
6458 QTest::newRow("Only auto-fill background") << true << false << QColor(Qt::blue);
6459 QTest::newRow("Only draw in paintEvent") << false << true << QColor(Qt::green);
6460 QTest::newRow("Auto-fill background and draw in paintEvent") << true << true << QColor(Qt::green);
6463 void tst_QWidget::render_systemClip2()
6465 QFETCH(bool, autoFillBackground);
6466 QFETCH(bool, usePaintEvent);
6467 QFETCH(QColor, expectedColor);
6469 QVERIFY2(expectedColor != QColor(Qt::red), "Qt::red is the reference color for the image, pick another color");
6471 class MyWidget : public QWidget
6475 void paintEvent(QPaintEvent *)
6478 QPainter(this).fillRect(rect(), Qt::green);
6483 widget.usePaintEvent = usePaintEvent;
6484 widget.setPalette(Qt::blue);
6485 // NB! widget.setAutoFillBackground(autoFillBackground) won't do the
6486 // trick here since the widget is a top-level. The background is filled
6487 // regardless, unless Qt::WA_OpaquePaintEvent or Qt::WA_NoSystemBackground
6488 // is set. We therefore use the opaque attribute to turn off auto-fill.
6489 if (!autoFillBackground)
6490 widget.setAttribute(Qt::WA_OpaquePaintEvent);
6491 widget.resize(100, 100);
6493 QImage image(widget.size(), QImage::Format_RGB32);
6494 image.fill(QColor(Qt::red).rgb());
6496 QPaintEngine *paintEngine = image.paintEngine();
6497 QVERIFY(paintEngine);
6499 QRegion systemClip(QRegion(50, 0, 50, 10));
6500 systemClip += QRegion(90, 10, 10, 40);
6501 paintEngine->setSystemClip(systemClip);
6503 // Render entire widget directly onto device.
6504 widget.render(&image);
6507 image.save("systemclip_with_device.png");
6509 // All pixels within the system clip should now be
6510 // the expectedColor, and the rest should be red.
6511 for (int i = 0; i < image.height(); ++i) {
6512 for (int j = 0; j < image.width(); ++j) {
6513 if (systemClip.contains(QPoint(j, i)))
6514 QCOMPARE(image.pixel(j, i), expectedColor.rgb());
6516 QCOMPARE(image.pixel(j, i), QColor(Qt::red).rgb());
6520 // Refill image with red.
6521 image.fill(QColor(Qt::red).rgb());
6522 paintEngine->setSystemClip(systemClip);
6524 // Do the same with an untransformed painter.
6525 QPainter painter(&image);
6526 //Make sure we're using the same paint engine and has the right clip set.
6527 QCOMPARE(painter.paintEngine(), paintEngine);
6528 QCOMPARE(paintEngine->systemClip(), systemClip);
6530 widget.render(&painter);
6533 image.save("systemclip_with_untransformed_painter.png");
6535 // All pixels within the system clip should now be
6536 // the expectedColor, and the rest should be red.
6537 for (int i = 0; i < image.height(); ++i) {
6538 for (int j = 0; j < image.width(); ++j) {
6539 if (systemClip.contains(QPoint(j, i)))
6540 QCOMPARE(image.pixel(j, i), expectedColor.rgb());
6542 QCOMPARE(image.pixel(j, i), QColor(Qt::red).rgb());
6547 void tst_QWidget::render_systemClip3_data()
6549 QTest::addColumn<QSize>("size");
6550 QTest::addColumn<bool>("useSystemClip");
6552 // Reference: http://en.wikipedia.org/wiki/Flag_of_Norway
6553 QTest::newRow("Norwegian Civil Flag") << QSize(220, 160) << false;
6554 QTest::newRow("Norwegian War Flag") << QSize(270, 160) << true;
6557 // This test ensures that the current engine clip (systemClip + painter clip)
6558 // is preserved after QPainter::setClipRegion(..., Qt::ReplaceClip);
6559 void tst_QWidget::render_systemClip3()
6561 QFETCH(QSize, size);
6562 QFETCH(bool, useSystemClip);
6564 // Calculate the inner/outer cross of the flag.
6565 QRegion outerCross(0, 0, size.width(), size.height());
6566 outerCross -= QRect(0, 0, 60, 60);
6567 outerCross -= QRect(100, 0, size.width() - 100, 60);
6568 outerCross -= QRect(0, 100, 60, 60);
6569 outerCross -= QRect(100, 100, size.width() - 100, 60);
6571 QRegion innerCross(0, 0, size.width(), size.height());
6572 innerCross -= QRect(0, 0, 70, 70);
6573 innerCross -= QRect(90, 0, size.width() - 90, 70);
6574 innerCross -= QRect(0, 90, 70, 70);
6575 innerCross -= QRect(90, 90, size.width() - 90, 70);
6577 const QRegion redArea(QRegion(0, 0, size.width(), size.height()) - outerCross);
6578 const QRegion whiteArea(outerCross - innerCross);
6579 const QRegion blueArea(innerCross);
6582 // Okay, here's the image that should look like a Norwegian civil/war flag in the end.
6583 QImage flag(size, QImage::Format_ARGB32);
6584 flag.fill(QColor(Qt::transparent).rgba());
6586 if (useSystemClip) {
6587 QPainterPath warClip(QPoint(size.width(), 0));
6588 warClip.lineTo(size.width() - 110, 60);
6589 warClip.lineTo(size.width(), 80);
6590 warClip.lineTo(size.width() - 110, 100);
6591 warClip.lineTo(size.width(), 160);
6592 warClip.closeSubpath();
6593 systemClip = QRegion(0, 0, size.width(), size.height()) - QRegion(warClip.toFillPolygon().toPolygon());
6594 flag.paintEngine()->setSystemClip(systemClip);
6597 QPainter painter(&flag);
6598 painter.fillRect(QRect(QPoint(), size), Qt::red); // Fill image background with red.
6599 painter.setClipRegion(outerCross); // Limit widget painting to inside the outer cross.
6601 // Here's the widget that's supposed to draw the inner/outer cross of the flag.
6602 // The outer cross (white) should be drawn when the background is auto-filled, and
6603 // the inner cross (blue) should be drawn in the paintEvent.
6604 class MyWidget : public QWidget
6606 void paintEvent(QPaintEvent *)
6608 QPainter painter(this);
6609 // Be evil and try to paint outside the outer cross. This should not be
6610 // possible since the shared painter is clipped to the outer cross.
6611 painter.setClipRect(0, 0, 60, 60, Qt::ReplaceClip);
6612 painter.fillRect(rect(), Qt::green);
6613 painter.setClipRegion(clip, Qt::ReplaceClip);
6614 painter.fillRect(rect(), Qt::blue);
6620 widget.clip = innerCross;
6621 widget.setFixedSize(size);
6622 widget.setPalette(Qt::white);
6623 widget.setAutoFillBackground(true);
6624 widget.render(&painter);
6627 flag.save("flag.png");
6630 // Let's make sure we got a Norwegian flag.
6631 for (int i = 0; i < flag.height(); ++i) {
6632 for (int j = 0; j < flag.width(); ++j) {
6633 const QPoint pixel(j, i);
6634 const QRgb pixelValue = flag.pixel(pixel);
6635 if (useSystemClip && !systemClip.contains(pixel))
6636 QCOMPARE(pixelValue, QColor(Qt::transparent).rgba());
6637 else if (redArea.contains(pixel))
6638 QCOMPARE(pixelValue, QColor(Qt::red).rgba());
6639 else if (whiteArea.contains(pixel))
6640 QCOMPARE(pixelValue, QColor(Qt::white).rgba());
6642 QCOMPARE(pixelValue, QColor(Qt::blue).rgba());
6647 void tst_QWidget::render_task252837()
6650 widget.resize(200, 200);
6652 QPixmap pixmap(widget.size());
6653 QPainter painter(&pixmap);
6654 // Please do not crash.
6655 widget.render(&painter);
6658 void tst_QWidget::render_worldTransform()
6660 class MyWidget : public QWidget
6662 void paintEvent(QPaintEvent *)
6664 QPainter painter(this);
6665 // Make sure world transform is identity.
6666 QCOMPARE(painter.worldTransform(), QTransform());
6668 // Make sure device transform is correct.
6669 const QPoint widgetOffset = geometry().topLeft();
6670 QTransform expectedDeviceTransform = QTransform::fromTranslate(105, 5);
6671 expectedDeviceTransform.rotate(90);
6672 expectedDeviceTransform.translate(widgetOffset.x(), widgetOffset.y());
6673 QCOMPARE(painter.deviceTransform(), expectedDeviceTransform);
6675 // Set new world transform.
6676 QTransform newWorldTransform = QTransform::fromTranslate(10, 10);
6677 newWorldTransform.rotate(90);
6678 painter.setWorldTransform(newWorldTransform);
6679 QCOMPARE(painter.worldTransform(), newWorldTransform);
6681 // Again, check device transform.
6682 expectedDeviceTransform.translate(10, 10);
6683 expectedDeviceTransform.rotate(90);
6684 QCOMPARE(painter.deviceTransform(), expectedDeviceTransform);
6686 painter.fillRect(QRect(0, 0, 20, 10), Qt::green);
6691 widget.setFixedSize(100, 100);
6692 widget.setPalette(Qt::red);
6693 widget.setAutoFillBackground(true);
6696 child.setParent(&widget);
6698 child.setFixedSize(50, 50);
6699 child.setPalette(Qt::blue);
6700 child.setAutoFillBackground(true);
6702 QImage image(QSize(110, 110), QImage::Format_RGB32);
6703 image.fill(QColor(Qt::black).rgb());
6705 QPainter painter(&image);
6706 painter.translate(105, 5);
6709 // Render widgets onto image.
6710 widget.render(&painter);
6712 image.save("render_worldTransform_image.png");
6715 // Ensure the transforms are unchanged after render.
6716 QCOMPARE(painter.worldTransform(), painter.worldTransform());
6717 QCOMPARE(painter.deviceTransform(), painter.deviceTransform());
6720 // Paint expected image.
6721 QImage expected(QSize(110, 110), QImage::Format_RGB32);
6722 expected.fill(QColor(Qt::black).rgb());
6724 QPainter expectedPainter(&expected);
6725 expectedPainter.translate(105, 5);
6726 expectedPainter.rotate(90);
6727 expectedPainter.save();
6728 expectedPainter.fillRect(widget.rect(),Qt::red);
6729 expectedPainter.translate(10, 10);
6730 expectedPainter.rotate(90);
6731 expectedPainter.fillRect(QRect(0, 0, 20, 10), Qt::green);
6732 expectedPainter.restore();
6733 expectedPainter.translate(50, 50);
6734 expectedPainter.fillRect(child.rect(),Qt::blue);
6735 expectedPainter.translate(10, 10);
6736 expectedPainter.rotate(90);
6737 expectedPainter.fillRect(QRect(0, 0, 20, 10), Qt::green);
6738 expectedPainter.end();
6741 expected.save("render_worldTransform_expected.png");
6744 QCOMPARE(image, expected);
6747 void tst_QWidget::setContentsMargins()
6749 QLabel label("why does it always rain on me?");
6750 QSize oldSize = label.sizeHint();
6751 label.setFrameStyle(QFrame::Sunken | QFrame::Box);
6752 QSize newSize = label.sizeHint();
6753 QVERIFY(oldSize != newSize);
6755 QLabel label2("why does it always rain on me?");
6757 label2.setFrameStyle(QFrame::Sunken | QFrame::Box);
6758 QCOMPARE(newSize, label2.sizeHint());
6760 QLabel label3("why does it always rain on me?");
6761 label3.setFrameStyle(QFrame::Sunken | QFrame::Box);
6762 QCOMPARE(newSize, label3.sizeHint());
6765 void tst_QWidget::moveWindowInShowEvent_data()
6767 QTest::addColumn<QPoint>("initial");
6768 QTest::addColumn<QPoint>("position");
6770 QPoint p = QApplication::desktop()->availableGeometry().topLeft();
6772 QTest::newRow("1") << p << (p + QPoint(10, 10));
6773 QTest::newRow("2") << (p + QPoint(10,10)) << p;
6776 void tst_QWidget::moveWindowInShowEvent()
6778 QFETCH(QPoint, initial);
6779 QFETCH(QPoint, position);
6781 class MoveWindowInShowEventWidget : public QWidget
6785 void showEvent(QShowEvent *)
6791 MoveWindowInShowEventWidget widget;
6792 widget.resize(QSize(qApp->desktop()->availableGeometry().size() / 3).expandedTo(QSize(1, 1)));
6793 // move to this position in showEvent()
6794 widget.position = position;
6796 // put the widget in it's starting position
6797 widget.move(initial);
6798 QCOMPARE(widget.pos(), initial);
6802 QTest::qWaitForWindowShown(widget.windowHandle());
6804 // it should have moved
6805 QCOMPARE(widget.pos(), position);
6808 void tst_QWidget::repaintWhenChildDeleted()
6811 if (QSysInfo::WindowsVersion & QSysInfo::WV_VISTA) {
6815 ColorWidget w(0, Qt::red);
6816 #if !defined(Q_OS_WINCE)
6817 QPoint startPoint = QApplication::desktop()->availableGeometry(&w).topLeft();
6818 startPoint.rx() += 50;
6819 startPoint.ry() += 50;
6820 w.setGeometry(QRect(startPoint, QSize(100, 100)));
6822 w.setGeometry(60, 60, 110, 110);
6825 QTest::qWaitForWindowShown(&w);
6827 QTRY_COMPARE(w.r, QRegion(w.rect()));
6831 ColorWidget child(&w, Qt::blue);
6832 child.setGeometry(10, 10, 10, 10);
6835 QTRY_COMPARE(child.r, QRegion(child.rect()));
6840 QTRY_COMPARE(w.r, QRegion(10, 10, 10, 10));
6844 void tst_QWidget::hideOpaqueChildWhileHidden()
6846 ColorWidget w(0, Qt::red);
6847 #if !defined(Q_OS_WINCE)
6848 QPoint startPoint = QApplication::desktop()->availableGeometry(&w).topLeft();
6849 startPoint.rx() += 50;
6850 startPoint.ry() += 50;
6851 w.setGeometry(QRect(startPoint, QSize(100, 100)));
6853 w.setGeometry(60, 60, 110, 110);
6856 ColorWidget child(&w, Qt::blue);
6857 child.setGeometry(10, 10, 80, 80);
6859 ColorWidget child2(&child, Qt::white);
6860 child2.setGeometry(10, 10, 60, 60);
6863 QTest::qWaitForWindowShown(&w);
6865 QTRY_COMPARE(child2.r, QRegion(child2.rect()));
6866 child.r = QRegion();
6867 child2.r = QRegion();
6874 QCOMPARE(w.r, QRegion(child.geometry()));
6878 QCOMPARE(child.r, QRegion(child.rect()));
6879 QCOMPARE(child2.r, QRegion());
6882 // This test doesn't make sense without support for showMinimized().
6883 #if !defined(Q_OS_WINCE)
6884 void tst_QWidget::updateWhileMinimized()
6886 UpdateWidget widget;
6887 // Filter out activation change and focus events to avoid update() calls in QWidget.
6888 widget.updateOnActivationChangeAndFocusIn = false;
6891 QTest::qWaitForWindowShown(&widget);
6892 QApplication::processEvents();
6893 QTRY_VERIFY(widget.numPaintEvents > 0);
6897 widget.showMinimized();
6902 // The widget is not visible on the screen (but isVisible() still returns true).
6903 // Make sure update requests are discarded until the widget is shown again.
6904 widget.update(0, 0, 50, 50);
6906 QCOMPARE(widget.numPaintEvents, 0);
6909 widget.showNormal();
6911 QTRY_COMPARE(widget.numPaintEvents, 1);
6912 QCOMPARE(widget.paintedRegion, QRegion(0, 0, 50, 50));
6916 class PaintOnScreenWidget: public QWidget
6919 PaintOnScreenWidget(QWidget *parent = 0, Qt::WindowFlags f = 0)
6923 #if defined(Q_OS_WIN)
6924 // This is the only way to enable PaintOnScreen on Windows.
6925 QPaintEngine * paintEngine () const {return 0;}
6929 void tst_QWidget::alienWidgets()
6931 if (m_platform != QStringLiteral("xcb") && m_platform != QStringLiteral("windows"))
6932 QSKIP("This test is only for X11/Windows.");
6934 qApp->setAttribute(Qt::AA_DontCreateNativeWidgetSiblings);
6936 QWidget child(&parent);
6937 QWidget grandChild(&child);
6938 QWidget greatGrandChild(&grandChild);
6941 QTest::qWaitForWindowShown(parent.windowHandle());
6943 // Verify that the WA_WState_Created attribute is set
6944 // and the top-level is the only native window.
6945 QVERIFY(parent.testAttribute(Qt::WA_WState_Created));
6946 QVERIFY(parent.internalWinId());
6948 QVERIFY(child.testAttribute(Qt::WA_WState_Created));
6949 QVERIFY(!child.internalWinId());
6951 QVERIFY(grandChild.testAttribute(Qt::WA_WState_Created));
6952 QVERIFY(!grandChild.internalWinId());
6954 QVERIFY(greatGrandChild.testAttribute(Qt::WA_WState_Created));
6955 QVERIFY(!greatGrandChild.internalWinId());
6957 // Enforce native windows all the way up in the parent hierarchy
6958 // if not WA_DontCreateNativeAncestors is set.
6959 grandChild.setAttribute(Qt::WA_DontCreateNativeAncestors);
6960 greatGrandChild.setAttribute(Qt::WA_NativeWindow);
6961 QVERIFY(greatGrandChild.internalWinId());
6962 QVERIFY(grandChild.internalWinId());
6963 QVERIFY(!child.internalWinId());
6966 // Ensure that hide() on an ancestor of a widget with
6967 // Qt::WA_DontCreateNativeAncestors still gets unmapped
6969 QWidget widget(&window);
6970 QWidget child(&widget);
6971 child.setAttribute(Qt::WA_NativeWindow);
6972 child.setAttribute(Qt::WA_DontCreateNativeAncestors);
6974 QVERIFY(child.testAttribute(Qt::WA_Mapped));
6976 QVERIFY(!child.testAttribute(Qt::WA_Mapped));
6979 // Enforce a native window when calling QWidget::winId.
6980 QVERIFY(child.winId());
6981 QVERIFY(child.internalWinId());
6983 // Check that paint on screen widgets (incl. children) are native.
6984 PaintOnScreenWidget paintOnScreen(&parent);
6985 QWidget paintOnScreenChild(&paintOnScreen);
6986 paintOnScreen.show();
6987 QVERIFY(paintOnScreen.testAttribute(Qt::WA_WState_Created));
6988 QVERIFY(!paintOnScreen.testAttribute(Qt::WA_NativeWindow));
6989 QVERIFY(!paintOnScreen.internalWinId());
6990 QVERIFY(!paintOnScreenChild.testAttribute(Qt::WA_NativeWindow));
6991 QVERIFY(!paintOnScreenChild.internalWinId());
6993 paintOnScreen.setAttribute(Qt::WA_PaintOnScreen);
6994 QVERIFY(paintOnScreen.testAttribute(Qt::WA_NativeWindow));
6995 QVERIFY(paintOnScreen.internalWinId());
6996 QVERIFY(paintOnScreenChild.testAttribute(Qt::WA_NativeWindow));
6997 QVERIFY(paintOnScreenChild.internalWinId());
6999 // Check that widgets with the Qt::MSWindowsOwnDC attribute set
7001 QWidget msWindowsOwnDC(&parent, Qt::MSWindowsOwnDC);
7002 msWindowsOwnDC.show();
7003 QVERIFY(msWindowsOwnDC.testAttribute(Qt::WA_WState_Created));
7004 QVERIFY(msWindowsOwnDC.testAttribute(Qt::WA_NativeWindow));
7005 QVERIFY(msWindowsOwnDC.internalWinId());
7007 { // Enforce a native window when calling QWidget::handle() (on X11) or QWidget::getDC() (on Windows).
7008 QWidget widget(&parent);
7010 QVERIFY(widget.testAttribute(Qt::WA_WState_Created));
7011 QVERIFY(!widget.internalWinId());
7014 QVERIFY(widget.internalWinId());
7017 if (m_platform == QStringLiteral("xcb")) {
7018 // Make sure we don't create native windows when setting Qt::WA_X11NetWmWindowType attributes
7019 // on alien widgets (see task 194231).
7021 QVERIFY(dummy.winId());
7022 QWidget widget(&dummy);
7023 widget.setAttribute(Qt::WA_X11NetWmWindowTypeToolBar);
7024 QVERIFY(!widget.internalWinId());
7027 { // Make sure we create native ancestors when setting Qt::WA_PaintOnScreen before show().
7029 QWidget child(&topLevel);
7030 QWidget grandChild(&child);
7031 PaintOnScreenWidget greatGrandChild(&grandChild);
7033 greatGrandChild.setAttribute(Qt::WA_PaintOnScreen);
7034 QVERIFY(!child.internalWinId());
7035 QVERIFY(!grandChild.internalWinId());
7036 QVERIFY(!greatGrandChild.internalWinId());
7039 QVERIFY(child.internalWinId());
7040 QVERIFY(grandChild.internalWinId());
7041 QVERIFY(greatGrandChild.internalWinId());
7044 { // Ensure that widgets reparented into Qt::WA_PaintOnScreen widgets become native.
7046 QWidget *widget = new PaintOnScreenWidget(&topLevel);
7047 widget->setAttribute(Qt::WA_PaintOnScreen);
7048 QWidget *child = new QWidget;
7049 QWidget *dummy = new QWidget(child);
7050 QWidget *grandChild = new QWidget(child);
7051 QWidget *dummy2 = new QWidget(grandChild);
7053 child->setParent(widget);
7055 QVERIFY(!topLevel.internalWinId());
7056 QVERIFY(!child->internalWinId());
7057 QVERIFY(!dummy->internalWinId());
7058 QVERIFY(!grandChild->internalWinId());
7059 QVERIFY(!dummy2->internalWinId());
7062 QVERIFY(topLevel.internalWinId());
7063 QVERIFY(widget->testAttribute(Qt::WA_NativeWindow));
7064 QVERIFY(child->internalWinId());
7065 QVERIFY(child->testAttribute(Qt::WA_NativeWindow));
7066 QVERIFY(!child->testAttribute(Qt::WA_PaintOnScreen));
7067 QVERIFY(!dummy->internalWinId());
7068 QVERIFY(!dummy->testAttribute(Qt::WA_NativeWindow));
7069 QVERIFY(!grandChild->internalWinId());
7070 QVERIFY(!grandChild->testAttribute(Qt::WA_NativeWindow));
7071 QVERIFY(!dummy2->internalWinId());
7072 QVERIFY(!dummy2->testAttribute(Qt::WA_NativeWindow));
7075 { // Ensure that ancestors of a Qt::WA_PaintOnScreen widget stay native
7076 // if they are re-created (typically in QWidgetPrivate::setParent_sys) (task 210822).
7078 QWidget child(&window);
7081 grandChild.setWindowTitle("This causes the widget to be created");
7083 PaintOnScreenWidget paintOnScreenWidget;
7084 paintOnScreenWidget.setAttribute(Qt::WA_PaintOnScreen);
7085 paintOnScreenWidget.setParent(&grandChild);
7087 grandChild.setParent(&child);
7091 QVERIFY(window.internalWinId());
7092 QVERIFY(child.internalWinId());
7093 QVERIFY(child.testAttribute(Qt::WA_NativeWindow));
7094 QVERIFY(grandChild.internalWinId());
7095 QVERIFY(grandChild.testAttribute(Qt::WA_NativeWindow));
7096 QVERIFY(paintOnScreenWidget.internalWinId());
7097 QVERIFY(paintOnScreenWidget.testAttribute(Qt::WA_NativeWindow));
7100 { // Ensure that all siblings are native unless Qt::AA_DontCreateNativeWidgetSiblings is set.
7101 qApp->setAttribute(Qt::AA_DontCreateNativeWidgetSiblings, false);
7103 QWidget *toolBar = new QWidget(&mainWindow);
7104 QWidget *dockWidget = new QWidget(&mainWindow);
7105 QWidget *centralWidget = new QWidget(&mainWindow);
7107 QWidget *button = new QWidget(centralWidget);
7108 QWidget *mdiArea = new QWidget(centralWidget);
7110 QWidget *horizontalScroll = new QWidget(mdiArea);
7111 QWidget *verticalScroll = new QWidget(mdiArea);
7112 QWidget *viewport = new QWidget(mdiArea);
7114 viewport->setAttribute(Qt::WA_NativeWindow);
7117 // Ensure that the viewport and its siblings are native:
7118 QVERIFY(verticalScroll->testAttribute(Qt::WA_NativeWindow));
7119 QVERIFY(verticalScroll->testAttribute(Qt::WA_NativeWindow));
7120 QVERIFY(horizontalScroll->testAttribute(Qt::WA_NativeWindow));
7122 // Ensure that the mdi area and its siblings are native:
7123 QVERIFY(mdiArea->testAttribute(Qt::WA_NativeWindow));
7124 QVERIFY(button->testAttribute(Qt::WA_NativeWindow));
7126 // Ensure that the central widget and its siblings are native:
7127 QVERIFY(centralWidget->testAttribute(Qt::WA_NativeWindow));
7128 QVERIFY(dockWidget->testAttribute(Qt::WA_NativeWindow));
7129 QVERIFY(toolBar->testAttribute(Qt::WA_NativeWindow));
7133 class ASWidget : public QWidget
7136 ASWidget(QSize sizeHint, QSizePolicy sizePolicy, bool layout, bool hfwLayout, QWidget *parent = 0)
7137 : QWidget(parent), mySizeHint(sizeHint)
7139 setSizePolicy(sizePolicy);
7141 QSizePolicy sp = QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
7142 sp.setHeightForWidth(hfwLayout);
7144 QVBoxLayout *vbox = new QVBoxLayout;
7146 vbox->addWidget(new ASWidget(sizeHint + QSize(30, 20), sp, false, false));
7151 QSize sizeHint() const {
7153 return layout()->totalSizeHint();
7156 int heightForWidth(int width) const {
7157 if (sizePolicy().hasHeightForWidth()) {
7167 void tst_QWidget::adjustSize_data()
7169 const int MagicW = 200;
7170 const int MagicH = 100;
7172 QTest::addColumn<QSize>("sizeHint");
7173 QTest::addColumn<int>("hPolicy");
7174 QTest::addColumn<int>("vPolicy");
7175 QTest::addColumn<bool>("hfwSP");
7176 QTest::addColumn<bool>("layout");
7177 QTest::addColumn<bool>("hfwLayout");
7178 QTest::addColumn<bool>("haveParent");
7179 QTest::addColumn<QSize>("expectedSize");
7181 QTest::newRow("1") << QSize(5, 6) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
7182 << false << false << false << false << QSize(5, qMax(6, MagicH));
7183 QTest::newRow("2") << QSize(5, 6) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
7184 << true << false << false << false << QSize(5, qMax(10, MagicH));
7185 QTest::newRow("3") << QSize(5, 6) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
7186 << false << true << false << false << QSize(35, 26);
7187 QTest::newRow("4") << QSize(5, 6) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
7188 << false << true << true << false << QSize(35, 70);
7189 QTest::newRow("5") << QSize(40001, 30001) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
7190 << false << false << false << false << QSize(100000, 100000);
7191 QTest::newRow("6") << QSize(40001, 30001) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
7192 << true << false << false << false << QSize(100000, 100000);
7193 QTest::newRow("7") << QSize(40001, 30001) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
7194 << false << true << false << false << QSize(100000, 100000);
7195 QTest::newRow("8") << QSize(40001, 30001) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
7196 << false << true << true << false << QSize(100000, 100000);
7197 QTest::newRow("9") << QSize(5, 6) << int(QSizePolicy::Expanding) << int(QSizePolicy::Minimum)
7198 << true << false << false << false << QSize(qMax(5, MagicW), 10);
7200 QTest::newRow("1c") << QSize(5, 6) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
7201 << false << false << false << true << QSize(5, 6);
7202 QTest::newRow("2c") << QSize(5, 6) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
7203 << true << false << false << true << QSize(5, 6 /* or 10 would be OK too, since hfw contradicts sizeHint() */);
7204 QTest::newRow("3c") << QSize(5, 6) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
7205 << false << true << false << true << QSize(35, 26);
7206 QTest::newRow("4c") << QSize(5, 6) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
7207 << false << true << true << true << QSize(35, 70);
7208 QTest::newRow("5c") << QSize(40001, 30001) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
7209 << false << false << false << true << QSize(40001, 30001);
7210 QTest::newRow("6c") << QSize(40001, 30001) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
7211 << true << false << false << true << QSize(40001, 30001 /* or 80002 would be OK too, since hfw contradicts sizeHint() */);
7212 QTest::newRow("7c") << QSize(40001, 30001) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
7213 << false << true << false << true << QSize(40001 + 30, 30001 + 20);
7214 QTest::newRow("8c") << QSize(40001, 30001) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
7215 << false << true << true << true << QSize(40001 + 30, 80002 + 60);
7216 QTest::newRow("9c") << QSize(5, 6) << int(QSizePolicy::Expanding) << int(QSizePolicy::Minimum)
7217 << true << false << false << true << QSize(5, 6);
7220 void tst_QWidget::adjustSize()
7222 QFETCH(QSize, sizeHint);
7223 QFETCH(int, hPolicy);
7224 QFETCH(int, vPolicy);
7225 QFETCH(bool, hfwSP);
7226 QFETCH(bool, layout);
7227 QFETCH(bool, hfwLayout);
7228 QFETCH(bool, haveParent);
7229 QFETCH(QSize, expectedSize);
7231 QWidget *parent = new QWidget;
7233 QSizePolicy sp = QSizePolicy(QSizePolicy::Policy(hPolicy), QSizePolicy::Policy(vPolicy));
7234 sp.setHeightForWidth(hfwSP);
7236 QWidget *child = new ASWidget(sizeHint, sp, layout, hfwLayout, haveParent ? parent : 0);
7237 child->resize(123, 456);
7238 child->adjustSize();
7239 if (expectedSize == QSize(100000, 100000)) {
7240 QVERIFY(child->size().width() < sizeHint.width());
7241 QVERIFY(child->size().height() < sizeHint.height());
7243 #if defined (Q_OS_WINCE)
7245 const QRect& desktopRect = qApp->desktop()->availableGeometry();
7246 expectedSize.setWidth(qMin(expectedSize.width(), desktopRect.width()));
7247 expectedSize.setHeight(qMin(expectedSize.height(), desktopRect.height()));
7250 QCOMPARE(child->size(), expectedSize);
7256 class TestLayout : public QVBoxLayout
7260 TestLayout(QWidget *w = 0) : QVBoxLayout(w)
7262 invalidated = false;
7273 void tst_QWidget::updateGeometry_data()
7275 QTest::addColumn<QSize>("minSize");
7276 QTest::addColumn<bool>("shouldInvalidate");
7277 QTest::addColumn<QSize>("maxSize");
7278 QTest::addColumn<bool>("shouldInvalidate2");
7279 QTest::addColumn<int>("verticalSizePolicy");
7280 QTest::addColumn<bool>("shouldInvalidate3");
7281 QTest::addColumn<bool>("setVisible");
7282 QTest::addColumn<bool>("shouldInvalidate4");
7284 QTest::newRow("setMinimumSize")
7285 << QSize(100, 100) << true
7287 << int(QSizePolicy::Preferred) << false
7289 QTest::newRow("setMaximumSize")
7291 << QSize(100, 100) << true
7292 << int(QSizePolicy::Preferred) << false
7294 QTest::newRow("setMinimumSize, then maximumSize to a different size")
7295 << QSize(100, 100) << true
7296 << QSize(300, 300) << true
7297 << int(QSizePolicy::Preferred) << false
7299 QTest::newRow("setMinimumSize, then maximumSize to the same size")
7300 << QSize(100, 100) << true
7301 << QSize(100, 100) << true
7302 << int(QSizePolicy::Preferred) << false
7304 QTest::newRow("setMinimumSize, then maximumSize to the same size and then hide it")
7305 << QSize(100, 100) << true
7306 << QSize(100, 100) << true
7307 << int(QSizePolicy::Preferred) << false
7309 QTest::newRow("Change sizePolicy")
7312 << int(QSizePolicy::Minimum) << true
7317 void tst_QWidget::updateGeometry()
7319 QFETCH(QSize, minSize);
7320 QFETCH(bool, shouldInvalidate);
7321 QFETCH(QSize, maxSize);
7322 QFETCH(bool, shouldInvalidate2);
7323 QFETCH(int, verticalSizePolicy);
7324 QFETCH(bool, shouldInvalidate3);
7325 QFETCH(bool, setVisible);
7326 QFETCH(bool, shouldInvalidate4);
7328 parent.resize(200, 200);
7329 TestLayout *lout = new TestLayout();
7330 parent.setLayout(lout);
7331 QWidget *child = new QWidget(&parent);
7332 lout->addWidget(child);
7334 QApplication::processEvents();
7336 lout->invalidated = false;
7337 if (minSize.isValid())
7338 child->setMinimumSize(minSize);
7339 QCOMPARE(lout->invalidated, shouldInvalidate);
7341 lout->invalidated = false;
7342 if (maxSize.isValid())
7343 child->setMaximumSize(maxSize);
7344 QCOMPARE(lout->invalidated, shouldInvalidate2);
7346 lout->invalidated = false;
7347 child->setSizePolicy(QSizePolicy(QSizePolicy::Preferred, (QSizePolicy::Policy)verticalSizePolicy));
7348 if (shouldInvalidate3)
7349 QCOMPARE(lout->invalidated, true);
7351 lout->invalidated = false;
7353 child->setVisible(false);
7354 QCOMPARE(lout->invalidated, shouldInvalidate4);
7357 void tst_QWidget::sendUpdateRequestImmediately()
7359 UpdateWidget updateWidget;
7360 updateWidget.show();
7362 QTest::qWaitForWindowShown(updateWidget.windowHandle());
7364 qApp->processEvents();
7365 updateWidget.reset();
7367 QCOMPARE(updateWidget.numUpdateRequestEvents, 0);
7368 updateWidget.repaint();
7369 QCOMPARE(updateWidget.numUpdateRequestEvents, 1);
7372 void tst_QWidget::doubleRepaint()
7374 #if defined(Q_OS_MAC)
7375 if (!macHasAccessToWindowsServer())
7376 QSKIP("Not having window server access causes the wrong number of repaints to be issues");
7378 UpdateWidget widget;
7379 widget.setFocusPolicy(Qt::StrongFocus);
7380 // Filter out activation change and focus events to avoid update() calls in QWidget.
7381 widget.updateOnActivationChangeAndFocusIn = false;
7384 int expectedRepaints = 1;
7386 QTest::qWaitForWindowShown(&widget);
7388 QTRY_COMPARE(widget.numPaintEvents, expectedRepaints);
7389 widget.numPaintEvents = 0;
7391 // Minmize: Should not trigger a repaint.
7392 widget.showMinimized();
7394 QCOMPARE(widget.numPaintEvents, 0);
7395 widget.numPaintEvents = 0;
7397 // Restore: Should not trigger a repaint.
7398 widget.showNormal();
7399 QTest::qWaitForWindowShown(&widget);
7401 QCOMPARE(widget.numPaintEvents, 0);
7404 void tst_QWidget::resizeInPaintEvent()
7407 UpdateWidget widget(&window);
7409 QTest::qWaitForWindowShown(&window);
7410 QTRY_VERIFY(widget.numPaintEvents > 0);
7413 QCOMPARE(widget.numPaintEvents, 0);
7415 widget.resizeInPaintEvent = true;
7416 // This will call resize in the paintEvent, which in turn will call
7417 // invalidateBuffer() and a new update request should be posted.
7419 QCOMPARE(widget.numPaintEvents, 1);
7420 widget.numPaintEvents = 0;
7423 // Make sure the resize triggers another update.
7424 QTRY_COMPARE(widget.numPaintEvents, 1);
7427 void tst_QWidget::opaqueChildren()
7430 widget.resize(200, 200);
7432 QWidget child(&widget);
7433 child.setGeometry(-700, -700, 200, 200);
7435 QWidget grandChild(&child);
7436 grandChild.resize(200, 200);
7438 QWidget greatGrandChild(&grandChild);
7439 greatGrandChild.setGeometry(50, 50, 200, 200);
7440 greatGrandChild.setPalette(Qt::red);
7441 greatGrandChild.setAutoFillBackground(true); // Opaque child widget.
7444 QTest::qWaitForWindowShown(widget.windowHandle());
7447 // Child, grandChild and greatGrandChild are outside the ancestor clip.
7448 QRegion expectedOpaqueRegion(50, 50, 150, 150);
7449 QCOMPARE(qt_widget_private(&grandChild)->getOpaqueChildren(), expectedOpaqueRegion);
7451 // Now they are all inside the ancestor clip.
7452 child.setGeometry(50, 50, 150, 150);
7453 QCOMPARE(qt_widget_private(&grandChild)->getOpaqueChildren(), expectedOpaqueRegion);
7455 // Set mask on greatGrandChild.
7456 const QRegion mask(10, 10, 50, 50);
7457 greatGrandChild.setMask(mask);
7458 expectedOpaqueRegion &= mask.translated(50, 50);
7459 QCOMPARE(qt_widget_private(&grandChild)->getOpaqueChildren(), expectedOpaqueRegion);
7461 // Make greatGrandChild "transparent".
7462 greatGrandChild.setAutoFillBackground(false);
7463 QCOMPARE(qt_widget_private(&grandChild)->getOpaqueChildren(), QRegion());
7467 class MaskSetWidget : public QWidget
7471 MaskSetWidget(QWidget* p =0)
7474 void paintEvent(QPaintEvent* event) {
7477 paintedRegion += event->region();
7478 foreach(QRect r, event->region().rects())
7479 p.fillRect(r, Qt::red);
7482 void resizeEvent(QResizeEvent*) {
7483 setMask(QRegion(QRect(0, 0, width(), 10).normalized()));
7486 QRegion paintedRegion;
7490 setGeometry(QRect(0, 50, 50, 50));
7494 setGeometry(QRect(0, 50, 150, 50));
7499 void tst_QWidget::setMaskInResizeEvent()
7504 w.setWindowFlags(Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint);
7507 MaskSetWidget testWidget(&w);
7508 testWidget.setGeometry(0, 0, 100, 100);
7509 testWidget.setMask(QRegion(QRect(0,0,100,10)));
7512 QTest::qWaitForWindowShown(&w);
7514 QTRY_VERIFY(w.numPaintEvents > 0);
7517 testWidget.paintedRegion = QRegion();
7518 QTimer::singleShot(0, &testWidget, SLOT(resizeDown()));
7521 QRegion expectedParentUpdate(0, 0, 100, 10); // Old testWidget area.
7522 expectedParentUpdate += testWidget.geometry(); // New testWidget area.
7523 QCOMPARE(w.paintedRegion, expectedParentUpdate);
7524 QCOMPARE(testWidget.paintedRegion, testWidget.mask());
7526 testWidget.paintedRegion = QRegion();
7527 // Now resize the widget again, but in the oposite direction
7528 QTimer::singleShot(0, &testWidget, SLOT(resizeUp()));
7531 QTRY_COMPARE(testWidget.paintedRegion, testWidget.mask());
7534 class MoveInResizeWidget : public QWidget
7538 MoveInResizeWidget(QWidget* p = 0)
7541 setWindowFlags(Qt::FramelessWindowHint);
7544 void resizeEvent(QResizeEvent*) {
7546 move(QPoint(100,100));
7548 static bool firstTime = true;
7550 QTimer::singleShot(250, this, SLOT(resizeMe()));
7561 void tst_QWidget::moveInResizeEvent()
7563 MoveInResizeWidget testWidget;
7564 testWidget.setGeometry(50, 50, 200, 200);
7566 QTest::qWaitForWindowShown(&testWidget);
7569 QRect expectedGeometry(100,100, 100, 100);
7570 QTRY_COMPARE(testWidget.geometry(), expectedGeometry);
7573 void tst_QWidget::immediateRepaintAfterShow()
7575 if (m_platform != QStringLiteral("xcb") && m_platform != QStringLiteral("windows"))
7576 QSKIP("We don't support immediate repaint right after show on other platforms.");
7578 UpdateWidget widget;
7580 qApp->processEvents();
7581 // On X11 in particular, we are now waiting for a MapNotify event before
7582 // syncing the backing store. However, if someone request a repaint()
7583 // we must repaint immediately regardless of the current state.
7584 widget.numPaintEvents = 0;
7586 QCOMPARE(widget.numPaintEvents, 1);
7589 void tst_QWidget::immediateRepaintAfterInvalidateBuffer()
7591 if (m_platform != QStringLiteral("xcb") && m_platform != QStringLiteral("windows"))
7592 QSKIP("We don't support immediate repaint right after show on other platforms.");
7594 QWidget *widget = new UpdateWidget;
7596 QTest::qWaitForWindowShown(widget->windowHandle());
7599 static_cast<UpdateWidget *>(widget)->numPaintEvents = 0;
7601 // Marks the area covered by the widget as dirty in the backing store and
7602 // posts an UpdateRequest event.
7603 qt_widget_private(widget)->invalidateBuffer(widget->rect());
7604 QCOMPARE(static_cast<UpdateWidget *>(widget)->numPaintEvents, 0);
7606 // The entire widget is already dirty, but this time we want to update immediately
7607 // by calling repaint(), and thus we have to repaint the widget and not wait for
7608 // the UpdateRequest to be sent when we get back to the event loop.
7610 QCOMPARE(static_cast<UpdateWidget *>(widget)->numPaintEvents, 1);
7615 void tst_QWidget::effectiveWinId()
7618 QWidget child(&parent);
7621 QVERIFY(!parent.effectiveWinId());
7622 QVERIFY(!child.effectiveWinId());
7626 QVERIFY(parent.effectiveWinId());
7627 QVERIFY(child.effectiveWinId());
7630 void tst_QWidget::effectiveWinId2()
7634 class MyWidget : public QWidget {
7635 bool event(QEvent *e)
7637 if (e->type() == QEvent::WinIdChange) {
7642 return QWidget::event(e);
7647 child.setParent(&parent);
7651 child.setParent(&parent);
7654 class CustomWidget : public QWidget
7657 mutable int metricCallCount;
7659 CustomWidget(QWidget *parent = 0) : QWidget(parent), metricCallCount(0) {}
7661 virtual int metric(PaintDeviceMetric metric) const {
7663 return QWidget::metric(metric);
7667 void tst_QWidget::customDpi()
7669 QWidget *topLevel = new QWidget;
7670 CustomWidget *custom = new CustomWidget(topLevel);
7671 QWidget *child = new QWidget(custom);
7673 custom->metricCallCount = 0;
7674 topLevel->logicalDpiX();
7675 QCOMPARE(custom->metricCallCount, 0);
7676 custom->logicalDpiX();
7677 QCOMPARE(custom->metricCallCount, 1);
7678 child->logicalDpiX();
7679 QCOMPARE(custom->metricCallCount, 2);
7684 void tst_QWidget::customDpiProperty()
7686 QWidget *topLevel = new QWidget;
7687 QWidget *middle = new CustomWidget(topLevel);
7688 QWidget *child = new QWidget(middle);
7690 const int initialDpiX = topLevel->logicalDpiX();
7691 const int initialDpiY = topLevel->logicalDpiY();
7693 middle->setProperty("_q_customDpiX", 300);
7694 middle->setProperty("_q_customDpiY", 400);
7696 QCOMPARE(topLevel->logicalDpiX(), initialDpiX);
7697 QCOMPARE(topLevel->logicalDpiY(), initialDpiY);
7699 QCOMPARE(middle->logicalDpiX(), 300);
7700 QCOMPARE(middle->logicalDpiY(), 400);
7702 QCOMPARE(child->logicalDpiX(), 300);
7703 QCOMPARE(child->logicalDpiY(), 400);
7705 middle->setProperty("_q_customDpiX", QVariant());
7706 middle->setProperty("_q_customDpiY", QVariant());
7708 QCOMPARE(topLevel->logicalDpiX(), initialDpiX);
7709 QCOMPARE(topLevel->logicalDpiY(), initialDpiY);
7711 QCOMPARE(middle->logicalDpiX(), initialDpiX);
7712 QCOMPARE(middle->logicalDpiY(), initialDpiY);
7714 QCOMPARE(child->logicalDpiX(), initialDpiX);
7715 QCOMPARE(child->logicalDpiY(), initialDpiY);
7720 void tst_QWidget::quitOnCloseAttribute()
7723 QCOMPARE(w.testAttribute(Qt::WA_QuitOnClose), true);
7724 w.setAttribute(Qt::WA_QuitOnClose, false);
7725 QCOMPARE(w.testAttribute(Qt::WA_QuitOnClose), false);
7727 w.setAttribute(Qt::WA_QuitOnClose);
7728 w.setWindowFlags(Qt::Tool);
7729 QCOMPARE(w.testAttribute(Qt::WA_QuitOnClose), false);
7731 w.setAttribute(Qt::WA_QuitOnClose);
7732 w.setWindowFlags(Qt::Popup);
7733 QCOMPARE(w.testAttribute(Qt::WA_QuitOnClose), false);
7735 w.setAttribute(Qt::WA_QuitOnClose);
7736 w.setWindowFlags(Qt::ToolTip);
7737 QCOMPARE(w.testAttribute(Qt::WA_QuitOnClose), false);
7739 w.setAttribute(Qt::WA_QuitOnClose);
7740 w.setWindowFlags(Qt::SplashScreen);
7741 QCOMPARE(w.testAttribute(Qt::WA_QuitOnClose), false);
7743 w.setAttribute(Qt::WA_QuitOnClose);
7744 w.setWindowFlags(Qt::SubWindow);
7745 QCOMPARE(w.testAttribute(Qt::WA_QuitOnClose), false);
7747 w.setAttribute(Qt::WA_QuitOnClose);
7748 w.setWindowFlags(Qt::Dialog);
7749 QCOMPARE(w.testAttribute(Qt::WA_QuitOnClose), true);
7751 QCOMPARE(w.testAttribute(Qt::WA_QuitOnClose), true);
7752 w.setWindowFlags(Qt::Tool);
7753 QCOMPARE(w.testAttribute(Qt::WA_QuitOnClose), false);
7756 void tst_QWidget::moveRect()
7759 widget.setUpdatesEnabled(false);
7760 QWidget child(&widget);
7761 child.setUpdatesEnabled(false);
7762 child.setAttribute(Qt::WA_OpaquePaintEvent);
7765 child.move(10, 10); // Don't crash.
7769 class GDIWidget : public QDialog
7773 GDIWidget() { setAttribute(Qt::WA_PaintOnScreen); }
7774 QPaintEngine *paintEngine() const { return 0; }
7777 void paintEvent(QPaintEvent *) {
7778 QPlatformNativeInterface *ni = QGuiApplication::platformNativeInterface();
7779 const HDC hdc = (HDC)ni->nativeResourceForWindow(QByteArrayLiteral("getDC"), windowHandle());
7781 qWarning("%s: Unable to obtain native DC.", Q_FUNC_INFO);
7782 QTimer::singleShot(0, this, SLOT(reject()));
7785 SelectObject(hdc, CreateSolidBrush(RGB(255, 0, 0)));
7786 Rectangle(hdc, 0, 0, 10, 10);
7788 ni->nativeResourceForWindow(QByteArrayLiteral("releaseDC"), windowHandle());
7790 QTimer::singleShot(0, this, SLOT(slotTimer()));
7793 QSize sizeHint() const {
7794 return QSize(400, 300);
7799 QScreen *screen = windowHandle()->screen();
7800 const QImage im = screen->grabWindow(internalWinId(), 0, 0, -1, -1).toImage();
7801 color = im.pixel(1, 1);
7809 void tst_QWidget::gdiPainting()
7814 QCOMPARE(w.color, QColor(255, 0, 0));
7818 void tst_QWidget::paintOnScreenPossible()
7821 w1.setAttribute(Qt::WA_PaintOnScreen);
7822 QVERIFY(!w1.testAttribute(Qt::WA_PaintOnScreen));
7825 w2.setAttribute(Qt::WA_PaintOnScreen);
7826 QVERIFY(w2.testAttribute(Qt::WA_PaintOnScreen));
7830 void tst_QWidget::reparentStaticWidget()
7834 QWidget *child = new QWidget(&window1);
7835 child->setPalette(Qt::red);
7836 child->setAutoFillBackground(true);
7837 child->setAttribute(Qt::WA_StaticContents);
7838 child->resize(100, 100);
7840 QWidget *grandChild = new QWidget(child);
7841 grandChild->setPalette(Qt::blue);
7842 grandChild->setAutoFillBackground(true);
7843 grandChild->resize(50, 50);
7844 grandChild->setAttribute(Qt::WA_StaticContents);
7846 QTest::qWaitForWindowShown(&window1);
7850 QTest::qWaitForWindowShown(&window2);
7853 // Reparent into another top-level.
7854 child->setParent(&window2);
7857 // Please don't crash.
7858 window1.resize(window1.size() + QSize(2, 2));
7861 // Make sure we move all static children even though
7862 // the reparented widget itself is non-static.
7863 child->setAttribute(Qt::WA_StaticContents, false);
7864 child->setParent(&window1);
7867 // Please don't crash.
7868 window2.resize(window2.size() + QSize(2, 2));
7871 child->setParent(0);
7875 // Please don't crash.
7876 child->resize(child->size() + QSize(2, 2));
7877 window2.resize(window2.size() + QSize(2, 2));
7880 QWidget *siblingOfGrandChild = new QWidget(child);
7881 siblingOfGrandChild->show();
7884 // Nothing should happen when reparenting within the same top-level.
7885 grandChild->setParent(siblingOfGrandChild);
7889 QWidget paintOnScreen;
7890 paintOnScreen.setAttribute(Qt::WA_PaintOnScreen);
7891 paintOnScreen.show();
7892 QTest::qWaitForWindowShown(&paintOnScreen);
7895 child->setParent(&paintOnScreen);
7899 // Please don't crash.
7900 paintOnScreen.resize(paintOnScreen.size() + QSize(2, 2));
7905 void tst_QWidget::QTBUG6883_reparentStaticWidget2()
7908 QDockWidget *one = new QDockWidget("one", &mw);
7909 mw.addDockWidget(Qt::LeftDockWidgetArea, one , Qt::Vertical);
7911 QWidget *child = new QWidget();
7912 child->setPalette(Qt::red);
7913 child->setAutoFillBackground(true);
7914 child->setAttribute(Qt::WA_StaticContents);
7915 child->resize(100, 100);
7916 one->setWidget(child);
7918 QToolBar *mainTools = mw.addToolBar("Main Tools");
7919 mainTools->addWidget(new QLineEdit);
7922 QTest::qWaitForWindowShown(&mw);
7924 one->setFloating(true);
7929 class ColorRedWidget : public QWidget
7932 ColorRedWidget(QWidget *parent = 0)
7933 : QWidget(parent, Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint | Qt::ToolTip)
7937 void paintEvent(QPaintEvent *) {
7939 p.fillRect(rect(),Qt::red);
7943 void tst_QWidget::translucentWidget()
7947 ColorRedWidget label;
7948 label.setFixedSize(16,16);
7949 label.setAttribute(Qt::WA_TranslucentBackground);
7950 const QPoint labelPos = qApp->desktop()->availableGeometry().topLeft();
7951 label.move(labelPos);
7953 QTest::qWaitForWindowShown(label.windowHandle());
7956 QPixmap widgetSnapshot;
7959 QWidget *desktopWidget = QApplication::desktop()->screen(0);
7960 if (QSysInfo::windowsVersion() >= QSysInfo::WV_VISTA)
7961 widgetSnapshot = qApp->primaryScreen()->grabWindow(desktopWidget->winId(), labelPos.x(), labelPos.y(), label.width(), label.height());
7964 widgetSnapshot = label.grab(QRect(QPoint(0, 0), label.size()));
7965 QImage actual = widgetSnapshot.toImage().convertToFormat(QImage::Format_RGB32);
7966 QImage expected = pm.toImage().convertToFormat(QImage::Format_RGB32);
7967 QCOMPARE(actual.size(),expected.size());
7968 QCOMPARE(actual,expected);
7971 class MaskResizeTestWidget : public QWidget
7975 MaskResizeTestWidget(QWidget* p =0)
7977 setMask(QRegion(QRect(0, 0, 100, 100).normalized()));
7980 void paintEvent(QPaintEvent* event) {
7983 paintedRegion += event->region();
7984 foreach(QRect r, event->region().rects())
7985 p.fillRect(r, Qt::red);
7988 QRegion paintedRegion;
7991 void enlargeMask() {
7992 QRegion newMask(QRect(0, 0, 150, 150).normalized());
7997 QRegion newMask(QRect(0, 0, 50, 50).normalized());
8003 void tst_QWidget::setClearAndResizeMask()
8005 UpdateWidget topLevel;
8006 topLevel.resize(150, 150);
8008 QTest::qWaitForWindowShown(&topLevel);
8009 QTRY_VERIFY(topLevel.numPaintEvents > 0);
8012 // Mask top-level widget
8013 const QRegion topLevelMask(0, 0, 100, 100, QRegion::Ellipse);
8014 topLevel.setMask(topLevelMask);
8015 QCOMPARE(topLevel.mask(), topLevelMask);
8016 // Ensure that the top-level doesn't get any update.
8017 // We don't control what's happening on platforms other than X11, Windows
8018 if (m_platform == QStringLiteral("xcb") || m_platform == QStringLiteral("windows"))
8019 QCOMPARE(topLevel.numPaintEvents, 0);
8023 // Clear top-level mask
8024 topLevel.clearMask();
8025 QCOMPARE(topLevel.mask(), QRegion());
8027 QRegion outsideOldMask(topLevel.rect());
8028 outsideOldMask -= topLevelMask;
8029 // Ensure that the top-level gets an update for the area outside the old mask.
8030 // We don't control what's happening on platforms other than X11, Windows
8031 if (m_platform == QStringLiteral("xcb") || m_platform == QStringLiteral("windows")) {
8032 QTRY_VERIFY(topLevel.numPaintEvents > 0);
8033 QTRY_COMPARE(topLevel.paintedRegion, outsideOldMask);
8036 UpdateWidget child(&topLevel);
8037 child.setAutoFillBackground(true); // NB! Opaque child.
8038 child.setPalette(Qt::red);
8039 child.resize(100, 100);
8046 // Mask child widget with a mask that is smaller than the rect
8047 const QRegion childMask(0, 0, 50, 50);
8048 child.setMask(childMask);
8049 QTRY_COMPARE(child.mask(), childMask);
8051 // and ensure that the child widget doesn't get any update.
8053 // Mac always issues a full update when calling setMask, and we cannot force it to not do so.
8054 if (child.internalWinId())
8055 QCOMPARE(child.numPaintEvents, 1);
8058 QCOMPARE(child.numPaintEvents, 0);
8059 // and the parent widget gets an update for the newly exposed area.
8060 QTRY_COMPARE(topLevel.numPaintEvents, 1);
8061 QRegion expectedParentExpose(child.rect());
8062 expectedParentExpose -= childMask;
8063 QCOMPARE(topLevel.paintedRegion, expectedParentExpose);
8068 // Clear child widget mask
8070 QTRY_COMPARE(child.mask(), QRegion());
8072 // and ensure that that the child widget gets an update for the area outside the old mask.
8073 QTRY_COMPARE(child.numPaintEvents, 1);
8074 outsideOldMask = child.rect();
8076 // Mac always issues a full update when calling setMask, and we cannot force it to not do so.
8077 if (!child.internalWinId())
8079 outsideOldMask -= childMask;
8080 QCOMPARE(child.paintedRegion, outsideOldMask);
8081 // and the parent widget doesn't get any update.
8082 QCOMPARE(topLevel.numPaintEvents, 0);
8087 // Mask child widget with a mask that is bigger than the rect
8088 child.setMask(QRegion(0, 0, 1000, 1000));
8091 // Mac always issues a full update when calling setMask, and we cannot force it to not do so.
8092 if (child.internalWinId())
8093 QTRY_COMPARE(child.numPaintEvents, 1);
8096 // and ensure that we don't get any updates at all.
8097 QTRY_COMPARE(child.numPaintEvents, 0);
8098 QCOMPARE(topLevel.numPaintEvents, 0);
8100 // ...and the same applies when clearing the mask.
8104 // Mac always issues a full update when calling setMask, and we cannot force it to not do so.
8105 if (child.internalWinId())
8106 QTRY_VERIFY(child.numPaintEvents > 0);
8109 QCOMPARE(child.numPaintEvents, 0);
8110 QCOMPARE(topLevel.numPaintEvents, 0);
8112 QWidget resizeParent;
8113 MaskResizeTestWidget resizeChild(&resizeParent);
8115 resizeParent.resize(300,300);
8116 resizeParent.raise();
8117 resizeParent.setWindowFlags(Qt::WindowStaysOnTopHint);
8118 resizeChild.setGeometry(50,50,200,200);
8119 QPalette pal = resizeParent.palette();
8120 pal.setColor(QPalette::Window, QColor(Qt::white));
8121 resizeParent.setPalette(pal);
8123 resizeParent.show();
8124 QTest::qWaitForWindowShown(&resizeParent);
8125 // Disable the size grip on the Mac; otherwise it'll be included when grabbing the window.
8126 resizeParent.setFixedSize(resizeParent.size());
8129 resizeChild.paintedRegion = QRegion();
8131 QTimer::singleShot(100, &resizeChild, SLOT(shrinkMask()));
8134 // Mac always issues a full update when calling setMask, and we cannot force it to not do so.
8135 if (child.internalWinId())
8136 QTRY_COMPARE(resizeChild.paintedRegion, resizeChild.mask());
8139 QTRY_COMPARE(resizeChild.paintedRegion, QRegion());
8141 resizeChild.paintedRegion = QRegion();
8142 const QRegion oldMask = resizeChild.mask();
8143 QTimer::singleShot(0, &resizeChild, SLOT(enlargeMask()));
8146 // Mac always issues a full update when calling setMask, and we cannot force it to not do so.
8147 if (child.internalWinId())
8148 QTRY_COMPARE(resizeChild.paintedRegion, resizeChild.mask());
8151 QTRY_COMPARE(resizeChild.paintedRegion, resizeChild.mask() - oldMask);
8154 void tst_QWidget::maskedUpdate()
8156 UpdateWidget topLevel;
8157 topLevel.resize(200, 200);
8158 const QRegion topLevelMask(50, 50, 70, 70);
8159 topLevel.setMask(topLevelMask);
8161 UpdateWidget child(&topLevel);
8162 child.setGeometry(20, 20, 180, 180);
8163 const QRegion childMask(60, 60, 30, 30);
8164 child.setMask(childMask);
8166 UpdateWidget grandChild(&child);
8167 grandChild.setGeometry(50, 50, 100, 100);
8168 const QRegion grandChildMask(20, 20, 10, 10);
8169 grandChild.setMask(grandChildMask);
8172 QTest::qWaitForWindowShown(&topLevel);
8173 QTRY_VERIFY(topLevel.numPaintEvents > 0);
8176 #define RESET_WIDGETS \
8181 #define CLEAR_MASK(widget) \
8182 widget.clearMask(); \
8183 QTest::qWait(100); \
8186 // All widgets are transparent at this point, so any call to update() will result
8187 // in composition, i.e. the update propagates to ancestors and children.
8194 QTRY_COMPARE(topLevel.paintedRegion, topLevelMask);
8195 QTRY_COMPARE(child.paintedRegion, childMask);
8196 QTRY_COMPARE(grandChild.paintedRegion, grandChildMask);
8203 QTRY_COMPARE(topLevel.paintedRegion, childMask.translated(child.pos()));
8204 QTRY_COMPARE(child.paintedRegion, childMask);
8205 QTRY_COMPARE(grandChild.paintedRegion, grandChildMask);
8207 // GrandChild update.
8209 grandChild.update();
8212 QTRY_COMPARE(topLevel.paintedRegion, grandChildMask.translated(grandChild.mapTo(&topLevel, QPoint())));
8213 QTRY_COMPARE(child.paintedRegion, grandChildMask.translated(grandChild.pos()));
8214 QTRY_COMPARE(grandChild.paintedRegion, grandChildMask);
8216 topLevel.setAttribute(Qt::WA_OpaquePaintEvent);
8217 child.setAttribute(Qt::WA_OpaquePaintEvent);
8218 grandChild.setAttribute(Qt::WA_OpaquePaintEvent);
8220 // All widgets are now opaque, which means no composition, i.e.
8221 // the update does not propate to ancestors and children.
8228 QRegion expectedTopLevelUpdate = topLevelMask;
8229 expectedTopLevelUpdate -= childMask.translated(child.pos()); // Subtract opaque children.
8230 QTRY_COMPARE(topLevel.paintedRegion, expectedTopLevelUpdate);
8231 QTRY_COMPARE(child.paintedRegion, QRegion());
8232 QTRY_COMPARE(grandChild.paintedRegion, QRegion());
8239 QTRY_COMPARE(topLevel.paintedRegion, QRegion());
8240 QRegion expectedChildUpdate = childMask;
8241 expectedChildUpdate -= grandChildMask.translated(grandChild.pos()); // Subtract oapque children.
8242 QTRY_COMPARE(child.paintedRegion, expectedChildUpdate);
8243 QTRY_COMPARE(grandChild.paintedRegion, QRegion());
8245 // GrandChild update.
8247 grandChild.update();
8250 QTRY_COMPARE(topLevel.paintedRegion, QRegion());
8251 QTRY_COMPARE(child.paintedRegion, QRegion());
8252 QTRY_COMPARE(grandChild.paintedRegion, grandChildMask);
8254 // GrandChild update.
8255 CLEAR_MASK(grandChild);
8256 grandChild.update();
8259 QTRY_COMPARE(topLevel.paintedRegion, QRegion());
8260 QTRY_COMPARE(child.paintedRegion, QRegion());
8261 QRegion expectedGrandChildUpdate = grandChild.rect();
8262 // Clip with parent's mask.
8263 expectedGrandChildUpdate &= childMask.translated(-grandChild.pos());
8264 QCOMPARE(grandChild.paintedRegion, expectedGrandChildUpdate);
8266 // GrandChild update.
8268 grandChild.update();
8271 QTRY_COMPARE(topLevel.paintedRegion, QRegion());
8272 QTRY_COMPARE(child.paintedRegion, QRegion());
8273 expectedGrandChildUpdate = grandChild.rect();
8274 // Clip with parent's mask.
8275 expectedGrandChildUpdate &= topLevelMask.translated(-grandChild.mapTo(&topLevel, QPoint()));
8276 QTRY_COMPARE(grandChild.paintedRegion, expectedGrandChildUpdate);
8283 QTRY_COMPARE(topLevel.paintedRegion, QRegion());
8284 expectedChildUpdate = child.rect();
8285 // Clip with parent's mask.
8286 expectedChildUpdate &= topLevelMask.translated(-child.pos());
8287 expectedChildUpdate -= grandChild.geometry(); // Subtract opaque children.
8288 QTRY_COMPARE(child.paintedRegion, expectedChildUpdate);
8289 QTRY_COMPARE(grandChild.paintedRegion, QRegion());
8291 // GrandChild update.
8292 CLEAR_MASK(topLevel);
8293 grandChild.update();
8296 QTRY_COMPARE(topLevel.paintedRegion, QRegion());
8297 QTRY_COMPARE(child.paintedRegion, QRegion());
8298 QTRY_COMPARE(grandChild.paintedRegion, QRegion(grandChild.rect())); // Full update.
8301 // Windows Mobile has no proper cursor support, so skip this test on that platform.
8302 #if !defined(Q_OS_WINCE_WM)
8303 void tst_QWidget::syntheticEnterLeave()
8305 class MyWidget : public QWidget
8308 MyWidget(QWidget *parent = 0) : QWidget(parent), numEnterEvents(0), numLeaveEvents(0) {}
8309 void enterEvent(QEvent *) { ++numEnterEvents; }
8310 void leaveEvent(QEvent *) { ++numLeaveEvents; }
8315 QCursor::setPos(QPoint(0,0));
8318 window.setWindowFlags(Qt::WindowStaysOnTopHint);
8319 window.resize(200, 200);
8321 MyWidget *child1 = new MyWidget(&window);
8322 child1->setPalette(Qt::blue);
8323 child1->setAutoFillBackground(true);
8324 child1->resize(200, 200);
8325 child1->setCursor(Qt::OpenHandCursor);
8327 MyWidget *child2 = new MyWidget(&window);
8328 child2->resize(200, 200);
8330 MyWidget *grandChild = new MyWidget(child2);
8331 grandChild->setPalette(Qt::red);
8332 grandChild->setAutoFillBackground(true);
8333 grandChild->resize(200, 200);
8334 grandChild->setCursor(Qt::WaitCursor);
8339 QTest::qWaitForWindowShown(window.windowHandle());
8342 #define RESET_EVENT_COUNTS \
8343 window.numEnterEvents = 0; \
8344 window.numLeaveEvents = 0; \
8345 child1->numEnterEvents = 0; \
8346 child1->numLeaveEvents = 0; \
8347 child2->numEnterEvents = 0; \
8348 child2->numLeaveEvents = 0; \
8349 grandChild->numEnterEvents = 0; \
8350 grandChild->numLeaveEvents = 0;
8352 // Position the cursor in the middle of the window.
8353 const QPoint globalPos = window.mapToGlobal(QPoint(100, 100));
8354 QCursor::setPos(globalPos); // Enter child2 and grandChild.
8357 QCOMPARE(window.numLeaveEvents, 0);
8358 QCOMPARE(child2->numLeaveEvents, 0);
8359 QCOMPARE(grandChild->numLeaveEvents, 0);
8360 QCOMPARE(child1->numLeaveEvents, 0);
8362 // This event arrives asynchronously
8363 QTRY_COMPARE(window.numEnterEvents, 1);
8364 QCOMPARE(child2->numEnterEvents, 1);
8365 QCOMPARE(grandChild->numEnterEvents, 1);
8366 QCOMPARE(child1->numEnterEvents, 0);
8369 child2->hide(); // Leave child2 and grandChild, enter child1.
8371 QCOMPARE(window.numLeaveEvents, 0);
8372 QCOMPARE(child2->numLeaveEvents, 1);
8373 QCOMPARE(grandChild->numLeaveEvents, 1);
8374 QCOMPARE(child1->numLeaveEvents, 0);
8376 QCOMPARE(window.numEnterEvents, 0);
8377 QCOMPARE(child2->numEnterEvents, 0);
8378 QCOMPARE(grandChild->numEnterEvents, 0);
8379 QCOMPARE(child1->numEnterEvents, 1);
8382 child2->show(); // Leave child1, enter child2 and grandChild.
8384 QCOMPARE(window.numLeaveEvents, 0);
8385 QCOMPARE(child2->numLeaveEvents, 0);
8386 QCOMPARE(grandChild->numLeaveEvents, 0);
8387 QCOMPARE(child1->numLeaveEvents, 1);
8389 QCOMPARE(window.numEnterEvents, 0);
8390 QCOMPARE(child2->numEnterEvents, 1);
8391 QCOMPARE(grandChild->numEnterEvents, 1);
8392 QCOMPARE(child1->numEnterEvents, 0);
8395 delete child2; // Enter child1 (and do not send leave events to child2 and grandChild).
8397 QCOMPARE(window.numLeaveEvents, 0);
8398 QCOMPARE(child1->numLeaveEvents, 0);
8400 QCOMPARE(window.numEnterEvents, 0);
8401 QCOMPARE(child1->numEnterEvents, 1);
8405 // Windows Mobile has no proper cursor support, so skip this test on that platform.
8406 #if !defined(Q_OS_WINCE_WM)
8407 void tst_QWidget::taskQTBUG_4055_sendSyntheticEnterLeave()
8409 class SELParent : public QWidget
8412 SELParent(QWidget *parent = 0): QWidget(parent) { }
8414 void mousePressEvent(QMouseEvent *) { child->show(); }
8418 class SELChild : public QWidget
8421 SELChild(QWidget *parent = 0) : QWidget(parent), numEnterEvents(0), numMouseMoveEvents(0) {}
8422 void enterEvent(QEvent *) { ++numEnterEvents; }
8423 void mouseMoveEvent(QMouseEvent *event)
8425 QCOMPARE(event->button(), Qt::NoButton);
8426 QCOMPARE(event->buttons(), Qt::MouseButtons(Qt::NoButton));
8427 ++numMouseMoveEvents;
8429 void reset() { numEnterEvents = numMouseMoveEvents = 0; }
8430 int numEnterEvents, numMouseMoveEvents;
8433 QCursor::setPos(QPoint(0,0));
8436 parent.resize(200, 200);
8437 SELChild child(&parent);
8438 child.resize(200, 200);
8440 QTest::qWaitForWindowShown(parent.windowHandle());
8443 QCursor::setPos(child.mapToGlobal(QPoint(100, 100)));
8444 // Make sure the cursor has entered the child.
8445 QTRY_VERIFY(child.numEnterEvents > 0);
8451 // Make sure the child gets enter event and no mouse move event.
8452 QTRY_COMPARE(child.numEnterEvents, 1);
8453 QCOMPARE(child.numMouseMoveEvents, 0);
8457 child.setMouseTracking(true);
8460 // Make sure the child gets enter event and mouse move event.
8461 // Note that we verify event->button() and event->buttons()
8462 // in SELChild::mouseMoveEvent().
8463 QTRY_COMPARE(child.numEnterEvents, 1);
8464 QCOMPARE(child.numMouseMoveEvents, 1);
8466 // Sending synthetic enter/leave trough the parent's mousePressEvent handler.
8467 parent.child = &child;
8471 QTest::mouseClick(&parent, Qt::LeftButton);
8473 // Make sure the child gets enter event and one mouse move event.
8474 QTRY_COMPARE(child.numEnterEvents, 1);
8475 QCOMPARE(child.numMouseMoveEvents, 1);
8479 child.setMouseTracking(false);
8480 QTest::mouseClick(&parent, Qt::LeftButton);
8482 // Make sure the child gets enter event and no mouse move event.
8483 QTRY_COMPARE(child.numEnterEvents, 1);
8484 QCOMPARE(child.numMouseMoveEvents, 0);
8488 void tst_QWidget::windowFlags()
8491 w.setWindowFlags(w.windowFlags() | Qt::FramelessWindowHint);
8492 QVERIFY(w.windowFlags() & Qt::FramelessWindowHint);
8495 void tst_QWidget::initialPosForDontShowOnScreenWidgets()
8497 { // Check default position.
8498 const QPoint expectedPos(0, 0);
8500 widget.setAttribute(Qt::WA_DontShowOnScreen);
8501 widget.winId(); // Make sure create_sys is called.
8502 QCOMPARE(widget.pos(), expectedPos);
8503 QCOMPARE(widget.geometry().topLeft(), expectedPos);
8506 { // Explicitly move to a position.
8507 const QPoint expectedPos(100, 100);
8509 widget.setAttribute(Qt::WA_DontShowOnScreen);
8510 widget.move(expectedPos);
8511 widget.winId(); // Make sure create_sys is called.
8512 QCOMPARE(widget.pos(), expectedPos);
8513 QCOMPARE(widget.geometry().topLeft(), expectedPos);
8517 class MyEvilObject : public QObject
8521 MyEvilObject(QWidget *widgetToCrash) : QObject(), widget(widgetToCrash)
8523 connect(widget, SIGNAL(destroyed(QObject *)), this, SLOT(beEvil(QObject *)));
8529 void beEvil(QObject *) { widget->update(0, 0, 150, 150); }
8532 void tst_QWidget::updateOnDestroyedSignal()
8536 QWidget *child = new QWidget(&widget);
8537 child->resize(100, 100);
8538 child->setAutoFillBackground(true);
8539 child->setPalette(Qt::red);
8542 QTest::qWaitForWindowShown(widget.windowHandle());
8545 // Please do not crash.
8546 MyEvilObject evil(child);
8550 void tst_QWidget::toplevelLineEditFocus()
8556 QTest::qWaitForWindowShown(&w);
8559 QTRY_COMPARE(QApplication::activeWindow(), (QWidget*)&w);
8560 QTRY_COMPARE(QApplication::focusWidget(), (QWidget*)&w);
8563 void tst_QWidget::focusWidget_task254563()
8565 //having different visibility for widget is important
8568 QWidget container(&top);
8569 QWidget *widget = new QWidget(&container);
8572 widget->setFocus(); //set focus (will set the focus widget up to the toplevel to be 'widget')
8573 container.setFocus();
8574 delete widget; // will call clearFocus but that doesn't help
8575 QVERIFY(top.focusWidget() != widget); //dangling pointer
8578 // This test case relies on developer build (AUTOTEST_EXPORT).
8579 #ifdef QT_BUILD_INTERNAL
8580 void tst_QWidget::destroyBackingStore()
8586 QTest::qWaitForWindowShown(&w);
8587 QApplication::processEvents();
8588 QTRY_VERIFY(w.numPaintEvents > 0);
8591 qt_widget_private(&w)->topData()->backingStoreTracker.create(&w);
8594 QApplication::processEvents();
8596 QCOMPARE(w.numPaintEvents, 1);
8598 // Check one more time, because the second time around does more caching.
8600 QApplication::processEvents();
8601 QCOMPARE(w.numPaintEvents, 2);
8603 #endif // QT_BUILD_INTERNAL
8606 QWidgetBackingStore* backingStore(QWidget &widget)
8608 QWidgetBackingStore *backingStore = 0;
8609 #ifdef QT_BUILD_INTERNAL
8610 if (QTLWExtra *topExtra = qt_widget_private(&widget)->maybeTopData())
8611 backingStore = topExtra->backingStoreTracker.data();
8613 return backingStore;
8616 // Tables of 5000 elements do not make sense on Windows Mobile.
8617 #ifndef Q_OS_WINCE_WM
8618 void tst_QWidget::rectOutsideCoordinatesLimit_task144779()
8620 QApplication::setOverrideCursor(Qt::BlankCursor); //keep the cursor out of screen grabs
8621 QWidget main(0,Qt::FramelessWindowHint); //don't get confused by the size of the window frame
8623 palette.setColor(QPalette::Window, Qt::red);
8624 main.setPalette(palette);
8626 QDesktopWidget desktop;
8627 QRect desktopDimensions = desktop.availableGeometry(&main);
8628 QSize mainSize(400, 400);
8629 mainSize = mainSize.boundedTo(desktopDimensions.size());
8630 main.resize(mainSize);
8632 QWidget *offsetWidget = new QWidget(&main);
8633 offsetWidget->setGeometry(0, -(15000 - mainSize.height()), mainSize.width(), 15000);
8635 // big widget is too big for the coordinates, it must be limited by wrect
8636 // if wrect is not at the right position because of offsetWidget, bigwidget
8637 // is not painted correctly
8638 QWidget *bigWidget = new QWidget(offsetWidget);
8639 bigWidget->setGeometry(0, 0, mainSize.width(), 50000);
8640 palette.setColor(QPalette::Window, Qt::green);
8641 bigWidget->setPalette(palette);
8642 bigWidget->setAutoFillBackground(true);
8645 QTest::qWaitForWindowShown(&main);
8647 QPixmap correct(main.size());
8648 correct.fill(Qt::green);
8649 const QPixmap mainPixmap = main.grab(QRect(QPoint(0, 0), QSize(-1, -1)));
8651 QTRY_COMPARE(mainPixmap.toImage().convertToFormat(QImage::Format_RGB32),
8652 correct.toImage().convertToFormat(QImage::Format_RGB32));
8653 QApplication::restoreOverrideCursor();
8657 void tst_QWidget::inputFocus_task257832()
8659 QLineEdit *widget = new QLineEdit;
8661 widget->winId(); // make sure, widget has been created
8663 QTRY_VERIFY(widget->hasFocus());
8664 QCOMPARE(qApp->inputMethod()->inputItem(), static_cast<QWidget*>(widget));
8665 widget->setReadOnly(true);
8666 QVERIFY(!qApp->inputMethod()->inputItem());
8670 void tst_QWidget::setGraphicsEffect()
8672 // Check that we don't have any effect by default.
8673 QWidget *widget = new QWidget;
8674 QVERIFY(!widget->graphicsEffect());
8677 QPointer<QGraphicsEffect> blurEffect = new QGraphicsBlurEffect;
8678 widget->setGraphicsEffect(blurEffect);
8679 QCOMPARE(widget->graphicsEffect(), static_cast<QGraphicsEffect *>(blurEffect));
8681 // Ensure the existing effect is deleted when setting a new one.
8682 QPointer<QGraphicsEffect> shadowEffect = new QGraphicsDropShadowEffect;
8683 widget->setGraphicsEffect(shadowEffect);
8684 QVERIFY(!blurEffect);
8685 QCOMPARE(widget->graphicsEffect(), static_cast<QGraphicsEffect *>(shadowEffect));
8686 blurEffect = new QGraphicsBlurEffect;
8688 // Ensure the effect is uninstalled when setting it on a new target.
8689 QWidget *anotherWidget = new QWidget;
8690 anotherWidget->setGraphicsEffect(blurEffect);
8691 widget->setGraphicsEffect(blurEffect);
8692 QVERIFY(!anotherWidget->graphicsEffect());
8693 QVERIFY(!shadowEffect);
8695 // Ensure the existing effect is deleted when deleting the widget.
8697 QVERIFY(!blurEffect);
8698 delete anotherWidget;
8700 // Ensure the effect is uninstalled when deleting it
8701 widget = new QWidget;
8702 blurEffect = new QGraphicsBlurEffect;
8703 widget->setGraphicsEffect(blurEffect);
8705 QVERIFY(!widget->graphicsEffect());
8707 // Ensure the existing effect is uninstalled and deleted when setting a null effect
8708 blurEffect = new QGraphicsBlurEffect;
8709 widget->setGraphicsEffect(blurEffect);
8710 widget->setGraphicsEffect(0);
8711 QVERIFY(!widget->graphicsEffect());
8712 QVERIFY(!blurEffect);
8717 void tst_QWidget::activateWindow()
8719 // Test case for task 260685
8721 // Create first mainwindow and set it active
8722 QMainWindow* mainwindow = new QMainWindow();
8723 QLabel* label = new QLabel(mainwindow);
8724 mainwindow->setCentralWidget(label);
8725 mainwindow->setVisible(true);
8726 mainwindow->activateWindow();
8727 QTest::qWaitForWindowShown(mainwindow);
8728 qApp->processEvents();
8730 QTRY_VERIFY(mainwindow->isActiveWindow());
8732 // Create second mainwindow and set it active
8733 QMainWindow* mainwindow2 = new QMainWindow();
8734 QLabel* label2 = new QLabel(mainwindow2);
8735 mainwindow2->setCentralWidget(label2);
8736 mainwindow2->setVisible(true);
8737 mainwindow2->activateWindow();
8738 qApp->processEvents();
8740 QTRY_VERIFY(!mainwindow->isActiveWindow());
8741 QTRY_VERIFY(mainwindow2->isActiveWindow());
8743 // Revert first mainwindow back to visible active
8744 mainwindow->setVisible(true);
8745 mainwindow->activateWindow();
8746 qApp->processEvents();
8748 QTRY_VERIFY(mainwindow->isActiveWindow());
8749 QTRY_VERIFY(!mainwindow2->isActiveWindow());
8752 void tst_QWidget::openModal_taskQTBUG_5804()
8754 class Widget : public QWidget
8757 Widget(QWidget *parent) : QWidget(parent)
8763 QTimer::singleShot(10, &msgbox, SLOT(accept()));
8764 msgbox.exec(); //open a modal dialog
8768 QWidget *win = new QWidget;
8771 QTest::qWaitForWindowShown(win);
8775 void tst_QWidget::focusProxyAndInputMethods()
8777 QWidget *toplevel = new QWidget(0, Qt::X11BypassWindowManagerHint);
8778 toplevel->setAttribute(Qt::WA_InputMethodEnabled, true);
8780 QWidget *child = new QWidget(toplevel);
8781 child->setFocusProxy(toplevel);
8782 child->setAttribute(Qt::WA_InputMethodEnabled, true);
8784 toplevel->setFocusPolicy(Qt::WheelFocus);
8785 child->setFocusPolicy(Qt::WheelFocus);
8787 QVERIFY(!child->hasFocus());
8788 QVERIFY(!toplevel->hasFocus());
8791 QTest::qWaitForWindowShown(toplevel);
8792 QApplication::setActiveWindow(toplevel);
8793 QVERIFY(toplevel->hasFocus());
8794 QVERIFY(child->hasFocus());
8796 // verify that toggling input methods on the child widget
8797 // correctly propagate to the focus proxy's input method
8798 // and that the input method gets the focus proxy passed
8799 // as the focus widget instead of the child widget.
8800 // otherwise input method queries go to the wrong widget
8801 QCOMPARE(qApp->inputPanel()->inputItem(), toplevel);
8803 toplevel->setAttribute(Qt::WA_InputMethodEnabled, false);
8804 QVERIFY(!qApp->inputPanel()->inputItem());
8806 toplevel->setAttribute(Qt::WA_InputMethodEnabled, true);
8807 QCOMPARE(qApp->inputPanel()->inputItem(), toplevel);
8812 #ifdef QT_BUILD_INTERNAL
8813 class scrollWidgetWBS : public QWidget
8816 void deleteBackingStore()
8818 static_cast<QWidgetPrivate*>(d_ptr.data())->topData()->backingStoreTracker.destroy();
8820 void enableBackingStore()
8822 if (!static_cast<QWidgetPrivate*>(d_ptr.data())->maybeBackingStore()) {
8823 static_cast<QWidgetPrivate*>(d_ptr.data())->topData()->backingStoreTracker.create(this);
8824 static_cast<QWidgetPrivate*>(d_ptr.data())->invalidateBuffer(this->rect());
8831 // Test case relies on developer build (AUTOTEST_EXPORT).
8832 #ifdef QT_BUILD_INTERNAL
8833 void tst_QWidget::scrollWithoutBackingStore()
8835 scrollWidgetWBS scrollable;
8836 scrollable.resize(100,100);
8837 QLabel child(QString("@"),&scrollable);
8838 child.resize(50,50);
8840 QTest::qWaitForWindowShown(&scrollable);
8841 scrollable.scroll(50,50);
8842 QCOMPARE(child.pos(),QPoint(50,50));
8843 scrollable.deleteBackingStore();
8844 scrollable.scroll(-25,-25);
8845 QCOMPARE(child.pos(),QPoint(25,25));
8846 scrollable.enableBackingStore();
8847 QCOMPARE(child.pos(),QPoint(25,25));
8851 void tst_QWidget::taskQTBUG_7532_tabOrderWithFocusProxy()
8854 w.setFocusPolicy(Qt::TabFocus);
8855 QWidget *fp = new QWidget(&w);
8856 fp->setFocusPolicy(Qt::TabFocus);
8857 w.setFocusProxy(fp);
8858 QWidget::setTabOrder(&w, fp);
8860 // In debug mode, no assertion failure means it's alright.
8863 void tst_QWidget::movedAndResizedAttributes()
8865 #if defined (Q_OS_MAC)
8866 QEXPECT_FAIL("", "FixMe, QTBUG-8941 and QTBUG-8977", Abort);
8872 QVERIFY(!w.testAttribute(Qt::WA_Moved));
8873 QVERIFY(!w.testAttribute(Qt::WA_Resized));
8875 w.setWindowState(Qt::WindowFullScreen);
8877 QVERIFY(!w.testAttribute(Qt::WA_Moved));
8878 QVERIFY(!w.testAttribute(Qt::WA_Resized));
8880 w.setWindowState(Qt::WindowMaximized);
8882 QVERIFY(!w.testAttribute(Qt::WA_Moved));
8883 QVERIFY(!w.testAttribute(Qt::WA_Resized));
8885 w.setWindowState(Qt::WindowMinimized);
8887 QVERIFY(!w.testAttribute(Qt::WA_Moved));
8888 QVERIFY(!w.testAttribute(Qt::WA_Resized));
8892 QVERIFY(!w.testAttribute(Qt::WA_Moved));
8893 QVERIFY(!w.testAttribute(Qt::WA_Resized));
8897 QVERIFY(!w.testAttribute(Qt::WA_Moved));
8898 QVERIFY(!w.testAttribute(Qt::WA_Resized));
8902 QVERIFY(!w.testAttribute(Qt::WA_Moved));
8903 QVERIFY(!w.testAttribute(Qt::WA_Resized));
8907 QVERIFY(w.testAttribute(Qt::WA_Moved));
8908 QVERIFY(!w.testAttribute(Qt::WA_Resized));
8911 QVERIFY(w.testAttribute(Qt::WA_Moved));
8912 QVERIFY(w.testAttribute(Qt::WA_Resized));
8916 void tst_QWidget::childAt()
8918 QWidget parent(0, Qt::FramelessWindowHint);
8919 parent.resize(200, 200);
8921 QWidget *child = new QWidget(&parent);
8922 child->setPalette(Qt::red);
8923 child->setAutoFillBackground(true);
8924 child->setGeometry(20, 20, 160, 160);
8926 QWidget *grandChild = new QWidget(child);
8927 grandChild->setPalette(Qt::blue);
8928 grandChild->setAutoFillBackground(true);
8929 grandChild->setGeometry(-20, -20, 220, 220);
8931 QVERIFY(!parent.childAt(19, 19));
8932 QVERIFY(!parent.childAt(180, 180));
8933 QCOMPARE(parent.childAt(20, 20), grandChild);
8934 QCOMPARE(parent.childAt(179, 179), grandChild);
8936 grandChild->setAttribute(Qt::WA_TransparentForMouseEvents);
8937 QCOMPARE(parent.childAt(20, 20), child);
8938 QCOMPARE(parent.childAt(179, 179), child);
8939 grandChild->setAttribute(Qt::WA_TransparentForMouseEvents, false);
8941 child->setMask(QRect(50, 50, 60, 60));
8943 QVERIFY(!parent.childAt(69, 69));
8944 QVERIFY(!parent.childAt(130, 130));
8945 QCOMPARE(parent.childAt(70, 70), grandChild);
8946 QCOMPARE(parent.childAt(129, 129), grandChild);
8948 child->setAttribute(Qt::WA_MouseNoMask);
8949 QCOMPARE(parent.childAt(69, 69), grandChild);
8950 QCOMPARE(parent.childAt(130, 130), grandChild);
8951 child->setAttribute(Qt::WA_MouseNoMask, false);
8953 grandChild->setAttribute(Qt::WA_TransparentForMouseEvents);
8954 QCOMPARE(parent.childAt(70, 70), child);
8955 QCOMPARE(parent.childAt(129, 129), child);
8956 grandChild->setAttribute(Qt::WA_TransparentForMouseEvents, false);
8958 grandChild->setMask(QRect(80, 80, 40, 40));
8960 QCOMPARE(parent.childAt(79, 79), child);
8961 QCOMPARE(parent.childAt(120, 120), child);
8962 QCOMPARE(parent.childAt(80, 80), grandChild);
8963 QCOMPARE(parent.childAt(119, 119), grandChild);
8965 grandChild->setAttribute(Qt::WA_MouseNoMask);
8967 QCOMPARE(parent.childAt(79, 79), grandChild);
8968 QCOMPARE(parent.childAt(120, 120), grandChild);
8972 void tst_QWidget::childAt_unifiedToolBar()
8974 QLabel *label = new QLabel(QLatin1String("foo"));
8975 QToolBar *toolBar = new QToolBar;
8976 toolBar->addWidget(new QLabel("dummy"));
8977 toolBar->addWidget(label);
8979 QMainWindow mainWindow;
8980 mainWindow.addToolBar(toolBar);
8983 // Calculate the top-left corner of the tool bar and the label (in mainWindow's coordinates).
8984 QPoint labelTopLeft = label->mapTo(&mainWindow, QPoint());
8985 QPoint toolBarTopLeft = toolBar->mapTo(&mainWindow, QPoint());
8987 QCOMPARE(mainWindow.childAt(toolBarTopLeft), static_cast<QWidget *>(toolBar));
8988 QCOMPARE(mainWindow.childAt(labelTopLeft), static_cast<QWidget *>(label));
8990 // Enable unified tool bars.
8991 mainWindow.setUnifiedTitleAndToolBarOnMac(true);
8994 // The tool bar is now in the "non-client" area of QMainWindow, i.e.
8995 // outside the mainWindow's rect(), and since mapTo et al. doesn't work
8996 // in that case (see commit 35667fd45ada49269a5987c235fdedfc43e92bb8),
8997 // we use mapToGlobal/mapFromGlobal to re-calculate the corners.
8998 QPoint oldToolBarTopLeft = toolBarTopLeft;
8999 toolBarTopLeft = mainWindow.mapFromGlobal(toolBar->mapToGlobal(QPoint()));
9000 QVERIFY(toolBarTopLeft != oldToolBarTopLeft);
9001 QVERIFY(toolBarTopLeft.y() < 0);
9002 labelTopLeft = mainWindow.mapFromGlobal(label->mapToGlobal(QPoint()));
9004 QCOMPARE(mainWindow.childAt(toolBarTopLeft), static_cast<QWidget *>(toolBar));
9005 QCOMPARE(mainWindow.childAt(labelTopLeft), static_cast<QWidget *>(label));
9008 void tst_QWidget::taskQTBUG_11373()
9010 QMainWindow * myWindow = new QMainWindow();
9011 QWidget * center = new QWidget();
9012 myWindow -> setCentralWidget(center);
9013 QWidget * drawer = new QWidget(myWindow, Qt::Drawer);
9015 QCOMPARE(drawer->isVisible(), false);
9017 myWindow -> raise();
9018 // The drawer shouldn't be visible now.
9019 QCOMPARE(drawer->isVisible(), false);
9020 myWindow -> setWindowState(Qt::WindowFullScreen);
9021 myWindow -> setWindowState(Qt::WindowNoState);
9022 // The drawer should still not be visible, since we haven't shown it.
9023 QCOMPARE(drawer->isVisible(), false);
9027 void tst_QWidget::taskQTBUG_17333_ResizeInfiniteRecursion()
9030 const char *s = "border: 1px solid;";
9031 tb.setStyleSheet(s);
9034 QTest::qWaitForWindowShown(&tb);
9035 tb.setGeometry(QRect(100, 100, 0, 100));
9036 // No crash, it works.
9039 void tst_QWidget::nativeChildFocus()
9042 QLayout *layout = new QVBoxLayout;
9043 w.setLayout(layout);
9044 QLineEdit *p1 = new QLineEdit;
9045 QLineEdit *p2 = new QLineEdit;
9046 layout->addWidget(p1);
9047 layout->addWidget(p2);
9048 p1->setObjectName("p1");
9049 p2->setObjectName("p2");
9053 p1->setAttribute(Qt::WA_NativeWindow);
9054 p2->setAttribute(Qt::WA_NativeWindow);
9055 QApplication::processEvents();
9056 QTest::qWaitForWindowShown(&w);
9059 QCOMPARE(QApplication::activeWindow(), &w);
9060 QCOMPARE(QApplication::focusWidget(), static_cast<QWidget*>(p1));
9065 static bool lenientCompare(const QPixmap &actual, const QPixmap &expected)
9067 QImage expectedImage = expected.toImage().convertToFormat(QImage::Format_RGB32);
9068 QImage actualImage = actual.toImage().convertToFormat(QImage::Format_RGB32);
9070 if (expectedImage.size() != actualImage.size()) {
9071 qWarning("Image size comparison failed: expected: %dx%d, got %dx%d",
9072 expectedImage.size().width(), expectedImage.size().height(),
9073 actualImage.size().width(), actualImage.size().height());
9077 const int size = actual.width() * actual.height();
9078 const int threshold = QPixmap::defaultDepth() == 16 ? 10 : 2;
9080 QRgb *a = (QRgb *)actualImage.bits();
9081 QRgb *e = (QRgb *)expectedImage.bits();
9082 for (int i = 0; i < size; ++i) {
9083 const QColor ca(a[i]);
9084 const QColor ce(e[i]);
9085 if (qAbs(ca.red() - ce.red()) > threshold
9086 || qAbs(ca.green() - ce.green()) > threshold
9087 || qAbs(ca.blue() - ce.blue()) > threshold) {
9088 qWarning("Color mismatch at pixel #%d: Expected: %d,%d,%d, got %d,%d,%d",
9089 i, ce.red(), ce.green(), ce.blue(), ca.red(), ca.green(), ca.blue());
9097 void tst_QWidget::grab()
9099 for (int opaque = 0; opaque < 2; ++opaque) {
9101 QImage image(128, 128, opaque ? QImage::Format_RGB32 : QImage::Format_ARGB32_Premultiplied);
9102 for (int row = 0; row < image.height(); ++row) {
9103 QRgb *line = reinterpret_cast<QRgb *>(image.scanLine(row));
9104 for (int col = 0; col < image.width(); ++col)
9105 line[col] = qRgba(rand() & 255, row, col, opaque ? 255 : 127);
9108 QPalette pal = widget.palette();
9109 pal.setBrush(QPalette::Window, QBrush(image));
9110 widget.setPalette(pal);
9111 widget.resize(128, 128);
9113 QPixmap expected(64, 64);
9115 expected.fill(Qt::transparent);
9117 QPainter p(&expected);
9118 p.translate(-64, -64);
9119 p.drawTiledPixmap(0, 0, 128, 128, pal.brush(QPalette::Window).texture(), 0, 0);
9122 QPixmap actual = widget.grab(QRect(64, 64, 64, 64));
9123 QVERIFY(lenientCompare(actual, expected));
9125 actual = widget.grab(QRect(64, 64, -1, -1));
9126 QVERIFY(lenientCompare(actual, expected));
9128 // Make sure a widget that is not yet shown is grabbed correctly.
9129 QTreeWidget widget2;
9130 actual = widget2.grab(QRect());
9132 expected = widget2.grab(QRect());
9134 QVERIFY(lenientCompare(actual, expected));
9138 QTEST_MAIN(tst_QWidget)
9139 #include "tst_qwidget.moc"