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>
46 #include <qpa/qwindowsysteminterface.h>
50 class tst_QGuiApplication: public QObject
58 void topLevelWindows();
59 void abortQuitOnShow();
60 void changeFocusWindow();
61 void keyboardModifiers();
63 void quitOnLastWindowClosed();
66 void tst_QGuiApplication::displayName()
69 char *argv[] = { const_cast<char*>("tst_qguiapplication") };
70 QGuiApplication app(argc, argv);
71 QCOMPARE(::qAppName(), QString::fromLatin1("tst_qguiapplication"));
72 QCOMPARE(QGuiApplication::applicationName(), QString::fromLatin1("tst_qguiapplication"));
73 QCOMPARE(QGuiApplication::applicationDisplayName(), QString::fromLatin1("tst_qguiapplication"));
74 QGuiApplication::setApplicationDisplayName("The GUI Application");
75 QCOMPARE(QGuiApplication::applicationDisplayName(), QString::fromLatin1("The GUI Application"));
78 class DummyWindow : public QWindow
81 DummyWindow() : m_focusObject(0) {}
83 virtual QObject *focusObject() const
88 void setFocusObject(QObject *object)
90 m_focusObject = object;
91 emit focusObjectChanged(object);
94 QObject *m_focusObject;
98 void tst_QGuiApplication::focusObject()
101 QGuiApplication app(argc, 0);
103 QObject obj1, obj2, obj3;
108 QSignalSpy spy(&app, SIGNAL(focusObjectChanged(QObject *)));
111 // verify active window focus propagates to qguiapplication
112 window1.requestActivateWindow();
113 QVERIFY(QTest::qWaitForWindowActive(&window1));
114 QCOMPARE(app.focusWindow(), &window1);
116 window1.setFocusObject(&obj1);
117 QCOMPARE(app.focusObject(), &obj1);
118 QCOMPARE(spy.count(), 1);
121 window1.setFocusObject(&obj2);
122 QCOMPARE(app.focusObject(), &obj2);
123 QCOMPARE(spy.count(), 1);
126 window2.setFocusObject(&obj3);
127 QCOMPARE(app.focusObject(), &obj2); // not yet changed
129 QVERIFY(QTest::qWaitForWindowExposed(&window2));
130 QTRY_COMPARE(app.focusWindow(), &window2);
131 QCOMPARE(app.focusObject(), &obj3);
132 QCOMPARE(spy.count(), 1);
134 // focus change on unfocused window does not show
136 window1.setFocusObject(&obj1);
137 QCOMPARE(spy.count(), 0);
138 QCOMPARE(app.focusObject(), &obj3);
141 void tst_QGuiApplication::allWindows()
144 QGuiApplication app(argc, 0);
145 QWindow *window1 = new QWindow;
146 QWindow *window2 = new QWindow(window1);
147 QVERIFY(app.allWindows().contains(window1));
148 QVERIFY(app.allWindows().contains(window2));
149 QCOMPARE(app.allWindows().count(), 2);
153 QVERIFY(!app.allWindows().contains(window2));
154 QVERIFY(!app.allWindows().contains(window1));
155 QCOMPARE(app.allWindows().count(), 0);
158 void tst_QGuiApplication::topLevelWindows()
161 QGuiApplication app(argc, 0);
162 QWindow *window1 = new QWindow;
163 QWindow *window2 = new QWindow(window1);
164 QVERIFY(app.topLevelWindows().contains(window1));
165 QVERIFY(!app.topLevelWindows().contains(window2));
166 QCOMPARE(app.topLevelWindows().count(), 1);
170 QVERIFY(!app.topLevelWindows().contains(window2));
171 QVERIFY(!app.topLevelWindows().contains(window1));
172 QCOMPARE(app.topLevelWindows().count(), 0);
175 class ShowCloseShowWindow : public QWindow
179 ShowCloseShowWindow(bool showAgain, QWindow *parent = 0)
180 : QWindow(parent), showAgain(showAgain)
182 QTimer::singleShot(0, this, SLOT(doClose()));
183 QTimer::singleShot(500, this, SLOT(exitApp()));
201 void tst_QGuiApplication::abortQuitOnShow()
204 QGuiApplication app(argc, 0);
205 QWindow *window1 = new ShowCloseShowWindow(false);
207 QCOMPARE(app.exec(), 0);
209 QWindow *window2 = new ShowCloseShowWindow(true);
211 QCOMPARE(app.exec(), 1);
215 class FocusChangeWindow: public QWindow
218 virtual bool event(QEvent *ev)
220 if (ev->type() == QEvent::FocusAboutToChange)
221 windowDuringFocusAboutToChange = qGuiApp->focusWindow();
222 return QWindow::event(ev);
225 virtual void focusOutEvent(QFocusEvent *)
227 windowDuringFocusOut = qGuiApp->focusWindow();
231 FocusChangeWindow() : QWindow(), windowDuringFocusAboutToChange(0), windowDuringFocusOut(0) {}
233 QWindow *windowDuringFocusAboutToChange;
234 QWindow *windowDuringFocusOut;
237 void tst_QGuiApplication::changeFocusWindow()
240 QGuiApplication app(argc, 0);
242 // focus is changed between FocusAboutToChange and FocusChanged
243 FocusChangeWindow window1, window2;
246 QVERIFY(QTest::qWaitForWindowExposed(&window1));
247 QVERIFY(QTest::qWaitForWindowExposed(&window2));
248 window1.requestActivateWindow();
249 QTRY_COMPARE(app.focusWindow(), &window1);
251 window2.requestActivateWindow();
252 QTRY_COMPARE(app.focusWindow(), &window2);
253 QCOMPARE(window1.windowDuringFocusAboutToChange, &window1);
254 QCOMPARE(window1.windowDuringFocusOut, &window2);
257 void tst_QGuiApplication::keyboardModifiers()
260 QGuiApplication app(argc, 0);
262 QWindow *window = new QWindow;
264 QVERIFY(QTest::qWaitForWindowExposed(window));
265 QCOMPARE(QGuiApplication::keyboardModifiers(), Qt::NoModifier);
268 QPoint center = window->geometry().center();
269 QTest::mouseEvent(QTest::MousePress, window, Qt::LeftButton, Qt::NoModifier, center);
270 QCOMPARE(QGuiApplication::keyboardModifiers(), Qt::NoModifier);
271 QTest::mouseEvent(QTest::MouseRelease, window, Qt::LeftButton, Qt::NoModifier, center);
272 QCOMPARE(QGuiApplication::keyboardModifiers(), Qt::NoModifier);
273 QTest::mouseEvent(QTest::MousePress, window, Qt::RightButton, Qt::ControlModifier, center);
274 QCOMPARE(QGuiApplication::keyboardModifiers(), Qt::ControlModifier);
275 QTest::mouseEvent(QTest::MouseRelease, window, Qt::RightButton, Qt::ControlModifier, center);
276 QCOMPARE(QGuiApplication::keyboardModifiers(), Qt::ControlModifier);
279 QWindowSystemInterface::tryHandleSynchronousShortcutEvent(window, Qt::Key_5, Qt::MetaModifier);
280 QCOMPARE(QGuiApplication::keyboardModifiers(), Qt::MetaModifier);
281 QWindowSystemInterface::tryHandleSynchronousShortcutEvent(window, Qt::Key_Period, Qt::NoModifier);
282 QCOMPARE(QGuiApplication::keyboardModifiers(), Qt::NoModifier);
283 QWindowSystemInterface::tryHandleSynchronousShortcutEvent(window, Qt::Key_0, Qt::ControlModifier);
284 QCOMPARE(QGuiApplication::keyboardModifiers(), Qt::ControlModifier);
287 QTest::keyEvent(QTest::Press, window, Qt::Key_C);
288 QCOMPARE(QGuiApplication::keyboardModifiers(), Qt::NoModifier);
289 QTest::keyEvent(QTest::Release, window, Qt::Key_C);
290 QCOMPARE(QGuiApplication::keyboardModifiers(), Qt::NoModifier);
292 QTest::keyEvent(QTest::Press, window, Qt::Key_U, Qt::ControlModifier);
293 QCOMPARE(QGuiApplication::keyboardModifiers(), Qt::ControlModifier);
294 QTest::keyEvent(QTest::Release, window, Qt::Key_U, Qt::ControlModifier);
295 QCOMPARE(QGuiApplication::keyboardModifiers(), Qt::ControlModifier);
297 QTest::keyEvent(QTest::Press, window, Qt::Key_T);
298 QCOMPARE(QGuiApplication::keyboardModifiers(), Qt::NoModifier);
299 QTest::keyEvent(QTest::Release, window, Qt::Key_T);
300 QCOMPARE(QGuiApplication::keyboardModifiers(), Qt::NoModifier);
302 QTest::keyEvent(QTest::Press, window, Qt::Key_E, Qt::ControlModifier);
303 QCOMPARE(QGuiApplication::keyboardModifiers(), Qt::ControlModifier);
304 QTest::keyEvent(QTest::Release, window, Qt::Key_E, Qt::ControlModifier);
305 QCOMPARE(QGuiApplication::keyboardModifiers(), Qt::ControlModifier);
308 QPoint global = window->mapToGlobal(center);
310 QWindowSystemInterface::handleWheelEvent(window, center, global, delta, delta, Qt::NoModifier);
311 QWindowSystemInterface::sendWindowSystemEvents(QEventLoop::AllEvents);
312 QCOMPARE(QGuiApplication::keyboardModifiers(), Qt::NoModifier);
313 QWindowSystemInterface::handleWheelEvent(window, center, global, delta, delta, Qt::AltModifier);
314 QWindowSystemInterface::sendWindowSystemEvents(QEventLoop::AllEvents);
315 QCOMPARE(QGuiApplication::keyboardModifiers(), Qt::AltModifier);
316 QWindowSystemInterface::handleWheelEvent(window, center, global, delta, delta, Qt::ControlModifier);
317 QWindowSystemInterface::sendWindowSystemEvents(QEventLoop::AllEvents);
318 QCOMPARE(QGuiApplication::keyboardModifiers(), Qt::ControlModifier);
321 QList<const QTouchDevice *> touchDevices = QTouchDevice::devices();
322 if (!touchDevices.isEmpty()) {
323 QTouchDevice *touchDevice = const_cast<QTouchDevice *>(touchDevices.first());
324 QTest::touchEvent(window, touchDevice).press(1, center).release(1, center);
325 QCOMPARE(QGuiApplication::keyboardModifiers(), Qt::NoModifier);
332 class BlockableWindow : public QWindow
338 inline BlockableWindow()
344 bool event(QEvent *e)
347 case QEvent::WindowBlocked:
350 case QEvent::WindowUnblocked:
356 return QWindow::event(e);
360 void tst_QGuiApplication::modalWindow()
363 QGuiApplication app(argc, 0);
365 BlockableWindow *window1 = new BlockableWindow;
367 BlockableWindow *window2 = new BlockableWindow;
369 BlockableWindow *windowModalWindow1 = new BlockableWindow;
370 windowModalWindow1->setTransientParent(window1);
371 windowModalWindow1->setWindowModality(Qt::WindowModal);
373 BlockableWindow *windowModalWindow2 = new BlockableWindow;
374 windowModalWindow2->setTransientParent(windowModalWindow1);
375 windowModalWindow2->setWindowModality(Qt::WindowModal);
377 BlockableWindow *applicationModalWindow1 = new BlockableWindow;
378 applicationModalWindow1->setWindowModality(Qt::ApplicationModal);
380 // show the 2 windows, nothing is blocked
383 QVERIFY(QTest::qWaitForWindowExposed(window1));
384 QVERIFY(QTest::qWaitForWindowExposed(window2));
385 QCOMPARE(app.modalWindow(), static_cast<QWindow *>(0));
386 QCOMPARE(window1->blocked, 0);
387 QCOMPARE(window2->blocked, 0);
388 QCOMPARE(windowModalWindow1->blocked, 0);
389 QCOMPARE(windowModalWindow2->blocked, 0);
390 QCOMPARE(applicationModalWindow1->blocked, 0);
392 // show applicationModalWindow1, everything is blocked
393 applicationModalWindow1->show();
394 QCOMPARE(app.modalWindow(), applicationModalWindow1);
395 QCOMPARE(window1->blocked, 1);
396 QCOMPARE(window2->blocked, 1);
397 QCOMPARE(windowModalWindow1->blocked, 1);
398 QCOMPARE(windowModalWindow2->blocked, 1);
399 QCOMPARE(applicationModalWindow1->blocked, 0);
401 // everything is unblocked when applicationModalWindow1 is hidden
402 applicationModalWindow1->hide();
403 QCOMPARE(app.modalWindow(), static_cast<QWindow *>(0));
404 QCOMPARE(window1->blocked, 0);
405 QCOMPARE(window2->blocked, 0);
406 QCOMPARE(windowModalWindow1->blocked, 0);
407 QCOMPARE(windowModalWindow2->blocked, 0);
408 QCOMPARE(applicationModalWindow1->blocked, 0);
410 // show the windowModalWindow1, only window1 is blocked
411 windowModalWindow1->show();
412 QCOMPARE(app.modalWindow(), windowModalWindow1);
413 QCOMPARE(window1->blocked, 1);
414 QCOMPARE(window2->blocked, 0);
415 QCOMPARE(windowModalWindow1->blocked, 0);
416 QCOMPARE(windowModalWindow2->blocked, 0);
417 QCOMPARE(applicationModalWindow1->blocked, 0);
419 // show the windowModalWindow2, windowModalWindow1 is blocked as well
420 windowModalWindow2->show();
421 QCOMPARE(app.modalWindow(), windowModalWindow2);
422 QCOMPARE(window1->blocked, 1);
423 QCOMPARE(window2->blocked, 0);
424 QCOMPARE(windowModalWindow1->blocked, 1);
425 QCOMPARE(windowModalWindow2->blocked, 0);
426 QCOMPARE(applicationModalWindow1->blocked, 0);
428 // hide windowModalWindow1, nothing is unblocked
429 windowModalWindow1->hide();
430 QCOMPARE(app.modalWindow(), windowModalWindow2);
431 QCOMPARE(window1->blocked, 1);
432 QCOMPARE(window2->blocked, 0);
433 QCOMPARE(windowModalWindow1->blocked, 1);
434 QCOMPARE(windowModalWindow2->blocked, 0);
435 QCOMPARE(applicationModalWindow1->blocked, 0);
437 // hide windowModalWindow2, windowModalWindow1 and window1 are unblocked
438 windowModalWindow2->hide();
439 QCOMPARE(app.modalWindow(), static_cast<QWindow *>(0));
440 QCOMPARE(window1->blocked, 0);
441 QCOMPARE(window2->blocked, 0);
442 QCOMPARE(windowModalWindow1->blocked, 0);
443 QCOMPARE(windowModalWindow2->blocked, 0);
444 QCOMPARE(applicationModalWindow1->blocked, 0);
446 // show windowModalWindow1 again, window1 is blocked
447 windowModalWindow1->show();
448 QCOMPARE(app.modalWindow(), windowModalWindow1);
449 QCOMPARE(window1->blocked, 1);
450 QCOMPARE(window2->blocked, 0);
451 QCOMPARE(windowModalWindow1->blocked, 0);
452 QCOMPARE(windowModalWindow2->blocked, 0);
453 QCOMPARE(applicationModalWindow1->blocked, 0);
455 // show windowModalWindow2 again, windowModalWindow1 is also blocked
456 windowModalWindow2->show();
457 QCOMPARE(app.modalWindow(), windowModalWindow2);
458 QCOMPARE(window1->blocked, 1);
459 QCOMPARE(window2->blocked, 0);
460 QCOMPARE(windowModalWindow1->blocked, 1);
461 QCOMPARE(windowModalWindow2->blocked, 0);
462 QCOMPARE(applicationModalWindow1->blocked, 0);
464 // show applicationModalWindow1, everything is blocked
465 applicationModalWindow1->show();
466 QCOMPARE(app.modalWindow(), applicationModalWindow1);
467 QCOMPARE(window1->blocked, 1);
468 QCOMPARE(window2->blocked, 1);
469 QCOMPARE(windowModalWindow1->blocked, 1);
470 QCOMPARE(windowModalWindow2->blocked, 1);
471 QCOMPARE(applicationModalWindow1->blocked, 0);
473 // hide applicationModalWindow1, windowModalWindow1 and window1 are blocked
474 applicationModalWindow1->hide();
475 QCOMPARE(app.modalWindow(), windowModalWindow2);
476 QCOMPARE(window1->blocked, 1);
477 QCOMPARE(window2->blocked, 0);
478 QCOMPARE(windowModalWindow1->blocked, 1);
479 QCOMPARE(windowModalWindow2->blocked, 0);
480 QCOMPARE(applicationModalWindow1->blocked, 0);
482 // hide windowModalWindow2, window1 is blocked
483 windowModalWindow2->hide();
484 QCOMPARE(app.modalWindow(), windowModalWindow1);
485 QCOMPARE(window1->blocked, 1);
486 QCOMPARE(window2->blocked, 0);
487 QCOMPARE(windowModalWindow1->blocked, 0);
488 QCOMPARE(windowModalWindow2->blocked, 0);
489 QCOMPARE(applicationModalWindow1->blocked, 0);
491 // hide windowModalWindow1, everything is unblocked
492 windowModalWindow1->hide();
493 QCOMPARE(app.modalWindow(), static_cast<QWindow *>(0));
494 QCOMPARE(window1->blocked, 0);
495 QCOMPARE(window2->blocked, 0);
496 QCOMPARE(windowModalWindow1->blocked, 0);
497 QCOMPARE(windowModalWindow2->blocked, 0);
498 QCOMPARE(applicationModalWindow1->blocked, 0);
503 delete applicationModalWindow1;
504 delete windowModalWindow2;
505 delete windowModalWindow1;
510 void tst_QGuiApplication::quitOnLastWindowClosed()
514 QGuiApplication app(argc, 0);
517 timer.setInterval(100);
519 QSignalSpy spy(&app, SIGNAL(aboutToQuit()));
520 QSignalSpy spy2(&timer, SIGNAL(timeout()));
522 QPointer<QWindow> mainWindow = new QWindow;
523 QPointer<QWindow> dialog = new QWindow;
525 dialog->setTransientParent(mainWindow);
527 QVERIFY(app.quitOnLastWindowClosed());
533 QTimer::singleShot(1000, mainWindow, SLOT(close())); // This should quit the application
534 QTimer::singleShot(2000, &app, SLOT(quit())); // This makes sure we quit even if it didn't
538 QCOMPARE(spy.count(), 1);
539 QVERIFY(spy2.count() < 15); // Should be around 10 if closing caused the quit
543 QGuiApplication app(argc, 0);
546 timer.setInterval(100);
548 QSignalSpy spy(&app, SIGNAL(aboutToQuit()));
549 QSignalSpy spy2(&timer, SIGNAL(timeout()));
551 QPointer<QWindow> mainWindow = new QWindow;
552 QPointer<QWindow> dialog = new QWindow;
554 QVERIFY(!dialog->transientParent());
555 QVERIFY(app.quitOnLastWindowClosed());
561 QTimer::singleShot(1000, mainWindow, SLOT(close())); // This should not quit the application
562 QTimer::singleShot(2000, &app, SLOT(quit()));
566 QCOMPARE(spy.count(), 1);
567 QVERIFY(spy2.count() > 15); // Should be around 20 if closing did not cause the quit
572 QTEST_APPLESS_MAIN(tst_QGuiApplication)
573 #include "tst_qguiapplication.moc"