Rename all QWindow properties that have "window" in them
[profile/ivi/qtbase.git] / tests / auto / gui / kernel / qguiapplication / tst_qguiapplication.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the test suite of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia.  For licensing terms and
14 ** conditions see http://qt.digia.com/licensing.  For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file.  Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights.  These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file.  Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
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 #include <qgenericplugin.h>
48
49 #include <QDebug>
50
51 class tst_QGuiApplication: public QObject
52 {
53     Q_OBJECT
54
55 private slots:
56     void displayName();
57     void focusObject();
58     void allWindows();
59     void topLevelWindows();
60     void abortQuitOnShow();
61     void changeFocusWindow();
62     void keyboardModifiers();
63     void modalWindow();
64     void quitOnLastWindowClosed();
65     void genericPluginsAndWindowSystemEvents();
66 };
67
68 void tst_QGuiApplication::displayName()
69 {
70     int argc = 1;
71     char *argv[] = { const_cast<char*>("tst_qguiapplication") };
72     QGuiApplication app(argc, argv);
73     QCOMPARE(::qAppName(), QString::fromLatin1("tst_qguiapplication"));
74     QCOMPARE(QGuiApplication::applicationName(), QString::fromLatin1("tst_qguiapplication"));
75     QCOMPARE(QGuiApplication::applicationDisplayName(), QString::fromLatin1("tst_qguiapplication"));
76     QGuiApplication::setApplicationDisplayName("The GUI Application");
77     QCOMPARE(QGuiApplication::applicationDisplayName(), QString::fromLatin1("The GUI Application"));
78 }
79
80 class DummyWindow : public QWindow
81 {
82 public:
83     DummyWindow() : m_focusObject(0) {}
84
85     virtual QObject *focusObject() const
86     {
87         return m_focusObject;
88     }
89
90     void setFocusObject(QObject *object)
91     {
92         m_focusObject = object;
93         emit focusObjectChanged(object);
94     }
95
96     QObject *m_focusObject;
97 };
98
99
100 void tst_QGuiApplication::focusObject()
101 {
102     int argc = 0;
103     QGuiApplication app(argc, 0);
104
105     QObject obj1, obj2, obj3;
106     DummyWindow window1;
107     DummyWindow window2;
108     window1.show();
109
110     QSignalSpy spy(&app, SIGNAL(focusObjectChanged(QObject*)));
111
112
113     // verify active window focus propagates to qguiapplication
114     window1.requestActivate();
115     QVERIFY(QTest::qWaitForWindowActive(&window1));
116     QCOMPARE(app.focusWindow(), &window1);
117
118     window1.setFocusObject(&obj1);
119     QCOMPARE(app.focusObject(), &obj1);
120     QCOMPARE(spy.count(), 1);
121
122     spy.clear();
123     window1.setFocusObject(&obj2);
124     QCOMPARE(app.focusObject(), &obj2);
125     QCOMPARE(spy.count(), 1);
126
127     spy.clear();
128     window2.setFocusObject(&obj3);
129     QCOMPARE(app.focusObject(), &obj2); // not yet changed
130     window2.show();
131     QVERIFY(QTest::qWaitForWindowExposed(&window2));
132     QTRY_COMPARE(app.focusWindow(), &window2);
133     QCOMPARE(app.focusObject(), &obj3);
134     QCOMPARE(spy.count(), 1);
135
136     // focus change on unfocused window does not show
137     spy.clear();
138     window1.setFocusObject(&obj1);
139     QCOMPARE(spy.count(), 0);
140     QCOMPARE(app.focusObject(), &obj3);
141 }
142
143 void tst_QGuiApplication::allWindows()
144 {
145     int argc = 0;
146     QGuiApplication app(argc, 0);
147     QWindow *window1 = new QWindow;
148     QWindow *window2 = new QWindow(window1);
149     QVERIFY(app.allWindows().contains(window1));
150     QVERIFY(app.allWindows().contains(window2));
151     QCOMPARE(app.allWindows().count(), 2);
152     delete window1;
153     window1 = 0;
154     window2 = 0;
155     QVERIFY(!app.allWindows().contains(window2));
156     QVERIFY(!app.allWindows().contains(window1));
157     QCOMPARE(app.allWindows().count(), 0);
158 }
159
160 void tst_QGuiApplication::topLevelWindows()
161 {
162     int argc = 0;
163     QGuiApplication app(argc, 0);
164     QWindow *window1 = new QWindow;
165     QWindow *window2 = new QWindow(window1);
166     QVERIFY(app.topLevelWindows().contains(window1));
167     QVERIFY(!app.topLevelWindows().contains(window2));
168     QCOMPARE(app.topLevelWindows().count(), 1);
169     delete window1;
170     window1 = 0;
171     window2 = 0;
172     QVERIFY(!app.topLevelWindows().contains(window2));
173     QVERIFY(!app.topLevelWindows().contains(window1));
174     QCOMPARE(app.topLevelWindows().count(), 0);
175 }
176
177 class ShowCloseShowWindow : public QWindow
178 {
179     Q_OBJECT
180 public:
181     ShowCloseShowWindow(bool showAgain, QWindow *parent = 0)
182       : QWindow(parent), showAgain(showAgain)
183     {
184         QTimer::singleShot(0, this, SLOT(doClose()));
185         QTimer::singleShot(500, this, SLOT(exitApp()));
186     }
187
188 private slots:
189     void doClose() {
190         close();
191         if (showAgain)
192             show();
193     }
194
195     void exitApp() {
196       qApp->exit(1);
197     }
198
199 private:
200     bool showAgain;
201 };
202
203 void tst_QGuiApplication::abortQuitOnShow()
204 {
205     int argc = 0;
206     QGuiApplication app(argc, 0);
207     QWindow *window1 = new ShowCloseShowWindow(false);
208     window1->show();
209     QCOMPARE(app.exec(), 0);
210
211     QWindow *window2 = new ShowCloseShowWindow(true);
212     window2->show();
213     QCOMPARE(app.exec(), 1);
214 }
215
216
217 class FocusChangeWindow: public QWindow
218 {
219 protected:
220     virtual bool event(QEvent *ev)
221     {
222         if (ev->type() == QEvent::FocusAboutToChange)
223             windowDuringFocusAboutToChange = qGuiApp->focusWindow();
224         return QWindow::event(ev);
225     }
226
227     virtual void focusOutEvent(QFocusEvent *)
228     {
229         windowDuringFocusOut = qGuiApp->focusWindow();
230     }
231
232 public:
233     FocusChangeWindow() : QWindow(), windowDuringFocusAboutToChange(0), windowDuringFocusOut(0) {}
234
235     QWindow *windowDuringFocusAboutToChange;
236     QWindow *windowDuringFocusOut;
237 };
238
239 void tst_QGuiApplication::changeFocusWindow()
240 {
241     int argc = 0;
242     QGuiApplication app(argc, 0);
243
244     // focus is changed between FocusAboutToChange and FocusChanged
245     FocusChangeWindow window1, window2;
246     window1.show();
247     window2.show();
248     QVERIFY(QTest::qWaitForWindowExposed(&window1));
249     QVERIFY(QTest::qWaitForWindowExposed(&window2));
250     window1.requestActivate();
251     QTRY_COMPARE(app.focusWindow(), &window1);
252
253     window2.requestActivate();
254     QTRY_COMPARE(app.focusWindow(), &window2);
255     QCOMPARE(window1.windowDuringFocusAboutToChange, &window1);
256     QCOMPARE(window1.windowDuringFocusOut, &window2);
257 }
258
259 void tst_QGuiApplication::keyboardModifiers()
260 {
261     int argc = 0;
262     QGuiApplication app(argc, 0);
263
264     QWindow *window = new QWindow;
265     window->show();
266     QVERIFY(QTest::qWaitForWindowExposed(window));
267     QCOMPARE(QGuiApplication::keyboardModifiers(), Qt::NoModifier);
268
269     // mouse events
270     QPoint center = window->geometry().center();
271     QTest::mouseEvent(QTest::MousePress, window, Qt::LeftButton, Qt::NoModifier, center);
272     QCOMPARE(QGuiApplication::keyboardModifiers(), Qt::NoModifier);
273     QTest::mouseEvent(QTest::MouseRelease, window, Qt::LeftButton, Qt::NoModifier, center);
274     QCOMPARE(QGuiApplication::keyboardModifiers(), Qt::NoModifier);
275     QTest::mouseEvent(QTest::MousePress, window, Qt::RightButton, Qt::ControlModifier, center);
276     QCOMPARE(QGuiApplication::keyboardModifiers(), Qt::ControlModifier);
277     QTest::mouseEvent(QTest::MouseRelease, window, Qt::RightButton, Qt::ControlModifier, center);
278     QCOMPARE(QGuiApplication::keyboardModifiers(), Qt::ControlModifier);
279
280     // shortcut events
281     QWindowSystemInterface::tryHandleShortcutEvent(window, Qt::Key_5, Qt::MetaModifier);
282     QCOMPARE(QGuiApplication::keyboardModifiers(), Qt::MetaModifier);
283     QWindowSystemInterface::tryHandleShortcutEvent(window, Qt::Key_Period, Qt::NoModifier);
284     QCOMPARE(QGuiApplication::keyboardModifiers(), Qt::NoModifier);
285     QWindowSystemInterface::tryHandleShortcutEvent(window, Qt::Key_0, Qt::ControlModifier);
286     QCOMPARE(QGuiApplication::keyboardModifiers(), Qt::ControlModifier);
287
288     // key events
289     QTest::keyEvent(QTest::Press, window, Qt::Key_C);
290     QCOMPARE(QGuiApplication::keyboardModifiers(), Qt::NoModifier);
291     QTest::keyEvent(QTest::Release, window, Qt::Key_C);
292     QCOMPARE(QGuiApplication::keyboardModifiers(), Qt::NoModifier);
293
294     QTest::keyEvent(QTest::Press, window, Qt::Key_U, Qt::ControlModifier);
295     QCOMPARE(QGuiApplication::keyboardModifiers(), Qt::ControlModifier);
296     QTest::keyEvent(QTest::Release, window, Qt::Key_U, Qt::ControlModifier);
297     QCOMPARE(QGuiApplication::keyboardModifiers(), Qt::ControlModifier);
298
299     QTest::keyEvent(QTest::Press, window, Qt::Key_T);
300     QCOMPARE(QGuiApplication::keyboardModifiers(), Qt::NoModifier);
301     QTest::keyEvent(QTest::Release, window, Qt::Key_T);
302     QCOMPARE(QGuiApplication::keyboardModifiers(), Qt::NoModifier);
303
304     QTest::keyEvent(QTest::Press, window, Qt::Key_E, Qt::ControlModifier);
305     QCOMPARE(QGuiApplication::keyboardModifiers(), Qt::ControlModifier);
306     QTest::keyEvent(QTest::Release, window, Qt::Key_E, Qt::ControlModifier);
307     QCOMPARE(QGuiApplication::keyboardModifiers(), Qt::ControlModifier);
308
309     // wheel events
310     QPoint global = window->mapToGlobal(center);
311     QPoint delta(0, 1);
312     QWindowSystemInterface::handleWheelEvent(window, center, global, delta, delta, Qt::NoModifier);
313     QWindowSystemInterface::sendWindowSystemEvents(QEventLoop::AllEvents);
314     QCOMPARE(QGuiApplication::keyboardModifiers(), Qt::NoModifier);
315     QWindowSystemInterface::handleWheelEvent(window, center, global, delta, delta, Qt::AltModifier);
316     QWindowSystemInterface::sendWindowSystemEvents(QEventLoop::AllEvents);
317     QCOMPARE(QGuiApplication::keyboardModifiers(), Qt::AltModifier);
318     QWindowSystemInterface::handleWheelEvent(window, center, global, delta, delta, Qt::ControlModifier);
319     QWindowSystemInterface::sendWindowSystemEvents(QEventLoop::AllEvents);
320     QCOMPARE(QGuiApplication::keyboardModifiers(), Qt::ControlModifier);
321
322     // touch events
323     QList<const QTouchDevice *> touchDevices = QTouchDevice::devices();
324     if (!touchDevices.isEmpty()) {
325         QTouchDevice *touchDevice = const_cast<QTouchDevice *>(touchDevices.first());
326         QTest::touchEvent(window, touchDevice).press(1, center).release(1, center);
327         QCOMPARE(QGuiApplication::keyboardModifiers(), Qt::NoModifier);
328     }
329
330     window->close();
331     delete window;
332 }
333
334 class BlockableWindow : public QWindow
335 {
336     Q_OBJECT
337 public:
338     int blocked;
339     int leaves;
340     int enters;
341
342     inline BlockableWindow()
343         : QWindow(), blocked(false), enters(0), leaves(0) {}
344
345     bool event(QEvent *e)
346     {
347         switch (e->type()) {
348         case QEvent::WindowBlocked:
349             ++blocked;
350             break;
351         case QEvent::WindowUnblocked:
352             --blocked;
353             break;
354         case QEvent::Leave:
355             leaves++;
356             break;
357         case QEvent::Enter:
358             enters++;
359             break;
360         default:
361             break;
362         }
363         return QWindow::event(e);
364     }
365
366     void resetCounts()
367     {
368         leaves = 0;
369         enters = 0;
370     }
371 };
372
373 void tst_QGuiApplication::modalWindow()
374 {
375     int argc = 0;
376     QGuiApplication app(argc, 0);
377
378     BlockableWindow *window1 = new BlockableWindow;
379
380     BlockableWindow *window2 = new BlockableWindow;
381
382     BlockableWindow *windowModalWindow1 = new BlockableWindow;
383     windowModalWindow1->setTransientParent(window1);
384     windowModalWindow1->setModality(Qt::WindowModal);
385
386     BlockableWindow *windowModalWindow2 = new BlockableWindow;
387     windowModalWindow2->setTransientParent(windowModalWindow1);
388     windowModalWindow2->setModality(Qt::WindowModal);
389
390     BlockableWindow *applicationModalWindow1 = new BlockableWindow;
391     applicationModalWindow1->setModality(Qt::ApplicationModal);
392
393     // show the 2 windows, nothing is blocked
394     window1->show();
395     window2->show();
396     QVERIFY(QTest::qWaitForWindowExposed(window1));
397     QVERIFY(QTest::qWaitForWindowExposed(window2));
398     QCOMPARE(app.modalWindow(), static_cast<QWindow *>(0));
399     QCOMPARE(window1->blocked, 0);
400     QCOMPARE(window2->blocked, 0);
401     QCOMPARE(windowModalWindow1->blocked, 0);
402     QCOMPARE(windowModalWindow2->blocked, 0);
403     QCOMPARE(applicationModalWindow1->blocked, 0);
404
405     // enter mouse in window1
406     QWindowSystemInterface::handleEnterEvent(window1);
407     QGuiApplication::processEvents();
408     QCOMPARE(window1->enters, 1);
409     QCOMPARE(window1->leaves, 0);
410
411     // show applicationModalWindow1, everything is blocked
412     applicationModalWindow1->show();
413     QCOMPARE(app.modalWindow(), applicationModalWindow1);
414     QCOMPARE(window1->blocked, 1);
415     QCOMPARE(window2->blocked, 1);
416     QCOMPARE(windowModalWindow1->blocked, 1);
417     QCOMPARE(windowModalWindow2->blocked, 1);
418     QCOMPARE(applicationModalWindow1->blocked, 0);
419
420     // opening modal causes leave for previously entered window, but not others
421     QGuiApplication::processEvents();
422     QCOMPARE(window1->enters, 1);
423     QCOMPARE(window1->leaves, 1);
424     QCOMPARE(window2->enters, 0);
425     QCOMPARE(window2->leaves, 0);
426     QCOMPARE(applicationModalWindow1->enters, 0);
427     QCOMPARE(applicationModalWindow1->leaves, 0);
428     window1->resetCounts();
429
430     // Try entering/leaving blocked window2 - no events should reach it
431     QWindowSystemInterface::handleEnterEvent(window2);
432     QGuiApplication::processEvents();
433     QWindowSystemInterface::handleLeaveEvent(window2);
434     QGuiApplication::processEvents();
435     QCOMPARE(window2->enters, 0);
436     QCOMPARE(window2->leaves, 0);
437
438     // everything is unblocked when applicationModalWindow1 is hidden
439     applicationModalWindow1->hide();
440     QCOMPARE(app.modalWindow(), static_cast<QWindow *>(0));
441     QCOMPARE(window1->blocked, 0);
442     QCOMPARE(window2->blocked, 0);
443     QCOMPARE(windowModalWindow1->blocked, 0);
444     QCOMPARE(windowModalWindow2->blocked, 0);
445     QCOMPARE(applicationModalWindow1->blocked, 0);
446
447     // Enter window2 - should not be blocked
448     QWindowSystemInterface::handleEnterEvent(window2);
449     QGuiApplication::processEvents();
450     QCOMPARE(window2->enters, 1);
451     QCOMPARE(window2->leaves, 0);
452
453     // show the windowModalWindow1, only window1 is blocked
454     windowModalWindow1->show();
455     QCOMPARE(app.modalWindow(), windowModalWindow1);
456     QCOMPARE(window1->blocked, 1);
457     QCOMPARE(window2->blocked, 0);
458     QCOMPARE(windowModalWindow1->blocked, 0);
459     QCOMPARE(windowModalWindow2->blocked, 0);
460     QCOMPARE(applicationModalWindow1->blocked, 0);
461
462     // opening window modal window doesn't cause leave for unblocked window
463     QGuiApplication::processEvents();
464     QCOMPARE(window1->enters, 0);
465     QCOMPARE(window1->leaves, 0);
466     QCOMPARE(window2->enters, 1);
467     QCOMPARE(window2->leaves, 0);
468     QCOMPARE(windowModalWindow1->enters, 0);
469     QCOMPARE(windowModalWindow1->leaves, 0);
470
471     // show the windowModalWindow2, windowModalWindow1 is blocked as well
472     windowModalWindow2->show();
473     QCOMPARE(app.modalWindow(), windowModalWindow2);
474     QCOMPARE(window1->blocked, 1);
475     QCOMPARE(window2->blocked, 0);
476     QCOMPARE(windowModalWindow1->blocked, 1);
477     QCOMPARE(windowModalWindow2->blocked, 0);
478     QCOMPARE(applicationModalWindow1->blocked, 0);
479
480     // hide windowModalWindow1, nothing is unblocked
481     windowModalWindow1->hide();
482     QCOMPARE(app.modalWindow(), windowModalWindow2);
483     QCOMPARE(window1->blocked, 1);
484     QCOMPARE(window2->blocked, 0);
485     QCOMPARE(windowModalWindow1->blocked, 1);
486     QCOMPARE(windowModalWindow2->blocked, 0);
487     QCOMPARE(applicationModalWindow1->blocked, 0);
488
489     // hide windowModalWindow2, windowModalWindow1 and window1 are unblocked
490     windowModalWindow2->hide();
491     QCOMPARE(app.modalWindow(), static_cast<QWindow *>(0));
492     QCOMPARE(window1->blocked, 0);
493     QCOMPARE(window2->blocked, 0);
494     QCOMPARE(windowModalWindow1->blocked, 0);
495     QCOMPARE(windowModalWindow2->blocked, 0);
496     QCOMPARE(applicationModalWindow1->blocked, 0);
497
498     // show windowModalWindow1 again, window1 is blocked
499     windowModalWindow1->show();
500     QCOMPARE(app.modalWindow(), windowModalWindow1);
501     QCOMPARE(window1->blocked, 1);
502     QCOMPARE(window2->blocked, 0);
503     QCOMPARE(windowModalWindow1->blocked, 0);
504     QCOMPARE(windowModalWindow2->blocked, 0);
505     QCOMPARE(applicationModalWindow1->blocked, 0);
506
507     // show windowModalWindow2 again, windowModalWindow1 is also blocked
508     windowModalWindow2->show();
509     QCOMPARE(app.modalWindow(), windowModalWindow2);
510     QCOMPARE(window1->blocked, 1);
511     QCOMPARE(window2->blocked, 0);
512     QCOMPARE(windowModalWindow1->blocked, 1);
513     QCOMPARE(windowModalWindow2->blocked, 0);
514     QCOMPARE(applicationModalWindow1->blocked, 0);
515
516     // show applicationModalWindow1, everything is blocked
517     applicationModalWindow1->show();
518     QCOMPARE(app.modalWindow(), applicationModalWindow1);
519     QCOMPARE(window1->blocked, 1);
520     QCOMPARE(window2->blocked, 1);
521     QCOMPARE(windowModalWindow1->blocked, 1);
522     QCOMPARE(windowModalWindow2->blocked, 1);
523     QCOMPARE(applicationModalWindow1->blocked, 0);
524
525     // window2 gets finally the leave
526     QGuiApplication::processEvents();
527     QCOMPARE(window1->enters, 0);
528     QCOMPARE(window1->leaves, 0);
529     QCOMPARE(window2->enters, 1);
530     QCOMPARE(window2->leaves, 1);
531     QCOMPARE(windowModalWindow1->enters, 0);
532     QCOMPARE(windowModalWindow1->leaves, 0);
533     QCOMPARE(applicationModalWindow1->enters, 0);
534     QCOMPARE(applicationModalWindow1->leaves, 0);
535
536     // hide applicationModalWindow1, windowModalWindow1 and window1 are blocked
537     applicationModalWindow1->hide();
538     QCOMPARE(app.modalWindow(), windowModalWindow2);
539     QCOMPARE(window1->blocked, 1);
540     QCOMPARE(window2->blocked, 0);
541     QCOMPARE(windowModalWindow1->blocked, 1);
542     QCOMPARE(windowModalWindow2->blocked, 0);
543     QCOMPARE(applicationModalWindow1->blocked, 0);
544
545     // hide windowModalWindow2, window1 is blocked
546     windowModalWindow2->hide();
547     QCOMPARE(app.modalWindow(), windowModalWindow1);
548     QCOMPARE(window1->blocked, 1);
549     QCOMPARE(window2->blocked, 0);
550     QCOMPARE(windowModalWindow1->blocked, 0);
551     QCOMPARE(windowModalWindow2->blocked, 0);
552     QCOMPARE(applicationModalWindow1->blocked, 0);
553
554     // hide windowModalWindow1, everything is unblocked
555     windowModalWindow1->hide();
556     QCOMPARE(app.modalWindow(), static_cast<QWindow *>(0));
557     QCOMPARE(window1->blocked, 0);
558     QCOMPARE(window2->blocked, 0);
559     QCOMPARE(windowModalWindow1->blocked, 0);
560     QCOMPARE(windowModalWindow2->blocked, 0);
561     QCOMPARE(applicationModalWindow1->blocked, 0);
562
563     window2->hide();
564     window1->hide();
565
566     delete applicationModalWindow1;
567     delete windowModalWindow2;
568     delete windowModalWindow1;
569     delete window2;
570     delete window1;
571 }
572
573 void tst_QGuiApplication::quitOnLastWindowClosed()
574 {
575     {
576         int argc = 0;
577         QGuiApplication app(argc, 0);
578
579         QTimer timer;
580         timer.setInterval(100);
581
582         QSignalSpy spy(&app, SIGNAL(aboutToQuit()));
583         QSignalSpy spy2(&timer, SIGNAL(timeout()));
584
585         QPointer<QWindow> mainWindow = new QWindow;
586         QPointer<QWindow> dialog = new QWindow;
587
588         dialog->setTransientParent(mainWindow);
589
590         QVERIFY(app.quitOnLastWindowClosed());
591
592         mainWindow->show();
593         dialog->show();
594
595         timer.start();
596         QTimer::singleShot(1000, mainWindow, SLOT(close())); // This should quit the application
597         QTimer::singleShot(2000, &app, SLOT(quit()));        // This makes sure we quit even if it didn't
598
599         app.exec();
600
601         QCOMPARE(spy.count(), 1);
602         QVERIFY(spy2.count() < 15);      // Should be around 10 if closing caused the quit
603     }
604     {
605         int argc = 0;
606         QGuiApplication app(argc, 0);
607
608         QTimer timer;
609         timer.setInterval(100);
610
611         QSignalSpy spy(&app, SIGNAL(aboutToQuit()));
612         QSignalSpy spy2(&timer, SIGNAL(timeout()));
613
614         QPointer<QWindow> mainWindow = new QWindow;
615         QPointer<QWindow> dialog = new QWindow;
616
617         QVERIFY(!dialog->transientParent());
618         QVERIFY(app.quitOnLastWindowClosed());
619
620         mainWindow->show();
621         dialog->show();
622
623         timer.start();
624         QTimer::singleShot(1000, mainWindow, SLOT(close())); // This should not quit the application
625         QTimer::singleShot(2000, &app, SLOT(quit()));
626
627         app.exec();
628
629         QCOMPARE(spy.count(), 1);
630         QVERIFY(spy2.count() > 15);      // Should be around 20 if closing did not cause the quit
631     }
632 }
633
634 static Qt::ScreenOrientation testOrientationToSend = Qt::PrimaryOrientation;
635
636 class TestPlugin : public QObject
637 {
638     Q_OBJECT
639 public:
640     TestPlugin()
641     {
642         QScreen* screen = QGuiApplication::primaryScreen();
643         // Make sure the orientation we want to send doesn't get filtered out.
644         screen->setOrientationUpdateMask(screen->orientationUpdateMask() | testOrientationToSend);
645         QWindowSystemInterface::handleScreenOrientationChange(screen, testOrientationToSend);
646     }
647 };
648
649 class TestPluginFactory : public QGenericPlugin
650 {
651     Q_OBJECT
652     Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QGenericPluginFactoryInterface" FILE "testplugin.json")
653 public:
654     QObject* create(const QString &key, const QString &)
655     {
656         if (key == "testplugin")
657             return new TestPlugin;
658         return 0;
659     }
660 };
661
662 class TestEventReceiver : public QObject
663 {
664     Q_OBJECT
665 public:
666     int customEvents;
667
668     TestEventReceiver()
669         : customEvents(0)
670     {}
671
672     virtual void customEvent(QEvent *)
673     {
674         customEvents++;
675     }
676 };
677
678 #include "tst_qguiapplication.moc"
679
680 void tst_QGuiApplication::genericPluginsAndWindowSystemEvents()
681 {
682     testOrientationToSend = Qt::InvertedLandscapeOrientation;
683
684     TestEventReceiver testReceiver;
685     QCoreApplication::postEvent(&testReceiver, new QEvent(QEvent::User));
686     QCOMPARE(testReceiver.customEvents, 0);
687
688     QStaticPlugin testPluginInfo;
689     testPluginInfo.instance = qt_plugin_instance;
690     testPluginInfo.metaData = qt_plugin_query_metadata;
691     qRegisterStaticPluginFunction(testPluginInfo);
692     int argc = 3;
693     char *argv[] = { const_cast<char*>("tst_qguiapplication"), const_cast<char*>("-plugin"), const_cast<char*>("testplugin") };
694     QGuiApplication app(argc, argv);
695
696     QVERIFY(QGuiApplication::primaryScreen());
697     QVERIFY(QGuiApplication::primaryScreen()->orientation() == testOrientationToSend);
698
699     QCOMPARE(testReceiver.customEvents, 0);
700     QCoreApplication::sendPostedEvents(&testReceiver);
701     QCOMPARE(testReceiver.customEvents, 1);
702 }
703
704 QTEST_APPLESS_MAIN(tst_QGuiApplication)