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