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>
70 #include <qtableview.h>
72 #include <QtWidgets/QGraphicsView>
73 #include <QtWidgets/QGraphicsProxyWidget>
76 # include <qscreen_qws.h>
80 #include "tst_qwidget_mac_helpers.h" // Abstract the ObjC stuff out so not everyone must run an ObjC++ compile.
83 #include <QtTest/QtTest>
86 # include <QtCore/qt_windows.h>
87 # include <QtGui/private/qguiapplication_p.h>
88 # include <QtGui/QPlatformNativeInterface>
89 # include <QtGui/QPlatformIntegration>
91 static HWND winHandleOf(const QWidget *w)
93 static QPlatformNativeInterface *nativeInterface
94 = QGuiApplicationPrivate::instance()->platformIntegration()->nativeInterface();
95 if (void *handle = nativeInterface->nativeResourceForWindow("handle", w->window()->windowHandle()))
96 return reinterpret_cast<HWND>(handle);
97 qWarning() << "Cannot obtain native handle for " << w;
102 #if defined(Q_WS_WIN)
103 # include <qt_windows.h>
104 # if !defined(Q_OS_WINCE)
105 #define Q_CHECK_PAINTEVENTS \
106 if (::SwitchDesktop(::GetThreadDesktop(::GetCurrentThreadId())) == 0) \
107 QSKIP("desktop is not visible, this test would fail");
109 # define Q_CHECK_PAINTEVENTS
111 #elif defined(Q_WS_X11)
112 # include <private/qt_x11_p.h>
113 # include <qx11info_x11.h>
114 #elif defined(Q_WS_QWS)
115 # include <qwindowsystem_qws.h>
118 #if !defined(Q_WS_WIN)
119 #define Q_CHECK_PAINTEVENTS
122 #if defined(Q_OS_WINCE_WM)
123 #include <qguifunctions_wince.h>
124 // taken from qguifunctions_wce.cpp
125 #define SPI_GETPLATFORMTYPE 257
126 bool qt_wince_is_platform(const QString &platformString) {
127 wchar_t tszPlatform[64];
128 if (SystemParametersInfo(SPI_GETPLATFORMTYPE,
129 sizeof(tszPlatform)/sizeof(*tszPlatform),tszPlatform,0))
130 if (0 == _tcsicmp(reinterpret_cast<const wchar_t *> (platformString.utf16()), tszPlatform))
134 bool qt_wince_is_smartphone() {
135 return qt_wince_is_platform(QString::fromLatin1("Smartphone"));
140 #include <Security/AuthSession.h>
141 bool macHasAccessToWindowsServer()
143 SecuritySessionId mySession;
144 SessionAttributeBits sessionInfo;
145 SessionGetInfo(callerSecuritySession, &mySession, &sessionInfo);
146 return (sessionInfo & sessionHasGraphicAccess);
155 class tst_QWidget : public QObject
161 virtual ~tst_QWidget();
165 void cleanupTestCase();
170 void fontPropagation();
171 void fontPropagation2();
172 void palettePropagation();
173 void palettePropagation2();
174 void enabledPropagation();
175 #ifndef QT_NO_DRAGANDDROP
176 void acceptDropsPropagation();
180 void visible_setWindowOpacity();
184 void mapFromAndTo_data();
186 void focusChainOnHide();
187 void focusChainOnReparent();
196 void showMaximized();
197 void showFullScreen();
198 void showMinimized();
199 void showMinimizedKeepsFocus();
203 void hideWhenFocusWidgetIsChild();
205 void normalGeometry();
209 void windowOpacity();
213 #ifndef QT_MAC_USE_COCOA
216 void testContentsPropagation();
218 void saveRestoreGeometry();
219 void restoreVersion1Geometry_data();
220 void restoreVersion1Geometry();
228 void optimizedResizeMove();
229 void optimizedResize_topLevel();
233 void testDeletionInEventHandlers();
235 void childDeletesItsSibling();
237 void setMinimumSize();
238 void setMaximumSize();
241 void ensureCreated();
242 void winIdChangeEvent();
243 void persistentWinId();
244 void showNativeChild();
245 void qobject_castInDestroyedSlot();
247 void showHideEvent_data();
248 void showHideEvent();
250 void lostUpdatesOnHide();
260 // tests QWidget::setGeometry()
261 void setWindowGeometry_data();
262 void setWindowGeometry();
265 #if !defined(Q_WS_X11) && !defined(Q_OS_IRIX)
266 // tests QWidget::move() and resize()
267 void windowMoveResize_data();
268 void windowMoveResize();
271 void moveChild_data();
273 void showAndMoveChild();
275 #ifndef QT_MAC_USE_COCOA
276 void subtractOpaqueSiblings();
282 void setGeometry_win();
288 void multipleToplevelFocusCheck();
292 void testWindowIconChangeEventPropagation();
294 void minAndMaxSizeWithX11BypassWindowManagerHint();
296 void clean_qt_x11_enforce_cursor();
301 void renderInvisible();
302 void renderWithPainter();
303 void render_task188133();
304 void render_task211796();
305 void render_task217815();
307 void render_windowOpacity();
309 void render_systemClip();
310 void render_systemClip2_data();
311 void render_systemClip2();
312 void render_systemClip3_data();
313 void render_systemClip3();
314 void render_task252837();
315 void render_worldTransform();
317 void setContentsMargins();
320 void moveWindowInShowEvent_data();
321 void moveWindowInShowEvent();
324 void repaintWhenChildDeleted();
325 void hideOpaqueChildWhileHidden();
326 #if !defined(Q_OS_WINCE) && !defined(Q_WS_QWS)
327 void updateWhileMinimized();
329 #if defined(Q_WS_WIN) || defined(Q_WS_X11)
333 void adjustSize_data();
334 void updateGeometry();
335 void updateGeometry_data();
336 void sendUpdateRequestImmediately();
338 void doubleRepaint();
340 void resizeInPaintEvent();
341 void opaqueChildren();
343 void setMaskInResizeEvent();
344 void moveInResizeEvent();
346 #if defined(Q_WS_WIN) || defined(Q_WS_X11)
347 // We don't support immediate repaint right after show on
348 // other platforms. Must be compatible with Qt 4.3.
349 void immediateRepaintAfterShow();
350 void immediateRepaintAfterInvalidateBuffer();
352 void effectiveWinId();
353 void effectiveWinId2();
355 void customDpiProperty();
357 void quitOnCloseAttribute();
360 #if defined (Q_WS_WIN)
362 void paintOnScreenPossible();
364 void reparentStaticWidget();
365 void QTBUG6883_reparentStaticWidget2();
367 void updateOutsideSurfaceClip();
369 void translucentWidget();
371 void setClearAndResizeMask();
373 #if !defined(Q_OS_WINCE_WM)
374 void syntheticEnterLeave();
375 void taskQTBUG_4055_sendSyntheticEnterLeave();
378 void initialPosForDontShowOnScreenWidgets();
380 void paintOutsidePaintEvent();
382 void updateOnDestroyedSignal();
383 void toplevelLineEditFocus();
384 void inputFocus_task257832();
386 void focusWidget_task254563();
387 #ifndef Q_OS_WINCE_WM
388 void rectOutsideCoordinatesLimit_task144779();
390 void setGraphicsEffect();
392 #ifdef QT_BUILD_INTERNAL
393 void destroyBackingStore();
396 void activateWindow();
398 void openModal_taskQTBUG_5804();
400 void focusProxyAndInputMethods();
401 #ifdef QT_BUILD_INTERNAL
402 void scrollWithoutBackingStore();
405 void taskQTBUG_7532_tabOrderWithFocusProxy();
406 void movedAndResizedAttributes();
409 void childAt_unifiedToolBar();
410 void taskQTBUG_11373();
412 void taskQTBUG_17333_ResizeInfiniteRecursion();
414 void nativeChildFocus();
417 bool ensureScreenSize(int width, int height);
421 bool tst_QWidget::ensureScreenSize(int width, int height)
425 available = QDesktopWidget().availableGeometry().size();
426 if (available.width() < width || available.height() < height) {
427 QScreen *screen = QScreen::instance();
430 screen->setMode(width, height, screen->depth());
434 available = QDesktopWidget().availableGeometry().size();
435 return (available.width() >= width && available.height() >= height);
438 // Testing get/set functions
439 void tst_QWidget::getSetCheck()
442 QWidget child1(&obj1);
443 // QStyle * QWidget::style()
444 // void QWidget::setStyle(QStyle *)
445 QWindowsStyle *var1 = new QWindowsStyle;
447 QCOMPARE(static_cast<QStyle *>(var1), obj1.style());
448 obj1.setStyle((QStyle *)0);
449 QVERIFY(var1 != obj1.style());
450 QVERIFY(0 != obj1.style()); // style can never be 0 for a widget
452 // int QWidget::minimumWidth()
453 // void QWidget::setMinimumWidth(int)
454 obj1.setMinimumWidth(0);
455 QCOMPARE(obj1.minimumWidth(), 0);
456 obj1.setMinimumWidth(INT_MIN);
457 QCOMPARE(obj1.minimumWidth(), 0); // A widgets width can never be less than 0
458 obj1.setMinimumWidth(INT_MAX);
459 #ifndef Q_WS_QWS //QWS doesn't allow toplevels to be bigger than the screen
460 QCOMPARE(obj1.minimumWidth(), QWIDGETSIZE_MAX); // The largest minimum size should only be as big as the maximium
463 child1.setMinimumWidth(0);
464 QCOMPARE(child1.minimumWidth(), 0);
465 child1.setMinimumWidth(INT_MIN);
466 QCOMPARE(child1.minimumWidth(), 0); // A widgets width can never be less than 0
467 child1.setMinimumWidth(INT_MAX);
468 QCOMPARE(child1.minimumWidth(), QWIDGETSIZE_MAX); // The largest minimum size should only be as big as the maximium
470 // int QWidget::minimumHeight()
471 // void QWidget::setMinimumHeight(int)
472 obj1.setMinimumHeight(0);
473 QCOMPARE(obj1.minimumHeight(), 0);
474 obj1.setMinimumHeight(INT_MIN);
475 QCOMPARE(obj1.minimumHeight(), 0); // A widgets height can never be less than 0
476 obj1.setMinimumHeight(INT_MAX);
477 #ifndef Q_WS_QWS //QWS doesn't allow toplevels to be bigger than the screen
478 QCOMPARE(obj1.minimumHeight(), QWIDGETSIZE_MAX); // The largest minimum size should only be as big as the maximium
481 child1.setMinimumHeight(0);
482 QCOMPARE(child1.minimumHeight(), 0);
483 child1.setMinimumHeight(INT_MIN);
484 QCOMPARE(child1.minimumHeight(), 0); // A widgets height can never be less than 0
485 child1.setMinimumHeight(INT_MAX);
486 QCOMPARE(child1.minimumHeight(), QWIDGETSIZE_MAX); // The largest minimum size should only be as big as the maximium
488 // int QWidget::maximumWidth()
489 // void QWidget::setMaximumWidth(int)
490 obj1.setMaximumWidth(0);
491 QCOMPARE(obj1.maximumWidth(), 0);
492 obj1.setMaximumWidth(INT_MIN);
493 QCOMPARE(obj1.maximumWidth(), 0); // A widgets width can never be less than 0
494 obj1.setMaximumWidth(INT_MAX);
495 QCOMPARE(obj1.maximumWidth(), QWIDGETSIZE_MAX); // QWIDGETSIZE_MAX is the abs max, not INT_MAX
497 // int QWidget::maximumHeight()
498 // void QWidget::setMaximumHeight(int)
499 obj1.setMaximumHeight(0);
500 QCOMPARE(obj1.maximumHeight(), 0);
501 obj1.setMaximumHeight(INT_MIN);
502 QCOMPARE(obj1.maximumHeight(), 0); // A widgets height can never be less than 0
503 obj1.setMaximumHeight(INT_MAX);
504 QCOMPARE(obj1.maximumHeight(), QWIDGETSIZE_MAX); // QWIDGETSIZE_MAX is the abs max, not INT_MAX
507 obj1.setMinimumWidth(0);
508 obj1.setMinimumHeight(0);
509 obj1.setMaximumWidth(QWIDGETSIZE_MAX);
510 obj1.setMaximumHeight(QWIDGETSIZE_MAX);
512 // const QPalette & QWidget::palette()
513 // void QWidget::setPalette(const QPalette &)
515 obj1.setPalette(var6);
516 QCOMPARE(var6, obj1.palette());
517 obj1.setPalette(QPalette());
518 QCOMPARE(QPalette(), obj1.palette());
520 // const QFont & QWidget::font()
521 // void QWidget::setFont(const QFont &)
524 QCOMPARE(var7, obj1.font());
525 obj1.setFont(QFont());
526 QCOMPARE(QFont(), obj1.font());
528 // qreal QWidget::windowOpacity()
529 // void QWidget::setWindowOpacity(qreal)
530 obj1.setWindowOpacity(0.0);
531 QCOMPARE(0.0, obj1.windowOpacity());
532 obj1.setWindowOpacity(1.1f);
533 QCOMPARE(1.0, obj1.windowOpacity()); // 1.0 is the fullest opacity possible
535 // QWidget * QWidget::focusProxy()
536 // void QWidget::setFocusProxy(QWidget *)
537 QWidget *var9 = new QWidget();
538 obj1.setFocusProxy(var9);
539 QCOMPARE(var9, obj1.focusProxy());
540 obj1.setFocusProxy((QWidget *)0);
541 QCOMPARE((QWidget *)0, obj1.focusProxy());
544 // const QRect & QWidget::geometry()
545 // void QWidget::setGeometry(const QRect &)
546 qApp->processEvents();
547 QRect var10(10, 10, 100, 100);
548 obj1.setGeometry(var10);
549 qApp->processEvents();
550 qDebug() << obj1.geometry();
551 QCOMPARE(var10, obj1.geometry());
552 obj1.setGeometry(QRect(0,0,0,0));
553 qDebug() << obj1.geometry();
554 QCOMPARE(QRect(0,0,0,0), obj1.geometry());
556 // QLayout * QWidget::layout()
557 // void QWidget::setLayout(QLayout *)
558 QBoxLayout *var11 = new QBoxLayout(QBoxLayout::LeftToRight);
559 obj1.setLayout(var11);
560 QCOMPARE(static_cast<QLayout *>(var11), obj1.layout());
561 obj1.setLayout((QLayout *)0);
562 QCOMPARE(static_cast<QLayout *>(var11), obj1.layout()); // You cannot set a 0-pointer layout, that keeps the current
563 delete var11; // This will remove the layout from the widget
564 QCOMPARE((QLayout *)0, obj1.layout());
566 // bool QWidget::acceptDrops()
567 // void QWidget::setAcceptDrops(bool)
568 obj1.setAcceptDrops(false);
569 QCOMPARE(false, obj1.acceptDrops());
570 obj1.setAcceptDrops(true);
571 QCOMPARE(true, obj1.acceptDrops());
573 // bool QWidget::autoFillBackground()
574 // void QWidget::setAutoFillBackground(bool)
575 obj1.setAutoFillBackground(false);
576 QCOMPARE(false, obj1.autoFillBackground());
577 obj1.setAutoFillBackground(true);
578 QCOMPARE(true, obj1.autoFillBackground());
581 #if defined (Q_WS_WIN) && !defined(Q_OS_WINCE)
582 obj1.setWindowFlags(Qt::FramelessWindowHint | Qt::WindowSystemMenuHint);
583 HWND handle = obj1.winId();
584 long flags = GetWindowLong(handle, GWL_STYLE);
585 QVERIFY(flags & WS_POPUP);
589 tst_QWidget::tst_QWidget()
593 font.setPointSize(42);
594 qApp->setFont(font, "QPropagationTestWidget");
597 palette.setColor(QPalette::ToolTipBase, QColor(12, 13, 14));
598 palette.setColor(QPalette::Text, QColor(21, 22, 23));
599 qApp->setPalette(palette, "QPropagationTestWidget");
604 tst_QWidget::~tst_QWidget()
608 class BezierViewer : public QWidget {
610 BezierViewer( QWidget* parent=0, const char* name=0 );
611 void paintEvent( QPaintEvent* );
612 void setPoints( const QPolygonF& poly );
618 void tst_QWidget::initTestCase()
620 #ifdef Q_OS_WINCE //disable magic for WindowsCE
621 qApp->setAutoMaximizeThreshold(-1);
623 // Create the test class
624 testWidget = new BezierViewer( 0, "testObject");
625 testWidget->resize(200,200);
627 QTest::qWaitForWindowShown(testWidget);
631 void tst_QWidget::cleanupTestCase()
637 void tst_QWidget::init()
639 // TODO: Add initialization code here.
640 // This will be executed immediately before each test is run.
641 testWidget->setFont(QFont());
642 testWidget->setPalette(QPalette());
645 void tst_QWidget::cleanup()
651 BezierViewer::BezierViewer( QWidget* parent, const char* name )
656 pal.setColor(backgroundRole(), Qt::white);
661 void BezierViewer::setPoints( const QPolygonF& a )
666 #include "private/qbezier_p.h"
667 void BezierViewer::paintEvent( QPaintEvent* )
669 if ( points.size() != 4 ) {
670 #if defined(QT_CHECK_RANGE)
671 qWarning( "QPolygon::bezier: The array must have 4 control points" );
676 /* Calculate Bezier curve */
677 QPolygonF bezier = QBezier::fromPoints(points.at(0),points.at(1),points.at(2),points.at(3)).toPolygon();
679 QPainter painter( this );
681 /* Calculate scale to fit in window */
682 QRectF br = bezier.boundingRect() | points.boundingRect();
684 int scl = qMax( qMin(pr.width()/br.width(), pr.height()/br.height()), qreal(1.) );
687 /* Scale Bezier curve vertices */
688 for ( QPolygonF::Iterator it = bezier.begin(); it != bezier.end(); ++it ) {
689 it->setX( (it->x()-br.x()) * scl + border );
690 it->setY( (it->y()-br.y()) * scl + border );
694 painter.setPen( Qt::lightGray );
696 for ( i = border; i <= pr.width(); i += scl ) {
697 painter.drawLine( i, 0, i, pr.height() );
699 for ( int j = border; j <= pr.height(); j += scl ) {
700 painter.drawLine( 0, j, pr.width(), j );
703 /* Write number of vertices */
704 painter.setPen( Qt::red );
705 painter.setFont( QFont("Helvetica", 14, QFont::DemiBold, true ) );
707 caption.setNum( bezier.size() );
708 caption += QString::fromLatin1( " vertices" );
709 painter.drawText( 10, pr.height()-10, caption );
711 /* Draw Bezier curve */
712 painter.setPen( Qt::black );
713 painter.drawPolyline( bezier );
715 /* Scale and draw control points */
716 painter.setPen( Qt::darkGreen );
717 for ( QPolygonF::Iterator p1 = points.begin(); p1 != points.end(); ++p1 ) {
718 int x = (p1->x()-br.x()) * scl + border;
719 int y = (p1->y()-br.y()) * scl + border;
720 painter.drawLine( x-4, y-4, x+4, y+4 );
721 painter.drawLine( x+4, y-4, x-4, y+4 );
725 painter.setPen( Qt::red );
726 painter.setBrush( Qt::red );
727 for ( QPolygonF::Iterator p2 = bezier.begin(); p2 != bezier.end(); ++p2 )
728 painter.drawEllipse( p2->x()-1, p2->y()-1, 3, 3 );
731 void tst_QWidget::fontPropagation()
733 QFont font = testWidget->font();
734 QWidget* childWidget = new QWidget( testWidget );
736 QCOMPARE( font, childWidget->font() );
738 font.setBold( true );
739 testWidget->setFont( font );
740 QCOMPARE( font, testWidget->font() );
741 QCOMPARE( font, childWidget->font() );
743 QFont newFont = font;
744 newFont.setItalic( true );
745 childWidget->setFont( newFont );
746 QWidget* grandChildWidget = new QWidget( childWidget );
747 QCOMPARE( font, testWidget->font() );
748 QCOMPARE( newFont, grandChildWidget->font() );
750 font.setUnderline( true );
751 testWidget->setFont( font );
753 // the child and grand child should now have merged bold and
755 newFont.setUnderline( true );
757 QCOMPARE( newFont, childWidget->font() );
758 QCOMPARE( newFont, grandChildWidget->font() );
760 // make sure font propagation continues working after reparenting
761 font = testWidget->font();
762 font.setPointSize(font.pointSize() + 2);
763 testWidget->setFont(font);
765 QWidget *one = new QWidget(testWidget);
766 QWidget *two = new QWidget(one);
767 QWidget *three = new QWidget(two);
768 QWidget *four = new QWidget(two);
770 four->setParent(three);
771 four->move(QPoint(0,0));
773 font.setPointSize(font.pointSize() + 2);
774 testWidget->setFont(font);
776 QCOMPARE(testWidget->font(), one->font());
777 QCOMPARE(one->font(), two->font());
778 QCOMPARE(two->font(), three->font());
779 QCOMPARE(three->font(), four->font());
781 QVERIFY(testWidget->testAttribute(Qt::WA_SetFont));
782 QVERIFY(! one->testAttribute(Qt::WA_SetFont));
783 QVERIFY(! two->testAttribute(Qt::WA_SetFont));
784 QVERIFY(! three->testAttribute(Qt::WA_SetFont));
785 QVERIFY(! four->testAttribute(Qt::WA_SetFont));
787 font.setPointSize(font.pointSize() + 2);
790 QCOMPARE(one->font(), two->font());
791 QCOMPARE(two->font(), three->font());
792 QCOMPARE(three->font(), four->font());
794 QVERIFY(one->testAttribute(Qt::WA_SetFont));
795 QVERIFY(! two->testAttribute(Qt::WA_SetFont));
796 QVERIFY(! three->testAttribute(Qt::WA_SetFont));
797 QVERIFY(! four->testAttribute(Qt::WA_SetFont));
799 font.setPointSize(font.pointSize() + 2);
802 QCOMPARE(two->font(), three->font());
803 QCOMPARE(three->font(), four->font());
805 QVERIFY(two->testAttribute(Qt::WA_SetFont));
806 QVERIFY(! three->testAttribute(Qt::WA_SetFont));
807 QVERIFY(! four->testAttribute(Qt::WA_SetFont));
809 font.setPointSize(font.pointSize() + 2);
810 three->setFont(font);
812 QCOMPARE(three->font(), four->font());
814 QVERIFY(three->testAttribute(Qt::WA_SetFont));
815 QVERIFY(! four->testAttribute(Qt::WA_SetFont));
817 font.setPointSize(font.pointSize() + 2);
820 QVERIFY(four->testAttribute(Qt::WA_SetFont));
823 class QPropagationTestWidget : public QWidget
827 QPropagationTestWidget(QWidget *parent = 0)
832 void tst_QWidget::fontPropagation2()
834 // ! Note, the code below is executed in tst_QWidget's constructor.
836 // font.setBold(true);
837 // font.setPointSize(42);
838 // qApp->setFont(font, "QPropagationTestWidget");
840 QWidget *root = new QWidget;
841 QWidget *child0 = new QWidget(root);
842 QWidget *child1 = new QWidget(child0);
843 QWidget *child2 = new QPropagationTestWidget(child1);
844 QWidget *child3 = new QWidget(child2);
845 QWidget *child4 = new QWidget(child3);
846 QWidget *child5 = new QWidget(child4);
849 // Check that only the application fonts apply.
850 QCOMPARE(root->font(), QApplication::font());
851 QCOMPARE(child0->font(), QApplication::font());
852 QCOMPARE(child1->font(), QApplication::font());
853 QCOMPARE(child2->font().pointSize(), 42);
854 QVERIFY(child2->font().bold());
855 QCOMPARE(child3->font().pointSize(), 42);
856 QVERIFY(child3->font().bold());
857 QCOMPARE(child4->font().pointSize(), 42);
858 QVERIFY(child4->font().bold());
859 QCOMPARE(child5->font().pointSize(), 42);
860 QVERIFY(child5->font().bold());
862 // Set child0's font size to 15, and remove bold on child4.
864 font.setPointSize(15);
865 child0->setFont(font);
867 unboldFont.setBold(false);
868 child4->setFont(unboldFont);
870 // Check that the above settings propagate correctly.
871 QCOMPARE(root->font(), QApplication::font());
872 QCOMPARE(child0->font().pointSize(), 15);
873 QVERIFY(!child0->font().bold());
874 QCOMPARE(child1->font().pointSize(), 15);
875 QVERIFY(!child1->font().bold());
876 QCOMPARE(child2->font().pointSize(), 15);
877 QVERIFY(child2->font().bold());
878 QCOMPARE(child3->font().pointSize(), 15);
879 QVERIFY(child3->font().bold());
880 QCOMPARE(child4->font().pointSize(), 15);
881 QVERIFY(!child4->font().bold());
882 QCOMPARE(child5->font().pointSize(), 15);
883 QVERIFY(!child5->font().bold());
885 // Replace the app font for child2. Italic should propagate
886 // but the size should still be ignored. The previous bold
888 QFont italicSizeFont;
889 italicSizeFont.setItalic(true);
890 italicSizeFont.setPointSize(33);
891 qApp->setFont(italicSizeFont, "QPropagationTestWidget");
893 // Check that this propagates correctly.
894 QCOMPARE(root->font(), QApplication::font());
895 QCOMPARE(child0->font().pointSize(), 15);
896 QVERIFY(!child0->font().bold());
897 QVERIFY(!child0->font().italic());
898 QCOMPARE(child1->font().pointSize(), 15);
899 QVERIFY(!child1->font().bold());
900 QVERIFY(!child1->font().italic());
901 QCOMPARE(child2->font().pointSize(), 15);
902 QVERIFY(!child2->font().bold());
903 QVERIFY(child2->font().italic());
904 QCOMPARE(child3->font().pointSize(), 15);
905 QVERIFY(!child3->font().bold());
906 QVERIFY(child3->font().italic());
907 QCOMPARE(child4->font().pointSize(), 15);
908 QVERIFY(!child4->font().bold());
909 QVERIFY(child4->font().italic());
910 QCOMPARE(child5->font().pointSize(), 15);
911 QVERIFY(!child5->font().bold());
912 QVERIFY(child5->font().italic());
915 void tst_QWidget::palettePropagation()
917 QPalette palette = testWidget->palette();
918 QWidget* childWidget = new QWidget( testWidget );
920 QCOMPARE( palette, childWidget->palette() );
922 palette.setColor( QPalette::Base, Qt::red );
923 testWidget->setPalette( palette );
924 QCOMPARE( palette, testWidget->palette() );
925 QCOMPARE( palette, childWidget->palette() );
927 QPalette newPalette = palette;
928 newPalette.setColor( QPalette::Highlight, Qt::green );
929 childWidget->setPalette( newPalette );
930 QWidget* grandChildWidget = new QWidget( childWidget );
931 QCOMPARE( palette, testWidget->palette() );
932 QCOMPARE( newPalette, grandChildWidget->palette() );
934 palette.setColor( QPalette::Text, Qt::blue );
935 testWidget->setPalette( palette );
937 // the child and grand child should now have merged green
938 // highlight and blue text
939 newPalette.setColor( QPalette::Text, Qt::blue);
941 QCOMPARE( newPalette, childWidget->palette() );
942 QCOMPARE( newPalette, grandChildWidget->palette() );
945 void tst_QWidget::palettePropagation2()
947 // ! Note, the code below is executed in tst_QWidget's constructor.
949 // font.setColor(QPalette::ToolTipBase, QColor(12, 13, 14));
950 // font.setColor(QPalette::Text, QColor(21, 22, 23));
951 // qApp->setPalette(palette, "QPropagationTestWidget");
953 QWidget *root = new QWidget;
954 QWidget *child0 = new QWidget(root);
955 QWidget *child1 = new QWidget(child0);
956 QWidget *child2 = new QPropagationTestWidget(child1);
957 QWidget *child3 = new QWidget(child2);
958 QWidget *child4 = new QWidget(child3);
959 QWidget *child5 = new QWidget(child4);
963 // These colors are unlikely to be imposed on the default palette of
965 QColor sysPalText(21, 22, 23);
966 QColor sysPalToolTipBase(12, 13, 14);
967 QColor overridePalText(42, 43, 44);
968 QColor overridePalToolTipBase(45, 46, 47);
969 QColor sysPalButton(99, 98, 97);
971 // Check that only the application fonts apply.
972 QPalette appPal = QApplication::palette();
973 QCOMPARE(root->palette(), appPal);
974 QCOMPARE(child0->palette(), appPal);
975 QCOMPARE(child1->palette(), appPal);
976 QCOMPARE(child2->palette().color(QPalette::ToolTipBase), sysPalToolTipBase);
977 QCOMPARE(child2->palette().color(QPalette::Text), sysPalText);
978 QCOMPARE(child2->palette().color(QPalette::ToolTipText), appPal.color(QPalette::ToolTipText));
979 QCOMPARE(child3->palette().color(QPalette::ToolTipBase), sysPalToolTipBase);
980 QCOMPARE(child3->palette().color(QPalette::Text), sysPalText);
981 QCOMPARE(child3->palette().color(QPalette::ToolTipText), appPal.color(QPalette::ToolTipText));
982 QCOMPARE(child4->palette().color(QPalette::ToolTipBase), sysPalToolTipBase);
983 QCOMPARE(child4->palette().color(QPalette::Text), sysPalText);
984 QCOMPARE(child4->palette().color(QPalette::ToolTipText), appPal.color(QPalette::ToolTipText));
985 QCOMPARE(child5->palette().color(QPalette::ToolTipBase), sysPalToolTipBase);
986 QCOMPARE(child5->palette().color(QPalette::Text), sysPalText);
987 QCOMPARE(child5->palette().color(QPalette::ToolTipText), appPal.color(QPalette::ToolTipText));
989 // Set child0's Text, and set ToolTipBase on child4.
990 QPalette textPalette;
991 textPalette.setColor(QPalette::Text, overridePalText);
992 child0->setPalette(textPalette);
993 QPalette toolTipPalette;
994 toolTipPalette.setColor(QPalette::ToolTipBase, overridePalToolTipBase);
995 child4->setPalette(toolTipPalette);
997 // Check that the above settings propagate correctly.
998 QCOMPARE(root->palette(), appPal);
999 QCOMPARE(child0->palette().color(QPalette::Text), overridePalText);
1000 QCOMPARE(child0->palette().color(QPalette::ToolTipBase), appPal.color(QPalette::ToolTipBase));
1001 QCOMPARE(child0->palette().color(QPalette::ToolTipText), appPal.color(QPalette::ToolTipText));
1002 QCOMPARE(child1->palette().color(QPalette::Text), overridePalText);
1003 QCOMPARE(child1->palette().color(QPalette::ToolTipBase), appPal.color(QPalette::ToolTipBase));
1004 QCOMPARE(child1->palette().color(QPalette::ToolTipText), appPal.color(QPalette::ToolTipText));
1005 QCOMPARE(child2->palette().color(QPalette::Text), overridePalText);
1006 QCOMPARE(child2->palette().color(QPalette::ToolTipBase), sysPalToolTipBase);
1007 QCOMPARE(child2->palette().color(QPalette::ToolTipText), appPal.color(QPalette::ToolTipText));
1008 QCOMPARE(child3->palette().color(QPalette::Text), overridePalText);
1009 QCOMPARE(child3->palette().color(QPalette::ToolTipBase), sysPalToolTipBase);
1010 QCOMPARE(child3->palette().color(QPalette::ToolTipText), appPal.color(QPalette::ToolTipText));
1011 QCOMPARE(child4->palette().color(QPalette::Text), overridePalText);
1012 QCOMPARE(child4->palette().color(QPalette::ToolTipBase), overridePalToolTipBase);
1013 QCOMPARE(child4->palette().color(QPalette::ToolTipText), appPal.color(QPalette::ToolTipText));
1014 QCOMPARE(child5->palette().color(QPalette::Text), overridePalText);
1015 QCOMPARE(child5->palette().color(QPalette::ToolTipBase), overridePalToolTipBase);
1016 QCOMPARE(child5->palette().color(QPalette::ToolTipText), appPal.color(QPalette::ToolTipText));
1018 // Replace the app palette for child2. Button should propagate but Text
1019 // should still be ignored. The previous ToolTipBase setting is gone.
1020 QPalette buttonPalette;
1021 buttonPalette.setColor(QPalette::ToolTipText, sysPalButton);
1022 qApp->setPalette(buttonPalette, "QPropagationTestWidget");
1024 // Check that the above settings propagate correctly.
1025 QCOMPARE(root->palette(), appPal);
1026 QCOMPARE(child0->palette().color(QPalette::Text), overridePalText);
1027 QCOMPARE(child0->palette().color(QPalette::ToolTipBase), appPal.color(QPalette::ToolTipBase));
1028 QCOMPARE(child0->palette().color(QPalette::ToolTipText), appPal.color(QPalette::ToolTipText));
1029 QCOMPARE(child1->palette().color(QPalette::Text), overridePalText);
1030 QCOMPARE(child1->palette().color(QPalette::ToolTipBase), appPal.color(QPalette::ToolTipBase));
1031 QCOMPARE(child1->palette().color(QPalette::ToolTipText), appPal.color(QPalette::ToolTipText));
1032 QCOMPARE(child2->palette().color(QPalette::Text), overridePalText);
1033 QCOMPARE(child2->palette().color(QPalette::ToolTipBase), appPal.color(QPalette::ToolTipBase));
1034 QCOMPARE(child2->palette().color(QPalette::ToolTipText), sysPalButton);
1035 QCOMPARE(child3->palette().color(QPalette::Text), overridePalText);
1036 QCOMPARE(child3->palette().color(QPalette::ToolTipBase), appPal.color(QPalette::ToolTipBase));
1037 QCOMPARE(child3->palette().color(QPalette::ToolTipText), sysPalButton);
1038 QCOMPARE(child4->palette().color(QPalette::Text), overridePalText);
1039 QCOMPARE(child4->palette().color(QPalette::ToolTipBase), overridePalToolTipBase);
1040 QCOMPARE(child4->palette().color(QPalette::ToolTipText), sysPalButton);
1041 QCOMPARE(child5->palette().color(QPalette::Text), overridePalText);
1042 QCOMPARE(child5->palette().color(QPalette::ToolTipBase), overridePalToolTipBase);
1043 QCOMPARE(child5->palette().color(QPalette::ToolTipText), sysPalButton);
1046 void tst_QWidget::enabledPropagation()
1048 QWidget* childWidget = new QWidget( testWidget );
1049 childWidget->show();
1050 QVERIFY( testWidget->isEnabled() );
1051 QVERIFY( childWidget->isEnabled() );
1053 testWidget->setEnabled( false );
1054 QVERIFY( !testWidget->isEnabled() );
1055 QVERIFY( !childWidget->isEnabled() );
1057 testWidget->setDisabled( false );
1058 QVERIFY( testWidget->isEnabled() );
1059 QVERIFY( childWidget->isEnabled() );
1061 QWidget* grandChildWidget = new QWidget( childWidget );
1062 QVERIFY( grandChildWidget->isEnabled() );
1064 testWidget->setDisabled( true );
1065 QVERIFY( !testWidget->isEnabled() );
1066 QVERIFY( !childWidget->isEnabled() );
1067 QVERIFY( !grandChildWidget->isEnabled() );
1069 grandChildWidget->setEnabled( false );
1070 testWidget->setEnabled( true );
1071 QVERIFY( testWidget->isEnabled() );
1072 QVERIFY( childWidget->isEnabled() );
1073 QVERIFY( !grandChildWidget->isEnabled() );
1075 grandChildWidget->setEnabled( true );
1076 testWidget->setEnabled( false );
1077 childWidget->setDisabled( true );
1078 testWidget->setEnabled( true );
1079 QVERIFY( testWidget->isEnabled() );
1080 QVERIFY( !childWidget->isEnabled() );
1081 QVERIFY( !grandChildWidget->isEnabled() );
1084 // Drag'n drop disabled in this build.
1085 #ifndef QT_NO_DRAGANDDROP
1086 void tst_QWidget::acceptDropsPropagation()
1088 QWidget *childWidget = new QWidget(testWidget);
1089 childWidget->show();
1090 QVERIFY(!testWidget->acceptDrops());
1091 QVERIFY(!childWidget->acceptDrops());
1093 testWidget->setAcceptDrops(true);
1094 QVERIFY(testWidget->acceptDrops());
1095 QVERIFY(!childWidget->acceptDrops());
1096 QVERIFY(childWidget->testAttribute(Qt::WA_DropSiteRegistered));
1098 testWidget->setAcceptDrops(false);
1099 QVERIFY(!testWidget->acceptDrops());
1100 QVERIFY(!childWidget->acceptDrops());
1101 QVERIFY(!childWidget->testAttribute(Qt::WA_DropSiteRegistered));
1103 QWidget *grandChildWidget = new QWidget(childWidget);
1104 QVERIFY(!grandChildWidget->acceptDrops());
1105 QVERIFY(!grandChildWidget->testAttribute(Qt::WA_DropSiteRegistered));
1107 testWidget->setAcceptDrops(true);
1108 QVERIFY(testWidget->acceptDrops());
1109 QVERIFY(!childWidget->acceptDrops());
1110 QVERIFY(childWidget->testAttribute(Qt::WA_DropSiteRegistered));
1111 QVERIFY(!grandChildWidget->acceptDrops());
1112 QVERIFY(grandChildWidget->testAttribute(Qt::WA_DropSiteRegistered));
1114 grandChildWidget->setAcceptDrops(true);
1115 testWidget->setAcceptDrops(false);
1116 QVERIFY(!testWidget->acceptDrops());
1117 QVERIFY(!childWidget->acceptDrops());
1118 QVERIFY(grandChildWidget->acceptDrops());
1119 QVERIFY(grandChildWidget->testAttribute(Qt::WA_DropSiteRegistered));
1121 grandChildWidget->setAcceptDrops(false);
1122 QVERIFY(!grandChildWidget->testAttribute(Qt::WA_DropSiteRegistered));
1123 testWidget->setAcceptDrops(true);
1124 childWidget->setAcceptDrops(true);
1125 testWidget->setAcceptDrops(false);
1126 QVERIFY(!testWidget->acceptDrops());
1127 QVERIFY(childWidget->acceptDrops());
1128 QVERIFY(!grandChildWidget->acceptDrops());
1129 QVERIFY(grandChildWidget->testAttribute(Qt::WA_DropSiteRegistered));
1133 void tst_QWidget::isEnabledTo()
1135 QWidget* childWidget = new QWidget( testWidget );
1136 QWidget* grandChildWidget = new QWidget( childWidget );
1138 QVERIFY( childWidget->isEnabledTo( testWidget ) );
1139 QVERIFY( grandChildWidget->isEnabledTo( testWidget ) );
1141 childWidget->setEnabled( false );
1142 QVERIFY( !childWidget->isEnabledTo( testWidget ) );
1143 QVERIFY( grandChildWidget->isEnabledTo( childWidget ) );
1144 QVERIFY( !grandChildWidget->isEnabledTo( testWidget ) );
1147 void tst_QWidget::visible()
1149 // Ensure that the testWidget is hidden for this test at the
1153 QVERIFY( !testWidget->isVisible() );
1154 QWidget* childWidget = new QWidget( testWidget );
1155 QVERIFY( !childWidget->isVisible() );
1158 QVERIFY( testWidget->isVisible() );
1159 QVERIFY( childWidget->isVisible() );
1161 QWidget* grandChildWidget = new QWidget( childWidget );
1162 QVERIFY( !grandChildWidget->isVisible() );
1163 grandChildWidget->show();
1164 QVERIFY( grandChildWidget->isVisible() );
1166 grandChildWidget->hide();
1169 QVERIFY( !grandChildWidget->isVisible() );
1170 QVERIFY( testWidget->isVisible() );
1171 QVERIFY( childWidget->isVisible() );
1173 grandChildWidget->show();
1174 childWidget->hide();
1177 QVERIFY( testWidget->isVisible() );
1178 QVERIFY( !childWidget->isVisible() );
1179 QVERIFY( !grandChildWidget->isVisible() );
1181 grandChildWidget->show();
1182 QVERIFY( !grandChildWidget->isVisible() );
1185 void tst_QWidget::setLocale()
1188 QCOMPARE(w.locale(), QLocale());
1190 w.setLocale(QLocale::Italian);
1191 QCOMPARE(w.locale(), QLocale(QLocale::Italian));
1194 QCOMPARE(child1.locale(), QLocale(QLocale::Italian));
1197 QCOMPARE(w.locale(), QLocale());
1198 QCOMPARE(child1.locale(), QLocale());
1200 w.setLocale(QLocale::French);
1201 QCOMPARE(w.locale(), QLocale(QLocale::French));
1202 QCOMPARE(child1.locale(), QLocale(QLocale::French));
1204 child1.setLocale(QLocale::Italian);
1205 QCOMPARE(w.locale(), QLocale(QLocale::French));
1206 QCOMPARE(child1.locale(), QLocale(QLocale::Italian));
1208 child1.unsetLocale();
1209 QCOMPARE(w.locale(), QLocale(QLocale::French));
1210 QCOMPARE(child1.locale(), QLocale(QLocale::French));
1213 QCOMPARE(child2.locale(), QLocale());
1214 child2.setParent(&w);
1215 QCOMPARE(child2.locale(), QLocale(QLocale::French));
1218 void tst_QWidget::visible_setWindowOpacity()
1221 QVERIFY( !testWidget->isVisible() );
1222 testWidget->setWindowOpacity(0.5);
1224 QVERIFY(!::IsWindowVisible(winHandleOf(testWidget)));
1226 testWidget->setWindowOpacity(1.0);
1229 void tst_QWidget::isVisibleTo()
1231 // Ensure that the testWidget is hidden for this test at the
1235 QWidget* childWidget = new QWidget( testWidget );
1236 QVERIFY( childWidget->isVisibleTo( testWidget ) );
1237 childWidget->hide();
1238 QVERIFY( !childWidget->isVisibleTo( testWidget ) );
1240 QWidget* grandChildWidget = new QWidget( childWidget );
1241 QVERIFY( !grandChildWidget->isVisibleTo( testWidget ) );
1242 QVERIFY( grandChildWidget->isVisibleTo( childWidget ) );
1245 childWidget->show();
1247 QVERIFY( childWidget->isVisibleTo( testWidget ) );
1248 grandChildWidget->hide();
1249 QVERIFY( !grandChildWidget->isVisibleTo( childWidget ) );
1250 QVERIFY( !grandChildWidget->isVisibleTo( testWidget ) );
1254 void tst_QWidget::isHidden()
1256 // Ensure that the testWidget is hidden for this test at the
1260 QVERIFY( testWidget->isHidden() );
1261 QWidget* childWidget = new QWidget( testWidget );
1262 QVERIFY( !childWidget->isHidden() );
1265 QVERIFY( !testWidget->isHidden() );
1266 QVERIFY( !childWidget->isHidden() );
1268 QWidget* grandChildWidget = new QWidget( childWidget );
1269 QVERIFY( grandChildWidget->isHidden() );
1270 grandChildWidget->show();
1271 QVERIFY( !grandChildWidget->isHidden() );
1273 grandChildWidget->hide();
1276 QVERIFY( grandChildWidget->isHidden() );
1277 QVERIFY( !testWidget->isHidden() );
1278 QVERIFY( !childWidget->isHidden() );
1280 grandChildWidget->show();
1281 childWidget->hide();
1284 QVERIFY( !testWidget->isHidden() );
1285 QVERIFY( childWidget->isHidden() );
1286 QVERIFY( !grandChildWidget->isHidden() );
1288 grandChildWidget->show();
1289 QVERIFY( !grandChildWidget->isHidden() );
1292 void tst_QWidget::fonts()
1294 // Tests setFont(), ownFont() and unsetFont()
1295 QWidget* cleanTestWidget = new QWidget( testWidget );
1296 QFont originalFont = cleanTestWidget->font();
1298 QVERIFY( !cleanTestWidget->testAttribute(Qt::WA_SetFont) );
1299 cleanTestWidget->setFont(QFont());
1300 QVERIFY( !cleanTestWidget->testAttribute(Qt::WA_SetFont) );
1302 QFont newFont( "times", 18 );
1303 cleanTestWidget->setFont( newFont );
1304 newFont = newFont.resolve( testWidget->font() );
1306 QVERIFY( cleanTestWidget->testAttribute(Qt::WA_SetFont) );
1307 QVERIFY( cleanTestWidget->font() == newFont );
1309 cleanTestWidget->setFont(QFont());
1310 QVERIFY( !cleanTestWidget->testAttribute(Qt::WA_SetFont) );
1311 QVERIFY( cleanTestWidget->font() == originalFont );
1314 void tst_QWidget::mapFromAndTo_data()
1316 QTest::addColumn<bool>("windowHidden");
1317 QTest::addColumn<bool>("subWindow1Hidden");
1318 QTest::addColumn<bool>("subWindow2Hidden");
1319 QTest::addColumn<bool>("subSubWindowHidden");
1320 QTest::addColumn<bool>("windowMinimized");
1321 QTest::addColumn<bool>("subWindow1Minimized");
1323 QTest::newRow("window 1 sub1 1 sub2 1 subsub 1") << false << false << false << false << false << false;
1324 QTest::newRow("window 0 sub1 1 sub2 1 subsub 1") << true << false << false << false << false << false;
1325 QTest::newRow("window 1 sub1 0 sub2 1 subsub 1") << false << true << false << false << false << false;
1326 QTest::newRow("window 0 sub1 0 sub2 1 subsub 1") << true << true << false << false << false << false;
1327 QTest::newRow("window 1 sub1 1 sub2 0 subsub 1") << false << false << true << false << false << false;
1328 QTest::newRow("window 0 sub1 1 sub2 0 subsub 1") << true << false << true << false << false << false;
1329 QTest::newRow("window 1 sub1 0 sub2 0 subsub 1") << false << true << true << false << false << false;
1330 QTest::newRow("window 0 sub1 0 sub2 0 subsub 1") << true << true << true << false << false << false;
1331 QTest::newRow("window 1 sub1 1 sub2 1 subsub 0") << false << false << false << true << false << false;
1332 QTest::newRow("window 0 sub1 1 sub2 1 subsub 0") << true << false << false << true << false << false;
1333 QTest::newRow("window 1 sub1 0 sub2 1 subsub 0") << false << true << false << true << false << false;
1334 QTest::newRow("window 0 sub1 0 sub2 1 subsub 0") << true << true << false << true << false << false;
1335 QTest::newRow("window 1 sub1 1 sub2 0 subsub 0") << false << false << true << true << false << false;
1336 QTest::newRow("window 0 sub1 1 sub2 0 subsub 0") << true << false << true << true << false << false;
1337 QTest::newRow("window 1 sub1 0 sub2 0 subsub 0") << false << true << true << true << false << false;
1338 QTest::newRow("window 0 sub1 0 sub2 0 subsub 0") << true << true << true << true << false << false;
1339 QTest::newRow("window 1 sub1 1 sub2 1 subsub 1 windowMinimized") << false << false << false << false << true << false;
1340 QTest::newRow("window 0 sub1 1 sub2 1 subsub 1 windowMinimized") << true << false << false << false << true << false;
1341 QTest::newRow("window 1 sub1 0 sub2 1 subsub 1 windowMinimized") << false << true << false << false << true << false;
1342 QTest::newRow("window 0 sub1 0 sub2 1 subsub 1 windowMinimized") << true << true << false << false << true << false;
1343 QTest::newRow("window 1 sub1 1 sub2 0 subsub 1 windowMinimized") << false << false << true << false << true << false;
1344 QTest::newRow("window 0 sub1 1 sub2 0 subsub 1 windowMinimized") << true << false << true << false << true << false;
1345 QTest::newRow("window 1 sub1 0 sub2 0 subsub 1 windowMinimized") << false << true << true << false << true << false;
1346 QTest::newRow("window 0 sub1 0 sub2 0 subsub 1 windowMinimized") << true << true << true << false << true << false;
1347 QTest::newRow("window 1 sub1 1 sub2 1 subsub 0 windowMinimized") << false << false << false << true << true << false;
1348 QTest::newRow("window 0 sub1 1 sub2 1 subsub 0 windowMinimized") << true << false << false << true << true << false;
1349 QTest::newRow("window 1 sub1 0 sub2 1 subsub 0 windowMinimized") << false << true << false << true << true << false;
1350 QTest::newRow("window 0 sub1 0 sub2 1 subsub 0 windowMinimized") << true << true << false << true << true << false;
1351 QTest::newRow("window 1 sub1 1 sub2 0 subsub 0 windowMinimized") << false << false << true << true << true << false;
1352 QTest::newRow("window 0 sub1 1 sub2 0 subsub 0 windowMinimized") << true << false << true << true << true << false;
1353 QTest::newRow("window 1 sub1 0 sub2 0 subsub 0 windowMinimized") << false << true << true << true << true << false;
1354 QTest::newRow("window 0 sub1 0 sub2 0 subsub 0 windowMinimized") << true << true << true << true << true << false;
1355 QTest::newRow("window 1 sub1 1 sub2 1 subsub 1 subWindow1Minimized") << false << false << false << false << false << true;
1356 QTest::newRow("window 0 sub1 1 sub2 1 subsub 1 subWindow1Minimized") << true << false << false << false << false << true;
1357 QTest::newRow("window 1 sub1 0 sub2 1 subsub 1 subWindow1Minimized") << false << true << false << false << false << true;
1358 QTest::newRow("window 0 sub1 0 sub2 1 subsub 1 subWindow1Minimized") << true << true << false << false << false << true;
1359 QTest::newRow("window 1 sub1 1 sub2 0 subsub 1 subWindow1Minimized") << false << false << true << false << false << true;
1360 QTest::newRow("window 0 sub1 1 sub2 0 subsub 1 subWindow1Minimized") << true << false << true << false << false << true;
1361 QTest::newRow("window 1 sub1 0 sub2 0 subsub 1 subWindow1Minimized") << false << true << true << false << false << true;
1362 QTest::newRow("window 0 sub1 0 sub2 0 subsub 1 subWindow1Minimized") << true << true << true << false << false << true;
1363 QTest::newRow("window 1 sub1 1 sub2 1 subsub 0 subWindow1Minimized") << false << false << false << true << false << true;
1364 QTest::newRow("window 0 sub1 1 sub2 1 subsub 0 subWindow1Minimized") << true << false << false << true << false << true;
1365 QTest::newRow("window 1 sub1 0 sub2 1 subsub 0 subWindow1Minimized") << false << true << false << true << false << true;
1366 QTest::newRow("window 0 sub1 0 sub2 1 subsub 0 subWindow1Minimized") << true << true << false << true << false << true;
1367 QTest::newRow("window 1 sub1 1 sub2 0 subsub 0 subWindow1Minimized") << false << false << true << true << false << true;
1368 QTest::newRow("window 0 sub1 1 sub2 0 subsub 0 subWindow1Minimized") << true << false << true << true << false << true;
1369 QTest::newRow("window 1 sub1 0 sub2 0 subsub 0 subWindow1Minimized") << false << true << true << true << false << true;
1370 QTest::newRow("window 0 sub1 0 sub2 0 subsub 0 subWindow1Minimized") << true << true << true << true << false << true;
1375 void tst_QWidget::mapFromAndTo()
1377 QFETCH(bool, windowHidden);
1378 QFETCH(bool, subWindow1Hidden);
1379 QFETCH(bool, subWindow2Hidden);
1380 QFETCH(bool, subSubWindowHidden);
1381 QFETCH(bool, windowMinimized);
1382 QFETCH(bool, subWindow1Minimized);
1384 // create a toplevel and two overlapping siblings
1386 window.setWindowFlags(window.windowFlags() | Qt::X11BypassWindowManagerHint);
1387 QWidget *subWindow1 = new QWidget(&window);
1388 QWidget *subWindow2 = new QWidget(&window);
1389 QWidget *subSubWindow = new QWidget(subWindow1);
1391 // set their geometries
1392 window.setGeometry(100, 100, 100, 100);
1393 subWindow1->setGeometry(50, 50, 100, 100);
1394 subWindow2->setGeometry(75, 75, 100, 100);
1395 subSubWindow->setGeometry(10, 10, 10, 10);
1397 #if !defined (Q_OS_WINCE) //still no proper minimizing
1399 if (windowMinimized) {
1400 if (!windowHidden) {
1401 window.showMinimized();
1402 QVERIFY(window.isMinimized());
1405 window.setVisible(!windowHidden);
1407 if (subWindow1Minimized) {
1409 subWindow1->showMinimized();
1410 QVERIFY(subWindow1->isMinimized());
1412 subWindow1->setVisible(!subWindow1Hidden);
1415 Q_UNUSED(windowHidden);
1416 Q_UNUSED(subWindow1Hidden);
1417 Q_UNUSED(windowMinimized);
1418 Q_UNUSED(subWindow1Minimized);
1421 subWindow2->setVisible(!subWindow2Hidden);
1422 subSubWindow->setVisible(!subSubWindowHidden);
1425 QCOMPARE(window.mapToGlobal(QPoint(0, 0)), QPoint(100, 100));
1426 QCOMPARE(window.mapToGlobal(QPoint(10, 0)), QPoint(110, 100));
1427 QCOMPARE(window.mapToGlobal(QPoint(0, 10)), QPoint(100, 110));
1428 QCOMPARE(window.mapToGlobal(QPoint(-10, 0)), QPoint(90, 100));
1429 QCOMPARE(window.mapToGlobal(QPoint(0, -10)), QPoint(100, 90));
1430 QCOMPARE(window.mapToGlobal(QPoint(100, 100)), QPoint(200, 200));
1431 QCOMPARE(window.mapToGlobal(QPoint(110, 100)), QPoint(210, 200));
1432 QCOMPARE(window.mapToGlobal(QPoint(100, 110)), QPoint(200, 210));
1433 QCOMPARE(window.mapFromGlobal(QPoint(100, 100)), QPoint(0, 0));
1434 QCOMPARE(window.mapFromGlobal(QPoint(110, 100)), QPoint(10, 0));
1435 QCOMPARE(window.mapFromGlobal(QPoint(100, 110)), QPoint(0, 10));
1436 QCOMPARE(window.mapFromGlobal(QPoint(90, 100)), QPoint(-10, 0));
1437 QCOMPARE(window.mapFromGlobal(QPoint(100, 90)), QPoint(0, -10));
1438 QCOMPARE(window.mapFromGlobal(QPoint(200, 200)), QPoint(100, 100));
1439 QCOMPARE(window.mapFromGlobal(QPoint(210, 200)), QPoint(110, 100));
1440 QCOMPARE(window.mapFromGlobal(QPoint(200, 210)), QPoint(100, 110));
1441 QCOMPARE(window.mapToParent(QPoint(0, 0)), QPoint(100, 100));
1442 QCOMPARE(window.mapToParent(QPoint(10, 0)), QPoint(110, 100));
1443 QCOMPARE(window.mapToParent(QPoint(0, 10)), QPoint(100, 110));
1444 QCOMPARE(window.mapToParent(QPoint(-10, 0)), QPoint(90, 100));
1445 QCOMPARE(window.mapToParent(QPoint(0, -10)), QPoint(100, 90));
1446 QCOMPARE(window.mapToParent(QPoint(100, 100)), QPoint(200, 200));
1447 QCOMPARE(window.mapToParent(QPoint(110, 100)), QPoint(210, 200));
1448 QCOMPARE(window.mapToParent(QPoint(100, 110)), QPoint(200, 210));
1449 QCOMPARE(window.mapFromParent(QPoint(100, 100)), QPoint(0, 0));
1450 QCOMPARE(window.mapFromParent(QPoint(110, 100)), QPoint(10, 0));
1451 QCOMPARE(window.mapFromParent(QPoint(100, 110)), QPoint(0, 10));
1452 QCOMPARE(window.mapFromParent(QPoint(90, 100)), QPoint(-10, 0));
1453 QCOMPARE(window.mapFromParent(QPoint(100, 90)), QPoint(0, -10));
1454 QCOMPARE(window.mapFromParent(QPoint(200, 200)), QPoint(100, 100));
1455 QCOMPARE(window.mapFromParent(QPoint(210, 200)), QPoint(110, 100));
1456 QCOMPARE(window.mapFromParent(QPoint(200, 210)), QPoint(100, 110));
1459 QCOMPARE(subWindow1->mapToGlobal(QPoint(0, 0)), QPoint(150, 150));
1460 QCOMPARE(subWindow1->mapToGlobal(QPoint(10, 0)), QPoint(160, 150));
1461 QCOMPARE(subWindow1->mapToGlobal(QPoint(0, 10)), QPoint(150, 160));
1462 QCOMPARE(subWindow1->mapToGlobal(QPoint(-10, 0)), QPoint(140, 150));
1463 QCOMPARE(subWindow1->mapToGlobal(QPoint(0, -10)), QPoint(150, 140));
1464 QCOMPARE(subWindow1->mapToGlobal(QPoint(100, 100)), QPoint(250, 250));
1465 QCOMPARE(subWindow1->mapToGlobal(QPoint(110, 100)), QPoint(260, 250));
1466 QCOMPARE(subWindow1->mapToGlobal(QPoint(100, 110)), QPoint(250, 260));
1467 QCOMPARE(subWindow1->mapFromGlobal(QPoint(150, 150)), QPoint(0, 0));
1468 QCOMPARE(subWindow1->mapFromGlobal(QPoint(160, 150)), QPoint(10, 0));
1469 QCOMPARE(subWindow1->mapFromGlobal(QPoint(150, 160)), QPoint(0, 10));
1470 QCOMPARE(subWindow1->mapFromGlobal(QPoint(140, 150)), QPoint(-10, 0));
1471 QCOMPARE(subWindow1->mapFromGlobal(QPoint(150, 140)), QPoint(0, -10));
1472 QCOMPARE(subWindow1->mapFromGlobal(QPoint(250, 250)), QPoint(100, 100));
1473 QCOMPARE(subWindow1->mapFromGlobal(QPoint(260, 250)), QPoint(110, 100));
1474 QCOMPARE(subWindow1->mapFromGlobal(QPoint(250, 260)), QPoint(100, 110));
1475 QCOMPARE(subWindow1->mapToParent(QPoint(0, 0)), QPoint(50, 50));
1476 QCOMPARE(subWindow1->mapToParent(QPoint(10, 0)), QPoint(60, 50));
1477 QCOMPARE(subWindow1->mapToParent(QPoint(0, 10)), QPoint(50, 60));
1478 QCOMPARE(subWindow1->mapToParent(QPoint(-10, 0)), QPoint(40, 50));
1479 QCOMPARE(subWindow1->mapToParent(QPoint(0, -10)), QPoint(50, 40));
1480 QCOMPARE(subWindow1->mapToParent(QPoint(100, 100)), QPoint(150, 150));
1481 QCOMPARE(subWindow1->mapToParent(QPoint(110, 100)), QPoint(160, 150));
1482 QCOMPARE(subWindow1->mapToParent(QPoint(100, 110)), QPoint(150, 160));
1483 QCOMPARE(subWindow1->mapFromParent(QPoint(50, 50)), QPoint(0, 0));
1484 QCOMPARE(subWindow1->mapFromParent(QPoint(60, 50)), QPoint(10, 0));
1485 QCOMPARE(subWindow1->mapFromParent(QPoint(50, 60)), QPoint(0, 10));
1486 QCOMPARE(subWindow1->mapFromParent(QPoint(40, 50)), QPoint(-10, 0));
1487 QCOMPARE(subWindow1->mapFromParent(QPoint(50, 40)), QPoint(0, -10));
1488 QCOMPARE(subWindow1->mapFromParent(QPoint(150, 150)), QPoint(100, 100));
1489 QCOMPARE(subWindow1->mapFromParent(QPoint(160, 150)), QPoint(110, 100));
1490 QCOMPARE(subWindow1->mapFromParent(QPoint(150, 160)), QPoint(100, 110));
1493 QCOMPARE(subSubWindow->mapToGlobal(QPoint(0, 0)), QPoint(160, 160));
1494 QCOMPARE(subSubWindow->mapToGlobal(QPoint(10, 0)), QPoint(170, 160));
1495 QCOMPARE(subSubWindow->mapToGlobal(QPoint(0, 10)), QPoint(160, 170));
1496 QCOMPARE(subSubWindow->mapToGlobal(QPoint(-10, 0)), QPoint(150, 160));
1497 QCOMPARE(subSubWindow->mapToGlobal(QPoint(0, -10)), QPoint(160, 150));
1498 QCOMPARE(subSubWindow->mapToGlobal(QPoint(100, 100)), QPoint(260, 260));
1499 QCOMPARE(subSubWindow->mapToGlobal(QPoint(110, 100)), QPoint(270, 260));
1500 QCOMPARE(subSubWindow->mapToGlobal(QPoint(100, 110)), QPoint(260, 270));
1501 QCOMPARE(subSubWindow->mapFromGlobal(QPoint(160, 160)), QPoint(0, 0));
1502 QCOMPARE(subSubWindow->mapFromGlobal(QPoint(170, 160)), QPoint(10, 0));
1503 QCOMPARE(subSubWindow->mapFromGlobal(QPoint(160, 170)), QPoint(0, 10));
1504 QCOMPARE(subSubWindow->mapFromGlobal(QPoint(150, 160)), QPoint(-10, 0));
1505 QCOMPARE(subSubWindow->mapFromGlobal(QPoint(160, 150)), QPoint(0, -10));
1506 QCOMPARE(subSubWindow->mapFromGlobal(QPoint(260, 260)), QPoint(100, 100));
1507 QCOMPARE(subSubWindow->mapFromGlobal(QPoint(270, 260)), QPoint(110, 100));
1508 QCOMPARE(subSubWindow->mapFromGlobal(QPoint(260, 270)), QPoint(100, 110));
1509 QCOMPARE(subSubWindow->mapToParent(QPoint(0, 0)), QPoint(10, 10));
1510 QCOMPARE(subSubWindow->mapToParent(QPoint(10, 0)), QPoint(20, 10));
1511 QCOMPARE(subSubWindow->mapToParent(QPoint(0, 10)), QPoint(10, 20));
1512 QCOMPARE(subSubWindow->mapToParent(QPoint(-10, 0)), QPoint(0, 10));
1513 QCOMPARE(subSubWindow->mapToParent(QPoint(0, -10)), QPoint(10, 0));
1514 QCOMPARE(subSubWindow->mapToParent(QPoint(100, 100)), QPoint(110, 110));
1515 QCOMPARE(subSubWindow->mapToParent(QPoint(110, 100)), QPoint(120, 110));
1516 QCOMPARE(subSubWindow->mapToParent(QPoint(100, 110)), QPoint(110, 120));
1517 QCOMPARE(subSubWindow->mapFromParent(QPoint(10, 10)), QPoint(0, 0));
1518 QCOMPARE(subSubWindow->mapFromParent(QPoint(20, 10)), QPoint(10, 0));
1519 QCOMPARE(subSubWindow->mapFromParent(QPoint(10, 20)), QPoint(0, 10));
1520 QCOMPARE(subSubWindow->mapFromParent(QPoint(0, 10)), QPoint(-10, 0));
1521 QCOMPARE(subSubWindow->mapFromParent(QPoint(10, 0)), QPoint(0, -10));
1522 QCOMPARE(subSubWindow->mapFromParent(QPoint(110, 110)), QPoint(100, 100));
1523 QCOMPARE(subSubWindow->mapFromParent(QPoint(120, 110)), QPoint(110, 100));
1524 QCOMPARE(subSubWindow->mapFromParent(QPoint(110, 120)), QPoint(100, 110));
1527 void tst_QWidget::focusChainOnReparent()
1530 QWidget *child1 = new QWidget(&window);
1531 QWidget *child2 = new QWidget(&window);
1532 QWidget *child3 = new QWidget(&window);
1533 QWidget *child21 = new QWidget(child2);
1534 QWidget *child22 = new QWidget(child2);
1535 QWidget *child4 = new QWidget(&window);
1537 QWidget *expectedOriginalChain[8] = {&window, child1, child2, child3, child21, child22, child4, &window};
1538 QWidget *w = &window;
1539 for (int i = 0; i <8; ++i) {
1540 QCOMPARE(w, expectedOriginalChain[i]);
1541 w = w->nextInFocusChain();
1543 for (int i = 7; i >= 0; --i) {
1544 w = w->previousInFocusChain();
1545 QCOMPARE(w, expectedOriginalChain[i]);
1549 child2->setParent(&window2);
1551 QWidget *expectedNewChain[5] = {&window2, child2, child21, child22, &window2};
1553 for (int i = 0; i <5; ++i) {
1554 QCOMPARE(w, expectedNewChain[i]);
1555 w = w->nextInFocusChain();
1557 for (int i = 4; i >= 0; --i) {
1558 w = w->previousInFocusChain();
1559 QCOMPARE(w, expectedNewChain[i]);
1562 QWidget *expectedOldChain[5] = {&window, child1, child3, child4, &window};
1564 for (int i = 0; i <5; ++i) {
1565 QCOMPARE(w, expectedOldChain[i]);
1566 w = w->nextInFocusChain();
1568 for (int i = 4; i >= 0; --i) {
1569 w = w->previousInFocusChain();
1570 QCOMPARE(w, expectedOldChain[i]);
1575 void tst_QWidget::focusChainOnHide()
1577 testWidget->hide(); // We do not want to get disturbed by other widgets
1578 // focus should move to the next widget in the focus chain when we hide it.
1579 QWidget *parent = new QWidget();
1580 parent->setObjectName(QLatin1String("Parent"));
1581 parent->setFocusPolicy(Qt::StrongFocus);
1582 QWidget *child = new QWidget(parent);
1583 child->setObjectName(QLatin1String("child"));
1584 child->setFocusPolicy(Qt::StrongFocus);
1585 QWidget::setTabOrder(child, parent);
1588 qApp->setActiveWindow(parent->window());
1589 child->activateWindow();
1591 qApp->processEvents();
1593 QTRY_COMPARE(child->hasFocus(), true);
1595 qApp->processEvents();
1597 QTRY_COMPARE(parent->hasFocus(), true);
1598 QCOMPARE(parent, qApp->focusWidget());
1601 testWidget->show(); //don't disturb later tests
1604 class Container : public QWidget
1611 box = new QVBoxLayout(this);
1612 //(new QVBoxLayout(this))->setAutoAdd(true);
1617 focusNextPrevChild(true);
1622 focusNextPrevChild(false);
1626 class Composite : public QFrame
1629 Composite(QWidget* parent = 0, const char* name = 0)
1632 setObjectName(name);
1633 //QHBoxLayout* hbox = new QHBoxLayout(this, 2, 0);
1634 //hbox->setAutoAdd(true);
1635 QHBoxLayout* hbox = new QHBoxLayout(this);
1637 lineEdit = new QLineEdit(this);
1638 hbox->addWidget(lineEdit);
1640 button = new QPushButton(this);
1641 hbox->addWidget(button);
1642 button->setFocusPolicy( Qt::NoFocus );
1644 setFocusProxy( lineEdit );
1645 setFocusPolicy( Qt::StrongFocus );
1647 setTabOrder(lineEdit, button);
1651 QLineEdit* lineEdit;
1652 QPushButton* button;
1655 #define NUM_WIDGETS 4
1657 void tst_QWidget::setTabOrder()
1661 Container container;
1663 Composite* comp[NUM_WIDGETS];
1665 QLineEdit *firstEdit = new QLineEdit(&container);
1666 container.box->addWidget(firstEdit);
1669 for(i = 0; i < NUM_WIDGETS; i++) {
1670 comp[i] = new Composite(&container);
1671 container.box->addWidget(comp[i]);
1674 QLineEdit *lastEdit = new QLineEdit(&container);
1675 container.box->addWidget(lastEdit);
1677 container.setTabOrder(lastEdit, comp[NUM_WIDGETS-1]);
1678 for(i = NUM_WIDGETS-1; i > 0; i--) {
1679 container.setTabOrder(comp[i], comp[i-1]);
1681 container.setTabOrder(comp[0], firstEdit);
1683 int current = NUM_WIDGETS-1;
1684 lastEdit->setFocus();
1687 container.activateWindow();
1688 qApp->setActiveWindow(&container);
1690 QTest::qWaitForWindowShown(&container);
1696 QTRY_VERIFY(lastEdit->hasFocus());
1699 QVERIFY(comp[current]->focusProxy()->hasFocus());
1702 } while (current >= 0);
1704 QVERIFY(firstEdit->hasFocus());
1708 void tst_QWidget::activation()
1712 #if defined(Q_OS_WINCE)
1713 int waitTime = 1000;
1719 qApp->processEvents();
1722 widget1.setWindowTitle("Widget1");
1725 widget2.setWindowTitle("Widget2");
1730 QTest::qWait(waitTime);
1731 QVERIFY(qApp->activeWindow() == &widget2);
1732 widget2.showMinimized();
1733 QTest::qWait(waitTime);
1735 QVERIFY(qApp->activeWindow() == &widget1);
1736 widget2.showMaximized();
1737 QTest::qWait(waitTime);
1738 QVERIFY(qApp->activeWindow() == &widget2);
1739 widget2.showMinimized();
1740 QTest::qWait(waitTime);
1741 QVERIFY(qApp->activeWindow() == &widget1);
1742 widget2.showNormal();
1743 QTest::qWait(waitTime);
1744 #if defined(Q_WS_WIN) && !defined(Q_OS_WINCE)
1745 if (QSysInfo::WindowsVersion >= QSysInfo::WV_VISTA)
1746 QEXPECT_FAIL("", "MS introduced new behavior after XP", Continue);
1748 QTest::qWait(waitTime);
1749 QVERIFY(qApp->activeWindow() == &widget2);
1751 QTest::qWait(waitTime);
1752 QVERIFY(qApp->activeWindow() == &widget1);
1756 // Many window managers do not support window state properly, which causes this test to fail.
1758 void tst_QWidget::windowState()
1760 #ifdef Q_OS_WINCE_WM
1761 QPoint pos(500, 500);
1762 QSize size(200, 200);
1763 if (qt_wince_is_smartphone()) { //small screen
1764 pos = QPoint(10,10);
1765 size = QSize(100,100);
1768 const QPoint pos(500, 500);
1769 const QSize size(200, 200);
1774 widget1.resize(size);
1775 QCOMPARE(widget1.pos(), pos);
1776 QCOMPARE(widget1.size(), size);
1778 widget1.setWindowTitle("Widget1");
1779 QCOMPARE(widget1.pos(), pos);
1780 QCOMPARE(widget1.size(), size);
1782 #define VERIFY_STATE(s) QCOMPARE(int(widget1.windowState() & stateMask), int(s))
1784 const int stateMask = Qt::WindowMaximized|Qt::WindowMinimized|Qt::WindowFullScreen;
1786 widget1.setWindowState(Qt::WindowMaximized);
1788 VERIFY_STATE(Qt::WindowMaximized);
1789 QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowMaximized);
1793 VERIFY_STATE(Qt::WindowMaximized);
1794 QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowMaximized);
1796 widget1.setWindowState(widget1.windowState() ^ Qt::WindowMaximized);
1798 QVERIFY(!(widget1.windowState() & Qt::WindowMaximized));
1799 QTRY_COMPARE(widget1.pos(), pos);
1800 QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowNoState);
1802 widget1.setWindowState(Qt::WindowMinimized);
1804 VERIFY_STATE(Qt::WindowMinimized);
1805 QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowMinimized);
1807 widget1.setWindowState(widget1.windowState() | Qt::WindowMaximized);
1809 VERIFY_STATE((Qt::WindowMinimized|Qt::WindowMaximized));
1810 QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowMinimized);
1812 widget1.setWindowState(widget1.windowState() ^ Qt::WindowMinimized);
1814 VERIFY_STATE(Qt::WindowMaximized);
1815 QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowMaximized);
1817 widget1.setWindowState(widget1.windowState() ^ Qt::WindowMaximized);
1819 QVERIFY(!(widget1.windowState() & (Qt::WindowMinimized|Qt::WindowMaximized)));
1820 QTRY_COMPARE(widget1.pos(), pos);
1821 QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowNoState);
1823 widget1.setWindowState(Qt::WindowFullScreen);
1825 VERIFY_STATE(Qt::WindowFullScreen);
1826 QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowFullScreen);
1828 widget1.setWindowState(widget1.windowState() ^ Qt::WindowMinimized);
1830 VERIFY_STATE((Qt::WindowFullScreen|Qt::WindowMinimized));
1831 QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowMinimized);
1833 widget1.setWindowState(widget1.windowState() ^ Qt::WindowMinimized);
1835 VERIFY_STATE(Qt::WindowFullScreen);
1836 QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowFullScreen);
1838 widget1.setWindowState(Qt::WindowNoState);
1840 VERIFY_STATE(Qt::WindowNoState);
1841 QTRY_COMPARE(widget1.pos(), pos);
1842 QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowNoState);
1844 widget1.setWindowState(Qt::WindowFullScreen);
1846 VERIFY_STATE(Qt::WindowFullScreen);
1847 QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowFullScreen);
1849 widget1.setWindowState(widget1.windowState() ^ Qt::WindowMaximized);
1851 VERIFY_STATE((Qt::WindowFullScreen|Qt::WindowMaximized));
1852 QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowFullScreen);
1854 widget1.setWindowState(widget1.windowState() ^ Qt::WindowMinimized);
1856 VERIFY_STATE((Qt::WindowFullScreen|Qt::WindowMaximized|Qt::WindowMinimized));
1857 QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowMinimized);
1859 widget1.setWindowState(widget1.windowState() ^ Qt::WindowMinimized);
1861 VERIFY_STATE((Qt::WindowFullScreen|Qt::WindowMaximized));
1862 QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowFullScreen);
1864 widget1.setWindowState(widget1.windowState() ^ Qt::WindowFullScreen);
1866 VERIFY_STATE(Qt::WindowMaximized);
1867 QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowMaximized);
1869 widget1.setWindowState(widget1.windowState() ^ Qt::WindowMaximized);
1871 QVERIFY(!(widget1.windowState() & stateMask));
1872 QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowNoState);
1874 QTRY_COMPARE(widget1.pos(), pos);
1875 QTRY_COMPARE(widget1.size(), size);
1879 void tst_QWidget::showMaximized()
1882 QHBoxLayout *layout;
1883 layout = new QHBoxLayout;
1889 layout->addWidget(&le);
1890 layout->addWidget(&le2);
1891 layout->addWidget(&le3);
1893 layouted.setLayout(layout);
1895 plain.showMaximized();
1896 QVERIFY(plain.windowState() & Qt::WindowMaximized);
1899 QVERIFY(!(plain.windowState() & Qt::WindowMaximized));
1901 layouted.showMaximized();
1902 QVERIFY(layouted.windowState() & Qt::WindowMaximized);
1904 layouted.showNormal();
1905 QVERIFY(!(layouted.windowState() & Qt::WindowMaximized));
1907 // ### fixme: embedded may choose a different size to fit on the screen.
1908 if (layouted.size() != layouted.sizeHint())
1909 QEXPECT_FAIL("", "QTBUG-22326", Continue);
1910 QCOMPARE(layouted.size(), layouted.sizeHint());
1912 layouted.showMaximized();
1913 QVERIFY(layouted.isMaximized());
1914 QVERIFY(layouted.isVisible());
1917 QVERIFY(layouted.isMaximized());
1918 QVERIFY(!layouted.isVisible());
1920 layouted.showMaximized();
1921 QVERIFY(layouted.isMaximized());
1922 QVERIFY(layouted.isVisible());
1924 layouted.showMinimized();
1925 QVERIFY(layouted.isMinimized());
1926 QVERIFY(layouted.isMaximized());
1928 layouted.showMaximized();
1929 QVERIFY(!layouted.isMinimized());
1930 QVERIFY(layouted.isMaximized());
1931 QVERIFY(layouted.isVisible());
1933 layouted.showMinimized();
1934 QVERIFY(layouted.isMinimized());
1935 QVERIFY(layouted.isMaximized());
1937 layouted.showMaximized();
1938 QVERIFY(!layouted.isMinimized());
1939 QVERIFY(layouted.isMaximized());
1940 QVERIFY(layouted.isVisible());
1944 QWidget widget(&frame);
1945 widget.showMaximized();
1946 QVERIFY(widget.isMaximized());
1951 widget.setGeometry(0, 0, 10, 10);
1952 widget.showMaximized();
1953 QTRY_VERIFY(widget.size().width() > 20 && widget.size().height() > 20);
1957 void tst_QWidget::showFullScreen()
1960 QHBoxLayout *layout;
1965 layout = new QHBoxLayout;
1967 layout->addWidget(&le);
1968 layout->addWidget(&le2);
1969 layout->addWidget(&le3);
1971 layouted.setLayout(layout);
1973 plain.showFullScreen();
1974 QVERIFY(plain.windowState() & Qt::WindowFullScreen);
1977 QVERIFY(!(plain.windowState() & Qt::WindowFullScreen));
1979 layouted.showFullScreen();
1980 QVERIFY(layouted.windowState() & Qt::WindowFullScreen);
1982 layouted.showNormal();
1983 QVERIFY(!(layouted.windowState() & Qt::WindowFullScreen));
1985 // ### fixme: embedded may choose a different size to fit on the screen.
1986 if (layouted.size() != layouted.sizeHint())
1987 QEXPECT_FAIL("", "QTBUG-22326", Continue);
1988 QCOMPARE(layouted.size(), layouted.sizeHint());
1990 layouted.showFullScreen();
1991 QVERIFY(layouted.isFullScreen());
1992 QVERIFY(layouted.isVisible());
1995 QVERIFY(layouted.isFullScreen());
1996 QVERIFY(!layouted.isVisible());
1998 layouted.showFullScreen();
1999 QVERIFY(layouted.isFullScreen());
2000 QVERIFY(layouted.isVisible());
2002 layouted.showMinimized();
2003 QVERIFY(layouted.isMinimized());
2004 QVERIFY(layouted.isFullScreen());
2006 layouted.showFullScreen();
2007 QVERIFY(!layouted.isMinimized());
2008 QVERIFY(layouted.isFullScreen());
2009 QVERIFY(layouted.isVisible());
2011 layouted.showMinimized();
2012 QVERIFY(layouted.isMinimized());
2013 QVERIFY(layouted.isFullScreen());
2015 layouted.showFullScreen();
2016 QVERIFY(!layouted.isMinimized());
2017 QVERIFY(layouted.isFullScreen());
2018 QVERIFY(layouted.isVisible());
2022 QWidget widget(&frame);
2023 widget.showFullScreen();
2024 QVERIFY(widget.isFullScreen());
2028 class ResizeWidget : public QWidget {
2030 ResizeWidget(QWidget *p = 0) : QWidget(p)
2032 m_resizeEventCount = 0;
2035 void resizeEvent(QResizeEvent *e){
2036 QCOMPARE(size(), e->size());
2037 ++m_resizeEventCount;
2041 int m_resizeEventCount;
2044 void tst_QWidget::resizeEvent()
2048 ResizeWidget wChild(&wParent);
2050 QCOMPARE (wChild.m_resizeEventCount, 1); // initial resize event before paint
2052 QSize safeSize(640,480);
2053 if (wChild.size() == safeSize)
2054 safeSize.setWidth(639);
2055 wChild.resize(safeSize);
2056 QCOMPARE (wChild.m_resizeEventCount, 1);
2058 QCOMPARE (wChild.m_resizeEventCount, 2);
2062 ResizeWidget wTopLevel;
2064 QCOMPARE (wTopLevel.m_resizeEventCount, 1); // initial resize event before paint for toplevels
2066 QSize safeSize(640,480);
2067 if (wTopLevel.size() == safeSize)
2068 safeSize.setWidth(639);
2069 wTopLevel.resize(safeSize);
2070 QCOMPARE (wTopLevel.m_resizeEventCount, 1);
2072 QCOMPARE (wTopLevel.m_resizeEventCount, 2);
2076 void tst_QWidget::showMinimized()
2079 plain.move(100, 100);
2080 plain.resize(200, 200);
2081 QPoint pos = plain.pos();
2083 plain.showMinimized();
2084 QVERIFY(plain.isMinimized());
2085 QVERIFY(plain.isVisible());
2086 QCOMPARE(plain.pos(), pos);
2089 QVERIFY(!plain.isMinimized());
2090 QVERIFY(plain.isVisible());
2091 QCOMPARE(plain.pos(), pos);
2093 plain.showMinimized();
2094 QVERIFY(plain.isMinimized());
2095 QVERIFY(plain.isVisible());
2096 QCOMPARE(plain.pos(), pos);
2099 QVERIFY(plain.isMinimized());
2100 QVERIFY(!plain.isVisible());
2102 plain.showMinimized();
2103 QVERIFY(plain.isMinimized());
2104 QVERIFY(plain.isVisible());
2106 plain.setGeometry(200, 200, 300, 300);
2108 QCOMPARE(plain.geometry(), QRect(200, 200, 300, 300));
2112 QWidget widget(&frame);
2113 widget.showMinimized();
2114 QVERIFY(widget.isMinimized());
2118 void tst_QWidget::showMinimizedKeepsFocus()
2120 //here we test that minimizing a widget and restoring it doesn't change the focus inside of it
2123 QWidget child1(&window), child2(&window);
2124 child1.setFocusPolicy(Qt::StrongFocus);
2125 child2.setFocusPolicy(Qt::StrongFocus);
2127 qApp->setActiveWindow(&window);
2128 QTest::qWaitForWindowShown(&window);
2132 QTRY_COMPARE(window.focusWidget(), &child2);
2133 QTRY_COMPARE(qApp->focusWidget(), &child2);
2135 window.showMinimized();
2137 QTRY_VERIFY(window.isMinimized());
2138 QTRY_COMPARE(window.focusWidget(), &child2);
2140 window.showNormal();
2142 QTRY_COMPARE(window.focusWidget(), &child2);
2145 //testing deletion of the focusWidget
2148 QWidget *child = new QWidget(&window);
2149 child->setFocusPolicy(Qt::StrongFocus);
2151 qApp->setActiveWindow(&window);
2152 QTest::qWaitForWindowShown(&window);
2155 QTRY_COMPARE(window.focusWidget(), child);
2156 QTRY_COMPARE(qApp->focusWidget(), child);
2159 QCOMPARE(window.focusWidget(), static_cast<QWidget*>(0));
2160 QCOMPARE(qApp->focusWidget(), static_cast<QWidget*>(0));
2163 //testing reparenting the focus widget
2166 QWidget *child = new QWidget(&window);
2167 child->setFocusPolicy(Qt::StrongFocus);
2169 qApp->setActiveWindow(&window);
2170 QTest::qWaitForWindowShown(&window);
2173 QTRY_COMPARE(window.focusWidget(), child);
2174 QTRY_COMPARE(qApp->focusWidget(), child);
2176 child->setParent(0);
2177 QCOMPARE(window.focusWidget(), static_cast<QWidget*>(0));
2178 QCOMPARE(qApp->focusWidget(), static_cast<QWidget*>(0));
2181 //testing setEnabled(false)
2184 QWidget *child = new QWidget(&window);
2185 child->setFocusPolicy(Qt::StrongFocus);
2187 qApp->setActiveWindow(&window);
2188 QTest::qWaitForWindowShown(&window);
2191 QTRY_COMPARE(window.focusWidget(), child);
2192 QTRY_COMPARE(qApp->focusWidget(), child);
2194 child->setEnabled(false);
2195 QCOMPARE(window.focusWidget(), static_cast<QWidget*>(0));
2196 QCOMPARE(qApp->focusWidget(), static_cast<QWidget*>(0));
2199 //testing clearFocus
2202 QWidget *firstchild = new QWidget(&window);
2203 firstchild->setFocusPolicy(Qt::StrongFocus);
2204 QWidget *child = new QWidget(&window);
2205 child->setFocusPolicy(Qt::StrongFocus);
2207 qApp->setActiveWindow(&window);
2208 QTest::qWaitForWindowShown(&window);
2211 QTRY_COMPARE(window.focusWidget(), child);
2212 QTRY_COMPARE(qApp->focusWidget(), child);
2214 child->clearFocus();
2215 QCOMPARE(window.focusWidget(), static_cast<QWidget*>(0));
2216 QCOMPARE(qApp->focusWidget(), static_cast<QWidget*>(0));
2218 window.showMinimized();
2220 QTRY_VERIFY(window.isMinimized());
2222 QEXPECT_FAIL("", "QWS does not implement showMinimized()", Continue);
2224 QCOMPARE(window.focusWidget(), static_cast<QWidget*>(0));
2226 QEXPECT_FAIL("", "QWS does not implement showMinimized()", Continue);
2228 QTRY_COMPARE(qApp->focusWidget(), static_cast<QWidget*>(0));
2230 window.showNormal();
2231 qApp->setActiveWindow(&window);
2232 QTest::qWaitForWindowShown(&window);
2235 if (!macHasAccessToWindowsServer())
2236 QEXPECT_FAIL("", "When not having WindowServer access, we lose focus.", Continue);
2238 QTRY_COMPARE(window.focusWidget(), firstchild);
2240 if (!macHasAccessToWindowsServer())
2241 QEXPECT_FAIL("", "When not having WindowServer access, we lose focus.", Continue);
2243 QTRY_COMPARE(qApp->focusWidget(), firstchild);
2248 void tst_QWidget::reparent()
2251 parent.setWindowTitle("Toplevel");
2252 parent.setGeometry(300, 300, 200, 150);
2255 child.setObjectName("child");
2256 child.setGeometry(10, 10, 180, 130);
2258 pal1.setColor(child.backgroundRole(), Qt::white);
2259 child.setPalette(pal1);
2261 QWidget childTLW(&child, Qt::Window);
2262 childTLW.setObjectName("childTLW");
2263 childTLW.setGeometry(100, 100, 50, 50);
2265 pal2.setColor(childTLW.backgroundRole(), Qt::yellow);
2266 childTLW.setPalette(pal2);
2270 QTest::qWaitForWindowShown(&parent);
2273 parent.move(50, 50);
2275 parent.move(300, 300);
2278 QPoint childPos = parent.mapToGlobal(child.pos());
2279 QPoint tlwPos = childTLW.pos();
2281 child.setParent(0, child.windowFlags() & ~Qt::WindowType_Mask);
2282 child.setGeometry(childPos.x(), childPos.y(), child.width(), child.height());
2286 // On X11, the window manager will apply NorthWestGravity rules to 'child', which
2287 // means the top-left corner of the window frame will be placed at 'childPos',
2288 // causing this test to fail
2290 QCOMPARE(child.geometry().topLeft(), childPos);
2292 QTRY_COMPARE(childTLW.pos(), tlwPos);
2294 // This following part of the test only makes sense on Windows.
2296 QWidget childTLWChild(&childTLW);
2297 childTLWChild.setObjectName("childTLWChild");
2299 QWidget grandChild(&child);
2300 grandChild.setObjectName("grandChild");
2301 grandChild.setGeometry(10, 10, 160, 110);
2303 pal3.setColor(grandChild.backgroundRole(), Qt::red);
2304 grandChild.setPalette(pal3);
2305 //grandChild.setPaletteBackgroundColor(Qt::red);
2307 QWidget grandChildTLW(&grandChild, Qt::Window);
2308 grandChildTLW.setObjectName("grandChildTLW");
2309 grandChildTLW.setGeometry(200, 200, 50, 50);
2311 pal4.setColor(grandChildTLW.backgroundRole(), Qt::yellow);
2312 grandChildTLW.setPalette(pal4);
2313 //grandChildTLW.setPaletteBackgroundColor(Qt::yellow);
2315 QWidget grandChildTLWChild(&grandChildTLW);
2316 grandChildTLWChild.setObjectName("grandChildTLWChild");
2318 QVERIFY(IsWindow(childTLW.winId()));
2319 QVERIFY(IsWindow(childTLWChild.winId()));
2320 QVERIFY(IsWindow(grandChildTLW.winId()));
2321 QVERIFY(IsWindow(grandChildTLWChild.winId()));
2325 QVERIFY(IsWindow(childTLW.winId()));
2326 QVERIFY(IsWindow(childTLWChild.winId()));
2327 QVERIFY(IsWindow(grandChildTLW.winId()));
2328 QVERIFY(IsWindow(grandChildTLWChild.winId()));
2330 child.setParent(&parent);
2334 // this appears to stabelize results
2335 qApp->processEvents();
2337 QVERIFY(IsWindow(childTLW.winId()));
2338 QVERIFY(IsWindow(childTLWChild.winId()));
2340 QVERIFY(IsWindow(grandChildTLW.winId()));
2341 QVERIFY(IsWindow(grandChildTLWChild.winId()));
2345 // Qt/Embedded does it differently.
2347 void tst_QWidget::icon()
2351 testWidget->setWindowIcon(p);
2353 QVERIFY(!testWidget->windowIcon().isNull());
2355 QVERIFY(!testWidget->windowIcon().isNull());
2356 testWidget->showFullScreen();
2357 QVERIFY(!testWidget->windowIcon().isNull());
2358 testWidget->showNormal();
2359 QVERIFY(!testWidget->windowIcon().isNull());
2363 void tst_QWidget::hideWhenFocusWidgetIsChild()
2365 testWidget->activateWindow();
2366 QWidget *parentWidget = new QWidget(testWidget);
2367 parentWidget->setObjectName("parentWidget");
2368 parentWidget->setGeometry(0, 0, 100, 100);
2369 QLineEdit *edit = new QLineEdit(parentWidget);
2370 edit->setObjectName("edit1");
2371 QLineEdit *edit3 = new QLineEdit(parentWidget);
2372 edit3->setObjectName("edit3");
2374 parentWidget->show();
2375 QLineEdit *edit2 = new QLineEdit(testWidget);
2376 edit2->setObjectName("edit2");
2378 edit2->move(110, 100);
2380 qApp->processEvents();
2381 QString actualFocusWidget, expectedFocusWidget;
2383 if (!qApp->focusWidget())
2384 QSKIP("Your window manager is too broken for this test");
2386 QVERIFY(qApp->focusWidget());
2387 actualFocusWidget.sprintf("%p %s %s", qApp->focusWidget(), qApp->focusWidget()->objectName().toLatin1().constData(), qApp->focusWidget()->metaObject()->className());
2388 expectedFocusWidget.sprintf("%p %s %s", edit, edit->objectName().toLatin1().constData(), edit->metaObject()->className());
2389 QCOMPARE(actualFocusWidget, expectedFocusWidget);
2391 parentWidget->hide();
2392 qApp->processEvents();
2393 actualFocusWidget.sprintf("%p %s %s", qApp->focusWidget(), qApp->focusWidget()->objectName().toLatin1().constData(), qApp->focusWidget()->metaObject()->className());
2394 expectedFocusWidget.sprintf("%p %s %s", edit2, edit2->objectName().toLatin1().constData(), edit2->metaObject()->className());
2395 QCOMPARE(actualFocusWidget, expectedFocusWidget);
2398 delete parentWidget;
2401 // 4DWM issues on IRIX makes this test fail.
2403 void tst_QWidget::normalGeometry()
2406 parent.setWindowTitle("NormalGeometry parent");
2407 QWidget *child = new QWidget(&parent);
2409 QCOMPARE(parent.normalGeometry(), parent.geometry());
2410 QCOMPARE(child->normalGeometry(), QRect());
2412 parent.setGeometry(100, 100, 200, 200);
2414 QTest::qWaitForWindowShown(&parent);
2415 QApplication::processEvents();
2417 QRect geom = parent.geometry();
2418 // ### the window manager places the top-left corner at
2419 // ### 100,100... making geom something like 102,124 (offset by
2420 // ### the frame/frame)... this indicates a rather large different
2421 // ### between how X11 and Windows works
2422 // QCOMPARE(geom, QRect(100, 100, 200, 200));
2423 QCOMPARE(parent.normalGeometry(), geom);
2425 parent.setWindowState(parent.windowState() ^ Qt::WindowMaximized);
2427 QTRY_VERIFY(parent.windowState() & Qt::WindowMaximized);
2428 QTRY_VERIFY(parent.geometry() != geom);
2429 QTRY_COMPARE(parent.normalGeometry(), geom);
2431 parent.setWindowState(parent.windowState() ^ Qt::WindowMaximized);
2433 QTRY_VERIFY(!(parent.windowState() & Qt::WindowMaximized));
2434 QTRY_COMPARE(parent.geometry(), geom);
2435 QTRY_COMPARE(parent.normalGeometry(), geom);
2437 parent.showMaximized();
2439 QTRY_VERIFY(parent.windowState() & Qt::WindowMaximized);
2440 QTRY_VERIFY(parent.geometry() != geom);
2441 QCOMPARE(parent.normalGeometry(), geom);
2443 parent.showNormal();
2445 QTRY_VERIFY(!(parent.windowState() & Qt::WindowMaximized));
2446 QTRY_COMPARE(parent.geometry(), geom);
2447 QCOMPARE(parent.normalGeometry(), geom);
2449 parent.setWindowState(parent.windowState() ^ Qt::WindowMinimized);
2451 parent.setWindowState(parent.windowState() ^ Qt::WindowMaximized);
2453 QTRY_VERIFY(parent.windowState() & (Qt::WindowMinimized|Qt::WindowMaximized));
2454 // ### when minimized and maximized at the same time, the geometry
2455 // ### does *NOT* have to be the normal geometry, it could be the
2456 // ### maximized geometry.
2457 // QCOMPARE(parent.geometry(), geom);
2458 QTRY_COMPARE(parent.normalGeometry(), geom);
2460 parent.setWindowState(parent.windowState() ^ Qt::WindowMinimized);
2462 QTRY_VERIFY(!(parent.windowState() & Qt::WindowMinimized));
2463 QTRY_VERIFY(parent.windowState() & Qt::WindowMaximized);
2464 QTRY_VERIFY(parent.geometry() != geom);
2465 QTRY_COMPARE(parent.normalGeometry(), geom);
2467 parent.setWindowState(parent.windowState() ^ Qt::WindowMaximized);
2469 QTRY_VERIFY(!(parent.windowState() & Qt::WindowMaximized));
2470 QTRY_COMPARE(parent.geometry(), geom);
2471 QTRY_COMPARE(parent.normalGeometry(), geom);
2473 parent.setWindowState(parent.windowState() ^ Qt::WindowFullScreen);
2475 QTRY_VERIFY(parent.windowState() & Qt::WindowFullScreen);
2476 QTRY_VERIFY(parent.geometry() != geom);
2477 QTRY_COMPARE(parent.normalGeometry(), geom);
2479 parent.setWindowState(parent.windowState() ^ Qt::WindowFullScreen);
2481 QVERIFY(!(parent.windowState() & Qt::WindowFullScreen));
2482 QTRY_COMPARE(parent.geometry(), geom);
2483 QTRY_COMPARE(parent.normalGeometry(), geom);
2485 parent.showFullScreen();
2487 QTRY_VERIFY(parent.windowState() & Qt::WindowFullScreen);
2488 QTRY_VERIFY(parent.geometry() != geom);
2489 QTRY_COMPARE(parent.normalGeometry(), geom);
2491 parent.showNormal();
2493 QTRY_VERIFY(!(parent.windowState() & Qt::WindowFullScreen));
2494 QTRY_COMPARE(parent.geometry(), geom);
2495 QTRY_COMPARE(parent.normalGeometry(), geom);
2497 parent.showNormal();
2498 parent.setWindowState(Qt:: WindowFullScreen | Qt::WindowMaximized);
2499 parent.setWindowState(Qt::WindowMinimized | Qt:: WindowFullScreen | Qt::WindowMaximized);
2500 parent.setWindowState(Qt:: WindowFullScreen | Qt::WindowMaximized);
2502 QTRY_COMPARE(parent.normalGeometry(), geom);
2506 void tst_QWidget::setGeometry()
2509 QWidget child(&tlw);
2511 QRect tr(100,100,200,200);
2512 QRect cr(50,50,50,50);
2513 tlw.setGeometry(tr);
2514 child.setGeometry(cr);
2517 QCOMPARE(tlw.geometry().size(), tr.size());
2518 QCOMPARE(child.geometry(), cr);
2520 tlw.setParent(0, Qt::Window|Qt::FramelessWindowHint);
2521 tr = QRect(0,0,100,100);
2522 tr.moveTopLeft(QApplication::desktop()->availableGeometry().topLeft());
2523 tlw.setGeometry(tr);
2524 QCOMPARE(tlw.geometry(), tr);
2527 if (tlw.frameGeometry() != tlw.geometry())
2528 QSKIP("Your window manager is too broken for this test");
2529 QCOMPARE(tlw.geometry(), tr);
2533 // Windows CE does not support windowOpacity.
2535 void tst_QWidget::windowOpacity()
2538 QWidget child(&widget);
2540 // Initial value should be 1.0
2541 QCOMPARE(widget.windowOpacity(), 1.0);
2542 // children should always return 1.0
2543 QCOMPARE(child.windowOpacity(), 1.0);
2545 widget.setWindowOpacity(0.0);
2546 QCOMPARE(widget.windowOpacity(), 0.0);
2547 child.setWindowOpacity(0.0);
2548 QCOMPARE(child.windowOpacity(), 1.0);
2550 widget.setWindowOpacity(1.0);
2551 QCOMPARE(widget.windowOpacity(), 1.0);
2552 child.setWindowOpacity(1.0);
2553 QCOMPARE(child.windowOpacity(), 1.0);
2555 widget.setWindowOpacity(2.0);
2556 QCOMPARE(widget.windowOpacity(), 1.0);
2557 child.setWindowOpacity(2.0);
2558 QCOMPARE(child.windowOpacity(), 1.0);
2560 widget.setWindowOpacity(-1.0);
2561 QCOMPARE(widget.windowOpacity(), 0.0);
2562 child.setWindowOpacity(-1.0);
2563 QCOMPARE(child.windowOpacity(), 1.0);
2567 class UpdateWidget : public QWidget
2570 UpdateWidget(QWidget *parent = 0) : QWidget(parent) {
2574 void paintEvent(QPaintEvent *e) {
2575 paintedRegion += e->region();
2577 if (resizeInPaintEvent) {
2578 resizeInPaintEvent = false;
2579 resize(size() + QSize(2, 2));
2583 bool event(QEvent *event)
2585 switch (event->type()) {
2586 case QEvent::ZOrderChange:
2587 ++numZOrderChangeEvents;
2589 case QEvent::UpdateRequest:
2590 ++numUpdateRequestEvents;
2592 case QEvent::ActivationChange:
2593 case QEvent::FocusIn:
2594 case QEvent::FocusOut:
2595 case QEvent::WindowActivate:
2596 case QEvent::WindowDeactivate:
2597 if (!updateOnActivationChangeAndFocusIn)
2598 return true; // Filter out to avoid update() calls in QWidget.
2603 return QWidget::event(event);
2608 numZOrderChangeEvents = 0;
2609 numUpdateRequestEvents = 0;
2610 updateOnActivationChangeAndFocusIn = false;
2611 resizeInPaintEvent = false;
2612 paintedRegion = QRegion();
2616 int numZOrderChangeEvents;
2617 int numUpdateRequestEvents;
2618 bool updateOnActivationChangeAndFocusIn;
2619 bool resizeInPaintEvent;
2620 QRegion paintedRegion;
2623 void tst_QWidget::lostUpdatesOnHide()
2626 UpdateWidget widget;
2627 widget.setAttribute(Qt::WA_DontShowOnScreen);
2634 QCOMPARE(widget.numPaintEvents, 1);
2638 void tst_QWidget::raise()
2641 QWidget *parent = new QWidget(0);
2642 QList<UpdateWidget *> allChildren;
2644 UpdateWidget *child1 = new UpdateWidget(parent);
2645 child1->setAutoFillBackground(true);
2646 allChildren.append(child1);
2648 UpdateWidget *child2 = new UpdateWidget(parent);
2649 child2->setAutoFillBackground(true);
2650 allChildren.append(child2);
2652 UpdateWidget *child3 = new UpdateWidget(parent);
2653 child3->setAutoFillBackground(true);
2654 allChildren.append(child3);
2656 UpdateWidget *child4 = new UpdateWidget(parent);
2657 child4->setAutoFillBackground(true);
2658 allChildren.append(child4);
2661 QTest::qWaitForWindowShown(parent);
2665 if (child1->internalWinId()) {
2666 QSKIP("Cocoa has no Z-Order for views, we hack it, but it results in paint events.");
2670 QList<QObject *> list1;
2671 list1 << child1 << child2 << child3 << child4;
2672 QVERIFY(parent->children() == list1);
2673 QCOMPARE(allChildren.count(), list1.count());
2675 foreach (UpdateWidget *child, allChildren) {
2676 int expectedPaintEvents = child == child4 ? 1 : 0;
2677 if (expectedPaintEvents == 0) {
2678 QVERIFY(child->numPaintEvents == 0);
2680 // show() issues multiple paint events on some window managers
2681 QTRY_VERIFY(child->numPaintEvents >= expectedPaintEvents);
2683 QCOMPARE(child->numZOrderChangeEvents, 0);
2687 for (int i = 0; i < 5; ++i)
2691 foreach (UpdateWidget *child, allChildren) {
2692 int expectedPaintEvents = child == child2 ? 1 : 0;
2693 int expectedZOrderChangeEvents = child == child2 ? 1 : 0;
2695 QSKIP("Not yet sure why this fails.");
2697 QTRY_COMPARE(child->numPaintEvents, expectedPaintEvents);
2698 QCOMPARE(child->numZOrderChangeEvents, expectedZOrderChangeEvents);
2702 QList<QObject *> list2;
2703 list2 << child1 << child3 << child4 << child2;
2704 QVERIFY(parent->children() == list2);
2706 // Creates a widget on top of all the children and checks that raising one of
2707 // the children underneath doesn't trigger a repaint on the covering widget.
2709 parent->setParent(&topLevel);
2711 QTest::qWaitForWindowShown(&topLevel);
2714 UpdateWidget *onTop = new UpdateWidget(&topLevel);
2716 onTop->resize(topLevel.size());
2717 onTop->setAutoFillBackground(true);
2720 QTRY_VERIFY(onTop->numPaintEvents > 0);
2723 // Reset all the children.
2724 foreach (UpdateWidget *child, allChildren)
2727 for (int i = 0; i < 5; ++i)
2731 QCOMPARE(onTop->numPaintEvents, 0);
2732 QCOMPARE(onTop->numZOrderChangeEvents, 0);
2734 QList<QObject *> list3;
2735 list3 << child1 << child4 << child2 << child3;
2736 QVERIFY(parent->children() == list3);
2738 foreach (UpdateWidget *child, allChildren) {
2739 int expectedPaintEvents = 0;
2740 int expectedZOrderChangeEvents = child == child3 ? 1 : 0;
2741 QTRY_COMPARE(child->numPaintEvents, expectedPaintEvents);
2742 QCOMPARE(child->numZOrderChangeEvents, expectedZOrderChangeEvents);
2747 // Cocoa has no Z-Order for views, we hack it, but it results in paint events.
2749 void tst_QWidget::lower()
2751 QWidget *parent = new QWidget(0);
2752 QList<UpdateWidget *> allChildren;
2754 UpdateWidget *child1 = new UpdateWidget(parent);
2755 child1->setAutoFillBackground(true);
2756 allChildren.append(child1);
2758 UpdateWidget *child2 = new UpdateWidget(parent);
2759 child2->setAutoFillBackground(true);
2760 allChildren.append(child2);
2762 UpdateWidget *child3 = new UpdateWidget(parent);
2763 child3->setAutoFillBackground(true);
2764 allChildren.append(child3);
2766 UpdateWidget *child4 = new UpdateWidget(parent);
2767 child4->setAutoFillBackground(true);
2768 allChildren.append(child4);
2771 QTest::qWaitForWindowShown(parent);
2774 QList<QObject *> list1;
2775 list1 << child1 << child2 << child3 << child4;
2776 QVERIFY(parent->children() == list1);
2777 QCOMPARE(allChildren.count(), list1.count());
2779 foreach (UpdateWidget *child, allChildren) {
2780 int expectedPaintEvents = child == child4 ? 1 : 0;
2781 if (expectedPaintEvents == 0) {
2782 QVERIFY(child->numPaintEvents == 0);
2784 // show() issues multiple paint events on some window managers
2785 QTRY_VERIFY(child->numPaintEvents >= expectedPaintEvents);
2787 QCOMPARE(child->numZOrderChangeEvents, 0);
2791 for (int i = 0; i < 5; ++i)
2796 foreach (UpdateWidget *child, allChildren) {
2797 int expectedPaintEvents = child == child3 ? 1 : 0;
2798 int expectedZOrderChangeEvents = child == child4 ? 1 : 0;
2799 QTRY_COMPARE(child->numZOrderChangeEvents, expectedZOrderChangeEvents);
2800 QTRY_COMPARE(child->numPaintEvents, expectedPaintEvents);
2804 QList<QObject *> list2;
2805 list2 << child4 << child1 << child2 << child3;
2806 QVERIFY(parent->children() == list2);
2812 // Cocoa has no Z-Order for views, we hack it, but it results in paint events.
2814 void tst_QWidget::stackUnder()
2817 QWidget *parent = new QWidget(0);
2818 QList<UpdateWidget *> allChildren;
2820 UpdateWidget *child1 = new UpdateWidget(parent);
2821 child1->setAutoFillBackground(true);
2822 allChildren.append(child1);
2824 UpdateWidget *child2 = new UpdateWidget(parent);
2825 child2->setAutoFillBackground(true);
2826 allChildren.append(child2);
2828 UpdateWidget *child3 = new UpdateWidget(parent);
2829 child3->setAutoFillBackground(true);
2830 allChildren.append(child3);
2832 UpdateWidget *child4 = new UpdateWidget(parent);
2833 child4->setAutoFillBackground(true);
2834 allChildren.append(child4);
2837 QTest::qWaitForWindowShown(parent);
2840 QApplication::sendPostedEvents(); //glib workaround
2843 QList<QObject *> list1;
2844 list1 << child1 << child2 << child3 << child4;
2845 QVERIFY(parent->children() == list1);
2847 foreach (UpdateWidget *child, allChildren) {
2848 int expectedPaintEvents = child == child4 ? 1 : 0;
2849 #if defined(Q_WS_WIN) || defined(Q_OS_MAC)
2850 if (expectedPaintEvents == 1 && child->numPaintEvents == 2)
2851 QEXPECT_FAIL(0, "Mac and Windows issues double repaints for Z-Order change", Continue);
2853 QTRY_COMPARE(child->numPaintEvents, expectedPaintEvents);
2854 QCOMPARE(child->numZOrderChangeEvents, 0);
2858 for (int i = 0; i < 5; ++i)
2859 child4->stackUnder(child2);
2862 QList<QObject *> list2;
2863 list2 << child1 << child4 << child2 << child3;
2864 QVERIFY(parent->children() == list2);
2866 foreach (UpdateWidget *child, allChildren) {
2867 int expectedPaintEvents = child == child3 ? 1 : 0;
2868 int expectedZOrderChangeEvents = child == child4 ? 1 : 0;
2869 QTRY_COMPARE(child->numPaintEvents, expectedPaintEvents);
2870 QTRY_COMPARE(child->numZOrderChangeEvents, expectedZOrderChangeEvents);
2874 for (int i = 0; i < 5; ++i)
2875 child1->stackUnder(child3);
2878 QList<QObject *> list3;
2879 list3 << child4 << child2 << child1 << child3;
2880 QVERIFY(parent->children() == list3);
2882 foreach (UpdateWidget *child, allChildren) {
2883 int expectedZOrderChangeEvents = child == child1 ? 1 : 0;
2884 if (child == child3) {
2886 qApp->processEvents();
2889 QEXPECT_FAIL(0, "See QTBUG-493", Continue);
2891 QCOMPARE(child->numPaintEvents, 0);
2893 QCOMPARE(child->numPaintEvents, 0);
2895 QTRY_COMPARE(child->numZOrderChangeEvents, expectedZOrderChangeEvents);
2903 void drawPolygon(QPaintDevice *dev, int w, int h)
2906 p.fillRect(0, 0, w, h, Qt::white);
2909 a << QPoint(0, 0) << QPoint(w/2, h/2) << QPoint(w, 0)
2910 << QPoint(w/2, h) << QPoint(0, 0);
2912 p.setPen(QPen(Qt::black, 1));
2913 p.setBrush(Qt::DiagCrossPattern);
2917 class ContentsPropagationWidget : public QWidget
2921 ContentsPropagationWidget(QWidget *parent = 0) : QWidget(parent)
2923 QWidget *child = this;
2924 for (int i=0; i<32; ++i) {
2925 child = new QWidget(child);
2926 child->setGeometry(i, i, 400 - i*2, 400 - i*2);
2930 void setContentsPropagation(bool enable) {
2931 foreach (QObject *child, children())
2932 qobject_cast<QWidget *>(child)->setAutoFillBackground(!enable);
2936 void paintEvent(QPaintEvent *)
2938 int w = width(), h = height();
2939 drawPolygon(this, w, h);
2942 QSize sizeHint() const { return QSize(500, 500); }
2945 void tst_QWidget::testContentsPropagation()
2947 ContentsPropagationWidget widget;
2949 widget.resize(500,500);
2951 widget.setFixedSize(500, 500);
2953 widget.setContentsPropagation(false);
2954 QPixmap widgetSnapshot = QPixmap::grabWidget(&widget);
2956 QPixmap correct(500, 500);
2957 drawPolygon(&correct, 500, 500);
2958 //correct.save("correct.png", "PNG");
2960 //widgetSnapshot.save("snap1.png", "PNG");
2961 QVERIFY(widgetSnapshot.toImage() != correct.toImage());
2963 widget.setContentsPropagation(true);
2964 widgetSnapshot = QPixmap::grabWidget(&widget);
2965 //widgetSnapshot.save("snap2.png", "PNG");
2967 QCOMPARE(widgetSnapshot, correct);
2971 Test that saving and restoring window geometry with
2972 saveGeometry() and restoreGeometry() works.
2974 // 4DWM issues on IRIX makes this test fail.
2976 void tst_QWidget::saveRestoreGeometry()
2978 const QPoint position(100, 100);
2979 const QSize size(200, 200);
2981 QByteArray savedGeometry;
2985 widget.move(position);
2986 widget.resize(size);
2988 QTest::qWaitForWindowShown(&widget);
2989 QApplication::processEvents();
2991 QTRY_COMPARE(widget.pos(), position);
2992 QCOMPARE(widget.size(), size);
2993 savedGeometry = widget.saveGeometry();
2999 const QByteArray empty;
3000 const QByteArray one("a");
3001 const QByteArray two("ab");
3002 const QByteArray three("abc");
3003 const QByteArray four("abca");
3004 const QByteArray garbage("abcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabc");
3006 QVERIFY(widget.restoreGeometry(empty) == false);
3007 QVERIFY(widget.restoreGeometry(one) == false);
3008 QVERIFY(widget.restoreGeometry(two) == false);
3009 QVERIFY(widget.restoreGeometry(three) == false);
3010 QVERIFY(widget.restoreGeometry(four) == false);
3011 QVERIFY(widget.restoreGeometry(garbage) == false);
3013 QVERIFY(widget.restoreGeometry(savedGeometry));
3015 QTest::qWaitForWindowShown(&widget);
3016 QApplication::processEvents();
3018 QTRY_COMPARE(widget.pos(), position);
3019 QCOMPARE(widget.size(), size);
3021 QCOMPARE(widget.pos(), position);
3022 QCOMPARE(widget.size(), size);
3027 widget.move(position);
3028 widget.resize(size);
3030 QTest::qWaitForWindowShown(&widget);
3032 QTRY_COMPARE(widget.geometry().size(), size);
3036 //Restore from Full screen
3037 savedGeometry = widget.saveGeometry();
3038 geom = widget.geometry();
3039 widget.setWindowState(widget.windowState() | Qt::WindowFullScreen);
3040 QTRY_VERIFY((widget.windowState() & Qt::WindowFullScreen));
3042 QVERIFY(widget.restoreGeometry(savedGeometry));
3044 QTRY_VERIFY(!(widget.windowState() & Qt::WindowFullScreen));
3045 QTRY_COMPARE(widget.geometry(), geom);
3047 //Restore to full screen
3048 widget.setWindowState(widget.windowState() | Qt::WindowFullScreen);
3050 QTRY_VERIFY((widget.windowState() & Qt::WindowFullScreen));
3052 savedGeometry = widget.saveGeometry();
3053 geom = widget.geometry();
3054 widget.setWindowState(widget.windowState() ^ Qt::WindowFullScreen);
3056 QTRY_VERIFY(!(widget.windowState() & Qt::WindowFullScreen));
3058 QVERIFY(widget.restoreGeometry(savedGeometry));
3060 QTRY_VERIFY((widget.windowState() & Qt::WindowFullScreen));
3061 QTRY_COMPARE(widget.geometry(), geom);
3062 QVERIFY((widget.windowState() & Qt::WindowFullScreen));
3063 widget.setWindowState(widget.windowState() ^ Qt::WindowFullScreen);
3065 QTRY_VERIFY(!(widget.windowState() & Qt::WindowFullScreen));
3068 //Restore from Maximised
3069 widget.move(position);
3070 widget.resize(size);
3072 QTRY_COMPARE(widget.size(), size);
3074 savedGeometry = widget.saveGeometry();
3075 geom = widget.geometry();
3076 widget.setWindowState(widget.windowState() | Qt::WindowMaximized);
3078 QTRY_VERIFY((widget.windowState() & Qt::WindowMaximized));
3079 QTRY_VERIFY(widget.geometry() != geom);
3081 QVERIFY(widget.restoreGeometry(savedGeometry));
3083 QTRY_COMPARE(widget.geometry(), geom);
3085 QVERIFY(!(widget.windowState() & Qt::WindowMaximized));
3087 //Restore to maximised
3088 widget.setWindowState(widget.windowState() | Qt::WindowMaximized);
3090 QTRY_VERIFY((widget.windowState() & Qt::WindowMaximized));
3092 geom = widget.geometry();
3093 savedGeometry = widget.saveGeometry();
3094 widget.setWindowState(widget.windowState() ^ Qt::WindowMaximized);
3096 QTRY_VERIFY(!(widget.windowState() & Qt::WindowMaximized));
3098 QVERIFY(widget.restoreGeometry(savedGeometry));
3100 QTRY_VERIFY((widget.windowState() & Qt::WindowMaximized));
3101 QTRY_COMPARE(widget.geometry(), geom);
3106 // 4DWM issues on IRIX makes this test fail.
3108 void tst_QWidget::restoreVersion1Geometry_data()
3110 QTest::addColumn<QString>("fileName");
3111 QTest::addColumn<uint>("expectedWindowState");
3112 QTest::addColumn<QPoint>("expectedPosition");
3113 QTest::addColumn<QSize>("expectedSize");
3114 QTest::addColumn<QRect>("expectedNormalGeometry");
3115 const QPoint position(100, 100);
3116 const QSize size(200, 200);
3117 const QRect normalGeometry(102, 124, 200, 200);
3119 QTest::newRow("geometry.dat") << ":geometry.dat" << uint(Qt::WindowNoState) << position << size << normalGeometry;
3120 QTest::newRow("geometry-maximized.dat") << ":geometry-maximized.dat" << uint(Qt::WindowMaximized) << position << size << normalGeometry;
3121 QTest::newRow("geometry-fullscreen.dat") << ":geometry-fullscreen.dat" << uint(Qt::WindowFullScreen) << position << size << normalGeometry;
3125 Test that the current version of restoreGeometry() can restore geometry
3126 saved width saveGeometry() version 1.0.
3128 void tst_QWidget::restoreVersion1Geometry()
3130 QFETCH(QString, fileName);
3131 QFETCH(uint, expectedWindowState);
3132 QFETCH(QPoint, expectedPosition);
3133 QFETCH(QSize, expectedSize);
3134 QFETCH(QRect, expectedNormalGeometry);
3136 // WindowActive is uninteresting for this test
3137 const uint WindowStateMask = Qt::WindowFullScreen | Qt::WindowMaximized | Qt::WindowMinimized;
3140 QVERIFY(f.exists());
3141 f.open(QIODevice::ReadOnly);
3142 const QByteArray savedGeometry = f.readAll();
3143 QCOMPARE(savedGeometry.count(), 46);
3148 QVERIFY(widget.restoreGeometry(savedGeometry));
3150 QCOMPARE(uint(widget.windowState() & WindowStateMask), expectedWindowState);
3151 if (expectedWindowState == Qt::WindowNoState) {
3152 QCOMPARE(widget.pos(), expectedPosition);
3153 QCOMPARE(widget.size(), expectedSize);
3156 QTest::qWaitForWindowShown(&widget);
3159 if (expectedWindowState == Qt::WindowNoState) {
3160 QTRY_COMPARE(widget.pos(), expectedPosition);
3161 QTRY_COMPARE(widget.size(), expectedSize);
3164 widget.showNormal();
3167 if (expectedWindowState != Qt::WindowNoState) {
3168 // restoring from maximized or fullscreen, we can only restore to the normal geometry
3169 QTRY_COMPARE(widget.geometry(), expectedNormalGeometry);
3171 QTRY_COMPARE(widget.pos(), expectedPosition);
3172 QTRY_COMPARE(widget.size(), expectedSize);
3176 // Code for saving a new geometry*.dat files
3178 QWidget widgetToSave;
3179 widgetToSave.move(expectedPosition);
3180 widgetToSave.resize(expectedSize);
3181 widgetToSave.show();
3183 qt_x11_wait_for_window_manager(&widget);
3185 QTest::qWait(500); // stabilize
3186 widgetToSave.setWindowState(Qt::WindowStates(expectedWindowState));
3187 QTest::qWait(500); // stabilize
3189 QByteArray geometryToSave = widgetToSave.saveGeometry();
3191 // Code for saving a new geometry.dat file.
3192 f.setFileName(fileName.mid(1));
3193 QVERIFY(f.open(QIODevice::WriteOnly)); // did you forget to 'p4 edit *.dat'? :)
3194 f.write(geometryToSave);
3201 void tst_QWidget::widgetAt()
3205 QWidget *w1 = new QWidget(0, Qt::X11BypassWindowManagerHint);
3206 w1->setGeometry(0,0,150,150);
3207 w1->setObjectName("w1");
3209 QWidget *w2 = new QWidget(0, Qt::X11BypassWindowManagerHint | Qt::FramelessWindowHint);
3210 w2->setGeometry(50,50,100,100);
3211 w2->setObjectName("w2");
3213 QTest::qWaitForWindowShown(w1);
3214 qApp->processEvents();
3216 QTRY_VERIFY((wr = QApplication::widgetAt(100, 100)));
3217 QCOMPARE(wr->objectName(), QString("w1"));
3220 QTest::qWaitForWindowShown(w2);
3221 qApp->processEvents();
3222 qApp->processEvents();
3223 qApp->processEvents();
3224 QTRY_VERIFY((wr = QApplication::widgetAt(100, 100)));
3225 QCOMPARE(wr->objectName(), QString("w2"));
3228 qApp->processEvents();
3229 QTRY_VERIFY((wr = QApplication::widgetAt(100, 100)) && wr->objectName() == QString("w1"));
3232 qApp->processEvents();
3233 QTRY_VERIFY((wr = QApplication::widgetAt(100, 100)) && wr->objectName() == QString("w2"));
3235 QWidget *w3 = new QWidget(w2);
3236 w3->setGeometry(10,10,50,50);
3237 w3->setObjectName("w3");
3239 qApp->processEvents();
3240 QTRY_VERIFY((wr = QApplication::widgetAt(100,100)) && wr->objectName() == QString("w3"));
3242 w3->setAttribute(Qt::WA_TransparentForMouseEvents);
3243 qApp->processEvents();
3244 QTRY_VERIFY((wr = QApplication::widgetAt(100, 100)) && wr->objectName() == QString("w2"));
3246 QRegion rgn = QRect(QPoint(0,0), w2->size());
3247 QPoint point = w2->mapFromGlobal(QPoint(100,100));
3248 rgn -= QRect(point, QSize(1,1));
3250 qApp->processEvents();
3252 #if defined(Q_OS_WINCE)
3253 QEXPECT_FAIL("", "Windows CE does only support rectangular regions", Continue); //See also task 147191
3255 /// ### fixme: Check platforms
3256 QEXPECT_FAIL("", "Window mask not implemented on Lighthouse QTBUG-22326", Continue);
3258 QTRY_COMPARE(QApplication::widgetAt(100,100)->objectName(), w1->objectName());
3259 QTRY_COMPARE(QApplication::widgetAt(101,101)->objectName(), w2->objectName());
3261 QBitmap bitmap(w2->size());
3262 QPainter p(&bitmap);
3263 p.fillRect(bitmap.rect(), Qt::color1);
3264 p.setPen(Qt::color0);
3265 p.drawPoint(w2->mapFromGlobal(QPoint(100,100)));
3267 w2->setMask(bitmap);
3268 qApp->processEvents();
3270 #if defined(Q_OS_WINCE)
3271 QEXPECT_FAIL("", "Windows CE does only support rectangular regions", Continue); //See also task 147191
3273 /// ### fixme: Check platforms
3274 QEXPECT_FAIL("", "Window mask not implemented on Lighthouse QTBUG-22326", Continue);
3275 QTRY_VERIFY(QApplication::widgetAt(100,100) == w1);
3276 QTRY_VERIFY(QApplication::widgetAt(101,101) == w2);
3282 #if defined(Q_WS_X11)
3283 bool getProperty(Display *display, Window target, Atom type, Atom property,
3284 unsigned char** data, unsigned long* count)
3288 unsigned long nitems, bytes_left;
3290 int ret = XGetWindowProperty(display, target, property,
3292 type, &atom_return, &size,
3293 &nitems, &bytes_left, data);
3294 if (ret != Success || nitems < 1)
3297 if (bytes_left != 0) {
3299 unsigned long remain = ((size / 8) * nitems) + bytes_left;
3300 ret = XGetWindowProperty(display, target,
3301 property, 0l, remain, false,
3302 type, &atom_return, &size,
3303 &nitems, &bytes_left, data);
3312 QString textPropertyToString(Display *display, XTextProperty& text_prop)
3315 if (text_prop.value && text_prop.nitems > 0) {
3316 if (text_prop.encoding == XA_STRING) {
3317 ret = reinterpret_cast<char *>(text_prop.value);
3319 text_prop.nitems = strlen(reinterpret_cast<char *>(text_prop.value));
3322 if (XmbTextPropertyToTextList(display, &text_prop, &list, &num) == Success
3323 && num > 0 && *list) {
3324 ret = QString::fromLocal8Bit(*list);
3325 XFreeStringList(list);
3333 void tst_QWidget::task110173()
3337 QPushButton *pb1 = new QPushButton("click", &w);
3338 pb1->setFocusPolicy(Qt::ClickFocus);
3339 pb1->move(100, 100);
3341 QPushButton *pb2 = new QPushButton("push", &w);
3342 pb2->setFocusPolicy(Qt::ClickFocus);
3343 pb2->move(300, 300);
3345 QTest::keyClick( &w, Qt::Key_Tab );
3347 QTest::qWaitForWindowShown(&w);
3351 class Widget : public QWidget
3354 Widget() : deleteThis(false) { setFocusPolicy(Qt::StrongFocus); }
3355 void actionEvent(QActionEvent *) { if (deleteThis) delete this; }
3356 void changeEvent(QEvent *) { if (deleteThis) delete this; }
3357 void closeEvent(QCloseEvent *) { if (deleteThis) delete this; }
3358 void hideEvent(QHideEvent *) { if (deleteThis) delete this; }
3359 void focusOutEvent(QFocusEvent *) { if (deleteThis) delete this; }
3360 void keyPressEvent(QKeyEvent *) { if (deleteThis) delete this; }
3361 void keyReleaseEvent(QKeyEvent *) { if (deleteThis) delete this; }
3362 void mouseDoubleClickEvent(QMouseEvent *) { if (deleteThis) delete this; }
3363 void mousePressEvent(QMouseEvent *) { if (deleteThis) delete this; }
3364 void mouseReleaseEvent(QMouseEvent *) { if (deleteThis) delete this; }
3365 void mouseMoveEvent(QMouseEvent *) { if (deleteThis) delete this; }
3370 void tst_QWidget::testDeletionInEventHandlers()
3373 QPointer<Widget> w = new Widget;
3374 w->deleteThis = true;
3379 // focusOut (crashes)
3383 //QVERIFY(qApp->focusWidget() == w);
3384 //w->deleteThis = true;
3391 w->deleteThis = true;
3392 QTest::keyPress(w, Qt::Key_A);
3399 w->deleteThis = true;
3400 QTest::keyRelease(w, Qt::Key_A);
3407 w->deleteThis = true;
3408 QTest::mousePress(w, Qt::LeftButton);
3415 w->deleteThis = true;
3416 QTest::mouseRelease(w, Qt::LeftButton);
3420 // mouse double click
3423 w->deleteThis = true;
3424 QTest::mouseDClick(w, Qt::LeftButton);
3428 // hide event (crashes)
3431 //w->deleteThis = true;
3437 w->deleteThis = true;
3438 w->addAction(new QAction(w));
3445 w->deleteThis = true;
3446 w->setMouseTracking(true);
3451 w->setMouseTracking(true);
3453 w->deleteThis = true;
3454 QMouseEvent me(QEvent::MouseMove, QPoint(0, 0), Qt::NoButton, Qt::NoButton, Qt::NoModifier);
3455 QApplication::sendEvent(w, &me);
3461 void tst_QWidget::sheetOpacity()
3464 QWidget sheet(&tmpWindow, Qt::Sheet);
3467 QCOMPARE(int(sheet.windowOpacity() * 255), 242); // 95%
3468 sheet.setParent(0, Qt::Dialog);
3469 QCOMPARE(int(sheet.windowOpacity() * 255), 255);
3472 class MaskedPainter : public QWidget
3478 : mask(20, 20, 50, 50)
3483 void paintEvent(QPaintEvent *)
3486 p.fillRect(mask, QColor(Qt::red));
3491 Verifies that the entire area inside the mask is painted red.
3493 bool verifyWidgetMask(QWidget *widget, QRect mask)
3495 const QImage image = QPixmap::grabWindow(widget->winId()).toImage();
3497 const QImage masked = image.copy(mask);
3499 red.fill(QColor(Qt::red).rgb());
3501 return (masked == red);
3504 void tst_QWidget::setMask()
3506 testWidget->hide(); // get this out of the way.
3513 QVERIFY(verifyWidgetMask(&w, w.mask));
3518 w.setWindowFlags(w.windowFlags() | Qt::FramelessWindowHint);
3521 QRect mask = w.mask;
3523 QVERIFY(verifyWidgetMask(&w, mask));
3528 class StaticWidget : public QWidget
3534 QRegion paintedRegion;
3536 StaticWidget(QWidget *parent = 0)
3539 setAttribute(Qt::WA_StaticContents);
3540 setAttribute(Qt::WA_OpaquePaintEvent);
3541 setPalette(Qt::red); // Make sure we have an opaque palette.
3542 setAutoFillBackground(true);
3543 gotPaintEvent = false;
3546 void paintEvent(QPaintEvent *e)
3548 paintedRegion += e->region();
3549 gotPaintEvent = true;
3550 // qDebug() << "paint" << e->region();
3551 // Look for a full update, set partial to false if found.
3552 foreach(QRect r, e->region().rects()) {
3553 partial = (r != rect());
3554 if (partial == false)
3561 Test that widget resizes and moves can be done with minimal repaints when WA_StaticContents
3562 and WA_OpaquePaintEvent is set. Test is mac-only for now.
3564 void tst_QWidget::optimizedResizeMove()
3567 parent.resize(400, 400);
3569 StaticWidget staticWidget(&parent);
3570 staticWidget.gotPaintEvent = false;
3571 staticWidget.move(150, 150);
3572 staticWidget.resize(150, 150);
3574 QTest::qWaitForWindowShown(&parent);
3576 QTRY_COMPARE(staticWidget.gotPaintEvent, true);
3578 staticWidget.gotPaintEvent = false;
3579 staticWidget.move(staticWidget.pos() + QPoint(10, 10));
3581 QCOMPARE(staticWidget.gotPaintEvent, false);
3583 staticWidget.gotPaintEvent = false;
3584 staticWidget.move(staticWidget.pos() + QPoint(-10, -10));
3586 QCOMPARE(staticWidget.gotPaintEvent, false);
3588 staticWidget.gotPaintEvent = false;
3589 staticWidget.move(staticWidget.pos() + QPoint(-10, 10));
3591 QCOMPARE(staticWidget.gotPaintEvent, false);
3593 staticWidget.gotPaintEvent = false;
3594 staticWidget.resize(staticWidget.size() + QSize(10, 10));
3596 QCOMPARE(staticWidget.gotPaintEvent, true);
3597 QCOMPARE(staticWidget.partial, true);
3599 staticWidget.gotPaintEvent = false;
3600 staticWidget.resize(staticWidget.size() + QSize(-10, -10));
3602 QCOMPARE(staticWidget.gotPaintEvent, false);
3604 staticWidget.gotPaintEvent = false;
3605 staticWidget.resize(staticWidget.size() + QSize(10, -10));
3607 QCOMPARE(staticWidget.gotPaintEvent, true);
3608 QCOMPARE(staticWidget.partial, true);
3610 staticWidget.gotPaintEvent = false;
3611 staticWidget.move(staticWidget.pos() + QPoint(10, 10));
3612 staticWidget.resize(staticWidget.size() + QSize(-10, -10));
3614 QCOMPARE(staticWidget.gotPaintEvent, false);
3616 staticWidget.gotPaintEvent = false;
3617 staticWidget.move(staticWidget.pos() + QPoint(10, 10));
3618 staticWidget.resize(staticWidget.size() + QSize(10, 10));
3620 QCOMPARE(staticWidget.gotPaintEvent, true);
3621 QCOMPARE(staticWidget.partial, true);
3623 staticWidget.gotPaintEvent = false;
3624 staticWidget.move(staticWidget.pos() + QPoint(-10, -10));
3625 staticWidget.resize(staticWidget.size() + QSize(-10, -10));
3627 QCOMPARE(staticWidget.gotPaintEvent, false);
3629 staticWidget.setAttribute(Qt::WA_StaticContents, false);
3630 staticWidget.gotPaintEvent = false;
3631 staticWidget.move(staticWidget.pos() + QPoint(-10, -10));
3632 staticWidget.resize(staticWidget.size() + QSize(-10, -10));
3634 QCOMPARE(staticWidget.gotPaintEvent, true);
3635 QCOMPARE(staticWidget.partial, false);
3636 staticWidget.setAttribute(Qt::WA_StaticContents, true);
3638 staticWidget.setAttribute(Qt::WA_StaticContents, false);
3639 staticWidget.gotPaintEvent = false;
3640 staticWidget.move(staticWidget.pos() + QPoint(10, 10));
3642 QCOMPARE(staticWidget.gotPaintEvent, false);
3643 staticWidget.setAttribute(Qt::WA_StaticContents, true);
3646 void tst_QWidget::optimizedResize_topLevel()
3648 #if defined(Q_OS_MAC) || defined(Q_WS_QWS)
3649 QSKIP("We do not yet have static contents support for *top-levels* on this platform");
3652 StaticWidget topLevel;
3653 topLevel.gotPaintEvent = false;
3655 QTest::qWaitForWindowShown(&topLevel);
3657 QTRY_COMPARE(topLevel.gotPaintEvent, true);
3659 topLevel.gotPaintEvent = false;
3660 topLevel.partial = false;
3661 topLevel.paintedRegion = QRegion();
3664 topLevel.resize(topLevel.size() + QSize(10, 10));
3666 // Static contents does not work when programmatically resizing
3667 // top-levels with QWidget::resize. We do some funky stuff in
3668 // setGeometry_sys. However, resizing it with the mouse or with
3669 // a native function call works (it basically has to go through
3670 // WM_RESIZE in QApplication). This is a corner case, though.
3672 const QRect frame = topLevel.frameGeometry();
3673 MoveWindow(topLevel.winId(), frame.x(), frame.y(),
3674 frame.width() + 10, frame.height() + 10,
3680 // Expected update region: New rect - old rect.
3681 QRegion expectedUpdateRegion(topLevel.rect());
3682 expectedUpdateRegion -= QRect(QPoint(), topLevel.size() - QSize(10, 10));
3684 QTRY_COMPARE(topLevel.gotPaintEvent, true);
3685 QCOMPARE(topLevel.partial, true);
3686 QCOMPARE(topLevel.paintedRegion, expectedUpdateRegion);
3689 class SiblingDeleter : public QWidget
3692 inline SiblingDeleter(QWidget *sibling, QWidget *parent)
3693 : QWidget(parent), sibling(sibling) {}
3694 inline virtual ~SiblingDeleter() { delete sibling; }
3697 QPointer<QWidget> sibling;
3701 void tst_QWidget::childDeletesItsSibling()
3703 QWidget *commonParent = new QWidget(0);
3704 QPointer<QWidget> child = new QWidget(0);
3705 QPointer<QWidget> siblingDeleter = new SiblingDeleter(child, commonParent);
3706 child->setParent(commonParent);
3707 delete commonParent; // don't crash
3709 QVERIFY(!siblingDeleter);
3714 # define SET_SAFE_SIZE(w) \
3716 QSize safeSize(qt_screen->width() - 250, qt_screen->height() - 250); \
3717 if (!safeSize.isValid()) \
3718 QSKIP("Screen size too small"); \
3719 if (defaultSize.width() > safeSize.width() || defaultSize.height() > safeSize.height()) { \
3720 defaultSize = safeSize; \
3721 w.resize(defaultSize); \
3722 w.setAttribute(Qt::WA_Resized, false); \
3726 # define SET_SAFE_SIZE(w)
3730 void tst_QWidget::setMinimumSize()
3733 QSize defaultSize = w.size();
3736 w.setMinimumSize(defaultSize + QSize(100, 100));
3737 QCOMPARE(w.size(), defaultSize + QSize(100, 100));
3738 QVERIFY(!w.testAttribute(Qt::WA_Resized));
3740 w.setMinimumSize(defaultSize + QSize(50, 50));
3741 QCOMPARE(w.size(), defaultSize + QSize(100, 100));
3742 QVERIFY(!w.testAttribute(Qt::WA_Resized));
3744 w.setMinimumSize(defaultSize + QSize(200, 200));
3745 QCOMPARE(w.size(), defaultSize + QSize(200, 200));
3746 QVERIFY(!w.testAttribute(Qt::WA_Resized));
3748 // Setting a minimum size larger than the desktop does not work on WinCE,
3749 // so skip this part of the test.
3751 QSize nonDefaultSize = defaultSize + QSize(5,5);
3752 w.setMinimumSize(nonDefaultSize);
3755 QVERIFY(w.height() >= nonDefaultSize.height());
3756 QVERIFY(w.width() >= nonDefaultSize.width());
3760 void tst_QWidget::setMaximumSize()
3763 QSize defaultSize = w.size();
3766 w.setMinimumSize(defaultSize + QSize(100, 100));
3767 QCOMPARE(w.size(), defaultSize + QSize(100, 100));
3768 QVERIFY(!w.testAttribute(Qt::WA_Resized));
3769 w.setMinimumSize(defaultSize);
3771 w.setMaximumSize(defaultSize + QSize(200, 200));
3772 QCOMPARE(w.size(), defaultSize + QSize(100, 100));
3773 QVERIFY(!w.testAttribute(Qt::WA_Resized));
3775 w.setMaximumSize(defaultSize + QSize(50, 50));
3776 QCOMPARE(w.size(), defaultSize + QSize(50, 50));
3777 QVERIFY(!w.testAttribute(Qt::WA_Resized));
3780 void tst_QWidget::setFixedSize()
3783 QSize defaultSize = w.size();
3786 w.setFixedSize(defaultSize + QSize(100, 100));
3787 QCOMPARE(w.size(), defaultSize + QSize(100, 100));
3788 QVERIFY(w.testAttribute(Qt::WA_Resized));
3790 w.setFixedSize(defaultSize + QSize(200, 200));
3792 QCOMPARE(w.minimumSize(), defaultSize + QSize(200,200));
3793 QCOMPARE(w.maximumSize(), defaultSize + QSize(200,200));
3794 QCOMPARE(w.size(), defaultSize + QSize(200, 200));
3795 QVERIFY(w.testAttribute(Qt::WA_Resized));
3797 w.setFixedSize(defaultSize + QSize(50, 50));
3798 QCOMPARE(w.size(), defaultSize + QSize(50, 50));
3799 QVERIFY(w.testAttribute(Qt::WA_Resized));
3801 w.setAttribute(Qt::WA_Resized, false);
3802 w.setFixedSize(defaultSize + QSize(50, 50));
3803 QVERIFY(!w.testAttribute(Qt::WA_Resized));
3805 w.setFixedSize(defaultSize + QSize(150, 150));
3808 QVERIFY(w.size() == defaultSize + QSize(150,150));
3811 void tst_QWidget::ensureCreated()
3815 WId widgetWinId = widget.winId();
3816 Q_UNUSED(widgetWinId);
3817 QVERIFY(widget.testAttribute(Qt::WA_WState_Created));
3823 QDialog dialog(&window);
3824 dialog.setWindowModality(Qt::NonModal);
3826 WId dialogWinId = dialog.winId();
3827 Q_UNUSED(dialogWinId);
3828 QVERIFY(dialog.testAttribute(Qt::WA_WState_Created));
3829 QVERIFY(window.testAttribute(Qt::WA_WState_Created));
3835 QDialog dialog(&window);
3836 dialog.setWindowModality(Qt::WindowModal);
3838 WId dialogWinId = dialog.winId();
3839 Q_UNUSED(dialogWinId);
3840 QVERIFY(dialog.testAttribute(Qt::WA_WState_Created));
3841 QVERIFY(window.testAttribute(Qt::WA_WState_Created));
3847 QDialog dialog(&window);
3848 dialog.setWindowModality(Qt::ApplicationModal);
3850 WId dialogWinId = dialog.winId();
3851 Q_UNUSED(dialogWinId);
3852 QVERIFY(dialog.testAttribute(Qt::WA_WState_Created));
3853 QVERIFY(window.testAttribute(Qt::WA_WState_Created));
3857 class WinIdChangeWidget : public QWidget {
3859 WinIdChangeWidget(QWidget *p = 0)
3865 bool event(QEvent *e)
3867 if (e->type() == QEvent::WinIdChange) {
3868 m_winIdList.append(internalWinId());
3871 return QWidget::event(e);
3874 QList<WId> m_winIdList;
3875 int winIdChangeEventCount() const { return m_winIdList.count(); }
3878 void tst_QWidget::winIdChangeEvent()
3881 // Transforming an alien widget into a native widget
3882 WinIdChangeWidget widget;
3883 const WId winIdBefore = widget.internalWinId();
3884 const WId winIdAfter = widget.winId();
3885 QVERIFY(winIdBefore != winIdAfter);
3886 QCOMPARE(widget.winIdChangeEventCount(), 1);
3890 // Changing parent of a native widget
3891 // Should cause winId of child to change, on all platforms
3892 QWidget parent1, parent2;
3893 WinIdChangeWidget child(&parent1);
3894 const WId winIdBefore = child.winId();
3895 QCOMPARE(child.winIdChangeEventCount(), 1);
3896 child.setParent(&parent2);
3897 const WId winIdAfter = child.internalWinId();
3898 QVERIFY(winIdBefore != winIdAfter);
3899 QCOMPARE(child.winIdChangeEventCount(), 3);
3900 // winId is set to zero during reparenting
3901 QVERIFY(0 == child.m_winIdList[1]);
3905 // Changing grandparent of a native widget
3906 QWidget grandparent1, grandparent2;
3907 QWidget parent(&grandparent1);
3908 WinIdChangeWidget child(&parent);
3909 const WId winIdBefore = child.winId();
3910 QCOMPARE(child.winIdChangeEventCount(), 1);
3911 parent.setParent(&grandparent2);
3912 const WId winIdAfter = child.internalWinId();
3913 QCOMPARE(winIdBefore, winIdAfter);
3914 QCOMPARE(child.winIdChangeEventCount(), 1);
3918 // Changing parent of an alien widget
3919 QWidget parent1, parent2;
3920 WinIdChangeWidget child(&parent1);
3921 const WId winIdBefore = child.internalWinId();
3922 child.setParent(&parent2);
3923 const WId winIdAfter = child.internalWinId();
3924 QCOMPARE(winIdBefore, winIdAfter);
3925 QCOMPARE(child.winIdChangeEventCount(), 0);
3929 // Making native child widget into a top-level window
3931 WinIdChangeWidget child(&parent);
3933 const WId winIdBefore = child.internalWinId();
3934 QCOMPARE(child.winIdChangeEventCount(), 1);
3935 const Qt::WindowFlags flags = child.windowFlags();
3936 child.setWindowFlags(flags | Qt::Window);
3937 const WId winIdAfter = child.internalWinId();
3938 QVERIFY(winIdBefore != winIdAfter);
3939 QCOMPARE(child.winIdChangeEventCount(), 3);
3940 // winId is set to zero during reparenting
3941 QVERIFY(0 == child.m_winIdList[1]);
3945 void tst_QWidget::persistentWinId()
3947 QWidget *parent = new QWidget;
3948 QWidget *w1 = new QWidget;
3949 QWidget *w2 = new QWidget;
3950 QWidget *w3 = new QWidget;
3951 w1->setParent(parent);
3955 WId winId1 = w1->winId();
3956 WId winId2 = w2->winId();
3957 WId winId3 = w3->winId();
3959 // reparenting should change the winId of the widget being reparented, but not of its children
3961 QVERIFY(w1->winId() != winId1);
3962 winId1 = w1->winId();
3963 QCOMPARE(w2->winId(), winId2);
3964 QCOMPARE(w3->winId(), winId3);
3966 w1->setParent(parent);
3967 QVERIFY(w1->winId() != winId1);
3968 winId1 = w1->winId();
3969 QCOMPARE(w2->winId(), winId2);
3970 QCOMPARE(w3->winId(), winId3);
3973 QVERIFY(w2->winId() != winId2);
3974 winId2 = w2->winId();
3975 QCOMPARE(w3->winId(), winId3);
3977 w2->setParent(parent);
3978 QVERIFY(w2->winId() != winId2);
3979 winId2 = w2->winId();
3980 QCOMPARE(w3->winId(), winId3);
3983 QVERIFY(w2->winId() != winId2);
3984 winId2 = w2->winId();
3985 QCOMPARE(w3->winId(), winId3);
3988 QVERIFY(w3->winId() != winId3);
3989 winId3 = w3->winId();
3992 QVERIFY(w3->winId() != winId3);
3993 winId3 = w3->winId();
3996 QVERIFY(w3->winId() != winId3);
3997 winId3 = w3->winId();
4002 void tst_QWidget::showNativeChild()
4005 topLevel.setGeometry(0, 0, 100, 100);
4006 QWidget child(&topLevel);
4009 QTest::qWaitForWindowShown(&topLevel);
4012 class ShowHideEventWidget : public QWidget
4015 int numberOfShowEvents, numberOfHideEvents;
4017 ShowHideEventWidget(QWidget *parent = 0)
4018 : QWidget(parent), numberOfShowEvents(0), numberOfHideEvents(0)
4022 { QWidget::create(); }
4024 void showEvent(QShowEvent *)
4025 { ++numberOfShowEvents; }
4027 void hideEvent(QHideEvent *)
4028 { ++numberOfHideEvents; }
4031 void tst_QWidget::showHideEvent_data()
4033 QTest::addColumn<bool>("show");
4034 QTest::addColumn<bool>("hide");
4035 QTest::addColumn<bool>("create");
4036 QTest::addColumn<int>("expectedShowEvents");
4037 QTest::addColumn<int>("expectedHideEvents");
4039 QTest::newRow("window: only show")
4045 QTest::newRow("window: show/hide")
4051 QTest::newRow("window: show/hide/create")
4057 QTest::newRow("window: hide/create")
4063 QTest::newRow("window: only hide")
4069 QTest::newRow("window: nothing")
4077 void tst_QWidget::showHideEvent()
4081 QFETCH(bool, create);
4082 QFETCH(int, expectedShowEvents);
4083 QFETCH(int, expectedHideEvents);
4085 ShowHideEventWidget widget;
4090 if (create && !widget.testAttribute(Qt::WA_WState_Created))
4093 QCOMPARE(widget.numberOfShowEvents, expectedShowEvents);
4094 QCOMPARE(widget.numberOfHideEvents, expectedHideEvents);
4097 void tst_QWidget::update()
4099 QTest::qWait(10); // Wait for the initStuff to do it's stuff.
4103 w.setGeometry(50, 50, 100, 100);
4105 QTest::qWaitForWindowShown(&w);
4107 QApplication::processEvents();
4108 QApplication::processEvents();
4111 QEXPECT_FAIL(0, "Cocoa compositor says to paint this twice.", Continue);
4113 QTRY_COMPARE(w.numPaintEvents, 1);
4115 QCOMPARE(w.visibleRegion(), QRegion(w.rect()));
4116 QCOMPARE(w.paintedRegion, w.visibleRegion());
4119 UpdateWidget child(&w);
4120 child.setGeometry(10, 10, 80, 80);
4123 QPoint childOffset = child.mapToParent(QPoint());
4125 // widgets are transparent by default, so both should get repaints
4127 QApplication::processEvents();
4128 QApplication::processEvents();
4129 QCOMPARE(child.numPaintEvents, 1);
4130 QCOMPARE(child.visibleRegion(), QRegion(child.rect()));
4131 QCOMPARE(child.paintedRegion, child.visibleRegion());
4132 QCOMPARE(w.numPaintEvents, 1);
4133 QCOMPARE(w.visibleRegion(), QRegion(w.rect()));
4134 QCOMPARE(w.paintedRegion, child.visibleRegion().translated(childOffset));
4140 QApplication::processEvents();
4141 QApplication::processEvents();
4142 QCOMPARE(child.numPaintEvents, 1);
4143 QCOMPARE(child.visibleRegion(), QRegion(child.rect()));
4144 QCOMPARE(child.paintedRegion, child.visibleRegion());
4145 QCOMPARE(w.numPaintEvents, 1);
4146 QCOMPARE(w.visibleRegion(), QRegion(w.rect()));
4147 QCOMPARE(w.paintedRegion, w.visibleRegion());
4150 QPalette opaquePalette = child.palette();
4151 opaquePalette.setColor(child.backgroundRole(), QColor(Qt::red));
4153 // setting an opaque background on the child should prevent paint-events
4154 // for the parent in the child area
4156 child.setPalette(opaquePalette);
4157 child.setAutoFillBackground(true);
4158 QApplication::processEvents();
4164 QApplication::processEvents();
4165 QApplication::processEvents();
4167 QCOMPARE(w.numPaintEvents, 1);
4168 QRegion expectedVisible = QRegion(w.rect())
4169 - child.visibleRegion().translated(childOffset);
4170 QCOMPARE(w.visibleRegion(), expectedVisible);
4171 QCOMPARE(w.paintedRegion, expectedVisible);
4172 QCOMPARE(child.numPaintEvents, 0);
4178 QApplication::processEvents();
4179 QApplication::processEvents();
4181 QCOMPARE(w.numPaintEvents, 0);
4182 QCOMPARE(child.numPaintEvents, 1);
4183 QCOMPARE(child.paintedRegion, child.visibleRegion());
4189 // overlapping sibling
4190 UpdateWidget sibling(&w);
4191 child.setGeometry(10, 10, 20, 20);
4192 sibling.setGeometry(15, 15, 20, 20);
4195 QApplication::processEvents();
4200 const QPoint siblingOffset = sibling.mapToParent(QPoint());
4203 QApplication::processEvents();
4204 QApplication::processEvents();
4206 // child is opaque, sibling transparent
4208 QCOMPARE(sibling.numPaintEvents, 1);
4209 QCOMPARE(sibling.paintedRegion, sibling.visibleRegion());
4211 QCOMPARE(child.numPaintEvents, 1);
4212 QCOMPARE(child.paintedRegion.translated(childOffset),
4213 child.visibleRegion().translated(childOffset)
4214 & sibling.visibleRegion().translated(siblingOffset));
4216 QCOMPARE(w.numPaintEvents, 1);
4217 QCOMPARE(w.paintedRegion,
4218 w.visibleRegion() & sibling.visibleRegion().translated(siblingOffset));
4219 QCOMPARE(w.paintedRegion,
4220 (w.visibleRegion() - child.visibleRegion().translated(childOffset))
4221 & sibling.visibleRegion().translated(siblingOffset));
4228 sibling.setPalette(opaquePalette);
4229 sibling.setAutoFillBackground(true);
4232 QApplication::processEvents();
4233 QApplication::processEvents();
4235 // child opaque, sibling opaque
4237 QCOMPARE(sibling.numPaintEvents, 1);
4238 QCOMPARE(sibling.paintedRegion, sibling.visibleRegion());
4241 if (child.internalWinId()) // child is native
4242 QEXPECT_FAIL(0, "Cocoa compositor paints child and sibling", Continue);
4244 QCOMPARE(child.numPaintEvents, 0);
4245 QCOMPARE(child.visibleRegion(),
4246 QRegion(child.rect())
4247 - sibling.visibleRegion().translated(siblingOffset - childOffset));
4249 QCOMPARE(w.numPaintEvents, 0);
4250 QCOMPARE(w.visibleRegion(),
4252 - child.visibleRegion().translated(childOffset)
4253 - sibling.visibleRegion().translated(siblingOffset));
4257 static inline bool isOpaque(QWidget *widget)
4261 return qt_widget_private(widget)->isOpaque;
4264 void tst_QWidget::isOpaque()
4268 QVERIFY(::isOpaque(&w));
4271 QVERIFY(!::isOpaque(&child));
4273 child.setAutoFillBackground(true);
4274 QVERIFY(::isOpaque(&child));
4280 palette = child.palette();
4281 palette.setColor(child.backgroundRole(), QColor(255, 0, 0, 127));
4282 child.setPalette(palette);
4283 QVERIFY(!::isOpaque(&child));
4285 palette.setColor(child.backgroundRole(), QColor(255, 0, 0, 255));
4286 child.setPalette(palette);
4287 QVERIFY(::isOpaque(&child));
4289 palette.setColor(QPalette::Window, QColor(0, 0, 255, 127));
4290 w.setPalette(palette);
4292 QVERIFY(!::isOpaque(&w));
4294 child.setAutoFillBackground(false);
4295 QVERIFY(!::isOpaque(&child));
4297 // Qt::WA_OpaquePaintEvent
4299 child.setAttribute(Qt::WA_OpaquePaintEvent);
4300 QVERIFY(::isOpaque(&child));
4302 child.setAttribute(Qt::WA_OpaquePaintEvent, false);
4303 QVERIFY(!::isOpaque(&child));
4305 // Qt::WA_NoSystemBackground
4307 child.setAttribute(Qt::WA_NoSystemBackground);
4308 QVERIFY(!::isOpaque(&child));
4310 child.setAttribute(Qt::WA_NoSystemBackground, false);
4311 QVERIFY(!::isOpaque(&child));
4313 palette.setColor(QPalette::Window, QColor(0, 0, 255, 255));
4314 w.setPalette(palette);
4315 QVERIFY(::isOpaque(&w));
4317 w.setAttribute(Qt::WA_NoSystemBackground);
4318 QVERIFY(!::isOpaque(&w));
4320 w.setAttribute(Qt::WA_NoSystemBackground, false);
4321 QVERIFY(::isOpaque(&w));
4324 QPalette palette = QApplication::palette();
4325 QPalette old = palette;
4326 palette.setColor(QPalette::Window, Qt::transparent);
4327 QApplication::setPalette(palette);
4330 QVERIFY(!::isOpaque(&widget));
4332 QApplication::setPalette(old);
4333 QCOMPARE(::isOpaque(&widget), old.color(QPalette::Window).alpha() == 255);
4340 Test that scrolling of a widget invalidates the correct regions
4342 void tst_QWidget::scroll()
4344 UpdateWidget updateWidget;
4345 updateWidget.resize(500, 500);
4346 updateWidget.reset();
4347 updateWidget.show();
4348 QTest::qWaitForWindowShown(&updateWidget);
4350 qApp->processEvents();
4351 QTRY_VERIFY(updateWidget.numPaintEvents > 0);
4354 updateWidget.reset();
4355 updateWidget.scroll(10, 10);
4356 qApp->processEvents();
4357 QRegion dirty(QRect(0, 0, 500, 10));
4358 dirty += QRegion(QRect(0, 10, 10, 490));
4359 QCOMPARE(updateWidget.paintedRegion, dirty);
4363 updateWidget.reset();
4364 updateWidget.update(0, 0, 10, 10);
4365 updateWidget.scroll(0, 10);
4366 qApp->processEvents();
4367 QRegion dirty(QRect(0, 0, 500, 10));
4368 dirty += QRegion(QRect(0, 10, 10, 10));
4369 QCOMPARE(updateWidget.paintedRegion, dirty);
4373 updateWidget.reset();
4374 updateWidget.update(0, 0, 100, 100);
4375 updateWidget.scroll(10, 10, QRect(50, 50, 100, 100));
4376 qApp->processEvents();
4377 QRegion dirty(QRect(0, 0, 100, 50));
4378 dirty += QRegion(QRect(0, 50, 150, 10));
4379 dirty += QRegion(QRect(0, 60, 110, 40));
4380 dirty += QRegion(QRect(50, 100, 60, 10));
4381 dirty += QRegion(QRect(50, 110, 10, 40));
4382 QCOMPARE(updateWidget.paintedRegion, dirty);
4386 updateWidget.reset();
4387 updateWidget.update(0, 0, 100, 100);
4388 updateWidget.scroll(10, 10, QRect(100, 100, 100, 100));
4389 qApp->processEvents();
4390 QRegion dirty(QRect(0, 0, 100, 100));
4391 dirty += QRegion(QRect(100, 100, 100, 10));
4392 dirty += QRegion(QRect(100, 110, 10, 90));
4393 QCOMPARE(updateWidget.paintedRegion, dirty);
4398 class DestroyedSlotChecker : public QObject
4405 DestroyedSlotChecker()
4411 void destroyedSlot(QObject *object)
4413 wasQWidget = (qobject_cast<QWidget *>(object) != 0 || object->isWidgetType());
4418 Test that qobject_cast<QWidget*> returns 0 in a slot
4419 connected to QObject::destroyed.
4421 void tst_QWidget::qobject_castInDestroyedSlot()
4423 DestroyedSlotChecker checker;
4424 QWidget *widget = new QWidget();
4426 QObject::connect(widget, SIGNAL(destroyed(QObject *)), &checker, SLOT(destroyedSlot(QObject *)));
4429 QVERIFY(checker.wasQWidget == true);
4432 Q_DECLARE_METATYPE(QList<QRect>)
4434 // Since X11 WindowManager operations are all async, and we have no way to know if the window
4435 // manager has finished playing with the window geometry, this test can't be reliable on X11.
4437 void tst_QWidget::setWindowGeometry_data()
4439 QTest::addColumn<QList<QRect> >("rects");
4440 QTest::addColumn<int>("windowFlags");
4442 QList<QList<QRect> > rects;
4443 rects << (QList<QRect>()
4444 << QRect(100, 100, 200, 200)
4445 << QApplication::desktop()->availableGeometry().adjusted(100, 100, -100, -100)
4446 << QRect(130, 100, 0, 200)
4447 << QRect(100, 50, 200, 0)
4448 << QRect(130, 50, 0, 0))
4450 << QApplication::desktop()->availableGeometry().adjusted(100, 100, -100, -100)
4451 << QRect(130, 100, 0, 200)
4452 << QRect(100, 50, 200, 0)
4453 << QRect(130, 50, 0, 0)
4454 << QRect(100, 100, 200, 200))
4456 << QRect(130, 100, 0, 200)
4457 << QRect(100, 50, 200, 0)
4458 << QRect(130, 50, 0, 0)
4459 << QRect(100, 100, 200, 200)
4460 << QApplication::desktop()->availableGeometry().adjusted(100, 100, -100, -100))
4462 << QRect(100, 50, 200, 0)
4463 << QRect(130, 50, 0, 0)
4464 << QRect(100, 100, 200, 200)
4465 << QApplication::desktop()->availableGeometry().adjusted(100, 100, -100, -100)
4466 << QRect(130, 100, 0, 200))
4468 << QRect(130, 50, 0, 0)
4469 << QRect(100, 100, 200, 200)
4470 << QApplication::desktop()->availableGeometry().adjusted(100, 100, -100, -100)
4471 << QRect(130, 100, 0, 200)
4472 << QRect(100, 50, 200, 0));
4474 QList<int> windowFlags;
4475 windowFlags << 0 << Qt::FramelessWindowHint;
4477 foreach (QList<QRect> l, rects) {
4478 QRect rect = l.first();
4479 foreach (int windowFlag, windowFlags) {
4480 QTest::newRow(QString("%1,%2 %3x%4, flags %5")
4485 .arg(windowFlag, 0, 16).toAscii())
4492 void tst_QWidget::setWindowGeometry()
4494 QFETCH(QList<QRect>, rects);
4495 QFETCH(int, windowFlags);
4496 QRect rect = rects.takeFirst();
4499 // test setGeometry() without actually showing the window
4501 if (windowFlags != 0)
4502 widget.setWindowFlags(Qt::WindowFlags(windowFlags));
4504 widget.setGeometry(rect);
4506 QCOMPARE(widget.geometry(), rect);
4508 // setGeometry() without showing
4509 foreach (QRect r, rects) {
4510 widget.setGeometry(r);
4512 QCOMPARE(widget.geometry(), r);
4517 // setGeometry() first, then show()
4519 if (windowFlags != 0)
4520 widget.setWindowFlags(Qt::WindowFlags(windowFlags));
4522 widget.setGeometry(rect);
4524 QTest::qWaitForWindowShown(&widget);
4526 QTRY_COMPARE(widget.geometry(), rect);
4528 // setGeometry() while shown
4529 foreach (QRect r, rects) {
4530 widget.setGeometry(r);
4532 QTRY_COMPARE(widget.geometry(), r);
4534 widget.setGeometry(rect);
4536 QTRY_COMPARE(widget.geometry(), rect);
4541 QTRY_COMPARE(widget.geometry(), rect);
4543 // setGeometry() after hide()
4544 foreach (QRect r, rects) {
4545 widget.setGeometry(r);
4547 QTRY_COMPARE(widget.geometry(), r);
4549 widget.setGeometry(rect);
4551 QTRY_COMPARE(widget.geometry(), rect);
4553 // show() again, geometry() should still be the same
4555 QTest::qWaitForWindowShown(&widget);
4557 QTRY_COMPARE(widget.geometry(), rect);
4559 // final hide(), again geometry() should be unchanged
4562 QTRY_COMPARE(widget.geometry(), rect);
4566 // show() first, then setGeometry()
4568 if (windowFlags != 0)
4569 widget.setWindowFlags(Qt::WindowFlags(windowFlags));
4572 QTest::qWaitForWindowShown(&widget);
4573 widget.setGeometry(rect);
4575 QTRY_COMPARE(widget.geometry(), rect);
4577 // setGeometry() while shown
4578 foreach (QRect r, rects) {
4579 widget.setGeometry(r);
4581 QTRY_COMPARE(widget.geometry(), r);
4583 widget.setGeometry(rect);
4585 QTRY_COMPARE(widget.geometry(), rect);
4590 QTRY_COMPARE(widget.geometry(), rect);
4592 // setGeometry() after hide()
4593 foreach (QRect r, rects) {
4594 widget.setGeometry(r);
4596 QTRY_COMPARE(widget.geometry(), r);
4598 widget.setGeometry(rect);
4600 QTRY_COMPARE(widget.geometry(), rect);
4602 // show() again, geometry() should still be the same
4604 QTest::qWaitForWindowShown(&widget);
4606 QTRY_COMPARE(widget.geometry(), rect);
4608 // final hide(), again geometry() should be unchanged
4611 QTRY_COMPARE(widget.geometry(), rect);
4616 #if defined (Q_WS_WIN) && !defined(Q_OS_WINCE)
4617 void tst_QWidget::setGeometry_win()
4620 widget.setGeometry(0, 600, 100,100);
4622 widget.setWindowState(widget.windowState() | Qt::WindowMaximized);
4623 QRect geom = widget.normalGeometry();
4625 widget.setGeometry(geom);
4626 widget.setWindowState(widget.windowState() | Qt::WindowMaximized);
4629 ::GetWindowRect(widget.internalWinId(), &rt);
4630 QVERIFY(rt.left <= 0);
4631 QVERIFY(rt.top <= 0);
4635 // Since X11 WindowManager operation are all async, and we have no way to know if the window
4636 // manager has finished playing with the window geometry, this test can't be reliable on X11.
4637 // 4DWM issues on IRIX also makes this test fail.
4638 #if !defined(Q_WS_X11) && !defined(Q_OS_IRIX)
4639 void tst_QWidget::windowMoveResize_data()
4641 setWindowGeometry_data();
4644 void tst_QWidget::windowMoveResize()
4646 QFETCH(QList<QRect>, rects);
4647 QFETCH(int, windowFlags);
4649 QRect rect = rects.takeFirst();
4652 // test setGeometry() without actually showing the window
4654 if (windowFlags != 0)
4655 widget.setWindowFlags(Qt::WindowFlags(windowFlags));
4657 widget.move(rect.topLeft());
4658 widget.resize(rect.size());
4660 QTRY_COMPARE(widget.pos(), rect.topLeft());
4661 QTRY_COMPARE(widget.size(), rect.size());
4663 // move() without showing
4664 foreach (QRect r, rects) {
4665 widget.move(r.topLeft());
4666 widget.resize(r.size());
4667 QApplication::processEvents();
4668 QTRY_COMPARE(widget.pos(), r.topLeft());
4669 QTRY_COMPARE(widget.size(), r.size());
4674 // move() first, then show()
4676 if (windowFlags != 0)
4677 widget.setWindowFlags(Qt::WindowFlags(windowFlags));
4679 widget.move(rect.topLeft());
4680 widget.resize(rect.size());
4684 QTRY_COMPARE(widget.pos(), rect.topLeft());
4685 QTRY_COMPARE(widget.size(), rect.size());
4687 // move() while shown
4688 foreach (QRect r, rects) {
4690 if ((widget.width() == 0 || widget.height() == 0) && r.width() != 0 && r.height() != 0) {
4691 QEXPECT_FAIL("130,100 0x200, flags 0",
4692 "First resize after show of zero-sized gets wrong win_gravity.",
4694 QEXPECT_FAIL("100,50 200x0, flags 0",
4695 "First resize after show of zero-sized gets wrong win_gravity.",
4697 QEXPECT_FAIL("130,50 0x0, flags 0",
4698 "First resize after show of zero-sized gets wrong win_gravity.",
4702 widget.move(r.topLeft());
4703 widget.resize(r.size());
4704 QApplication::processEvents();
4705 QTRY_COMPARE(widget.pos(), r.topLeft());
4706 QTRY_COMPARE(widget.size(), r.size());
4708 widget.move(rect.topLeft());
4709 widget.resize(rect.size());
4710 QApplication::processEvents();
4711 QTRY_COMPARE(widget.pos(), rect.topLeft());
4712 QTRY_COMPARE(widget.size(), rect.size());
4717 QTRY_COMPARE(widget.pos(), rect.topLeft());
4718 QTRY_COMPARE(widget.size(), rect.size());
4720 // move() after hide()
4721 foreach (QRect r, rects) {
4722 widget.move(r.topLeft());
4723 widget.resize(r.size());
4724 QApplication::processEvents();
4725 #if defined(Q_OS_MAC)
4726 if (r.width() == 0 && r.height() > 0) {
4727 widget.move(r.topLeft());
4728 widget.resize(r.size());
4731 QTRY_COMPARE(widget.pos(), r.topLeft());
4732 QTRY_COMPARE(widget.size(), r.size());
4734 widget.move(rect.topLeft());
4735 widget.resize(rect.size());
4737 QTRY_COMPARE(widget.pos(), rect.topLeft());
4738 QTRY_COMPARE(widget.size(), rect.size());
4740 // show() again, pos() should be the same
4742 QTest::qWaitForWindowShown(&widget);
4743 QApplication::processEvents();
4744 QTRY_COMPARE(widget.pos(), rect.topLeft());
4745 QTRY_COMPARE(widget.size(), rect.size());
4747 // final hide(), again pos() should be unchanged
4749 QApplication::processEvents();
4750 QTRY_COMPARE(widget.pos(), rect.topLeft());
4751 QTRY_COMPARE(widget.size(), rect.size());
4755 // show() first, then move()
4757 if (windowFlags != 0)
4758 widget.setWindowFlags(Qt::WindowFlags(windowFlags));
4761 QTest::qWaitForWindowShown(&widget);
4762 QApplication::processEvents();
4763 widget.move(rect.topLeft());
4764 widget.resize(rect.size());
4765 QApplication::processEvents();
4766 QTRY_COMPARE(widget.pos(), rect.topLeft());
4767 QTRY_COMPARE(widget.size(), rect.size());
4769 // move() while shown
4770 foreach (QRect r, rects) {
4771 widget.move(r.topLeft());
4772 widget.resize(r.size());
4773 QApplication::processEvents();
4774 QTRY_COMPARE(widget.pos(), r.topLeft());
4775 QTRY_COMPARE(widget.size(), r.size());
4777 widget.move(rect.topLeft());
4778 widget.resize(rect.size());
4779 QApplication::processEvents();
4780 QTRY_COMPARE(widget.pos(), rect.topLeft());
4781 QTRY_COMPARE(widget.size(), rect.size());
4785 QApplication::processEvents();
4786 QTRY_COMPARE(widget.pos(), rect.topLeft());
4787 QTRY_COMPARE(widget.size(), rect.size());
4789 // move() after hide()
4790 foreach (QRect r, rects) {
4791 widget.move(r.topLeft());
4792 widget.resize(r.size());
4793 QApplication::processEvents();
4794 #if defined(Q_OS_MAC)
4795 if (r.width() == 0 && r.height() > 0) {
4796 widget.move(r.topLeft());
4797 widget.resize(r.size());
4800 QTRY_COMPARE(widget.pos(), r.topLeft());
4801 QTRY_COMPARE(widget.size(), r.size());
4803 widget.move(rect.topLeft());
4804 widget.resize(rect.size());
4805 QApplication::processEvents();
4806 QTRY_COMPARE(widget.pos(), rect.topLeft());
4807 QTRY_COMPARE(widget.size(), rect.size());
4809 // show() again, pos() should be the same
4811 QTest::qWaitForWindowShown(&widget);
4813 QTRY_COMPARE(widget.pos(), rect.topLeft());
4814 QTRY_COMPARE(widget.size(), rect.size());
4816 // final hide(), again pos() should be unchanged
4819 QTRY_COMPARE(widget.pos(), rect.topLeft());
4820 QTRY_COMPARE(widget.size(), rect.size());
4825 class ColorWidget : public QWidget
4828 ColorWidget(QWidget *parent = 0, const QColor &c = QColor(Qt::red))
4829 : QWidget(parent, Qt::FramelessWindowHint), color(c)
4831 QPalette opaquePalette = palette();
4832 opaquePalette.setColor(backgroundRole(), color);
4833 setPalette(opaquePalette);
4834 setAutoFillBackground(true);
4837 void paintEvent(QPaintEvent *e) {
4849 #define VERIFY_COLOR(region, color) { \
4850 const QRegion r = QRegion(region); \
4851 for (int i = 0; i < r.rects().size(); ++i) { \
4852 const QRect rect = r.rects().at(i); \
4853 for (int t = 0; t < 5; t++) { \
4854 const QPixmap pixmap = QPixmap::grabWindow(QDesktopWidget().winId(), \
4855 rect.left(), rect.top(), \
4856 rect.width(), rect.height()); \
4857 QCOMPARE(pixmap.size(), rect.size()); \
4858 QPixmap expectedPixmap(pixmap); /* ensure equal formats */ \
4859 expectedPixmap.detach(); \
4860 expectedPixmap.fill(color); \
4861 QImage image = pixmap.toImage(); \
4862 uint alphaCorrection = image.format() == QImage::Format_RGB32 ? 0xff000000 : 0; \
4863 uint firstPixel = image.pixel(0,0) | alphaCorrection; \
4864 if ( firstPixel != QColor(color).rgb() && t < 4 ) \
4865 { QTest::qWait(200); continue; } \
4866 QCOMPARE(firstPixel, QColor(color).rgb()); \
4867 QCOMPARE(pixmap, expectedPixmap); \
4873 void tst_QWidget::moveChild_data()
4875 QTest::addColumn<QPoint>("offset");
4877 QTest::newRow("right") << QPoint(20, 0);
4878 QTest::newRow("down") << QPoint(0, 20);
4879 QTest::newRow("left") << QPoint(-20, 0);
4880 QTest::newRow("up") << QPoint(0, -20);
4883 void tst_QWidget::moveChild()
4885 QFETCH(QPoint, offset);
4888 // prevent custom styles
4889 parent.setStyle(new QWindowsStyle);
4890 ColorWidget child(&parent, Qt::blue);
4893 parent.setGeometry(QRect(QPoint(QApplication::desktop()->availableGeometry(&parent).topLeft()),
4896 parent.setGeometry(60, 60, 150, 150);
4898 child.setGeometry(25, 25, 50, 50);
4900 QTest::qWaitForWindowShown(&parent);
4902 const QPoint tlwOffset = parent.geometry().topLeft();
4904 QTRY_COMPARE(parent.r, QRegion(parent.rect()) - child.geometry());
4905 QTRY_COMPARE(child.r, QRegion(child.rect()));
4906 VERIFY_COLOR(child.geometry().translated(tlwOffset),
4908 VERIFY_COLOR(QRegion(parent.geometry()) - child.geometry().translated(tlwOffset),
4915 const QRect oldGeometry = child.geometry();
4917 QPoint pos = child.pos() + offset;
4920 QTRY_COMPARE(pos, child.pos());
4922 QCOMPARE(parent.r, QRegion(oldGeometry) - child.geometry());
4923 #if !defined(Q_OS_MAC)
4924 // should be scrolled in backingstore
4925 QCOMPARE(child.r, QRegion());
4927 VERIFY_COLOR(child.geometry().translated(tlwOffset),
4929 VERIFY_COLOR(QRegion(parent.geometry()) - child.geometry().translated(tlwOffset),
4933 void tst_QWidget::showAndMoveChild()
4935 QWidget parent(0, Qt::FramelessWindowHint);
4936 // prevent custom styles
4937 parent.setStyle(new QWindowsStyle);
4939 QDesktopWidget desktop;
4940 QRect desktopDimensions = desktop.availableGeometry(&parent);
4941 desktopDimensions = desktopDimensions.adjusted(64, 64, -64, -64);
4943 parent.setGeometry(desktopDimensions);
4944 parent.setPalette(Qt::red);
4946 QTest::qWaitForWindowShown(&parent);
4949 const QPoint tlwOffset = parent.geometry().topLeft();
4950 QWidget child(&parent);
4951 child.resize(desktopDimensions.width()/2, desktopDimensions.height()/2);
4952 child.setPalette(Qt::blue);
4953 child.setAutoFillBackground(true);
4955 // Ensure that the child is repainted correctly when moved right after show.
4956 // NB! Do NOT processEvents() (or qWait()) in between show() and move().
4958 child.move(desktopDimensions.width()/2, desktopDimensions.height()/2);
4959 qApp->processEvents();
4961 VERIFY_COLOR(child.geometry().translated(tlwOffset), Qt::blue);
4962 VERIFY_COLOR(QRegion(parent.geometry()) - child.geometry().translated(tlwOffset), Qt::red);
4965 // Cocoa only has rect granularity.
4967 void tst_QWidget::subtractOpaqueSiblings()
4970 w.setGeometry(50, 50, 300, 300);
4972 ColorWidget *large = new ColorWidget(&w, Qt::red);
4973 large->setGeometry(50, 50, 200, 200);
4975 ColorWidget *medium = new ColorWidget(large, Qt::gray);
4976 medium->setGeometry(50, 50, 100, 100);
4978 ColorWidget *tall = new ColorWidget(&w, Qt::blue);
4979 tall->setGeometry(100, 30, 50, 100);
4982 QTest::qWaitForWindowShown(&w);
4992 // QWidgetPrivate::subtractOpaqueSiblings() should prevent parts of medium
4993 // to be repainted and tall from be repainted at all.
4995 QTRY_COMPARE(large->r, QRegion());
4996 QTRY_COMPARE(tall->r, QRegion());
4997 QTRY_COMPARE(medium->r.translated(medium->mapTo(&w, QPoint())),
4998 QRegion(medium->geometry().translated(large->pos()))
4999 - tall->geometry());
5003 void tst_QWidget::deleteStyle()
5006 widget.setStyle(new QWindowsStyle);
5008 delete widget.style();
5009 qApp->processEvents();
5013 void tst_QWidget::getDC()
5016 widget.setGeometry(0, 0, 2, 4);
5018 HDC dc = widget.getDC();
5021 widget.releaseDC(dc);
5025 class TopLevelFocusCheck: public QWidget
5030 TopLevelFocusCheck(QWidget* parent = 0) : QWidget(parent)
5032 edit = new QLineEdit(this);
5034 edit->installEventFilter(this);
5038 void mouseDoubleClickEvent ( QMouseEvent * /*event*/ )
5041 edit->setFocus(Qt::OtherFocusReason);
5042 qApp->processEvents();
5044 bool eventFilter(QObject *obj, QEvent *event)
5046 if (obj == edit && event->type()== QEvent::FocusOut) {
5054 void tst_QWidget::multipleToplevelFocusCheck()
5056 TopLevelFocusCheck w1;
5057 TopLevelFocusCheck w2;
5059 w1.resize(200, 200);
5061 QTest::qWaitForWindowShown(&w1);
5064 QTest::qWaitForWindowShown(&w2);
5068 QApplication::setActiveWindow(&w1);
5069 w1.activateWindow();
5070 QApplication::processEvents();
5071 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&w1));
5073 QTest::mouseDClick(&w1, Qt::LeftButton);
5074 QTRY_COMPARE(QApplication::focusWidget(), static_cast<QWidget *>(w1.edit));
5076 w2.activateWindow();
5077 QApplication::setActiveWindow(&w2);
5078 QApplication::processEvents();
5079 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&w2));
5080 QTest::mouseClick(&w2, Qt::LeftButton);
5082 QEXPECT_FAIL("", "embedded toplevels take focus anyway", Continue);
5084 QTRY_COMPARE(QApplication::focusWidget(), (QWidget *)0);
5086 QTest::mouseDClick(&w2, Qt::LeftButton);
5087 QTRY_COMPARE(QApplication::focusWidget(), static_cast<QWidget *>(w2.edit));
5089 w1.activateWindow();
5090 QApplication::setActiveWindow(&w1);
5091 QApplication::processEvents();
5092 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&w1));
5093 QTest::mouseDClick(&w1, Qt::LeftButton);
5094 QTRY_COMPARE(QApplication::focusWidget(), static_cast<QWidget *>(w1.edit));
5096 w2.activateWindow();
5097 QApplication::setActiveWindow(&w2);
5098 QApplication::processEvents();
5099 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&w2));
5100 QTest::mouseClick(&w2, Qt::LeftButton);
5101 QTRY_COMPARE(QApplication::focusWidget(), (QWidget *)0);
5104 void tst_QWidget::setFocus()
5107 // move focus to another window
5108 testWidget->activateWindow();
5109 QApplication::setActiveWindow(testWidget);
5110 if (testWidget->focusWidget())
5111 testWidget->focusWidget()->clearFocus();
5113 testWidget->clearFocus();
5115 // window and children never shown, nobody gets focus
5118 QWidget child1(&window);
5119 child1.setFocusPolicy(Qt::StrongFocus);
5121 QWidget child2(&window);
5122 child2.setFocusPolicy(Qt::StrongFocus);
5125 QVERIFY(!child1.hasFocus());
5126 QCOMPARE(window.focusWidget(), &child1);
5127 QCOMPARE(QApplication::focusWidget(), static_cast<QWidget *>(0));
5130 QVERIFY(!child2.hasFocus());
5131 QCOMPARE(window.focusWidget(), &child2);
5132 QCOMPARE(QApplication::focusWidget(), static_cast<QWidget *>(0));
5136 // window and children show, but window not active, nobody gets focus
5139 QWidget child1(&window);
5140 child1.setFocusPolicy(Qt::StrongFocus);
5142 QWidget child2(&window);
5143 child2.setFocusPolicy(Qt::StrongFocus);
5147 // note: window may be active, but we don't want it to be
5148 testWidget->activateWindow();
5149 QApplication::setActiveWindow(testWidget);
5150 if (testWidget->focusWidget())
5151 testWidget->focusWidget()->clearFocus();
5153 testWidget->clearFocus();
5156 QVERIFY(!child1.hasFocus());
5157 QCOMPARE(window.focusWidget(), &child1);
5158 QCOMPARE(QApplication::focusWidget(), static_cast<QWidget *>(0));
5161 QVERIFY(!child2.hasFocus());
5162 QCOMPARE(window.focusWidget(), &child2);
5163 QCOMPARE(QApplication::focusWidget(), static_cast<QWidget *>(0));
5167 // window and children show, but window *is* active, children get focus
5170 QWidget child1(&window);
5171 child1.setFocusPolicy(Qt::StrongFocus);
5173 QWidget child2(&window);
5174 child2.setFocusPolicy(Qt::StrongFocus);
5178 QApplication::setActiveWindow(&window);
5179 QTest::qWaitForWindowShown(&window);
5181 window.activateWindow();
5182 QApplication::processEvents();
5186 QTRY_VERIFY(child1.hasFocus());
5187 QCOMPARE(window.focusWidget(), &child1);
5188 QCOMPARE(QApplication::focusWidget(), &child1);
5191 QVERIFY(child2.hasFocus());
5192 QCOMPARE(window.focusWidget(), &child2);
5193 QCOMPARE(QApplication::focusWidget(), &child2);
5197 // window shown and active, children created, don't get focus, but get focus when shown
5202 QApplication::setActiveWindow(&window);
5203 QTest::qWaitForWindowShown(&window);
5205 window.activateWindow();
5208 QWidget child1(&window);
5209 child1.setFocusPolicy(Qt::StrongFocus);
5211 QWidget child2(&window);
5212 child2.setFocusPolicy(Qt::StrongFocus);
5215 QVERIFY(!child1.hasFocus());
5216 QCOMPARE(window.focusWidget(), static_cast<QWidget *>(0));
5217 QCOMPARE(QApplication::focusWidget(), static_cast<QWidget *>(0));
5221 QApplication::setActiveWindow(&child1);
5222 child1.activateWindow();
5224 QApplication::processEvents();
5225 QTRY_VERIFY(child1.hasFocus());
5226 QCOMPARE(window.focusWidget(), &child1);
5227 QCOMPARE(QApplication::focusWidget(), &child1);
5230 QVERIFY(!child2.hasFocus());
5231 QCOMPARE(window.focusWidget(), &child1);
5232 QCOMPARE(QApplication::focusWidget(), &child1);
5235 QVERIFY(child2.hasFocus());
5236 QCOMPARE(window.focusWidget(), &child2);
5237 QCOMPARE(QApplication::focusWidget(), &child2);
5241 // window shown and active, children created, don't get focus,
5242 // even after setFocus(), hide(), then show()
5247 QApplication::setActiveWindow(&window);
5248 QTest::qWaitForWindowShown(&window);
5250 window.activateWindow();
5253 QWidget child1(&window);
5254 child1.setFocusPolicy(Qt::StrongFocus);
5256 QWidget child2(&window);
5257 child2.setFocusPolicy(Qt::StrongFocus);
5260 QVERIFY(!child1.hasFocus());
5261 QCOMPARE(window.focusWidget(), static_cast<QWidget *>(0));
5262 QCOMPARE(QApplication::focusWidget(), static_cast<QWidget *>(0));
5265 QVERIFY(!child1.hasFocus());
5266 QCOMPARE(window.focusWidget(), static_cast<QWidget *>(0));
5267 QCOMPARE(QApplication::focusWidget(), static_cast<QWidget *>(0));
5270 QVERIFY(!child1.hasFocus());
5271 QCOMPARE(window.focusWidget(), static_cast<QWidget *>(0));
5272 QCOMPARE(QApplication::focusWidget(), static_cast<QWidget *>(0));
5275 QVERIFY(!child2.hasFocus());
5276 QCOMPARE(window.focusWidget(), static_cast<QWidget *>(0));
5277 QCOMPARE(QApplication::focusWidget(), static_cast<QWidget *>(0));
5280 QVERIFY(!child2.hasFocus());
5281 QCOMPARE(window.focusWidget(), static_cast<QWidget *>(0));
5282 QCOMPARE(QApplication::focusWidget(), static_cast<QWidget *>(0));
5285 QVERIFY(!child2.hasFocus());
5286 QCOMPARE(window.focusWidget(), static_cast<QWidget *>(0));
5287 QCOMPARE(QApplication::focusWidget(), static_cast<QWidget *>(0));
5291 class EventSpy : public QObject
5294 EventSpy(QWidget *widget, QEvent::Type event)
5295 : m_widget(widget), eventToSpy(event), m_count(0)
5298 m_widget->installEventFilter(this);
5301 QWidget *widget() const { return m_widget; }
5302 int count() const { return m_count; }
5303 void clear() { m_count = 0; }
5306 bool eventFilter(QObject *object, QEvent *event)
5308 if (event->type() == eventToSpy)
5310 return QObject::eventFilter(object, event);
5315 QEvent::Type eventToSpy;
5319 void tst_QWidget::setCursor()
5321 #ifndef QT_NO_CURSOR
5324 QWidget child(&window);
5326 QVERIFY(!window.testAttribute(Qt::WA_SetCursor));
5327 QVERIFY(!child.testAttribute(Qt::WA_SetCursor));
5329 window.setCursor(window.cursor());
5330 QVERIFY(window.testAttribute(Qt::WA_SetCursor));
5331 QVERIFY(!child.testAttribute(Qt::WA_SetCursor));
5332 QCOMPARE(child.cursor().shape(), window.cursor().shape());
5335 // do it again, but with window show()n
5338 QWidget child(&window);
5341 QVERIFY(!window.testAttribute(Qt::WA_SetCursor));
5342 QVERIFY(!child.testAttribute(Qt::WA_SetCursor));
5344 window.setCursor(window.cursor());
5345 QVERIFY(window.testAttribute(Qt::WA_SetCursor));
5346 QVERIFY(!child.testAttribute(Qt::WA_SetCursor));
5347 QCOMPARE(child.cursor().shape(), window.cursor().shape());
5353 QWidget child(&window);
5355 window.setCursor(Qt::WaitCursor);
5356 QVERIFY(window.testAttribute(Qt::WA_SetCursor));
5357 QVERIFY(!child.testAttribute(Qt::WA_SetCursor));
5358 QCOMPARE(child.cursor().shape(), window.cursor().shape());
5361 // same thing again, just with window show()n
5364 QWidget child(&window);
5367 window.setCursor(Qt::WaitCursor);
5368 QVERIFY(window.testAttribute(Qt::WA_SetCursor));
5369 QVERIFY(!child.testAttribute(Qt::WA_SetCursor));
5370 QCOMPARE(child.cursor().shape(), window.cursor().shape());
5373 // reparenting child should not cause the WA_SetCursor to become set
5377 QWidget child(&window);
5379 window.setCursor(Qt::WaitCursor);
5382 QVERIFY(!child.testAttribute(Qt::WA_SetCursor));
5383 QCOMPARE(child.cursor().shape(), QCursor().shape());
5385 child.setParent(&window2);
5386 QVERIFY(!child.testAttribute(Qt::WA_SetCursor));
5387 QCOMPARE(child.cursor().shape(), window2.cursor().shape());
5389 window2.setCursor(Qt::WaitCursor);
5390 QVERIFY(!child.testAttribute(Qt::WA_SetCursor));
5391 QCOMPARE(child.cursor().shape(), window2.cursor().shape());
5394 // again, with windows show()n
5398 QWidget child(&window);
5400 window.setCursor(Qt::WaitCursor);
5404 QVERIFY(!child.testAttribute(Qt::WA_SetCursor));
5405 QCOMPARE(child.cursor().shape(), QCursor().shape());
5407 child.setParent(&window2);
5408 QVERIFY(!child.testAttribute(Qt::WA_SetCursor));
5409 QCOMPARE(child.cursor().shape(), window2.cursor().shape());
5412 window2.setCursor(Qt::WaitCursor);
5413 QVERIFY(!child.testAttribute(Qt::WA_SetCursor));
5414 QCOMPARE(child.cursor().shape(), window2.cursor().shape());
5417 // test if CursorChange is sent
5420 EventSpy spy(&widget, QEvent::CursorChange);
5421 QCOMPARE(spy.count(), 0);
5422 widget.setCursor(QCursor(Qt::WaitCursor));
5423 QCOMPARE(spy.count(), 1);
5424 widget.unsetCursor();
5425 QCOMPARE(spy.count(), 2);
5430 void tst_QWidget::setToolTip()
5433 EventSpy spy(&widget, QEvent::ToolTipChange);
5434 QCOMPARE(spy.count(), 0);
5436 QCOMPARE(widget.toolTip(), QString());
5437 widget.setToolTip(QString("Hello"));
5438 QCOMPARE(widget.toolTip(), QString("Hello"));
5439 QCOMPARE(spy.count(), 1);
5440 widget.setToolTip(QString());
5441 QCOMPARE(widget.toolTip(), QString());
5442 QCOMPARE(spy.count(), 2);
5444 // Mouse over doesn't work on Windows mobile, so skip the rest of the test for that platform.
5445 #ifndef Q_OS_WINCE_WM
5446 for (int pass = 0; pass < 2; ++pass) {
5447 QWidget *popup = new QWidget(0, Qt::Popup);
5448 popup->resize(150, 50);
5449 QFrame *frame = new QFrame(popup);
5450 frame->setGeometry(0, 0, 50, 50);
5451 frame->setFrameStyle(QFrame::Box | QFrame::Plain);
5452 EventSpy spy1(frame, QEvent::ToolTip);
5453 EventSpy spy2(popup, QEvent::ToolTip);
5454 frame->setMouseTracking(pass == 0 ? false : true);
5455 frame->setToolTip(QLatin1String("TOOLTIP FRAME"));
5456 popup->setToolTip(QLatin1String("TOOLTIP POPUP"));
5458 QTest::qWaitForWindowShown(popup);
5460 QTest::mouseMove(frame);
5461 QTest::qWait(900); // delay is 700
5463 QCOMPARE(spy1.count(), 1);
5464 QCOMPARE(spy2.count(), 0);
5466 QTest::qWait(2200); // delay is 2000
5467 QTest::mouseMove(popup);
5473 void tst_QWidget::testWindowIconChangeEventPropagation()
5475 // Create widget hierarchy.
5476 QWidget topLevelWidget;
5477 QWidget topLevelChild(&topLevelWidget);
5479 QDialog dialog(&topLevelWidget);
5480 QWidget dialogChild(&dialog);
5482 QWidgetList widgets;
5483 widgets << &topLevelWidget << &topLevelChild
5484 << &dialog << &dialogChild;
5485 QCOMPARE(widgets.count(), 4);
5487 // Create spy lists.
5488 QList <EventSpy *> applicationEventSpies;
5489 QList <EventSpy *> widgetEventSpies;
5490 foreach (QWidget *widget, widgets) {
5491 applicationEventSpies.append(new EventSpy(widget, QEvent::ApplicationWindowIconChange));
5492 widgetEventSpies.append(new EventSpy(widget, QEvent::WindowIconChange));
5495 // QApplication::setWindowIcon
5496 const QIcon windowIcon = qApp->style()->standardIcon(QStyle::SP_TitleBarMenuButton);
5497 qApp->setWindowIcon(windowIcon);
5499 for (int i = 0; i < widgets.count(); ++i) {
5500 // Check QEvent::ApplicationWindowIconChange
5501 EventSpy *spy = applicationEventSpies.at(i);
5502 QWidget *widget = spy->widget();
5503 if (widget->isWindow()) {
5504 QCOMPARE(spy->count(), 1);
5505 QCOMPARE(widget->windowIcon(), windowIcon);
5507 QCOMPARE(spy->count(), 0);
5511 // Check QEvent::WindowIconChange
5512 spy = widgetEventSpies.at(i);
5513 QCOMPARE(spy->count(), 1);
5517 // Set icon on a top-level widget.
5518 topLevelWidget.setWindowIcon(*new QIcon);
5520 for (int i = 0; i < widgets.count(); ++i) {
5521 // Check QEvent::ApplicationWindowIconChange
5522 EventSpy *spy = applicationEventSpies.at(i);
5523 QCOMPARE(spy->count(), 0);
5526 // Check QEvent::WindowIconChange
5527 spy = widgetEventSpies.at(i);
5528 QWidget *widget = spy->widget();
5529 if (widget == &topLevelWidget) {
5530 QCOMPARE(widget->windowIcon(), QIcon());
5531 QCOMPARE(spy->count(), 1);
5532 } else if (topLevelWidget.isAncestorOf(widget)) {
5533 QCOMPARE(spy->count(), 1);
5535 QCOMPARE(spy->count(), 0);
5541 for (int i = 0; i < widgets.count(); ++i) {
5542 delete applicationEventSpies.at(i);
5543 delete widgetEventSpies.at(i);
5545 qApp->setWindowIcon(QIcon());
5549 void tst_QWidget::minAndMaxSizeWithX11BypassWindowManagerHint()
5551 // Same size as in QWidget::create_sys().
5552 const QSize desktopSize = QApplication::desktop()->size();
5553 const QSize originalSize(desktopSize.width() / 2, desktopSize.height() * 4 / 10);
5556 QWidget widget(0, Qt::X11BypassWindowManagerHint);
5558 const QSize newMaximumSize = widget.size().boundedTo(originalSize) - QSize(10, 10);
5559 widget.setMaximumSize(newMaximumSize);
5560 QCOMPARE(widget.size(), newMaximumSize);
5563 qt_x11_wait_for_window_manager(&widget);
5564 QCOMPARE(widget.size(), newMaximumSize);
5568 QWidget widget(0, Qt::X11BypassWindowManagerHint);
5570 const QSize newMinimumSize = widget.size().expandedTo(originalSize) + QSize(10, 10);
5571 widget.setMinimumSize(newMinimumSize);
5572 QCOMPARE(widget.size(), newMinimumSize);
5575 qt_x11_wait_for_window_manager(&widget);
5576 QCOMPARE(widget.size(), newMinimumSize);
5580 class ShowHideShowWidget : public QWidget
5586 bool gotExpectedMapNotify;
5588 ShowHideShowWidget()
5589 : state(0), gotExpectedMapNotify(false)
5594 void timerEvent(QTimerEvent *)
5606 bool x11Event(XEvent *event)
5608 if (state == 1 && event->type == MapNotify)
5609 gotExpectedMapNotify = true;
5617 void tst_QWidget::showHideShow()
5619 ShowHideShowWidget w;
5623 QEventLoop eventLoop;
5624 connect(&w, SIGNAL(done()), &eventLoop, SLOT(quit()));
5627 QVERIFY(w.gotExpectedMapNotify);
5630 void tst_QWidget::clean_qt_x11_enforce_cursor()
5634 QWidget *w = new QWidget(&window);
5635 QWidget *child = new QWidget(w);
5636 child->setAttribute(Qt::WA_SetCursor, true);
5639 QApplication::setActiveWindow(&window);
5640 QTest::qWaitForWindowShown(&window);
5642 QCursor::setPos(window.geometry().center());
5646 QApplication::processEvents();
5652 QGraphicsScene scene;
5653 QLineEdit *edit = new QLineEdit;
5654 scene.addWidget(edit);
5656 // If the test didn't crash, then it passed.
5660 class EventRecorder : public QObject
5665 typedef QList<QPair<QWidget *, QEvent::Type> > EventList;
5667 EventRecorder(QObject *parent = 0)
5671 EventList eventList()
5681 bool eventFilter(QObject *object, QEvent *event)
5683 QWidget *widget = qobject_cast<QWidget *>(object);
5684 if (widget && !event->spontaneous())
5685 events.append(qMakePair(widget, event->type()));
5693 void tst_QWidget::childEvents()
5695 EventRecorder::EventList expected;
5696 bool accessibilityEnabled = false;
5698 // Move away the cursor; otherwise it might result in an enter event if it's
5699 // inside the widget when the widget is shown.
5700 QCursor::setPos(qApp->desktop()->availableGeometry().bottomRight());
5704 // no children created, not shown
5707 widget.installEventFilter(&spy);
5709 QCoreApplication::postEvent(&widget, new QEvent(QEvent::Type(QEvent::User + 1)));
5711 QCoreApplication::sendPostedEvents();
5714 EventRecorder::EventList()
5715 << qMakePair(&widget, QEvent::PolishRequest)
5716 << qMakePair(&widget, QEvent::Polish)
5717 << qMakePair(&widget, QEvent::Type(QEvent::User + 1));
5718 QCOMPARE(spy.eventList(), expected);
5722 // no children, shown
5725 widget.installEventFilter(&spy);
5727 QCoreApplication::postEvent(&widget, new QEvent(QEvent::Type(QEvent::User + 1)));
5731 EventRecorder::EventList()
5732 << qMakePair(&widget, QEvent::WinIdChange)
5733 << qMakePair(&widget, QEvent::Polish)
5734 << qMakePair(&widget, QEvent::Move)
5735 << qMakePair(&widget, QEvent::Resize)
5736 << qMakePair(&widget, QEvent::Show);
5738 if (accessibilityEnabled)
5739 expected << qMakePair(&widget, QEvent::AccessibilityPrepare);
5740 expected << qMakePair(&widget, QEvent::ShowToParent);
5741 QCOMPARE(spy.eventList(), expected);
5744 QCoreApplication::sendPostedEvents();
5746 EventRecorder::EventList()
5747 << qMakePair(&widget, QEvent::PolishRequest)
5748 << qMakePair(&widget, QEvent::Type(QEvent::User + 1));
5751 expected << qMakePair(&widget, QEvent::UpdateLater);
5753 expected << qMakePair(&widget, QEvent::UpdateRequest);
5755 QCOMPARE(spy.eventList(), expected);
5759 // 2 children, not shown
5762 widget.installEventFilter(&spy);
5764 QCoreApplication::postEvent(&widget, new QEvent(QEvent::Type(QEvent::User + 1)));
5766 QWidget child1(&widget);
5768 child2.setParent(&widget);
5770 QCoreApplication::postEvent(&widget, new QEvent(QEvent::Type(QEvent::User + 2)));
5773 EventRecorder::EventList()
5774 << qMakePair(&widget, QEvent::ChildAdded)
5775 << qMakePair(&widget, QEvent::ChildAdded);
5776 QCOMPARE(spy.eventList(), expected);
5779 QCoreApplication::sendPostedEvents();
5781 EventRecorder::EventList()
5782 << qMakePair(&widget, QEvent::PolishRequest)
5783 << qMakePair(&widget, QEvent::Polish)
5784 << qMakePair(&widget, QEvent::ChildPolished)
5785 << qMakePair(&widget, QEvent::ChildPolished)
5786 << qMakePair(&widget, QEvent::Type(QEvent::User + 1))
5787 << qMakePair(&widget, QEvent::Type(QEvent::User + 2));
5788 QCOMPARE(spy.eventList(), expected);
5792 // 2 children, widget shown
5795 widget.installEventFilter(&spy);
5797 QCoreApplication::postEvent(&widget, new QEvent(QEvent::Type(QEvent::User + 1)));
5799 QWidget child1(&widget);
5801 child2.setParent(&widget);
5803 QCoreApplication::postEvent(&widget, new QEvent(QEvent::Type(QEvent::User + 2)));
5806 EventRecorder::EventList()
5807 << qMakePair(&widget, QEvent::ChildAdded)
5808 << qMakePair(&widget, QEvent::ChildAdded);
5809 QCOMPARE(spy.eventList(), expected);
5814 EventRecorder::EventList()
5815 << qMakePair(&widget, QEvent::WinIdChange)
5816 << qMakePair(&widget, QEvent::Polish)
5817 << qMakePair(&widget, QEvent::ChildPolished)
5818 << qMakePair(&widget, QEvent::ChildPolished)
5819 << qMakePair(&widget, QEvent::Move)
5820 << qMakePair(&widget, QEvent::Resize)
5821 << qMakePair(&widget, QEvent::Show);
5823 if (accessibilityEnabled)
5824 expected << qMakePair(&widget, QEvent::AccessibilityPrepare);
5825 expected << qMakePair(&widget, QEvent::ShowToParent);
5826 QCOMPARE(spy.eventList(), expected);
5829 QCoreApplication::sendPostedEvents();
5831 EventRecorder::EventList()
5832 << qMakePair(&widget, QEvent::PolishRequest)
5833 << qMakePair(&widget, QEvent::Type(QEvent::User + 1))
5834 << qMakePair(&widget, QEvent::Type(QEvent::User + 2));
5837 expected << qMakePair(&widget, QEvent::UpdateLater);
5839 expected << qMakePair(&widget, QEvent::UpdateRequest);
5841 QCOMPARE(spy.eventList(), expected);
5845 // 2 children, but one is reparented away, not shown
5848 widget.installEventFilter(&spy);
5850 QCoreApplication::postEvent(&widget, new QEvent(QEvent::Type(QEvent::User + 1)));
5852 QWidget child1(&widget);
5854 child2.setParent(&widget);
5855 child2.setParent(0);
5857 QCoreApplication::postEvent(&widget, new QEvent(QEvent::Type(QEvent::User + 2)));
5860 EventRecorder::EventList()
5861 << qMakePair(&widget, QEvent::ChildAdded)
5862 << qMakePair(&widget, QEvent::ChildAdded)
5863 << qMakePair(&widget, QEvent::ChildRemoved);
5864 QCOMPARE(spy.eventList(), expected);
5867 QCoreApplication::sendPostedEvents();
5869 EventRecorder::EventList()
5870 << qMakePair(&widget, QEvent::PolishRequest)
5871 << qMakePair(&widget, QEvent::Polish)
5872 << qMakePair(&widget, QEvent::ChildPolished)
5873 << qMakePair(&widget, QEvent::Type(QEvent::User + 1))
5874 << qMakePair(&widget, QEvent::Type(QEvent::User + 2));
5875 QCOMPARE(spy.eventList(), expected);
5879 // 2 children, but one is reparented away, then widget is shown
5882 widget.installEventFilter(&spy);
5884 QCoreApplication::postEvent(&widget, new QEvent(QEvent::Type(QEvent::User + 1)));
5886 QWidget child1(&widget);
5888 child2.setParent(&widget);
5889 child2.setParent(0);
5891 QCoreApplication::postEvent(&widget, new QEvent(QEvent::Type(QEvent::User + 2)));
5894 EventRecorder::EventList()
5895 << qMakePair(&widget, QEvent::ChildAdded)
5896 << qMakePair(&widget, QEvent::ChildAdded)
5897 << qMakePair(&widget, QEvent::ChildRemoved);
5898 QCOMPARE(spy.eventList(), expected);
5903 EventRecorder::EventList()
5904 << qMakePair(&widget, QEvent::WinIdChange)
5905 << qMakePair(&widget, QEvent::Polish)
5906 << qMakePair(&widget, QEvent::ChildPolished)
5907 << qMakePair(&widget, QEvent::Move)
5908 << qMakePair(&widget, QEvent::Resize)
5909 << qMakePair(&widget, QEvent::Show);
5911 if (accessibilityEnabled)
5912 expected << qMakePair(&widget, QEvent::AccessibilityPrepare);
5913 expected << qMakePair(&widget, QEvent::ShowToParent);
5914 QCOMPARE(spy.eventList(), expected);
5917 QCoreApplication::sendPostedEvents();
5919 EventRecorder::EventList()
5920 << qMakePair(&widget, QEvent::PolishRequest)
5921 << qMakePair(&widget, QEvent::Type(QEvent::User + 1))
5922 << qMakePair(&widget, QEvent::Type(QEvent::User + 2));
5925 expected << qMakePair(&widget, QEvent::UpdateLater);
5927 expected << qMakePair(&widget, QEvent::UpdateRequest);
5929 QCOMPARE(spy.eventList(), expected);
5933 class RenderWidget : public QWidget
5936 RenderWidget(QWidget *source)
5937 : source(source), ellipse(false) {}
5939 void setEllipseEnabled(bool enable = true)
5946 void paintEvent(QPaintEvent *)
5949 QPainter painter(this);
5950 painter.fillRect(rect(), Qt::red);
5952 QRegion regionToRender = QRegion(0, 0, source->width(), source->height() / 2,
5954 source->render(this, QPoint(0, 30), regionToRender);
5956 source->render(this);
5965 void tst_QWidget::render()
5968 QCalendarWidget source;
5969 // disable anti-aliasing to eliminate potential differences when subpixel antialiasing
5970 // is enabled on the screen
5972 f.setStyleStrategy(QFont::NoAntialias);
5975 QTest::qWaitForWindowShown(&source);
5977 // Render the entire source into target.
5978 RenderWidget target(&source);
5979 target.resize(source.size());
5982 qApp->processEvents();
5983 qApp->sendPostedEvents();
5986 QImage sourceImage = QPixmap::grabWidget(&source).toImage();
5987 qApp->processEvents();
5988 QImage targetImage = QPixmap::grabWidget(&target).toImage();
5989 qApp->processEvents();
5990 QCOMPARE(sourceImage, targetImage);
5992 // Fill target.rect() will Qt::red and render
5993 // QRegion(0, 0, source->width(), source->height() / 2, QRegion::Ellipse)
5994 // of source into target with offset (0, 30).
5995 target.setEllipseEnabled();
5996 qApp->processEvents();
5997 qApp->sendPostedEvents();
5999 targetImage = QPixmap::grabWidget(&target).toImage();
6000 QVERIFY(sourceImage != targetImage);
6002 QCOMPARE(targetImage.pixel(target.width() / 2, 29), QColor(Qt::red).rgb());
6003 QCOMPARE(targetImage.pixel(target.width() / 2, 30), sourceImage.pixel(source.width() / 2, 0));
6005 // Test that a child widget properly fills its background
6008 window.resize(100, 100);
6009 // prevent custom styles
6010 window.setStyle(new QWindowsStyle);
6012 QTest::qWaitForWindowShown(&window);
6013 QWidget child(&window);
6014 child.resize(window.size());
6017 qApp->processEvents();
6018 QCOMPARE(QPixmap::grabWidget(&child), QPixmap::grabWidget(&window));
6021 { // Check that the target offset is correct.
6023 widget.resize(200, 200);
6024 widget.setAutoFillBackground(true);
6025 widget.setPalette(Qt::red);
6026 // prevent custom styles
6027 widget.setStyle(new QWindowsStyle);
6029 QTest::qWaitForWindowShown(&widget);
6030 QImage image(widget.size(), QImage::Format_RGB32);
6031 image.fill(QColor(Qt::blue).rgb());
6033 // Target offset (0, 0)
6034 widget.render(&image, QPoint(), QRect(20, 20, 100, 100));
6035 QCOMPARE(image.pixel(0, 0), QColor(Qt::red).rgb());
6036 QCOMPARE(image.pixel(99, 99), QColor(Qt::red).rgb());
6037 QCOMPARE(image.pixel(100, 100), QColor(Qt::blue).rgb());
6039 // Target offset (20, 20).
6040 image.fill(QColor(Qt::blue).rgb());
6041 widget.render(&image, QPoint(20, 20), QRect(20, 20, 100, 100));
6042 QCOMPARE(image.pixel(0, 0), QColor(Qt::blue).rgb());
6043 QCOMPARE(image.pixel(19, 19), QColor(Qt::blue).rgb());
6044 QCOMPARE(image.pixel(20, 20), QColor(Qt::red).rgb());
6045 QCOMPARE(image.pixel(119, 119), QColor(Qt::red).rgb());
6046 QCOMPARE(image.pixel(120, 120), QColor(Qt::blue).rgb());
6050 // On Windows the active palette is used instead of the inactive palette even
6051 // though the widget is invisible. This is probably related to task 178507/168682,
6052 // but for the renderInvisible test it doesn't matter, we're mostly interested
6053 // in testing the geometry so just workaround the palette issue for now.
6054 static void workaroundPaletteIssue(QWidget *widget)
6062 QWidget *navigationBar = qFindChild<QWidget *>(widget, QLatin1String("qt_calendar_navigationbar"));
6063 QVERIFY(navigationBar);
6065 QPalette palette = navigationBar->palette();
6066 const QColor background = palette.color(QPalette::Inactive, navigationBar->backgroundRole());
6067 const QColor highlightedText = palette.color(QPalette::Inactive, QPalette::HighlightedText);
6068 palette.setColor(QPalette::Active, navigationBar->backgroundRole(), background);
6069 palette.setColor(QPalette::Active, QPalette::HighlightedText, highlightedText);
6070 navigationBar->setPalette(palette);
6073 //#define RENDER_DEBUG
6074 void tst_QWidget::renderInvisible()
6076 QCalendarWidget *calendar = new QCalendarWidget;
6077 // disable anti-aliasing to eliminate potential differences when subpixel antialiasing
6078 // is enabled on the screen
6080 f.setStyleStrategy(QFont::NoAntialias);
6081 calendar->setFont(f);
6083 QTest::qWaitForWindowShown(calendar);
6085 // Create a dummy focus widget to get rid of focus rect in reference image.
6086 QLineEdit dummyFocusWidget;
6087 dummyFocusWidget.show();
6088 QTest::qWaitForWindowShown(&dummyFocusWidget);
6089 qApp->processEvents();
6092 // Create normal reference image.
6093 const QSize calendarSize = calendar->size();
6094 QImage referenceImage(calendarSize, QImage::Format_ARGB32);
6095 calendar->render(&referenceImage);
6097 referenceImage.save("referenceImage.png");
6099 QVERIFY(!referenceImage.isNull());
6101 // Create resized reference image.
6102 const QSize calendarSizeResized = calendar->size() + QSize(50, 50);
6103 calendar->resize(calendarSizeResized);
6104 qApp->processEvents();
6106 QImage referenceImageResized(calendarSizeResized, QImage::Format_ARGB32);
6107 calendar->render(&referenceImageResized);
6109 referenceImageResized.save("referenceImageResized.png");
6111 QVERIFY(!referenceImageResized.isNull());
6113 // Explicitly hide the calendar.
6115 qApp->processEvents();
6117 workaroundPaletteIssue(calendar);
6119 { // Make sure we get the same image when the calendar is explicitly hidden.
6120 QImage testImage(calendarSizeResized, QImage::Format_ARGB32);
6121 calendar->render(&testImage);
6123 testImage.save("explicitlyHiddenCalendarResized.png");
6125 QCOMPARE(testImage, referenceImageResized);
6128 // Now that we have reference images we can delete the source and re-create
6129 // the calendar and check that we get the same images from a calendar which has never
6130 // been visible, laid out or created (Qt::WA_WState_Created).
6132 calendar = new QCalendarWidget;
6133 calendar->setFont(f);
6134 workaroundPaletteIssue(calendar);
6136 { // Never been visible, created or laid out.
6137 QImage testImage(calendarSize, QImage::Format_ARGB32);
6138 calendar->render(&testImage);
6140 testImage.save("neverBeenVisibleCreatedOrLaidOut.png");
6142 QCOMPARE(testImage, referenceImage);
6146 qApp->processEvents();
6149 { // Calendar explicitly hidden.
6150 QImage testImage(calendarSize, QImage::Format_ARGB32);
6151 calendar->render(&testImage);
6153 testImage.save("explicitlyHiddenCalendar.png");
6155 QCOMPARE(testImage, referenceImage);
6158 // Get navigation bar and explicitly hide it.
6159 QWidget *navigationBar = qFindChild<QWidget *>(calendar, QLatin1String("qt_calendar_navigationbar"));
6160 QVERIFY(navigationBar);
6161 navigationBar->hide();
6163 { // Check that the navigation bar isn't drawn when rendering the entire calendar.
6164 QImage testImage(calendarSize, QImage::Format_ARGB32);
6165 calendar->render(&testImage);
6167 testImage.save("calendarWithoutNavigationBar.png");
6169 QVERIFY(testImage != referenceImage);
6172 { // Make sure the navigation bar renders correctly even though it's hidden.
6173 QImage testImage(navigationBar->size(), QImage::Format_ARGB32);
6174 navigationBar->render(&testImage);
6176 testImage.save("explicitlyHiddenNavigationBar.png");
6178 QCOMPARE(testImage, referenceImage.copy(navigationBar->rect()));
6181 // Get next month button.
6182 QWidget *nextMonthButton = qFindChild<QWidget *>(navigationBar, QLatin1String("qt_calendar_nextmonth"));
6183 QVERIFY(nextMonthButton);
6185 { // Render next month button.
6186 // Fill test image with correct background color.
6187 QImage testImage(nextMonthButton->size(), QImage::Format_ARGB32);
6188 navigationBar->render(&testImage, QPoint(), QRegion(), QWidget::RenderFlags());
6190 testImage.save("nextMonthButtonBackground.png");
6193 // Set the button's background color to Qt::transparent; otherwise it will fill the
6194 // background with QPalette::Window.
6195 const QPalette originalPalette = nextMonthButton->palette();
6196 QPalette palette = originalPalette;
6197 palette.setColor(QPalette::Window, Qt::transparent);
6198 nextMonthButton->setPalette(palette);
6200 // Render the button on top of the background.
6201 nextMonthButton->render(&testImage);
6203 testImage.save("nextMonthButton.png");
6205 const QRect buttonRect(nextMonthButton->mapTo(calendar, QPoint()), nextMonthButton->size());
6206 QCOMPARE(testImage, referenceImage.copy(buttonRect));
6209 nextMonthButton->setPalette(originalPalette);
6212 // Navigation bar isn't explicitly hidden anymore.
6213 navigationBar->show();
6214 qApp->processEvents();
6216 QVERIFY(!calendar->isVisible());
6218 // Now, completely mess up the layout. This will trigger an update on the layout
6219 // when the calendar is visible or shown, but it's not. QWidget::render must therefore
6220 // make sure the layout is activated before rendering.
6221 QVERIFY(!calendar->isVisible());
6222 calendar->resize(calendarSizeResized);
6223 qApp->processEvents();
6225 { // Make sure we get an image equal to the resized reference image.
6226 QImage testImage(calendarSizeResized, QImage::Format_ARGB32);
6227 calendar->render(&testImage);
6229 testImage.save("calendarResized.png");
6231 QCOMPARE(testImage, referenceImageResized);
6234 { // Make sure we lay out the widget correctly the first time it's rendered.
6235 QCalendarWidget calendar;
6236 const QSize calendarSize = calendar.sizeHint();
6238 QImage image(2 * calendarSize, QImage::Format_ARGB32);
6239 image.fill(QColor(Qt::red).rgb());
6240 calendar.render(&image);
6242 for (int i = calendarSize.height(); i < 2 * calendarSize.height(); ++i)
6243 for (int j = calendarSize.width(); j < 2 * calendarSize.width(); ++j)
6244 QCOMPARE(image.pixel(j, i), QColor(Qt::red).rgb());
6247 { // Ensure that we don't call adjustSize() on invisible top-levels if render() is called
6248 // right after widgets have been added/removed to/from its layout.
6250 topLevel.setLayout(new QVBoxLayout);
6252 QWidget *widget = new QLineEdit;
6253 topLevel.layout()->addWidget(widget);
6255 const QSize initialSize = topLevel.size();
6256 QPixmap pixmap(topLevel.sizeHint());
6257 topLevel.render(&pixmap); // triggers adjustSize()
6258 const QSize finalSize = topLevel.size();
6259 QVERIFY(finalSize != initialSize);
6261 topLevel.layout()->removeWidget(widget);
6262 QCOMPARE(topLevel.size(), finalSize);
6263 topLevel.render(&pixmap);
6264 QCOMPARE(topLevel.size(), finalSize);
6266 topLevel.layout()->addWidget(widget);
6267 QCOMPARE(topLevel.size(), finalSize);
6268 topLevel.render(&pixmap);
6269 QCOMPARE(topLevel.size(), finalSize);
6273 void tst_QWidget::renderWithPainter()
6276 // prevent custom styles
6277 widget.setStyle(new QWindowsStyle);
6279 widget.resize(70, 50);
6280 widget.setAutoFillBackground(true);
6281 widget.setPalette(Qt::black);
6283 // Render the entire widget onto the image.
6284 QImage image(QSize(70, 50), QImage::Format_ARGB32);
6285 image.fill(QColor(Qt::red).rgb());
6286 QPainter painter(&image);
6287 widget.render(&painter);
6289 for (int i = 0; i < image.height(); ++i) {
6290 for (int j = 0; j < image.width(); ++j)
6291 QCOMPARE(image.pixel(j, i), QColor(Qt::black).rgb());
6294 // Translate painter (10, 10).
6296 image.fill(QColor(Qt::red).rgb());
6297 painter.translate(10, 10);
6298 widget.render(&painter);
6301 for (int i = 0; i < image.height(); ++i) {
6302 for (int j = 0; j < image.width(); ++j) {
6303 if (i < 10 || j < 10)
6304 QCOMPARE(image.pixel(j, i), QColor(Qt::red).rgb());
6306 QCOMPARE(image.pixel(j, i), QColor(Qt::black).rgb());
6310 // Pass target offset (10, 10) (the same as QPainter::translate).
6311 image.fill(QColor(Qt::red).rgb());
6312 widget.render(&painter, QPoint(10, 10));
6314 for (int i = 0; i < image.height(); ++i) {
6315 for (int j = 0; j < image.width(); ++j) {
6316 if (i < 10 || j < 10)
6317 QCOMPARE(image.pixel(j, i), QColor(Qt::red).rgb());
6319 QCOMPARE(image.pixel(j, i), QColor(Qt::black).rgb());
6323 // Translate (10, 10) and pass target offset (10, 10).
6325 image.fill(QColor(Qt::red).rgb());
6326 painter.translate(10, 10);
6327 widget.render(&painter, QPoint(10, 10));
6330 for (int i = 0; i < image.height(); ++i) {
6331 for (int j = 0; j < image.width(); ++j) {
6332 if (i < 20 || j < 20)
6333 QCOMPARE(image.pixel(j, i), QColor(Qt::red).rgb());
6335 QCOMPARE(image.pixel(j, i), QColor(Qt::black).rgb());
6339 // Rotate painter 90 degrees.
6341 image.fill(QColor(Qt::red).rgb());
6343 widget.render(&painter);
6346 for (int i = 0; i < image.height(); ++i) {
6347 for (int j = 0; j < image.width(); ++j)
6348 QCOMPARE(image.pixel(j, i), QColor(Qt::red).rgb());
6351 // Translate and rotate.
6352 image.fill(QColor(Qt::red).rgb());
6353 widget.resize(40, 10);
6354 painter.translate(10, 10);
6356 widget.render(&painter);
6358 for (int i = 0; i < image.height(); ++i) {
6359 for (int j = 0; j < image.width(); ++j) {
6360 if (i >= 10 && j >= 0 && j < 10)
6361 QCOMPARE(image.pixel(j, i), QColor(Qt::black).rgb());
6363 QCOMPARE(image.pixel(j, i), QColor(Qt::red).rgb());
6367 // Make sure QWidget::render does not modify the render hints set on the painter.
6368 painter.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform
6369 | QPainter::NonCosmeticDefaultPen | QPainter::TextAntialiasing);
6370 QPainter::RenderHints oldRenderHints = painter.renderHints();
6371 widget.render(&painter);
6372 QCOMPARE(painter.renderHints(), oldRenderHints);
6375 void tst_QWidget::render_task188133()
6377 QMainWindow mainWindow;
6379 // Make sure QWidget::render does not trigger QWidget::repaint/update
6380 // and asserts for Qt::WA_WState_Created.
6381 QPixmap pixmap = QPixmap::grabWidget(&mainWindow);
6384 void tst_QWidget::render_task211796()
6386 class MyWidget : public QWidget
6388 void resizeEvent(QResizeEvent *)
6390 QPixmap pixmap(size());
6395 { // Please don't die in a resize recursion.
6397 widget.resize(200, 200);
6401 { // Same check with a deeper hierarchy.
6404 QWidget child(&widget);
6405 MyWidget grandChild;
6406 grandChild.setParent(&child);
6407 grandChild.resize(100, 100);
6412 void tst_QWidget::render_task217815()
6414 // Make sure we don't change the size of the widget when calling
6415 // render() and the widget has an explicit size set.
6416 // This was a problem on Windows because we called createWinId(),
6417 // which in turn enforced the size to be bigger than the smallest
6418 // possible native window size (which is (115,something) on WinXP).
6420 const QSize explicitSize(80, 20);
6421 widget.resize(explicitSize);
6422 QCOMPARE(widget.size(), explicitSize);
6424 QPixmap pixmap(explicitSize);
6425 widget.render(&pixmap);
6427 QCOMPARE(widget.size(), explicitSize);
6430 // Window Opacity is not supported on Windows CE.
6432 void tst_QWidget::render_windowOpacity()
6434 const qreal opacity = 0.5;
6436 { // Check that the painter opacity effects the widget drawing.
6438 QWidget child(&topLevel);
6439 child.resize(50, 50);
6440 child.setPalette(Qt::red);
6441 child.setAutoFillBackground(true);
6443 QPixmap expected(child.size());
6445 if (expected.depth() < 24)
6446 QSKIP("This test won't give correct results with dithered pixmaps");
6448 expected.fill(Qt::green);
6449 QPainter painter(&expected);
6450 painter.setOpacity(opacity);
6451 painter.fillRect(QRect(QPoint(0, 0), child.size()), Qt::red);
6454 QPixmap result(child.size());
6455 result.fill(Qt::green);
6456 painter.begin(&result);
6457 painter.setOpacity(opacity);
6458 child.render(&painter);
6460 QCOMPARE(result, expected);
6463 { // Combine the opacity set on the painter with the widget opacity.
6464 class MyWidget : public QWidget
6467 void paintEvent(QPaintEvent *)
6469 QPainter painter(this);
6470 painter.setOpacity(opacity);
6471 QCOMPARE(painter.opacity(), opacity);
6472 painter.fillRect(rect(), Qt::red);
6478 widget.resize(50, 50);
6479 widget.opacity = opacity;
6480 widget.setPalette(Qt::blue);
6481 widget.setAutoFillBackground(true);
6483 QPixmap expected(widget.size());
6484 expected.fill(Qt::green);
6485 QPainter painter(&expected);
6486 painter.setOpacity(opacity);
6487 QPixmap pixmap(widget.size());
6488 pixmap.fill(Qt::blue);
6489 QPainter pixmapPainter(&pixmap);
6490 pixmapPainter.setOpacity(opacity);
6491 pixmapPainter.fillRect(QRect(QPoint(), widget.size()), Qt::red);
6492 painter.drawPixmap(QPoint(), pixmap);
6495 QPixmap result(widget.size());
6496 result.fill(Qt::green);
6497 painter.begin(&result);
6498 painter.setOpacity(opacity);
6499 widget.render(&painter);
6501 QCOMPARE(result, expected);
6506 void tst_QWidget::render_systemClip()
6509 widget.setPalette(Qt::blue);
6510 widget.resize(100, 100);
6512 QImage image(widget.size(), QImage::Format_RGB32);
6513 image.fill(QColor(Qt::red).rgb());
6515 QPaintEngine *paintEngine = image.paintEngine();
6516 QVERIFY(paintEngine);
6517 paintEngine->setSystemClip(QRegion(0, 0, 50, 50));
6519 QPainter painter(&image);
6520 // Make sure we're using the same paint engine and has the right clip set.
6521 QCOMPARE(painter.paintEngine(), paintEngine);
6522 QCOMPARE(paintEngine->systemClip(), QRegion(0, 0, 50, 50));
6524 // Translate painter outside system clip.
6525 painter.translate(50, 0);
6526 widget.render(&painter);
6529 image.save("outside_systemclip.png");
6532 // All pixels should be red.
6533 for (int i = 0; i < image.height(); ++i) {
6534 for (int j = 0; j < image.width(); ++j)
6535 QCOMPARE(image.pixel(j, i), QColor(Qt::red).rgb());
6538 // Restore painter and refill image with red.
6539 image.fill(QColor(Qt::red).rgb());
6540 painter.translate(-50, 0);
6542 // Set transform on the painter.
6543 QTransform transform;
6544 transform.shear(0, 1);
6545 painter.setTransform(transform);
6546 widget.render(&painter);
6549 image.save("blue_triangle.png");
6552 // We should now have a blue triangle starting at scan line 1, and the rest should be red.
6562 for (int i = 0; i < image.height(); ++i) {
6563 for (int j = 0; j < image.width(); ++j) {
6564 if (i < 50 && j < i)
6565 QCOMPARE(image.pixel(j, i), QColor(Qt::blue).rgb());
6567 QCOMPARE(image.pixel(j, i), QColor(Qt::red).rgb());
6571 // We don't paint directly on the image on the Mac, so we cannot do the pixel comparison
6572 // as above due to QPainter::SmoothPixmapTransform. We therefore need to generate an
6573 // expected image by first painting on a pixmap, and then draw the pixmap onto
6574 // the image using QPainter::SmoothPixmapTransform. Then we can compare pixels :)
6575 // The check is basically the same, except that it takes the smoothening into account.
6576 QPixmap pixmap(50, 50);
6577 const QRegion sysClip(0, 0, 50, 50);
6578 widget.render(&pixmap, QPoint(), sysClip);
6580 QImage expectedImage(widget.size(), QImage::Format_RGB32);
6581 expectedImage.fill(QColor(Qt::red).rgb());
6582 expectedImage.paintEngine()->setSystemClip(sysClip);
6584 QPainter expectedImagePainter(&expectedImage);
6585 expectedImagePainter.setTransform(QTransform().shear(0, 1));
6586 // NB! This is the important part (SmoothPixmapTransform).
6587 expectedImagePainter.setRenderHints(QPainter::SmoothPixmapTransform);
6588 expectedImagePainter.drawPixmap(QPoint(0, 0), pixmap);
6589 expectedImagePainter.end();
6591 QCOMPARE(image, expectedImage);
6595 void tst_QWidget::render_systemClip2_data()
6597 QTest::addColumn<bool>("autoFillBackground");
6598 QTest::addColumn<bool>("usePaintEvent");
6599 QTest::addColumn<QColor>("expectedColor");
6601 QTest::newRow("Only auto-fill background") << true << false << QColor(Qt::blue);
6602 QTest::newRow("Only draw in paintEvent") << false << true << QColor(Qt::green);
6603 QTest::newRow("Auto-fill background and draw in paintEvent") << true << true << QColor(Qt::green);
6606 void tst_QWidget::render_systemClip2()
6608 QFETCH(bool, autoFillBackground);
6609 QFETCH(bool, usePaintEvent);
6610 QFETCH(QColor, expectedColor);
6612 QVERIFY2(expectedColor != QColor(Qt::red), "Qt::red is the reference color for the image, pick another color");
6614 class MyWidget : public QWidget
6618 void paintEvent(QPaintEvent *)
6621 QPainter(this).fillRect(rect(), Qt::green);
6626 widget.usePaintEvent = usePaintEvent;
6627 widget.setPalette(Qt::blue);
6628 // NB! widget.setAutoFillBackground(autoFillBackground) won't do the
6629 // trick here since the widget is a top-level. The background is filled
6630 // regardless, unless Qt::WA_OpaquePaintEvent or Qt::WA_NoSystemBackground
6631 // is set. We therefore use the opaque attribute to turn off auto-fill.
6632 if (!autoFillBackground)
6633 widget.setAttribute(Qt::WA_OpaquePaintEvent);
6634 widget.resize(100, 100);
6636 QImage image(widget.size(), QImage::Format_RGB32);
6637 image.fill(QColor(Qt::red).rgb());
6639 QPaintEngine *paintEngine = image.paintEngine();
6640 QVERIFY(paintEngine);
6642 QRegion systemClip(QRegion(50, 0, 50, 10));
6643 systemClip += QRegion(90, 10, 10, 40);
6644 paintEngine->setSystemClip(systemClip);
6646 // Render entire widget directly onto device.
6647 widget.render(&image);
6650 image.save("systemclip_with_device.png");
6652 // All pixels within the system clip should now be
6653 // the expectedColor, and the rest should be red.
6654 for (int i = 0; i < image.height(); ++i) {
6655 for (int j = 0; j < image.width(); ++j) {
6656 if (systemClip.contains(QPoint(j, i)))
6657 QCOMPARE(image.pixel(j, i), expectedColor.rgb());
6659 QCOMPARE(image.pixel(j, i), QColor(Qt::red).rgb());
6663 // Refill image with red.
6664 image.fill(QColor(Qt::red).rgb());
6665 paintEngine->setSystemClip(systemClip);
6667 // Do the same with an untransformed painter.
6668 QPainter painter(&image);
6669 //Make sure we're using the same paint engine and has the right clip set.
6670 QCOMPARE(painter.paintEngine(), paintEngine);
6671 QCOMPARE(paintEngine->systemClip(), systemClip);
6673 widget.render(&painter);
6676 image.save("systemclip_with_untransformed_painter.png");
6678 // All pixels within the system clip should now be
6679 // the expectedColor, and the rest should be red.
6680 for (int i = 0; i < image.height(); ++i) {
6681 for (int j = 0; j < image.width(); ++j) {
6682 if (systemClip.contains(QPoint(j, i)))
6683 QCOMPARE(image.pixel(j, i), expectedColor.rgb());
6685 QCOMPARE(image.pixel(j, i), QColor(Qt::red).rgb());
6690 void tst_QWidget::render_systemClip3_data()
6692 QTest::addColumn<QSize>("size");
6693 QTest::addColumn<bool>("useSystemClip");
6695 // Reference: http://en.wikipedia.org/wiki/Flag_of_Norway
6696 QTest::newRow("Norwegian Civil Flag") << QSize(220, 160) << false;
6697 QTest::newRow("Norwegian War Flag") << QSize(270, 160) << true;
6700 // This test ensures that the current engine clip (systemClip + painter clip)
6701 // is preserved after QPainter::setClipRegion(..., Qt::ReplaceClip);
6702 void tst_QWidget::render_systemClip3()
6704 QFETCH(QSize, size);
6705 QFETCH(bool, useSystemClip);
6707 // Calculate the inner/outer cross of the flag.
6708 QRegion outerCross(0, 0, size.width(), size.height());
6709 outerCross -= QRect(0, 0, 60, 60);
6710 outerCross -= QRect(100, 0, size.width() - 100, 60);
6711 outerCross -= QRect(0, 100, 60, 60);
6712 outerCross -= QRect(100, 100, size.width() - 100, 60);
6714 QRegion innerCross(0, 0, size.width(), size.height());
6715 innerCross -= QRect(0, 0, 70, 70);
6716 innerCross -= QRect(90, 0, size.width() - 90, 70);
6717 innerCross -= QRect(0, 90, 70, 70);
6718 innerCross -= QRect(90, 90, size.width() - 90, 70);
6720 const QRegion redArea(QRegion(0, 0, size.width(), size.height()) - outerCross);
6721 const QRegion whiteArea(outerCross - innerCross);
6722 const QRegion blueArea(innerCross);
6725 // Okay, here's the image that should look like a Norwegian civil/war flag in the end.
6726 QImage flag(size, QImage::Format_ARGB32);
6727 flag.fill(QColor(Qt::transparent).rgba());
6729 if (useSystemClip) {
6730 QPainterPath warClip(QPoint(size.width(), 0));
6731 warClip.lineTo(size.width() - 110, 60);
6732 warClip.lineTo(size.width(), 80);
6733 warClip.lineTo(size.width() - 110, 100);
6734 warClip.lineTo(size.width(), 160);
6735 warClip.closeSubpath();
6736 systemClip = QRegion(0, 0, size.width(), size.height()) - QRegion(warClip.toFillPolygon().toPolygon());
6737 flag.paintEngine()->setSystemClip(systemClip);
6740 QPainter painter(&flag);
6741 painter.fillRect(QRect(QPoint(), size), Qt::red); // Fill image background with red.
6742 painter.setClipRegion(outerCross); // Limit widget painting to inside the outer cross.
6744 // Here's the widget that's supposed to draw the inner/outer cross of the flag.
6745 // The outer cross (white) should be drawn when the background is auto-filled, and
6746 // the inner cross (blue) should be drawn in the paintEvent.
6747 class MyWidget : public QWidget
6749 void paintEvent(QPaintEvent *)
6751 QPainter painter(this);
6752 // Be evil and try to paint outside the outer cross. This should not be
6753 // possible since the shared painter is clipped to the outer cross.
6754 painter.setClipRect(0, 0, 60, 60, Qt::ReplaceClip);
6755 painter.fillRect(rect(), Qt::green);
6756 painter.setClipRegion(clip, Qt::ReplaceClip);
6757 painter.fillRect(rect(), Qt::blue);
6763 widget.clip = innerCross;
6764 widget.setFixedSize(size);
6765 widget.setPalette(Qt::white);
6766 widget.setAutoFillBackground(true);
6767 widget.render(&painter);
6770 flag.save("flag.png");
6773 // Let's make sure we got a Norwegian flag.
6774 for (int i = 0; i < flag.height(); ++i) {
6775 for (int j = 0; j < flag.width(); ++j) {
6776 const QPoint pixel(j, i);
6777 const QRgb pixelValue = flag.pixel(pixel);
6778 if (useSystemClip && !systemClip.contains(pixel))
6779 QCOMPARE(pixelValue, QColor(Qt::transparent).rgba());
6780 else if (redArea.contains(pixel))
6781 QCOMPARE(pixelValue, QColor(Qt::red).rgba());
6782 else if (whiteArea.contains(pixel))
6783 QCOMPARE(pixelValue, QColor(Qt::white).rgba());
6785 QCOMPARE(pixelValue, QColor(Qt::blue).rgba());
6790 void tst_QWidget::render_task252837()
6793 widget.resize(200, 200);
6795 QPixmap pixmap(widget.size());
6796 QPainter painter(&pixmap);
6797 // Please do not crash.
6798 widget.render(&painter);
6801 void tst_QWidget::render_worldTransform()
6803 class MyWidget : public QWidget
6805 void paintEvent(QPaintEvent *)
6807 QPainter painter(this);
6808 // Make sure world transform is identity.
6809 QCOMPARE(painter.worldTransform(), QTransform());
6811 // Make sure device transform is correct.
6812 const QPoint widgetOffset = geometry().topLeft();
6813 QTransform expectedDeviceTransform = QTransform::fromTranslate(105, 5);
6814 expectedDeviceTransform.rotate(90);
6815 expectedDeviceTransform.translate(widgetOffset.x(), widgetOffset.y());
6816 QCOMPARE(painter.deviceTransform(), expectedDeviceTransform);
6818 // Set new world transform.
6819 QTransform newWorldTransform = QTransform::fromTranslate(10, 10);
6820 newWorldTransform.rotate(90);
6821 painter.setWorldTransform(newWorldTransform);
6822 QCOMPARE(painter.worldTransform(), newWorldTransform);
6824 // Again, check device transform.
6825 expectedDeviceTransform.translate(10, 10);
6826 expectedDeviceTransform.rotate(90);
6827 QCOMPARE(painter.deviceTransform(), expectedDeviceTransform);
6829 painter.fillRect(QRect(0, 0, 20, 10), Qt::green);
6834 widget.setFixedSize(100, 100);
6835 widget.setPalette(Qt::red);
6836 widget.setAutoFillBackground(true);
6839 child.setParent(&widget);
6841 child.setFixedSize(50, 50);
6842 child.setPalette(Qt::blue);
6843 child.setAutoFillBackground(true);
6845 QImage image(QSize(110, 110), QImage::Format_RGB32);
6846 image.fill(QColor(Qt::black).rgb());
6848 QPainter painter(&image);
6849 painter.translate(105, 5);
6852 // Render widgets onto image.
6853 widget.render(&painter);
6855 image.save("render_worldTransform_image.png");
6858 // Ensure the transforms are unchanged after render.
6859 QCOMPARE(painter.worldTransform(), painter.worldTransform());
6860 QCOMPARE(painter.deviceTransform(), painter.deviceTransform());
6863 // Paint expected image.
6864 QImage expected(QSize(110, 110), QImage::Format_RGB32);
6865 expected.fill(QColor(Qt::black).rgb());
6867 QPainter expectedPainter(&expected);
6868 expectedPainter.translate(105, 5);
6869 expectedPainter.rotate(90);
6870 expectedPainter.save();
6871 expectedPainter.fillRect(widget.rect(),Qt::red);
6872 expectedPainter.translate(10, 10);
6873 expectedPainter.rotate(90);
6874 expectedPainter.fillRect(QRect(0, 0, 20, 10), Qt::green);
6875 expectedPainter.restore();
6876 expectedPainter.translate(50, 50);
6877 expectedPainter.fillRect(child.rect(),Qt::blue);
6878 expectedPainter.translate(10, 10);
6879 expectedPainter.rotate(90);
6880 expectedPainter.fillRect(QRect(0, 0, 20, 10), Qt::green);
6881 expectedPainter.end();
6884 expected.save("render_worldTransform_expected.png");
6887 QCOMPARE(image, expected);
6890 void tst_QWidget::setContentsMargins()
6892 QLabel label("why does it always rain on me?");
6893 QSize oldSize = label.sizeHint();
6894 label.setFrameStyle(QFrame::Sunken | QFrame::Box);
6895 QSize newSize = label.sizeHint();
6896 QVERIFY(oldSize != newSize);
6898 QLabel label2("why does it always rain on me?");
6900 label2.setFrameStyle(QFrame::Sunken | QFrame::Box);
6901 QCOMPARE(newSize, label2.sizeHint());
6903 QLabel label3("why does it always rain on me?");
6904 label3.setFrameStyle(QFrame::Sunken | QFrame::Box);
6905 QCOMPARE(newSize, label3.sizeHint());
6908 // 4DWM issues on IRIX makes this test fail.
6910 void tst_QWidget::moveWindowInShowEvent_data()
6912 QTest::addColumn<QPoint>("initial");
6913 QTest::addColumn<QPoint>("position");
6915 QPoint p = QApplication::desktop()->availableGeometry().topLeft();
6917 QTest::newRow("1") << p << (p + QPoint(10, 10));
6918 QTest::newRow("2") << (p + QPoint(10,10)) << p;
6921 void tst_QWidget::moveWindowInShowEvent()
6923 QFETCH(QPoint, initial);
6924 QFETCH(QPoint, position);
6926 class MoveWindowInShowEventWidget : public QWidget
6930 void showEvent(QShowEvent *)
6936 MoveWindowInShowEventWidget widget;
6937 widget.resize(QSize(qApp->desktop()->availableGeometry().size() / 3).expandedTo(QSize(1, 1)));
6938 // move to this position in showEvent()
6939 widget.position = position;
6941 // put the widget in it's starting position
6942 widget.move(initial);
6943 QCOMPARE(widget.pos(), initial);
6948 qt_x11_wait_for_window_manager(&widget);
6951 // it should have moved
6952 QCOMPARE(widget.pos(), position);
6956 void tst_QWidget::repaintWhenChildDeleted()
6959 if (QSysInfo::WindowsVersion & QSysInfo::WV_VISTA) {
6963 ColorWidget w(0, Qt::red);
6964 #if !defined(Q_OS_WINCE)
6965 QPoint startPoint = QApplication::desktop()->availableGeometry(&w).topLeft();
6966 startPoint.rx() += 50;
6967 startPoint.ry() += 50;
6968 w.setGeometry(QRect(startPoint, QSize(100, 100)));
6970 w.setGeometry(60, 60, 110, 110);
6973 QTest::qWaitForWindowShown(&w);
6975 QTRY_COMPARE(w.r, QRegion(w.rect()));
6979 ColorWidget child(&w, Qt::blue);
6980 child.setGeometry(10, 10, 10, 10);
6983 QTRY_COMPARE(child.r, QRegion(child.rect()));
6988 QTRY_COMPARE(w.r, QRegion(10, 10, 10, 10));
6992 void tst_QWidget::hideOpaqueChildWhileHidden()
6994 ColorWidget w(0, Qt::red);
6995 #if !defined(Q_OS_WINCE)
6996 QPoint startPoint = QApplication::desktop()->availableGeometry(&w).topLeft();
6997 startPoint.rx() += 50;
6998 startPoint.ry() += 50;
6999 w.setGeometry(QRect(startPoint, QSize(100, 100)));
7001 w.setGeometry(60, 60, 110, 110);
7004 ColorWidget child(&w, Qt::blue);
7005 child.setGeometry(10, 10, 80, 80);
7007 ColorWidget child2(&child, Qt::white);
7008 child2.setGeometry(10, 10, 60, 60);
7011 QTest::qWaitForWindowShown(&w);
7013 QTRY_COMPARE(child2.r, QRegion(child2.rect()));
7014 child.r = QRegion();
7015 child2.r = QRegion();
7022 QCOMPARE(w.r, QRegion(child.geometry()));
7026 QCOMPARE(child.r, QRegion(child.rect()));
7027 QCOMPARE(child2.r, QRegion());
7030 // This test doesn't make sense without support for showMinimized().
7031 #if !defined(Q_OS_WINCE) && !defined(Q_WS_QWS)
7032 void tst_QWidget::updateWhileMinimized()
7034 UpdateWidget widget;
7035 // Filter out activation change and focus events to avoid update() calls in QWidget.
7036 widget.updateOnActivationChangeAndFocusIn = false;
7039 QTest::qWaitForWindowShown(&widget);
7040 QApplication::processEvents();
7041 QTRY_VERIFY(widget.numPaintEvents > 0);
7045 widget.showMinimized();
7050 // The widget is not visible on the screen (but isVisible() still returns true).
7051 // Make sure update requests are discarded until the widget is shown again.
7052 widget.update(0, 0, 50, 50);
7054 QCOMPARE(widget.numPaintEvents, 0);
7057 widget.showNormal();
7059 QTRY_COMPARE(widget.numPaintEvents, 1);
7060 QCOMPARE(widget.paintedRegion, QRegion(0, 0, 50, 50));
7064 #if defined(Q_WS_WIN) || defined(Q_WS_X11)
7065 class PaintOnScreenWidget: public QWidget
7068 PaintOnScreenWidget(QWidget *parent = 0, Qt::WindowFlags f = 0)
7072 #if defined(Q_WS_WIN)
7073 // This is the only way to enable PaintOnScreen on Windows.
7074 QPaintEngine * paintEngine () const {return 0;}
7078 void tst_QWidget::alienWidgets()
7080 qApp->setAttribute(Qt::AA_DontCreateNativeWidgetSiblings);
7082 QWidget child(&parent);
7083 QWidget grandChild(&child);
7084 QWidget greatGrandChild(&grandChild);
7088 qt_x11_wait_for_window_manager(&parent);
7091 // Verify that the WA_WState_Created attribute is set
7092 // and the top-level is the only native window.
7093 QVERIFY(parent.testAttribute(Qt::WA_WState_Created));
7094 QVERIFY(parent.internalWinId());
7096 QVERIFY(child.testAttribute(Qt::WA_WState_Created));
7097 QVERIFY(!child.internalWinId());
7099 QVERIFY(grandChild.testAttribute(Qt::WA_WState_Created));
7100 QVERIFY(!grandChild.internalWinId());
7102 QVERIFY(greatGrandChild.testAttribute(Qt::WA_WState_Created));
7103 QVERIFY(!greatGrandChild.internalWinId());
7105 // Enforce native windows all the way up in the parent hierarchy
7106 // if not WA_DontCreateNativeAncestors is set.
7107 grandChild.setAttribute(Qt::WA_DontCreateNativeAncestors);
7108 greatGrandChild.setAttribute(Qt::WA_NativeWindow);
7109 QVERIFY(greatGrandChild.internalWinId());
7110 QVERIFY(grandChild.internalWinId());
7111 QVERIFY(!child.internalWinId());
7114 // Ensure that hide() on an ancestor of a widget with
7115 // Qt::WA_DontCreateNativeAncestors still gets unmapped
7117 QWidget widget(&window);
7118 QWidget child(&widget);
7119 child.setAttribute(Qt::WA_NativeWindow);
7120 child.setAttribute(Qt::WA_DontCreateNativeAncestors);
7122 QVERIFY(child.testAttribute(Qt::WA_Mapped));
7124 QVERIFY(!child.testAttribute(Qt::WA_Mapped));
7127 // Enforce a native window when calling QWidget::winId.
7128 QVERIFY(child.winId());
7129 QVERIFY(child.internalWinId());
7131 // Check that paint on screen widgets (incl. children) are native.
7132 PaintOnScreenWidget paintOnScreen(&parent);
7133 QWidget paintOnScreenChild(&paintOnScreen);
7134 paintOnScreen.show();
7135 QVERIFY(paintOnScreen.testAttribute(Qt::WA_WState_Created));
7136 QVERIFY(!paintOnScreen.testAttribute(Qt::WA_NativeWindow));
7137 QVERIFY(!paintOnScreen.internalWinId());
7138 QVERIFY(!paintOnScreenChild.testAttribute(Qt::WA_NativeWindow));
7139 QVERIFY(!paintOnScreenChild.internalWinId());
7141 paintOnScreen.setAttribute(Qt::WA_PaintOnScreen);
7142 QVERIFY(paintOnScreen.testAttribute(Qt::WA_NativeWindow));
7143 QVERIFY(paintOnScreen.internalWinId());
7144 QVERIFY(paintOnScreenChild.testAttribute(Qt::WA_NativeWindow));
7145 QVERIFY(paintOnScreenChild.internalWinId());
7147 // Check that widgets with the Qt::MSWindowsOwnDC attribute set
7149 QWidget msWindowsOwnDC(&parent, Qt::MSWindowsOwnDC);
7150 msWindowsOwnDC.show();
7151 QVERIFY(msWindowsOwnDC.testAttribute(Qt::WA_WState_Created));
7152 QVERIFY(msWindowsOwnDC.testAttribute(Qt::WA_NativeWindow));
7153 QVERIFY(msWindowsOwnDC.internalWinId());
7155 { // Enforce a native window when calling QWidget::handle() (on X11) or QWidget::getDC() (on Windows).
7156 QWidget widget(&parent);
7158 QVERIFY(widget.testAttribute(Qt::WA_WState_Created));
7159 QVERIFY(!widget.internalWinId());
7165 QVERIFY(widget.internalWinId());
7169 #ifndef QT_NO_XRENDER
7170 { // Enforce a native window when calling QWidget::x11PictureHandle().
7171 QWidget widget(&parent);
7173 QVERIFY(widget.testAttribute(Qt::WA_WState_Created));
7174 QVERIFY(!widget.internalWinId());
7175 widget.x11PictureHandle();
7176 QVERIFY(widget.internalWinId());
7180 { // Make sure we don't create native windows when setting Qt::WA_X11NetWmWindowType attributes
7181 // on alien widgets (see task 194231).
7183 QVERIFY(dummy.winId());
7184 QWidget widget(&dummy);
7185 widget.setAttribute(Qt::WA_X11NetWmWindowTypeToolBar);
7186 QVERIFY(!widget.internalWinId());
7191 { // Make sure we create native ancestors when setting Qt::WA_PaintOnScreen before show().
7193 QWidget child(&topLevel);
7194 QWidget grandChild(&child);
7195 PaintOnScreenWidget greatGrandChild(&grandChild);
7197 greatGrandChild.setAttribute(Qt::WA_PaintOnScreen);
7198 QVERIFY(!child.internalWinId());
7199 QVERIFY(!grandChild.internalWinId());
7200 QVERIFY(!greatGrandChild.internalWinId());
7203 QVERIFY(child.internalWinId());
7204 QVERIFY(grandChild.internalWinId());
7205 QVERIFY(greatGrandChild.internalWinId());
7208 { // Ensure that widgets reparented into Qt::WA_PaintOnScreen widgets become native.
7210 QWidget *widget = new PaintOnScreenWidget(&topLevel);
7211 widget->setAttribute(Qt::WA_PaintOnScreen);
7212 QWidget *child = new QWidget;
7213 QWidget *dummy = new QWidget(child);
7214 QWidget *grandChild = new QWidget(child);
7215 QWidget *dummy2 = new QWidget(grandChild);
7217 child->setParent(widget);
7219 QVERIFY(!topLevel.internalWinId());
7220 QVERIFY(!child->internalWinId());
7221 QVERIFY(!dummy->internalWinId());
7222 QVERIFY(!grandChild->internalWinId());
7223 QVERIFY(!dummy2->internalWinId());
7226 QVERIFY(topLevel.internalWinId());
7227 QVERIFY(widget->testAttribute(Qt::WA_NativeWindow));
7228 QVERIFY(child->internalWinId());
7229 QVERIFY(child->testAttribute(Qt::WA_NativeWindow));
7230 QVERIFY(!child->testAttribute(Qt::WA_PaintOnScreen));
7231 QVERIFY(!dummy->internalWinId());
7232 QVERIFY(!dummy->testAttribute(Qt::WA_NativeWindow));
7233 QVERIFY(!grandChild->internalWinId());
7234 QVERIFY(!grandChild->testAttribute(Qt::WA_NativeWindow));
7235 QVERIFY(!dummy2->internalWinId());
7236 QVERIFY(!dummy2->testAttribute(Qt::WA_NativeWindow));
7239 { // Ensure that ancestors of a Qt::WA_PaintOnScreen widget stay native
7240 // if they are re-created (typically in QWidgetPrivate::setParent_sys) (task 210822).
7242 QWidget child(&window);
7245 grandChild.setWindowTitle("This causes the widget to be created");
7247 PaintOnScreenWidget paintOnScreenWidget;
7248 paintOnScreenWidget.setAttribute(Qt::WA_PaintOnScreen);
7249 paintOnScreenWidget.setParent(&grandChild);
7251 grandChild.setParent(&child);
7255 QVERIFY(window.internalWinId());
7256 QVERIFY(child.internalWinId());
7257 QVERIFY(child.testAttribute(Qt::WA_NativeWindow));
7258 QVERIFY(grandChild.internalWinId());
7259 QVERIFY(grandChild.testAttribute(Qt::WA_NativeWindow));
7260 QVERIFY(paintOnScreenWidget.internalWinId());
7261 QVERIFY(paintOnScreenWidget.testAttribute(Qt::WA_NativeWindow));
7264 { // Ensure that all siblings are native unless Qt::AA_DontCreateNativeWidgetSiblings is set.
7265 qApp->setAttribute(Qt::AA_DontCreateNativeWidgetSiblings, false);
7267 QWidget *toolBar = new QWidget(&mainWindow);
7268 QWidget *dockWidget = new QWidget(&mainWindow);
7269 QWidget *centralWidget = new QWidget(&mainWindow);
7271 QWidget *button = new QWidget(centralWidget);
7272 QWidget *mdiArea = new QWidget(centralWidget);
7274 QWidget *horizontalScroll = new QWidget(mdiArea);
7275 QWidget *verticalScroll = new QWidget(mdiArea);
7276 QWidget *viewport = new QWidget(mdiArea);
7278 viewport->setAttribute(Qt::WA_NativeWindow);
7281 // Ensure that the viewport and its siblings are native:
7282 QVERIFY(verticalScroll->testAttribute(Qt::WA_NativeWindow));
7283 QVERIFY(verticalScroll->testAttribute(Qt::WA_NativeWindow));
7284 QVERIFY(horizontalScroll->testAttribute(Qt::WA_NativeWindow));
7286 // Ensure that the mdi area and its siblings are native:
7287 QVERIFY(mdiArea->testAttribute(Qt::WA_NativeWindow));
7288 QVERIFY(button->testAttribute(Qt::WA_NativeWindow));
7290 // Ensure that the central widget and its siblings are native:
7291 QVERIFY(centralWidget->testAttribute(Qt::WA_NativeWindow));
7292 QVERIFY(dockWidget->testAttribute(Qt::WA_NativeWindow));
7293 QVERIFY(toolBar->testAttribute(Qt::WA_NativeWindow));
7296 #endif // Q_WS_WIN / Q_WS_X11
7298 class ASWidget : public QWidget
7301 ASWidget(QSize sizeHint, QSizePolicy sizePolicy, bool layout, bool hfwLayout, QWidget *parent = 0)
7302 : QWidget(parent), mySizeHint(sizeHint)
7304 setSizePolicy(sizePolicy);
7306 QSizePolicy sp = QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
7307 sp.setHeightForWidth(hfwLayout);
7309 QVBoxLayout *vbox = new QVBoxLayout;
7311 vbox->addWidget(new ASWidget(sizeHint + QSize(30, 20), sp, false, false));
7316 QSize sizeHint() const {
7318 return layout()->totalSizeHint();
7321 int heightForWidth(int width) const {
7322 if (sizePolicy().hasHeightForWidth()) {
7332 void tst_QWidget::adjustSize_data()
7334 const int MagicW = 200;
7335 const int MagicH = 100;
7337 QTest::addColumn<QSize>("sizeHint");
7338 QTest::addColumn<int>("hPolicy");
7339 QTest::addColumn<int>("vPolicy");
7340 QTest::addColumn<bool>("hfwSP");
7341 QTest::addColumn<bool>("layout");
7342 QTest::addColumn<bool>("hfwLayout");
7343 QTest::addColumn<bool>("haveParent");
7344 QTest::addColumn<QSize>("expectedSize");
7346 QTest::newRow("1") << QSize(5, 6) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
7347 << false << false << false << false << QSize(5, qMax(6, MagicH));
7348 QTest::newRow("2") << QSize(5, 6) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
7349 << true << false << false << false << QSize(5, qMax(10, MagicH));
7350 QTest::newRow("3") << QSize(5, 6) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
7351 << false << true << false << false << QSize(35, 26);
7352 QTest::newRow("4") << QSize(5, 6) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
7353 << false << true << true << false << QSize(35, 70);
7354 QTest::newRow("5") << QSize(40001, 30001) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
7355 << false << false << false << false << QSize(100000, 100000);
7356 QTest::newRow("6") << QSize(40001, 30001) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
7357 << true << false << false << false << QSize(100000, 100000);
7358 QTest::newRow("7") << QSize(40001, 30001) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
7359 << false << true << false << false << QSize(100000, 100000);
7360 QTest::newRow("8") << QSize(40001, 30001) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
7361 << false << true << true << false << QSize(100000, 100000);
7362 QTest::newRow("9") << QSize(5, 6) << int(QSizePolicy::Expanding) << int(QSizePolicy::Minimum)
7363 << true << false << false << false << QSize(qMax(5, MagicW), 10);
7365 QTest::newRow("1c") << QSize(5, 6) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
7366 << false << false << false << true << QSize(5, 6);
7367 QTest::newRow("2c") << QSize(5, 6) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
7368 << true << false << false << true << QSize(5, 6 /* or 10 would be OK too, since hfw contradicts sizeHint() */);
7369 QTest::newRow("3c") << QSize(5, 6) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
7370 << false << true << false << true << QSize(35, 26);
7371 QTest::newRow("4c") << QSize(5, 6) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
7372 << false << true << true << true << QSize(35, 70);
7373 QTest::newRow("5c") << QSize(40001, 30001) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
7374 << false << false << false << true << QSize(40001, 30001);
7375 QTest::newRow("6c") << QSize(40001, 30001) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
7376 << true << false << false << true << QSize(40001, 30001 /* or 80002 would be OK too, since hfw contradicts sizeHint() */);
7377 QTest::newRow("7c") << QSize(40001, 30001) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
7378 << false << true << false << true << QSize(40001 + 30, 30001 + 20);
7379 QTest::newRow("8c") << QSize(40001, 30001) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
7380 << false << true << true << true << QSize(40001 + 30, 80002 + 60);
7381 QTest::newRow("9c") << QSize(5, 6) << int(QSizePolicy::Expanding) << int(QSizePolicy::Minimum)
7382 << true << false << false << true << QSize(5, 6);
7385 void tst_QWidget::adjustSize()
7387 QFETCH(QSize, sizeHint);
7388 QFETCH(int, hPolicy);
7389 QFETCH(int, vPolicy);
7390 QFETCH(bool, hfwSP);
7391 QFETCH(bool, layout);
7392 QFETCH(bool, hfwLayout);
7393 QFETCH(bool, haveParent);
7394 QFETCH(QSize, expectedSize);
7396 QWidget *parent = new QWidget;
7398 QSizePolicy sp = QSizePolicy(QSizePolicy::Policy(hPolicy), QSizePolicy::Policy(vPolicy));
7399 sp.setHeightForWidth(hfwSP);
7401 QWidget *child = new ASWidget(sizeHint, sp, layout, hfwLayout, haveParent ? parent : 0);
7402 child->resize(123, 456);
7403 child->adjustSize();
7404 if (expectedSize == QSize(100000, 100000)) {
7405 QVERIFY(child->size().width() < sizeHint.width());
7406 QVERIFY(child->size().height() < sizeHint.height());
7408 #if defined (Q_OS_WINCE)
7410 const QRect& desktopRect = qApp->desktop()->availableGeometry();
7411 expectedSize.setWidth(qMin(expectedSize.width(), desktopRect.width()));
7412 expectedSize.setHeight(qMin(expectedSize.height(), desktopRect.height()));
7415 QCOMPARE(child->size(), expectedSize);
7421 class TestLayout : public QVBoxLayout
7425 TestLayout(QWidget *w = 0) : QVBoxLayout(w)
7427 invalidated = false;
7438 void tst_QWidget::updateGeometry_data()
7440 QTest::addColumn<QSize>("minSize");
7441 QTest::addColumn<bool>("shouldInvalidate");
7442 QTest::addColumn<QSize>("maxSize");
7443 QTest::addColumn<bool>("shouldInvalidate2");
7444 QTest::addColumn<int>("verticalSizePolicy");
7445 QTest::addColumn<bool>("shouldInvalidate3");
7446 QTest::addColumn<bool>("setVisible");
7447 QTest::addColumn<bool>("shouldInvalidate4");
7449 QTest::newRow("setMinimumSize")
7450 << QSize(100, 100) << true
7452 << int(QSizePolicy::Preferred) << false
7454 QTest::newRow("setMaximumSize")
7456 << QSize(100, 100) << true
7457 << int(QSizePolicy::Preferred) << false
7459 QTest::newRow("setMinimumSize, then maximumSize to a different size")
7460 << QSize(100, 100) << true
7461 << QSize(300, 300) << true
7462 << int(QSizePolicy::Preferred) << false
7464 QTest::newRow("setMinimumSize, then maximumSize to the same size")
7465 << QSize(100, 100) << true
7466 << QSize(100, 100) << true
7467 << int(QSizePolicy::Preferred) << false
7469 QTest::newRow("setMinimumSize, then maximumSize to the same size and then hide it")
7470 << QSize(100, 100) << true
7471 << QSize(100, 100) << true
7472 << int(QSizePolicy::Preferred) << false
7474 QTest::newRow("Change sizePolicy")
7477 << int(QSizePolicy::Minimum) << true
7482 void tst_QWidget::updateGeometry()
7484 QFETCH(QSize, minSize);
7485 QFETCH(bool, shouldInvalidate);
7486 QFETCH(QSize, maxSize);
7487 QFETCH(bool, shouldInvalidate2);
7488 QFETCH(int, verticalSizePolicy);
7489 QFETCH(bool, shouldInvalidate3);
7490 QFETCH(bool, setVisible);
7491 QFETCH(bool, shouldInvalidate4);
7493 parent.resize(200, 200);
7494 TestLayout *lout = new TestLayout();
7495 parent.setLayout(lout);
7496 QWidget *child = new QWidget(&parent);
7497 lout->addWidget(child);
7499 QApplication::processEvents();
7501 lout->invalidated = false;
7502 if (minSize.isValid())
7503 child->setMinimumSize(minSize);
7504 QCOMPARE(lout->invalidated, shouldInvalidate);
7506 lout->invalidated = false;
7507 if (maxSize.isValid())
7508 child->setMaximumSize(maxSize);
7509 QCOMPARE(lout->invalidated, shouldInvalidate2);
7511 lout->invalidated = false;
7512 child->setSizePolicy(QSizePolicy(QSizePolicy::Preferred, (QSizePolicy::Policy)verticalSizePolicy));
7513 if (shouldInvalidate3)
7514 QCOMPARE(lout->invalidated, true);
7516 lout->invalidated = false;
7518 child->setVisible(false);
7519 QCOMPARE(lout->invalidated, shouldInvalidate4);
7522 void tst_QWidget::sendUpdateRequestImmediately()
7524 UpdateWidget updateWidget;
7525 updateWidget.show();
7527 qt_x11_wait_for_window_manager(&updateWidget);
7530 qApp->processEvents();
7532 QApplication::sendPostedEvents(); //glib workaround
7534 updateWidget.reset();
7536 QCOMPARE(updateWidget.numUpdateRequestEvents, 0);
7537 updateWidget.repaint();
7538 QCOMPARE(updateWidget.numUpdateRequestEvents, 1);
7541 // 4DWM issues on IRIX makes this test fail.
7543 void tst_QWidget::doubleRepaint()
7545 #if defined(Q_OS_MAC)
7546 if (!macHasAccessToWindowsServer())
7547 QSKIP("Not having window server access causes the wrong number of repaints to be issues");
7549 UpdateWidget widget;
7550 widget.setFocusPolicy(Qt::StrongFocus);
7551 // Filter out activation change and focus events to avoid update() calls in QWidget.
7552 widget.updateOnActivationChangeAndFocusIn = false;
7555 int expectedRepaints = 1;
7557 QTest::qWaitForWindowShown(&widget);
7559 QTRY_COMPARE(widget.numPaintEvents, expectedRepaints);
7560 widget.numPaintEvents = 0;
7562 // Minmize: Should not trigger a repaint.
7563 widget.showMinimized();
7565 QCOMPARE(widget.numPaintEvents, 0);
7566 widget.numPaintEvents = 0;
7568 // Restore: Should not trigger a repaint.
7569 widget.showNormal();
7570 QTest::qWaitForWindowShown(&widget);
7572 QCOMPARE(widget.numPaintEvents, 0);
7576 void tst_QWidget::resizeInPaintEvent()
7579 UpdateWidget widget(&window);
7581 QTest::qWaitForWindowShown(&window);
7582 QTRY_VERIFY(widget.numPaintEvents > 0);
7585 QCOMPARE(widget.numPaintEvents, 0);
7587 widget.resizeInPaintEvent = true;
7588 // This will call resize in the paintEvent, which in turn will call
7589 // invalidateBuffer() and a new update request should be posted.
7591 QCOMPARE(widget.numPaintEvents, 1);
7592 widget.numPaintEvents = 0;
7595 // Make sure the resize triggers another update.
7596 QTRY_COMPARE(widget.numPaintEvents, 1);
7599 void tst_QWidget::opaqueChildren()
7602 widget.resize(200, 200);
7604 QWidget child(&widget);
7605 child.setGeometry(-700, -700, 200, 200);
7607 QWidget grandChild(&child);
7608 grandChild.resize(200, 200);
7610 QWidget greatGrandChild(&grandChild);
7611 greatGrandChild.setGeometry(50, 50, 200, 200);
7612 greatGrandChild.setPalette(Qt::red);
7613 greatGrandChild.setAutoFillBackground(true); // Opaque child widget.
7617 qt_x11_wait_for_window_manager(&widget);
7621 // Child, grandChild and greatGrandChild are outside the ancestor clip.
7622 QRegion expectedOpaqueRegion(50, 50, 150, 150);
7623 QCOMPARE(qt_widget_private(&grandChild)->getOpaqueChildren(), expectedOpaqueRegion);
7625 // Now they are all inside the ancestor clip.
7626 child.setGeometry(50, 50, 150, 150);
7627 QCOMPARE(qt_widget_private(&grandChild)->getOpaqueChildren(), expectedOpaqueRegion);
7629 // Set mask on greatGrandChild.
7630 const QRegion mask(10, 10, 50, 50);
7631 greatGrandChild.setMask(mask);
7632 expectedOpaqueRegion &= mask.translated(50, 50);
7633 QCOMPARE(qt_widget_private(&grandChild)->getOpaqueChildren(), expectedOpaqueRegion);
7635 // Make greatGrandChild "transparent".
7636 greatGrandChild.setAutoFillBackground(false);
7637 QCOMPARE(qt_widget_private(&grandChild)->getOpaqueChildren(), QRegion());
7641 class MaskSetWidget : public QWidget
7645 MaskSetWidget(QWidget* p =0)
7648 void paintEvent(QPaintEvent* event) {
7651 paintedRegion += event->region();
7652 foreach(QRect r, event->region().rects())
7653 p.fillRect(r, Qt::red);
7656 void resizeEvent(QResizeEvent*) {
7657 setMask(QRegion(QRect(0, 0, width(), 10).normalized()));
7660 QRegion paintedRegion;
7664 setGeometry(QRect(0, 50, 50, 50));
7668 setGeometry(QRect(0, 50, 150, 50));
7673 void tst_QWidget::setMaskInResizeEvent()
7678 w.setWindowFlags(Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint);
7681 MaskSetWidget testWidget(&w);
7682 testWidget.setGeometry(0, 0, 100, 100);
7683 testWidget.setMask(QRegion(QRect(0,0,100,10)));
7686 QTest::qWaitForWindowShown(&w);
7688 QTRY_VERIFY(w.numPaintEvents > 0);
7691 testWidget.paintedRegion = QRegion();
7692 QTimer::singleShot(0, &testWidget, SLOT(resizeDown()));
7695 QRegion expectedParentUpdate(0, 0, 100, 10); // Old testWidget area.
7696 expectedParentUpdate += testWidget.geometry(); // New testWidget area.
7697 QCOMPARE(w.paintedRegion, expectedParentUpdate);
7698 QCOMPARE(testWidget.paintedRegion, testWidget.mask());
7700 testWidget.paintedRegion = QRegion();
7701 // Now resize the widget again, but in the oposite direction
7702 QTimer::singleShot(0, &testWidget, SLOT(resizeUp()));
7705 QTRY_COMPARE(testWidget.paintedRegion, testWidget.mask());
7708 class MoveInResizeWidget : public QWidget
7712 MoveInResizeWidget(QWidget* p = 0)
7715 setWindowFlags(Qt::FramelessWindowHint);
7718 void resizeEvent(QResizeEvent*) {
7720 move(QPoint(100,100));
7722 static bool firstTime = true;
7724 QTimer::singleShot(250, this, SLOT(resizeMe()));
7735 void tst_QWidget::moveInResizeEvent()
7737 MoveInResizeWidget testWidget;
7738 testWidget.setGeometry(50, 50, 200, 200);
7740 QTest::qWaitForWindowShown(&testWidget);
7743 QRect expectedGeometry(100,100, 100, 100);
7744 QTRY_COMPARE(testWidget.geometry(), expectedGeometry);
7748 #if defined(Q_WS_WIN) || defined(Q_WS_X11)
7749 void tst_QWidget::immediateRepaintAfterShow()
7751 UpdateWidget widget;
7753 qApp->processEvents();
7754 // On X11 in particular, we are now waiting for a MapNotify event before
7755 // syncing the backing store. However, if someone request a repaint()
7756 // we must repaint immediately regardless of the current state.
7757 widget.numPaintEvents = 0;
7759 QCOMPARE(widget.numPaintEvents, 1);
7762 void tst_QWidget::immediateRepaintAfterInvalidateBuffer()
7764 QWidget *widget = new UpdateWidget;
7767 qt_x11_wait_for_window_manager(widget);
7771 static_cast<UpdateWidget *>(widget)->numPaintEvents = 0;
7773 // Marks the area covered by the widget as dirty in the backing store and
7774 // posts an UpdateRequest event.
7775 qt_widget_private(widget)->invalidateBuffer(widget->rect());
7776 QCOMPARE(static_cast<UpdateWidget *>(widget)->numPaintEvents, 0);
7778 // The entire widget is already dirty, but this time we want to update immediately
7779 // by calling repaint(), and thus we have to repaint the widget and not wait for
7780 // the UpdateRequest to be sent when we get back to the event loop.
7782 QCOMPARE(static_cast<UpdateWidget *>(widget)->numPaintEvents, 1);
7788 void tst_QWidget::effectiveWinId()
7791 QWidget child(&parent);
7794 QVERIFY(!parent.effectiveWinId());
7795 QVERIFY(!child.effectiveWinId());
7799 QVERIFY(parent.effectiveWinId());
7800 QVERIFY(child.effectiveWinId());
7803 void tst_QWidget::effectiveWinId2()
7807 class MyWidget : public QWidget {
7808 bool event(QEvent *e)
7810 if (e->type() == QEvent::WinIdChange) {
7815 return QWidget::event(e);
7820 child.setParent(&parent);
7824 child.setParent(&parent);
7827 class CustomWidget : public QWidget
7830 mutable int metricCallCount;
7832 CustomWidget(QWidget *parent = 0) : QWidget(parent), metricCallCount(0) {}
7834 virtual int metric(PaintDeviceMetric metric) const {
7836 return QWidget::metric(metric);
7840 void tst_QWidget::customDpi()
7842 QWidget *topLevel = new QWidget;
7843 CustomWidget *custom = new CustomWidget(topLevel);
7844 QWidget *child = new QWidget(custom);
7846 custom->metricCallCount = 0;
7847 topLevel->logicalDpiX();
7848 QCOMPARE(custom->metricCallCount, 0);
7849 custom->logicalDpiX();
7850 QCOMPARE(custom->metricCallCount, 1);
7851 child->logicalDpiX();
7852 QCOMPARE(custom->metricCallCount, 2);
7857 void tst_QWidget::customDpiProperty()
7859 QWidget *topLevel = new QWidget;
7860 QWidget *middle = new CustomWidget(topLevel);
7861 QWidget *child = new QWidget(middle);
7863 const int initialDpiX = topLevel->logicalDpiX();
7864 const int initialDpiY = topLevel->logicalDpiY();
7866 middle->setProperty("_q_customDpiX", 300);
7867 middle->setProperty("_q_customDpiY", 400);
7869 QCOMPARE(topLevel->logicalDpiX(), initialDpiX);
7870 QCOMPARE(topLevel->logicalDpiY(), initialDpiY);
7872 QCOMPARE(middle->logicalDpiX(), 300);
7873 QCOMPARE(middle->logicalDpiY(), 400);
7875 QCOMPARE(child->logicalDpiX(), 300);
7876 QCOMPARE(child->logicalDpiY(), 400);
7878 middle->setProperty("_q_customDpiX", QVariant());
7879 middle->setProperty("_q_customDpiY", QVariant());
7881 QCOMPARE(topLevel->logicalDpiX(), initialDpiX);
7882 QCOMPARE(topLevel->logicalDpiY(), initialDpiY);
7884 QCOMPARE(middle->logicalDpiX(), initialDpiX);
7885 QCOMPARE(middle->logicalDpiY(), initialDpiY);
7887 QCOMPARE(child->logicalDpiX(), initialDpiX);
7888 QCOMPARE(child->logicalDpiY(), initialDpiY);
7893 void tst_QWidget::quitOnCloseAttribute()
7896 QCOMPARE(w.testAttribute(Qt::WA_QuitOnClose), true);
7897 w.setAttribute(Qt::WA_QuitOnClose, false);
7898 QCOMPARE(w.testAttribute(Qt::WA_QuitOnClose), false);
7900 w.setAttribute(Qt::WA_QuitOnClose);
7901 w.setWindowFlags(Qt::Tool);
7902 QCOMPARE(w.testAttribute(Qt::WA_QuitOnClose), false);
7904 w.setAttribute(Qt::WA_QuitOnClose);
7905 w.setWindowFlags(Qt::Popup);
7906 QCOMPARE(w.testAttribute(Qt::WA_QuitOnClose), false);
7908 w.setAttribute(Qt::WA_QuitOnClose);
7909 w.setWindowFlags(Qt::ToolTip);
7910 QCOMPARE(w.testAttribute(Qt::WA_QuitOnClose), false);
7912 w.setAttribute(Qt::WA_QuitOnClose);
7913 w.setWindowFlags(Qt::SplashScreen);
7914 QCOMPARE(w.testAttribute(Qt::WA_QuitOnClose), false);
7916 w.setAttribute(Qt::WA_QuitOnClose);
7917 w.setWindowFlags(Qt::SubWindow);
7918 QCOMPARE(w.testAttribute(Qt::WA_QuitOnClose), false);
7920 w.setAttribute(Qt::WA_QuitOnClose);
7921 w.setWindowFlags(Qt::Dialog);
7922 QCOMPARE(w.testAttribute(Qt::WA_QuitOnClose), true);
7924 QCOMPARE(w.testAttribute(Qt::WA_QuitOnClose), true);
7925 w.setWindowFlags(Qt::Tool);
7926 QCOMPARE(w.testAttribute(Qt::WA_QuitOnClose), false);
7929 void tst_QWidget::moveRect()
7932 widget.setUpdatesEnabled(false);
7933 QWidget child(&widget);
7934 child.setUpdatesEnabled(false);
7935 child.setAttribute(Qt::WA_OpaquePaintEvent);
7938 child.move(10, 10); // Don't crash.
7942 class GDIWidget : public QDialog
7945 GDIWidget() { setAttribute(Qt::WA_PaintOnScreen); }
7946 QPaintEngine *paintEngine() const { return 0; }
7949 void paintEvent(QPaintEvent *) {
7951 SelectObject(hdc, CreateSolidBrush(RGB(255, 0, 0)));
7952 Rectangle(hdc, 0, 0, 10, 10);
7956 QImage im = QPixmap::grabWindow(winId(), 0, 0, width(), height()).toImage();
7957 color = im.pixel(1, 1);
7962 QSize sizeHint() const {
7963 return QSize(400, 300);
7969 void tst_QWidget::gdiPainting()
7974 QCOMPARE(w.color, QColor(255, 0, 0));
7978 void tst_QWidget::paintOnScreenPossible()
7981 w1.setAttribute(Qt::WA_PaintOnScreen);
7982 QVERIFY(!w1.testAttribute(Qt::WA_PaintOnScreen));
7985 w2.setAttribute(Qt::WA_PaintOnScreen);
7986 QVERIFY(w2.testAttribute(Qt::WA_PaintOnScreen));
7990 void tst_QWidget::reparentStaticWidget()
7994 QWidget *child = new QWidget(&window1);
7995 child->setPalette(Qt::red);
7996 child->setAutoFillBackground(true);
7997 child->setAttribute(Qt::WA_StaticContents);
7998 child->resize(100, 100);
8000 QWidget *grandChild = new QWidget(child);
8001 grandChild->setPalette(Qt::blue);
8002 grandChild->setAutoFillBackground(true);
8003 grandChild->resize(50, 50);
8004 grandChild->setAttribute(Qt::WA_StaticContents);
8006 QTest::qWaitForWindowShown(&window1);
8010 QTest::qWaitForWindowShown(&window2);
8013 // Reparent into another top-level.
8014 child->setParent(&window2);
8017 // Please don't crash.
8018 window1.resize(window1.size() + QSize(2, 2));
8021 // Make sure we move all static children even though
8022 // the reparented widget itself is non-static.
8023 child->setAttribute(Qt::WA_StaticContents, false);
8024 child->setParent(&window1);
8027 // Please don't crash.
8028 window2.resize(window2.size() + QSize(2, 2));
8031 child->setParent(0);
8035 // Please don't crash.
8036 child->resize(child->size() + QSize(2, 2));
8037 window2.resize(window2.size() + QSize(2, 2));
8040 QWidget *siblingOfGrandChild = new QWidget(child);
8041 siblingOfGrandChild->show();
8044 // Nothing should happen when reparenting within the same top-level.
8045 grandChild->setParent(siblingOfGrandChild);
8049 QWidget paintOnScreen;
8050 paintOnScreen.setAttribute(Qt::WA_PaintOnScreen);
8051 paintOnScreen.show();
8052 QTest::qWaitForWindowShown(&paintOnScreen);
8055 child->setParent(&paintOnScreen);
8059 // Please don't crash.
8060 paintOnScreen.resize(paintOnScreen.size() + QSize(2, 2));
8065 void tst_QWidget::QTBUG6883_reparentStaticWidget2()
8068 QDockWidget *one = new QDockWidget("one", &mw);
8069 mw.addDockWidget(Qt::LeftDockWidgetArea, one , Qt::Vertical);
8071 QWidget *child = new QWidget();
8072 child->setPalette(Qt::red);
8073 child->setAutoFillBackground(true);
8074 child->setAttribute(Qt::WA_StaticContents);
8075 child->resize(100, 100);
8076 one->setWidget(child);
8078 QToolBar *mainTools = mw.addToolBar("Main Tools");
8079 mainTools->addWidget(new QLineEdit);
8082 QTest::qWaitForWindowShown(&mw);
8084 one->setFloating(true);
8090 void tst_QWidget::updateOutsideSurfaceClip()
8092 UpdateWidget widget;
8093 widget.setWindowFlags(Qt::FramelessWindowHint);
8094 widget.resize(100, 100);
8100 // Move widget partially outside buffer and change the surface clip.
8101 widget.move(-50, 0);
8104 // Update region is outside the surface clip and should not trigger a repaint.
8105 widget.update(0, 0, 20, 20);
8107 QCOMPARE(widget.numPaintEvents, 0);
8109 // Now, move the widget back so that the update region is inside the clip
8110 // and make sure we get a repaint of the dirty area.
8113 QCOMPARE(widget.numPaintEvents, 1);
8114 QCOMPARE(widget.paintedRegion, QRegion(0, 0, 20, 20));
8117 class ColorRedWidget : public QWidget
8120 ColorRedWidget(QWidget *parent = 0)
8121 : QWidget(parent, Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint | Qt::ToolTip)
8125 void paintEvent(QPaintEvent *) {
8127 p.fillRect(rect(),Qt::red);
8131 void tst_QWidget::translucentWidget()
8135 ColorRedWidget label;
8136 label.setFixedSize(16,16);
8137 label.setAttribute(Qt::WA_TranslucentBackground);
8138 label.move(qApp->desktop()->availableGeometry().topLeft());
8141 qt_x11_wait_for_window_manager(&label);
8145 QPixmap widgetSnapshot;
8148 QWidget *desktopWidget = QApplication::desktop()->screen(0);
8149 if (QSysInfo::windowsVersion() >= QSysInfo::WV_VISTA)
8150 widgetSnapshot = QPixmap::grabWindow(desktopWidget->winId(), 0,0, label.width(), label.height());
8153 widgetSnapshot = QPixmap::grabWindow(label.winId());
8154 QImage actual = widgetSnapshot.toImage().convertToFormat(QImage::Format_RGB32);
8155 QImage expected = pm.toImage().convertToFormat(QImage::Format_RGB32);
8156 QCOMPARE(actual.size(),expected.size());
8157 QCOMPARE(actual,expected);
8160 class MaskResizeTestWidget : public QWidget
8164 MaskResizeTestWidget(QWidget* p =0)
8166 setMask(QRegion(QRect(0, 0, 100, 100).normalized()));
8169 void paintEvent(QPaintEvent* event) {
8172 paintedRegion += event->region();
8173 foreach(QRect r, event->region().rects())
8174 p.fillRect(r, Qt::red);
8177 QRegion paintedRegion;
8180 void enlargeMask() {
8181 QRegion newMask(QRect(0, 0, 150, 150).normalized());
8186 QRegion newMask(QRect(0, 0, 50, 50).normalized());
8192 void tst_QWidget::setClearAndResizeMask()
8194 UpdateWidget topLevel;
8195 topLevel.resize(150, 150);
8197 QTest::qWaitForWindowShown(&topLevel);
8198 QTRY_VERIFY(topLevel.numPaintEvents > 0);
8201 // Mask top-level widget
8202 const QRegion topLevelMask(0, 0, 100, 100, QRegion::Ellipse);
8203 topLevel.setMask(topLevelMask);
8204 QCOMPARE(topLevel.mask(), topLevelMask);
8205 #if defined(Q_WS_WIN) || defined(Q_WS_X11) // We don't control what's happening on other platforms.
8206 // and ensure that the top-level doesn't get any update.
8207 QCOMPARE(topLevel.numPaintEvents, 0);
8212 // Clear top-level mask
8213 topLevel.clearMask();
8214 QCOMPARE(topLevel.mask(), QRegion());
8216 QRegion outsideOldMask(topLevel.rect());
8217 outsideOldMask -= topLevelMask;
8218 #if defined(Q_WS_WIN) || defined(Q_WS_X11) // We don't control what's happening on other platforms.
8219 // and ensure that the top-level gets an update for the area outside the old mask.
8220 QTRY_VERIFY(topLevel.numPaintEvents > 0);
8221 QTRY_COMPARE(topLevel.paintedRegion, outsideOldMask);
8224 UpdateWidget child(&topLevel);
8225 child.setAutoFillBackground(true); // NB! Opaque child.
8226 child.setPalette(Qt::red);
8227 child.resize(100, 100);
8234 // Mask child widget with a mask that is smaller than the rect
8235 const QRegion childMask(0, 0, 50, 50);
8236 child.setMask(childMask);
8237 QTRY_COMPARE(child.mask(), childMask);
8239 // and ensure that the child widget doesn't get any update.
8241 // Mac always issues a full update when calling setMask, and we cannot force it to not do so.
8242 if (child.internalWinId())
8243 QCOMPARE(child.numPaintEvents, 1);
8246 QCOMPARE(child.numPaintEvents, 0);
8247 // and the parent widget gets an update for the newly exposed area.
8248 QTRY_COMPARE(topLevel.numPaintEvents, 1);
8249 QRegion expectedParentExpose(child.rect());
8250 expectedParentExpose -= childMask;
8251 QCOMPARE(topLevel.paintedRegion, expectedParentExpose);
8256 // Clear child widget mask
8258 QTRY_COMPARE(child.mask(), QRegion());
8260 // and ensure that that the child widget gets an update for the area outside the old mask.
8261 QTRY_COMPARE(child.numPaintEvents, 1);
8262 outsideOldMask = child.rect();
8264 // Mac always issues a full update when calling setMask, and we cannot force it to not do so.
8265 if (!child.internalWinId())
8267 outsideOldMask -= childMask;
8268 QCOMPARE(child.paintedRegion, outsideOldMask);
8269 // and the parent widget doesn't get any update.
8270 QCOMPARE(topLevel.numPaintEvents, 0);
8275 // Mask child widget with a mask that is bigger than the rect
8276 child.setMask(QRegion(0, 0, 1000, 1000));
8279 // Mac always issues a full update when calling setMask, and we cannot force it to not do so.
8280 if (child.internalWinId())
8281 QTRY_COMPARE(child.numPaintEvents, 1);
8284 // and ensure that we don't get any updates at all.
8285 QTRY_COMPARE(child.numPaintEvents, 0);
8286 QCOMPARE(topLevel.numPaintEvents, 0);
8288 // ...and the same applies when clearing the mask.
8292 // Mac always issues a full update when calling setMask, and we cannot force it to not do so.
8293 if (child.internalWinId())
8294 QTRY_VERIFY(child.numPaintEvents > 0);
8297 QCOMPARE(child.numPaintEvents, 0);
8298 QCOMPARE(topLevel.numPaintEvents, 0);
8300 QWidget resizeParent;
8301 MaskResizeTestWidget resizeChild(&resizeParent);
8303 resizeParent.resize(300,300);
8304 resizeParent.raise();
8305 resizeParent.setWindowFlags(Qt::WindowStaysOnTopHint);
8306 resizeChild.setGeometry(50,50,200,200);
8307 QPalette pal = resizeParent.palette();
8308 pal.setColor(QPalette::Window, QColor(Qt::white));
8309 resizeParent.setPalette(pal);
8311 resizeParent.show();
8312 QTest::qWaitForWindowShown(&resizeParent);
8313 // Disable the size grip on the Mac; otherwise it'll be included when grabbing the window.
8314 resizeParent.setFixedSize(resizeParent.size());
8317 resizeChild.paintedRegion = QRegion();
8319 QTimer::singleShot(100, &resizeChild, SLOT(shrinkMask()));
8322 // Mac always issues a full update when calling setMask, and we cannot force it to not do so.
8323 if (child.internalWinId())
8324 QTRY_COMPARE(resizeChild.paintedRegion, resizeChild.mask());
8327 QTRY_COMPARE(resizeChild.paintedRegion, QRegion());
8329 resizeChild.paintedRegion = QRegion();
8330 const QRegion oldMask = resizeChild.mask();
8331 QTimer::singleShot(0, &resizeChild, SLOT(enlargeMask()));
8334 // Mac always issues a full update when calling setMask, and we cannot force it to not do so.
8335 if (child.internalWinId())
8336 QTRY_COMPARE(resizeChild.paintedRegion, resizeChild.mask());
8339 QTRY_COMPARE(resizeChild.paintedRegion, resizeChild.mask() - oldMask);
8342 void tst_QWidget::maskedUpdate()
8344 UpdateWidget topLevel;
8345 topLevel.resize(200, 200);
8346 const QRegion topLevelMask(50, 50, 70, 70);
8347 topLevel.setMask(topLevelMask);
8349 UpdateWidget child(&topLevel);
8350 child.setGeometry(20, 20, 180, 180);
8351 const QRegion childMask(60, 60, 30, 30);
8352 child.setMask(childMask);
8354 UpdateWidget grandChild(&child);
8355 grandChild.setGeometry(50, 50, 100, 100);
8356 const QRegion grandChildMask(20, 20, 10, 10);
8357 grandChild.setMask(grandChildMask);
8360 QTest::qWaitForWindowShown(&topLevel);
8361 QTRY_VERIFY(topLevel.numPaintEvents > 0);
8364 #define RESET_WIDGETS \
8369 #define CLEAR_MASK(widget) \
8370 widget.clearMask(); \
8371 QTest::qWait(100); \
8374 // All widgets are transparent at this point, so any call to update() will result
8375 // in composition, i.e. the update propagates to ancestors and children.
8382 QTRY_COMPARE(topLevel.paintedRegion, topLevelMask);
8383 QTRY_COMPARE(child.paintedRegion, childMask);
8384 QTRY_COMPARE(grandChild.paintedRegion, grandChildMask);
8391 QTRY_COMPARE(topLevel.paintedRegion, childMask.translated(child.pos()));
8392 QTRY_COMPARE(child.paintedRegion, childMask);
8393 QTRY_COMPARE(grandChild.paintedRegion, grandChildMask);
8395 // GrandChild update.
8397 grandChild.update();
8400 QTRY_COMPARE(topLevel.paintedRegion, grandChildMask.translated(grandChild.mapTo(&topLevel, QPoint())));
8401 QTRY_COMPARE(child.paintedRegion, grandChildMask.translated(grandChild.pos()));
8402 QTRY_COMPARE(grandChild.paintedRegion, grandChildMask);
8404 topLevel.setAttribute(Qt::WA_OpaquePaintEvent);
8405 child.setAttribute(Qt::WA_OpaquePaintEvent);
8406 grandChild.setAttribute(Qt::WA_OpaquePaintEvent);
8408 // All widgets are now opaque, which means no composition, i.e.
8409 // the update does not propate to ancestors and children.
8416 QRegion expectedTopLevelUpdate = topLevelMask;
8417 expectedTopLevelUpdate -= childMask.translated(child.pos()); // Subtract opaque children.
8418 QTRY_COMPARE(topLevel.paintedRegion, expectedTopLevelUpdate);
8419 QTRY_COMPARE(child.paintedRegion, QRegion());
8420 QTRY_COMPARE(grandChild.paintedRegion, QRegion());
8427 QTRY_COMPARE(topLevel.paintedRegion, QRegion());
8428 QRegion expectedChildUpdate = childMask;
8429 expectedChildUpdate -= grandChildMask.translated(grandChild.pos()); // Subtract oapque children.
8430 QTRY_COMPARE(child.paintedRegion, expectedChildUpdate);
8431 QTRY_COMPARE(grandChild.paintedRegion, QRegion());
8433 // GrandChild update.
8435 grandChild.update();
8438 QTRY_COMPARE(topLevel.paintedRegion, QRegion());
8439 QTRY_COMPARE(child.paintedRegion, QRegion());
8440 QTRY_COMPARE(grandChild.paintedRegion, grandChildMask);
8442 // GrandChild update.
8443 CLEAR_MASK(grandChild);
8444 grandChild.update();
8447 QTRY_COMPARE(topLevel.paintedRegion, QRegion());
8448 QTRY_COMPARE(child.paintedRegion, QRegion());
8449 QRegion expectedGrandChildUpdate = grandChild.rect();
8450 // Clip with parent's mask.
8451 expectedGrandChildUpdate &= childMask.translated(-grandChild.pos());
8452 QCOMPARE(grandChild.paintedRegion, expectedGrandChildUpdate);
8454 // GrandChild update.
8456 grandChild.update();
8459 QTRY_COMPARE(topLevel.paintedRegion, QRegion());
8460 QTRY_COMPARE(child.paintedRegion, QRegion());
8461 expectedGrandChildUpdate = grandChild.rect();
8462 // Clip with parent's mask.
8463 expectedGrandChildUpdate &= topLevelMask.translated(-grandChild.mapTo(&topLevel, QPoint()));
8464 QTRY_COMPARE(grandChild.paintedRegion, expectedGrandChildUpdate);
8471 QTRY_COMPARE(topLevel.paintedRegion, QRegion());
8472 expectedChildUpdate = child.rect();
8473 // Clip with parent's mask.
8474 expectedChildUpdate &= topLevelMask.translated(-child.pos());
8475 expectedChildUpdate -= grandChild.geometry(); // Subtract opaque children.
8476 QTRY_COMPARE(child.paintedRegion, expectedChildUpdate);
8477 QTRY_COMPARE(grandChild.paintedRegion, QRegion());
8479 // GrandChild update.
8480 CLEAR_MASK(topLevel);
8481 grandChild.update();
8484 QTRY_COMPARE(topLevel.paintedRegion, QRegion());
8485 QTRY_COMPARE(child.paintedRegion, QRegion());
8486 QTRY_COMPARE(grandChild.paintedRegion, QRegion(grandChild.rect())); // Full update.
8489 // Windows Mobile has no proper cursor support, so skip this test on that platform.
8490 #if !defined(Q_OS_WINCE_WM)
8491 void tst_QWidget::syntheticEnterLeave()
8493 class MyWidget : public QWidget
8496 MyWidget(QWidget *parent = 0) : QWidget(parent), numEnterEvents(0), numLeaveEvents(0) {}
8497 void enterEvent(QEvent *) { ++numEnterEvents; }
8498 void leaveEvent(QEvent *) { ++numLeaveEvents; }
8503 QCursor::setPos(QPoint(0,0));
8506 window.setWindowFlags(Qt::WindowStaysOnTopHint);
8507 window.resize(200, 200);
8509 MyWidget *child1 = new MyWidget(&window);
8510 child1->setPalette(Qt::blue);
8511 child1->setAutoFillBackground(true);
8512 child1->resize(200, 200);
8513 child1->setCursor(Qt::OpenHandCursor);
8515 MyWidget *child2 = new MyWidget(&window);
8516 child2->resize(200, 200);
8518 MyWidget *grandChild = new MyWidget(child2);
8519 grandChild->setPalette(Qt::red);
8520 grandChild->setAutoFillBackground(true);
8521 grandChild->resize(200, 200);
8522 grandChild->setCursor(Qt::WaitCursor);
8527 qt_x11_wait_for_window_manager(&window);
8531 #define RESET_EVENT_COUNTS \
8532 window.numEnterEvents = 0; \
8533 window.numLeaveEvents = 0; \
8534 child1->numEnterEvents = 0; \
8535 child1->numLeaveEvents = 0; \
8536 child2->numEnterEvents = 0; \
8537 child2->numLeaveEvents = 0; \
8538 grandChild->numEnterEvents = 0; \
8539 grandChild->numLeaveEvents = 0;
8541 // Position the cursor in the middle of the window.
8542 const QPoint globalPos = window.mapToGlobal(QPoint(100, 100));
8543 QCursor::setPos(globalPos); // Enter child2 and grandChild.
8546 QCOMPARE(window.numLeaveEvents, 0);
8547 QCOMPARE(child2->numLeaveEvents, 0);
8548 QCOMPARE(grandChild->numLeaveEvents, 0);
8549 QCOMPARE(child1->numLeaveEvents, 0);
8551 // This event arrives asynchronously
8552 QTRY_COMPARE(window.numEnterEvents, 1);
8553 QCOMPARE(child2->numEnterEvents, 1);
8554 QCOMPARE(grandChild->numEnterEvents, 1);
8555 QCOMPARE(child1->numEnterEvents, 0);
8558 child2->hide(); // Leave child2 and grandChild, enter child1.
8560 QCOMPARE(window.numLeaveEvents, 0);
8561 QCOMPARE(child2->numLeaveEvents, 1);
8562 QCOMPARE(grandChild->numLeaveEvents, 1);
8563 QCOMPARE(child1->numLeaveEvents, 0);
8565 QCOMPARE(window.numEnterEvents, 0);
8566 QCOMPARE(child2->numEnterEvents, 0);
8567 QCOMPARE(grandChild->numEnterEvents, 0);
8568 QCOMPARE(child1->numEnterEvents, 1);
8571 child2->show(); // Leave child1, enter child2 and grandChild.
8573 QCOMPARE(window.numLeaveEvents, 0);
8574 QCOMPARE(child2->numLeaveEvents, 0);
8575 QCOMPARE(grandChild->numLeaveEvents, 0);
8576 QCOMPARE(child1->numLeaveEvents, 1);
8578 QCOMPARE(window.numEnterEvents, 0);
8579 QCOMPARE(child2->numEnterEvents, 1);
8580 QCOMPARE(grandChild->numEnterEvents, 1);
8581 QCOMPARE(child1->numEnterEvents, 0);
8584 delete child2; // Enter child1 (and do not send leave events to child2 and grandChild).
8586 QCOMPARE(window.numLeaveEvents, 0);
8587 QCOMPARE(child1->numLeaveEvents, 0);
8589 QCOMPARE(window.numEnterEvents, 0);
8590 QCOMPARE(child1->numEnterEvents, 1);
8594 // Windows Mobile has no proper cursor support, so skip this test on that platform.
8595 #if !defined(Q_OS_WINCE_WM)
8596 void tst_QWidget::taskQTBUG_4055_sendSyntheticEnterLeave()
8598 class SELParent : public QWidget
8601 SELParent(QWidget *parent = 0): QWidget(parent) { }
8603 void mousePressEvent(QMouseEvent *) { child->show(); }
8607 class SELChild : public QWidget
8610 SELChild(QWidget *parent = 0) : QWidget(parent), numEnterEvents(0), numMouseMoveEvents(0) {}
8611 void enterEvent(QEvent *) { ++numEnterEvents; }
8612 void mouseMoveEvent(QMouseEvent *event)
8614 QCOMPARE(event->button(), Qt::NoButton);
8615 QCOMPARE(event->buttons(), Qt::MouseButtons(Qt::NoButton));
8616 ++numMouseMoveEvents;
8618 void reset() { numEnterEvents = numMouseMoveEvents = 0; }
8619 int numEnterEvents, numMouseMoveEvents;
8622 QCursor::setPos(QPoint(0,0));
8625 parent.resize(200, 200);
8626 SELChild child(&parent);
8627 child.resize(200, 200);
8630 qt_x11_wait_for_window_manager(&parent);
8634 QCursor::setPos(child.mapToGlobal(QPoint(100, 100)));
8635 // Make sure the cursor has entered the child.
8636 QTRY_VERIFY(child.numEnterEvents > 0);
8642 // Make sure the child gets enter event and no mouse move event.
8643 QTRY_COMPARE(child.numEnterEvents, 1);
8644 QCOMPARE(child.numMouseMoveEvents, 0);
8648 child.setMouseTracking(true);
8651 // Make sure the child gets enter event and mouse move event.
8652 // Note that we verify event->button() and event->buttons()
8653 // in SELChild::mouseMoveEvent().
8654 QTRY_COMPARE(child.numEnterEvents, 1);
8655 QCOMPARE(child.numMouseMoveEvents, 1);
8657 // Sending synthetic enter/leave trough the parent's mousePressEvent handler.
8658 parent.child = &child;
8662 QTest::mouseClick(&parent, Qt::LeftButton);
8664 // Make sure the child gets enter event and one mouse move event.
8665 QTRY_COMPARE(child.numEnterEvents, 1);
8666 QCOMPARE(child.numMouseMoveEvents, 1);
8670 child.setMouseTracking(false);
8671 QTest::mouseClick(&parent, Qt::LeftButton);
8673 // Make sure the child gets enter event and no mouse move event.
8674 QTRY_COMPARE(child.numEnterEvents, 1);
8675 QCOMPARE(child.numMouseMoveEvents, 0);
8679 void tst_QWidget::windowFlags()
8682 w.setWindowFlags(w.windowFlags() | Qt::FramelessWindowHint);
8683 QVERIFY(w.windowFlags() & Qt::FramelessWindowHint);
8686 void tst_QWidget::initialPosForDontShowOnScreenWidgets()
8688 { // Check default position.
8689 const QPoint expectedPos(0, 0);
8691 widget.setAttribute(Qt::WA_DontShowOnScreen);
8692 widget.winId(); // Make sure create_sys is called.
8693 QCOMPARE(widget.pos(), expectedPos);
8694 QCOMPARE(widget.geometry().topLeft(), expectedPos);
8697 { // Explicitly move to a position.
8698 const QPoint expectedPos(100, 100);
8700 widget.setAttribute(Qt::WA_DontShowOnScreen);
8701 widget.move(expectedPos);
8702 widget.winId(); // Make sure create_sys is called.
8703 QCOMPARE(widget.pos(), expectedPos);
8704 QCOMPARE(widget.geometry().topLeft(), expectedPos);
8709 void tst_QWidget::paintOutsidePaintEvent()
8712 widget.resize(200, 200);
8714 QWidget child1(&widget);
8715 child1.resize(100, 100);
8716 child1.setPalette(Qt::red);
8717 child1.setAutoFillBackground(true);
8719 QWidget child2(&widget);
8720 child2.setGeometry(50, 50, 100, 100);
8721 child2.setPalette(Qt::blue);
8722 child2.setAutoFillBackground(true);
8725 QTest::qWaitForWindowShown(&widget);
8728 const QPixmap before = QPixmap::grabWindow(widget.winId());
8730 // Child 1 should be clipped by child 2, so nothing should change.
8731 child1.setAttribute(Qt::WA_PaintOutsidePaintEvent);
8732 QPainter painter(&child1);
8733 painter.fillRect(child1.rect(), Qt::red);
8735 XSync(QX11Info::display(), false); // Flush output buffer.
8738 const QPixmap after = QPixmap::grabWindow(widget.winId());
8740 QCOMPARE(before, after);
8744 class MyEvilObject : public QObject
8748 MyEvilObject(QWidget *widgetToCrash) : QObject(), widget(widgetToCrash)
8750 connect(widget, SIGNAL(destroyed(QObject *)), this, SLOT(beEvil(QObject *)));
8756 void beEvil(QObject *) { widget->update(0, 0, 150, 150); }
8759 void tst_QWidget::updateOnDestroyedSignal()
8763 QWidget *child = new QWidget(&widget);
8764 child->resize(100, 100);
8765 child->setAutoFillBackground(true);
8766 child->setPalette(Qt::red);
8770 qt_x11_wait_for_window_manager(&widget);
8774 // Please do not crash.
8775 MyEvilObject evil(child);
8779 void tst_QWidget::toplevelLineEditFocus()
8785 QTest::qWaitForWindowShown(&w);
8788 QTRY_COMPARE(QApplication::activeWindow(), (QWidget*)&w);
8789 QTRY_COMPARE(QApplication::focusWidget(), (QWidget*)&w);
8792 void tst_QWidget::focusWidget_task254563()
8794 //having different visibility for widget is important
8797 QWidget container(&top);
8798 QWidget *widget = new QWidget(&container);
8801 widget->setFocus(); //set focus (will set the focus widget up to the toplevel to be 'widget')
8802 container.setFocus();
8803 delete widget; // will call clearFocus but that doesn't help
8804 QVERIFY(top.focusWidget() != widget); //dangling pointer
8807 // This test case relies on developer build (AUTOTEST_EXPORT).
8808 #ifdef QT_BUILD_INTERNAL
8809 void tst_QWidget::destroyBackingStore()
8815 QTest::qWaitForWindowShown(&w);
8816 QApplication::processEvents();
8817 QTRY_VERIFY(w.numPaintEvents > 0);
8820 qt_widget_private(&w)->topData()->backingStoreTracker.create(&w);
8823 QApplication::processEvents();
8825 QApplication::processEvents();
8827 QCOMPARE(w.numPaintEvents, 1);
8829 // Check one more time, because the second time around does more caching.
8831 QApplication::processEvents();
8832 QCOMPARE(w.numPaintEvents, 2);
8837 QWidgetBackingStore* backingStore(QWidget &widget)
8839 QWidgetBackingStore *backingStore = 0;
8840 #ifdef QT_BUILD_INTERNAL
8841 if (QTLWExtra *topExtra = qt_widget_private(&widget)->maybeTopData())
8842 backingStore = topExtra->backingStoreTracker.data();
8844 return backingStore;
8847 // Tables of 5000 elements do not make sense on Windows Mobile.
8848 #ifndef Q_OS_WINCE_WM
8849 void tst_QWidget::rectOutsideCoordinatesLimit_task144779()
8851 QApplication::setOverrideCursor(Qt::BlankCursor); //keep the cursor out of screen grabs
8852 QWidget main(0,Qt::FramelessWindowHint); //don't get confused by the size of the window frame
8854 palette.setColor(QPalette::Window, Qt::red);
8855 main.setPalette(palette);
8857 QDesktopWidget desktop;
8858 QRect desktopDimensions = desktop.availableGeometry(&main);
8859 QSize mainSize(400, 400);
8860 mainSize = mainSize.boundedTo(desktopDimensions.size());
8861 main.resize(mainSize);
8863 QWidget *offsetWidget = new QWidget(&main);
8864 offsetWidget->setGeometry(0, -(15000 - mainSize.height()), mainSize.width(), 15000);
8866 // big widget is too big for the coordinates, it must be limited by wrect
8867 // if wrect is not at the right position because of offsetWidget, bigwidget
8868 // is not painted correctly
8869 QWidget *bigWidget = new QWidget(offsetWidget);
8870 bigWidget->setGeometry(0, 0, mainSize.width(), 50000);
8871 palette.setColor(QPalette::Window, Qt::green);
8872 bigWidget->setPalette(palette);
8873 bigWidget->setAutoFillBackground(true);
8876 QTest::qWaitForWindowShown(&main);
8878 QPixmap correct(main.size());
8879 correct.fill(Qt::green);
8881 QTRY_COMPARE(QPixmap::grabWindow(main.winId()).toImage().convertToFormat(QImage::Format_RGB32),
8882 correct.toImage().convertToFormat(QImage::Format_RGB32));
8883 QApplication::restoreOverrideCursor();
8887 void tst_QWidget::inputFocus_task257832()
8889 QLineEdit *widget = new QLineEdit;
8891 widget->winId(); // make sure, widget has been created
8893 QTRY_VERIFY(widget->hasFocus());
8894 QCOMPARE(qApp->inputMethod()->inputItem(), static_cast<QWidget*>(widget));
8895 widget->setReadOnly(true);
8896 QVERIFY(!qApp->inputMethod()->inputItem());
8900 void tst_QWidget::setGraphicsEffect()
8902 // Check that we don't have any effect by default.
8903 QWidget *widget = new QWidget;
8904 QVERIFY(!widget->graphicsEffect());
8907 QPointer<QGraphicsEffect> blurEffect = new QGraphicsBlurEffect;
8908 widget->setGraphicsEffect(blurEffect);
8909 QCOMPARE(widget->graphicsEffect(), static_cast<QGraphicsEffect *>(blurEffect));
8911 // Ensure the existing effect is deleted when setting a new one.
8912 QPointer<QGraphicsEffect> shadowEffect = new QGraphicsDropShadowEffect;
8913 widget->setGraphicsEffect(shadowEffect);
8914 QVERIFY(!blurEffect);
8915 QCOMPARE(widget->graphicsEffect(), static_cast<QGraphicsEffect *>(shadowEffect));
8916 blurEffect = new QGraphicsBlurEffect;
8918 // Ensure the effect is uninstalled when setting it on a new target.
8919 QWidget *anotherWidget = new QWidget;
8920 anotherWidget->setGraphicsEffect(blurEffect);
8921 widget->setGraphicsEffect(blurEffect);
8922 QVERIFY(!anotherWidget->graphicsEffect());
8923 QVERIFY(!shadowEffect);
8925 // Ensure the existing effect is deleted when deleting the widget.
8927 QVERIFY(!blurEffect);
8928 delete anotherWidget;
8930 // Ensure the effect is uninstalled when deleting it
8931 widget = new QWidget;
8932 blurEffect = new QGraphicsBlurEffect;
8933 widget->setGraphicsEffect(blurEffect);
8935 QVERIFY(!widget->graphicsEffect());
8937 // Ensure the existing effect is uninstalled and deleted when setting a null effect
8938 blurEffect = new QGraphicsBlurEffect;
8939 widget->setGraphicsEffect(blurEffect);
8940 widget->setGraphicsEffect(0);
8941 QVERIFY(!widget->graphicsEffect());
8942 QVERIFY(!blurEffect);
8947 void tst_QWidget::activateWindow()
8949 // Test case for task 260685
8951 // Create first mainwindow and set it active
8952 QMainWindow* mainwindow = new QMainWindow();
8953 QLabel* label = new QLabel(mainwindow);
8954 mainwindow->setCentralWidget(label);
8955 mainwindow->setVisible(true);
8956 mainwindow->activateWindow();
8957 QTest::qWaitForWindowShown(mainwindow);
8958 qApp->processEvents();
8960 QTRY_VERIFY(mainwindow->isActiveWindow());
8962 // Create second mainwindow and set it active
8963 QMainWindow* mainwindow2 = new QMainWindow();
8964 QLabel* label2 = new QLabel(mainwindow2);
8965 mainwindow2->setCentralWidget(label2);
8966 mainwindow2->setVisible(true);
8967 mainwindow2->activateWindow();
8968 qApp->processEvents();
8970 QTRY_VERIFY(!mainwindow->isActiveWindow());
8971 QTRY_VERIFY(mainwindow2->isActiveWindow());
8973 // Revert first mainwindow back to visible active
8974 mainwindow->setVisible(true);
8975 mainwindow->activateWindow();
8976 qApp->processEvents();
8978 QTRY_VERIFY(mainwindow->isActiveWindow());
8979 QTRY_VERIFY(!mainwindow2->isActiveWindow());
8982 void tst_QWidget::openModal_taskQTBUG_5804()
8984 class Widget : public QWidget
8987 Widget(QWidget *parent) : QWidget(parent)
8993 QTimer::singleShot(10, &msgbox, SLOT(accept()));
8994 msgbox.exec(); //open a modal dialog
8998 QWidget *win = new QWidget;
9001 QTest::qWaitForWindowShown(win);
9005 void tst_QWidget::focusProxyAndInputMethods()
9007 QWidget *toplevel = new QWidget(0, Qt::X11BypassWindowManagerHint);
9008 toplevel->setAttribute(Qt::WA_InputMethodEnabled, true);
9010 QWidget *child = new QWidget(toplevel);
9011 child->setFocusProxy(toplevel);
9012 child->setAttribute(Qt::WA_InputMethodEnabled, true);
9014 toplevel->setFocusPolicy(Qt::WheelFocus);
9015 child->setFocusPolicy(Qt::WheelFocus);
9017 QVERIFY(!child->hasFocus());
9018 QVERIFY(!toplevel->hasFocus());
9021 QTest::qWaitForWindowShown(toplevel);
9022 QApplication::setActiveWindow(toplevel);
9023 QVERIFY(toplevel->hasFocus());
9024 QVERIFY(child->hasFocus());
9026 // verify that toggling input methods on the child widget
9027 // correctly propagate to the focus proxy's input method
9028 // and that the input method gets the focus proxy passed
9029 // as the focus widget instead of the child widget.
9030 // otherwise input method queries go to the wrong widget
9031 QCOMPARE(qApp->inputPanel()->inputItem(), toplevel);
9033 toplevel->setAttribute(Qt::WA_InputMethodEnabled, false);
9034 QVERIFY(!qApp->inputPanel()->inputItem());
9036 toplevel->setAttribute(Qt::WA_InputMethodEnabled, true);
9037 QCOMPARE(qApp->inputPanel()->inputItem(), toplevel);
9042 #ifdef QT_BUILD_INTERNAL
9043 class scrollWidgetWBS : public QWidget
9046 void deleteBackingStore()
9048 static_cast<QWidgetPrivate*>(d_ptr.data())->topData()->backingStoreTracker.destroy();
9050 void enableBackingStore()
9052 if (!static_cast<QWidgetPrivate*>(d_ptr.data())->maybeBackingStore()) {
9053 static_cast<QWidgetPrivate*>(d_ptr.data())->topData()->backingStoreTracker.create(this);
9054 static_cast<QWidgetPrivate*>(d_ptr.data())->invalidateBuffer(this->rect());
9061 // Test case relies on developer build (AUTOTEST_EXPORT).
9062 #ifdef QT_BUILD_INTERNAL
9063 void tst_QWidget::scrollWithoutBackingStore()
9065 scrollWidgetWBS scrollable;
9066 scrollable.resize(100,100);
9067 QLabel child(QString("@"),&scrollable);
9068 child.resize(50,50);
9070 QTest::qWaitForWindowShown(&scrollable);
9071 scrollable.scroll(50,50);
9072 QCOMPARE(child.pos(),QPoint(50,50));
9073 scrollable.deleteBackingStore();
9074 scrollable.scroll(-25,-25);
9075 QCOMPARE(child.pos(),QPoint(25,25));
9076 scrollable.enableBackingStore();
9077 QCOMPARE(child.pos(),QPoint(25,25));
9081 void tst_QWidget::taskQTBUG_7532_tabOrderWithFocusProxy()
9084 w.setFocusPolicy(Qt::TabFocus);
9085 QWidget *fp = new QWidget(&w);
9086 fp->setFocusPolicy(Qt::TabFocus);
9087 w.setFocusProxy(fp);
9088 QWidget::setTabOrder(&w, fp);
9090 // In debug mode, no assertion failure means it's alright.
9093 void tst_QWidget::movedAndResizedAttributes()
9095 #if defined (Q_OS_MAC) || defined(Q_WS_QWS)
9096 QEXPECT_FAIL("", "FixMe, QTBUG-8941 and QTBUG-8977", Abort);
9102 QVERIFY(!w.testAttribute(Qt::WA_Moved));
9103 QVERIFY(!w.testAttribute(Qt::WA_Resized));
9105 w.setWindowState(Qt::WindowFullScreen);
9107 QVERIFY(!w.testAttribute(Qt::WA_Moved));
9108 QVERIFY(!w.testAttribute(Qt::WA_Resized));
9110 w.setWindowState(Qt::WindowMaximized);
9112 QVERIFY(!w.testAttribute(Qt::WA_Moved));
9113 QVERIFY(!w.testAttribute(Qt::WA_Resized));
9115 w.setWindowState(Qt::WindowMinimized);
9117 QVERIFY(!w.testAttribute(Qt::WA_Moved));
9118 QVERIFY(!w.testAttribute(Qt::WA_Resized));
9122 QVERIFY(!w.testAttribute(Qt::WA_Moved));
9123 QVERIFY(!w.testAttribute(Qt::WA_Resized));
9127 QVERIFY(!w.testAttribute(Qt::WA_Moved));
9128 QVERIFY(!w.testAttribute(Qt::WA_Resized));
9132 QVERIFY(!w.testAttribute(Qt::WA_Moved));
9133 QVERIFY(!w.testAttribute(Qt::WA_Resized));
9137 QVERIFY(w.testAttribute(Qt::WA_Moved));
9138 #if defined(Q_OS_WIN)
9139 QEXPECT_FAIL("", "FixMe, QTBUG-8911", Abort);
9141 QVERIFY(!w.testAttribute(Qt::WA_Resized));
9144 QVERIFY(w.testAttribute(Qt::WA_Moved));
9145 QVERIFY(w.testAttribute(Qt::WA_Resized));
9149 void tst_QWidget::childAt()
9151 QWidget parent(0, Qt::FramelessWindowHint);
9152 parent.resize(200, 200);
9154 QWidget *child = new QWidget(&parent);
9155 child->setPalette(Qt::red);
9156 child->setAutoFillBackground(true);
9157 child->setGeometry(20, 20, 160, 160);
9159 QWidget *grandChild = new QWidget(child);
9160 grandChild->setPalette(Qt::blue);
9161 grandChild->setAutoFillBackground(true);
9162 grandChild->setGeometry(-20, -20, 220, 220);
9164 QVERIFY(!parent.childAt(19, 19));
9165 QVERIFY(!parent.childAt(180, 180));
9166 QCOMPARE(parent.childAt(20, 20), grandChild);
9167 QCOMPARE(parent.childAt(179, 179), grandChild);
9169 grandChild->setAttribute(Qt::WA_TransparentForMouseEvents);
9170 QCOMPARE(parent.childAt(20, 20), child);
9171 QCOMPARE(parent.childAt(179, 179), child);
9172 grandChild->setAttribute(Qt::WA_TransparentForMouseEvents, false);
9174 child->setMask(QRect(50, 50, 60, 60));
9176 QVERIFY(!parent.childAt(69, 69));
9177 QVERIFY(!parent.childAt(130, 130));
9178 QCOMPARE(parent.childAt(70, 70), grandChild);
9179 QCOMPARE(parent.childAt(129, 129), grandChild);
9181 child->setAttribute(Qt::WA_MouseNoMask);
9182 QCOMPARE(parent.childAt(69, 69), grandChild);
9183 QCOMPARE(parent.childAt(130, 130), grandChild);
9184 child->setAttribute(Qt::WA_MouseNoMask, false);
9186 grandChild->setAttribute(Qt::WA_TransparentForMouseEvents);
9187 QCOMPARE(parent.childAt(70, 70), child);
9188 QCOMPARE(parent.childAt(129, 129), child);
9189 grandChild->setAttribute(Qt::WA_TransparentForMouseEvents, false);
9191 grandChild->setMask(QRect(80, 80, 40, 40));
9193 QCOMPARE(parent.childAt(79, 79), child);
9194 QCOMPARE(parent.childAt(120, 120), child);
9195 QCOMPARE(parent.childAt(80, 80), grandChild);
9196 QCOMPARE(parent.childAt(119, 119), grandChild);
9198 grandChild->setAttribute(Qt::WA_MouseNoMask);
9200 QCOMPARE(parent.childAt(79, 79), grandChild);
9201 QCOMPARE(parent.childAt(120, 120), grandChild);
9205 void tst_QWidget::childAt_unifiedToolBar()
9207 QLabel *label = new QLabel(QLatin1String("foo"));
9208 QToolBar *toolBar = new QToolBar;
9209 toolBar->addWidget(new QLabel("dummy"));
9210 toolBar->addWidget(label);
9212 QMainWindow mainWindow;
9213 mainWindow.addToolBar(toolBar);
9216 // Calculate the top-left corner of the tool bar and the label (in mainWindow's coordinates).
9217 QPoint labelTopLeft = label->mapTo(&mainWindow, QPoint());
9218 QPoint toolBarTopLeft = toolBar->mapTo(&mainWindow, QPoint());
9220 QCOMPARE(mainWindow.childAt(toolBarTopLeft), static_cast<QWidget *>(toolBar));
9221 QCOMPARE(mainWindow.childAt(labelTopLeft), static_cast<QWidget *>(label));
9223 // Enable unified tool bars.
9224 mainWindow.setUnifiedTitleAndToolBarOnMac(true);
9227 // The tool bar is now in the "non-client" area of QMainWindow, i.e.
9228 // outside the mainWindow's rect(), and since mapTo et al. doesn't work
9229 // in that case (see commit 35667fd45ada49269a5987c235fdedfc43e92bb8),
9230 // we use mapToGlobal/mapFromGlobal to re-calculate the corners.
9231 QPoint oldToolBarTopLeft = toolBarTopLeft;
9232 toolBarTopLeft = mainWindow.mapFromGlobal(toolBar->mapToGlobal(QPoint()));
9233 QVERIFY(toolBarTopLeft != oldToolBarTopLeft);
9234 QVERIFY(toolBarTopLeft.y() < 0);
9235 labelTopLeft = mainWindow.mapFromGlobal(label->mapToGlobal(QPoint()));
9237 QCOMPARE(mainWindow.childAt(toolBarTopLeft), static_cast<QWidget *>(toolBar));
9238 QCOMPARE(mainWindow.childAt(labelTopLeft), static_cast<QWidget *>(label));
9241 void tst_QWidget::taskQTBUG_11373()
9243 QMainWindow * myWindow = new QMainWindow();
9244 QWidget * center = new QWidget();
9245 myWindow -> setCentralWidget(center);
9246 QWidget * drawer = new QWidget(myWindow, Qt::Drawer);
9248 QCOMPARE(drawer->isVisible(), false);
9250 myWindow -> raise();
9251 // The drawer shouldn't be visible now.
9252 QCOMPARE(drawer->isVisible(), false);
9253 myWindow -> setWindowState(Qt::WindowFullScreen);
9254 myWindow -> setWindowState(Qt::WindowNoState);
9255 // The drawer should still not be visible, since we haven't shown it.
9256 QCOMPARE(drawer->isVisible(), false);
9260 void tst_QWidget::taskQTBUG_17333_ResizeInfiniteRecursion()
9263 const char *s = "border: 1px solid;";
9264 tb.setStyleSheet(s);
9267 QTest::qWaitForWindowShown(&tb);
9268 tb.setGeometry(QRect(100, 100, 0, 100));
9269 // No crash, it works.
9272 void tst_QWidget::nativeChildFocus()
9275 QLayout *layout = new QVBoxLayout;
9276 w.setLayout(layout);
9277 QLineEdit *p1 = new QLineEdit;
9278 QLineEdit *p2 = new QLineEdit;
9279 layout->addWidget(p1);
9280 layout->addWidget(p2);
9281 p1->setObjectName("p1");
9282 p2->setObjectName("p2");
9286 p1->setAttribute(Qt::WA_NativeWindow);
9287 p2->setAttribute(Qt::WA_NativeWindow);
9288 QApplication::processEvents();
9289 QTest::qWaitForWindowShown(&w);
9292 QCOMPARE(QApplication::activeWindow(), &w);
9293 QCOMPARE(QApplication::focusWidget(), static_cast<QWidget*>(p1));
9298 QTEST_MAIN(tst_QWidget)
9299 #include "tst_qwidget.moc"