Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qguiapplication.cpp
Go to the documentation of this file.
1// Copyright (C) 2021 The Qt Company Ltd.
2// Copyright (C) 2016 Intel Corporation.
3// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
4// Qt-Security score:significant reason:default
5
7
8#include "private/qguiapplication_p.h"
9#include "private/qabstractfileiconprovider_p.h"
10#include <qpa/qplatformintegrationfactory_p.h>
11#include "private/qevent_p.h"
12#include "private/qeventpoint_p.h"
13#include "private/qiconloader_p.h"
14#include "qfont.h"
16#include <qpa/qplatformfontdatabase.h>
17#include <qpa/qplatformwindow.h>
18#include <qpa/qplatformnativeinterface.h>
19#include <qpa/qplatformtheme.h>
20#include <qpa/qplatformintegration.h>
21#include <qpa/qplatformkeymapper.h>
22
23#include <QtCore/QAbstractEventDispatcher>
24#include <QtCore/QFileInfo>
25#include <QtCore/QStandardPaths>
26#include <QtCore/QVariant>
27#include <QtCore/private/qcoreapplication_p.h>
28#include <QtCore/private/qabstracteventdispatcher_p.h>
29#include <QtCore/private/qminimalflatset_p.h>
30#include <QtCore/qmutex.h>
31#include <QtCore/private/qthread_p.h>
32#include <QtCore/private/qlocking_p.h>
33#include <QtCore/private/qflatmap_p.h>
34#include <QtCore/qdir.h>
35#include <QtCore/qlibraryinfo.h>
36#include <QtCore/private/qnumeric_p.h>
37#include <QtDebug>
38#if QT_CONFIG(accessibility)
39#include "qaccessible.h"
40#include <QtGui/private/qaccessiblewindow_p.h>
41#endif
42#include <qpalette.h>
43#include <qscreen.h>
45#include <private/qcolortrclut_p.h>
46#include <private/qscreen_p.h>
47
48#include <QtGui/qgenericpluginfactory.h>
49#include <QtGui/qstylehints.h>
50#include <QtGui/private/qstylehints_p.h>
51#include <QtGui/qinputmethod.h>
52#include <QtGui/qpixmapcache.h>
53#include <qpa/qplatforminputcontext.h>
54#include <qpa/qplatforminputcontext_p.h>
55
56#include <qpa/qwindowsysteminterface.h>
57#include <qpa/qwindowsysteminterface_p.h>
58#include "private/qwindow_p.h"
59#include "private/qicon_p.h"
60#include "private/qcursor_p.h"
61#if QT_CONFIG(opengl)
62# include "private/qopenglcontext_p.h"
63#endif
64#include "private/qinputdevicemanager_p.h"
65#include "private/qinputmethod_p.h"
66#include "private/qpointingdevice_p.h"
67
68#include <qpa/qplatformthemefactory_p.h>
69
70#if QT_CONFIG(draganddrop)
71#include <qpa/qplatformdrag.h>
72#include <private/qdnd_p.h>
73#endif
74
75#ifndef QT_NO_CURSOR
76#include <qpa/qplatformcursor.h>
77#endif
78
79#include <QtGui/QPixmap>
80
81#ifndef QT_NO_CLIPBOARD
82#include <QtGui/QClipboard>
83#endif
84
85#if QT_CONFIG(library)
86#include <QtCore/QLibrary>
87#endif
88
89#if defined(Q_OS_APPLE)
90# include "private/qcore_mac_p.h"
91#elif defined(Q_OS_WIN)
92# include <QtCore/qt_windows.h>
93# include <QtCore/QLibraryInfo>
94#endif // Q_OS_WIN
95
96#ifdef Q_OS_WASM
97#include <emscripten.h>
98#endif
99
100#if QT_CONFIG(vulkan)
101#include <private/qvulkandefaultinstance_p.h>
102#endif
103
104#if QT_CONFIG(thread)
105#include <QtCore/QThreadPool>
106#endif
107
108#include <qtgui_tracepoints_p.h>
109
110#include <private/qtools_p.h>
111
112#include <limits>
113
115
116Q_LOGGING_CATEGORY(lcPopup, "qt.gui.popup");
117Q_LOGGING_CATEGORY(lcVirtualKeyboard, "qt.gui.virtualkeyboard");
118
119using namespace Qt::StringLiterals;
120using namespace QtMiscUtils;
121
122// Helper macro for static functions to check on the existence of the application class.
123#define CHECK_QAPP_INSTANCE(...)
124 if (Q_LIKELY(QCoreApplication::instance())) {
125 } else {
126 qWarning("Must construct a QGuiApplication first.");
127 return __VA_ARGS__;
128 }
129
132
133Q_CONSTINIT Qt::MouseButtons QGuiApplicationPrivate::mouse_buttons = Qt::NoButton;
134Q_CONSTINIT Qt::KeyboardModifiers QGuiApplicationPrivate::modifier_buttons = Qt::NoModifier;
135
136Q_CONSTINIT QGuiApplicationPrivate::QLastCursorPosition QGuiApplicationPrivate::lastCursorPosition;
137
138Q_CONSTINIT QWindow *QGuiApplicationPrivate::currentMouseWindow = nullptr;
139
140Q_CONSTINIT QString QGuiApplicationPrivate::styleOverride;
141
142Q_CONSTINIT Qt::ApplicationState QGuiApplicationPrivate::applicationState = Qt::ApplicationInactive;
143
144Q_CONSTINIT Qt::HighDpiScaleFactorRoundingPolicy QGuiApplicationPrivate::highDpiScaleFactorRoundingPolicy =
145 Qt::HighDpiScaleFactorRoundingPolicy::PassThrough;
146
147Q_CONSTINIT QPointer<QWindow> QGuiApplicationPrivate::currentDragWindow;
148
149Q_CONSTINIT QList<QGuiApplicationPrivate::TabletPointData> QGuiApplicationPrivate::tabletDevicePoints; // TODO remove
150
151Q_CONSTINIT QPlatformIntegration *QGuiApplicationPrivate::platform_integration = nullptr;
152Q_CONSTINIT QPlatformTheme *QGuiApplicationPrivate::platform_theme = nullptr;
153
154Q_CONSTINIT QList<QObject *> QGuiApplicationPrivate::generic_plugin_list;
155
160
162
163Q_CONSTINIT QIcon *QGuiApplicationPrivate::app_icon = nullptr;
164
165Q_CONSTINIT QString *QGuiApplicationPrivate::platform_name = nullptr;
166Q_CONSTINIT QString *QGuiApplicationPrivate::displayName = nullptr;
167Q_CONSTINIT QString *QGuiApplicationPrivate::desktopFileName = nullptr;
168
169Q_CONSTINIT QPalette *QGuiApplicationPrivate::app_pal = nullptr; // default application palette
170
171Q_CONSTINIT Qt::MouseButton QGuiApplicationPrivate::mousePressButton = Qt::NoButton;
172
175
176Q_CONSTINIT QWindow *QGuiApplicationPrivate::currentMousePressWindow = nullptr;
177
178Q_CONSTINIT static Qt::LayoutDirection layout_direction = Qt::LayoutDirectionAuto;
179Q_CONSTINIT static Qt::LayoutDirection effective_layout_direction = Qt::LeftToRight;
180Q_CONSTINIT static bool force_reverse = false;
181
182Q_DECL_DEPRECATED_X("Use QGuiApplicationPrivate::instance() instead")
183Q_CONSTINIT QGuiApplicationPrivate *QGuiApplicationPrivate::self = nullptr;
184
185Q_CONSTINIT int QGuiApplicationPrivate::m_fakeMouseSourcePointId = -1;
186
187#ifndef QT_NO_CLIPBOARD
188Q_CONSTINIT QClipboard *QGuiApplicationPrivate::qt_clipboard = nullptr;
189#endif
190
191Q_CONSTINIT QList<QScreen *> QGuiApplicationPrivate::screen_list;
192
193Q_CONSTINIT QWindowList QGuiApplicationPrivate::window_list;
194Q_CONSTINIT QWindowList QGuiApplicationPrivate::popup_list;
195Q_CONSTINIT const QWindow *QGuiApplicationPrivate::active_popup_on_press = nullptr;
196Q_CONSTINIT QWindow *QGuiApplicationPrivate::focus_window = nullptr;
197
198Q_CONSTINIT static QBasicMutex applicationFontMutex;
199Q_CONSTINIT QFont *QGuiApplicationPrivate::app_font = nullptr;
200Q_CONSTINIT QStyleHints *QGuiApplicationPrivate::styleHints = nullptr;
201Q_CONSTINIT bool QGuiApplicationPrivate::obey_desktop_settings = true;
202Q_CONSTINIT bool QGuiApplicationPrivate::popup_closed_on_press = false;
203
204Q_CONSTINIT QInputDeviceManager *QGuiApplicationPrivate::m_inputDeviceManager = nullptr;
205
206Q_CONSTINIT qreal QGuiApplicationPrivate::m_maxDevicePixelRatio = 0.0;
207Q_CONSTINIT QBasicAtomicInt QGuiApplicationPrivate::m_primaryScreenDpis = Q_BASIC_ATOMIC_INITIALIZER(0);
208
209Q_CONSTINIT static qreal fontSmoothingGamma = 1.7;
210
211Q_CONSTINIT bool QGuiApplicationPrivate::quitOnLastWindowClosed = true;
212
213extern void qRegisterGuiVariant();
214#if QT_CONFIG(animation)
215extern void qRegisterGuiGetInterpolator();
216#endif
217
219{
220 return force_reverse ^
221 (QGuiApplication::tr("QT_LAYOUT_DIRECTION",
222 "Translate this string to the string 'LTR' in left-to-right"
223 " languages or to 'RTL' in right-to-left languages (such as Hebrew"
224 " and Arabic) to get proper widget layout.") == "RTL"_L1);
225}
226
227static void initFontUnlocked()
228{
229 if (!QGuiApplicationPrivate::app_font) {
230 if (const QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme())
231 if (const QFont *font = theme->font(QPlatformTheme::SystemFont))
232 QGuiApplicationPrivate::app_font = new QFont(*font);
233 }
234 if (!QGuiApplicationPrivate::app_font)
235 QGuiApplicationPrivate::app_font =
236 new QFont(QGuiApplicationPrivate::platformIntegration()->fontDatabase()->defaultFont());
237}
238
239static inline void clearFontUnlocked()
240{
241 delete QGuiApplicationPrivate::app_font;
242 QGuiApplicationPrivate::app_font = nullptr;
243}
244
245static void initThemeHints()
246{
247 mouseDoubleClickDistance = QGuiApplicationPrivate::platformTheme()->themeHint(QPlatformTheme::MouseDoubleClickDistance).toInt();
248 touchDoubleTapDistance = QGuiApplicationPrivate::platformTheme()->themeHint(QPlatformTheme::TouchDoubleTapDistance).toInt();
249}
250
251#if defined(Q_OS_UNIX) && !defined(Q_OS_DARWIN)
252static bool checkNeedPortalSupport()
253{
254#if QT_CONFIG(dbus)
255 return QFileInfo::exists("/.flatpak-info"_L1) || qEnvironmentVariableIsSet("SNAP");
256#else
257 return false;
258#endif // QT_CONFIG(dbus)
259}
260#endif
261
262// Using aggregate initialization instead of ctor so we can have a POD global static
263#define Q_WINDOW_GEOMETRY_SPECIFICATION_INITIALIZER { Qt::TopLeftCorner, -1, -1, -1, -1 }
264
265// Geometry specification for top level windows following the convention of the
266// -geometry command line arguments in X11 (see XParseGeometry).
268{
269 static QWindowGeometrySpecification fromArgument(const QByteArray &a);
270 void applyTo(QWindow *window) const;
271
275 int width;
277};
278
279// Parse a token of a X11 geometry specification "200x100+10-20".
280static inline int nextGeometryToken(const QByteArray &a, int &pos, char *op)
281{
282 *op = 0;
283 const qsizetype size = a.size();
284 if (pos >= size)
285 return -1;
286
287 *op = a.at(pos);
288 if (*op == '+' || *op == '-' || *op == 'x')
289 pos++;
290 else if (isAsciiDigit(*op))
291 *op = 'x'; // If it starts with a digit, it is supposed to be a width specification.
292 else
293 return -1;
294
295 const int numberPos = pos;
296 for ( ; pos < size && isAsciiDigit(a.at(pos)); ++pos) ;
297
298 bool ok;
299 const int result = a.mid(numberPos, pos - numberPos).toInt(&ok);
300 return ok ? result : -1;
301}
302
304{
306 int pos = 0;
307 for (int i = 0; i < 4; ++i) {
308 char op;
309 const int value = nextGeometryToken(a, pos, &op);
310 if (value < 0)
311 break;
312 switch (op) {
313 case 'x':
314 (result.width >= 0 ? result.height : result.width) = value;
315 break;
316 case '+':
317 case '-':
318 if (result.xOffset >= 0) {
319 result.yOffset = value;
320 if (op == '-')
321 result.corner = result.corner == Qt::TopRightCorner ? Qt::BottomRightCorner : Qt::BottomLeftCorner;
322 } else {
323 result.xOffset = value;
324 if (op == '-')
325 result.corner = Qt::TopRightCorner;
326 }
327 }
328 }
329 return result;
330}
331
332void QWindowGeometrySpecification::applyTo(QWindow *window) const
333{
334 QRect windowGeometry = window->frameGeometry();
335 QSize size = windowGeometry.size();
336 if (width >= 0 || height >= 0) {
337 const QSize windowMinimumSize = window->minimumSize();
338 const QSize windowMaximumSize = window->maximumSize();
339 if (width >= 0)
340 size.setWidth(qBound(windowMinimumSize.width(), width, windowMaximumSize.width()));
341 if (height >= 0)
342 size.setHeight(qBound(windowMinimumSize.height(), height, windowMaximumSize.height()));
343 window->resize(size);
344 }
345 if (xOffset >= 0 || yOffset >= 0) {
346 const QRect availableGeometry = window->screen()->virtualGeometry();
347 QPoint topLeft = windowGeometry.topLeft();
348 if (xOffset >= 0) {
349 topLeft.setX(corner == Qt::TopLeftCorner || corner == Qt::BottomLeftCorner ?
350 xOffset :
351 qMax(availableGeometry.right() - size.width() - xOffset, availableGeometry.left()));
352 }
353 if (yOffset >= 0) {
354 topLeft.setY(corner == Qt::TopLeftCorner || corner == Qt::TopRightCorner ?
355 yOffset :
356 qMax(availableGeometry.bottom() - size.height() - yOffset, availableGeometry.top()));
357 }
358 window->setFramePosition(topLeft);
359 }
360}
361
363
364/*!
365 \macro qGuiApp
366 \relates QGuiApplication
367
368 A global pointer referring to the unique application object.
369 Only valid for use when that object is a QGuiApplication.
370
371 \sa QCoreApplication::instance(), qApp
372*/
373
374/*!
375 \class QGuiApplication
376 \brief The QGuiApplication class manages the GUI application's control
377 flow and main settings.
378
379 \inmodule QtGui
380 \since 5.0
381
382 QGuiApplication contains the main event loop, where all events from the window
383 system and other sources are processed and dispatched. It also handles the
384 application's initialization and finalization, and provides session management.
385 In addition, QGuiApplication handles most of the system-wide and application-wide
386 settings.
387
388 For any GUI application using Qt, there is precisely \b one QGuiApplication
389 object no matter whether the application has 0, 1, 2 or more windows at
390 any given time. For non-GUI Qt applications, use QCoreApplication instead,
391 as it does not depend on the Qt GUI module. For QWidget based Qt applications,
392 use QApplication instead, as it provides some functionality needed for creating
393 QWidget instances.
394
395 The QGuiApplication object is accessible through the instance() function, which
396 returns a pointer equivalent to the global \l qApp pointer.
397
398 QGuiApplication's main areas of responsibility are:
399 \list
400 \li It initializes the application with the user's desktop settings,
401 such as palette(), font() and styleHints(). It keeps
402 track of these properties in case the user changes the desktop
403 globally, for example, through some kind of control panel.
404
405 \li It performs event handling, meaning that it receives events
406 from the underlying window system and dispatches them to the
407 relevant widgets. You can send your own events to windows by
408 using sendEvent() and postEvent().
409
410 \li It parses common command line arguments and sets its internal
411 state accordingly. See the \l{QGuiApplication::QGuiApplication()}
412 {constructor documentation} below for more details.
413
414 \li It provides localization of strings that are visible to the
415 user via translate().
416
417 \li It provides some magical objects like the clipboard().
418
419 \li It knows about the application's windows. You can ask which
420 window is at a certain position using topLevelAt(), get a list of
421 topLevelWindows(), etc.
422
423 \li It manages the application's mouse cursor handling, see
424 setOverrideCursor()
425
426 \li It provides support for sophisticated \l{Session Management}
427 {session management}. This makes it possible for applications
428 to terminate gracefully when the user logs out, to cancel a
429 shutdown process if termination isn't possible and even to
430 preserve the entire application's state for a future session.
431 See isSessionRestored(), sessionId() and commitDataRequest() and
432 saveStateRequest() for details.
433 \endlist
434
435 Since the QGuiApplication object does so much initialization, it \e{must} be
436 created before any other objects related to the user interface are created.
437 QGuiApplication also deals with common command line arguments. Hence, it is
438 usually a good idea to create it \e before any interpretation or
439 modification of \c argv is done in the application itself.
440
441 \table
442 \header
443 \li{2,1} Groups of functions
444
445 \row
446 \li System settings
447 \li desktopSettingsAware(),
448 setDesktopSettingsAware(),
449 styleHints(),
450 palette(),
451 setPalette(),
452 font(),
453 setFont().
454
455 \row
456 \li Event handling
457 \li exec(),
458 processEvents(),
459 exit(),
460 quit().
461 sendEvent(),
462 postEvent(),
463 sendPostedEvents(),
464 removePostedEvents(),
465 notify().
466
467 \row
468 \li Windows
469 \li allWindows(),
470 topLevelWindows(),
471 focusWindow(),
472 clipboard(),
473 topLevelAt().
474
475 \row
476 \li Advanced cursor handling
477 \li overrideCursor(),
478 setOverrideCursor(),
479 restoreOverrideCursor().
480
481 \row
482 \li Session management
483 \li isSessionRestored(),
484 sessionId(),
485 commitDataRequest(),
486 saveStateRequest().
487
488 \row
489 \li Miscellaneous
490 \li startingUp(),
491 closingDown().
492 \endtable
493
494 \sa QCoreApplication, QAbstractEventDispatcher, QEventLoop
495*/
496
497/*!
498 \class QGuiApplicationPrivate
499 \inmodule QtGui
500 \internal
501*/
502
503/*!
504 Initializes the window system and constructs an application object with
505 \a argc command line arguments in \a argv.
506
507 \warning The data referred to by \a argc and \a argv must stay valid for
508 the entire lifetime of the QGuiApplication object. In addition, \a argc must
509 be greater than zero and \a argv must contain at least one valid character
510 string.
511
512 The global \c qApp pointer refers to this application object. Only one
513 application object should be created.
514
515 This application object must be constructed before any \l{QPaintDevice}
516 {paint devices} (including pixmaps, bitmaps etc.).
517
518 \note \a argc and \a argv might be changed as Qt removes command line
519 arguments that it recognizes.
520
521 \section1 Supported Command Line Options
522
523 All Qt programs automatically support a set of command-line options that
524 allow modifying the way Qt will interact with the windowing system. Some of
525 the options are also accessible via environment variables, which are the
526 preferred form if the application can launch GUI sub-processes or other
527 applications (environment variables will be inherited by child processes).
528 When in doubt, use the environment variables.
529
530 The options currently supported are the following:
531 \list
532
533 \li \c{-platform} \e {platformName[:options]}, specifies the
534 \l{Qt Platform Abstraction} (QPA) plugin.
535
536 Overrides the \c QT_QPA_PLATFORM environment variable.
537 \li \c{-platformpluginpath} \e path, specifies the path to platform
538 plugins.
539
540 Overrides the \c QT_QPA_PLATFORM_PLUGIN_PATH environment variable.
541
542 \li \c{-platformtheme} \e platformTheme, specifies the platform theme.
543
544 Overrides the \c QT_QPA_PLATFORMTHEME environment variable.
545
546 \li \c{-plugin} \e plugin, specifies additional plugins to load. The argument
547 may appear multiple times.
548
549 Concatenated with the plugins in the \c QT_QPA_GENERIC_PLUGINS environment
550 variable.
551
552 \li \c{-qmljsdebugger=}, activates the QML/JS debugger with a specified port.
553 The value must be of format \c{port:1234}\e{[,block]}, where
554 \e block is optional
555 and will make the application wait until a debugger connects to it.
556 \li \c {-qwindowgeometry} \e geometry, specifies window geometry for
557 the main window using the X11-syntax. For example:
558 \c {-qwindowgeometry 100x100+50+50}
559 \li \c {-qwindowicon}, sets the default window icon
560 \li \c {-qwindowtitle}, sets the title of the first window
561 \li \c{-reverse}, sets the application's layout direction to
562 Qt::RightToLeft. This option is intended to aid debugging and should
563 not be used in production. The default value is automatically detected
564 from the user's locale (see also QLocale::textDirection()).
565 \li \c{-session} \e session, restores the application from an earlier
566 \l{Session Management}{session}.
567 \endlist
568
569 The following standard command line options are available for X11:
570
571 \list
572 \li \c {-display} \e {hostname:screen_number}, switches displays on X11.
573
574 Overrides the \c DISPLAY environment variable.
575 \li \c {-geometry} \e geometry, same as \c {-qwindowgeometry}.
576 \endlist
577
578 \section1 Platform-Specific Arguments
579
580 You can specify platform-specific arguments for the \c{-platform} option.
581 Place them after the platform plugin name following a colon as a
582 comma-separated list. For example,
583 \c{-platform windows:dialogs=xp,fontengine=freetype}.
584
585 The following parameters are available for \c {-platform windows}:
586
587 \list
588 \li \c {altgr}, detect the key \c {AltGr} found on some keyboards as
589 Qt::GroupSwitchModifier (since Qt 5.12).
590 \li \c {darkmode=[0|1|2]} controls how Qt responds to the activation
591 of the \e{Dark Mode for applications} introduced in Windows 10
592 1903 (since Qt 5.15).
593
594 A value of 0 disables dark mode support.
595
596 A value of 1 causes Qt to switch the window borders to black
597 when \e{Dark Mode for applications} is activated and no High
598 Contrast Theme is in use. This is intended for applications
599 that implement their own theming.
600
601 A value of 2 will in addition cause the Windows Vista style to
602 be deactivated and switch to the Windows style using a
603 simplified palette in dark mode. This is currently
604 experimental pending the introduction of new style that
605 properly adapts to dark mode.
606
607 As of Qt 6.5, the default value is 2; to disable dark mode
608 support, set the value to 0 or 1.
609
610 \li \c {dialogs=[xp|none]}, \c xp uses XP-style native dialogs and
611 \c none disables them.
612
613 \li \c {fontengine=freetype}, uses the FreeType font engine.
614 \li \c {fontengine=gdi}, uses the legacy GDI-based
615 font database and defaults to using the GDI font
616 engine (which is otherwise only used for some font types
617 or font properties.) (Since Qt 6.8).
618 \li \c {menus=[native|none]}, controls the use of native menus.
619
620 Native menus are implemented using Win32 API and are simpler than
621 QMenu-based menus in for example that they do allow for placing
622 widgets on them or changing properties like fonts and do not
623 provide hover signals. They are mainly intended for Qt Quick.
624 By default, they will be used if the application is not an
625 instance of QApplication or for Qt Quick Controls 2
626 applications (since Qt 5.10).
627
628 \li \c {nocolorfonts} Turn off DirectWrite Color fonts
629 (since Qt 5.8).
630
631 \li \c {nodirectwrite} Turn off DirectWrite fonts (since Qt 5.8). This implicitly
632 also selects the GDI font engine.
633
634 \li \c {nomousefromtouch} Ignores mouse events synthesized
635 from touch events by the operating system.
636
637 \li \c {nowmpointer} Switches from Pointer Input Messages handling
638 to legacy mouse handling (since Qt 5.12).
639 \li \c {reverse} Activates Right-to-left mode (experimental).
640 Windows title bars will be shown accordingly in Right-to-left locales
641 (since Qt 5.13).
642 \li \c {tabletabsoluterange=<value>} Sets a value for mouse mode detection
643 of WinTab tablets (Legacy, since Qt 5.3).
644 \endlist
645
646 The following parameter is available for \c {-platform cocoa} (on macOS):
647
648 \list
649 \li \c {fontengine=freetype}, uses the FreeType font engine.
650 \endlist
651
652 For more information about the platform-specific arguments available for
653 embedded Linux platforms, see \l{Qt for Embedded Linux}.
654
655 \sa arguments(), QGuiApplication::platformName
656*/
657#ifdef Q_QDOC
658QGuiApplication::QGuiApplication(int &argc, char **argv)
659#else
660QGuiApplication::QGuiApplication(int &argc, char **argv, int)
661#endif
662 : QCoreApplication(*new QGuiApplicationPrivate(argc, argv))
663{
664 d_func()->init();
665
666 QCoreApplicationPrivate::eventDispatcher->startingUp();
667}
668
669/*!
670 \internal
671*/
672QGuiApplication::QGuiApplication(QGuiApplicationPrivate &p)
673 : QCoreApplication(p)
674{
675}
676
677/*!
678 Destructs the application.
679*/
680QGuiApplication::~QGuiApplication()
681{
682 Q_D(QGuiApplication);
683
684 qt_call_post_routines();
685
686 d->eventDispatcher->closingDown();
687 d->eventDispatcher = nullptr;
688
689#ifndef QT_NO_CLIPBOARD
690 delete QGuiApplicationPrivate::qt_clipboard;
691 QGuiApplicationPrivate::qt_clipboard = nullptr;
692#endif
693
694#ifndef QT_NO_SESSIONMANAGER
695 delete d->session_manager;
696 d->session_manager = nullptr;
697#endif //QT_NO_SESSIONMANAGER
698
699 QGuiApplicationPrivate::clearPalette();
700 QFontDatabase::removeAllApplicationFonts();
701
702#ifndef QT_NO_CURSOR
703 d->cursor_list.clear();
704#endif
705
706#if QT_CONFIG(qtgui_threadpool)
707 // Synchronize and stop the gui thread pool threads.
708 QThreadPool *guiThreadPool = nullptr;
709 QT_TRY {
710 guiThreadPool = QGuiApplicationPrivate::qtGuiThreadPool();
711 } QT_CATCH (...) {
712 // swallow the exception, since destructors shouldn't throw
713 }
714 if (guiThreadPool) {
715 guiThreadPool->waitForDone();
716 delete guiThreadPool;
717 }
718#endif
719
720 delete QGuiApplicationPrivate::app_icon;
721 QGuiApplicationPrivate::app_icon = nullptr;
722 delete QGuiApplicationPrivate::platform_name;
723 QGuiApplicationPrivate::platform_name = nullptr;
724 delete QGuiApplicationPrivate::displayName;
725 QGuiApplicationPrivate::displayName = nullptr;
726 delete QGuiApplicationPrivate::m_inputDeviceManager;
727 QGuiApplicationPrivate::m_inputDeviceManager = nullptr;
728 delete QGuiApplicationPrivate::desktopFileName;
729 QGuiApplicationPrivate::desktopFileName = nullptr;
730 QGuiApplicationPrivate::mouse_buttons = Qt::NoButton;
731 QGuiApplicationPrivate::modifier_buttons = Qt::NoModifier;
732 QGuiApplicationPrivate::lastCursorPosition.reset();
733 QGuiApplicationPrivate::currentMousePressWindow = QGuiApplicationPrivate::currentMouseWindow = nullptr;
734 QGuiApplicationPrivate::applicationState = Qt::ApplicationInactive;
735 QGuiApplicationPrivate::highDpiScaleFactorRoundingPolicy = Qt::HighDpiScaleFactorRoundingPolicy::PassThrough;
736 QGuiApplicationPrivate::currentDragWindow = nullptr;
737 QGuiApplicationPrivate::tabletDevicePoints.clear();
738 QGuiApplicationPrivate::m_primaryScreenDpis.storeRelaxed(0);
739}
740
741QGuiApplicationPrivate::QGuiApplicationPrivate(int &argc, char **argv)
742 : QCoreApplicationPrivate(argc, argv),
743 inputMethod(nullptr),
744 lastTouchType(QEvent::TouchEnd)
745{
746 // Note: Not same as QCoreApplication::self
747 QT_IGNORE_DEPRECATIONS(QGuiApplicationPrivate::self = this;)
748
749 application_type = QCoreApplicationPrivate::Gui;
750#ifndef QT_NO_SESSIONMANAGER
751 is_session_restored = false;
752 is_saving_session = false;
753#endif
754}
755
756/*!
757 \property QGuiApplication::applicationDisplayName
758 \brief the user-visible name of this application
759 \since 5.0
760
761 This name is shown to the user, for instance in window titles.
762 It can be translated, if necessary.
763
764 If not set, the application display name defaults to the application name.
765
766 \sa applicationName
767*/
768void QGuiApplication::setApplicationDisplayName(const QString &name)
769{
770 if (!QGuiApplicationPrivate::displayName) {
771 QGuiApplicationPrivate::displayName = new QString(name);
772 if (qGuiApp) {
773 disconnect(qGuiApp, &QGuiApplication::applicationNameChanged,
774 qGuiApp, &QGuiApplication::applicationDisplayNameChanged);
775
776 if (*QGuiApplicationPrivate::displayName != applicationName())
777 emit qGuiApp->applicationDisplayNameChanged();
778 }
779 } else if (name != *QGuiApplicationPrivate::displayName) {
780 *QGuiApplicationPrivate::displayName = name;
781 if (qGuiApp)
782 emit qGuiApp->applicationDisplayNameChanged();
783 }
784}
785
786QString QGuiApplication::applicationDisplayName()
787{
788 return QGuiApplicationPrivate::displayName ? *QGuiApplicationPrivate::displayName : applicationName();
789}
790
791/*!
792 \property QGuiApplication::badgeNumber
793 \brief the number shown in the application's badge
794
795 Useful for providing feedback to the user about the number
796 of unread messages or similar.
797
798 The badge will be overlaid on the application's icon in the Dock
799 on \macos, the home screen icon on iOS, or the task bar on Windows
800 and Linux.
801
802 If the number is outside the range supported by the platform, the
803 number will be clamped to the supported range. If the number does
804 not fit within the badge, the number may be visually elided.
805
806 Setting the number to 0 will clear the badge. The default value is 0.
807
808 \since 6.5
809 \sa applicationName, applicationProgress
810*/
811qint64 QGuiApplication::badgeNumber() const
812{
813 Q_D(const QGuiApplication);
814 return d->badgeNumber;
815}
816
817void QGuiApplication::setBadgeNumber(qint64 number)
818{
819 Q_D(QGuiApplication);
820 // Always forward to the platform, even if unchanged, as some platforms
821 // (e.g. iOS) persist the badge across launches, and applications rely
822 // on setBadgeNumber(0) to clear a stale badge.
823 QGuiApplicationPrivate::platformIntegration()->setApplicationBadge(number);
824 if (d->badgeNumber == number)
825 return;
826 d->badgeNumber = number;
827 emit badgeNumberChanged(number);
828}
829
830/*!
831 \property QGuiApplication::desktopFileName
832 \brief the base name of the desktop entry for this application
833 \since 5.7
834
835 This is the file name, without the full path or the trailing ".desktop"
836 extension of the desktop entry that represents this application
837 according to the freedesktop desktop entry specification.
838
839 This property gives a precise indication of what desktop entry represents
840 the application and it is needed by the windowing system to retrieve
841 such information without resorting to imprecise heuristics.
842
843 The latest version of the freedesktop desktop entry specification can be obtained
844 \l{http://standards.freedesktop.org/desktop-entry-spec/latest/}{here}.
845*/
846void QGuiApplication::setDesktopFileName(const QString &name)
847{
848 if (!QGuiApplicationPrivate::desktopFileName)
849 QGuiApplicationPrivate::desktopFileName = new QString;
850 *QGuiApplicationPrivate::desktopFileName = name;
851 if (name.endsWith(QLatin1String(".desktop"))) { // ### Qt 7: remove
852 const QString filePath = QStandardPaths::locate(QStandardPaths::ApplicationsLocation, name);
853 if (!filePath.isEmpty()) {
854 qWarning("QGuiApplication::setDesktopFileName: the specified desktop file name "
855 "ends with .desktop. For compatibility reasons, the .desktop suffix will "
856 "be removed. Please specify a desktop file name without .desktop suffix");
857 (*QGuiApplicationPrivate::desktopFileName).chop(8);
858 }
859 }
860}
861
862QString QGuiApplication::desktopFileName()
863{
864 return QGuiApplicationPrivate::desktopFileName ? *QGuiApplicationPrivate::desktopFileName : QString();
865}
866
867/*!
868 Returns the most recently shown modal window. If no modal windows are
869 visible, this function returns zero.
870
871 A modal window is a window which has its
872 \l{QWindow::modality}{modality} property set to Qt::WindowModal
873 or Qt::ApplicationModal. A modal window must be closed before the user can
874 continue with other parts of the program.
875
876 Modal window are organized in a stack. This function returns the modal
877 window at the top of the stack.
878
879 \sa Qt::WindowModality, QWindow::setModality()
880*/
881QWindow *QGuiApplication::modalWindow()
882{
883 CHECK_QAPP_INSTANCE(nullptr)
884 const auto &modalWindows = QGuiApplicationPrivate::instance()->modalWindowList;
885 if (modalWindows.isEmpty())
886 return nullptr;
887 return modalWindows.constFirst();
888}
889
890static void updateBlockedStatusRecursion(QWindow *window, bool shouldBeBlocked)
891{
892 QWindowPrivate *p = qt_window_private(window);
893 if (p->blockedByModalWindow != shouldBeBlocked) {
894 p->blockedByModalWindow = shouldBeBlocked;
895 QEvent e(shouldBeBlocked ? QEvent::WindowBlocked : QEvent::WindowUnblocked);
896 QGuiApplication::sendEvent(window, &e);
897 for (QObject *c : window->children()) {
898 if (c->isWindowType())
899 updateBlockedStatusRecursion(static_cast<QWindow *>(c), shouldBeBlocked);
900 }
901 }
902}
903
904void QGuiApplicationPrivate::updateBlockedStatus(QWindow *window)
905{
906 bool shouldBeBlocked = false;
907 const bool popupType = (window->type() == Qt::ToolTip) || (window->type() == Qt::Popup);
908 if (!popupType && !QGuiApplicationPrivate::instance()->modalWindowList.isEmpty())
909 shouldBeBlocked = QGuiApplicationPrivate::instance()->isWindowBlocked(window);
910 updateBlockedStatusRecursion(window, shouldBeBlocked);
911}
912
913// Return whether the window needs to be notified about window blocked events.
914// As opposed to QGuiApplication::topLevelWindows(), embedded windows are
915// included in this list (QTBUG-18099).
916static inline bool needsWindowBlockedEvent(const QWindow *w)
917{
918 return w->isTopLevel();
919}
920
921void QGuiApplicationPrivate::showModalWindow(QWindow *modal)
922{
923 auto *guiAppPrivate = QGuiApplicationPrivate::instance();
924 guiAppPrivate->modalWindowList.prepend(modal);
925
926 // Send leave for currently entered window if it should be blocked
927 if (currentMouseWindow && !QWindowPrivate::get(currentMouseWindow)->isPopup()) {
928 bool shouldBeBlocked = guiAppPrivate->isWindowBlocked(currentMouseWindow);
929 if (shouldBeBlocked) {
930 // Remove the new window from modalWindowList temporarily so leave can go through
931 guiAppPrivate->modalWindowList.removeFirst();
932 QEvent e(QEvent::Leave);
933 QGuiApplication::sendEvent(currentMouseWindow, &e);
934 currentMouseWindow = nullptr;
935 guiAppPrivate->modalWindowList.prepend(modal);
936 }
937 }
938
939 for (QWindow *window : std::as_const(QGuiApplicationPrivate::window_list)) {
940 if (needsWindowBlockedEvent(window) && !window->d_func()->blockedByModalWindow)
941 updateBlockedStatus(window);
942 }
943
944 updateBlockedStatus(modal);
945}
946
947void QGuiApplicationPrivate::hideModalWindow(QWindow *window)
948{
949 QGuiApplicationPrivate::instance()->modalWindowList.removeAll(window);
950
951 for (QWindow *window : std::as_const(QGuiApplicationPrivate::window_list)) {
952 if (needsWindowBlockedEvent(window) && window->d_func()->blockedByModalWindow)
953 updateBlockedStatus(window);
954 }
955}
956
957Qt::WindowModality QGuiApplicationPrivate::defaultModality() const
958{
959 return Qt::NonModal;
960}
961
962bool QGuiApplicationPrivate::windowNeverBlocked(QWindow *window) const
963{
964 Q_UNUSED(window);
965 return false;
966}
967
968/*
969 Returns \c true if \a window is blocked by a modal window. If \a
970 blockingWindow is non-zero, *blockingWindow will be set to the blocking
971 window (or to zero if \a window is not blocked).
972*/
973bool QGuiApplicationPrivate::isWindowBlocked(QWindow *window, QWindow **blockingWindow) const
974{
975 Q_ASSERT_X(window, Q_FUNC_INFO, "The window must not be null");
976
977 QWindow *unused = nullptr;
978 if (!blockingWindow)
979 blockingWindow = &unused;
980 *blockingWindow = nullptr;
981
982 if (modalWindowList.isEmpty() || windowNeverBlocked(window))
983 return false;
984
985 for (int i = 0; i < modalWindowList.size(); ++i) {
986 QWindow *modalWindow = modalWindowList.at(i);
987
988 // A window is not blocked by another modal window if the two are
989 // the same, or if the window is a child of the modal window.
990 if (window == modalWindow || modalWindow->isAncestorOf(window, QWindow::IncludeTransients))
991 return false;
992
993 switch (modalWindow->modality() == Qt::NonModal ? defaultModality()
994 : modalWindow->modality()) {
995 case Qt::ApplicationModal:
996 *blockingWindow = modalWindow;
997 return true;
998 case Qt::WindowModal: {
999 // Find the nearest ancestor of window which is also an ancestor of modal window to
1000 // determine if the modal window blocks the window.
1001 auto *current = window;
1002 do {
1003 if (current->isAncestorOf(modalWindow, QWindow::IncludeTransients)) {
1004 *blockingWindow = modalWindow;
1005 return true;
1006 }
1007 current = current->parent(QWindow::IncludeTransients);
1008 } while (current);
1009 break;
1010 }
1011 default:
1012 Q_ASSERT_X(false, "QGuiApplication", "internal error, a modal widget cannot be modeless");
1013 break;
1014 }
1015 }
1016 return false;
1017}
1018
1019QWindow *QGuiApplicationPrivate::activePopupWindow()
1020{
1021 // might be the same as focusWindow() if that's a popup
1022 return QGuiApplicationPrivate::popup_list.isEmpty() ?
1023 nullptr : QGuiApplicationPrivate::popup_list.constLast();
1024}
1025
1026void QGuiApplicationPrivate::activatePopup(QWindow *popup)
1027{
1028 if (!popup->isVisible())
1029 return;
1030 popup_list.removeOne(popup); // ensure that there's only one entry, and it's the last
1031 qCDebug(lcPopup) << "appending popup" << popup << "to existing" << popup_list;
1032 popup_list.append(popup);
1033}
1034
1035bool QGuiApplicationPrivate::closePopup(QWindow *popup)
1036{
1037 const auto removed = QGuiApplicationPrivate::popup_list.removeAll(popup);
1038 qCDebug(lcPopup) << "removed?" << removed << "popup" << popup << "; remaining" << popup_list;
1039 return removed; // >= 1 if something was removed
1040}
1041
1042/*!
1043 Returns \c true if there are no more open popups.
1044*/
1045bool QGuiApplicationPrivate::closeAllPopups()
1046{
1047 // Close all popups: In case some popup refuses to close,
1048 // we give up after 1024 attempts (to avoid an infinite loop).
1049 int maxiter = 1024;
1050 QWindow *popup;
1051 while ((popup = activePopupWindow()) && maxiter--)
1052 popup->close(); // this will call QApplicationPrivate::closePopup
1053 return QGuiApplicationPrivate::popup_list.isEmpty();
1054}
1055
1056/*!
1057 Returns the QWindow that receives events tied to focus,
1058 such as key events.
1059
1060 \sa QWindow::requestActivate()
1061*/
1062QWindow *QGuiApplication::focusWindow()
1063{
1064 return QGuiApplicationPrivate::focus_window;
1065}
1066
1067/*!
1068 \fn QGuiApplication::focusObjectChanged(QObject *focusObject)
1069
1070 This signal is emitted when final receiver of events tied to focus is changed.
1071 \a focusObject is the new receiver.
1072
1073 \sa focusObject()
1074*/
1075
1076/*!
1077 \fn QGuiApplication::focusWindowChanged(QWindow *focusWindow)
1078
1079 This signal is emitted when the focused window changes.
1080 \a focusWindow is the new focused window.
1081
1082 \sa focusWindow()
1083*/
1084
1085/*!
1086 Returns the QObject in currently active window that will be final receiver of events
1087 tied to focus, such as key events.
1088 */
1089QObject *QGuiApplication::focusObject()
1090{
1091 if (focusWindow())
1092 return focusWindow()->focusObject();
1093 return nullptr;
1094}
1095
1096/*!
1097 \fn QGuiApplication::allWindows()
1098
1099 Returns a list of all the windows in the application.
1100
1101 The list is empty if there are no windows.
1102
1103 \sa topLevelWindows()
1104 */
1105QWindowList QGuiApplication::allWindows()
1106{
1107 return QGuiApplicationPrivate::window_list;
1108}
1109
1110/*!
1111 \fn QGuiApplication::topLevelWindows()
1112
1113 Returns a list of the top-level windows in the application.
1114
1115 \sa allWindows()
1116 */
1117QWindowList QGuiApplication::topLevelWindows()
1118{
1119 const QWindowList &list = QGuiApplicationPrivate::window_list;
1120 QWindowList topLevelWindows;
1121 for (int i = 0; i < list.size(); ++i) {
1122 QWindow *window = list.at(i);
1123 if (!window->isTopLevel())
1124 continue;
1125
1126 // Windows embedded in native windows do not have QWindow parents,
1127 // but they are not true top level windows, so do not include them.
1128 if (window->handle() && window->handle()->isEmbedded())
1129 continue;
1130
1131 topLevelWindows.prepend(window);
1132 }
1133
1134 return topLevelWindows;
1135}
1136
1137QScreen *QGuiApplication::primaryScreen()
1138{
1139 if (QGuiApplicationPrivate::screen_list.isEmpty())
1140 return nullptr;
1141 return QGuiApplicationPrivate::screen_list.at(0);
1142}
1143
1144/*!
1145 Returns a list of all the screens associated with the
1146 windowing system the application is connected to.
1147*/
1148QList<QScreen *> QGuiApplication::screens()
1149{
1150 return QGuiApplicationPrivate::screen_list;
1151}
1152
1153/*!
1154 Returns the screen at \a point, or \nullptr if outside of any screen.
1155
1156 The \a point is in relation to the virtualGeometry() of each set of virtual
1157 siblings. If the point maps to more than one set of virtual siblings the first
1158 match is returned. If you wish to search only the virtual desktop siblings
1159 of a known screen (for example siblings of the screen of your application
1160 window \c QWidget::windowHandle()->screen()), use QScreen::virtualSiblingAt().
1161
1162 \since 5.10
1163*/
1164QScreen *QGuiApplication::screenAt(const QPoint &point)
1165{
1166 QVarLengthArray<const QScreen *, 8> visitedScreens;
1167 for (const QScreen *screen : QGuiApplication::screens()) {
1168 if (visitedScreens.contains(screen))
1169 continue;
1170
1171 // The virtual siblings include the screen itself, so iterate directly
1172 for (QScreen *sibling : screen->virtualSiblings()) {
1173 if (sibling->geometry().contains(point))
1174 return sibling;
1175
1176 visitedScreens.append(sibling);
1177 }
1178 }
1179
1180 return nullptr;
1181}
1182
1183/*!
1184 \fn void QGuiApplication::screenAdded(QScreen *screen)
1185
1186 This signal is emitted whenever a new screen \a screen has been added to the system.
1187
1188 \sa screens(), primaryScreen, screenRemoved()
1189*/
1190
1191/*!
1192 \fn void QGuiApplication::screenRemoved(QScreen *screen)
1193
1194 This signal is emitted whenever a \a screen is removed from the system. It
1195 provides an opportunity to manage the windows on the screen before Qt falls back
1196 to moving them to the primary screen.
1197
1198 \sa screens(), screenAdded(), QObject::destroyed(), QWindow::setScreen()
1199
1200 \since 5.4
1201*/
1202
1203
1204/*!
1205 \property QGuiApplication::primaryScreen
1206
1207 \brief the primary (or default) screen of the application.
1208
1209 This will be the screen where QWindows are initially shown, unless otherwise specified.
1210
1211 The primaryScreenChanged signal was introduced in Qt 5.6.
1212
1213 \sa screens()
1214*/
1215
1216/*!
1217 Returns the highest screen device pixel ratio found on
1218 the system. This is the ratio between physical pixels and
1219 device-independent pixels.
1220
1221 Use this function only when you don't know which window you are targeting.
1222 If you do know the target window, use QWindow::devicePixelRatio() instead.
1223
1224 \sa QWindow::devicePixelRatio()
1225*/
1226qreal QGuiApplication::devicePixelRatio() const
1227{
1228 if (!qFuzzyIsNull(QGuiApplicationPrivate::m_maxDevicePixelRatio))
1229 return QGuiApplicationPrivate::m_maxDevicePixelRatio;
1230
1231 QGuiApplicationPrivate::m_maxDevicePixelRatio = 1.0; // make sure we never return 0.
1232 for (QScreen *screen : std::as_const(QGuiApplicationPrivate::screen_list))
1233 QGuiApplicationPrivate::m_maxDevicePixelRatio = qMax(QGuiApplicationPrivate::m_maxDevicePixelRatio, screen->devicePixelRatio());
1234
1235 return QGuiApplicationPrivate::m_maxDevicePixelRatio;
1236}
1237
1238void QGuiApplicationPrivate::resetCachedDevicePixelRatio()
1239{
1240 m_maxDevicePixelRatio = 0.0;
1241}
1242
1243void QGuiApplicationPrivate::_q_updatePrimaryScreenDpis()
1244{
1245 int dpis = 0;
1246 const QScreen *screen = QGuiApplication::primaryScreen();
1247 if (screen) {
1248 int dpiX = qRound(screen->logicalDotsPerInchX());
1249 int dpiY = qRound(screen->logicalDotsPerInchY());
1250 dpis = (dpiX << 16) | (dpiY & 0xffff);
1251 QObject::connect(screen, SIGNAL(logicalDotsPerInchChanged(qreal)),
1252 q_func(), SLOT(_q_updatePrimaryScreenDpis()), Qt::UniqueConnection);
1253 }
1254 m_primaryScreenDpis.storeRelaxed(dpis);
1255}
1256
1257/*!
1258 Returns the top level window at the given position \a pos, if any.
1259*/
1260QWindow *QGuiApplication::topLevelAt(const QPoint &pos)
1261{
1262 if (QScreen *windowScreen = screenAt(pos)) {
1263 const QPoint devicePosition = QHighDpi::toNativePixels(pos, windowScreen);
1264 return windowScreen->handle()->topLevelAt(devicePosition);
1265 }
1266 return nullptr;
1267}
1268
1269/*!
1270 \property QGuiApplication::platformName
1271 \brief The name of the underlying platform plugin.
1272
1273 The QPA platform plugins are located in \c {qtbase\src\plugins\platforms}.
1274 At the time of writing, the following platform plugin names are supported:
1275
1276 \list
1277 \li \c android
1278 \li \c cocoa is a platform plugin for \macos.
1279 \li \c directfb
1280 \li \c eglfs is a platform plugin for running Qt5 applications on top of
1281 EGL and OpenGL ES 2.0 without an actual windowing system (like X11
1282 or Wayland). For more information, see \l{EGLFS}.
1283 \li \c ios (also used for tvOS)
1284 \li \c linuxfb writes directly to the framebuffer. For more information,
1285 see \l{LinuxFB}.
1286 \li \c minimal is provided as an examples for developers who want to
1287 write their own platform plugins. However, you can use the plugin to
1288 run GUI applications in environments without a GUI, such as servers.
1289 \li \c minimalegl is an example plugin.
1290 \li \c offscreen
1291 \li \c qnx
1292 \li \c windows
1293 \li \c wayland is a platform plugin for the Wayland display server protocol,
1294 used on some Linux desktops and embedded systems.
1295 \li \c xcb is a plugin for the X11 window system, used on some desktop Linux platforms.
1296 \endlist
1297
1298 \note Calling this function without a QGuiApplication will return the default
1299 platform name, if available. The default platform name is not affected by the
1300 \c{-platform} command line option, or the \c QT_QPA_PLATFORM environment variable.
1301
1302 For more information about the platform plugins for embedded Linux devices,
1303 see \l{Qt for Embedded Linux}.
1304*/
1305
1306QString QGuiApplication::platformName()
1307{
1308 if (!QGuiApplication::instance()) {
1309#ifdef QT_QPA_DEFAULT_PLATFORM_NAME
1310 return QStringLiteral(QT_QPA_DEFAULT_PLATFORM_NAME);
1311#else
1312 return QString();
1313#endif
1314 } else {
1315 return QGuiApplicationPrivate::platform_name ?
1316 *QGuiApplicationPrivate::platform_name : QString();
1317 }
1318}
1319
1320Q_STATIC_LOGGING_CATEGORY(lcQpaPluginLoading, "qt.qpa.plugin");
1321Q_STATIC_LOGGING_CATEGORY(lcQpaTheme, "qt.qpa.theme");
1322Q_STATIC_LOGGING_CATEGORY(lcPtrDispatch, "qt.pointer.dispatch");
1323
1324static void init_platform(const QString &pluginNamesWithArguments, const QString &platformPluginPath, const QString &platformThemeName, int &argc, char **argv)
1325{
1326 qCDebug(lcQpaPluginLoading) << "init_platform called with"
1327 << "pluginNamesWithArguments" << pluginNamesWithArguments
1328 << "platformPluginPath" << platformPluginPath
1329 << "platformThemeName" << platformThemeName;
1330
1331 QStringList plugins = pluginNamesWithArguments.split(u';', Qt::SkipEmptyParts);
1332 QStringList platformArguments;
1333 QStringList availablePlugins = QPlatformIntegrationFactory::keys(platformPluginPath);
1334 for (const auto &pluginArgument : std::as_const(plugins)) {
1335 // Split into platform name and arguments
1336 QStringList arguments = pluginArgument.split(u':', Qt::SkipEmptyParts);
1337 if (arguments.isEmpty())
1338 continue;
1339 const QString name = arguments.takeFirst().toLower();
1340 QString argumentsKey = name;
1341 if (name.isEmpty())
1342 continue;
1343 argumentsKey[0] = argumentsKey.at(0).toUpper();
1344 arguments.append(QLibraryInfo::platformPluginArguments(argumentsKey));
1345
1346 qCDebug(lcQpaPluginLoading) << "Attempting to load Qt platform plugin" << name << "with arguments" << arguments;
1347
1348 // Create the platform integration.
1349 QGuiApplicationPrivate::platform_integration = QPlatformIntegrationFactory::create(name, arguments, argc, argv, platformPluginPath);
1350 if (Q_UNLIKELY(!QGuiApplicationPrivate::platform_integration)) {
1351 if (availablePlugins.contains(name)) {
1352 if (name == QStringLiteral("xcb") && QVersionNumber::compare(QLibraryInfo::version(), QVersionNumber(6, 5, 0)) >= 0) {
1353 qCWarning(lcQpaPluginLoading).nospace().noquote()
1354 << "From 6.5.0, xcb-cursor0 or libxcb-cursor0 is needed to load the Qt xcb platform plugin.";
1355 }
1356 qCInfo(lcQpaPluginLoading).nospace().noquote()
1357 << "Could not load the Qt platform plugin \"" << name << "\" in \""
1358 << QDir::toNativeSeparators(platformPluginPath) << "\" even though it was found.";
1359 } else {
1360 qCWarning(lcQpaPluginLoading).nospace().noquote()
1361 << "Could not find the Qt platform plugin \"" << name << "\" in \""
1362 << QDir::toNativeSeparators(platformPluginPath) << "\"";
1363 }
1364 } else {
1365 qCDebug(lcQpaPluginLoading) << "Successfully loaded Qt platform plugin" << name;
1366 QGuiApplicationPrivate::platform_name = new QString(name);
1367 platformArguments = arguments;
1368 break;
1369 }
1370 }
1371
1372 if (Q_UNLIKELY(!QGuiApplicationPrivate::platform_integration)) {
1373 QString fatalMessage = QStringLiteral("This application failed to start because no Qt platform plugin could be initialized. "
1374 "Reinstalling the application may fix this problem.\n");
1375
1376 if (!availablePlugins.isEmpty())
1377 fatalMessage += "\nAvailable platform plugins are: %1.\n"_L1.arg(availablePlugins.join(", "_L1));
1378
1379#if defined(Q_OS_WIN)
1380 // Windows: Display message box unless it is a console application
1381 // or debug build showing an assert box.
1382 if (!QLibraryInfo::isDebugBuild() && !GetConsoleWindow())
1383 MessageBox(0, (LPCTSTR)fatalMessage.utf16(), (LPCTSTR)(QCoreApplication::applicationName().utf16()), MB_OK | MB_ICONERROR);
1384#endif // Q_OS_WIN
1385 qFatal("%s", qPrintable(fatalMessage));
1386
1387 return;
1388 }
1389
1390 // Create the platform theme:
1391
1392 // 1) Try the platform name from the environment if present
1393 QStringList themeNames;
1394 if (!platformThemeName.isEmpty()) {
1395 qCDebug(lcQpaTheme) << "Adding" << platformThemeName << "from environment";
1396 themeNames.append(platformThemeName);
1397 }
1398
1399#if defined(Q_OS_UNIX) && !defined(Q_OS_DARWIN)
1400 // 2) Special case - check whether it's a flatpak or snap app to use xdg-desktop-portal platform theme for portals support
1401 if (checkNeedPortalSupport()) {
1402 qCDebug(lcQpaTheme) << "Adding xdgdesktopportal to list of theme names";
1403 themeNames.append(QStringLiteral("xdgdesktopportal"));
1404 }
1405#endif
1406
1407 // 3) Ask the platform integration for a list of theme names
1408 const auto platformIntegrationThemeNames = QGuiApplicationPrivate::platform_integration->themeNames();
1409 qCDebug(lcQpaTheme) << "Adding platform integration's theme names to list of theme names:" << platformIntegrationThemeNames;
1410 themeNames.append(platformIntegrationThemeNames);
1411
1412 // 4) Look for a theme plugin.
1413 for (const QString &themeName : std::as_const(themeNames)) {
1414 qCDebug(lcQpaTheme) << "Attempting to create platform theme" << themeName << "via QPlatformThemeFactory::create";
1415 QGuiApplicationPrivate::platform_theme = QPlatformThemeFactory::create(themeName, platformPluginPath);
1416 if (QGuiApplicationPrivate::platform_theme) {
1417 qCDebug(lcQpaTheme) << "Successfully created platform theme" << themeName << "via QPlatformThemeFactory::create";
1418 break;
1419 }
1420 qCDebug(lcQpaTheme) << "Attempting to create platform theme" << themeName << "via createPlatformTheme";
1421 QGuiApplicationPrivate::platform_theme = QGuiApplicationPrivate::platform_integration->createPlatformTheme(themeName);
1422 if (QGuiApplicationPrivate::platform_theme) {
1423 qCDebug(lcQpaTheme) << "Successfully created platform theme" << themeName << "via createPlatformTheme";
1424 break;
1425 }
1426 }
1427
1428 // 5) Fall back on the built-in "null" platform theme.
1429 if (!QGuiApplicationPrivate::platform_theme) {
1430 qCDebug(lcQpaTheme) << "Failed to create platform theme; using \"null\" platform theme";
1431 QGuiApplicationPrivate::platform_theme = new QPlatformTheme;
1432 }
1433
1434 // Set arguments as dynamic properties on the native interface as
1435 // boolean 'foo' or strings: 'foo=bar'
1436 if (!platformArguments.isEmpty()) {
1437 if (QObject *nativeInterface = QGuiApplicationPrivate::platform_integration->nativeInterface()) {
1438 for (const QString &argument : std::as_const(platformArguments)) {
1439 const qsizetype equalsPos = argument.indexOf(u'=');
1440 const QByteArray name =
1441 equalsPos != -1 ? argument.left(equalsPos).toUtf8() : argument.toUtf8();
1442 QVariant value =
1443 equalsPos != -1 ? QVariant(argument.mid(equalsPos + 1)) : QVariant(true);
1444 nativeInterface->setProperty(name.constData(), std::move(value));
1445 }
1446 }
1447 }
1448
1449 const auto *platformIntegration = QGuiApplicationPrivate::platformIntegration();
1450 fontSmoothingGamma = platformIntegration->styleHint(QPlatformIntegration::FontSmoothingGamma).toReal();
1451 QCoreApplication::setAttribute(Qt::AA_DontShowShortcutsInContextMenus,
1452 !QGuiApplication::styleHints()->showShortcutsInContextMenus());
1453
1454 if (const auto *platformTheme = QGuiApplicationPrivate::platformTheme()) {
1455 QCoreApplication::setAttribute(Qt::AA_DontShowIconsInMenus,
1456 !platformTheme->themeHint(QPlatformTheme::ShowIconsInMenus).toBool());
1457 }
1458}
1459
1460static void init_plugins(const QList<QByteArray> &pluginList)
1461{
1462 for (int i = 0; i < pluginList.size(); ++i) {
1463 QByteArray pluginSpec = pluginList.at(i);
1464 qsizetype colonPos = pluginSpec.indexOf(':');
1465 QObject *plugin;
1466 if (colonPos < 0)
1467 plugin = QGenericPluginFactory::create(QLatin1StringView(pluginSpec), QString());
1468 else
1469 plugin = QGenericPluginFactory::create(QLatin1StringView(pluginSpec.mid(0, colonPos)),
1470 QLatin1StringView(pluginSpec.mid(colonPos+1)));
1471 if (plugin)
1472 QGuiApplicationPrivate::generic_plugin_list.append(plugin);
1473 else
1474 qWarning("No such plugin for spec \"%s\"", pluginSpec.constData());
1475 }
1476}
1477
1478#if QT_CONFIG(commandlineparser)
1479void QGuiApplicationPrivate::addQtOptions(QList<QCommandLineOption> *options)
1480{
1481 QCoreApplicationPrivate::addQtOptions(options);
1482
1483#if defined(Q_OS_UNIX) && !defined(Q_OS_DARWIN)
1484 const QByteArray sessionType = qgetenv("XDG_SESSION_TYPE");
1485 const bool x11 = sessionType == "x11";
1486 // Technically the x11 aliases are only available if platformName is "xcb", but we can't know that here.
1487#else
1488 const bool x11 = false;
1489#endif
1490
1491 options->append(QCommandLineOption(QStringLiteral("platform"),
1492 QGuiApplication::tr("QPA plugin. See QGuiApplication documentation for available options for each plugin."), QStringLiteral("platformName[:options]")));
1493 options->append(QCommandLineOption(QStringLiteral("platformpluginpath"),
1494 QGuiApplication::tr("Path to the platform plugins."), QStringLiteral("path")));
1495 options->append(QCommandLineOption(QStringLiteral("platformtheme"),
1496 QGuiApplication::tr("Platform theme."), QStringLiteral("theme")));
1497 options->append(QCommandLineOption(QStringLiteral("plugin"),
1498 QGuiApplication::tr("Additional plugins to load, can be specified multiple times."), QStringLiteral("plugin")));
1499 options->append(QCommandLineOption(QStringLiteral("qwindowgeometry"),
1500 QGuiApplication::tr("Window geometry for the main window, using the X11-syntax, like 100x100+50+50."), QStringLiteral("geometry")));
1501 options->append(QCommandLineOption(QStringLiteral("qwindowicon"),
1502 QGuiApplication::tr("Default window icon."), QStringLiteral("icon")));
1503 options->append(QCommandLineOption(QStringLiteral("qwindowtitle"),
1504 QGuiApplication::tr("Title of the first window."), QStringLiteral("title")));
1505 options->append(QCommandLineOption(QStringLiteral("reverse"),
1506 QGuiApplication::tr("Sets the application's layout direction to Qt::RightToLeft (debugging helper).")));
1507 options->append(QCommandLineOption(QStringLiteral("session"),
1508 QGuiApplication::tr("Restores the application from an earlier session."), QStringLiteral("session")));
1509
1510 if (x11) {
1511 options->append(QCommandLineOption(QStringLiteral("display"),
1512 QGuiApplication::tr("Display name, overrides $DISPLAY."), QStringLiteral("display")));
1513 options->append(QCommandLineOption(QStringLiteral("name"),
1514 QGuiApplication::tr("Instance name according to ICCCM 4.1.2.5."), QStringLiteral("name")));
1515 options->append(QCommandLineOption(QStringLiteral("nograb"),
1516 QGuiApplication::tr("Disable mouse grabbing (useful in debuggers).")));
1517 options->append(QCommandLineOption(QStringLiteral("dograb"),
1518 QGuiApplication::tr("Force mouse grabbing (even when running in a debugger).")));
1519 options->append(QCommandLineOption(QStringLiteral("visual"),
1520 QGuiApplication::tr("ID of the X11 Visual to use."), QStringLiteral("id")));
1521 // Not using the "QStringList names" solution for those aliases, because it makes the first column too wide
1522 options->append(QCommandLineOption(QStringLiteral("geometry"),
1523 QGuiApplication::tr("Alias for --qwindowgeometry."), QStringLiteral("geometry")));
1524 options->append(QCommandLineOption(QStringLiteral("icon"),
1525 QGuiApplication::tr("Alias for --qwindowicon."), QStringLiteral("icon")));
1526 options->append(QCommandLineOption(QStringLiteral("title"),
1527 QGuiApplication::tr("Alias for --qwindowtitle."), QStringLiteral("title")));
1528 }
1529}
1530#endif // QT_CONFIG(commandlineparser)
1531
1532void QGuiApplicationPrivate::createPlatformIntegration()
1533{
1534 QHighDpiScaling::initHighDpiScaling();
1535
1536 // Load the platform integration
1537 QString platformPluginPath = qEnvironmentVariable("QT_QPA_PLATFORM_PLUGIN_PATH");
1538
1539
1540 QByteArray platformName;
1541#ifdef QT_QPA_DEFAULT_PLATFORM_NAME
1542 platformName = QT_QPA_DEFAULT_PLATFORM_NAME;
1543#endif
1544#if defined(Q_OS_UNIX) && !defined(Q_OS_DARWIN)
1545 QList<QByteArray> platformArguments = platformName.split(':');
1546 QByteArray platformPluginBase = platformArguments.first();
1547
1548 const bool hasWaylandDisplay = qEnvironmentVariableIsSet("WAYLAND_DISPLAY");
1549 const bool isWaylandSessionType = qgetenv("XDG_SESSION_TYPE") == "wayland";
1550
1551 QVector<QByteArray> preferredPlatformOrder;
1552 const bool defaultIsXcb = platformPluginBase == "xcb";
1553 const QByteArray xcbPlatformName = defaultIsXcb ? platformName : "xcb";
1554 if (qEnvironmentVariableIsSet("DISPLAY")) {
1555 preferredPlatformOrder << xcbPlatformName;
1556 if (defaultIsXcb)
1557 platformName.clear();
1558 }
1559
1560 const bool defaultIsWayland = !defaultIsXcb && platformPluginBase.startsWith("wayland");
1561 const QByteArray waylandPlatformName = defaultIsWayland ? platformName : "wayland";
1562 if (hasWaylandDisplay || isWaylandSessionType) {
1563 preferredPlatformOrder.prepend(waylandPlatformName);
1564
1565 if (defaultIsWayland)
1566 platformName.clear();
1567 }
1568
1569 if (!platformName.isEmpty())
1570 preferredPlatformOrder.append(platformName);
1571
1572 platformName = preferredPlatformOrder.join(';');
1573#endif
1574
1575 bool platformExplicitlySelected = false;
1576 QByteArray platformNameEnv = qgetenv("QT_QPA_PLATFORM");
1577 if (!platformNameEnv.isEmpty()) {
1578 platformName = platformNameEnv;
1579 platformExplicitlySelected = true;
1580 }
1581
1582 QString platformThemeName = QString::fromLocal8Bit(qgetenv("QT_QPA_PLATFORMTHEME"));
1583
1584 // Get command line params
1585
1586 QString icon;
1587
1588 int j = argc ? 1 : 0;
1589 for (int i=1; i<argc; i++) {
1590 if (!argv[i])
1591 continue;
1592 if (*argv[i] != '-') {
1593 argv[j++] = argv[i];
1594 continue;
1595 }
1596 const bool xcbIsDefault = platformName.startsWith("xcb");
1597 const char *arg = argv[i];
1598 if (arg[1] == '-') // startsWith("--")
1599 ++arg;
1600 if (strcmp(arg, "-platformpluginpath") == 0) {
1601 if (++i < argc)
1602 platformPluginPath = QFile::decodeName(argv[i]);
1603 } else if (strcmp(arg, "-platform") == 0) {
1604 if (++i < argc) {
1605 platformExplicitlySelected = true;
1606 platformName = argv[i];
1607 }
1608 } else if (strcmp(arg, "-platformtheme") == 0) {
1609 if (++i < argc)
1610 platformThemeName = QString::fromLocal8Bit(argv[i]);
1611 } else if (strcmp(arg, "-qwindowgeometry") == 0 || (xcbIsDefault && strcmp(arg, "-geometry") == 0)) {
1612 if (++i < argc)
1613 windowGeometrySpecification = QWindowGeometrySpecification::fromArgument(argv[i]);
1614 } else if (strcmp(arg, "-qwindowtitle") == 0 || (xcbIsDefault && strcmp(arg, "-title") == 0)) {
1615 if (++i < argc)
1616 firstWindowTitle = QString::fromLocal8Bit(argv[i]);
1617 } else if (strcmp(arg, "-qwindowicon") == 0 || (xcbIsDefault && strcmp(arg, "-icon") == 0)) {
1618 if (++i < argc) {
1619 icon = QFile::decodeName(argv[i]);
1620 }
1621 } else {
1622 argv[j++] = argv[i];
1623 }
1624 }
1625
1626 if (j < argc) {
1627 argv[j] = nullptr;
1628 argc = j;
1629 }
1630
1631 Q_UNUSED(platformExplicitlySelected);
1632
1633 init_platform(QLatin1StringView(platformName), platformPluginPath, platformThemeName, argc, argv);
1634 QStyleHintsPrivate::get(QGuiApplication::styleHints())->update(platformTheme());
1635
1636 if (!icon.isEmpty())
1637 forcedWindowIcon = QDir::isAbsolutePath(icon) ? QIcon(icon) : QIcon::fromTheme(icon);
1638}
1639
1640/*!
1641 Called from QCoreApplication::init()
1642
1643 Responsible for creating an event dispatcher when QCoreApplication
1644 decides that it needs one (because a custom one has not been set).
1645*/
1646void QGuiApplicationPrivate::createEventDispatcher()
1647{
1648 Q_ASSERT(!eventDispatcher);
1649
1650 if (platform_integration == nullptr)
1651 createPlatformIntegration();
1652
1653 // The platform integration should not result in creating an event dispatcher
1654 Q_ASSERT_X(!threadData.loadRelaxed()->eventDispatcher, "QGuiApplication",
1655 "Creating the platform integration resulted in creating an event dispatcher");
1656
1657 // Nor should it mess with the QCoreApplication's event dispatcher
1658 Q_ASSERT(!eventDispatcher);
1659
1660 eventDispatcher = platform_integration->createEventDispatcher();
1661}
1662
1663void QGuiApplicationPrivate::eventDispatcherReady()
1664{
1665 if (platform_integration == nullptr)
1666 createPlatformIntegration();
1667
1668 platform_integration->initialize();
1669}
1670
1671void Q_TRACE_INSTRUMENT(qtgui) QGuiApplicationPrivate::init()
1672{
1673 Q_TRACE_SCOPE(QGuiApplicationPrivate_init);
1674
1675#if defined(Q_OS_MACOS)
1676 QMacAutoReleasePool pool;
1677#endif
1678
1679 QObject::connect(q_func(), SIGNAL(screenAdded(QScreen*)),
1680 q_func(), SLOT(_q_updatePrimaryScreenDpis()));
1681 QObject::connect(q_func(), SIGNAL(primaryScreenChanged(QScreen *)),
1682 q_func(), SLOT(_q_updatePrimaryScreenDpis()));
1683
1684 QCoreApplicationPrivate::init();
1685
1686 QCoreApplicationPrivate::is_app_running = false; // Starting up.
1687
1688 bool loadTestability = false;
1689 QList<QByteArray> pluginList;
1690 // Get command line params
1691#ifndef QT_NO_SESSIONMANAGER
1692 QString session_id;
1693 QString session_key;
1694# if defined(Q_OS_WIN)
1695 wchar_t guidstr[40];
1696 GUID guid;
1697 CoCreateGuid(&guid);
1698 StringFromGUID2(guid, guidstr, 40);
1699 session_id = QString::fromWCharArray(guidstr);
1700 CoCreateGuid(&guid);
1701 StringFromGUID2(guid, guidstr, 40);
1702 session_key = QString::fromWCharArray(guidstr);
1703# endif
1704#endif
1705 QString s;
1706 int j = argc ? 1 : 0;
1707 for (int i=1; i<argc; i++) {
1708 if (!argv[i])
1709 continue;
1710 if (*argv[i] != '-') {
1711 argv[j++] = argv[i];
1712 continue;
1713 }
1714 const char *arg = argv[i];
1715 if (arg[1] == '-') // startsWith("--")
1716 ++arg;
1717 if (strcmp(arg, "-plugin") == 0) {
1718 if (++i < argc)
1719 pluginList << argv[i];
1720 } else if (strcmp(arg, "-reverse") == 0) {
1721 force_reverse = true;
1722#ifdef Q_OS_MACOS
1723 } else if (strncmp(arg, "-psn_", 5) == 0) {
1724 // eat "-psn_xxxx" on Mac, which is passed when starting an app from Finder.
1725 // special hack to change working directory (for an app bundle) when running from finder
1726 if (QDir::currentPath() == "/"_L1) {
1727 QCFType<CFURLRef> bundleURL(CFBundleCopyBundleURL(CFBundleGetMainBundle()));
1728 QString qbundlePath = QCFString(CFURLCopyFileSystemPath(bundleURL,
1729 kCFURLPOSIXPathStyle));
1730 if (qbundlePath.endsWith(".app"_L1))
1731 QDir::setCurrent(qbundlePath.section(u'/', 0, -2));
1732 }
1733#endif
1734#ifndef QT_NO_SESSIONMANAGER
1735 } else if (strcmp(arg, "-session") == 0 && i < argc - 1) {
1736 ++i;
1737 if (argv[i] && *argv[i]) {
1738 session_id = QString::fromLatin1(argv[i]);
1739 qsizetype p = session_id.indexOf(u'_');
1740 if (p >= 0) {
1741 session_key = session_id.mid(p +1);
1742 session_id = session_id.left(p);
1743 }
1744 is_session_restored = true;
1745 }
1746#endif
1747 } else if (strcmp(arg, "-testability") == 0) {
1748 loadTestability = true;
1749 } else if (strncmp(arg, "-style=", 7) == 0) {
1750 s = QString::fromLocal8Bit(arg + 7);
1751 } else if (strcmp(arg, "-style") == 0 && i < argc - 1) {
1752 s = QString::fromLocal8Bit(argv[++i]);
1753 } else {
1754 argv[j++] = argv[i];
1755 }
1756
1757 if (!s.isEmpty())
1758 styleOverride = s;
1759 }
1760
1761 if (j < argc) {
1762 argv[j] = nullptr;
1763 argc = j;
1764 }
1765
1766 // Load environment exported generic plugins
1767 QByteArray envPlugins = qgetenv("QT_QPA_GENERIC_PLUGINS");
1768 if (!envPlugins.isEmpty())
1769 pluginList += envPlugins.split(',');
1770
1771 if (platform_integration == nullptr)
1772 createPlatformIntegration();
1773
1774 updatePalette();
1775 QFont::initialize();
1776 initThemeHints();
1777
1778#ifndef QT_NO_CURSOR
1779 QCursorData::initialize();
1780#endif
1781
1782 // trigger registering of QVariant's GUI types
1783 qRegisterGuiVariant();
1784
1785#if QT_CONFIG(animation)
1786 // trigger registering of animation interpolators
1787 qRegisterGuiGetInterpolator();
1788#endif
1789
1790 QWindowSystemInterfacePrivate::eventTime.start();
1791
1792#if QT_CONFIG(accessibility)
1793 QAccessible::installFactory([](const QString &classname, QObject *object)
1794 -> QAccessibleInterface * {
1795 if (classname == "QForeignWindow"_L1)
1796 return new QAccessibleWindow(static_cast<QWindow *>(object));
1797 return nullptr;
1798 });
1799#endif
1800
1801 is_app_running = true;
1802 init_plugins(pluginList);
1803 QWindowSystemInterface::flushWindowSystemEvents();
1804
1805 Q_Q(QGuiApplication);
1806#ifndef QT_NO_SESSIONMANAGER
1807 // connect to the session manager
1808 session_manager = new QSessionManager(q, session_id, session_key);
1809#endif
1810
1811#if QT_CONFIG(library)
1812 if (qEnvironmentVariableIntValue("QT_LOAD_TESTABILITY") > 0)
1813 loadTestability = true;
1814
1815 if (loadTestability) {
1816 QLibrary testLib(QStringLiteral("qttestability"));
1817 if (Q_UNLIKELY(!testLib.load())) {
1818 qCritical() << "Library qttestability load failed:" << testLib.errorString();
1819 } else {
1820 typedef void (*TasInitialize)(void);
1821 TasInitialize initFunction = (TasInitialize)testLib.resolve("qt_testability_init");
1822 if (Q_UNLIKELY(!initFunction)) {
1823 qCritical("Library qttestability resolve failed!");
1824 } else {
1825 initFunction();
1826 }
1827 }
1828 }
1829#else
1830 Q_UNUSED(loadTestability);
1831#endif // QT_CONFIG(library)
1832
1833 // trigger changed signal and event delivery
1834 QGuiApplication::setLayoutDirection(layout_direction);
1835
1836 if (!QGuiApplicationPrivate::displayName)
1837 QObject::connect(q, &QGuiApplication::applicationNameChanged,
1838 q, &QGuiApplication::applicationDisplayNameChanged);
1839}
1840
1841extern void qt_cleanupFontDatabase();
1842
1843QGuiApplicationPrivate::~QGuiApplicationPrivate()
1844{
1845#if defined(Q_OS_MACOS)
1846 QMacAutoReleasePool pool;
1847#endif
1848
1849 is_app_closing = true;
1850 is_app_running = false;
1851
1852 for (int i = 0; i < generic_plugin_list.size(); ++i)
1853 delete generic_plugin_list.at(i);
1854 generic_plugin_list.clear();
1855
1856 clearFontUnlocked();
1857
1858 QFont::cleanup();
1859
1860#ifndef QT_NO_CURSOR
1861 QCursorData::cleanup();
1862#endif
1863
1864 layout_direction = Qt::LayoutDirectionAuto;
1865
1866 cleanupThreadData();
1867
1868 delete QGuiApplicationPrivate::styleHints;
1869 QGuiApplicationPrivate::styleHints = nullptr;
1870 delete inputMethod;
1871
1872 qt_cleanupFontDatabase();
1873
1874 QPixmapCache::clear();
1875
1876#ifndef QT_NO_OPENGL
1877 if (ownGlobalShareContext) {
1878 delete qt_gl_global_share_context();
1879 qt_gl_set_global_share_context(nullptr);
1880 }
1881#endif
1882
1883#if QT_CONFIG(vulkan)
1884 QVulkanDefaultInstance::cleanup();
1885#endif
1886
1887 platform_integration->destroy();
1888
1889 delete platform_theme;
1890 platform_theme = nullptr;
1891 delete platform_integration;
1892 platform_integration = nullptr;
1893
1894 window_list.clear();
1895 popup_list.clear();
1896 screen_list.clear();
1897
1898 // Note: Not same as QCoreApplication::self
1899 QT_IGNORE_DEPRECATIONS(QGuiApplicationPrivate::self = nullptr;)
1900}
1901
1902#if 0
1903#ifndef QT_NO_CURSOR
1904QCursor *overrideCursor();
1905void setOverrideCursor(const QCursor &);
1906void changeOverrideCursor(const QCursor &);
1907void restoreOverrideCursor();
1908#endif
1909
1910static QFont font();
1911static QFont font(const QWidget*);
1912static QFont font(const char *className);
1913static void setFont(const QFont &, const char *className = nullptr);
1914static QFontMetrics fontMetrics();
1915
1916#ifndef QT_NO_CLIPBOARD
1917static QClipboard *clipboard();
1918#endif
1919#endif
1920
1921/*!
1922 Returns the current state of the modifier keys on the keyboard. The current
1923 state is updated synchronously as the event queue is emptied of events that
1924 will spontaneously change the keyboard state (QEvent::KeyPress and
1925 QEvent::KeyRelease events).
1926
1927 It should be noted this may not reflect the actual keys held on the input
1928 device at the time of calling but rather the modifiers as last reported in
1929 one of the above events. If no keys are being held Qt::NoModifier is
1930 returned.
1931
1932 \sa mouseButtons(), queryKeyboardModifiers()
1933*/
1934Qt::KeyboardModifiers QGuiApplication::keyboardModifiers()
1935{
1936 return QGuiApplicationPrivate::modifier_buttons;
1937}
1938
1939/*!
1940 \fn Qt::KeyboardModifiers QGuiApplication::queryKeyboardModifiers()
1941
1942 Queries and returns the state of the modifier keys on the keyboard.
1943 Unlike keyboardModifiers, this method returns the actual keys held
1944 on the input device at the time of calling the method.
1945
1946 It does not rely on the keypress events having been received by this
1947 process, which makes it possible to check the modifiers while moving
1948 a window, for instance. Note that in most cases, you should use
1949 keyboardModifiers(), which is faster and more accurate since it contains
1950 the state of the modifiers as they were when the currently processed
1951 event was received.
1952
1953 \sa keyboardModifiers()
1954*/
1955Qt::KeyboardModifiers QGuiApplication::queryKeyboardModifiers()
1956{
1957 CHECK_QAPP_INSTANCE(Qt::KeyboardModifiers{})
1958 QPlatformIntegration *pi = QGuiApplicationPrivate::platformIntegration();
1959 return pi->keyMapper()->queryKeyboardModifiers();
1960}
1961
1962/*!
1963 Returns the current state of the buttons on the mouse. The current state is
1964 updated synchronously as the event queue is emptied of events that will
1965 spontaneously change the mouse state (QEvent::MouseButtonPress and
1966 QEvent::MouseButtonRelease events).
1967
1968 It should be noted this may not reflect the actual buttons held on the
1969 input device at the time of calling but rather the mouse buttons as last
1970 reported in one of the above events. If no mouse buttons are being held
1971 Qt::NoButton is returned.
1972
1973 \sa keyboardModifiers()
1974*/
1975Qt::MouseButtons QGuiApplication::mouseButtons()
1976{
1977 return QGuiApplicationPrivate::mouse_buttons;
1978}
1979
1980/*!
1981 \internal
1982 Returns the platform's native interface, for platform specific
1983 functionality.
1984*/
1985QPlatformNativeInterface *QGuiApplication::platformNativeInterface()
1986{
1987 QPlatformIntegration *pi = QGuiApplicationPrivate::platformIntegration();
1988 return pi ? pi->nativeInterface() : nullptr;
1989}
1990
1991/*!
1992 \internal
1993 Returns a function pointer from the platformplugin matching \a function
1994*/
1995QFunctionPointer QGuiApplication::platformFunction(const QByteArray &function)
1996{
1997 QPlatformIntegration *pi = QGuiApplicationPrivate::platformIntegration();
1998 if (!pi) {
1999 qWarning("QGuiApplication::platformFunction(): Must construct a QGuiApplication before accessing a platform function");
2000 return nullptr;
2001 }
2002
2003 return pi->nativeInterface() ? pi->nativeInterface()->platformFunction(function) : nullptr;
2004}
2005
2006/*!
2007 Enters the main event loop and waits until exit() is called, and then
2008 returns the value that was set to exit() (which is 0 if exit() is called
2009 via quit()).
2010
2011 It is necessary to call this function to start event handling. The main
2012 event loop receives events from the window system and dispatches these to
2013 the application widgets.
2014
2015 Generally, no user interaction can take place before calling exec().
2016
2017 To make your application perform idle processing, e.g., executing a
2018 special function whenever there are no pending events, use a QChronoTimer
2019 with 0ns timeout. More advanced idle processing schemes can be achieved
2020 using processEvents().
2021
2022 We recommend that you connect clean-up code to the
2023 \l{QCoreApplication::}{aboutToQuit()} signal, instead of putting it in your
2024 application's \c{main()} function. This is because, on some platforms, the
2025 QApplication::exec() call may not return.
2026
2027 \sa quitOnLastWindowClosed, quit(), exit(), processEvents(),
2028 QCoreApplication::exec()
2029*/
2030int QGuiApplication::exec()
2031{
2032#if QT_CONFIG(accessibility)
2033 QAccessible::setRootObject(qApp);
2034#endif
2035 return QCoreApplication::exec();
2036}
2037
2038void QGuiApplicationPrivate::captureGlobalModifierState(QEvent *e)
2039{
2040 if (e->spontaneous()) {
2041 // Capture the current mouse and keyboard states. Doing so here is
2042 // required in order to support Qt Test synthesized events. Real mouse
2043 // and keyboard state updates from the platform plugin are managed by
2044 // QGuiApplicationPrivate::process(Mouse|Wheel|Key|Touch|Tablet)Event();
2045 // ### FIXME: Qt Test should not call qapp->notify(), but rather route
2046 // the events through the proper QPA interface. This is required to
2047 // properly generate all other events such as enter/leave etc.
2048 switch (e->type()) {
2049 case QEvent::MouseButtonPress: {
2050 QMouseEvent *me = static_cast<QMouseEvent *>(e);
2051 QGuiApplicationPrivate::modifier_buttons = me->modifiers();
2052 QGuiApplicationPrivate::mouse_buttons |= me->button();
2053 break;
2054 }
2055 case QEvent::MouseButtonDblClick: {
2056 QMouseEvent *me = static_cast<QMouseEvent *>(e);
2057 QGuiApplicationPrivate::modifier_buttons = me->modifiers();
2058 QGuiApplicationPrivate::mouse_buttons |= me->button();
2059 break;
2060 }
2061 case QEvent::MouseButtonRelease: {
2062 QMouseEvent *me = static_cast<QMouseEvent *>(e);
2063 QGuiApplicationPrivate::modifier_buttons = me->modifiers();
2064 QGuiApplicationPrivate::mouse_buttons &= ~me->button();
2065 break;
2066 }
2067 case QEvent::KeyPress:
2068 case QEvent::KeyRelease:
2069 case QEvent::MouseMove:
2070#if QT_CONFIG(wheelevent)
2071 case QEvent::Wheel:
2072#endif
2073 case QEvent::TouchBegin:
2074 case QEvent::TouchUpdate:
2075 case QEvent::TouchEnd:
2076#if QT_CONFIG(tabletevent)
2077 case QEvent::TabletMove:
2078 case QEvent::TabletPress:
2079 case QEvent::TabletRelease:
2080#endif
2081 {
2082 QInputEvent *ie = static_cast<QInputEvent *>(e);
2083 QGuiApplicationPrivate::modifier_buttons = ie->modifiers();
2084 break;
2085 }
2086 default:
2087 break;
2088 }
2089 }
2090}
2091
2092/*! \reimp
2093*/
2094bool QGuiApplication::notify(QObject *object, QEvent *event)
2095{
2096 Q_D(QGuiApplication);
2097 if (object->isWindowType()) {
2098 if (QGuiApplicationPrivate::sendQWindowEventToQPlatformWindow(static_cast<QWindow *>(object), event))
2099 return true; // Platform plugin ate the event
2100 }
2101
2102 switch (event->type()) {
2103 case QEvent::ApplicationDeactivate:
2104 case QEvent::OrientationChange:
2105 // Close all popups (triggers when switching applications
2106 // by pressing ALT-TAB on Windows, which is not received as a key event.
2107 // triggers when the screen rotates.)
2108 // This is also necessary on Wayland, and platforms where
2109 // QWindow::setMouseGrabEnabled(true) doesn't work.
2110 d->closeAllPopups();
2111 break;
2112 default:
2113 break;
2114 }
2115
2116 QGuiApplicationPrivate::captureGlobalModifierState(event);
2117
2118 return QCoreApplication::notify(object, event);
2119}
2120
2121/*! \reimp
2122*/
2123bool QGuiApplication::event(QEvent *e)
2124{
2125 switch (e->type()) {
2126 case QEvent::LanguageChange:
2127 // if the layout direction was set explicitly, then don't override it here
2128 if (layout_direction == Qt::LayoutDirectionAuto)
2129 setLayoutDirection(layout_direction);
2130 for (auto *topLevelWindow : QGuiApplication::topLevelWindows())
2131 postEvent(topLevelWindow, new QEvent(QEvent::LanguageChange));
2132 break;
2133 case QEvent::ApplicationFontChange:
2134 case QEvent::ApplicationPaletteChange:
2135 postEvent(QGuiApplication::styleHints(), e->clone());
2136 for (auto *topLevelWindow : QGuiApplication::topLevelWindows())
2137 postEvent(topLevelWindow, new QEvent(e->type()));
2138 break;
2139 case QEvent::ThemeChange:
2140 forwardEvent(QGuiApplication::styleHints(), e);
2141 for (auto *w : QGuiApplication::allWindows())
2142 forwardEvent(w, e);
2143 break;
2144 case QEvent::Quit:
2145 // Close open windows. This is done in order to deliver de-expose
2146 // events while the event loop is still running.
2147 for (QWindow *topLevelWindow : QGuiApplication::topLevelWindows()) {
2148 // Already closed windows will not have a platform window, skip those
2149 if (!topLevelWindow->handle())
2150 continue;
2151 if (!topLevelWindow->close()) {
2152 e->ignore();
2153 return true;
2154 }
2155 }
2156 break;
2157 default:
2158 break;
2159 }
2160 return QCoreApplication::event(e);
2161}
2162
2163#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
2164/*!
2165 \internal
2166*/
2167bool QGuiApplication::compressEvent(QEvent *event, QObject *receiver, QPostEventList *postedEvents)
2168{
2169 QT_IGNORE_DEPRECATIONS(
2170 return QCoreApplication::compressEvent(event, receiver, postedEvents);
2171 )
2172}
2173#endif
2174
2175bool QGuiApplicationPrivate::sendQWindowEventToQPlatformWindow(QWindow *window, QEvent *event)
2176{
2177 if (!window)
2178 return false;
2179 QPlatformWindow *platformWindow = window->handle();
2180 if (!platformWindow)
2181 return false;
2182 // spontaneous events come from the platform integration already, we don't need to send the events back
2183 if (event->spontaneous())
2184 return false;
2185 // let the platform window do any handling it needs to as well
2186 return platformWindow->windowEvent(event);
2187}
2188
2189bool QGuiApplicationPrivate::processNativeEvent(QWindow *window, const QByteArray &eventType, void *message, qintptr *result)
2190{
2191 return window->nativeEvent(eventType, message, result);
2192}
2193
2194bool QGuiApplicationPrivate::isUsingVirtualKeyboard()
2195{
2196 static const bool usingVirtualKeyboard = getenv("QT_IM_MODULE") == QByteArrayView("qtvirtualkeyboard");
2197 return usingVirtualKeyboard;
2198}
2199
2200// If a virtual keyboard exists, forward mouse event
2201bool QGuiApplicationPrivate::maybeForwardEventToVirtualKeyboard(QEvent *e)
2202{
2203 if (!isUsingVirtualKeyboard()) {
2204 qCDebug(lcVirtualKeyboard) << "Virtual keyboard not supported.";
2205 return false;
2206 }
2207
2208 static QPointer<QWindow> virtualKeyboard;
2209 const QEvent::Type type = e->type();
2210 Q_ASSERT(type == QEvent::MouseButtonPress || type == QEvent::MouseButtonRelease);
2211 const auto me = static_cast<QMouseEvent *>(e);
2212 const QPointF posF = me->globalPosition();
2213 const QPoint pos = posF.toPoint();
2214
2215 // Is there a visible virtual keyboard at event position?
2216 if (!virtualKeyboard) {
2217 if (QWindow *win = QGuiApplication::topLevelAt(pos);
2218 win->inherits("QtVirtualKeyboard::InputView")) {
2219 virtualKeyboard = win;
2220 } else {
2221 qCDebug(lcVirtualKeyboard) << "Virtual keyboard supported, but inactive.";
2222 return false;
2223 }
2224 }
2225
2226 Q_ASSERT(virtualKeyboard);
2227 const bool virtualKeyboardUnderMouse = virtualKeyboard->isVisible()
2228 && virtualKeyboard->geometry().contains(pos);
2229
2230 if (!virtualKeyboardUnderMouse) {
2231 qCDebug(lcVirtualKeyboard) << type << "at" << pos << "is outside geometry"
2232 << virtualKeyboard->geometry() << "of" << virtualKeyboard.data();
2233 return false;
2234 }
2235
2236 QMouseEvent vkbEvent(type, virtualKeyboard->mapFromGlobal(pos), pos,
2237 me->button(), me->buttons(), me->modifiers(),
2238 me->pointingDevice());
2239
2240 QGuiApplication::sendEvent(virtualKeyboard, &vkbEvent);
2241 qCDebug(lcVirtualKeyboard) << "Forwarded" << type << "to" << virtualKeyboard.data()
2242 << "at" << pos;
2243
2244 return true;
2245}
2246
2247void Q_TRACE_INSTRUMENT(qtgui) QGuiApplicationPrivate::processWindowSystemEvent(QWindowSystemInterfacePrivate::WindowSystemEvent *e)
2248{
2249 Q_TRACE_PARAM_REPLACE(QWindowSystemInterfacePrivate::WindowSystemEvent *, int);
2250 Q_TRACE_SCOPE(QGuiApplicationPrivate_processWindowSystemEvent, e->type);
2251
2252 const bool haveGuiApplication = QGuiApplication::instance() && QGuiApplicationPrivate::instance();
2253 Q_ASSERT_X(haveGuiApplication, "QGuiApplication", "Asked to process QPA event without a QGuiApplication");
2254 if (!haveGuiApplication) {
2255 qWarning("QGuiApplication was asked to process QPA event without a QGuiApplication instance");
2256 e->eventAccepted = false;
2257 return;
2258 }
2259
2260 switch(e->type) {
2261 case QWindowSystemInterfacePrivate::Mouse:
2262 QGuiApplicationPrivate::processMouseEvent(static_cast<QWindowSystemInterfacePrivate::MouseEvent *>(e));
2263 break;
2264 case QWindowSystemInterfacePrivate::Wheel:
2265 QGuiApplicationPrivate::processWheelEvent(static_cast<QWindowSystemInterfacePrivate::WheelEvent *>(e));
2266 break;
2267 case QWindowSystemInterfacePrivate::Key:
2268 QGuiApplicationPrivate::processKeyEvent(static_cast<QWindowSystemInterfacePrivate::KeyEvent *>(e));
2269 break;
2270 case QWindowSystemInterfacePrivate::Touch:
2271 QGuiApplicationPrivate::processTouchEvent(static_cast<QWindowSystemInterfacePrivate::TouchEvent *>(e));
2272 break;
2273 case QWindowSystemInterfacePrivate::GeometryChange:
2274 QGuiApplicationPrivate::processGeometryChangeEvent(static_cast<QWindowSystemInterfacePrivate::GeometryChangeEvent*>(e));
2275 break;
2276 case QWindowSystemInterfacePrivate::Enter:
2277 QGuiApplicationPrivate::processEnterEvent(static_cast<QWindowSystemInterfacePrivate::EnterEvent *>(e));
2278 break;
2279 case QWindowSystemInterfacePrivate::Leave:
2280 QGuiApplicationPrivate::processLeaveEvent(static_cast<QWindowSystemInterfacePrivate::LeaveEvent *>(e));
2281 break;
2282 case QWindowSystemInterfacePrivate::FocusWindow:
2283 QGuiApplicationPrivate::processFocusWindowEvent(static_cast<QWindowSystemInterfacePrivate::FocusWindowEvent *>(e));
2284 break;
2285 case QWindowSystemInterfacePrivate::WindowStateChanged:
2286 QGuiApplicationPrivate::processWindowStateChangedEvent(static_cast<QWindowSystemInterfacePrivate::WindowStateChangedEvent *>(e));
2287 break;
2288 case QWindowSystemInterfacePrivate::WindowScreenChanged:
2289 QGuiApplicationPrivate::processWindowScreenChangedEvent(static_cast<QWindowSystemInterfacePrivate::WindowScreenChangedEvent *>(e));
2290 break;
2291 case QWindowSystemInterfacePrivate::WindowDevicePixelRatioChanged:
2292 QGuiApplicationPrivate::processWindowDevicePixelRatioChangedEvent(static_cast<QWindowSystemInterfacePrivate::WindowDevicePixelRatioChangedEvent *>(e));
2293 break;
2294 case QWindowSystemInterfacePrivate::SafeAreaMarginsChanged:
2295 QGuiApplicationPrivate::processSafeAreaMarginsChangedEvent(static_cast<QWindowSystemInterfacePrivate::SafeAreaMarginsChangedEvent *>(e));
2296 break;
2297 case QWindowSystemInterfacePrivate::ApplicationStateChanged: {
2298 QWindowSystemInterfacePrivate::ApplicationStateChangedEvent * changeEvent = static_cast<QWindowSystemInterfacePrivate::ApplicationStateChangedEvent *>(e);
2299 QGuiApplicationPrivate::setApplicationState(changeEvent->newState, changeEvent->forcePropagate); }
2300 break;
2301 case QWindowSystemInterfacePrivate::ApplicationTermination:
2302 QGuiApplicationPrivate::processApplicationTermination(e);
2303 break;
2304 case QWindowSystemInterfacePrivate::FlushEvents: {
2305 QWindowSystemInterfacePrivate::FlushEventsEvent *flushEventsEvent = static_cast<QWindowSystemInterfacePrivate::FlushEventsEvent *>(e);
2306 QWindowSystemInterface::deferredFlushWindowSystemEvents(flushEventsEvent->flags); }
2307 break;
2308 case QWindowSystemInterfacePrivate::Close:
2309 QGuiApplicationPrivate::processCloseEvent(
2310 static_cast<QWindowSystemInterfacePrivate::CloseEvent *>(e));
2311 break;
2312 case QWindowSystemInterfacePrivate::ScreenOrientation:
2313 QGuiApplicationPrivate::processScreenOrientationChange(
2314 static_cast<QWindowSystemInterfacePrivate::ScreenOrientationEvent *>(e));
2315 break;
2316 case QWindowSystemInterfacePrivate::ScreenGeometry:
2317 QGuiApplicationPrivate::processScreenGeometryChange(
2318 static_cast<QWindowSystemInterfacePrivate::ScreenGeometryEvent *>(e));
2319 break;
2320 case QWindowSystemInterfacePrivate::ScreenLogicalDotsPerInch:
2321 QGuiApplicationPrivate::processScreenLogicalDotsPerInchChange(
2322 static_cast<QWindowSystemInterfacePrivate::ScreenLogicalDotsPerInchEvent *>(e));
2323 break;
2324 case QWindowSystemInterfacePrivate::ScreenRefreshRate:
2325 QGuiApplicationPrivate::processScreenRefreshRateChange(
2326 static_cast<QWindowSystemInterfacePrivate::ScreenRefreshRateEvent *>(e));
2327 break;
2328 case QWindowSystemInterfacePrivate::ThemeChange:
2329 QGuiApplicationPrivate::processThemeChanged(
2330 static_cast<QWindowSystemInterfacePrivate::ThemeChangeEvent *>(e));
2331 break;
2332 case QWindowSystemInterfacePrivate::Expose:
2333 QGuiApplicationPrivate::processExposeEvent(static_cast<QWindowSystemInterfacePrivate::ExposeEvent *>(e));
2334 break;
2335 case QWindowSystemInterfacePrivate::Paint:
2336 QGuiApplicationPrivate::processPaintEvent(static_cast<QWindowSystemInterfacePrivate::PaintEvent *>(e));
2337 break;
2338 case QWindowSystemInterfacePrivate::Tablet:
2339 QGuiApplicationPrivate::processTabletEvent(
2340 static_cast<QWindowSystemInterfacePrivate::TabletEvent *>(e));
2341 break;
2342 case QWindowSystemInterfacePrivate::TabletEnterProximity:
2343 QGuiApplicationPrivate::processTabletEnterProximityEvent(
2344 static_cast<QWindowSystemInterfacePrivate::TabletEnterProximityEvent *>(e));
2345 break;
2346 case QWindowSystemInterfacePrivate::TabletLeaveProximity:
2347 QGuiApplicationPrivate::processTabletLeaveProximityEvent(
2348 static_cast<QWindowSystemInterfacePrivate::TabletLeaveProximityEvent *>(e));
2349 break;
2350#ifndef QT_NO_GESTURES
2351 case QWindowSystemInterfacePrivate::Gesture:
2352 QGuiApplicationPrivate::processGestureEvent(
2353 static_cast<QWindowSystemInterfacePrivate::GestureEvent *>(e));
2354 break;
2355#endif
2356 case QWindowSystemInterfacePrivate::PlatformPanel:
2357 QGuiApplicationPrivate::processPlatformPanelEvent(
2358 static_cast<QWindowSystemInterfacePrivate::PlatformPanelEvent *>(e));
2359 break;
2360 case QWindowSystemInterfacePrivate::FileOpen:
2361 QGuiApplicationPrivate::processFileOpenEvent(
2362 static_cast<QWindowSystemInterfacePrivate::FileOpenEvent *>(e));
2363 break;
2364#ifndef QT_NO_CONTEXTMENU
2365 case QWindowSystemInterfacePrivate::ContextMenu:
2366 QGuiApplicationPrivate::processContextMenuEvent(
2367 static_cast<QWindowSystemInterfacePrivate::ContextMenuEvent *>(e));
2368 break;
2369#endif
2370 case QWindowSystemInterfacePrivate::EnterWhatsThisMode:
2371 QGuiApplication::postEvent(QGuiApplication::instance(), new QEvent(QEvent::EnterWhatsThisMode));
2372 break;
2373 default:
2374 qWarning() << "Unknown user input event type:" << e->type;
2375 break;
2376 }
2377}
2378
2379/*! \internal
2380
2381 History is silent on why Qt splits mouse events that change position and
2382 button state at the same time. We believe that this was done to emulate mouse
2383 behavior on touch screens. If mouse tracking is enabled, we will get move
2384 events before the button is pressed. A touch panel does not generally give
2385 move events when not pressed, so without event splitting code path we would
2386 only see a press in a new location without any intervening moves. This could
2387 confuse code that is written for a real mouse. The same is true for mouse
2388 release events that change position, see tst_QWidget::touchEventSynthesizedMouseEvent()
2389 and tst_QWindow::generatedMouseMove() auto tests.
2390*/
2391void QGuiApplicationPrivate::processMouseEvent(QWindowSystemInterfacePrivate::MouseEvent *e)
2392{
2393 QEvent::Type type = QEvent::None;
2394 Qt::MouseButton button = Qt::NoButton;
2395 QWindow *window = e->window.data();
2396 const QPointingDevice *device = static_cast<const QPointingDevice *>(e->device);
2397 Q_ASSERT(device);
2398 QPointingDevicePrivate *devPriv = QPointingDevicePrivate::get(const_cast<QPointingDevice*>(device));
2399 bool positionChanged = QGuiApplicationPrivate::lastCursorPosition != e->globalPos;
2400 bool mouseMove = false;
2401 bool mousePress = false;
2402 const QPointF lastGlobalPosition = QGuiApplicationPrivate::lastCursorPosition;
2403 QPointF globalPoint = e->globalPos;
2404
2405 if (qIsNaN(e->globalPos.x()) || qIsNaN(e->globalPos.y())) {
2406 qWarning("QGuiApplicationPrivate::processMouseEvent: Got NaN in mouse position");
2407 return;
2408 }
2409
2410 type = e->buttonType;
2411 button = e->button;
2412
2413 if (type == QEvent::NonClientAreaMouseMove || type == QEvent::MouseMove)
2414 mouseMove = true;
2415 else if (type == QEvent::NonClientAreaMouseButtonPress || type == QEvent::MouseButtonPress)
2416 mousePress = true;
2417
2418 if (!mouseMove && positionChanged) {
2419 QWindowSystemInterfacePrivate::MouseEvent moveEvent(window, e->timestamp,
2420 e->localPos, e->globalPos, e->buttons ^ button, e->modifiers, Qt::NoButton,
2421 e->nonClientArea ? QEvent::NonClientAreaMouseMove : QEvent::MouseMove,
2422 e->source, e->nonClientArea, device, e->eventPointId);
2423 if (e->synthetic())
2424 moveEvent.flags |= QWindowSystemInterfacePrivate::WindowSystemEvent::Synthetic;
2425 processMouseEvent(&moveEvent); // mouse move excluding state change
2426 processMouseEvent(e); // the original mouse event
2427 return;
2428 }
2429 if (type == QEvent::MouseMove && !positionChanged) {
2430 // On Windows, and possibly other platforms, a touchpad can send a mouse move
2431 // that does not change position, between a press and a release. This may
2432 // confuse applications, so we always filter out these mouse events for
2433 // consistent behavior among platforms.
2434 return;
2435 }
2436
2437 modifier_buttons = e->modifiers;
2438 QPointF localPoint = e->localPos;
2439 bool doubleClick = false;
2440 auto persistentEPD = devPriv->pointById(0);
2441
2442 if (e->synthetic(); auto *originalDeviceEPD = devPriv->queryPointById(e->eventPointId))
2443 QMutableEventPoint::update(originalDeviceEPD->eventPoint, persistentEPD->eventPoint);
2444
2445 if (mouseMove) {
2446 QGuiApplicationPrivate::lastCursorPosition = globalPoint;
2447 const auto doubleClickDistance = (e->device && e->device->type() == QInputDevice::DeviceType::Mouse ?
2448 mouseDoubleClickDistance : touchDoubleTapDistance);
2449 const auto pressPos = persistentEPD->eventPoint.globalPressPosition();
2450 if (qAbs(globalPoint.x() - pressPos.x()) > doubleClickDistance ||
2451 qAbs(globalPoint.y() - pressPos.y()) > doubleClickDistance)
2452 mousePressButton = Qt::NoButton;
2453 } else {
2454 static unsigned long lastPressTimestamp = 0;
2455 static QPointer<QWindow> lastPressWindow = nullptr;
2456 mouse_buttons = e->buttons;
2457 if (mousePress) {
2458 ulong doubleClickInterval = static_cast<ulong>(QGuiApplication::styleHints()->mouseDoubleClickInterval());
2459 const auto timestampDelta = e->timestamp - lastPressTimestamp;
2460 doubleClick = timestampDelta > 0 && timestampDelta < doubleClickInterval
2461 && button == mousePressButton && lastPressWindow == e->window;
2462 mousePressButton = button;
2463 lastPressTimestamp = e ->timestamp;
2464 lastPressWindow = e->window;
2465 }
2466 }
2467
2468 if (e->nullWindow()) {
2469 window = QGuiApplication::topLevelAt(globalPoint.toPoint());
2470 if (window) {
2471 // Moves and the release following a press must go to the same
2472 // window, even if the cursor has moved on over another window.
2473 if (e->buttons != Qt::NoButton) {
2474 if (!currentMousePressWindow)
2475 currentMousePressWindow = window;
2476 else
2477 window = currentMousePressWindow;
2478 } else if (currentMousePressWindow) {
2479 window = currentMousePressWindow;
2480 currentMousePressWindow = nullptr;
2481 }
2482 localPoint = window->mapFromGlobal(globalPoint);
2483 }
2484 }
2485
2486 if (!window)
2487 return;
2488
2489#ifndef QT_NO_CURSOR
2490 if (!e->synthetic()) {
2491 if (const QScreen *screen = window->screen())
2492 if (QPlatformCursor *cursor = screen->handle()->cursor()) {
2493 const QPointF nativeLocalPoint = QHighDpi::toNativePixels(localPoint, screen);
2494 const QPointF nativeGlobalPoint = QHighDpi::toNativePixels(globalPoint, screen);
2495 QMouseEvent ev(type, nativeLocalPoint, nativeLocalPoint, nativeGlobalPoint,
2496 button, e->buttons, e->modifiers, e->source, device);
2497 // avoid incorrect velocity calculation: ev is in the native coordinate system,
2498 // but we need to consistently use the logical coordinate system for velocity
2499 // whenever QEventPoint::setTimestamp() is called
2500 ev.QInputEvent::setTimestamp(e->timestamp);
2501 cursor->pointerEvent(ev);
2502 }
2503 }
2504#endif
2505
2506 const auto *activePopup = activePopupWindow();
2507 if (type == QEvent::MouseButtonPress)
2508 active_popup_on_press = activePopup;
2509 if (window->d_func()->blockedByModalWindow && !activePopup) {
2510 // a modal window is blocking this window, don't allow mouse events through
2511 return;
2512 }
2513
2514 QMouseEvent ev(type, localPoint, localPoint, globalPoint, button, e->buttons, e->modifiers, e->source, device);
2515 Q_ASSERT(devPriv->pointById(0) == persistentEPD); // we don't expect reallocation in QPlatformCursor::pointerEvenmt()
2516 // restore globalLastPosition to avoid invalidating the velocity calculations,
2517 // because the QPlatformCursor mouse event above was in native coordinates
2518 QMutableEventPoint::setGlobalLastPosition(persistentEPD->eventPoint, lastGlobalPosition);
2519 persistentEPD = nullptr; // incoming and synth events can cause reallocation during delivery, so don't use this again
2520 // ev now contains a detached copy of the QEventPoint from QPointingDevicePrivate::activePoints
2521 ev.setTimestamp(e->timestamp);
2522
2523 if (activePopup && activePopup != window && (!popup_closed_on_press || type == QEvent::MouseButtonRelease)) {
2524 // If the popup handles the event, we're done.
2525 auto *handlingPopup = window->d_func()->forwardToPopup(&ev, active_popup_on_press);
2526 if (handlingPopup) {
2527 if (type == QEvent::MouseButtonPress)
2528 active_popup_on_press = handlingPopup;
2529 return;
2530 }
2531 }
2532
2533 if (doubleClick && (ev.type() == QEvent::MouseButtonPress)) {
2534 // QtBUG-25831, used to suppress delivery in qwidgetwindow.cpp
2535 QMutableSinglePointEvent::setDoubleClick(&ev, true);
2536 }
2537
2538 QGuiApplication::sendSpontaneousEvent(window, &ev);
2539 e->eventAccepted = ev.isAccepted();
2540 if (!e->synthetic() && !ev.isAccepted()
2541 && !e->nonClientArea
2542 && qApp->testAttribute(Qt::AA_SynthesizeTouchForUnhandledMouseEvents)) {
2543 QList<QWindowSystemInterface::TouchPoint> points;
2544 QWindowSystemInterface::TouchPoint point;
2545 point.id = 1;
2546 point.area = QHighDpi::toNativePixels(QRectF(globalPoint.x() - 2, globalPoint.y() - 2, 4, 4), window);
2547
2548 // only translate left button related events to
2549 // avoid strange touch event sequences when several
2550 // buttons are pressed
2551 if (type == QEvent::MouseButtonPress && button == Qt::LeftButton) {
2552 point.state = QEventPoint::State::Pressed;
2553 } else if (type == QEvent::MouseButtonRelease && button == Qt::LeftButton) {
2554 point.state = QEventPoint::State::Released;
2555 } else if (type == QEvent::MouseMove && (e->buttons & Qt::LeftButton)) {
2556 point.state = QEventPoint::State::Updated;
2557 } else {
2558 return;
2559 }
2560
2561 points << point;
2562
2563 QEvent::Type type;
2564 const QList<QEventPoint> &touchPoints =
2565 QWindowSystemInterfacePrivate::fromNativeTouchPoints(points, window, &type);
2566
2567 QWindowSystemInterfacePrivate::TouchEvent fake(window, e->timestamp, type, device, touchPoints, e->modifiers);
2568 fake.flags |= QWindowSystemInterfacePrivate::WindowSystemEvent::Synthetic;
2569 processTouchEvent(&fake);
2570 }
2571 if (doubleClick) {
2572 mousePressButton = Qt::NoButton;
2573 if (!e->window.isNull() || e->nullWindow()) { // QTBUG-36364, check if window closed in response to press
2574 const QEvent::Type doubleClickType = e->nonClientArea ? QEvent::NonClientAreaMouseButtonDblClick : QEvent::MouseButtonDblClick;
2575 QMouseEvent dblClickEvent(doubleClickType, localPoint, localPoint, globalPoint,
2576 button, e->buttons, e->modifiers, e->source, device);
2577 dblClickEvent.setTimestamp(e->timestamp);
2578 QGuiApplication::sendSpontaneousEvent(window, &dblClickEvent);
2579 }
2580 }
2581 if (type == QEvent::MouseButtonRelease && e->buttons == Qt::NoButton) {
2582 popup_closed_on_press = false;
2583 if (auto *persistentEPD = devPriv->queryPointById(0)) {
2584 ev.setExclusiveGrabber(persistentEPD->eventPoint, nullptr);
2585 ev.clearPassiveGrabbers(persistentEPD->eventPoint);
2586 }
2587 }
2588}
2589
2590void QGuiApplicationPrivate::processWheelEvent(QWindowSystemInterfacePrivate::WheelEvent *e)
2591{
2592#if QT_CONFIG(wheelevent)
2593 QWindow *window = e->window.data();
2594 QPointF globalPoint = e->globalPos;
2595 QPointF localPoint = e->localPos;
2596
2597 if (e->nullWindow()) {
2598 window = QGuiApplication::topLevelAt(globalPoint.toPoint());
2599 if (window)
2600 localPoint = window->mapFromGlobal(globalPoint);
2601 }
2602
2603 if (!window)
2604 return;
2605
2606 QGuiApplicationPrivate::lastCursorPosition = globalPoint;
2607 modifier_buttons = e->modifiers;
2608
2609 if (window->d_func()->blockedByModalWindow) {
2610 // a modal window is blocking this window, don't allow wheel events through
2611 return;
2612 }
2613
2614 const QPointingDevice *device = static_cast<const QPointingDevice *>(e->device);
2615 QWheelEvent ev(localPoint, globalPoint, e->pixelDelta, e->angleDelta,
2616 mouse_buttons, e->modifiers, e->phase, e->inverted, e->source, device);
2617 ev.setTimestamp(e->timestamp);
2618 QGuiApplication::sendSpontaneousEvent(window, &ev);
2619 e->eventAccepted = ev.isAccepted();
2620#else
2621 Q_UNUSED(e);
2622#endif // QT_CONFIG(wheelevent)
2623}
2624
2625void QGuiApplicationPrivate::processKeyEvent(QWindowSystemInterfacePrivate::KeyEvent *e)
2626{
2627 QWindow *window = e->window.data();
2628 modifier_buttons = e->modifiers;
2629 if (e->nullWindow())
2630 window = QGuiApplication::focusWindow();
2631
2632 if (!window) {
2633 e->eventAccepted = false;
2634 return;
2635 }
2636
2637#if !defined(Q_OS_MACOS)
2638 // FIXME: Include OS X in this code path by passing the key event through
2639 // QPlatformInputContext::filterEvent().
2640 if (e->keyType == QEvent::KeyPress) {
2641 if (QWindowSystemInterface::handleShortcutEvent(window, e->timestamp, e->key, e->modifiers,
2642 e->nativeScanCode, e->nativeVirtualKey, e->nativeModifiers, e->unicode, e->repeat, e->repeatCount)) {
2643 return;
2644 }
2645 }
2646#endif
2647
2648 QKeyEvent ev(e->keyType, e->key, e->modifiers,
2649 e->nativeScanCode, e->nativeVirtualKey, e->nativeModifiers,
2650 e->unicode, e->repeat, e->repeatCount);
2651 ev.setTimestamp(e->timestamp);
2652
2653 const auto *activePopup = activePopupWindow();
2654 if (activePopup && activePopup != window) {
2655 // If the popup handles the event, we're done.
2656 if (window->d_func()->forwardToPopup(&ev, active_popup_on_press))
2657 return;
2658 }
2659
2660 // only deliver key events when we have a window, and no modal window is blocking this window
2661
2662 if (!window->d_func()->blockedByModalWindow)
2663 QGuiApplication::sendSpontaneousEvent(window, &ev);
2664#ifdef Q_OS_ANDROID
2665 else
2666 ev.setAccepted(false);
2667#endif
2668 e->eventAccepted = ev.isAccepted();
2669}
2670
2671void QGuiApplicationPrivate::processEnterEvent(QWindowSystemInterfacePrivate::EnterEvent *e)
2672{
2673 if (!e->enter)
2674 return;
2675 if (e->enter.data()->d_func()->blockedByModalWindow) {
2676 // a modal window is blocking this window, don't allow enter events through
2677 return;
2678 }
2679
2680 currentMouseWindow = e->enter;
2681
2682 // TODO later: EnterEvent must report _which_ mouse entered the window; for now we assume primaryPointingDevice()
2683 QEnterEvent event(e->localPos, e->localPos, e->globalPos);
2684
2685 // Since we don't always track mouse moves that occur outside a window, any residual velocity
2686 // stored in the persistent QEventPoint may be inaccurate (especially in fast-moving autotests).
2687 // Reset the Kalman filter so that the velocity of the first mouse event after entering the window
2688 // will be based on a zero residual velocity (but the result can still be non-zero if the mouse
2689 // moves to a different position from where this enter event occurred; tests often do that).
2690 const QPointingDevicePrivate *devPriv = QPointingDevicePrivate::get(event.pointingDevice());
2691 auto epd = devPriv->queryPointById(event.points().first().id());
2692 Q_ASSERT(epd);
2693 QMutableEventPoint::setVelocity(epd->eventPoint, {});
2694
2695 QCoreApplication::sendSpontaneousEvent(e->enter.data(), &event);
2696}
2697
2698void QGuiApplicationPrivate::processLeaveEvent(QWindowSystemInterfacePrivate::LeaveEvent *e)
2699{
2700 if (!e->leave)
2701 return;
2702 if (e->leave.data()->d_func()->blockedByModalWindow) {
2703 // a modal window is blocking this window, don't allow leave events through
2704 return;
2705 }
2706
2707 currentMouseWindow = nullptr;
2708
2709 QEvent event(QEvent::Leave);
2710 QCoreApplication::sendSpontaneousEvent(e->leave.data(), &event);
2711}
2712
2713void QGuiApplicationPrivate::processFocusWindowEvent(QWindowSystemInterfacePrivate::FocusWindowEvent *e)
2714{
2715 QWindow *previous = QGuiApplicationPrivate::focus_window;
2716 QWindow *newFocus = e->focused.data();
2717
2718 if (previous == newFocus)
2719 return;
2720
2721 bool activatedPopup = false;
2722 if (newFocus) {
2723 if (QPlatformWindow *platformWindow = newFocus->handle())
2724 if (platformWindow->isAlertState())
2725 platformWindow->setAlertState(false);
2726 activatedPopup = (newFocus->flags() & Qt::WindowType_Mask) == Qt::Popup;
2727 if (activatedPopup)
2728 activatePopup(newFocus);
2729 }
2730
2731 QObject *previousFocusObject = previous ? previous->focusObject() : nullptr;
2732
2733 if (previous) {
2734 QFocusEvent focusAboutToChange(QEvent::FocusAboutToChange);
2735 QCoreApplication::sendSpontaneousEvent(previous, &focusAboutToChange);
2736 }
2737
2738 QGuiApplicationPrivate::focus_window = newFocus;
2739 if (!qApp)
2740 return;
2741
2742 if (previous) {
2743 Qt::FocusReason r = e->reason;
2744 if ((r == Qt::OtherFocusReason || r == Qt::ActiveWindowFocusReason) && activatedPopup)
2745 r = Qt::PopupFocusReason;
2746 QFocusEvent focusOut(QEvent::FocusOut, r);
2747 QCoreApplication::sendSpontaneousEvent(previous, &focusOut);
2748 QObject::disconnect(previous, SIGNAL(focusObjectChanged(QObject*)),
2749 qApp, SLOT(_q_updateFocusObject(QObject*)));
2750 } else if (!platformIntegration()->hasCapability(QPlatformIntegration::ApplicationState)) {
2751 setApplicationState(Qt::ApplicationActive);
2752 }
2753
2754 if (QGuiApplicationPrivate::focus_window) {
2755 Qt::FocusReason r = e->reason;
2756 if ((r == Qt::OtherFocusReason || r == Qt::ActiveWindowFocusReason) &&
2757 previous && (previous->flags() & Qt::Popup) == Qt::Popup)
2758 r = Qt::PopupFocusReason;
2759 QFocusEvent focusIn(QEvent::FocusIn, r);
2760 QCoreApplication::sendSpontaneousEvent(QGuiApplicationPrivate::focus_window, &focusIn);
2761 QObject::connect(QGuiApplicationPrivate::focus_window, SIGNAL(focusObjectChanged(QObject*)),
2762 qApp, SLOT(_q_updateFocusObject(QObject*)));
2763 } else if (!platformIntegration()->hasCapability(QPlatformIntegration::ApplicationState)) {
2764 setApplicationState(Qt::ApplicationInactive);
2765 }
2766
2767 if (auto *guiAppPrivate = QGuiApplicationPrivate::instance()) {
2768 guiAppPrivate->notifyActiveWindowChange(previous);
2769
2770 if (previousFocusObject != qApp->focusObject() ||
2771 // We are getting an activation change but there is no new focusObject, and we also
2772 // don't have a previousFocusObject in the previously active window anymore. This can
2773 // happen when window gets destroyed (see QWidgetWindow::focusObject returning nullptr
2774 // when already in the QWidget destructor), so update the focusObject to avoid dangling
2775 // pointers. See also QWidget::clearFocus(), which tries to cover for this as well.
2776 (previous && previousFocusObject == nullptr && qApp->focusObject() == nullptr)) {
2777 guiAppPrivate->_q_updateFocusObject(qApp->focusObject());
2778 }
2779 }
2780
2781 emit qApp->focusWindowChanged(newFocus);
2782 if (previous)
2783 emit previous->activeChanged();
2784 if (newFocus)
2785 emit newFocus->activeChanged();
2786}
2787
2788void QGuiApplicationPrivate::processWindowStateChangedEvent(QWindowSystemInterfacePrivate::WindowStateChangedEvent *wse)
2789{
2790 if (QWindow *window = wse->window.data()) {
2791 QWindowPrivate *windowPrivate = qt_window_private(window);
2792 const auto originalEffectiveState = QWindowPrivate::effectiveState(windowPrivate->windowState);
2793
2794 windowPrivate->windowState = wse->newState;
2795 const auto newEffectiveState = QWindowPrivate::effectiveState(windowPrivate->windowState);
2796 if (newEffectiveState != originalEffectiveState)
2797 emit window->windowStateChanged(newEffectiveState);
2798
2799 windowPrivate->updateVisibility();
2800
2801 QWindowStateChangeEvent e(wse->oldState);
2802 QGuiApplication::sendSpontaneousEvent(window, &e);
2803 }
2804}
2805
2806void QGuiApplicationPrivate::processWindowScreenChangedEvent(QWindowSystemInterfacePrivate::WindowScreenChangedEvent *wse)
2807{
2808 QWindow *window = wse->window.data();
2809 if (!window)
2810 return;
2811
2812 QScreen *screen = wse->screen.data();
2813 if (window->screen() == screen)
2814 return;
2815
2816 auto *windowPrivate = QWindowPrivate::get(window);
2817 QWindow *topLevelWindow = windowPrivate->topLevelWindow(QWindow::ExcludeTransients);
2818 if (window == topLevelWindow) {
2819 if (screen)
2820 topLevelWindow->d_func()->setTopLevelScreen(screen, false /* recreate */);
2821 else // Fall back to default behavior, and try to find some appropriate screen
2822 topLevelWindow->setScreen(nullptr);
2823 } else if (screen) {
2824 // Child windows reflect the screen of their top level parent. When a
2825 // window is reparented into a window that lives on a different screen
2826 // we don't need to update the top level screen, but do need to emit
2827 // screen changes for the child and its children,
2828 windowPrivate->emitScreenChangedRecursion(screen);
2829 }
2830}
2831
2832void QGuiApplicationPrivate::processWindowDevicePixelRatioChangedEvent(QWindowSystemInterfacePrivate::WindowDevicePixelRatioChangedEvent *wde)
2833{
2834 if (wde->window.isNull())
2835 return;
2836 QWindowPrivate::get(wde->window)->updateDevicePixelRatio();
2837}
2838
2839void QGuiApplicationPrivate::processSafeAreaMarginsChangedEvent(QWindowSystemInterfacePrivate::SafeAreaMarginsChangedEvent *wse)
2840{
2841 if (wse->window.isNull())
2842 return;
2843
2844 emit wse->window->safeAreaMarginsChanged(wse->window->safeAreaMargins());
2845
2846 QEvent event(QEvent::SafeAreaMarginsChange);
2847 QGuiApplication::sendSpontaneousEvent(wse->window, &event);
2848}
2849
2850void QGuiApplicationPrivate::processThemeChanged(QWindowSystemInterfacePrivate::ThemeChangeEvent *)
2851{
2852 // FIXME: Remove check once we ensure that the platform plugin is
2853 // torn down before QGuiApplication.
2854 if (!qGuiApp)
2855 return;
2856
2857 if (auto *guiAppPrivate = QGuiApplicationPrivate::instance())
2858 guiAppPrivate->handleThemeChanged();
2859
2860 QIconPrivate::clearIconCache();
2861
2862 QEvent themeChangeEvent(QEvent::ThemeChange);
2863 QGuiApplication::sendSpontaneousEvent(qGuiApp, &themeChangeEvent);
2864}
2865
2866void QGuiApplicationPrivate::handleThemeChanged()
2867{
2868 QStyleHintsPrivate::get(QGuiApplication::styleHints())->update(platformTheme());
2869 updatePalette();
2870
2871 QIconLoader::instance()->updateSystemTheme();
2872 QAbstractFileIconProviderPrivate::clearIconTypeCache();
2873
2874 if (!(applicationResourceFlags & ApplicationFontExplicitlySet)) {
2875 const auto locker = qt_scoped_lock(applicationFontMutex);
2876 clearFontUnlocked();
2877 initFontUnlocked();
2878 }
2879 initThemeHints();
2880}
2881
2882void QGuiApplicationPrivate::processGeometryChangeEvent(QWindowSystemInterfacePrivate::GeometryChangeEvent *e)
2883{
2884 if (e->window.isNull())
2885 return;
2886
2887 QWindow *window = e->window.data();
2888 if (!window)
2889 return;
2890
2891 const QRect lastReportedGeometry = window->d_func()->geometry;
2892 const QRect requestedGeometry = e->requestedGeometry;
2893 const QRect actualGeometry = e->newGeometry;
2894
2895 // We send size and move events only if the geometry has changed from
2896 // what was last reported, or if the user tried to set a new geometry,
2897 // but the window manager responded by keeping the old geometry. In the
2898 // latter case we send move/resize events with the same geometry as the
2899 // last reported geometry, to indicate that the window wasn't moved or
2900 // resized. Note that this logic does not apply to the property changes
2901 // of the window, as we don't treat them as part of this request/response
2902 // protocol of QWindow/QPA.
2903 const bool isResize = actualGeometry.size() != lastReportedGeometry.size()
2904 || requestedGeometry.size() != actualGeometry.size();
2905 const bool isMove = actualGeometry.topLeft() != lastReportedGeometry.topLeft()
2906 || requestedGeometry.topLeft() != actualGeometry.topLeft();
2907
2908 window->d_func()->geometry = actualGeometry;
2909
2910 if (isResize || window->d_func()->resizeEventPending) {
2911 QResizeEvent e(actualGeometry.size(), lastReportedGeometry.size());
2912 QGuiApplication::sendSpontaneousEvent(window, &e);
2913
2914 window->d_func()->resizeEventPending = false;
2915
2916 if (actualGeometry.width() != lastReportedGeometry.width())
2917 emit window->widthChanged(actualGeometry.width());
2918 if (actualGeometry.height() != lastReportedGeometry.height())
2919 emit window->heightChanged(actualGeometry.height());
2920 }
2921
2922 if (isMove) {
2923 //### frame geometry
2924 QMoveEvent e(actualGeometry.topLeft(), lastReportedGeometry.topLeft());
2925 QGuiApplication::sendSpontaneousEvent(window, &e);
2926
2927 if (actualGeometry.x() != lastReportedGeometry.x())
2928 emit window->xChanged(actualGeometry.x());
2929 if (actualGeometry.y() != lastReportedGeometry.y())
2930 emit window->yChanged(actualGeometry.y());
2931 }
2932}
2933
2934void QGuiApplicationPrivate::processCloseEvent(QWindowSystemInterfacePrivate::CloseEvent *e)
2935{
2936 if (e->window.isNull())
2937 return;
2938 if (e->window.data()->d_func()->blockedByModalWindow && !e->window.data()->d_func()->inClose) {
2939 // a modal window is blocking this window, don't allow close events through, unless they
2940 // originate from a call to QWindow::close.
2941 e->eventAccepted = false;
2942 return;
2943 }
2944
2945 QCloseEvent event;
2946 QGuiApplication::sendSpontaneousEvent(e->window.data(), &event);
2947
2948 e->eventAccepted = event.isAccepted();
2949}
2950
2951void QGuiApplicationPrivate::processFileOpenEvent(QWindowSystemInterfacePrivate::FileOpenEvent *e)
2952{
2953 if (e->url.isEmpty())
2954 return;
2955
2956 QFileOpenEvent event(e->url);
2957 QGuiApplication::sendSpontaneousEvent(qApp, &event);
2958}
2959
2960QGuiApplicationPrivate::TabletPointData &QGuiApplicationPrivate::tabletDevicePoint(qint64 deviceId)
2961{
2962 for (int i = 0; i < tabletDevicePoints.size(); ++i) {
2963 TabletPointData &pointData = tabletDevicePoints[i];
2964 if (pointData.deviceId == deviceId)
2965 return pointData;
2966 }
2967
2968 tabletDevicePoints.append(TabletPointData(deviceId));
2969 return tabletDevicePoints.last();
2970}
2971
2972void QGuiApplicationPrivate::processTabletEvent(QWindowSystemInterfacePrivate::TabletEvent *e)
2973{
2974#if QT_CONFIG(tabletevent)
2975 const auto device = static_cast<const QPointingDevice *>(e->device);
2976 TabletPointData &pointData = tabletDevicePoint(device->uniqueId().numericId());
2977
2978 QEvent::Type type = QEvent::TabletMove;
2979 if (e->buttons != pointData.state)
2980 type = (e->buttons > pointData.state) ? QEvent::TabletPress : QEvent::TabletRelease;
2981
2982 QWindow *window = e->window.data();
2983 modifier_buttons = e->modifiers;
2984
2985 bool localValid = true;
2986 // If window is null, pick one based on the global position and make sure all
2987 // subsequent events up to the release are delivered to that same window.
2988 // If window is given, just send to that.
2989 if (type == QEvent::TabletPress) {
2990 if (e->nullWindow()) {
2991 window = QGuiApplication::topLevelAt(e->global.toPoint());
2992 localValid = false;
2993 }
2994 if (!window)
2995 return;
2996 active_popup_on_press = activePopupWindow();
2997 pointData.target = window;
2998 } else {
2999 if (e->nullWindow()) {
3000 window = pointData.target;
3001 localValid = false;
3002 }
3003 if (type == QEvent::TabletRelease)
3004 pointData.target = nullptr;
3005 if (!window)
3006 return;
3007 }
3008 QPointF local = e->local;
3009 if (!localValid) {
3010 QPointF delta = e->global - e->global.toPoint();
3011 local = window->mapFromGlobal(e->global.toPoint()) + delta;
3012 }
3013
3014 // TODO stop deducing the button state change here: rather require it from the platform plugin, as with mouse events
3015 Qt::MouseButtons stateChange = e->buttons ^ pointData.state;
3016 Qt::MouseButton button = Qt::NoButton;
3017 for (int check = Qt::LeftButton; check <= int(Qt::MaxMouseButton); check = check << 1) {
3018 if (check & stateChange) {
3019 button = Qt::MouseButton(check);
3020 break;
3021 }
3022 }
3023
3024 const auto *activePopup = activePopupWindow();
3025 if (window->d_func()->blockedByModalWindow && !activePopup) {
3026 // a modal window is blocking this window, don't allow events through
3027 return;
3028 }
3029
3030 QTabletEvent tabletEvent(type, device, local, e->global,
3031 e->pressure, e->xTilt, e->yTilt,
3032 e->tangentialPressure, e->rotation, e->z,
3033 e->modifiers, button, e->buttons);
3034 tabletEvent.setAccepted(false);
3035 tabletEvent.setTimestamp(e->timestamp);
3036
3037 if (activePopup && activePopup != window) {
3038 // If the popup handles the event, we're done.
3039 if (window->d_func()->forwardToPopup(&tabletEvent, active_popup_on_press))
3040 return;
3041 }
3042
3043 QGuiApplication::sendSpontaneousEvent(window, &tabletEvent);
3044 pointData.state = e->buttons;
3045 if (!tabletEvent.isAccepted()
3046 && !QWindowSystemInterfacePrivate::TabletEvent::platformSynthesizesMouse
3047 && qApp->testAttribute(Qt::AA_SynthesizeMouseForUnhandledTabletEvents)) {
3048
3049 const QEvent::Type mouseType = [&]() {
3050 switch (type) {
3051 case QEvent::TabletPress: return QEvent::MouseButtonPress;
3052 case QEvent::TabletMove: return QEvent::MouseMove;
3053 case QEvent::TabletRelease: return QEvent::MouseButtonRelease;
3054 default: Q_UNREACHABLE();
3055 }
3056 }();
3057 QWindowSystemInterfacePrivate::MouseEvent mouseEvent(window, e->timestamp, e->local,
3058 e->global, e->buttons, e->modifiers, button, mouseType, Qt::MouseEventNotSynthesized, false, device);
3059 mouseEvent.flags |= QWindowSystemInterfacePrivate::WindowSystemEvent::Synthetic;
3060 qCDebug(lcPtrDispatch) << "synthesizing mouse from tablet event" << mouseType
3061 << e->local << button << e->buttons << e->modifiers;
3062 processMouseEvent(&mouseEvent);
3063 }
3064#else
3065 Q_UNUSED(e);
3066#endif
3067}
3068
3069void QGuiApplicationPrivate::processTabletEnterProximityEvent(QWindowSystemInterfacePrivate::TabletEnterProximityEvent *e)
3070{
3071#if QT_CONFIG(tabletevent)
3072 const QPointingDevice *dev = static_cast<const QPointingDevice *>(e->device);
3073 QTabletEvent ev(QEvent::TabletEnterProximity, dev, e->local, e->global,
3074 e->pressure, e->xTilt, e->yTilt,
3075 e->tangentialPressure, e->rotation, e->z,
3076 e->modifiers, Qt::NoButton,
3077 tabletDevicePoint(dev->uniqueId().numericId()).state);
3078 ev.setTimestamp(e->timestamp);
3079 QGuiApplication::sendSpontaneousEvent(qGuiApp, &ev);
3080#else
3081 Q_UNUSED(e);
3082#endif
3083}
3084
3085void QGuiApplicationPrivate::processTabletLeaveProximityEvent(QWindowSystemInterfacePrivate::TabletLeaveProximityEvent *e)
3086{
3087#if QT_CONFIG(tabletevent)
3088 const QPointingDevice *dev = static_cast<const QPointingDevice *>(e->device);
3089 QTabletEvent ev(QEvent::TabletLeaveProximity, dev, e->local, e->global,
3090 e->pressure, e->xTilt, e->yTilt,
3091 e->tangentialPressure, e->rotation, e->z,
3092 e->modifiers, Qt::NoButton,
3093 tabletDevicePoint(dev->uniqueId().numericId()).state);
3094 ev.setTimestamp(e->timestamp);
3095 QGuiApplication::sendSpontaneousEvent(qGuiApp, &ev);
3096#else
3097 Q_UNUSED(e);
3098#endif
3099}
3100
3101#ifndef QT_NO_GESTURES
3102void QGuiApplicationPrivate::processGestureEvent(QWindowSystemInterfacePrivate::GestureEvent *e)
3103{
3104 if (e->window.isNull())
3105 return;
3106
3107 const QPointingDevice *device = static_cast<const QPointingDevice *>(e->device);
3108 QNativeGestureEvent ev(e->type, device, e->fingerCount, e->pos, e->pos, e->globalPos, (e->intValue ? e->intValue : e->realValue),
3109 e->delta, e->sequenceId);
3110 ev.setTimestamp(e->timestamp);
3111 QGuiApplication::sendSpontaneousEvent(e->window, &ev);
3112}
3113#endif // QT_NO_GESTURES
3114
3115void QGuiApplicationPrivate::processPlatformPanelEvent(QWindowSystemInterfacePrivate::PlatformPanelEvent *e)
3116{
3117 if (!e->window)
3118 return;
3119
3120 if (e->window->d_func()->blockedByModalWindow) {
3121 // a modal window is blocking this window, don't allow events through
3122 return;
3123 }
3124
3125 QEvent ev(QEvent::PlatformPanel);
3126 QGuiApplication::sendSpontaneousEvent(e->window.data(), &ev);
3127}
3128
3129#ifndef QT_NO_CONTEXTMENU
3130void QGuiApplicationPrivate::processContextMenuEvent(QWindowSystemInterfacePrivate::ContextMenuEvent *e)
3131{
3132 // Widgets do not care about mouse triggered context menu events. Also, do not forward event
3133 // to a window blocked by a modal window.
3134 if (!e->window || e->mouseTriggered || e->window->d_func()->blockedByModalWindow)
3135 return;
3136
3137 QContextMenuEvent ev(QContextMenuEvent::Keyboard, e->pos, e->globalPos, e->modifiers);
3138 QGuiApplication::sendSpontaneousEvent(e->window.data(), &ev);
3139 e->eventAccepted = ev.isAccepted();
3140}
3141#endif
3142
3143void QGuiApplicationPrivate::processTouchEvent(QWindowSystemInterfacePrivate::TouchEvent *e)
3144{
3145 // The QPA side might need to know whether the touch event was accepted on
3146 // Qt side. In the flow below we might send multiple QTouchEvents, with
3147 // multiple QTouchPoints, and even synthesize mouse events if the touch
3148 // was not handled. Lacking a more granular reporting structure we treat
3149 // a single event acceptance as the QWSI event being accepted.
3150 e->eventAccepted = false;
3151
3152 if (!QInputDevicePrivate::isRegistered(e->device))
3153 return;
3154
3155 modifier_buttons = e->modifiers;
3156 QPointingDevice *device = const_cast<QPointingDevice *>(static_cast<const QPointingDevice *>(e->device));
3157 QPointingDevicePrivate *devPriv = QPointingDevicePrivate::get(device);
3158
3159 auto *guiAppPrivate = QGuiApplicationPrivate::instance();
3160
3161 if (e->touchType == QEvent::TouchCancel) {
3162 // The touch sequence has been canceled (e.g. by the compositor).
3163 // Send the TouchCancel to all windows with active touches and clean up.
3164 QTouchEvent touchEvent(QEvent::TouchCancel, device, e->modifiers);
3165 touchEvent.setTimestamp(e->timestamp);
3166 constexpr qsizetype Prealloc = decltype(devPriv->activePoints)::mapped_container_type::PreallocatedSize;
3167 QMinimalVarLengthFlatSet<QWindow *, Prealloc> windowsNeedingCancel;
3168
3169 for (auto &epd : devPriv->activePoints.values()) {
3170 if (QWindow *w = QMutableEventPoint::window(epd.eventPoint))
3171 windowsNeedingCancel.insert(w);
3172 }
3173
3174 for (QWindow *w : windowsNeedingCancel) {
3175 QGuiApplication::sendSpontaneousEvent(w, &touchEvent);
3176 e->eventAccepted |= touchEvent.isAccepted();
3177 }
3178
3179 if (!guiAppPrivate->synthesizedMousePoints.isEmpty() && !e->synthetic()) {
3180 for (QHash<QWindow *, SynthesizedMouseData>::const_iterator synthIt = guiAppPrivate->synthesizedMousePoints.constBegin(),
3181 synthItEnd = guiAppPrivate->synthesizedMousePoints.constEnd(); synthIt != synthItEnd; ++synthIt) {
3182 if (!synthIt->window)
3183 continue;
3184 QWindowSystemInterfacePrivate::MouseEvent fake(synthIt->window.data(),
3185 e->timestamp,
3186 synthIt->pos,
3187 synthIt->screenPos,
3188 Qt::NoButton,
3189 e->modifiers,
3190 Qt::LeftButton,
3191 QEvent::MouseButtonRelease,
3192 Qt::MouseEventNotSynthesized,
3193 false,
3194 device);
3195 fake.flags |= QWindowSystemInterfacePrivate::WindowSystemEvent::Synthetic;
3196 processMouseEvent(&fake);
3197 }
3198 guiAppPrivate->synthesizedMousePoints.clear();
3199 }
3200
3201 guiAppPrivate->lastTouchType = e->touchType;
3202 devPriv->activePoints.clear();
3203 return;
3204 }
3205
3206 // Prevent sending ill-formed event sequences: Cancel can only be followed by a Begin.
3207 if (guiAppPrivate->lastTouchType == QEvent::TouchCancel && e->touchType != QEvent::TouchBegin)
3208 return;
3209
3210 guiAppPrivate->lastTouchType = e->touchType;
3211
3212 QPointer<QWindow> window = e->window; // the platform hopefully tells us which window received the event
3213 QVarLengthArray<QMutableTouchEvent, 2> touchEvents;
3214
3215 // For each temporary QEventPoint from the QPA TouchEvent:
3216 // - update the persistent QEventPoint in QPointingDevicePrivate::activePoints with current values
3217 // - determine which window to deliver it to
3218 // - add it to the QTouchEvent instance for that window (QMutableTouchEvent::target() will be QWindow*, for now)
3219 for (auto &tempPt : e->points) {
3220 // update state
3221 auto epd = devPriv->pointById(tempPt.id());
3222 auto &ep = epd->eventPoint;
3223 epd->eventPoint.setAccepted(false);
3224 switch (tempPt.state()) {
3225 case QEventPoint::State::Pressed:
3226 // On touchpads, send all touch points to the same window.
3227 if (!window && e->device && e->device->type() == QInputDevice::DeviceType::TouchPad)
3228 window = devPriv->firstActiveWindow();
3229 // If the QPA event didn't tell us which window, find the one under the touchpoint position.
3230 if (!window)
3231 window = QGuiApplication::topLevelAt(tempPt.globalPosition().toPoint());
3232 QMutableEventPoint::setWindow(ep, window);
3233 active_popup_on_press = activePopupWindow();
3234 break;
3235
3236 case QEventPoint::State::Released:
3237 if (Q_UNLIKELY(!window.isNull() && window != QMutableEventPoint::window(ep)))
3238 qCDebug(lcPtrDispatch) << "delivering touch release to same window"
3239 << QMutableEventPoint::window(ep) << "not" << window.data();
3240 window = QMutableEventPoint::window(ep);
3241 break;
3242
3243 default: // update or stationary
3244 if (Q_UNLIKELY(!window.isNull() && window != QMutableEventPoint::window(ep)))
3245 qCDebug(lcPtrDispatch) << "delivering touch update to same window"
3246 << QMutableEventPoint::window(ep) << "not" << window.data();
3247 window = QMutableEventPoint::window(ep);
3248 break;
3249 }
3250 // If we somehow still don't have a window, we can't deliver this touchpoint. (should never happen)
3251 if (Q_UNLIKELY(!window)) {
3252 qCDebug(lcPtrDispatch) << "skipping" << &tempPt << ": no target window";
3253 continue;
3254 }
3255 QMutableEventPoint::update(tempPt, ep);
3256
3257 Q_ASSERT(window.data() != nullptr);
3258
3259 // make the *scene* position the same as the *global* position
3260 QMutableEventPoint::setScenePosition(ep, tempPt.globalPosition());
3261
3262 // store the scene position as local position, for now
3263 QMutableEventPoint::setPosition(ep, window->mapFromGlobal(tempPt.globalPosition()));
3264
3265 // setTimeStamp has side effects, so we do it last
3266 QMutableEventPoint::setTimestamp(ep, e->timestamp);
3267
3268 // add the touchpoint to the event that will be delivered to the window
3269 bool added = false;
3270 for (QMutableTouchEvent &ev : touchEvents) {
3271 if (ev.target() == window.data()) {
3272 ev.addPoint(ep);
3273 added = true;
3274 break;
3275 }
3276 }
3277 if (!added) {
3278 QMutableTouchEvent mte(e->touchType, device, e->modifiers, {ep});
3279 mte.setTimestamp(e->timestamp);
3280 mte.setTarget(window.data());
3281 touchEvents.append(mte);
3282 }
3283 }
3284
3285 if (touchEvents.isEmpty())
3286 return;
3287
3288 for (QMutableTouchEvent &touchEvent : touchEvents) {
3289 QWindow *window = static_cast<QWindow *>(touchEvent.target());
3290
3291 QEvent::Type eventType;
3292 switch (touchEvent.touchPointStates()) {
3293 case QEventPoint::State::Pressed:
3294 eventType = QEvent::TouchBegin;
3295 break;
3296 case QEventPoint::State::Released:
3297 eventType = QEvent::TouchEnd;
3298 break;
3299 default:
3300 eventType = QEvent::TouchUpdate;
3301 break;
3302 }
3303
3304 const auto *activePopup = activePopupWindow();
3305 if (window->d_func()->blockedByModalWindow && !activePopup) {
3306 // a modal window is blocking this window, don't allow touch events through
3307
3308 // QTBUG-37371 temporary fix; TODO: revisit when we have a forwarding solution
3309 if (touchEvent.type() == QEvent::TouchEnd) {
3310 // but don't leave dangling state: e.g.
3311 // QQuickWindowPrivate::itemForTouchPointId needs to be cleared.
3312 QTouchEvent touchEvent(QEvent::TouchCancel, device, e->modifiers);
3313 touchEvent.setTimestamp(e->timestamp);
3314 QGuiApplication::sendSpontaneousEvent(window, &touchEvent);
3315 }
3316 continue;
3317 }
3318
3319 if (activePopup && activePopup != window) {
3320 // If the popup handles the event, we're done.
3321 if (window->d_func()->forwardToPopup(&touchEvent, active_popup_on_press))
3322 return;
3323 }
3324
3325 // Note: after the call to sendSpontaneousEvent, touchEvent.position() will have
3326 // changed to reflect the local position inside the last (random) widget it tried
3327 // to deliver the touch event to, and will therefore be invalid afterwards.
3328 QGuiApplication::sendSpontaneousEvent(window, &touchEvent);
3329 e->eventAccepted |= touchEvent.isAccepted();
3330
3331 if (!e->synthetic() && !touchEvent.isAccepted() && qApp->testAttribute(Qt::AA_SynthesizeMouseForUnhandledTouchEvents)) {
3332 // exclude devices which generate their own mouse events
3333 if (!(touchEvent.device()->capabilities().testFlag(QInputDevice::Capability::MouseEmulation))) {
3334
3335 QEvent::Type mouseEventType = QEvent::MouseMove;
3336 Qt::MouseButton button = Qt::NoButton;
3337 Qt::MouseButtons buttons = Qt::LeftButton;
3338 if (eventType == QEvent::TouchBegin || m_fakeMouseSourcePointId < 0) {
3339 m_fakeMouseSourcePointId = touchEvent.point(0).id();
3340 qCDebug(lcPtrDispatch) << "synthesizing mouse events from touchpoint" << m_fakeMouseSourcePointId;
3341 }
3342 if (m_fakeMouseSourcePointId >= 0) {
3343 const auto *touchPoint = touchEvent.pointById(m_fakeMouseSourcePointId);
3344 if (touchPoint) {
3345 switch (touchPoint->state()) {
3346 case QEventPoint::State::Pressed:
3347 mouseEventType = QEvent::MouseButtonPress;
3348 button = Qt::LeftButton;
3349 break;
3350 case QEventPoint::State::Released:
3351 mouseEventType = QEvent::MouseButtonRelease;
3352 button = Qt::LeftButton;
3353 buttons = Qt::NoButton;
3354 Q_ASSERT(m_fakeMouseSourcePointId == touchPoint->id());
3355 m_fakeMouseSourcePointId = -1;
3356 break;
3357 default:
3358 break;
3359 }
3360 if (touchPoint->state() != QEventPoint::State::Released) {
3361 guiAppPrivate->synthesizedMousePoints.insert(window, SynthesizedMouseData(
3362 touchPoint->position(), touchPoint->globalPosition(), window));
3363 }
3364 // All touch events that are not accepted by the application will be translated to
3365 // left mouse button events instead (see AA_SynthesizeMouseForUnhandledTouchEvents docs).
3366 // Sending a QPA event (rather than simply sending a QMouseEvent) takes care of
3367 // side-effects such as double-click synthesis.
3368 QWindowSystemInterfacePrivate::MouseEvent fake(window, e->timestamp,
3369 window->mapFromGlobal(touchPoint->globalPosition().toPoint()),
3370 touchPoint->globalPosition(),
3371 buttons,
3372 e->modifiers,
3373 button,
3374 mouseEventType,
3375 Qt::MouseEventSynthesizedByQt,
3376 false,
3377 device,
3378 touchPoint->id());
3379 fake.flags |= QWindowSystemInterfacePrivate::WindowSystemEvent::Synthetic;
3380 processMouseEvent(&fake);
3381 e->eventAccepted |= fake.eventAccepted;
3382 }
3383 }
3384 if (eventType == QEvent::TouchEnd)
3385 guiAppPrivate->synthesizedMousePoints.clear();
3386 }
3387 }
3388 }
3389
3390 // Remove released points from QPointingDevicePrivate::activePoints only after the event is
3391 // delivered. Widgets and Qt Quick are allowed to access them at any time before this.
3392 for (const QEventPoint &touchPoint : e->points) {
3393 if (touchPoint.state() == QEventPoint::State::Released)
3394 devPriv->removePointById(touchPoint.id());
3395 }
3396}
3397
3398void QGuiApplicationPrivate::processScreenOrientationChange(QWindowSystemInterfacePrivate::ScreenOrientationEvent *e)
3399{
3400 // This operation only makes sense after the QGuiApplication constructor runs
3401 if (QCoreApplication::startingUp())
3402 return;
3403
3404 if (!e->screen)
3405 return;
3406
3407 QScreen *s = e->screen.data();
3408 s->d_func()->orientation = e->orientation;
3409
3410 emit s->orientationChanged(s->orientation());
3411
3412 QScreenOrientationChangeEvent event(s, s->orientation());
3413 QCoreApplication::sendEvent(QCoreApplication::instance(), &event);
3414}
3415
3416void QGuiApplicationPrivate::processScreenGeometryChange(QWindowSystemInterfacePrivate::ScreenGeometryEvent *e)
3417{
3418 // This operation only makes sense after the QGuiApplication constructor runs
3419 if (QCoreApplication::startingUp())
3420 return;
3421
3422 if (!e->screen)
3423 return;
3424
3425 {
3426 QScreen *s = e->screen.data();
3427 QScreenPrivate::UpdateEmitter updateEmitter(s);
3428
3429 // Note: The incoming geometries have already been scaled by QHighDpi
3430 // in the QWSI layer, so we don't need to call updateGeometry() here.
3431 s->d_func()->geometry = e->geometry;
3432 s->d_func()->availableGeometry = e->availableGeometry;
3433
3434 s->d_func()->updatePrimaryOrientation();
3435 }
3436
3437 resetCachedDevicePixelRatio();
3438}
3439
3440void QGuiApplicationPrivate::processScreenLogicalDotsPerInchChange(QWindowSystemInterfacePrivate::ScreenLogicalDotsPerInchEvent *e)
3441{
3442 // This operation only makes sense after the QGuiApplication constructor runs
3443 if (QCoreApplication::startingUp())
3444 return;
3445
3446 QHighDpiScaling::updateHighDpiScaling();
3447
3448 if (!e->screen)
3449 return;
3450
3451 {
3452 QScreen *s = e->screen.data();
3453 QScreenPrivate::UpdateEmitter updateEmitter(s);
3454 s->d_func()->logicalDpi = QDpi(e->dpiX, e->dpiY);
3455 s->d_func()->updateGeometry();
3456 }
3457
3458 for (QWindow *window : QGuiApplication::allWindows())
3459 if (window->screen() == e->screen)
3460 QWindowPrivate::get(window)->updateDevicePixelRatio();
3461
3462 resetCachedDevicePixelRatio();
3463}
3464
3465void QGuiApplicationPrivate::processScreenRefreshRateChange(QWindowSystemInterfacePrivate::ScreenRefreshRateEvent *e)
3466{
3467 // This operation only makes sense after the QGuiApplication constructor runs
3468 if (QCoreApplication::startingUp())
3469 return;
3470
3471 if (!e->screen)
3472 return;
3473
3474 QScreen *s = e->screen.data();
3475 qreal rate = e->rate;
3476 // safeguard ourselves against buggy platform behavior...
3477 if (rate < 1.0)
3478 rate = 60.0;
3479 if (!qFuzzyCompare(s->d_func()->refreshRate, rate)) {
3480 s->d_func()->refreshRate = rate;
3481 emit s->refreshRateChanged(s->refreshRate());
3482 }
3483}
3484
3485void QGuiApplicationPrivate::processExposeEvent(QWindowSystemInterfacePrivate::ExposeEvent *e)
3486{
3487 if (!e->window)
3488 return;
3489
3490 QWindow *window = e->window.data();
3491 if (!window)
3492 return;
3493 QWindowPrivate *p = qt_window_private(window);
3494
3495 if (e->isExposed) {
3496 // If the window has been automatically positioned or resized by the
3497 // window manager, we now assume those have taken effect, even for
3498 // asynchronous window managers. From this point on we want the window
3499 // to keep its geometry, even when recreated.
3500 p->positionAutomatic = false;
3501 p->resizeAutomatic = false;
3502 }
3503
3504 if (!p->receivedExpose) {
3505 if (p->resizeEventPending) {
3506 // as a convenience for plugins, send a resize event before the first expose event if they haven't done so
3507 // window->geometry() should have a valid size as soon as a handle exists.
3508 QResizeEvent e(window->geometry().size(), p->geometry.size());
3509 QGuiApplication::sendSpontaneousEvent(window, &e);
3510
3511 p->resizeEventPending = false;
3512 }
3513
3514 // FIXME: It would logically make sense to set this _after_ we've sent the
3515 // expose event to the window, to mark that it now has received an expose.
3516 // But some parts of Qt (mis)use this private member to check whether the
3517 // window has been mapped yet, which they do in code that is triggered
3518 // by the very same expose event we send below. To keep the code working
3519 // we need to set the variable up front, until the code has been fixed.
3520 p->receivedExpose = true;
3521 }
3522
3523 // If the platform does not send paint events we need to synthesize them from expose events
3524 const bool shouldSynthesizePaintEvents = !platformIntegration()->hasCapability(QPlatformIntegration::PaintEvents);
3525
3526 const bool wasExposed = p->exposed;
3527 p->exposed = e->isExposed && window->screen();
3528
3529 // We expect that the platform plugins send DevicePixelRatioChange events.
3530 // As a fail-safe make a final check here to make sure the cached DPR value is
3531 // always up to date before sending the expose event.
3532 if (e->isExposed && !e->region.isEmpty()) {
3533 const bool dprWasChanged = QWindowPrivate::get(window)->updateDevicePixelRatio();
3534 if (dprWasChanged)
3535 qWarning() << "The cached device pixel ratio value was stale on window expose. "
3536 << "Please file a QTBUG which explains how to reproduce.";
3537 }
3538
3539 // We treat expose events for an already exposed window as paint events
3540 if (wasExposed && p->exposed && shouldSynthesizePaintEvents) {
3541 QPaintEvent paintEvent(e->region);
3542 QCoreApplication::sendSpontaneousEvent(window, &paintEvent);
3543 if (paintEvent.isAccepted())
3544 return; // No need to send expose
3545
3546 // The paint event was not accepted, so we fall through and send an expose
3547 // event instead, to maintain compatibility for clients that haven't adopted
3548 // paint events yet.
3549 }
3550
3551 QExposeEvent exposeEvent(e->region);
3552 QCoreApplication::sendSpontaneousEvent(window, &exposeEvent);
3553 e->eventAccepted = exposeEvent.isAccepted();
3554
3555 // If the window was just exposed we also need to send a paint event,
3556 // so that clients that implement paint events will draw something.
3557 // Note that we we can not skip this based on the expose event being
3558 // accepted, as clients may implement exposeEvent to track the state
3559 // change, but without drawing anything.
3560 if (!wasExposed && p->exposed && shouldSynthesizePaintEvents) {
3561 QPaintEvent paintEvent(e->region);
3562 QCoreApplication::sendSpontaneousEvent(window, &paintEvent);
3563 }
3564}
3565
3566void QGuiApplicationPrivate::processPaintEvent(QWindowSystemInterfacePrivate::PaintEvent *e)
3567{
3568 Q_ASSERT_X(platformIntegration()->hasCapability(QPlatformIntegration::PaintEvents), "QGuiApplication",
3569 "The platform sent paint events without claiming support for it in QPlatformIntegration::capabilities()");
3570
3571 if (!e->window)
3572 return;
3573
3574 QPaintEvent paintEvent(e->region);
3575 QCoreApplication::sendSpontaneousEvent(e->window, &paintEvent);
3576
3577 // We report back the accepted state to the platform, so that it can
3578 // decide when the best time to send the fallback expose event is.
3579 e->eventAccepted = paintEvent.isAccepted();
3580}
3581
3582#if QT_CONFIG(draganddrop)
3583
3584/*! \internal
3585
3586 This function updates an internal state to keep the source compatibility.
3587 ### Qt 6 - Won't need after QTBUG-73829
3588*/
3589static void updateMouseAndModifierButtonState(Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers)
3590{
3591 QGuiApplicationPrivate::mouse_buttons = buttons;
3592 QGuiApplicationPrivate::modifier_buttons = modifiers;
3593}
3594
3595QPlatformDragQtResponse QGuiApplicationPrivate::processDrag(QWindow *w, const QMimeData *dropData,
3596 const QPoint &p, Qt::DropActions supportedActions,
3597 Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers)
3598{
3599 updateMouseAndModifierButtonState(buttons, modifiers);
3600
3601 static Qt::DropAction lastAcceptedDropAction = Qt::IgnoreAction;
3602 QPlatformDrag *platformDrag = platformIntegration()->drag();
3603 if (!platformDrag || (w && w->d_func()->blockedByModalWindow)) {
3604 lastAcceptedDropAction = Qt::IgnoreAction;
3605 return QPlatformDragQtResponse(false, lastAcceptedDropAction, QRect());
3606 }
3607
3608 if (!dropData) {
3609 currentDragWindow = nullptr;
3610 QDragLeaveEvent e;
3611 QGuiApplication::sendEvent(w, &e);
3612 lastAcceptedDropAction = Qt::IgnoreAction;
3613 return QPlatformDragQtResponse(false, lastAcceptedDropAction, QRect());
3614 }
3615 QDragMoveEvent me(QPointF(p), supportedActions, dropData, buttons, modifiers);
3616
3617 if (w != currentDragWindow) {
3618 lastAcceptedDropAction = Qt::IgnoreAction;
3619 if (currentDragWindow) {
3620 QDragLeaveEvent e;
3621 QGuiApplication::sendEvent(currentDragWindow, &e);
3622 }
3623 currentDragWindow = w;
3624 QDragEnterEvent e(QPointF(p), supportedActions, dropData, buttons, modifiers);
3625 QGuiApplication::sendEvent(w, &e);
3626 if (e.isAccepted() && e.dropAction() != Qt::IgnoreAction)
3627 lastAcceptedDropAction = e.dropAction();
3628 }
3629
3630 // Handling 'DragEnter' should suffice for the application.
3631 if (lastAcceptedDropAction != Qt::IgnoreAction
3632 && (supportedActions & lastAcceptedDropAction)) {
3633 me.setDropAction(lastAcceptedDropAction);
3634 me.accept();
3635 }
3636 QGuiApplication::sendEvent(w, &me);
3637 lastAcceptedDropAction = me.isAccepted() ?
3638 me.dropAction() : Qt::IgnoreAction;
3639 return QPlatformDragQtResponse(me.isAccepted(), lastAcceptedDropAction, me.answerRect());
3640}
3641
3642QPlatformDropQtResponse QGuiApplicationPrivate::processDrop(QWindow *w, const QMimeData *dropData,
3643 const QPoint &p, Qt::DropActions supportedActions,
3644 Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers)
3645{
3646 updateMouseAndModifierButtonState(buttons, modifiers);
3647
3648 currentDragWindow = nullptr;
3649
3650 QDropEvent de(p, supportedActions, dropData, buttons, modifiers);
3651 QGuiApplication::sendEvent(w, &de);
3652
3653 Qt::DropAction acceptedAction = de.isAccepted() ? de.dropAction() : Qt::IgnoreAction;
3654 QPlatformDropQtResponse response(de.isAccepted(),acceptedAction);
3655 return response;
3656}
3657
3658#endif // QT_CONFIG(draganddrop)
3659
3660#ifndef QT_NO_CLIPBOARD
3661/*!
3662 Returns the object for interacting with the clipboard.
3663*/
3664QClipboard * QGuiApplication::clipboard()
3665{
3666 if (QGuiApplicationPrivate::qt_clipboard == nullptr) {
3667 if (!qApp) {
3668 qWarning("QGuiApplication: Must construct a QGuiApplication before accessing a QClipboard");
3669 return nullptr;
3670 }
3671 QGuiApplicationPrivate::qt_clipboard = new QClipboard(nullptr);
3672 }
3673 return QGuiApplicationPrivate::qt_clipboard;
3674}
3675#endif
3676
3677/*!
3678 \since 5.4
3679 \fn void QGuiApplication::paletteChanged(const QPalette &palette)
3680 \deprecated [6.0] Handle QEvent::ApplicationPaletteChange instead.
3681
3682 This signal is emitted when the \a palette of the application changes. Use
3683 QEvent::ApplicationPaletteChanged instead.
3684
3685 \sa palette()
3686*/
3687
3688/*!
3689 Returns the current application palette.
3690
3691 Roles that have not been explicitly set will reflect the system's platform theme.
3692
3693 \sa setPalette()
3694*/
3695
3696QPalette QGuiApplication::palette()
3697{
3698 if (!QGuiApplicationPrivate::app_pal)
3699 QGuiApplicationPrivate::updatePalette();
3700
3701 return *QGuiApplicationPrivate::app_pal;
3702}
3703
3704void QGuiApplicationPrivate::updatePalette()
3705{
3706 if (app_pal) {
3707 if (setPalette(*app_pal) && qGuiApp)
3708 qGuiApp->d_func()->handlePaletteChanged();
3709 } else {
3710 setPalette(QPalette());
3711 }
3712}
3713
3714QEvent::Type QGuiApplicationPrivate::contextMenuEventType()
3715{
3716 switch (QGuiApplication::styleHints()->contextMenuTrigger()) {
3717 case Qt::ContextMenuTrigger::Press: return QEvent::MouseButtonPress;
3718 case Qt::ContextMenuTrigger::Release: return QEvent::MouseButtonRelease;
3719 }
3720 return QEvent::None;
3721}
3722
3723void QGuiApplicationPrivate::clearPalette()
3724{
3725 delete app_pal;
3726 app_pal = nullptr;
3727}
3728
3729/*!
3730 Changes the application palette to \a pal.
3731
3732 The color roles from this palette are combined with the system's platform
3733 theme to form the application's final palette.
3734
3735 \sa palette()
3736*/
3737void QGuiApplication::setPalette(const QPalette &pal)
3738{
3739 if (QGuiApplicationPrivate::setPalette(pal) && qGuiApp)
3740 qGuiApp->d_func()->handlePaletteChanged();
3741}
3742
3743bool QGuiApplicationPrivate::setPalette(const QPalette &palette)
3744{
3745 // Resolve the palette against the theme palette, filling in
3746 // any missing roles, while keeping the original resolve mask.
3747 QPalette basePalette = qGuiApp ? qGuiApp->d_func()->basePalette() : Qt::gray;
3748 basePalette.setResolveMask(0); // The base palette only contributes missing colors roles
3749 QPalette resolvedPalette = palette.resolve(basePalette);
3750
3751 if (app_pal && resolvedPalette == *app_pal && resolvedPalette.resolveMask() == app_pal->resolveMask())
3752 return false;
3753
3754 if (!app_pal)
3755 app_pal = new QPalette(resolvedPalette);
3756 else
3757 *app_pal = resolvedPalette;
3758
3759 QCoreApplication::setAttribute(Qt::AA_SetPalette, app_pal->resolveMask() != 0);
3760
3761 return true;
3762}
3763
3764/*
3765 Returns the base palette used to fill in missing roles in
3766 the current application palette.
3767
3768 Normally this is the theme palette, but QApplication
3769 overrides this for compatibility reasons.
3770*/
3771QPalette QGuiApplicationPrivate::basePalette() const
3772{
3773 const auto pf = platformTheme();
3774 return pf && pf->palette() ? *pf->palette() : Qt::gray;
3775}
3776
3777void QGuiApplicationPrivate::handlePaletteChanged(const char *className)
3778{
3779#if QT_DEPRECATED_SINCE(6, 0)
3780 if (!className) {
3781 Q_ASSERT(app_pal);
3782QT_WARNING_PUSH
3783QT_WARNING_DISABLE_DEPRECATED
3784 emit qGuiApp->paletteChanged(*QGuiApplicationPrivate::app_pal);
3785QT_WARNING_POP
3786 }
3787#else
3788 Q_UNUSED(className);
3789#endif // QT_DEPRECATED_SINCE(6, 0)
3790
3791 if (is_app_running && !is_app_closing) {
3792 QEvent event(QEvent::ApplicationPaletteChange);
3793 QGuiApplication::sendEvent(qGuiApp, &event);
3794 }
3795}
3796
3797void QGuiApplicationPrivate::applyWindowGeometrySpecificationTo(QWindow *window)
3798{
3799 windowGeometrySpecification.applyTo(window);
3800}
3801
3802/*!
3803 \since 5.11
3804 \fn void QGuiApplication::fontChanged(const QFont &font)
3805 \deprecated [6.0] Handle QEvent::ApplicationFontChange instead.
3806
3807 This signal is emitted when the \a font of the application changes. Use
3808 QEvent::ApplicationFontChanged instead.
3809
3810 \sa font()
3811*/
3812
3813/*!
3814 Returns the default application font.
3815
3816 \sa setFont()
3817*/
3818QFont QGuiApplication::font()
3819{
3820 const auto locker = qt_scoped_lock(applicationFontMutex);
3821 if (!QGuiApplicationPrivate::instance() && !QGuiApplicationPrivate::app_font) {
3822 qWarning("QGuiApplication::font(): no QGuiApplication instance and no application font set.");
3823 return QFont(); // in effect: QFont((QFontPrivate*)nullptr), so no recursion
3824 }
3825 initFontUnlocked();
3826 return *QGuiApplicationPrivate::app_font;
3827}
3828
3829/*!
3830 Changes the default application font to \a font.
3831
3832 \sa font()
3833*/
3834void QGuiApplication::setFont(const QFont &font)
3835{
3836 auto locker = qt_unique_lock(applicationFontMutex);
3837 const bool emitChange = !QGuiApplicationPrivate::app_font
3838 || (*QGuiApplicationPrivate::app_font != font);
3839 if (!QGuiApplicationPrivate::app_font)
3840 QGuiApplicationPrivate::app_font = new QFont(font);
3841 else
3842 *QGuiApplicationPrivate::app_font = font;
3843 applicationResourceFlags |= ApplicationFontExplicitlySet;
3844
3845 if (emitChange && qGuiApp) {
3846 auto font = *QGuiApplicationPrivate::app_font;
3847 locker.unlock();
3848#if QT_DEPRECATED_SINCE(6, 0)
3849QT_WARNING_PUSH
3850QT_WARNING_DISABLE_DEPRECATED
3851 emit qGuiApp->fontChanged(font);
3852QT_WARNING_POP
3853#else
3854 Q_UNUSED(font);
3855#endif // QT_DEPRECATED_SINCE(6, 0)
3856 QEvent event(QEvent::ApplicationFontChange);
3857 QGuiApplication::sendEvent(qGuiApp, &event);
3858 }
3859}
3860
3861/*!
3862 \fn bool QGuiApplication::isRightToLeft()
3863
3864 Returns \c true if the application's layout direction is
3865 Qt::RightToLeft; otherwise returns \c false.
3866
3867 \sa layoutDirection(), isLeftToRight()
3868*/
3869
3870/*!
3871 \fn bool QGuiApplication::isLeftToRight()
3872
3873 Returns \c true if the application's layout direction is
3874 Qt::LeftToRight; otherwise returns \c false.
3875
3876 \sa layoutDirection(), isRightToLeft()
3877*/
3878
3879void QGuiApplicationPrivate::notifyLayoutDirectionChange()
3880{
3881 const QWindowList list = QGuiApplication::topLevelWindows();
3882 for (int i = 0; i < list.size(); ++i) {
3883 QEvent ev(QEvent::ApplicationLayoutDirectionChange);
3884 QCoreApplication::sendEvent(list.at(i), &ev);
3885 }
3886}
3887
3888void QGuiApplicationPrivate::notifyActiveWindowChange(QWindow *prev)
3889{
3890 if (prev) {
3891 QEvent de(QEvent::WindowDeactivate);
3892 QCoreApplication::sendEvent(prev, &de);
3893 }
3894 if (QGuiApplicationPrivate::instance()->focus_window) {
3895 QEvent ae(QEvent::WindowActivate);
3896 QCoreApplication::sendEvent(focus_window, &ae);
3897 }
3898}
3899
3900/*!
3901 \property QGuiApplication::windowIcon
3902 \brief the default window icon
3903
3904 \sa QWindow::setIcon(), {Setting the Application Icon}
3905*/
3906QIcon QGuiApplication::windowIcon()
3907{
3908 return QGuiApplicationPrivate::app_icon ? *QGuiApplicationPrivate::app_icon : QIcon();
3909}
3910
3911void QGuiApplication::setWindowIcon(const QIcon &icon)
3912{
3913 if (!QGuiApplicationPrivate::app_icon)
3914 QGuiApplicationPrivate::app_icon = new QIcon();
3915 *QGuiApplicationPrivate::app_icon = icon;
3916 if (QGuiApplicationPrivate::platform_integration
3917 && QGuiApplicationPrivate::platform_integration->hasCapability(QPlatformIntegration::ApplicationIcon))
3918 QGuiApplicationPrivate::platform_integration->setApplicationIcon(icon);
3919 if (QGuiApplicationPrivate::is_app_running && !QGuiApplicationPrivate::is_app_closing)
3920 QGuiApplicationPrivate::instance()->notifyWindowIconChanged();
3921}
3922
3923void QGuiApplicationPrivate::notifyWindowIconChanged()
3924{
3925 QEvent ev(QEvent::ApplicationWindowIconChange);
3926 const QWindowList list = QGuiApplication::topLevelWindows();
3927 for (int i = 0; i < list.size(); ++i)
3928 QCoreApplication::sendEvent(list.at(i), &ev);
3929}
3930
3931
3932
3933/*!
3934 \property QGuiApplication::quitOnLastWindowClosed
3935
3936 \brief whether the application implicitly quits when the last window is
3937 closed.
3938
3939 The default is \c true.
3940
3941 If this property is \c true, the application will attempt to
3942 quit when the last visible \l{Primary and Secondary Windows}{primary window}
3943 (i.e. top level window with no transient parent) is closed.
3944
3945 Note that attempting a quit may not necessarily result in the
3946 application quitting, for example if there still are active
3947 QEventLoopLocker instances, or the QEvent::Quit event is ignored.
3948
3949 \sa quit(), QWindow::close()
3950 */
3951
3952void QGuiApplication::setQuitOnLastWindowClosed(bool quit)
3953{
3954 QGuiApplicationPrivate::quitOnLastWindowClosed = quit;
3955}
3956
3957bool QGuiApplication::quitOnLastWindowClosed()
3958{
3959 return QGuiApplicationPrivate::quitOnLastWindowClosed;
3960}
3961
3962void QGuiApplicationPrivate::maybeLastWindowClosed()
3963{
3964 if (!lastWindowClosed())
3965 return;
3966
3967 if (in_exec)
3968 emit q_func()->lastWindowClosed();
3969
3970 if (quitOnLastWindowClosed && canQuitAutomatically())
3971 quitAutomatically();
3972}
3973
3974/*!
3975 \fn void QGuiApplication::lastWindowClosed()
3976
3977 This signal is emitted from exec() when the last visible
3978 \l{Primary and Secondary Windows}{primary window} (i.e.
3979 top level window with no transient parent) is closed.
3980
3981 By default, QGuiApplication quits after this signal is emitted. This feature
3982 can be turned off by setting \l quitOnLastWindowClosed to \c false.
3983
3984 \sa QWindow::close(), QWindow::isTopLevel(), QWindow::transientParent()
3985*/
3986
3987bool QGuiApplicationPrivate::lastWindowClosed() const
3988{
3989 for (auto *window : QGuiApplication::topLevelWindows()) {
3990 auto *windowPrivate = qt_window_private(window);
3991 if (!windowPrivate->participatesInLastWindowClosed())
3992 continue;
3993
3994 if (windowPrivate->treatAsVisible())
3995 return false;
3996 }
3997
3998 return true;
3999}
4000
4001bool QGuiApplicationPrivate::canQuitAutomatically()
4002{
4003 // The automatic quit functionality is triggered by
4004 // both QEventLoopLocker and maybeLastWindowClosed.
4005 // Although the former is a QCoreApplication feature
4006 // we don't want to quit the application when there
4007 // are open windows, regardless of whether the app
4008 // also quits automatically on maybeLastWindowClosed.
4009 if (!lastWindowClosed())
4010 return false;
4011
4012 return QCoreApplicationPrivate::canQuitAutomatically();
4013}
4014
4015void QGuiApplicationPrivate::quit()
4016{
4017 if (auto *platformIntegration = QGuiApplicationPrivate::platformIntegration())
4018 platformIntegration->quit();
4019 else
4020 QCoreApplicationPrivate::quit();
4021}
4022
4023void QGuiApplicationPrivate::processApplicationTermination(QWindowSystemInterfacePrivate::WindowSystemEvent *windowSystemEvent)
4024{
4025 QEvent event(QEvent::Quit);
4026 QGuiApplication::sendSpontaneousEvent(QGuiApplication::instance(), &event);
4027 windowSystemEvent->eventAccepted = event.isAccepted();
4028}
4029
4030/*!
4031 \since 5.2
4032 \fn Qt::ApplicationState QGuiApplication::applicationState()
4033
4034
4035 Returns the current state of the application.
4036
4037 You can react to application state changes to perform actions such as
4038 stopping/resuming CPU-intensive tasks, freeing/loading resources or
4039 saving/restoring application data.
4040 */
4041
4042Qt::ApplicationState QGuiApplication::applicationState()
4043{
4044 return QGuiApplicationPrivate::applicationState;
4045}
4046
4047/*!
4048 \since 5.14
4049
4050 Sets the high-DPI scale factor rounding policy for the application. The
4051 \a policy decides how non-integer scale factors (such as Windows 150%) are
4052 handled.
4053
4054 The two principal options are whether fractional scale factors should
4055 be rounded to an integer or not. Keeping the scale factor as-is will
4056 make the user interface size match the OS setting exactly, but may cause
4057 painting errors, for example with the Windows style.
4058
4059 If rounding is wanted, then which type of rounding should be decided
4060 next. Mathematically correct rounding is supported but may not give
4061 the best visual results: Consider if you want to render 1.5x as 1x
4062 ("small UI") or as 2x ("large UI"). See the Qt::HighDpiScaleFactorRoundingPolicy
4063 enum for a complete list of all options.
4064
4065 This function must be called before creating the application object.
4066 The QGuiApplication::highDpiScaleFactorRoundingPolicy()
4067 accessor will reflect the environment, if set.
4068
4069 The default value is Qt::HighDpiScaleFactorRoundingPolicy::PassThrough.
4070*/
4071void QGuiApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy policy)
4072{
4073 if (qApp)
4074 qWarning("setHighDpiScaleFactorRoundingPolicy must be called before creating the QGuiApplication instance");
4075 QGuiApplicationPrivate::highDpiScaleFactorRoundingPolicy = policy;
4076}
4077
4078/*!
4079 \since 5.14
4080
4081 Returns the high-DPI scale factor rounding policy.
4082*/
4083Qt::HighDpiScaleFactorRoundingPolicy QGuiApplication::highDpiScaleFactorRoundingPolicy()
4084{
4085 return QGuiApplicationPrivate::highDpiScaleFactorRoundingPolicy;
4086}
4087
4088/*!
4089 \since 5.2
4090 \fn void QGuiApplication::applicationStateChanged(Qt::ApplicationState state)
4091
4092 This signal is emitted when the \a state of the application changes.
4093
4094 \sa applicationState()
4095*/
4096
4097void QGuiApplicationPrivate::setApplicationState(Qt::ApplicationState state, bool forcePropagate)
4098{
4099 if ((applicationState == state) && !forcePropagate)
4100 return;
4101
4102 applicationState = state;
4103
4104 switch (state) {
4105 case Qt::ApplicationActive: {
4106 QEvent appActivate(QEvent::ApplicationActivate);
4107 QCoreApplication::sendSpontaneousEvent(qApp, &appActivate);
4108 break; }
4109 case Qt::ApplicationInactive: {
4110 QEvent appDeactivate(QEvent::ApplicationDeactivate);
4111 QCoreApplication::sendSpontaneousEvent(qApp, &appDeactivate);
4112 break; }
4113 default:
4114 break;
4115 }
4116
4117 QApplicationStateChangeEvent event(applicationState);
4118 QCoreApplication::sendSpontaneousEvent(qApp, &event);
4119
4120 emit qApp->applicationStateChanged(applicationState);
4121}
4122
4123/*!
4124 \since 4.2
4125 \fn void QGuiApplication::commitDataRequest(QSessionManager &manager)
4126
4127 This signal deals with \l{Session Management}{session management}. It is
4128 emitted when the QSessionManager wants the application to commit all its
4129 data.
4130
4131 Usually this means saving all open files, after getting permission from
4132 the user. Furthermore you may want to provide a means by which the user
4133 can cancel the shutdown.
4134
4135 You should not exit the application within this signal. Instead,
4136 the session manager may or may not do this afterwards, depending on the
4137 context.
4138
4139 \warning Within this signal, no user interaction is possible, \e
4140 unless you ask the \a manager for explicit permission. See
4141 QSessionManager::allowsInteraction() and
4142 QSessionManager::allowsErrorInteraction() for details and example
4143 usage.
4144
4145 \note You should use Qt::DirectConnection when connecting to this signal.
4146
4147 \sa isSessionRestored(), sessionId(), saveStateRequest(), {Session Management}
4148*/
4149
4150/*!
4151 \since 4.2
4152 \fn void QGuiApplication::saveStateRequest(QSessionManager &manager)
4153
4154 This signal deals with \l{Session Management}{session management}. It is
4155 invoked when the \l{QSessionManager}{session manager} wants the application
4156 to preserve its state for a future session.
4157
4158 For example, a text editor would create a temporary file that includes the
4159 current contents of its edit buffers, the location of the cursor and other
4160 aspects of the current editing session.
4161
4162 You should never exit the application within this signal. Instead, the
4163 session manager may or may not do this afterwards, depending on the
4164 context. Furthermore, most session managers will very likely request a saved
4165 state immediately after the application has been started. This permits the
4166 session manager to learn about the application's restart policy.
4167
4168 \warning Within this signal, no user interaction is possible, \e
4169 unless you ask the \a manager for explicit permission. See
4170 QSessionManager::allowsInteraction() and
4171 QSessionManager::allowsErrorInteraction() for details.
4172
4173 \note You should use Qt::DirectConnection when connecting to this signal.
4174
4175 \sa isSessionRestored(), sessionId(), commitDataRequest(), {Session Management}
4176*/
4177
4178/*!
4179 \fn bool QGuiApplication::isSessionRestored() const
4180
4181 Returns \c true if the application has been restored from an earlier
4182 \l{Session Management}{session}; otherwise returns \c false.
4183
4184 \sa sessionId(), commitDataRequest(), saveStateRequest()
4185*/
4186
4187/*!
4188 \since 5.0
4189 \fn bool QGuiApplication::isSavingSession() const
4190
4191 Returns \c true if the application is currently saving the
4192 \l{Session Management}{session}; otherwise returns \c false.
4193
4194 This is \c true when commitDataRequest() and saveStateRequest() are emitted,
4195 but also when the windows are closed afterwards by session management.
4196
4197 \sa sessionId(), commitDataRequest(), saveStateRequest()
4198*/
4199
4200/*!
4201 \fn QString QGuiApplication::sessionId() const
4202
4203 Returns the current \l{Session Management}{session's} identifier.
4204
4205 If the application has been restored from an earlier session, this
4206 identifier is the same as it was in that previous session. The session
4207 identifier is guaranteed to be unique both for different applications
4208 and for different instances of the same application.
4209
4210 \sa isSessionRestored(), sessionKey(), commitDataRequest(), saveStateRequest()
4211*/
4212
4213/*!
4214 \fn QString QGuiApplication::sessionKey() const
4215
4216 Returns the session key in the current \l{Session Management}{session}.
4217
4218 If the application has been restored from an earlier session, this key is
4219 the same as it was when the previous session ended.
4220
4221 The session key changes every time the session is saved. If the shutdown process
4222 is cancelled, another session key will be used when shutting down again.
4223
4224 \sa isSessionRestored(), sessionId(), commitDataRequest(), saveStateRequest()
4225*/
4226#ifndef QT_NO_SESSIONMANAGER
4227bool QGuiApplication::isSessionRestored() const
4228{
4229 Q_D(const QGuiApplication);
4230 return d->is_session_restored;
4231}
4232
4233QString QGuiApplication::sessionId() const
4234{
4235 Q_D(const QGuiApplication);
4236 return d->session_manager->sessionId();
4237}
4238
4239QString QGuiApplication::sessionKey() const
4240{
4241 Q_D(const QGuiApplication);
4242 return d->session_manager->sessionKey();
4243}
4244
4245bool QGuiApplication::isSavingSession() const
4246{
4247 Q_D(const QGuiApplication);
4248 return d->is_saving_session;
4249}
4250
4251void QGuiApplicationPrivate::commitData()
4252{
4253 Q_Q(QGuiApplication);
4254 is_saving_session = true;
4255 emit q->commitDataRequest(*session_manager);
4256 is_saving_session = false;
4257}
4258
4259
4260void QGuiApplicationPrivate::saveState()
4261{
4262 Q_Q(QGuiApplication);
4263 is_saving_session = true;
4264 emit q->saveStateRequest(*session_manager);
4265 is_saving_session = false;
4266}
4267#endif //QT_NO_SESSIONMANAGER
4268
4269/*!
4270 \since 5.2
4271
4272 Function that can be used to sync Qt state with the Window Systems state.
4273
4274 This function will first empty Qts events by calling QCoreApplication::processEvents(),
4275 then the platform plugin will sync up with the windowsystem, and finally Qts events
4276 will be delived by another call to QCoreApplication::processEvents();
4277
4278 This function is timeconsuming and its use is discouraged.
4279*/
4280void QGuiApplication::sync()
4281{
4282 QCoreApplication::processEvents();
4283 if (QGuiApplicationPrivate::platform_integration
4284 && QGuiApplicationPrivate::platform_integration->hasCapability(QPlatformIntegration::SyncState)) {
4285 QGuiApplicationPrivate::platform_integration->sync();
4286 QCoreApplication::processEvents();
4287 QWindowSystemInterface::flushWindowSystemEvents();
4288 }
4289}
4290
4291/*!
4292 \property QGuiApplication::layoutDirection
4293 \brief the default layout direction for this application
4294
4295 On system start-up, or when the direction is explicitly set to
4296 Qt::LayoutDirectionAuto, the default layout direction depends on the
4297 application's language.
4298
4299 The notifier signal was introduced in Qt 5.4.
4300
4301 \sa QWidget::layoutDirection, isLeftToRight(), isRightToLeft()
4302 */
4303
4304void QGuiApplication::setLayoutDirection(Qt::LayoutDirection direction)
4305{
4306 layout_direction = direction;
4307 if (direction == Qt::LayoutDirectionAuto)
4308 direction = qt_detectRTLLanguage() ? Qt::RightToLeft : Qt::LeftToRight;
4309
4310 // no change to the explicitly set or auto-detected layout direction
4311 if (direction == effective_layout_direction)
4312 return;
4313
4314 effective_layout_direction = direction;
4315 if (qGuiApp) {
4316 emit qGuiApp->layoutDirectionChanged(direction);
4317 QGuiApplicationPrivate::instance()->notifyLayoutDirectionChange();
4318 }
4319}
4320
4321Qt::LayoutDirection QGuiApplication::layoutDirection()
4322{
4323 /*
4324 effective_layout_direction defaults to Qt::LeftToRight, and is updated with what is
4325 auto-detected by a call to setLayoutDirection(Qt::LayoutDirectionAuto). This happens in
4326 QGuiApplicationPrivate::init and when the language changes (or before if the application
4327 calls the static function, but then no translators are installed so the auto-detection
4328 always yields Qt::LeftToRight).
4329 So we can be certain that it's always the right value.
4330 */
4331 return effective_layout_direction;
4332}
4333
4334/*!
4335 \fn QCursor *QGuiApplication::overrideCursor()
4336
4337 Returns the active application override cursor.
4338
4339 This function returns \nullptr if no application cursor has been defined (i.e. the
4340 internal cursor stack is empty).
4341
4342 \sa setOverrideCursor(), restoreOverrideCursor()
4343*/
4344#ifndef QT_NO_CURSOR
4345QCursor *QGuiApplication::overrideCursor()
4346{
4347 CHECK_QAPP_INSTANCE(nullptr)
4348 return qGuiApp->d_func()->cursor_list.isEmpty() ? nullptr : &qGuiApp->d_func()->cursor_list.first();
4349}
4350
4351/*!
4352 Changes the currently active application override cursor to \a cursor.
4353
4354 This function has no effect if setOverrideCursor() was not called.
4355
4356 \sa setOverrideCursor(), overrideCursor(), restoreOverrideCursor(),
4357 QWidget::setCursor()
4358 */
4359void QGuiApplication::changeOverrideCursor(const QCursor &cursor)
4360{
4362 if (qGuiApp->d_func()->cursor_list.isEmpty())
4363 return;
4364 qGuiApp->d_func()->cursor_list.removeFirst();
4365 setOverrideCursor(cursor);
4366}
4367#endif
4368
4369
4370#ifndef QT_NO_CURSOR
4371static inline void applyCursor(QWindow *w, QCursor c)
4372{
4373 if (const QScreen *screen = w->screen())
4374 if (QPlatformCursor *cursor = screen->handle()->cursor())
4375 cursor->changeCursor(&c, w);
4376}
4377
4378static inline void unsetCursor(QWindow *w)
4379{
4380 if (const QScreen *screen = w->screen())
4381 if (QPlatformCursor *cursor = screen->handle()->cursor())
4382 cursor->changeCursor(nullptr, w);
4383}
4384
4385static inline void applyCursor(const QList<QWindow *> &l, const QCursor &c)
4386{
4387 for (int i = 0; i < l.size(); ++i) {
4388 QWindow *w = l.at(i);
4389 if (w->handle())
4390 applyCursor(w, c);
4391 }
4392}
4393
4394static inline void applyOverrideCursor(const QList<QScreen *> &screens, const QCursor &c)
4395{
4396 for (QScreen *screen : screens) {
4397 if (QPlatformCursor *cursor = screen->handle()->cursor())
4398 cursor->setOverrideCursor(c);
4399 }
4400}
4401
4402static inline void clearOverrideCursor(const QList<QScreen *> &screens)
4403{
4404 for (QScreen *screen : screens) {
4405 if (QPlatformCursor *cursor = screen->handle()->cursor())
4406 cursor->clearOverrideCursor();
4407 }
4408}
4409
4410static inline void applyWindowCursor(const QList<QWindow *> &l)
4411{
4412 for (int i = 0; i < l.size(); ++i) {
4413 QWindow *w = l.at(i);
4414 if (w->handle()) {
4415 if (qt_window_private(w)->hasCursor) {
4416 applyCursor(w, w->cursor());
4417 } else {
4418 unsetCursor(w);
4419 }
4420 }
4421 }
4422}
4423
4424/*!
4425 \fn void QGuiApplication::setOverrideCursor(const QCursor &cursor)
4426
4427 Sets the application override cursor to \a cursor.
4428
4429 Application override cursors are intended for showing the user that the
4430 application is in a special state, for example during an operation that
4431 might take some time.
4432
4433 This cursor will be displayed in all the application's widgets until
4434 restoreOverrideCursor() or another setOverrideCursor() is called.
4435
4436 Application cursors are stored on an internal stack. setOverrideCursor()
4437 pushes the cursor onto the stack, and restoreOverrideCursor() pops the
4438 active cursor off the stack. changeOverrideCursor() changes the currently
4439 active application override cursor.
4440
4441 Every setOverrideCursor() must eventually be followed by a corresponding
4442 restoreOverrideCursor(), otherwise the stack will never be emptied.
4443
4444 Example:
4445 \snippet code/src_gui_kernel_qguiapplication_x11.cpp 0
4446
4447 \sa overrideCursor(), restoreOverrideCursor(), changeOverrideCursor(),
4448 QWidget::setCursor()
4449*/
4450void QGuiApplication::setOverrideCursor(const QCursor &cursor)
4451{
4453 qGuiApp->d_func()->cursor_list.prepend(cursor);
4454 if (QPlatformCursor::capabilities().testFlag(QPlatformCursor::OverrideCursor))
4455 applyOverrideCursor(QGuiApplicationPrivate::screen_list, cursor);
4456 else
4457 applyCursor(QGuiApplicationPrivate::window_list, cursor);
4458}
4459
4460/*!
4461 \fn void QGuiApplication::restoreOverrideCursor()
4462
4463 Undoes the last setOverrideCursor().
4464
4465 If setOverrideCursor() has been called twice, calling
4466 restoreOverrideCursor() will activate the first cursor set. Calling this
4467 function a second time restores the original widgets' cursors.
4468
4469 \sa setOverrideCursor(), overrideCursor()
4470*/
4471void QGuiApplication::restoreOverrideCursor()
4472{
4474 if (qGuiApp->d_func()->cursor_list.isEmpty())
4475 return;
4476 qGuiApp->d_func()->cursor_list.removeFirst();
4477 if (qGuiApp->d_func()->cursor_list.size() > 0) {
4478 QCursor c(qGuiApp->d_func()->cursor_list.value(0));
4479 if (QPlatformCursor::capabilities().testFlag(QPlatformCursor::OverrideCursor))
4480 applyOverrideCursor(QGuiApplicationPrivate::screen_list, c);
4481 else
4482 applyCursor(QGuiApplicationPrivate::window_list, c);
4483 } else {
4484 if (QPlatformCursor::capabilities().testFlag(QPlatformCursor::OverrideCursor))
4485 clearOverrideCursor(QGuiApplicationPrivate::screen_list);
4486 applyWindowCursor(QGuiApplicationPrivate::window_list);
4487 }
4488}
4489#endif// QT_NO_CURSOR
4490
4491/*!
4492 Returns the application's style hints.
4493
4494 The style hints encapsulate a set of platform dependent properties
4495 such as double click intervals, full width selection and others.
4496
4497 The hints can be used to integrate tighter with the underlying platform.
4498
4499 \sa QStyleHints
4500 */
4501QStyleHints *QGuiApplication::styleHints()
4502{
4503 if (!QGuiApplicationPrivate::styleHints)
4504 QGuiApplicationPrivate::styleHints = new QStyleHints();
4505 return QGuiApplicationPrivate::styleHints;
4506}
4507
4508/*!
4509 Sets whether Qt should use the system's standard colors, fonts, etc., to
4510 \a on. By default, this is \c true.
4511
4512 This function must be called before creating the QGuiApplication object, like
4513 this:
4514
4515 \snippet code/src_gui_kernel_qguiapplication.cpp 0
4516
4517 \sa desktopSettingsAware()
4518*/
4519void QGuiApplication::setDesktopSettingsAware(bool on)
4520{
4521 QGuiApplicationPrivate::obey_desktop_settings = on;
4522}
4523
4524/*!
4525 Returns \c true if Qt is set to use the system's standard colors, fonts, etc.;
4526 otherwise returns \c false. The default is \c true.
4527
4528 \sa setDesktopSettingsAware()
4529*/
4530bool QGuiApplication::desktopSettingsAware()
4531{
4532 return QGuiApplicationPrivate::obey_desktop_settings;
4533}
4534
4535/*!
4536 returns the input method.
4537
4538 The input method returns properties about the state and position of
4539 the virtual keyboard. It also provides information about the position of the
4540 current focused input element.
4541
4542 \sa QInputMethod
4543 */
4544QInputMethod *QGuiApplication::inputMethod()
4545{
4546 CHECK_QAPP_INSTANCE(nullptr)
4547 if (!qGuiApp->d_func()->inputMethod)
4548 qGuiApp->d_func()->inputMethod = new QInputMethod();
4549 return qGuiApp->d_func()->inputMethod;
4550}
4551
4552/*!
4553 \fn void QGuiApplication::fontDatabaseChanged()
4554
4555 This signal is emitted when the available fonts have changed.
4556
4557 This can happen when application fonts are added or removed, or when the
4558 system fonts change.
4559
4560 \sa QFontDatabase::addApplicationFont(),
4561 QFontDatabase::addApplicationFontFromData(),
4562 QFontDatabase::removeAllApplicationFonts(),
4563 QFontDatabase::removeApplicationFont()
4564*/
4565
4566QPixmap QGuiApplicationPrivate::getPixmapCursor(Qt::CursorShape cshape)
4567{
4568 Q_UNUSED(cshape);
4569 return QPixmap();
4570}
4571
4572QPoint QGuiApplicationPrivate::QLastCursorPosition::toPoint() const noexcept
4573{
4574 // Guard against the default initialization of qInf() (avoid UB or SIGFPE in conversion).
4575 if (Q_UNLIKELY(qIsInf(thePoint.x())))
4576 return QPoint(std::numeric_limits<int>::max(), std::numeric_limits<int>::max());
4577 return thePoint.toPoint();
4578}
4579
4580#if QT_CONFIG(draganddrop)
4581void QGuiApplicationPrivate::notifyDragStarted(const QDrag *drag)
4582{
4583 Q_UNUSED(drag);
4584
4585}
4586#endif
4587
4588const QColorTrcLut *QGuiApplicationPrivate::colorProfileForA8Text()
4589{
4590#ifdef Q_OS_WIN
4591 if (!m_a8ColorProfile)
4592 m_a8ColorProfile = QColorTrcLut::fromGamma(2.31f); // This is a hard-coded thing for Windows text rendering
4593 return m_a8ColorProfile.get();
4594#else
4595 return colorProfileForA32Text();
4596#endif
4597}
4598
4599const QColorTrcLut *QGuiApplicationPrivate::colorProfileForA32Text()
4600{
4601 if (!m_a32ColorProfile)
4602 m_a32ColorProfile = QColorTrcLut::fromGamma(float(fontSmoothingGamma));
4603 return m_a32ColorProfile.get();
4604}
4605
4606void QGuiApplicationPrivate::_q_updateFocusObject(QObject *object)
4607{
4608 Q_Q(QGuiApplication);
4609
4610 QPlatformInputContext *inputContext = platformIntegration()->inputContext();
4611 const bool enabled = inputContext && QInputMethodPrivate::objectAcceptsInputMethod(object);
4612
4613 QPlatformInputContextPrivate::setInputMethodAccepted(enabled);
4614 if (inputContext)
4615 inputContext->setFocusObject(object);
4616 emit q->focusObjectChanged(object);
4617}
4618
4619enum MouseMasks {
4620 MouseCapsMask = 0xFF,
4621 MouseSourceMaskDst = 0xFF00,
4622 MouseSourceMaskSrc = MouseCapsMask,
4623 MouseSourceShift = 8,
4624 MouseFlagsCapsMask = 0xFF0000,
4625 MouseFlagsShift = 16
4626};
4627
4628QInputDeviceManager *QGuiApplicationPrivate::inputDeviceManager()
4629{
4630 Q_ASSERT(QGuiApplication::instance());
4631
4632 if (!m_inputDeviceManager)
4633 m_inputDeviceManager = new QInputDeviceManager(QGuiApplication::instance());
4634
4635 return m_inputDeviceManager;
4636}
4637
4638/*!
4639 Returns the QThreadPool instance for Qt Gui.
4640 \internal
4641*/
4642QThreadPool *QGuiApplicationPrivate::qtGuiThreadPool()
4643{
4644#if QT_CONFIG(qtgui_threadpool)
4645 Q_CONSTINIT static QPointer<QThreadPool> guiInstance;
4646 Q_CONSTINIT static QBasicMutex theMutex;
4647 const static bool runtime_disable = qEnvironmentVariableIsSet("QT_NO_GUI_THREADPOOL");
4648 if (runtime_disable)
4649 return nullptr;
4650 const QMutexLocker locker(&theMutex);
4651 if (guiInstance.isNull() && !QCoreApplication::closingDown()) {
4652 guiInstance = new QThreadPool();
4653 // Limit max thread to avoid too many parallel threads.
4654 // We are not optimized for much more than 4 or 8 threads.
4655 if (guiInstance && guiInstance->maxThreadCount() > 4)
4656 guiInstance->setMaxThreadCount(qBound(4, guiInstance->maxThreadCount() / 2, 8));
4657 }
4658 return guiInstance;
4659#else
4660 return nullptr;
4661#endif
4662}
4663
4664/*!
4665 \fn template <typename QNativeInterface> QNativeInterface *QGuiApplication::nativeInterface() const
4666
4667 Returns a native interface of the given type for the application.
4668
4669 This function provides access to platform specific functionality
4670 of QGuiApplication, as defined in the QNativeInterface namespace:
4671
4672 \annotatedlist native-interfaces-qguiapplication
4673
4674 If the requested interface is not available a \nullptr is returned.
4675 */
4676
4677void *QGuiApplication::resolveInterface(const char *name, int revision) const
4678{
4679 using namespace QNativeInterface;
4680 using namespace QNativeInterface::Private;
4681
4682 auto *platformIntegration = QGuiApplicationPrivate::platformIntegration();
4683 Q_UNUSED(platformIntegration);
4684
4685#if defined(Q_OS_WIN)
4686 QT_NATIVE_INTERFACE_RETURN_IF(QWindowsApplication, platformIntegration);
4687#endif
4688#if QT_CONFIG(xcb)
4689 QT_NATIVE_INTERFACE_RETURN_IF(QX11Application, platformNativeInterface());
4690#endif
4691#if QT_CONFIG(wayland)
4692 QT_NATIVE_INTERFACE_RETURN_IF(QWaylandApplication, platformNativeInterface());
4693#endif
4694#if defined(Q_OS_VISIONOS)
4695 QT_NATIVE_INTERFACE_RETURN_IF(QVisionOSApplication, platformIntegration);
4696#endif
4697
4698 return QCoreApplication::resolveInterface(name, revision);
4699}
4700
4701QT_END_NAMESPACE
4702
4703#include "moc_qguiapplication.cpp"
The QClipboard class provides access to the window system clipboard.
Definition qclipboard.h:21
\reentrant
Definition qfont.h:23
The QIcon class provides scalable icons in different modes and states.
Definition qicon.h:21
QInputDeviceManager acts as a communication hub between QtGui and the input handlers.
The QPalette class contains color groups for each widget state.
Definition qpalette.h:20
The QPlatformIntegration class is the entry for WindowSystem specific functionality.
The QPlatformTheme class allows customizing the UI based on themes.
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:177
The QStyleHints class contains platform specific hints and settings. \inmodule QtGui.
Definition qstylehints.h:20
\inmodule QtGui
Definition qwindow.h:64
#define qApp
Q_LOGGING_CATEGORY(lcEventDispatcher, "qt.eventdispatcher")
static bool needsWindowBlockedEvent(const QWindow *w)
Q_CORE_EXPORT void qt_call_post_routines()
static void init_plugins(const QList< QByteArray > &pluginList)
static void initFontUnlocked()
static void clearFontUnlocked()
void qRegisterGuiVariant()
static Q_CONSTINIT unsigned applicationResourceFlags
static Q_CONSTINIT int touchDoubleTapDistance
static QWindowGeometrySpecification windowGeometrySpecification
static bool qt_detectRTLLanguage()
Q_CONSTINIT Q_GUI_EXPORT bool qt_is_tty_app
static Q_CONSTINIT bool force_reverse
static Q_CONSTINIT int mouseDoubleClickDistance
#define Q_WINDOW_GEOMETRY_SPECIFICATION_INITIALIZER
static void init_platform(const QString &pluginNamesWithArguments, const QString &platformPluginPath, const QString &platformThemeName, int &argc, char **argv)
static void initThemeHints()
static int nextGeometryToken(const QByteArray &a, int &pos, char *op)
#define CHECK_QAPP_INSTANCE(...)
ApplicationResourceFlags
@ ApplicationFontExplicitlySet
static void updateBlockedStatusRecursion(QWindow *window, bool shouldBeBlocked)
#define qGuiApp
QT_BEGIN_NAMESPACE Q_STATIC_LOGGING_CATEGORY(lcSynthesizedIterableAccess, "qt.iterable.synthesized", QtWarningMsg)
QDebug Q_GUI_EXPORT & operator<<(QDebug &s, const QVectorPath &path)
void applyTo(QWindow *window) const
static QWindowGeometrySpecification fromArgument(const QByteArray &a)