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