1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the test suite of the Qt Toolkit.
7**
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.
16**
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.
24**
25** $QT_END_LICENSE$
26**
27****************************************************************************/
28
29
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/qplatformintegration.h>
39#include <qpa/qwindowsysteminterface.h>
40#include <qgenericplugin.h>
41
42#include <private/qguiapplication_p.h>
43
44#if defined(Q_OS_QNX)
45#include <QOpenGLContext>
46#endif
47
48#include <QtGui/private/qopenglcontext_p.h>
49
50#include <QDebug>
51
52#include "tst_qcoreapplication.h"
53
54enum { spacing = 50, windowSize = 200 };
55
56class tst_QGuiApplication: public tst_QCoreApplication
57{
58 Q_OBJECT
59
60private slots:
61 void initTestCase();
62 void cleanup();
63 void displayName();
64 void desktopFileName();
65 void firstWindowTitle();
66 void windowIcon();
67 void focusObject();
68 void allWindows();
69 void topLevelWindows();
70 void abortQuitOnShow();
71 void changeFocusWindow();
72 void keyboardModifiers();
73 void palette();
74 void font();
75 void modalWindow();
76 void quitOnLastWindowClosed();
77 void quitOnLastWindowClosedMulti();
78 void dontQuitOnLastWindowClosed();
79 void genericPluginsAndWindowSystemEvents();
80 void layoutDirection();
81 void globalShareContext();
82 void testSetPaletteAttribute();
83
84 void staticFunctions();
85
86 void settableStyleHints_data();
87 void settableStyleHints(); // Needs to run last as it changes style hints.
88};
89
90void tst_QGuiApplication::initTestCase()
91{
92#ifdef QT_QPA_DEFAULT_PLATFORM_NAME
93 if ((QString::compare(QStringLiteral(QT_QPA_DEFAULT_PLATFORM_NAME),
94 QStringLiteral("eglfs"), cs: Qt::CaseInsensitive) == 0) ||
95 (QString::compare(s1: QString::fromLatin1(str: qgetenv(varName: "QT_QPA_PLATFORM")),
96 QStringLiteral("eglfs"), cs: Qt::CaseInsensitive) == 0)) {
97 // Set env variables to disable input and cursor because eglfs is single fullscreen window
98 // and trying to initialize input and cursor will crash test.
99 qputenv(varName: "QT_QPA_EGLFS_DISABLE_INPUT", value: "1");
100 qputenv(varName: "QT_QPA_EGLFS_HIDECURSOR", value: "1");
101 }
102#endif
103}
104
105void tst_QGuiApplication::cleanup()
106{
107 QVERIFY(QGuiApplication::allWindows().isEmpty());
108}
109
110void tst_QGuiApplication::displayName()
111{
112 int argc = 1;
113 char *argv[] = { const_cast<char*>("tst_qguiapplication") };
114 QGuiApplication app(argc, argv);
115 QSignalSpy spy(&app, &QGuiApplication::applicationDisplayNameChanged);
116
117 QCOMPARE(::qAppName(), QString::fromLatin1("tst_qguiapplication"));
118 QCOMPARE(QGuiApplication::applicationName(), QString::fromLatin1("tst_qguiapplication"));
119 QCOMPARE(QGuiApplication::applicationDisplayName(), QString::fromLatin1("tst_qguiapplication"));
120
121 QGuiApplication::setApplicationName("The Core Application");
122 QCOMPARE(QGuiApplication::applicationName(), QString::fromLatin1("The Core Application"));
123 QCOMPARE(QGuiApplication::applicationDisplayName(), QString::fromLatin1("The Core Application"));
124 QCOMPARE(spy.count(), 1);
125
126 QGuiApplication::setApplicationDisplayName("The GUI Application");
127 QCOMPARE(QGuiApplication::applicationDisplayName(), QString::fromLatin1("The GUI Application"));
128 QCOMPARE(spy.count(), 2);
129
130 QGuiApplication::setApplicationName("The Core Application 2");
131 QCOMPARE(QGuiApplication::applicationName(), QString::fromLatin1("The Core Application 2"));
132 QCOMPARE(QGuiApplication::applicationDisplayName(), QString::fromLatin1("The GUI Application"));
133 QCOMPARE(spy.count(), 2);
134
135 QGuiApplication::setApplicationDisplayName("The GUI Application 2");
136 QCOMPARE(QGuiApplication::applicationDisplayName(), QString::fromLatin1("The GUI Application 2"));
137 QCOMPARE(spy.count(), 3);
138}
139
140void tst_QGuiApplication::desktopFileName()
141{
142 int argc = 1;
143 char *argv[] = { const_cast<char*>("tst_qguiapplication") };
144 QGuiApplication app(argc, argv);
145
146 QCOMPARE(QGuiApplication::desktopFileName(), QString());
147
148 QGuiApplication::setDesktopFileName("io.qt.QGuiApplication.desktop");
149 QCOMPARE(QGuiApplication::desktopFileName(), QString::fromLatin1("io.qt.QGuiApplication.desktop"));
150
151 QGuiApplication::setDesktopFileName(QString());
152 QCOMPARE(QGuiApplication::desktopFileName(), QString());
153}
154
155void tst_QGuiApplication::firstWindowTitle()
156{
157 int argc = 3;
158 char *argv[] = { const_cast<char*>("tst_qguiapplication"), const_cast<char*>("-qwindowtitle"), const_cast<char*>("User Title") };
159 QGuiApplication app(argc, argv);
160 QWindow window;
161 window.setTitle("Application Title");
162 window.show();
163 QCOMPARE(window.title(), QString("User Title"));
164}
165
166void tst_QGuiApplication::windowIcon()
167{
168 int argc = 3;
169 char *argv[] = { const_cast<char*>("tst_qguiapplication"), const_cast<char*>("-qwindowicon"), const_cast<char*>(":/icons/usericon.png") };
170 QGuiApplication app(argc, argv);
171 QIcon appIcon(":/icons/appicon.png");
172 app.setWindowIcon(appIcon);
173
174 QWindow window;
175 window.show();
176
177 QIcon userIcon(":/icons/usericon.png");
178 // Comparing icons is hard. cacheKey() differs because the icon was independently loaded.
179 // So we use availableSizes, after making sure that the app and user icons do have different sizes.
180 QVERIFY(userIcon.availableSizes() != appIcon.availableSizes());
181 QCOMPARE(window.icon().availableSizes(), userIcon.availableSizes());
182}
183
184class DummyWindow : public QWindow
185{
186public:
187 DummyWindow() : m_focusObject(nullptr) {}
188
189 virtual QObject *focusObject() const
190 {
191 return m_focusObject;
192 }
193
194 void setFocusObject(QObject *object)
195 {
196 m_focusObject = object;
197 emit focusObjectChanged(object);
198 }
199
200 QObject *m_focusObject;
201};
202
203
204void tst_QGuiApplication::focusObject()
205{
206 int argc = 0;
207 QGuiApplication app(argc, nullptr);
208
209 if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(cap: QPlatformIntegration::WindowActivation))
210 QSKIP("QWindow::requestActivate() is not supported.");
211
212 QObject obj1, obj2, obj3;
213 const QRect screenGeometry = QGuiApplication::primaryScreen()->availableVirtualGeometry();
214
215 DummyWindow window1;
216#if defined(Q_OS_QNX)
217 window1.setSurfaceType(QSurface::OpenGLSurface);
218#endif
219 window1.resize(w: windowSize, h: windowSize);
220 window1.setTitle(QStringLiteral("focusObject:window1"));
221 window1.setFramePosition(QPoint(screenGeometry.left() + spacing, screenGeometry.top() + spacing));
222 DummyWindow window2;
223 window2.resize(w: windowSize, h: windowSize);
224 window2.setFramePosition(QPoint(screenGeometry.left() + 2 * spacing + windowSize, screenGeometry.top() + spacing));
225 window2.setTitle(QStringLiteral("focusObject:window2"));
226
227 window1.show();
228
229#if defined(Q_OS_QNX) // We either need to create a eglSurface or a create a backing store
230 // and then post the window in order for screen to show the window
231 QOpenGLContext context;
232 context.create();
233 context.makeCurrent(&window1);
234 QVERIFY(QTest::qWaitForWindowExposed(&window1)); // Buffer swap only succeeds with exposed window
235 context.swapBuffers(&window1);
236#endif
237
238 QSignalSpy spy(&app, SIGNAL(focusObjectChanged(QObject*)));
239
240
241 // verify active window focus propagates to qguiapplication
242 window1.requestActivate();
243 QVERIFY(QTest::qWaitForWindowActive(&window1));
244 QCOMPARE(app.focusWindow(), &window1);
245
246 window1.setFocusObject(&obj1);
247 QCOMPARE(app.focusObject(), &obj1);
248 QCOMPARE(spy.count(), 1);
249
250 spy.clear();
251 window1.setFocusObject(&obj2);
252 QCOMPARE(app.focusObject(), &obj2);
253 QCOMPARE(spy.count(), 1);
254
255 spy.clear();
256 window2.setFocusObject(&obj3);
257 QCOMPARE(app.focusObject(), &obj2); // not yet changed
258 window2.show();
259 QVERIFY(QTest::qWaitForWindowExposed(&window2));
260 QTRY_COMPARE(app.focusWindow(), &window2);
261 QCOMPARE(app.focusObject(), &obj3);
262 QCOMPARE(spy.count(), 1);
263
264 // focus change on unfocused window does not show
265 spy.clear();
266 window1.setFocusObject(&obj1);
267 QCOMPARE(spy.count(), 0);
268 QCOMPARE(app.focusObject(), &obj3);
269}
270
271void tst_QGuiApplication::allWindows()
272{
273 int argc = 0;
274 QGuiApplication app(argc, nullptr);
275 QWindow *window1 = new QWindow;
276 QWindow *window2 = new QWindow(window1);
277 QVERIFY(app.allWindows().contains(window1));
278 QVERIFY(app.allWindows().contains(window2));
279 QCOMPARE(app.allWindows().count(), 2);
280 delete window1;
281 window1 = nullptr;
282 window2 = nullptr;
283 QVERIFY(!app.allWindows().contains(window2));
284 QVERIFY(!app.allWindows().contains(window1));
285 QCOMPARE(app.allWindows().count(), 0);
286}
287
288void tst_QGuiApplication::topLevelWindows()
289{
290 int argc = 0;
291 QGuiApplication app(argc, nullptr);
292 QWindow *window1 = new QWindow;
293 QWindow *window2 = new QWindow(window1);
294 QVERIFY(app.topLevelWindows().contains(window1));
295 QVERIFY(!app.topLevelWindows().contains(window2));
296 QCOMPARE(app.topLevelWindows().count(), 1);
297 delete window1;
298 window1 = nullptr;
299 window2 = nullptr;
300 QVERIFY(!app.topLevelWindows().contains(window2));
301 QVERIFY(!app.topLevelWindows().contains(window1));
302 QCOMPARE(app.topLevelWindows().count(), 0);
303}
304
305class ShowCloseShowWindow : public QWindow
306{
307 Q_OBJECT
308public:
309 ShowCloseShowWindow(bool showAgain, QWindow *parent = nullptr)
310 : QWindow(parent), showAgain(showAgain)
311 {
312 QTimer::singleShot(msec: 0, receiver: this, SLOT(doClose()));
313 QTimer::singleShot(msec: 500, receiver: this, SLOT(exitApp()));
314 }
315
316private slots:
317 void doClose() {
318 close();
319 if (showAgain)
320 show();
321 }
322
323 void exitApp() {
324 qApp->exit(retcode: 1);
325 }
326
327private:
328 bool showAgain;
329};
330
331void tst_QGuiApplication::abortQuitOnShow()
332{
333 int argc = 0;
334 QGuiApplication app(argc, nullptr);
335 const QRect screenGeometry = QGuiApplication::primaryScreen()->availableVirtualGeometry();
336
337 QScopedPointer<QWindow> window1(new ShowCloseShowWindow(false));
338 window1->resize(w: windowSize, h: windowSize);
339 window1->setFramePosition(QPoint(screenGeometry.left() + spacing, screenGeometry.top() + spacing));
340 window1->setTitle(QStringLiteral("abortQuitOnShow:window1"));
341 window1->show();
342 QCOMPARE(app.exec(), 0);
343
344 QScopedPointer<QWindow> window2(new ShowCloseShowWindow(true));
345 window2->setTitle(QStringLiteral("abortQuitOnShow:window2"));
346 window2->resize(w: windowSize, h: windowSize);
347 window2->setFramePosition(QPoint(screenGeometry.left() + 2 * spacing + windowSize, screenGeometry.top() + spacing));
348 window2->show();
349 QCOMPARE(app.exec(), 1);
350}
351
352
353class FocusChangeWindow: public QWindow
354{
355protected:
356 virtual bool event(QEvent *ev)
357 {
358 if (ev->type() == QEvent::FocusAboutToChange)
359 windowDuringFocusAboutToChange = qGuiApp->focusWindow();
360 return QWindow::event(ev);
361 }
362
363 virtual void focusOutEvent(QFocusEvent *)
364 {
365 windowDuringFocusOut = qGuiApp->focusWindow();
366 }
367
368public:
369 FocusChangeWindow() : QWindow(), windowDuringFocusAboutToChange(nullptr), windowDuringFocusOut(nullptr) {}
370
371 QWindow *windowDuringFocusAboutToChange;
372 QWindow *windowDuringFocusOut;
373};
374
375void tst_QGuiApplication::changeFocusWindow()
376{
377#ifdef Q_OS_WINRT
378 QSKIP("WinRt does not support multiple native windows.");
379#endif
380 int argc = 0;
381 QGuiApplication app(argc, nullptr);
382
383 if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(cap: QPlatformIntegration::WindowActivation))
384 QSKIP("QWindow::requestActivate() is not supported.");
385
386 const QRect screenGeometry = QGuiApplication::primaryScreen()->availableVirtualGeometry();
387
388 // focus is changed between FocusAboutToChange and FocusChanged
389 FocusChangeWindow window1;
390#if defined(Q_OS_QNX)
391 window1.setSurfaceType(QSurface::OpenGLSurface);
392#endif
393 window1.resize(w: windowSize, h: windowSize);
394 window1.setFramePosition(QPoint(screenGeometry.left() + spacing, screenGeometry.top() + spacing));
395 window1.setTitle(QStringLiteral("changeFocusWindow:window1"));
396 window1.show();
397#if defined(Q_OS_QNX) // We either need to create a eglSurface or a create a backing store
398 // and then post the window in order for screen to show the window
399 QOpenGLContext context;
400 context.create();
401 context.makeCurrent(&window1);
402 QVERIFY(QTest::qWaitForWindowExposed(&window1)); // Buffer swap only succeeds with exposed window
403 context.swapBuffers(&window1);
404#endif
405 FocusChangeWindow window2;
406#if defined(Q_OS_QNX)
407 window2.setSurfaceType(QSurface::OpenGLSurface);
408#endif
409 window2.resize(w: windowSize, h: windowSize);
410 window2.setFramePosition(QPoint(screenGeometry.left() + 2 * spacing + windowSize, screenGeometry.top() + spacing));
411 window2.setTitle(QStringLiteral("changeFocusWindow:window2"));
412 window2.show();
413#if defined(Q_OS_QNX) // We either need to create a eglSurface or a create a backing store
414 // and then post the window in order for screen to show the window
415 context.makeCurrent(&window2);
416 QVERIFY(QTest::qWaitForWindowExposed(&window2)); // Buffer swap only succeeds with exposed window
417 context.swapBuffers(&window2);
418#endif
419 QVERIFY(QTest::qWaitForWindowExposed(&window1));
420 QVERIFY(QTest::qWaitForWindowExposed(&window2));
421 window1.requestActivate();
422 QTRY_COMPARE(app.focusWindow(), &window1);
423
424 window2.requestActivate();
425 QTRY_COMPARE(app.focusWindow(), &window2);
426 QCOMPARE(window1.windowDuringFocusAboutToChange, &window1);
427 QCOMPARE(window1.windowDuringFocusOut, &window2);
428}
429
430void tst_QGuiApplication::keyboardModifiers()
431{
432 int argc = 0;
433 QGuiApplication app(argc, nullptr);
434 const QRect screenGeometry = QGuiApplication::primaryScreen()->availableVirtualGeometry();
435
436 QScopedPointer<QWindow> window(new QWindow);
437 window->resize(w: windowSize, h: windowSize);
438 window->setFramePosition(QPoint(screenGeometry.left() + spacing, screenGeometry.top() + spacing));
439 window->setTitle(QStringLiteral("keyboardModifiers"));
440
441 window->show();
442 QVERIFY(QTest::qWaitForWindowExposed(window.data()));
443 QCOMPARE(QGuiApplication::keyboardModifiers(), Qt::NoModifier);
444
445 // mouse events
446 QPoint center = window->geometry().center();
447 QTest::mouseEvent(action: QTest::MousePress, window: window.data(), button: Qt::LeftButton, stateKey: Qt::NoModifier, pos: center);
448 QCOMPARE(QGuiApplication::keyboardModifiers(), Qt::NoModifier);
449 QTest::mouseEvent(action: QTest::MouseRelease, window: window.data(), button: Qt::LeftButton, stateKey: Qt::NoModifier, pos: center);
450 QCOMPARE(QGuiApplication::keyboardModifiers(), Qt::NoModifier);
451 QTest::mouseEvent(action: QTest::MousePress, window: window.data(), button: Qt::RightButton, stateKey: Qt::ControlModifier, pos: center);
452 QCOMPARE(QGuiApplication::keyboardModifiers(), Qt::ControlModifier);
453 QTest::mouseEvent(action: QTest::MouseRelease, window: window.data(), button: Qt::RightButton, stateKey: Qt::ControlModifier, pos: center);
454 QCOMPARE(QGuiApplication::keyboardModifiers(), Qt::ControlModifier);
455
456 // shortcut events
457 QTest::keyEvent(action: QTest::Shortcut, window: window.data(), key: Qt::Key_5, modifier: Qt::MetaModifier);
458 QCOMPARE(QGuiApplication::keyboardModifiers(), Qt::MetaModifier);
459 QTest::keyEvent(action: QTest::Shortcut, window: window.data(), key: Qt::Key_Period, modifier: Qt::NoModifier);
460 QCOMPARE(QGuiApplication::keyboardModifiers(), Qt::NoModifier);
461 QTest::keyEvent(action: QTest::Shortcut, window: window.data(), key: Qt::Key_0, modifier: Qt::ControlModifier);
462 QCOMPARE(QGuiApplication::keyboardModifiers(), Qt::ControlModifier);
463
464 // key events
465 QTest::keyEvent(action: QTest::Press, window: window.data(), key: Qt::Key_C);
466 QCOMPARE(QGuiApplication::keyboardModifiers(), Qt::NoModifier);
467 QTest::keyEvent(action: QTest::Release, window: window.data(), key: Qt::Key_C);
468 QCOMPARE(QGuiApplication::keyboardModifiers(), Qt::NoModifier);
469
470 QTest::keyEvent(action: QTest::Press, window: window.data(), key: Qt::Key_U, modifier: Qt::ControlModifier);
471 QCOMPARE(QGuiApplication::keyboardModifiers(), Qt::ControlModifier);
472 QTest::keyEvent(action: QTest::Release, window: window.data(), key: Qt::Key_U, modifier: Qt::ControlModifier);
473 QCOMPARE(QGuiApplication::keyboardModifiers(), Qt::ControlModifier);
474
475 QTest::keyEvent(action: QTest::Press, window: window.data(), key: Qt::Key_T);
476 QCOMPARE(QGuiApplication::keyboardModifiers(), Qt::NoModifier);
477 QTest::keyEvent(action: QTest::Release, window: window.data(), key: Qt::Key_T);
478 QCOMPARE(QGuiApplication::keyboardModifiers(), Qt::NoModifier);
479
480 QTest::keyEvent(action: QTest::Press, window: window.data(), key: Qt::Key_E, modifier: Qt::ControlModifier);
481 QCOMPARE(QGuiApplication::keyboardModifiers(), Qt::ControlModifier);
482 QTest::keyEvent(action: QTest::Release, window: window.data(), key: Qt::Key_E, modifier: Qt::ControlModifier);
483 QCOMPARE(QGuiApplication::keyboardModifiers(), Qt::ControlModifier);
484
485 // wheel events
486 QPoint global = window->mapToGlobal(pos: center);
487 QPoint delta(0, 1);
488 QWindowSystemInterface::handleWheelEvent(window: window.data(), local: center, global, pixelDelta: delta, angleDelta: delta, mods: Qt::NoModifier);
489 QWindowSystemInterface::sendWindowSystemEvents(flags: QEventLoop::AllEvents);
490 QCOMPARE(QGuiApplication::keyboardModifiers(), Qt::NoModifier);
491 QWindowSystemInterface::handleWheelEvent(window: window.data(), local: center, global, pixelDelta: delta, angleDelta: delta, mods: Qt::AltModifier);
492 QWindowSystemInterface::sendWindowSystemEvents(flags: QEventLoop::AllEvents);
493 QCOMPARE(QGuiApplication::keyboardModifiers(), Qt::AltModifier);
494 QWindowSystemInterface::handleWheelEvent(window: window.data(), local: center, global, pixelDelta: delta, angleDelta: delta, mods: Qt::ControlModifier);
495 QWindowSystemInterface::sendWindowSystemEvents(flags: QEventLoop::AllEvents);
496 QCOMPARE(QGuiApplication::keyboardModifiers(), Qt::ControlModifier);
497
498 // touch events
499 QList<const QTouchDevice *> touchDevices = QTouchDevice::devices();
500 if (!touchDevices.isEmpty()) {
501 QTouchDevice *touchDevice = const_cast<QTouchDevice *>(touchDevices.first());
502 QTest::touchEvent(window: window.data(), device: touchDevice).press(touchId: 1, pt: center).release(touchId: 1, pt: center);
503 QCOMPARE(QGuiApplication::keyboardModifiers(), Qt::NoModifier);
504 }
505
506 window->close();
507}
508
509/*
510 Compare actual against expected but ignore unset roles.
511
512 Comparing palettes via operator== will compare all roles.
513*/
514static bool palettesMatch(const QPalette &actual, const QPalette &expected)
515{
516 if (actual.resolve() != expected.resolve())
517 return false;
518
519 for (int i = 0; i < QPalette::NColorGroups; i++) {
520 for (int j = 0; j < QPalette::NColorRoles; j++) {
521 const auto g = QPalette::ColorGroup(i);
522 const auto r = QPalette::ColorRole(j);
523 if (expected.isBrushSet(cg: g, cr: r)) {
524 if (actual.brush(cg: g, cr: r) != expected.brush(cg: g, cr: r))
525 return false;
526 }
527 }
528 }
529 return true;
530}
531
532void tst_QGuiApplication::palette()
533{
534 // Getting the palette before application construction should work
535 QPalette paletteBeforeAppConstruction = QGuiApplication::palette();
536 // And should be reflected in the default constructed palette
537 QCOMPARE(paletteBeforeAppConstruction, QPalette());
538
539 int argc = 1;
540 char *argv[] = { const_cast<char*>("tst_qguiapplication") };
541 QGuiApplication app(argc, argv);
542
543 // The same should be true after application construction
544 QCOMPARE(QGuiApplication::palette(), QPalette());
545
546 // The default application palette is not resolved
547 QVERIFY(!QGuiApplication::palette().resolve());
548
549 QSignalSpy signalSpy(&app, SIGNAL(paletteChanged(QPalette)));
550
551 QPalette oldPalette = QGuiApplication::palette();
552 QPalette newPalette = QPalette(Qt::red);
553
554 QGuiApplication::setPalette(newPalette);
555 QVERIFY(palettesMatch(QGuiApplication::palette(), newPalette));
556 QCOMPARE(signalSpy.count(), 1);
557 QVERIFY(palettesMatch(signalSpy.at(0).at(0).value<QPalette>(), newPalette));
558 QCOMPARE(QGuiApplication::palette(), QPalette());
559
560 QGuiApplication::setPalette(oldPalette);
561 QVERIFY(palettesMatch(QGuiApplication::palette(), oldPalette));
562 QCOMPARE(signalSpy.count(), 2);
563 QVERIFY(palettesMatch(signalSpy.at(1).at(0).value<QPalette>(), oldPalette));
564 QCOMPARE(QGuiApplication::palette(), QPalette());
565
566 QGuiApplication::setPalette(oldPalette);
567 QVERIFY(palettesMatch(QGuiApplication::palette(), oldPalette));
568 QCOMPARE(signalSpy.count(), 2);
569 QCOMPARE(QGuiApplication::palette(), QPalette());
570}
571
572void tst_QGuiApplication::font()
573{
574 int argc = 1;
575 char *argv[] = { const_cast<char*>("tst_qguiapplication") };
576 QGuiApplication app(argc, argv);
577 QSignalSpy signalSpy(&app, SIGNAL(fontChanged(QFont)));
578
579 QFont oldFont = QGuiApplication::font();
580 QFont newFont = QFont("BogusFont", 33);
581
582 QGuiApplication::setFont(newFont);
583 QCOMPARE(QGuiApplication::font(), newFont);
584 QCOMPARE(signalSpy.count(), 1);
585 QCOMPARE(signalSpy.at(0).at(0), QVariant(newFont));
586
587 QGuiApplication::setFont(oldFont);
588 QCOMPARE(QGuiApplication::font(), oldFont);
589 QCOMPARE(signalSpy.count(), 2);
590 QCOMPARE(signalSpy.at(1).at(0), QVariant(oldFont));
591
592 QGuiApplication::setFont(oldFont);
593 QCOMPARE(QGuiApplication::font(), oldFont);
594 QCOMPARE(signalSpy.count(), 2);
595}
596
597class BlockableWindow : public QWindow
598{
599 Q_OBJECT
600public:
601 int blocked;
602 int leaves;
603 int enters;
604
605 inline explicit BlockableWindow(QWindow *parent = nullptr)
606 : QWindow(parent), blocked(false), leaves(0), enters(0) {}
607
608 bool event(QEvent *e)
609 {
610 switch (e->type()) {
611 case QEvent::WindowBlocked:
612 ++blocked;
613 break;
614 case QEvent::WindowUnblocked:
615 --blocked;
616 break;
617 case QEvent::Leave:
618 leaves++;
619 break;
620 case QEvent::Enter:
621 enters++;
622 break;
623 default:
624 break;
625 }
626 return QWindow::event(e);
627 }
628
629 void resetCounts()
630 {
631 leaves = 0;
632 enters = 0;
633 }
634};
635
636void tst_QGuiApplication::modalWindow()
637{
638#ifdef Q_OS_WINRT
639 QSKIP("WinRt does not support multiple native windows.");
640#endif
641 int argc = 0;
642 QGuiApplication app(argc, nullptr);
643 const QRect screenGeometry = QGuiApplication::primaryScreen()->availableVirtualGeometry();
644
645 int x = screenGeometry.left() + spacing;
646 int y = screenGeometry.top() + spacing;
647
648 QScopedPointer<BlockableWindow> window1(new BlockableWindow);
649 window1->setTitle(QStringLiteral("window1"));
650 window1->resize(w: windowSize, h: windowSize);
651 window1->setFramePosition(QPoint(x, y));
652 BlockableWindow *childWindow1 = new BlockableWindow(window1.data());
653 childWindow1->resize(w: windowSize / 2, h: windowSize / 2);
654 x += spacing + windowSize;
655
656 QScopedPointer<BlockableWindow> window2(new BlockableWindow);
657 window2->setTitle(QStringLiteral("window2"));
658 window2->setFlags(window2->flags() & Qt::Tool); // QTBUG-32433, don't be fooled by unusual window flags.
659 window2->resize(w: windowSize, h: windowSize);
660 window2->setFramePosition(QPoint(x, y));
661 x += spacing + windowSize;
662
663 QScopedPointer<BlockableWindow> windowModalWindow1(new BlockableWindow);
664 windowModalWindow1->setTitle(QStringLiteral("windowModalWindow1"));
665 windowModalWindow1->setTransientParent(window1.data());
666 windowModalWindow1->setModality(Qt::WindowModal);
667 windowModalWindow1->resize(w: windowSize, h: windowSize);
668 windowModalWindow1->setFramePosition(QPoint(x, y));
669 x += spacing + windowSize;
670
671 QScopedPointer<BlockableWindow> windowModalWindow2(new BlockableWindow);
672 windowModalWindow2->setTitle(QStringLiteral("windowModalWindow2"));
673 windowModalWindow2->setTransientParent(windowModalWindow1.data());
674 windowModalWindow2->setModality(Qt::WindowModal);
675 windowModalWindow2->resize(w: windowSize, h: windowSize);
676 windowModalWindow2->setFramePosition(QPoint(x, y));
677 x = screenGeometry.left() + spacing;
678 y += spacing + windowSize;
679
680 QScopedPointer<BlockableWindow> applicationModalWindow1(new BlockableWindow);
681 applicationModalWindow1->setTitle(QStringLiteral("applicationModalWindow1"));
682 applicationModalWindow1->setModality(Qt::ApplicationModal);
683 applicationModalWindow1->resize(w: windowSize, h: windowSize);
684 applicationModalWindow1->setFramePosition(QPoint(x, y));
685
686#ifndef QT_NO_CURSOR // Get the mouse cursor out of the way since we are manually sending enter/leave.
687 QCursor::setPos(QPoint(x + 2 * spacing + windowSize, y));
688#endif
689
690 // show the 2 windows, nothing is blocked
691 window1->show();
692 window2->show();
693 QVERIFY(QTest::qWaitForWindowExposed(window1.data()));
694 QVERIFY(QTest::qWaitForWindowExposed(window2.data()));
695 QCOMPARE(app.modalWindow(), static_cast<QWindow *>(nullptr));
696 QCOMPARE(window1->blocked, 0);
697 QCOMPARE(childWindow1->blocked, 0);
698 QCOMPARE(window2->blocked, 0);
699 QCOMPARE(windowModalWindow1->blocked, 0);
700 QCOMPARE(windowModalWindow2->blocked, 0);
701 QCOMPARE(applicationModalWindow1->blocked, 0);
702
703 // enter mouse in window1
704 QWindowSystemInterface::handleEnterEvent(window: window1.data());
705 QGuiApplication::processEvents();
706 QCOMPARE(window1->enters, 1);
707 QCOMPARE(window1->leaves, 0);
708
709 // show applicationModalWindow1, everything is blocked
710 applicationModalWindow1->show();
711 QCOMPARE(app.modalWindow(), applicationModalWindow1.data());
712 QCOMPARE(window1->blocked, 1);
713 QCOMPARE(childWindow1->blocked, 1); // QTBUG-32242, blocked status needs to be set on children as well.
714 QCOMPARE(window2->blocked, 1);
715 QCOMPARE(windowModalWindow1->blocked, 1);
716 QCOMPARE(windowModalWindow2->blocked, 1);
717 QCOMPARE(applicationModalWindow1->blocked, 0);
718
719 // opening modal causes leave for previously entered window, but not others
720 QGuiApplication::processEvents();
721 QCOMPARE(window1->enters, 1);
722 QCOMPARE(window1->leaves, 1);
723 QCOMPARE(window2->enters, 0);
724 QCOMPARE(window2->leaves, 0);
725 QCOMPARE(applicationModalWindow1->enters, 0);
726 QCOMPARE(applicationModalWindow1->leaves, 0);
727 window1->resetCounts();
728
729 // Try entering/leaving blocked window2 - no events should reach it
730 QWindowSystemInterface::handleEnterEvent(window: window2.data());
731 QGuiApplication::processEvents();
732 QWindowSystemInterface::handleLeaveEvent(window: window2.data());
733 QGuiApplication::processEvents();
734 QCOMPARE(window2->enters, 0);
735 QCOMPARE(window2->leaves, 0);
736
737 // everything is unblocked when applicationModalWindow1 is hidden
738 applicationModalWindow1->hide();
739 QCOMPARE(app.modalWindow(), static_cast<QWindow *>(nullptr));
740 QCOMPARE(window1->blocked, 0);
741 QCOMPARE(childWindow1->blocked, 0); // QTBUG-32242, blocked status needs to be set on children as well.
742 QCOMPARE(window2->blocked, 0);
743 QCOMPARE(windowModalWindow1->blocked, 0);
744 QCOMPARE(windowModalWindow2->blocked, 0);
745 QCOMPARE(applicationModalWindow1->blocked, 0);
746
747 // Enter window2 - should not be blocked
748 QWindowSystemInterface::handleEnterEvent(window: window2.data());
749 QGuiApplication::processEvents();
750 QCOMPARE(window2->enters, 1);
751 QCOMPARE(window2->leaves, 0);
752
753 // show the windowModalWindow1, only window1 is blocked
754 windowModalWindow1->show();
755 QCOMPARE(app.modalWindow(), windowModalWindow1.data());
756 QCOMPARE(window1->blocked, 1);
757 QCOMPARE(window2->blocked, 0);
758 QCOMPARE(windowModalWindow1->blocked, 0);
759 QCOMPARE(windowModalWindow2->blocked, 0);
760 QCOMPARE(applicationModalWindow1->blocked, 0);
761
762 // opening window modal window doesn't cause leave for unblocked window
763 QGuiApplication::processEvents();
764 QCOMPARE(window1->enters, 0);
765 QCOMPARE(window1->leaves, 0);
766 QCOMPARE(window2->enters, 1);
767 QCOMPARE(window2->leaves, 0);
768 QCOMPARE(windowModalWindow1->enters, 0);
769 QCOMPARE(windowModalWindow1->leaves, 0);
770
771 // show the windowModalWindow2, windowModalWindow1 is blocked as well
772 windowModalWindow2->show();
773 QCOMPARE(app.modalWindow(), windowModalWindow2.data());
774 QCOMPARE(window1->blocked, 1);
775 QCOMPARE(window2->blocked, 0);
776 QCOMPARE(windowModalWindow1->blocked, 1);
777 QCOMPARE(windowModalWindow2->blocked, 0);
778 QCOMPARE(applicationModalWindow1->blocked, 0);
779
780 // hide windowModalWindow1, nothing is unblocked
781 windowModalWindow1->hide();
782 QCOMPARE(app.modalWindow(), windowModalWindow2.data());
783 QCOMPARE(window1->blocked, 1);
784 QCOMPARE(window2->blocked, 0);
785 QCOMPARE(windowModalWindow1->blocked, 1);
786 QCOMPARE(windowModalWindow2->blocked, 0);
787 QCOMPARE(applicationModalWindow1->blocked, 0);
788
789 // hide windowModalWindow2, windowModalWindow1 and window1 are unblocked
790 windowModalWindow2->hide();
791 QCOMPARE(app.modalWindow(), static_cast<QWindow *>(nullptr));
792 QCOMPARE(window1->blocked, 0);
793 QCOMPARE(window2->blocked, 0);
794 QCOMPARE(windowModalWindow1->blocked, 0);
795 QCOMPARE(windowModalWindow2->blocked, 0);
796 QCOMPARE(applicationModalWindow1->blocked, 0);
797
798 // show windowModalWindow1 again, window1 is blocked
799 windowModalWindow1->show();
800 QCOMPARE(app.modalWindow(), windowModalWindow1.data());
801 QCOMPARE(window1->blocked, 1);
802 QCOMPARE(window2->blocked, 0);
803 QCOMPARE(windowModalWindow1->blocked, 0);
804 QCOMPARE(windowModalWindow2->blocked, 0);
805 QCOMPARE(applicationModalWindow1->blocked, 0);
806
807 // show windowModalWindow2 again, windowModalWindow1 is also blocked
808 windowModalWindow2->show();
809 QCOMPARE(app.modalWindow(), windowModalWindow2.data());
810 QCOMPARE(window1->blocked, 1);
811 QCOMPARE(window2->blocked, 0);
812 QCOMPARE(windowModalWindow1->blocked, 1);
813 QCOMPARE(windowModalWindow2->blocked, 0);
814 QCOMPARE(applicationModalWindow1->blocked, 0);
815
816 // show applicationModalWindow1, everything is blocked
817 applicationModalWindow1->show();
818 QCOMPARE(app.modalWindow(), applicationModalWindow1.data());
819 QCOMPARE(window1->blocked, 1);
820 QCOMPARE(window2->blocked, 1);
821 QCOMPARE(windowModalWindow1->blocked, 1);
822 QCOMPARE(windowModalWindow2->blocked, 1);
823 QCOMPARE(applicationModalWindow1->blocked, 0);
824
825 // window2 gets finally the leave
826 QGuiApplication::processEvents();
827 QCOMPARE(window1->enters, 0);
828 QCOMPARE(window1->leaves, 0);
829 QCOMPARE(window2->enters, 1);
830 QCOMPARE(window2->leaves, 1);
831 QCOMPARE(windowModalWindow1->enters, 0);
832 QCOMPARE(windowModalWindow1->leaves, 0);
833 QCOMPARE(applicationModalWindow1->enters, 0);
834 QCOMPARE(applicationModalWindow1->leaves, 0);
835
836 // hide applicationModalWindow1, windowModalWindow1 and window1 are blocked
837 applicationModalWindow1->hide();
838 QCOMPARE(app.modalWindow(), windowModalWindow2.data());
839 QCOMPARE(window1->blocked, 1);
840 QCOMPARE(window2->blocked, 0);
841 QCOMPARE(windowModalWindow1->blocked, 1);
842 QCOMPARE(windowModalWindow2->blocked, 0);
843 QCOMPARE(applicationModalWindow1->blocked, 0);
844
845 // hide windowModalWindow2, window1 is blocked
846 windowModalWindow2->hide();
847 QCOMPARE(app.modalWindow(), windowModalWindow1.data());
848 QCOMPARE(window1->blocked, 1);
849 QCOMPARE(window2->blocked, 0);
850 QCOMPARE(windowModalWindow1->blocked, 0);
851 QCOMPARE(windowModalWindow2->blocked, 0);
852 QCOMPARE(applicationModalWindow1->blocked, 0);
853
854 // hide windowModalWindow1, everything is unblocked
855 windowModalWindow1->hide();
856 QCOMPARE(app.modalWindow(), static_cast<QWindow *>(nullptr));
857 QCOMPARE(window1->blocked, 0);
858 QCOMPARE(window2->blocked, 0);
859 QCOMPARE(windowModalWindow1->blocked, 0);
860 QCOMPARE(windowModalWindow2->blocked, 0);
861 QCOMPARE(applicationModalWindow1->blocked, 0);
862
863 window2->hide();
864 window1->hide();
865}
866
867void tst_QGuiApplication::quitOnLastWindowClosed()
868{
869 int argc = 0;
870 QGuiApplication app(argc, nullptr);
871 const QRect screenGeometry = QGuiApplication::primaryScreen()->availableVirtualGeometry();
872
873 QTimer timer;
874 timer.setInterval(100);
875
876 QSignalSpy spyAboutToQuit(&app, &QCoreApplication::aboutToQuit);
877 QSignalSpy spyTimeout(&timer, &QTimer::timeout);
878
879 QWindow mainWindow;
880 mainWindow.setTitle(QStringLiteral("quitOnLastWindowClosedMainWindow"));
881 mainWindow.resize(w: windowSize, h: windowSize);
882 mainWindow.setFramePosition(QPoint(screenGeometry.left() + spacing, screenGeometry.top() + spacing));
883
884 QWindow dialog;
885 dialog.setTransientParent(&mainWindow);
886 dialog.setTitle(QStringLiteral("quitOnLastWindowClosedDialog"));
887 dialog.resize(w: windowSize, h: windowSize);
888 dialog.setFramePosition(QPoint(screenGeometry.left() + 2 * spacing + windowSize, screenGeometry.top() + spacing));
889
890 QVERIFY(app.quitOnLastWindowClosed());
891
892 mainWindow.show();
893 dialog.show();
894 QVERIFY(QTest::qWaitForWindowExposed(&dialog));
895
896 timer.start();
897 QTimer::singleShot(interval: 1000, receiver: &mainWindow, slot: &QWindow::close); // This should quit the application
898 QTimer::singleShot(interval: 2000, context: &app, slot: QCoreApplication::quit); // This makes sure we quit even if it didn't
899
900 app.exec();
901
902 QCOMPARE(spyAboutToQuit.count(), 1);
903 // Should be around 10 if closing caused the quit
904 QVERIFY2(spyTimeout.count() < 15, QByteArray::number(spyTimeout.count()).constData());
905}
906
907void tst_QGuiApplication::quitOnLastWindowClosedMulti()
908{
909 int argc = 0;
910 QGuiApplication app(argc, nullptr);
911 const QRect screenGeometry = QGuiApplication::primaryScreen()->availableVirtualGeometry();
912
913 QTimer timer;
914 timer.setInterval(100);
915
916 QSignalSpy spyAboutToQuit(&app, &QCoreApplication::aboutToQuit);
917 QSignalSpy spyTimeout(&timer, &QTimer::timeout);
918
919 QWindow mainWindow;
920 mainWindow.setTitle(QStringLiteral("quitOnLastWindowClosedMultiMainWindow"));
921 mainWindow.resize(w: windowSize, h: windowSize);
922 mainWindow.setFramePosition(QPoint(screenGeometry.left() + spacing, screenGeometry.top() + spacing));
923
924 QWindow dialog;
925 dialog.setTitle(QStringLiteral("quitOnLastWindowClosedMultiDialog"));
926 dialog.resize(w: windowSize, h: windowSize);
927 dialog.setFramePosition(QPoint(screenGeometry.left() + 2 * spacing + windowSize, screenGeometry.top() + spacing));
928
929 QVERIFY(!dialog.transientParent());
930 QVERIFY(app.quitOnLastWindowClosed());
931
932 mainWindow.show();
933 dialog.show();
934 QVERIFY(QTest::qWaitForWindowExposed(&dialog));
935
936 timer.start();
937 QTimer::singleShot(interval: 1000, receiver: &mainWindow, slot: &QWindow::close); // This should not quit the application
938 QTimer::singleShot(interval: 2000, context: &app, slot: &QCoreApplication::quit);
939
940 app.exec();
941
942 QCOMPARE(spyAboutToQuit.count(), 1);
943 // Should be around 20 if closing did not cause the quit
944 QVERIFY2(spyTimeout.count() > 15, QByteArray::number(spyTimeout.count()).constData());
945}
946
947void tst_QGuiApplication::dontQuitOnLastWindowClosed()
948{
949 int argc = 0;
950 QGuiApplication app(argc, nullptr);
951 app.setQuitOnLastWindowClosed(false);
952
953 QTimer timer;
954 timer.setInterval(2000);
955 timer.setSingleShot(true);
956 QObject::connect(sender: &timer, signal: &QTimer::timeout, context: &app, slot: &QCoreApplication::quit);
957
958 QSignalSpy spyLastWindowClosed(&app, &QGuiApplication::lastWindowClosed);
959 QSignalSpy spyTimeout(&timer, &QTimer::timeout);
960
961 QScopedPointer<QWindow> mainWindow(new QWindow);
962
963 mainWindow->show();
964
965 QTimer::singleShot(interval: 1000, receiver: mainWindow.data(), slot: &QWindow::close); // This should not quit the application
966 timer.start();
967
968 app.exec();
969
970 app.setQuitOnLastWindowClosed(true); // restore underlying static to default value
971
972 QCOMPARE(spyTimeout.count(), 1); // quit timer fired
973 QCOMPARE(spyLastWindowClosed.count(), 1); // lastWindowClosed emitted
974}
975
976static Qt::ScreenOrientation testOrientationToSend = Qt::PrimaryOrientation;
977
978class TestPlugin : public QObject
979{
980 Q_OBJECT
981public:
982 TestPlugin()
983 {
984 QScreen* screen = QGuiApplication::primaryScreen();
985 // Make sure the orientation we want to send doesn't get filtered out.
986 screen->setOrientationUpdateMask(screen->orientationUpdateMask() | testOrientationToSend);
987 QWindowSystemInterface::handleScreenOrientationChange(screen, newOrientation: testOrientationToSend);
988 }
989};
990
991class TestPluginFactory : public QGenericPlugin
992{
993 Q_OBJECT
994 Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QGenericPluginFactoryInterface" FILE "testplugin.json")
995public:
996 QObject* create(const QString &key, const QString &)
997 {
998 if (key == "testplugin")
999 return new TestPlugin;
1000 return nullptr;
1001 }
1002};
1003
1004class TestEventReceiver : public QObject
1005{
1006 Q_OBJECT
1007public:
1008 int customEvents;
1009
1010 TestEventReceiver()
1011 : customEvents(0)
1012 {}
1013
1014 virtual void customEvent(QEvent *)
1015 {
1016 customEvents++;
1017 }
1018};
1019
1020#include "tst_qguiapplication.moc"
1021
1022void tst_QGuiApplication::genericPluginsAndWindowSystemEvents()
1023{
1024 testOrientationToSend = Qt::InvertedLandscapeOrientation;
1025
1026 TestEventReceiver testReceiver;
1027 QCoreApplication::postEvent(receiver: &testReceiver, event: new QEvent(QEvent::User));
1028 QCOMPARE(testReceiver.customEvents, 0);
1029
1030#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
1031 QStaticPlugin testPluginInfo(qt_plugin_instance, qt_plugin_query_metadata);
1032#else
1033 QStaticPlugin testPluginInfo;
1034 testPluginInfo.instance = qt_plugin_instance;
1035 testPluginInfo.rawMetaData = qt_plugin_query_metadata;
1036#endif
1037 qRegisterStaticPluginFunction(staticPlugin: testPluginInfo);
1038 int argc = 3;
1039 char *argv[] = { const_cast<char*>(QTest::currentAppName()), const_cast<char*>("-plugin"), const_cast<char*>("testplugin") };
1040 QGuiApplication app(argc, argv);
1041
1042 QVERIFY(QGuiApplication::primaryScreen());
1043 QCOMPARE(QGuiApplication::primaryScreen()->orientation(), testOrientationToSend);
1044
1045 QCOMPARE(testReceiver.customEvents, 0);
1046 QCoreApplication::sendPostedEvents(receiver: &testReceiver);
1047 QCOMPARE(testReceiver.customEvents, 1);
1048}
1049
1050Q_DECLARE_METATYPE(Qt::LayoutDirection)
1051void tst_QGuiApplication::layoutDirection()
1052{
1053 qRegisterMetaType<Qt::LayoutDirection>();
1054
1055 Qt::LayoutDirection oldDirection = QGuiApplication::layoutDirection();
1056 Qt::LayoutDirection newDirection = oldDirection == Qt::LeftToRight ? Qt::RightToLeft : Qt::LeftToRight;
1057
1058 QGuiApplication::setLayoutDirection(newDirection);
1059 QCOMPARE(QGuiApplication::layoutDirection(), newDirection);
1060
1061 int argc = 1;
1062 char *argv[] = { const_cast<char*>("tst_qguiapplication") };
1063 QGuiApplication app(argc, argv);
1064 QSignalSpy signalSpy(&app, SIGNAL(layoutDirectionChanged(Qt::LayoutDirection)));
1065
1066 QGuiApplication::setLayoutDirection(oldDirection);
1067 QCOMPARE(QGuiApplication::layoutDirection(), oldDirection);
1068 QCOMPARE(signalSpy.count(), 1);
1069 QCOMPARE(signalSpy.at(0).at(0).toInt(), static_cast<int>(oldDirection));
1070
1071 QGuiApplication::setLayoutDirection(oldDirection);
1072 QCOMPARE(QGuiApplication::layoutDirection(), oldDirection);
1073 QCOMPARE(signalSpy.count(), 1);
1074}
1075
1076void tst_QGuiApplication::globalShareContext()
1077{
1078#ifndef QT_NO_OPENGL
1079 // Test that there is a global share context when requested.
1080 QCoreApplication::setAttribute(attribute: Qt::AA_ShareOpenGLContexts);
1081 int argc = 1;
1082 char *argv[] = { const_cast<char*>("tst_qguiapplication") };
1083 QScopedPointer<QGuiApplication> app(new QGuiApplication(argc, argv));
1084 QOpenGLContext *ctx = qt_gl_global_share_context();
1085 QVERIFY(ctx);
1086 app.reset();
1087 ctx = qt_gl_global_share_context();
1088 QVERIFY(!ctx);
1089
1090 // Test that there is no global share context by default.
1091 QCoreApplication::setAttribute(attribute: Qt::AA_ShareOpenGLContexts, on: false);
1092 app.reset(other: new QGuiApplication(argc, argv));
1093 ctx = qt_gl_global_share_context();
1094 QVERIFY(!ctx);
1095#else
1096 QSKIP("No OpenGL support");
1097#endif
1098}
1099
1100void tst_QGuiApplication::testSetPaletteAttribute()
1101{
1102 QCoreApplication::setAttribute(attribute: Qt::AA_SetPalette, on: false);
1103 int argc = 1;
1104 char *argv[] = { const_cast<char*>("tst_qguiapplication") };
1105
1106 QGuiApplication app(argc, argv);
1107
1108 QVERIFY(!QCoreApplication::testAttribute(Qt::AA_SetPalette));
1109 QPalette palette;
1110 palette.setColor(acr: QPalette::WindowText, acolor: Qt::red);
1111 QGuiApplication::setPalette(palette);
1112
1113 QVERIFY(QCoreApplication::testAttribute(Qt::AA_SetPalette));
1114
1115 QGuiApplication::setPalette(QPalette());
1116 QVERIFY(!QCoreApplication::testAttribute(Qt::AA_SetPalette));
1117}
1118
1119// Test that static functions do not crash if there is no application instance.
1120void tst_QGuiApplication::staticFunctions()
1121{
1122 QGuiApplication::setApplicationDisplayName(QString());
1123 QGuiApplication::applicationDisplayName();
1124 QGuiApplication::allWindows();
1125 QGuiApplication::topLevelWindows();
1126 QGuiApplication::topLevelAt(pos: QPoint(0, 0));
1127 QGuiApplication::setWindowIcon(QIcon());
1128 QGuiApplication::windowIcon();
1129 QGuiApplication::platformName();
1130 QGuiApplication::modalWindow();
1131 QGuiApplication::focusWindow();
1132 QGuiApplication::focusObject();
1133 QGuiApplication::primaryScreen();
1134 QGuiApplication::screens();
1135 QGuiApplication::overrideCursor();
1136 QGuiApplication::setOverrideCursor(QCursor());
1137 QGuiApplication::changeOverrideCursor(QCursor());
1138 QGuiApplication::restoreOverrideCursor();
1139 QGuiApplication::keyboardModifiers();
1140 QGuiApplication::queryKeyboardModifiers();
1141 QGuiApplication::mouseButtons();
1142 QGuiApplication::setLayoutDirection(Qt::LeftToRight);
1143 QGuiApplication::layoutDirection();
1144 QGuiApplication::styleHints();
1145 QGuiApplication::setDesktopSettingsAware(true);
1146 QGuiApplication::desktopSettingsAware();
1147 QGuiApplication::inputMethod();
1148 QGuiApplication::platformNativeInterface();
1149 QGuiApplication::platformFunction(QByteArrayLiteral("bla"));
1150 QGuiApplication::setQuitOnLastWindowClosed(true);
1151 QGuiApplication::quitOnLastWindowClosed();
1152 QGuiApplication::applicationState();
1153
1154 QPixmap::defaultDepth();
1155}
1156
1157void tst_QGuiApplication::settableStyleHints_data()
1158{
1159 QTest::addColumn<bool>(name: "appInstance");
1160 QTest::newRow(dataTag: "app") << true;
1161 QTest::newRow(dataTag: "no-app") << false;
1162}
1163
1164void tst_QGuiApplication::settableStyleHints()
1165{
1166 QFETCH(bool, appInstance);
1167 int argc = 0;
1168 QScopedPointer<QGuiApplication> app;
1169 if (appInstance)
1170 app.reset(other: new QGuiApplication(argc, nullptr));
1171
1172 const int keyboardInputInterval = 555;
1173 QGuiApplication::styleHints()->setKeyboardInputInterval(keyboardInputInterval);
1174 QCOMPARE(QGuiApplication::styleHints()->keyboardInputInterval(), keyboardInputInterval);
1175}
1176
1177QTEST_APPLESS_MAIN(tst_QGuiApplication)
1178

source code of qtbase/tests/auto/gui/kernel/qguiapplication/tst_qguiapplication.cpp