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