1
/****************************************************************************
3
** Copyright (C) 2016 The Qt Company Ltd.
4
** Contact: https://www.qt.io/licensing/
6
** This file is part of the test suite of the Qt Toolkit.
8
** $QT_BEGIN_LICENSE:GPL-EXCEPT$
9
** Commercial License Usage
10
** Licensees holding valid commercial Qt licenses may use this file in
11
** accordance with the commercial license agreement provided with the
12
** Software or, alternatively, in accordance with the terms contained in
13
** a written agreement between you and The Qt Company. For licensing terms
14
** and conditions see https://www.qt.io/terms-conditions. For further
15
** information use the contact form at https://www.qt.io/contact-us.
17
** GNU General Public License Usage
18
** Alternatively, this file may be used under the terms of the GNU
19
** General Public License version 3 as published by the Free Software
20
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
21
** included in the packaging of this file. Please review the following
22
** information to ensure the GNU General Public License requirements will
23
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
27
****************************************************************************/
30
#include <QtTest/QtTest>
31
#include <QtGui/QGuiApplication>
32
#include <QtGui/QWindow>
33
#include <QtGui/QScreen>
34
#include <QtGui/QCursor>
35
#include <QtGui/QFont>
36
#include <QtGui/QPalette>
37
#include <QtGui/QStyleHints>
38
#include <qpa/qwindowsysteminterface.h>
39
#include <qgenericplugin.h>
42
#include <QOpenGLContext>
45
#include <QtGui/private/qopenglcontext_p.h>
49
#include "tst_qcoreapplication.h"
51
enum { spacing = 50, windowSize = 200 };
53
class tst_QGuiApplication: public tst_QCoreApplication
61
void desktopFileName();
62
void firstWindowTitle();
66
void topLevelWindows();
67
void abortQuitOnShow();
68
void changeFocusWindow();
69
void keyboardModifiers();
72
void quitOnLastWindowClosed();
73
void genericPluginsAndWindowSystemEvents();
74
void layoutDirection();
75
void globalShareContext();
76
void testSetPaletteAttribute();
78
void staticFunctions();
80
void settableStyleHints_data();
81
void settableStyleHints(); // Needs to run last as it changes style hints.
84
void tst_QGuiApplication::initTestCase()
86
#ifdef QT_QPA_DEFAULT_PLATFORM_NAME
87
if ((QString::compare(QStringLiteral(QT_QPA_DEFAULT_PLATFORM_NAME),
88
QStringLiteral("eglfs"), Qt::CaseInsensitive) == 0) ||
89
(QString::compare(QString::fromLatin1(qgetenv("QT_QPA_PLATFORM")),
90
QStringLiteral("eglfs"), Qt::CaseInsensitive) == 0)) {
91
// Set env variables to disable input and cursor because eglfs is single fullscreen window
92
// and trying to initialize input and cursor will crash test.
93
qputenv("QT_QPA_EGLFS_DISABLE_INPUT", "1");
94
qputenv("QT_QPA_EGLFS_HIDECURSOR", "1");
99
void tst_QGuiApplication::cleanup()
101
QVERIFY(QGuiApplication::allWindows().isEmpty());
104
void tst_QGuiApplication::displayName()
107
char *argv[] = { const_cast<char*>("tst_qguiapplication") };
108
QGuiApplication app(argc, argv);
109
QCOMPARE(::qAppName(), QString::fromLatin1("tst_qguiapplication"));
110
QCOMPARE(QGuiApplication::applicationName(), QString::fromLatin1("tst_qguiapplication"));
111
QCOMPARE(QGuiApplication::applicationDisplayName(), QString::fromLatin1("tst_qguiapplication"));
112
QGuiApplication::setApplicationDisplayName("The GUI Application");
113
QCOMPARE(QGuiApplication::applicationDisplayName(), QString::fromLatin1("The GUI Application"));
116
void tst_QGuiApplication::desktopFileName()
119
char *argv[] = { const_cast<char*>("tst_qguiapplication") };
120
QGuiApplication app(argc, argv);
122
QCOMPARE(QGuiApplication::desktopFileName(), QString());
124
QGuiApplication::setDesktopFileName("io.qt.QGuiApplication.desktop");
125
QCOMPARE(QGuiApplication::desktopFileName(), QString::fromLatin1("io.qt.QGuiApplication.desktop"));
127
QGuiApplication::setDesktopFileName(QString());
128
QCOMPARE(QGuiApplication::desktopFileName(), QString());
131
void tst_QGuiApplication::firstWindowTitle()
134
char *argv[] = { const_cast<char*>("tst_qguiapplication"), const_cast<char*>("-qwindowtitle"), const_cast<char*>("User Title") };
135
QGuiApplication app(argc, argv);
137
window.setTitle("Application Title");
139
QCOMPARE(window.title(), QString("User Title"));
142
void tst_QGuiApplication::windowIcon()
145
char *argv[] = { const_cast<char*>("tst_qguiapplication"), const_cast<char*>("-qwindowicon"), const_cast<char*>(":/icons/usericon.png") };
146
QGuiApplication app(argc, argv);
147
QIcon appIcon(":/icons/appicon.png");
148
app.setWindowIcon(appIcon);
153
QIcon userIcon(":/icons/usericon.png");
154
// Comparing icons is hard. cacheKey() differs because the icon was independently loaded.
155
// So we use availableSizes, after making sure that the app and user icons do have different sizes.
156
QVERIFY(userIcon.availableSizes() != appIcon.availableSizes());
157
QCOMPARE(window.icon().availableSizes(), userIcon.availableSizes());
160
class DummyWindow : public QWindow
163
DummyWindow() : m_focusObject(0) {}
165
virtual QObject *focusObject() const
167
return m_focusObject;
170
void setFocusObject(QObject *object)
172
m_focusObject = object;
173
emit focusObjectChanged(object);
176
QObject *m_focusObject;
180
void tst_QGuiApplication::focusObject()
183
QGuiApplication app(argc, 0);
185
if (!QGuiApplication::platformName().compare(QLatin1String("wayland"), Qt::CaseInsensitive))
186
QSKIP("Wayland: This fails. Figure out why.");
188
QObject obj1, obj2, obj3;
189
const QRect screenGeometry = QGuiApplication::primaryScreen()->availableVirtualGeometry();
192
#if defined(Q_OS_QNX)
193
window1.setSurfaceType(QSurface::OpenGLSurface);
195
window1.resize(windowSize, windowSize);
196
window1.setTitle(QStringLiteral("focusObject:window1"));
197
window1.setFramePosition(QPoint(screenGeometry.left() + spacing, screenGeometry.top() + spacing));
199
window2.resize(windowSize, windowSize);
200
window2.setFramePosition(QPoint(screenGeometry.left() + 2 * spacing + windowSize, screenGeometry.top() + spacing));
201
window2.setTitle(QStringLiteral("focusObject:window2"));
205
#if defined(Q_OS_QNX) // We either need to create a eglSurface or a create a backing store
206
// and then post the window in order for screen to show the window
207
QOpenGLContext context;
209
context.makeCurrent(&window1);
210
QTest::qWaitForWindowExposed(&window1); // Buffer swap only succeeds with exposed window
211
context.swapBuffers(&window1);
214
QSignalSpy spy(&app, SIGNAL(focusObjectChanged(QObject*)));
217
// verify active window focus propagates to qguiapplication
218
window1.requestActivate();
219
QVERIFY(QTest::qWaitForWindowActive(&window1));
220
QCOMPARE(app.focusWindow(), &window1);
222
window1.setFocusObject(&obj1);
223
QCOMPARE(app.focusObject(), &obj1);
224
QCOMPARE(spy.count(), 1);
227
window1.setFocusObject(&obj2);
228
QCOMPARE(app.focusObject(), &obj2);
229
QCOMPARE(spy.count(), 1);
232
window2.setFocusObject(&obj3);
233
QCOMPARE(app.focusObject(), &obj2); // not yet changed
235
QVERIFY(QTest::qWaitForWindowExposed(&window2));
236
QTRY_COMPARE(app.focusWindow(), &window2);
237
QCOMPARE(app.focusObject(), &obj3);
238
QCOMPARE(spy.count(), 1);
240
// focus change on unfocused window does not show
242
window1.setFocusObject(&obj1);
243
QCOMPARE(spy.count(), 0);
244
QCOMPARE(app.focusObject(), &obj3);
247
void tst_QGuiApplication::allWindows()
250
QGuiApplication app(argc, 0);
251
QWindow *window1 = new QWindow;
252
QWindow *window2 = new QWindow(window1);
253
QVERIFY(app.allWindows().contains(window1));
254
QVERIFY(app.allWindows().contains(window2));
255
QCOMPARE(app.allWindows().count(), 2);
259
QVERIFY(!app.allWindows().contains(window2));
260
QVERIFY(!app.allWindows().contains(window1));
261
QCOMPARE(app.allWindows().count(), 0);
264
void tst_QGuiApplication::topLevelWindows()
267
QGuiApplication app(argc, 0);
268
QWindow *window1 = new QWindow;
269
QWindow *window2 = new QWindow(window1);
270
QVERIFY(app.topLevelWindows().contains(window1));
271
QVERIFY(!app.topLevelWindows().contains(window2));
272
QCOMPARE(app.topLevelWindows().count(), 1);
276
QVERIFY(!app.topLevelWindows().contains(window2));
277
QVERIFY(!app.topLevelWindows().contains(window1));
278
QCOMPARE(app.topLevelWindows().count(), 0);
281
class ShowCloseShowWindow : public QWindow
285
ShowCloseShowWindow(bool showAgain, QWindow *parent = 0)
286
: QWindow(parent), showAgain(showAgain)
288
QTimer::singleShot(0, this, SLOT(doClose()));
289
QTimer::singleShot(500, this, SLOT(exitApp()));
307
void tst_QGuiApplication::abortQuitOnShow()
310
QGuiApplication app(argc, 0);
311
const QRect screenGeometry = QGuiApplication::primaryScreen()->availableVirtualGeometry();
313
QScopedPointer<QWindow> window1(new ShowCloseShowWindow(false));
314
window1->resize(windowSize, windowSize);
315
window1->setFramePosition(QPoint(screenGeometry.left() + spacing, screenGeometry.top() + spacing));
316
window1->setTitle(QStringLiteral("abortQuitOnShow:window1"));
318
QCOMPARE(app.exec(), 0);
320
QScopedPointer<QWindow> window2(new ShowCloseShowWindow(true));
321
window2->setTitle(QStringLiteral("abortQuitOnShow:window2"));
322
window2->resize(windowSize, windowSize);
323
window2->setFramePosition(QPoint(screenGeometry.left() + 2 * spacing + windowSize, screenGeometry.top() + spacing));
325
QCOMPARE(app.exec(), 1);
329
class FocusChangeWindow: public QWindow
332
virtual bool event(QEvent *ev)
334
if (ev->type() == QEvent::FocusAboutToChange)
335
windowDuringFocusAboutToChange = qGuiApp->focusWindow();
336
return QWindow::event(ev);
339
virtual void focusOutEvent(QFocusEvent *)
341
windowDuringFocusOut = qGuiApp->focusWindow();
345
FocusChangeWindow() : QWindow(), windowDuringFocusAboutToChange(0), windowDuringFocusOut(0) {}
347
QWindow *windowDuringFocusAboutToChange;
348
QWindow *windowDuringFocusOut;
351
void tst_QGuiApplication::changeFocusWindow()
354
QGuiApplication app(argc, 0);
356
if (!QGuiApplication::platformName().compare(QLatin1String("wayland"), Qt::CaseInsensitive))
357
QSKIP("Wayland: This fails. Figure out why.");
359
const QRect screenGeometry = QGuiApplication::primaryScreen()->availableVirtualGeometry();
361
// focus is changed between FocusAboutToChange and FocusChanged
362
FocusChangeWindow window1;
363
#if defined(Q_OS_QNX)
364
window1.setSurfaceType(QSurface::OpenGLSurface);
366
window1.resize(windowSize, windowSize);
367
window1.setFramePosition(QPoint(screenGeometry.left() + spacing, screenGeometry.top() + spacing));
368
window1.setTitle(QStringLiteral("changeFocusWindow:window1"));
370
#if defined(Q_OS_QNX) // We either need to create a eglSurface or a create a backing store
371
// and then post the window in order for screen to show the window
372
QOpenGLContext context;
374
context.makeCurrent(&window1);
375
QTest::qWaitForWindowExposed(&window1); // Buffer swap only succeeds with exposed window
376
context.swapBuffers(&window1);
378
FocusChangeWindow window2;
379
#if defined(Q_OS_QNX)
380
window2.setSurfaceType(QSurface::OpenGLSurface);
382
window2.resize(windowSize, windowSize);
383
window2.setFramePosition(QPoint(screenGeometry.left() + 2 * spacing + windowSize, screenGeometry.top() + spacing));
384
window2.setTitle(QStringLiteral("changeFocusWindow:window2"));
386
#if defined(Q_OS_QNX) // We either need to create a eglSurface or a create a backing store
387
// and then post the window in order for screen to show the window
388
context.makeCurrent(&window2);
389
QTest::qWaitForWindowExposed(&window2); // Buffer swap only succeeds with exposed window
390
context.swapBuffers(&window2);
392
QVERIFY(QTest::qWaitForWindowExposed(&window1));
393
QVERIFY(QTest::qWaitForWindowExposed(&window2));
394
window1.requestActivate();
395
QTRY_COMPARE(app.focusWindow(), &window1);
397
window2.requestActivate();
398
QTRY_COMPARE(app.focusWindow(), &window2);
399
QCOMPARE(window1.windowDuringFocusAboutToChange, &window1);
400
QCOMPARE(window1.windowDuringFocusOut, &window2);
403
void tst_QGuiApplication::keyboardModifiers()
406
QGuiApplication app(argc, 0);
407
const QRect screenGeometry = QGuiApplication::primaryScreen()->availableVirtualGeometry();
409
QScopedPointer<QWindow> window(new QWindow);
410
window->resize(windowSize, windowSize);
411
window->setFramePosition(QPoint(screenGeometry.left() + spacing, screenGeometry.top() + spacing));
412
window->setTitle(QStringLiteral("keyboardModifiers"));
415
QVERIFY(QTest::qWaitForWindowExposed(window.data()));
416
QCOMPARE(QGuiApplication::keyboardModifiers(), Qt::NoModifier);
419
QPoint center = window->geometry().center();
420
QTest::mouseEvent(QTest::MousePress, window.data(), Qt::LeftButton, Qt::NoModifier, center);
421
QCOMPARE(QGuiApplication::keyboardModifiers(), Qt::NoModifier);
422
QTest::mouseEvent(QTest::MouseRelease, window.data(), Qt::LeftButton, Qt::NoModifier, center);
423
QCOMPARE(QGuiApplication::keyboardModifiers(), Qt::NoModifier);
424
QTest::mouseEvent(QTest::MousePress, window.data(), Qt::RightButton, Qt::ControlModifier, center);
425
QCOMPARE(QGuiApplication::keyboardModifiers(), Qt::ControlModifier);
426
QTest::mouseEvent(QTest::MouseRelease, window.data(), Qt::RightButton, Qt::ControlModifier, center);
427
QCOMPARE(QGuiApplication::keyboardModifiers(), Qt::ControlModifier);
430
QTest::keyEvent(QTest::Shortcut, window.data(), Qt::Key_5, Qt::MetaModifier);
431
QCOMPARE(QGuiApplication::keyboardModifiers(), Qt::MetaModifier);
432
QTest::keyEvent(QTest::Shortcut, window.data(), Qt::Key_Period, Qt::NoModifier);
433
QCOMPARE(QGuiApplication::keyboardModifiers(), Qt::NoModifier);
434
QTest::keyEvent(QTest::Shortcut, window.data(), Qt::Key_0, Qt::ControlModifier);
435
QCOMPARE(QGuiApplication::keyboardModifiers(), Qt::ControlModifier);
438
QTest::keyEvent(QTest::Press, window.data(), Qt::Key_C);
439
QCOMPARE(QGuiApplication::keyboardModifiers(), Qt::NoModifier);
440
QTest::keyEvent(QTest::Release, window.data(), Qt::Key_C);
441
QCOMPARE(QGuiApplication::keyboardModifiers(), Qt::NoModifier);
443
QTest::keyEvent(QTest::Press, window.data(), Qt::Key_U, Qt::ControlModifier);
444
QCOMPARE(QGuiApplication::keyboardModifiers(), Qt::ControlModifier);
445
QTest::keyEvent(QTest::Release, window.data(), Qt::Key_U, Qt::ControlModifier);
446
QCOMPARE(QGuiApplication::keyboardModifiers(), Qt::ControlModifier);
448
QTest::keyEvent(QTest::Press, window.data(), Qt::Key_T);
449
QCOMPARE(QGuiApplication::keyboardModifiers(), Qt::NoModifier);
450
QTest::keyEvent(QTest::Release, window.data(), Qt::Key_T);
451
QCOMPARE(QGuiApplication::keyboardModifiers(), Qt::NoModifier);
453
QTest::keyEvent(QTest::Press, window.data(), Qt::Key_E, Qt::ControlModifier);
454
QCOMPARE(QGuiApplication::keyboardModifiers(), Qt::ControlModifier);
455
QTest::keyEvent(QTest::Release, window.data(), Qt::Key_E, Qt::ControlModifier);
456
QCOMPARE(QGuiApplication::keyboardModifiers(), Qt::ControlModifier);
459
QPoint global = window->mapToGlobal(center);
461
QWindowSystemInterface::handleWheelEvent(window.data(), center, global, delta, delta, Qt::NoModifier);
462
QWindowSystemInterface::sendWindowSystemEvents(QEventLoop::AllEvents);
463
QCOMPARE(QGuiApplication::keyboardModifiers(), Qt::NoModifier);
464
QWindowSystemInterface::handleWheelEvent(window.data(), center, global, delta, delta, Qt::AltModifier);
465
QWindowSystemInterface::sendWindowSystemEvents(QEventLoop::AllEvents);
466
QCOMPARE(QGuiApplication::keyboardModifiers(), Qt::AltModifier);
467
QWindowSystemInterface::handleWheelEvent(window.data(), center, global, delta, delta, Qt::ControlModifier);
468
QWindowSystemInterface::sendWindowSystemEvents(QEventLoop::AllEvents);
469
QCOMPARE(QGuiApplication::keyboardModifiers(), Qt::ControlModifier);
472
QList<const QTouchDevice *> touchDevices = QTouchDevice::devices();
473
if (!touchDevices.isEmpty()) {
474
QTouchDevice *touchDevice = const_cast<QTouchDevice *>(touchDevices.first());
475
QTest::touchEvent(window.data(), touchDevice).press(1, center).release(1, center);
476
QCOMPARE(QGuiApplication::keyboardModifiers(), Qt::NoModifier);
482
void tst_QGuiApplication::palette()
485
char *argv[] = { const_cast<char*>("tst_qguiapplication") };
486
QGuiApplication app(argc, argv);
487
QSignalSpy signalSpy(&app, SIGNAL(paletteChanged(QPalette)));
489
QPalette oldPalette = QGuiApplication::palette();
490
QPalette newPalette = QPalette(Qt::red);
492
QGuiApplication::setPalette(newPalette);
493
QCOMPARE(QGuiApplication::palette(), newPalette);
494
QCOMPARE(signalSpy.count(), 1);
495
QCOMPARE(signalSpy.at(0).at(0), QVariant(newPalette));
497
QGuiApplication::setPalette(oldPalette);
498
QCOMPARE(QGuiApplication::palette(), oldPalette);
499
QCOMPARE(signalSpy.count(), 2);
500
QCOMPARE(signalSpy.at(1).at(0), QVariant(oldPalette));
502
QGuiApplication::setPalette(oldPalette);
503
QCOMPARE(QGuiApplication::palette(), oldPalette);
504
QCOMPARE(signalSpy.count(), 2);
507
class BlockableWindow : public QWindow
515
inline explicit BlockableWindow(QWindow *parent = 0)
516
: QWindow(parent), blocked(false), leaves(0), enters(0) {}
518
bool event(QEvent *e)
521
case QEvent::WindowBlocked:
524
case QEvent::WindowUnblocked:
536
return QWindow::event(e);
546
void tst_QGuiApplication::modalWindow()
549
QGuiApplication app(argc, 0);
550
const QRect screenGeometry = QGuiApplication::primaryScreen()->availableVirtualGeometry();
552
int x = screenGeometry.left() + spacing;
553
int y = screenGeometry.top() + spacing;
555
QScopedPointer<BlockableWindow> window1(new BlockableWindow);
556
window1->setTitle(QStringLiteral("window1"));
557
window1->resize(windowSize, windowSize);
558
window1->setFramePosition(QPoint(x, y));
559
BlockableWindow *childWindow1 = new BlockableWindow(window1.data());
560
childWindow1->resize(windowSize / 2, windowSize / 2);
561
x += spacing + windowSize;
563
QScopedPointer<BlockableWindow> window2(new BlockableWindow);
564
window2->setTitle(QStringLiteral("window2"));
565
window2->setFlags(window2->flags() & Qt::Tool); // QTBUG-32433, don't be fooled by unusual window flags.
566
window2->resize(windowSize, windowSize);
567
window2->setFramePosition(QPoint(x, y));
568
x += spacing + windowSize;
570
QScopedPointer<BlockableWindow> windowModalWindow1(new BlockableWindow);
571
windowModalWindow1->setTitle(QStringLiteral("windowModalWindow1"));
572
windowModalWindow1->setTransientParent(window1.data());
573
windowModalWindow1->setModality(Qt::WindowModal);
574
windowModalWindow1->resize(windowSize, windowSize);
575
windowModalWindow1->setFramePosition(QPoint(x, y));
576
x += spacing + windowSize;
578
QScopedPointer<BlockableWindow> windowModalWindow2(new BlockableWindow);
579
windowModalWindow2->setTitle(QStringLiteral("windowModalWindow2"));
580
windowModalWindow2->setTransientParent(windowModalWindow1.data());
581
windowModalWindow2->setModality(Qt::WindowModal);
582
windowModalWindow2->resize(windowSize, windowSize);
583
windowModalWindow2->setFramePosition(QPoint(x, y));
584
x = screenGeometry.left() + spacing;
585
y += spacing + windowSize;
587
QScopedPointer<BlockableWindow> applicationModalWindow1(new BlockableWindow);
588
applicationModalWindow1->setTitle(QStringLiteral("applicationModalWindow1"));
589
applicationModalWindow1->setModality(Qt::ApplicationModal);
590
applicationModalWindow1->resize(windowSize, windowSize);
591
applicationModalWindow1->setFramePosition(QPoint(x, y));
593
#ifndef QT_NO_CURSOR // Get the mouse cursor out of the way since we are manually sending enter/leave.
594
QCursor::setPos(QPoint(x + 2 * spacing + windowSize, y));
597
// show the 2 windows, nothing is blocked
600
QVERIFY(QTest::qWaitForWindowExposed(window1.data()));
601
QVERIFY(QTest::qWaitForWindowExposed(window2.data()));
602
QCOMPARE(app.modalWindow(), static_cast<QWindow *>(0));
603
QCOMPARE(window1->blocked, 0);
604
QCOMPARE(childWindow1->blocked, 0);
605
QCOMPARE(window2->blocked, 0);
606
QCOMPARE(windowModalWindow1->blocked, 0);
607
QCOMPARE(windowModalWindow2->blocked, 0);
608
QCOMPARE(applicationModalWindow1->blocked, 0);
610
// enter mouse in window1
611
QWindowSystemInterface::handleEnterEvent(window1.data());
612
QGuiApplication::processEvents();
613
QCOMPARE(window1->enters, 1);
614
QCOMPARE(window1->leaves, 0);
616
// show applicationModalWindow1, everything is blocked
617
applicationModalWindow1->show();
618
QCOMPARE(app.modalWindow(), applicationModalWindow1.data());
619
QCOMPARE(window1->blocked, 1);
620
QCOMPARE(childWindow1->blocked, 1); // QTBUG-32242, blocked status needs to be set on children as well.
621
QCOMPARE(window2->blocked, 1);
622
QCOMPARE(windowModalWindow1->blocked, 1);
623
QCOMPARE(windowModalWindow2->blocked, 1);
624
QCOMPARE(applicationModalWindow1->blocked, 0);
626
// opening modal causes leave for previously entered window, but not others
627
QGuiApplication::processEvents();
628
QCOMPARE(window1->enters, 1);
629
QCOMPARE(window1->leaves, 1);
630
QCOMPARE(window2->enters, 0);
631
QCOMPARE(window2->leaves, 0);
632
QCOMPARE(applicationModalWindow1->enters, 0);
633
QCOMPARE(applicationModalWindow1->leaves, 0);
634
window1->resetCounts();
636
// Try entering/leaving blocked window2 - no events should reach it
637
QWindowSystemInterface::handleEnterEvent(window2.data());
638
QGuiApplication::processEvents();
639
QWindowSystemInterface::handleLeaveEvent(window2.data());
640
QGuiApplication::processEvents();
641
QCOMPARE(window2->enters, 0);
642
QCOMPARE(window2->leaves, 0);
644
// everything is unblocked when applicationModalWindow1 is hidden
645
applicationModalWindow1->hide();
646
QCOMPARE(app.modalWindow(), static_cast<QWindow *>(0));
647
QCOMPARE(window1->blocked, 0);
648
QCOMPARE(childWindow1->blocked, 0); // QTBUG-32242, blocked status needs to be set on children as well.
649
QCOMPARE(window2->blocked, 0);
650
QCOMPARE(windowModalWindow1->blocked, 0);
651
QCOMPARE(windowModalWindow2->blocked, 0);
652
QCOMPARE(applicationModalWindow1->blocked, 0);
654
// Enter window2 - should not be blocked
655
QWindowSystemInterface::handleEnterEvent(window2.data());
656
QGuiApplication::processEvents();
657
QCOMPARE(window2->enters, 1);
658
QCOMPARE(window2->leaves, 0);
660
// show the windowModalWindow1, only window1 is blocked
661
windowModalWindow1->show();
662
QCOMPARE(app.modalWindow(), windowModalWindow1.data());
663
QCOMPARE(window1->blocked, 1);
664
QCOMPARE(window2->blocked, 0);
665
QCOMPARE(windowModalWindow1->blocked, 0);
666
QCOMPARE(windowModalWindow2->blocked, 0);
667
QCOMPARE(applicationModalWindow1->blocked, 0);
669
// opening window modal window doesn't cause leave for unblocked window
670
QGuiApplication::processEvents();
671
QCOMPARE(window1->enters, 0);
672
QCOMPARE(window1->leaves, 0);
673
QCOMPARE(window2->enters, 1);
674
QCOMPARE(window2->leaves, 0);
675
QCOMPARE(windowModalWindow1->enters, 0);
676
QCOMPARE(windowModalWindow1->leaves, 0);
678
// show the windowModalWindow2, windowModalWindow1 is blocked as well
679
windowModalWindow2->show();
680
QCOMPARE(app.modalWindow(), windowModalWindow2.data());
681
QCOMPARE(window1->blocked, 1);
682
QCOMPARE(window2->blocked, 0);
683
QCOMPARE(windowModalWindow1->blocked, 1);
684
QCOMPARE(windowModalWindow2->blocked, 0);
685
QCOMPARE(applicationModalWindow1->blocked, 0);
687
// hide windowModalWindow1, nothing is unblocked
688
windowModalWindow1->hide();
689
QCOMPARE(app.modalWindow(), windowModalWindow2.data());
690
QCOMPARE(window1->blocked, 1);
691
QCOMPARE(window2->blocked, 0);
692
QCOMPARE(windowModalWindow1->blocked, 1);
693
QCOMPARE(windowModalWindow2->blocked, 0);
694
QCOMPARE(applicationModalWindow1->blocked, 0);
696
// hide windowModalWindow2, windowModalWindow1 and window1 are unblocked
697
windowModalWindow2->hide();
698
QCOMPARE(app.modalWindow(), static_cast<QWindow *>(0));
699
QCOMPARE(window1->blocked, 0);
700
QCOMPARE(window2->blocked, 0);
701
QCOMPARE(windowModalWindow1->blocked, 0);
702
QCOMPARE(windowModalWindow2->blocked, 0);
703
QCOMPARE(applicationModalWindow1->blocked, 0);
705
// show windowModalWindow1 again, window1 is blocked
706
windowModalWindow1->show();
707
QCOMPARE(app.modalWindow(), windowModalWindow1.data());
708
QCOMPARE(window1->blocked, 1);
709
QCOMPARE(window2->blocked, 0);
710
QCOMPARE(windowModalWindow1->blocked, 0);
711
QCOMPARE(windowModalWindow2->blocked, 0);
712
QCOMPARE(applicationModalWindow1->blocked, 0);
714
// show windowModalWindow2 again, windowModalWindow1 is also blocked
715
windowModalWindow2->show();
716
QCOMPARE(app.modalWindow(), windowModalWindow2.data());
717
QCOMPARE(window1->blocked, 1);
718
QCOMPARE(window2->blocked, 0);
719
QCOMPARE(windowModalWindow1->blocked, 1);
720
QCOMPARE(windowModalWindow2->blocked, 0);
721
QCOMPARE(applicationModalWindow1->blocked, 0);
723
// show applicationModalWindow1, everything is blocked
724
applicationModalWindow1->show();
725
QCOMPARE(app.modalWindow(), applicationModalWindow1.data());
726
QCOMPARE(window1->blocked, 1);
727
QCOMPARE(window2->blocked, 1);
728
QCOMPARE(windowModalWindow1->blocked, 1);
729
QCOMPARE(windowModalWindow2->blocked, 1);
730
QCOMPARE(applicationModalWindow1->blocked, 0);
732
// window2 gets finally the leave
733
QGuiApplication::processEvents();
734
QCOMPARE(window1->enters, 0);
735
QCOMPARE(window1->leaves, 0);
736
QCOMPARE(window2->enters, 1);
737
QCOMPARE(window2->leaves, 1);
738
QCOMPARE(windowModalWindow1->enters, 0);
739
QCOMPARE(windowModalWindow1->leaves, 0);
740
QCOMPARE(applicationModalWindow1->enters, 0);
741
QCOMPARE(applicationModalWindow1->leaves, 0);
743
// hide applicationModalWindow1, windowModalWindow1 and window1 are blocked
744
applicationModalWindow1->hide();
745
QCOMPARE(app.modalWindow(), windowModalWindow2.data());
746
QCOMPARE(window1->blocked, 1);
747
QCOMPARE(window2->blocked, 0);
748
QCOMPARE(windowModalWindow1->blocked, 1);
749
QCOMPARE(windowModalWindow2->blocked, 0);
750
QCOMPARE(applicationModalWindow1->blocked, 0);
752
// hide windowModalWindow2, window1 is blocked
753
windowModalWindow2->hide();
754
QCOMPARE(app.modalWindow(), windowModalWindow1.data());
755
QCOMPARE(window1->blocked, 1);
756
QCOMPARE(window2->blocked, 0);
757
QCOMPARE(windowModalWindow1->blocked, 0);
758
QCOMPARE(windowModalWindow2->blocked, 0);
759
QCOMPARE(applicationModalWindow1->blocked, 0);
761
// hide windowModalWindow1, everything is unblocked
762
windowModalWindow1->hide();
763
QCOMPARE(app.modalWindow(), static_cast<QWindow *>(0));
764
QCOMPARE(window1->blocked, 0);
765
QCOMPARE(window2->blocked, 0);
766
QCOMPARE(windowModalWindow1->blocked, 0);
767
QCOMPARE(windowModalWindow2->blocked, 0);
768
QCOMPARE(applicationModalWindow1->blocked, 0);
774
void tst_QGuiApplication::quitOnLastWindowClosed()
778
QGuiApplication app(argc, 0);
779
const QRect screenGeometry = QGuiApplication::primaryScreen()->availableVirtualGeometry();
782
timer.setInterval(100);
784
QSignalSpy spy(&app, SIGNAL(aboutToQuit()));
785
QSignalSpy spy2(&timer, SIGNAL(timeout()));
788
mainWindow.setTitle(QStringLiteral("quitOnLastWindowClosedMainWindow"));
789
mainWindow.resize(windowSize, windowSize);
790
mainWindow.setFramePosition(QPoint(screenGeometry.left() + spacing, screenGeometry.top() + spacing));
793
dialog.setTransientParent(&mainWindow);
794
dialog.setTitle(QStringLiteral("quitOnLastWindowClosedDialog"));
795
dialog.resize(windowSize, windowSize);
796
dialog.setFramePosition(QPoint(screenGeometry.left() + 2 * spacing + windowSize, screenGeometry.top() + spacing));
798
QVERIFY(app.quitOnLastWindowClosed());
802
QVERIFY(QTest::qWaitForWindowExposed(&dialog));
805
QTimer::singleShot(1000, &mainWindow, SLOT(close())); // This should quit the application
806
QTimer::singleShot(2000, &app, SLOT(quit())); // This makes sure we quit even if it didn't
810
QCOMPARE(spy.count(), 1);
811
QVERIFY(spy2.count() < 15); // Should be around 10 if closing caused the quit
815
QGuiApplication app(argc, 0);
816
const QRect screenGeometry = QGuiApplication::primaryScreen()->availableVirtualGeometry();
819
timer.setInterval(100);
821
QSignalSpy spy(&app, SIGNAL(aboutToQuit()));
822
QSignalSpy spy2(&timer, SIGNAL(timeout()));
825
mainWindow.setTitle(QStringLiteral("quitOnLastWindowClosedMainWindow"));
826
mainWindow.resize(windowSize, windowSize);
827
mainWindow.setFramePosition(QPoint(screenGeometry.left() + spacing, screenGeometry.top() + spacing));
830
dialog.setTitle(QStringLiteral("quitOnLastWindowClosedDialog"));
831
dialog.resize(windowSize, windowSize);
832
dialog.setFramePosition(QPoint(screenGeometry.left() + 2 * spacing + windowSize, screenGeometry.top() + spacing));
834
QVERIFY(!dialog.transientParent());
835
QVERIFY(app.quitOnLastWindowClosed());
839
QVERIFY(QTest::qWaitForWindowExposed(&dialog));
842
QTimer::singleShot(1000, &mainWindow, SLOT(close())); // This should not quit the application
843
QTimer::singleShot(2000, &app, SLOT(quit()));
847
QCOMPARE(spy.count(), 1);
848
QVERIFY(spy2.count() > 15); // Should be around 20 if closing did not cause the quit
852
QGuiApplication app(argc, 0);
853
app.setQuitOnLastWindowClosed(false);
856
timer.setInterval(2000);
857
timer.setSingleShot(true);
858
QObject::connect(&timer, SIGNAL(timeout()), &app, SLOT(quit()));
860
QSignalSpy spy(&app, SIGNAL(lastWindowClosed()));
861
QSignalSpy spy2(&timer, SIGNAL(timeout()));
863
QPointer<QWindow> mainWindow = new QWindow;
867
QTimer::singleShot(1000, mainWindow, SLOT(close())); // This should not quit the application
872
QCOMPARE(spy2.count(), 1); // quit timer fired
873
QCOMPARE(spy.count(), 1); // lastWindowClosed emitted
875
app.setQuitOnLastWindowClosed(true); // restore underlying static to default value
879
static Qt::ScreenOrientation testOrientationToSend = Qt::PrimaryOrientation;
881
class TestPlugin : public QObject
887
QScreen* screen = QGuiApplication::primaryScreen();
888
// Make sure the orientation we want to send doesn't get filtered out.
889
screen->setOrientationUpdateMask(screen->orientationUpdateMask() | testOrientationToSend);
890
QWindowSystemInterface::handleScreenOrientationChange(screen, testOrientationToSend);
894
class TestPluginFactory : public QGenericPlugin
897
Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QGenericPluginFactoryInterface" FILE "testplugin.json")
899
QObject* create(const QString &key, const QString &)
901
if (key == "testplugin")
902
return new TestPlugin;
907
class TestEventReceiver : public QObject
917
virtual void customEvent(QEvent *)
923
#include "tst_qguiapplication.moc"
925
void tst_QGuiApplication::genericPluginsAndWindowSystemEvents()
927
testOrientationToSend = Qt::InvertedLandscapeOrientation;
929
TestEventReceiver testReceiver;
930
QCoreApplication::postEvent(&testReceiver, new QEvent(QEvent::User));
931
QCOMPARE(testReceiver.customEvents, 0);
933
QStaticPlugin testPluginInfo;
934
testPluginInfo.instance = qt_plugin_instance;
935
testPluginInfo.rawMetaData = qt_plugin_query_metadata;
936
qRegisterStaticPluginFunction(testPluginInfo);
938
char *argv[] = { const_cast<char*>(QTest::currentAppName()), const_cast<char*>("-plugin"), const_cast<char*>("testplugin") };
939
QGuiApplication app(argc, argv);
941
QVERIFY(QGuiApplication::primaryScreen());
942
QCOMPARE(QGuiApplication::primaryScreen()->orientation(), testOrientationToSend);
944
QCOMPARE(testReceiver.customEvents, 0);
945
QCoreApplication::sendPostedEvents(&testReceiver);
946
QCOMPARE(testReceiver.customEvents, 1);
949
Q_DECLARE_METATYPE(Qt::LayoutDirection)
950
void tst_QGuiApplication::layoutDirection()
952
qRegisterMetaType<Qt::LayoutDirection>();
954
Qt::LayoutDirection oldDirection = QGuiApplication::layoutDirection();
955
Qt::LayoutDirection newDirection = oldDirection == Qt::LeftToRight ? Qt::RightToLeft : Qt::LeftToRight;
957
QGuiApplication::setLayoutDirection(newDirection);
958
QCOMPARE(QGuiApplication::layoutDirection(), newDirection);
961
char *argv[] = { const_cast<char*>("tst_qguiapplication") };
962
QGuiApplication app(argc, argv);
963
QSignalSpy signalSpy(&app, SIGNAL(layoutDirectionChanged(Qt::LayoutDirection)));
965
QGuiApplication::setLayoutDirection(oldDirection);
966
QCOMPARE(QGuiApplication::layoutDirection(), oldDirection);
967
QCOMPARE(signalSpy.count(), 1);
968
QCOMPARE(signalSpy.at(0).at(0).toInt(), static_cast<int>(oldDirection));
970
QGuiApplication::setLayoutDirection(oldDirection);
971
QCOMPARE(QGuiApplication::layoutDirection(), oldDirection);
972
QCOMPARE(signalSpy.count(), 1);
975
void tst_QGuiApplication::globalShareContext()
978
// Test that there is a global share context when requested.
979
QCoreApplication::setAttribute(Qt::AA_ShareOpenGLContexts);
981
char *argv[] = { const_cast<char*>("tst_qguiapplication") };
982
QScopedPointer<QGuiApplication> app(new QGuiApplication(argc, argv));
983
QOpenGLContext *ctx = qt_gl_global_share_context();
986
ctx = qt_gl_global_share_context();
989
// Test that there is no global share context by default.
990
QCoreApplication::setAttribute(Qt::AA_ShareOpenGLContexts, false);
991
app.reset(new QGuiApplication(argc, argv));
992
ctx = qt_gl_global_share_context();
995
QSKIP("No OpenGL support");
999
void tst_QGuiApplication::testSetPaletteAttribute()
1001
QCoreApplication::setAttribute(Qt::AA_SetPalette, false);
1003
char *argv[] = { const_cast<char*>("tst_qguiapplication") };
1005
QGuiApplication app(argc, argv);
1007
QVERIFY(!QCoreApplication::testAttribute(Qt::AA_SetPalette));
1009
palette.setColor(QPalette::Foreground, Qt::red);
1010
QGuiApplication::setPalette(palette);
1012
QVERIFY(QCoreApplication::testAttribute(Qt::AA_SetPalette));
1015
// Test that static functions do not crash if there is no application instance.
1016
void tst_QGuiApplication::staticFunctions()
1018
QGuiApplication::setApplicationDisplayName(QString());
1019
QGuiApplication::applicationDisplayName();
1020
QGuiApplication::allWindows();
1021
QGuiApplication::topLevelWindows();
1022
QGuiApplication::topLevelAt(QPoint(0, 0));
1023
QGuiApplication::setWindowIcon(QIcon());
1024
QGuiApplication::windowIcon();
1025
QGuiApplication::platformName();
1026
QGuiApplication::modalWindow();
1027
QGuiApplication::focusWindow();
1028
QGuiApplication::focusObject();
1029
QGuiApplication::primaryScreen();
1030
QGuiApplication::screens();
1031
QGuiApplication::overrideCursor();
1032
QGuiApplication::setOverrideCursor(QCursor());
1033
QGuiApplication::changeOverrideCursor(QCursor());
1034
QGuiApplication::restoreOverrideCursor();
1035
QGuiApplication::keyboardModifiers();
1036
QGuiApplication::queryKeyboardModifiers();
1037
QGuiApplication::mouseButtons();
1038
QGuiApplication::setLayoutDirection(Qt::LeftToRight);
1039
QGuiApplication::layoutDirection();
1040
QGuiApplication::styleHints();
1041
QGuiApplication::setDesktopSettingsAware(true);
1042
QGuiApplication::desktopSettingsAware();
1043
QGuiApplication::inputMethod();
1044
QGuiApplication::platformNativeInterface();
1045
QGuiApplication::platformFunction(QByteArrayLiteral("bla"));
1046
QGuiApplication::setQuitOnLastWindowClosed(true);
1047
QGuiApplication::quitOnLastWindowClosed();
1048
QGuiApplication::applicationState();
1051
void tst_QGuiApplication::settableStyleHints_data()
1053
QTest::addColumn<bool>("appInstance");
1054
QTest::newRow("app") << true;
1055
QTest::newRow("no-app") << false;
1058
void tst_QGuiApplication::settableStyleHints()
1060
QFETCH(bool, appInstance);
1062
QScopedPointer<QGuiApplication> app;
1064
app.reset(new QGuiApplication(argc, 0));
1066
const int keyboardInputInterval = 555;
1067
QGuiApplication::styleHints()->setKeyboardInputInterval(keyboardInputInterval);
1068
QCOMPARE(QGuiApplication::styleHints()->keyboardInputInterval(), keyboardInputInterval);
1071
QTEST_APPLESS_MAIN(tst_QGuiApplication)