Revert "Move QWindowSystemInterface out of qpa."
[profile/ivi/qtbase.git] / tests / auto / widgets / kernel / qapplication / tst_qapplication.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 //#define QT_TST_QAPP_DEBUG
44 #include <qdebug.h>
45
46 #include <QtTest/QtTest>
47
48 #include <QtCore/QAbstractEventDispatcher>
49 #include <QtCore/QFileInfo>
50 #include <QtCore/QDir>
51 #include <QtCore/QProcess>
52 #include <QtCore/private/qeventloop_p.h>
53
54 #include <QtGui/QFontDatabase>
55 #include <QtGui/QClipboard>
56
57 #include <QtWidgets/QApplication>
58 #include <QtWidgets/QMessageBox>
59 #include <QtWidgets/QStyleFactory>
60 #include <QtWidgets/QHBoxLayout>
61 #include <QtWidgets/QPushButton>
62 #include <QtWidgets/QLineEdit>
63 #include <QtWidgets/QLabel>
64 #include <QtWidgets/QMainWindow>
65 #include <QtWidgets/private/qapplication_p.h>
66 #include <QtWidgets/private/qstylesheetstyle_p.h>
67
68 #ifdef Q_OS_WINCE
69 #include <windows.h>
70 #endif
71
72 #include <qpa/qwindowsysteminterface.h>
73
74
75 QT_BEGIN_NAMESPACE
76 static QWindowSystemInterface::TouchPoint touchPoint(const QTouchEvent::TouchPoint& pt)
77 {
78     QWindowSystemInterface::TouchPoint p;
79     p.id = pt.id();
80     p.flags = pt.flags();
81     p.normalPosition = pt.normalizedPos();
82     p.area = pt.screenRect();
83     p.pressure = pt.pressure();
84     p.state = pt.state();
85     p.velocity = pt.velocity();
86     p.rawPositions = pt.rawScreenPositions();
87     return p;
88 }
89
90 static QList<struct QWindowSystemInterface::TouchPoint> touchPointList(const QList<QTouchEvent::TouchPoint>& pointList)
91 {
92     QList<struct QWindowSystemInterface::TouchPoint> newList;
93
94     Q_FOREACH (QTouchEvent::TouchPoint p, pointList)
95     {
96         newList.append(touchPoint(p));
97     }
98     return newList;
99 }
100
101
102
103 extern bool Q_GUI_EXPORT qt_tab_all_widgets; // from qapplication.cpp
104 QT_END_NAMESPACE
105
106 class tst_QApplication : public QObject
107 {
108 Q_OBJECT
109
110 public:
111     tst_QApplication();
112     virtual ~tst_QApplication();
113
114 public slots:
115     void initTestCase();
116     void init();
117     void cleanup();
118 private slots:
119     void sendEventsOnProcessEvents(); // this must be the first test
120     void staticSetup();
121
122     void alert();
123
124     void multiple_data();
125     void multiple();
126
127     void nonGui();
128
129     void setFont_data();
130     void setFont();
131
132     void args_data();
133     void args();
134     void appName();
135
136     void lastWindowClosed();
137     void quitOnLastWindowClosed();
138     void closeAllWindows();
139     void testDeleteLater();
140     void testDeleteLaterProcessEvents();
141
142     void libraryPaths();
143     void libraryPaths_qt_plugin_path();
144     void libraryPaths_qt_plugin_path_2();
145
146     void sendPostedEvents();
147
148     void thread();
149     void desktopSettingsAware();
150
151     void setActiveWindow();
152
153     void focusChanged();
154     void focusOut();
155
156     void execAfterExit();
157
158     void wheelScrollLines();
159
160     void task109149();
161
162     void style();
163
164     void allWidgets();
165     void topLevelWidgets();
166
167     void setAttribute();
168
169     void windowsCommandLine_data();
170     void windowsCommandLine();
171
172     void touchEventPropagation();
173
174     void qtbug_12673();
175     void noQuitOnHide();
176
177     void globalStaticObjectDestruction(); // run this last
178
179     void abortQuitOnShow();
180 };
181
182 class EventSpy : public QObject
183 {
184    Q_OBJECT
185
186 public:
187     QList<int> recordedEvents;
188     bool eventFilter(QObject *, QEvent *event)
189     {
190         recordedEvents.append(event->type());
191         return false;
192     }
193 };
194
195 void tst_QApplication::initTestCase()
196 {
197     // chdir to our testdata path and execute helper apps relative to that.
198     const QString testdataDir = QFileInfo(QFINDTESTDATA("desktopsettingsaware")).absolutePath();
199     QVERIFY2(QDir::setCurrent(testdataDir), qPrintable("Could not chdir to " + testdataDir));
200 }
201
202 void tst_QApplication::sendEventsOnProcessEvents()
203 {
204     int argc = 0;
205     QApplication app(argc, 0, QApplication::GuiServer);
206
207     EventSpy spy;
208     app.installEventFilter(&spy);
209
210     QCoreApplication::postEvent(&app,  new QEvent(QEvent::Type(QEvent::User + 1)));
211     QCoreApplication::processEvents();
212     QVERIFY(spy.recordedEvents.contains(QEvent::User + 1));
213 }
214
215
216 class CloseEventTestWindow : public QWidget
217 {
218 public:
219     CloseEventTestWindow(QWidget *parent = 0)
220         : QWidget(parent)
221     {
222     }
223
224     void closeEvent(QCloseEvent *event)
225     {
226         QWidget dialog;
227         dialog.show();
228         dialog.close();
229
230         event->ignore();
231     }
232 };
233
234 static  char *argv0;
235
236 tst_QApplication::tst_QApplication()
237 {
238 #ifdef Q_OS_WINCE
239     // Clean up environment previously to launching test
240     qputenv("QT_PLUGIN_PATH", QByteArray());
241 #endif
242 }
243
244 tst_QApplication::~tst_QApplication()
245 {
246
247 }
248
249 void tst_QApplication::init()
250 {
251 // TODO: Add initialization code here.
252 // This will be executed immediately before each test is run.
253 }
254
255 void tst_QApplication::cleanup()
256 {
257 // TODO: Add cleanup code here.
258 // This will be executed immediately after each test is run.
259 }
260
261 void tst_QApplication::staticSetup()
262 {
263     QVERIFY(!qApp);
264
265     QStyle *style = QStyleFactory::create(QLatin1String("Windows"));
266     QVERIFY(style);
267     QApplication::setStyle(style);
268
269     QPalette pal;
270     QApplication::setPalette(pal);
271
272     /*QFont font;
273     QApplication::setFont(font);*/
274
275     int argc = 0;
276     QApplication app(argc, 0, QApplication::GuiServer);
277 }
278
279
280 // QApp subclass that exits the event loop after 150ms
281 class TestApplication : public QApplication
282 {
283 public:
284     TestApplication( int &argc, char **argv )
285         : QApplication( argc, argv, QApplication::GuiServer )
286     {
287         startTimer( 150 );
288     }
289
290     void timerEvent( QTimerEvent * )
291     {
292         quit();
293     }
294 };
295
296 void tst_QApplication::alert()
297 {
298     int argc = 0;
299     QApplication app(argc, 0, QApplication::GuiServer);
300     app.alert(0, 0);
301
302     QWidget widget;
303     QWidget widget2;
304     app.alert(&widget, 100);
305     widget.show();
306     widget2.show();
307     QVERIFY(QTest::qWaitForWindowExposed(&widget));
308     QVERIFY(QTest::qWaitForWindowExposed(&widget2));
309     QTest::qWait(100);
310     app.alert(&widget, -1);
311     app.alert(&widget, 250);
312     widget2.activateWindow();
313     QApplication::setActiveWindow(&widget2);
314     app.alert(&widget, 0);
315     widget.activateWindow();
316     QApplication::setActiveWindow(&widget);
317     app.alert(&widget, 200);
318     app.syncX();
319 }
320
321 void tst_QApplication::multiple_data()
322 {
323     QTest::addColumn<QStringList>("features");
324
325     // return a list of things to try
326     QTest::newRow( "data0" ) << QStringList( "" );
327     QTest::newRow( "data1" ) << QStringList( "QFont" );
328     QTest::newRow( "data2" ) << QStringList( "QPixmap" );
329     QTest::newRow( "data3" ) << QStringList( "QWidget" );
330 }
331
332 void tst_QApplication::multiple()
333 {
334     QFETCH(QStringList,features);
335
336     int i = 0;
337     int argc = 0;
338     while ( i++ < 5 ) {
339         TestApplication app( argc, 0 );
340
341         if ( features.contains( "QFont" ) ) {
342             // create font and force loading
343             QFont font( "Arial", 12 );
344             QFontInfo finfo( font );
345             finfo.exactMatch();
346         }
347         if ( features.contains( "QPixmap" ) ) {
348             QPixmap pix( 100, 100 );
349             pix.fill( Qt::black );
350         }
351         if ( features.contains( "QWidget" ) ) {
352             QWidget widget;
353         }
354
355         QVERIFY(!app.exec());
356     }
357 }
358
359 void tst_QApplication::nonGui()
360 {
361 #ifdef Q_OS_HPUX
362     // ### This is only to allow us to generate a test report for now.
363     QSKIP("This test shuts down the window manager on HP-UX.");
364 #endif
365
366     int argc = 0;
367     QApplication app(argc, 0, false);
368     QCOMPARE(qApp, &app);
369 }
370
371 void tst_QApplication::setFont_data()
372 {
373     QTest::addColumn<QString>("family");
374     QTest::addColumn<int>("pointsize");
375     QTest::addColumn<bool>("beforeAppConstructor");
376
377     int argc = 0;
378     QApplication app(argc, 0, QApplication::GuiServer); // Needed for QFontDatabase
379
380     int cnt = 0;
381     QFontDatabase fdb;
382     QStringList families = fdb.families();
383     for (QStringList::const_iterator itr = families.begin();
384          itr != families.end();
385          ++itr) {
386         if (cnt < 3) {
387             QString family = *itr;
388             QStringList styles = fdb.styles(family);
389             if (styles.size() > 0) {
390                 QString style = styles.first();
391                 QList<int> sizes = fdb.pointSizes(family, style);
392                 if (!sizes.size())
393                     sizes = fdb.standardSizes();
394                 if (sizes.size() > 0) {
395                     QTest::newRow(QString("data%1a").arg(cnt).toLatin1().constData())
396                         << family
397                         << sizes.first()
398                         << false;
399                     QTest::newRow(QString("data%1b").arg(cnt).toLatin1().constData())
400                         << family
401                         << sizes.first()
402                         << true;
403                 }
404             }
405         }
406         ++cnt;
407     }
408
409     QTest::newRow("nonexistingfont after") << "nosuchfont_probably_quiteunlikely"
410         << 0 << false;
411     QTest::newRow("nonexistingfont before") << "nosuchfont_probably_quiteunlikely"
412         << 0 << true;
413
414     QTest::newRow("largescaleable after") << "smoothtimes" << 100 << false;
415     QTest::newRow("largescaleable before") << "smoothtimes" << 100 << true;
416
417     QTest::newRow("largeunscaleale after") << "helvetica" << 100 << false;
418     QTest::newRow("largeunscaleale before") << "helvetica" << 100 << true;
419 }
420
421 void tst_QApplication::setFont()
422 {
423     QFETCH( QString, family );
424     QFETCH( int, pointsize );
425     QFETCH( bool, beforeAppConstructor );
426
427     QFont font( family, pointsize );
428     if (beforeAppConstructor) {
429         QApplication::setFont( font );
430         QCOMPARE(QApplication::font(), font);
431     }
432
433     int argc = 0;
434     QApplication app( argc, 0, QApplication::GuiServer );
435     if (!beforeAppConstructor)
436         QApplication::setFont( font );
437
438     QCOMPARE( app.font(), font );
439 }
440
441 void tst_QApplication::args_data()
442 {
443     QTest::addColumn<int>("argc_in");
444     QTest::addColumn<QString>("args_in");
445     QTest::addColumn<int>("argc_out");
446     QTest::addColumn<QString>("args_out");
447
448     QTest::newRow( "App name" ) << 1 << "/usr/bin/appname" << 1 << "/usr/bin/appname";
449     QTest::newRow( "No arguments" ) << 0 << QString() << 0 << QString();
450     QTest::newRow( "App name, style" ) << 3 << "/usr/bin/appname -style motif" << 1 << "/usr/bin/appname";
451     QTest::newRow( "App name, style, arbitrary, reverse" ) << 5 << "/usr/bin/appname -style motif -arbitrary -reverse"
452                                                         << 2 << "/usr/bin/appname -arbitrary";
453 }
454
455 void tst_QApplication::task109149()
456 {
457     int argc = 0;
458     QApplication app(argc, 0, QApplication::GuiServer);
459     QApplication::setFont(QFont("helvetica", 100));
460
461     QWidget w;
462     w.setWindowTitle("hello");
463     w.show();
464
465     app.processEvents();
466 }
467
468 static char ** QString2cstrings( const QString &args )
469 {
470     static QList<QByteArray> cache;
471
472     int i;
473     char **argarray = 0;
474     QStringList list = args.split(' ');;
475     argarray = new char*[list.count()+1];
476
477     for (i = 0; i < (int)list.count(); ++i ) {
478         QByteArray l1 = list[i].toLatin1();
479         argarray[i] = l1.data();
480         cache.append(l1);
481     }
482     argarray[i] = 0;
483
484     return argarray;
485 }
486
487 static QString cstrings2QString( char **args )
488 {
489     QString string;
490     if ( !args )
491         return string;
492
493     int i = 0;
494     while ( args[i] ) {
495         string += args[i];
496         if ( args[i+1] )
497             string += " ";
498         ++i;
499     }
500     return string;
501 }
502
503 void tst_QApplication::args()
504 {
505     QFETCH( int, argc_in );
506     QFETCH( QString, args_in );
507     QFETCH( int, argc_out );
508     QFETCH( QString, args_out );
509
510     char **argv = QString2cstrings( args_in );
511
512     QApplication app( argc_in, argv, QApplication::GuiServer );
513     QString argv_out = cstrings2QString(argv);
514
515     QCOMPARE( argc_in, argc_out );
516     QCOMPARE( argv_out, args_out );
517
518     delete [] argv;
519 }
520
521 void tst_QApplication::appName()
522 {
523     char argv0[] = "tst_qapplication";
524     char *argv[] = { argv0, 0 };
525     int argc = 1;
526     QApplication app(argc, argv);
527     QCOMPARE(::qAppName(), QString::fromLatin1("tst_qapplication"));
528     QCOMPARE(QCoreApplication::applicationName(), QString::fromLatin1("tst_qapplication"));
529 }
530
531 class CloseWidget : public QWidget
532 {
533     Q_OBJECT
534 public:
535     CloseWidget()
536     {
537         startTimer(500);
538     }
539
540 protected:
541     void timerEvent(QTimerEvent *)
542     {
543         close();
544     }
545
546 };
547
548 void tst_QApplication::lastWindowClosed()
549 {
550     int argc = 0;
551     QApplication app(argc, 0, QApplication::GuiServer);
552
553     QSignalSpy spy(&app, SIGNAL(lastWindowClosed()));
554
555     QPointer<QDialog> dialog = new QDialog;
556     QVERIFY(dialog->testAttribute(Qt::WA_QuitOnClose));
557     QTimer::singleShot(1000, dialog, SLOT(accept()));
558     dialog->exec();
559     QVERIFY(dialog);
560     QCOMPARE(spy.count(), 0);
561
562     QPointer<CloseWidget>widget = new CloseWidget;
563     QVERIFY(widget->testAttribute(Qt::WA_QuitOnClose));
564     widget->show();
565     QObject::connect(&app, SIGNAL(lastWindowClosed()), widget, SLOT(deleteLater()));
566     app.exec();
567     QVERIFY(!widget);
568     QCOMPARE(spy.count(), 1);
569     spy.clear();
570
571     delete dialog;
572
573     // show 3 windows, close them, should only get lastWindowClosed once
574     QWidget w1;
575     QWidget w2;
576     QWidget w3;
577     w1.show();
578     w2.show();
579     w3.show();
580
581     QTimer::singleShot(1000, &app, SLOT(closeAllWindows()));
582     app.exec();
583     QCOMPARE(spy.count(), 1);
584 }
585
586 class QuitOnLastWindowClosedDialog : public QDialog
587 {
588     Q_OBJECT
589 public:
590     QPushButton *okButton;
591
592     QuitOnLastWindowClosedDialog()
593     {
594         QHBoxLayout *hbox = new QHBoxLayout(this);
595         okButton = new QPushButton("&ok", this);
596
597         hbox->addWidget(okButton);
598         connect(okButton, SIGNAL(clicked()), this, SLOT(accept()));
599         connect(okButton, SIGNAL(clicked()), this, SLOT(ok_clicked()));
600     }
601
602 public slots:
603     void ok_clicked()
604     {
605         QDialog other;
606
607         QTimer timer;
608         connect(&timer, SIGNAL(timeout()), &other, SLOT(accept()));
609         QSignalSpy spy(&timer, SIGNAL(timeout()));
610         QSignalSpy appSpy(qApp, SIGNAL(lastWindowClosed()));
611
612         timer.start(1000);
613         other.exec();
614
615         // verify that the eventloop ran and let the timer fire
616         QCOMPARE(spy.count(), 1);
617         QCOMPARE(appSpy.count(), 1);
618     }
619 };
620
621 class QuitOnLastWindowClosedWindow : public QWidget
622 {
623     Q_OBJECT
624
625 public:
626     QuitOnLastWindowClosedWindow()
627     { }
628
629 public slots:
630     void execDialogThenShow()
631     {
632         QDialog dialog;
633         QTimer timer1;
634         connect(&timer1, SIGNAL(timeout()), &dialog, SLOT(accept()));
635         QSignalSpy spy1(&timer1, SIGNAL(timeout()));
636         timer1.setSingleShot(true);
637         timer1.start(1000);
638         dialog.exec();
639         QCOMPARE(spy1.count(), 1);
640
641         show();
642     }
643 };
644
645 void tst_QApplication::quitOnLastWindowClosed()
646 {
647     {
648         int argc = 0;
649         QApplication app(argc, 0, QApplication::GuiServer);
650
651         QuitOnLastWindowClosedDialog d;
652         d.show();
653         QTimer::singleShot(1000, d.okButton, SLOT(animateClick()));
654
655         QSignalSpy appSpy(&app, SIGNAL(lastWindowClosed()));
656         app.exec();
657
658         // lastWindowClosed() signal should only be sent after the last dialog is closed
659         QCOMPARE(appSpy.count(), 2);
660     }
661     {
662         int argc = 0;
663         QApplication app(argc, 0, QApplication::GuiServer);
664         QSignalSpy appSpy(&app, SIGNAL(lastWindowClosed()));
665
666         QDialog dialog;
667         QTimer timer1;
668         connect(&timer1, SIGNAL(timeout()), &dialog, SLOT(accept()));
669         QSignalSpy spy1(&timer1, SIGNAL(timeout()));
670         timer1.setSingleShot(true);
671         timer1.start(1000);
672         dialog.exec();
673         QCOMPARE(spy1.count(), 1);
674         QCOMPARE(appSpy.count(), 0);
675
676         QTimer timer2;
677         connect(&timer2, SIGNAL(timeout()), &app, SLOT(quit()));
678         QSignalSpy spy2(&timer2, SIGNAL(timeout()));
679         timer2.setSingleShot(true);
680         timer2.start(1000);
681         int returnValue = app.exec();
682         QCOMPARE(returnValue, 0);
683         QCOMPARE(spy2.count(), 1);
684         QCOMPARE(appSpy.count(), 0);
685     }
686     {
687         int argc = 0;
688         QApplication app(argc, 0, QApplication::GuiServer);
689         QTimer timer;
690         timer.setInterval(100);
691
692         QSignalSpy spy(&app, SIGNAL(aboutToQuit()));
693         QSignalSpy spy2(&timer, SIGNAL(timeout()));
694
695         QPointer<QMainWindow> mainWindow = new QMainWindow;
696         QPointer<QDialog> dialog = new QDialog(mainWindow);
697
698         QVERIFY(app.quitOnLastWindowClosed());
699         QVERIFY(mainWindow->testAttribute(Qt::WA_QuitOnClose));
700         QVERIFY(dialog->testAttribute(Qt::WA_QuitOnClose));
701
702         mainWindow->show();
703         dialog->show();
704
705         timer.start();
706         QTimer::singleShot(1000, mainWindow, SLOT(close())); // This should quit the application
707         QTimer::singleShot(2000, &app, SLOT(quit()));        // This makes sure we quit even if it didn't
708
709         app.exec();
710
711         QCOMPARE(spy.count(), 1);
712         QVERIFY(spy2.count() < 15);      // Should be around 10 if closing caused the quit
713     }
714     {
715         int argc = 0;
716         QApplication app(argc, 0, QApplication::GuiServer);
717         QTimer timer;
718         timer.setInterval(100);
719
720         QSignalSpy spy(&app, SIGNAL(aboutToQuit()));
721         QSignalSpy spy2(&timer, SIGNAL(timeout()));
722
723         QPointer<CloseEventTestWindow> mainWindow = new CloseEventTestWindow;
724
725         QVERIFY(app.quitOnLastWindowClosed());
726         QVERIFY(mainWindow->testAttribute(Qt::WA_QuitOnClose));
727
728         mainWindow->show();
729
730         timer.start();
731         QTimer::singleShot(1000, mainWindow, SLOT(close())); // This should quit the application
732         QTimer::singleShot(2000, &app, SLOT(quit()));        // This makes sure we quit even if it didn't
733
734         app.exec();
735
736         QCOMPARE(spy.count(), 1);
737         QVERIFY(spy2.count() > 15);      // Should be around 20 if closing did not caused the quit
738     }
739     {
740         int argc = 0;
741         QApplication app(argc, 0, QApplication::GuiServer);
742         QSignalSpy appSpy(&app, SIGNAL(lastWindowClosed()));
743
744         // exec a dialog for 1 second, then show the window
745         QuitOnLastWindowClosedWindow window;
746         QTimer::singleShot(0, &window, SLOT(execDialogThenShow()));
747
748         QTimer timer;
749         QSignalSpy timerSpy(&timer, SIGNAL(timeout()));
750         connect(&timer, SIGNAL(timeout()), &window, SLOT(close()));
751         timer.setSingleShot(true);
752         timer.start(2000);
753         int returnValue = app.exec();
754         QCOMPARE(returnValue, 0);
755         // failure here means the timer above didn't fire, and the
756         // quit was caused the the dialog being closed (not the window)
757         QCOMPARE(timerSpy.count(), 1);
758         QCOMPARE(appSpy.count(), 2);
759     }
760     {
761         int argc = 0;
762         QApplication app(argc, 0, QApplication::GuiServer);
763         QVERIFY(app.quitOnLastWindowClosed());
764
765         QTimer timer;
766         timer.setInterval(100);
767         QSignalSpy timerSpy(&timer, SIGNAL(timeout()));
768
769         QWindow w;
770         w.show();
771
772         QWidget wid;
773         wid.show();
774
775         timer.start();
776         QTimer::singleShot(1000, &wid, SLOT(close())); // This should NOT quit the application because the
777                                                        // QWindow is still there.
778         QTimer::singleShot(2000, &app, SLOT(quit()));  // This causes the quit.
779
780         app.exec();
781
782         QVERIFY(timerSpy.count() > 15);      // Should be around 20 if closing did not caused the quit
783     }
784 }
785
786 class PromptOnCloseWidget : public QWidget
787 {
788 public:
789     void closeEvent(QCloseEvent *event)
790     {
791         QMessageBox *messageBox = new QMessageBox(this);
792         messageBox->setWindowTitle("Unsaved data");
793         messageBox->setText("Would you like to save or discard your current data?");
794         messageBox->setStandardButtons(QMessageBox::Save|QMessageBox::Discard|QMessageBox::Cancel);
795         messageBox->setDefaultButton(QMessageBox::Save);
796
797         messageBox->show();
798         QVERIFY(QTest::qWaitForWindowExposed(messageBox));
799
800         // verify that all windows are visible
801         foreach (QWidget *w, qApp->topLevelWidgets())
802             QVERIFY(w->isVisible());
803         // flush event queue
804         qApp->processEvents();
805         // close all windows
806         qApp->closeAllWindows();
807
808         if (messageBox->standardButton(messageBox->clickedButton()) == QMessageBox::Cancel)
809             event->ignore();
810         else
811             event->accept();
812
813         delete messageBox;
814     }
815 };
816
817 void tst_QApplication::closeAllWindows()
818 {
819     int argc = 0;
820     QApplication app(argc, 0, QApplication::GuiServer);
821
822     // create some windows
823     new QWidget;
824     new QWidget;
825     new QWidget;
826
827     // show all windows
828     foreach (QWidget *w, app.topLevelWidgets()) {
829         w->show();
830         QVERIFY(QTest::qWaitForWindowExposed(w));
831     }
832     // verify that they are visible
833     foreach (QWidget *w, app.topLevelWidgets())
834         QVERIFY(w->isVisible());
835     // empty event queue
836     app.processEvents();
837     // close all windows
838     app.closeAllWindows();
839     // all windows should no longer be visible
840     foreach (QWidget *w, app.topLevelWidgets())
841         QVERIFY(!w->isVisible());
842
843     // add a window that prompts the user when closed
844     PromptOnCloseWidget *promptOnCloseWidget = new PromptOnCloseWidget;
845     // show all windows
846     foreach (QWidget *w, app.topLevelWidgets()) {
847         w->show();
848         QVERIFY(QTest::qWaitForWindowExposed(w));
849     }
850     // close the last window to open the prompt (eventloop recurses)
851     promptOnCloseWidget->close();
852     // all windows should not be visible, except the one that opened the prompt
853     foreach (QWidget *w, app.topLevelWidgets()) {
854         if (w == promptOnCloseWidget)
855             QVERIFY(w->isVisible());
856         else
857             QVERIFY(!w->isVisible());
858     }
859
860     qDeleteAll(app.topLevelWidgets());
861 }
862
863 bool isPathListIncluded(const QStringList &l, const QStringList &r)
864 {
865     int size = r.count();
866     if (size > l.count())
867         return false;
868 #if defined (Q_OS_WIN)
869     Qt::CaseSensitivity cs = Qt::CaseInsensitive;
870 #else
871     Qt::CaseSensitivity cs = Qt::CaseSensitive;
872 #endif
873     int i = 0, j = 0;
874     for ( ; i < l.count() && j < r.count(); ++i) {
875         if (QDir::toNativeSeparators(l[i]).compare(QDir::toNativeSeparators(r[j]), cs) == 0) {
876             ++j;
877             i = -1;
878         }
879     }
880     return j == r.count();
881 }
882
883 #define QT_TST_QAPP_DEBUG
884 void tst_QApplication::libraryPaths()
885 {
886     {
887 #ifndef Q_OS_WINCE
888         QString testDir = QFileInfo(QFINDTESTDATA("test/test.pro")).absolutePath();
889 #else
890         // On Windows CE we need QApplication object to have valid
891         // current Path. Therefore we need to identify it ourselves
892         // here for the test.
893         QFileInfo filePath;
894         wchar_t module_name[MAX_PATH];
895         GetModuleFileName(0, module_name, MAX_PATH);
896         filePath = QString::fromWCharArray(module_name);
897         QString testDir = filePath.path() + "/test";
898 #endif
899         QApplication::setLibraryPaths(QStringList() << testDir);
900         QCOMPARE(QApplication::libraryPaths(), (QStringList() << testDir));
901
902         // creating QApplication adds the applicationDirPath to the libraryPath
903         int argc = 1;
904         QApplication app(argc, &argv0, QApplication::GuiServer);
905         QString appDirPath = QDir(app.applicationDirPath()).canonicalPath();
906
907         QStringList actual = QApplication::libraryPaths();
908         actual.sort();
909         QStringList expected = QSet<QString>::fromList((QStringList() << testDir << appDirPath)).toList();
910         expected.sort();
911
912         QVERIFY2(isPathListIncluded(actual, expected),
913                  qPrintable("actual:\n - " + actual.join("\n - ") +
914                             "\nexpected:\n - " + expected.join("\n - ")));
915     }
916     {
917         // creating QApplication adds the applicationDirPath and plugin install path to the libraryPath
918         int argc = 1;
919         QApplication app(argc, &argv0, QApplication::GuiServer);
920         QString appDirPath = app.applicationDirPath();
921         QString installPathPlugins =  QLibraryInfo::location(QLibraryInfo::PluginsPath);
922
923         QStringList actual = QApplication::libraryPaths();
924         actual.sort();
925
926         QStringList expected = QSet<QString>::fromList((QStringList() << installPathPlugins << appDirPath)).toList();
927         expected.sort();
928
929         QVERIFY2(isPathListIncluded(actual, expected),
930                  qPrintable("actual:\n - " + actual.join("\n - ") +
931                             "\nexpected:\n - " + expected.join("\n - ")));
932
933         // setting the library paths overrides everything
934         QString testDir = QFileInfo(QFINDTESTDATA("test/test.pro")).absolutePath();
935         QApplication::setLibraryPaths(QStringList() << testDir);
936         QVERIFY2(isPathListIncluded(QApplication::libraryPaths(), (QStringList() << testDir)),
937                  qPrintable("actual:\n - " + QApplication::libraryPaths().join("\n - ") +
938                             "\nexpected:\n - " + testDir));
939     }
940     {
941 #ifdef QT_TST_QAPP_DEBUG
942         qDebug() << "Initial library path:" << QApplication::libraryPaths();
943 #endif
944
945         int count = QApplication::libraryPaths().count();
946 #if 0
947         // this test doesn't work if KDE 4 is installed
948         QCOMPARE(count, 1); // before creating QApplication, only the PluginsPath is in the libraryPaths()
949 #endif
950         QString installPathPlugins =  QLibraryInfo::location(QLibraryInfo::PluginsPath);
951         QApplication::addLibraryPath(installPathPlugins);
952 #ifdef QT_TST_QAPP_DEBUG
953         qDebug() << "installPathPlugins" << installPathPlugins;
954         qDebug() << "After adding plugins path:" << QApplication::libraryPaths();
955 #endif
956         QCOMPARE(QApplication::libraryPaths().count(), count);
957         QString testDir = QFileInfo(QFINDTESTDATA("test/test.pro")).absolutePath();
958         QApplication::addLibraryPath(testDir);
959         QCOMPARE(QApplication::libraryPaths().count(), count + 1);
960
961         // creating QApplication adds the applicationDirPath to the libraryPath
962         int argc = 1;
963         QApplication app(argc, &argv0, QApplication::GuiServer);
964         QString appDirPath = app.applicationDirPath();
965         qDebug() << QApplication::libraryPaths();
966         // On Windows CE these are identical and might also be the case for other
967         // systems too
968         if (appDirPath != installPathPlugins)
969             QCOMPARE(QApplication::libraryPaths().count(), count + 2);
970     }
971     {
972         int argc = 1;
973         QApplication app(argc, &argv0, QApplication::GuiServer);
974
975 #ifdef QT_TST_QAPP_DEBUG
976         qDebug() << "Initial library path:" << app.libraryPaths();
977 #endif
978         int count = app.libraryPaths().count();
979         QString installPathPlugins =  QLibraryInfo::location(QLibraryInfo::PluginsPath);
980         app.addLibraryPath(installPathPlugins);
981 #ifdef QT_TST_QAPP_DEBUG
982         qDebug() << "installPathPlugins" << installPathPlugins;
983         qDebug() << "After adding plugins path:" << app.libraryPaths();
984 #endif
985         QCOMPARE(app.libraryPaths().count(), count);
986
987         QString appDirPath = app.applicationDirPath();
988
989         app.addLibraryPath(appDirPath);
990 #ifdef Q_OS_WINCE
991         app.addLibraryPath(appDirPath + "/../..");
992 #else
993         app.addLibraryPath(appDirPath + "/..");
994 #endif
995 #ifdef QT_TST_QAPP_DEBUG
996         qDebug() << "appDirPath" << appDirPath;
997         qDebug() << "After adding appDirPath && appDirPath + /..:" << app.libraryPaths();
998 #endif
999         QCOMPARE(app.libraryPaths().count(), count + 1);
1000 #ifdef Q_OS_MAC
1001         app.addLibraryPath(appDirPath + "/../MacOS");
1002 #else
1003         app.addLibraryPath(appDirPath + "/tmp/..");
1004 #endif
1005 #ifdef QT_TST_QAPP_DEBUG
1006         qDebug() << "After adding appDirPath + /tmp/..:" << app.libraryPaths();
1007 #endif
1008         QCOMPARE(app.libraryPaths().count(), count + 1);
1009     }
1010 }
1011
1012 void tst_QApplication::libraryPaths_qt_plugin_path()
1013 {
1014     int argc = 1;
1015
1016     QApplication app(argc, &argv0, QApplication::GuiServer);
1017     QString appDirPath = app.applicationDirPath();
1018
1019     // Our hook into libraryPaths() initialization: Set the QT_PLUGIN_PATH environment variable
1020     QString installPathPluginsDeCanon = appDirPath + QString::fromLatin1("/tmp/..");
1021     QByteArray ascii = QFile::encodeName(installPathPluginsDeCanon);
1022     qputenv("QT_PLUGIN_PATH", ascii);
1023
1024     QVERIFY(!app.libraryPaths().contains(appDirPath + QString::fromLatin1("/tmp/..")));
1025 }
1026
1027 void tst_QApplication::libraryPaths_qt_plugin_path_2()
1028 {
1029 #ifdef Q_OS_UNIX
1030     QByteArray validPath = QDir("/tmp").canonicalPath().toLatin1();
1031     QByteArray nonExistentPath = "/nonexistent";
1032     QByteArray pluginPath = validPath + ":" + nonExistentPath;
1033 #elif defined(Q_OS_WIN)
1034 # ifdef Q_OS_WINCE
1035     QByteArray validPath = "/Temp";
1036     QByteArray nonExistentPath = "/nonexistent";
1037     QByteArray pluginPath = validPath + ";" + nonExistentPath;
1038 # else
1039     QByteArray validPath = "C:\\windows";
1040     QByteArray nonExistentPath = "Z:\\nonexistent";
1041     QByteArray pluginPath = validPath + ";" + nonExistentPath;
1042 # endif
1043 #endif
1044
1045     {
1046         // Our hook into libraryPaths() initialization: Set the QT_PLUGIN_PATH environment variable
1047         qputenv("QT_PLUGIN_PATH", pluginPath);
1048
1049         int argc = 1;
1050
1051         QApplication app(argc, &argv0, QApplication::GuiServer);
1052
1053         // library path list should contain the default plus the one valid path
1054         QStringList expected =
1055             QStringList()
1056             << QLibraryInfo::location(QLibraryInfo::PluginsPath)
1057             << QDir(app.applicationDirPath()).canonicalPath()
1058             << QDir(QDir::fromNativeSeparators(QString::fromLatin1(validPath))).canonicalPath();
1059 # ifdef Q_OS_WINCE
1060         expected = QSet<QString>::fromList(expected).toList();
1061 # endif
1062         QVERIFY2(isPathListIncluded(app.libraryPaths(), expected),
1063                  qPrintable("actual:\n - " + app.libraryPaths().join("\n - ") +
1064                             "\nexpected:\n - " + expected.join("\n - ")));
1065     }
1066
1067     {
1068         int argc = 1;
1069
1070         QApplication app(argc, &argv0, QApplication::GuiServer);
1071
1072         // library paths are initialized by the QApplication, setting
1073         // the environment variable here doesn't work
1074         qputenv("QT_PLUGIN_PATH", pluginPath);
1075
1076         // library path list should contain the default
1077         QStringList expected =
1078             QStringList()
1079             << QLibraryInfo::location(QLibraryInfo::PluginsPath)
1080             << app.applicationDirPath();
1081 # ifdef Q_OS_WINCE
1082         expected = QSet<QString>::fromList(expected).toList();
1083 # endif
1084         QVERIFY(isPathListIncluded(app.libraryPaths(), expected));
1085
1086         qputenv("QT_PLUGIN_PATH", QByteArray());
1087     }
1088 }
1089
1090 class SendPostedEventsTester : public QObject
1091 {
1092     Q_OBJECT
1093 public:
1094     QList<int> eventSpy;
1095     bool event(QEvent *e);
1096 private slots:
1097     void doTest();
1098 };
1099
1100 bool SendPostedEventsTester::event(QEvent *e)
1101 {
1102     eventSpy.append(e->type());
1103     return QObject::event(e);
1104 }
1105
1106 void SendPostedEventsTester::doTest()
1107 {
1108     QPointer<SendPostedEventsTester> p = this;
1109     QApplication::postEvent(this, new QEvent(QEvent::User));
1110     // DeferredDelete should not be delivered until returning from this function
1111     QApplication::postEvent(this, new QDeferredDeleteEvent());
1112
1113     QEventLoop eventLoop;
1114     QMetaObject::invokeMethod(&eventLoop, "quit", Qt::QueuedConnection);
1115     eventLoop.exec();
1116     QVERIFY(p != 0);
1117
1118     QCOMPARE(eventSpy.count(), 2);
1119     QCOMPARE(eventSpy.at(0), int(QEvent::MetaCall));
1120     QCOMPARE(eventSpy.at(1), int(QEvent::User));
1121     eventSpy.clear();
1122 }
1123
1124 void tst_QApplication::sendPostedEvents()
1125 {
1126     int argc = 0;
1127     QApplication app(argc, 0, QApplication::GuiServer);
1128     SendPostedEventsTester *tester = new SendPostedEventsTester;
1129     QMetaObject::invokeMethod(tester, "doTest", Qt::QueuedConnection);
1130     QMetaObject::invokeMethod(&app, "quit", Qt::QueuedConnection);
1131     QPointer<SendPostedEventsTester> p = tester;
1132     (void) app.exec();
1133     QVERIFY(p == 0);
1134 }
1135
1136 void tst_QApplication::thread()
1137 {
1138     QThread *currentThread = QThread::currentThread();
1139     // no app, but still have a valid thread
1140     QVERIFY(currentThread != 0);
1141
1142     // the thread should be running and not finished
1143     QVERIFY(currentThread->isRunning());
1144     QVERIFY(!currentThread->isFinished());
1145
1146     // this should probably be in the tst_QObject::thread() test, but
1147     // we put it here since we want to make sure that objects created
1148     // *before* the QApplication has a thread
1149     QObject object;
1150     QObject child(&object);
1151     QVERIFY(object.thread() == currentThread);
1152     QVERIFY(child.thread() == currentThread);
1153
1154     {
1155         int argc = 0;
1156         QApplication app(argc, 0, QApplication::GuiServer);
1157
1158         // current thread still valid
1159         QVERIFY(QThread::currentThread() != 0);
1160         // thread should be the same as before
1161         QCOMPARE(QThread::currentThread(), currentThread);
1162
1163         // app's thread should be the current thread
1164         QCOMPARE(app.thread(), currentThread);
1165
1166         // the thread should still be running and not finished
1167         QVERIFY(currentThread->isRunning());
1168         QVERIFY(!currentThread->isFinished());
1169
1170         QTestEventLoop::instance().enterLoop(1);
1171     }
1172
1173     // app dead, current thread still valid
1174     QVERIFY(QThread::currentThread() != 0);
1175     QCOMPARE(QThread::currentThread(), currentThread);
1176
1177     // the thread should still be running and not finished
1178     QVERIFY(currentThread->isRunning());
1179     QVERIFY(!currentThread->isFinished());
1180
1181     // should still have a thread
1182     QVERIFY(object.thread() == currentThread);
1183     QVERIFY(child.thread() == currentThread);
1184
1185     // do the test again, making sure that the thread is the same as
1186     // before
1187     {
1188         int argc = 0;
1189         QApplication app(argc, 0, QApplication::GuiServer);
1190
1191         // current thread still valid
1192         QVERIFY(QThread::currentThread() != 0);
1193         // thread should be the same as before
1194         QCOMPARE(QThread::currentThread(), currentThread);
1195
1196         // app's thread should be the current thread
1197         QCOMPARE(app.thread(), currentThread);
1198
1199         // the thread should be running and not finished
1200         QVERIFY(currentThread->isRunning());
1201         QVERIFY(!currentThread->isFinished());
1202
1203         // should still have a thread
1204         QVERIFY(object.thread() == currentThread);
1205         QVERIFY(child.thread() == currentThread);
1206
1207         QTestEventLoop::instance().enterLoop(1);
1208     }
1209
1210     // app dead, current thread still valid
1211     QVERIFY(QThread::currentThread() != 0);
1212     QCOMPARE(QThread::currentThread(), currentThread);
1213
1214     // the thread should still be running and not finished
1215     QVERIFY(currentThread->isRunning());
1216     QVERIFY(!currentThread->isFinished());
1217
1218     // should still have a thread
1219     QVERIFY(object.thread() == currentThread);
1220     QVERIFY(child.thread() == currentThread);
1221 }
1222
1223 class DeleteLaterWidget : public QWidget
1224 {
1225     Q_OBJECT
1226 public:
1227     DeleteLaterWidget(QApplication *_app, QWidget *parent = 0)
1228         : QWidget(parent) { app = _app; child_deleted = false; }
1229
1230     bool child_deleted;
1231     QApplication *app;
1232
1233 public slots:
1234     void runTest();
1235     void checkDeleteLater();
1236     void childDeleted() { child_deleted = true; }
1237 };
1238
1239
1240 void DeleteLaterWidget::runTest()
1241 {
1242     QObject *stillAlive = qFindChild<QObject*>(this, "deleteLater");
1243
1244     QWidget *w = new QWidget(this);
1245     connect(w, SIGNAL(destroyed()), this, SLOT(childDeleted()));
1246
1247     w->deleteLater();
1248     QVERIFY(!child_deleted);
1249
1250     QDialog dlg;
1251     QTimer::singleShot(500, &dlg, SLOT(reject()));
1252     dlg.exec();
1253
1254     QVERIFY(!child_deleted);
1255     app->processEvents();
1256     QVERIFY(!child_deleted);
1257
1258     QTimer::singleShot(500, this, SLOT(checkDeleteLater()));
1259
1260     app->processEvents();
1261
1262     QVERIFY(!stillAlive); // verify at the end to make test terminate
1263 }
1264
1265 void DeleteLaterWidget::checkDeleteLater()
1266 {
1267     QVERIFY(child_deleted);
1268
1269     close();
1270 }
1271
1272 void tst_QApplication::testDeleteLater()
1273 {
1274 #ifdef Q_OS_MAC
1275     QSKIP("This test fails and then hangs on Mac OS X, see QTBUG-24318");
1276 #endif
1277     int argc = 0;
1278     QApplication app(argc, 0, QApplication::GuiServer);
1279     connect(&app, SIGNAL(lastWindowClosed()), &app, SLOT(quit()));
1280
1281     DeleteLaterWidget *wgt = new DeleteLaterWidget(&app);
1282     QTimer::singleShot(500, wgt, SLOT(runTest()));
1283
1284     QObject *object = new QObject(wgt);
1285     object->setObjectName("deleteLater");
1286     object->deleteLater();
1287
1288     QObject *stillAlive = qFindChild<QObject*>(wgt, "deleteLater");
1289     QVERIFY(stillAlive);
1290
1291     app.exec();
1292
1293     delete wgt;
1294
1295 }
1296
1297 class EventLoopNester : public QObject
1298 {
1299     Q_OBJECT
1300 public slots:
1301     void deleteLaterAndEnterLoop()
1302     {
1303         QEventLoop eventLoop;
1304         QPointer<QObject> p(this);
1305         deleteLater();
1306         /*
1307           DeferredDelete events are compressed, meaning this second
1308           deleteLater() will *not* delete the object in the nested
1309           event loop
1310         */
1311         QMetaObject::invokeMethod(this, "deleteLater", Qt::QueuedConnection);
1312         QTimer::singleShot(1000, &eventLoop, SLOT(quit()));
1313         eventLoop.exec();
1314         QVERIFY(p);
1315     }
1316     void deleteLaterAndExitLoop()
1317     {
1318         // Check that 'p' is not deleted before exec returns, since the call
1319         // to QEventLoop::quit() should stop 'eventLoop' from processing
1320         // any more events (that is, delete later) until we return to the
1321         // _current_ event loop:
1322         QEventLoop eventLoop;
1323         QPointer<QObject> p(this);
1324         QMetaObject::invokeMethod(this, "deleteLater", Qt::QueuedConnection);
1325         QMetaObject::invokeMethod(&eventLoop, "quit", Qt::QueuedConnection);
1326         eventLoop.exec();
1327         QVERIFY(p); // not dead yet
1328     }
1329
1330     void processEventsOnly()
1331     {
1332         QApplication::processEvents();
1333     }
1334     void sendPostedEventsWithDeferredDelete()
1335     {
1336         QApplication::sendPostedEvents(0, QEvent::DeferredDelete);
1337     }
1338
1339     void deleteLaterAndProcessEvents()
1340     {
1341         QEventLoop eventLoop;
1342
1343         QPointer<QObject> p = this;
1344         deleteLater();
1345
1346         // trying to delete this object in a deeper eventloop just won't work
1347         QMetaObject::invokeMethod(this,
1348                                   "processEventsOnly",
1349                                   Qt::QueuedConnection);
1350         QMetaObject::invokeMethod(&eventLoop, "quit", Qt::QueuedConnection);
1351         eventLoop.exec();
1352         QVERIFY(p);
1353         QMetaObject::invokeMethod(this,
1354                                   "sendPostedEventsWithDeferredDelete",
1355                                   Qt::QueuedConnection);
1356         QMetaObject::invokeMethod(&eventLoop, "quit", Qt::QueuedConnection);
1357         eventLoop.exec();
1358         QVERIFY(p);
1359
1360         // trying to delete it from this eventloop still doesn't work
1361         QApplication::processEvents();
1362         QVERIFY(p);
1363
1364         // however, it *will* work with this magic incantation
1365         QApplication::sendPostedEvents(0, QEvent::DeferredDelete);
1366         QVERIFY(!p);
1367     }
1368 };
1369
1370 void tst_QApplication::testDeleteLaterProcessEvents()
1371 {
1372     int argc = 0;
1373
1374     // Calling processEvents() with no event dispatcher does nothing.
1375     QObject *object = new QObject;
1376     QPointer<QObject> p(object);
1377     object->deleteLater();
1378     QApplication::processEvents();
1379     QVERIFY(p);
1380     delete object;
1381
1382     {
1383         QApplication app(argc, 0, QApplication::GuiServer);
1384         // If you call processEvents() with an event dispatcher present, but
1385         // outside any event loops, deferred deletes are not processed unless
1386         // sendPostedEvents(0, DeferredDelete) is called.
1387         object = new QObject;
1388         p = object;
1389         object->deleteLater();
1390         app.processEvents();
1391         QVERIFY(p);
1392         QApplication::sendPostedEvents(0, QEvent::DeferredDelete);
1393         QVERIFY(!p);
1394
1395         // If you call deleteLater() on an object when there is no parent
1396         // event loop, and then enter an event loop, the object will get
1397         // deleted.
1398         object = new QObject;
1399         p = object;
1400         object->deleteLater();
1401         QEventLoop loop;
1402         QTimer::singleShot(1000, &loop, SLOT(quit()));
1403         loop.exec();
1404         QVERIFY(!p);
1405     }
1406     {
1407         // When an object is in an event loop, then calls deleteLater() and enters
1408         // an event loop recursively, it should not die until the parent event
1409         // loop continues.
1410         QApplication app(argc, 0, QApplication::GuiServer);
1411         QEventLoop loop;
1412         EventLoopNester *nester = new EventLoopNester;
1413         p = nester;
1414         QTimer::singleShot(3000, &loop, SLOT(quit()));
1415         QTimer::singleShot(0, nester, SLOT(deleteLaterAndEnterLoop()));
1416
1417         loop.exec();
1418         QVERIFY(!p);
1419     }
1420
1421     {
1422         // When the event loop that calls deleteLater() is exited
1423         // immediately, the object should die when returning to the
1424         // parent event loop
1425         QApplication app(argc, 0, QApplication::GuiServer);
1426         QEventLoop loop;
1427         EventLoopNester *nester = new EventLoopNester;
1428         p = nester;
1429         QTimer::singleShot(3000, &loop, SLOT(quit()));
1430         QTimer::singleShot(0, nester, SLOT(deleteLaterAndExitLoop()));
1431
1432         loop.exec();
1433         QVERIFY(!p);
1434     }
1435
1436     {
1437         // when the event loop that calls deleteLater() also calls
1438         // processEvents() immediately afterwards, the object should
1439         // not die until the parent loop continues
1440         QApplication app(argc, 0, QApplication::GuiServer);
1441         QEventLoop loop;
1442         EventLoopNester *nester = new EventLoopNester();
1443         p = nester;
1444         QTimer::singleShot(3000, &loop, SLOT(quit()));
1445         QTimer::singleShot(0, nester, SLOT(deleteLaterAndProcessEvents()));
1446
1447         loop.exec();
1448         QVERIFY(!p);
1449     }
1450 }
1451
1452 /*
1453     Test for crash with QApplication::setDesktopSettingsAware(false).
1454 */
1455 void tst_QApplication::desktopSettingsAware()
1456 {
1457 #ifndef QT_NO_PROCESS
1458     QString path;
1459     {
1460         // We need an application object for QFINDTESTDATA to work
1461         // properly in all cases.
1462         int argc = 0;
1463         QCoreApplication app(argc, 0);
1464         path = QFINDTESTDATA("desktopsettingsaware/");
1465     }
1466     QVERIFY2(!path.isEmpty(), "Cannot locate desktopsettingsaware helper application");
1467     path += "desktopsettingsaware";
1468 #ifdef Q_OS_WINCE
1469     int argc = 0;
1470     QApplication tmpApp(argc, 0, QApplication::GuiServer);
1471 #endif
1472     QProcess testProcess;
1473     testProcess.start(path);
1474     QVERIFY2(testProcess.waitForStarted(),
1475              qPrintable(QString::fromLatin1("Cannot start '%1': %2").arg(path, testProcess.errorString())));
1476     QVERIFY(testProcess.waitForFinished(10000));
1477     QCOMPARE(int(testProcess.state()), int(QProcess::NotRunning));
1478     QVERIFY(int(testProcess.error()) != int(QProcess::Crashed));
1479 #endif
1480 }
1481
1482 void tst_QApplication::setActiveWindow()
1483 {
1484     int argc = 0;
1485     QApplication MyApp(argc, 0, QApplication::GuiServer);
1486
1487     QWidget* w = new QWidget;
1488     QVBoxLayout* layout = new QVBoxLayout(w);
1489
1490     QLineEdit* pb1 = new QLineEdit("Testbutton1", w);
1491     QLineEdit* pb2 = new QLineEdit("Test Line Edit", w);
1492
1493     layout->addWidget(pb1);
1494     layout->addWidget(pb2);
1495
1496     pb2->setFocus();
1497     pb2->setParent(0);
1498     delete pb2;
1499
1500     w->show();
1501     QApplication::setActiveWindow(w); // needs this on twm (focus follows mouse)
1502     QVERIFY(pb1->hasFocus());
1503     delete w;
1504 }
1505
1506
1507 /* This might fail on some X11 window managers? */
1508 void tst_QApplication::focusChanged()
1509 {
1510     int argc = 0;
1511     QApplication app(argc, 0, QApplication::GuiServer);
1512
1513     QSignalSpy spy(&app, SIGNAL(focusChanged(QWidget *, QWidget *)));
1514     QWidget *now = 0;
1515     QWidget *old = 0;
1516
1517     QWidget parent1;
1518     QHBoxLayout hbox1(&parent1);
1519     QLabel lb1(&parent1);
1520     QLineEdit le1(&parent1);
1521     QPushButton pb1(&parent1);
1522     hbox1.addWidget(&lb1);
1523     hbox1.addWidget(&le1);
1524     hbox1.addWidget(&pb1);
1525
1526     QCOMPARE(spy.count(), 0);
1527
1528     parent1.show();
1529     QApplication::setActiveWindow(&parent1); // needs this on twm (focus follows mouse)
1530     QCOMPARE(spy.count(), 1);
1531     QCOMPARE(spy.at(0).count(), 2);
1532     old = qvariant_cast<QWidget*>(spy.at(0).at(0));
1533     now = qvariant_cast<QWidget*>(spy.at(0).at(1));
1534     QVERIFY(now == &le1);
1535     QVERIFY(now == QApplication::focusWidget());
1536     QVERIFY(old == 0);
1537     spy.clear();
1538     QCOMPARE(spy.count(), 0);
1539
1540     pb1.setFocus();
1541     QCOMPARE(spy.count(), 1);
1542     old = qvariant_cast<QWidget*>(spy.at(0).at(0));
1543     now = qvariant_cast<QWidget*>(spy.at(0).at(1));
1544     QVERIFY(now == &pb1);
1545     QVERIFY(now == QApplication::focusWidget());
1546     QVERIFY(old == &le1);
1547     spy.clear();
1548
1549     lb1.setFocus();
1550     QCOMPARE(spy.count(), 1);
1551     old = qvariant_cast<QWidget*>(spy.at(0).at(0));
1552     now = qvariant_cast<QWidget*>(spy.at(0).at(1));
1553     QVERIFY(now == &lb1);
1554     QVERIFY(now == QApplication::focusWidget());
1555     QVERIFY(old == &pb1);
1556     spy.clear();
1557
1558     lb1.clearFocus();
1559     QCOMPARE(spy.count(), 1);
1560     old = qvariant_cast<QWidget*>(spy.at(0).at(0));
1561     now = qvariant_cast<QWidget*>(spy.at(0).at(1));
1562     QVERIFY(now == 0);
1563     QVERIFY(now == QApplication::focusWidget());
1564     QVERIFY(old == &lb1);
1565     spy.clear();
1566
1567     QWidget parent2;
1568     QHBoxLayout hbox2(&parent2);
1569     QLabel lb2(&parent2);
1570     QLineEdit le2(&parent2);
1571     QPushButton pb2(&parent2);
1572     hbox2.addWidget(&lb2);
1573     hbox2.addWidget(&le2);
1574     hbox2.addWidget(&pb2);
1575
1576     parent2.show();
1577     QApplication::setActiveWindow(&parent2); // needs this on twm (focus follows mouse)
1578     QVERIFY(spy.count() > 0); // one for deactivation, one for activation on Windows
1579     old = qvariant_cast<QWidget*>(spy.at(spy.count()-1).at(0));
1580     now = qvariant_cast<QWidget*>(spy.at(spy.count()-1).at(1));
1581     QVERIFY(now == &le2);
1582     QVERIFY(now == QApplication::focusWidget());
1583     QVERIFY(old == 0);
1584     spy.clear();
1585
1586     QTestKeyEvent tab(QTest::Press, Qt::Key_Tab, 0, 0);
1587     QTestKeyEvent backtab(QTest::Press, Qt::Key_Backtab, 0, 0);
1588     QTestMouseEvent click(QTest::MouseClick, Qt::LeftButton, 0, QPoint(5, 5), 0);
1589
1590     bool tabAllControls = true;
1591 #ifdef Q_OS_MAC
1592     // Mac has two modes, one where you tab to everything, one where you can
1593     // only tab to input controls, here's what we get. Determine which ones we
1594     // should get.
1595     QSettings appleSettings(QLatin1String("apple.com"));
1596     QVariant appleValue = appleSettings.value(QLatin1String("AppleKeyboardUIMode"), 0);
1597     tabAllControls = (appleValue.toInt() & 0x2);
1598     if (!tabAllControls) {
1599         QEXPECT_FAIL("", "QTBUG-24372 Mac tab key \"Text boxes and lists only\" vs "
1600                          "\"All controls\" setting is not respected in Qt5", Abort);
1601     }
1602 #endif
1603
1604     // make sure Qt's idea of tabbing between widgets matches what we think it should
1605     QCOMPARE(qt_tab_all_widgets, tabAllControls);
1606
1607     tab.simulate(now);
1608     if (!tabAllControls) {
1609         QVERIFY(spy.count() == 0);
1610         QVERIFY(now == QApplication::focusWidget());
1611     } else {
1612         QVERIFY(spy.count() > 0);
1613         old = qvariant_cast<QWidget*>(spy.at(0).at(0));
1614         now = qvariant_cast<QWidget*>(spy.at(0).at(1));
1615         QVERIFY(now == &pb2);
1616         QVERIFY(now == QApplication::focusWidget());
1617         QVERIFY(old == &le2);
1618         spy.clear();
1619     }
1620
1621     if (!tabAllControls) {
1622         QVERIFY(spy.count() == 0);
1623         QVERIFY(now == QApplication::focusWidget());
1624     } else {
1625         tab.simulate(now);
1626         QVERIFY(spy.count() > 0);
1627         old = qvariant_cast<QWidget*>(spy.at(0).at(0));
1628         now = qvariant_cast<QWidget*>(spy.at(0).at(1));
1629         QVERIFY(now == &le2);
1630         QVERIFY(now == QApplication::focusWidget());
1631         QVERIFY(old == &pb2);
1632         spy.clear();
1633     }
1634
1635     if (!tabAllControls) {
1636         QVERIFY(spy.count() == 0);
1637         QVERIFY(now == QApplication::focusWidget());
1638     } else {
1639         backtab.simulate(now);
1640         QVERIFY(spy.count() > 0);
1641         old = qvariant_cast<QWidget*>(spy.at(0).at(0));
1642         now = qvariant_cast<QWidget*>(spy.at(0).at(1));
1643         QVERIFY(now == &pb2);
1644         QVERIFY(now == QApplication::focusWidget());
1645         QVERIFY(old == &le2);
1646         spy.clear();
1647     }
1648
1649
1650     if (!tabAllControls) {
1651         QVERIFY(spy.count() == 0);
1652         QVERIFY(now == QApplication::focusWidget());
1653         old = &pb2;
1654     } else {
1655         backtab.simulate(now);
1656         QVERIFY(spy.count() > 0);
1657         old = qvariant_cast<QWidget*>(spy.at(0).at(0));
1658         now = qvariant_cast<QWidget*>(spy.at(0).at(1));
1659         QVERIFY(now == &le2);
1660         QVERIFY(now == QApplication::focusWidget());
1661         QVERIFY(old == &pb2);
1662         spy.clear();
1663     }
1664
1665     click.simulate(old);
1666     if (!(pb2.focusPolicy() & Qt::ClickFocus)) {
1667         QVERIFY(spy.count() == 0);
1668         QVERIFY(now == QApplication::focusWidget());
1669     } else {
1670         QVERIFY(spy.count() > 0);
1671         old = qvariant_cast<QWidget*>(spy.at(0).at(0));
1672         now = qvariant_cast<QWidget*>(spy.at(0).at(1));
1673         QVERIFY(now == &pb2);
1674         QVERIFY(now == QApplication::focusWidget());
1675         QVERIFY(old == &le2);
1676         spy.clear();
1677
1678         click.simulate(old);
1679         QVERIFY(spy.count() > 0);
1680         old = qvariant_cast<QWidget*>(spy.at(0).at(0));
1681         now = qvariant_cast<QWidget*>(spy.at(0).at(1));
1682         QVERIFY(now == &le2);
1683         QVERIFY(now == QApplication::focusWidget());
1684         QVERIFY(old == &pb2);
1685         spy.clear();
1686     }
1687
1688     parent1.activateWindow();
1689     QApplication::setActiveWindow(&parent1); // needs this on twm (focus follows mouse)
1690     QVERIFY(spy.count() == 1 || spy.count() == 2); // one for deactivation, one for activation on Windows
1691
1692     //on windows, the change of focus is made in 2 steps
1693     //(the focusChanged SIGNAL is emitted twice)
1694     if (spy.count()==1)
1695         old = qvariant_cast<QWidget*>(spy.at(spy.count()-1).at(0));
1696     else
1697         old = qvariant_cast<QWidget*>(spy.at(spy.count()-2).at(0));
1698     now = qvariant_cast<QWidget*>(spy.at(spy.count()-1).at(1));
1699     QVERIFY(now == &le1);
1700     QVERIFY(now == QApplication::focusWidget());
1701     QVERIFY(old == &le2);
1702     spy.clear();
1703 }
1704
1705 class LineEdit : public QLineEdit
1706 {
1707 public:
1708     LineEdit(QWidget *parent = 0) : QLineEdit(parent) { }
1709
1710 protected:
1711     void focusOutEvent(QFocusEvent *e) {
1712         QLineEdit::focusOutEvent(e);
1713         if (objectName() == "le1")
1714             setStyleSheet("");
1715     }
1716
1717     void focusInEvent(QFocusEvent *e) {
1718         QLineEdit::focusInEvent(e);
1719         if (objectName() == "le2")
1720             setStyleSheet("");
1721     }
1722 };
1723
1724 void tst_QApplication::focusOut()
1725 {
1726     int argc = 1;
1727     QApplication app(argc, &argv0, QApplication::GuiServer);
1728
1729     // Tests the case where the style pointer changes when on focus in/out
1730     // (the above is the case when the stylesheet changes)
1731     QWidget w;
1732     QLineEdit *le1 = new LineEdit(&w);
1733     le1->setObjectName("le1");
1734     le1->setStyleSheet("background: #fee");
1735     le1->setFocus();
1736
1737     QLineEdit *le2 = new LineEdit(&w);
1738     le2->setObjectName("le2");
1739     le2->setStyleSheet("background: #fee");
1740     le2->move(100, 100);
1741     w.show();
1742
1743     QTest::qWait(2000);
1744     le2->setFocus();
1745     QTest::qWait(2000);
1746 }
1747
1748 void tst_QApplication::execAfterExit()
1749 {
1750     int argc = 1;
1751     QApplication app(argc, &argv0, QApplication::GuiServer);
1752     QMetaObject::invokeMethod(&app, "quit", Qt::QueuedConnection);
1753     // this should be ignored, as exec() will reset the exitCode
1754     QApplication::exit(1);
1755     int exitCode = app.exec();
1756     QCOMPARE(exitCode, 0);
1757
1758     // the quitNow flag should have been reset, so we can spin an
1759     // eventloop after QApplication::exec() returns
1760     QEventLoop eventLoop;
1761     QMetaObject::invokeMethod(&eventLoop, "quit", Qt::QueuedConnection);
1762     exitCode = eventLoop.exec();
1763     QCOMPARE(exitCode, 0);
1764 }
1765
1766 void tst_QApplication::wheelScrollLines()
1767 {
1768     int argc = 1;
1769     QApplication app(argc, &argv0, QApplication::GuiServer);
1770     // If wheelScrollLines returns 0, the mose wheel will be disabled.
1771     QVERIFY(app.wheelScrollLines() > 0);
1772 }
1773
1774 void tst_QApplication::style()
1775 {
1776     int argc = 1;
1777
1778     {
1779         QApplication app(argc, &argv0, QApplication::GuiServer);
1780         QPointer<QStyle> style = app.style();
1781         app.setStyle(new QWindowsStyle);
1782         QVERIFY(style.isNull());
1783     }
1784
1785     QApplication app(argc, &argv0, QApplication::GuiServer);
1786
1787     // qApp style can never be 0
1788     QVERIFY(QApplication::style() != 0);
1789 }
1790
1791 void tst_QApplication::allWidgets()
1792 {
1793     int argc = 1;
1794     QApplication app(argc, &argv0, QApplication::GuiServer);
1795     QWidget *w = new QWidget;
1796     QVERIFY(app.allWidgets().contains(w)); // uncreate widget test
1797     QVERIFY(app.allWidgets().contains(w)); // created widget test
1798     delete w;
1799     w = 0;
1800     QVERIFY(!app.allWidgets().contains(w)); // removal test
1801 }
1802
1803 void tst_QApplication::topLevelWidgets()
1804 {
1805     int argc = 1;
1806     QApplication app(argc, &argv0, QApplication::GuiServer);
1807     QWidget *w = new QWidget;
1808     w->show();
1809 #ifndef QT_NO_CLIPBOARD
1810     QClipboard *clipboard = QApplication::clipboard();
1811     QString originalText = clipboard->text();
1812     clipboard->setText(QString("newText"));
1813 #endif
1814     app.processEvents();
1815     QVERIFY(QApplication::topLevelWidgets().contains(w));
1816     QCOMPARE(QApplication::topLevelWidgets().count(), 1);
1817     delete w;
1818     w = 0;
1819     app.processEvents();
1820     QCOMPARE(QApplication::topLevelWidgets().count(), 0);
1821 }
1822
1823
1824
1825 void tst_QApplication::setAttribute()
1826 {
1827     int argc = 1;
1828     QApplication app(argc, &argv0, QApplication::GuiServer);
1829     QVERIFY(!QApplication::testAttribute(Qt::AA_ImmediateWidgetCreation));
1830     QWidget  *w = new QWidget;
1831     QVERIFY(!w->testAttribute(Qt::WA_WState_Created));
1832     delete w;
1833
1834     QApplication::setAttribute(Qt::AA_ImmediateWidgetCreation);
1835     QVERIFY(QApplication::testAttribute(Qt::AA_ImmediateWidgetCreation));
1836     w = new QWidget;
1837     QVERIFY(w->testAttribute(Qt::WA_WState_Created));
1838     QWidget *w2 = new QWidget(w);
1839     w2->setParent(0);
1840     QVERIFY(w2->testAttribute(Qt::WA_WState_Created));
1841     delete w;
1842     delete w2;
1843
1844     QApplication::setAttribute(Qt::AA_ImmediateWidgetCreation, false);
1845     QVERIFY(!QApplication::testAttribute(Qt::AA_ImmediateWidgetCreation));
1846     w = new QWidget;
1847     QVERIFY(!w->testAttribute(Qt::WA_WState_Created));
1848     delete w;
1849 }
1850
1851 void tst_QApplication::windowsCommandLine_data()
1852 {
1853 #if defined(Q_OS_WIN)
1854     QTest::addColumn<QString>("args");
1855     QTest::addColumn<QString>("expected");
1856
1857     QTest::newRow("hello world")
1858         << QString("Hello \"World\"")
1859         << QString("Hello \"World\"");
1860     QTest::newRow("sql")
1861         << QString("SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'PNR' AND TABLE_TYPE = 'VIEW' ORDER BY TABLE_NAME")
1862         << QString("SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'PNR' AND TABLE_TYPE = 'VIEW' ORDER BY TABLE_NAME");
1863 #endif
1864 }
1865
1866 void tst_QApplication::windowsCommandLine()
1867 {
1868 #if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
1869     QFETCH(QString, args);
1870     QFETCH(QString, expected);
1871
1872     QProcess testProcess;
1873     const QString path = QStringLiteral("wincmdline/wincmdline");
1874     testProcess.start(path, QStringList(args));
1875     QVERIFY2(testProcess.waitForStarted(),
1876              qPrintable(QString::fromLatin1("Cannot start '%1': %2").arg(path, testProcess.errorString())));
1877     QVERIFY(testProcess.waitForFinished(10000));
1878     QByteArray error = testProcess.readAllStandardError();
1879     QString procError(error);
1880     QCOMPARE(procError, expected);
1881 #endif
1882 }
1883
1884 class TouchEventPropagationTestWidget : public QWidget
1885 {
1886     Q_OBJECT
1887
1888 public:
1889     bool seenTouchEvent, acceptTouchEvent, seenMouseEvent, acceptMouseEvent;
1890
1891     TouchEventPropagationTestWidget(QWidget *parent = 0)
1892         : QWidget(parent), seenTouchEvent(false), acceptTouchEvent(false), seenMouseEvent(false), acceptMouseEvent(false)
1893     { }
1894
1895     void reset()
1896     {
1897         seenTouchEvent = acceptTouchEvent = seenMouseEvent = acceptMouseEvent = false;
1898     }
1899
1900     bool event(QEvent *event)
1901     {
1902         switch (event->type()) {
1903         case QEvent::MouseButtonPress:
1904         case QEvent::MouseMove:
1905         case QEvent::MouseButtonRelease:
1906             // qDebug() << objectName() << "seenMouseEvent = true";
1907             seenMouseEvent = true;
1908             event->setAccepted(acceptMouseEvent);
1909             break;
1910         case QEvent::TouchBegin:
1911         case QEvent::TouchUpdate:
1912         case QEvent::TouchEnd:
1913             // qDebug() << objectName() << "seenTouchEvent = true";
1914             seenTouchEvent = true;
1915             event->setAccepted(acceptTouchEvent);
1916             break;
1917         default:
1918             return QWidget::event(event);
1919         }
1920         return true;
1921     }
1922 };
1923
1924 void tst_QApplication::touchEventPropagation()
1925 {
1926     int argc = 1;
1927     QApplication app(argc, &argv0, QApplication::GuiServer);
1928
1929     QList<QTouchEvent::TouchPoint> pressedTouchPoints;
1930     QTouchEvent::TouchPoint press(0);
1931     press.setState(Qt::TouchPointPressed);
1932     pressedTouchPoints << press;
1933
1934     QList<QTouchEvent::TouchPoint> releasedTouchPoints;
1935     QTouchEvent::TouchPoint release(0);
1936     release.setState(Qt::TouchPointReleased);
1937     releasedTouchPoints << release;
1938
1939     QTouchDevice *device = new QTouchDevice;
1940     device->setType(QTouchDevice::TouchScreen);
1941     QWindowSystemInterface::registerTouchDevice(device);
1942
1943     {
1944         // touch event behavior on a window
1945         TouchEventPropagationTestWidget window;
1946         window.setObjectName("1. window");
1947         window.show(); // Must have an explicitly specified QWindow for handleTouchEvent,
1948                        // passing 0 would result in using topLevelAt() which is not ok in this case
1949                        // as the screen position in the point is bogus.
1950         QVERIFY(QTest::qWaitForWindowExposed(&window));
1951         // QPA always takes screen positions and since we map the TouchPoint back to QPA's structure first,
1952         // we must ensure there is a screen position in the TouchPoint that maps to a local 0, 0.
1953         pressedTouchPoints[0].setScreenPos(window.mapToGlobal(QPoint(0, 0)));
1954         releasedTouchPoints[0].setScreenPos(window.mapToGlobal(QPoint(0, 0)));
1955
1956         QWindowSystemInterface::handleTouchEvent(window.windowHandle(),
1957                                                  0,
1958                                                  device,
1959                                                  touchPointList(pressedTouchPoints));
1960         QWindowSystemInterface::handleTouchEvent(window.windowHandle(),
1961                                                  0,
1962                                                  device,
1963                                                  touchPointList(releasedTouchPoints));
1964         QCoreApplication::processEvents();
1965         QVERIFY(!window.seenTouchEvent);
1966         QVERIFY(window.seenMouseEvent); // Since QApplication transforms ignored touch events in mouse events
1967
1968         window.reset();
1969         window.setAttribute(Qt::WA_AcceptTouchEvents);
1970         QWindowSystemInterface::handleTouchEvent(window.windowHandle(),
1971                                                  0,
1972                                                  device,
1973                                                  touchPointList(pressedTouchPoints));
1974         QWindowSystemInterface::handleTouchEvent(window.windowHandle(),
1975                                                  0,
1976                                                  device,
1977                                                  touchPointList(releasedTouchPoints));
1978         QCoreApplication::processEvents();
1979         QVERIFY(window.seenTouchEvent);
1980         QVERIFY(window.seenMouseEvent);
1981
1982         window.reset();
1983         window.acceptTouchEvent = true;
1984         QWindowSystemInterface::handleTouchEvent(window.windowHandle(),
1985                                                  0,
1986                                                  device,
1987                                                  touchPointList(pressedTouchPoints));
1988         QWindowSystemInterface::handleTouchEvent(window.windowHandle(),
1989                                                  0,
1990                                                  device,
1991                                                  touchPointList(releasedTouchPoints));
1992         QCoreApplication::processEvents();
1993         QVERIFY(window.seenTouchEvent);
1994         QVERIFY(!window.seenMouseEvent);
1995     }
1996
1997     {
1998         // touch event behavior on a window with a child widget
1999         TouchEventPropagationTestWidget window;
2000         window.setObjectName("2. window");
2001         TouchEventPropagationTestWidget widget(&window);
2002         widget.setObjectName("2. widget");
2003         window.show();
2004         QVERIFY(QTest::qWaitForWindowExposed(&window));
2005         pressedTouchPoints[0].setScreenPos(window.mapToGlobal(QPoint(0, 0)));
2006         releasedTouchPoints[0].setScreenPos(window.mapToGlobal(QPoint(0, 0)));
2007
2008         QWindowSystemInterface::handleTouchEvent(window.windowHandle(),
2009                                                  0,
2010                                                  device,
2011                                                  touchPointList(pressedTouchPoints));
2012         QWindowSystemInterface::handleTouchEvent(window.windowHandle(),
2013                                                  0,
2014                                                  device,
2015                                                  touchPointList(releasedTouchPoints));
2016         QCoreApplication::processEvents();
2017         QVERIFY(!widget.seenTouchEvent);
2018         QVERIFY(widget.seenMouseEvent);
2019         QVERIFY(!window.seenTouchEvent);
2020         QVERIFY(window.seenMouseEvent);
2021
2022         window.reset();
2023         widget.reset();
2024         widget.setAttribute(Qt::WA_AcceptTouchEvents);
2025         QWindowSystemInterface::handleTouchEvent(window.windowHandle(),
2026                                                  0,
2027                                                  device,
2028                                                  touchPointList(pressedTouchPoints));
2029         QWindowSystemInterface::handleTouchEvent(window.windowHandle(),
2030                                                  0,
2031                                                  device,
2032                                                  touchPointList(releasedTouchPoints));
2033         QCoreApplication::processEvents();
2034         QVERIFY(widget.seenTouchEvent);
2035         QVERIFY(widget.seenMouseEvent);
2036         QVERIFY(!window.seenTouchEvent);
2037         QVERIFY(window.seenMouseEvent);
2038
2039         window.reset();
2040         widget.reset();
2041         widget.acceptMouseEvent = true;
2042         QWindowSystemInterface::handleTouchEvent(window.windowHandle(),
2043                                                  0,
2044                                                  device,
2045                                                  touchPointList(pressedTouchPoints));
2046         QWindowSystemInterface::handleTouchEvent(window.windowHandle(),
2047                                                  0,
2048                                                  device,
2049                                                  touchPointList(releasedTouchPoints));
2050         QCoreApplication::processEvents();
2051         QVERIFY(widget.seenTouchEvent);
2052         QVERIFY(widget.seenMouseEvent);
2053         QVERIFY(!window.seenTouchEvent);
2054         QVERIFY(!window.seenMouseEvent);
2055
2056         window.reset();
2057         widget.reset();
2058         widget.acceptTouchEvent = true;
2059         QWindowSystemInterface::handleTouchEvent(window.windowHandle(),
2060                                                  0,
2061                                                  device,
2062                                                  touchPointList(pressedTouchPoints));
2063         QWindowSystemInterface::handleTouchEvent(window.windowHandle(),
2064                                                  0,
2065                                                  device,
2066                                                  touchPointList(releasedTouchPoints));
2067         QCoreApplication::processEvents();
2068         QVERIFY(widget.seenTouchEvent);
2069         QVERIFY(!widget.seenMouseEvent);
2070         QVERIFY(!window.seenTouchEvent);
2071         QVERIFY(!window.seenMouseEvent);
2072
2073         window.reset();
2074         widget.reset();
2075         widget.setAttribute(Qt::WA_AcceptTouchEvents, false);
2076         window.setAttribute(Qt::WA_AcceptTouchEvents);
2077         QWindowSystemInterface::handleTouchEvent(window.windowHandle(),
2078                                                  0,
2079                                                  device,
2080                                                  touchPointList(pressedTouchPoints));
2081         QWindowSystemInterface::handleTouchEvent(window.windowHandle(),
2082                                                  0,
2083                                                  device,
2084                                                  touchPointList(releasedTouchPoints));
2085         QCoreApplication::processEvents();
2086         QVERIFY(!widget.seenTouchEvent);
2087         QVERIFY(widget.seenMouseEvent);
2088         QVERIFY(window.seenTouchEvent);
2089         QVERIFY(window.seenMouseEvent);
2090
2091         window.reset();
2092         widget.reset();
2093         window.acceptTouchEvent = true;
2094         QWindowSystemInterface::handleTouchEvent(window.windowHandle(),
2095                                                  0,
2096                                                  device,
2097                                                  touchPointList(pressedTouchPoints));
2098         QWindowSystemInterface::handleTouchEvent(window.windowHandle(),
2099                                                  0,
2100                                                  device,
2101                                                  touchPointList(releasedTouchPoints));
2102         QCoreApplication::processEvents();
2103         QVERIFY(!widget.seenTouchEvent);
2104         QVERIFY(widget.seenMouseEvent);
2105         QVERIFY(window.seenTouchEvent);
2106         QVERIFY(!window.seenMouseEvent);
2107
2108         window.reset();
2109         widget.reset();
2110         widget.acceptMouseEvent = true; // it matters, touch events are propagated in parallel to synthesized mouse events
2111         window.acceptTouchEvent = true;
2112         QWindowSystemInterface::handleTouchEvent(window.windowHandle(),
2113                                                  0,
2114                                                  device,
2115                                                  touchPointList(pressedTouchPoints));
2116         QWindowSystemInterface::handleTouchEvent(window.windowHandle(),
2117                                                  0,
2118                                                  device,
2119                                                  touchPointList(releasedTouchPoints));
2120         QCoreApplication::processEvents();
2121         QVERIFY(!widget.seenTouchEvent);
2122         QVERIFY(widget.seenMouseEvent);
2123         QVERIFY(!window.seenTouchEvent);
2124         QVERIFY(!window.seenMouseEvent);
2125     }
2126 }
2127
2128 void tst_QApplication::qtbug_12673()
2129 {
2130     QString path;
2131     {
2132         // We need an application object for QFINDTESTDATA to work
2133         // properly in all cases.
2134         int argc = 0;
2135         QCoreApplication app(argc, 0);
2136         path = QFINDTESTDATA("modal/");
2137     }
2138     QVERIFY2(!path.isEmpty(), "Cannot locate modal helper application");
2139     path += "modal";
2140
2141     QProcess testProcess;
2142     QStringList arguments;
2143     testProcess.start(path, arguments);
2144     QVERIFY2(testProcess.waitForStarted(),
2145              qPrintable(QString::fromLatin1("Cannot start '%1': %2").arg(path, testProcess.errorString())));
2146     QVERIFY(testProcess.waitForFinished(20000));
2147     QCOMPARE(testProcess.exitStatus(), QProcess::NormalExit);
2148 }
2149
2150 class NoQuitOnHideWidget : public QWidget
2151 {
2152     Q_OBJECT
2153 public:
2154     explicit NoQuitOnHideWidget(QWidget *parent = 0)
2155       : QWidget(parent)
2156     {
2157         QTimer::singleShot(0, this, SLOT(hide()));
2158         QTimer::singleShot(500, this, SLOT(exitApp()));
2159     }
2160
2161 private slots:
2162     void exitApp() {
2163       qApp->exit(1);
2164     }
2165 };
2166
2167 void tst_QApplication::noQuitOnHide()
2168 {
2169     int argc = 0;
2170     QApplication app(argc, 0);
2171     QWidget *window1 = new NoQuitOnHideWidget;
2172     window1->show();
2173     QCOMPARE(app.exec(), 1);
2174 }
2175
2176 class ShowCloseShowWidget : public QWidget
2177 {
2178     Q_OBJECT
2179 public:
2180     ShowCloseShowWidget(bool showAgain, QWidget *parent = 0)
2181       : QWidget(parent), showAgain(showAgain)
2182     {
2183         QTimer::singleShot(0, this, SLOT(doClose()));
2184         QTimer::singleShot(500, this, SLOT(exitApp()));
2185     }
2186
2187 private slots:
2188     void doClose() {
2189         close();
2190         if (showAgain)
2191             show();
2192     }
2193
2194     void exitApp() {
2195       qApp->exit(1);
2196     }
2197
2198 private:
2199     bool showAgain;
2200 };
2201
2202 void tst_QApplication::abortQuitOnShow()
2203 {
2204     int argc = 0;
2205     QApplication app(argc, 0);
2206     QWidget *window1 = new ShowCloseShowWidget(false);
2207     window1->show();
2208     QCOMPARE(app.exec(), 0);
2209
2210     QWidget *window2 = new ShowCloseShowWidget(true);
2211     window2->show();
2212     QCOMPARE(app.exec(), 1);
2213 }
2214
2215 /*
2216     This test is meant to ensure that certain objects (public & commonly used)
2217     can safely be used in a Q_GLOBAL_STATIC such that their destructors are
2218     executed *after* the destruction of QApplication.
2219  */
2220 Q_GLOBAL_STATIC(QLocale, tst_qapp_locale);
2221 Q_GLOBAL_STATIC(QProcess, tst_qapp_process);
2222 Q_GLOBAL_STATIC(QFileSystemWatcher, tst_qapp_fileSystemWatcher);
2223 #ifndef QT_NO_SHAREDMEMORY
2224 Q_GLOBAL_STATIC(QSharedMemory, tst_qapp_sharedMemory);
2225 #endif
2226 Q_GLOBAL_STATIC(QElapsedTimer, tst_qapp_elapsedTimer);
2227 Q_GLOBAL_STATIC(QMutex, tst_qapp_mutex);
2228 Q_GLOBAL_STATIC(QWidget, tst_qapp_widget);
2229 Q_GLOBAL_STATIC(QPixmap, tst_qapp_pixmap);
2230 Q_GLOBAL_STATIC(QFont, tst_qapp_font);
2231 Q_GLOBAL_STATIC(QRegion, tst_qapp_region);
2232 Q_GLOBAL_STATIC(QFontDatabase, tst_qapp_fontDatabase);
2233 Q_GLOBAL_STATIC(QCursor, tst_qapp_cursor);
2234
2235 void tst_QApplication::globalStaticObjectDestruction()
2236 {
2237     int argc = 1;
2238     QApplication app(argc, &argv0, QApplication::GuiServer);
2239     QVERIFY(tst_qapp_locale());
2240     QVERIFY(tst_qapp_process());
2241     QVERIFY(tst_qapp_fileSystemWatcher());
2242 #ifndef QT_NO_SHAREDMEMORY
2243     QVERIFY(tst_qapp_sharedMemory());
2244 #endif
2245     QVERIFY(tst_qapp_elapsedTimer());
2246     QVERIFY(tst_qapp_mutex());
2247     QVERIFY(tst_qapp_widget());
2248     QVERIFY(tst_qapp_pixmap());
2249     QVERIFY(tst_qapp_font());
2250     QVERIFY(tst_qapp_region());
2251     QVERIFY(tst_qapp_fontDatabase());
2252     QVERIFY(tst_qapp_cursor());
2253 }
2254
2255 //QTEST_APPLESS_MAIN(tst_QApplication)
2256 int main(int argc, char *argv[])
2257 {
2258     tst_QApplication tc;
2259     argv0 = argv[0];
2260     return QTest::qExec(&tc, argc, argv);
2261 }
2262
2263 #include "tst_qapplication.moc"