Revert "Move QWindowSystemInterface out of qpa."
[profile/ivi/qtbase.git] / tests / auto / gui / kernel / qguiapplication / tst_qguiapplication.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
5 **
6 ** This file is part of the test suite of the Qt Toolkit.
7 **
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.
16 **
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.
20 **
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.
28 **
29 ** Other Usage
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.
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42
43 #include <QtTest/QtTest>
44 #include <QtGui/QGuiApplication>
45 #include <QtGui/QWindow>
46 #include <qpa/qwindowsysteminterface.h>
47
48 #include <QDebug>
49
50 class tst_QGuiApplication: public QObject
51 {
52     Q_OBJECT
53
54 private slots:
55     void displayName();
56     void focusObject();
57     void allWindows();
58     void topLevelWindows();
59     void abortQuitOnShow();
60     void changeFocusWindow();
61     void keyboardModifiers();
62     void modalWindow();
63     void quitOnLastWindowClosed();
64 };
65
66 void tst_QGuiApplication::displayName()
67 {
68     int argc = 1;
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"));
76 }
77
78 class DummyWindow : public QWindow
79 {
80 public:
81     DummyWindow() : m_focusObject(0) {}
82
83     virtual QObject *focusObject() const
84     {
85         return m_focusObject;
86     }
87
88     void setFocusObject(QObject *object)
89     {
90         m_focusObject = object;
91         emit focusObjectChanged(object);
92     }
93
94     QObject *m_focusObject;
95 };
96
97
98 void tst_QGuiApplication::focusObject()
99 {
100     int argc = 0;
101     QGuiApplication app(argc, 0);
102
103     QObject obj1, obj2, obj3;
104     DummyWindow window1;
105     DummyWindow window2;
106     window1.show();
107
108     QSignalSpy spy(&app, SIGNAL(focusObjectChanged(QObject *)));
109
110
111     // verify active window focus propagates to qguiapplication
112     window1.requestActivateWindow();
113     QVERIFY(QTest::qWaitForWindowActive(&window1));
114     QCOMPARE(app.focusWindow(), &window1);
115
116     window1.setFocusObject(&obj1);
117     QCOMPARE(app.focusObject(), &obj1);
118     QCOMPARE(spy.count(), 1);
119
120     spy.clear();
121     window1.setFocusObject(&obj2);
122     QCOMPARE(app.focusObject(), &obj2);
123     QCOMPARE(spy.count(), 1);
124
125     spy.clear();
126     window2.setFocusObject(&obj3);
127     QCOMPARE(app.focusObject(), &obj2); // not yet changed
128     window2.show();
129     QVERIFY(QTest::qWaitForWindowExposed(&window2));
130     QTRY_COMPARE(app.focusWindow(), &window2);
131     QCOMPARE(app.focusObject(), &obj3);
132     QCOMPARE(spy.count(), 1);
133
134     // focus change on unfocused window does not show
135     spy.clear();
136     window1.setFocusObject(&obj1);
137     QCOMPARE(spy.count(), 0);
138     QCOMPARE(app.focusObject(), &obj3);
139 }
140
141 void tst_QGuiApplication::allWindows()
142 {
143     int argc = 0;
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);
150     delete window1;
151     window1 = 0;
152     window2 = 0;
153     QVERIFY(!app.allWindows().contains(window2));
154     QVERIFY(!app.allWindows().contains(window1));
155     QCOMPARE(app.allWindows().count(), 0);
156 }
157
158 void tst_QGuiApplication::topLevelWindows()
159 {
160     int argc = 0;
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);
167     delete window1;
168     window1 = 0;
169     window2 = 0;
170     QVERIFY(!app.topLevelWindows().contains(window2));
171     QVERIFY(!app.topLevelWindows().contains(window1));
172     QCOMPARE(app.topLevelWindows().count(), 0);
173 }
174
175 class ShowCloseShowWindow : public QWindow
176 {
177     Q_OBJECT
178 public:
179     ShowCloseShowWindow(bool showAgain, QWindow *parent = 0)
180       : QWindow(parent), showAgain(showAgain)
181     {
182         QTimer::singleShot(0, this, SLOT(doClose()));
183         QTimer::singleShot(500, this, SLOT(exitApp()));
184     }
185
186 private slots:
187     void doClose() {
188         close();
189         if (showAgain)
190             show();
191     }
192
193     void exitApp() {
194       qApp->exit(1);
195     }
196
197 private:
198     bool showAgain;
199 };
200
201 void tst_QGuiApplication::abortQuitOnShow()
202 {
203     int argc = 0;
204     QGuiApplication app(argc, 0);
205     QWindow *window1 = new ShowCloseShowWindow(false);
206     window1->show();
207     QCOMPARE(app.exec(), 0);
208
209     QWindow *window2 = new ShowCloseShowWindow(true);
210     window2->show();
211     QCOMPARE(app.exec(), 1);
212 }
213
214
215 class FocusChangeWindow: public QWindow
216 {
217 protected:
218     virtual bool event(QEvent *ev)
219     {
220         if (ev->type() == QEvent::FocusAboutToChange)
221             windowDuringFocusAboutToChange = qGuiApp->focusWindow();
222         return QWindow::event(ev);
223     }
224
225     virtual void focusOutEvent(QFocusEvent *)
226     {
227         windowDuringFocusOut = qGuiApp->focusWindow();
228     }
229
230 public:
231     FocusChangeWindow() : QWindow(), windowDuringFocusAboutToChange(0), windowDuringFocusOut(0) {}
232
233     QWindow *windowDuringFocusAboutToChange;
234     QWindow *windowDuringFocusOut;
235 };
236
237 void tst_QGuiApplication::changeFocusWindow()
238 {
239     int argc = 0;
240     QGuiApplication app(argc, 0);
241
242     // focus is changed between FocusAboutToChange and FocusChanged
243     FocusChangeWindow window1, window2;
244     window1.show();
245     window2.show();
246     QVERIFY(QTest::qWaitForWindowExposed(&window1));
247     QVERIFY(QTest::qWaitForWindowExposed(&window2));
248     window1.requestActivateWindow();
249     QTRY_COMPARE(app.focusWindow(), &window1);
250
251     window2.requestActivateWindow();
252     QTRY_COMPARE(app.focusWindow(), &window2);
253     QCOMPARE(window1.windowDuringFocusAboutToChange, &window1);
254     QCOMPARE(window1.windowDuringFocusOut, &window2);
255 }
256
257 void tst_QGuiApplication::keyboardModifiers()
258 {
259     int argc = 0;
260     QGuiApplication app(argc, 0);
261
262     QWindow *window = new QWindow;
263     window->show();
264     QVERIFY(QTest::qWaitForWindowExposed(window));
265     QCOMPARE(QGuiApplication::keyboardModifiers(), Qt::NoModifier);
266
267     // mouse events
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);
277
278     // shortcut events
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);
285
286     // key events
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);
291
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);
296
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);
301
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);
306
307     // wheel events
308     QPoint global = window->mapToGlobal(center);
309     QPoint delta(0, 1);
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);
319
320     // touch events
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);
326     }
327
328     window->close();
329     delete window;
330 }
331
332 class BlockableWindow : public QWindow
333 {
334     Q_OBJECT
335 public:
336     int blocked;
337
338     inline BlockableWindow()
339         : QWindow()
340     {
341         blocked = false;
342     }
343
344     bool event(QEvent *e)
345     {
346         switch (e->type()) {
347         case QEvent::WindowBlocked:
348             ++blocked;
349             break;
350         case QEvent::WindowUnblocked:
351             --blocked;
352             break;
353         default:
354             break;
355         }
356         return QWindow::event(e);
357     }
358 };
359
360 void tst_QGuiApplication::modalWindow()
361 {
362     int argc = 0;
363     QGuiApplication app(argc, 0);
364
365     BlockableWindow *window1 = new BlockableWindow;
366
367     BlockableWindow *window2 = new BlockableWindow;
368
369     BlockableWindow *windowModalWindow1 = new BlockableWindow;
370     windowModalWindow1->setTransientParent(window1);
371     windowModalWindow1->setWindowModality(Qt::WindowModal);
372
373     BlockableWindow *windowModalWindow2 = new BlockableWindow;
374     windowModalWindow2->setTransientParent(windowModalWindow1);
375     windowModalWindow2->setWindowModality(Qt::WindowModal);
376
377     BlockableWindow *applicationModalWindow1 = new BlockableWindow;
378     applicationModalWindow1->setWindowModality(Qt::ApplicationModal);
379
380     // show the 2 windows, nothing is blocked
381     window1->show();
382     window2->show();
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);
391
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);
400
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);
409
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);
418
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);
427
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);
436
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);
445
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);
454
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);
463
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);
472
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);
481
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);
490
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);
499
500     window2->hide();
501     window1->hide();
502
503     delete applicationModalWindow1;
504     delete windowModalWindow2;
505     delete windowModalWindow1;
506     delete window2;
507     delete window1;
508 }
509
510 void tst_QGuiApplication::quitOnLastWindowClosed()
511 {
512     {
513         int argc = 0;
514         QGuiApplication app(argc, 0);
515
516         QTimer timer;
517         timer.setInterval(100);
518
519         QSignalSpy spy(&app, SIGNAL(aboutToQuit()));
520         QSignalSpy spy2(&timer, SIGNAL(timeout()));
521
522         QPointer<QWindow> mainWindow = new QWindow;
523         QPointer<QWindow> dialog = new QWindow;
524
525         dialog->setTransientParent(mainWindow);
526
527         QVERIFY(app.quitOnLastWindowClosed());
528
529         mainWindow->show();
530         dialog->show();
531
532         timer.start();
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
535
536         app.exec();
537
538         QCOMPARE(spy.count(), 1);
539         QVERIFY(spy2.count() < 15);      // Should be around 10 if closing caused the quit
540     }
541     {
542         int argc = 0;
543         QGuiApplication app(argc, 0);
544
545         QTimer timer;
546         timer.setInterval(100);
547
548         QSignalSpy spy(&app, SIGNAL(aboutToQuit()));
549         QSignalSpy spy2(&timer, SIGNAL(timeout()));
550
551         QPointer<QWindow> mainWindow = new QWindow;
552         QPointer<QWindow> dialog = new QWindow;
553
554         QVERIFY(!dialog->transientParent());
555         QVERIFY(app.quitOnLastWindowClosed());
556
557         mainWindow->show();
558         dialog->show();
559
560         timer.start();
561         QTimer::singleShot(1000, mainWindow, SLOT(close())); // This should not quit the application
562         QTimer::singleShot(2000, &app, SLOT(quit()));
563
564         app.exec();
565
566         QCOMPARE(spy.count(), 1);
567         QVERIFY(spy2.count() > 15);      // Should be around 20 if closing did not cause the quit
568     }
569 }
570
571
572 QTEST_APPLESS_MAIN(tst_QGuiApplication)
573 #include "tst_qguiapplication.moc"