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 /// ### fixme: Check platforms
3129 QEXPECT_FAIL("", "Window mask not implemented on Lighthouse QTBUG-22326", Continue);
3131 QTRY_COMPARE(QApplication::widgetAt(100,100)->objectName(), w1->objectName());
3132 QTRY_COMPARE(QApplication::widgetAt(101,101)->objectName(), w2->objectName());
3134 QBitmap bitmap(w2->size());
3135 QPainter p(&bitmap);
3136 p.fillRect(bitmap.rect(), Qt::color1);
3137 p.setPen(Qt::color0);
3138 p.drawPoint(w2->mapFromGlobal(QPoint(100,100)));
3140 w2->setMask(bitmap);
3141 qApp->processEvents();
3143 #if defined(Q_OS_WINCE)
3144 QEXPECT_FAIL("", "Windows CE does only support rectangular regions", Continue); //See also task 147191
3146 /// ### fixme: Check platforms
3147 QEXPECT_FAIL("", "Window mask not implemented on Lighthouse QTBUG-22326", Continue);
3148 QTRY_VERIFY(QApplication::widgetAt(100,100) == w1);
3149 QTRY_VERIFY(QApplication::widgetAt(101,101) == w2);
3155 void tst_QWidget::task110173()
3159 QPushButton *pb1 = new QPushButton("click", &w);
3160 pb1->setFocusPolicy(Qt::ClickFocus);
3161 pb1->move(100, 100);
3163 QPushButton *pb2 = new QPushButton("push", &w);
3164 pb2->setFocusPolicy(Qt::ClickFocus);
3165 pb2->move(300, 300);
3167 QTest::keyClick( &w, Qt::Key_Tab );
3169 QTest::qWaitForWindowShown(&w);
3173 class Widget : public QWidget
3176 Widget() : deleteThis(false) { setFocusPolicy(Qt::StrongFocus); }
3177 void actionEvent(QActionEvent *) { if (deleteThis) delete this; }
3178 void changeEvent(QEvent *) { if (deleteThis) delete this; }
3179 void closeEvent(QCloseEvent *) { if (deleteThis) delete this; }
3180 void hideEvent(QHideEvent *) { if (deleteThis) delete this; }
3181 void focusOutEvent(QFocusEvent *) { if (deleteThis) delete this; }
3182 void keyPressEvent(QKeyEvent *) { if (deleteThis) delete this; }
3183 void keyReleaseEvent(QKeyEvent *) { if (deleteThis) delete this; }
3184 void mouseDoubleClickEvent(QMouseEvent *) { if (deleteThis) delete this; }
3185 void mousePressEvent(QMouseEvent *) { if (deleteThis) delete this; }
3186 void mouseReleaseEvent(QMouseEvent *) { if (deleteThis) delete this; }
3187 void mouseMoveEvent(QMouseEvent *) { if (deleteThis) delete this; }
3192 void tst_QWidget::testDeletionInEventHandlers()
3195 QPointer<Widget> w = new Widget;
3196 w->deleteThis = true;
3201 // focusOut (crashes)
3205 //QVERIFY(qApp->focusWidget() == w);
3206 //w->deleteThis = true;
3213 w->deleteThis = true;
3214 QTest::keyPress(w, Qt::Key_A);
3221 w->deleteThis = true;
3222 QTest::keyRelease(w, Qt::Key_A);
3229 w->deleteThis = true;
3230 QTest::mousePress(w, Qt::LeftButton);
3237 w->deleteThis = true;
3238 QTest::mouseRelease(w, Qt::LeftButton);
3242 // mouse double click
3245 w->deleteThis = true;
3246 QTest::mouseDClick(w, Qt::LeftButton);
3250 // hide event (crashes)
3253 //w->deleteThis = true;
3259 w->deleteThis = true;
3260 w->addAction(new QAction(w));
3267 w->deleteThis = true;
3268 w->setMouseTracking(true);
3273 w->setMouseTracking(true);
3275 w->deleteThis = true;
3276 QMouseEvent me(QEvent::MouseMove, QPoint(0, 0), Qt::NoButton, Qt::NoButton, Qt::NoModifier);
3277 QApplication::sendEvent(w, &me);
3283 void tst_QWidget::sheetOpacity()
3286 QWidget sheet(&tmpWindow, Qt::Sheet);
3289 QCOMPARE(int(sheet.windowOpacity() * 255), 242); // 95%
3290 sheet.setParent(0, Qt::Dialog);
3291 QCOMPARE(int(sheet.windowOpacity() * 255), 255);
3294 class MaskedPainter : public QWidget
3300 : mask(20, 20, 50, 50)
3305 void paintEvent(QPaintEvent *)
3308 p.fillRect(mask, QColor(Qt::red));
3313 Verifies that the entire area inside the mask is painted red.
3315 bool verifyWidgetMask(QWidget *widget, QRect mask)
3317 const QImage image = widget->grab(QRect(QPoint(0, 0), widget->size())).toImage();
3319 const QImage masked = image.copy(mask);
3321 red.fill(QColor(Qt::red).rgb());
3323 return (masked == red);
3326 void tst_QWidget::setMask()
3328 testWidget->hide(); // get this out of the way.
3335 QVERIFY(verifyWidgetMask(&w, w.mask));
3340 w.setWindowFlags(w.windowFlags() | Qt::FramelessWindowHint);
3343 QRect mask = w.mask;
3345 QVERIFY(verifyWidgetMask(&w, mask));
3350 class StaticWidget : public QWidget
3356 QRegion paintedRegion;
3358 StaticWidget(QWidget *parent = 0)
3361 setAttribute(Qt::WA_StaticContents);
3362 setAttribute(Qt::WA_OpaquePaintEvent);
3363 setPalette(Qt::red); // Make sure we have an opaque palette.
3364 setAutoFillBackground(true);
3365 gotPaintEvent = false;
3368 void paintEvent(QPaintEvent *e)
3370 paintedRegion += e->region();
3371 gotPaintEvent = true;
3372 // qDebug() << "paint" << e->region();
3373 // Look for a full update, set partial to false if found.
3374 foreach(QRect r, e->region().rects()) {
3375 partial = (r != rect());
3376 if (partial == false)
3383 Test that widget resizes and moves can be done with minimal repaints when WA_StaticContents
3384 and WA_OpaquePaintEvent is set. Test is mac-only for now.
3386 void tst_QWidget::optimizedResizeMove()
3389 parent.resize(400, 400);
3391 StaticWidget staticWidget(&parent);
3392 staticWidget.gotPaintEvent = false;
3393 staticWidget.move(150, 150);
3394 staticWidget.resize(150, 150);
3396 QTest::qWaitForWindowShown(&parent);
3398 QTRY_COMPARE(staticWidget.gotPaintEvent, true);
3400 staticWidget.gotPaintEvent = false;
3401 staticWidget.move(staticWidget.pos() + QPoint(10, 10));
3403 QCOMPARE(staticWidget.gotPaintEvent, false);
3405 staticWidget.gotPaintEvent = false;
3406 staticWidget.move(staticWidget.pos() + QPoint(-10, -10));
3408 QCOMPARE(staticWidget.gotPaintEvent, false);
3410 staticWidget.gotPaintEvent = false;
3411 staticWidget.move(staticWidget.pos() + QPoint(-10, 10));
3413 QCOMPARE(staticWidget.gotPaintEvent, false);
3415 staticWidget.gotPaintEvent = false;
3416 staticWidget.resize(staticWidget.size() + QSize(10, 10));
3418 QCOMPARE(staticWidget.gotPaintEvent, true);
3419 QCOMPARE(staticWidget.partial, true);
3421 staticWidget.gotPaintEvent = false;
3422 staticWidget.resize(staticWidget.size() + QSize(-10, -10));
3424 QCOMPARE(staticWidget.gotPaintEvent, false);
3426 staticWidget.gotPaintEvent = false;
3427 staticWidget.resize(staticWidget.size() + QSize(10, -10));
3429 QCOMPARE(staticWidget.gotPaintEvent, true);
3430 QCOMPARE(staticWidget.partial, true);
3432 staticWidget.gotPaintEvent = false;
3433 staticWidget.move(staticWidget.pos() + QPoint(10, 10));
3434 staticWidget.resize(staticWidget.size() + QSize(-10, -10));
3436 QCOMPARE(staticWidget.gotPaintEvent, false);
3438 staticWidget.gotPaintEvent = false;
3439 staticWidget.move(staticWidget.pos() + QPoint(10, 10));
3440 staticWidget.resize(staticWidget.size() + QSize(10, 10));
3442 QCOMPARE(staticWidget.gotPaintEvent, true);
3443 QCOMPARE(staticWidget.partial, true);
3445 staticWidget.gotPaintEvent = false;
3446 staticWidget.move(staticWidget.pos() + QPoint(-10, -10));
3447 staticWidget.resize(staticWidget.size() + QSize(-10, -10));
3449 QCOMPARE(staticWidget.gotPaintEvent, false);
3451 staticWidget.setAttribute(Qt::WA_StaticContents, false);
3452 staticWidget.gotPaintEvent = false;
3453 staticWidget.move(staticWidget.pos() + QPoint(-10, -10));
3454 staticWidget.resize(staticWidget.size() + QSize(-10, -10));
3456 QCOMPARE(staticWidget.gotPaintEvent, true);
3457 QCOMPARE(staticWidget.partial, false);
3458 staticWidget.setAttribute(Qt::WA_StaticContents, true);
3460 staticWidget.setAttribute(Qt::WA_StaticContents, false);
3461 staticWidget.gotPaintEvent = false;
3462 staticWidget.move(staticWidget.pos() + QPoint(10, 10));
3464 QCOMPARE(staticWidget.gotPaintEvent, false);
3465 staticWidget.setAttribute(Qt::WA_StaticContents, true);
3468 void tst_QWidget::optimizedResize_topLevel()
3470 #if defined(Q_OS_MAC)
3471 QSKIP("We do not yet have static contents support for *top-levels* on this platform");
3474 StaticWidget topLevel;
3475 topLevel.gotPaintEvent = false;
3477 QTest::qWaitForWindowShown(&topLevel);
3479 QTRY_COMPARE(topLevel.gotPaintEvent, true);
3481 topLevel.gotPaintEvent = false;
3482 topLevel.partial = false;
3483 topLevel.paintedRegion = QRegion();
3486 topLevel.resize(topLevel.size() + QSize(10, 10));
3488 // Static contents does not work when programmatically resizing
3489 // top-levels with QWidget::resize. We do some funky stuff in
3490 // setGeometry_sys. However, resizing it with the mouse or with
3491 // a native function call works (it basically has to go through
3492 // WM_RESIZE in QApplication). This is a corner case, though.
3494 const QRect frame = topLevel.frameGeometry();
3495 MoveWindow(winHandleOf(&topLevel), frame.x(), frame.y(),
3496 frame.width() + 10, frame.height() + 10,
3502 // Expected update region: New rect - old rect.
3503 QRegion expectedUpdateRegion(topLevel.rect());
3504 expectedUpdateRegion -= QRect(QPoint(), topLevel.size() - QSize(10, 10));
3506 QTRY_COMPARE(topLevel.gotPaintEvent, true);
3507 QCOMPARE(topLevel.partial, true);
3508 QCOMPARE(topLevel.paintedRegion, expectedUpdateRegion);
3511 class SiblingDeleter : public QWidget
3514 inline SiblingDeleter(QWidget *sibling, QWidget *parent)
3515 : QWidget(parent), sibling(sibling) {}
3516 inline virtual ~SiblingDeleter() { delete sibling; }
3519 QPointer<QWidget> sibling;
3523 void tst_QWidget::childDeletesItsSibling()
3525 QWidget *commonParent = new QWidget(0);
3526 QPointer<QWidget> child = new QWidget(0);
3527 QPointer<QWidget> siblingDeleter = new SiblingDeleter(child, commonParent);
3528 child->setParent(commonParent);
3529 delete commonParent; // don't crash
3531 QVERIFY(!siblingDeleter);
3535 void tst_QWidget::setMinimumSize()
3538 QSize defaultSize = w.size();
3540 w.setMinimumSize(defaultSize + QSize(100, 100));
3541 QCOMPARE(w.size(), defaultSize + QSize(100, 100));
3542 QVERIFY(!w.testAttribute(Qt::WA_Resized));
3544 w.setMinimumSize(defaultSize + QSize(50, 50));
3545 QCOMPARE(w.size(), defaultSize + QSize(100, 100));
3546 QVERIFY(!w.testAttribute(Qt::WA_Resized));
3548 w.setMinimumSize(defaultSize + QSize(200, 200));
3549 QCOMPARE(w.size(), defaultSize + QSize(200, 200));
3550 QVERIFY(!w.testAttribute(Qt::WA_Resized));
3552 // Setting a minimum size larger than the desktop does not work on WinCE,
3553 // so skip this part of the test.
3555 QSize nonDefaultSize = defaultSize + QSize(5,5);
3556 w.setMinimumSize(nonDefaultSize);
3559 QVERIFY(w.height() >= nonDefaultSize.height());
3560 QVERIFY(w.width() >= nonDefaultSize.width());
3564 void tst_QWidget::setMaximumSize()
3567 QSize defaultSize = w.size();
3569 w.setMinimumSize(defaultSize + QSize(100, 100));
3570 QCOMPARE(w.size(), defaultSize + QSize(100, 100));
3571 QVERIFY(!w.testAttribute(Qt::WA_Resized));
3572 w.setMinimumSize(defaultSize);
3574 w.setMaximumSize(defaultSize + QSize(200, 200));
3575 QCOMPARE(w.size(), defaultSize + QSize(100, 100));
3576 QVERIFY(!w.testAttribute(Qt::WA_Resized));
3578 w.setMaximumSize(defaultSize + QSize(50, 50));
3579 QCOMPARE(w.size(), defaultSize + QSize(50, 50));
3580 QVERIFY(!w.testAttribute(Qt::WA_Resized));
3583 void tst_QWidget::setFixedSize()
3586 QSize defaultSize = w.size();
3588 w.setFixedSize(defaultSize + QSize(100, 100));
3589 QCOMPARE(w.size(), defaultSize + QSize(100, 100));
3590 QVERIFY(w.testAttribute(Qt::WA_Resized));
3592 w.setFixedSize(defaultSize + QSize(200, 200));
3594 QCOMPARE(w.minimumSize(), defaultSize + QSize(200,200));
3595 QCOMPARE(w.maximumSize(), defaultSize + QSize(200,200));
3596 QCOMPARE(w.size(), defaultSize + QSize(200, 200));
3597 QVERIFY(w.testAttribute(Qt::WA_Resized));
3599 w.setFixedSize(defaultSize + QSize(50, 50));
3600 QCOMPARE(w.size(), defaultSize + QSize(50, 50));
3601 QVERIFY(w.testAttribute(Qt::WA_Resized));
3603 w.setAttribute(Qt::WA_Resized, false);
3604 w.setFixedSize(defaultSize + QSize(50, 50));
3605 QVERIFY(!w.testAttribute(Qt::WA_Resized));
3607 w.setFixedSize(defaultSize + QSize(150, 150));
3610 QVERIFY(w.size() == defaultSize + QSize(150,150));
3613 void tst_QWidget::ensureCreated()
3617 WId widgetWinId = widget.winId();
3618 Q_UNUSED(widgetWinId);
3619 QVERIFY(widget.testAttribute(Qt::WA_WState_Created));
3625 QDialog dialog(&window);
3626 dialog.setWindowModality(Qt::NonModal);
3628 WId dialogWinId = dialog.winId();
3629 Q_UNUSED(dialogWinId);
3630 QVERIFY(dialog.testAttribute(Qt::WA_WState_Created));
3631 QVERIFY(window.testAttribute(Qt::WA_WState_Created));
3637 QDialog dialog(&window);
3638 dialog.setWindowModality(Qt::WindowModal);
3640 WId dialogWinId = dialog.winId();
3641 Q_UNUSED(dialogWinId);
3642 QVERIFY(dialog.testAttribute(Qt::WA_WState_Created));
3643 QVERIFY(window.testAttribute(Qt::WA_WState_Created));
3649 QDialog dialog(&window);
3650 dialog.setWindowModality(Qt::ApplicationModal);
3652 WId dialogWinId = dialog.winId();
3653 Q_UNUSED(dialogWinId);
3654 QVERIFY(dialog.testAttribute(Qt::WA_WState_Created));
3655 QVERIFY(window.testAttribute(Qt::WA_WState_Created));
3659 class WinIdChangeWidget : public QWidget {
3661 WinIdChangeWidget(QWidget *p = 0)
3667 bool event(QEvent *e)
3669 if (e->type() == QEvent::WinIdChange) {
3670 m_winIdList.append(internalWinId());
3673 return QWidget::event(e);
3676 QList<WId> m_winIdList;
3677 int winIdChangeEventCount() const { return m_winIdList.count(); }
3680 void tst_QWidget::winIdChangeEvent()
3683 // Transforming an alien widget into a native widget
3684 WinIdChangeWidget widget;
3685 const WId winIdBefore = widget.internalWinId();
3686 const WId winIdAfter = widget.winId();
3687 QVERIFY(winIdBefore != winIdAfter);
3688 QCOMPARE(widget.winIdChangeEventCount(), 1);
3692 // Changing parent of a native widget
3693 // Should cause winId of child to change, on all platforms
3694 QWidget parent1, parent2;
3695 WinIdChangeWidget child(&parent1);
3696 const WId winIdBefore = child.winId();
3697 QCOMPARE(child.winIdChangeEventCount(), 1);
3698 child.setParent(&parent2);
3699 const WId winIdAfter = child.internalWinId();
3700 QVERIFY(winIdBefore != winIdAfter);
3701 QCOMPARE(child.winIdChangeEventCount(), 3);
3702 // winId is set to zero during reparenting
3703 QVERIFY(0 == child.m_winIdList[1]);
3707 // Changing grandparent of a native widget
3708 QWidget grandparent1, grandparent2;
3709 QWidget parent(&grandparent1);
3710 WinIdChangeWidget child(&parent);
3711 const WId winIdBefore = child.winId();
3712 QCOMPARE(child.winIdChangeEventCount(), 1);
3713 parent.setParent(&grandparent2);
3714 const WId winIdAfter = child.internalWinId();
3715 QCOMPARE(winIdBefore, winIdAfter);
3716 QCOMPARE(child.winIdChangeEventCount(), 1);
3720 // Changing parent of an alien widget
3721 QWidget parent1, parent2;
3722 WinIdChangeWidget child(&parent1);
3723 const WId winIdBefore = child.internalWinId();
3724 child.setParent(&parent2);
3725 const WId winIdAfter = child.internalWinId();
3726 QCOMPARE(winIdBefore, winIdAfter);
3727 QCOMPARE(child.winIdChangeEventCount(), 0);
3731 // Making native child widget into a top-level window
3733 WinIdChangeWidget child(&parent);
3735 const WId winIdBefore = child.internalWinId();
3736 QCOMPARE(child.winIdChangeEventCount(), 1);
3737 const Qt::WindowFlags flags = child.windowFlags();
3738 child.setWindowFlags(flags | Qt::Window);
3739 const WId winIdAfter = child.internalWinId();
3740 QVERIFY(winIdBefore != winIdAfter);
3741 QCOMPARE(child.winIdChangeEventCount(), 3);
3742 // winId is set to zero during reparenting
3743 QVERIFY(0 == child.m_winIdList[1]);
3747 void tst_QWidget::persistentWinId()
3749 QWidget *parent = new QWidget;
3750 QWidget *w1 = new QWidget;
3751 QWidget *w2 = new QWidget;
3752 QWidget *w3 = new QWidget;
3753 w1->setParent(parent);
3757 WId winId1 = w1->winId();
3758 WId winId2 = w2->winId();
3759 WId winId3 = w3->winId();
3761 // reparenting should change the winId of the widget being reparented, but not of its children
3763 QVERIFY(w1->winId() != winId1);
3764 winId1 = w1->winId();
3765 QCOMPARE(w2->winId(), winId2);
3766 QCOMPARE(w3->winId(), winId3);
3768 w1->setParent(parent);
3769 QVERIFY(w1->winId() != winId1);
3770 winId1 = w1->winId();
3771 QCOMPARE(w2->winId(), winId2);
3772 QCOMPARE(w3->winId(), winId3);
3775 QVERIFY(w2->winId() != winId2);
3776 winId2 = w2->winId();
3777 QCOMPARE(w3->winId(), winId3);
3779 w2->setParent(parent);
3780 QVERIFY(w2->winId() != winId2);
3781 winId2 = w2->winId();
3782 QCOMPARE(w3->winId(), winId3);
3785 QVERIFY(w2->winId() != winId2);
3786 winId2 = w2->winId();
3787 QCOMPARE(w3->winId(), winId3);
3790 QVERIFY(w3->winId() != winId3);
3791 winId3 = w3->winId();
3794 QVERIFY(w3->winId() != winId3);
3795 winId3 = w3->winId();
3798 QVERIFY(w3->winId() != winId3);
3799 winId3 = w3->winId();
3804 void tst_QWidget::showNativeChild()
3807 topLevel.setGeometry(0, 0, 100, 100);
3808 QWidget child(&topLevel);
3811 QTest::qWaitForWindowShown(&topLevel);
3814 class ShowHideEventWidget : public QWidget
3817 int numberOfShowEvents, numberOfHideEvents;
3819 ShowHideEventWidget(QWidget *parent = 0)
3820 : QWidget(parent), numberOfShowEvents(0), numberOfHideEvents(0)
3824 { QWidget::create(); }
3826 void showEvent(QShowEvent *)
3827 { ++numberOfShowEvents; }
3829 void hideEvent(QHideEvent *)
3830 { ++numberOfHideEvents; }
3833 void tst_QWidget::showHideEvent_data()
3835 QTest::addColumn<bool>("show");
3836 QTest::addColumn<bool>("hide");
3837 QTest::addColumn<bool>("create");
3838 QTest::addColumn<int>("expectedShowEvents");
3839 QTest::addColumn<int>("expectedHideEvents");
3841 QTest::newRow("window: only show")
3847 QTest::newRow("window: show/hide")
3853 QTest::newRow("window: show/hide/create")
3859 QTest::newRow("window: hide/create")
3865 QTest::newRow("window: only hide")
3871 QTest::newRow("window: nothing")
3879 void tst_QWidget::showHideEvent()
3883 QFETCH(bool, create);
3884 QFETCH(int, expectedShowEvents);
3885 QFETCH(int, expectedHideEvents);
3887 ShowHideEventWidget widget;
3892 if (create && !widget.testAttribute(Qt::WA_WState_Created))
3895 QCOMPARE(widget.numberOfShowEvents, expectedShowEvents);
3896 QCOMPARE(widget.numberOfHideEvents, expectedHideEvents);
3899 void tst_QWidget::update()
3901 QTest::qWait(10); // Wait for the initStuff to do it's stuff.
3905 w.setGeometry(50, 50, 100, 100);
3907 QTest::qWaitForWindowShown(&w);
3909 QApplication::processEvents();
3910 QApplication::processEvents();
3913 QEXPECT_FAIL(0, "Cocoa compositor says to paint this twice.", Continue);
3915 QTRY_COMPARE(w.numPaintEvents, 1);
3917 QCOMPARE(w.visibleRegion(), QRegion(w.rect()));
3918 QCOMPARE(w.paintedRegion, w.visibleRegion());
3921 UpdateWidget child(&w);
3922 child.setGeometry(10, 10, 80, 80);
3925 QPoint childOffset = child.mapToParent(QPoint());
3927 // widgets are transparent by default, so both should get repaints
3929 QApplication::processEvents();
3930 QApplication::processEvents();
3931 QCOMPARE(child.numPaintEvents, 1);
3932 QCOMPARE(child.visibleRegion(), QRegion(child.rect()));
3933 QCOMPARE(child.paintedRegion, child.visibleRegion());
3934 QCOMPARE(w.numPaintEvents, 1);
3935 QCOMPARE(w.visibleRegion(), QRegion(w.rect()));
3936 QCOMPARE(w.paintedRegion, child.visibleRegion().translated(childOffset));
3942 QApplication::processEvents();
3943 QApplication::processEvents();
3944 QCOMPARE(child.numPaintEvents, 1);
3945 QCOMPARE(child.visibleRegion(), QRegion(child.rect()));
3946 QCOMPARE(child.paintedRegion, child.visibleRegion());
3947 QCOMPARE(w.numPaintEvents, 1);
3948 QCOMPARE(w.visibleRegion(), QRegion(w.rect()));
3949 QCOMPARE(w.paintedRegion, w.visibleRegion());
3952 QPalette opaquePalette = child.palette();
3953 opaquePalette.setColor(child.backgroundRole(), QColor(Qt::red));
3955 // setting an opaque background on the child should prevent paint-events
3956 // for the parent in the child area
3958 child.setPalette(opaquePalette);
3959 child.setAutoFillBackground(true);
3960 QApplication::processEvents();
3966 QApplication::processEvents();
3967 QApplication::processEvents();
3969 QCOMPARE(w.numPaintEvents, 1);
3970 QRegion expectedVisible = QRegion(w.rect())
3971 - child.visibleRegion().translated(childOffset);
3972 QCOMPARE(w.visibleRegion(), expectedVisible);
3973 QCOMPARE(w.paintedRegion, expectedVisible);
3974 QCOMPARE(child.numPaintEvents, 0);
3980 QApplication::processEvents();
3981 QApplication::processEvents();
3983 QCOMPARE(w.numPaintEvents, 0);
3984 QCOMPARE(child.numPaintEvents, 1);
3985 QCOMPARE(child.paintedRegion, child.visibleRegion());
3991 // overlapping sibling
3992 UpdateWidget sibling(&w);
3993 child.setGeometry(10, 10, 20, 20);
3994 sibling.setGeometry(15, 15, 20, 20);
3997 QApplication::processEvents();
4002 const QPoint siblingOffset = sibling.mapToParent(QPoint());
4005 QApplication::processEvents();
4006 QApplication::processEvents();
4008 // child is opaque, sibling transparent
4010 QCOMPARE(sibling.numPaintEvents, 1);
4011 QCOMPARE(sibling.paintedRegion, sibling.visibleRegion());
4013 QCOMPARE(child.numPaintEvents, 1);
4014 QCOMPARE(child.paintedRegion.translated(childOffset),
4015 child.visibleRegion().translated(childOffset)
4016 & sibling.visibleRegion().translated(siblingOffset));
4018 QCOMPARE(w.numPaintEvents, 1);
4019 QCOMPARE(w.paintedRegion,
4020 w.visibleRegion() & sibling.visibleRegion().translated(siblingOffset));
4021 QCOMPARE(w.paintedRegion,
4022 (w.visibleRegion() - child.visibleRegion().translated(childOffset))
4023 & sibling.visibleRegion().translated(siblingOffset));
4030 sibling.setPalette(opaquePalette);
4031 sibling.setAutoFillBackground(true);
4034 QApplication::processEvents();
4035 QApplication::processEvents();
4037 // child opaque, sibling opaque
4039 QCOMPARE(sibling.numPaintEvents, 1);
4040 QCOMPARE(sibling.paintedRegion, sibling.visibleRegion());
4043 if (child.internalWinId()) // child is native
4044 QEXPECT_FAIL(0, "Cocoa compositor paints child and sibling", Continue);
4046 QCOMPARE(child.numPaintEvents, 0);
4047 QCOMPARE(child.visibleRegion(),
4048 QRegion(child.rect())
4049 - sibling.visibleRegion().translated(siblingOffset - childOffset));
4051 QCOMPARE(w.numPaintEvents, 0);
4052 QCOMPARE(w.visibleRegion(),
4054 - child.visibleRegion().translated(childOffset)
4055 - sibling.visibleRegion().translated(siblingOffset));
4059 static inline bool isOpaque(QWidget *widget)
4063 return qt_widget_private(widget)->isOpaque;
4066 void tst_QWidget::isOpaque()
4070 QVERIFY(::isOpaque(&w));
4073 QVERIFY(!::isOpaque(&child));
4075 child.setAutoFillBackground(true);
4076 QVERIFY(::isOpaque(&child));
4082 palette = child.palette();
4083 palette.setColor(child.backgroundRole(), QColor(255, 0, 0, 127));
4084 child.setPalette(palette);
4085 QVERIFY(!::isOpaque(&child));
4087 palette.setColor(child.backgroundRole(), QColor(255, 0, 0, 255));
4088 child.setPalette(palette);
4089 QVERIFY(::isOpaque(&child));
4091 palette.setColor(QPalette::Window, QColor(0, 0, 255, 127));
4092 w.setPalette(palette);
4094 QVERIFY(!::isOpaque(&w));
4096 child.setAutoFillBackground(false);
4097 QVERIFY(!::isOpaque(&child));
4099 // Qt::WA_OpaquePaintEvent
4101 child.setAttribute(Qt::WA_OpaquePaintEvent);
4102 QVERIFY(::isOpaque(&child));
4104 child.setAttribute(Qt::WA_OpaquePaintEvent, false);
4105 QVERIFY(!::isOpaque(&child));
4107 // Qt::WA_NoSystemBackground
4109 child.setAttribute(Qt::WA_NoSystemBackground);
4110 QVERIFY(!::isOpaque(&child));
4112 child.setAttribute(Qt::WA_NoSystemBackground, false);
4113 QVERIFY(!::isOpaque(&child));
4115 palette.setColor(QPalette::Window, QColor(0, 0, 255, 255));
4116 w.setPalette(palette);
4117 QVERIFY(::isOpaque(&w));
4119 w.setAttribute(Qt::WA_NoSystemBackground);
4120 QVERIFY(!::isOpaque(&w));
4122 w.setAttribute(Qt::WA_NoSystemBackground, false);
4123 QVERIFY(::isOpaque(&w));
4126 QPalette palette = QApplication::palette();
4127 QPalette old = palette;
4128 palette.setColor(QPalette::Window, Qt::transparent);
4129 QApplication::setPalette(palette);
4132 QVERIFY(!::isOpaque(&widget));
4134 QApplication::setPalette(old);
4135 QCOMPARE(::isOpaque(&widget), old.color(QPalette::Window).alpha() == 255);
4142 Test that scrolling of a widget invalidates the correct regions
4144 void tst_QWidget::scroll()
4146 UpdateWidget updateWidget;
4147 updateWidget.resize(500, 500);
4148 updateWidget.reset();
4149 updateWidget.show();
4150 QTest::qWaitForWindowShown(&updateWidget);
4152 qApp->processEvents();
4153 QTRY_VERIFY(updateWidget.numPaintEvents > 0);
4156 updateWidget.reset();
4157 updateWidget.scroll(10, 10);
4158 qApp->processEvents();
4159 QRegion dirty(QRect(0, 0, 500, 10));
4160 dirty += QRegion(QRect(0, 10, 10, 490));
4161 QCOMPARE(updateWidget.paintedRegion, dirty);
4165 updateWidget.reset();
4166 updateWidget.update(0, 0, 10, 10);
4167 updateWidget.scroll(0, 10);
4168 qApp->processEvents();
4169 QRegion dirty(QRect(0, 0, 500, 10));
4170 dirty += QRegion(QRect(0, 10, 10, 10));
4171 QCOMPARE(updateWidget.paintedRegion, dirty);
4175 updateWidget.reset();
4176 updateWidget.update(0, 0, 100, 100);
4177 updateWidget.scroll(10, 10, QRect(50, 50, 100, 100));
4178 qApp->processEvents();
4179 QRegion dirty(QRect(0, 0, 100, 50));
4180 dirty += QRegion(QRect(0, 50, 150, 10));
4181 dirty += QRegion(QRect(0, 60, 110, 40));
4182 dirty += QRegion(QRect(50, 100, 60, 10));
4183 dirty += QRegion(QRect(50, 110, 10, 40));
4184 QCOMPARE(updateWidget.paintedRegion, dirty);
4188 updateWidget.reset();
4189 updateWidget.update(0, 0, 100, 100);
4190 updateWidget.scroll(10, 10, QRect(100, 100, 100, 100));
4191 qApp->processEvents();
4192 QRegion dirty(QRect(0, 0, 100, 100));
4193 dirty += QRegion(QRect(100, 100, 100, 10));
4194 dirty += QRegion(QRect(100, 110, 10, 90));
4195 QCOMPARE(updateWidget.paintedRegion, dirty);
4200 class DestroyedSlotChecker : public QObject
4207 DestroyedSlotChecker()
4213 void destroyedSlot(QObject *object)
4215 wasQWidget = (qobject_cast<QWidget *>(object) != 0 || object->isWidgetType());
4220 Test that qobject_cast<QWidget*> returns 0 in a slot
4221 connected to QObject::destroyed.
4223 void tst_QWidget::qobject_castInDestroyedSlot()
4225 DestroyedSlotChecker checker;
4226 QWidget *widget = new QWidget();
4228 QObject::connect(widget, SIGNAL(destroyed(QObject *)), &checker, SLOT(destroyedSlot(QObject *)));
4231 QVERIFY(checker.wasQWidget == true);
4234 Q_DECLARE_METATYPE(QList<QRect>)
4236 // Since X11 WindowManager operations are all async, and we have no way to know if the window
4237 // manager has finished playing with the window geometry, this test can't be reliable on X11.
4239 void tst_QWidget::setWindowGeometry_data()
4241 QTest::addColumn<QList<QRect> >("rects");
4242 QTest::addColumn<int>("windowFlags");
4244 QList<QList<QRect> > rects;
4245 rects << (QList<QRect>()
4246 << QRect(100, 100, 200, 200)
4247 << QApplication::desktop()->availableGeometry().adjusted(100, 100, -100, -100)
4248 << QRect(130, 100, 0, 200)
4249 << QRect(100, 50, 200, 0)
4250 << QRect(130, 50, 0, 0))
4252 << QApplication::desktop()->availableGeometry().adjusted(100, 100, -100, -100)
4253 << QRect(130, 100, 0, 200)
4254 << QRect(100, 50, 200, 0)
4255 << QRect(130, 50, 0, 0)
4256 << QRect(100, 100, 200, 200))
4258 << QRect(130, 100, 0, 200)
4259 << QRect(100, 50, 200, 0)
4260 << QRect(130, 50, 0, 0)
4261 << QRect(100, 100, 200, 200)
4262 << QApplication::desktop()->availableGeometry().adjusted(100, 100, -100, -100))
4264 << QRect(100, 50, 200, 0)
4265 << QRect(130, 50, 0, 0)
4266 << QRect(100, 100, 200, 200)
4267 << QApplication::desktop()->availableGeometry().adjusted(100, 100, -100, -100)
4268 << QRect(130, 100, 0, 200))
4270 << QRect(130, 50, 0, 0)
4271 << QRect(100, 100, 200, 200)
4272 << QApplication::desktop()->availableGeometry().adjusted(100, 100, -100, -100)
4273 << QRect(130, 100, 0, 200)
4274 << QRect(100, 50, 200, 0));
4276 QList<int> windowFlags;
4277 windowFlags << 0 << Qt::FramelessWindowHint;
4279 foreach (QList<QRect> l, rects) {
4280 QRect rect = l.first();
4281 foreach (int windowFlag, windowFlags) {
4282 QTest::newRow(QString("%1,%2 %3x%4, flags %5")
4287 .arg(windowFlag, 0, 16).toLatin1())
4294 void tst_QWidget::setWindowGeometry()
4296 if (m_platform == QStringLiteral("xcb"))
4297 QSKIP("X11: Skip this test due to Window manager positioning issues.");
4299 QFETCH(QList<QRect>, rects);
4300 QFETCH(int, windowFlags);
4301 QRect rect = rects.takeFirst();
4304 // test setGeometry() without actually showing the window
4306 if (windowFlags != 0)
4307 widget.setWindowFlags(Qt::WindowFlags(windowFlags));
4309 widget.setGeometry(rect);
4311 QCOMPARE(widget.geometry(), rect);
4313 // setGeometry() without showing
4314 foreach (QRect r, rects) {
4315 widget.setGeometry(r);
4317 QCOMPARE(widget.geometry(), r);
4322 // setGeometry() first, then show()
4324 if (windowFlags != 0)
4325 widget.setWindowFlags(Qt::WindowFlags(windowFlags));
4327 widget.setGeometry(rect);
4329 QTest::qWaitForWindowShown(&widget);
4331 QTRY_COMPARE(widget.geometry(), rect);
4333 // setGeometry() while shown
4334 foreach (QRect r, rects) {
4335 widget.setGeometry(r);
4337 QTRY_COMPARE(widget.geometry(), r);
4339 widget.setGeometry(rect);
4341 QTRY_COMPARE(widget.geometry(), rect);
4346 QTRY_COMPARE(widget.geometry(), rect);
4348 // setGeometry() after hide()
4349 foreach (QRect r, rects) {
4350 widget.setGeometry(r);
4352 QTRY_COMPARE(widget.geometry(), r);
4354 widget.setGeometry(rect);
4356 QTRY_COMPARE(widget.geometry(), rect);
4358 // show() again, geometry() should still be the same
4360 QTest::qWaitForWindowShown(&widget);
4362 QTRY_COMPARE(widget.geometry(), rect);
4364 // final hide(), again geometry() should be unchanged
4367 QTRY_COMPARE(widget.geometry(), rect);
4371 // show() first, then setGeometry()
4373 if (windowFlags != 0)
4374 widget.setWindowFlags(Qt::WindowFlags(windowFlags));
4377 QTest::qWaitForWindowShown(&widget);
4378 widget.setGeometry(rect);
4380 QTRY_COMPARE(widget.geometry(), rect);
4382 // setGeometry() while shown
4383 foreach (QRect r, rects) {
4384 widget.setGeometry(r);
4386 QTRY_COMPARE(widget.geometry(), r);
4388 widget.setGeometry(rect);
4390 QTRY_COMPARE(widget.geometry(), rect);
4395 QTRY_COMPARE(widget.geometry(), rect);
4397 // setGeometry() after hide()
4398 foreach (QRect r, rects) {
4399 widget.setGeometry(r);
4401 QTRY_COMPARE(widget.geometry(), r);
4403 widget.setGeometry(rect);
4405 QTRY_COMPARE(widget.geometry(), rect);
4407 // show() again, geometry() should still be the same
4409 QTest::qWaitForWindowShown(&widget);
4411 QTRY_COMPARE(widget.geometry(), rect);
4413 // final hide(), again geometry() should be unchanged
4416 QTRY_COMPARE(widget.geometry(), rect);
4420 #if defined (Q_OS_WIN) && !defined(Q_OS_WINCE)
4421 void tst_QWidget::setGeometry_win()
4424 widget.setGeometry(0, 600, 100,100);
4426 widget.setWindowState(widget.windowState() | Qt::WindowMaximized);
4427 QRect geom = widget.normalGeometry();
4429 widget.setGeometry(geom);
4430 widget.setWindowState(widget.windowState() | Qt::WindowMaximized);
4433 ::GetWindowRect(winHandleOf(&widget), &rt);
4434 QVERIFY(rt.left <= 0);
4435 QVERIFY(rt.top <= 0);
4437 #endif // defined (Q_OS_WIN) && !defined(Q_OS_WINCE)
4439 // Since X11 WindowManager operation are all async, and we have no way to know if the window
4440 // manager has finished playing with the window geometry, this test can't be reliable on X11.
4442 void tst_QWidget::windowMoveResize_data()
4444 setWindowGeometry_data();
4447 void tst_QWidget::windowMoveResize()
4449 if (m_platform == QStringLiteral("xcb"))
4450 QSKIP("X11: Skip this test due to Window manager positioning issues.");
4452 QFETCH(QList<QRect>, rects);
4453 QFETCH(int, windowFlags);
4455 QRect rect = rects.takeFirst();
4458 // test setGeometry() without actually showing the window
4460 if (windowFlags != 0)
4461 widget.setWindowFlags(Qt::WindowFlags(windowFlags));
4463 widget.move(rect.topLeft());
4464 widget.resize(rect.size());
4466 QTRY_COMPARE(widget.pos(), rect.topLeft());
4467 QTRY_COMPARE(widget.size(), rect.size());
4469 // move() without showing
4470 foreach (QRect r, rects) {
4471 widget.move(r.topLeft());
4472 widget.resize(r.size());
4473 QApplication::processEvents();
4474 QTRY_COMPARE(widget.pos(), r.topLeft());
4475 QTRY_COMPARE(widget.size(), r.size());
4480 // move() first, then show()
4482 if (windowFlags != 0)
4483 widget.setWindowFlags(Qt::WindowFlags(windowFlags));
4485 widget.move(rect.topLeft());
4486 widget.resize(rect.size());
4490 QTRY_COMPARE(widget.pos(), rect.topLeft());
4491 QTRY_COMPARE(widget.size(), rect.size());
4493 // move() while shown
4494 foreach (const QRect &r, rects) {
4495 if (m_platform == QStringLiteral("xcb")
4496 && ((widget.width() == 0 || widget.height() == 0) && r.width() != 0 && r.height() != 0)) {
4497 QEXPECT_FAIL("130,100 0x200, flags 0",
4498 "First resize after show of zero-sized gets wrong win_gravity.",
4500 QEXPECT_FAIL("100,50 200x0, flags 0",
4501 "First resize after show of zero-sized gets wrong win_gravity.",
4503 QEXPECT_FAIL("130,50 0x0, flags 0",
4504 "First resize after show of zero-sized gets wrong win_gravity.",
4508 widget.move(r.topLeft());
4509 widget.resize(r.size());
4510 QApplication::processEvents();
4511 QTRY_COMPARE(widget.pos(), r.topLeft());
4512 QTRY_COMPARE(widget.size(), r.size());
4514 widget.move(rect.topLeft());
4515 widget.resize(rect.size());
4516 QApplication::processEvents();
4517 QTRY_COMPARE(widget.pos(), rect.topLeft());
4518 QTRY_COMPARE(widget.size(), rect.size());
4523 QTRY_COMPARE(widget.pos(), rect.topLeft());
4524 QTRY_COMPARE(widget.size(), rect.size());
4526 // move() after hide()
4527 foreach (QRect r, rects) {
4528 widget.move(r.topLeft());
4529 widget.resize(r.size());
4530 QApplication::processEvents();
4531 #if defined(Q_OS_MAC)
4532 if (r.width() == 0 && r.height() > 0) {
4533 widget.move(r.topLeft());
4534 widget.resize(r.size());
4537 QTRY_COMPARE(widget.pos(), r.topLeft());
4538 QTRY_COMPARE(widget.size(), r.size());
4540 widget.move(rect.topLeft());
4541 widget.resize(rect.size());
4543 QTRY_COMPARE(widget.pos(), rect.topLeft());
4544 QTRY_COMPARE(widget.size(), rect.size());
4546 // show() again, pos() should be the same
4548 QTest::qWaitForWindowShown(&widget);
4549 QApplication::processEvents();
4550 QTRY_COMPARE(widget.pos(), rect.topLeft());
4551 QTRY_COMPARE(widget.size(), rect.size());
4553 // final hide(), again pos() should be unchanged
4555 QApplication::processEvents();
4556 QTRY_COMPARE(widget.pos(), rect.topLeft());
4557 QTRY_COMPARE(widget.size(), rect.size());
4561 // show() first, then move()
4563 if (windowFlags != 0)
4564 widget.setWindowFlags(Qt::WindowFlags(windowFlags));
4567 QTest::qWaitForWindowShown(&widget);
4568 QApplication::processEvents();
4569 widget.move(rect.topLeft());
4570 widget.resize(rect.size());
4571 QApplication::processEvents();
4572 QTRY_COMPARE(widget.pos(), rect.topLeft());
4573 QTRY_COMPARE(widget.size(), rect.size());
4575 // move() while shown
4576 foreach (QRect r, rects) {
4577 widget.move(r.topLeft());
4578 widget.resize(r.size());
4579 QApplication::processEvents();
4580 QTRY_COMPARE(widget.pos(), r.topLeft());
4581 QTRY_COMPARE(widget.size(), r.size());
4583 widget.move(rect.topLeft());
4584 widget.resize(rect.size());
4585 QApplication::processEvents();
4586 QTRY_COMPARE(widget.pos(), rect.topLeft());
4587 QTRY_COMPARE(widget.size(), rect.size());
4591 QApplication::processEvents();
4592 QTRY_COMPARE(widget.pos(), rect.topLeft());
4593 QTRY_COMPARE(widget.size(), rect.size());
4595 // move() after hide()
4596 foreach (QRect r, rects) {
4597 widget.move(r.topLeft());
4598 widget.resize(r.size());
4599 QApplication::processEvents();
4600 #if defined(Q_OS_MAC)
4601 if (r.width() == 0 && r.height() > 0) {
4602 widget.move(r.topLeft());
4603 widget.resize(r.size());
4606 QTRY_COMPARE(widget.pos(), r.topLeft());
4607 QTRY_COMPARE(widget.size(), r.size());
4609 widget.move(rect.topLeft());
4610 widget.resize(rect.size());
4611 QApplication::processEvents();
4612 QTRY_COMPARE(widget.pos(), rect.topLeft());
4613 QTRY_COMPARE(widget.size(), rect.size());
4615 // show() again, pos() should be the same
4617 QTest::qWaitForWindowShown(&widget);
4619 QTRY_COMPARE(widget.pos(), rect.topLeft());
4620 QTRY_COMPARE(widget.size(), rect.size());
4622 // final hide(), again pos() should be unchanged
4625 QTRY_COMPARE(widget.pos(), rect.topLeft());
4626 QTRY_COMPARE(widget.size(), rect.size());
4630 class ColorWidget : public QWidget
4633 ColorWidget(QWidget *parent = 0, const QColor &c = QColor(Qt::red))
4634 : QWidget(parent, Qt::FramelessWindowHint), color(c)
4636 QPalette opaquePalette = palette();
4637 opaquePalette.setColor(backgroundRole(), color);
4638 setPalette(opaquePalette);
4639 setAutoFillBackground(true);
4642 void paintEvent(QPaintEvent *e) {
4654 #define VERIFY_COLOR(region, color) { \
4655 const QRegion r = QRegion(region); \
4656 QScreen *screen = qApp->primaryScreen(); \
4657 const WId desktopWinId = QDesktopWidget().winId(); \
4658 for (int i = 0; i < r.rects().size(); ++i) { \
4659 const QRect rect = r.rects().at(i); \
4660 for (int t = 0; t < 5; t++) { \
4661 const QPixmap pixmap = screen->grabWindow(desktopWinId, \
4662 rect.left(), rect.top(), \
4663 rect.width(), rect.height()); \
4664 QCOMPARE(pixmap.size(), rect.size()); \
4665 QPixmap expectedPixmap(pixmap); /* ensure equal formats */ \
4666 expectedPixmap.detach(); \
4667 expectedPixmap.fill(color); \
4668 QImage image = pixmap.toImage(); \
4669 uint alphaCorrection = image.format() == QImage::Format_RGB32 ? 0xff000000 : 0; \
4670 uint firstPixel = image.pixel(0,0) | alphaCorrection; \
4671 if ( firstPixel != QColor(color).rgb() && t < 4 ) \
4672 { QTest::qWait(200); continue; } \
4673 QCOMPARE(firstPixel, QColor(color).rgb()); \
4674 QCOMPARE(pixmap, expectedPixmap); \
4680 void tst_QWidget::popupEnterLeave()
4683 parent.setWindowFlags(Qt::FramelessWindowHint);
4684 parent.setGeometry(10, 10, 200, 100);
4686 ColorWidget alien(&parent, Qt::black);
4687 alien.setGeometry(0, 0, 10, 10);
4692 QTest::qWaitForWindowShown(parent.windowHandle());
4694 QWindowSystemInterface::handleMouseEvent(parent.windowHandle(), QPointF(5, 5), QPointF(), Qt::LeftButton, Qt::NoModifier);
4696 QWindowSystemInterface::handleMouseEvent(parent.windowHandle(), QPointF(5, 5), QPointF(), Qt::NoButton, Qt::NoModifier);
4699 QStringList wordList;
4700 wordList << "alpha" << "omega" << "omicron" << "zeta";
4702 QLineEdit popup(&parent);
4704 QCompleter completer(wordList);
4705 completer.setCaseSensitivity(Qt::CaseInsensitive);
4706 popup.setCompleter(&completer);
4707 popup.setWindowFlags(Qt::Popup);
4708 popup.setGeometry(20, 20, 80, 20);
4712 QTest::qWaitForWindowShown(popup.windowHandle());
4716 QWindowSystemInterface::handleMouseEvent(popup.windowHandle(), QPointF(-5, -5), QPointF(), Qt::LeftButton, Qt::NoModifier);
4718 QWindowSystemInterface::handleMouseEvent(popup.windowHandle(), QPointF(-5, -5), QPointF(), Qt::NoButton, Qt::NoModifier);
4722 QVERIFY(!popup.underMouse());
4725 void tst_QWidget::moveChild_data()
4727 QTest::addColumn<QPoint>("offset");
4729 QTest::newRow("right") << QPoint(20, 0);
4730 QTest::newRow("down") << QPoint(0, 20);
4731 QTest::newRow("left") << QPoint(-20, 0);
4732 QTest::newRow("up") << QPoint(0, -20);
4735 void tst_QWidget::moveChild()
4737 QFETCH(QPoint, offset);
4740 // prevent custom styles
4741 parent.setStyle(new QWindowsStyle);
4742 ColorWidget child(&parent, Qt::blue);
4745 parent.setGeometry(QRect(QPoint(QApplication::desktop()->availableGeometry(&parent).topLeft()),
4748 parent.setGeometry(60, 60, 150, 150);
4750 child.setGeometry(25, 25, 50, 50);
4752 QTest::qWaitForWindowShown(&parent);
4754 const QPoint tlwOffset = parent.geometry().topLeft();
4756 QTRY_COMPARE(parent.r, QRegion(parent.rect()) - child.geometry());
4757 QTRY_COMPARE(child.r, QRegion(child.rect()));
4758 VERIFY_COLOR(child.geometry().translated(tlwOffset),
4760 VERIFY_COLOR(QRegion(parent.geometry()) - child.geometry().translated(tlwOffset),
4767 const QRect oldGeometry = child.geometry();
4769 QPoint pos = child.pos() + offset;
4772 QTRY_COMPARE(pos, child.pos());
4774 QCOMPARE(parent.r, QRegion(oldGeometry) - child.geometry());
4775 #if !defined(Q_OS_MAC)
4776 // should be scrolled in backingstore
4777 QCOMPARE(child.r, QRegion());
4779 VERIFY_COLOR(child.geometry().translated(tlwOffset),
4781 VERIFY_COLOR(QRegion(parent.geometry()) - child.geometry().translated(tlwOffset),
4785 void tst_QWidget::showAndMoveChild()
4787 QWidget parent(0, Qt::FramelessWindowHint);
4788 // prevent custom styles
4789 parent.setStyle(new QWindowsStyle);
4791 QDesktopWidget desktop;
4792 QRect desktopDimensions = desktop.availableGeometry(&parent);
4793 desktopDimensions = desktopDimensions.adjusted(64, 64, -64, -64);
4795 parent.setGeometry(desktopDimensions);
4796 parent.setPalette(Qt::red);
4798 QTest::qWaitForWindowShown(&parent);
4801 const QPoint tlwOffset = parent.geometry().topLeft();
4802 QWidget child(&parent);
4803 child.resize(desktopDimensions.width()/2, desktopDimensions.height()/2);
4804 child.setPalette(Qt::blue);
4805 child.setAutoFillBackground(true);
4807 // Ensure that the child is repainted correctly when moved right after show.
4808 // NB! Do NOT processEvents() (or qWait()) in between show() and move().
4810 child.move(desktopDimensions.width()/2, desktopDimensions.height()/2);
4811 qApp->processEvents();
4813 VERIFY_COLOR(child.geometry().translated(tlwOffset), Qt::blue);
4814 VERIFY_COLOR(QRegion(parent.geometry()) - child.geometry().translated(tlwOffset), Qt::red);
4817 // Cocoa only has rect granularity.
4819 void tst_QWidget::subtractOpaqueSiblings()
4822 w.setGeometry(50, 50, 300, 300);
4824 ColorWidget *large = new ColorWidget(&w, Qt::red);
4825 large->setGeometry(50, 50, 200, 200);
4827 ColorWidget *medium = new ColorWidget(large, Qt::gray);
4828 medium->setGeometry(50, 50, 100, 100);
4830 ColorWidget *tall = new ColorWidget(&w, Qt::blue);
4831 tall->setGeometry(100, 30, 50, 100);
4834 QTest::qWaitForWindowShown(&w);
4844 // QWidgetPrivate::subtractOpaqueSiblings() should prevent parts of medium
4845 // to be repainted and tall from be repainted at all.
4847 QTRY_COMPARE(large->r, QRegion());
4848 QTRY_COMPARE(tall->r, QRegion());
4849 QTRY_COMPARE(medium->r.translated(medium->mapTo(&w, QPoint())),
4850 QRegion(medium->geometry().translated(large->pos()))
4851 - tall->geometry());
4855 void tst_QWidget::deleteStyle()
4858 widget.setStyle(new QWindowsStyle);
4860 delete widget.style();
4861 qApp->processEvents();
4864 class TopLevelFocusCheck: public QWidget
4869 TopLevelFocusCheck(QWidget* parent = 0) : QWidget(parent)
4871 edit = new QLineEdit(this);
4873 edit->installEventFilter(this);
4877 void mouseDoubleClickEvent ( QMouseEvent * /*event*/ )
4880 edit->setFocus(Qt::OtherFocusReason);
4881 qApp->processEvents();
4883 bool eventFilter(QObject *obj, QEvent *event)
4885 if (obj == edit && event->type()== QEvent::FocusOut) {
4893 void tst_QWidget::multipleToplevelFocusCheck()
4895 TopLevelFocusCheck w1;
4896 TopLevelFocusCheck w2;
4898 w1.resize(200, 200);
4900 QTest::qWaitForWindowShown(&w1);
4903 QTest::qWaitForWindowShown(&w2);
4907 QApplication::setActiveWindow(&w1);
4908 w1.activateWindow();
4909 QApplication::processEvents();
4910 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&w1));
4912 QTest::mouseDClick(&w1, Qt::LeftButton);
4913 QTRY_COMPARE(QApplication::focusWidget(), static_cast<QWidget *>(w1.edit));
4915 w2.activateWindow();
4916 QApplication::setActiveWindow(&w2);
4917 QApplication::processEvents();
4918 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&w2));
4919 QTest::mouseClick(&w2, Qt::LeftButton);
4920 QTRY_COMPARE(QApplication::focusWidget(), (QWidget *)0);
4922 QTest::mouseDClick(&w2, Qt::LeftButton);
4923 QTRY_COMPARE(QApplication::focusWidget(), static_cast<QWidget *>(w2.edit));
4925 w1.activateWindow();
4926 QApplication::setActiveWindow(&w1);
4927 QApplication::processEvents();
4928 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&w1));
4929 QTest::mouseDClick(&w1, Qt::LeftButton);
4930 QTRY_COMPARE(QApplication::focusWidget(), static_cast<QWidget *>(w1.edit));
4932 w2.activateWindow();
4933 QApplication::setActiveWindow(&w2);
4934 QApplication::processEvents();
4935 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&w2));
4936 QTest::mouseClick(&w2, Qt::LeftButton);
4937 QTRY_COMPARE(QApplication::focusWidget(), (QWidget *)0);
4940 class FocusWidget: public QWidget
4943 virtual bool event(QEvent *ev)
4945 if (ev->type() == QEvent::FocusAboutToChange)
4946 widgetDuringFocusAboutToChange = qApp->focusWidget();
4947 return QWidget::event(ev);
4949 virtual void focusOutEvent(QFocusEvent *)
4951 widgetDuringFocusOut = qApp->focusWidget();
4955 FocusWidget(QWidget *parent) : QWidget(parent), widgetDuringFocusAboutToChange(0), widgetDuringFocusOut(0) {}
4957 QWidget *widgetDuringFocusAboutToChange;
4958 QWidget *widgetDuringFocusOut;
4961 void tst_QWidget::setFocus()
4964 // move focus to another window
4965 testWidget->activateWindow();
4966 QApplication::setActiveWindow(testWidget);
4967 if (testWidget->focusWidget())
4968 testWidget->focusWidget()->clearFocus();
4970 testWidget->clearFocus();
4972 // window and children never shown, nobody gets focus
4975 QWidget child1(&window);
4976 child1.setFocusPolicy(Qt::StrongFocus);
4978 QWidget child2(&window);
4979 child2.setFocusPolicy(Qt::StrongFocus);
4982 QVERIFY(!child1.hasFocus());
4983 QCOMPARE(window.focusWidget(), &child1);
4984 QCOMPARE(QApplication::focusWidget(), static_cast<QWidget *>(0));
4987 QVERIFY(!child2.hasFocus());
4988 QCOMPARE(window.focusWidget(), &child2);
4989 QCOMPARE(QApplication::focusWidget(), static_cast<QWidget *>(0));
4993 // window and children show, but window not active, nobody gets focus
4996 QWidget child1(&window);
4997 child1.setFocusPolicy(Qt::StrongFocus);
4999 QWidget child2(&window);
5000 child2.setFocusPolicy(Qt::StrongFocus);
5004 // note: window may be active, but we don't want it to be
5005 testWidget->activateWindow();
5006 QApplication::setActiveWindow(testWidget);
5007 if (testWidget->focusWidget())
5008 testWidget->focusWidget()->clearFocus();
5010 testWidget->clearFocus();
5013 QVERIFY(!child1.hasFocus());
5014 QCOMPARE(window.focusWidget(), &child1);
5015 QCOMPARE(QApplication::focusWidget(), static_cast<QWidget *>(0));
5018 QVERIFY(!child2.hasFocus());
5019 QCOMPARE(window.focusWidget(), &child2);
5020 QCOMPARE(QApplication::focusWidget(), static_cast<QWidget *>(0));
5024 // window and children show, but window *is* active, children get focus
5027 FocusWidget child1(&window);
5028 child1.setFocusPolicy(Qt::StrongFocus);
5030 QWidget child2(&window);
5031 child2.setFocusPolicy(Qt::StrongFocus);
5034 window.activateWindow();
5035 QTest::qWaitForWindowShown(&window);
5036 QTRY_VERIFY(qGuiApp->focusWindow());
5039 QTRY_VERIFY(child1.hasFocus());
5040 QCOMPARE(window.focusWidget(), &child1);
5041 QCOMPARE(QApplication::focusWidget(), &child1);
5044 QVERIFY(child2.hasFocus());
5045 QCOMPARE(window.focusWidget(), &child2);
5046 QCOMPARE(QApplication::focusWidget(), &child2);
5048 // focus changed in between the events
5049 QCOMPARE(child1.widgetDuringFocusAboutToChange, &child1);
5050 QCOMPARE(child1.widgetDuringFocusOut, &child2);
5054 // window shown and active, children created, don't get focus, but get focus when shown
5058 window.activateWindow();
5059 QTest::qWaitForWindowShown(&window);
5060 QTRY_VERIFY(qGuiApp->focusWindow());
5062 QWidget child1(&window);
5063 child1.setFocusPolicy(Qt::StrongFocus);
5065 QWidget child2(&window);
5066 child2.setFocusPolicy(Qt::StrongFocus);
5069 QVERIFY(!child1.hasFocus());
5070 QCOMPARE(window.focusWidget(), static_cast<QWidget *>(0));
5071 QCOMPARE(QApplication::focusWidget(), static_cast<QWidget *>(0));
5074 QApplication::processEvents();
5075 QTRY_VERIFY(child1.hasFocus());
5076 QCOMPARE(window.focusWidget(), &child1);
5077 QCOMPARE(QApplication::focusWidget(), &child1);
5080 QVERIFY(!child2.hasFocus());
5081 QCOMPARE(window.focusWidget(), &child1);
5082 QCOMPARE(QApplication::focusWidget(), &child1);
5085 QVERIFY(child2.hasFocus());
5086 QCOMPARE(window.focusWidget(), &child2);
5087 QCOMPARE(QApplication::focusWidget(), &child2);
5091 // window shown and active, children created, don't get focus,
5092 // even after setFocus(), hide(), then show()
5096 window.activateWindow();
5097 QTest::qWaitForWindowShown(&window);
5098 QTRY_VERIFY(qGuiApp->focusWindow());
5100 QWidget child1(&window);
5101 child1.setFocusPolicy(Qt::StrongFocus);
5103 QWidget child2(&window);
5104 child2.setFocusPolicy(Qt::StrongFocus);
5107 QVERIFY(!child1.hasFocus());
5108 QCOMPARE(window.focusWidget(), static_cast<QWidget *>(0));
5109 QCOMPARE(QApplication::focusWidget(), static_cast<QWidget *>(0));
5112 QVERIFY(!child1.hasFocus());
5113 QCOMPARE(window.focusWidget(), static_cast<QWidget *>(0));
5114 QCOMPARE(QApplication::focusWidget(), static_cast<QWidget *>(0));
5117 QVERIFY(!child1.hasFocus());
5118 QCOMPARE(window.focusWidget(), static_cast<QWidget *>(0));
5119 QCOMPARE(QApplication::focusWidget(), static_cast<QWidget *>(0));
5122 QVERIFY(!child2.hasFocus());
5123 QCOMPARE(window.focusWidget(), static_cast<QWidget *>(0));
5124 QCOMPARE(QApplication::focusWidget(), static_cast<QWidget *>(0));
5127 QVERIFY(!child2.hasFocus());
5128 QCOMPARE(window.focusWidget(), static_cast<QWidget *>(0));
5129 QCOMPARE(QApplication::focusWidget(), static_cast<QWidget *>(0));
5132 QVERIFY(!child2.hasFocus());
5133 QCOMPARE(window.focusWidget(), static_cast<QWidget *>(0));
5134 QCOMPARE(QApplication::focusWidget(), static_cast<QWidget *>(0));
5138 class EventSpy : public QObject
5141 EventSpy(QWidget *widget, QEvent::Type event)
5142 : m_widget(widget), eventToSpy(event), m_count(0)
5145 m_widget->installEventFilter(this);
5148 QWidget *widget() const { return m_widget; }
5149 int count() const { return m_count; }
5150 void clear() { m_count = 0; }
5153 bool eventFilter(QObject *object, QEvent *event)
5155 if (event->type() == eventToSpy)
5157 return QObject::eventFilter(object, event);
5162 QEvent::Type eventToSpy;
5166 void tst_QWidget::setCursor()
5168 #ifndef QT_NO_CURSOR
5171 QWidget child(&window);
5173 QVERIFY(!window.testAttribute(Qt::WA_SetCursor));
5174 QVERIFY(!child.testAttribute(Qt::WA_SetCursor));
5176 window.setCursor(window.cursor());
5177 QVERIFY(window.testAttribute(Qt::WA_SetCursor));
5178 QVERIFY(!child.testAttribute(Qt::WA_SetCursor));
5179 QCOMPARE(child.cursor().shape(), window.cursor().shape());
5182 // do it again, but with window show()n
5185 QWidget child(&window);
5188 QVERIFY(!window.testAttribute(Qt::WA_SetCursor));
5189 QVERIFY(!child.testAttribute(Qt::WA_SetCursor));
5191 window.setCursor(window.cursor());
5192 QVERIFY(window.testAttribute(Qt::WA_SetCursor));
5193 QVERIFY(!child.testAttribute(Qt::WA_SetCursor));
5194 QCOMPARE(child.cursor().shape(), window.cursor().shape());
5200 QWidget child(&window);
5202 window.setCursor(Qt::WaitCursor);
5203 QVERIFY(window.testAttribute(Qt::WA_SetCursor));
5204 QVERIFY(!child.testAttribute(Qt::WA_SetCursor));
5205 QCOMPARE(child.cursor().shape(), window.cursor().shape());
5208 // same thing again, just with window show()n
5211 QWidget child(&window);
5214 window.setCursor(Qt::WaitCursor);
5215 QVERIFY(window.testAttribute(Qt::WA_SetCursor));
5216 QVERIFY(!child.testAttribute(Qt::WA_SetCursor));
5217 QCOMPARE(child.cursor().shape(), window.cursor().shape());
5220 // reparenting child should not cause the WA_SetCursor to become set
5224 QWidget child(&window);
5226 window.setCursor(Qt::WaitCursor);
5229 QVERIFY(!child.testAttribute(Qt::WA_SetCursor));
5230 QCOMPARE(child.cursor().shape(), QCursor().shape());
5232 child.setParent(&window2);
5233 QVERIFY(!child.testAttribute(Qt::WA_SetCursor));
5234 QCOMPARE(child.cursor().shape(), window2.cursor().shape());
5236 window2.setCursor(Qt::WaitCursor);
5237 QVERIFY(!child.testAttribute(Qt::WA_SetCursor));
5238 QCOMPARE(child.cursor().shape(), window2.cursor().shape());
5241 // again, with windows show()n
5245 QWidget child(&window);
5247 window.setCursor(Qt::WaitCursor);
5251 QVERIFY(!child.testAttribute(Qt::WA_SetCursor));
5252 QCOMPARE(child.cursor().shape(), QCursor().shape());
5254 child.setParent(&window2);
5255 QVERIFY(!child.testAttribute(Qt::WA_SetCursor));
5256 QCOMPARE(child.cursor().shape(), window2.cursor().shape());
5259 window2.setCursor(Qt::WaitCursor);
5260 QVERIFY(!child.testAttribute(Qt::WA_SetCursor));
5261 QCOMPARE(child.cursor().shape(), window2.cursor().shape());
5264 // test if CursorChange is sent
5267 EventSpy spy(&widget, QEvent::CursorChange);
5268 QCOMPARE(spy.count(), 0);
5269 widget.setCursor(QCursor(Qt::WaitCursor));
5270 QCOMPARE(spy.count(), 1);
5271 widget.unsetCursor();
5272 QCOMPARE(spy.count(), 2);
5277 void tst_QWidget::setToolTip()
5280 EventSpy spy(&widget, QEvent::ToolTipChange);
5281 QCOMPARE(spy.count(), 0);
5283 QCOMPARE(widget.toolTip(), QString());
5284 widget.setToolTip(QString("Hello"));
5285 QCOMPARE(widget.toolTip(), QString("Hello"));
5286 QCOMPARE(spy.count(), 1);
5287 widget.setToolTip(QString());
5288 QCOMPARE(widget.toolTip(), QString());
5289 QCOMPARE(spy.count(), 2);
5291 // Mouse over doesn't work on Windows mobile, so skip the rest of the test for that platform.
5292 #ifndef Q_OS_WINCE_WM
5293 for (int pass = 0; pass < 2; ++pass) {
5294 QWidget *popup = new QWidget(0, Qt::Popup);
5295 popup->resize(150, 50);
5296 QFrame *frame = new QFrame(popup);
5297 frame->setGeometry(0, 0, 50, 50);
5298 frame->setFrameStyle(QFrame::Box | QFrame::Plain);
5299 EventSpy spy1(frame, QEvent::ToolTip);
5300 EventSpy spy2(popup, QEvent::ToolTip);
5301 frame->setMouseTracking(pass == 0 ? false : true);
5302 frame->setToolTip(QLatin1String("TOOLTIP FRAME"));
5303 popup->setToolTip(QLatin1String("TOOLTIP POPUP"));
5305 QTest::qWaitForWindowShown(popup);
5307 QTest::mouseMove(frame);
5308 QTest::qWait(900); // delay is 700
5310 QCOMPARE(spy1.count(), 1);
5311 QCOMPARE(spy2.count(), 0);
5313 QTest::qWait(2200); // delay is 2000
5314 QTest::mouseMove(popup);
5320 void tst_QWidget::testWindowIconChangeEventPropagation()
5322 // Create widget hierarchy.
5323 QWidget topLevelWidget;
5324 QWidget topLevelChild(&topLevelWidget);
5326 QDialog dialog(&topLevelWidget);
5327 QWidget dialogChild(&dialog);
5329 QWidgetList widgets;
5330 widgets << &topLevelWidget << &topLevelChild
5331 << &dialog << &dialogChild;
5332 QCOMPARE(widgets.count(), 4);
5334 // Create spy lists.
5335 QList <EventSpy *> applicationEventSpies;
5336 QList <EventSpy *> widgetEventSpies;
5337 foreach (QWidget *widget, widgets) {
5338 applicationEventSpies.append(new EventSpy(widget, QEvent::ApplicationWindowIconChange));
5339 widgetEventSpies.append(new EventSpy(widget, QEvent::WindowIconChange));
5342 // QApplication::setWindowIcon
5343 const QIcon windowIcon = qApp->style()->standardIcon(QStyle::SP_TitleBarMenuButton);
5344 qApp->setWindowIcon(windowIcon);
5346 for (int i = 0; i < widgets.count(); ++i) {
5347 // Check QEvent::ApplicationWindowIconChange
5348 EventSpy *spy = applicationEventSpies.at(i);
5349 QWidget *widget = spy->widget();
5350 if (widget->isWindow()) {
5351 QCOMPARE(spy->count(), 1);
5352 QCOMPARE(widget->windowIcon(), windowIcon);
5354 QCOMPARE(spy->count(), 0);
5358 // Check QEvent::WindowIconChange
5359 spy = widgetEventSpies.at(i);
5360 QCOMPARE(spy->count(), 1);
5364 // Set icon on a top-level widget.
5365 topLevelWidget.setWindowIcon(*new QIcon);
5367 for (int i = 0; i < widgets.count(); ++i) {
5368 // Check QEvent::ApplicationWindowIconChange
5369 EventSpy *spy = applicationEventSpies.at(i);
5370 QCOMPARE(spy->count(), 0);
5373 // Check QEvent::WindowIconChange
5374 spy = widgetEventSpies.at(i);
5375 QWidget *widget = spy->widget();
5376 if (widget == &topLevelWidget) {
5377 QCOMPARE(widget->windowIcon(), QIcon());
5378 QCOMPARE(spy->count(), 1);
5379 } else if (topLevelWidget.isAncestorOf(widget)) {
5380 QCOMPARE(spy->count(), 1);
5382 QCOMPARE(spy->count(), 0);
5388 for (int i = 0; i < widgets.count(); ++i) {
5389 delete applicationEventSpies.at(i);
5390 delete widgetEventSpies.at(i);
5392 qApp->setWindowIcon(QIcon());
5395 void tst_QWidget::minAndMaxSizeWithX11BypassWindowManagerHint()
5397 if (m_platform != QStringLiteral("xcb"))
5398 QSKIP("This test is for X11 only.");
5399 // Same size as in QWidget::create_sys().
5400 const QSize desktopSize = QApplication::desktop()->size();
5401 const QSize originalSize(desktopSize.width() / 2, desktopSize.height() * 4 / 10);
5404 QWidget widget(0, Qt::X11BypassWindowManagerHint);
5406 const QSize newMaximumSize = widget.size().boundedTo(originalSize) - QSize(10, 10);
5407 widget.setMaximumSize(newMaximumSize);
5408 QCOMPARE(widget.size(), newMaximumSize);
5411 QTest::qWaitForWindowShown(widget.windowHandle());
5412 QCOMPARE(widget.size(), newMaximumSize);
5416 QWidget widget(0, Qt::X11BypassWindowManagerHint);
5418 const QSize newMinimumSize = widget.size().expandedTo(originalSize) + QSize(10, 10);
5419 widget.setMinimumSize(newMinimumSize);
5420 QCOMPARE(widget.size(), newMinimumSize);
5423 QTest::qWaitForWindowShown(widget.windowHandle());
5424 QCOMPARE(widget.size(), newMinimumSize);
5428 class ShowHideShowWidget : public QWidget
5434 bool gotExpectedMapNotify;
5436 ShowHideShowWidget()
5437 : state(0), gotExpectedMapNotify(false)
5442 void timerEvent(QTimerEvent *)
5454 bool nativeEvent(const QByteArray &eventType, void *message, long *)
5456 enum { XCB_MAP_NOTIFY = 19 };
5458 if (state == 1 && eventType == QByteArrayLiteral("xcb_generic_event_t")) {
5459 // XCB events have a uint8 response_type member at the beginning.
5460 const unsigned char responseType = *(const unsigned char *)(message);
5461 if ((responseType & ~0x80) == XCB_MAP_NOTIFY)
5462 gotExpectedMapNotify = true;
5471 void tst_QWidget::showHideShowX11()
5473 if (m_platform != QStringLiteral("xcb"))
5474 QSKIP("This test is for X11 only.");
5476 ShowHideShowWidget w;
5480 QEventLoop eventLoop;
5481 connect(&w, SIGNAL(done()), &eventLoop, SLOT(quit()));
5484 QVERIFY(w.gotExpectedMapNotify);
5487 void tst_QWidget::clean_qt_x11_enforce_cursor()
5489 if (m_platform != QStringLiteral("xcb"))
5490 QSKIP("This test is for X11 only.");
5494 QWidget *w = new QWidget(&window);
5495 QWidget *child = new QWidget(w);
5496 child->setAttribute(Qt::WA_SetCursor, true);
5499 QApplication::setActiveWindow(&window);
5500 QTest::qWaitForWindowShown(&window);
5502 QCursor::setPos(window.geometry().center());
5506 QApplication::processEvents();
5512 QGraphicsScene scene;
5513 QLineEdit *edit = new QLineEdit;
5514 scene.addWidget(edit);
5516 // If the test didn't crash, then it passed.
5519 class EventRecorder : public QObject
5524 typedef QList<QPair<QWidget *, QEvent::Type> > EventList;
5526 EventRecorder(QObject *parent = 0)
5530 EventList eventList()
5540 bool eventFilter(QObject *object, QEvent *event)
5542 QWidget *widget = qobject_cast<QWidget *>(object);
5543 if (widget && !event->spontaneous())
5544 events.append(qMakePair(widget, event->type()));
5552 void tst_QWidget::childEvents()
5554 EventRecorder::EventList expected;
5556 // Move away the cursor; otherwise it might result in an enter event if it's
5557 // inside the widget when the widget is shown.
5558 QCursor::setPos(qApp->desktop()->availableGeometry().bottomRight());
5562 // no children created, not shown
5565 widget.installEventFilter(&spy);
5567 QCoreApplication::postEvent(&widget, new QEvent(QEvent::Type(QEvent::User + 1)));
5569 QCoreApplication::sendPostedEvents();
5572 EventRecorder::EventList()
5573 << qMakePair(&widget, QEvent::PolishRequest)
5574 << qMakePair(&widget, QEvent::Polish)
5575 << qMakePair(&widget, QEvent::Type(QEvent::User + 1));
5576 QCOMPARE(spy.eventList(), expected);
5580 // no children, shown
5583 widget.installEventFilter(&spy);
5585 QCoreApplication::postEvent(&widget, new QEvent(QEvent::Type(QEvent::User + 1)));
5589 EventRecorder::EventList()
5590 << qMakePair(&widget, QEvent::WinIdChange)
5591 << qMakePair(&widget, QEvent::Polish)
5592 << qMakePair(&widget, QEvent::Move)
5593 << qMakePair(&widget, QEvent::Resize)
5594 << qMakePair(&widget, QEvent::Show);
5596 expected << qMakePair(&widget, QEvent::ShowToParent);
5597 QCOMPARE(spy.eventList(), expected);
5600 QCoreApplication::sendPostedEvents();
5602 EventRecorder::EventList()
5603 << qMakePair(&widget, QEvent::PolishRequest)
5604 << qMakePair(&widget, QEvent::Type(QEvent::User + 1));
5607 expected << qMakePair(&widget, QEvent::UpdateLater);
5609 expected << qMakePair(&widget, QEvent::UpdateRequest);
5611 QCOMPARE(spy.eventList(), expected);
5615 // 2 children, not shown
5618 widget.installEventFilter(&spy);
5620 QCoreApplication::postEvent(&widget, new QEvent(QEvent::Type(QEvent::User + 1)));
5622 QWidget child1(&widget);
5624 child2.setParent(&widget);
5626 QCoreApplication::postEvent(&widget, new QEvent(QEvent::Type(QEvent::User + 2)));
5629 EventRecorder::EventList()
5630 << qMakePair(&widget, QEvent::ChildAdded)
5631 << qMakePair(&widget, QEvent::ChildAdded);
5632 QCOMPARE(spy.eventList(), expected);
5635 QCoreApplication::sendPostedEvents();
5637 EventRecorder::EventList()
5638 << qMakePair(&widget, QEvent::PolishRequest)
5639 << qMakePair(&widget, QEvent::Polish)
5640 << qMakePair(&widget, QEvent::ChildPolished)
5641 << qMakePair(&widget, QEvent::ChildPolished)
5642 << qMakePair(&widget, QEvent::Type(QEvent::User + 1))
5643 << qMakePair(&widget, QEvent::Type(QEvent::User + 2));
5644 QCOMPARE(spy.eventList(), expected);
5648 // 2 children, widget shown
5651 widget.installEventFilter(&spy);
5653 QCoreApplication::postEvent(&widget, new QEvent(QEvent::Type(QEvent::User + 1)));
5655 QWidget child1(&widget);
5657 child2.setParent(&widget);
5659 QCoreApplication::postEvent(&widget, new QEvent(QEvent::Type(QEvent::User + 2)));
5662 EventRecorder::EventList()
5663 << qMakePair(&widget, QEvent::ChildAdded)
5664 << qMakePair(&widget, QEvent::ChildAdded);
5665 QCOMPARE(spy.eventList(), expected);
5670 EventRecorder::EventList()
5671 << qMakePair(&widget, QEvent::WinIdChange)
5672 << qMakePair(&widget, QEvent::Polish)
5673 << qMakePair(&widget, QEvent::ChildPolished)
5674 << qMakePair(&widget, QEvent::ChildPolished)
5675 << qMakePair(&widget, QEvent::Move)
5676 << qMakePair(&widget, QEvent::Resize)
5677 << qMakePair(&widget, QEvent::Show);
5679 expected << qMakePair(&widget, QEvent::ShowToParent);
5680 QCOMPARE(spy.eventList(), expected);
5683 QCoreApplication::sendPostedEvents();
5685 EventRecorder::EventList()
5686 << qMakePair(&widget, QEvent::PolishRequest)
5687 << qMakePair(&widget, QEvent::Type(QEvent::User + 1))
5688 << qMakePair(&widget, QEvent::Type(QEvent::User + 2));
5691 expected << qMakePair(&widget, QEvent::UpdateLater);
5693 expected << qMakePair(&widget, QEvent::UpdateRequest);
5695 QCOMPARE(spy.eventList(), expected);
5699 // 2 children, but one is reparented away, not shown
5702 widget.installEventFilter(&spy);
5704 QCoreApplication::postEvent(&widget, new QEvent(QEvent::Type(QEvent::User + 1)));
5706 QWidget child1(&widget);
5708 child2.setParent(&widget);
5709 child2.setParent(0);
5711 QCoreApplication::postEvent(&widget, new QEvent(QEvent::Type(QEvent::User + 2)));
5714 EventRecorder::EventList()
5715 << qMakePair(&widget, QEvent::ChildAdded)
5716 << qMakePair(&widget, QEvent::ChildAdded)
5717 << qMakePair(&widget, QEvent::ChildRemoved);
5718 QCOMPARE(spy.eventList(), expected);
5721 QCoreApplication::sendPostedEvents();
5723 EventRecorder::EventList()
5724 << qMakePair(&widget, QEvent::PolishRequest)
5725 << qMakePair(&widget, QEvent::Polish)
5726 << qMakePair(&widget, QEvent::ChildPolished)
5727 << qMakePair(&widget, QEvent::Type(QEvent::User + 1))
5728 << qMakePair(&widget, QEvent::Type(QEvent::User + 2));
5729 QCOMPARE(spy.eventList(), expected);
5733 // 2 children, but one is reparented away, then widget is shown
5736 widget.installEventFilter(&spy);
5738 QCoreApplication::postEvent(&widget, new QEvent(QEvent::Type(QEvent::User + 1)));
5740 QWidget child1(&widget);
5742 child2.setParent(&widget);
5743 child2.setParent(0);
5745 QCoreApplication::postEvent(&widget, new QEvent(QEvent::Type(QEvent::User + 2)));
5748 EventRecorder::EventList()
5749 << qMakePair(&widget, QEvent::ChildAdded)
5750 << qMakePair(&widget, QEvent::ChildAdded)
5751 << qMakePair(&widget, QEvent::ChildRemoved);
5752 QCOMPARE(spy.eventList(), expected);
5757 EventRecorder::EventList()
5758 << qMakePair(&widget, QEvent::WinIdChange)
5759 << qMakePair(&widget, QEvent::Polish)
5760 << qMakePair(&widget, QEvent::ChildPolished)
5761 << qMakePair(&widget, QEvent::Move)
5762 << qMakePair(&widget, QEvent::Resize)
5763 << qMakePair(&widget, QEvent::Show);
5765 expected << qMakePair(&widget, QEvent::ShowToParent);
5766 QCOMPARE(spy.eventList(), expected);
5769 QCoreApplication::sendPostedEvents();
5771 EventRecorder::EventList()
5772 << qMakePair(&widget, QEvent::PolishRequest)
5773 << qMakePair(&widget, QEvent::Type(QEvent::User + 1))
5774 << qMakePair(&widget, QEvent::Type(QEvent::User + 2));
5777 expected << qMakePair(&widget, QEvent::UpdateLater);
5779 expected << qMakePair(&widget, QEvent::UpdateRequest);
5781 QCOMPARE(spy.eventList(), expected);
5785 class RenderWidget : public QWidget
5788 RenderWidget(QWidget *source)
5789 : source(source), ellipse(false) {}
5791 void setEllipseEnabled(bool enable = true)
5798 void paintEvent(QPaintEvent *)
5801 QPainter painter(this);
5802 painter.fillRect(rect(), Qt::red);
5804 QRegion regionToRender = QRegion(0, 0, source->width(), source->height() / 2,
5806 source->render(this, QPoint(0, 30), regionToRender);
5808 source->render(this);
5817 void tst_QWidget::render()
5820 QCalendarWidget source;
5821 // disable anti-aliasing to eliminate potential differences when subpixel antialiasing
5822 // is enabled on the screen
5824 f.setStyleStrategy(QFont::NoAntialias);
5827 QTest::qWaitForWindowShown(&source);
5829 // Render the entire source into target.
5830 RenderWidget target(&source);
5831 target.resize(source.size());
5834 qApp->processEvents();
5835 qApp->sendPostedEvents();
5838 const QImage sourceImage = source.grab(QRect(QPoint(0, 0), QSize(-1, -1))).toImage();
5839 qApp->processEvents();
5840 QImage targetImage = target.grab(QRect(QPoint(0, 0), QSize(-1, -1))).toImage();
5841 qApp->processEvents();
5842 QCOMPARE(sourceImage, targetImage);
5844 // Fill target.rect() will Qt::red and render
5845 // QRegion(0, 0, source->width(), source->height() / 2, QRegion::Ellipse)
5846 // of source into target with offset (0, 30).
5847 target.setEllipseEnabled();
5848 qApp->processEvents();
5849 qApp->sendPostedEvents();
5851 targetImage = target.grab(QRect(QPoint(0, 0), QSize(-1, -1))).toImage();
5852 QVERIFY(sourceImage != targetImage);
5854 QCOMPARE(targetImage.pixel(target.width() / 2, 29), QColor(Qt::red).rgb());
5855 QCOMPARE(targetImage.pixel(target.width() / 2, 30), sourceImage.pixel(source.width() / 2, 0));
5857 // Test that a child widget properly fills its background
5860 window.resize(100, 100);
5861 // prevent custom styles
5862 window.setStyle(new QWindowsStyle);
5864 QTest::qWaitForWindowShown(&window);
5865 QWidget child(&window);
5866 child.resize(window.size());
5869 qApp->processEvents();
5870 const QPixmap childPixmap = child.grab(QRect(QPoint(0, 0), QSize(-1, -1)));
5871 const QPixmap windowPixmap = window.grab(QRect(QPoint(0, 0), QSize(-1, -1)));
5872 QCOMPARE(childPixmap, windowPixmap);
5875 { // Check that the target offset is correct.
5877 widget.resize(200, 200);
5878 widget.setAutoFillBackground(true);
5879 widget.setPalette(Qt::red);
5880 // prevent custom styles
5881 widget.setStyle(new QWindowsStyle);
5883 QTest::qWaitForWindowShown(&widget);
5884 QImage image(widget.size(), QImage::Format_RGB32);
5885 image.fill(QColor(Qt::blue).rgb());
5887 // Target offset (0, 0)
5888 widget.render(&image, QPoint(), QRect(20, 20, 100, 100));
5889 QCOMPARE(image.pixel(0, 0), QColor(Qt::red).rgb());
5890 QCOMPARE(image.pixel(99, 99), QColor(Qt::red).rgb());
5891 QCOMPARE(image.pixel(100, 100), QColor(Qt::blue).rgb());
5893 // Target offset (20, 20).
5894 image.fill(QColor(Qt::blue).rgb());
5895 widget.render(&image, QPoint(20, 20), QRect(20, 20, 100, 100));
5896 QCOMPARE(image.pixel(0, 0), QColor(Qt::blue).rgb());
5897 QCOMPARE(image.pixel(19, 19), QColor(Qt::blue).rgb());
5898 QCOMPARE(image.pixel(20, 20), QColor(Qt::red).rgb());
5899 QCOMPARE(image.pixel(119, 119), QColor(Qt::red).rgb());
5900 QCOMPARE(image.pixel(120, 120), QColor(Qt::blue).rgb());
5904 // On Windows the active palette is used instead of the inactive palette even
5905 // though the widget is invisible. This is probably related to task 178507/168682,
5906 // but for the renderInvisible test it doesn't matter, we're mostly interested
5907 // in testing the geometry so just workaround the palette issue for now.
5908 static void workaroundPaletteIssue(QWidget *widget)
5916 QWidget *navigationBar = qFindChild<QWidget *>(widget, QLatin1String("qt_calendar_navigationbar"));
5917 QVERIFY(navigationBar);
5919 QPalette palette = navigationBar->palette();
5920 const QColor background = palette.color(QPalette::Inactive, navigationBar->backgroundRole());
5921 const QColor highlightedText = palette.color(QPalette::Inactive, QPalette::HighlightedText);
5922 palette.setColor(QPalette::Active, navigationBar->backgroundRole(), background);
5923 palette.setColor(QPalette::Active, QPalette::HighlightedText, highlightedText);
5924 navigationBar->setPalette(palette);
5927 //#define RENDER_DEBUG
5928 void tst_QWidget::renderInvisible()
5930 QCalendarWidget *calendar = new QCalendarWidget;
5931 // disable anti-aliasing to eliminate potential differences when subpixel antialiasing
5932 // is enabled on the screen
5934 f.setStyleStrategy(QFont::NoAntialias);
5935 calendar->setFont(f);
5937 QTest::qWaitForWindowShown(calendar);
5939 // Create a dummy focus widget to get rid of focus rect in reference image.
5940 QLineEdit dummyFocusWidget;
5941 dummyFocusWidget.show();
5942 QTest::qWaitForWindowShown(&dummyFocusWidget);
5943 qApp->processEvents();
5946 // Create normal reference image.
5947 const QSize calendarSize = calendar->size();
5948 QImage referenceImage(calendarSize, QImage::Format_ARGB32);
5949 calendar->render(&referenceImage);
5951 referenceImage.save("referenceImage.png");
5953 QVERIFY(!referenceImage.isNull());
5955 // Create resized reference image.
5956 const QSize calendarSizeResized = calendar->size() + QSize(50, 50);
5957 calendar->resize(calendarSizeResized);
5958 qApp->processEvents();
5960 QImage referenceImageResized(calendarSizeResized, QImage::Format_ARGB32);
5961 calendar->render(&referenceImageResized);
5963 referenceImageResized.save("referenceImageResized.png");
5965 QVERIFY(!referenceImageResized.isNull());
5967 // Explicitly hide the calendar.
5969 qApp->processEvents();
5971 workaroundPaletteIssue(calendar);
5973 { // Make sure we get the same image when the calendar is explicitly hidden.
5974 QImage testImage(calendarSizeResized, QImage::Format_ARGB32);
5975 calendar->render(&testImage);
5977 testImage.save("explicitlyHiddenCalendarResized.png");
5979 QCOMPARE(testImage, referenceImageResized);
5982 // Now that we have reference images we can delete the source and re-create
5983 // the calendar and check that we get the same images from a calendar which has never
5984 // been visible, laid out or created (Qt::WA_WState_Created).
5986 calendar = new QCalendarWidget;
5987 calendar->setFont(f);
5988 workaroundPaletteIssue(calendar);
5990 { // Never been visible, created or laid out.
5991 QImage testImage(calendarSize, QImage::Format_ARGB32);
5992 calendar->render(&testImage);
5994 testImage.save("neverBeenVisibleCreatedOrLaidOut.png");
5996 QCOMPARE(testImage, referenceImage);
6000 qApp->processEvents();
6003 { // Calendar explicitly hidden.
6004 QImage testImage(calendarSize, QImage::Format_ARGB32);
6005 calendar->render(&testImage);
6007 testImage.save("explicitlyHiddenCalendar.png");
6009 QCOMPARE(testImage, referenceImage);
6012 // Get navigation bar and explicitly hide it.
6013 QWidget *navigationBar = qFindChild<QWidget *>(calendar, QLatin1String("qt_calendar_navigationbar"));
6014 QVERIFY(navigationBar);
6015 navigationBar->hide();
6017 { // Check that the navigation bar isn't drawn when rendering the entire calendar.
6018 QImage testImage(calendarSize, QImage::Format_ARGB32);
6019 calendar->render(&testImage);
6021 testImage.save("calendarWithoutNavigationBar.png");
6023 QVERIFY(testImage != referenceImage);
6026 { // Make sure the navigation bar renders correctly even though it's hidden.
6027 QImage testImage(navigationBar->size(), QImage::Format_ARGB32);
6028 navigationBar->render(&testImage);
6030 testImage.save("explicitlyHiddenNavigationBar.png");
6032 QCOMPARE(testImage, referenceImage.copy(navigationBar->rect()));
6035 // Get next month button.
6036 QWidget *nextMonthButton = qFindChild<QWidget *>(navigationBar, QLatin1String("qt_calendar_nextmonth"));
6037 QVERIFY(nextMonthButton);
6039 { // Render next month button.
6040 // Fill test image with correct background color.
6041 QImage testImage(nextMonthButton->size(), QImage::Format_ARGB32);
6042 navigationBar->render(&testImage, QPoint(), QRegion(), QWidget::RenderFlags());
6044 testImage.save("nextMonthButtonBackground.png");
6047 // Set the button's background color to Qt::transparent; otherwise it will fill the
6048 // background with QPalette::Window.
6049 const QPalette originalPalette = nextMonthButton->palette();
6050 QPalette palette = originalPalette;
6051 palette.setColor(QPalette::Window, Qt::transparent);
6052 nextMonthButton->setPalette(palette);
6054 // Render the button on top of the background.
6055 nextMonthButton->render(&testImage);
6057 testImage.save("nextMonthButton.png");
6059 const QRect buttonRect(nextMonthButton->mapTo(calendar, QPoint()), nextMonthButton->size());
6060 QCOMPARE(testImage, referenceImage.copy(buttonRect));
6063 nextMonthButton->setPalette(originalPalette);
6066 // Navigation bar isn't explicitly hidden anymore.
6067 navigationBar->show();
6068 qApp->processEvents();
6070 QVERIFY(!calendar->isVisible());
6072 // Now, completely mess up the layout. This will trigger an update on the layout
6073 // when the calendar is visible or shown, but it's not. QWidget::render must therefore
6074 // make sure the layout is activated before rendering.
6075 QVERIFY(!calendar->isVisible());
6076 calendar->resize(calendarSizeResized);
6077 qApp->processEvents();
6079 { // Make sure we get an image equal to the resized reference image.
6080 QImage testImage(calendarSizeResized, QImage::Format_ARGB32);
6081 calendar->render(&testImage);
6083 testImage.save("calendarResized.png");
6085 QCOMPARE(testImage, referenceImageResized);
6088 { // Make sure we lay out the widget correctly the first time it's rendered.
6089 QCalendarWidget calendar;
6090 const QSize calendarSize = calendar.sizeHint();
6092 QImage image(2 * calendarSize, QImage::Format_ARGB32);
6093 image.fill(QColor(Qt::red).rgb());
6094 calendar.render(&image);
6096 for (int i = calendarSize.height(); i < 2 * calendarSize.height(); ++i)
6097 for (int j = calendarSize.width(); j < 2 * calendarSize.width(); ++j)
6098 QCOMPARE(image.pixel(j, i), QColor(Qt::red).rgb());
6101 { // Ensure that we don't call adjustSize() on invisible top-levels if render() is called
6102 // right after widgets have been added/removed to/from its layout.
6104 topLevel.setLayout(new QVBoxLayout);
6106 QWidget *widget = new QLineEdit;
6107 topLevel.layout()->addWidget(widget);
6109 const QSize initialSize = topLevel.size();
6110 QPixmap pixmap(topLevel.sizeHint());
6111 topLevel.render(&pixmap); // triggers adjustSize()
6112 const QSize finalSize = topLevel.size();
6113 QVERIFY(finalSize != initialSize);
6115 topLevel.layout()->removeWidget(widget);
6116 QCOMPARE(topLevel.size(), finalSize);
6117 topLevel.render(&pixmap);
6118 QCOMPARE(topLevel.size(), finalSize);
6120 topLevel.layout()->addWidget(widget);
6121 QCOMPARE(topLevel.size(), finalSize);
6122 topLevel.render(&pixmap);
6123 QCOMPARE(topLevel.size(), finalSize);
6127 void tst_QWidget::renderWithPainter()
6130 // prevent custom styles
6131 widget.setStyle(new QWindowsStyle);
6133 widget.resize(70, 50);
6134 widget.setAutoFillBackground(true);
6135 widget.setPalette(Qt::black);
6137 // Render the entire widget onto the image.
6138 QImage image(QSize(70, 50), QImage::Format_ARGB32);
6139 image.fill(QColor(Qt::red).rgb());
6140 QPainter painter(&image);
6141 widget.render(&painter);
6143 for (int i = 0; i < image.height(); ++i) {
6144 for (int j = 0; j < image.width(); ++j)
6145 QCOMPARE(image.pixel(j, i), QColor(Qt::black).rgb());
6148 // Translate painter (10, 10).
6150 image.fill(QColor(Qt::red).rgb());
6151 painter.translate(10, 10);
6152 widget.render(&painter);
6155 for (int i = 0; i < image.height(); ++i) {
6156 for (int j = 0; j < image.width(); ++j) {
6157 if (i < 10 || j < 10)
6158 QCOMPARE(image.pixel(j, i), QColor(Qt::red).rgb());
6160 QCOMPARE(image.pixel(j, i), QColor(Qt::black).rgb());
6164 // Pass target offset (10, 10) (the same as QPainter::translate).
6165 image.fill(QColor(Qt::red).rgb());
6166 widget.render(&painter, QPoint(10, 10));
6168 for (int i = 0; i < image.height(); ++i) {
6169 for (int j = 0; j < image.width(); ++j) {
6170 if (i < 10 || j < 10)
6171 QCOMPARE(image.pixel(j, i), QColor(Qt::red).rgb());
6173 QCOMPARE(image.pixel(j, i), QColor(Qt::black).rgb());
6177 // Translate (10, 10) and pass target offset (10, 10).
6179 image.fill(QColor(Qt::red).rgb());
6180 painter.translate(10, 10);
6181 widget.render(&painter, QPoint(10, 10));
6184 for (int i = 0; i < image.height(); ++i) {
6185 for (int j = 0; j < image.width(); ++j) {
6186 if (i < 20 || j < 20)
6187 QCOMPARE(image.pixel(j, i), QColor(Qt::red).rgb());
6189 QCOMPARE(image.pixel(j, i), QColor(Qt::black).rgb());
6193 // Rotate painter 90 degrees.
6195 image.fill(QColor(Qt::red).rgb());
6197 widget.render(&painter);
6200 for (int i = 0; i < image.height(); ++i) {
6201 for (int j = 0; j < image.width(); ++j)
6202 QCOMPARE(image.pixel(j, i), QColor(Qt::red).rgb());
6205 // Translate and rotate.
6206 image.fill(QColor(Qt::red).rgb());
6207 widget.resize(40, 10);
6208 painter.translate(10, 10);
6210 widget.render(&painter);
6212 for (int i = 0; i < image.height(); ++i) {
6213 for (int j = 0; j < image.width(); ++j) {
6214 if (i >= 10 && j >= 0 && j < 10)
6215 QCOMPARE(image.pixel(j, i), QColor(Qt::black).rgb());
6217 QCOMPARE(image.pixel(j, i), QColor(Qt::red).rgb());
6221 // Make sure QWidget::render does not modify the render hints set on the painter.
6222 painter.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform
6223 | QPainter::NonCosmeticDefaultPen | QPainter::TextAntialiasing);
6224 QPainter::RenderHints oldRenderHints = painter.renderHints();
6225 widget.render(&painter);
6226 QCOMPARE(painter.renderHints(), oldRenderHints);
6229 void tst_QWidget::render_task188133()
6231 QMainWindow mainWindow;
6233 // Make sure QWidget::render does not trigger QWidget::repaint/update
6234 // and asserts for Qt::WA_WState_Created.
6235 const QPixmap pixmap = mainWindow.grab(QRect(QPoint(0, 0), QSize(-1, -1)));
6239 void tst_QWidget::render_task211796()
6241 class MyWidget : public QWidget
6243 void resizeEvent(QResizeEvent *)
6245 QPixmap pixmap(size());
6250 { // Please don't die in a resize recursion.
6252 widget.resize(200, 200);
6256 { // Same check with a deeper hierarchy.
6259 QWidget child(&widget);
6260 MyWidget grandChild;
6261 grandChild.setParent(&child);
6262 grandChild.resize(100, 100);
6267 void tst_QWidget::render_task217815()
6269 // Make sure we don't change the size of the widget when calling
6270 // render() and the widget has an explicit size set.
6271 // This was a problem on Windows because we called createWinId(),
6272 // which in turn enforced the size to be bigger than the smallest
6273 // possible native window size (which is (115,something) on WinXP).
6275 const QSize explicitSize(80, 20);
6276 widget.resize(explicitSize);
6277 QCOMPARE(widget.size(), explicitSize);
6279 QPixmap pixmap(explicitSize);
6280 widget.render(&pixmap);
6282 QCOMPARE(widget.size(), explicitSize);
6285 // Window Opacity is not supported on Windows CE.
6287 void tst_QWidget::render_windowOpacity()
6289 const qreal opacity = 0.5;
6291 { // Check that the painter opacity effects the widget drawing.
6293 QWidget child(&topLevel);
6294 child.resize(50, 50);
6295 child.setPalette(Qt::red);
6296 child.setAutoFillBackground(true);
6298 QPixmap expected(child.size());
6300 if (m_platform == QStringLiteral("xcb") && expected.depth() < 24)
6301 QSKIP("This test won't give correct results with dithered pixmaps");
6303 expected.fill(Qt::green);
6304 QPainter painter(&expected);
6305 painter.setOpacity(opacity);
6306 painter.fillRect(QRect(QPoint(0, 0), child.size()), Qt::red);
6309 QPixmap result(child.size());
6310 result.fill(Qt::green);
6311 painter.begin(&result);
6312 painter.setOpacity(opacity);
6313 child.render(&painter);
6315 QCOMPARE(result, expected);
6318 { // Combine the opacity set on the painter with the widget opacity.
6319 class MyWidget : public QWidget
6322 void paintEvent(QPaintEvent *)
6324 QPainter painter(this);
6325 painter.setOpacity(opacity);
6326 QCOMPARE(painter.opacity(), opacity);
6327 painter.fillRect(rect(), Qt::red);
6333 widget.resize(50, 50);
6334 widget.opacity = opacity;
6335 widget.setPalette(Qt::blue);
6336 widget.setAutoFillBackground(true);
6338 QPixmap expected(widget.size());
6339 expected.fill(Qt::green);
6340 QPainter painter(&expected);
6341 painter.setOpacity(opacity);
6342 QPixmap pixmap(widget.size());
6343 pixmap.fill(Qt::blue);
6344 QPainter pixmapPainter(&pixmap);
6345 pixmapPainter.setOpacity(opacity);
6346 pixmapPainter.fillRect(QRect(QPoint(), widget.size()), Qt::red);
6347 painter.drawPixmap(QPoint(), pixmap);
6350 QPixmap result(widget.size());
6351 result.fill(Qt::green);
6352 painter.begin(&result);
6353 painter.setOpacity(opacity);
6354 widget.render(&painter);
6356 QCOMPARE(result, expected);
6361 void tst_QWidget::render_systemClip()
6364 widget.setPalette(Qt::blue);
6365 widget.resize(100, 100);
6367 QImage image(widget.size(), QImage::Format_RGB32);
6368 image.fill(QColor(Qt::red).rgb());
6370 QPaintEngine *paintEngine = image.paintEngine();
6371 QVERIFY(paintEngine);
6372 paintEngine->setSystemClip(QRegion(0, 0, 50, 50));
6374 QPainter painter(&image);
6375 // Make sure we're using the same paint engine and has the right clip set.
6376 QCOMPARE(painter.paintEngine(), paintEngine);
6377 QCOMPARE(paintEngine->systemClip(), QRegion(0, 0, 50, 50));
6379 // Translate painter outside system clip.
6380 painter.translate(50, 0);
6381 widget.render(&painter);
6384 image.save("outside_systemclip.png");
6387 // All pixels should be red.
6388 for (int i = 0; i < image.height(); ++i) {
6389 for (int j = 0; j < image.width(); ++j)
6390 QCOMPARE(image.pixel(j, i), QColor(Qt::red).rgb());
6393 // Restore painter and refill image with red.
6394 image.fill(QColor(Qt::red).rgb());
6395 painter.translate(-50, 0);
6397 // Set transform on the painter.
6398 QTransform transform;
6399 transform.shear(0, 1);
6400 painter.setTransform(transform);
6401 widget.render(&painter);
6404 image.save("blue_triangle.png");
6407 // We should now have a blue triangle starting at scan line 1, and the rest should be red.
6417 for (int i = 0; i < image.height(); ++i) {
6418 for (int j = 0; j < image.width(); ++j) {
6419 if (i < 50 && j < i)
6420 QCOMPARE(image.pixel(j, i), QColor(Qt::blue).rgb());
6422 QCOMPARE(image.pixel(j, i), QColor(Qt::red).rgb());
6426 // We don't paint directly on the image on the Mac, so we cannot do the pixel comparison
6427 // as above due to QPainter::SmoothPixmapTransform. We therefore need to generate an
6428 // expected image by first painting on a pixmap, and then draw the pixmap onto
6429 // the image using QPainter::SmoothPixmapTransform. Then we can compare pixels :)
6430 // The check is basically the same, except that it takes the smoothening into account.
6431 QPixmap pixmap(50, 50);
6432 const QRegion sysClip(0, 0, 50, 50);
6433 widget.render(&pixmap, QPoint(), sysClip);
6435 QImage expectedImage(widget.size(), QImage::Format_RGB32);
6436 expectedImage.fill(QColor(Qt::red).rgb());
6437 expectedImage.paintEngine()->setSystemClip(sysClip);
6439 QPainter expectedImagePainter(&expectedImage);
6440 expectedImagePainter.setTransform(QTransform().shear(0, 1));
6441 // NB! This is the important part (SmoothPixmapTransform).
6442 expectedImagePainter.setRenderHints(QPainter::SmoothPixmapTransform);
6443 expectedImagePainter.drawPixmap(QPoint(0, 0), pixmap);
6444 expectedImagePainter.end();
6446 QCOMPARE(image, expectedImage);
6450 void tst_QWidget::render_systemClip2_data()
6452 QTest::addColumn<bool>("autoFillBackground");
6453 QTest::addColumn<bool>("usePaintEvent");
6454 QTest::addColumn<QColor>("expectedColor");
6456 QTest::newRow("Only auto-fill background") << true << false << QColor(Qt::blue);
6457 QTest::newRow("Only draw in paintEvent") << false << true << QColor(Qt::green);
6458 QTest::newRow("Auto-fill background and draw in paintEvent") << true << true << QColor(Qt::green);
6461 void tst_QWidget::render_systemClip2()
6463 QFETCH(bool, autoFillBackground);
6464 QFETCH(bool, usePaintEvent);
6465 QFETCH(QColor, expectedColor);
6467 QVERIFY2(expectedColor != QColor(Qt::red), "Qt::red is the reference color for the image, pick another color");
6469 class MyWidget : public QWidget
6473 void paintEvent(QPaintEvent *)
6476 QPainter(this).fillRect(rect(), Qt::green);
6481 widget.usePaintEvent = usePaintEvent;
6482 widget.setPalette(Qt::blue);
6483 // NB! widget.setAutoFillBackground(autoFillBackground) won't do the
6484 // trick here since the widget is a top-level. The background is filled
6485 // regardless, unless Qt::WA_OpaquePaintEvent or Qt::WA_NoSystemBackground
6486 // is set. We therefore use the opaque attribute to turn off auto-fill.
6487 if (!autoFillBackground)
6488 widget.setAttribute(Qt::WA_OpaquePaintEvent);
6489 widget.resize(100, 100);
6491 QImage image(widget.size(), QImage::Format_RGB32);
6492 image.fill(QColor(Qt::red).rgb());
6494 QPaintEngine *paintEngine = image.paintEngine();
6495 QVERIFY(paintEngine);
6497 QRegion systemClip(QRegion(50, 0, 50, 10));
6498 systemClip += QRegion(90, 10, 10, 40);
6499 paintEngine->setSystemClip(systemClip);
6501 // Render entire widget directly onto device.
6502 widget.render(&image);
6505 image.save("systemclip_with_device.png");
6507 // All pixels within the system clip should now be
6508 // the expectedColor, and the rest should be red.
6509 for (int i = 0; i < image.height(); ++i) {
6510 for (int j = 0; j < image.width(); ++j) {
6511 if (systemClip.contains(QPoint(j, i)))
6512 QCOMPARE(image.pixel(j, i), expectedColor.rgb());
6514 QCOMPARE(image.pixel(j, i), QColor(Qt::red).rgb());
6518 // Refill image with red.
6519 image.fill(QColor(Qt::red).rgb());
6520 paintEngine->setSystemClip(systemClip);
6522 // Do the same with an untransformed painter.
6523 QPainter painter(&image);
6524 //Make sure we're using the same paint engine and has the right clip set.
6525 QCOMPARE(painter.paintEngine(), paintEngine);
6526 QCOMPARE(paintEngine->systemClip(), systemClip);
6528 widget.render(&painter);
6531 image.save("systemclip_with_untransformed_painter.png");
6533 // All pixels within the system clip should now be
6534 // the expectedColor, and the rest should be red.
6535 for (int i = 0; i < image.height(); ++i) {
6536 for (int j = 0; j < image.width(); ++j) {
6537 if (systemClip.contains(QPoint(j, i)))
6538 QCOMPARE(image.pixel(j, i), expectedColor.rgb());
6540 QCOMPARE(image.pixel(j, i), QColor(Qt::red).rgb());
6545 void tst_QWidget::render_systemClip3_data()
6547 QTest::addColumn<QSize>("size");
6548 QTest::addColumn<bool>("useSystemClip");
6550 // Reference: http://en.wikipedia.org/wiki/Flag_of_Norway
6551 QTest::newRow("Norwegian Civil Flag") << QSize(220, 160) << false;
6552 QTest::newRow("Norwegian War Flag") << QSize(270, 160) << true;
6555 // This test ensures that the current engine clip (systemClip + painter clip)
6556 // is preserved after QPainter::setClipRegion(..., Qt::ReplaceClip);
6557 void tst_QWidget::render_systemClip3()
6559 QFETCH(QSize, size);
6560 QFETCH(bool, useSystemClip);
6562 // Calculate the inner/outer cross of the flag.
6563 QRegion outerCross(0, 0, size.width(), size.height());
6564 outerCross -= QRect(0, 0, 60, 60);
6565 outerCross -= QRect(100, 0, size.width() - 100, 60);
6566 outerCross -= QRect(0, 100, 60, 60);
6567 outerCross -= QRect(100, 100, size.width() - 100, 60);
6569 QRegion innerCross(0, 0, size.width(), size.height());
6570 innerCross -= QRect(0, 0, 70, 70);
6571 innerCross -= QRect(90, 0, size.width() - 90, 70);
6572 innerCross -= QRect(0, 90, 70, 70);
6573 innerCross -= QRect(90, 90, size.width() - 90, 70);
6575 const QRegion redArea(QRegion(0, 0, size.width(), size.height()) - outerCross);
6576 const QRegion whiteArea(outerCross - innerCross);
6577 const QRegion blueArea(innerCross);
6580 // Okay, here's the image that should look like a Norwegian civil/war flag in the end.
6581 QImage flag(size, QImage::Format_ARGB32);
6582 flag.fill(QColor(Qt::transparent).rgba());
6584 if (useSystemClip) {
6585 QPainterPath warClip(QPoint(size.width(), 0));
6586 warClip.lineTo(size.width() - 110, 60);
6587 warClip.lineTo(size.width(), 80);
6588 warClip.lineTo(size.width() - 110, 100);
6589 warClip.lineTo(size.width(), 160);
6590 warClip.closeSubpath();
6591 systemClip = QRegion(0, 0, size.width(), size.height()) - QRegion(warClip.toFillPolygon().toPolygon());
6592 flag.paintEngine()->setSystemClip(systemClip);
6595 QPainter painter(&flag);
6596 painter.fillRect(QRect(QPoint(), size), Qt::red); // Fill image background with red.
6597 painter.setClipRegion(outerCross); // Limit widget painting to inside the outer cross.
6599 // Here's the widget that's supposed to draw the inner/outer cross of the flag.
6600 // The outer cross (white) should be drawn when the background is auto-filled, and
6601 // the inner cross (blue) should be drawn in the paintEvent.
6602 class MyWidget : public QWidget
6604 void paintEvent(QPaintEvent *)
6606 QPainter painter(this);
6607 // Be evil and try to paint outside the outer cross. This should not be
6608 // possible since the shared painter is clipped to the outer cross.
6609 painter.setClipRect(0, 0, 60, 60, Qt::ReplaceClip);
6610 painter.fillRect(rect(), Qt::green);
6611 painter.setClipRegion(clip, Qt::ReplaceClip);
6612 painter.fillRect(rect(), Qt::blue);
6618 widget.clip = innerCross;
6619 widget.setFixedSize(size);
6620 widget.setPalette(Qt::white);
6621 widget.setAutoFillBackground(true);
6622 widget.render(&painter);
6625 flag.save("flag.png");
6628 // Let's make sure we got a Norwegian flag.
6629 for (int i = 0; i < flag.height(); ++i) {
6630 for (int j = 0; j < flag.width(); ++j) {
6631 const QPoint pixel(j, i);
6632 const QRgb pixelValue = flag.pixel(pixel);
6633 if (useSystemClip && !systemClip.contains(pixel))
6634 QCOMPARE(pixelValue, QColor(Qt::transparent).rgba());
6635 else if (redArea.contains(pixel))
6636 QCOMPARE(pixelValue, QColor(Qt::red).rgba());
6637 else if (whiteArea.contains(pixel))
6638 QCOMPARE(pixelValue, QColor(Qt::white).rgba());
6640 QCOMPARE(pixelValue, QColor(Qt::blue).rgba());
6645 void tst_QWidget::render_task252837()
6648 widget.resize(200, 200);
6650 QPixmap pixmap(widget.size());
6651 QPainter painter(&pixmap);
6652 // Please do not crash.
6653 widget.render(&painter);
6656 void tst_QWidget::render_worldTransform()
6658 class MyWidget : public QWidget
6660 void paintEvent(QPaintEvent *)
6662 QPainter painter(this);
6663 // Make sure world transform is identity.
6664 QCOMPARE(painter.worldTransform(), QTransform());
6666 // Make sure device transform is correct.
6667 const QPoint widgetOffset = geometry().topLeft();
6668 QTransform expectedDeviceTransform = QTransform::fromTranslate(105, 5);
6669 expectedDeviceTransform.rotate(90);
6670 expectedDeviceTransform.translate(widgetOffset.x(), widgetOffset.y());
6671 QCOMPARE(painter.deviceTransform(), expectedDeviceTransform);
6673 // Set new world transform.
6674 QTransform newWorldTransform = QTransform::fromTranslate(10, 10);
6675 newWorldTransform.rotate(90);
6676 painter.setWorldTransform(newWorldTransform);
6677 QCOMPARE(painter.worldTransform(), newWorldTransform);
6679 // Again, check device transform.
6680 expectedDeviceTransform.translate(10, 10);
6681 expectedDeviceTransform.rotate(90);
6682 QCOMPARE(painter.deviceTransform(), expectedDeviceTransform);
6684 painter.fillRect(QRect(0, 0, 20, 10), Qt::green);
6689 widget.setFixedSize(100, 100);
6690 widget.setPalette(Qt::red);
6691 widget.setAutoFillBackground(true);
6694 child.setParent(&widget);
6696 child.setFixedSize(50, 50);
6697 child.setPalette(Qt::blue);
6698 child.setAutoFillBackground(true);
6700 QImage image(QSize(110, 110), QImage::Format_RGB32);
6701 image.fill(QColor(Qt::black).rgb());
6703 QPainter painter(&image);
6704 painter.translate(105, 5);
6707 // Render widgets onto image.
6708 widget.render(&painter);
6710 image.save("render_worldTransform_image.png");
6713 // Ensure the transforms are unchanged after render.
6714 QCOMPARE(painter.worldTransform(), painter.worldTransform());
6715 QCOMPARE(painter.deviceTransform(), painter.deviceTransform());
6718 // Paint expected image.
6719 QImage expected(QSize(110, 110), QImage::Format_RGB32);
6720 expected.fill(QColor(Qt::black).rgb());
6722 QPainter expectedPainter(&expected);
6723 expectedPainter.translate(105, 5);
6724 expectedPainter.rotate(90);
6725 expectedPainter.save();
6726 expectedPainter.fillRect(widget.rect(),Qt::red);
6727 expectedPainter.translate(10, 10);
6728 expectedPainter.rotate(90);
6729 expectedPainter.fillRect(QRect(0, 0, 20, 10), Qt::green);
6730 expectedPainter.restore();
6731 expectedPainter.translate(50, 50);
6732 expectedPainter.fillRect(child.rect(),Qt::blue);
6733 expectedPainter.translate(10, 10);
6734 expectedPainter.rotate(90);
6735 expectedPainter.fillRect(QRect(0, 0, 20, 10), Qt::green);
6736 expectedPainter.end();
6739 expected.save("render_worldTransform_expected.png");
6742 QCOMPARE(image, expected);
6745 void tst_QWidget::setContentsMargins()
6747 QLabel label("why does it always rain on me?");
6748 QSize oldSize = label.sizeHint();
6749 label.setFrameStyle(QFrame::Sunken | QFrame::Box);
6750 QSize newSize = label.sizeHint();
6751 QVERIFY(oldSize != newSize);
6753 QLabel label2("why does it always rain on me?");
6755 label2.setFrameStyle(QFrame::Sunken | QFrame::Box);
6756 QCOMPARE(newSize, label2.sizeHint());
6758 QLabel label3("why does it always rain on me?");
6759 label3.setFrameStyle(QFrame::Sunken | QFrame::Box);
6760 QCOMPARE(newSize, label3.sizeHint());
6763 void tst_QWidget::moveWindowInShowEvent_data()
6765 QTest::addColumn<QPoint>("initial");
6766 QTest::addColumn<QPoint>("position");
6768 QPoint p = QApplication::desktop()->availableGeometry().topLeft();
6770 QTest::newRow("1") << p << (p + QPoint(10, 10));
6771 QTest::newRow("2") << (p + QPoint(10,10)) << p;
6774 void tst_QWidget::moveWindowInShowEvent()
6776 QFETCH(QPoint, initial);
6777 QFETCH(QPoint, position);
6779 class MoveWindowInShowEventWidget : public QWidget
6783 void showEvent(QShowEvent *)
6789 MoveWindowInShowEventWidget widget;
6790 widget.resize(QSize(qApp->desktop()->availableGeometry().size() / 3).expandedTo(QSize(1, 1)));
6791 // move to this position in showEvent()
6792 widget.position = position;
6794 // put the widget in it's starting position
6795 widget.move(initial);
6796 QCOMPARE(widget.pos(), initial);
6800 QTest::qWaitForWindowShown(widget.windowHandle());
6802 // it should have moved
6803 QCOMPARE(widget.pos(), position);
6806 void tst_QWidget::repaintWhenChildDeleted()
6809 if (QSysInfo::WindowsVersion & QSysInfo::WV_VISTA) {
6813 ColorWidget w(0, Qt::red);
6814 #if !defined(Q_OS_WINCE)
6815 QPoint startPoint = QApplication::desktop()->availableGeometry(&w).topLeft();
6816 startPoint.rx() += 50;
6817 startPoint.ry() += 50;
6818 w.setGeometry(QRect(startPoint, QSize(100, 100)));
6820 w.setGeometry(60, 60, 110, 110);
6823 QTest::qWaitForWindowShown(&w);
6825 QTRY_COMPARE(w.r, QRegion(w.rect()));
6829 ColorWidget child(&w, Qt::blue);
6830 child.setGeometry(10, 10, 10, 10);
6833 QTRY_COMPARE(child.r, QRegion(child.rect()));
6838 QTRY_COMPARE(w.r, QRegion(10, 10, 10, 10));
6842 void tst_QWidget::hideOpaqueChildWhileHidden()
6844 ColorWidget w(0, Qt::red);
6845 #if !defined(Q_OS_WINCE)
6846 QPoint startPoint = QApplication::desktop()->availableGeometry(&w).topLeft();
6847 startPoint.rx() += 50;
6848 startPoint.ry() += 50;
6849 w.setGeometry(QRect(startPoint, QSize(100, 100)));
6851 w.setGeometry(60, 60, 110, 110);
6854 ColorWidget child(&w, Qt::blue);
6855 child.setGeometry(10, 10, 80, 80);
6857 ColorWidget child2(&child, Qt::white);
6858 child2.setGeometry(10, 10, 60, 60);
6861 QTest::qWaitForWindowShown(&w);
6863 QTRY_COMPARE(child2.r, QRegion(child2.rect()));
6864 child.r = QRegion();
6865 child2.r = QRegion();
6872 QCOMPARE(w.r, QRegion(child.geometry()));
6876 QCOMPARE(child.r, QRegion(child.rect()));
6877 QCOMPARE(child2.r, QRegion());
6880 // This test doesn't make sense without support for showMinimized().
6881 #if !defined(Q_OS_WINCE)
6882 void tst_QWidget::updateWhileMinimized()
6884 UpdateWidget widget;
6885 // Filter out activation change and focus events to avoid update() calls in QWidget.
6886 widget.updateOnActivationChangeAndFocusIn = false;
6889 QTest::qWaitForWindowShown(&widget);
6890 QApplication::processEvents();
6891 QTRY_VERIFY(widget.numPaintEvents > 0);
6895 widget.showMinimized();
6900 // The widget is not visible on the screen (but isVisible() still returns true).
6901 // Make sure update requests are discarded until the widget is shown again.
6902 widget.update(0, 0, 50, 50);
6904 QCOMPARE(widget.numPaintEvents, 0);
6907 widget.showNormal();
6909 QTRY_COMPARE(widget.numPaintEvents, 1);
6910 QCOMPARE(widget.paintedRegion, QRegion(0, 0, 50, 50));
6914 class PaintOnScreenWidget: public QWidget
6917 PaintOnScreenWidget(QWidget *parent = 0, Qt::WindowFlags f = 0)
6921 #if defined(Q_OS_WIN)
6922 // This is the only way to enable PaintOnScreen on Windows.
6923 QPaintEngine * paintEngine () const {return 0;}
6927 void tst_QWidget::alienWidgets()
6929 if (m_platform != QStringLiteral("xcb") && m_platform != QStringLiteral("windows"))
6930 QSKIP("This test is only for X11/Windows.");
6932 qApp->setAttribute(Qt::AA_DontCreateNativeWidgetSiblings);
6934 QWidget child(&parent);
6935 QWidget grandChild(&child);
6936 QWidget greatGrandChild(&grandChild);
6939 QTest::qWaitForWindowShown(parent.windowHandle());
6941 // Verify that the WA_WState_Created attribute is set
6942 // and the top-level is the only native window.
6943 QVERIFY(parent.testAttribute(Qt::WA_WState_Created));
6944 QVERIFY(parent.internalWinId());
6946 QVERIFY(child.testAttribute(Qt::WA_WState_Created));
6947 QVERIFY(!child.internalWinId());
6949 QVERIFY(grandChild.testAttribute(Qt::WA_WState_Created));
6950 QVERIFY(!grandChild.internalWinId());
6952 QVERIFY(greatGrandChild.testAttribute(Qt::WA_WState_Created));
6953 QVERIFY(!greatGrandChild.internalWinId());
6955 // Enforce native windows all the way up in the parent hierarchy
6956 // if not WA_DontCreateNativeAncestors is set.
6957 grandChild.setAttribute(Qt::WA_DontCreateNativeAncestors);
6958 greatGrandChild.setAttribute(Qt::WA_NativeWindow);
6959 QVERIFY(greatGrandChild.internalWinId());
6960 QVERIFY(grandChild.internalWinId());
6961 QVERIFY(!child.internalWinId());
6964 // Ensure that hide() on an ancestor of a widget with
6965 // Qt::WA_DontCreateNativeAncestors still gets unmapped
6967 QWidget widget(&window);
6968 QWidget child(&widget);
6969 child.setAttribute(Qt::WA_NativeWindow);
6970 child.setAttribute(Qt::WA_DontCreateNativeAncestors);
6972 QVERIFY(child.testAttribute(Qt::WA_Mapped));
6974 QVERIFY(!child.testAttribute(Qt::WA_Mapped));
6977 // Enforce a native window when calling QWidget::winId.
6978 QVERIFY(child.winId());
6979 QVERIFY(child.internalWinId());
6981 // Check that paint on screen widgets (incl. children) are native.
6982 PaintOnScreenWidget paintOnScreen(&parent);
6983 QWidget paintOnScreenChild(&paintOnScreen);
6984 paintOnScreen.show();
6985 QVERIFY(paintOnScreen.testAttribute(Qt::WA_WState_Created));
6986 QVERIFY(!paintOnScreen.testAttribute(Qt::WA_NativeWindow));
6987 QVERIFY(!paintOnScreen.internalWinId());
6988 QVERIFY(!paintOnScreenChild.testAttribute(Qt::WA_NativeWindow));
6989 QVERIFY(!paintOnScreenChild.internalWinId());
6991 paintOnScreen.setAttribute(Qt::WA_PaintOnScreen);
6992 QVERIFY(paintOnScreen.testAttribute(Qt::WA_NativeWindow));
6993 QVERIFY(paintOnScreen.internalWinId());
6994 QVERIFY(paintOnScreenChild.testAttribute(Qt::WA_NativeWindow));
6995 QVERIFY(paintOnScreenChild.internalWinId());
6997 // Check that widgets with the Qt::MSWindowsOwnDC attribute set
6999 QWidget msWindowsOwnDC(&parent, Qt::MSWindowsOwnDC);
7000 msWindowsOwnDC.show();
7001 QVERIFY(msWindowsOwnDC.testAttribute(Qt::WA_WState_Created));
7002 QVERIFY(msWindowsOwnDC.testAttribute(Qt::WA_NativeWindow));
7003 QVERIFY(msWindowsOwnDC.internalWinId());
7005 { // Enforce a native window when calling QWidget::handle() (on X11) or QWidget::getDC() (on Windows).
7006 QWidget widget(&parent);
7008 QVERIFY(widget.testAttribute(Qt::WA_WState_Created));
7009 QVERIFY(!widget.internalWinId());
7012 QVERIFY(widget.internalWinId());
7015 if (m_platform == QStringLiteral("xcb")) {
7016 // Make sure we don't create native windows when setting Qt::WA_X11NetWmWindowType attributes
7017 // on alien widgets (see task 194231).
7019 QVERIFY(dummy.winId());
7020 QWidget widget(&dummy);
7021 widget.setAttribute(Qt::WA_X11NetWmWindowTypeToolBar);
7022 QVERIFY(!widget.internalWinId());
7025 { // Make sure we create native ancestors when setting Qt::WA_PaintOnScreen before show().
7027 QWidget child(&topLevel);
7028 QWidget grandChild(&child);
7029 PaintOnScreenWidget greatGrandChild(&grandChild);
7031 greatGrandChild.setAttribute(Qt::WA_PaintOnScreen);
7032 QVERIFY(!child.internalWinId());
7033 QVERIFY(!grandChild.internalWinId());
7034 QVERIFY(!greatGrandChild.internalWinId());
7037 QVERIFY(child.internalWinId());
7038 QVERIFY(grandChild.internalWinId());
7039 QVERIFY(greatGrandChild.internalWinId());
7042 { // Ensure that widgets reparented into Qt::WA_PaintOnScreen widgets become native.
7044 QWidget *widget = new PaintOnScreenWidget(&topLevel);
7045 widget->setAttribute(Qt::WA_PaintOnScreen);
7046 QWidget *child = new QWidget;
7047 QWidget *dummy = new QWidget(child);
7048 QWidget *grandChild = new QWidget(child);
7049 QWidget *dummy2 = new QWidget(grandChild);
7051 child->setParent(widget);
7053 QVERIFY(!topLevel.internalWinId());
7054 QVERIFY(!child->internalWinId());
7055 QVERIFY(!dummy->internalWinId());
7056 QVERIFY(!grandChild->internalWinId());
7057 QVERIFY(!dummy2->internalWinId());
7060 QVERIFY(topLevel.internalWinId());
7061 QVERIFY(widget->testAttribute(Qt::WA_NativeWindow));
7062 QVERIFY(child->internalWinId());
7063 QVERIFY(child->testAttribute(Qt::WA_NativeWindow));
7064 QVERIFY(!child->testAttribute(Qt::WA_PaintOnScreen));
7065 QVERIFY(!dummy->internalWinId());
7066 QVERIFY(!dummy->testAttribute(Qt::WA_NativeWindow));
7067 QVERIFY(!grandChild->internalWinId());
7068 QVERIFY(!grandChild->testAttribute(Qt::WA_NativeWindow));
7069 QVERIFY(!dummy2->internalWinId());
7070 QVERIFY(!dummy2->testAttribute(Qt::WA_NativeWindow));
7073 { // Ensure that ancestors of a Qt::WA_PaintOnScreen widget stay native
7074 // if they are re-created (typically in QWidgetPrivate::setParent_sys) (task 210822).
7076 QWidget child(&window);
7079 grandChild.setWindowTitle("This causes the widget to be created");
7081 PaintOnScreenWidget paintOnScreenWidget;
7082 paintOnScreenWidget.setAttribute(Qt::WA_PaintOnScreen);
7083 paintOnScreenWidget.setParent(&grandChild);
7085 grandChild.setParent(&child);
7089 QVERIFY(window.internalWinId());
7090 QVERIFY(child.internalWinId());
7091 QVERIFY(child.testAttribute(Qt::WA_NativeWindow));
7092 QVERIFY(grandChild.internalWinId());
7093 QVERIFY(grandChild.testAttribute(Qt::WA_NativeWindow));
7094 QVERIFY(paintOnScreenWidget.internalWinId());
7095 QVERIFY(paintOnScreenWidget.testAttribute(Qt::WA_NativeWindow));
7098 { // Ensure that all siblings are native unless Qt::AA_DontCreateNativeWidgetSiblings is set.
7099 qApp->setAttribute(Qt::AA_DontCreateNativeWidgetSiblings, false);
7101 QWidget *toolBar = new QWidget(&mainWindow);
7102 QWidget *dockWidget = new QWidget(&mainWindow);
7103 QWidget *centralWidget = new QWidget(&mainWindow);
7105 QWidget *button = new QWidget(centralWidget);
7106 QWidget *mdiArea = new QWidget(centralWidget);
7108 QWidget *horizontalScroll = new QWidget(mdiArea);
7109 QWidget *verticalScroll = new QWidget(mdiArea);
7110 QWidget *viewport = new QWidget(mdiArea);
7112 viewport->setAttribute(Qt::WA_NativeWindow);
7115 // Ensure that the viewport and its siblings are native:
7116 QVERIFY(verticalScroll->testAttribute(Qt::WA_NativeWindow));
7117 QVERIFY(verticalScroll->testAttribute(Qt::WA_NativeWindow));
7118 QVERIFY(horizontalScroll->testAttribute(Qt::WA_NativeWindow));
7120 // Ensure that the mdi area and its siblings are native:
7121 QVERIFY(mdiArea->testAttribute(Qt::WA_NativeWindow));
7122 QVERIFY(button->testAttribute(Qt::WA_NativeWindow));
7124 // Ensure that the central widget and its siblings are native:
7125 QVERIFY(centralWidget->testAttribute(Qt::WA_NativeWindow));
7126 QVERIFY(dockWidget->testAttribute(Qt::WA_NativeWindow));
7127 QVERIFY(toolBar->testAttribute(Qt::WA_NativeWindow));
7131 class ASWidget : public QWidget
7134 ASWidget(QSize sizeHint, QSizePolicy sizePolicy, bool layout, bool hfwLayout, QWidget *parent = 0)
7135 : QWidget(parent), mySizeHint(sizeHint)
7137 setSizePolicy(sizePolicy);
7139 QSizePolicy sp = QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
7140 sp.setHeightForWidth(hfwLayout);
7142 QVBoxLayout *vbox = new QVBoxLayout;
7144 vbox->addWidget(new ASWidget(sizeHint + QSize(30, 20), sp, false, false));
7149 QSize sizeHint() const {
7151 return layout()->totalSizeHint();
7154 int heightForWidth(int width) const {
7155 if (sizePolicy().hasHeightForWidth()) {
7165 void tst_QWidget::adjustSize_data()
7167 const int MagicW = 200;
7168 const int MagicH = 100;
7170 QTest::addColumn<QSize>("sizeHint");
7171 QTest::addColumn<int>("hPolicy");
7172 QTest::addColumn<int>("vPolicy");
7173 QTest::addColumn<bool>("hfwSP");
7174 QTest::addColumn<bool>("layout");
7175 QTest::addColumn<bool>("hfwLayout");
7176 QTest::addColumn<bool>("haveParent");
7177 QTest::addColumn<QSize>("expectedSize");
7179 QTest::newRow("1") << QSize(5, 6) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
7180 << false << false << false << false << QSize(5, qMax(6, MagicH));
7181 QTest::newRow("2") << QSize(5, 6) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
7182 << true << false << false << false << QSize(5, qMax(10, MagicH));
7183 QTest::newRow("3") << QSize(5, 6) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
7184 << false << true << false << false << QSize(35, 26);
7185 QTest::newRow("4") << QSize(5, 6) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
7186 << false << true << true << false << QSize(35, 70);
7187 QTest::newRow("5") << QSize(40001, 30001) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
7188 << false << false << false << false << QSize(100000, 100000);
7189 QTest::newRow("6") << QSize(40001, 30001) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
7190 << true << false << false << false << QSize(100000, 100000);
7191 QTest::newRow("7") << QSize(40001, 30001) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
7192 << false << true << false << false << QSize(100000, 100000);
7193 QTest::newRow("8") << QSize(40001, 30001) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
7194 << false << true << true << false << QSize(100000, 100000);
7195 QTest::newRow("9") << QSize(5, 6) << int(QSizePolicy::Expanding) << int(QSizePolicy::Minimum)
7196 << true << false << false << false << QSize(qMax(5, MagicW), 10);
7198 QTest::newRow("1c") << QSize(5, 6) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
7199 << false << false << false << true << QSize(5, 6);
7200 QTest::newRow("2c") << QSize(5, 6) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
7201 << true << false << false << true << QSize(5, 6 /* or 10 would be OK too, since hfw contradicts sizeHint() */);
7202 QTest::newRow("3c") << QSize(5, 6) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
7203 << false << true << false << true << QSize(35, 26);
7204 QTest::newRow("4c") << QSize(5, 6) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
7205 << false << true << true << true << QSize(35, 70);
7206 QTest::newRow("5c") << QSize(40001, 30001) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
7207 << false << false << false << true << QSize(40001, 30001);
7208 QTest::newRow("6c") << QSize(40001, 30001) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
7209 << true << false << false << true << QSize(40001, 30001 /* or 80002 would be OK too, since hfw contradicts sizeHint() */);
7210 QTest::newRow("7c") << QSize(40001, 30001) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
7211 << false << true << false << true << QSize(40001 + 30, 30001 + 20);
7212 QTest::newRow("8c") << QSize(40001, 30001) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
7213 << false << true << true << true << QSize(40001 + 30, 80002 + 60);
7214 QTest::newRow("9c") << QSize(5, 6) << int(QSizePolicy::Expanding) << int(QSizePolicy::Minimum)
7215 << true << false << false << true << QSize(5, 6);
7218 void tst_QWidget::adjustSize()
7220 QFETCH(QSize, sizeHint);
7221 QFETCH(int, hPolicy);
7222 QFETCH(int, vPolicy);
7223 QFETCH(bool, hfwSP);
7224 QFETCH(bool, layout);
7225 QFETCH(bool, hfwLayout);
7226 QFETCH(bool, haveParent);
7227 QFETCH(QSize, expectedSize);
7229 QWidget *parent = new QWidget;
7231 QSizePolicy sp = QSizePolicy(QSizePolicy::Policy(hPolicy), QSizePolicy::Policy(vPolicy));
7232 sp.setHeightForWidth(hfwSP);
7234 QWidget *child = new ASWidget(sizeHint, sp, layout, hfwLayout, haveParent ? parent : 0);
7235 child->resize(123, 456);
7236 child->adjustSize();
7237 if (expectedSize == QSize(100000, 100000)) {
7238 QVERIFY(child->size().width() < sizeHint.width());
7239 QVERIFY(child->size().height() < sizeHint.height());
7241 #if defined (Q_OS_WINCE)
7243 const QRect& desktopRect = qApp->desktop()->availableGeometry();
7244 expectedSize.setWidth(qMin(expectedSize.width(), desktopRect.width()));
7245 expectedSize.setHeight(qMin(expectedSize.height(), desktopRect.height()));
7248 QCOMPARE(child->size(), expectedSize);
7254 class TestLayout : public QVBoxLayout
7258 TestLayout(QWidget *w = 0) : QVBoxLayout(w)
7260 invalidated = false;
7271 void tst_QWidget::updateGeometry_data()
7273 QTest::addColumn<QSize>("minSize");
7274 QTest::addColumn<bool>("shouldInvalidate");
7275 QTest::addColumn<QSize>("maxSize");
7276 QTest::addColumn<bool>("shouldInvalidate2");
7277 QTest::addColumn<int>("verticalSizePolicy");
7278 QTest::addColumn<bool>("shouldInvalidate3");
7279 QTest::addColumn<bool>("setVisible");
7280 QTest::addColumn<bool>("shouldInvalidate4");
7282 QTest::newRow("setMinimumSize")
7283 << QSize(100, 100) << true
7285 << int(QSizePolicy::Preferred) << false
7287 QTest::newRow("setMaximumSize")
7289 << QSize(100, 100) << true
7290 << int(QSizePolicy::Preferred) << false
7292 QTest::newRow("setMinimumSize, then maximumSize to a different size")
7293 << QSize(100, 100) << true
7294 << QSize(300, 300) << true
7295 << int(QSizePolicy::Preferred) << false
7297 QTest::newRow("setMinimumSize, then maximumSize to the same size")
7298 << QSize(100, 100) << true
7299 << QSize(100, 100) << true
7300 << int(QSizePolicy::Preferred) << false
7302 QTest::newRow("setMinimumSize, then maximumSize to the same size and then hide it")
7303 << QSize(100, 100) << true
7304 << QSize(100, 100) << true
7305 << int(QSizePolicy::Preferred) << false
7307 QTest::newRow("Change sizePolicy")
7310 << int(QSizePolicy::Minimum) << true
7315 void tst_QWidget::updateGeometry()
7317 QFETCH(QSize, minSize);
7318 QFETCH(bool, shouldInvalidate);
7319 QFETCH(QSize, maxSize);
7320 QFETCH(bool, shouldInvalidate2);
7321 QFETCH(int, verticalSizePolicy);
7322 QFETCH(bool, shouldInvalidate3);
7323 QFETCH(bool, setVisible);
7324 QFETCH(bool, shouldInvalidate4);
7326 parent.resize(200, 200);
7327 TestLayout *lout = new TestLayout();
7328 parent.setLayout(lout);
7329 QWidget *child = new QWidget(&parent);
7330 lout->addWidget(child);
7332 QApplication::processEvents();
7334 lout->invalidated = false;
7335 if (minSize.isValid())
7336 child->setMinimumSize(minSize);
7337 QCOMPARE(lout->invalidated, shouldInvalidate);
7339 lout->invalidated = false;
7340 if (maxSize.isValid())
7341 child->setMaximumSize(maxSize);
7342 QCOMPARE(lout->invalidated, shouldInvalidate2);
7344 lout->invalidated = false;
7345 child->setSizePolicy(QSizePolicy(QSizePolicy::Preferred, (QSizePolicy::Policy)verticalSizePolicy));
7346 if (shouldInvalidate3)
7347 QCOMPARE(lout->invalidated, true);
7349 lout->invalidated = false;
7351 child->setVisible(false);
7352 QCOMPARE(lout->invalidated, shouldInvalidate4);
7355 void tst_QWidget::sendUpdateRequestImmediately()
7357 UpdateWidget updateWidget;
7358 updateWidget.show();
7360 QTest::qWaitForWindowShown(updateWidget.windowHandle());
7362 qApp->processEvents();
7363 updateWidget.reset();
7365 QCOMPARE(updateWidget.numUpdateRequestEvents, 0);
7366 updateWidget.repaint();
7367 QCOMPARE(updateWidget.numUpdateRequestEvents, 1);
7370 void tst_QWidget::doubleRepaint()
7372 #if defined(Q_OS_MAC)
7373 if (!macHasAccessToWindowsServer())
7374 QSKIP("Not having window server access causes the wrong number of repaints to be issues");
7376 UpdateWidget widget;
7377 widget.setFocusPolicy(Qt::StrongFocus);
7378 // Filter out activation change and focus events to avoid update() calls in QWidget.
7379 widget.updateOnActivationChangeAndFocusIn = false;
7382 int expectedRepaints = 1;
7384 QTest::qWaitForWindowShown(&widget);
7386 QTRY_COMPARE(widget.numPaintEvents, expectedRepaints);
7387 widget.numPaintEvents = 0;
7389 // Minmize: Should not trigger a repaint.
7390 widget.showMinimized();
7392 QCOMPARE(widget.numPaintEvents, 0);
7393 widget.numPaintEvents = 0;
7395 // Restore: Should not trigger a repaint.
7396 widget.showNormal();
7397 QTest::qWaitForWindowShown(&widget);
7399 QCOMPARE(widget.numPaintEvents, 0);
7402 void tst_QWidget::resizeInPaintEvent()
7405 UpdateWidget widget(&window);
7407 QTest::qWaitForWindowShown(&window);
7408 QTRY_VERIFY(widget.numPaintEvents > 0);
7411 QCOMPARE(widget.numPaintEvents, 0);
7413 widget.resizeInPaintEvent = true;
7414 // This will call resize in the paintEvent, which in turn will call
7415 // invalidateBuffer() and a new update request should be posted.
7417 QCOMPARE(widget.numPaintEvents, 1);
7418 widget.numPaintEvents = 0;
7421 // Make sure the resize triggers another update.
7422 QTRY_COMPARE(widget.numPaintEvents, 1);
7425 void tst_QWidget::opaqueChildren()
7428 widget.resize(200, 200);
7430 QWidget child(&widget);
7431 child.setGeometry(-700, -700, 200, 200);
7433 QWidget grandChild(&child);
7434 grandChild.resize(200, 200);
7436 QWidget greatGrandChild(&grandChild);
7437 greatGrandChild.setGeometry(50, 50, 200, 200);
7438 greatGrandChild.setPalette(Qt::red);
7439 greatGrandChild.setAutoFillBackground(true); // Opaque child widget.
7442 QTest::qWaitForWindowShown(widget.windowHandle());
7445 // Child, grandChild and greatGrandChild are outside the ancestor clip.
7446 QRegion expectedOpaqueRegion(50, 50, 150, 150);
7447 QCOMPARE(qt_widget_private(&grandChild)->getOpaqueChildren(), expectedOpaqueRegion);
7449 // Now they are all inside the ancestor clip.
7450 child.setGeometry(50, 50, 150, 150);
7451 QCOMPARE(qt_widget_private(&grandChild)->getOpaqueChildren(), expectedOpaqueRegion);
7453 // Set mask on greatGrandChild.
7454 const QRegion mask(10, 10, 50, 50);
7455 greatGrandChild.setMask(mask);
7456 expectedOpaqueRegion &= mask.translated(50, 50);
7457 QCOMPARE(qt_widget_private(&grandChild)->getOpaqueChildren(), expectedOpaqueRegion);
7459 // Make greatGrandChild "transparent".
7460 greatGrandChild.setAutoFillBackground(false);
7461 QCOMPARE(qt_widget_private(&grandChild)->getOpaqueChildren(), QRegion());
7465 class MaskSetWidget : public QWidget
7469 MaskSetWidget(QWidget* p =0)
7472 void paintEvent(QPaintEvent* event) {
7475 paintedRegion += event->region();
7476 foreach(QRect r, event->region().rects())
7477 p.fillRect(r, Qt::red);
7480 void resizeEvent(QResizeEvent*) {
7481 setMask(QRegion(QRect(0, 0, width(), 10).normalized()));
7484 QRegion paintedRegion;
7488 setGeometry(QRect(0, 50, 50, 50));
7492 setGeometry(QRect(0, 50, 150, 50));
7497 void tst_QWidget::setMaskInResizeEvent()
7502 w.setWindowFlags(Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint);
7505 MaskSetWidget testWidget(&w);
7506 testWidget.setGeometry(0, 0, 100, 100);
7507 testWidget.setMask(QRegion(QRect(0,0,100,10)));
7510 QTest::qWaitForWindowShown(&w);
7512 QTRY_VERIFY(w.numPaintEvents > 0);
7515 testWidget.paintedRegion = QRegion();
7516 QTimer::singleShot(0, &testWidget, SLOT(resizeDown()));
7519 QRegion expectedParentUpdate(0, 0, 100, 10); // Old testWidget area.
7520 expectedParentUpdate += testWidget.geometry(); // New testWidget area.
7521 QCOMPARE(w.paintedRegion, expectedParentUpdate);
7522 QCOMPARE(testWidget.paintedRegion, testWidget.mask());
7524 testWidget.paintedRegion = QRegion();
7525 // Now resize the widget again, but in the oposite direction
7526 QTimer::singleShot(0, &testWidget, SLOT(resizeUp()));
7529 QTRY_COMPARE(testWidget.paintedRegion, testWidget.mask());
7532 class MoveInResizeWidget : public QWidget
7536 MoveInResizeWidget(QWidget* p = 0)
7539 setWindowFlags(Qt::FramelessWindowHint);
7542 void resizeEvent(QResizeEvent*) {
7544 move(QPoint(100,100));
7546 static bool firstTime = true;
7548 QTimer::singleShot(250, this, SLOT(resizeMe()));
7559 void tst_QWidget::moveInResizeEvent()
7561 MoveInResizeWidget testWidget;
7562 testWidget.setGeometry(50, 50, 200, 200);
7564 QTest::qWaitForWindowShown(&testWidget);
7567 QRect expectedGeometry(100,100, 100, 100);
7568 QTRY_COMPARE(testWidget.geometry(), expectedGeometry);
7571 void tst_QWidget::immediateRepaintAfterShow()
7573 if (m_platform != QStringLiteral("xcb") && m_platform != QStringLiteral("windows"))
7574 QSKIP("We don't support immediate repaint right after show on other platforms.");
7576 UpdateWidget widget;
7578 qApp->processEvents();
7579 // On X11 in particular, we are now waiting for a MapNotify event before
7580 // syncing the backing store. However, if someone request a repaint()
7581 // we must repaint immediately regardless of the current state.
7582 widget.numPaintEvents = 0;
7584 QCOMPARE(widget.numPaintEvents, 1);
7587 void tst_QWidget::immediateRepaintAfterInvalidateBuffer()
7589 if (m_platform != QStringLiteral("xcb") && m_platform != QStringLiteral("windows"))
7590 QSKIP("We don't support immediate repaint right after show on other platforms.");
7592 QWidget *widget = new UpdateWidget;
7594 QTest::qWaitForWindowShown(widget->windowHandle());
7597 static_cast<UpdateWidget *>(widget)->numPaintEvents = 0;
7599 // Marks the area covered by the widget as dirty in the backing store and
7600 // posts an UpdateRequest event.
7601 qt_widget_private(widget)->invalidateBuffer(widget->rect());
7602 QCOMPARE(static_cast<UpdateWidget *>(widget)->numPaintEvents, 0);
7604 // The entire widget is already dirty, but this time we want to update immediately
7605 // by calling repaint(), and thus we have to repaint the widget and not wait for
7606 // the UpdateRequest to be sent when we get back to the event loop.
7608 QCOMPARE(static_cast<UpdateWidget *>(widget)->numPaintEvents, 1);
7613 void tst_QWidget::effectiveWinId()
7616 QWidget child(&parent);
7619 QVERIFY(!parent.effectiveWinId());
7620 QVERIFY(!child.effectiveWinId());
7624 QVERIFY(parent.effectiveWinId());
7625 QVERIFY(child.effectiveWinId());
7628 void tst_QWidget::effectiveWinId2()
7632 class MyWidget : public QWidget {
7633 bool event(QEvent *e)
7635 if (e->type() == QEvent::WinIdChange) {
7640 return QWidget::event(e);
7645 child.setParent(&parent);
7649 child.setParent(&parent);
7652 class CustomWidget : public QWidget
7655 mutable int metricCallCount;
7657 CustomWidget(QWidget *parent = 0) : QWidget(parent), metricCallCount(0) {}
7659 virtual int metric(PaintDeviceMetric metric) const {
7661 return QWidget::metric(metric);
7665 void tst_QWidget::customDpi()
7667 QWidget *topLevel = new QWidget;
7668 CustomWidget *custom = new CustomWidget(topLevel);
7669 QWidget *child = new QWidget(custom);
7671 custom->metricCallCount = 0;
7672 topLevel->logicalDpiX();
7673 QCOMPARE(custom->metricCallCount, 0);
7674 custom->logicalDpiX();
7675 QCOMPARE(custom->metricCallCount, 1);
7676 child->logicalDpiX();
7677 QCOMPARE(custom->metricCallCount, 2);
7682 void tst_QWidget::customDpiProperty()
7684 QWidget *topLevel = new QWidget;
7685 QWidget *middle = new CustomWidget(topLevel);
7686 QWidget *child = new QWidget(middle);
7688 const int initialDpiX = topLevel->logicalDpiX();
7689 const int initialDpiY = topLevel->logicalDpiY();
7691 middle->setProperty("_q_customDpiX", 300);
7692 middle->setProperty("_q_customDpiY", 400);
7694 QCOMPARE(topLevel->logicalDpiX(), initialDpiX);
7695 QCOMPARE(topLevel->logicalDpiY(), initialDpiY);
7697 QCOMPARE(middle->logicalDpiX(), 300);
7698 QCOMPARE(middle->logicalDpiY(), 400);
7700 QCOMPARE(child->logicalDpiX(), 300);
7701 QCOMPARE(child->logicalDpiY(), 400);
7703 middle->setProperty("_q_customDpiX", QVariant());
7704 middle->setProperty("_q_customDpiY", QVariant());
7706 QCOMPARE(topLevel->logicalDpiX(), initialDpiX);
7707 QCOMPARE(topLevel->logicalDpiY(), initialDpiY);
7709 QCOMPARE(middle->logicalDpiX(), initialDpiX);
7710 QCOMPARE(middle->logicalDpiY(), initialDpiY);
7712 QCOMPARE(child->logicalDpiX(), initialDpiX);
7713 QCOMPARE(child->logicalDpiY(), initialDpiY);
7718 void tst_QWidget::quitOnCloseAttribute()
7721 QCOMPARE(w.testAttribute(Qt::WA_QuitOnClose), true);
7722 w.setAttribute(Qt::WA_QuitOnClose, false);
7723 QCOMPARE(w.testAttribute(Qt::WA_QuitOnClose), false);
7725 w.setAttribute(Qt::WA_QuitOnClose);
7726 w.setWindowFlags(Qt::Tool);
7727 QCOMPARE(w.testAttribute(Qt::WA_QuitOnClose), false);
7729 w.setAttribute(Qt::WA_QuitOnClose);
7730 w.setWindowFlags(Qt::Popup);
7731 QCOMPARE(w.testAttribute(Qt::WA_QuitOnClose), false);
7733 w.setAttribute(Qt::WA_QuitOnClose);
7734 w.setWindowFlags(Qt::ToolTip);
7735 QCOMPARE(w.testAttribute(Qt::WA_QuitOnClose), false);
7737 w.setAttribute(Qt::WA_QuitOnClose);
7738 w.setWindowFlags(Qt::SplashScreen);
7739 QCOMPARE(w.testAttribute(Qt::WA_QuitOnClose), false);
7741 w.setAttribute(Qt::WA_QuitOnClose);
7742 w.setWindowFlags(Qt::SubWindow);
7743 QCOMPARE(w.testAttribute(Qt::WA_QuitOnClose), false);
7745 w.setAttribute(Qt::WA_QuitOnClose);
7746 w.setWindowFlags(Qt::Dialog);
7747 QCOMPARE(w.testAttribute(Qt::WA_QuitOnClose), true);
7749 QCOMPARE(w.testAttribute(Qt::WA_QuitOnClose), true);
7750 w.setWindowFlags(Qt::Tool);
7751 QCOMPARE(w.testAttribute(Qt::WA_QuitOnClose), false);
7754 void tst_QWidget::moveRect()
7757 widget.setUpdatesEnabled(false);
7758 QWidget child(&widget);
7759 child.setUpdatesEnabled(false);
7760 child.setAttribute(Qt::WA_OpaquePaintEvent);
7763 child.move(10, 10); // Don't crash.
7767 class GDIWidget : public QDialog
7771 GDIWidget() { setAttribute(Qt::WA_PaintOnScreen); }
7772 QPaintEngine *paintEngine() const { return 0; }
7775 void paintEvent(QPaintEvent *) {
7776 QPlatformNativeInterface *ni = QGuiApplication::platformNativeInterface();
7777 const HDC hdc = (HDC)ni->nativeResourceForWindow(QByteArrayLiteral("getDC"), windowHandle());
7779 qWarning("%s: Unable to obtain native DC.", Q_FUNC_INFO);
7780 QTimer::singleShot(0, this, SLOT(reject()));
7783 SelectObject(hdc, CreateSolidBrush(RGB(255, 0, 0)));
7784 Rectangle(hdc, 0, 0, 10, 10);
7786 ni->nativeResourceForWindow(QByteArrayLiteral("releaseDC"), windowHandle());
7788 QTimer::singleShot(0, this, SLOT(slotTimer()));
7791 QSize sizeHint() const {
7792 return QSize(400, 300);
7797 QScreen *screen = windowHandle()->screen();
7798 const QImage im = screen->grabWindow(internalWinId(), 0, 0, -1, -1).toImage();
7799 color = im.pixel(1, 1);
7807 void tst_QWidget::gdiPainting()
7812 QCOMPARE(w.color, QColor(255, 0, 0));
7816 void tst_QWidget::paintOnScreenPossible()
7819 w1.setAttribute(Qt::WA_PaintOnScreen);
7820 QVERIFY(!w1.testAttribute(Qt::WA_PaintOnScreen));
7823 w2.setAttribute(Qt::WA_PaintOnScreen);
7824 QVERIFY(w2.testAttribute(Qt::WA_PaintOnScreen));
7828 void tst_QWidget::reparentStaticWidget()
7832 QWidget *child = new QWidget(&window1);
7833 child->setPalette(Qt::red);
7834 child->setAutoFillBackground(true);
7835 child->setAttribute(Qt::WA_StaticContents);
7836 child->resize(100, 100);
7838 QWidget *grandChild = new QWidget(child);
7839 grandChild->setPalette(Qt::blue);
7840 grandChild->setAutoFillBackground(true);
7841 grandChild->resize(50, 50);
7842 grandChild->setAttribute(Qt::WA_StaticContents);
7844 QTest::qWaitForWindowShown(&window1);
7848 QTest::qWaitForWindowShown(&window2);
7851 // Reparent into another top-level.
7852 child->setParent(&window2);
7855 // Please don't crash.
7856 window1.resize(window1.size() + QSize(2, 2));
7859 // Make sure we move all static children even though
7860 // the reparented widget itself is non-static.
7861 child->setAttribute(Qt::WA_StaticContents, false);
7862 child->setParent(&window1);
7865 // Please don't crash.
7866 window2.resize(window2.size() + QSize(2, 2));
7869 child->setParent(0);
7873 // Please don't crash.
7874 child->resize(child->size() + QSize(2, 2));
7875 window2.resize(window2.size() + QSize(2, 2));
7878 QWidget *siblingOfGrandChild = new QWidget(child);
7879 siblingOfGrandChild->show();
7882 // Nothing should happen when reparenting within the same top-level.
7883 grandChild->setParent(siblingOfGrandChild);
7887 QWidget paintOnScreen;
7888 paintOnScreen.setAttribute(Qt::WA_PaintOnScreen);
7889 paintOnScreen.show();
7890 QTest::qWaitForWindowShown(&paintOnScreen);
7893 child->setParent(&paintOnScreen);
7897 // Please don't crash.
7898 paintOnScreen.resize(paintOnScreen.size() + QSize(2, 2));
7903 void tst_QWidget::QTBUG6883_reparentStaticWidget2()
7906 QDockWidget *one = new QDockWidget("one", &mw);
7907 mw.addDockWidget(Qt::LeftDockWidgetArea, one , Qt::Vertical);
7909 QWidget *child = new QWidget();
7910 child->setPalette(Qt::red);
7911 child->setAutoFillBackground(true);
7912 child->setAttribute(Qt::WA_StaticContents);
7913 child->resize(100, 100);
7914 one->setWidget(child);
7916 QToolBar *mainTools = mw.addToolBar("Main Tools");
7917 mainTools->addWidget(new QLineEdit);
7920 QTest::qWaitForWindowShown(&mw);
7922 one->setFloating(true);
7927 class ColorRedWidget : public QWidget
7930 ColorRedWidget(QWidget *parent = 0)
7931 : QWidget(parent, Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint | Qt::ToolTip)
7935 void paintEvent(QPaintEvent *) {
7937 p.fillRect(rect(),Qt::red);
7941 void tst_QWidget::translucentWidget()
7945 ColorRedWidget label;
7946 label.setFixedSize(16,16);
7947 label.setAttribute(Qt::WA_TranslucentBackground);
7948 const QPoint labelPos = qApp->desktop()->availableGeometry().topLeft();
7949 label.move(labelPos);
7951 QTest::qWaitForWindowShown(label.windowHandle());
7954 QPixmap widgetSnapshot;
7957 QWidget *desktopWidget = QApplication::desktop()->screen(0);
7958 if (QSysInfo::windowsVersion() >= QSysInfo::WV_VISTA)
7959 widgetSnapshot = qApp->primaryScreen()->grabWindow(desktopWidget->winId(), labelPos.x(), labelPos.y(), label.width(), label.height());
7962 widgetSnapshot = label.grab(QRect(QPoint(0, 0), label.size()));
7963 QImage actual = widgetSnapshot.toImage().convertToFormat(QImage::Format_RGB32);
7964 QImage expected = pm.toImage().convertToFormat(QImage::Format_RGB32);
7965 QCOMPARE(actual.size(),expected.size());
7966 QCOMPARE(actual,expected);
7969 class MaskResizeTestWidget : public QWidget
7973 MaskResizeTestWidget(QWidget* p =0)
7975 setMask(QRegion(QRect(0, 0, 100, 100).normalized()));
7978 void paintEvent(QPaintEvent* event) {
7981 paintedRegion += event->region();
7982 foreach(QRect r, event->region().rects())
7983 p.fillRect(r, Qt::red);
7986 QRegion paintedRegion;
7989 void enlargeMask() {
7990 QRegion newMask(QRect(0, 0, 150, 150).normalized());
7995 QRegion newMask(QRect(0, 0, 50, 50).normalized());
8001 void tst_QWidget::setClearAndResizeMask()
8003 UpdateWidget topLevel;
8004 topLevel.resize(150, 150);
8006 QTest::qWaitForWindowShown(&topLevel);
8007 QTRY_VERIFY(topLevel.numPaintEvents > 0);
8010 // Mask top-level widget
8011 const QRegion topLevelMask(0, 0, 100, 100, QRegion::Ellipse);
8012 topLevel.setMask(topLevelMask);
8013 QCOMPARE(topLevel.mask(), topLevelMask);
8014 // Ensure that the top-level doesn't get any update.
8015 // We don't control what's happening on platforms other than X11, Windows
8016 if (m_platform == QStringLiteral("xcb") || m_platform == QStringLiteral("windows"))
8017 QCOMPARE(topLevel.numPaintEvents, 0);
8021 // Clear top-level mask
8022 topLevel.clearMask();
8023 QCOMPARE(topLevel.mask(), QRegion());
8025 QRegion outsideOldMask(topLevel.rect());
8026 outsideOldMask -= topLevelMask;
8027 // Ensure that the top-level gets an update for the area outside the old mask.
8028 // We don't control what's happening on platforms other than X11, Windows
8029 if (m_platform == QStringLiteral("xcb") || m_platform == QStringLiteral("windows")) {
8030 QTRY_VERIFY(topLevel.numPaintEvents > 0);
8031 QTRY_COMPARE(topLevel.paintedRegion, outsideOldMask);
8034 UpdateWidget child(&topLevel);
8035 child.setAutoFillBackground(true); // NB! Opaque child.
8036 child.setPalette(Qt::red);
8037 child.resize(100, 100);
8044 // Mask child widget with a mask that is smaller than the rect
8045 const QRegion childMask(0, 0, 50, 50);
8046 child.setMask(childMask);
8047 QTRY_COMPARE(child.mask(), childMask);
8049 // and ensure that the child widget doesn't get any update.
8051 // Mac always issues a full update when calling setMask, and we cannot force it to not do so.
8052 if (child.internalWinId())
8053 QCOMPARE(child.numPaintEvents, 1);
8056 QCOMPARE(child.numPaintEvents, 0);
8057 // and the parent widget gets an update for the newly exposed area.
8058 QTRY_COMPARE(topLevel.numPaintEvents, 1);
8059 QRegion expectedParentExpose(child.rect());
8060 expectedParentExpose -= childMask;
8061 QCOMPARE(topLevel.paintedRegion, expectedParentExpose);
8066 // Clear child widget mask
8068 QTRY_COMPARE(child.mask(), QRegion());
8070 // and ensure that that the child widget gets an update for the area outside the old mask.
8071 QTRY_COMPARE(child.numPaintEvents, 1);
8072 outsideOldMask = child.rect();
8074 // Mac always issues a full update when calling setMask, and we cannot force it to not do so.
8075 if (!child.internalWinId())
8077 outsideOldMask -= childMask;
8078 QCOMPARE(child.paintedRegion, outsideOldMask);
8079 // and the parent widget doesn't get any update.
8080 QCOMPARE(topLevel.numPaintEvents, 0);
8085 // Mask child widget with a mask that is bigger than the rect
8086 child.setMask(QRegion(0, 0, 1000, 1000));
8089 // Mac always issues a full update when calling setMask, and we cannot force it to not do so.
8090 if (child.internalWinId())
8091 QTRY_COMPARE(child.numPaintEvents, 1);
8094 // and ensure that we don't get any updates at all.
8095 QTRY_COMPARE(child.numPaintEvents, 0);
8096 QCOMPARE(topLevel.numPaintEvents, 0);
8098 // ...and the same applies when clearing the mask.
8102 // Mac always issues a full update when calling setMask, and we cannot force it to not do so.
8103 if (child.internalWinId())
8104 QTRY_VERIFY(child.numPaintEvents > 0);
8107 QCOMPARE(child.numPaintEvents, 0);
8108 QCOMPARE(topLevel.numPaintEvents, 0);
8110 QWidget resizeParent;
8111 MaskResizeTestWidget resizeChild(&resizeParent);
8113 resizeParent.resize(300,300);
8114 resizeParent.raise();
8115 resizeParent.setWindowFlags(Qt::WindowStaysOnTopHint);
8116 resizeChild.setGeometry(50,50,200,200);
8117 QPalette pal = resizeParent.palette();
8118 pal.setColor(QPalette::Window, QColor(Qt::white));
8119 resizeParent.setPalette(pal);
8121 resizeParent.show();
8122 QTest::qWaitForWindowShown(&resizeParent);
8123 // Disable the size grip on the Mac; otherwise it'll be included when grabbing the window.
8124 resizeParent.setFixedSize(resizeParent.size());
8127 resizeChild.paintedRegion = QRegion();
8129 QTimer::singleShot(100, &resizeChild, SLOT(shrinkMask()));
8132 // Mac always issues a full update when calling setMask, and we cannot force it to not do so.
8133 if (child.internalWinId())
8134 QTRY_COMPARE(resizeChild.paintedRegion, resizeChild.mask());
8137 QTRY_COMPARE(resizeChild.paintedRegion, QRegion());
8139 resizeChild.paintedRegion = QRegion();
8140 const QRegion oldMask = resizeChild.mask();
8141 QTimer::singleShot(0, &resizeChild, SLOT(enlargeMask()));
8144 // Mac always issues a full update when calling setMask, and we cannot force it to not do so.
8145 if (child.internalWinId())
8146 QTRY_COMPARE(resizeChild.paintedRegion, resizeChild.mask());
8149 QTRY_COMPARE(resizeChild.paintedRegion, resizeChild.mask() - oldMask);
8152 void tst_QWidget::maskedUpdate()
8154 UpdateWidget topLevel;
8155 topLevel.resize(200, 200);
8156 const QRegion topLevelMask(50, 50, 70, 70);
8157 topLevel.setMask(topLevelMask);
8159 UpdateWidget child(&topLevel);
8160 child.setGeometry(20, 20, 180, 180);
8161 const QRegion childMask(60, 60, 30, 30);
8162 child.setMask(childMask);
8164 UpdateWidget grandChild(&child);
8165 grandChild.setGeometry(50, 50, 100, 100);
8166 const QRegion grandChildMask(20, 20, 10, 10);
8167 grandChild.setMask(grandChildMask);
8170 QTest::qWaitForWindowShown(&topLevel);
8171 QTRY_VERIFY(topLevel.numPaintEvents > 0);
8174 #define RESET_WIDGETS \
8179 #define CLEAR_MASK(widget) \
8180 widget.clearMask(); \
8181 QTest::qWait(100); \
8184 // All widgets are transparent at this point, so any call to update() will result
8185 // in composition, i.e. the update propagates to ancestors and children.
8192 QTRY_COMPARE(topLevel.paintedRegion, topLevelMask);
8193 QTRY_COMPARE(child.paintedRegion, childMask);
8194 QTRY_COMPARE(grandChild.paintedRegion, grandChildMask);
8201 QTRY_COMPARE(topLevel.paintedRegion, childMask.translated(child.pos()));
8202 QTRY_COMPARE(child.paintedRegion, childMask);
8203 QTRY_COMPARE(grandChild.paintedRegion, grandChildMask);
8205 // GrandChild update.
8207 grandChild.update();
8210 QTRY_COMPARE(topLevel.paintedRegion, grandChildMask.translated(grandChild.mapTo(&topLevel, QPoint())));
8211 QTRY_COMPARE(child.paintedRegion, grandChildMask.translated(grandChild.pos()));
8212 QTRY_COMPARE(grandChild.paintedRegion, grandChildMask);
8214 topLevel.setAttribute(Qt::WA_OpaquePaintEvent);
8215 child.setAttribute(Qt::WA_OpaquePaintEvent);
8216 grandChild.setAttribute(Qt::WA_OpaquePaintEvent);
8218 // All widgets are now opaque, which means no composition, i.e.
8219 // the update does not propate to ancestors and children.
8226 QRegion expectedTopLevelUpdate = topLevelMask;
8227 expectedTopLevelUpdate -= childMask.translated(child.pos()); // Subtract opaque children.
8228 QTRY_COMPARE(topLevel.paintedRegion, expectedTopLevelUpdate);
8229 QTRY_COMPARE(child.paintedRegion, QRegion());
8230 QTRY_COMPARE(grandChild.paintedRegion, QRegion());
8237 QTRY_COMPARE(topLevel.paintedRegion, QRegion());
8238 QRegion expectedChildUpdate = childMask;
8239 expectedChildUpdate -= grandChildMask.translated(grandChild.pos()); // Subtract oapque children.
8240 QTRY_COMPARE(child.paintedRegion, expectedChildUpdate);
8241 QTRY_COMPARE(grandChild.paintedRegion, QRegion());
8243 // GrandChild update.
8245 grandChild.update();
8248 QTRY_COMPARE(topLevel.paintedRegion, QRegion());
8249 QTRY_COMPARE(child.paintedRegion, QRegion());
8250 QTRY_COMPARE(grandChild.paintedRegion, grandChildMask);
8252 // GrandChild update.
8253 CLEAR_MASK(grandChild);
8254 grandChild.update();
8257 QTRY_COMPARE(topLevel.paintedRegion, QRegion());
8258 QTRY_COMPARE(child.paintedRegion, QRegion());
8259 QRegion expectedGrandChildUpdate = grandChild.rect();
8260 // Clip with parent's mask.
8261 expectedGrandChildUpdate &= childMask.translated(-grandChild.pos());
8262 QCOMPARE(grandChild.paintedRegion, expectedGrandChildUpdate);
8264 // GrandChild update.
8266 grandChild.update();
8269 QTRY_COMPARE(topLevel.paintedRegion, QRegion());
8270 QTRY_COMPARE(child.paintedRegion, QRegion());
8271 expectedGrandChildUpdate = grandChild.rect();
8272 // Clip with parent's mask.
8273 expectedGrandChildUpdate &= topLevelMask.translated(-grandChild.mapTo(&topLevel, QPoint()));
8274 QTRY_COMPARE(grandChild.paintedRegion, expectedGrandChildUpdate);
8281 QTRY_COMPARE(topLevel.paintedRegion, QRegion());
8282 expectedChildUpdate = child.rect();
8283 // Clip with parent's mask.
8284 expectedChildUpdate &= topLevelMask.translated(-child.pos());
8285 expectedChildUpdate -= grandChild.geometry(); // Subtract opaque children.
8286 QTRY_COMPARE(child.paintedRegion, expectedChildUpdate);
8287 QTRY_COMPARE(grandChild.paintedRegion, QRegion());
8289 // GrandChild update.
8290 CLEAR_MASK(topLevel);
8291 grandChild.update();
8294 QTRY_COMPARE(topLevel.paintedRegion, QRegion());
8295 QTRY_COMPARE(child.paintedRegion, QRegion());
8296 QTRY_COMPARE(grandChild.paintedRegion, QRegion(grandChild.rect())); // Full update.
8299 // Windows Mobile has no proper cursor support, so skip this test on that platform.
8300 #if !defined(Q_OS_WINCE_WM)
8301 void tst_QWidget::syntheticEnterLeave()
8303 class MyWidget : public QWidget
8306 MyWidget(QWidget *parent = 0) : QWidget(parent), numEnterEvents(0), numLeaveEvents(0) {}
8307 void enterEvent(QEvent *) { ++numEnterEvents; }
8308 void leaveEvent(QEvent *) { ++numLeaveEvents; }
8313 QCursor::setPos(QPoint(0,0));
8316 window.setWindowFlags(Qt::WindowStaysOnTopHint);
8317 window.resize(200, 200);
8319 MyWidget *child1 = new MyWidget(&window);
8320 child1->setPalette(Qt::blue);
8321 child1->setAutoFillBackground(true);
8322 child1->resize(200, 200);
8323 child1->setCursor(Qt::OpenHandCursor);
8325 MyWidget *child2 = new MyWidget(&window);
8326 child2->resize(200, 200);
8328 MyWidget *grandChild = new MyWidget(child2);
8329 grandChild->setPalette(Qt::red);
8330 grandChild->setAutoFillBackground(true);
8331 grandChild->resize(200, 200);
8332 grandChild->setCursor(Qt::WaitCursor);
8337 QTest::qWaitForWindowShown(window.windowHandle());
8340 #define RESET_EVENT_COUNTS \
8341 window.numEnterEvents = 0; \
8342 window.numLeaveEvents = 0; \
8343 child1->numEnterEvents = 0; \
8344 child1->numLeaveEvents = 0; \
8345 child2->numEnterEvents = 0; \
8346 child2->numLeaveEvents = 0; \
8347 grandChild->numEnterEvents = 0; \
8348 grandChild->numLeaveEvents = 0;
8350 // Position the cursor in the middle of the window.
8351 const QPoint globalPos = window.mapToGlobal(QPoint(100, 100));
8352 QCursor::setPos(globalPos); // Enter child2 and grandChild.
8355 QCOMPARE(window.numLeaveEvents, 0);
8356 QCOMPARE(child2->numLeaveEvents, 0);
8357 QCOMPARE(grandChild->numLeaveEvents, 0);
8358 QCOMPARE(child1->numLeaveEvents, 0);
8360 // This event arrives asynchronously
8361 QTRY_COMPARE(window.numEnterEvents, 1);
8362 QCOMPARE(child2->numEnterEvents, 1);
8363 QCOMPARE(grandChild->numEnterEvents, 1);
8364 QCOMPARE(child1->numEnterEvents, 0);
8367 child2->hide(); // Leave child2 and grandChild, enter child1.
8369 QCOMPARE(window.numLeaveEvents, 0);
8370 QCOMPARE(child2->numLeaveEvents, 1);
8371 QCOMPARE(grandChild->numLeaveEvents, 1);
8372 QCOMPARE(child1->numLeaveEvents, 0);
8374 QCOMPARE(window.numEnterEvents, 0);
8375 QCOMPARE(child2->numEnterEvents, 0);
8376 QCOMPARE(grandChild->numEnterEvents, 0);
8377 QCOMPARE(child1->numEnterEvents, 1);
8380 child2->show(); // Leave child1, enter child2 and grandChild.
8382 QCOMPARE(window.numLeaveEvents, 0);
8383 QCOMPARE(child2->numLeaveEvents, 0);
8384 QCOMPARE(grandChild->numLeaveEvents, 0);
8385 QCOMPARE(child1->numLeaveEvents, 1);
8387 QCOMPARE(window.numEnterEvents, 0);
8388 QCOMPARE(child2->numEnterEvents, 1);
8389 QCOMPARE(grandChild->numEnterEvents, 1);
8390 QCOMPARE(child1->numEnterEvents, 0);
8393 delete child2; // Enter child1 (and do not send leave events to child2 and grandChild).
8395 QCOMPARE(window.numLeaveEvents, 0);
8396 QCOMPARE(child1->numLeaveEvents, 0);
8398 QCOMPARE(window.numEnterEvents, 0);
8399 QCOMPARE(child1->numEnterEvents, 1);
8403 // Windows Mobile has no proper cursor support, so skip this test on that platform.
8404 #if !defined(Q_OS_WINCE_WM)
8405 void tst_QWidget::taskQTBUG_4055_sendSyntheticEnterLeave()
8407 class SELParent : public QWidget
8410 SELParent(QWidget *parent = 0): QWidget(parent) { }
8412 void mousePressEvent(QMouseEvent *) { child->show(); }
8416 class SELChild : public QWidget
8419 SELChild(QWidget *parent = 0) : QWidget(parent), numEnterEvents(0), numMouseMoveEvents(0) {}
8420 void enterEvent(QEvent *) { ++numEnterEvents; }
8421 void mouseMoveEvent(QMouseEvent *event)
8423 QCOMPARE(event->button(), Qt::NoButton);
8424 QCOMPARE(event->buttons(), Qt::MouseButtons(Qt::NoButton));
8425 ++numMouseMoveEvents;
8427 void reset() { numEnterEvents = numMouseMoveEvents = 0; }
8428 int numEnterEvents, numMouseMoveEvents;
8431 QCursor::setPos(QPoint(0,0));
8434 parent.resize(200, 200);
8435 SELChild child(&parent);
8436 child.resize(200, 200);
8438 QTest::qWaitForWindowShown(parent.windowHandle());
8441 QCursor::setPos(child.mapToGlobal(QPoint(100, 100)));
8442 // Make sure the cursor has entered the child.
8443 QTRY_VERIFY(child.numEnterEvents > 0);
8449 // Make sure the child gets enter event and no mouse move event.
8450 QTRY_COMPARE(child.numEnterEvents, 1);
8451 QCOMPARE(child.numMouseMoveEvents, 0);
8455 child.setMouseTracking(true);
8458 // Make sure the child gets enter event and mouse move event.
8459 // Note that we verify event->button() and event->buttons()
8460 // in SELChild::mouseMoveEvent().
8461 QTRY_COMPARE(child.numEnterEvents, 1);
8462 QCOMPARE(child.numMouseMoveEvents, 1);
8464 // Sending synthetic enter/leave trough the parent's mousePressEvent handler.
8465 parent.child = &child;
8469 QTest::mouseClick(&parent, Qt::LeftButton);
8471 // Make sure the child gets enter event and one mouse move event.
8472 QTRY_COMPARE(child.numEnterEvents, 1);
8473 QCOMPARE(child.numMouseMoveEvents, 1);
8477 child.setMouseTracking(false);
8478 QTest::mouseClick(&parent, Qt::LeftButton);
8480 // Make sure the child gets enter event and no mouse move event.
8481 QTRY_COMPARE(child.numEnterEvents, 1);
8482 QCOMPARE(child.numMouseMoveEvents, 0);
8486 void tst_QWidget::windowFlags()
8489 w.setWindowFlags(w.windowFlags() | Qt::FramelessWindowHint);
8490 QVERIFY(w.windowFlags() & Qt::FramelessWindowHint);
8493 void tst_QWidget::initialPosForDontShowOnScreenWidgets()
8495 { // Check default position.
8496 const QPoint expectedPos(0, 0);
8498 widget.setAttribute(Qt::WA_DontShowOnScreen);
8499 widget.winId(); // Make sure create_sys is called.
8500 QCOMPARE(widget.pos(), expectedPos);
8501 QCOMPARE(widget.geometry().topLeft(), expectedPos);
8504 { // Explicitly move to a position.
8505 const QPoint expectedPos(100, 100);
8507 widget.setAttribute(Qt::WA_DontShowOnScreen);
8508 widget.move(expectedPos);
8509 widget.winId(); // Make sure create_sys is called.
8510 QCOMPARE(widget.pos(), expectedPos);
8511 QCOMPARE(widget.geometry().topLeft(), expectedPos);
8515 class MyEvilObject : public QObject
8519 MyEvilObject(QWidget *widgetToCrash) : QObject(), widget(widgetToCrash)
8521 connect(widget, SIGNAL(destroyed(QObject *)), this, SLOT(beEvil(QObject *)));
8527 void beEvil(QObject *) { widget->update(0, 0, 150, 150); }
8530 void tst_QWidget::updateOnDestroyedSignal()
8534 QWidget *child = new QWidget(&widget);
8535 child->resize(100, 100);
8536 child->setAutoFillBackground(true);
8537 child->setPalette(Qt::red);
8540 QTest::qWaitForWindowShown(widget.windowHandle());
8543 // Please do not crash.
8544 MyEvilObject evil(child);
8548 void tst_QWidget::toplevelLineEditFocus()
8554 QTest::qWaitForWindowShown(&w);
8557 QTRY_COMPARE(QApplication::activeWindow(), (QWidget*)&w);
8558 QTRY_COMPARE(QApplication::focusWidget(), (QWidget*)&w);
8561 void tst_QWidget::focusWidget_task254563()
8563 //having different visibility for widget is important
8566 QWidget container(&top);
8567 QWidget *widget = new QWidget(&container);
8570 widget->setFocus(); //set focus (will set the focus widget up to the toplevel to be 'widget')
8571 container.setFocus();
8572 delete widget; // will call clearFocus but that doesn't help
8573 QVERIFY(top.focusWidget() != widget); //dangling pointer
8576 // This test case relies on developer build (AUTOTEST_EXPORT).
8577 #ifdef QT_BUILD_INTERNAL
8578 void tst_QWidget::destroyBackingStore()
8584 QTest::qWaitForWindowShown(&w);
8585 QApplication::processEvents();
8586 QTRY_VERIFY(w.numPaintEvents > 0);
8589 qt_widget_private(&w)->topData()->backingStoreTracker.create(&w);
8592 QApplication::processEvents();
8594 QCOMPARE(w.numPaintEvents, 1);
8596 // Check one more time, because the second time around does more caching.
8598 QApplication::processEvents();
8599 QCOMPARE(w.numPaintEvents, 2);
8601 #endif // QT_BUILD_INTERNAL
8604 QWidgetBackingStore* backingStore(QWidget &widget)
8606 QWidgetBackingStore *backingStore = 0;
8607 #ifdef QT_BUILD_INTERNAL
8608 if (QTLWExtra *topExtra = qt_widget_private(&widget)->maybeTopData())
8609 backingStore = topExtra->backingStoreTracker.data();
8611 return backingStore;
8614 // Tables of 5000 elements do not make sense on Windows Mobile.
8615 #ifndef Q_OS_WINCE_WM
8616 void tst_QWidget::rectOutsideCoordinatesLimit_task144779()
8618 QApplication::setOverrideCursor(Qt::BlankCursor); //keep the cursor out of screen grabs
8619 QWidget main(0,Qt::FramelessWindowHint); //don't get confused by the size of the window frame
8621 palette.setColor(QPalette::Window, Qt::red);
8622 main.setPalette(palette);
8624 QDesktopWidget desktop;
8625 QRect desktopDimensions = desktop.availableGeometry(&main);
8626 QSize mainSize(400, 400);
8627 mainSize = mainSize.boundedTo(desktopDimensions.size());
8628 main.resize(mainSize);
8630 QWidget *offsetWidget = new QWidget(&main);
8631 offsetWidget->setGeometry(0, -(15000 - mainSize.height()), mainSize.width(), 15000);
8633 // big widget is too big for the coordinates, it must be limited by wrect
8634 // if wrect is not at the right position because of offsetWidget, bigwidget
8635 // is not painted correctly
8636 QWidget *bigWidget = new QWidget(offsetWidget);
8637 bigWidget->setGeometry(0, 0, mainSize.width(), 50000);
8638 palette.setColor(QPalette::Window, Qt::green);
8639 bigWidget->setPalette(palette);
8640 bigWidget->setAutoFillBackground(true);
8643 QTest::qWaitForWindowShown(&main);
8645 QPixmap correct(main.size());
8646 correct.fill(Qt::green);
8647 const QPixmap mainPixmap = main.grab(QRect(QPoint(0, 0), QSize(-1, -1)));
8649 QTRY_COMPARE(mainPixmap.toImage().convertToFormat(QImage::Format_RGB32),
8650 correct.toImage().convertToFormat(QImage::Format_RGB32));
8651 QApplication::restoreOverrideCursor();
8655 void tst_QWidget::inputFocus_task257832()
8657 QLineEdit *widget = new QLineEdit;
8659 widget->winId(); // make sure, widget has been created
8661 QTRY_VERIFY(widget->hasFocus());
8662 QCOMPARE(qApp->inputMethod()->inputItem(), static_cast<QWidget*>(widget));
8663 widget->setReadOnly(true);
8664 QVERIFY(!qApp->inputMethod()->inputItem());
8668 void tst_QWidget::setGraphicsEffect()
8670 // Check that we don't have any effect by default.
8671 QWidget *widget = new QWidget;
8672 QVERIFY(!widget->graphicsEffect());
8675 QPointer<QGraphicsEffect> blurEffect = new QGraphicsBlurEffect;
8676 widget->setGraphicsEffect(blurEffect);
8677 QCOMPARE(widget->graphicsEffect(), static_cast<QGraphicsEffect *>(blurEffect));
8679 // Ensure the existing effect is deleted when setting a new one.
8680 QPointer<QGraphicsEffect> shadowEffect = new QGraphicsDropShadowEffect;
8681 widget->setGraphicsEffect(shadowEffect);
8682 QVERIFY(!blurEffect);
8683 QCOMPARE(widget->graphicsEffect(), static_cast<QGraphicsEffect *>(shadowEffect));
8684 blurEffect = new QGraphicsBlurEffect;
8686 // Ensure the effect is uninstalled when setting it on a new target.
8687 QWidget *anotherWidget = new QWidget;
8688 anotherWidget->setGraphicsEffect(blurEffect);
8689 widget->setGraphicsEffect(blurEffect);
8690 QVERIFY(!anotherWidget->graphicsEffect());
8691 QVERIFY(!shadowEffect);
8693 // Ensure the existing effect is deleted when deleting the widget.
8695 QVERIFY(!blurEffect);
8696 delete anotherWidget;
8698 // Ensure the effect is uninstalled when deleting it
8699 widget = new QWidget;
8700 blurEffect = new QGraphicsBlurEffect;
8701 widget->setGraphicsEffect(blurEffect);
8703 QVERIFY(!widget->graphicsEffect());
8705 // Ensure the existing effect is uninstalled and deleted when setting a null effect
8706 blurEffect = new QGraphicsBlurEffect;
8707 widget->setGraphicsEffect(blurEffect);
8708 widget->setGraphicsEffect(0);
8709 QVERIFY(!widget->graphicsEffect());
8710 QVERIFY(!blurEffect);
8715 void tst_QWidget::activateWindow()
8717 // Test case for task 260685
8719 // Create first mainwindow and set it active
8720 QMainWindow* mainwindow = new QMainWindow();
8721 QLabel* label = new QLabel(mainwindow);
8722 mainwindow->setCentralWidget(label);
8723 mainwindow->setVisible(true);
8724 mainwindow->activateWindow();
8725 QTest::qWaitForWindowShown(mainwindow);
8726 qApp->processEvents();
8728 QTRY_VERIFY(mainwindow->isActiveWindow());
8730 // Create second mainwindow and set it active
8731 QMainWindow* mainwindow2 = new QMainWindow();
8732 QLabel* label2 = new QLabel(mainwindow2);
8733 mainwindow2->setCentralWidget(label2);
8734 mainwindow2->setVisible(true);
8735 mainwindow2->activateWindow();
8736 qApp->processEvents();
8738 QTRY_VERIFY(!mainwindow->isActiveWindow());
8739 QTRY_VERIFY(mainwindow2->isActiveWindow());
8741 // Revert first mainwindow back to visible active
8742 mainwindow->setVisible(true);
8743 mainwindow->activateWindow();
8744 qApp->processEvents();
8746 QTRY_VERIFY(mainwindow->isActiveWindow());
8747 QTRY_VERIFY(!mainwindow2->isActiveWindow());
8750 void tst_QWidget::openModal_taskQTBUG_5804()
8752 class Widget : public QWidget
8755 Widget(QWidget *parent) : QWidget(parent)
8761 QTimer::singleShot(10, &msgbox, SLOT(accept()));
8762 msgbox.exec(); //open a modal dialog
8766 QWidget *win = new QWidget;
8769 QTest::qWaitForWindowShown(win);
8773 void tst_QWidget::focusProxyAndInputMethods()
8775 QWidget *toplevel = new QWidget(0, Qt::X11BypassWindowManagerHint);
8776 toplevel->setAttribute(Qt::WA_InputMethodEnabled, true);
8778 QWidget *child = new QWidget(toplevel);
8779 child->setFocusProxy(toplevel);
8780 child->setAttribute(Qt::WA_InputMethodEnabled, true);
8782 toplevel->setFocusPolicy(Qt::WheelFocus);
8783 child->setFocusPolicy(Qt::WheelFocus);
8785 QVERIFY(!child->hasFocus());
8786 QVERIFY(!toplevel->hasFocus());
8789 QTest::qWaitForWindowShown(toplevel);
8790 QApplication::setActiveWindow(toplevel);
8791 QVERIFY(toplevel->hasFocus());
8792 QVERIFY(child->hasFocus());
8794 // verify that toggling input methods on the child widget
8795 // correctly propagate to the focus proxy's input method
8796 // and that the input method gets the focus proxy passed
8797 // as the focus widget instead of the child widget.
8798 // otherwise input method queries go to the wrong widget
8799 QCOMPARE(qApp->inputPanel()->inputItem(), toplevel);
8801 toplevel->setAttribute(Qt::WA_InputMethodEnabled, false);
8802 QVERIFY(!qApp->inputPanel()->inputItem());
8804 toplevel->setAttribute(Qt::WA_InputMethodEnabled, true);
8805 QCOMPARE(qApp->inputPanel()->inputItem(), toplevel);
8810 #ifdef QT_BUILD_INTERNAL
8811 class scrollWidgetWBS : public QWidget
8814 void deleteBackingStore()
8816 static_cast<QWidgetPrivate*>(d_ptr.data())->topData()->backingStoreTracker.destroy();
8818 void enableBackingStore()
8820 if (!static_cast<QWidgetPrivate*>(d_ptr.data())->maybeBackingStore()) {
8821 static_cast<QWidgetPrivate*>(d_ptr.data())->topData()->backingStoreTracker.create(this);
8822 static_cast<QWidgetPrivate*>(d_ptr.data())->invalidateBuffer(this->rect());
8829 // Test case relies on developer build (AUTOTEST_EXPORT).
8830 #ifdef QT_BUILD_INTERNAL
8831 void tst_QWidget::scrollWithoutBackingStore()
8833 scrollWidgetWBS scrollable;
8834 scrollable.resize(100,100);
8835 QLabel child(QString("@"),&scrollable);
8836 child.resize(50,50);
8838 QTest::qWaitForWindowShown(&scrollable);
8839 scrollable.scroll(50,50);
8840 QCOMPARE(child.pos(),QPoint(50,50));
8841 scrollable.deleteBackingStore();
8842 scrollable.scroll(-25,-25);
8843 QCOMPARE(child.pos(),QPoint(25,25));
8844 scrollable.enableBackingStore();
8845 QCOMPARE(child.pos(),QPoint(25,25));
8849 void tst_QWidget::taskQTBUG_7532_tabOrderWithFocusProxy()
8852 w.setFocusPolicy(Qt::TabFocus);
8853 QWidget *fp = new QWidget(&w);
8854 fp->setFocusPolicy(Qt::TabFocus);
8855 w.setFocusProxy(fp);
8856 QWidget::setTabOrder(&w, fp);
8858 // In debug mode, no assertion failure means it's alright.
8861 void tst_QWidget::movedAndResizedAttributes()
8863 #if defined (Q_OS_MAC)
8864 QEXPECT_FAIL("", "FixMe, QTBUG-8941 and QTBUG-8977", Abort);
8870 QVERIFY(!w.testAttribute(Qt::WA_Moved));
8871 QVERIFY(!w.testAttribute(Qt::WA_Resized));
8873 w.setWindowState(Qt::WindowFullScreen);
8875 QVERIFY(!w.testAttribute(Qt::WA_Moved));
8876 QVERIFY(!w.testAttribute(Qt::WA_Resized));
8878 w.setWindowState(Qt::WindowMaximized);
8880 QVERIFY(!w.testAttribute(Qt::WA_Moved));
8881 QVERIFY(!w.testAttribute(Qt::WA_Resized));
8883 w.setWindowState(Qt::WindowMinimized);
8885 QVERIFY(!w.testAttribute(Qt::WA_Moved));
8886 QVERIFY(!w.testAttribute(Qt::WA_Resized));
8890 QVERIFY(!w.testAttribute(Qt::WA_Moved));
8891 QVERIFY(!w.testAttribute(Qt::WA_Resized));
8895 QVERIFY(!w.testAttribute(Qt::WA_Moved));
8896 QVERIFY(!w.testAttribute(Qt::WA_Resized));
8900 QVERIFY(!w.testAttribute(Qt::WA_Moved));
8901 QVERIFY(!w.testAttribute(Qt::WA_Resized));
8905 QVERIFY(w.testAttribute(Qt::WA_Moved));
8906 #if defined(Q_OS_WIN)
8907 QEXPECT_FAIL("", "FixMe, QTBUG-8911", Abort);
8909 QVERIFY(!w.testAttribute(Qt::WA_Resized));
8912 QVERIFY(w.testAttribute(Qt::WA_Moved));
8913 QVERIFY(w.testAttribute(Qt::WA_Resized));
8917 void tst_QWidget::childAt()
8919 QWidget parent(0, Qt::FramelessWindowHint);
8920 parent.resize(200, 200);
8922 QWidget *child = new QWidget(&parent);
8923 child->setPalette(Qt::red);
8924 child->setAutoFillBackground(true);
8925 child->setGeometry(20, 20, 160, 160);
8927 QWidget *grandChild = new QWidget(child);
8928 grandChild->setPalette(Qt::blue);
8929 grandChild->setAutoFillBackground(true);
8930 grandChild->setGeometry(-20, -20, 220, 220);
8932 QVERIFY(!parent.childAt(19, 19));
8933 QVERIFY(!parent.childAt(180, 180));
8934 QCOMPARE(parent.childAt(20, 20), grandChild);
8935 QCOMPARE(parent.childAt(179, 179), grandChild);
8937 grandChild->setAttribute(Qt::WA_TransparentForMouseEvents);
8938 QCOMPARE(parent.childAt(20, 20), child);
8939 QCOMPARE(parent.childAt(179, 179), child);
8940 grandChild->setAttribute(Qt::WA_TransparentForMouseEvents, false);
8942 child->setMask(QRect(50, 50, 60, 60));
8944 QVERIFY(!parent.childAt(69, 69));
8945 QVERIFY(!parent.childAt(130, 130));
8946 QCOMPARE(parent.childAt(70, 70), grandChild);
8947 QCOMPARE(parent.childAt(129, 129), grandChild);
8949 child->setAttribute(Qt::WA_MouseNoMask);
8950 QCOMPARE(parent.childAt(69, 69), grandChild);
8951 QCOMPARE(parent.childAt(130, 130), grandChild);
8952 child->setAttribute(Qt::WA_MouseNoMask, false);
8954 grandChild->setAttribute(Qt::WA_TransparentForMouseEvents);
8955 QCOMPARE(parent.childAt(70, 70), child);
8956 QCOMPARE(parent.childAt(129, 129), child);
8957 grandChild->setAttribute(Qt::WA_TransparentForMouseEvents, false);
8959 grandChild->setMask(QRect(80, 80, 40, 40));
8961 QCOMPARE(parent.childAt(79, 79), child);
8962 QCOMPARE(parent.childAt(120, 120), child);
8963 QCOMPARE(parent.childAt(80, 80), grandChild);
8964 QCOMPARE(parent.childAt(119, 119), grandChild);
8966 grandChild->setAttribute(Qt::WA_MouseNoMask);
8968 QCOMPARE(parent.childAt(79, 79), grandChild);
8969 QCOMPARE(parent.childAt(120, 120), grandChild);
8973 void tst_QWidget::childAt_unifiedToolBar()
8975 QLabel *label = new QLabel(QLatin1String("foo"));
8976 QToolBar *toolBar = new QToolBar;
8977 toolBar->addWidget(new QLabel("dummy"));
8978 toolBar->addWidget(label);
8980 QMainWindow mainWindow;
8981 mainWindow.addToolBar(toolBar);
8984 // Calculate the top-left corner of the tool bar and the label (in mainWindow's coordinates).
8985 QPoint labelTopLeft = label->mapTo(&mainWindow, QPoint());
8986 QPoint toolBarTopLeft = toolBar->mapTo(&mainWindow, QPoint());
8988 QCOMPARE(mainWindow.childAt(toolBarTopLeft), static_cast<QWidget *>(toolBar));
8989 QCOMPARE(mainWindow.childAt(labelTopLeft), static_cast<QWidget *>(label));
8991 // Enable unified tool bars.
8992 mainWindow.setUnifiedTitleAndToolBarOnMac(true);
8995 // The tool bar is now in the "non-client" area of QMainWindow, i.e.
8996 // outside the mainWindow's rect(), and since mapTo et al. doesn't work
8997 // in that case (see commit 35667fd45ada49269a5987c235fdedfc43e92bb8),
8998 // we use mapToGlobal/mapFromGlobal to re-calculate the corners.
8999 QPoint oldToolBarTopLeft = toolBarTopLeft;
9000 toolBarTopLeft = mainWindow.mapFromGlobal(toolBar->mapToGlobal(QPoint()));
9001 QVERIFY(toolBarTopLeft != oldToolBarTopLeft);
9002 QVERIFY(toolBarTopLeft.y() < 0);
9003 labelTopLeft = mainWindow.mapFromGlobal(label->mapToGlobal(QPoint()));
9005 QCOMPARE(mainWindow.childAt(toolBarTopLeft), static_cast<QWidget *>(toolBar));
9006 QCOMPARE(mainWindow.childAt(labelTopLeft), static_cast<QWidget *>(label));
9009 void tst_QWidget::taskQTBUG_11373()
9011 QMainWindow * myWindow = new QMainWindow();
9012 QWidget * center = new QWidget();
9013 myWindow -> setCentralWidget(center);
9014 QWidget * drawer = new QWidget(myWindow, Qt::Drawer);
9016 QCOMPARE(drawer->isVisible(), false);
9018 myWindow -> raise();
9019 // The drawer shouldn't be visible now.
9020 QCOMPARE(drawer->isVisible(), false);
9021 myWindow -> setWindowState(Qt::WindowFullScreen);
9022 myWindow -> setWindowState(Qt::WindowNoState);
9023 // The drawer should still not be visible, since we haven't shown it.
9024 QCOMPARE(drawer->isVisible(), false);
9028 void tst_QWidget::taskQTBUG_17333_ResizeInfiniteRecursion()
9031 const char *s = "border: 1px solid;";
9032 tb.setStyleSheet(s);
9035 QTest::qWaitForWindowShown(&tb);
9036 tb.setGeometry(QRect(100, 100, 0, 100));
9037 // No crash, it works.
9040 void tst_QWidget::nativeChildFocus()
9043 QLayout *layout = new QVBoxLayout;
9044 w.setLayout(layout);
9045 QLineEdit *p1 = new QLineEdit;
9046 QLineEdit *p2 = new QLineEdit;
9047 layout->addWidget(p1);
9048 layout->addWidget(p2);
9049 p1->setObjectName("p1");
9050 p2->setObjectName("p2");
9054 p1->setAttribute(Qt::WA_NativeWindow);
9055 p2->setAttribute(Qt::WA_NativeWindow);
9056 QApplication::processEvents();
9057 QTest::qWaitForWindowShown(&w);
9060 QCOMPARE(QApplication::activeWindow(), &w);
9061 QCOMPARE(QApplication::focusWidget(), static_cast<QWidget*>(p1));
9066 static bool lenientCompare(const QPixmap &actual, const QPixmap &expected)
9068 QImage expectedImage = expected.toImage().convertToFormat(QImage::Format_RGB32);
9069 QImage actualImage = actual.toImage().convertToFormat(QImage::Format_RGB32);
9071 if (expectedImage.size() != actualImage.size()) {
9072 qWarning("Image size comparison failed: expected: %dx%d, got %dx%d",
9073 expectedImage.size().width(), expectedImage.size().height(),
9074 actualImage.size().width(), actualImage.size().height());
9078 const int size = actual.width() * actual.height();
9079 const int threshold = QPixmap::defaultDepth() == 16 ? 10 : 2;
9081 QRgb *a = (QRgb *)actualImage.bits();
9082 QRgb *e = (QRgb *)expectedImage.bits();
9083 for (int i = 0; i < size; ++i) {
9084 const QColor ca(a[i]);
9085 const QColor ce(e[i]);
9086 if (qAbs(ca.red() - ce.red()) > threshold
9087 || qAbs(ca.green() - ce.green()) > threshold
9088 || qAbs(ca.blue() - ce.blue()) > threshold) {
9089 qWarning("Color mismatch at pixel #%d: Expected: %d,%d,%d, got %d,%d,%d",
9090 i, ce.red(), ce.green(), ce.blue(), ca.red(), ca.green(), ca.blue());
9098 void tst_QWidget::grab()
9100 for (int opaque = 0; opaque < 2; ++opaque) {
9102 QImage image(128, 128, opaque ? QImage::Format_RGB32 : QImage::Format_ARGB32_Premultiplied);
9103 for (int row = 0; row < image.height(); ++row) {
9104 QRgb *line = reinterpret_cast<QRgb *>(image.scanLine(row));
9105 for (int col = 0; col < image.width(); ++col)
9106 line[col] = qRgba(rand() & 255, row, col, opaque ? 255 : 127);
9109 QPalette pal = widget.palette();
9110 pal.setBrush(QPalette::Window, QBrush(image));
9111 widget.setPalette(pal);
9112 widget.resize(128, 128);
9114 QPixmap expected(64, 64);
9116 expected.fill(Qt::transparent);
9118 QPainter p(&expected);
9119 p.translate(-64, -64);
9120 p.drawTiledPixmap(0, 0, 128, 128, pal.brush(QPalette::Window).texture(), 0, 0);
9123 QPixmap actual = widget.grab(QRect(64, 64, 64, 64));
9124 QVERIFY(lenientCompare(actual, expected));
9126 actual = widget.grab(QRect(64, 64, -1, -1));
9127 QVERIFY(lenientCompare(actual, expected));
9129 // Make sure a widget that is not yet shown is grabbed correctly.
9130 QTreeWidget widget2;
9131 actual = widget2.grab(QRect());
9133 expected = widget2.grab(QRect());
9135 QVERIFY(lenientCompare(actual, expected));
9139 QTEST_MAIN(tst_QWidget)
9140 #include "tst_qwidget.moc"