summaryrefslogtreecommitdiffstats
path: root/tests/auto/macgui
diff options
context:
space:
mode:
Diffstat (limited to 'tests/auto/macgui')
-rw-r--r--tests/auto/macgui/.gitignore1
-rw-r--r--tests/auto/macgui/guitest.cpp350
-rw-r--r--tests/auto/macgui/guitest.h186
-rw-r--r--tests/auto/macgui/macgui.pro11
-rw-r--r--tests/auto/macgui/tst_macgui.cpp251
5 files changed, 799 insertions, 0 deletions
diff --git a/tests/auto/macgui/.gitignore b/tests/auto/macgui/.gitignore
new file mode 100644
index 0000000000..2b13357fac
--- /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 0000000000..a4cdeb5cab
--- /dev/null
+++ b/tests/auto/macgui/guitest.cpp
@@ -0,0 +1,350 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (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 Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@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 0000000000..2ebe4dceb3
--- /dev/null
+++ b/tests/auto/macgui/guitest.h
@@ -0,0 +1,186 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (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 Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@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 0000000000..0ed2350a48
--- /dev/null
+++ b/tests/auto/macgui/macgui.pro
@@ -0,0 +1,11 @@
+load(qttest_p4)
+TEMPLATE = app
+DEPENDPATH += .
+INCLUDEPATH += .
+
+# Input
+SOURCES += tst_macgui.cpp guitest.cpp
+HEADERS += guitest.h
+
+requires(mac)
+
diff --git a/tests/auto/macgui/tst_macgui.cpp b/tests/auto/macgui/tst_macgui.cpp
new file mode 100644
index 0000000000..9daf8a8034
--- /dev/null
+++ b/tests/auto/macgui/tst_macgui.cpp
@@ -0,0 +1,251 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (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 Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@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_MacGui : public GuiTester
+{
+Q_OBJECT
+private slots:
+ void scrollbarPainting();
+
+ void dummy();
+ void splashScreenModality();
+ void nonModalOrder();
+
+ void spinBoxArrowButtons();
+};
+
+
+QPixmap grabWindowContents(QWidget * widget)
+{
+ return QPixmap::grabWindow(widget->winId());
+}
+
+/*
+ Test that vertical and horizontal mac-style scrollbars paint their
+ entire area.
+*/
+void tst_MacGui::scrollbarPainting()
+{
+ 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_MacGui::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_MacGui::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);
+}
+
+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_MacGui::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_MacGui::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_MacGui)
+
+#else
+
+QTEST_NOOP_MAIN
+
+#endif
+
+#include "tst_macgui.moc"
+