/**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** ** This file is part of the test suite of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage ** This file contains pre-release code and may not be distributed. ** You may use this file in accordance with the terms and conditions ** contained in the either Technology Preview License Agreement or the ** Beta Release License Agreement. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Nokia gives you certain ** additional rights. These rights are described in the Nokia Qt LGPL ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this ** package. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3.0 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU General Public License version 3.0 requirements will be ** met: http://www.gnu.org/copyleft/gpl.html. ** ** If you are unsure which license is appropriate for your use, please ** contact the sales department at qt-sales@nokia.com. ** $QT_END_LICENSE$ ** ****************************************************************************/ #if defined(QT3_SUPPORT) #include #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef Q_WS_QWS # include #endif // I *MUST* have QtTest afterwards or this test won't work with newer headers #if defined(Q_WS_MAC) # include #undef verify #include "tst_qwidget_mac_helpers.h" // Abstract the ObjC stuff out so not everyone must run an ObjC++ compile. #endif #include #if defined(Q_WS_WIN) # include # if !defined(Q_OS_WINCE) #define Q_CHECK_PAINTEVENTS \ if (::SwitchDesktop(::GetThreadDesktop(::GetCurrentThreadId())) == 0) \ QSKIP("desktop is not visible, this test would fail", SkipSingle); # else # define Q_CHECK_PAINTEVENTS # endif #elif defined(Q_WS_X11) # include # include #elif defined(Q_WS_QWS) # include #endif #if !defined(Q_WS_WIN) #define Q_CHECK_PAINTEVENTS #endif #if defined(Q_OS_WINCE_WM) #include // taken from qguifunctions_wce.cpp #define SPI_GETPLATFORMTYPE 257 bool qt_wince_is_platform(const QString &platformString) { TCHAR tszPlatform[64]; if (SystemParametersInfo(SPI_GETPLATFORMTYPE, sizeof(tszPlatform)/sizeof(*tszPlatform),tszPlatform,0)) if (0 == _tcsicmp(reinterpret_cast (platformString.utf16()), tszPlatform)) return true; return false; } bool qt_wince_is_smartphone() { return qt_wince_is_platform(QString::fromLatin1("Smartphone")); } #endif #ifdef Q_WS_MAC #include bool macHasAccessToWindowsServer() { SecuritySessionId mySession; SessionAttributeBits sessionInfo; SessionGetInfo(callerSecuritySession, &mySession, &sessionInfo); return (sessionInfo & sessionHasGraphicAccess); } #endif #if defined(Bool) #undef Bool #endif // Will try to wait for the condition while allowing event processing // for a maximum of 2 seconds. #define WAIT_FOR_CONDITION(expr, expected) \ do { \ const int step = 100; \ for (int i = 0; i < 2000 && expr != expected; i+=step) { \ QTest::qWait(step); \ } \ } while(0) //TESTED_CLASS= //TESTED_FILES= class tst_QWidget : public QObject { Q_OBJECT public: tst_QWidget(); virtual ~tst_QWidget(); public slots: void initTestCase(); void cleanupTestCase(); void init(); void cleanup(); private slots: void getSetCheck(); void fontPropagation(); void fontPropagation2(); void palettePropagation(); void palettePropagation2(); void enabledPropagation(); void acceptDropsPropagation(); void isEnabledTo(); void visible(); void visible_setWindowOpacity(); void isVisibleTo(); void isHidden(); void fonts(); void mapToGlobal(); void mapFromAndTo_data(); void mapFromAndTo(); void checkFocus(); void focusChainOnHide(); void focusChainOnReparent(); void setTabOrder(); void activation(); void reparent(); void windowState(); void showMaximized(); void showFullScreen(); void showMinimized(); void showMinimizedKeepsFocus(); void icon(); void hideWhenFocusWidgetIsChild(); void normalGeometry(); void setGeometry(); void windowOpacity(); void raise(); void lower(); void stackUnder(); void testContentsPropagation(); void saveRestoreGeometry(); void restoreVersion1Geometry_data(); void restoreVersion1Geometry(); void windowTitle(); void windowModified(); void windowIconText(); void widgetAt(); #ifdef Q_WS_MAC void retainHIView(); void sheetOpacity(); void setMask(); #endif void optimizedResizeMove(); void optimizedResize_topLevel(); void resizeEvent(); void task110173(); void testDeletionInEventHandlers(); void childDeletesItsSibling(); void setMinimumSize(); void setMaximumSize(); void setFixedSize(); void ensureCreated(); void persistentWinId(); void qobject_castInDestroyedSlot(); void showHideEvent_data(); void showHideEvent(); void lostUpdatesOnHide(); void update(); void isOpaque(); #ifndef Q_WS_MAC void scroll(); #endif // tests QWidget::setGeometry() on windows only void setWindowGeometry_data(); void setWindowGeometry(); // tests QWidget::move() and resize() on windows only void windowMoveResize_data(); void windowMoveResize(); void moveChild_data(); void moveChild(); void subtractOpaqueSiblings(); #ifdef Q_WS_WIN void getDC(); #ifndef Q_OS_WINCE void setGeometry_win(); #endif #endif void setLocale(); void deleteStyle(); void multipleToplevelFocusCheck(); void setFocus(); void setCursor(); void setToolTip(); void testWindowIconChangeEventPropagation(); #ifdef Q_WS_X11 void minAndMaxSizeWithX11BypassWindowManagerHint(); void showHideShow(); #endif void compatibilityChildInsertedEvents(); void render(); void renderInvisible(); void renderWithPainter(); void render_task188133(); void render_task211796(); void render_task217815(); void render_windowOpacity(); void render_systemClip(); void render_systemClip2_data(); void render_systemClip2(); void render_systemClip3_data(); void render_systemClip3(); void render_task252837(); void render_worldTransform(); void setContentsMargins(); void moveWindowInShowEvent_data(); void moveWindowInShowEvent(); void repaintWhenChildDeleted(); void hideOpaqueChildWhileHidden(); void updateWhileMinimized(); #if defined(Q_WS_WIN) || defined(Q_WS_X11) void alienWidgets(); #endif void adjustSize(); void adjustSize_data(); void updateGeometry(); void updateGeometry_data(); void sendUpdateRequestImmediately(); void painterRedirection(); void doubleRepaint(); #ifndef Q_WS_MAC void resizeInPaintEvent(); #endif void setMaskInResizeEvent(); void moveInResizeEvent(); #if defined(Q_WS_WIN) || defined(Q_WS_X11) // We don't support immediate repaint right after show on // other platforms. Must be compatible with Qt 4.3. void immediateRepaintAfterShow(); void immediateRepaintAfterInvalidateBuffer(); #endif void effectiveWinId(); void customDpi(); void customDpiProperty(); void quitOnCloseAttribute(); void moveRect(); #if defined (Q_WS_WIN) void gdiPainting(); void paintOnScreenPossible(); #endif void reparentStaticWidget(); #ifdef Q_WS_QWS void updateOutsideSurfaceClip(); #endif void translucentWidget(); void setClearAndResizeMask(); void maskedUpdate(); #if defined(Q_WS_WIN) || defined(Q_WS_X11) void syntheticEnterLeave(); #endif void windowFlags(); void initialPosForDontShowOnScreenWidgets(); #ifdef Q_WS_X11 void paintOutsidePaintEvent(); #endif void updateOnDestroyedSignal(); void toplevelLineEditFocus(); void focusWidget_task254563(); private: bool ensureScreenSize(int width, int height); QWidget *testWidget; }; bool tst_QWidget::ensureScreenSize(int width, int height) { QSize available; #ifdef Q_WS_QWS available = QDesktopWidget().availableGeometry().size(); if (available.width() < width || available.height() < height) { QScreen *screen = QScreen::instance(); if (!screen) return false; screen->setMode(width, height, screen->depth()); } #endif // Q_WS_QWS available = QDesktopWidget().availableGeometry().size(); return (available.width() >= width && available.height() >= height); } class MyInputContext : public QInputContext { public: MyInputContext() : QInputContext() {} QString identifierName() { return QString("NoName"); } QString language() { return QString("NoLanguage"); } void reset() {} bool isComposing() const { return false; } }; // Testing get/set functions void tst_QWidget::getSetCheck() { QWidget obj1; QWidget child1(&obj1); // QStyle * QWidget::style() // void QWidget::setStyle(QStyle *) QWindowsStyle *var1 = new QWindowsStyle; obj1.setStyle(var1); QCOMPARE(static_cast(var1), obj1.style()); obj1.setStyle((QStyle *)0); QVERIFY(var1 != obj1.style()); QVERIFY(0 != obj1.style()); // style can never be 0 for a widget // int QWidget::minimumWidth() // void QWidget::setMinimumWidth(int) obj1.setMinimumWidth(0); QCOMPARE(obj1.minimumWidth(), 0); obj1.setMinimumWidth(INT_MIN); QCOMPARE(obj1.minimumWidth(), 0); // A widgets width can never be less than 0 obj1.setMinimumWidth(INT_MAX); #ifndef Q_WS_QWS //QWS doesn't allow toplevels to be bigger than the screen #if defined(Q_CC_MSVC) && !defined(Q_CC_MSVC_NET) QCOMPARE((long)obj1.minimumWidth(), QWIDGETSIZE_MAX); // The largest minimum size should only be as big as the maximium #else QCOMPARE(obj1.minimumWidth(), QWIDGETSIZE_MAX); // The largest minimum size should only be as big as the maximium #endif #endif child1.setMinimumWidth(0); QCOMPARE(child1.minimumWidth(), 0); child1.setMinimumWidth(INT_MIN); QCOMPARE(child1.minimumWidth(), 0); // A widgets width can never be less than 0 child1.setMinimumWidth(INT_MAX); #if defined(Q_CC_MSVC) && !defined(Q_CC_MSVC_NET) QCOMPARE((long)child1.minimumWidth(), QWIDGETSIZE_MAX); // The largest minimum size should only be as big as the maximium #else QCOMPARE(child1.minimumWidth(), QWIDGETSIZE_MAX); // The largest minimum size should only be as big as the maximium #endif // int QWidget::minimumHeight() // void QWidget::setMinimumHeight(int) obj1.setMinimumHeight(0); QCOMPARE(obj1.minimumHeight(), 0); obj1.setMinimumHeight(INT_MIN); QCOMPARE(obj1.minimumHeight(), 0); // A widgets height can never be less than 0 obj1.setMinimumHeight(INT_MAX); #ifndef Q_WS_QWS //QWS doesn't allow toplevels to be bigger than the screen #if defined(Q_CC_MSVC) && !defined(Q_CC_MSVC_NET) QCOMPARE((long)obj1.minimumHeight(), QWIDGETSIZE_MAX); // The largest minimum size should only be as big as the maximium #else QCOMPARE(obj1.minimumHeight(), QWIDGETSIZE_MAX); // The largest minimum size should only be as big as the maximium #endif #endif child1.setMinimumHeight(0); QCOMPARE(child1.minimumHeight(), 0); child1.setMinimumHeight(INT_MIN); QCOMPARE(child1.minimumHeight(), 0); // A widgets height can never be less than 0 child1.setMinimumHeight(INT_MAX); #if defined(Q_CC_MSVC) && !defined(Q_CC_MSVC_NET) QCOMPARE((long)child1.minimumHeight(), QWIDGETSIZE_MAX); // The largest minimum size should only be as big as the maximium #else QCOMPARE(child1.minimumHeight(), QWIDGETSIZE_MAX); // The largest minimum size should only be as big as the maximium #endif // int QWidget::maximumWidth() // void QWidget::setMaximumWidth(int) obj1.setMaximumWidth(0); QCOMPARE(obj1.maximumWidth(), 0); obj1.setMaximumWidth(INT_MIN); QCOMPARE(obj1.maximumWidth(), 0); // A widgets width can never be less than 0 obj1.setMaximumWidth(INT_MAX); #if defined(Q_CC_MSVC) && !defined(Q_CC_MSVC_NET) QCOMPARE((long)obj1.maximumWidth(), QWIDGETSIZE_MAX); // QWIDGETSIZE_MAX is the abs max, not INT_MAX #else QCOMPARE(obj1.maximumWidth(), QWIDGETSIZE_MAX); // QWIDGETSIZE_MAX is the abs max, not INT_MAX #endif // int QWidget::maximumHeight() // void QWidget::setMaximumHeight(int) obj1.setMaximumHeight(0); QCOMPARE(obj1.maximumHeight(), 0); obj1.setMaximumHeight(INT_MIN); QCOMPARE(obj1.maximumHeight(), 0); // A widgets height can never be less than 0 obj1.setMaximumHeight(INT_MAX); #if defined(Q_CC_MSVC) && !defined(Q_CC_MSVC_NET) QCOMPARE((long)obj1.maximumHeight(), QWIDGETSIZE_MAX); // QWIDGETSIZE_MAX is the abs max, not INT_MAX #else QCOMPARE(obj1.maximumHeight(), QWIDGETSIZE_MAX); // QWIDGETSIZE_MAX is the abs max, not INT_MAX #endif // back to normal obj1.setMinimumWidth(0); obj1.setMinimumHeight(0); obj1.setMaximumWidth(QWIDGETSIZE_MAX); obj1.setMaximumHeight(QWIDGETSIZE_MAX); // const QPalette & QWidget::palette() // void QWidget::setPalette(const QPalette &) QPalette var6; obj1.setPalette(var6); QCOMPARE(var6, obj1.palette()); obj1.setPalette(QPalette()); QCOMPARE(QPalette(), obj1.palette()); // const QFont & QWidget::font() // void QWidget::setFont(const QFont &) QFont var7; obj1.setFont(var7); QCOMPARE(var7, obj1.font()); obj1.setFont(QFont()); QCOMPARE(QFont(), obj1.font()); // qreal QWidget::windowOpacity() // void QWidget::setWindowOpacity(qreal) obj1.setWindowOpacity(0.0); QCOMPARE(0.0, obj1.windowOpacity()); obj1.setWindowOpacity(1.1f); QCOMPARE(1.0, obj1.windowOpacity()); // 1.0 is the fullest opacity possible // QWidget * QWidget::focusProxy() // void QWidget::setFocusProxy(QWidget *) QWidget *var9 = new QWidget(); obj1.setFocusProxy(var9); QCOMPARE(var9, obj1.focusProxy()); obj1.setFocusProxy((QWidget *)0); QCOMPARE((QWidget *)0, obj1.focusProxy()); delete var9; // const QRect & QWidget::geometry() // void QWidget::setGeometry(const QRect &) qApp->processEvents(); QRect var10(10, 10, 100, 100); obj1.setGeometry(var10); qApp->processEvents(); qDebug() << obj1.geometry(); QCOMPARE(var10, obj1.geometry()); obj1.setGeometry(QRect(0,0,0,0)); qDebug() << obj1.geometry(); QCOMPARE(QRect(0,0,0,0), obj1.geometry()); // QLayout * QWidget::layout() // void QWidget::setLayout(QLayout *) QBoxLayout *var11 = new QBoxLayout(QBoxLayout::LeftToRight); obj1.setLayout(var11); QCOMPARE(static_cast(var11), obj1.layout()); obj1.setLayout((QLayout *)0); QCOMPARE(static_cast(var11), obj1.layout()); // You cannot set a 0-pointer layout, that keeps the current delete var11; // This will remove the layout from the widget QCOMPARE((QLayout *)0, obj1.layout()); // bool QWidget::acceptDrops() // void QWidget::setAcceptDrops(bool) obj1.setAcceptDrops(false); QCOMPARE(false, obj1.acceptDrops()); obj1.setAcceptDrops(true); QCOMPARE(true, obj1.acceptDrops()); // QInputContext * QWidget::inputContext() // void QWidget::setInputContext(QInputContext *) MyInputContext *var13 = new MyInputContext; obj1.setInputContext(var13); QCOMPARE((QInputContext *)0, obj1.inputContext()); // The widget by default doesn't have the WA_InputMethodEnabled attribute obj1.setAttribute(Qt::WA_InputMethodEnabled); obj1.setInputContext(var13); QCOMPARE(static_cast(var13), obj1.inputContext()); obj1.setInputContext((QInputContext *)0); QCOMPARE(qApp->inputContext(), obj1.inputContext()); QVERIFY(qApp->inputContext() != var13); //delete var13; // No delete, since QWidget takes ownership // bool QWidget::autoFillBackground() // void QWidget::setAutoFillBackground(bool) obj1.setAutoFillBackground(false); QCOMPARE(false, obj1.autoFillBackground()); obj1.setAutoFillBackground(true); QCOMPARE(true, obj1.autoFillBackground()); delete var1; #if defined (Q_WS_WIN) && !defined(Q_OS_WINCE) obj1.setWindowFlags(Qt::FramelessWindowHint | Qt::WindowSystemMenuHint); HWND handle = obj1.winId(); long flags = GetWindowLong(handle, GWL_STYLE); QVERIFY(flags & WS_POPUP); #endif } tst_QWidget::tst_QWidget() { QFont font; font.setBold(true); font.setPointSize(42); qApp->setFont(font, "QPropagationTestWidget"); QPalette palette; palette.setColor(QPalette::ToolTipBase, QColor(12, 13, 14)); palette.setColor(QPalette::Text, QColor(21, 22, 23)); qApp->setPalette(palette, "QPropagationTestWidget"); testWidget = 0; } tst_QWidget::~tst_QWidget() { } class BezierViewer : public QWidget { public: BezierViewer( QWidget* parent=0, const char* name=0 ); void paintEvent( QPaintEvent* ); void setPoints( const QPolygonF& poly ); private: QPolygonF points; }; void tst_QWidget::initTestCase() { #ifdef Q_OS_WINCE //disable magic for WindowsCE qApp->setAutoMaximizeThreshold(-1); #endif // Create the test class testWidget = new BezierViewer( 0, "testObject"); testWidget->resize(200,200); #ifdef QT3_SUPPORT qApp->setMainWidget(testWidget); #endif testWidget->show(); #ifdef Q_WS_X11 qt_x11_wait_for_window_manager(testWidget); #endif } void tst_QWidget::cleanupTestCase() { delete testWidget; testWidget = 0; } void tst_QWidget::init() { // TODO: Add initialization code here. // This will be executed immediately before each test is run. testWidget->setFont(QFont()); testWidget->setPalette(QPalette()); } void tst_QWidget::cleanup() { } // Helper class... BezierViewer::BezierViewer( QWidget* parent, const char* name ) : QWidget( parent ) { setObjectName(name); QPalette pal; pal.setColor(backgroundRole(), Qt::white); setPalette(pal); } void BezierViewer::setPoints( const QPolygonF& a ) { points = a; } #include "private/qbezier_p.h" void BezierViewer::paintEvent( QPaintEvent* ) { if ( points.size() != 4 ) { #if defined(QT_CHECK_RANGE) qWarning( "QPolygon::bezier: The array must have 4 control points" ); #endif return; } /* Calculate Bezier curve */ QPolygonF bezier = QBezier::fromPoints(points.at(0),points.at(1),points.at(2),points.at(3)).toPolygon(); QPainter painter( this ); /* Calculate scale to fit in window */ QRectF br = bezier.boundingRect() | points.boundingRect(); QRectF pr = rect(); int scl = qMax( qMin(pr.width()/br.width(), pr.height()/br.height()), qreal(1.) ); int border = scl-1; /* Scale Bezier curve vertices */ for ( QPolygonF::Iterator it = bezier.begin(); it != bezier.end(); ++it ) { it->setX( (it->x()-br.x()) * scl + border ); it->setY( (it->y()-br.y()) * scl + border ); } /* Draw grid */ painter.setPen( Qt::lightGray ); int i; for ( i = border; i <= pr.width(); i += scl ) { painter.drawLine( i, 0, i, pr.height() ); } for ( int j = border; j <= pr.height(); j += scl ) { painter.drawLine( 0, j, pr.width(), j ); } /* Write number of vertices */ painter.setPen( Qt::red ); painter.setFont( QFont("Helvetica", 14, QFont::DemiBold, TRUE ) ); QString caption; caption.setNum( bezier.size() ); caption += QString::fromLatin1( " vertices" ); painter.drawText( 10, pr.height()-10, caption ); /* Draw Bezier curve */ painter.setPen( Qt::black ); painter.drawPolyline( bezier ); /* Scale and draw control points */ painter.setPen( Qt::darkGreen ); for ( QPolygonF::Iterator p1 = points.begin(); p1 != points.end(); ++p1 ) { int x = (p1->x()-br.x()) * scl + border; int y = (p1->y()-br.y()) * scl + border; painter.drawLine( x-4, y-4, x+4, y+4 ); painter.drawLine( x+4, y-4, x-4, y+4 ); } /* Draw vertices */ painter.setPen( Qt::red ); painter.setBrush( Qt::red ); for ( QPolygonF::Iterator p2 = bezier.begin(); p2 != bezier.end(); ++p2 ) painter.drawEllipse( p2->x()-1, p2->y()-1, 3, 3 ); } void tst_QWidget::fontPropagation() { QFont font = testWidget->font(); QWidget* childWidget = new QWidget( testWidget ); childWidget->show(); QCOMPARE( font, childWidget->font() ); font.setBold( TRUE ); testWidget->setFont( font ); QCOMPARE( font, testWidget->font() ); QCOMPARE( font, childWidget->font() ); QFont newFont = font; newFont.setItalic( TRUE ); childWidget->setFont( newFont ); QWidget* grandChildWidget = new QWidget( childWidget ); QCOMPARE( font, testWidget->font() ); QCOMPARE( newFont, grandChildWidget->font() ); font.setUnderline( TRUE ); testWidget->setFont( font ); // the child and grand child should now have merged bold and // underline newFont.setUnderline( TRUE ); QCOMPARE( newFont, childWidget->font() ); QCOMPARE( newFont, grandChildWidget->font() ); // make sure font propagation continues working after reparenting font = testWidget->font(); font.setPointSize(font.pointSize() + 2); testWidget->setFont(font); QWidget *one = new QWidget(testWidget); QWidget *two = new QWidget(one); QWidget *three = new QWidget(two); QWidget *four = new QWidget(two); four->setParent(three); four->move(QPoint(0,0)); font.setPointSize(font.pointSize() + 2); testWidget->setFont(font); QCOMPARE(testWidget->font(), one->font()); QCOMPARE(one->font(), two->font()); QCOMPARE(two->font(), three->font()); QCOMPARE(three->font(), four->font()); QVERIFY(testWidget->testAttribute(Qt::WA_SetFont)); QVERIFY(! one->testAttribute(Qt::WA_SetFont)); QVERIFY(! two->testAttribute(Qt::WA_SetFont)); QVERIFY(! three->testAttribute(Qt::WA_SetFont)); QVERIFY(! four->testAttribute(Qt::WA_SetFont)); font.setPointSize(font.pointSize() + 2); one->setFont(font); QCOMPARE(one->font(), two->font()); QCOMPARE(two->font(), three->font()); QCOMPARE(three->font(), four->font()); QVERIFY(one->testAttribute(Qt::WA_SetFont)); QVERIFY(! two->testAttribute(Qt::WA_SetFont)); QVERIFY(! three->testAttribute(Qt::WA_SetFont)); QVERIFY(! four->testAttribute(Qt::WA_SetFont)); font.setPointSize(font.pointSize() + 2); two->setFont(font); QCOMPARE(two->font(), three->font()); QCOMPARE(three->font(), four->font()); QVERIFY(two->testAttribute(Qt::WA_SetFont)); QVERIFY(! three->testAttribute(Qt::WA_SetFont)); QVERIFY(! four->testAttribute(Qt::WA_SetFont)); font.setPointSize(font.pointSize() + 2); three->setFont(font); QCOMPARE(three->font(), four->font()); QVERIFY(three->testAttribute(Qt::WA_SetFont)); QVERIFY(! four->testAttribute(Qt::WA_SetFont)); font.setPointSize(font.pointSize() + 2); four->setFont(font); QVERIFY(four->testAttribute(Qt::WA_SetFont)); } class QPropagationTestWidget : public QWidget { Q_OBJECT public: QPropagationTestWidget(QWidget *parent = 0) : QWidget(parent) { } }; void tst_QWidget::fontPropagation2() { // ! Note, the code below is executed in tst_QWidget's constructor. // QFont font; // font.setBold(true); // font.setPointSize(42); // qApp->setFont(font, "QPropagationTestWidget"); QWidget *root = new QWidget; QWidget *child0 = new QWidget(root); QWidget *child1 = new QWidget(child0); QWidget *child2 = new QPropagationTestWidget(child1); QWidget *child3 = new QWidget(child2); QWidget *child4 = new QWidget(child3); QWidget *child5 = new QWidget(child4); root->show(); // Check that only the application fonts apply. QCOMPARE(root->font(), QApplication::font()); QCOMPARE(child0->font(), QApplication::font()); QCOMPARE(child1->font(), QApplication::font()); QCOMPARE(child2->font().pointSize(), 42); QVERIFY(child2->font().bold()); QCOMPARE(child3->font().pointSize(), 42); QVERIFY(child3->font().bold()); QCOMPARE(child4->font().pointSize(), 42); QVERIFY(child4->font().bold()); QCOMPARE(child5->font().pointSize(), 42); QVERIFY(child5->font().bold()); // Set child0's font size to 15, and remove bold on child4. QFont font; font.setPointSize(15); child0->setFont(font); QFont unboldFont; unboldFont.setBold(false); child4->setFont(unboldFont); // Check that the above settings propagate correctly. QCOMPARE(root->font(), QApplication::font()); QCOMPARE(child0->font().pointSize(), 15); QVERIFY(!child0->font().bold()); QCOMPARE(child1->font().pointSize(), 15); QVERIFY(!child1->font().bold()); QCOMPARE(child2->font().pointSize(), 15); QVERIFY(child2->font().bold()); QCOMPARE(child3->font().pointSize(), 15); QVERIFY(child3->font().bold()); QCOMPARE(child4->font().pointSize(), 15); QVERIFY(!child4->font().bold()); QCOMPARE(child5->font().pointSize(), 15); QVERIFY(!child5->font().bold()); // Replace the app font for child2. Italic should propagate // but the size should still be ignored. The previous bold // setting is gone. QFont italicSizeFont; italicSizeFont.setItalic(true); italicSizeFont.setPointSize(33); qApp->setFont(italicSizeFont, "QPropagationTestWidget"); // Check that this propagates correctly. QCOMPARE(root->font(), QApplication::font()); QCOMPARE(child0->font().pointSize(), 15); QVERIFY(!child0->font().bold()); QVERIFY(!child0->font().italic()); QCOMPARE(child1->font().pointSize(), 15); QVERIFY(!child1->font().bold()); QVERIFY(!child1->font().italic()); QCOMPARE(child2->font().pointSize(), 15); QVERIFY(!child2->font().bold()); QVERIFY(child2->font().italic()); QCOMPARE(child3->font().pointSize(), 15); QVERIFY(!child3->font().bold()); QVERIFY(child3->font().italic()); QCOMPARE(child4->font().pointSize(), 15); QVERIFY(!child4->font().bold()); QVERIFY(child4->font().italic()); QCOMPARE(child5->font().pointSize(), 15); QVERIFY(!child5->font().bold()); QVERIFY(child5->font().italic()); } void tst_QWidget::palettePropagation() { QPalette palette = testWidget->palette(); QWidget* childWidget = new QWidget( testWidget ); childWidget->show(); QCOMPARE( palette, childWidget->palette() ); palette.setColor( QPalette::Base, Qt::red ); testWidget->setPalette( palette ); QCOMPARE( palette, testWidget->palette() ); QCOMPARE( palette, childWidget->palette() ); QPalette newPalette = palette; newPalette.setColor( QPalette::Highlight, Qt::green ); childWidget->setPalette( newPalette ); QWidget* grandChildWidget = new QWidget( childWidget ); QCOMPARE( palette, testWidget->palette() ); QCOMPARE( newPalette, grandChildWidget->palette() ); palette.setColor( QPalette::Text, Qt::blue ); testWidget->setPalette( palette ); // the child and grand child should now have merged green // highlight and blue text newPalette.setColor( QPalette::Text, Qt::blue); QCOMPARE( newPalette, childWidget->palette() ); QCOMPARE( newPalette, grandChildWidget->palette() ); } void tst_QWidget::palettePropagation2() { // ! Note, the code below is executed in tst_QWidget's constructor. // QPalette palette; // font.setColor(QPalette::ToolTipBase, QColor(12, 13, 14)); // font.setColor(QPalette::Text, QColor(21, 22, 23)); // qApp->setPalette(palette, "QPropagationTestWidget"); QWidget *root = new QWidget; QWidget *child0 = new QWidget(root); QWidget *child1 = new QWidget(child0); QWidget *child2 = new QPropagationTestWidget(child1); QWidget *child3 = new QWidget(child2); QWidget *child4 = new QWidget(child3); QWidget *child5 = new QWidget(child4); root->show(); QTest::qWait(100); // These colors are unlikely to be imposed on the default palette of // QWidget ;-). QColor sysPalText(21, 22, 23); QColor sysPalToolTipBase(12, 13, 14); QColor overridePalText(42, 43, 44); QColor overridePalToolTipBase(45, 46, 47); QColor sysPalButton(99, 98, 97); // Check that only the application fonts apply. QPalette appPal = QApplication::palette(); QCOMPARE(root->palette(), appPal); QCOMPARE(child0->palette(), appPal); QCOMPARE(child1->palette(), appPal); QCOMPARE(child2->palette().color(QPalette::ToolTipBase), sysPalToolTipBase); QCOMPARE(child2->palette().color(QPalette::Text), sysPalText); QCOMPARE(child2->palette().color(QPalette::ToolTipText), appPal.color(QPalette::ToolTipText)); QCOMPARE(child3->palette().color(QPalette::ToolTipBase), sysPalToolTipBase); QCOMPARE(child3->palette().color(QPalette::Text), sysPalText); QCOMPARE(child3->palette().color(QPalette::ToolTipText), appPal.color(QPalette::ToolTipText)); QCOMPARE(child4->palette().color(QPalette::ToolTipBase), sysPalToolTipBase); QCOMPARE(child4->palette().color(QPalette::Text), sysPalText); QCOMPARE(child4->palette().color(QPalette::ToolTipText), appPal.color(QPalette::ToolTipText)); QCOMPARE(child5->palette().color(QPalette::ToolTipBase), sysPalToolTipBase); QCOMPARE(child5->palette().color(QPalette::Text), sysPalText); QCOMPARE(child5->palette().color(QPalette::ToolTipText), appPal.color(QPalette::ToolTipText)); // Set child0's Text, and set ToolTipBase on child4. QPalette textPalette; textPalette.setColor(QPalette::Text, overridePalText); child0->setPalette(textPalette); QPalette toolTipPalette; toolTipPalette.setColor(QPalette::ToolTipBase, overridePalToolTipBase); child4->setPalette(toolTipPalette); // Check that the above settings propagate correctly. QCOMPARE(root->palette(), appPal); QCOMPARE(child0->palette().color(QPalette::Text), overridePalText); QCOMPARE(child0->palette().color(QPalette::ToolTipBase), appPal.color(QPalette::ToolTipBase)); QCOMPARE(child0->palette().color(QPalette::ToolTipText), appPal.color(QPalette::ToolTipText)); QCOMPARE(child1->palette().color(QPalette::Text), overridePalText); QCOMPARE(child1->palette().color(QPalette::ToolTipBase), appPal.color(QPalette::ToolTipBase)); QCOMPARE(child1->palette().color(QPalette::ToolTipText), appPal.color(QPalette::ToolTipText)); QCOMPARE(child2->palette().color(QPalette::Text), overridePalText); QCOMPARE(child2->palette().color(QPalette::ToolTipBase), sysPalToolTipBase); QCOMPARE(child2->palette().color(QPalette::ToolTipText), appPal.color(QPalette::ToolTipText)); QCOMPARE(child3->palette().color(QPalette::Text), overridePalText); QCOMPARE(child3->palette().color(QPalette::ToolTipBase), sysPalToolTipBase); QCOMPARE(child3->palette().color(QPalette::ToolTipText), appPal.color(QPalette::ToolTipText)); QCOMPARE(child4->palette().color(QPalette::Text), overridePalText); QCOMPARE(child4->palette().color(QPalette::ToolTipBase), overridePalToolTipBase); QCOMPARE(child4->palette().color(QPalette::ToolTipText), appPal.color(QPalette::ToolTipText)); QCOMPARE(child5->palette().color(QPalette::Text), overridePalText); QCOMPARE(child5->palette().color(QPalette::ToolTipBase), overridePalToolTipBase); QCOMPARE(child5->palette().color(QPalette::ToolTipText), appPal.color(QPalette::ToolTipText)); // Replace the app palette for child2. Button should propagate but Text // should still be ignored. The previous ToolTipBase setting is gone. QPalette buttonPalette; buttonPalette.setColor(QPalette::ToolTipText, sysPalButton); qApp->setPalette(buttonPalette, "QPropagationTestWidget"); // Check that the above settings propagate correctly. QCOMPARE(root->palette(), appPal); QCOMPARE(child0->palette().color(QPalette::Text), overridePalText); QCOMPARE(child0->palette().color(QPalette::ToolTipBase), appPal.color(QPalette::ToolTipBase)); QCOMPARE(child0->palette().color(QPalette::ToolTipText), appPal.color(QPalette::ToolTipText)); QCOMPARE(child1->palette().color(QPalette::Text), overridePalText); QCOMPARE(child1->palette().color(QPalette::ToolTipBase), appPal.color(QPalette::ToolTipBase)); QCOMPARE(child1->palette().color(QPalette::ToolTipText), appPal.color(QPalette::ToolTipText)); QCOMPARE(child2->palette().color(QPalette::Text), overridePalText); QCOMPARE(child2->palette().color(QPalette::ToolTipBase), appPal.color(QPalette::ToolTipBase)); QCOMPARE(child2->palette().color(QPalette::ToolTipText), sysPalButton); QCOMPARE(child3->palette().color(QPalette::Text), overridePalText); QCOMPARE(child3->palette().color(QPalette::ToolTipBase), appPal.color(QPalette::ToolTipBase)); QCOMPARE(child3->palette().color(QPalette::ToolTipText), sysPalButton); QCOMPARE(child4->palette().color(QPalette::Text), overridePalText); QCOMPARE(child4->palette().color(QPalette::ToolTipBase), overridePalToolTipBase); QCOMPARE(child4->palette().color(QPalette::ToolTipText), sysPalButton); QCOMPARE(child5->palette().color(QPalette::Text), overridePalText); QCOMPARE(child5->palette().color(QPalette::ToolTipBase), overridePalToolTipBase); QCOMPARE(child5->palette().color(QPalette::ToolTipText), sysPalButton); } void tst_QWidget::enabledPropagation() { QWidget* childWidget = new QWidget( testWidget ); childWidget->show(); QVERIFY( testWidget->isEnabled() ); QVERIFY( childWidget->isEnabled() ); testWidget->setEnabled( FALSE ); QVERIFY( !testWidget->isEnabled() ); QVERIFY( !childWidget->isEnabled() ); testWidget->setDisabled( FALSE ); QVERIFY( testWidget->isEnabled() ); QVERIFY( childWidget->isEnabled() ); QWidget* grandChildWidget = new QWidget( childWidget ); QVERIFY( grandChildWidget->isEnabled() ); testWidget->setDisabled( TRUE ); QVERIFY( !testWidget->isEnabled() ); QVERIFY( !childWidget->isEnabled() ); QVERIFY( !grandChildWidget->isEnabled() ); grandChildWidget->setEnabled( FALSE ); testWidget->setEnabled( TRUE ); QVERIFY( testWidget->isEnabled() ); QVERIFY( childWidget->isEnabled() ); QVERIFY( !grandChildWidget->isEnabled() ); grandChildWidget->setEnabled( TRUE ); testWidget->setEnabled( FALSE ); childWidget->setDisabled( TRUE ); testWidget->setEnabled( TRUE ); QVERIFY( testWidget->isEnabled() ); QVERIFY( !childWidget->isEnabled() ); QVERIFY( !grandChildWidget->isEnabled() ); } void tst_QWidget::acceptDropsPropagation() { QWidget *childWidget = new QWidget(testWidget); childWidget->show(); QVERIFY(!testWidget->acceptDrops()); QVERIFY(!childWidget->acceptDrops()); testWidget->setAcceptDrops(true); QVERIFY(testWidget->acceptDrops()); QVERIFY(!childWidget->acceptDrops()); QVERIFY(childWidget->testAttribute(Qt::WA_DropSiteRegistered)); testWidget->setAcceptDrops(false); QVERIFY(!testWidget->acceptDrops()); QVERIFY(!childWidget->acceptDrops()); QVERIFY(!childWidget->testAttribute(Qt::WA_DropSiteRegistered)); QWidget *grandChildWidget = new QWidget(childWidget); QVERIFY(!grandChildWidget->acceptDrops()); QVERIFY(!grandChildWidget->testAttribute(Qt::WA_DropSiteRegistered)); testWidget->setAcceptDrops(true); QVERIFY(testWidget->acceptDrops()); QVERIFY(!childWidget->acceptDrops()); QVERIFY(childWidget->testAttribute(Qt::WA_DropSiteRegistered)); QVERIFY(!grandChildWidget->acceptDrops()); QVERIFY(grandChildWidget->testAttribute(Qt::WA_DropSiteRegistered)); grandChildWidget->setAcceptDrops(true); testWidget->setAcceptDrops(false); QVERIFY(!testWidget->acceptDrops()); QVERIFY(!childWidget->acceptDrops()); QVERIFY(grandChildWidget->acceptDrops()); QVERIFY(grandChildWidget->testAttribute(Qt::WA_DropSiteRegistered)); grandChildWidget->setAcceptDrops(false); QVERIFY(!grandChildWidget->testAttribute(Qt::WA_DropSiteRegistered)); testWidget->setAcceptDrops(true); childWidget->setAcceptDrops(true); testWidget->setAcceptDrops(false); QVERIFY(!testWidget->acceptDrops()); QVERIFY(childWidget->acceptDrops()); QVERIFY(!grandChildWidget->acceptDrops()); QVERIFY(grandChildWidget->testAttribute(Qt::WA_DropSiteRegistered)); } void tst_QWidget::isEnabledTo() { QWidget* childWidget = new QWidget( testWidget ); QWidget* grandChildWidget = new QWidget( childWidget ); QVERIFY( childWidget->isEnabledTo( testWidget ) ); QVERIFY( grandChildWidget->isEnabledTo( testWidget ) ); childWidget->setEnabled( FALSE ); QVERIFY( !childWidget->isEnabledTo( testWidget ) ); QVERIFY( grandChildWidget->isEnabledTo( childWidget ) ); QVERIFY( !grandChildWidget->isEnabledTo( testWidget ) ); } void tst_QWidget::visible() { // Ensure that the testWidget is hidden for this test at the // start testWidget->hide(); QVERIFY( !testWidget->isVisible() ); QWidget* childWidget = new QWidget( testWidget ); QVERIFY( !childWidget->isVisible() ); testWidget->show(); QVERIFY( testWidget->isVisible() ); QVERIFY( childWidget->isVisible() ); QWidget* grandChildWidget = new QWidget( childWidget ); QVERIFY( !grandChildWidget->isVisible() ); grandChildWidget->show(); QVERIFY( grandChildWidget->isVisible() ); grandChildWidget->hide(); testWidget->hide(); testWidget->show(); QVERIFY( !grandChildWidget->isVisible() ); QVERIFY( testWidget->isVisible() ); QVERIFY( childWidget->isVisible() ); grandChildWidget->show(); childWidget->hide(); testWidget->hide(); testWidget->show(); QVERIFY( testWidget->isVisible() ); QVERIFY( !childWidget->isVisible() ); QVERIFY( !grandChildWidget->isVisible() ); grandChildWidget->show(); QVERIFY( !grandChildWidget->isVisible() ); } void tst_QWidget::setLocale() { QWidget w; QCOMPARE(w.locale(), QLocale()); w.setLocale(QLocale::Italian); QCOMPARE(w.locale(), QLocale(QLocale::Italian)); QWidget child1(&w); QCOMPARE(child1.locale(), QLocale(QLocale::Italian)); w.unsetLocale(); QCOMPARE(w.locale(), QLocale()); QCOMPARE(child1.locale(), QLocale()); w.setLocale(QLocale::French); QCOMPARE(w.locale(), QLocale(QLocale::French)); QCOMPARE(child1.locale(), QLocale(QLocale::French)); child1.setLocale(QLocale::Italian); QCOMPARE(w.locale(), QLocale(QLocale::French)); QCOMPARE(child1.locale(), QLocale(QLocale::Italian)); child1.unsetLocale(); QCOMPARE(w.locale(), QLocale(QLocale::French)); QCOMPARE(child1.locale(), QLocale(QLocale::French)); QWidget child2; QCOMPARE(child2.locale(), QLocale()); child2.setParent(&w); QCOMPARE(child2.locale(), QLocale(QLocale::French)); } void tst_QWidget::visible_setWindowOpacity() { testWidget->hide(); QVERIFY( !testWidget->isVisible() ); testWidget->setWindowOpacity(0.5); #ifdef Q_OS_WIN QVERIFY(::IsWindowVisible(testWidget->winId()) == FALSE); #endif testWidget->setWindowOpacity(1.0); } void tst_QWidget::isVisibleTo() { // Ensure that the testWidget is hidden for this test at the // start testWidget->hide(); QWidget* childWidget = new QWidget( testWidget ); QVERIFY( childWidget->isVisibleTo( testWidget ) ); childWidget->hide(); QVERIFY( !childWidget->isVisibleTo( testWidget ) ); QWidget* grandChildWidget = new QWidget( childWidget ); QVERIFY( !grandChildWidget->isVisibleTo( testWidget ) ); QVERIFY( grandChildWidget->isVisibleTo( childWidget ) ); testWidget->show(); childWidget->show(); QVERIFY( childWidget->isVisibleTo( testWidget ) ); grandChildWidget->hide(); QVERIFY( !grandChildWidget->isVisibleTo( childWidget ) ); QVERIFY( !grandChildWidget->isVisibleTo( testWidget ) ); } void tst_QWidget::isHidden() { // Ensure that the testWidget is hidden for this test at the // start testWidget->hide(); QVERIFY( testWidget->isHidden() ); QWidget* childWidget = new QWidget( testWidget ); QVERIFY( !childWidget->isHidden() ); testWidget->show(); QVERIFY( !testWidget->isHidden() ); QVERIFY( !childWidget->isHidden() ); QWidget* grandChildWidget = new QWidget( childWidget ); QVERIFY( grandChildWidget->isHidden() ); grandChildWidget->show(); QVERIFY( !grandChildWidget->isHidden() ); grandChildWidget->hide(); testWidget->hide(); testWidget->show(); QVERIFY( grandChildWidget->isHidden() ); QVERIFY( !testWidget->isHidden() ); QVERIFY( !childWidget->isHidden() ); grandChildWidget->show(); childWidget->hide(); testWidget->hide(); testWidget->show(); QVERIFY( !testWidget->isHidden() ); QVERIFY( childWidget->isHidden() ); QVERIFY( !grandChildWidget->isHidden() ); grandChildWidget->show(); QVERIFY( !grandChildWidget->isHidden() ); } void tst_QWidget::fonts() { // Tests setFont(), ownFont() and unsetFont() QWidget* cleanTestWidget = new QWidget( testWidget ); QFont originalFont = cleanTestWidget->font(); QVERIFY( !cleanTestWidget->testAttribute(Qt::WA_SetFont) ); cleanTestWidget->setFont(QFont()); QVERIFY( !cleanTestWidget->testAttribute(Qt::WA_SetFont) ); QFont newFont( "times", 18 ); cleanTestWidget->setFont( newFont ); newFont = newFont.resolve( testWidget->font() ); QVERIFY( cleanTestWidget->testAttribute(Qt::WA_SetFont) ); QVERIFY( cleanTestWidget->font() == newFont ); cleanTestWidget->setFont(QFont()); QVERIFY( !cleanTestWidget->testAttribute(Qt::WA_SetFont) ); QVERIFY( cleanTestWidget->font() == originalFont ); } void tst_QWidget::mapToGlobal() { #if !defined(QT3_SUPPORT) QSKIP("No Qt3 Support", SkipAll); #else QPoint vis = testWidget->mapToGlobal(QPoint(0,0)); testWidget->hide(); QCOMPARE(testWidget->mapToGlobal(QPoint(0,0)), vis); testWidget->show(); // test in a layout and witha move Q3HBox * qhb = new Q3HBox(testWidget); QWidget * qw = new QWidget(qhb); qw->move(6,12); QPoint wVis = qw->mapToGlobal(QPoint(0,0)); qw->hide(); QCOMPARE(qw->mapToGlobal(QPoint(0,0)), wVis); delete qhb; #endif // QT3_SUPPORT } void tst_QWidget::mapFromAndTo_data() { QTest::addColumn("windowHidden"); QTest::addColumn("subWindow1Hidden"); QTest::addColumn("subWindow2Hidden"); QTest::addColumn("subSubWindowHidden"); QTest::addColumn("windowMinimized"); QTest::addColumn("subWindow1Minimized"); QTest::newRow("window 1 sub1 1 sub2 1 subsub 1") << false << false << false << false << false << false; QTest::newRow("window 0 sub1 1 sub2 1 subsub 1") << true << false << false << false << false << false; QTest::newRow("window 1 sub1 0 sub2 1 subsub 1") << false << true << false << false << false << false; QTest::newRow("window 0 sub1 0 sub2 1 subsub 1") << true << true << false << false << false << false; QTest::newRow("window 1 sub1 1 sub2 0 subsub 1") << false << false << true << false << false << false; QTest::newRow("window 0 sub1 1 sub2 0 subsub 1") << true << false << true << false << false << false; QTest::newRow("window 1 sub1 0 sub2 0 subsub 1") << false << true << true << false << false << false; QTest::newRow("window 0 sub1 0 sub2 0 subsub 1") << true << true << true << false << false << false; QTest::newRow("window 1 sub1 1 sub2 1 subsub 0") << false << false << false << true << false << false; QTest::newRow("window 0 sub1 1 sub2 1 subsub 0") << true << false << false << true << false << false; QTest::newRow("window 1 sub1 0 sub2 1 subsub 0") << false << true << false << true << false << false; QTest::newRow("window 0 sub1 0 sub2 1 subsub 0") << true << true << false << true << false << false; QTest::newRow("window 1 sub1 1 sub2 0 subsub 0") << false << false << true << true << false << false; QTest::newRow("window 0 sub1 1 sub2 0 subsub 0") << true << false << true << true << false << false; QTest::newRow("window 1 sub1 0 sub2 0 subsub 0") << false << true << true << true << false << false; QTest::newRow("window 0 sub1 0 sub2 0 subsub 0") << true << true << true << true << false << false; QTest::newRow("window 1 sub1 1 sub2 1 subsub 1 windowMinimized") << false << false << false << false << true << false; QTest::newRow("window 0 sub1 1 sub2 1 subsub 1 windowMinimized") << true << false << false << false << true << false; QTest::newRow("window 1 sub1 0 sub2 1 subsub 1 windowMinimized") << false << true << false << false << true << false; QTest::newRow("window 0 sub1 0 sub2 1 subsub 1 windowMinimized") << true << true << false << false << true << false; QTest::newRow("window 1 sub1 1 sub2 0 subsub 1 windowMinimized") << false << false << true << false << true << false; QTest::newRow("window 0 sub1 1 sub2 0 subsub 1 windowMinimized") << true << false << true << false << true << false; QTest::newRow("window 1 sub1 0 sub2 0 subsub 1 windowMinimized") << false << true << true << false << true << false; QTest::newRow("window 0 sub1 0 sub2 0 subsub 1 windowMinimized") << true << true << true << false << true << false; QTest::newRow("window 1 sub1 1 sub2 1 subsub 0 windowMinimized") << false << false << false << true << true << false; QTest::newRow("window 0 sub1 1 sub2 1 subsub 0 windowMinimized") << true << false << false << true << true << false; QTest::newRow("window 1 sub1 0 sub2 1 subsub 0 windowMinimized") << false << true << false << true << true << false; QTest::newRow("window 0 sub1 0 sub2 1 subsub 0 windowMinimized") << true << true << false << true << true << false; QTest::newRow("window 1 sub1 1 sub2 0 subsub 0 windowMinimized") << false << false << true << true << true << false; QTest::newRow("window 0 sub1 1 sub2 0 subsub 0 windowMinimized") << true << false << true << true << true << false; QTest::newRow("window 1 sub1 0 sub2 0 subsub 0 windowMinimized") << false << true << true << true << true << false; QTest::newRow("window 0 sub1 0 sub2 0 subsub 0 windowMinimized") << true << true << true << true << true << false; QTest::newRow("window 1 sub1 1 sub2 1 subsub 1 subWindow1Minimized") << false << false << false << false << false << true; QTest::newRow("window 0 sub1 1 sub2 1 subsub 1 subWindow1Minimized") << true << false << false << false << false << true; QTest::newRow("window 1 sub1 0 sub2 1 subsub 1 subWindow1Minimized") << false << true << false << false << false << true; QTest::newRow("window 0 sub1 0 sub2 1 subsub 1 subWindow1Minimized") << true << true << false << false << false << true; QTest::newRow("window 1 sub1 1 sub2 0 subsub 1 subWindow1Minimized") << false << false << true << false << false << true; QTest::newRow("window 0 sub1 1 sub2 0 subsub 1 subWindow1Minimized") << true << false << true << false << false << true; QTest::newRow("window 1 sub1 0 sub2 0 subsub 1 subWindow1Minimized") << false << true << true << false << false << true; QTest::newRow("window 0 sub1 0 sub2 0 subsub 1 subWindow1Minimized") << true << true << true << false << false << true; QTest::newRow("window 1 sub1 1 sub2 1 subsub 0 subWindow1Minimized") << false << false << false << true << false << true; QTest::newRow("window 0 sub1 1 sub2 1 subsub 0 subWindow1Minimized") << true << false << false << true << false << true; QTest::newRow("window 1 sub1 0 sub2 1 subsub 0 subWindow1Minimized") << false << true << false << true << false << true; QTest::newRow("window 0 sub1 0 sub2 1 subsub 0 subWindow1Minimized") << true << true << false << true << false << true; QTest::newRow("window 1 sub1 1 sub2 0 subsub 0 subWindow1Minimized") << false << false << true << true << false << true; QTest::newRow("window 0 sub1 1 sub2 0 subsub 0 subWindow1Minimized") << true << false << true << true << false << true; QTest::newRow("window 1 sub1 0 sub2 0 subsub 0 subWindow1Minimized") << false << true << true << true << false << true; QTest::newRow("window 0 sub1 0 sub2 0 subsub 0 subWindow1Minimized") << true << true << true << true << false << true; } void tst_QWidget::mapFromAndTo() { QFETCH(bool, windowHidden); QFETCH(bool, subWindow1Hidden); QFETCH(bool, subWindow2Hidden); QFETCH(bool, subSubWindowHidden); QFETCH(bool, windowMinimized); QFETCH(bool, subWindow1Minimized); // create a toplevel and two overlapping siblings QWidget window; window.setWindowFlags(window.windowFlags() | Qt::X11BypassWindowManagerHint); QWidget *subWindow1 = new QWidget(&window); QWidget *subWindow2 = new QWidget(&window); QWidget *subSubWindow = new QWidget(subWindow1); // set their geometries window.setGeometry(100, 100, 100, 100); subWindow1->setGeometry(50, 50, 100, 100); subWindow2->setGeometry(75, 75, 100, 100); subSubWindow->setGeometry(10, 10, 10, 10); #ifndef Q_OS_WINCE //still no proper minimizing //update visibility if (windowMinimized) { if (!windowHidden) { window.showMinimized(); QVERIFY(window.isMinimized()); } } else { window.setVisible(!windowHidden); } if (subWindow1Minimized) { subWindow1->hide(); subWindow1->showMinimized(); QVERIFY(subWindow1->isMinimized()); } else { subWindow1->setVisible(!subWindow1Hidden); } #else Q_UNUSED(windowHidden); Q_UNUSED(subWindow1Hidden); Q_UNUSED(windowMinimized); Q_UNUSED(subWindow1Minimized); #endif subWindow2->setVisible(!subWindow2Hidden); subSubWindow->setVisible(!subSubWindowHidden); // window QCOMPARE(window.mapToGlobal(QPoint(0, 0)), QPoint(100, 100)); QCOMPARE(window.mapToGlobal(QPoint(10, 0)), QPoint(110, 100)); QCOMPARE(window.mapToGlobal(QPoint(0, 10)), QPoint(100, 110)); QCOMPARE(window.mapToGlobal(QPoint(-10, 0)), QPoint(90, 100)); QCOMPARE(window.mapToGlobal(QPoint(0, -10)), QPoint(100, 90)); QCOMPARE(window.mapToGlobal(QPoint(100, 100)), QPoint(200, 200)); QCOMPARE(window.mapToGlobal(QPoint(110, 100)), QPoint(210, 200)); QCOMPARE(window.mapToGlobal(QPoint(100, 110)), QPoint(200, 210)); QCOMPARE(window.mapFromGlobal(QPoint(100, 100)), QPoint(0, 0)); QCOMPARE(window.mapFromGlobal(QPoint(110, 100)), QPoint(10, 0)); QCOMPARE(window.mapFromGlobal(QPoint(100, 110)), QPoint(0, 10)); QCOMPARE(window.mapFromGlobal(QPoint(90, 100)), QPoint(-10, 0)); QCOMPARE(window.mapFromGlobal(QPoint(100, 90)), QPoint(0, -10)); QCOMPARE(window.mapFromGlobal(QPoint(200, 200)), QPoint(100, 100)); QCOMPARE(window.mapFromGlobal(QPoint(210, 200)), QPoint(110, 100)); QCOMPARE(window.mapFromGlobal(QPoint(200, 210)), QPoint(100, 110)); QCOMPARE(window.mapToParent(QPoint(0, 0)), QPoint(100, 100)); QCOMPARE(window.mapToParent(QPoint(10, 0)), QPoint(110, 100)); QCOMPARE(window.mapToParent(QPoint(0, 10)), QPoint(100, 110)); QCOMPARE(window.mapToParent(QPoint(-10, 0)), QPoint(90, 100)); QCOMPARE(window.mapToParent(QPoint(0, -10)), QPoint(100, 90)); QCOMPARE(window.mapToParent(QPoint(100, 100)), QPoint(200, 200)); QCOMPARE(window.mapToParent(QPoint(110, 100)), QPoint(210, 200)); QCOMPARE(window.mapToParent(QPoint(100, 110)), QPoint(200, 210)); QCOMPARE(window.mapFromParent(QPoint(100, 100)), QPoint(0, 0)); QCOMPARE(window.mapFromParent(QPoint(110, 100)), QPoint(10, 0)); QCOMPARE(window.mapFromParent(QPoint(100, 110)), QPoint(0, 10)); QCOMPARE(window.mapFromParent(QPoint(90, 100)), QPoint(-10, 0)); QCOMPARE(window.mapFromParent(QPoint(100, 90)), QPoint(0, -10)); QCOMPARE(window.mapFromParent(QPoint(200, 200)), QPoint(100, 100)); QCOMPARE(window.mapFromParent(QPoint(210, 200)), QPoint(110, 100)); QCOMPARE(window.mapFromParent(QPoint(200, 210)), QPoint(100, 110)); // first subwindow QCOMPARE(subWindow1->mapToGlobal(QPoint(0, 0)), QPoint(150, 150)); QCOMPARE(subWindow1->mapToGlobal(QPoint(10, 0)), QPoint(160, 150)); QCOMPARE(subWindow1->mapToGlobal(QPoint(0, 10)), QPoint(150, 160)); QCOMPARE(subWindow1->mapToGlobal(QPoint(-10, 0)), QPoint(140, 150)); QCOMPARE(subWindow1->mapToGlobal(QPoint(0, -10)), QPoint(150, 140)); QCOMPARE(subWindow1->mapToGlobal(QPoint(100, 100)), QPoint(250, 250)); QCOMPARE(subWindow1->mapToGlobal(QPoint(110, 100)), QPoint(260, 250)); QCOMPARE(subWindow1->mapToGlobal(QPoint(100, 110)), QPoint(250, 260)); QCOMPARE(subWindow1->mapFromGlobal(QPoint(150, 150)), QPoint(0, 0)); QCOMPARE(subWindow1->mapFromGlobal(QPoint(160, 150)), QPoint(10, 0)); QCOMPARE(subWindow1->mapFromGlobal(QPoint(150, 160)), QPoint(0, 10)); QCOMPARE(subWindow1->mapFromGlobal(QPoint(140, 150)), QPoint(-10, 0)); QCOMPARE(subWindow1->mapFromGlobal(QPoint(150, 140)), QPoint(0, -10)); QCOMPARE(subWindow1->mapFromGlobal(QPoint(250, 250)), QPoint(100, 100)); QCOMPARE(subWindow1->mapFromGlobal(QPoint(260, 250)), QPoint(110, 100)); QCOMPARE(subWindow1->mapFromGlobal(QPoint(250, 260)), QPoint(100, 110)); QCOMPARE(subWindow1->mapToParent(QPoint(0, 0)), QPoint(50, 50)); QCOMPARE(subWindow1->mapToParent(QPoint(10, 0)), QPoint(60, 50)); QCOMPARE(subWindow1->mapToParent(QPoint(0, 10)), QPoint(50, 60)); QCOMPARE(subWindow1->mapToParent(QPoint(-10, 0)), QPoint(40, 50)); QCOMPARE(subWindow1->mapToParent(QPoint(0, -10)), QPoint(50, 40)); QCOMPARE(subWindow1->mapToParent(QPoint(100, 100)), QPoint(150, 150)); QCOMPARE(subWindow1->mapToParent(QPoint(110, 100)), QPoint(160, 150)); QCOMPARE(subWindow1->mapToParent(QPoint(100, 110)), QPoint(150, 160)); QCOMPARE(subWindow1->mapFromParent(QPoint(50, 50)), QPoint(0, 0)); QCOMPARE(subWindow1->mapFromParent(QPoint(60, 50)), QPoint(10, 0)); QCOMPARE(subWindow1->mapFromParent(QPoint(50, 60)), QPoint(0, 10)); QCOMPARE(subWindow1->mapFromParent(QPoint(40, 50)), QPoint(-10, 0)); QCOMPARE(subWindow1->mapFromParent(QPoint(50, 40)), QPoint(0, -10)); QCOMPARE(subWindow1->mapFromParent(QPoint(150, 150)), QPoint(100, 100)); QCOMPARE(subWindow1->mapFromParent(QPoint(160, 150)), QPoint(110, 100)); QCOMPARE(subWindow1->mapFromParent(QPoint(150, 160)), QPoint(100, 110)); // subsubwindow QCOMPARE(subSubWindow->mapToGlobal(QPoint(0, 0)), QPoint(160, 160)); QCOMPARE(subSubWindow->mapToGlobal(QPoint(10, 0)), QPoint(170, 160)); QCOMPARE(subSubWindow->mapToGlobal(QPoint(0, 10)), QPoint(160, 170)); QCOMPARE(subSubWindow->mapToGlobal(QPoint(-10, 0)), QPoint(150, 160)); QCOMPARE(subSubWindow->mapToGlobal(QPoint(0, -10)), QPoint(160, 150)); QCOMPARE(subSubWindow->mapToGlobal(QPoint(100, 100)), QPoint(260, 260)); QCOMPARE(subSubWindow->mapToGlobal(QPoint(110, 100)), QPoint(270, 260)); QCOMPARE(subSubWindow->mapToGlobal(QPoint(100, 110)), QPoint(260, 270)); QCOMPARE(subSubWindow->mapFromGlobal(QPoint(160, 160)), QPoint(0, 0)); QCOMPARE(subSubWindow->mapFromGlobal(QPoint(170, 160)), QPoint(10, 0)); QCOMPARE(subSubWindow->mapFromGlobal(QPoint(160, 170)), QPoint(0, 10)); QCOMPARE(subSubWindow->mapFromGlobal(QPoint(150, 160)), QPoint(-10, 0)); QCOMPARE(subSubWindow->mapFromGlobal(QPoint(160, 150)), QPoint(0, -10)); QCOMPARE(subSubWindow->mapFromGlobal(QPoint(260, 260)), QPoint(100, 100)); QCOMPARE(subSubWindow->mapFromGlobal(QPoint(270, 260)), QPoint(110, 100)); QCOMPARE(subSubWindow->mapFromGlobal(QPoint(260, 270)), QPoint(100, 110)); QCOMPARE(subSubWindow->mapToParent(QPoint(0, 0)), QPoint(10, 10)); QCOMPARE(subSubWindow->mapToParent(QPoint(10, 0)), QPoint(20, 10)); QCOMPARE(subSubWindow->mapToParent(QPoint(0, 10)), QPoint(10, 20)); QCOMPARE(subSubWindow->mapToParent(QPoint(-10, 0)), QPoint(0, 10)); QCOMPARE(subSubWindow->mapToParent(QPoint(0, -10)), QPoint(10, 0)); QCOMPARE(subSubWindow->mapToParent(QPoint(100, 100)), QPoint(110, 110)); QCOMPARE(subSubWindow->mapToParent(QPoint(110, 100)), QPoint(120, 110)); QCOMPARE(subSubWindow->mapToParent(QPoint(100, 110)), QPoint(110, 120)); QCOMPARE(subSubWindow->mapFromParent(QPoint(10, 10)), QPoint(0, 0)); QCOMPARE(subSubWindow->mapFromParent(QPoint(20, 10)), QPoint(10, 0)); QCOMPARE(subSubWindow->mapFromParent(QPoint(10, 20)), QPoint(0, 10)); QCOMPARE(subSubWindow->mapFromParent(QPoint(0, 10)), QPoint(-10, 0)); QCOMPARE(subSubWindow->mapFromParent(QPoint(10, 0)), QPoint(0, -10)); QCOMPARE(subSubWindow->mapFromParent(QPoint(110, 110)), QPoint(100, 100)); QCOMPARE(subSubWindow->mapFromParent(QPoint(120, 110)), QPoint(110, 100)); QCOMPARE(subSubWindow->mapFromParent(QPoint(110, 120)), QPoint(100, 110)); } void tst_QWidget::focusChainOnReparent() { QWidget window; QWidget *child1 = new QWidget(&window); QWidget *child2 = new QWidget(&window); QWidget *child3 = new QWidget(&window); QWidget *child21 = new QWidget(child2); QWidget *child22 = new QWidget(child2); QWidget *child4 = new QWidget(&window); QWidget *expectedOriginalChain[8] = {&window, child1, child2, child3, child21, child22, child4, &window}; QWidget *w = &window; for (int i = 0; i <8; ++i) { QCOMPARE(w, expectedOriginalChain[i]); w = w->nextInFocusChain(); } for (int i = 7; i >= 0; --i) { w = w->previousInFocusChain(); QCOMPARE(w, expectedOriginalChain[i]); } QWidget window2; child2->setParent(&window2); QWidget *expectedNewChain[5] = {&window2, child2, child21, child22, &window2}; w = &window2; for (int i = 0; i <5; ++i) { QCOMPARE(w, expectedNewChain[i]); w = w->nextInFocusChain(); } for (int i = 4; i >= 0; --i) { w = w->previousInFocusChain(); QCOMPARE(w, expectedNewChain[i]); } QWidget *expectedOldChain[5] = {&window, child1, child3, child4, &window}; w = &window; for (int i = 0; i <5; ++i) { QCOMPARE(w, expectedOldChain[i]); w = w->nextInFocusChain(); } for (int i = 4; i >= 0; --i) { w = w->previousInFocusChain(); QCOMPARE(w, expectedOldChain[i]); } } void tst_QWidget::focusChainOnHide() { testWidget->hide(); // We do not want to get disturbed by other widgets // focus should move to the next widget in the focus chain when we hide it. QWidget *parent = new QWidget(); parent->setObjectName(QLatin1String("Parent")); parent->setFocusPolicy(Qt::StrongFocus); QWidget *child = new QWidget(parent); child->setObjectName(QLatin1String("child")); child->setFocusPolicy(Qt::StrongFocus); QWidget::setTabOrder(child, parent); parent->show(); qApp->setActiveWindow(parent->window()); child->activateWindow(); child->setFocus(); qApp->processEvents(); WAIT_FOR_CONDITION(child->hasFocus(), true); QCOMPARE(child->hasFocus(), true); child->hide(); qApp->processEvents(); WAIT_FOR_CONDITION(parent->hasFocus(), true); QCOMPARE(parent->hasFocus(), true); QCOMPARE(parent, qApp->focusWidget()); delete parent; testWidget->show(); //don't disturb later tests } void tst_QWidget::checkFocus() { #if !defined(QT3_SUPPORT) QSKIP("No Qt3 Support", SkipAll); #else // This is a very specific test for a specific bug, the bug was // that when setEnabled(FALSE) then setEnabled(TRUE) was called on // the parent of a child widget which had focus while hidden, then // when the widget was shown, the focus would be in the wrong place. Q3HBox widget; QLineEdit *focusWidget = new QLineEdit( &widget ); new QLineEdit( &widget ); new QPushButton( &widget ); focusWidget->setFocus(); widget.setEnabled( FALSE ); widget.setEnabled( TRUE ); widget.show(); #ifdef Q_WS_X11 qt_x11_wait_for_window_manager(&widget); #endif QTest::qWait( 100 ); widget.activateWindow(); // next call is necessary since the window manager may not give the focus to the widget when // it is shown, which causes the QVERIFY to fail QApplication::setActiveWindow(&widget); QVERIFY( qApp->focusWidget() == focusWidget ); #endif // QT3_SUPPORT } class Container : public QWidget { public: QVBoxLayout* box; Container() { box = new QVBoxLayout(this); //(new QVBoxLayout(this))->setAutoAdd(true); } void tab() { focusNextPrevChild(TRUE); } void backTab() { focusNextPrevChild(FALSE); } }; class Composite : public QFrame { public: Composite(QWidget* parent = 0, const char* name = 0) : QFrame(parent) { setObjectName(name); //QHBoxLayout* hbox = new QHBoxLayout(this, 2, 0); //hbox->setAutoAdd(true); QHBoxLayout* hbox = new QHBoxLayout(this); lineEdit = new QLineEdit(this); hbox->addWidget(lineEdit); button = new QPushButton(this); hbox->addWidget(button); button->setFocusPolicy( Qt::NoFocus ); setFocusProxy( lineEdit ); setFocusPolicy( Qt::StrongFocus ); setTabOrder(lineEdit, button); } private: QLineEdit* lineEdit; QPushButton* button; }; #define NUM_WIDGETS 4 void tst_QWidget::setTabOrder() { QTest::qWait(100); Container container; Composite* comp[NUM_WIDGETS]; QLineEdit *firstEdit = new QLineEdit(&container); container.box->addWidget(firstEdit); int i = 0; for(i = 0; i < NUM_WIDGETS; i++) { comp[i] = new Composite(&container); container.box->addWidget(comp[i]); } QLineEdit *lastEdit = new QLineEdit(&container); container.box->addWidget(lastEdit); container.setTabOrder(lastEdit, comp[NUM_WIDGETS-1]); for(i = NUM_WIDGETS-1; i > 0; i--) { container.setTabOrder(comp[i], comp[i-1]); } container.setTabOrder(comp[0], firstEdit); int current = NUM_WIDGETS-1; lastEdit->setFocus(); container.show(); container.activateWindow(); #ifdef Q_WS_X11 qt_x11_wait_for_window_manager(&container); QTest::qWait(50); #endif qApp->setActiveWindow(&container); QTest::qWait(100); QVERIFY(lastEdit->hasFocus()); container.tab(); do { QVERIFY(comp[current]->focusProxy()->hasFocus()); container.tab(); current--; } while (current >= 0); QVERIFY(firstEdit->hasFocus()); } void tst_QWidget::activation() { #if !defined(Q_WS_WIN) QSKIP("This test is Windows-only.", SkipAll); #endif Q_CHECK_PAINTEVENTS #if defined(Q_OS_WINCE) int waitTime = 1000; #else int waitTime = 100; #endif #ifdef Q_OS_WINCE qApp->processEvents(); #endif QWidget widget1; widget1.setWindowTitle("Widget1"); QWidget widget2; widget2.setWindowTitle("Widget2"); widget1.show(); widget2.show(); QTest::qWait(waitTime); QVERIFY(qApp->activeWindow() == &widget2); widget2.showMinimized(); QTest::qWait(waitTime); QVERIFY(qApp->activeWindow() == &widget1); widget2.showMaximized(); QTest::qWait(waitTime); QVERIFY(qApp->activeWindow() == &widget2); widget2.showMinimized(); QTest::qWait(waitTime); QVERIFY(qApp->activeWindow() == &widget1); widget2.showNormal(); QTest::qWait(waitTime); #if defined(Q_WS_WIN) && !defined(Q_OS_WINCE) if (QSysInfo::WindowsVersion >= QSysInfo::WV_VISTA) QEXPECT_FAIL("", "MS introduced new behavior after XP", Continue); #endif QTest::qWait(waitTime); QVERIFY(qApp->activeWindow() == &widget2); widget2.hide(); QTest::qWait(waitTime); QVERIFY(qApp->activeWindow() == &widget1); } void tst_QWidget::windowState() { #ifdef Q_WS_X11 QSKIP("Many window managers do not support window state properly, which causes this " "test to fail.", SkipAll); #else #ifdef Q_OS_WINCE_WM QPoint pos(500, 500); QSize size(200, 200); if (qt_wince_is_smartphone()) { //small screen pos = QPoint(10,10); size = QSize(100,100); } #else const QPoint pos(500, 500); const QSize size(200, 200); #endif QWidget widget1; widget1.move(pos); widget1.resize(size); QCOMPARE(widget1.pos(), pos); QCOMPARE(widget1.size(), size); QTest::qWait(100); widget1.setWindowTitle("Widget1"); QCOMPARE(widget1.pos(), pos); QCOMPARE(widget1.size(), size); #define VERIFY_STATE(s) QCOMPARE(int(widget1.windowState() & stateMask), int(s)) const int stateMask = Qt::WindowMaximized|Qt::WindowMinimized|Qt::WindowFullScreen; widget1.setWindowState(Qt::WindowMaximized); QTest::qWait(100); VERIFY_STATE(Qt::WindowMaximized); widget1.show(); QTest::qWait(100); VERIFY_STATE(Qt::WindowMaximized); widget1.setWindowState(widget1.windowState() ^ Qt::WindowMaximized); QTest::qWait(100); QVERIFY(!(widget1.windowState() & Qt::WindowMaximized)); QCOMPARE(widget1.pos(), pos); widget1.setWindowState(Qt::WindowMinimized); QTest::qWait(100); VERIFY_STATE(Qt::WindowMinimized); widget1.setWindowState(widget1.windowState() | Qt::WindowMaximized); QTest::qWait(100); VERIFY_STATE((Qt::WindowMinimized|Qt::WindowMaximized)); widget1.setWindowState(widget1.windowState() ^ Qt::WindowMinimized); QTest::qWait(100); VERIFY_STATE(Qt::WindowMaximized); widget1.setWindowState(widget1.windowState() ^ Qt::WindowMaximized); QTest::qWait(100); QVERIFY(!(widget1.windowState() & (Qt::WindowMinimized|Qt::WindowMaximized))); QCOMPARE(widget1.pos(), pos); widget1.setWindowState(Qt::WindowFullScreen); QTest::qWait(100); VERIFY_STATE(Qt::WindowFullScreen); widget1.setWindowState(widget1.windowState() ^ Qt::WindowMinimized); QTest::qWait(100); VERIFY_STATE((Qt::WindowFullScreen|Qt::WindowMinimized)); widget1.setWindowState(widget1.windowState() ^ Qt::WindowMinimized); QTest::qWait(100); VERIFY_STATE(Qt::WindowFullScreen); widget1.setWindowState(widget1.windowState() ^ Qt::WindowMaximized); QTest::qWait(100); VERIFY_STATE((Qt::WindowFullScreen|Qt::WindowMaximized)); widget1.setWindowState(widget1.windowState() ^ Qt::WindowMinimized); QTest::qWait(100); VERIFY_STATE((Qt::WindowFullScreen|Qt::WindowMaximized|Qt::WindowMinimized)); widget1.setWindowState(widget1.windowState() ^ Qt::WindowMinimized); QTest::qWait(100); VERIFY_STATE((Qt::WindowFullScreen|Qt::WindowMaximized)); widget1.setWindowState(widget1.windowState() ^ Qt::WindowFullScreen); QTest::qWait(100); VERIFY_STATE(Qt::WindowMaximized); widget1.setWindowState(widget1.windowState() ^ Qt::WindowMaximized); QTest::qWait(100); QVERIFY(!(widget1.windowState() & stateMask)); QCOMPARE(widget1.pos(), pos); QCOMPARE(widget1.size(), size); #endif } void tst_QWidget::showMaximized() { QWidget plain; QHBoxLayout *layout; layout = new QHBoxLayout; QWidget layouted; QLineEdit le; QLineEdit le2; QLineEdit le3; layout->addWidget(&le); layout->addWidget(&le2); layout->addWidget(&le3); layouted.setLayout(layout); plain.showMaximized(); QVERIFY(plain.windowState() & Qt::WindowMaximized); plain.showNormal(); QVERIFY(!(plain.windowState() & Qt::WindowMaximized)); layouted.showMaximized(); QVERIFY(layouted.windowState() & Qt::WindowMaximized); layouted.showNormal(); QVERIFY(!(layouted.windowState() & Qt::WindowMaximized)); #if !defined(Q_WS_QWS) && !defined(Q_OS_WINCE) //embedded may choose a different size to fit on the screen. QCOMPARE(layouted.size(), layouted.sizeHint()); #endif layouted.showMaximized(); QVERIFY(layouted.isMaximized()); QVERIFY(layouted.isVisible()); layouted.hide(); QVERIFY(layouted.isMaximized()); QVERIFY(!layouted.isVisible()); layouted.showMaximized(); QVERIFY(layouted.isMaximized()); QVERIFY(layouted.isVisible()); layouted.showMinimized(); QVERIFY(layouted.isMinimized()); QVERIFY(layouted.isMaximized()); layouted.showMaximized(); QVERIFY(!layouted.isMinimized()); QVERIFY(layouted.isMaximized()); QVERIFY(layouted.isVisible()); layouted.showMinimized(); QVERIFY(layouted.isMinimized()); QVERIFY(layouted.isMaximized()); layouted.showMaximized(); QVERIFY(!layouted.isMinimized()); QVERIFY(layouted.isMaximized()); QVERIFY(layouted.isVisible()); { QWidget frame; QWidget widget(&frame); widget.showMaximized(); QVERIFY(widget.isMaximized()); } #ifdef QT3_SUPPORT #if !defined(Q_WS_QWS) //embedded respects max/min sizes by design -- maybe wrong design, but that's the way it is now. { Q3HBox box; QWidget widget(&box); widget.setMinimumSize(500, 500); box.showMaximized(); QVERIFY(box.isMaximized()); } { Q3HBox box; QWidget widget(&box); widget.setMaximumSize(500, 500); box.showMaximized(); QVERIFY(box.isMaximized()); } #endif #endif // QT3_SUPPORT } void tst_QWidget::showFullScreen() { QWidget plain; QHBoxLayout *layout; QWidget layouted; QLineEdit le; QLineEdit le2; QLineEdit le3; layout = new QHBoxLayout; layout->addWidget(&le); layout->addWidget(&le2); layout->addWidget(&le3); layouted.setLayout(layout); plain.showFullScreen(); QVERIFY(plain.windowState() & Qt::WindowFullScreen); plain.showNormal(); QVERIFY(!(plain.windowState() & Qt::WindowFullScreen)); layouted.showFullScreen(); QVERIFY(layouted.windowState() & Qt::WindowFullScreen); layouted.showNormal(); QVERIFY(!(layouted.windowState() & Qt::WindowFullScreen)); #if !defined(Q_WS_QWS) && !defined(Q_OS_WINCE) //embedded may choose a different size to fit on the screen. QCOMPARE(layouted.size(), layouted.sizeHint()); #endif layouted.showFullScreen(); QVERIFY(layouted.isFullScreen()); QVERIFY(layouted.isVisible()); layouted.hide(); QVERIFY(layouted.isFullScreen()); QVERIFY(!layouted.isVisible()); layouted.showFullScreen(); QVERIFY(layouted.isFullScreen()); QVERIFY(layouted.isVisible()); layouted.showMinimized(); QVERIFY(layouted.isMinimized()); QVERIFY(layouted.isFullScreen()); layouted.showFullScreen(); QVERIFY(!layouted.isMinimized()); QVERIFY(layouted.isFullScreen()); QVERIFY(layouted.isVisible()); layouted.showMinimized(); QVERIFY(layouted.isMinimized()); QVERIFY(layouted.isFullScreen()); layouted.showFullScreen(); QVERIFY(!layouted.isMinimized()); QVERIFY(layouted.isFullScreen()); QVERIFY(layouted.isVisible()); { QWidget frame; QWidget widget(&frame); widget.showFullScreen(); QVERIFY(widget.isFullScreen()); } #ifdef QT3_SUPPORT #if !defined(Q_WS_QWS) //embedded respects max/min sizes by design -- maybe wrong design, but that's the way it is now. { Q3HBox box; QWidget widget(&box); widget.setMinimumSize(500, 500); box.showFullScreen(); QVERIFY(box.isFullScreen()); } { Q3HBox box; QWidget widget(&box); widget.setMaximumSize(500, 500); box.showFullScreen(); QVERIFY(box.isFullScreen()); } #endif #endif // QT3_SUPPORT } class ResizeWidget : public QWidget { public: ResizeWidget(QWidget *p = 0) : QWidget(p) { m_resizeEventCount = 0; } protected: void resizeEvent(QResizeEvent *e){ QCOMPARE(size(), e->size()); ++m_resizeEventCount; } public: int m_resizeEventCount; }; void tst_QWidget::resizeEvent() { { QWidget wParent; ResizeWidget wChild(&wParent); wParent.show(); QCOMPARE (wChild.m_resizeEventCount, 1); // initial resize event before paint wParent.hide(); wChild.resize(QSize(640,480)); QCOMPARE (wChild.m_resizeEventCount, 1); wParent.show(); QCOMPARE (wChild.m_resizeEventCount, 2); } { ResizeWidget wTopLevel; wTopLevel.show(); QCOMPARE (wTopLevel.m_resizeEventCount, 1); // initial resize event before paint for toplevels wTopLevel.hide(); wTopLevel.resize(QSize(640,480)); QCOMPARE (wTopLevel.m_resizeEventCount, 1); wTopLevel.show(); QCOMPARE (wTopLevel.m_resizeEventCount, 2); } } void tst_QWidget::showMinimized() { QWidget plain; plain.move(100, 100); plain.resize(200, 200); QPoint pos = plain.pos(); plain.showMinimized(); QVERIFY(plain.isMinimized()); QVERIFY(plain.isVisible()); QCOMPARE(plain.pos(), pos); plain.showNormal(); QVERIFY(!plain.isMinimized()); QVERIFY(plain.isVisible()); QCOMPARE(plain.pos(), pos); plain.showMinimized(); QVERIFY(plain.isMinimized()); QVERIFY(plain.isVisible()); QCOMPARE(plain.pos(), pos); plain.hide(); QVERIFY(plain.isMinimized()); QVERIFY(!plain.isVisible()); plain.showMinimized(); QVERIFY(plain.isMinimized()); QVERIFY(plain.isVisible()); plain.setGeometry(200, 200, 300, 300); plain.showNormal(); QCOMPARE(plain.geometry(), QRect(200, 200, 300, 300)); { QWidget frame; QWidget widget(&frame); widget.showMinimized(); QVERIFY(widget.isMinimized()); } } void tst_QWidget::showMinimizedKeepsFocus() { //here we test that minimizing a widget and restoring it doesn't change the focus inside of it { QWidget window; QWidget child1(&window), child2(&window); child1.setFocusPolicy(Qt::StrongFocus); child2.setFocusPolicy(Qt::StrongFocus); window.show(); qApp->setActiveWindow(&window); child2.setFocus(); QTest::qWait(500); QCOMPARE(window.focusWidget(), &child2); QCOMPARE(qApp->focusWidget(), &child2); window.showMinimized(); QTest::qWait(100); QVERIFY(window.isMinimized()); QCOMPARE(window.focusWidget(), &child2); window.showNormal(); QTest::qWait(100); QCOMPARE(window.focusWidget(), &child2); } //testing deletion of the focusWidget { QWidget window; QWidget *child = new QWidget(&window); child->setFocusPolicy(Qt::StrongFocus); window.show(); qApp->setActiveWindow(&window); child->setFocus(); QTest::qWait(500); QCOMPARE(window.focusWidget(), child); QCOMPARE(qApp->focusWidget(), child); delete child; QCOMPARE(window.focusWidget(), static_cast(0)); QCOMPARE(qApp->focusWidget(), static_cast(0)); } //testing reparenting the focus widget { QWidget window; QWidget *child = new QWidget(&window); child->setFocusPolicy(Qt::StrongFocus); window.show(); qApp->setActiveWindow(&window); child->setFocus(); QTest::qWait(500); QCOMPARE(window.focusWidget(), child); QCOMPARE(qApp->focusWidget(), child); child->setParent(0); QCOMPARE(window.focusWidget(), static_cast(0)); QCOMPARE(qApp->focusWidget(), static_cast(0)); } //testing setEnabled(false) { QWidget window; QWidget *child = new QWidget(&window); child->setFocusPolicy(Qt::StrongFocus); window.show(); qApp->setActiveWindow(&window); child->setFocus(); QTest::qWait(1000); QCOMPARE(window.focusWidget(), child); QCOMPARE(qApp->focusWidget(), child); child->setEnabled(false); QCOMPARE(window.focusWidget(), static_cast(0)); QCOMPARE(qApp->focusWidget(), static_cast(0)); } //testing clearFocus { QWidget window; QWidget *firstchild = new QWidget(&window); firstchild->setFocusPolicy(Qt::StrongFocus); QWidget *child = new QWidget(&window); child->setFocusPolicy(Qt::StrongFocus); window.show(); qApp->setActiveWindow(&window); child->setFocus(); QTest::qWait(1000); QCOMPARE(window.focusWidget(), child); QCOMPARE(qApp->focusWidget(), child); child->clearFocus(); QCOMPARE(window.focusWidget(), static_cast(0)); QCOMPARE(qApp->focusWidget(), static_cast(0)); window.showMinimized(); QTest::qWait(100); QVERIFY(window.isMinimized()); #ifdef Q_WS_QWS QEXPECT_FAIL("", "QWS does not implement showMinimized()", Continue); #endif QCOMPARE(window.focusWidget(), static_cast(0)); #ifdef Q_WS_QWS QEXPECT_FAIL("", "QWS does not implement showMinimized()", Continue); #endif QCOMPARE(qApp->focusWidget(), static_cast(0)); window.showNormal(); #ifdef Q_WS_X11 qt_x11_wait_for_window_manager(&window); #endif QTest::qWait(300); qApp->setActiveWindow(&window); #ifdef Q_WS_MAC if (!macHasAccessToWindowsServer()) QEXPECT_FAIL("", "When not having WindowServer access, we lose focus.", Continue); #endif QCOMPARE(window.focusWidget(), firstchild); #ifdef Q_WS_MAC if (!macHasAccessToWindowsServer()) QEXPECT_FAIL("", "When not having WindowServer access, we lose focus.", Continue); #endif QCOMPARE(qApp->focusWidget(), firstchild); } } void tst_QWidget::reparent() { QWidget parent; parent.setWindowTitle("Toplevel"); parent.setGeometry(300, 300, 200, 150); QWidget child(0); child.setObjectName("child"); child.setGeometry(10, 10, 180, 130); QPalette pal1; pal1.setColor(child.backgroundRole(), Qt::white); child.setPalette(pal1); QWidget childTLW(&child, Qt::Window); childTLW.setObjectName("childTLW"); childTLW.setGeometry(100, 100, 50, 50); QPalette pal2; pal2.setColor(childTLW.backgroundRole(), Qt::yellow); childTLW.setPalette(pal2); parent.show(); childTLW.show(); #ifdef Q_WS_X11 qt_x11_wait_for_window_manager(&parent); qt_x11_wait_for_window_manager(&childTLW); #endif #ifdef Q_OS_WINCE parent.move(50, 50); #else parent.move(300, 300); #endif QPoint childPos = parent.mapToGlobal(child.pos()); QPoint tlwPos = childTLW.pos(); child.setParent(0, child.windowFlags() & ~Qt::WindowType_Mask); child.setGeometry(childPos.x(), childPos.y(), child.width(), child.height()); child.show(); #ifdef Q_WS_X11 qt_x11_wait_for_window_manager(&child); // On X11, the window manager will apply NorthWestGravity rules to 'child', which // means the top-left corner of the window frame will be placed at 'childPos', // causing this test to fail #else QCOMPARE(child.geometry().topLeft(), childPos); #endif QCOMPARE(childTLW.pos(), tlwPos); #ifdef Q_WS_WIN QWidget childTLWChild(&childTLW); childTLWChild.setObjectName("childTLWChild"); QWidget grandChild(&child); grandChild.setObjectName("grandChild"); grandChild.setGeometry(10, 10, 160, 110); QPalette pal3; pal3.setColor(grandChild.backgroundRole(), Qt::red); grandChild.setPalette(pal3); //grandChild.setPaletteBackgroundColor(Qt::red); QWidget grandChildTLW(&grandChild, Qt::Window); grandChildTLW.setObjectName("grandChildTLW"); grandChildTLW.setGeometry(200, 200, 50, 50); QPalette pal4; pal4.setColor(grandChildTLW.backgroundRole(), Qt::yellow); grandChildTLW.setPalette(pal4); //grandChildTLW.setPaletteBackgroundColor(Qt::yellow); QWidget grandChildTLWChild(&grandChildTLW); grandChildTLWChild.setObjectName("grandChildTLWChild"); QVERIFY(IsWindow(childTLW.winId())); QVERIFY(IsWindow(childTLWChild.winId())); QVERIFY(IsWindow(grandChildTLW.winId())); QVERIFY(IsWindow(grandChildTLWChild.winId())); parent.show(); QVERIFY(IsWindow(childTLW.winId())); QVERIFY(IsWindow(childTLWChild.winId())); QVERIFY(IsWindow(grandChildTLW.winId())); QVERIFY(IsWindow(grandChildTLWChild.winId())); child.setParent(&parent); child.move(10,10); child.show(); // this appears to stabelize results qApp->processEvents(); QVERIFY(IsWindow(childTLW.winId())); QVERIFY(IsWindow(childTLWChild.winId())); QVERIFY(IsWindow(grandChildTLW.winId())); QVERIFY(IsWindow(grandChildTLWChild.winId())); #else QSKIP("This test makes only sense on Windows", SkipAll); #endif } void tst_QWidget::icon() { #if defined(Q_WS_QWS) QSKIP("Qt/Embedded does it differently", SkipAll); #else QPixmap p(20,20); p.fill(Qt::red); testWidget->setWindowIcon(p); QVERIFY(!testWidget->windowIcon().isNull()); testWidget->show(); QVERIFY(!testWidget->windowIcon().isNull()); testWidget->showFullScreen(); QVERIFY(!testWidget->windowIcon().isNull()); testWidget->showNormal(); QVERIFY(!testWidget->windowIcon().isNull()); #endif } void tst_QWidget::hideWhenFocusWidgetIsChild() { testWidget->activateWindow(); QWidget *parentWidget = new QWidget(testWidget); parentWidget->setObjectName("parentWidget"); parentWidget->setGeometry(0, 0, 100, 100); QLineEdit *edit = new QLineEdit(parentWidget); edit->setObjectName("edit1"); QLineEdit *edit3 = new QLineEdit(parentWidget); edit3->setObjectName("edit3"); edit3->move(0,50); parentWidget->show(); QLineEdit *edit2 = new QLineEdit(testWidget); edit2->setObjectName("edit2"); edit2->show(); edit2->move(110, 100); edit->setFocus(); qApp->processEvents(); QString actualFocusWidget, expectedFocusWidget; #ifdef Q_WS_X11 if (!qApp->focusWidget()) QSKIP("Your window manager is too broken for this test", SkipAll); #endif QVERIFY(qApp->focusWidget()); actualFocusWidget.sprintf("%p %s %s", qApp->focusWidget(), qApp->focusWidget()->objectName().toLatin1().constData(), qApp->focusWidget()->metaObject()->className()); expectedFocusWidget.sprintf("%p %s %s", edit, edit->objectName().toLatin1().constData(), edit->metaObject()->className()); QCOMPARE(actualFocusWidget, expectedFocusWidget); parentWidget->hide(); qApp->processEvents(); actualFocusWidget.sprintf("%p %s %s", qApp->focusWidget(), qApp->focusWidget()->objectName().toLatin1().constData(), qApp->focusWidget()->metaObject()->className()); expectedFocusWidget.sprintf("%p %s %s", edit2, edit2->objectName().toLatin1().constData(), edit2->metaObject()->className()); QCOMPARE(actualFocusWidget, expectedFocusWidget); } void tst_QWidget::normalGeometry() { #ifdef Q_OS_IRIX QSKIP("4DWM issues on IRIX makes this test fail", SkipAll); #endif QWidget parent; parent.setWindowTitle("NormalGeometry parent"); QWidget *child = new QWidget(&parent); QCOMPARE(parent.normalGeometry(), parent.geometry()); QCOMPARE(child->normalGeometry(), QRect()); parent.setGeometry(100, 100, 200, 200); parent.show(); QTestEventLoop::instance().enterLoop(1); QRect geom = parent.geometry(); // ### the window manager places the top-left corner at // ### 100,100... making geom something like 102,124 (offset by // ### the frame/frame)... this indicates a rather large different // ### between how X11 and Windows works // QCOMPARE(geom, QRect(100, 100, 200, 200)); QCOMPARE(parent.normalGeometry(), geom); parent.setWindowState(parent.windowState() ^ Qt::WindowMaximized); QTestEventLoop::instance().enterLoop(1); QVERIFY(parent.windowState() & Qt::WindowMaximized); QVERIFY(parent.geometry() != geom); QCOMPARE(parent.normalGeometry(), geom); parent.setWindowState(parent.windowState() ^ Qt::WindowMaximized); QTestEventLoop::instance().enterLoop(1); QVERIFY(!(parent.windowState() & Qt::WindowMaximized)); QCOMPARE(parent.geometry(), geom); QCOMPARE(parent.normalGeometry(), geom); parent.showMaximized(); QTestEventLoop::instance().enterLoop(1); QVERIFY(parent.windowState() & Qt::WindowMaximized); QVERIFY(parent.geometry() != geom); QCOMPARE(parent.normalGeometry(), geom); parent.showNormal(); QTestEventLoop::instance().enterLoop(1); QVERIFY(!(parent.windowState() & Qt::WindowMaximized)); QCOMPARE(parent.geometry(), geom); QCOMPARE(parent.normalGeometry(), geom); parent.setWindowState(parent.windowState() ^ Qt::WindowMinimized); QTestEventLoop::instance().enterLoop(1); parent.setWindowState(parent.windowState() ^ Qt::WindowMaximized); QTestEventLoop::instance().enterLoop(1); QVERIFY(parent.windowState() & (Qt::WindowMinimized|Qt::WindowMaximized)); // ### when minimized and maximized at the same time, the geometry // ### does *NOT* have to be the normal geometry, it could be the // ### maximized geometry. // QCOMPARE(parent.geometry(), geom); QCOMPARE(parent.normalGeometry(), geom); parent.setWindowState(parent.windowState() ^ Qt::WindowMinimized); QTestEventLoop::instance().enterLoop(1); QVERIFY(!(parent.windowState() & Qt::WindowMinimized)); QVERIFY(parent.windowState() & Qt::WindowMaximized); QVERIFY(parent.geometry() != geom); QCOMPARE(parent.normalGeometry(), geom); parent.setWindowState(parent.windowState() ^ Qt::WindowMaximized); QTestEventLoop::instance().enterLoop(1); QVERIFY(!(parent.windowState() & Qt::WindowMaximized)); QCOMPARE(parent.geometry(), geom); QCOMPARE(parent.normalGeometry(), geom); parent.setWindowState(parent.windowState() ^ Qt::WindowFullScreen); QTestEventLoop::instance().enterLoop(1); QVERIFY(parent.windowState() & Qt::WindowFullScreen); QVERIFY(parent.geometry() != geom); QCOMPARE(parent.normalGeometry(), geom); parent.setWindowState(parent.windowState() ^ Qt::WindowFullScreen); QTestEventLoop::instance().enterLoop(1); QVERIFY(!(parent.windowState() & Qt::WindowFullScreen)); QCOMPARE(parent.geometry(), geom); QCOMPARE(parent.normalGeometry(), geom); parent.showFullScreen(); QTestEventLoop::instance().enterLoop(1); QVERIFY(parent.windowState() & Qt::WindowFullScreen); QVERIFY(parent.geometry() != geom); QCOMPARE(parent.normalGeometry(), geom); parent.showNormal(); QTestEventLoop::instance().enterLoop(1); QVERIFY(!(parent.windowState() & Qt::WindowFullScreen)); QCOMPARE(parent.geometry(), geom); QCOMPARE(parent.normalGeometry(), geom); parent.showNormal(); parent.setWindowState(Qt:: WindowFullScreen | Qt::WindowMaximized); parent.setWindowState(Qt::WindowMinimized | Qt:: WindowFullScreen | Qt::WindowMaximized); parent.setWindowState(Qt:: WindowFullScreen | Qt::WindowMaximized); QTestEventLoop::instance().enterLoop(1); QCOMPARE(parent.normalGeometry(), geom); } void tst_QWidget::setGeometry() { QWidget tlw; QWidget child(&tlw); QRect tr(100,100,200,200); QRect cr(50,50,50,50); tlw.setGeometry(tr); child.setGeometry(cr); tlw.show(); QTest::qWait(50); QCOMPARE(tlw.geometry().size(), tr.size()); QCOMPARE(child.geometry(), cr); tlw.setParent(0, Qt::Window|Qt::FramelessWindowHint); tr = QRect(0,0,100,100); tr.moveTopLeft(QApplication::desktop()->availableGeometry().topLeft()); tlw.setGeometry(tr); QCOMPARE(tlw.geometry(), tr); tlw.show(); QTest::qWait(50); if (tlw.frameGeometry() != tlw.geometry()) QSKIP("Your window manager is too broken for this test", SkipAll); QCOMPARE(tlw.geometry(), tr); } void tst_QWidget::windowOpacity() { #ifdef Q_OS_WINCE QSKIP( "Windows CE does not support windowOpacity", SkipAll); #endif QWidget widget; QWidget child(&widget); // Initial value should be 1.0 QCOMPARE(widget.windowOpacity(), 1.0); // children should always return 1.0 QCOMPARE(child.windowOpacity(), 1.0); widget.setWindowOpacity(0.0); QCOMPARE(widget.windowOpacity(), 0.0); child.setWindowOpacity(0.0); QCOMPARE(child.windowOpacity(), 1.0); widget.setWindowOpacity(1.0); QCOMPARE(widget.windowOpacity(), 1.0); child.setWindowOpacity(1.0); QCOMPARE(child.windowOpacity(), 1.0); widget.setWindowOpacity(2.0); QCOMPARE(widget.windowOpacity(), 1.0); child.setWindowOpacity(2.0); QCOMPARE(child.windowOpacity(), 1.0); widget.setWindowOpacity(-1.0); QCOMPARE(widget.windowOpacity(), 0.0); child.setWindowOpacity(-1.0); QCOMPARE(child.windowOpacity(), 1.0); } class UpdateWidget : public QWidget { public: UpdateWidget(QWidget *parent = 0) : QWidget(parent) { reset(); } void paintEvent(QPaintEvent *e) { paintedRegion += e->region(); ++numPaintEvents; if (resizeInPaintEvent) { resizeInPaintEvent = false; resize(size() + QSize(2, 2)); } } bool event(QEvent *event) { switch (event->type()) { case QEvent::ZOrderChange: ++numZOrderChangeEvents; break; case QEvent::UpdateRequest: ++numUpdateRequestEvents; break; case QEvent::ActivationChange: case QEvent::FocusIn: case QEvent::FocusOut: case QEvent::WindowActivate: case QEvent::WindowDeactivate: if (!updateOnActivationChangeAndFocusIn) return true; // Filter out to avoid update() calls in QWidget. break; default: break; } return QWidget::event(event); } void reset() { numPaintEvents = 0; numZOrderChangeEvents = 0; numUpdateRequestEvents = 0; updateOnActivationChangeAndFocusIn = false; resizeInPaintEvent = false; paintedRegion = QRegion(); } int numPaintEvents; int numZOrderChangeEvents; int numUpdateRequestEvents; bool updateOnActivationChangeAndFocusIn; bool resizeInPaintEvent; QRegion paintedRegion; }; void tst_QWidget::lostUpdatesOnHide() { #ifndef Q_WS_MAC UpdateWidget widget; widget.setAttribute(Qt::WA_DontShowOnScreen); widget.show(); widget.hide(); QTest::qWait(50); widget.show(); QTest::qWait(50); QCOMPARE(widget.numPaintEvents, 1); #endif } void tst_QWidget::raise() { #ifdef QT_MAC_USE_COCOA QSKIP("Cocoa has no Z-Order for views, we hack it, but it results in paint events.", SkipAll); #endif QTest::qWait(1000); QWidget *parent = new QWidget(0); QList allChildren; UpdateWidget *child1 = new UpdateWidget(parent); child1->setAutoFillBackground(true); allChildren.append(child1); UpdateWidget *child2 = new UpdateWidget(parent); child2->setAutoFillBackground(true); allChildren.append(child2); UpdateWidget *child3 = new UpdateWidget(parent); child3->setAutoFillBackground(true); allChildren.append(child3); UpdateWidget *child4 = new UpdateWidget(parent); child4->setAutoFillBackground(true); allChildren.append(child4); parent->show(); #ifdef Q_WS_X11 qt_x11_wait_for_window_manager(parent); #endif QTest::qWait(500); QList list1; list1 << child1 << child2 << child3 << child4; QVERIFY(parent->children() == list1); QCOMPARE(allChildren.count(), list1.count()); foreach (UpdateWidget *child, allChildren) { int expectedPaintEvents = child == child4 ? 1 : 0; if (expectedPaintEvents == 0) { QVERIFY(child->numPaintEvents == 0); } else { // show() issues multiple paint events on some window managers QVERIFY(child->numPaintEvents >= expectedPaintEvents); } QCOMPARE(child->numZOrderChangeEvents, 0); child->reset(); } for (int i = 0; i < 5; ++i) child2->raise(); QTest::qWait(500); foreach (UpdateWidget *child, allChildren) { int expectedPaintEvents = child == child2 ? 1 : 0; int expectedZOrderChangeEvents = child == child2 ? 1 : 0; QCOMPARE(child->numPaintEvents, expectedPaintEvents); QCOMPARE(child->numZOrderChangeEvents, expectedZOrderChangeEvents); child->reset(); } QList list2; list2 << child1 << child3 << child4 << child2; QVERIFY(parent->children() == list2); // Creates a widget on top of all the children and checks that raising one of // the children underneath doesn't trigger a repaint on the covering widget. QWidget topLevel; parent->setParent(&topLevel); topLevel.show(); #ifdef Q_WS_X11 qt_x11_wait_for_window_manager(&topLevel); #endif QTest::qWait(500); UpdateWidget *onTop = new UpdateWidget(&topLevel); onTop->resize(topLevel.size()); onTop->setAutoFillBackground(true); onTop->show(); QTest::qWait(500); onTop->reset(); // Reset all the children. foreach (UpdateWidget *child, allChildren) child->reset(); for (int i = 0; i < 5; ++i) child3->raise(); QTest::qWait(500); QCOMPARE(onTop->numPaintEvents, 0); QCOMPARE(onTop->numZOrderChangeEvents, 0); QList list3; list3 << child1 << child4 << child2 << child3; QVERIFY(parent->children() == list3); foreach (UpdateWidget *child, allChildren) { int expectedPaintEvents = 0; int expectedZOrderChangeEvents = child == child3 ? 1 : 0; QCOMPARE(child->numPaintEvents, expectedPaintEvents); QCOMPARE(child->numZOrderChangeEvents, expectedZOrderChangeEvents); child->reset(); } } void tst_QWidget::lower() { #ifdef QT_MAC_USE_COCOA QSKIP("Cocoa has no Z-Order for views, we hack it, but it results in paint events.", SkipAll); #endif QWidget *parent = new QWidget(0); QList allChildren; UpdateWidget *child1 = new UpdateWidget(parent); child1->setAutoFillBackground(true); allChildren.append(child1); UpdateWidget *child2 = new UpdateWidget(parent); child2->setAutoFillBackground(true); allChildren.append(child2); UpdateWidget *child3 = new UpdateWidget(parent); child3->setAutoFillBackground(true); allChildren.append(child3); UpdateWidget *child4 = new UpdateWidget(parent); child4->setAutoFillBackground(true); allChildren.append(child4); parent->show(); #ifdef Q_WS_X11 qt_x11_wait_for_window_manager(parent); #endif QTest::qWait(1000); QList list1; list1 << child1 << child2 << child3 << child4; QVERIFY(parent->children() == list1); QCOMPARE(allChildren.count(), list1.count()); foreach (UpdateWidget *child, allChildren) { int expectedPaintEvents = child == child4 ? 1 : 0; if (expectedPaintEvents == 0) { QVERIFY(child->numPaintEvents == 0); } else { // show() issues multiple paint events on some window managers QVERIFY(child->numPaintEvents >= expectedPaintEvents); } QCOMPARE(child->numZOrderChangeEvents, 0); child->reset(); } for (int i = 0; i < 5; ++i) child4->lower(); QTest::qWait(1000); foreach (UpdateWidget *child, allChildren) { int expectedPaintEvents = child == child3 ? 1 : 0; int expectedZOrderChangeEvents = child == child4 ? 1 : 0; QCOMPARE(child->numZOrderChangeEvents, expectedZOrderChangeEvents); QCOMPARE(child->numPaintEvents, expectedPaintEvents); child->reset(); } QList list2; list2 << child4 << child1 << child2 << child3; QVERIFY(parent->children() == list2); delete parent; } void tst_QWidget::stackUnder() { #ifdef QT_MAC_USE_COCOA QSKIP("Cocoa has no Z-Order for views, we hack it, but it results in paint events.", SkipAll); #endif QTest::qWait(1000); QWidget *parent = new QWidget(0); QList allChildren; UpdateWidget *child1 = new UpdateWidget(parent); child1->setAutoFillBackground(true); allChildren.append(child1); UpdateWidget *child2 = new UpdateWidget(parent); child2->setAutoFillBackground(true); allChildren.append(child2); UpdateWidget *child3 = new UpdateWidget(parent); child3->setAutoFillBackground(true); allChildren.append(child3); UpdateWidget *child4 = new UpdateWidget(parent); child4->setAutoFillBackground(true); allChildren.append(child4); parent->show(); #ifdef Q_WS_X11 qt_x11_wait_for_window_manager(parent); #endif QTest::qWait(1000); #ifdef Q_WS_QWS QApplication::sendPostedEvents(); //glib workaround #endif QList list1; list1 << child1 << child2 << child3 << child4; QVERIFY(parent->children() == list1); foreach (UpdateWidget *child, allChildren) { int expectedPaintEvents = child == child4 ? 1 : 0; #if defined(Q_WS_WIN) || defined(Q_WS_MAC) if (expectedPaintEvents == 1 && child->numPaintEvents == 2) QEXPECT_FAIL(0, "Mac and Windows issues double repaints for Z-Order change", Continue); #endif QCOMPARE(child->numPaintEvents, expectedPaintEvents); QCOMPARE(child->numZOrderChangeEvents, 0); child->reset(); } for (int i = 0; i < 5; ++i) child4->stackUnder(child2); QTest::qWait(1000); QList list2; list2 << child1 << child4 << child2 << child3; QVERIFY(parent->children() == list2); foreach (UpdateWidget *child, allChildren) { int expectedPaintEvents = child == child3 ? 1 : 0; int expectedZOrderChangeEvents = child == child4 ? 1 : 0; QCOMPARE(child->numPaintEvents, expectedPaintEvents); QCOMPARE(child->numZOrderChangeEvents, expectedZOrderChangeEvents); child->reset(); } for (int i = 0; i < 5; ++i) child1->stackUnder(child3); QTest::qWait(1000); QList list3; list3 << child4 << child2 << child1 << child3; QVERIFY(parent->children() == list3); foreach (UpdateWidget *child, allChildren) { int expectedZOrderChangeEvents = child == child1 ? 1 : 0; if (child == child3) { #ifdef Q_OS_WINCE qApp->processEvents(); #endif #ifndef Q_WS_MAC QEXPECT_FAIL(0, "Task 153869", Continue); #endif QCOMPARE(child->numPaintEvents, 0); } else { QCOMPARE(child->numPaintEvents, 0); } QCOMPARE(child->numZOrderChangeEvents, expectedZOrderChangeEvents); child->reset(); } delete parent; } void drawPolygon(QPaintDevice *dev, int w, int h) { QPainter p(dev); p.fillRect(0, 0, w, h, Qt::white); QPolygon a; a << QPoint(0, 0) << QPoint(w/2, h/2) << QPoint(w, 0) << QPoint(w/2, h) << QPoint(0, 0); p.setPen(QPen(Qt::black, 1)); p.setBrush(Qt::DiagCrossPattern); p.drawPolygon(a); } class ContentsPropagationWidget : public QWidget { Q_OBJECT public: ContentsPropagationWidget(QWidget *parent = 0) : QWidget(parent) { QWidget *child = this; for (int i=0; i<32; ++i) { child = new QWidget(child); child->setGeometry(i, i, 400 - i*2, 400 - i*2); } } void setContentsPropagation(bool enable) { foreach (QObject *child, children()) qobject_cast(child)->setAutoFillBackground(!enable); } protected: void paintEvent(QPaintEvent *) { int w = width(), h = height(); drawPolygon(this, w, h); } QSize sizeHint() const { return QSize(500, 500); } }; void tst_QWidget::testContentsPropagation() { #ifdef Q_WS_MAC QSKIP("Pixmap is not antialiased whereas widget is.", SkipAll); #endif ContentsPropagationWidget widget; #ifdef Q_WS_QWS widget.resize(500,500); #else widget.setFixedSize(500, 500); #endif widget.setContentsPropagation(false); QPixmap widgetSnapshot = QPixmap::grabWidget(&widget); QPixmap correct(500, 500); drawPolygon(&correct, 500, 500); //correct.save("correct.png", "PNG"); //widgetSnapshot.save("snap1.png", "PNG"); QVERIFY(widgetSnapshot.toImage() != correct.toImage()); widget.setContentsPropagation(true); widgetSnapshot = QPixmap::grabWidget(&widget); //widgetSnapshot.save("snap2.png", "PNG"); QCOMPARE(widgetSnapshot, correct); } /* Test that saving and restoring window geometry with saveGeometry() and restoreGeometry() works. */ void tst_QWidget::saveRestoreGeometry() { #ifdef Q_OS_IRIX QSKIP("4DWM issues on IRIX makes this test fail", SkipAll); #endif const QPoint position(100, 100); const QSize size(200, 200); QByteArray savedGeometry; { QWidget widget; widget.move(position); widget.resize(size); widget.show(); #ifdef Q_WS_X11 qt_x11_wait_for_window_manager(&widget); #endif QTest::qWait(100); QCOMPARE(widget.pos(), position); QCOMPARE(widget.size(), size); savedGeometry = widget.saveGeometry(); } { QWidget widget; const QByteArray empty; const QByteArray one("a"); const QByteArray two("ab"); const QByteArray three("abc"); const QByteArray four("abca"); const QByteArray garbage("abcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabc"); QVERIFY(widget.restoreGeometry(empty) == false); QVERIFY(widget.restoreGeometry(one) == false); QVERIFY(widget.restoreGeometry(two) == false); QVERIFY(widget.restoreGeometry(three) == false); QVERIFY(widget.restoreGeometry(four) == false); QVERIFY(widget.restoreGeometry(garbage) == false); QVERIFY(widget.restoreGeometry(savedGeometry)); widget.show(); #ifdef Q_WS_X11 qt_x11_wait_for_window_manager(&widget); #endif QTest::qWait(100); QCOMPARE(widget.pos(), position); QCOMPARE(widget.size(), size); widget.show(); QCOMPARE(widget.pos(), position); QCOMPARE(widget.size(), size); } { QWidget widget; widget.move(position); widget.resize(size); widget.show(); #ifdef Q_WS_X11 qt_x11_wait_for_window_manager(&widget); #endif QTest::qWait(100); QRect geom; //Restore from Full screen savedGeometry = widget.saveGeometry(); geom = widget.geometry(); widget.setWindowState(widget.windowState() | Qt::WindowFullScreen); #ifdef Q_WS_X11 qt_x11_wait_for_window_manager(&widget); #endif QTest::qWait(100); QVERIFY((widget.windowState() & Qt::WindowFullScreen)); QVERIFY(widget.restoreGeometry(savedGeometry)); #ifdef Q_WS_X11 qt_x11_wait_for_window_manager(&widget); #endif QTest::qWait(100); QCOMPARE(widget.geometry(), geom); QVERIFY(!(widget.windowState() & Qt::WindowFullScreen)); //Restore to full screen widget.setWindowState(widget.windowState() | Qt::WindowFullScreen); #ifdef Q_WS_X11 qt_x11_wait_for_window_manager(&widget); #endif QTest::qWait(100); QVERIFY((widget.windowState() & Qt::WindowFullScreen)); savedGeometry = widget.saveGeometry(); geom = widget.geometry(); widget.setWindowState(widget.windowState() ^ Qt::WindowFullScreen); #ifdef Q_WS_X11 qt_x11_wait_for_window_manager(&widget); #endif QTest::qWait(100); QVERIFY(widget.restoreGeometry(savedGeometry)); #ifdef Q_WS_X11 qt_x11_wait_for_window_manager(&widget); #endif QTest::qWait(100); QCOMPARE(widget.geometry(), geom); QVERIFY((widget.windowState() & Qt::WindowFullScreen)); widget.setWindowState(widget.windowState() ^ Qt::WindowFullScreen); #ifdef Q_WS_X11 qt_x11_wait_for_window_manager(&widget); #endif QTest::qWait(100); //Restore from Maximised widget.move(position); widget.resize(size); #ifdef Q_WS_X11 qt_x11_wait_for_window_manager(&widget); #endif QTest::qWait(100); savedGeometry = widget.saveGeometry(); geom = widget.geometry(); widget.setWindowState(widget.windowState() | Qt::WindowMaximized); #ifdef Q_WS_X11 qt_x11_wait_for_window_manager(&widget); #endif QTest::qWait(100); QVERIFY((widget.windowState() & Qt::WindowMaximized)); QVERIFY(widget.geometry() != geom); QVERIFY(widget.restoreGeometry(savedGeometry)); #ifdef Q_WS_X11 qt_x11_wait_for_window_manager(&widget); #endif QTest::qWait(100); QCOMPARE(widget.geometry(), geom); QVERIFY(!(widget.windowState() & Qt::WindowMaximized)); //Restore to maximised widget.setWindowState(widget.windowState() | Qt::WindowMaximized); #ifdef Q_WS_X11 qt_x11_wait_for_window_manager(&widget); #endif QTest::qWait(100); QVERIFY((widget.windowState() & Qt::WindowMaximized)); geom = widget.geometry(); savedGeometry = widget.saveGeometry(); widget.setWindowState(widget.windowState() ^ Qt::WindowMaximized); #ifdef Q_WS_X11 qt_x11_wait_for_window_manager(&widget); #endif QTest::qWait(100); QVERIFY(widget.restoreGeometry(savedGeometry)); #ifdef Q_WS_X11 qt_x11_wait_for_window_manager(&widget); #endif QTest::qWait(100); QCOMPARE(widget.geometry(), geom); QVERIFY((widget.windowState() & Qt::WindowMaximized)); } } void tst_QWidget::restoreVersion1Geometry_data() { QTest::addColumn("fileName"); QTest::addColumn("expectedWindowState"); QTest::addColumn("expectedPosition"); QTest::addColumn("expectedSize"); QTest::addColumn("expectedNormalGeometry"); const QPoint position(100, 100); const QSize size(200, 200); const QRect normalGeometry(102, 124, 200, 200); QTest::newRow("geometry.dat") << ":geometry.dat" << uint(Qt::WindowNoState) << position << size << normalGeometry; QTest::newRow("geometry-maximized.dat") << ":geometry-maximized.dat" << uint(Qt::WindowMaximized) << position << size << normalGeometry; QTest::newRow("geometry-fullscreen.dat") << ":geometry-fullscreen.dat" << uint(Qt::WindowFullScreen) << position << size << normalGeometry; } /* Test that the current version of restoreGeometry() can restore geometry saved width saveGeometry() version 1.0. */ void tst_QWidget::restoreVersion1Geometry() { #ifdef Q_OS_IRIX QSKIP("4DWM issues on IRIX makes this test fail", SkipAll); #endif QFETCH(QString, fileName); QFETCH(uint, expectedWindowState); QFETCH(QPoint, expectedPosition); QFETCH(QSize, expectedSize); QFETCH(QRect, expectedNormalGeometry); // WindowActive is uninteresting for this test const uint WindowStateMask = Qt::WindowFullScreen | Qt::WindowMaximized | Qt::WindowMinimized; QFile f(fileName); QVERIFY(f.exists()); f.open(QIODevice::ReadOnly); const QByteArray savedGeometry = f.readAll(); QCOMPARE(savedGeometry.count(), 46); f.close(); QWidget widget; QVERIFY(widget.restoreGeometry(savedGeometry)); QCOMPARE(uint(widget.windowState() & WindowStateMask), expectedWindowState); if (expectedWindowState == Qt::WindowNoState) { QCOMPARE(widget.pos(), expectedPosition); QCOMPARE(widget.size(), expectedSize); } widget.show(); #ifdef Q_WS_X11 qt_x11_wait_for_window_manager(&widget); #endif QTest::qWait(100); if (expectedWindowState == Qt::WindowNoState) { QCOMPARE(widget.pos(), expectedPosition); QCOMPARE(widget.size(), expectedSize); } widget.showNormal(); QTest::qWait(1000); if (expectedWindowState != Qt::WindowNoState) { // restoring from maximized or fullscreen, we can only restore to the normal geometry QCOMPARE(widget.geometry(), expectedNormalGeometry); } else { QCOMPARE(widget.pos(), expectedPosition); QCOMPARE(widget.size(), expectedSize); } #if 0 // Code for saving a new geometry*.dat files { QWidget widgetToSave; widgetToSave.move(expectedPosition); widgetToSave.resize(expectedSize); widgetToSave.show(); #ifdef Q_WS_X11 qt_x11_wait_for_window_manager(&widget); #endif QTest::qWait(500); // stabilize widgetToSave.setWindowState(Qt::WindowStates(expectedWindowState)); QTest::qWait(500); // stabilize QByteArray geometryToSave = widgetToSave.saveGeometry(); // Code for saving a new geometry.dat file. f.setFileName(fileName.mid(1)); QVERIFY(f.open(QIODevice::WriteOnly)); // did you forget to 'p4 edit *.dat'? :) f.write(geometryToSave); f.close(); } #endif } void tst_QWidget::widgetAt() { Q_CHECK_PAINTEVENTS QWidget *w1 = new QWidget(0, Qt::X11BypassWindowManagerHint); w1->setGeometry(0,0,150,150); w1->setObjectName("w1"); QWidget *w2 = new QWidget(0, Qt::X11BypassWindowManagerHint | Qt::FramelessWindowHint); w2->setGeometry(50,50,100,100); w2->setObjectName("w2"); w1->show(); #ifdef Q_WS_X11 qt_x11_wait_for_window_manager(w1); #endif qApp->processEvents(); QWidget *wr = QApplication::widgetAt(100, 100); QVERIFY(wr); QCOMPARE(wr->objectName(), QString("w1")); w2->show(); qApp->processEvents(); qApp->processEvents(); qApp->processEvents(); wr = QApplication::widgetAt(100, 100); QVERIFY(wr); QCOMPARE(wr->objectName(), QString("w2")); w2->lower(); qApp->processEvents(); wr = QApplication::widgetAt(100, 100); QVERIFY(wr); QCOMPARE(wr->objectName(), QString("w1")); w2->raise(); qApp->processEvents(); wr = QApplication::widgetAt(100, 100); QVERIFY(wr); QCOMPARE(wr->objectName(), QString("w2")); QWidget *w3 = new QWidget(w2); w3->setGeometry(10,10,50,50); w3->setObjectName("w3"); w3->show(); qApp->processEvents(); wr = QApplication::widgetAt(100,100); QVERIFY(wr); QCOMPARE(wr->objectName(), QString("w3")); w3->setAttribute(Qt::WA_TransparentForMouseEvents); qApp->processEvents(); wr = QApplication::widgetAt(100, 100); QVERIFY(wr); QCOMPARE(wr->objectName(), QString("w2")); QRegion rgn = QRect(QPoint(0,0), w2->size()); QPoint point = w2->mapFromGlobal(QPoint(100,100)); rgn -= QRect(point, QSize(1,1)); w2->setMask(rgn); qApp->processEvents(); QTest::qWait(1000); #if defined(Q_OS_WINCE) QEXPECT_FAIL("", "Windows CE does only support rectangular regions", Continue); //See also task 147191 #endif QCOMPARE(QApplication::widgetAt(100,100)->objectName(), w1->objectName()); QCOMPARE(QApplication::widgetAt(101,101)->objectName(), w2->objectName()); QBitmap bitmap(w2->size()); QPainter p(&bitmap); p.fillRect(bitmap.rect(), Qt::color1); p.setPen(Qt::color0); p.drawPoint(w2->mapFromGlobal(QPoint(100,100))); p.end(); w2->setMask(bitmap); qApp->processEvents(); QTest::qWait(1000); #if defined(Q_OS_WINCE) QEXPECT_FAIL("", "Windows CE does only support rectangular regions", Continue); //See also task 147191 #endif QVERIFY(QApplication::widgetAt(100,100) == w1); QVERIFY(QApplication::widgetAt(101,101) == w2); delete w2; delete w1; } #if defined(Q_WS_X11) bool getProperty(Display *display, Window target, Atom type, Atom property, unsigned char** data, unsigned long* count) { Atom atom_return; int size; unsigned long nitems, bytes_left; int ret = XGetWindowProperty(display, target, property, 0l, 1l, false, type, &atom_return, &size, &nitems, &bytes_left, data); if (ret != Success || nitems < 1) return false; if (bytes_left != 0) { XFree(*data); unsigned long remain = ((size / 8) * nitems) + bytes_left; ret = XGetWindowProperty(display, target, property, 0l, remain, false, type, &atom_return, &size, &nitems, &bytes_left, data); if (ret != Success) return false; } *count = nitems; return true; } QString textPropertyToString(Display *display, XTextProperty& text_prop) { QString ret; if (text_prop.value && text_prop.nitems > 0) { if (text_prop.encoding == XA_STRING) { ret = reinterpret_cast(text_prop.value); } else { text_prop.nitems = strlen(reinterpret_cast(text_prop.value)); char **list; int num; if (XmbTextPropertyToTextList(display, &text_prop, &list, &num) == Success && num > 0 && *list) { ret = QString::fromLocal8Bit(*list); XFreeStringList(list); } } } return ret; } #endif static QString visibleWindowTitle(QWidget *window, Qt::WindowState state = Qt::WindowNoState) { QString vTitle; #ifdef Q_WS_WIN Q_UNUSED(state); const size_t maxTitleLength = 256; WCHAR title[maxTitleLength]; GetWindowTextW(window->winId(), title, maxTitleLength); vTitle = QString::fromUtf16((ushort *)title); #elif defined(Q_WS_X11) /* We can't check what the window manager displays, but we can check what we tell the window manager to display. This will have to do. */ Atom UTF8_STRING = XInternAtom(window->x11Info().display(), "UTF8_STRING", false); Atom _NET_WM_NAME = XInternAtom(window->x11Info().display(), "_NET_WM_NAME", false); Atom _NET_WM_ICON_NAME = XInternAtom(window->x11Info().display(), "_NET_WM_ICON_NAME", false); uchar *data = 0; ulong length = 0; if (state == Qt::WindowMinimized) { if (getProperty(window->x11Info().display(), window->winId(), UTF8_STRING, _NET_WM_ICON_NAME, &data, &length)) { vTitle = QString::fromUtf8((char *) data, length); XFree(data); } else { XTextProperty text_prop; if (XGetWMIconName(window->x11Info().display(), window->winId(), &text_prop)) { vTitle = textPropertyToString(window->x11Info().display(), text_prop); XFree((char *) text_prop.value); } } } else { if (getProperty(window->x11Info().display(), window->winId(), UTF8_STRING, _NET_WM_NAME, &data, &length)) { vTitle = QString::fromUtf8((char *) data, length); XFree(data); } else { XTextProperty text_prop; if (XGetWMName(window->x11Info().display(), window->winId(), &text_prop)) { vTitle = textPropertyToString(window->x11Info().display(), text_prop); XFree((char *) text_prop.value); } } } #elif defined(Q_WS_MAC) vTitle = nativeWindowTitle(window, state); #elif defined(Q_WS_QWS) if (qwsServer) { const QWSWindow *win = 0; const QList windows = qwsServer->clientWindows(); for (int i = 0; i < windows.count(); ++i) { const QWSWindow* w = windows.at(i); if (w->winId() == window->winId()) { win = w; break; } } if (win) vTitle = win->caption(); } #endif return vTitle; } void tst_QWidget::windowTitle() { QWidget widget(0); widget.setWindowTitle("Application Name"); widget.winId(); // Make sure the window is created... QCOMPARE(visibleWindowTitle(&widget), QString("Application Name")); widget.setWindowTitle("Application Name *"); QCOMPARE(visibleWindowTitle(&widget), QString("Application Name *")); widget.setWindowTitle("Application Name[*]"); QCOMPARE(visibleWindowTitle(&widget), QString("Application Name")); widget.setWindowTitle("Application Name[*][*]"); QCOMPARE(visibleWindowTitle(&widget), QString("Application Name[*]")); widget.setWindowTitle("Application Name[*][*][*]"); QCOMPARE(visibleWindowTitle(&widget), QString("Application Name[*]")); widget.setWindowTitle("Application Name[*][*][*][*]"); QCOMPARE(visibleWindowTitle(&widget), QString("Application Name[*][*]")); } void tst_QWidget::windowIconText() { QWidget widget(0); widget.setWindowTitle("Application Name"); widget.setWindowIconText("Application Minimized"); widget.showNormal(); QCOMPARE(visibleWindowTitle(&widget), QString("Application Name")); widget.showMinimized(); #if defined(Q_WS_QWS) || defined(Q_OS_WINCE) QEXPECT_FAIL(0, "Qt/Embedded/WinCE does not implement showMinimized()", Continue); //See task 147193 for WinCE #endif QApplication::instance()->processEvents(); QCOMPARE(visibleWindowTitle(&widget, Qt::WindowMinimized), QString("Application Minimized")); widget.setWindowTitle("Application Name[*]"); widget.setWindowIconText("Application Minimized[*]"); widget.showNormal(); QApplication::instance()->processEvents(); QCOMPARE(visibleWindowTitle(&widget), QString("Application Name")); widget.showMinimized(); #if defined (Q_WS_QWS) || defined(Q_OS_WINCE) QEXPECT_FAIL(0, "Qt/Embedded/WinCE does not implement showMinimized()", Continue); //See task 147193 for WinCE #endif QApplication::instance()->processEvents(); QCOMPARE(visibleWindowTitle(&widget, Qt::WindowMinimized), QString("Application Minimized")); widget.setWindowModified(true); widget.showNormal(); QApplication::instance()->processEvents(); if (widget.style()->styleHint(QStyle::SH_TitleBar_ModifyNotification, 0, &widget)) QCOMPARE(visibleWindowTitle(&widget), QString("Application Name*")); else QCOMPARE(visibleWindowTitle(&widget), QString("Application Name")); widget.showMinimized(); #if defined (Q_WS_QWS) || defined(Q_OS_WINCE) QEXPECT_FAIL(0, "Qt/Embedded/WinCE does not implement showMinimized()", Continue); //See task 147193 for WinCE #endif QApplication::instance()->processEvents(); #ifdef Q_WS_MAC QCOMPARE(visibleWindowTitle(&widget, Qt::WindowMinimized), QString("Application Minimized")); QVERIFY(nativeWindowModified(&widget)); #else QCOMPARE(visibleWindowTitle(&widget, Qt::WindowMinimized), QString("Application Minimized*")); #endif } void tst_QWidget::windowModified() { QWidget widget(0); widget.show(); #ifndef Q_WS_MAC QTest::ignoreMessage(QtWarningMsg, "QWidget::setWindowModified: The window title does not contain a '[*]' placeholder"); #endif widget.setWindowTitle("Application Name"); QTest::qWait(1000); QCOMPARE(visibleWindowTitle(&widget), QString("Application Name")); #ifdef Q_WS_MAC widget.setWindowModified(true); QVERIFY(nativeWindowModified(&widget)); #else widget.setWindowModified(true); QApplication::instance()->processEvents(); QCOMPARE(visibleWindowTitle(&widget), QString("Application Name")); widget.setWindowModified(false); QApplication::instance()->processEvents(); QCOMPARE(visibleWindowTitle(&widget), QString("Application Name")); widget.setWindowTitle("Application Name[*]"); widget.setWindowModified(true); QApplication::instance()->processEvents(); if (widget.style()->styleHint(QStyle::SH_TitleBar_ModifyNotification, 0, &widget)) QCOMPARE(visibleWindowTitle(&widget), QString("Application Name*")); else QCOMPARE(visibleWindowTitle(&widget), QString("Application Name")); widget.setWindowModified(false); QApplication::instance()->processEvents(); QCOMPARE(visibleWindowTitle(&widget), QString("Application Name")); widget.setWindowTitle("Application[*] Name[*]"); widget.setWindowModified(true); QApplication::instance()->processEvents(); QCOMPARE(visibleWindowTitle(&widget), QString("Application* Name*")); widget.setWindowModified(false); QApplication::instance()->processEvents(); QCOMPARE(visibleWindowTitle(&widget), QString("Application Name")); widget.setWindowTitle("Application Name[*][*]"); widget.setWindowModified(true); QApplication::instance()->processEvents(); QCOMPARE(visibleWindowTitle(&widget), QString("Application Name[*]")); widget.setWindowModified(false); QApplication::instance()->processEvents(); QCOMPARE(visibleWindowTitle(&widget), QString("Application Name[*]")); widget.setWindowTitle("Application[*][*] Name[*][*]"); widget.setWindowModified(true); QApplication::instance()->processEvents(); QCOMPARE(visibleWindowTitle(&widget), QString("Application[*] Name[*]")); widget.setWindowModified(false); QApplication::instance()->processEvents(); QCOMPARE(visibleWindowTitle(&widget), QString("Application[*] Name[*]")); widget.setWindowTitle("Application[*] Name[*][*][*]"); widget.setWindowModified(true); QApplication::instance()->processEvents(); QCOMPARE(visibleWindowTitle(&widget), QString("Application* Name[*]*")); widget.setWindowModified(false); QApplication::instance()->processEvents(); QCOMPARE(visibleWindowTitle(&widget), QString("Application Name[*]")); widget.setWindowTitle("Application[*][*][*] Name[*][*][*]"); widget.setWindowModified(true); QApplication::instance()->processEvents(); QCOMPARE(visibleWindowTitle(&widget), QString("Application[*]* Name[*]*")); widget.setWindowModified(false); QApplication::instance()->processEvents(); QCOMPARE(visibleWindowTitle(&widget), QString("Application[*] Name[*]")); #endif } void tst_QWidget::task110173() { QWidget w; QPushButton *pb1 = new QPushButton("click", &w); pb1->setFocusPolicy(Qt::ClickFocus); pb1->move(100, 100); QPushButton *pb2 = new QPushButton("push", &w); pb2->setFocusPolicy(Qt::ClickFocus); pb2->move(300, 300); QTest::keyClick( &w, Qt::Key_Tab ); w.show(); QTest::qWait(1000); } class Widget : public QWidget { public: Widget() : deleteThis(false) { setFocusPolicy(Qt::StrongFocus); } void actionEvent(QActionEvent *) { if (deleteThis) delete this; } void changeEvent(QEvent *) { if (deleteThis) delete this; } void closeEvent(QCloseEvent *) { if (deleteThis) delete this; } void hideEvent(QHideEvent *) { if (deleteThis) delete this; } void focusOutEvent(QFocusEvent *) { if (deleteThis) delete this; } void keyPressEvent(QKeyEvent *) { if (deleteThis) delete this; } void keyReleaseEvent(QKeyEvent *) { if (deleteThis) delete this; } void mouseDoubleClickEvent(QMouseEvent *) { if (deleteThis) delete this; } void mousePressEvent(QMouseEvent *) { if (deleteThis) delete this; } void mouseReleaseEvent(QMouseEvent *) { if (deleteThis) delete this; } void mouseMoveEvent(QMouseEvent *) { if (deleteThis) delete this; } bool deleteThis; }; void tst_QWidget::testDeletionInEventHandlers() { // closeEvent QPointer w = new Widget; w->deleteThis = true; w->close(); QVERIFY(w == 0); delete w; // focusOut (crashes) //w = new Widget; //w->show(); //w->setFocus(); //QVERIFY(qApp->focusWidget() == w); //w->deleteThis = true; //w->clearFocus(); //QVERIFY(w == 0); // key press w = new Widget; w->show(); w->deleteThis = true; QTest::keyPress(w, Qt::Key_A); QVERIFY(w == 0); delete w; // key release w = new Widget; w->show(); w->deleteThis = true; QTest::keyRelease(w, Qt::Key_A); QVERIFY(w == 0); delete w; // mouse press w = new Widget; w->show(); w->deleteThis = true; QTest::mousePress(w, Qt::LeftButton); QVERIFY(w == 0); delete w; // mouse release w = new Widget; w->show(); w->deleteThis = true; QTest::mouseRelease(w, Qt::LeftButton); QVERIFY(w == 0); delete w; // mouse double click w = new Widget; w->show(); w->deleteThis = true; QTest::mouseDClick(w, Qt::LeftButton); QVERIFY(w == 0); delete w; // hide event (crashes) //w = new Widget; //w->show(); //w->deleteThis = true; //w->hide(); //QVERIFY(w == 0); // action event w = new Widget; w->deleteThis = true; w->addAction(new QAction(w)); QVERIFY(w == 0); delete w; // change event w = new Widget; w->show(); w->deleteThis = true; w->setMouseTracking(true); QVERIFY(w == 0); delete w; w = new Widget; w->setMouseTracking(true); w->show(); w->deleteThis = true; QMouseEvent me(QEvent::MouseMove, QPoint(0, 0), Qt::NoButton, Qt::NoButton, Qt::NoModifier); QApplication::sendEvent(w, &me); QVERIFY(w == 0); delete w; } #ifdef Q_WS_MAC bool testAndRelease(const HIViewRef view) { // qDebug() << CFGetRetainCount(view); if (CFGetRetainCount(view) != 2) return false; CFRelease(view); CFRelease(view); return true; } typedef QPair WidgetViewPair; WidgetViewPair createAndRetain(QWidget * const parent = 0) { QWidget * const widget = new QWidget(parent); const HIViewRef view = (HIViewRef)widget->winId(); // Retain twice so we can safely call CFGetRetaintCount even if the retain count // is off by one because of a double release. CFRetain(view); CFRetain(view); return qMakePair(widget, view); } /* Test that retaining and releasing the HIView returned by QWidget::winId() works even if the widget itself is deleted. */ void tst_QWidget::retainHIView() { // Single window { const WidgetViewPair window = createAndRetain(); delete window.first; QVERIFY(testAndRelease(window.second)); } // Child widget { const WidgetViewPair parent = createAndRetain(); const WidgetViewPair child = createAndRetain(parent.first); delete parent.first; QVERIFY(testAndRelease(parent.second)); QVERIFY(testAndRelease(child.second)); } // Multiple children { const WidgetViewPair parent = createAndRetain(); const WidgetViewPair child1 = createAndRetain(parent.first); const WidgetViewPair child2 = createAndRetain(parent.first); delete parent.first; QVERIFY(testAndRelease(parent.second)); QVERIFY(testAndRelease(child1.second)); QVERIFY(testAndRelease(child2.second)); } // Grandchild widget { const WidgetViewPair parent = createAndRetain(); const WidgetViewPair child = createAndRetain(parent.first); const WidgetViewPair grandchild = createAndRetain(child.first); delete parent.first; QVERIFY(testAndRelease(parent.second)); QVERIFY(testAndRelease(child.second)); QVERIFY(testAndRelease(grandchild.second)); } // Reparent child widget { const WidgetViewPair parent1 = createAndRetain(); const WidgetViewPair parent2 = createAndRetain(); const WidgetViewPair child = createAndRetain(parent1.first); child.first->setParent(parent2.first); delete parent1.first; QVERIFY(testAndRelease(parent1.second)); delete parent2.first; QVERIFY(testAndRelease(parent2.second)); QVERIFY(testAndRelease(child.second)); } // Reparent window { const WidgetViewPair window1 = createAndRetain(); const WidgetViewPair window2 = createAndRetain(); const WidgetViewPair child1 = createAndRetain(window1.first); const WidgetViewPair child2 = createAndRetain(window2.first); window2.first->setParent(window1.first); delete window2.first; QVERIFY(testAndRelease(window2.second)); QVERIFY(testAndRelease(child2.second)); delete window1.first; QVERIFY(testAndRelease(window1.second)); QVERIFY(testAndRelease(child1.second)); } // Delete child widget { const WidgetViewPair parent = createAndRetain(); const WidgetViewPair child = createAndRetain(parent.first); delete child.first; QVERIFY(testAndRelease(child.second)); delete parent.first; QVERIFY(testAndRelease(parent.second)); } } void tst_QWidget::sheetOpacity() { QWidget tmpWindow; QWidget sheet(&tmpWindow, Qt::Sheet); tmpWindow.show(); sheet.show(); QCOMPARE(int(sheet.windowOpacity() * 255), 242); // 95% sheet.setParent(0, Qt::Dialog); QCOMPARE(int(sheet.windowOpacity() * 255), 255); } class MaskedPainter : public QWidget { public: QRect mask; MaskedPainter() : mask(20, 20, 50, 50) { setMask(mask); } void paintEvent(QPaintEvent *) { QPainter p(this); p.fillRect(mask, QColor(Qt::red)); } }; /* Verifies that the entire area inside the mask is painted red. */ bool verifyWidgetMask(QWidget *widget, QRect mask) { const QImage image = QPixmap::grabWindow(widget->winId()).toImage(); const QImage masked = image.copy(mask); QImage red(masked); red.fill(QColor(Qt::red).rgb()); return (masked == red); } void tst_QWidget::setMask() { testWidget->hide(); // get this out of the way. { MaskedPainter w; w.resize(200, 200); w.show(); QTest::qWait(100); QVERIFY(verifyWidgetMask(&w, w.mask)); } { MaskedPainter w; w.resize(200, 200); w.setWindowFlags(w.windowFlags() | Qt::FramelessWindowHint); w.show(); QTest::qWait(100); QRect mask = w.mask; QVERIFY(verifyWidgetMask(&w, mask)); } } #endif class StaticWidget : public QWidget { Q_OBJECT public: bool partial; bool gotPaintEvent; QRegion paintedRegion; StaticWidget(QWidget *parent = 0) :QWidget(parent) { setAttribute(Qt::WA_StaticContents); setPalette(Qt::red); // Make sure we have an opaque palette. setAutoFillBackground(true); gotPaintEvent = false; } void paintEvent(QPaintEvent *e) { paintedRegion += e->region(); gotPaintEvent = true; // qDebug() << "paint" << e->region(); // Look for a full update, set partial to false if found. foreach(QRect r, e->region().rects()) { partial = (r != rect()); if (partial == false) break; } } }; /* Test that widget resizes and moves can be done with minimal repaints when WA_StaticContents and WA_OpaquePaintEvent is set. Test is mac-only for now. */ void tst_QWidget::optimizedResizeMove() { QWidget parent; parent.resize(400, 400); StaticWidget staticWidget(&parent); staticWidget.move(150, 150); staticWidget.resize(150, 150); parent.show(); #ifdef Q_WS_X11 qt_x11_wait_for_window_manager(&parent); #endif QTest::qWait(200); staticWidget.gotPaintEvent = false; staticWidget.move(staticWidget.pos() + QPoint(10, 10)); QTest::qWait(100); QCOMPARE(staticWidget.gotPaintEvent, false); staticWidget.gotPaintEvent = false; staticWidget.move(staticWidget.pos() + QPoint(-10, -10)); QTest::qWait(100); QCOMPARE(staticWidget.gotPaintEvent, false); staticWidget.gotPaintEvent = false; staticWidget.move(staticWidget.pos() + QPoint(-10, 10)); QTest::qWait(100); QCOMPARE(staticWidget.gotPaintEvent, false); staticWidget.gotPaintEvent = false; staticWidget.resize(staticWidget.size() + QSize(10, 10)); QTest::qWait(100); QCOMPARE(staticWidget.gotPaintEvent, true); QCOMPARE(staticWidget.partial, true); staticWidget.gotPaintEvent = false; staticWidget.resize(staticWidget.size() + QSize(-10, -10)); QTest::qWait(100); QCOMPARE(staticWidget.gotPaintEvent, false); staticWidget.gotPaintEvent = false; staticWidget.resize(staticWidget.size() + QSize(10, -10)); QTest::qWait(100); QCOMPARE(staticWidget.gotPaintEvent, true); QCOMPARE(staticWidget.partial, true); staticWidget.gotPaintEvent = false; staticWidget.move(staticWidget.pos() + QPoint(10, 10)); staticWidget.resize(staticWidget.size() + QSize(-10, -10)); QTest::qWait(100); QCOMPARE(staticWidget.gotPaintEvent, false); staticWidget.gotPaintEvent = false; staticWidget.move(staticWidget.pos() + QPoint(10, 10)); staticWidget.resize(staticWidget.size() + QSize(10, 10)); QTest::qWait(100); QCOMPARE(staticWidget.gotPaintEvent, true); QCOMPARE(staticWidget.partial, true); staticWidget.gotPaintEvent = false; staticWidget.move(staticWidget.pos() + QPoint(-10, -10)); staticWidget.resize(staticWidget.size() + QSize(-10, -10)); QTest::qWait(100); QCOMPARE(staticWidget.gotPaintEvent, false); staticWidget.setAttribute(Qt::WA_StaticContents, false); staticWidget.gotPaintEvent = false; staticWidget.move(staticWidget.pos() + QPoint(-10, -10)); staticWidget.resize(staticWidget.size() + QSize(-10, -10)); QTest::qWait(100); QCOMPARE(staticWidget.gotPaintEvent, true); QCOMPARE(staticWidget.partial, false); staticWidget.setAttribute(Qt::WA_StaticContents, true); staticWidget.setAttribute(Qt::WA_StaticContents, false); staticWidget.gotPaintEvent = false; staticWidget.move(staticWidget.pos() + QPoint(10, 10)); QTest::qWait(100); QCOMPARE(staticWidget.gotPaintEvent, false); staticWidget.setAttribute(Qt::WA_StaticContents, true); } void tst_QWidget::optimizedResize_topLevel() { #if defined(Q_WS_MAC) || defined(Q_WS_QWS) QSKIP("We do not yet have static contents support for *top-levels* on this platform", SkipAll); #endif StaticWidget topLevel; topLevel.show(); #ifdef Q_WS_X11 qt_x11_wait_for_window_manager(&topLevel); #endif QTest::qWait(100); topLevel.gotPaintEvent = false; topLevel.partial = false; topLevel.paintedRegion = QRegion(); #ifndef Q_WS_WIN topLevel.resize(topLevel.size() + QSize(10, 10)); #else // Static contents does not work when programmatically resizing // top-levels with QWidget::resize. We do some funky stuff in // setGeometry_sys. However, resizing it with the mouse or with // a native function call works (it basically has to go through // WM_RESIZE in QApplication). This is a corner case, though. // See task 243708 const QRect frame = topLevel.frameGeometry(); MoveWindow(topLevel.winId(), frame.x(), frame.y(), frame.width() + 10, frame.height() + 10, true); #endif #ifdef Q_WS_X11 qt_x11_wait_for_window_manager(&topLevel); #endif QTest::qWait(100); // Expected update region: New rect - old rect. QRegion expectedUpdateRegion(topLevel.rect()); expectedUpdateRegion -= QRect(QPoint(), topLevel.size() - QSize(10, 10)); QCOMPARE(topLevel.gotPaintEvent, true); QCOMPARE(topLevel.partial, true); QCOMPARE(topLevel.paintedRegion, expectedUpdateRegion); } class SiblingDeleter : public QWidget { public: inline SiblingDeleter(QWidget *sibling, QWidget *parent) : QWidget(parent), sibling(sibling) {} inline virtual ~SiblingDeleter() { delete sibling; } private: QPointer sibling; }; void tst_QWidget::childDeletesItsSibling() { QWidget *commonParent = new QWidget(0); QPointer child = new QWidget(0); QPointer siblingDeleter = new SiblingDeleter(child, commonParent); child->setParent(commonParent); delete commonParent; // don't crash QVERIFY(!child); QVERIFY(!siblingDeleter); } #ifdef Q_WS_QWS # define SET_SAFE_SIZE(w) \ do { \ QSize safeSize(qt_screen->width() - 250, qt_screen->height() - 250); \ if (!safeSize.isValid()) \ QSKIP("Screen size too small", SkipAll); \ if (defaultSize.width() > safeSize.width() || defaultSize.height() > safeSize.height()) { \ defaultSize = safeSize; \ w.resize(defaultSize); \ w.setAttribute(Qt::WA_Resized, false); \ } \ } while (false) #else # define SET_SAFE_SIZE(w) #endif void tst_QWidget::setMinimumSize() { QWidget w; QSize defaultSize = w.size(); SET_SAFE_SIZE(w); w.setMinimumSize(defaultSize + QSize(100, 100)); QCOMPARE(w.size(), defaultSize + QSize(100, 100)); QVERIFY(!w.testAttribute(Qt::WA_Resized)); w.setMinimumSize(defaultSize + QSize(50, 50)); QCOMPARE(w.size(), defaultSize + QSize(100, 100)); QVERIFY(!w.testAttribute(Qt::WA_Resized)); w.setMinimumSize(defaultSize + QSize(200, 200)); QCOMPARE(w.size(), defaultSize + QSize(200, 200)); QVERIFY(!w.testAttribute(Qt::WA_Resized)); #ifdef Q_OS_WINCE QSKIP("Setting a minimum size larger than the desktop does not work", SkipAll); #endif QSize nonDefaultSize = defaultSize + QSize(5,5); w.setMinimumSize(nonDefaultSize); w.show(); QTest::qWait(50); QVERIFY(w.height() >= nonDefaultSize.height()); QVERIFY(w.width() >= nonDefaultSize.width()); } void tst_QWidget::setMaximumSize() { QWidget w; QSize defaultSize = w.size(); SET_SAFE_SIZE(w); w.setMinimumSize(defaultSize + QSize(100, 100)); QCOMPARE(w.size(), defaultSize + QSize(100, 100)); QVERIFY(!w.testAttribute(Qt::WA_Resized)); w.setMinimumSize(defaultSize); w.setMaximumSize(defaultSize + QSize(200, 200)); QCOMPARE(w.size(), defaultSize + QSize(100, 100)); QVERIFY(!w.testAttribute(Qt::WA_Resized)); w.setMaximumSize(defaultSize + QSize(50, 50)); QCOMPARE(w.size(), defaultSize + QSize(50, 50)); QVERIFY(!w.testAttribute(Qt::WA_Resized)); #if 0 //we don't enforce maximum size on show, apparently QSize nonDefaultSize = defaultSize - QSize(5,5); w.setMaximumSize(nonDefaultSize); w.show(); QTest::qWait(50); qDebug() << nonDefaultSize << w.size(); QVERIFY(w.height() <= nonDefaultSize.height()); QVERIFY(w.width() <= nonDefaultSize.width()); #endif } void tst_QWidget::setFixedSize() { QWidget w; QSize defaultSize = w.size(); SET_SAFE_SIZE(w); w.setFixedSize(defaultSize + QSize(100, 100)); QCOMPARE(w.size(), defaultSize + QSize(100, 100)); QVERIFY(w.testAttribute(Qt::WA_Resized)); w.setFixedSize(defaultSize + QSize(200, 200)); QCOMPARE(w.minimumSize(), defaultSize + QSize(200,200)); QCOMPARE(w.maximumSize(), defaultSize + QSize(200,200)); QCOMPARE(w.size(), defaultSize + QSize(200, 200)); QVERIFY(w.testAttribute(Qt::WA_Resized)); w.setFixedSize(defaultSize + QSize(50, 50)); QCOMPARE(w.size(), defaultSize + QSize(50, 50)); QVERIFY(w.testAttribute(Qt::WA_Resized)); w.setAttribute(Qt::WA_Resized, false); w.setFixedSize(defaultSize + QSize(50, 50)); QVERIFY(!w.testAttribute(Qt::WA_Resized)); w.setFixedSize(defaultSize + QSize(150, 150)); w.show(); QTest::qWait(50); QVERIFY(w.size() == defaultSize + QSize(150,150)); } void tst_QWidget::ensureCreated() { { QWidget widget; WId widgetWinId = widget.winId(); Q_UNUSED(widgetWinId); QVERIFY(widget.testAttribute(Qt::WA_WState_Created)); } { QWidget window; QDialog dialog(&window); dialog.setWindowModality(Qt::NonModal); WId dialogWinId = dialog.winId(); Q_UNUSED(dialogWinId); QVERIFY(dialog.testAttribute(Qt::WA_WState_Created)); QVERIFY(window.testAttribute(Qt::WA_WState_Created)); } { QWidget window; QDialog dialog(&window); dialog.setWindowModality(Qt::WindowModal); WId dialogWinId = dialog.winId(); Q_UNUSED(dialogWinId); QVERIFY(dialog.testAttribute(Qt::WA_WState_Created)); QVERIFY(window.testAttribute(Qt::WA_WState_Created)); } { QWidget window; QDialog dialog(&window); dialog.setWindowModality(Qt::ApplicationModal); WId dialogWinId = dialog.winId(); Q_UNUSED(dialogWinId); QVERIFY(dialog.testAttribute(Qt::WA_WState_Created)); QVERIFY(window.testAttribute(Qt::WA_WState_Created)); } } void tst_QWidget::persistentWinId() { QWidget *parent = new QWidget; QWidget *w1 = new QWidget; QWidget *w2 = new QWidget; QWidget *w3 = new QWidget; w1->setParent(parent); w2->setParent(w1); w3->setParent(w2); WId winId1 = w1->winId(); WId winId2 = w2->winId(); WId winId3 = w3->winId(); // reparenting should change the winId of the widget being reparented, but not of its children w1->setParent(0); QVERIFY(w1->winId() != winId1); winId1 = w1->winId(); QCOMPARE(w2->winId(), winId2); QCOMPARE(w3->winId(), winId3); w1->setParent(parent); QVERIFY(w1->winId() != winId1); winId1 = w1->winId(); QCOMPARE(w2->winId(), winId2); QCOMPARE(w3->winId(), winId3); w2->setParent(0); QVERIFY(w2->winId() != winId2); winId2 = w2->winId(); QCOMPARE(w3->winId(), winId3); w2->setParent(parent); QVERIFY(w2->winId() != winId2); winId2 = w2->winId(); QCOMPARE(w3->winId(), winId3); w2->setParent(w1); QVERIFY(w2->winId() != winId2); winId2 = w2->winId(); QCOMPARE(w3->winId(), winId3); w3->setParent(0); QVERIFY(w3->winId() != winId3); winId3 = w3->winId(); w3->setParent(w1); QVERIFY(w3->winId() != winId3); winId3 = w3->winId(); w3->setParent(w2); QVERIFY(w3->winId() != winId3); winId3 = w3->winId(); delete parent; } class ShowHideEventWidget : public QWidget { public: int numberOfShowEvents, numberOfHideEvents; ShowHideEventWidget(QWidget *parent = 0) : QWidget(parent), numberOfShowEvents(0), numberOfHideEvents(0) { } void create() { QWidget::create(); } void showEvent(QShowEvent *) { ++numberOfShowEvents; } void hideEvent(QHideEvent *) { ++numberOfHideEvents; } }; void tst_QWidget::showHideEvent_data() { QTest::addColumn("show"); QTest::addColumn("hide"); QTest::addColumn("create"); QTest::addColumn("expectedShowEvents"); QTest::addColumn("expectedHideEvents"); QTest::newRow("window: only show") << true << false << false << 1 << 0; QTest::newRow("window: show/hide") << true << true << false << 1 << 1; QTest::newRow("window: show/hide/create") << true << true << true << 1 << 1; QTest::newRow("window: hide/create") << false << true << true << 0 << 0; QTest::newRow("window: only hide") << false << true << false << 0 << 0; QTest::newRow("window: nothing") << false << false << false << 0 << 0; } void tst_QWidget::showHideEvent() { QFETCH(bool, show); QFETCH(bool, hide); QFETCH(bool, create); QFETCH(int, expectedShowEvents); QFETCH(int, expectedHideEvents); ShowHideEventWidget widget; if (show) widget.show(); if (hide) widget.hide(); if (create && !widget.testAttribute(Qt::WA_WState_Created)) widget.create(); QCOMPARE(widget.numberOfShowEvents, expectedShowEvents); QCOMPARE(widget.numberOfHideEvents, expectedHideEvents); } void tst_QWidget::update() { QTest::qWait(1000); // Wait for the initStuff to do it's stuff. Q_CHECK_PAINTEVENTS UpdateWidget w; w.setGeometry(50, 50, 100, 100); w.show(); #ifdef Q_WS_X11 qt_x11_wait_for_window_manager(&w); #endif QApplication::processEvents(); QApplication::processEvents(); QCOMPARE(w.numPaintEvents, 1); QCOMPARE(w.visibleRegion(), QRegion(w.rect())); QCOMPARE(w.paintedRegion, w.visibleRegion()); w.reset(); UpdateWidget child(&w); child.setGeometry(10, 10, 80, 80); child.show(); QPoint childOffset = child.mapToParent(QPoint()); // widgets are transparent by default, so both should get repaints { QApplication::processEvents(); QApplication::processEvents(); QCOMPARE(child.numPaintEvents, 1); QCOMPARE(child.visibleRegion(), QRegion(child.rect())); QCOMPARE(child.paintedRegion, child.visibleRegion()); QCOMPARE(w.numPaintEvents, 1); QCOMPARE(w.visibleRegion(), QRegion(w.rect())); #ifdef QT_MAC_USE_COCOA QEXPECT_FAIL(0, "Cocoa compositor paints the content view", Continue); #endif QCOMPARE(w.paintedRegion, child.visibleRegion().translated(childOffset)); w.reset(); child.reset(); w.update(); QApplication::processEvents(); QApplication::processEvents(); QCOMPARE(child.numPaintEvents, 1); QCOMPARE(child.visibleRegion(), QRegion(child.rect())); QCOMPARE(child.paintedRegion, child.visibleRegion()); QCOMPARE(w.numPaintEvents, 1); QCOMPARE(w.visibleRegion(), QRegion(w.rect())); QCOMPARE(w.paintedRegion, w.visibleRegion()); } QPalette opaquePalette = child.palette(); opaquePalette.setColor(child.backgroundRole(), QColor(Qt::red)); // setting an opaque background on the child should prevent paint-events // for the parent in the child area { child.setPalette(opaquePalette); child.setAutoFillBackground(true); QApplication::processEvents(); w.reset(); child.reset(); w.update(); QApplication::processEvents(); QApplication::processEvents(); QCOMPARE(w.numPaintEvents, 1); QRegion expectedVisible = QRegion(w.rect()) - child.visibleRegion().translated(childOffset); QCOMPARE(w.visibleRegion(), expectedVisible); #ifdef QT_MAC_USE_COCOA QEXPECT_FAIL(0, "Cocoa compositor paints the content view", Continue); #endif QCOMPARE(w.paintedRegion, expectedVisible); #ifdef QT_MAC_USE_COCOA QEXPECT_FAIL(0, "Cocoa compositor says to paint this.", Continue); #endif QCOMPARE(child.numPaintEvents, 0); w.reset(); child.reset(); child.update(); QApplication::processEvents(); QApplication::processEvents(); QCOMPARE(w.numPaintEvents, 0); QCOMPARE(child.numPaintEvents, 1); QCOMPARE(child.paintedRegion, child.visibleRegion()); w.reset(); child.reset(); } // overlapping sibling UpdateWidget sibling(&w); child.setGeometry(10, 10, 20, 20); sibling.setGeometry(15, 15, 20, 20); sibling.show(); QApplication::processEvents(); w.reset(); child.reset(); sibling.reset(); const QPoint siblingOffset = sibling.mapToParent(QPoint()); sibling.update(); QApplication::processEvents(); QApplication::processEvents(); // child is opaque, sibling transparent { QCOMPARE(sibling.numPaintEvents, 1); QCOMPARE(sibling.paintedRegion, sibling.visibleRegion()); QCOMPARE(child.numPaintEvents, 1); QCOMPARE(child.paintedRegion.translated(childOffset), child.visibleRegion().translated(childOffset) & sibling.visibleRegion().translated(siblingOffset)); QCOMPARE(w.numPaintEvents, 1); #ifdef QT_MAC_USE_COCOA QEXPECT_FAIL(0, "Cocoa compositor paints the content view", Continue); #endif QCOMPARE(w.paintedRegion, w.visibleRegion() & sibling.visibleRegion().translated(siblingOffset)); #ifdef QT_MAC_USE_COCOA QEXPECT_FAIL(0, "Cocoa compositor paints the content view", Continue); #endif QCOMPARE(w.paintedRegion, (w.visibleRegion() - child.visibleRegion().translated(childOffset)) & sibling.visibleRegion().translated(siblingOffset)); } w.reset(); child.reset(); sibling.reset(); sibling.setPalette(opaquePalette); sibling.setAutoFillBackground(true); sibling.update(); QApplication::processEvents(); QApplication::processEvents(); // child opaque, sibling opaque { QCOMPARE(sibling.numPaintEvents, 1); QCOMPARE(sibling.paintedRegion, sibling.visibleRegion()); #ifdef QT_MAC_USE_COCOA QEXPECT_FAIL(0, "Cocoa compositor paints child and sibling", Continue); #endif QCOMPARE(child.numPaintEvents, 0); QCOMPARE(child.visibleRegion(), QRegion(child.rect()) - sibling.visibleRegion().translated(siblingOffset - childOffset)); QCOMPARE(w.numPaintEvents, 0); QCOMPARE(w.visibleRegion(), QRegion(w.rect()) - child.visibleRegion().translated(childOffset) - sibling.visibleRegion().translated(siblingOffset)); } } static inline bool isOpaque(QWidget *widget) { if (!widget) return false; return qt_widget_private(widget)->isOpaque; } void tst_QWidget::isOpaque() { #ifndef Q_WS_MAC QWidget w; QVERIFY(::isOpaque(&w)); QWidget child(&w); QVERIFY(!::isOpaque(&child)); child.setAutoFillBackground(true); QVERIFY(::isOpaque(&child)); QPalette palette; // background color palette = child.palette(); palette.setColor(child.backgroundRole(), QColor(255, 0, 0, 127)); child.setPalette(palette); QVERIFY(!::isOpaque(&child)); palette.setColor(child.backgroundRole(), QColor(255, 0, 0, 255)); child.setPalette(palette); QVERIFY(::isOpaque(&child)); palette.setColor(QPalette::Window, QColor(0, 0, 255, 127)); w.setPalette(palette); QVERIFY(!::isOpaque(&w)); child.setAutoFillBackground(false); QVERIFY(!::isOpaque(&child)); // Qt::WA_OpaquePaintEvent child.setAttribute(Qt::WA_OpaquePaintEvent); QVERIFY(::isOpaque(&child)); child.setAttribute(Qt::WA_OpaquePaintEvent, false); QVERIFY(!::isOpaque(&child)); // Qt::WA_NoSystemBackground child.setAttribute(Qt::WA_NoSystemBackground); QVERIFY(!::isOpaque(&child)); child.setAttribute(Qt::WA_NoSystemBackground, false); QVERIFY(!::isOpaque(&child)); palette.setColor(QPalette::Window, QColor(0, 0, 255, 255)); w.setPalette(palette); QVERIFY(::isOpaque(&w)); w.setAttribute(Qt::WA_NoSystemBackground); QVERIFY(!::isOpaque(&w)); w.setAttribute(Qt::WA_NoSystemBackground, false); QVERIFY(::isOpaque(&w)); { QPalette palette = QApplication::palette(); QPalette old = palette; palette.setColor(QPalette::Window, Qt::transparent); QApplication::setPalette(palette); QWidget widget; QVERIFY(!::isOpaque(&widget)); QApplication::setPalette(old); QCOMPARE(::isOpaque(&widget), old.color(QPalette::Window).alpha() == 255); } #endif } #ifndef Q_WS_MAC /* Test that scrolling of a widget invalidates the correct regions */ void tst_QWidget::scroll() { UpdateWidget updateWidget; updateWidget.resize(500, 500); updateWidget.show(); #ifdef Q_WS_X11 qt_x11_wait_for_window_manager(&updateWidget); #elif defined(Q_WS_QWS) QTest::qWait(50); #endif qApp->processEvents(); { updateWidget.reset(); updateWidget.scroll(10, 10); qApp->processEvents(); QRegion dirty(QRect(0, 0, 500, 10)); dirty += QRegion(QRect(0, 10, 10, 490)); QCOMPARE(updateWidget.paintedRegion, dirty); } { updateWidget.reset(); updateWidget.update(0, 0, 10, 10); updateWidget.scroll(0, 10); qApp->processEvents(); QRegion dirty(QRect(0, 0, 500, 10)); dirty += QRegion(QRect(0, 10, 10, 10)); QCOMPARE(updateWidget.paintedRegion, dirty); } { updateWidget.reset(); updateWidget.update(0, 0, 100, 100); updateWidget.scroll(10, 10, QRect(50, 50, 100, 100)); qApp->processEvents(); QRegion dirty(QRect(0, 0, 100, 50)); dirty += QRegion(QRect(0, 50, 150, 10)); dirty += QRegion(QRect(0, 60, 110, 40)); dirty += QRegion(QRect(50, 100, 60, 10)); dirty += QRegion(QRect(50, 110, 10, 40)); QCOMPARE(updateWidget.paintedRegion, dirty); } { updateWidget.reset(); updateWidget.update(0, 0, 100, 100); updateWidget.scroll(10, 10, QRect(100, 100, 100, 100)); qApp->processEvents(); QRegion dirty(QRect(0, 0, 100, 100)); dirty += QRegion(QRect(100, 100, 100, 10)); dirty += QRegion(QRect(100, 110, 10, 90)); QCOMPARE(updateWidget.paintedRegion, dirty); } } #endif class DestroyedSlotChecker : public QObject { Q_OBJECT public: bool wasQWidget; DestroyedSlotChecker() : wasQWidget(false) { } public slots: void destroyedSlot(QObject *object) { wasQWidget = (qobject_cast(object) != 0 || object->isWidgetType()); } }; /* Test that qobject_cast returns 0 in a slot connected to QObject::destroyed. */ void tst_QWidget::qobject_castInDestroyedSlot() { DestroyedSlotChecker checker; QWidget *widget = new QWidget(); QObject::connect(widget, SIGNAL(destroyed(QObject *)), &checker, SLOT(destroyedSlot(QObject *))); delete widget; QVERIFY(checker.wasQWidget == true); } Q_DECLARE_METATYPE(QList) void tst_QWidget::setWindowGeometry_data() { QTest::addColumn >("rects"); QTest::addColumn("windowFlags"); QList > rects; rects << (QList() << QRect(100, 100, 200, 200) << QApplication::desktop()->availableGeometry().adjusted(100, 100, -100, -100) << QRect(130, 100, 0, 200) << QRect(100, 50, 200, 0) << QRect(130, 50, 0, 0)) << (QList() << QApplication::desktop()->availableGeometry().adjusted(100, 100, -100, -100) << QRect(130, 100, 0, 200) << QRect(100, 50, 200, 0) << QRect(130, 50, 0, 0) << QRect(100, 100, 200, 200)) << (QList() << QRect(130, 100, 0, 200) << QRect(100, 50, 200, 0) << QRect(130, 50, 0, 0) << QRect(100, 100, 200, 200) << QApplication::desktop()->availableGeometry().adjusted(100, 100, -100, -100)) << (QList() << QRect(100, 50, 200, 0) << QRect(130, 50, 0, 0) << QRect(100, 100, 200, 200) << QApplication::desktop()->availableGeometry().adjusted(100, 100, -100, -100) << QRect(130, 100, 0, 200)) << (QList() << QRect(130, 50, 0, 0) << QRect(100, 100, 200, 200) << QApplication::desktop()->availableGeometry().adjusted(100, 100, -100, -100) << QRect(130, 100, 0, 200) << QRect(100, 50, 200, 0)); QList windowFlags; windowFlags << 0 << Qt::FramelessWindowHint #ifdef Q_WS_X11 << Qt::X11BypassWindowManagerHint #endif ; foreach (QList l, rects) { QRect rect = l.first(); foreach (int windowFlag, windowFlags) { QTest::newRow(QString("%1,%2 %3x%4, flags %5") .arg(rect.x()) .arg(rect.y()) .arg(rect.width()) .arg(rect.height()) .arg(windowFlag, 0, 16).toAscii()) << l << windowFlag; } } } void tst_QWidget::setWindowGeometry() { QFETCH(QList, rects); QFETCH(int, windowFlags); QRect rect = rects.takeFirst(); { // test setGeometry() without actually showing the window QWidget widget; if (windowFlags != 0) widget.setWindowFlags(Qt::WindowFlags(windowFlags)); widget.setGeometry(rect); QTest::qWait(100); QCOMPARE(widget.geometry(), rect); // setGeometry() without showing foreach (QRect r, rects) { widget.setGeometry(r); QTest::qWait(100); QCOMPARE(widget.geometry(), r); } } { // setGeometry() first, then show() QWidget widget; if (windowFlags != 0) widget.setWindowFlags(Qt::WindowFlags(windowFlags)); widget.setGeometry(rect); widget.show(); #ifdef Q_WS_X11 qt_x11_wait_for_window_manager(&widget); #endif QTest::qWait(100); QCOMPARE(widget.geometry(), rect); // setGeometry() while shown foreach (QRect r, rects) { widget.setGeometry(r); QTest::qWait(100); QCOMPARE(widget.geometry(), r); } widget.setGeometry(rect); QTest::qWait(100); QCOMPARE(widget.geometry(), rect); // now hide widget.hide(); QTest::qWait(100); QCOMPARE(widget.geometry(), rect); // setGeometry() after hide() foreach (QRect r, rects) { widget.setGeometry(r); QTest::qWait(100); QCOMPARE(widget.geometry(), r); } widget.setGeometry(rect); QTest::qWait(100); QCOMPARE(widget.geometry(), rect); // show() again, geometry() should still be the same widget.show(); #ifdef Q_WS_X11 qt_x11_wait_for_window_manager(&widget); #endif QTest::qWait(100); QCOMPARE(widget.geometry(), rect); // final hide(), again geometry() should be unchanged widget.hide(); QTest::qWait(100); QCOMPARE(widget.geometry(), rect); } { // show() first, then setGeometry() QWidget widget; if (windowFlags != 0) widget.setWindowFlags(Qt::WindowFlags(windowFlags)); widget.show(); #ifdef Q_WS_X11 qt_x11_wait_for_window_manager(&widget); #endif widget.setGeometry(rect); QTest::qWait(100); QCOMPARE(widget.geometry(), rect); // setGeometry() while shown foreach (QRect r, rects) { widget.setGeometry(r); QTest::qWait(100); QCOMPARE(widget.geometry(), r); } widget.setGeometry(rect); QTest::qWait(100); QCOMPARE(widget.geometry(), rect); // now hide widget.hide(); QTest::qWait(100); QCOMPARE(widget.geometry(), rect); // setGeometry() after hide() foreach (QRect r, rects) { widget.setGeometry(r); QTest::qWait(100); QCOMPARE(widget.geometry(), r); } widget.setGeometry(rect); QTest::qWait(100); QCOMPARE(widget.geometry(), rect); // show() again, geometry() should still be the same widget.show(); #ifdef Q_WS_X11 qt_x11_wait_for_window_manager(&widget); #endif QTest::qWait(100); QCOMPARE(widget.geometry(), rect); // final hide(), again geometry() should be unchanged widget.hide(); QTest::qWait(100); QCOMPARE(widget.geometry(), rect); } } #if defined (Q_WS_WIN) && !defined(Q_OS_WINCE) void tst_QWidget::setGeometry_win() { QWidget widget; widget.setGeometry(0, 600, 100,100); widget.show(); widget.setWindowState(widget.windowState() | Qt::WindowMaximized); QRect geom = widget.normalGeometry(); widget.close(); widget.setGeometry(geom); widget.setWindowState(widget.windowState() | Qt::WindowMaximized); widget.show(); RECT rt; ::GetWindowRect(widget.internalWinId(), &rt); QVERIFY(rt.left <= 0); QVERIFY(rt.top <= 0); } #endif void tst_QWidget::windowMoveResize_data() { setWindowGeometry_data(); } void tst_QWidget::windowMoveResize() { #ifdef Q_OS_IRIX QSKIP("4DWM issues on IRIX makes this test fail", SkipAll); #endif QFETCH(QList, rects); QFETCH(int, windowFlags); QRect rect = rects.takeFirst(); { // test setGeometry() without actually showing the window QWidget widget; if (windowFlags != 0) widget.setWindowFlags(Qt::WindowFlags(windowFlags)); widget.move(rect.topLeft()); widget.resize(rect.size()); QTest::qWait(100); QCOMPARE(widget.pos(), rect.topLeft()); QCOMPARE(widget.size(), rect.size()); // move() without showing foreach (QRect r, rects) { widget.move(r.topLeft()); widget.resize(r.size()); QTest::qWait(100); QCOMPARE(widget.pos(), r.topLeft()); QCOMPARE(widget.size(), r.size()); } } { // move() first, then show() QWidget widget; if (windowFlags != 0) widget.setWindowFlags(Qt::WindowFlags(windowFlags)); widget.move(rect.topLeft()); widget.resize(rect.size()); widget.show(); #ifdef Q_WS_X11 qt_x11_wait_for_window_manager(&widget); #endif QTest::qWait(100); #if defined(Q_WS_MAC) && !defined(QT_MAC_USE_COCOA) QEXPECT_FAIL("130,50 0x0, flags 0", "Showing a window with 0x0 size shifts it up.", Continue); #endif QCOMPARE(widget.pos(), rect.topLeft()); QCOMPARE(widget.size(), rect.size()); // move() while shown foreach (QRect r, rects) { #ifdef Q_WS_X11 if ((widget.width() == 0 || widget.height() == 0) && r.width() != 0 && r.height() != 0) { QEXPECT_FAIL("130,100 0x200, flags 0", "First resize after show of zero-sized gets wrong win_gravity.", Continue); QEXPECT_FAIL("100,50 200x0, flags 0", "First resize after show of zero-sized gets wrong win_gravity.", Continue); QEXPECT_FAIL("130,50 0x0, flags 0", "First resize after show of zero-sized gets wrong win_gravity.", Continue); } #endif widget.move(r.topLeft()); widget.resize(r.size()); QTest::qWait(100); QCOMPARE(widget.pos(), r.topLeft()); QCOMPARE(widget.size(), r.size()); } widget.move(rect.topLeft()); widget.resize(rect.size()); QTest::qWait(100); QCOMPARE(widget.pos(), rect.topLeft()); QCOMPARE(widget.size(), rect.size()); // now hide widget.hide(); QTest::qWait(100); #if defined (Q_WS_MAC) && defined(QT_MAC_USE_COCOA) QEXPECT_FAIL("130,100 0x200, flags 800", "Cocoa's Delegate sends a spurios move event when the window has a width of zero and non-zero height", Abort); QEXPECT_FAIL("130,100 0x200, flags 0", "Cocoa's Delegate sends a spurios move event when the window has a width of zero and non-zero height", Abort); #endif QCOMPARE(widget.pos(), rect.topLeft()); QCOMPARE(widget.size(), rect.size()); // move() after hide() foreach (QRect r, rects) { widget.move(r.topLeft()); widget.resize(r.size()); QTest::qWait(1000); #if defined(Q_WS_MAC) && defined(QT_MAC_USE_COCOA) if (r.width() == 0 && r.height() > 0) { widget.move(r.topLeft()); widget.resize(r.size()); } #endif QCOMPARE(widget.pos(), r.topLeft()); QCOMPARE(widget.size(), r.size()); } widget.move(rect.topLeft()); widget.resize(rect.size()); QTest::qWait(100); QCOMPARE(widget.pos(), rect.topLeft()); QCOMPARE(widget.size(), rect.size()); // show() again, pos() should be the same widget.show(); #ifdef Q_WS_X11 qt_x11_wait_for_window_manager(&widget); #endif QTest::qWait(100); QCOMPARE(widget.pos(), rect.topLeft()); QCOMPARE(widget.size(), rect.size()); // final hide(), again pos() should be unchanged widget.hide(); QTest::qWait(100); QCOMPARE(widget.pos(), rect.topLeft()); QCOMPARE(widget.size(), rect.size()); } { // show() first, then move() QWidget widget; if (windowFlags != 0) widget.setWindowFlags(Qt::WindowFlags(windowFlags)); widget.show(); #ifdef Q_WS_X11 qt_x11_wait_for_window_manager(&widget); #endif widget.move(rect.topLeft()); widget.resize(rect.size()); QTest::qWait(100); QCOMPARE(widget.pos(), rect.topLeft()); QCOMPARE(widget.size(), rect.size()); // move() while shown foreach (QRect r, rects) { widget.move(r.topLeft()); widget.resize(r.size()); QTest::qWait(100); QCOMPARE(widget.pos(), r.topLeft()); QCOMPARE(widget.size(), r.size()); } widget.move(rect.topLeft()); widget.resize(rect.size()); QTest::qWait(100); QCOMPARE(widget.pos(), rect.topLeft()); QCOMPARE(widget.size(), rect.size()); // now hide widget.hide(); QTest::qWait(100); QCOMPARE(widget.pos(), rect.topLeft()); QCOMPARE(widget.size(), rect.size()); // move() after hide() foreach (QRect r, rects) { widget.move(r.topLeft()); widget.resize(r.size()); QTest::qWait(100); #if defined(Q_WS_MAC) && defined(QT_MAC_USE_COCOA) if (r.width() == 0 && r.height() > 0) { widget.move(r.topLeft()); widget.resize(r.size()); } #endif QCOMPARE(widget.pos(), r.topLeft()); QCOMPARE(widget.size(), r.size()); } widget.move(rect.topLeft()); widget.resize(rect.size()); QTest::qWait(100); QCOMPARE(widget.pos(), rect.topLeft()); QCOMPARE(widget.size(), rect.size()); // show() again, pos() should be the same widget.show(); #ifdef Q_WS_X11 qt_x11_wait_for_window_manager(&widget); #endif QTest::qWait(100); QCOMPARE(widget.pos(), rect.topLeft()); QCOMPARE(widget.size(), rect.size()); // final hide(), again pos() should be unchanged widget.hide(); QTest::qWait(100); QCOMPARE(widget.pos(), rect.topLeft()); QCOMPARE(widget.size(), rect.size()); } } class ColorWidget : public QWidget { public: ColorWidget(QWidget *parent = 0, const QColor &c = QColor(Qt::red)) : QWidget(parent, Qt::FramelessWindowHint), color(c) { QPalette opaquePalette = palette(); opaquePalette.setColor(backgroundRole(), color); setPalette(opaquePalette); setAutoFillBackground(true); } void paintEvent(QPaintEvent *e) { r += e->region(); } void reset() { r = QRegion(); } QColor color; QRegion r; }; #define VERIFY_COLOR(region, color) { \ const QRegion r = QRegion(region); \ for (int i = 0; i < r.rects().size(); ++i) { \ const QRect rect = r.rects().at(i); \ const QPixmap pixmap = QPixmap::grabWindow(QDesktopWidget().winId(), \ rect.left(), rect.top(), \ rect.width(), rect.height()); \ QCOMPARE(pixmap.size(), rect.size()); \ QPixmap expectedPixmap(pixmap); /* ensure equal formats */ \ expectedPixmap.fill(color); \ QCOMPARE(pixmap, expectedPixmap); \ } \ } void tst_QWidget::moveChild_data() { QTest::addColumn("offset"); QTest::newRow("right") << QPoint(20, 0); QTest::newRow("down") << QPoint(0, 20); QTest::newRow("left") << QPoint(-20, 0); QTest::newRow("up") << QPoint(0, -20); } void tst_QWidget::moveChild() { QFETCH(QPoint, offset); ColorWidget parent; ColorWidget child(&parent, Qt::blue); #ifndef Q_OS_WINCE parent.setGeometry(QRect(QPoint(QApplication::desktop()->availableGeometry(&parent).topLeft()), QSize(100, 100))); #else parent.setGeometry(60, 60, 150, 150); #endif child.setGeometry(25, 25, 50, 50); QPoint childOffset = child.mapToGlobal(QPoint()); parent.show(); QTest::qWait(1000); const QPoint tlwOffset = parent.geometry().topLeft(); #ifdef QT_MAC_USE_COCOA QEXPECT_FAIL(0, "Cocoa compositor paints the entire content view, even when opaque", Continue); #endif QCOMPARE(parent.r, QRegion(parent.rect()) - child.geometry()); QCOMPARE(child.r, QRegion(child.rect())); VERIFY_COLOR(child.geometry().translated(tlwOffset), child.color); VERIFY_COLOR(QRegion(parent.geometry()) - child.geometry().translated(tlwOffset), parent.color); parent.reset(); child.reset(); // move const QRect oldGeometry = child.geometry(); QPoint pos = child.pos() + offset; child.move(pos); QTest::qWait(1000); QCOMPARE(pos, child.pos()); QCOMPARE(parent.r, QRegion(oldGeometry) - child.geometry()); #ifndef Q_WS_MAC // should be scrolled in backingstore QCOMPARE(child.r, QRegion()); #endif VERIFY_COLOR(child.geometry().translated(tlwOffset), child.color); VERIFY_COLOR(QRegion(parent.geometry()) - child.geometry().translated(tlwOffset), parent.color); } void tst_QWidget::subtractOpaqueSiblings() { #ifdef QT_MAC_USE_COCOA QSKIP("Cocoa only has rect granularity.", SkipAll); #else QWidget w; w.setGeometry(50, 50, 300, 300); ColorWidget *large = new ColorWidget(&w, Qt::red); large->setGeometry(50, 50, 200, 200); ColorWidget *medium = new ColorWidget(large, Qt::gray); medium->setGeometry(50, 50, 100, 100); ColorWidget *tall = new ColorWidget(&w, Qt::blue); tall->setGeometry(100, 30, 50, 100); w.show(); QTest::qWait(1000); large->reset(); medium->reset(); tall->reset(); medium->update(); QTest::qWait(1000); // QWidgetPrivate::subtractOpaqueSiblings() should prevent parts of medium // to be repainted and tall from be repainted at all. QCOMPARE(large->r, QRegion()); QCOMPARE(tall->r, QRegion()); QCOMPARE(medium->r.translated(medium->mapTo(&w, QPoint())), QRegion(medium->geometry().translated(large->pos())) - tall->geometry()); #endif } void tst_QWidget::deleteStyle() { QWidget widget; widget.setStyle(new QWindowsStyle); widget.show(); delete widget.style(); qApp->processEvents(); } #ifdef Q_WS_WIN void tst_QWidget::getDC() { QWidget widget; widget.setGeometry(0, 0, 2, 4); HDC dc = widget.getDC(); QVERIFY(dc != 0); widget.releaseDC(dc); } #endif class TopLevelFocusCheck: public QWidget { Q_OBJECT public: QLineEdit* edit; TopLevelFocusCheck(QWidget* parent = 0) : QWidget(parent) { edit = new QLineEdit(this); edit->hide(); edit->installEventFilter(this); } public slots: void mouseDoubleClickEvent ( QMouseEvent * /*event*/ ) { edit->show(); edit->setFocus(Qt::OtherFocusReason); qApp->processEvents(); } bool eventFilter(QObject *obj, QEvent *event) { if (obj == edit && event->type()== QEvent::FocusOut) { edit->hide(); return true; } return false; } }; void tst_QWidget::multipleToplevelFocusCheck() { TopLevelFocusCheck w1; TopLevelFocusCheck w2; w1.resize(200, 200); w1.show(); w2.resize(200,200); w2.show(); #ifdef Q_WS_X11 qt_x11_wait_for_window_manager(&w1); qt_x11_wait_for_window_manager(&w2); #endif QTest::qWait(100); w1.activateWindow(); QApplication::setActiveWindow(&w1); QApplication::processEvents(); QTest::mouseDClick(&w1, Qt::LeftButton); QCOMPARE(QApplication::focusWidget(), static_cast(w1.edit)); w2.activateWindow(); QApplication::setActiveWindow(&w2); QApplication::processEvents(); QTest::mouseClick(&w2, Qt::LeftButton); #ifdef Q_WS_QWS QEXPECT_FAIL("", "embedded toplevels take focus anyway", Continue); #endif QCOMPARE(QApplication::focusWidget(), (QWidget *)0); QTest::mouseDClick(&w2, Qt::LeftButton); QCOMPARE(QApplication::focusWidget(), static_cast(w2.edit)); w1.activateWindow(); QApplication::setActiveWindow(&w1); QApplication::processEvents(); QTest::mouseDClick(&w1, Qt::LeftButton); QCOMPARE(QApplication::focusWidget(), static_cast(w1.edit)); w2.activateWindow(); QApplication::setActiveWindow(&w2); QApplication::processEvents(); QTest::mouseClick(&w2, Qt::LeftButton); QCOMPARE(QApplication::focusWidget(), (QWidget *)0); } void tst_QWidget::setFocus() { { // move focus to another window testWidget->activateWindow(); QApplication::setActiveWindow(testWidget); if (testWidget->focusWidget()) testWidget->focusWidget()->clearFocus(); else testWidget->clearFocus(); // window and children never shown, nobody gets focus QWidget window; QWidget child1(&window); child1.setFocusPolicy(Qt::StrongFocus); QWidget child2(&window); child2.setFocusPolicy(Qt::StrongFocus); child1.setFocus(); QVERIFY(!child1.hasFocus()); QCOMPARE(window.focusWidget(), &child1); QCOMPARE(QApplication::focusWidget(), static_cast(0)); child2.setFocus(); QVERIFY(!child2.hasFocus()); QCOMPARE(window.focusWidget(), &child2); QCOMPARE(QApplication::focusWidget(), static_cast(0)); } { // window and children show, but window not active, nobody gets focus QWidget window; QWidget child1(&window); child1.setFocusPolicy(Qt::StrongFocus); QWidget child2(&window); child2.setFocusPolicy(Qt::StrongFocus); window.show(); // note: window may be active, but we don't want it to be testWidget->activateWindow(); QApplication::setActiveWindow(testWidget); if (testWidget->focusWidget()) testWidget->focusWidget()->clearFocus(); else testWidget->clearFocus(); child1.setFocus(); QVERIFY(!child1.hasFocus()); QCOMPARE(window.focusWidget(), &child1); QCOMPARE(QApplication::focusWidget(), static_cast(0)); child2.setFocus(); QVERIFY(!child2.hasFocus()); QCOMPARE(window.focusWidget(), &child2); QCOMPARE(QApplication::focusWidget(), static_cast(0)); } { // window and children show, but window *is* active, children get focus QWidget window; QWidget child1(&window); child1.setFocusPolicy(Qt::StrongFocus); QWidget child2(&window); child2.setFocusPolicy(Qt::StrongFocus); window.show(); #ifdef Q_WS_X11 qt_x11_wait_for_window_manager(testWidget); QApplication::setActiveWindow(&window); #else window.activateWindow(); QApplication::processEvents(); #endif child1.setFocus(); QVERIFY(child1.hasFocus()); QCOMPARE(window.focusWidget(), &child1); QCOMPARE(QApplication::focusWidget(), &child1); child2.setFocus(); QVERIFY(child2.hasFocus()); QCOMPARE(window.focusWidget(), &child2); QCOMPARE(QApplication::focusWidget(), &child2); } { // window shown and active, children created, don't get focus, but get focus when shown QWidget window; window.show(); #ifdef Q_WS_X11 qt_x11_wait_for_window_manager(testWidget); QApplication::setActiveWindow(&window); #else window.activateWindow(); #endif QWidget child1(&window); child1.setFocusPolicy(Qt::StrongFocus); QWidget child2(&window); child2.setFocusPolicy(Qt::StrongFocus); child1.setFocus(); QVERIFY(!child1.hasFocus()); QCOMPARE(window.focusWidget(), static_cast(0)); QCOMPARE(QApplication::focusWidget(), static_cast(0)); child1.show(); #ifdef Q_WS_X11 qt_x11_wait_for_window_manager(&child1); QApplication::setActiveWindow(&child1); child1.activateWindow(); #endif QApplication::processEvents(); QVERIFY(child1.hasFocus()); QCOMPARE(window.focusWidget(), &child1); QCOMPARE(QApplication::focusWidget(), &child1); child2.setFocus(); QVERIFY(!child2.hasFocus()); QCOMPARE(window.focusWidget(), &child1); QCOMPARE(QApplication::focusWidget(), &child1); child2.show(); QVERIFY(child2.hasFocus()); QCOMPARE(window.focusWidget(), &child2); QCOMPARE(QApplication::focusWidget(), &child2); } { // window shown and active, children created, don't get focus, // even after setFocus(), hide(), then show() QWidget window; window.show(); #ifdef Q_WS_X11 qt_x11_wait_for_window_manager(testWidget); QApplication::setActiveWindow(&window); #else window.activateWindow(); #endif QWidget child1(&window); child1.setFocusPolicy(Qt::StrongFocus); QWidget child2(&window); child2.setFocusPolicy(Qt::StrongFocus); child1.setFocus(); QVERIFY(!child1.hasFocus()); QCOMPARE(window.focusWidget(), static_cast(0)); QCOMPARE(QApplication::focusWidget(), static_cast(0)); child1.hide(); QVERIFY(!child1.hasFocus()); QCOMPARE(window.focusWidget(), static_cast(0)); QCOMPARE(QApplication::focusWidget(), static_cast(0)); child1.show(); QVERIFY(!child1.hasFocus()); QCOMPARE(window.focusWidget(), static_cast(0)); QCOMPARE(QApplication::focusWidget(), static_cast(0)); child2.setFocus(); QVERIFY(!child2.hasFocus()); QCOMPARE(window.focusWidget(), static_cast(0)); QCOMPARE(QApplication::focusWidget(), static_cast(0)); child2.hide(); QVERIFY(!child2.hasFocus()); QCOMPARE(window.focusWidget(), static_cast(0)); QCOMPARE(QApplication::focusWidget(), static_cast(0)); child2.show(); QVERIFY(!child2.hasFocus()); QCOMPARE(window.focusWidget(), static_cast(0)); QCOMPARE(QApplication::focusWidget(), static_cast(0)); } } class EventSpy : public QObject { public: EventSpy(QWidget *widget, QEvent::Type event) : m_widget(widget), eventToSpy(event), m_count(0) { if (m_widget) m_widget->installEventFilter(this); } QWidget *widget() const { return m_widget; } int count() const { return m_count; } void clear() { m_count = 0; } protected: bool eventFilter(QObject *object, QEvent *event) { if (event->type() == eventToSpy) ++m_count; return QObject::eventFilter(object, event); } private: QWidget *m_widget; QEvent::Type eventToSpy; int m_count; }; void tst_QWidget::setCursor() { #ifndef QT_NO_CURSOR { QWidget window; QWidget child(&window); QVERIFY(!window.testAttribute(Qt::WA_SetCursor)); QVERIFY(!child.testAttribute(Qt::WA_SetCursor)); window.setCursor(window.cursor()); QVERIFY(window.testAttribute(Qt::WA_SetCursor)); QVERIFY(!child.testAttribute(Qt::WA_SetCursor)); QCOMPARE(child.cursor().shape(), window.cursor().shape()); } // do it again, but with window show()n { QWidget window; QWidget child(&window); window.show(); QVERIFY(!window.testAttribute(Qt::WA_SetCursor)); QVERIFY(!child.testAttribute(Qt::WA_SetCursor)); window.setCursor(window.cursor()); QVERIFY(window.testAttribute(Qt::WA_SetCursor)); QVERIFY(!child.testAttribute(Qt::WA_SetCursor)); QCOMPARE(child.cursor().shape(), window.cursor().shape()); } { QWidget window; QWidget child(&window); window.setCursor(Qt::WaitCursor); QVERIFY(window.testAttribute(Qt::WA_SetCursor)); QVERIFY(!child.testAttribute(Qt::WA_SetCursor)); QCOMPARE(child.cursor().shape(), window.cursor().shape()); } // same thing again, just with window show()n { QWidget window; QWidget child(&window); window.show(); window.setCursor(Qt::WaitCursor); QVERIFY(window.testAttribute(Qt::WA_SetCursor)); QVERIFY(!child.testAttribute(Qt::WA_SetCursor)); QCOMPARE(child.cursor().shape(), window.cursor().shape()); } // reparenting child should not cause the WA_SetCursor to become set { QWidget window; QWidget window2; QWidget child(&window); window.setCursor(Qt::WaitCursor); child.setParent(0); QVERIFY(!child.testAttribute(Qt::WA_SetCursor)); QCOMPARE(child.cursor().shape(), QCursor().shape()); child.setParent(&window2); QVERIFY(!child.testAttribute(Qt::WA_SetCursor)); QCOMPARE(child.cursor().shape(), window2.cursor().shape()); window2.setCursor(Qt::WaitCursor); QVERIFY(!child.testAttribute(Qt::WA_SetCursor)); QCOMPARE(child.cursor().shape(), window2.cursor().shape()); } // again, with windows show()n { QWidget window; QWidget window2; QWidget child(&window); window.setCursor(Qt::WaitCursor); window.show(); child.setParent(0); QVERIFY(!child.testAttribute(Qt::WA_SetCursor)); QCOMPARE(child.cursor().shape(), QCursor().shape()); child.setParent(&window2); QVERIFY(!child.testAttribute(Qt::WA_SetCursor)); QCOMPARE(child.cursor().shape(), window2.cursor().shape()); window2.show(); window2.setCursor(Qt::WaitCursor); QVERIFY(!child.testAttribute(Qt::WA_SetCursor)); QCOMPARE(child.cursor().shape(), window2.cursor().shape()); } // test if CursorChange is sent { QWidget widget; EventSpy spy(&widget, QEvent::CursorChange); QCOMPARE(spy.count(), 0); widget.setCursor(QCursor(Qt::WaitCursor)); QCOMPARE(spy.count(), 1); widget.unsetCursor(); QCOMPARE(spy.count(), 2); } #endif } void tst_QWidget::setToolTip() { QWidget widget; EventSpy spy(&widget, QEvent::ToolTipChange); QCOMPARE(spy.count(), 0); QCOMPARE(widget.toolTip(), QString()); widget.setToolTip(QString("Hello")); QCOMPARE(widget.toolTip(), QString("Hello")); QCOMPARE(spy.count(), 1); widget.setToolTip(QString()); QCOMPARE(widget.toolTip(), QString()); QCOMPARE(spy.count(), 2); for (int pass = 0; pass < 2; ++pass) { QWidget *popup = new QWidget(0, Qt::Popup); popup->resize(150, 50); QFrame *frame = new QFrame(popup); frame->setGeometry(0, 0, 50, 50); frame->setFrameStyle(QFrame::Box | QFrame::Plain); EventSpy spy1(frame, QEvent::ToolTip); EventSpy spy2(popup, QEvent::ToolTip); frame->setMouseTracking(pass == 0 ? false : true); frame->setToolTip(QLatin1String("TOOLTIP FRAME")); popup->setToolTip(QLatin1String("TOOLTIP POPUP")); popup->show(); #ifdef Q_WS_X11 qt_x11_wait_for_window_manager(popup); #endif QTest::qWait(100); QTest::mouseMove(frame); QTest::qWait(900); // delay is 700 QCOMPARE(spy1.count(), 1); QCOMPARE(spy2.count(), 0); if (pass == 0) QTest::qWait(2200); // delay is 2000 QTest::mouseMove(popup); delete popup; } } void tst_QWidget::testWindowIconChangeEventPropagation() { // Create widget hierarchy. QWidget topLevelWidget; QWidget topLevelChild(&topLevelWidget); QDialog dialog(&topLevelWidget); QWidget dialogChild(&dialog); QWidgetList widgets; widgets << &topLevelWidget << &topLevelChild << &dialog << &dialogChild; QCOMPARE(widgets.count(), 4); // Create spy lists. QList applicationEventSpies; QList widgetEventSpies; foreach (QWidget *widget, widgets) { applicationEventSpies.append(new EventSpy(widget, QEvent::ApplicationWindowIconChange)); widgetEventSpies.append(new EventSpy(widget, QEvent::WindowIconChange)); } // QApplication::setWindowIcon const QIcon windowIcon = qApp->style()->standardIcon(QStyle::SP_TitleBarMenuButton); qApp->setWindowIcon(windowIcon); for (int i = 0; i < widgets.count(); ++i) { // Check QEvent::ApplicationWindowIconChange EventSpy *spy = applicationEventSpies.at(i); QWidget *widget = spy->widget(); if (widget->isWindow()) { QCOMPARE(spy->count(), 1); QCOMPARE(widget->windowIcon(), windowIcon); } else { QCOMPARE(spy->count(), 0); } spy->clear(); // Check QEvent::WindowIconChange spy = widgetEventSpies.at(i); QCOMPARE(spy->count(), 1); spy->clear(); } // Set icon on a top-level widget. topLevelWidget.setWindowIcon(*new QIcon); for (int i = 0; i < widgets.count(); ++i) { // Check QEvent::ApplicationWindowIconChange EventSpy *spy = applicationEventSpies.at(i); QCOMPARE(spy->count(), 0); spy->clear(); // Check QEvent::WindowIconChange spy = widgetEventSpies.at(i); QWidget *widget = spy->widget(); if (widget == &topLevelWidget) { QCOMPARE(widget->windowIcon(), QIcon()); QCOMPARE(spy->count(), 1); } else if (topLevelWidget.isAncestorOf(widget)) { QCOMPARE(spy->count(), 1); } else { QCOMPARE(spy->count(), 0); } spy->clear(); } // Cleanup. for (int i = 0; i < widgets.count(); ++i) { delete applicationEventSpies.at(i); delete widgetEventSpies.at(i); } qApp->setWindowIcon(QIcon()); } #ifdef Q_WS_X11 void tst_QWidget::minAndMaxSizeWithX11BypassWindowManagerHint() { // Same size as in QWidget::create_sys(). const QSize desktopSize = QApplication::desktop()->size(); const QSize originalSize(desktopSize.width() / 2, desktopSize.height() * 4 / 10); { // Maximum size. QWidget widget(0, Qt::X11BypassWindowManagerHint); const QSize newMaximumSize = widget.size().boundedTo(originalSize) - QSize(10, 10); widget.setMaximumSize(newMaximumSize); QCOMPARE(widget.size(), newMaximumSize); widget.show(); qt_x11_wait_for_window_manager(&widget); QCOMPARE(widget.size(), newMaximumSize); } { // Minimum size. QWidget widget(0, Qt::X11BypassWindowManagerHint); const QSize newMinimumSize = widget.size().expandedTo(originalSize) + QSize(10, 10); widget.setMinimumSize(newMinimumSize); QCOMPARE(widget.size(), newMinimumSize); widget.show(); qt_x11_wait_for_window_manager(&widget); QCOMPARE(widget.size(), newMinimumSize); } } class ShowHideShowWidget : public QWidget { Q_OBJECT int state; public: bool gotExpectedMapNotify; ShowHideShowWidget() : state(0), gotExpectedMapNotify(false) { startTimer(1000); } void timerEvent(QTimerEvent *) { switch (state++) { case 0: show(); break; case 1: emit done(); break; } } bool x11Event(XEvent *event) { if (state == 1 && event->type == MapNotify) gotExpectedMapNotify = true; return false; } signals: void done(); }; void tst_QWidget::showHideShow() { ShowHideShowWidget w; w.show(); w.hide(); QEventLoop eventLoop; connect(&w, SIGNAL(done()), &eventLoop, SLOT(quit())); eventLoop.exec(); QVERIFY(w.gotExpectedMapNotify); } #endif class EventRecorder : public QObject { Q_OBJECT public: typedef QList > EventList; EventRecorder(QObject *parent = 0) : QObject(parent) { } EventList eventList() { return events; } void clear() { events.clear(); } bool eventFilter(QObject *object, QEvent *event) { QWidget *widget = qobject_cast(object); if (widget && !event->spontaneous()) events.append(qMakePair(widget, event->type())); return false; } private: EventList events; }; void tst_QWidget::compatibilityChildInsertedEvents() { EventRecorder::EventList expected; bool accessibilityEnabled = false; #if defined(Q_WS_MAC) && !defined(QT_MAC_USE_COCOA) accessibilityEnabled = AXAPIEnabled(); #endif // Move away the cursor; otherwise it might result in an enter event if it's // inside the widget when the widget is shown. QCursor::setPos(qApp->desktop()->availableGeometry().bottomRight()); QTest::qWait(100); { // no children created, not shown QWidget widget; EventRecorder spy; widget.installEventFilter(&spy); QCoreApplication::postEvent(&widget, new QEvent(QEvent::Type(QEvent::User + 1))); QCoreApplication::sendPostedEvents(); expected = EventRecorder::EventList() << qMakePair(&widget, QEvent::PolishRequest) << qMakePair(&widget, QEvent::Polish) << qMakePair(&widget, QEvent::Type(QEvent::User + 1)); QCOMPARE(spy.eventList(), expected); } { // no children, shown QWidget widget; EventRecorder spy; widget.installEventFilter(&spy); QCoreApplication::postEvent(&widget, new QEvent(QEvent::Type(QEvent::User + 1))); widget.show(); expected = EventRecorder::EventList() << qMakePair(&widget, QEvent::Polish) << qMakePair(&widget, QEvent::Move) << qMakePair(&widget, QEvent::Resize) << qMakePair(&widget, QEvent::Show); if (accessibilityEnabled) expected << qMakePair(&widget, QEvent::AccessibilityPrepare); expected << qMakePair(&widget, QEvent::ShowToParent); QCOMPARE(spy.eventList(), expected); spy.clear(); QCoreApplication::sendPostedEvents(); expected = EventRecorder::EventList() << qMakePair(&widget, QEvent::PolishRequest) << qMakePair(&widget, QEvent::Type(QEvent::User + 1)) #if defined(Q_WS_X11) || defined(Q_WS_WIN) || defined(Q_WS_QWS) << qMakePair(&widget, QEvent::UpdateRequest) #endif ; QCOMPARE(spy.eventList(), expected); } { // 2 children, not shown QWidget widget; EventRecorder spy; widget.installEventFilter(&spy); QCoreApplication::postEvent(&widget, new QEvent(QEvent::Type(QEvent::User + 1))); QWidget child1(&widget); QWidget child2; child2.setParent(&widget); QCoreApplication::postEvent(&widget, new QEvent(QEvent::Type(QEvent::User + 2))); expected = EventRecorder::EventList() << qMakePair(&widget, QEvent::ChildAdded) << qMakePair(&widget, QEvent::ChildAdded); QCOMPARE(spy.eventList(), expected); spy.clear(); QCoreApplication::sendPostedEvents(); expected = EventRecorder::EventList() #ifdef QT_HAS_QT3SUPPORT << qMakePair(&widget, QEvent::ChildInsertedRequest) << qMakePair(&widget, QEvent::ChildInserted) << qMakePair(&widget, QEvent::ChildInserted) #endif << qMakePair(&widget, QEvent::PolishRequest) << qMakePair(&widget, QEvent::Polish) << qMakePair(&widget, QEvent::ChildPolished) << qMakePair(&widget, QEvent::ChildPolished) << qMakePair(&widget, QEvent::Type(QEvent::User + 1)) << qMakePair(&widget, QEvent::Type(QEvent::User + 2)); QCOMPARE(spy.eventList(), expected); } { // 2 children, widget shown QWidget widget; EventRecorder spy; widget.installEventFilter(&spy); QCoreApplication::postEvent(&widget, new QEvent(QEvent::Type(QEvent::User + 1))); QWidget child1(&widget); QWidget child2; child2.setParent(&widget); QCoreApplication::postEvent(&widget, new QEvent(QEvent::Type(QEvent::User + 2))); expected = EventRecorder::EventList() << qMakePair(&widget, QEvent::ChildAdded) << qMakePair(&widget, QEvent::ChildAdded); QCOMPARE(spy.eventList(), expected); spy.clear(); widget.show(); expected = EventRecorder::EventList() << qMakePair(&widget, QEvent::Polish) #ifdef QT_HAS_QT3SUPPORT << qMakePair(&widget, QEvent::ChildInserted) << qMakePair(&widget, QEvent::ChildInserted) #endif << qMakePair(&widget, QEvent::ChildPolished) << qMakePair(&widget, QEvent::ChildPolished) << qMakePair(&widget, QEvent::Move) << qMakePair(&widget, QEvent::Resize) << qMakePair(&widget, QEvent::Show); if (accessibilityEnabled) expected << qMakePair(&widget, QEvent::AccessibilityPrepare); expected << qMakePair(&widget, QEvent::ShowToParent); QCOMPARE(spy.eventList(), expected); spy.clear(); QCoreApplication::sendPostedEvents(); expected = EventRecorder::EventList() #ifdef QT_HAS_QT3SUPPORT << qMakePair(&widget, QEvent::ChildInsertedRequest) #endif << qMakePair(&widget, QEvent::PolishRequest) << qMakePair(&widget, QEvent::Type(QEvent::User + 1)) << qMakePair(&widget, QEvent::Type(QEvent::User + 2)) #if defined(Q_WS_X11) || defined(Q_WS_WIN) || defined(Q_WS_QWS) << qMakePair(&widget, QEvent::UpdateRequest) #endif ; QCOMPARE(spy.eventList(), expected); } { // 2 children, but one is reparented away, not shown QWidget widget; EventRecorder spy; widget.installEventFilter(&spy); QCoreApplication::postEvent(&widget, new QEvent(QEvent::Type(QEvent::User + 1))); QWidget child1(&widget); QWidget child2; child2.setParent(&widget); child2.setParent(0); QCoreApplication::postEvent(&widget, new QEvent(QEvent::Type(QEvent::User + 2))); expected = EventRecorder::EventList() << qMakePair(&widget, QEvent::ChildAdded) << qMakePair(&widget, QEvent::ChildAdded) << qMakePair(&widget, QEvent::ChildRemoved); QCOMPARE(spy.eventList(), expected); spy.clear(); QCoreApplication::sendPostedEvents(); expected = EventRecorder::EventList() #ifdef QT_HAS_QT3SUPPORT << qMakePair(&widget, QEvent::ChildInsertedRequest) << qMakePair(&widget, QEvent::ChildInserted) #endif << qMakePair(&widget, QEvent::PolishRequest) << qMakePair(&widget, QEvent::Polish) << qMakePair(&widget, QEvent::ChildPolished) << qMakePair(&widget, QEvent::Type(QEvent::User + 1)) << qMakePair(&widget, QEvent::Type(QEvent::User + 2)); QCOMPARE(spy.eventList(), expected); } { // 2 children, but one is reparented away, then widget is shown QWidget widget; EventRecorder spy; widget.installEventFilter(&spy); QCoreApplication::postEvent(&widget, new QEvent(QEvent::Type(QEvent::User + 1))); QWidget child1(&widget); QWidget child2; child2.setParent(&widget); child2.setParent(0); QCoreApplication::postEvent(&widget, new QEvent(QEvent::Type(QEvent::User + 2))); expected = EventRecorder::EventList() << qMakePair(&widget, QEvent::ChildAdded) << qMakePair(&widget, QEvent::ChildAdded) << qMakePair(&widget, QEvent::ChildRemoved); QCOMPARE(spy.eventList(), expected); spy.clear(); widget.show(); expected = EventRecorder::EventList() << qMakePair(&widget, QEvent::Polish) #ifdef QT_HAS_QT3SUPPORT << qMakePair(&widget, QEvent::ChildInserted) #endif << qMakePair(&widget, QEvent::ChildPolished) << qMakePair(&widget, QEvent::Move) << qMakePair(&widget, QEvent::Resize) << qMakePair(&widget, QEvent::Show); if (accessibilityEnabled) expected << qMakePair(&widget, QEvent::AccessibilityPrepare); expected << qMakePair(&widget, QEvent::ShowToParent); QCOMPARE(spy.eventList(), expected); spy.clear(); QCoreApplication::sendPostedEvents(); expected = EventRecorder::EventList() #ifdef QT_HAS_QT3SUPPORT << qMakePair(&widget, QEvent::ChildInsertedRequest) #endif << qMakePair(&widget, QEvent::PolishRequest) << qMakePair(&widget, QEvent::Type(QEvent::User + 1)) << qMakePair(&widget, QEvent::Type(QEvent::User + 2)) #if defined(Q_WS_X11) || defined(Q_WS_WIN) || defined(Q_WS_QWS) << qMakePair(&widget, QEvent::UpdateRequest) #endif ; QCOMPARE(spy.eventList(), expected); } } class RenderWidget : public QWidget { public: RenderWidget(QWidget *source) : source(source), ellipse(false) {} void setEllipseEnabled(bool enable = true) { ellipse = enable; update(); } protected: void paintEvent(QPaintEvent *) { if (ellipse) { QPainter painter(this); painter.fillRect(rect(), Qt::red); painter.end(); QRegion regionToRender = QRegion(0, 0, source->width(), source->height() / 2, QRegion::Ellipse); source->render(this, QPoint(0, 30), regionToRender); } else { source->render(this); } } private: QWidget *source; bool ellipse; }; void tst_QWidget::render() { QCalendarWidget source; // disable anti-aliasing to eliminate potential differences when subpixel antialiasing // is enabled on the screen QFont f; f.setStyleStrategy(QFont::NoAntialias); source.setFont(f); source.show(); #ifdef Q_WS_X11 qt_x11_wait_for_window_manager(&source); #endif // Render the entire source into target. RenderWidget target(&source); target.resize(source.size()); target.show(); #ifdef Q_WS_X11 qt_x11_wait_for_window_manager(&target); #endif qApp->processEvents(); qApp->sendPostedEvents(); QTest::qWait(500); QImage sourceImage = QPixmap::grabWidget(&source).toImage(); qApp->processEvents(); QImage targetImage = QPixmap::grabWidget(&target).toImage(); qApp->processEvents(); QCOMPARE(sourceImage, targetImage); // Fill target.rect() will Qt::red and render // QRegion(0, 0, source->width(), source->height() / 2, QRegion::Ellipse) // of source into target with offset (0, 30). target.setEllipseEnabled(); qApp->processEvents(); qApp->sendPostedEvents(); targetImage = QPixmap::grabWidget(&target).toImage(); QVERIFY(sourceImage != targetImage); QCOMPARE(targetImage.pixel(target.width() / 2, 29), QColor(Qt::red).rgb()); QCOMPARE(targetImage.pixel(target.width() / 2, 30), sourceImage.pixel(source.width() / 2, 0)); // Test that a child widget properly fills its background { QWidget window; window.resize(100, 100); window.show(); #ifdef Q_WS_X11 qt_x11_wait_for_window_manager(&window); #endif QWidget child(&window); child.resize(window.size()); child.show(); qApp->processEvents(); QCOMPARE(QPixmap::grabWidget(&child), QPixmap::grabWidget(&window)); } { // Check that the target offset is correct. QWidget widget; widget.resize(200, 200); widget.setAutoFillBackground(true); widget.setPalette(Qt::red); widget.show(); #ifdef Q_WS_X11 qt_x11_wait_for_window_manager(&widget); #endif QImage image(widget.size(), QImage::Format_RGB32); image.fill(QColor(Qt::blue).rgb()); // Target offset (0, 0) widget.render(&image, QPoint(), QRect(20, 20, 100, 100)); QCOMPARE(image.pixel(0, 0), QColor(Qt::red).rgb()); QCOMPARE(image.pixel(99, 99), QColor(Qt::red).rgb()); QCOMPARE(image.pixel(100, 100), QColor(Qt::blue).rgb()); // Target offset (20, 20). image.fill(QColor(Qt::blue).rgb()); widget.render(&image, QPoint(20, 20), QRect(20, 20, 100, 100)); QCOMPARE(image.pixel(0, 0), QColor(Qt::blue).rgb()); QCOMPARE(image.pixel(19, 19), QColor(Qt::blue).rgb()); QCOMPARE(image.pixel(20, 20), QColor(Qt::red).rgb()); QCOMPARE(image.pixel(119, 119), QColor(Qt::red).rgb()); QCOMPARE(image.pixel(120, 120), QColor(Qt::blue).rgb()); } } // On Windows the active palette is used instead of the inactive palette even // though the widget is invisible. This is probably related to task 178507/168682, // but for the renderInvisible test it doesn't matter, we're mostly interested // in testing the geometry so just workaround the palette issue for now. static void workaroundPaletteIssue(QWidget *widget) { #ifndef Q_WS_WIN return; #endif if (!widget) return; QWidget *navigationBar = qFindChild(widget, QLatin1String("qt_calendar_navigationbar")); QVERIFY(navigationBar); QPalette palette = navigationBar->palette(); const QColor background = palette.color(QPalette::Inactive, navigationBar->backgroundRole()); const QColor highlightedText = palette.color(QPalette::Inactive, QPalette::HighlightedText); palette.setColor(QPalette::Active, navigationBar->backgroundRole(), background); palette.setColor(QPalette::Active, QPalette::HighlightedText, highlightedText); navigationBar->setPalette(palette); } //#define RENDER_DEBUG void tst_QWidget::renderInvisible() { QCalendarWidget *calendar = new QCalendarWidget; // disable anti-aliasing to eliminate potential differences when subpixel antialiasing // is enabled on the screen QFont f; f.setStyleStrategy(QFont::NoAntialias); calendar->setFont(f); calendar->show(); #ifdef Q_WS_X11 qt_x11_wait_for_window_manager(calendar); #endif // Create a dummy focus widget to get rid of focus rect in reference image. QLineEdit dummyFocusWidget; dummyFocusWidget.show(); #ifdef Q_WS_X11 qt_x11_wait_for_window_manager(&dummyFocusWidget); #endif qApp->processEvents(); // Create normal reference image. const QSize calendarSize = calendar->size(); QImage referenceImage(calendarSize, QImage::Format_ARGB32); calendar->render(&referenceImage); #ifdef RENDER_DEBUG referenceImage.save("referenceImage.png"); #endif QVERIFY(!referenceImage.isNull()); // Create resized reference image. const QSize calendarSizeResized = calendar->size() + QSize(50, 50); calendar->resize(calendarSizeResized); #ifdef Q_WS_X11 qt_x11_wait_for_window_manager(&dummyFocusWidget); #endif qApp->processEvents(); QImage referenceImageResized(calendarSizeResized, QImage::Format_ARGB32); calendar->render(&referenceImageResized); #ifdef RENDER_DEBUG referenceImageResized.save("referenceImageResized.png"); #endif QVERIFY(!referenceImageResized.isNull()); // Explicitly hide the calendar. calendar->hide(); #ifdef Q_WS_X11 qt_x11_wait_for_window_manager(calendar); #endif qApp->processEvents(); workaroundPaletteIssue(calendar); { // Make sure we get the same image when the calendar is explicitly hidden. QImage testImage(calendarSizeResized, QImage::Format_ARGB32); calendar->render(&testImage); #ifdef RENDER_DEBUG testImage.save("explicitlyHiddenCalendarResized.png"); #endif QCOMPARE(testImage, referenceImageResized); } // Now that we have reference images we can delete the source and re-create // the calendar and check that we get the same images from a calendar which has never // been visible, laid out or created (Qt::WA_WState_Created). delete calendar; calendar = new QCalendarWidget; calendar->setFont(f); workaroundPaletteIssue(calendar); { // Never been visible, created or laid out. QImage testImage(calendarSize, QImage::Format_ARGB32); calendar->render(&testImage); #ifdef RENDER_DEBUG testImage.save("neverBeenVisibleCreatedOrLaidOut.png"); #endif QCOMPARE(testImage, referenceImage); } calendar->hide(); qApp->processEvents(); { // Calendar explicitly hidden. QImage testImage(calendarSize, QImage::Format_ARGB32); calendar->render(&testImage); #ifdef RENDER_DEBUG testImage.save("explicitlyHiddenCalendar.png"); #endif QCOMPARE(testImage, referenceImage); } // Get navigation bar and explicitly hide it. QWidget *navigationBar = qFindChild(calendar, QLatin1String("qt_calendar_navigationbar")); QVERIFY(navigationBar); navigationBar->hide(); { // Check that the navigation bar isn't drawn when rendering the entire calendar. QImage testImage(calendarSize, QImage::Format_ARGB32); calendar->render(&testImage); #ifdef RENDER_DEBUG testImage.save("calendarWithoutNavigationBar.png"); #endif QVERIFY(testImage != referenceImage); } { // Make sure the navigation bar renders correctly even though it's hidden. QImage testImage(navigationBar->size(), QImage::Format_ARGB32); navigationBar->render(&testImage); #ifdef RENDER_DEBUG testImage.save("explicitlyHiddenNavigationBar.png"); #endif QCOMPARE(testImage, referenceImage.copy(navigationBar->rect())); } // Get next month button. QWidget *nextMonthButton = qFindChild(navigationBar, QLatin1String("qt_calendar_nextmonth")); QVERIFY(nextMonthButton); { // Render next month button. // Fill test image with correct background color. QImage testImage(nextMonthButton->size(), QImage::Format_ARGB32); navigationBar->render(&testImage, QPoint(), QRegion(), QWidget::RenderFlags()); #ifdef RENDER_DEBUG testImage.save("nextMonthButtonBackground.png"); #endif // Set the button's background color to Qt::transparent; otherwise it will fill the // background with QPalette::Window. const QPalette originalPalette = nextMonthButton->palette(); QPalette palette = originalPalette; palette.setColor(QPalette::Window, Qt::transparent); nextMonthButton->setPalette(palette); // Render the button on top of the background. nextMonthButton->render(&testImage); #ifdef RENDER_DEBUG testImage.save("nextMonthButton.png"); #endif const QRect buttonRect(nextMonthButton->mapTo(calendar, QPoint()), nextMonthButton->size()); QCOMPARE(testImage, referenceImage.copy(buttonRect)); // Restore palette. nextMonthButton->setPalette(originalPalette); } // Navigation bar isn't explicitly hidden anymore. navigationBar->show(); qApp->processEvents(); QVERIFY(!calendar->isVisible()); // Now, completely mess up the layout. This will trigger an update on the layout // when the calendar is visible or shown, but it's not. QWidget::render must therefore // make sure the layout is activated before rendering. QVERIFY(!calendar->isVisible()); calendar->resize(calendarSizeResized); qApp->processEvents(); { // Make sure we get an image equal to the resized reference image. QImage testImage(calendarSizeResized, QImage::Format_ARGB32); calendar->render(&testImage); #ifdef RENDER_DEBUG testImage.save("calendarResized.png"); #endif QCOMPARE(testImage, referenceImageResized); } { // Make sure we lay out the widget correctly the first time it's rendered. QCalendarWidget calendar; const QSize calendarSize = calendar.sizeHint(); QImage image(2 * calendarSize, QImage::Format_ARGB32); image.fill(QColor(Qt::red).rgb()); calendar.render(&image); for (int i = calendarSize.height(); i < 2 * calendarSize.height(); ++i) for (int j = calendarSize.width(); j < 2 * calendarSize.width(); ++j) QCOMPARE(image.pixel(j, i), QColor(Qt::red).rgb()); } { // Ensure that we don't call adjustSize() on invisible top-levels if render() is called // right after widgets have been added/removed to/from its layout. QWidget topLevel; topLevel.setLayout(new QVBoxLayout); QWidget *widget = new QLineEdit; topLevel.layout()->addWidget(widget); const QSize initialSize = topLevel.size(); QPixmap pixmap(topLevel.sizeHint()); topLevel.render(&pixmap); // triggers adjustSize() const QSize finalSize = topLevel.size(); QVERIFY(finalSize != initialSize); topLevel.layout()->removeWidget(widget); QCOMPARE(topLevel.size(), finalSize); topLevel.render(&pixmap); QCOMPARE(topLevel.size(), finalSize); topLevel.layout()->addWidget(widget); QCOMPARE(topLevel.size(), finalSize); topLevel.render(&pixmap); QCOMPARE(topLevel.size(), finalSize); } } void tst_QWidget::renderWithPainter() { QWidget widget; widget.show(); widget.resize(70, 50); widget.setAutoFillBackground(true); widget.setPalette(Qt::black); // Render the entire widget onto the image. QImage image(QSize(70, 50), QImage::Format_ARGB32); image.fill(QColor(Qt::red).rgb()); QPainter painter(&image); widget.render(&painter); for (int i = 0; i < image.height(); ++i) { for (int j = 0; j < image.width(); ++j) QCOMPARE(image.pixel(j, i), QColor(Qt::black).rgb()); } // Translate painter (10, 10). painter.save(); image.fill(QColor(Qt::red).rgb()); painter.translate(10, 10); widget.render(&painter); painter.restore(); for (int i = 0; i < image.height(); ++i) { for (int j = 0; j < image.width(); ++j) { if (i < 10 || j < 10) QCOMPARE(image.pixel(j, i), QColor(Qt::red).rgb()); else QCOMPARE(image.pixel(j, i), QColor(Qt::black).rgb()); } } // Pass target offset (10, 10) (the same as QPainter::translate). image.fill(QColor(Qt::red).rgb()); widget.render(&painter, QPoint(10, 10)); for (int i = 0; i < image.height(); ++i) { for (int j = 0; j < image.width(); ++j) { if (i < 10 || j < 10) QCOMPARE(image.pixel(j, i), QColor(Qt::red).rgb()); else QCOMPARE(image.pixel(j, i), QColor(Qt::black).rgb()); } } // Translate (10, 10) and pass target offset (10, 10). painter.save(); image.fill(QColor(Qt::red).rgb()); painter.translate(10, 10); widget.render(&painter, QPoint(10, 10)); painter.restore(); for (int i = 0; i < image.height(); ++i) { for (int j = 0; j < image.width(); ++j) { if (i < 20 || j < 20) QCOMPARE(image.pixel(j, i), QColor(Qt::red).rgb()); else QCOMPARE(image.pixel(j, i), QColor(Qt::black).rgb()); } } // Rotate painter 90 degrees. painter.save(); image.fill(QColor(Qt::red).rgb()); painter.rotate(90); widget.render(&painter); painter.restore(); for (int i = 0; i < image.height(); ++i) { for (int j = 0; j < image.width(); ++j) QCOMPARE(image.pixel(j, i), QColor(Qt::red).rgb()); } // Translate and rotate. image.fill(QColor(Qt::red).rgb()); widget.resize(40, 10); painter.translate(10, 10); painter.rotate(90); widget.render(&painter); for (int i = 0; i < image.height(); ++i) { for (int j = 0; j < image.width(); ++j) { if (i >= 10 && j >= 0 && j < 10) QCOMPARE(image.pixel(j, i), QColor(Qt::black).rgb()); else QCOMPARE(image.pixel(j, i), QColor(Qt::red).rgb()); } } // Make sure QWidget::render does not modify the render hints set on the painter. painter.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform | QPainter::NonCosmeticDefaultPen | QPainter::TextAntialiasing); QPainter::RenderHints oldRenderHints = painter.renderHints(); widget.render(&painter); QCOMPARE(painter.renderHints(), oldRenderHints); } void tst_QWidget::render_task188133() { QMainWindow mainWindow; #if defined(QT3_SUPPORT) mainWindow.setCentralWidget(new Q3TextEdit); #endif // Make sure QWidget::render does not trigger QWidget::repaint/update // and asserts for Qt::WA_WState_Created. QPixmap pixmap = QPixmap::grabWidget(&mainWindow); } void tst_QWidget::render_task211796() { class MyWidget : public QWidget { void resizeEvent(QResizeEvent *) { QPixmap pixmap(size()); render(&pixmap); } }; { // Please don't die in a resize recursion. MyWidget widget; widget.resize(200, 200); widget.show(); } { // Same check with a deeper hierarchy. QWidget widget; widget.show(); QWidget child(&widget); MyWidget grandChild; grandChild.setParent(&child); grandChild.resize(100, 100); child.show(); } } void tst_QWidget::render_task217815() { // Make sure we don't change the size of the widget when calling // render() and the widget has an explicit size set. // This was a problem on Windows because we called createWinId(), // which in turn enforced the size to be bigger than the smallest // possible native window size (which is (115,something) on WinXP). QWidget widget; const QSize explicitSize(80, 20); widget.resize(explicitSize); QCOMPARE(widget.size(), explicitSize); QPixmap pixmap(explicitSize); widget.render(&pixmap); QCOMPARE(widget.size(), explicitSize); } void tst_QWidget::render_windowOpacity() { #ifdef Q_OS_WINCE QSKIP("Window Opacity is not supported on Windows CE", SkipAll); #endif const qreal opacity = 0.5; { // Check that the painter opacity effects the widget drawing. QWidget topLevel; QWidget child(&topLevel); child.resize(50, 50); child.setPalette(Qt::red); child.setAutoFillBackground(true); QPixmap expected(child.size()); #ifdef Q_WS_X11 if (expected.depth() < 24) { QSKIP("This test won't give correct results with dithered pixmaps", SkipAll); } #endif expected.fill(Qt::green); QPainter painter(&expected); painter.setOpacity(opacity); painter.fillRect(QRect(QPoint(0, 0), child.size()), Qt::red); painter.end(); QPixmap result(child.size()); result.fill(Qt::green); painter.begin(&result); painter.setOpacity(opacity); child.render(&painter); painter.end(); QCOMPARE(result, expected); } { // Combine the opacity set on the painter with the widget opacity. class MyWidget : public QWidget { public: void paintEvent(QPaintEvent *) { QPainter painter(this); painter.setOpacity(opacity); QCOMPARE(painter.opacity(), opacity); painter.fillRect(rect(), Qt::red); } qreal opacity; }; MyWidget widget; widget.resize(50, 50); widget.opacity = opacity; widget.setPalette(Qt::blue); widget.setAutoFillBackground(true); QPixmap expected(widget.size()); expected.fill(Qt::green); QPainter painter(&expected); painter.setOpacity(opacity); QPixmap pixmap(widget.size()); pixmap.fill(Qt::blue); QPainter pixmapPainter(&pixmap); pixmapPainter.setOpacity(opacity); pixmapPainter.fillRect(QRect(QPoint(), widget.size()), Qt::red); painter.drawPixmap(QPoint(), pixmap); painter.end(); QPixmap result(widget.size()); result.fill(Qt::green); painter.begin(&result); painter.setOpacity(opacity); widget.render(&painter); painter.end(); QCOMPARE(result, expected); } } void tst_QWidget::render_systemClip() { QWidget widget; widget.setPalette(Qt::blue); widget.resize(100, 100); QImage image(widget.size(), QImage::Format_RGB32); image.fill(QColor(Qt::red).rgb()); QPaintEngine *paintEngine = image.paintEngine(); QVERIFY(paintEngine); paintEngine->setSystemClip(QRegion(0, 0, 50, 50)); QPainter painter(&image); // Make sure we're using the same paint engine and has the right clip set. QCOMPARE(painter.paintEngine(), paintEngine); QCOMPARE(paintEngine->systemClip(), QRegion(0, 0, 50, 50)); // Translate painter outside system clip. painter.translate(50, 0); widget.render(&painter); #ifdef RENDER_DEBUG image.save("outside_systemclip.png"); #endif // All pixels should be red. for (int i = 0; i < image.height(); ++i) { for (int j = 0; j < image.width(); ++j) QCOMPARE(image.pixel(j, i), QColor(Qt::red).rgb()); } // Restore painter and refill image with red. image.fill(QColor(Qt::red).rgb()); painter.translate(-50, 0); // Set transform on the painter. QTransform transform; transform.shear(0, 1); painter.setTransform(transform); widget.render(&painter); #ifdef RENDER_DEBUG image.save("blue_triangle.png"); #endif // We should now have a blue triangle starting at scan line 1, and the rest should be red. // rrrrrrrrrr // brrrrrrrrr // bbrrrrrrrr // bbbrrrrrrr // bbbbrrrrrr // rrrrrrrrrr // ... #ifndef Q_WS_MAC for (int i = 0; i < image.height(); ++i) { for (int j = 0; j < image.width(); ++j) { if (i < 50 && j < i) QCOMPARE(image.pixel(j, i), QColor(Qt::blue).rgb()); else QCOMPARE(image.pixel(j, i), QColor(Qt::red).rgb()); } } #else // We don't paint directly on the image on the Mac, so we cannot do the pixel comparison // as above due to QPainter::SmoothPixmapTransform. We therefore need to generate an // expected image by first painting on a pixmap, and then draw the pixmap onto // the image using QPainter::SmoothPixmapTransform. Then we can compare pixels :) // The check is basically the same, except that it takes the smoothening into account. QPixmap pixmap(50, 50); const QRegion sysClip(0, 0, 50, 50); widget.render(&pixmap, QPoint(), sysClip); QImage expectedImage(widget.size(), QImage::Format_RGB32); expectedImage.fill(QColor(Qt::red).rgb()); expectedImage.paintEngine()->setSystemClip(sysClip); QPainter expectedImagePainter(&expectedImage); expectedImagePainter.setTransform(QTransform().shear(0, 1)); // NB! This is the important part (SmoothPixmapTransform). expectedImagePainter.setRenderHints(QPainter::SmoothPixmapTransform); expectedImagePainter.drawPixmap(QPoint(0, 0), pixmap); expectedImagePainter.end(); QCOMPARE(image, expectedImage); #endif } void tst_QWidget::render_systemClip2_data() { QTest::addColumn("autoFillBackground"); QTest::addColumn("usePaintEvent"); QTest::addColumn("expectedColor"); QTest::newRow("Only auto-fill background") << true << false << QColor(Qt::blue); QTest::newRow("Only draw in paintEvent") << false << true << QColor(Qt::green); QTest::newRow("Auto-fill background and draw in paintEvent") << true << true << QColor(Qt::green); } void tst_QWidget::render_systemClip2() { QFETCH(bool, autoFillBackground); QFETCH(bool, usePaintEvent); QFETCH(QColor, expectedColor); Q_ASSERT_X(expectedColor != QColor(Qt::red), Q_FUNC_INFO, "Qt::red is the reference color for the image, pick another color"); class MyWidget : public QWidget { public: bool usePaintEvent; void paintEvent(QPaintEvent *) { if (usePaintEvent) QPainter(this).fillRect(rect(), Qt::green); } }; MyWidget widget; widget.usePaintEvent = usePaintEvent; widget.setPalette(Qt::blue); // NB! widget.setAutoFillBackground(autoFillBackground) won't do the // trick here since the widget is a top-level. The background is filled // regardless, unless Qt::WA_OpaquePaintEvent or Qt::WA_NoSystemBackground // is set. We therefore use the opaque attribute to turn off auto-fill. if (!autoFillBackground) widget.setAttribute(Qt::WA_OpaquePaintEvent); widget.resize(100, 100); QImage image(widget.size(), QImage::Format_RGB32); image.fill(QColor(Qt::red).rgb()); QPaintEngine *paintEngine = image.paintEngine(); QVERIFY(paintEngine); QRegion systemClip(QRegion(50, 0, 50, 10)); systemClip += QRegion(90, 10, 10, 40); paintEngine->setSystemClip(systemClip); // Render entire widget directly onto device. widget.render(&image); #ifdef RENDER_DEBUG image.save("systemclip_with_device.png"); #endif // All pixels within the system clip should now be // the expectedColor, and the rest should be red. for (int i = 0; i < image.height(); ++i) { for (int j = 0; j < image.width(); ++j) { if (systemClip.contains(QPoint(j, i))) QCOMPARE(image.pixel(j, i), expectedColor.rgb()); else QCOMPARE(image.pixel(j, i), QColor(Qt::red).rgb()); } } // Refill image with red. image.fill(QColor(Qt::red).rgb()); paintEngine->setSystemClip(systemClip); // Do the same with an untransformed painter. QPainter painter(&image); //Make sure we're using the same paint engine and has the right clip set. QCOMPARE(painter.paintEngine(), paintEngine); QCOMPARE(paintEngine->systemClip(), systemClip); widget.render(&painter); #ifdef RENDER_DEBUG image.save("systemclip_with_untransformed_painter.png"); #endif // All pixels within the system clip should now be // the expectedColor, and the rest should be red. for (int i = 0; i < image.height(); ++i) { for (int j = 0; j < image.width(); ++j) { if (systemClip.contains(QPoint(j, i))) QCOMPARE(image.pixel(j, i), expectedColor.rgb()); else QCOMPARE(image.pixel(j, i), QColor(Qt::red).rgb()); } } } void tst_QWidget::render_systemClip3_data() { QTest::addColumn("size"); QTest::addColumn("useSystemClip"); // Reference: http://en.wikipedia.org/wiki/Flag_of_Norway QTest::newRow("Norwegian Civil Flag") << QSize(220, 160) << false; QTest::newRow("Norwegian War Flag") << QSize(270, 160) << true; } // This test ensures that the current engine clip (systemClip + painter clip) // is preserved after QPainter::setClipRegion(..., Qt::ReplaceClip); void tst_QWidget::render_systemClip3() { QFETCH(QSize, size); QFETCH(bool, useSystemClip); // Calculate the inner/outer cross of the flag. QRegion outerCross(0, 0, size.width(), size.height()); outerCross -= QRect(0, 0, 60, 60); outerCross -= QRect(100, 0, size.width() - 100, 60); outerCross -= QRect(0, 100, 60, 60); outerCross -= QRect(100, 100, size.width() - 100, 60); QRegion innerCross(0, 0, size.width(), size.height()); innerCross -= QRect(0, 0, 70, 70); innerCross -= QRect(90, 0, size.width() - 90, 70); innerCross -= QRect(0, 90, 70, 70); innerCross -= QRect(90, 90, size.width() - 90, 70); const QRegion redArea(QRegion(0, 0, size.width(), size.height()) - outerCross); const QRegion whiteArea(outerCross - innerCross); const QRegion blueArea(innerCross); QRegion systemClip; // Okay, here's the image that should look like a Norwegian civil/war flag in the end. QImage flag(size, QImage::Format_ARGB32); flag.fill(QColor(Qt::transparent).rgba()); if (useSystemClip) { QPainterPath warClip(QPoint(size.width(), 0)); warClip.lineTo(size.width() - 110, 60); warClip.lineTo(size.width(), 80); warClip.lineTo(size.width() - 110, 100); warClip.lineTo(size.width(), 160); warClip.closeSubpath(); systemClip = QRegion(0, 0, size.width(), size.height()) - QRegion(warClip.toFillPolygon().toPolygon()); flag.paintEngine()->setSystemClip(systemClip); } QPainter painter(&flag); painter.fillRect(QRect(QPoint(), size), Qt::red); // Fill image background with red. painter.setClipRegion(outerCross); // Limit widget painting to inside the outer cross. // Here's the widget that's supposed to draw the inner/outer cross of the flag. // The outer cross (white) should be drawn when the background is auto-filled, and // the inner cross (blue) should be drawn in the paintEvent. class MyWidget : public QWidget { public: void paintEvent(QPaintEvent *) { QPainter painter(this); // Be evil and try to paint outside the outer cross. This should not be // possible since the shared painter is clipped to the outer cross. painter.setClipRect(0, 0, 60, 60, Qt::ReplaceClip); painter.fillRect(rect(), Qt::green); painter.setClipRegion(clip, Qt::ReplaceClip); painter.fillRect(rect(), Qt::blue); } QRegion clip; }; MyWidget widget; widget.clip = innerCross; widget.setFixedSize(size); widget.setPalette(Qt::white); widget.setAutoFillBackground(true); widget.render(&painter); #ifdef RENDER_DEBUG flag.save("flag.png"); #endif // Let's make sure we got a Norwegian flag. for (int i = 0; i < flag.height(); ++i) { for (int j = 0; j < flag.width(); ++j) { const QPoint pixel(j, i); const QRgb pixelValue = flag.pixel(pixel); if (useSystemClip && !systemClip.contains(pixel)) QCOMPARE(pixelValue, QColor(Qt::transparent).rgba()); else if (redArea.contains(pixel)) QCOMPARE(pixelValue, QColor(Qt::red).rgba()); else if (whiteArea.contains(pixel)) QCOMPARE(pixelValue, QColor(Qt::white).rgba()); else QCOMPARE(pixelValue, QColor(Qt::blue).rgba()); } } } void tst_QWidget::render_task252837() { QWidget widget; widget.resize(200, 200); QPixmap pixmap(widget.size()); QPainter painter(&pixmap); // Please do not crash. widget.render(&painter); } void tst_QWidget::render_worldTransform() { class MyWidget : public QWidget { public: void paintEvent(QPaintEvent *) { QPainter painter(this); // Make sure world transform is identity. QCOMPARE(painter.worldTransform(), QTransform()); // Make sure device transform is correct. const QPoint widgetOffset = geometry().topLeft(); QTransform expectedDeviceTransform = QTransform::fromTranslate(105, 5); expectedDeviceTransform.rotate(90); expectedDeviceTransform.translate(widgetOffset.x(), widgetOffset.y()); QCOMPARE(painter.deviceTransform(), expectedDeviceTransform); // Set new world transform. QTransform newWorldTransform = QTransform::fromTranslate(10, 10); newWorldTransform.rotate(90); painter.setWorldTransform(newWorldTransform); QCOMPARE(painter.worldTransform(), newWorldTransform); // Again, check device transform. expectedDeviceTransform.translate(10, 10); expectedDeviceTransform.rotate(90); QCOMPARE(painter.deviceTransform(), expectedDeviceTransform); painter.fillRect(QRect(0, 0, 20, 10), Qt::green); } }; MyWidget widget; widget.setFixedSize(100, 100); widget.setPalette(Qt::red); widget.setAutoFillBackground(true); MyWidget child; child.setParent(&widget); child.move(50, 50); child.setFixedSize(50, 50); child.setPalette(Qt::blue); child.setAutoFillBackground(true); QImage image(QSize(110, 110), QImage::Format_RGB32); image.fill(QColor(Qt::black).rgb()); QPainter painter(&image); painter.translate(105, 5); painter.rotate(90); const QTransform worldTransform = painter.worldTransform(); const QTransform deviceTransform = painter.deviceTransform(); // Render widgets onto image. widget.render(&painter); #ifdef RENDER_DEBUG image.save("render_worldTransform_image.png"); #endif // Ensure the transforms are unchanged after render. QCOMPARE(painter.worldTransform(), painter.worldTransform()); QCOMPARE(painter.deviceTransform(), painter.deviceTransform()); painter.end(); // Paint expected image. QImage expected(QSize(110, 110), QImage::Format_RGB32); expected.fill(QColor(Qt::black).rgb()); QPainter expectedPainter(&expected); expectedPainter.translate(105, 5); expectedPainter.rotate(90); expectedPainter.save(); expectedPainter.fillRect(widget.rect(),Qt::red); expectedPainter.translate(10, 10); expectedPainter.rotate(90); expectedPainter.fillRect(QRect(0, 0, 20, 10), Qt::green); expectedPainter.restore(); expectedPainter.translate(50, 50); expectedPainter.fillRect(child.rect(),Qt::blue); expectedPainter.translate(10, 10); expectedPainter.rotate(90); expectedPainter.fillRect(QRect(0, 0, 20, 10), Qt::green); expectedPainter.end(); #ifdef RENDER_DEBUG expected.save("render_worldTransform_expected.png"); #endif QCOMPARE(image, expected); } void tst_QWidget::setContentsMargins() { QLabel label("why does it always rain on me?"); QSize oldSize = label.sizeHint(); label.setFrameStyle(QFrame::Sunken | QFrame::Box); QSize newSize = label.sizeHint(); QVERIFY(oldSize != newSize); QLabel label2("why does it always rain on me?"); label2.show(); label2.setFrameStyle(QFrame::Sunken | QFrame::Box); QCOMPARE(newSize, label2.sizeHint()); QLabel label3("why does it always rain on me?"); label3.setFrameStyle(QFrame::Sunken | QFrame::Box); QCOMPARE(newSize, label3.sizeHint()); } void tst_QWidget::moveWindowInShowEvent_data() { QTest::addColumn("initial"); QTest::addColumn("position"); QPoint p = QApplication::desktop()->availableGeometry().topLeft(); QTest::newRow("1") << p << (p + QPoint(10, 10)); QTest::newRow("2") << (p + QPoint(10,10)) << p; } void tst_QWidget::moveWindowInShowEvent() { #ifdef Q_OS_IRIX QSKIP("4DWM issues on IRIX makes this test fail", SkipAll); #endif QFETCH(QPoint, initial); QFETCH(QPoint, position); class MoveWindowInShowEventWidget : public QWidget { public: QPoint position; void showEvent(QShowEvent *) { move(position); } }; MoveWindowInShowEventWidget widget; widget.resize(QSize(qApp->desktop()->availableGeometry().size() / 3).expandedTo(QSize(1, 1))); // move to this position in showEvent() widget.position = position; // put the widget in it's starting position widget.move(initial); QCOMPARE(widget.pos(), initial); // show it widget.show(); #ifdef Q_WS_X11 qt_x11_wait_for_window_manager(&widget); #endif QTest::qWait(100); // it should have moved QCOMPARE(widget.pos(), position); } void tst_QWidget::repaintWhenChildDeleted() { #ifdef Q_WS_WIN if (QSysInfo::WindowsVersion & QSysInfo::WV_VISTA) { QTest::qWait(1000); } #endif ColorWidget w(0, Qt::red); #ifndef Q_OS_WINCE QPoint startPoint = QApplication::desktop()->availableGeometry(&w).topLeft(); startPoint.rx() += 50; startPoint.ry() += 50; w.setGeometry(QRect(startPoint, QSize(100, 100))); #else w.setGeometry(60, 60, 110, 110); #endif w.show(); QTest::qWait(1000); #ifdef Q_WS_X11 qt_x11_wait_for_window_manager(&w); #endif QCOMPARE(w.r, QRegion(w.rect())); w.r = QRegion(); { const QPoint tlwOffset = w.geometry().topLeft(); ColorWidget child(&w, Qt::blue); child.setGeometry(10, 10, 10, 10); child.show(); QTest::qWait(100); QCOMPARE(child.r, QRegion(child.rect())); w.r = QRegion(); } QTest::qWait(100); QCOMPARE(w.r, QRegion(10, 10, 10, 10)); } // task 175114 void tst_QWidget::hideOpaqueChildWhileHidden() { ColorWidget w(0, Qt::red); #ifndef Q_OS_WINCE QPoint startPoint = QApplication::desktop()->availableGeometry(&w).topLeft(); startPoint.rx() += 50; startPoint.ry() += 50; w.setGeometry(QRect(startPoint, QSize(100, 100))); #else w.setGeometry(60, 60, 110, 110); #endif ColorWidget child(&w, Qt::blue); child.setGeometry(10, 10, 80, 80); ColorWidget child2(&child, Qt::white); child2.setGeometry(10, 10, 60, 60); w.show(); #ifdef Q_WS_X11 qt_x11_wait_for_window_manager(&w); #endif QTest::qWait(1000); QCOMPARE(child2.r, QRegion(child2.rect())); child.r = QRegion(); child2.r = QRegion(); w.r = QRegion(); child.hide(); child2.hide(); QTest::qWait(100); QCOMPARE(w.r, QRegion(child.geometry())); child.show(); QTest::qWait(100); QCOMPARE(child.r, QRegion(child.rect())); QCOMPARE(child2.r, QRegion()); } void tst_QWidget::updateWhileMinimized() { #if defined(Q_OS_WINCE) || defined(Q_WS_QWS) QSKIP("This test doesn't make sense without support for showMinimized()", SkipAll); #endif UpdateWidget widget; // Filter out activation change and focus events to avoid update() calls in QWidget. widget.updateOnActivationChangeAndFocusIn = false; widget.show(); #ifdef Q_WS_X11 qt_x11_wait_for_window_manager(&widget); #endif QTest::qWait(300); // Minimize window. widget.showMinimized(); #ifdef Q_WS_X11 qt_x11_wait_for_window_manager(&widget); #endif QTest::qWait(300); widget.reset(); // The widget is not visible on the screen (but isVisible() still returns true). // Make sure update requests are discarded until the widget is shown again. widget.update(0, 0, 50, 50); QTest::qWait(100); QCOMPARE(widget.numPaintEvents, 0); // Restore window. widget.showNormal(); #ifdef Q_WS_X11 qt_x11_wait_for_window_manager(&widget); #endif QTest::qWait(300); QCOMPARE(widget.numPaintEvents, 1); QCOMPARE(widget.paintedRegion, QRegion(0, 0, 50, 50)); } #if defined(Q_WS_WIN) || defined(Q_WS_X11) class PaintOnScreenWidget: public QWidget { public: PaintOnScreenWidget(QWidget *parent = 0, Qt::WindowFlags f = 0) :QWidget(parent, f) { } #if defined(Q_WS_WIN) // This is the only way to enable PaintOnScreen on Windows. QPaintEngine * paintEngine () const {return 0;} #endif }; void tst_QWidget::alienWidgets() { qApp->setAttribute(Qt::AA_DontCreateNativeWidgetSiblings); QWidget parent; QWidget child(&parent); QWidget grandChild(&child); QWidget greatGrandChild(&grandChild); parent.show(); #ifdef Q_WS_X11 qt_x11_wait_for_window_manager(&parent); #endif // Verify that the WA_WState_Created attribute is set // and the top-level is the only native window. QVERIFY(parent.testAttribute(Qt::WA_WState_Created)); QVERIFY(parent.internalWinId()); QVERIFY(child.testAttribute(Qt::WA_WState_Created)); QVERIFY(!child.internalWinId()); QVERIFY(grandChild.testAttribute(Qt::WA_WState_Created)); QVERIFY(!grandChild.internalWinId()); QVERIFY(greatGrandChild.testAttribute(Qt::WA_WState_Created)); QVERIFY(!greatGrandChild.internalWinId()); // Enforce native windows all the way up in the parent hierarchy // if not WA_DontCreateNativeAncestors is set. grandChild.setAttribute(Qt::WA_DontCreateNativeAncestors); greatGrandChild.setAttribute(Qt::WA_NativeWindow); QVERIFY(greatGrandChild.internalWinId()); QVERIFY(grandChild.internalWinId()); QVERIFY(!child.internalWinId()); { // Ensure that hide() on an ancestor of a widget with // Qt::WA_DontCreateNativeAncestors still gets unmapped QWidget window; QWidget widget(&window); QWidget child(&widget); child.setAttribute(Qt::WA_NativeWindow); child.setAttribute(Qt::WA_DontCreateNativeAncestors); window.show(); QVERIFY(child.testAttribute(Qt::WA_Mapped)); widget.hide(); QVERIFY(!child.testAttribute(Qt::WA_Mapped)); } // Enforce a native window when calling QWidget::winId. QVERIFY(child.winId()); QVERIFY(child.internalWinId()); // Check that paint on screen widgets (incl. children) are native. PaintOnScreenWidget paintOnScreen(&parent); QWidget paintOnScreenChild(&paintOnScreen); paintOnScreen.show(); QVERIFY(paintOnScreen.testAttribute(Qt::WA_WState_Created)); QVERIFY(!paintOnScreen.testAttribute(Qt::WA_NativeWindow)); QVERIFY(!paintOnScreen.internalWinId()); QVERIFY(!paintOnScreenChild.testAttribute(Qt::WA_NativeWindow)); QVERIFY(!paintOnScreenChild.internalWinId()); paintOnScreen.setAttribute(Qt::WA_PaintOnScreen); QVERIFY(paintOnScreen.testAttribute(Qt::WA_NativeWindow)); QVERIFY(paintOnScreen.internalWinId()); QVERIFY(paintOnScreenChild.testAttribute(Qt::WA_NativeWindow)); QVERIFY(paintOnScreenChild.internalWinId()); // Check that widgets with the Qt::MSWindowsOwnDC attribute set // are native. QWidget msWindowsOwnDC(&parent, Qt::MSWindowsOwnDC); msWindowsOwnDC.show(); QVERIFY(msWindowsOwnDC.testAttribute(Qt::WA_WState_Created)); QVERIFY(msWindowsOwnDC.testAttribute(Qt::WA_NativeWindow)); QVERIFY(msWindowsOwnDC.internalWinId()); { // Enforce a native window when calling QWidget::handle() (on X11) or QWidget::getDC() (on Windows). QWidget widget(&parent); widget.show(); QVERIFY(widget.testAttribute(Qt::WA_WState_Created)); QVERIFY(!widget.internalWinId()); #ifdef Q_WS_X11 widget.handle(); #else widget.getDC(); #endif QVERIFY(widget.internalWinId()); } #ifdef Q_WS_X11 #ifndef QT_NO_XRENDER { // Enforce a native window when calling QWidget::x11PictureHandle(). QWidget widget(&parent); widget.show(); QVERIFY(widget.testAttribute(Qt::WA_WState_Created)); QVERIFY(!widget.internalWinId()); widget.x11PictureHandle(); QVERIFY(widget.internalWinId()); } #endif { // Make sure we don't create native windows when setting Qt::WA_X11NetWmWindowType attributes // on alien widgets (see task 194231). QWidget dummy; QVERIFY(dummy.winId()); QWidget widget(&dummy); widget.setAttribute(Qt::WA_X11NetWmWindowTypeToolBar); QVERIFY(!widget.internalWinId()); } #endif { // Make sure we create native ancestors when setting Qt::WA_PaintOnScreen before show(). QWidget topLevel; QWidget child(&topLevel); QWidget grandChild(&child); PaintOnScreenWidget greatGrandChild(&grandChild); greatGrandChild.setAttribute(Qt::WA_PaintOnScreen); QVERIFY(!child.internalWinId()); QVERIFY(!grandChild.internalWinId()); QVERIFY(!greatGrandChild.internalWinId()); topLevel.show(); QVERIFY(child.internalWinId()); QVERIFY(grandChild.internalWinId()); QVERIFY(greatGrandChild.internalWinId()); } { // Ensure that widgets reparented into Qt::WA_PaintOnScreen widgets become native. QWidget topLevel; QWidget *widget = new PaintOnScreenWidget(&topLevel); widget->setAttribute(Qt::WA_PaintOnScreen); QWidget *child = new QWidget; QWidget *dummy = new QWidget(child); QWidget *grandChild = new QWidget(child); QWidget *dummy2 = new QWidget(grandChild); child->setParent(widget); QVERIFY(!topLevel.internalWinId()); QVERIFY(!child->internalWinId()); QVERIFY(!dummy->internalWinId()); QVERIFY(!grandChild->internalWinId()); QVERIFY(!dummy2->internalWinId()); topLevel.show(); QVERIFY(topLevel.internalWinId()); QVERIFY(widget->testAttribute(Qt::WA_NativeWindow)); QVERIFY(child->internalWinId()); QVERIFY(child->testAttribute(Qt::WA_NativeWindow)); QVERIFY(!child->testAttribute(Qt::WA_PaintOnScreen)); QVERIFY(!dummy->internalWinId()); QVERIFY(!dummy->testAttribute(Qt::WA_NativeWindow)); QVERIFY(!grandChild->internalWinId()); QVERIFY(!grandChild->testAttribute(Qt::WA_NativeWindow)); QVERIFY(!dummy2->internalWinId()); QVERIFY(!dummy2->testAttribute(Qt::WA_NativeWindow)); } { // Ensure that ancestors of a Qt::WA_PaintOnScreen widget stay native // if they are re-created (typically in QWidgetPrivate::setParent_sys) (task 210822). QWidget window; QWidget child(&window); QWidget grandChild; grandChild.setWindowTitle("This causes the widget to be created"); PaintOnScreenWidget paintOnScreenWidget; paintOnScreenWidget.setAttribute(Qt::WA_PaintOnScreen); paintOnScreenWidget.setParent(&grandChild); grandChild.setParent(&child); window.show(); QVERIFY(window.internalWinId()); QVERIFY(child.internalWinId()); QVERIFY(child.testAttribute(Qt::WA_NativeWindow)); QVERIFY(grandChild.internalWinId()); QVERIFY(grandChild.testAttribute(Qt::WA_NativeWindow)); QVERIFY(paintOnScreenWidget.internalWinId()); QVERIFY(paintOnScreenWidget.testAttribute(Qt::WA_NativeWindow)); } { // Ensure that all siblings are native unless Qt::AA_DontCreateNativeWidgetSiblings is set. qApp->setAttribute(Qt::AA_DontCreateNativeWidgetSiblings, false); QWidget mainWindow; QWidget *toolBar = new QWidget(&mainWindow); QWidget *dockWidget = new QWidget(&mainWindow); QWidget *centralWidget = new QWidget(&mainWindow); QWidget *button = new QWidget(centralWidget); QWidget *mdiArea = new QWidget(centralWidget); QWidget *horizontalScroll = new QWidget(mdiArea); QWidget *verticalScroll = new QWidget(mdiArea); QWidget *viewport = new QWidget(mdiArea); viewport->setAttribute(Qt::WA_NativeWindow); mainWindow.show(); // Ensure that the viewport and its siblings are native: QVERIFY(verticalScroll->testAttribute(Qt::WA_NativeWindow)); QVERIFY(verticalScroll->testAttribute(Qt::WA_NativeWindow)); QVERIFY(horizontalScroll->testAttribute(Qt::WA_NativeWindow)); // Ensure that the mdi area and its siblings are native: QVERIFY(mdiArea->testAttribute(Qt::WA_NativeWindow)); QVERIFY(button->testAttribute(Qt::WA_NativeWindow)); // Ensure that the central widget and its siblings are native: QVERIFY(centralWidget->testAttribute(Qt::WA_NativeWindow)); QVERIFY(dockWidget->testAttribute(Qt::WA_NativeWindow)); QVERIFY(toolBar->testAttribute(Qt::WA_NativeWindow)); } } #endif // Q_WS_WIN / Q_WS_X11 class ASWidget : public QWidget { public: ASWidget(QSize sizeHint, QSizePolicy sizePolicy, bool layout, bool hfwLayout, QWidget *parent = 0) : QWidget(parent), mySizeHint(sizeHint) { setSizePolicy(sizePolicy); if (layout) { QSizePolicy sp = QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); sp.setHeightForWidth(hfwLayout); QVBoxLayout *vbox = new QVBoxLayout; vbox->setMargin(0); vbox->addWidget(new ASWidget(sizeHint + QSize(30, 20), sp, false, false)); setLayout(vbox); } } QSize sizeHint() const { if (layout()) return layout()->totalSizeHint(); return mySizeHint; } int heightForWidth(int width) const { if (sizePolicy().hasHeightForWidth()) { return width * 2; } else { return -1; } } QSize mySizeHint; }; void tst_QWidget::adjustSize_data() { const int MagicW = 200; const int MagicH = 100; QTest::addColumn("sizeHint"); QTest::addColumn("hPolicy"); QTest::addColumn("vPolicy"); QTest::addColumn("hfwSP"); QTest::addColumn("layout"); QTest::addColumn("hfwLayout"); QTest::addColumn("haveParent"); QTest::addColumn("expectedSize"); QTest::newRow("1") << QSize(5, 6) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding) << false << false << false << false << QSize(5, qMax(6, MagicH)); QTest::newRow("2") << QSize(5, 6) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding) << true << false << false << false << QSize(5, qMax(10, MagicH)); QTest::newRow("3") << QSize(5, 6) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding) << false << true << false << false << QSize(35, 26); QTest::newRow("4") << QSize(5, 6) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding) << false << true << true << false << QSize(35, 70); QTest::newRow("5") << QSize(40001, 30001) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding) << false << false << false << false << QSize(100000, 100000); QTest::newRow("6") << QSize(40001, 30001) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding) << true << false << false << false << QSize(100000, 100000); QTest::newRow("7") << QSize(40001, 30001) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding) << false << true << false << false << QSize(100000, 100000); QTest::newRow("8") << QSize(40001, 30001) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding) << false << true << true << false << QSize(100000, 100000); QTest::newRow("9") << QSize(5, 6) << int(QSizePolicy::Expanding) << int(QSizePolicy::Minimum) << true << false << false << false << QSize(qMax(5, MagicW), 10); QTest::newRow("1c") << QSize(5, 6) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding) << false << false << false << true << QSize(5, 6); QTest::newRow("2c") << QSize(5, 6) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding) << true << false << false << true << QSize(5, 6 /* or 10 would be OK too, since hfw contradicts sizeHint() */); QTest::newRow("3c") << QSize(5, 6) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding) << false << true << false << true << QSize(35, 26); QTest::newRow("4c") << QSize(5, 6) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding) << false << true << true << true << QSize(35, 70); QTest::newRow("5c") << QSize(40001, 30001) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding) << false << false << false << true << QSize(40001, 30001); QTest::newRow("6c") << QSize(40001, 30001) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding) << true << false << false << true << QSize(40001, 30001 /* or 80002 would be OK too, since hfw contradicts sizeHint() */); QTest::newRow("7c") << QSize(40001, 30001) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding) << false << true << false << true << QSize(40001 + 30, 30001 + 20); QTest::newRow("8c") << QSize(40001, 30001) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding) << false << true << true << true << QSize(40001 + 30, 80002 + 60); QTest::newRow("9c") << QSize(5, 6) << int(QSizePolicy::Expanding) << int(QSizePolicy::Minimum) << true << false << false << true << QSize(5, 6); } void tst_QWidget::adjustSize() { QFETCH(QSize, sizeHint); QFETCH(int, hPolicy); QFETCH(int, vPolicy); QFETCH(bool, hfwSP); QFETCH(bool, layout); QFETCH(bool, hfwLayout); QFETCH(bool, haveParent); QFETCH(QSize, expectedSize); QWidget *parent = new QWidget; QSizePolicy sp = QSizePolicy(QSizePolicy::Policy(hPolicy), QSizePolicy::Policy(vPolicy)); sp.setHeightForWidth(hfwSP); QWidget *child = new ASWidget(sizeHint, sp, layout, hfwLayout, haveParent ? parent : 0); child->resize(123, 456); child->adjustSize(); if (expectedSize == QSize(100000, 100000)) { QVERIFY(child->size().width() < sizeHint.width()); QVERIFY(child->size().height() < sizeHint.height()); } else { #if defined (Q_OS_WINCE) if (!haveParent) { const QRect& desktopRect = qApp->desktop()->availableGeometry(); expectedSize.setWidth(qMin(expectedSize.width(), desktopRect.width())); expectedSize.setHeight(qMin(expectedSize.height(), desktopRect.height())); } #endif QCOMPARE(child->size(), expectedSize); } delete parent; } class TestLayout : public QVBoxLayout { Q_OBJECT public: TestLayout(QWidget *w = 0) : QVBoxLayout(w) { invalidated = false; } void invalidate() { invalidated = true; } bool invalidated; }; void tst_QWidget::updateGeometry_data() { QTest::addColumn("minSize"); QTest::addColumn("shouldInvalidate"); QTest::addColumn("maxSize"); QTest::addColumn("shouldInvalidate2"); QTest::addColumn("verticalSizePolicy"); QTest::addColumn("shouldInvalidate3"); QTest::addColumn("setVisible"); QTest::addColumn("shouldInvalidate4"); QTest::newRow("setMinimumSize") << QSize(100, 100) << true << QSize() << false << int(QSizePolicy::Preferred) << false << true << false; QTest::newRow("setMaximumSize") << QSize() << false << QSize(100, 100) << true << int(QSizePolicy::Preferred) << false << true << false; QTest::newRow("setMinimumSize, then maximumSize to a different size") << QSize(100, 100) << true << QSize(300, 300) << true << int(QSizePolicy::Preferred) << false << true << false; QTest::newRow("setMinimumSize, then maximumSize to the same size") << QSize(100, 100) << true << QSize(100, 100) << true << int(QSizePolicy::Preferred) << false << true << false; QTest::newRow("setMinimumSize, then maximumSize to the same size and then hide it") << QSize(100, 100) << true << QSize(100, 100) << true << int(QSizePolicy::Preferred) << false << false << true; QTest::newRow("Change sizePolicy") << QSize() << false << QSize() << false << int(QSizePolicy::Minimum) << true << true << false; } void tst_QWidget::updateGeometry() { QFETCH(QSize, minSize); QFETCH(bool, shouldInvalidate); QFETCH(QSize, maxSize); QFETCH(bool, shouldInvalidate2); QFETCH(int, verticalSizePolicy); QFETCH(bool, shouldInvalidate3); QFETCH(bool, setVisible); QFETCH(bool, shouldInvalidate4); QWidget parent; parent.resize(200, 200); TestLayout *lout = new TestLayout(); parent.setLayout(lout); QWidget *child = new QWidget(&parent); lout->addWidget(child); parent.show(); QApplication::processEvents(); lout->invalidated = false; if (minSize.isValid()) child->setMinimumSize(minSize); QCOMPARE(lout->invalidated, shouldInvalidate); lout->invalidated = false; if (maxSize.isValid()) child->setMaximumSize(maxSize); QCOMPARE(lout->invalidated, shouldInvalidate2); lout->invalidated = false; child->setSizePolicy(QSizePolicy(QSizePolicy::Preferred, (QSizePolicy::Policy)verticalSizePolicy)); if (shouldInvalidate3) QCOMPARE(lout->invalidated, true); lout->invalidated = false; if (!setVisible) child->setVisible(false); QCOMPARE(lout->invalidated, shouldInvalidate4); } void tst_QWidget::sendUpdateRequestImmediately() { #ifdef Q_WS_MAC if (!QApplicationPrivate::graphicsSystem()) QSKIP("We only send update requests on the Mac when passing -graphicssystem", SkipAll); #endif UpdateWidget updateWidget; updateWidget.show(); #ifdef Q_WS_X11 qt_x11_wait_for_window_manager(&updateWidget); #endif qApp->processEvents(); #ifdef Q_WS_QWS QApplication::sendPostedEvents(); //glib workaround #endif updateWidget.reset(); QCOMPARE(updateWidget.numUpdateRequestEvents, 0); updateWidget.repaint(); QCOMPARE(updateWidget.numUpdateRequestEvents, 1); } class RedirectedWidget : public QWidget { protected: void paintEvent(QPaintEvent *) { // Verify that the widget has a redirection set. The widget is redirected to // the backing store on all platforms using it; otherwise to itself if the wrect // does not start in (0, 0) or it has a mask set. QPaintDevice *oldRedirection = QPainter::redirected(this); #ifndef Q_WS_MAC QVERIFY(oldRedirection); #endif QImage image(size(), QImage::Format_RGB32); image.fill(Qt::blue); { QPainter painter(this); QCOMPARE(painter.device(), static_cast(this)); } QPainter::setRedirected(this, &image); QCOMPARE(QPainter::redirected(this), static_cast(&image)); QPainter painter(this); painter.fillRect(rect(), Qt::red); QPainter::restoreRedirected(this); QCOMPARE(QPainter::redirected(this), oldRedirection); for (int i = 0; i < image.height(); ++i) for (int j = 0; j < image.width(); ++j) QCOMPARE(image.pixel(j, i), QColor(Qt::red).rgb()); } }; // Test to make sure we're compatible in the particular case where QPainter::setRedirected // actually works. It has been broken for all other cases since Qt 4.1.4 (backing store). // QWidget::render is the modern and more powerful way of doing the same. void tst_QWidget::painterRedirection() { RedirectedWidget widget; // Set FramelessWindowHint and mask to trigger internal painter redirection on the Mac. widget.setWindowFlags(widget.windowFlags() | Qt::FramelessWindowHint); widget.setMask(QRect(10, 10, 50, 50)); widget.setFixedSize(100, 200); widget.show(); #ifdef Q_WS_X11 qt_x11_wait_for_window_manager(&widget); #endif QPixmap pixmap(widget.size()); QPainter::setRedirected(&widget, &pixmap, QPoint()); widget.repaint(); QCOMPARE(QPainter::redirected(&widget), static_cast(&pixmap)); } void tst_QWidget::doubleRepaint() { #ifdef Q_OS_IRIX QSKIP("4DWM issues on IRIX makes this test fail", SkipAll); #elif defined(Q_WS_MAC) if (!macHasAccessToWindowsServer()) QSKIP("Not having window server access causes the wrong number of repaints to be issues", SkipAll); #endif UpdateWidget widget; widget.setFocusPolicy(Qt::StrongFocus); // Filter out activation change and focus events to avoid update() calls in QWidget. widget.updateOnActivationChangeAndFocusIn = false; // Show: 1 repaint int expectedRepaints = 1; widget.show(); QTest::qWait(1000); QCOMPARE(widget.numPaintEvents, expectedRepaints); widget.numPaintEvents = 0; #ifndef Q_OS_WINCE //still no proper minimizing // Minmize: Should not trigger a repaint. widget.showMinimized(); #else // Hide: Should not trigger a repaint. widget.hide(); #endif QTest::qWait(1000); QCOMPARE(widget.numPaintEvents, 0); widget.numPaintEvents = 0; // Restore: Should not trigger a repaint. widget.showNormal(); QTest::qWait(1000); #ifndef Q_OS_WINCE QCOMPARE(widget.numPaintEvents, 0); #else // We called hide(), and then it'll get repainted once it's shown again. QCOMPARE(widget.numPaintEvents, 1); #endif } #ifndef Q_WS_MAC // This test only makes sense on the Mac when passing -graphicssystem. void tst_QWidget::resizeInPaintEvent() { QWidget window; UpdateWidget widget(&window); window.show(); #ifdef Q_WS_X11 qt_x11_wait_for_window_manager(&window); #endif QTest::qWait(100); widget.reset(); QCOMPARE(widget.numPaintEvents, 0); widget.resizeInPaintEvent = true; // This will call resize in the paintEvent, which in turn will call // invalidateBuffer() and a new update request should be posted. widget.repaint(); QCOMPARE(widget.numPaintEvents, 1); widget.numPaintEvents = 0; QTest::qWait(100); // Make sure the resize triggers another update. QCOMPARE(widget.numPaintEvents, 1); } #endif class MaskSetWidget : public QWidget { Q_OBJECT public: MaskSetWidget(QWidget* p =0) : QWidget(p) {} void paintEvent(QPaintEvent* event) { QPainter p(this); paintedRegion += event->region(); foreach(QRect r, event->region().rects()) p.fillRect(r, Qt::red); } void resizeEvent(QResizeEvent*) { setMask(QRegion(QRect(0, 0, width(), 10).normalized())); } QRegion paintedRegion; public slots: void resizeDown() { setGeometry(QRect(0, 50, 50, 50)); } void resizeUp() { setGeometry(QRect(0, 50, 150, 50)); } }; void tst_QWidget::setMaskInResizeEvent() { UpdateWidget w; w.resize(200, 200); w.setWindowFlags(Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint); w.raise(); MaskSetWidget testWidget(&w); testWidget.setGeometry(0, 0, 100, 100); testWidget.setMask(QRegion(QRect(0,0,100,10))); testWidget.show(); w.show(); QTest::qWait(800); w.reset(); testWidget.paintedRegion = QRegion(); QTimer::singleShot(0, &testWidget, SLOT(resizeDown())); QTest::qWait(100); QRegion expectedParentUpdate(0, 0, 100, 10); // Old testWidget area. expectedParentUpdate += testWidget.geometry(); // New testWidget area. QCOMPARE(w.paintedRegion, expectedParentUpdate); QCOMPARE(testWidget.paintedRegion, testWidget.mask()); testWidget.paintedRegion = QRegion(); // Now resize the widget again, but in the oposite direction QTimer::singleShot(0, &testWidget, SLOT(resizeUp())); QTest::qWait(300); QCOMPARE(testWidget.paintedRegion, testWidget.mask()); } class MoveInResizeWidget : public QWidget { Q_OBJECT public: MoveInResizeWidget(QWidget* p = 0) : QWidget(p) { setWindowFlags(Qt::FramelessWindowHint); } void resizeEvent(QResizeEvent*) { move(QPoint(100,100)); static bool firstTime = true; if (firstTime) QTimer::singleShot(100, this, SLOT(resizeMe())); firstTime = false; } public slots: void resizeMe() { resize(100, 100); } }; void tst_QWidget::moveInResizeEvent() { MoveInResizeWidget testWidget; testWidget.setGeometry(50, 50, 200, 200); testWidget.show(); #ifdef Q_WS_X11 qt_x11_wait_for_window_manager(&testWidget); #endif QTest::qWait(500); QRect expectedGeometry(100,100, 100, 100); QCOMPARE(testWidget.geometry(), expectedGeometry); } #if defined(Q_WS_WIN) || defined(Q_WS_X11) void tst_QWidget::immediateRepaintAfterShow() { UpdateWidget widget; widget.show(); qApp->processEvents(); // On X11 in particular, we are now waiting for a MapNotify event before // syncing the backing store. However, if someone request a repaint() // we must repaint immediately regardless of the current state. widget.numPaintEvents = 0; widget.repaint(); QCOMPARE(widget.numPaintEvents, 1); } void tst_QWidget::immediateRepaintAfterInvalidateBuffer() { QWidget *widget = new UpdateWidget; widget->show(); #ifdef Q_WS_X11 qt_x11_wait_for_window_manager(widget); #endif QTest::qWait(200); static_cast(widget)->numPaintEvents = 0; // Marks the area covered by the widget as dirty in the backing store and // posts an UpdateRequest event. qt_widget_private(widget)->invalidateBuffer(widget->rect()); QCOMPARE(static_cast(widget)->numPaintEvents, 0); // The entire widget is already dirty, but this time we want to update immediately // by calling repaint(), and thus we have to repaint the widget and not wait for // the UpdateRequest to be sent when we get back to the event loop. widget->repaint(); QCOMPARE(static_cast(widget)->numPaintEvents, 1); delete widget; } #endif void tst_QWidget::effectiveWinId() { QWidget parent; QWidget child(&parent); // Shouldn't crash. QVERIFY(!parent.effectiveWinId()); QVERIFY(!child.effectiveWinId()); parent.show(); QVERIFY(parent.effectiveWinId()); QVERIFY(child.effectiveWinId()); } class CustomWidget : public QWidget { public: mutable int metricCallCount; CustomWidget(QWidget *parent = 0) : QWidget(parent), metricCallCount(0) {} virtual int metric(PaintDeviceMetric metric) const { ++metricCallCount; return QWidget::metric(metric); } }; void tst_QWidget::customDpi() { QWidget *topLevel = new QWidget; CustomWidget *custom = new CustomWidget(topLevel); QWidget *child = new QWidget(custom); custom->metricCallCount = 0; topLevel->logicalDpiX(); QCOMPARE(custom->metricCallCount, 0); custom->logicalDpiX(); QCOMPARE(custom->metricCallCount, 1); child->logicalDpiX(); QCOMPARE(custom->metricCallCount, 2); delete topLevel; } void tst_QWidget::customDpiProperty() { QWidget *topLevel = new QWidget; QWidget *middle = new CustomWidget(topLevel); QWidget *child = new QWidget(middle); const int initialDpiX = topLevel->logicalDpiX(); const int initialDpiY = topLevel->logicalDpiY(); middle->setProperty("_q_customDpiX", 300); middle->setProperty("_q_customDpiY", 400); QCOMPARE(topLevel->logicalDpiX(), initialDpiX); QCOMPARE(topLevel->logicalDpiY(), initialDpiY); QCOMPARE(middle->logicalDpiX(), 300); QCOMPARE(middle->logicalDpiY(), 400); QCOMPARE(child->logicalDpiX(), 300); QCOMPARE(child->logicalDpiY(), 400); middle->setProperty("_q_customDpiX", QVariant()); middle->setProperty("_q_customDpiY", QVariant()); QCOMPARE(topLevel->logicalDpiX(), initialDpiX); QCOMPARE(topLevel->logicalDpiY(), initialDpiY); QCOMPARE(middle->logicalDpiX(), initialDpiX); QCOMPARE(middle->logicalDpiY(), initialDpiY); QCOMPARE(child->logicalDpiX(), initialDpiX); QCOMPARE(child->logicalDpiY(), initialDpiY); delete topLevel; } void tst_QWidget::quitOnCloseAttribute() { QWidget w; QCOMPARE(w.testAttribute(Qt::WA_QuitOnClose), true); w.setAttribute(Qt::WA_QuitOnClose, false); QCOMPARE(w.testAttribute(Qt::WA_QuitOnClose), false); w.setAttribute(Qt::WA_QuitOnClose); w.setWindowFlags(Qt::Tool); QCOMPARE(w.testAttribute(Qt::WA_QuitOnClose), false); w.setAttribute(Qt::WA_QuitOnClose); w.setWindowFlags(Qt::Popup); QCOMPARE(w.testAttribute(Qt::WA_QuitOnClose), false); w.setAttribute(Qt::WA_QuitOnClose); w.setWindowFlags(Qt::ToolTip); QCOMPARE(w.testAttribute(Qt::WA_QuitOnClose), false); w.setAttribute(Qt::WA_QuitOnClose); w.setWindowFlags(Qt::SplashScreen); QCOMPARE(w.testAttribute(Qt::WA_QuitOnClose), false); w.setAttribute(Qt::WA_QuitOnClose); w.setWindowFlags(Qt::SubWindow); QCOMPARE(w.testAttribute(Qt::WA_QuitOnClose), false); w.setAttribute(Qt::WA_QuitOnClose); w.setWindowFlags(Qt::Dialog); QCOMPARE(w.testAttribute(Qt::WA_QuitOnClose), true); w.show(); QCOMPARE(w.testAttribute(Qt::WA_QuitOnClose), true); w.setWindowFlags(Qt::Tool); QCOMPARE(w.testAttribute(Qt::WA_QuitOnClose), false); } void tst_QWidget::moveRect() { QWidget widget; widget.setUpdatesEnabled(false); QWidget child(&widget); child.setUpdatesEnabled(false); child.setAttribute(Qt::WA_OpaquePaintEvent); widget.show(); QTest::qWait(200); child.move(10, 10); // Don't crash. } #ifdef Q_WS_WIN class GDIWidget : public QDialog { public: GDIWidget() { setAttribute(Qt::WA_PaintOnScreen); } QPaintEngine *paintEngine() const { return 0; } void paintEvent(QPaintEvent *) { HDC hdc = getDC(); SelectObject(hdc, CreateSolidBrush(RGB(255, 0, 0))); Rectangle(hdc, 0, 0, 10, 10); releaseDC(hdc); QImage im = QPixmap::grabWindow(winId(), 0, 0, width(), height()).toImage(); color = im.pixel(1, 1); accept(); } QSize sizeHint() const { return QSize(400, 300); } QColor color; }; void tst_QWidget::gdiPainting() { GDIWidget w; w.exec(); QCOMPARE(w.color, QColor(255, 0, 0)); } void tst_QWidget::paintOnScreenPossible() { QWidget w1; w1.setAttribute(Qt::WA_PaintOnScreen); QVERIFY(!w1.testAttribute(Qt::WA_PaintOnScreen)); GDIWidget w2; w2.setAttribute(Qt::WA_PaintOnScreen); QVERIFY(w2.testAttribute(Qt::WA_PaintOnScreen)); } #endif void tst_QWidget::reparentStaticWidget() { QWidget window1; QWidget *child = new QWidget(&window1); child->setPalette(Qt::red); child->setAutoFillBackground(true); child->setAttribute(Qt::WA_StaticContents); child->resize(100, 100); QWidget *grandChild = new QWidget(child); grandChild->setPalette(Qt::blue); grandChild->setAutoFillBackground(true); grandChild->resize(50, 50); grandChild->setAttribute(Qt::WA_StaticContents); window1.show(); QWidget window2; window2.show(); #ifdef Q_WS_X11 qt_x11_wait_for_window_manager(&window1); qt_x11_wait_for_window_manager(&window2); #endif QTest::qWait(200); // Reparent into another top-level. child->setParent(&window2); child->show(); // Please don't crash. window1.resize(window1.size() + QSize(2, 2)); #ifdef Q_WS_X11 qt_x11_wait_for_window_manager(&window1); #endif QTest::qWait(200); // Make sure we move all static children even though // the reparented widget itself is non-static. child->setAttribute(Qt::WA_StaticContents, false); child->setParent(&window1); child->show(); // Please don't crash. window2.resize(window2.size() + QSize(2, 2)); #ifdef Q_WS_X11 qt_x11_wait_for_window_manager(&window2); #endif QTest::qWait(200); child->setParent(0); child->show(); #ifdef Q_WS_X11 qt_x11_wait_for_window_manager(child); #endif // Please don't crash. child->resize(child->size() + QSize(2, 2)); window2.resize(window2.size() + QSize(2, 2)); #ifdef Q_WS_X11 qt_x11_wait_for_window_manager(child); qt_x11_wait_for_window_manager(&window2); #endif QTest::qWait(200); QWidget *siblingOfGrandChild = new QWidget(child); siblingOfGrandChild->show(); QTest::qWait(200); // Nothing should happen when reparenting within the same top-level. grandChild->setParent(siblingOfGrandChild); grandChild->show(); QTest::qWait(200); QWidget paintOnScreen; paintOnScreen.setAttribute(Qt::WA_PaintOnScreen); paintOnScreen.show(); #ifdef Q_WS_X11 qt_x11_wait_for_window_manager(&paintOnScreen); #endif QTest::qWait(200); child->setParent(&paintOnScreen); child->show(); QTest::qWait(200); // Please don't crash. paintOnScreen.resize(paintOnScreen.size() + QSize(2, 2)); #ifdef Q_WS_X11 qt_x11_wait_for_window_manager(&paintOnScreen); #endif QTest::qWait(200); } #ifdef Q_WS_QWS void tst_QWidget::updateOutsideSurfaceClip() { UpdateWidget widget; widget.setWindowFlags(Qt::FramelessWindowHint); widget.resize(100, 100); widget.raise(); widget.show(); QTest::qWait(200); widget.reset(); // Move widget partially outside buffer and change the surface clip. widget.move(-50, 0); QTest::qWait(100); // Update region is outside the surface clip and should not trigger a repaint. widget.update(0, 0, 20, 20); QTest::qWait(100); QCOMPARE(widget.numPaintEvents, 0); // Now, move the widget back so that the update region is inside the clip // and make sure we get a repaint of the dirty area. widget.move(0, 0); QTest::qWait(100); QCOMPARE(widget.numPaintEvents, 1); QCOMPARE(widget.paintedRegion, QRegion(0, 0, 20, 20)); } #endif class ColorRedWidget : public QWidget { public: ColorRedWidget(QWidget *parent = 0) : QWidget(parent, Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint | Qt::ToolTip) { } void paintEvent(QPaintEvent *) { QPainter p(this); p.fillRect(rect(),Qt::red); } }; void tst_QWidget::translucentWidget() { QPixmap pm(16,16); pm.fill(Qt::red); ColorRedWidget label; label.setFixedSize(16,16); label.setAttribute(Qt::WA_TranslucentBackground); label.move(qApp->desktop()->availableGeometry().topLeft()); label.show(); #ifdef Q_WS_X11 qt_x11_wait_for_window_manager(&label); #endif QTest::qWait(200); QPixmap widgetSnapshot = QPixmap::grabWindow(label.winId()); QImage actual = widgetSnapshot.toImage().convertToFormat(QImage::Format_RGB32); QImage expected = pm.toImage().convertToFormat(QImage::Format_RGB32); QCOMPARE(actual.size(),expected.size()); QCOMPARE(actual,expected); } class MaskResizeTestWidget : public QWidget { Q_OBJECT public: MaskResizeTestWidget(QWidget* p =0) : QWidget(p) { setMask(QRegion(QRect(0, 0, 100, 100).normalized())); } void paintEvent(QPaintEvent* event) { QPainter p(this); paintedRegion += event->region(); foreach(QRect r, event->region().rects()) p.fillRect(r, Qt::red); } QRegion paintedRegion; public slots: void enlargeMask() { QRegion newMask(QRect(0, 0, 150, 150).normalized()); setMask(newMask); } void shrinkMask() { QRegion newMask(QRect(0, 0, 50, 50).normalized()); setMask(newMask); } }; void tst_QWidget::setClearAndResizeMask() { UpdateWidget topLevel; topLevel.resize(150, 150); topLevel.show(); QTest::qWait(400); topLevel.reset(); // Mask top-level widget const QRegion topLevelMask(0, 0, 100, 100, QRegion::Ellipse); topLevel.setMask(topLevelMask); QCOMPARE(topLevel.mask(), topLevelMask); #ifdef Q_WS_X11 qt_x11_wait_for_window_manager(&topLevel); #endif QTest::qWait(400); #if defined(Q_WS_WIN) || defined(Q_WS_X11) // We don't control what's happening on other platforms. // and ensure that the top-level doesn't get any update. QCOMPARE(topLevel.numPaintEvents, 0); #endif topLevel.reset(); // Clear top-level mask topLevel.clearMask(); QCOMPARE(topLevel.mask(), QRegion()); #ifdef Q_WS_X11 qt_x11_wait_for_window_manager(&topLevel); #endif QTest::qWait(100); QRegion outsideOldMask(topLevel.rect()); outsideOldMask -= topLevelMask; #if defined(Q_WS_WIN) || defined(Q_WS_X11) // We don't control what's happening on other platforms. // and ensure that the top-level gets an update for the area outside the old mask. QVERIFY(topLevel.numPaintEvents > 0); QCOMPARE(topLevel.paintedRegion, outsideOldMask); #endif UpdateWidget child(&topLevel); child.setAutoFillBackground(true); // NB! Opaque child. child.resize(100, 100); child.show(); QTest::qWait(50); child.reset(); topLevel.reset(); // Mask child widget with a mask that is smaller than the rect const QRegion childMask(0, 0, 50, 50); child.setMask(childMask); QCOMPARE(child.mask(), childMask); QTest::qWait(50); // and ensure that the child widget doesn't get any update. #ifdef Q_WS_MAC // Mac always issues a full update when calling setMask, and we cannot force it to not do so. QCOMPARE(child.numPaintEvents, 1); #else QCOMPARE(child.numPaintEvents, 0); #endif // and the parent widget gets an update for the newly exposed area. QCOMPARE(topLevel.numPaintEvents, 1); QRegion expectedParentExpose(child.rect()); expectedParentExpose -= childMask; QCOMPARE(topLevel.paintedRegion, expectedParentExpose); child.reset(); topLevel.reset(); // Clear child widget mask child.clearMask(); QCOMPARE(child.mask(), QRegion()); QTest::qWait(50); // and ensure that that the child widget gets an update for the area outside the old mask. QCOMPARE(child.numPaintEvents, 1); outsideOldMask = child.rect(); #ifndef Q_WS_MAC // Mac always issues a full update when calling setMask, and we cannot force it to not do so. outsideOldMask -= childMask; #endif QCOMPARE(child.paintedRegion, outsideOldMask); // and the parent widget doesn't get any update. QCOMPARE(topLevel.numPaintEvents, 0); child.reset(); topLevel.reset(); // Mask child widget with a mask that is bigger than the rect child.setMask(QRegion(0, 0, 1000, 1000)); QTest::qWait(50); #ifdef Q_WS_MAC // Mac always issues a full update when calling setMask, and we cannot force it to not do so. QCOMPARE(child.numPaintEvents, 1); #else // and ensure that we don't get any updates at all. QCOMPARE(child.numPaintEvents, 0); #endif QCOMPARE(topLevel.numPaintEvents, 0); // ...and the same applies when clearing the mask. child.clearMask(); QTest::qWait(50); #ifdef Q_WS_MAC // Mac always issues a full update when calling setMask, and we cannot force it to not do so. QVERIFY(child.numPaintEvents > 0); #else QCOMPARE(child.numPaintEvents, 0); #endif QCOMPARE(topLevel.numPaintEvents, 0); QWidget resizeParent; MaskResizeTestWidget resizeChild(&resizeParent); resizeParent.resize(300,300); resizeParent.raise(); resizeParent.setWindowFlags(Qt::WindowStaysOnTopHint); resizeChild.setGeometry(50,50,200,200); QPalette pal = resizeParent.palette(); pal.setColor(QPalette::Window, QColor(Qt::white)); resizeParent.setPalette(pal); resizeParent.show(); // Disable the size grip on the Mac; otherwise it'll be included when grabbing the window. resizeParent.setFixedSize(resizeParent.size()); resizeChild.show(); #ifdef Q_WS_X11 qt_x11_wait_for_window_manager(&resizeParent); #endif QTest::qWait(500); resizeChild.paintedRegion = QRegion(); QTimer::singleShot(100, &resizeChild, SLOT(shrinkMask())); QTest::qWait(200); #ifdef Q_WS_MAC // Mac always issues a full update when calling setMask, and we cannot force it to not do so. QCOMPARE(resizeChild.paintedRegion, resizeChild.mask()); #else QCOMPARE(resizeChild.paintedRegion, QRegion()); #endif resizeChild.paintedRegion = QRegion(); const QRegion oldMask = resizeChild.mask(); QTimer::singleShot(0, &resizeChild, SLOT(enlargeMask())); QTest::qWait(100); #ifdef Q_WS_MAC // Mac always issues a full update when calling setMask, and we cannot force it to not do so. QCOMPARE(resizeChild.paintedRegion, resizeChild.mask()); #else QCOMPARE(resizeChild.paintedRegion, resizeChild.mask() - oldMask); #endif } void tst_QWidget::maskedUpdate() { UpdateWidget topLevel; topLevel.resize(200, 200); const QRegion topLevelMask(50, 50, 70, 70); topLevel.setMask(topLevelMask); UpdateWidget child(&topLevel); child.setGeometry(20, 20, 180, 180); const QRegion childMask(60, 60, 30, 30); child.setMask(childMask); UpdateWidget grandChild(&child); grandChild.setGeometry(50, 50, 100, 100); const QRegion grandChildMask(20, 20, 10, 10); grandChild.setMask(grandChildMask); topLevel.show(); #ifdef Q_WS_X11 qt_x11_wait_for_window_manager(&topLevel); #endif QTest::qWait(200); #define RESET_WIDGETS \ topLevel.reset(); \ child.reset(); \ grandChild.reset(); #define CLEAR_MASK(widget) \ widget.clearMask(); \ QTest::qWait(100); \ RESET_WIDGETS; // All widgets are transparent at this point, so any call to update() will result // in composition, i.e. the update propagates to ancestors and children. // TopLevel update. RESET_WIDGETS; topLevel.update(); QTest::qWait(100); QCOMPARE(topLevel.paintedRegion, topLevelMask); QCOMPARE(child.paintedRegion, childMask); QCOMPARE(grandChild.paintedRegion, grandChildMask); // Child update. RESET_WIDGETS; child.update(); QTest::qWait(100); QCOMPARE(topLevel.paintedRegion, childMask.translated(child.pos())); QCOMPARE(child.paintedRegion, childMask); QCOMPARE(grandChild.paintedRegion, grandChildMask); // GrandChild update. RESET_WIDGETS; grandChild.update(); QTest::qWait(100); QCOMPARE(topLevel.paintedRegion, grandChildMask.translated(grandChild.mapTo(&topLevel, QPoint()))); QCOMPARE(child.paintedRegion, grandChildMask.translated(grandChild.pos())); QCOMPARE(grandChild.paintedRegion, grandChildMask); topLevel.setAttribute(Qt::WA_OpaquePaintEvent); child.setAttribute(Qt::WA_OpaquePaintEvent); grandChild.setAttribute(Qt::WA_OpaquePaintEvent); // All widgets are now opaque, which means no composition, i.e. // the update does not propate to ancestors and children. // TopLevel update. RESET_WIDGETS; topLevel.update(); QTest::qWait(100); QRegion expectedTopLevelUpdate = topLevelMask; expectedTopLevelUpdate -= childMask.translated(child.pos()); // Subtract opaque children. QCOMPARE(topLevel.paintedRegion, expectedTopLevelUpdate); QCOMPARE(child.paintedRegion, QRegion()); QCOMPARE(grandChild.paintedRegion, QRegion()); // Child update. RESET_WIDGETS; child.update(); QTest::qWait(100); QCOMPARE(topLevel.paintedRegion, QRegion()); QRegion expectedChildUpdate = childMask; expectedChildUpdate -= grandChildMask.translated(grandChild.pos()); // Subtract oapque children. QCOMPARE(child.paintedRegion, expectedChildUpdate); QCOMPARE(grandChild.paintedRegion, QRegion()); // GrandChild update. RESET_WIDGETS; grandChild.update(); QTest::qWait(100); QCOMPARE(topLevel.paintedRegion, QRegion()); QCOMPARE(child.paintedRegion, QRegion()); QCOMPARE(grandChild.paintedRegion, grandChildMask); // GrandChild update. CLEAR_MASK(grandChild); grandChild.update(); QTest::qWait(100); QCOMPARE(topLevel.paintedRegion, QRegion()); QCOMPARE(child.paintedRegion, QRegion()); QRegion expectedGrandChildUpdate = grandChild.rect(); // Clip with parent's mask. expectedGrandChildUpdate &= childMask.translated(-grandChild.pos()); QCOMPARE(grandChild.paintedRegion, expectedGrandChildUpdate); // GrandChild update. CLEAR_MASK(child); grandChild.update(); QTest::qWait(100); QCOMPARE(topLevel.paintedRegion, QRegion()); QCOMPARE(child.paintedRegion, QRegion()); expectedGrandChildUpdate = grandChild.rect(); // Clip with parent's mask. expectedGrandChildUpdate &= topLevelMask.translated(-grandChild.mapTo(&topLevel, QPoint())); QCOMPARE(grandChild.paintedRegion, expectedGrandChildUpdate); // Child update. RESET_WIDGETS; child.update(); QTest::qWait(100); QCOMPARE(topLevel.paintedRegion, QRegion()); expectedChildUpdate = child.rect(); // Clip with parent's mask. expectedChildUpdate &= topLevelMask.translated(-child.pos()); expectedChildUpdate -= grandChild.geometry(); // Subtract opaque children. QCOMPARE(child.paintedRegion, expectedChildUpdate); QCOMPARE(grandChild.paintedRegion, QRegion()); // GrandChild update. CLEAR_MASK(topLevel); grandChild.update(); QTest::qWait(100); QCOMPARE(topLevel.paintedRegion, QRegion()); QCOMPARE(child.paintedRegion, QRegion()); QCOMPARE(grandChild.paintedRegion, QRegion(grandChild.rect())); // Full update. } #if defined(Q_WS_X11) || defined(Q_WS_WIN) void tst_QWidget::syntheticEnterLeave() { class MyWidget : public QWidget { public: MyWidget(QWidget *parent = 0) : QWidget(parent), numEnterEvents(0), numLeaveEvents(0) {} void enterEvent(QEvent *) { ++numEnterEvents; } void leaveEvent(QEvent *) { ++numLeaveEvents; } int numEnterEvents; int numLeaveEvents; }; MyWidget window; window.setWindowFlags(Qt::WindowStaysOnTopHint); window.resize(200, 200); MyWidget *child1 = new MyWidget(&window); child1->setPalette(Qt::blue); child1->setAutoFillBackground(true); child1->resize(200, 200); child1->setCursor(Qt::OpenHandCursor); MyWidget *child2 = new MyWidget(&window); child2->resize(200, 200); MyWidget *grandChild = new MyWidget(child2); grandChild->setPalette(Qt::red); grandChild->setAutoFillBackground(true); grandChild->resize(200, 200); grandChild->setCursor(Qt::WaitCursor); window.show(); window.raise(); #ifdef Q_WS_X11 qt_x11_wait_for_window_manager(&window); #endif QTest::qWait(300); #define RESET_EVENT_COUNTS \ window.numEnterEvents = 0; \ window.numLeaveEvents = 0; \ child1->numEnterEvents = 0; \ child1->numLeaveEvents = 0; \ child2->numEnterEvents = 0; \ child2->numLeaveEvents = 0; \ grandChild->numEnterEvents = 0; \ grandChild->numLeaveEvents = 0; // Position the cursor in the middle of the window. const QPoint globalPos = window.mapToGlobal(QPoint(100, 100)); QCursor::setPos(globalPos); // Enter child2 and grandChild. QTest::qWait(300); #ifdef Q_OS_WINCE_WM QSKIP("Windows Mobile has no proper cursor support", SkipAll); #endif QCOMPARE(window.numLeaveEvents, 0); QCOMPARE(child2->numLeaveEvents, 0); QCOMPARE(grandChild->numLeaveEvents, 0); QCOMPARE(child1->numLeaveEvents, 0); QCOMPARE(window.numEnterEvents, 1); QCOMPARE(child2->numEnterEvents, 1); QCOMPARE(grandChild->numEnterEvents, 1); QCOMPARE(child1->numEnterEvents, 0); RESET_EVENT_COUNTS; child2->hide(); // Leave child2 and grandChild, enter child1. QCOMPARE(window.numLeaveEvents, 0); QCOMPARE(child2->numLeaveEvents, 1); QCOMPARE(grandChild->numLeaveEvents, 1); QCOMPARE(child1->numLeaveEvents, 0); QCOMPARE(window.numEnterEvents, 0); QCOMPARE(child2->numEnterEvents, 0); QCOMPARE(grandChild->numEnterEvents, 0); QCOMPARE(child1->numEnterEvents, 1); RESET_EVENT_COUNTS; child2->show(); // Leave child1, enter child2 and grandChild. QCOMPARE(window.numLeaveEvents, 0); QCOMPARE(child2->numLeaveEvents, 0); QCOMPARE(grandChild->numLeaveEvents, 0); QCOMPARE(child1->numLeaveEvents, 1); QCOMPARE(window.numEnterEvents, 0); QCOMPARE(child2->numEnterEvents, 1); QCOMPARE(grandChild->numEnterEvents, 1); QCOMPARE(child1->numEnterEvents, 0); RESET_EVENT_COUNTS; delete child2; // Enter child1 (and do not send leave events to child2 and grandChild). QCOMPARE(window.numLeaveEvents, 0); QCOMPARE(child1->numLeaveEvents, 0); QCOMPARE(window.numEnterEvents, 0); QCOMPARE(child1->numEnterEvents, 1); } #endif void tst_QWidget::windowFlags() { QWidget w; w.setWindowFlags(w.windowFlags() | Qt::FramelessWindowHint); QVERIFY(w.windowFlags() & Qt::FramelessWindowHint); } void tst_QWidget::initialPosForDontShowOnScreenWidgets() { { // Check default position. const QPoint expectedPos(0, 0); QWidget widget; widget.setAttribute(Qt::WA_DontShowOnScreen); widget.winId(); // Make sure create_sys is called. QCOMPARE(widget.pos(), expectedPos); QCOMPARE(widget.geometry().topLeft(), expectedPos); } { // Explicitly move to a position. const QPoint expectedPos(100, 100); QWidget widget; widget.setAttribute(Qt::WA_DontShowOnScreen); widget.move(expectedPos); widget.winId(); // Make sure create_sys is called. QCOMPARE(widget.pos(), expectedPos); QCOMPARE(widget.geometry().topLeft(), expectedPos); } } #ifdef Q_WS_X11 void tst_QWidget::paintOutsidePaintEvent() { QWidget widget; widget.resize(200, 200); QWidget child1(&widget); child1.resize(100, 100); child1.setPalette(Qt::red); child1.setAutoFillBackground(true); QWidget child2(&widget); child2.setGeometry(50, 50, 100, 100); child2.setPalette(Qt::blue); child2.setAutoFillBackground(true); widget.show(); qt_x11_wait_for_window_manager(&widget); QTest::qWait(200); const QPixmap before = QPixmap::grabWindow(widget.winId()); // Child 1 should be clipped by child 2, so nothing should change. child1.setAttribute(Qt::WA_PaintOutsidePaintEvent); QPainter painter(&child1); painter.fillRect(child1.rect(), Qt::red); painter.end(); XSync(QX11Info::display(), false); // Flush output buffer. const QPixmap after = QPixmap::grabWindow(widget.winId()); QCOMPARE(before, after); } #endif class MyEvilObject : public QObject { Q_OBJECT public: MyEvilObject(QWidget *widgetToCrash) : QObject(), widget(widgetToCrash) { connect(widget, SIGNAL(destroyed(QObject *)), this, SLOT(beEvil(QObject *))); delete widget; } QWidget *widget; private slots: void beEvil(QObject *) { widget->update(0, 0, 150, 150); } }; void tst_QWidget::updateOnDestroyedSignal() { QWidget widget; QWidget *child = new QWidget(&widget); child->resize(100, 100); child->setAutoFillBackground(true); child->setPalette(Qt::red); widget.show(); #ifdef Q_WS_X11 qt_x11_wait_for_window_manager(&widget); #endif QTest::qWait(200); // Please do not crash. MyEvilObject evil(child); QTest::qWait(200); } void tst_QWidget::toplevelLineEditFocus() { testWidget->hide(); QLineEdit w; w.show(); #ifdef Q_WS_X11 qt_x11_wait_for_window_manager(&w); #endif QTest::qWait(200); QCOMPARE(QApplication::activeWindow(), &w); QCOMPARE(QApplication::focusWidget(), &w); } void tst_QWidget::focusWidget_task254563() { //having different visibility for widget is important QWidget top; top.show(); QWidget container(&top); QWidget *widget = new QWidget(&container); widget->show(); widget->setFocus(); //set focus (will set the focus widget up to the toplevel to be 'widget') container.setFocus(); delete widget; // will call clearFocus but that doesn't help QVERIFY(top.focusWidget() != widget); //dangling pointer } QTEST_MAIN(tst_QWidget) #include "tst_qwidget.moc"