diff options
author | Lars Knoll <lars.knoll@nokia.com> | 2009-03-23 09:18:55 (GMT) |
---|---|---|
committer | Simon Hausmann <simon.hausmann@nokia.com> | 2009-03-23 09:18:55 (GMT) |
commit | e5fcad302d86d316390c6b0f62759a067313e8a9 (patch) | |
tree | c2afbf6f1066b6ce261f14341cf6d310e5595bc1 /tests/auto/macgui | |
download | Qt-e5fcad302d86d316390c6b0f62759a067313e8a9.zip Qt-e5fcad302d86d316390c6b0f62759a067313e8a9.tar.gz Qt-e5fcad302d86d316390c6b0f62759a067313e8a9.tar.bz2 |
Long live Qt 4.5!
Diffstat (limited to 'tests/auto/macgui')
-rw-r--r-- | tests/auto/macgui/.gitignore | 1 | ||||
-rw-r--r-- | tests/auto/macgui/guitest.cpp | 350 | ||||
-rw-r--r-- | tests/auto/macgui/guitest.h | 186 | ||||
-rw-r--r-- | tests/auto/macgui/macgui.pro | 15 | ||||
-rw-r--r-- | tests/auto/macgui/tst_gui.cpp | 282 |
5 files changed, 834 insertions, 0 deletions
diff --git a/tests/auto/macgui/.gitignore b/tests/auto/macgui/.gitignore new file mode 100644 index 0000000..2b13357 --- /dev/null +++ b/tests/auto/macgui/.gitignore @@ -0,0 +1 @@ +tst_macgui diff --git a/tests/auto/macgui/guitest.cpp b/tests/auto/macgui/guitest.cpp new file mode 100644 index 0000000..49f726c --- /dev/null +++ b/tests/auto/macgui/guitest.cpp @@ -0,0 +1,350 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + + +#include "guitest.h" +#include <QDebug> +#include <QWidget> +#include <QStack> +#include <QTimer> +#include <QtTest/QtTest> + +#ifdef Q_OS_MAC +# include <private/qt_mac_p.h> +#endif + + +/* + Not really a test, just prints interface info. +*/ +class PrintTest : public TestBase +{ +public: + bool operator()(InterfaceChildPair candidate) + { + qDebug() << ""; + qDebug() << "Name" << candidate.iface->text(QAccessible::Name, candidate.possibleChild); + qDebug() << "Pos" << candidate.iface->rect(candidate.possibleChild); + if (candidate.possibleChild == 0) + qDebug() << "Number of children" << candidate.iface->childCount(); + return false; + } +}; + +class NameTest : public TestBase +{ +public: + NameTest(const QString &text, QAccessible::Text textType) : text(text), textType(textType) {} + QString text; + QAccessible::Text textType; + + bool operator()(InterfaceChildPair candidate) + { + return (candidate.iface->text(textType, candidate.possibleChild) == text); + } +}; + +void WidgetNavigator::printAll(QWidget *widget) +{ + QAccessibleInterface * const iface = QAccessible::queryAccessibleInterface(widget); + deleteInDestructor(iface); + printAll(InterfaceChildPair(iface, 0)); +} + +void WidgetNavigator::printAll(InterfaceChildPair interface) +{ + PrintTest printTest; + recursiveSearch(&printTest, interface.iface, interface.possibleChild); +} + +InterfaceChildPair WidgetNavigator::find(QAccessible::Text textType, const QString &text, QWidget *start) +{ + QAccessibleInterface * const iface = QAccessible::queryAccessibleInterface(start); + deleteInDestructor(iface); + return find(textType, text, iface); +} + +InterfaceChildPair WidgetNavigator::find(QAccessible::Text textType, const QString &text, QAccessibleInterface *start) +{ + NameTest nameTest(text, textType); + return recursiveSearch(&nameTest, start, 0); +} + +/* + Recursiveley navigates the accessible hiearchy looking for an interfafce that + passsed the Test (meaning it returns true). +*/ +InterfaceChildPair WidgetNavigator::recursiveSearch(TestBase *test, QAccessibleInterface *iface, int possibleChild) +{ + QStack<InterfaceChildPair> todoInterfaces; + todoInterfaces.push(InterfaceChildPair(iface, possibleChild)); + + while (todoInterfaces.isEmpty() == false) { + InterfaceChildPair testInterface = todoInterfaces.pop(); + + if ((*test)(testInterface)) + return testInterface; + + if (testInterface.possibleChild != 0) + continue; + + const int numChildren = testInterface.iface->childCount(); + for (int i = 0; i < numChildren; ++i) { + QAccessibleInterface *childInterface = 0; + int newPossibleChild = testInterface.iface->navigate(QAccessible::Child, i + 1, &childInterface); + if (childInterface) { + todoInterfaces.push(InterfaceChildPair(childInterface, newPossibleChild)); + deleteInDestructor(childInterface); + } else if (newPossibleChild != -1) { + todoInterfaces.push(InterfaceChildPair(testInterface.iface, newPossibleChild)); + } + } + } + return InterfaceChildPair(); +} + +void WidgetNavigator::deleteInDestructor(QAccessibleInterface * interface) +{ + interfaces.insert(interface); +} + +QWidget *WidgetNavigator::getWidget(InterfaceChildPair interface) +{ + return qobject_cast<QWidget *>(interface.iface->object()); +} + +WidgetNavigator::~WidgetNavigator() +{ + foreach(QAccessibleInterface *interface, interfaces) { + delete interface; + } +} + +/////////////////////////////////////////////////////////////////////////////// + +namespace NativeEvents { +#ifdef Q_OS_MAC + void mouseClick(const QPoint &globalPos, Qt::MouseButtons buttons, MousePosition updateMouse) + { + CGPoint position; + position.x = globalPos.x(); + position.y = globalPos.y(); + + const bool updateMousePosition = (updateMouse == UpdatePosition); + + // Mouse down. + CGPostMouseEvent(position, updateMousePosition, 3, + (buttons & Qt::LeftButton) ? true : false, + (buttons & Qt::MidButton/* Middlebutton! */) ? true : false, + (buttons & Qt::RightButton) ? true : false); + + // Mouse up. + CGPostMouseEvent(position, updateMousePosition, 3, false, false, false); + } +#else +# error Oops, NativeEvents::mouseClick() is not implemented on this platform. +#endif +}; + +/////////////////////////////////////////////////////////////////////////////// + +GuiTester::GuiTester() +{ + clearSequence(); +} + +GuiTester::~GuiTester() +{ + foreach(DelayedAction *action, actions) + delete action; +} + +bool checkPixel(QColor pixel, QColor expected) +{ + const int allowedDiff = 20; + + return !(qAbs(pixel.red() - expected.red()) > allowedDiff || + qAbs(pixel.green() - expected.green()) > allowedDiff || + qAbs(pixel.blue() - expected.blue()) > allowedDiff); +} + +/* + Tests that the pixels inside rect in image all have the given color. +*/ +bool GuiTester::isFilled(const QImage image, const QRect &rect, const QColor &color) +{ + for (int y = rect.top(); y <= rect.bottom(); ++y) + for (int x = rect.left(); x <= rect.right(); ++x) { + const QColor pixel = image.pixel(x, y); + if (checkPixel(pixel, color) == false) { +// qDebug()<< "Wrong pixel value at" << x << y << pixel.red() << pixel.green() << pixel.blue(); + return false; + } + } + return true; +} + + +/* + Tests that stuff is painted to the pixels inside rect. + This test fails if any lines in the given direction have pixels + of only one color. +*/ +bool GuiTester::isContent(const QImage image, const QRect &rect, Directions directions) +{ + if (directions & Horizontal) { + for (int y = rect.top(); y <= rect.bottom(); ++y) { + QColor currentColor = image.pixel(rect.left(), y); + bool fullRun = true; + for (int x = rect.left() + 1; x <= rect.right(); ++x) { + if (checkPixel(image.pixel(x, y), currentColor) == false) { + fullRun = false; + break; + } + } + if (fullRun) { +// qDebug() << "Single-color line at horizontal line " << y << currentColor; + return false; + } + } + return true; + } + + if (directions & Vertical) { + for (int x = rect.left(); x <= rect.right(); ++x) { + QRgb currentColor = image.pixel(x, rect.top()); + bool fullRun = true; + for (int y = rect.top() + 1; y <= rect.bottom(); ++y) { + if (checkPixel(image.pixel(x, y), currentColor) == false) { + fullRun = false; + break; + } + } + if (fullRun) { +// qDebug() << "Single-color line at vertical line" << x << currentColor; + return false; + } + } + return true; + } + return false; // shut the compiler up. +} + +void DelayedAction::run() +{ + if (next) + QTimer::singleShot(next->delay, next, SLOT(run())); +}; + +/* + Schedules a mouse click at an interface using a singleShot timer. + Only one click can be scheduled at a time. +*/ +ClickLaterAction::ClickLaterAction(InterfaceChildPair interface, Qt::MouseButtons buttons) +{ + this->useInterface = true; + this->interface = interface; + this->buttons = buttons; +} + +/* + Schedules a mouse click at a widget using a singleShot timer. + Only one click can be scheduled at a time. +*/ +ClickLaterAction::ClickLaterAction(QWidget *widget, Qt::MouseButtons buttons) +{ + this->useInterface = false; + this->widget = widget; + this->buttons = buttons; +} + +void ClickLaterAction::run() +{ + if (useInterface) { + const QPoint globalCenter = interface.iface->rect(interface.possibleChild).center(); + NativeEvents::mouseClick(globalCenter, buttons); + } else { // use widget + const QSize halfSize = widget->size() / 2; + const QPoint globalCenter = widget->mapToGlobal(QPoint(halfSize.width(), halfSize.height())); + NativeEvents::mouseClick(globalCenter, buttons); + } + DelayedAction::run(); +} + +void GuiTester::clickLater(InterfaceChildPair interface, Qt::MouseButtons buttons, int delay) +{ + clearSequence(); + addToSequence(new ClickLaterAction(interface, buttons), delay); + runSequence(); +} + +void GuiTester::clickLater(QWidget *widget, Qt::MouseButtons buttons, int delay) +{ + clearSequence(); + addToSequence(new ClickLaterAction(widget, buttons), delay); + runSequence(); +} + +void GuiTester::clearSequence() +{ + startAction = new DelayedAction(); + actions.insert(startAction); + lastAction = startAction; +} + +void GuiTester::addToSequence(DelayedAction *action, int delay) +{ + actions.insert(action); + action->delay = delay; + lastAction->next = action; + lastAction = action; +} + +void GuiTester::runSequence() +{ + QTimer::singleShot(0, startAction, SLOT(run())); +} + +void GuiTester::exitLoopSlot() +{ + QTestEventLoop::instance().exitLoop(); +} + diff --git a/tests/auto/macgui/guitest.h b/tests/auto/macgui/guitest.h new file mode 100644 index 0000000..1b65361 --- /dev/null +++ b/tests/auto/macgui/guitest.h @@ -0,0 +1,186 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ +#ifndef GUITEST_H +#define GUITEST_H + +#include <QAccessibleInterface> +#include <QSet> +#include <QWidget> +#include <QPainter> + +QT_USE_NAMESPACE + +/* + GuiTest provides tools for: + - navigating the Qt Widget hiearchy using the accessibilty APIs. + - Simulating platform mouse and keybord events. +*/ + +/* + InterfaceChildPair specifies an accessibilty interface item. +*/ +class InterfaceChildPair { +public: + InterfaceChildPair() : iface(0), possibleChild(0) {} + InterfaceChildPair(QAccessibleInterface *iface, int possibleChild) + :iface(iface), possibleChild(possibleChild) + { } + + QAccessibleInterface *iface; + int possibleChild; +}; + +class TestBase { +public: + virtual bool operator()(InterfaceChildPair candidate) = 0; + virtual ~TestBase() {} +}; + +/* + WidgetNavigator navigates a Qt GUI hierarchy using the QAccessibility APIs. +*/ +class WidgetNavigator { +public: + WidgetNavigator() {}; + ~WidgetNavigator(); + + void printAll(QWidget *widget); + void printAll(InterfaceChildPair interface); + + InterfaceChildPair find(QAccessible::Text textType, const QString &text, QWidget *start); + InterfaceChildPair find(QAccessible::Text textType, const QString &text, QAccessibleInterface *start); + + InterfaceChildPair recursiveSearch(TestBase *test, QAccessibleInterface *iface, int possibleChild); + + void deleteInDestructor(QAccessibleInterface * interface); + static QWidget *getWidget(InterfaceChildPair interface); +private: + QSet<QAccessibleInterface *> interfaces; +}; + +/* + NativeEvents contains platform-specific code for simulating mouse and keybord events. + (Implemented so far: mouseClick on Mac) +*/ +namespace NativeEvents { + enum MousePosition { UpdatePosition, DontUpdatePosition }; + /* + Simulates a mouse click with button at globalPos. + */ + void mouseClick(const QPoint &globalPos, Qt::MouseButtons buttons, MousePosition updateMouse = DontUpdatePosition); +}; + +class ColorWidget : public QWidget +{ +public: + ColorWidget(QWidget *parent = 0, QColor color = QColor(Qt::red)) + : QWidget(parent), color(color) {} + + QColor color; + +protected: + void paintEvent(QPaintEvent *) + { + QPainter p(this); + p.fillRect(this->rect(), color); + } +}; + +class DelayedAction : public QObject +{ +Q_OBJECT +public: + DelayedAction() : delay(0), next(0) {} + virtual ~DelayedAction(){} +public slots: + virtual void run(); +public: + int delay; + DelayedAction *next; +}; + +class ClickLaterAction : public DelayedAction +{ +Q_OBJECT +public: + ClickLaterAction(InterfaceChildPair interface, Qt::MouseButtons buttons = Qt::LeftButton); + ClickLaterAction(QWidget *widget, Qt::MouseButtons buttons = Qt::LeftButton); +protected slots: + void run(); +private: + bool useInterface; + InterfaceChildPair interface; + QWidget *widget; + Qt::MouseButtons buttons; +}; + +/* + +*/ +class GuiTester : public QObject +{ +Q_OBJECT +public: + GuiTester(); + ~GuiTester(); + enum Direction {Horizontal = 1, Vertical = 2, HorizontalAndVertical = 3}; + Q_DECLARE_FLAGS(Directions, Direction) + bool isFilled(const QImage image, const QRect &rect, const QColor &color); + bool isContent(const QImage image, const QRect &rect, Directions directions = HorizontalAndVertical); +protected slots: + void exitLoopSlot(); +protected: + void clickLater(InterfaceChildPair interface, Qt::MouseButtons buttons = Qt::LeftButton, int delay = 300); + void clickLater(QWidget *widget, Qt::MouseButtons buttons = Qt::LeftButton, int delay = 300); + + void clearSequence(); + void addToSequence(DelayedAction *action, int delay = 0); + void runSequence(); + WidgetNavigator wn; +private: + QSet<DelayedAction *> actions; + DelayedAction *startAction; + DelayedAction *lastAction; +}; + +Q_DECLARE_OPERATORS_FOR_FLAGS(GuiTester::Directions) + +#endif diff --git a/tests/auto/macgui/macgui.pro b/tests/auto/macgui/macgui.pro new file mode 100644 index 0000000..dc64627 --- /dev/null +++ b/tests/auto/macgui/macgui.pro @@ -0,0 +1,15 @@ +load(qttest_p4) +TEMPLATE = app +DEPENDPATH += . +INCLUDEPATH += . + +# Input +SOURCES += tst_gui.cpp + +mac { + SOURCES += guitest.cpp + HEADERS += guitest.h +} + + + diff --git a/tests/auto/macgui/tst_gui.cpp b/tests/auto/macgui/tst_gui.cpp new file mode 100644 index 0000000..b302f8b --- /dev/null +++ b/tests/auto/macgui/tst_gui.cpp @@ -0,0 +1,282 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + + +#include <QApplication> +#include <QMessageBox> +#include <QtTest/QtTest> +#include <QSplashScreen> +#include <QScrollBar> +#include <QProgressDialog> +#include <QSpinBox> + +#include <guitest.h> + +#ifdef Q_OS_MAC + +class tst_gui : public GuiTester +{ +Q_OBJECT +private slots: + void scrollbarPainting(); + + void dummy(); + void splashScreenModality(); + void dialogModality(); + void nonModalOrder(); + + void spinBoxArrowButtons(); +}; + + +QPixmap grabWindowContents(QWidget * widget) +{ + const int titleBarHeight = widget->frameGeometry().height() - widget->height(); + return QPixmap::grabWindow(widget->winId(), 0, titleBarHeight, -1, widget->height()); +} + +/* + Test that vertical and horizontal mac-style scrollbars paint their + entire area. +*/ +void tst_gui::scrollbarPainting() +{ +#if defined (Q_WS_MAC) && defined (__i386__) + QSKIP("This test fails on scruffy when run by the autotest system (but not when you run it manually).", SkipAll); +#endif + + ColorWidget colorWidget; + colorWidget.resize(400, 400); + + QSize scrollBarSize; + + QScrollBar verticalScrollbar(&colorWidget); + verticalScrollbar.move(10, 10); + scrollBarSize = verticalScrollbar.sizeHint(); + scrollBarSize.setHeight(200); + verticalScrollbar.resize(scrollBarSize); + + QScrollBar horizontalScrollbar(&colorWidget); + horizontalScrollbar.move(30, 10); + horizontalScrollbar.setOrientation(Qt::Horizontal); + scrollBarSize = horizontalScrollbar.sizeHint(); + scrollBarSize.setWidth(200); + horizontalScrollbar.resize(scrollBarSize); + + colorWidget.show(); + colorWidget.raise(); + QTest::qWait(100); + + QPixmap pixmap = grabWindowContents(&colorWidget); + + QVERIFY(isContent(pixmap.toImage(), verticalScrollbar.geometry(), GuiTester::Horizontal)); + QVERIFY(isContent(pixmap.toImage(), horizontalScrollbar.geometry(), GuiTester::Vertical)); +} + +// When running the auto-tests on scruffy, the first enter-the-event-loop-and-wait-for-a-click +// test that runs always times out, so we have this dummy test. +void tst_gui::dummy() +{ + QPixmap pix(100, 100); + QSplashScreen splash(pix); + splash.show(); + + QMessageBox *box = new QMessageBox(); + box->setText("accessible?"); + box->show(); + + // Find the "OK" button and schedule a press. + InterfaceChildPair interface = wn.find(QAccessible::Name, "OK", box); + QVERIFY(interface.iface); + const int delay = 1000; + clickLater(interface, Qt::LeftButton, delay); + + // Show dialog and and enter event loop. + connect(wn.getWidget(interface), SIGNAL(clicked()), SLOT(exitLoopSlot())); + const int timeout = 4; + QTestEventLoop::instance().enterLoop(timeout); +} + +/* + Test that a message box pops up in front of a QSplashScreen. +*/ +void tst_gui::splashScreenModality() +{ + QPixmap pix(300, 300); + QSplashScreen splash(pix); + splash.show(); + + QMessageBox box; + //box.setWindowFlags(box.windowFlags() | Qt::WindowStaysOnTopHint); + box.setText("accessible?"); + box.show(); + + // Find the "OK" button and schedule a press. + InterfaceChildPair interface = wn.find(QAccessible::Name, "OK", &box); + QVERIFY(interface.iface); + const int delay = 1000; + clickLater(interface, Qt::LeftButton, delay); + + // Show dialog and and enter event loop. + connect(wn.getWidget(interface), SIGNAL(clicked()), SLOT(exitLoopSlot())); + const int timeout = 4; + QTestEventLoop::instance().enterLoop(timeout); + QVERIFY(QTestEventLoop::instance().timeout() == false); +} + + +/* + Test that a non-modal dialog created as a child of a modal dialog is + shown in front. +*/ +void tst_gui::dialogModality() +{ + QDialog d; + d.setModal(true); + d.show(); + + QProgressDialog progress(&d); + progress.setValue(2); + + InterfaceChildPair interface = wn.find(QAccessible::Name, "Cancel", &progress); + QVERIFY(interface.iface); + const int delay = 2000; + clickLater(interface, Qt::LeftButton, delay); + + connect(&progress, SIGNAL(canceled()), SLOT(exitLoopSlot())); + + const int timeout = 3; + QTestEventLoop::instance().enterLoop(timeout); + QVERIFY(QTestEventLoop::instance().timeout() == false); +} + +class PrimaryWindowDialog : public QDialog +{ +Q_OBJECT +public: + PrimaryWindowDialog(); + QWidget *secondaryWindow; + QWidget *frontWidget; +public slots: + void showSecondaryWindow(); + void test(); +}; + +PrimaryWindowDialog::PrimaryWindowDialog() : QDialog(0) +{ + frontWidget = 0; + secondaryWindow = new ColorWidget(this); + secondaryWindow->setWindowFlags(Qt::Window); + secondaryWindow->resize(400, 400); + secondaryWindow->move(100, 100); + QTimer::singleShot(1000, this, SLOT(showSecondaryWindow())); + QTimer::singleShot(2000, this, SLOT(test())); + QTimer::singleShot(3000, this, SLOT(close())); +} + +void PrimaryWindowDialog::showSecondaryWindow() +{ + secondaryWindow->show(); +} + +void PrimaryWindowDialog::test() +{ + frontWidget = QApplication::widgetAt(secondaryWindow->mapToGlobal(QPoint(100, 100))); +} + +/* + Test that a non-modal child window of a modal dialog is shown in front + of the dialog even if the dialog becomes modal after the child window + is created. +*/ +void tst_gui::nonModalOrder() +{ + clearSequence(); + PrimaryWindowDialog primary; + primary.resize(400, 400); + primary.move(100, 100); + primary.exec(); + QCOMPARE(primary.frontWidget, primary.secondaryWindow); +} + +/* + Test that the QSpinBox buttons are correctly positioned with the Mac style. +*/ +void tst_gui::spinBoxArrowButtons() +{ + ColorWidget colorWidget; + colorWidget.resize(200, 200); + QSpinBox spinBox(&colorWidget); + QSpinBox spinBox2(&colorWidget); + spinBox2.move(0, 100); + colorWidget.show(); + QTest::qWait(100); + + // Grab an unfocused spin box. + const QImage noFocus = grabWindowContents(&colorWidget).toImage(); + + // Set focus by clicking the less button. + InterfaceChildPair lessInterface = wn.find(QAccessible::Name, "Less", &spinBox); + QVERIFY(lessInterface.iface); + const int delay = 500; + clickLater(lessInterface, Qt::LeftButton, delay); + const int timeout = 1; + QTestEventLoop::instance().enterLoop(timeout); + + // Grab a focused spin box. + const QImage focus = grabWindowContents(&colorWidget).toImage(); + + // Compare the arrow area of the less button to see if it moved. + const QRect lessRect = lessInterface.iface->rect(lessInterface.possibleChild); + const QRect lessLocalRect(colorWidget.mapFromGlobal(lessRect.topLeft()), colorWidget.mapFromGlobal(lessRect.bottomRight())); + const QRect compareRect = lessLocalRect.adjusted(5, 3, -5, -7); + QVERIFY(noFocus.copy(compareRect) == focus.copy(compareRect)); +} + +QTEST_MAIN(tst_gui) + +#else + +QTEST_NOOP_MAIN + +#endif + +#include "tst_gui.moc" |