1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
6 ** This file is part of the test suite of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
43 #include <QtTest/QtTest>
44 #include <QtGui/QGuiApplication>
45 #include <QtGui/QWindow>
48 class tst_QGuiApplication: public QObject
55 void topLevelWindows();
56 void abortQuitOnShow();
57 void changeFocusWindow();
58 void keyboardModifiers();
60 void quitOnLastWindowClosed();
63 class DummyWindow : public QWindow
66 DummyWindow() : m_focusObject(0) {}
68 virtual QObject *focusObject() const
73 void setFocusObject(QObject *object)
75 m_focusObject = object;
76 emit focusObjectChanged(object);
79 QObject *m_focusObject;
83 void tst_QGuiApplication::focusObject()
86 QGuiApplication app(argc, 0);
88 QObject obj1, obj2, obj3;
93 QSignalSpy spy(&app, SIGNAL(focusObjectChanged(QObject *)));
96 // verify active window focus propagates to qguiapplication
97 QTest::qWaitForWindowShown(&window1);
98 window1.requestActivateWindow();
99 QTRY_COMPARE(app.focusWindow(), &window1);
101 window1.setFocusObject(&obj1);
102 QCOMPARE(app.focusObject(), &obj1);
103 QCOMPARE(spy.count(), 1);
106 window1.setFocusObject(&obj2);
107 QCOMPARE(app.focusObject(), &obj2);
108 QCOMPARE(spy.count(), 1);
111 window2.setFocusObject(&obj3);
112 QCOMPARE(app.focusObject(), &obj2); // not yet changed
114 QTest::qWaitForWindowShown(&window2);
115 QTRY_COMPARE(app.focusWindow(), &window2);
116 QCOMPARE(app.focusObject(), &obj3);
117 QCOMPARE(spy.count(), 1);
119 // focus change on unfocused window does not show
121 window1.setFocusObject(&obj1);
122 QCOMPARE(spy.count(), 0);
123 QCOMPARE(app.focusObject(), &obj3);
126 void tst_QGuiApplication::allWindows()
129 QGuiApplication app(argc, 0);
130 QWindow *window1 = new QWindow;
131 QWindow *window2 = new QWindow(window1);
132 QVERIFY(app.allWindows().contains(window1));
133 QVERIFY(app.allWindows().contains(window2));
134 QCOMPARE(app.allWindows().count(), 2);
138 QVERIFY(!app.allWindows().contains(window2));
139 QVERIFY(!app.allWindows().contains(window1));
140 QCOMPARE(app.allWindows().count(), 0);
143 void tst_QGuiApplication::topLevelWindows()
146 QGuiApplication app(argc, 0);
147 QWindow *window1 = new QWindow;
148 QWindow *window2 = new QWindow(window1);
149 QVERIFY(app.topLevelWindows().contains(window1));
150 QVERIFY(!app.topLevelWindows().contains(window2));
151 QCOMPARE(app.topLevelWindows().count(), 1);
155 QVERIFY(!app.topLevelWindows().contains(window2));
156 QVERIFY(!app.topLevelWindows().contains(window1));
157 QCOMPARE(app.topLevelWindows().count(), 0);
160 class ShowCloseShowWindow : public QWindow
164 ShowCloseShowWindow(bool showAgain, QWindow *parent = 0)
165 : QWindow(parent), showAgain(showAgain)
167 QTimer::singleShot(0, this, SLOT(doClose()));
168 QTimer::singleShot(500, this, SLOT(exitApp()));
186 void tst_QGuiApplication::abortQuitOnShow()
189 QGuiApplication app(argc, 0);
190 QWindow *window1 = new ShowCloseShowWindow(false);
192 QCOMPARE(app.exec(), 0);
194 QWindow *window2 = new ShowCloseShowWindow(true);
196 QCOMPARE(app.exec(), 1);
200 class FocusChangeWindow: public QWindow
203 virtual bool event(QEvent *ev)
205 if (ev->type() == QEvent::FocusAboutToChange)
206 windowDuringFocusAboutToChange = qGuiApp->focusWindow();
207 return QWindow::event(ev);
210 virtual void focusOutEvent(QFocusEvent *)
212 windowDuringFocusOut = qGuiApp->focusWindow();
216 FocusChangeWindow() : QWindow(), windowDuringFocusAboutToChange(0), windowDuringFocusOut(0) {}
218 QWindow *windowDuringFocusAboutToChange;
219 QWindow *windowDuringFocusOut;
222 void tst_QGuiApplication::changeFocusWindow()
225 QGuiApplication app(argc, 0);
227 // focus is changed between FocusAboutToChange and FocusChanged
228 FocusChangeWindow window1, window2;
231 QTest::qWaitForWindowShown(&window1);
232 QTest::qWaitForWindowShown(&window2);
233 window1.requestActivateWindow();
234 QTRY_COMPARE(app.focusWindow(), &window1);
236 window2.requestActivateWindow();
237 QTRY_COMPARE(app.focusWindow(), &window2);
238 QCOMPARE(window1.windowDuringFocusAboutToChange, &window1);
239 QCOMPARE(window1.windowDuringFocusOut, &window2);
242 void tst_QGuiApplication::keyboardModifiers()
245 QGuiApplication app(argc, 0);
247 QWindow *window = new QWindow;
249 QTest::qWaitForWindowShown(window);
250 QCOMPARE(QGuiApplication::keyboardModifiers(), Qt::NoModifier);
253 QPoint center = window->geometry().center();
254 QTest::mouseEvent(QTest::MousePress, window, Qt::LeftButton, Qt::NoModifier, center);
255 QCOMPARE(QGuiApplication::keyboardModifiers(), Qt::NoModifier);
256 QTest::mouseEvent(QTest::MouseRelease, window, Qt::LeftButton, Qt::NoModifier, center);
257 QCOMPARE(QGuiApplication::keyboardModifiers(), Qt::NoModifier);
258 QTest::mouseEvent(QTest::MousePress, window, Qt::RightButton, Qt::ControlModifier, center);
259 QCOMPARE(QGuiApplication::keyboardModifiers(), Qt::ControlModifier);
260 QTest::mouseEvent(QTest::MouseRelease, window, Qt::RightButton, Qt::ControlModifier, center);
261 QCOMPARE(QGuiApplication::keyboardModifiers(), Qt::ControlModifier);
264 QWindowSystemInterface::tryHandleSynchronousShortcutEvent(window, Qt::Key_5, Qt::MetaModifier);
265 QCOMPARE(QGuiApplication::keyboardModifiers(), Qt::MetaModifier);
266 QWindowSystemInterface::tryHandleSynchronousShortcutEvent(window, Qt::Key_Period, Qt::NoModifier);
267 QCOMPARE(QGuiApplication::keyboardModifiers(), Qt::NoModifier);
268 QWindowSystemInterface::tryHandleSynchronousShortcutEvent(window, Qt::Key_0, Qt::ControlModifier);
269 QCOMPARE(QGuiApplication::keyboardModifiers(), Qt::ControlModifier);
272 QTest::keyEvent(QTest::Press, window, Qt::Key_C);
273 QCOMPARE(QGuiApplication::keyboardModifiers(), Qt::NoModifier);
274 QTest::keyEvent(QTest::Release, window, Qt::Key_C);
275 QCOMPARE(QGuiApplication::keyboardModifiers(), Qt::NoModifier);
277 QTest::keyEvent(QTest::Press, window, Qt::Key_U, Qt::ControlModifier);
278 QCOMPARE(QGuiApplication::keyboardModifiers(), Qt::ControlModifier);
279 QTest::keyEvent(QTest::Release, window, Qt::Key_U, Qt::ControlModifier);
280 QCOMPARE(QGuiApplication::keyboardModifiers(), Qt::ControlModifier);
282 QTest::keyEvent(QTest::Press, window, Qt::Key_T);
283 QCOMPARE(QGuiApplication::keyboardModifiers(), Qt::NoModifier);
284 QTest::keyEvent(QTest::Release, window, Qt::Key_T);
285 QCOMPARE(QGuiApplication::keyboardModifiers(), Qt::NoModifier);
287 QTest::keyEvent(QTest::Press, window, Qt::Key_E, Qt::ControlModifier);
288 QCOMPARE(QGuiApplication::keyboardModifiers(), Qt::ControlModifier);
289 QTest::keyEvent(QTest::Release, window, Qt::Key_E, Qt::ControlModifier);
290 QCOMPARE(QGuiApplication::keyboardModifiers(), Qt::ControlModifier);
293 QPoint global = window->mapToGlobal(center);
295 QWindowSystemInterface::handleWheelEvent(window, center, global, delta, delta, Qt::NoModifier);
296 QWindowSystemInterface::sendWindowSystemEvents(app.eventDispatcher(), QEventLoop::AllEvents);
297 QCOMPARE(QGuiApplication::keyboardModifiers(), Qt::NoModifier);
298 QWindowSystemInterface::handleWheelEvent(window, center, global, delta, delta, Qt::AltModifier);
299 QWindowSystemInterface::sendWindowSystemEvents(app.eventDispatcher(), QEventLoop::AllEvents);
300 QCOMPARE(QGuiApplication::keyboardModifiers(), Qt::AltModifier);
301 QWindowSystemInterface::handleWheelEvent(window, center, global, delta, delta, Qt::ControlModifier);
302 QWindowSystemInterface::sendWindowSystemEvents(app.eventDispatcher(), QEventLoop::AllEvents);
303 QCOMPARE(QGuiApplication::keyboardModifiers(), Qt::ControlModifier);
306 QList<const QTouchDevice *> touchDevices = QTouchDevice::devices();
307 if (!touchDevices.isEmpty()) {
308 QTouchDevice *touchDevice = const_cast<QTouchDevice *>(touchDevices.first());
309 QTest::touchEvent(window, touchDevice).press(1, center).release(1, center);
310 QCOMPARE(QGuiApplication::keyboardModifiers(), Qt::NoModifier);
317 class BlockableWindow : public QWindow
323 inline BlockableWindow()
329 bool event(QEvent *e)
332 case QEvent::WindowBlocked:
335 case QEvent::WindowUnblocked:
341 return QWindow::event(e);
345 void tst_QGuiApplication::modalWindow()
348 QGuiApplication app(argc, 0);
350 BlockableWindow *window1 = new BlockableWindow;
352 BlockableWindow *window2 = new BlockableWindow;
354 BlockableWindow *windowModalWindow1 = new BlockableWindow;
355 windowModalWindow1->setTransientParent(window1);
356 windowModalWindow1->setWindowModality(Qt::WindowModal);
358 BlockableWindow *windowModalWindow2 = new BlockableWindow;
359 windowModalWindow2->setTransientParent(windowModalWindow1);
360 windowModalWindow2->setWindowModality(Qt::WindowModal);
362 BlockableWindow *applicationModalWindow1 = new BlockableWindow;
363 applicationModalWindow1->setWindowModality(Qt::ApplicationModal);
365 // show the 2 windows, nothing is blocked
368 QTest::qWaitForWindowShown(window1);
369 QTest::qWaitForWindowShown(window2);
370 QCOMPARE(app.modalWindow(), static_cast<QWindow *>(0));
371 QCOMPARE(window1->blocked, 0);
372 QCOMPARE(window2->blocked, 0);
373 QCOMPARE(windowModalWindow1->blocked, 0);
374 QCOMPARE(windowModalWindow2->blocked, 0);
375 QCOMPARE(applicationModalWindow1->blocked, 0);
377 // show applicationModalWindow1, everything is blocked
378 applicationModalWindow1->show();
379 QCOMPARE(app.modalWindow(), applicationModalWindow1);
380 QCOMPARE(window1->blocked, 1);
381 QCOMPARE(window2->blocked, 1);
382 QCOMPARE(windowModalWindow1->blocked, 1);
383 QCOMPARE(windowModalWindow2->blocked, 1);
384 QCOMPARE(applicationModalWindow1->blocked, 0);
386 // everything is unblocked when applicationModalWindow1 is hidden
387 applicationModalWindow1->hide();
388 QCOMPARE(app.modalWindow(), static_cast<QWindow *>(0));
389 QCOMPARE(window1->blocked, 0);
390 QCOMPARE(window2->blocked, 0);
391 QCOMPARE(windowModalWindow1->blocked, 0);
392 QCOMPARE(windowModalWindow2->blocked, 0);
393 QCOMPARE(applicationModalWindow1->blocked, 0);
395 // show the windowModalWindow1, only window1 is blocked
396 windowModalWindow1->show();
397 QCOMPARE(app.modalWindow(), windowModalWindow1);
398 QCOMPARE(window1->blocked, 1);
399 QCOMPARE(window2->blocked, 0);
400 QCOMPARE(windowModalWindow1->blocked, 0);
401 QCOMPARE(windowModalWindow2->blocked, 0);
402 QCOMPARE(applicationModalWindow1->blocked, 0);
404 // show the windowModalWindow2, windowModalWindow1 is blocked as well
405 windowModalWindow2->show();
406 QCOMPARE(app.modalWindow(), windowModalWindow2);
407 QCOMPARE(window1->blocked, 1);
408 QCOMPARE(window2->blocked, 0);
409 QCOMPARE(windowModalWindow1->blocked, 1);
410 QCOMPARE(windowModalWindow2->blocked, 0);
411 QCOMPARE(applicationModalWindow1->blocked, 0);
413 // hide windowModalWindow1, nothing is unblocked
414 windowModalWindow1->hide();
415 QCOMPARE(app.modalWindow(), windowModalWindow2);
416 QCOMPARE(window1->blocked, 1);
417 QCOMPARE(window2->blocked, 0);
418 QCOMPARE(windowModalWindow1->blocked, 1);
419 QCOMPARE(windowModalWindow2->blocked, 0);
420 QCOMPARE(applicationModalWindow1->blocked, 0);
422 // hide windowModalWindow2, windowModalWindow1 and window1 are unblocked
423 windowModalWindow2->hide();
424 QCOMPARE(app.modalWindow(), static_cast<QWindow *>(0));
425 QCOMPARE(window1->blocked, 0);
426 QCOMPARE(window2->blocked, 0);
427 QCOMPARE(windowModalWindow1->blocked, 0);
428 QCOMPARE(windowModalWindow2->blocked, 0);
429 QCOMPARE(applicationModalWindow1->blocked, 0);
431 // show windowModalWindow1 again, window1 is blocked
432 windowModalWindow1->show();
433 QCOMPARE(app.modalWindow(), windowModalWindow1);
434 QCOMPARE(window1->blocked, 1);
435 QCOMPARE(window2->blocked, 0);
436 QCOMPARE(windowModalWindow1->blocked, 0);
437 QCOMPARE(windowModalWindow2->blocked, 0);
438 QCOMPARE(applicationModalWindow1->blocked, 0);
440 // show windowModalWindow2 again, windowModalWindow1 is also blocked
441 windowModalWindow2->show();
442 QCOMPARE(app.modalWindow(), windowModalWindow2);
443 QCOMPARE(window1->blocked, 1);
444 QCOMPARE(window2->blocked, 0);
445 QCOMPARE(windowModalWindow1->blocked, 1);
446 QCOMPARE(windowModalWindow2->blocked, 0);
447 QCOMPARE(applicationModalWindow1->blocked, 0);
449 // show applicationModalWindow1, everything is blocked
450 applicationModalWindow1->show();
451 QCOMPARE(app.modalWindow(), applicationModalWindow1);
452 QCOMPARE(window1->blocked, 1);
453 QCOMPARE(window2->blocked, 1);
454 QCOMPARE(windowModalWindow1->blocked, 1);
455 QCOMPARE(windowModalWindow2->blocked, 1);
456 QCOMPARE(applicationModalWindow1->blocked, 0);
458 // hide applicationModalWindow1, windowModalWindow1 and window1 are blocked
459 applicationModalWindow1->hide();
460 QCOMPARE(app.modalWindow(), windowModalWindow2);
461 QCOMPARE(window1->blocked, 1);
462 QCOMPARE(window2->blocked, 0);
463 QCOMPARE(windowModalWindow1->blocked, 1);
464 QCOMPARE(windowModalWindow2->blocked, 0);
465 QCOMPARE(applicationModalWindow1->blocked, 0);
467 // hide windowModalWindow2, window1 is blocked
468 windowModalWindow2->hide();
469 QCOMPARE(app.modalWindow(), windowModalWindow1);
470 QCOMPARE(window1->blocked, 1);
471 QCOMPARE(window2->blocked, 0);
472 QCOMPARE(windowModalWindow1->blocked, 0);
473 QCOMPARE(windowModalWindow2->blocked, 0);
474 QCOMPARE(applicationModalWindow1->blocked, 0);
476 // hide windowModalWindow1, everything is unblocked
477 windowModalWindow1->hide();
478 QCOMPARE(app.modalWindow(), static_cast<QWindow *>(0));
479 QCOMPARE(window1->blocked, 0);
480 QCOMPARE(window2->blocked, 0);
481 QCOMPARE(windowModalWindow1->blocked, 0);
482 QCOMPARE(windowModalWindow2->blocked, 0);
483 QCOMPARE(applicationModalWindow1->blocked, 0);
488 delete applicationModalWindow1;
489 delete windowModalWindow2;
490 delete windowModalWindow1;
495 void tst_QGuiApplication::quitOnLastWindowClosed()
499 QGuiApplication app(argc, 0);
502 timer.setInterval(100);
504 QSignalSpy spy(&app, SIGNAL(aboutToQuit()));
505 QSignalSpy spy2(&timer, SIGNAL(timeout()));
507 QPointer<QWindow> mainWindow = new QWindow;
508 QPointer<QWindow> dialog = new QWindow;
510 dialog->setTransientParent(mainWindow);
512 QVERIFY(app.quitOnLastWindowClosed());
518 QTimer::singleShot(1000, mainWindow, SLOT(close())); // This should quit the application
519 QTimer::singleShot(2000, &app, SLOT(quit())); // This makes sure we quit even if it didn't
523 QCOMPARE(spy.count(), 1);
524 QVERIFY(spy2.count() < 15); // Should be around 10 if closing caused the quit
528 QGuiApplication app(argc, 0);
531 timer.setInterval(100);
533 QSignalSpy spy(&app, SIGNAL(aboutToQuit()));
534 QSignalSpy spy2(&timer, SIGNAL(timeout()));
536 QPointer<QWindow> mainWindow = new QWindow;
537 QPointer<QWindow> dialog = new QWindow;
539 QVERIFY(!dialog->transientParent());
540 QVERIFY(app.quitOnLastWindowClosed());
546 QTimer::singleShot(1000, mainWindow, SLOT(close())); // This should not quit the application
547 QTimer::singleShot(2000, &app, SLOT(quit()));
551 QCOMPARE(spy.count(), 1);
552 QVERIFY(spy2.count() > 15); // Should be around 20 if closing did not cause the quit
557 QTEST_APPLESS_MAIN(tst_QGuiApplication)
558 #include "tst_qguiapplication.moc"