1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "qplatformdefs.h"
5#include "qabstracteventdispatcher.h"
6#include "qapplication.h"
7#include "qclipboard.h"
8#include "qcursor.h"
9#include "qdir.h"
10#include "qevent.h"
11#include "qfile.h"
12#include "qfileinfo.h"
13#if QT_CONFIG(graphicsview)
14#include "qgraphicsscene.h"
15#include <QtWidgets/qgraphicsproxywidget.h>
16#endif
17#include "qhash.h"
18#include "qset.h"
19#include "qlayout.h"
20#include "qpixmapcache.h"
21#include "qstyle.h"
22#include "qstyleoption.h"
23#include "qstylefactory.h"
24#if QT_CONFIG(tooltip)
25#include "qtooltip.h"
26#endif
27#include "qtranslator.h"
28#include "qvariant.h"
29#include "qwidget.h"
30#if QT_CONFIG(draganddrop)
31#include <private/qdnd_p.h>
32#endif
33#include "private/qguiapplication_p.h"
34#include "qcolormap.h"
35#include "qdebug.h"
36#include "private/qstylesheetstyle_p.h"
37#include "private/qstyle_p.h"
38#if QT_CONFIG(messagebox)
39#include "qmessagebox.h"
40#endif
41#include "qwidgetwindow_p.h"
42#include <QtGui/qstylehints.h>
43#include <QtGui/qinputmethod.h>
44#include <QtGui/private/qwindow_p.h>
45#include <QtGui/qpointingdevice.h>
46#include <QtGui/private/qpointingdevice_p.h>
47#include <qpa/qplatformtheme.h>
48#if QT_CONFIG(whatsthis)
49#include <QtWidgets/QWhatsThis>
50#endif
51#if QT_CONFIG(accessibility)
52#include <QtGui/qaccessible_base.h>
53#include "private/qaccessiblewidgetfactory_p.h"
54#endif
55
56#include "private/qkeymapper_p.h"
57
58#include <qthread.h>
59#include <private/qthread_p.h>
60
61#include <QtGui/private/qevent_p.h>
62#include <QtGui/private/qeventpoint_p.h>
63#include <private/qfont_p.h>
64#if QT_CONFIG(action)
65#include <private/qaction_p.h>
66#endif
67
68#include <stdlib.h>
69
70#include "qapplication_p.h"
71#include "qwidget_p.h"
72
73#include "qgesture.h"
74#include "private/qgesturemanager_p.h"
75#include <qpa/qplatformfontdatabase.h>
76
77#include "qdatetime.h"
78
79#include <qpa/qplatformwindow.h>
80
81#include <qtwidgets_tracepoints_p.h>
82
83#ifdef Q_OS_MACOS
84#include <QtCore/private/qcore_mac_p.h>
85#endif
86
87#include <algorithm>
88#include <iterator>
89
90static void initResources()
91{
92 Q_INIT_RESOURCE(qstyle);
93
94#if QT_CONFIG(messagebox)
95 Q_INIT_RESOURCE(qmessagebox);
96#endif
97}
98
99QT_BEGIN_NAMESPACE
100
101using namespace Qt::StringLiterals;
102
103Q_TRACE_PREFIX(qtwidgets,
104 "#include <qcoreevent.h>"
105);
106Q_TRACE_METADATA(qtwidgets, "ENUM { AUTO, RANGE User ... MaxUser } QEvent::Type;");
107Q_TRACE_POINT(qtwidgets, QApplication_notify_entry, QObject *receiver, QEvent *event, QEvent::Type type);
108Q_TRACE_POINT(qtwidgets, QApplication_notify_exit, bool consumed, bool filtered);
109
110// Helper macro for static functions to check on the existence of the application class.
111#define CHECK_QAPP_INSTANCE(...) \
112 if (Q_LIKELY(QCoreApplication::instance())) { \
113 } else { \
114 qWarning("Must construct a QApplication first."); \
115 return __VA_ARGS__; \
116 }
117
118Q_CORE_EXPORT void qt_call_post_routines();
119Q_GUI_EXPORT bool qt_sendShortcutOverrideEvent(QObject *o, ulong timestamp, int k, Qt::KeyboardModifiers mods, const QString &text = QString(), bool autorep = false, ushort count = 1);
120
121QApplicationPrivate *QApplicationPrivate::self = nullptr;
122
123bool QApplicationPrivate::autoSipEnabled = true;
124
125QApplicationPrivate::QApplicationPrivate(int &argc, char **argv)
126 : QGuiApplicationPrivate(argc, argv)
127{
128 application_type = QApplicationPrivate::Gui;
129
130#ifndef QT_NO_GESTURES
131 gestureManager = nullptr;
132 gestureWidget = nullptr;
133#endif // QT_NO_GESTURES
134
135 if (!self)
136 self = this;
137}
138
139QApplicationPrivate::~QApplicationPrivate()
140{
141 if (self == this)
142 self = nullptr;
143}
144
145void QApplicationPrivate::createEventDispatcher()
146{
147 QGuiApplicationPrivate::createEventDispatcher();
148}
149
150/*!
151 \class QApplication
152 \brief The QApplication class manages the GUI application's control
153 flow and main settings.
154
155 \inmodule QtWidgets
156
157 QApplication specializes QGuiApplication with some functionality needed
158 for QWidget-based applications. It handles widget specific initialization,
159 finalization.
160
161 For any GUI application using Qt, there is precisely \b one QApplication
162 object, no matter whether the application has 0, 1, 2 or more windows at
163 any given time. For non-QWidget based Qt applications, use QGuiApplication instead,
164 as it does not depend on the \l QtWidgets library.
165
166 Some GUI applications provide a special batch mode ie. provide command line
167 arguments for executing tasks without manual intervention. In such non-GUI
168 mode, it is often sufficient to instantiate a plain QCoreApplication to
169 avoid unnecessarily initializing resources needed for a graphical user
170 interface. The following example shows how to dynamically create an
171 appropriate type of application instance:
172
173 \snippet code/src_gui_kernel_qapplication.cpp 0
174
175 The QApplication object is accessible through the instance() function that
176 returns a pointer equivalent to the global qApp pointer.
177
178 QApplication's main areas of responsibility are:
179 \list
180 \li It initializes the application with the user's desktop settings
181 such as palette(), font() and doubleClickInterval(). It keeps
182 track of these properties in case the user changes the desktop
183 globally, for example through some kind of control panel.
184
185 \li It performs event handling, meaning that it receives events
186 from the underlying window system and dispatches them to the
187 relevant widgets. By using sendEvent() and postEvent() you can
188 send your own events to widgets.
189
190 \li It parses common command line arguments and sets its internal
191 state accordingly. See the \l{QApplication::QApplication()}
192 {constructor documentation} below for more details.
193
194 \li It defines the application's look and feel, which is
195 encapsulated in a QStyle object. This can be changed at runtime
196 with setStyle().
197
198 \li It provides localization of strings that are visible to the
199 user via translate().
200
201 \li It provides some magical objects like the clipboard().
202
203 \li It knows about the application's windows. You can ask which
204 widget is at a certain position using widgetAt(), get a list of
205 topLevelWidgets() and closeAllWindows(), etc.
206
207 \li It manages the application's mouse cursor handling, see
208 setOverrideCursor()
209 \endlist
210
211 Since the QApplication object does so much initialization, it \e{must} be
212 created before any other objects related to the user interface are created.
213 QApplication also deals with common command line arguments. Hence, it is
214 usually a good idea to create it \e before any interpretation or
215 modification of \c argv is done in the application itself.
216
217 \table
218 \header
219 \li{2,1} Groups of functions
220
221 \row
222 \li System settings
223 \li desktopSettingsAware(),
224 setDesktopSettingsAware(),
225 cursorFlashTime(),
226 setCursorFlashTime(),
227 doubleClickInterval(),
228 setDoubleClickInterval(),
229 setKeyboardInputInterval(),
230 wheelScrollLines(),
231 setWheelScrollLines(),
232 palette(),
233 setPalette(),
234 font(),
235 setFont(),
236 fontMetrics().
237
238 \row
239 \li Event handling
240 \li exec(),
241 processEvents(),
242 exit(),
243 quit().
244 sendEvent(),
245 postEvent(),
246 sendPostedEvents(),
247 removePostedEvents(),
248 notify().
249
250 \row
251 \li GUI Styles
252 \li style(),
253 setStyle().
254
255 \row
256 \li Text handling
257 \li installTranslator(),
258 removeTranslator()
259 translate().
260
261 \row
262 \li Widgets
263 \li allWidgets(),
264 topLevelWidgets(),
265 activePopupWidget(),
266 activeModalWidget(),
267 clipboard(),
268 focusWidget(),
269 activeWindow(),
270 widgetAt().
271
272 \row
273 \li Advanced cursor handling
274 \li overrideCursor(),
275 setOverrideCursor(),
276 restoreOverrideCursor().
277
278 \row
279 \li Miscellaneous
280 \li closeAllWindows(),
281 startingUp(),
282 closingDown().
283 \endtable
284
285 \sa QCoreApplication, QAbstractEventDispatcher, QEventLoop, QSettings
286*/
287
288/*!
289 \fn QWidget *QApplication::topLevelAt(const QPoint &point)
290
291 Returns the top-level widget at the given \a point; returns \nullptr if
292 there is no such widget.
293*/
294QWidget *QApplication::topLevelAt(const QPoint &pos)
295{
296 if (const QWindow *window = QGuiApplication::topLevelAt(pos)) {
297 if (const QWidgetWindow *widgetWindow = qobject_cast<const QWidgetWindow *>(object: window))
298 return widgetWindow->widget();
299 }
300 return nullptr;
301}
302
303/*!
304 \fn QWidget *QApplication::topLevelAt(int x, int y)
305
306 \overload
307
308 Returns the top-level widget at the point (\a{x}, \a{y}); returns
309 0 if there is no such widget.
310*/
311
312void qt_init_tooltip_palette();
313void qt_cleanup();
314
315QStyle *QApplicationPrivate::app_style = nullptr; // default application style
316#ifndef QT_NO_STYLE_STYLESHEET
317QString QApplicationPrivate::styleSheet; // default application stylesheet
318#endif
319QPointer<QWidget> QApplicationPrivate::leaveAfterRelease = nullptr;
320
321QFont *QApplicationPrivate::sys_font = nullptr; // default system font
322QFont *QApplicationPrivate::set_font = nullptr; // default font set by programmer
323
324QWidget *QApplicationPrivate::main_widget = nullptr; // main application widget
325QWidget *QApplicationPrivate::focus_widget = nullptr; // has keyboard input focus
326QWidget *QApplicationPrivate::hidden_focus_widget = nullptr; // will get keyboard input focus after show()
327QWidget *QApplicationPrivate::active_window = nullptr; // toplevel with keyboard focus
328#if QT_CONFIG(wheelevent)
329QPointer<QWidget> QApplicationPrivate::wheel_widget;
330#endif
331bool qt_in_tab_key_event = false;
332int qt_antialiasing_threshold = -1;
333int QApplicationPrivate::enabledAnimations = QPlatformTheme::GeneralUiEffect;
334bool QApplicationPrivate::widgetCount = false;
335#ifdef QT_KEYPAD_NAVIGATION
336Qt::NavigationMode QApplicationPrivate::navigationMode = Qt::NavigationModeKeypadTabOrder;
337QWidget *QApplicationPrivate::oldEditFocus = nullptr;
338#endif
339
340inline bool QApplicationPrivate::isAlien(QWidget *widget)
341{
342 return widget && !widget->isWindow();
343}
344
345bool Q_WIDGETS_EXPORT qt_tab_all_widgets()
346{
347 return QGuiApplication::styleHints()->tabFocusBehavior() == Qt::TabFocusAllControls;
348}
349
350// ######## move to QApplicationPrivate
351// Default fonts (per widget type)
352Q_GLOBAL_STATIC(FontHash, app_fonts)
353// Exported accessor for use outside of this file
354FontHash *qt_app_fonts_hash() { return app_fonts(); }
355
356QWidgetList *QApplicationPrivate::popupWidgets = nullptr; // has keyboard input focus
357
358QWidget *qt_desktopWidget = nullptr; // root window widgets
359
360/*!
361 \internal
362*/
363void QApplicationPrivate::process_cmdline()
364{
365 if (styleOverride.isEmpty() && qEnvironmentVariableIsSet(varName: "QT_STYLE_OVERRIDE"))
366 styleOverride = QString::fromLocal8Bit(ba: qgetenv(varName: "QT_STYLE_OVERRIDE"));
367
368 // process platform-indep command line
369 if (qt_is_tty_app || !argc)
370 return;
371
372 int i, j;
373
374 j = 1;
375 for (i=1; i<argc; i++) { // if you add anything here, modify QCoreApplication::arguments()
376 if (!argv[i])
377 continue;
378 if (*argv[i] != '-') {
379 argv[j++] = argv[i];
380 continue;
381 }
382 const char *arg = argv[i];
383 if (arg[1] == '-') // startsWith("--")
384 ++arg;
385 if (strcmp(s1: arg, s2: "-qdevel") == 0 || strcmp(s1: arg, s2: "-qdebug") == 0) {
386 // obsolete argument
387#ifndef QT_NO_STYLE_STYLESHEET
388 } else if (strcmp(s1: arg, s2: "-stylesheet") == 0 && i < argc -1) {
389 styleSheet = "file:///"_L1;
390 styleSheet.append(s: QString::fromLocal8Bit(ba: argv[++i]));
391 } else if (strncmp(s1: arg, s2: "-stylesheet=", n: 12) == 0) {
392 styleSheet = "file:///"_L1;
393 styleSheet.append(s: QString::fromLocal8Bit(ba: arg + 12));
394#endif
395 } else if (qstrcmp(str1: arg, str2: "-widgetcount") == 0) {
396 widgetCount = true;
397 } else {
398 argv[j++] = argv[i];
399 }
400 }
401
402 if (j < argc) {
403 argv[j] = nullptr;
404 argc = j;
405 }
406}
407
408/*!
409 Initializes the window system and constructs an application object with
410 \a argc command line arguments in \a argv.
411
412 \warning The data referred to by \a argc and \a argv must stay valid for
413 the entire lifetime of the QApplication object. In addition, \a argc must
414 be greater than zero and \a argv must contain at least one valid character
415 string.
416
417 The global \c qApp pointer refers to this application object. Only one
418 application object should be created.
419
420 This application object must be constructed before any \l{QPaintDevice}
421 {paint devices} (including widgets, pixmaps, bitmaps etc.).
422
423 \note \a argc and \a argv might be changed as Qt removes command line
424 arguments that it recognizes.
425
426 All Qt programs automatically support the following command line options:
427 \list
428 \li -style= \e style, sets the application GUI style. Possible values
429 depend on your system configuration. If you compiled Qt with
430 additional styles or have additional styles as plugins these will
431 be available to the \c -style command line option. You can also
432 set the style for all Qt applications by setting the
433 \c QT_STYLE_OVERRIDE environment variable.
434 \li -style \e style, is the same as listed above.
435 \li -stylesheet= \e stylesheet, sets the application \l styleSheet. The
436 value must be a path to a file that contains the Style Sheet.
437 \note Relative URLs in the Style Sheet file are relative to the
438 Style Sheet file's path.
439 \li -stylesheet \e stylesheet, is the same as listed above.
440 \li -widgetcount, prints debug message at the end about number of
441 widgets left undestroyed and maximum number of widgets existed at
442 the same time
443 \li -reverse, sets the application's layout direction to
444 Qt::RightToLeft
445 \li -qmljsdebugger=, activates the QML/JS debugger with a specified port.
446 The value must be of format port:1234[,block], where block is optional
447 and will make the application wait until a debugger connects to it.
448 \endlist
449
450 \sa QCoreApplication::arguments()
451*/
452
453#ifdef Q_QDOC
454QApplication::QApplication(int &argc, char **argv)
455#else
456QApplication::QApplication(int &argc, char **argv, int)
457#endif
458 : QGuiApplication(*new QApplicationPrivate(argc, argv))
459{
460 Q_D(QApplication);
461 d->init();
462}
463
464/*!
465 \internal
466*/
467void QApplicationPrivate::init()
468{
469#if defined(Q_OS_MACOS)
470 QMacAutoReleasePool pool;
471#endif
472
473 QGuiApplicationPrivate::init();
474
475 initResources();
476
477 qt_is_tty_app = (application_type == QApplicationPrivate::Tty);
478 process_cmdline();
479
480 // Must be called before initialize()
481 QColormap::initialize();
482 initializeWidgetPalettesFromTheme();
483 qt_init_tooltip_palette();
484 QApplicationPrivate::initializeWidgetFontHash();
485
486 initialize();
487 eventDispatcher->startingUp();
488
489#if QT_CONFIG(accessibility)
490 // factory for accessible interfaces for widgets shipped with Qt
491 QAccessible::installFactory(&qAccessibleFactory);
492#endif
493
494}
495
496void qt_init_tooltip_palette()
497{
498#if QT_CONFIG(tooltip)
499 if (const QPalette *toolTipPalette = QGuiApplicationPrivate::platformTheme()->palette(type: QPlatformTheme::ToolTipPalette)) {
500 QPalette toolTipPal = *toolTipPalette;
501 toolTipPal.setResolveMask(0);
502 QToolTip::setPalette(toolTipPal);
503 }
504#endif
505}
506
507extern void qRegisterWidgetsVariant();
508
509/*!
510 Initializes the QApplication object, called from the constructors.
511*/
512void QApplicationPrivate::initialize()
513{
514 is_app_running = false; // Starting up.
515
516 QWidgetPrivate::mapper = new QWidgetMapper;
517 QWidgetPrivate::allWidgets = new QWidgetSet;
518
519 // needed for a static build.
520 qRegisterWidgetsVariant();
521
522 // needed for widgets in QML
523 QAbstractDeclarativeData::setWidgetParent = QWidgetPrivate::setWidgetParentHelper;
524
525 if (application_type != QApplicationPrivate::Tty) {
526 if (!styleOverride.isEmpty()) {
527 if (auto *style = QStyleFactory::create(styleOverride.toLower())) {
528 QApplication::setStyle(style);
529 } else {
530 qWarning(msg: "QApplication: invalid style override '%s' passed, ignoring it.\n"
531 "\tAvailable styles: %s", qPrintable(styleOverride),
532 qPrintable(QStyleFactory::keys().join(", "_L1)));
533 // Clear styleOverride so it is not picked by Qt Quick Controls (QTBUG-100563)
534 styleOverride.clear();
535 }
536 }
537
538 // Trigger default style if none was set already
539 Q_UNUSED(QApplication::style());
540 }
541
542 if (qEnvironmentVariableIntValue(varName: "QT_USE_NATIVE_WINDOWS") > 0)
543 QCoreApplication::setAttribute(attribute: Qt::AA_NativeWindows);
544
545 if (!qt_is_tty_app)
546 initializeMultitouch();
547
548 if (QGuiApplication::desktopSettingsAware())
549 if (const QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme()) {
550 QApplicationPrivate::enabledAnimations = theme->themeHint(hint: QPlatformTheme::UiEffects).toInt();
551 }
552
553 is_app_running = true; // no longer starting up
554}
555
556void QApplicationPrivate::initializeWidgetFontHash()
557{
558 const QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme();
559 if (!theme)
560 return;
561 FontHash *fontHash = app_fonts();
562 fontHash->clear();
563
564 if (const QFont *font = theme->font(type: QPlatformTheme::MenuFont))
565 fontHash->insert(QByteArrayLiteral("QMenu"), value: *font);
566 if (const QFont *font = theme->font(type: QPlatformTheme::MenuBarFont))
567 fontHash->insert(QByteArrayLiteral("QMenuBar"), value: *font);
568 if (const QFont *font = theme->font(type: QPlatformTheme::MenuItemFont))
569 fontHash->insert(QByteArrayLiteral("QMenuItem"), value: *font);
570 if (const QFont *font = theme->font(type: QPlatformTheme::MessageBoxFont))
571 fontHash->insert(QByteArrayLiteral("QMessageBox"), value: *font);
572 if (const QFont *font = theme->font(type: QPlatformTheme::LabelFont))
573 fontHash->insert(QByteArrayLiteral("QLabel"), value: *font);
574 if (const QFont *font = theme->font(type: QPlatformTheme::TipLabelFont))
575 fontHash->insert(QByteArrayLiteral("QTipLabel"), value: *font);
576 if (const QFont *font = theme->font(type: QPlatformTheme::TitleBarFont))
577 fontHash->insert(QByteArrayLiteral("QTitleBar"), value: *font);
578 if (const QFont *font = theme->font(type: QPlatformTheme::StatusBarFont))
579 fontHash->insert(QByteArrayLiteral("QStatusBar"), value: *font);
580 if (const QFont *font = theme->font(type: QPlatformTheme::MdiSubWindowTitleFont))
581 fontHash->insert(QByteArrayLiteral("QMdiSubWindowTitleBar"), value: *font);
582 if (const QFont *font = theme->font(type: QPlatformTheme::DockWidgetTitleFont))
583 fontHash->insert(QByteArrayLiteral("QDockWidgetTitle"), value: *font);
584 if (const QFont *font = theme->font(type: QPlatformTheme::PushButtonFont))
585 fontHash->insert(QByteArrayLiteral("QPushButton"), value: *font);
586 if (const QFont *font = theme->font(type: QPlatformTheme::CheckBoxFont))
587 fontHash->insert(QByteArrayLiteral("QCheckBox"), value: *font);
588 if (const QFont *font = theme->font(type: QPlatformTheme::RadioButtonFont))
589 fontHash->insert(QByteArrayLiteral("QRadioButton"), value: *font);
590 if (const QFont *font = theme->font(type: QPlatformTheme::ToolButtonFont))
591 fontHash->insert(QByteArrayLiteral("QToolButton"), value: *font);
592 if (const QFont *font = theme->font(type: QPlatformTheme::ItemViewFont))
593 fontHash->insert(QByteArrayLiteral("QAbstractItemView"), value: *font);
594 if (const QFont *font = theme->font(type: QPlatformTheme::ListViewFont))
595 fontHash->insert(QByteArrayLiteral("QListView"), value: *font);
596 if (const QFont *font = theme->font(type: QPlatformTheme::HeaderViewFont))
597 fontHash->insert(QByteArrayLiteral("QHeaderView"), value: *font);
598 if (const QFont *font = theme->font(type: QPlatformTheme::ListBoxFont))
599 fontHash->insert(QByteArrayLiteral("QListBox"), value: *font);
600 if (const QFont *font = theme->font(type: QPlatformTheme::ComboMenuItemFont))
601 fontHash->insert(QByteArrayLiteral("QComboMenuItem"), value: *font);
602 if (const QFont *font = theme->font(type: QPlatformTheme::ComboLineEditFont))
603 fontHash->insert(QByteArrayLiteral("QComboLineEdit"), value: *font);
604 if (const QFont *font = theme->font(type: QPlatformTheme::SmallFont))
605 fontHash->insert(QByteArrayLiteral("QSmallFont"), value: *font);
606 if (const QFont *font = theme->font(type: QPlatformTheme::MiniFont))
607 fontHash->insert(QByteArrayLiteral("QMiniFont"), value: *font);
608}
609
610/*****************************************************************************
611 Functions returning the active popup and modal widgets.
612 *****************************************************************************/
613
614/*!
615 Returns the active popup widget.
616
617 A popup widget is a special top-level widget that sets the \c
618 Qt::WType_Popup widget flag, e.g. the QMenu widget. When the application
619 opens a popup widget, all events are sent to the popup. Normal widgets and
620 modal widgets cannot be accessed before the popup widget is closed.
621
622 Only other popup widgets may be opened when a popup widget is shown. The
623 popup widgets are organized in a stack. This function returns the active
624 popup widget at the top of the stack.
625
626 \sa activeModalWidget(), topLevelWidgets()
627*/
628
629QWidget *QApplication::activePopupWidget()
630{
631 return QApplicationPrivate::popupWidgets && !QApplicationPrivate::popupWidgets->isEmpty() ?
632 QApplicationPrivate::popupWidgets->constLast() : nullptr;
633}
634
635
636/*!
637 Returns the active modal widget.
638
639 A modal widget is a special top-level widget which is a subclass of QDialog
640 that specifies the modal parameter of the constructor as true. A modal
641 widget must be closed before the user can continue with other parts of the
642 program.
643
644 Modal widgets are organized in a stack. This function returns the active
645 modal widget at the top of the stack.
646
647 \sa activePopupWidget(), topLevelWidgets()
648*/
649
650QWidget *QApplication::activeModalWidget()
651{
652 QWidgetWindow *widgetWindow = qobject_cast<QWidgetWindow *>(object: modalWindow());
653 return widgetWindow ? widgetWindow->widget() : nullptr;
654}
655
656/*!
657 Cleans up any window system resources that were allocated by this
658 application. Sets the global variable \c qApp to \nullptr.
659*/
660
661QApplication::~QApplication()
662{
663 Q_D(QApplication);
664
665 //### this should probable be done even later
666 qt_call_post_routines();
667
668 // kill timers before closing down the dispatcher
669 d->toolTipWakeUp.stop();
670 d->toolTipFallAsleep.stop();
671
672 QApplicationPrivate::is_app_closing = true;
673 QApplicationPrivate::is_app_running = false;
674
675 delete QWidgetPrivate::mapper;
676 QWidgetPrivate::mapper = nullptr;
677
678 // delete all widgets
679 if (QWidgetPrivate::allWidgets) {
680 QWidgetSet *mySet = QWidgetPrivate::allWidgets;
681 QWidgetPrivate::allWidgets = nullptr;
682 for (QWidgetSet::ConstIterator it = mySet->constBegin(), cend = mySet->constEnd(); it != cend; ++it) {
683 QWidget *w = *it;
684 if (!w->parent()) // window
685 w->destroy(destroyWindow: true, destroySubWindows: true);
686 }
687 delete mySet;
688 }
689
690 delete qt_desktopWidget;
691 qt_desktopWidget = nullptr;
692
693 QApplicationPrivate::widgetPalettes.clear();
694
695 delete QApplicationPrivate::sys_font;
696 QApplicationPrivate::sys_font = nullptr;
697 delete QApplicationPrivate::set_font;
698 QApplicationPrivate::set_font = nullptr;
699 app_fonts()->clear();
700
701 delete QApplicationPrivate::app_style;
702 QApplicationPrivate::app_style = nullptr;
703
704#if QT_CONFIG(draganddrop)
705 if (!qt_is_tty_app)
706 delete QDragManager::self();
707#endif
708
709 d->cleanupMultitouch();
710
711 qt_cleanup();
712
713 if (QApplicationPrivate::widgetCount)
714 qDebug(msg: "Widgets left: %i Max widgets: %i \n", QWidgetPrivate::instanceCounter, QWidgetPrivate::maxInstances);
715
716 QApplicationPrivate::obey_desktop_settings = true;
717
718 QApplicationPrivate::enabledAnimations = QPlatformTheme::GeneralUiEffect;
719 QApplicationPrivate::widgetCount = false;
720}
721
722void qt_cleanup()
723{
724 QPixmapCache::clear();
725 QColormap::cleanup();
726
727 QApplicationPrivate::active_window = nullptr; //### this should not be necessary
728}
729
730/*!
731 \fn QWidget *QApplication::widgetAt(const QPoint &point)
732
733 Returns the widget at global screen position \a point, or \nullptr
734 if there is no Qt widget there.
735
736 This function can be slow.
737
738 \sa QCursor::pos(), QWidget::grabMouse(), QWidget::grabKeyboard()
739*/
740QWidget *QApplication::widgetAt(const QPoint &p)
741{
742 QWidget *window = QApplication::topLevelAt(pos: p);
743 if (!window)
744 return nullptr;
745
746 QWidget *child = nullptr;
747
748 if (!window->testAttribute(attribute: Qt::WA_TransparentForMouseEvents))
749 child = window->childAt(p: window->mapFromGlobal(p));
750
751 if (child)
752 return child;
753
754 if (window->testAttribute(attribute: Qt::WA_TransparentForMouseEvents)) {
755 //shoot a hole in the widget and try once again,
756 //suboptimal on Qt for Embedded Linux where we do
757 //know the stacking order of the toplevels.
758 int x = p.x();
759 int y = p.y();
760 QRegion oldmask = window->mask();
761 QPoint wpoint = window->mapFromGlobal(QPoint(x, y));
762 QRegion newmask = (oldmask.isEmpty() ? QRegion(window->rect()) : oldmask)
763 - QRegion(wpoint.x(), wpoint.y(), 1, 1);
764 window->setMask(newmask);
765 QWidget *recurse = nullptr;
766 if (QApplication::topLevelAt(pos: p) != window) // verify recursion will terminate
767 recurse = widgetAt(x, y);
768 if (oldmask.isEmpty())
769 window->clearMask();
770 else
771 window->setMask(oldmask);
772 return recurse;
773 }
774 return window;
775}
776
777/*!
778 \fn QWidget *QApplication::widgetAt(int x, int y)
779
780 \overload
781
782 Returns the widget at global screen position (\a x, \a y), or
783 \nullptr if there is no Qt widget there.
784*/
785
786/*!
787 \internal
788*/
789bool QApplication::compressEvent(QEvent *event, QObject *receiver, QPostEventList *postedEvents)
790{
791 // Only compress the following events:
792 const QEvent::Type type = event->type();
793 switch (type) {
794 case QEvent::UpdateRequest:
795 case QEvent::LayoutRequest:
796 case QEvent::Resize:
797 case QEvent::Move:
798 case QEvent::LanguageChange:
799 break;
800 default:
801 return QGuiApplication::compressEvent(event, receiver, postedEvents);
802 }
803
804 for (const auto &postedEvent : std::as_const(t&: *postedEvents)) {
805
806 // Continue, unless a valid event of the same type exists for the same receiver
807 if (postedEvent.receiver != receiver
808 || !postedEvent.event
809 || postedEvent.event->type() != type) {
810 continue;
811 }
812
813 // Handle type specific compression
814 switch (type) {
815 case QEvent::Resize:
816 static_cast<QResizeEvent *>(postedEvent.event)->m_size =
817 static_cast<const QResizeEvent *>(event)->size();
818 break;
819 case QEvent::Move:
820 static_cast<QMoveEvent *>(postedEvent.event)->m_pos =
821 static_cast<const QMoveEvent *>(event)->pos();
822 break;
823 case QEvent::UpdateRequest:
824 case QEvent::LanguageChange:
825 case QEvent::LayoutRequest:
826 break;
827 default:
828 continue;
829 }
830 delete event;
831 return true;
832 }
833 return false;
834}
835
836/*!
837 \property QApplication::styleSheet
838 \brief the application style sheet
839 \since 4.2
840
841 By default, this property returns an empty string unless the user specifies
842 the \c{-stylesheet} option on the command line when running the application.
843
844 \sa QWidget::setStyle(), {Qt Style Sheets}
845*/
846
847/*!
848 \property QApplication::autoSipEnabled
849 \since 4.5
850 \brief toggles automatic SIP (software input panel) visibility
851
852 Set this property to \c true to automatically display the SIP when entering
853 widgets that accept keyboard input. This property only affects widgets with
854 the WA_InputMethodEnabled attribute set, and is typically used to launch
855 a virtual keyboard on devices which have very few or no keys.
856
857 \b{ The property only has an effect on platforms that use software input
858 panels.}
859
860 The default is platform dependent.
861*/
862void QApplication::setAutoSipEnabled(const bool enabled)
863{
864 QApplicationPrivate::autoSipEnabled = enabled;
865}
866
867bool QApplication::autoSipEnabled() const
868{
869 return QApplicationPrivate::autoSipEnabled;
870}
871
872#ifndef QT_NO_STYLE_STYLESHEET
873
874QString QApplication::styleSheet() const
875{
876 return QApplicationPrivate::styleSheet;
877}
878
879void QApplication::setStyleSheet(const QString& styleSheet)
880{
881 QApplicationPrivate::styleSheet = styleSheet;
882 QStyleSheetStyle *styleSheetStyle = qt_styleSheet(style: QApplicationPrivate::app_style);
883 if (styleSheet.isEmpty()) { // application style sheet removed
884 if (!styleSheetStyle)
885 return; // there was no stylesheet before
886 setStyle(styleSheetStyle->base);
887 } else if (styleSheetStyle) { // style sheet update, just repolish
888 styleSheetStyle->repolish(qApp);
889 } else { // stylesheet set the first time
890 QStyleSheetStyle *newStyleSheetStyle = new QStyleSheetStyle(QApplicationPrivate::app_style);
891 QApplicationPrivate::app_style->setParent(newStyleSheetStyle);
892 setStyle(newStyleSheetStyle);
893 }
894}
895
896#endif // QT_NO_STYLE_STYLESHEET
897
898/*!
899 Returns the application's style object.
900
901 \sa setStyle(), QStyle
902*/
903QStyle *QApplication::style()
904{
905 if (!QApplicationPrivate::app_style) {
906 // Create default style
907 if (!qobject_cast<QApplication *>(object: QCoreApplication::instance())) {
908 Q_ASSERT(!"No style available without QApplication!");
909 return nullptr;
910 }
911
912 auto &defaultStyle = QApplicationPrivate::app_style;
913
914 defaultStyle = QStyleFactory::create(QApplicationPrivate::desktopStyleKey());
915 if (!defaultStyle) {
916 const QStringList styles = QStyleFactory::keys();
917 for (const auto &style : styles) {
918 if ((defaultStyle = QStyleFactory::create(style)))
919 break;
920 }
921 }
922 if (!defaultStyle) {
923 Q_ASSERT(!"No styles available!");
924 return nullptr;
925 }
926
927 // Take ownership of the style
928 defaultStyle->setParent(qApp);
929
930 QGuiApplicationPrivate::updatePalette();
931
932#ifndef QT_NO_STYLE_STYLESHEET
933 if (!QApplicationPrivate::styleSheet.isEmpty()) {
934 qApp->setStyleSheet(QApplicationPrivate::styleSheet);
935 } else
936#endif
937 {
938 defaultStyle->polish(qApp);
939 }
940 }
941
942 return QApplicationPrivate::app_style;
943}
944
945/*!
946 Sets the application's GUI style to \a style. Ownership of the style object
947 is transferred to QApplication, so QApplication will delete the style
948 object on application exit or when a new style is set and the old style is
949 still the parent of the application object.
950
951 Example usage:
952 \snippet code/src_gui_kernel_qapplication.cpp 1
953
954 When switching application styles, the color palette is set back to the
955 initial colors or the system defaults. This is necessary since certain
956 styles have to adapt the color palette to be fully style-guide compliant.
957
958 Setting the style before a palette has been set, i.e., before creating
959 QApplication, will cause the application to use QStyle::standardPalette()
960 for the palette.
961
962 \warning Qt style sheets are currently not supported for custom QStyle
963 subclasses. We plan to address this in some future release.
964
965 \sa style(), QStyle, setPalette(), desktopSettingsAware()
966*/
967void QApplication::setStyle(QStyle *style)
968{
969 if (!style || style == QApplicationPrivate::app_style)
970 return;
971
972 QWidgetList all = allWidgets();
973
974 // clean up the old style
975 if (QApplicationPrivate::app_style) {
976 if (QApplicationPrivate::is_app_running && !QApplicationPrivate::is_app_closing) {
977 for (QWidgetList::ConstIterator it = all.constBegin(), cend = all.constEnd(); it != cend; ++it) {
978 QWidget *w = *it;
979 if (!(w->windowType() == Qt::Desktop) && // except desktop
980 w->testAttribute(attribute: Qt::WA_WState_Polished)) { // has been polished
981 QApplicationPrivate::app_style->unpolish(widget: w);
982 }
983 }
984 }
985 QApplicationPrivate::app_style->unpolish(qApp);
986 }
987
988 QStyle *old = QApplicationPrivate::app_style; // save
989
990#ifndef QT_NO_STYLE_STYLESHEET
991 if (!QApplicationPrivate::styleSheet.isEmpty() && !qt_styleSheet(style)) {
992 // we have a stylesheet already and a new style is being set
993 QStyleSheetStyle *newStyleSheetStyle = new QStyleSheetStyle(style);
994 style->setParent(newStyleSheetStyle);
995 QApplicationPrivate::app_style = newStyleSheetStyle;
996 } else
997#endif // QT_NO_STYLE_STYLESHEET
998 QApplicationPrivate::app_style = style;
999 QApplicationPrivate::app_style->setParent(qApp); // take ownership
1000
1001 // Take care of possible palette requirements of certain
1002 // styles. Do it before polishing the application since the
1003 // style might call QApplication::setPalette() itself.
1004 QGuiApplicationPrivate::updatePalette();
1005
1006 // The default widget font hash is based on the platform theme,
1007 // not the style, but the widget fonts could in theory have been
1008 // affected by polish of the previous style, without a proper
1009 // cleanup in unpolish, so reset it now before polishing the
1010 // new style.
1011 QApplicationPrivate::initializeWidgetFontHash();
1012
1013 // initialize the application with the new style
1014 QApplicationPrivate::app_style->polish(qApp);
1015
1016 // re-polish existing widgets if necessary
1017 if (QApplicationPrivate::is_app_running && !QApplicationPrivate::is_app_closing) {
1018 for (QWidgetList::ConstIterator it = all.constBegin(), cend = all.constEnd(); it != cend; ++it) {
1019 QWidget *w = *it;
1020 if (w->windowType() != Qt::Desktop && w->testAttribute(attribute: Qt::WA_WState_Polished)) {
1021 if (w->style() == QApplicationPrivate::app_style)
1022 QApplicationPrivate::app_style->polish(widget: w); // repolish
1023#ifndef QT_NO_STYLE_STYLESHEET
1024 else
1025 w->setStyleSheet(w->styleSheet()); // touch
1026#endif
1027 }
1028 }
1029
1030 for (QWidgetList::ConstIterator it = all.constBegin(), cend = all.constEnd(); it != cend; ++it) {
1031 QWidget *w = *it;
1032 if (w->windowType() != Qt::Desktop && !w->testAttribute(attribute: Qt::WA_SetStyle)) {
1033 QEvent e(QEvent::StyleChange);
1034 QCoreApplication::sendEvent(receiver: w, event: &e);
1035 w->update();
1036 }
1037 }
1038 }
1039
1040#ifndef QT_NO_STYLE_STYLESHEET
1041 if (QStyleSheetStyle *oldStyleSheetStyle = qt_styleSheet(style: old)) {
1042 oldStyleSheetStyle->deref();
1043 } else
1044#endif
1045 if (old && old->parent() == qApp) {
1046 delete old;
1047 }
1048
1049 if (QApplicationPrivate::focus_widget) {
1050 QFocusEvent in(QEvent::FocusIn, Qt::OtherFocusReason);
1051 QCoreApplication::sendEvent(receiver: QApplicationPrivate::focus_widget->style(), event: &in);
1052 QApplicationPrivate::focus_widget->update();
1053 }
1054}
1055
1056/*!
1057 \overload
1058
1059 Requests a QStyle object for \a style from the QStyleFactory.
1060
1061 The string must be one of the QStyleFactory::keys(), typically one of
1062 "windows", "windowsvista", "fusion", or "macos". Style
1063 names are case insensitive.
1064
1065 Returns \nullptr if an unknown \a style is passed, otherwise the QStyle object
1066 returned is set as the application's GUI style.
1067
1068 \warning To ensure that the application's style is set correctly, it is
1069 best to call this function before the QApplication constructor, if
1070 possible.
1071*/
1072QStyle* QApplication::setStyle(const QString& style)
1073{
1074 QStyle *s = QStyleFactory::create(style);
1075 if (!s)
1076 return nullptr;
1077
1078 setStyle(s);
1079 return s;
1080}
1081
1082// Widget specific palettes
1083QApplicationPrivate::PaletteHash QApplicationPrivate::widgetPalettes;
1084
1085QPalette QApplicationPrivate::basePalette() const
1086{
1087 // Start out with a palette based on the style, in case there's no theme
1088 // available, or so that we can fill in missing roles in the theme.
1089 QPalette palette = app_style ? app_style->standardPalette() : Qt::gray;
1090
1091 // Prefer theme palette if available, but fill in missing roles from style
1092 // for compatibility. Note that the style's standard palette is not prioritized
1093 // over the theme palette, as the documented way of applying the style's palette
1094 // is to set it explicitly using QApplication::setPalette().
1095 if (const QPalette *themePalette = platformTheme() ? platformTheme()->palette() : nullptr)
1096 palette = themePalette->resolve(other: palette);
1097
1098 // Finish off by letting the application style polish the palette. This will
1099 // not result in the polished palette becoming a user-set palette, as the
1100 // resulting base palette is only used as a fallback, with the resolve mask
1101 // set to 0.
1102 if (app_style)
1103 app_style->polish(palette);
1104
1105 return palette;
1106}
1107
1108/*!
1109 \fn QPalette QApplication::palette(const QWidget* widget)
1110
1111 If a \a widget is passed, the default palette for the widget's class is
1112 returned. This may or may not be the application palette. In most cases
1113 there is no special palette for certain types of widgets, but one notable
1114 exception is the popup menu under Windows, if the user has defined a
1115 special background color for menus in the display settings.
1116
1117 \sa setPalette(), QWidget::palette()
1118*/
1119QPalette QApplication::palette(const QWidget* w)
1120{
1121 auto &widgetPalettes = QApplicationPrivate::widgetPalettes;
1122 if (w && !widgetPalettes.isEmpty()) {
1123 auto it = widgetPalettes.constFind(key: w->metaObject()->className());
1124 const auto cend = widgetPalettes.constEnd();
1125 if (it != cend)
1126 return *it;
1127 for (it = widgetPalettes.constBegin(); it != cend; ++it) {
1128 if (w->inherits(classname: it.key()))
1129 return it.value();
1130 }
1131 }
1132 return palette();
1133}
1134
1135/*!
1136 \overload
1137
1138 Returns the palette for widgets of the given \a className.
1139
1140 \sa setPalette(), QWidget::palette()
1141*/
1142QPalette QApplication::palette(const char *className)
1143{
1144 auto &widgetPalettes = QApplicationPrivate::widgetPalettes;
1145 if (className && !widgetPalettes.isEmpty()) {
1146 auto it = widgetPalettes.constFind(key: className);
1147 if (it != widgetPalettes.constEnd())
1148 return *it;
1149 }
1150
1151 return QGuiApplication::palette();
1152}
1153
1154/*!
1155 Changes the application palette to \a palette.
1156
1157 If \a className is passed, the change applies only to widgets that inherit
1158 \a className (as reported by QObject::inherits()). If \a className is left
1159 0, the change affects all widgets, thus overriding any previously set class
1160 specific palettes.
1161
1162 The palette may be changed according to the current GUI style in
1163 QStyle::polish().
1164
1165 \warning Do not use this function in conjunction with \l{Qt Style Sheets}.
1166 When using style sheets, the palette of a widget can be customized using
1167 the "color", "background-color", "selection-color",
1168 "selection-background-color" and "alternate-background-color".
1169
1170 \note Some styles do not use the palette for all drawing, for instance, if
1171 they make use of native theme engines. This is the case for the
1172 Windows Vista and \macos styles.
1173
1174 \sa QWidget::setPalette(), palette(), QStyle::polish()
1175*/
1176void QApplication::setPalette(const QPalette &palette, const char* className)
1177{
1178 if (className) {
1179 QPalette polishedPalette = palette;
1180 if (QApplicationPrivate::app_style) {
1181 auto originalResolveMask = palette.resolveMask();
1182 QApplicationPrivate::app_style->polish(palette&: polishedPalette);
1183 polishedPalette.setResolveMask(originalResolveMask);
1184 }
1185
1186 QApplicationPrivate::widgetPalettes.insert(key: className, value: polishedPalette);
1187 if (qApp)
1188 qApp->d_func()->handlePaletteChanged(className);
1189 } else {
1190 QGuiApplication::setPalette(palette);
1191 }
1192}
1193
1194void QApplicationPrivate::handlePaletteChanged(const char *className)
1195{
1196 if (!is_app_running || is_app_closing)
1197 return;
1198
1199 // Setting the global application palette is documented to
1200 // reset any previously set class specific widget palettes.
1201 if (!className && !widgetPalettes.isEmpty())
1202 widgetPalettes.clear();
1203
1204 QGuiApplicationPrivate::handlePaletteChanged(className);
1205
1206 QEvent event(QEvent::ApplicationPaletteChange);
1207 const QWidgetList widgets = QApplication::allWidgets();
1208 for (auto widget : widgets) {
1209 if (!widget->isWindow() && widget->inherits(classname: className))
1210 QCoreApplication::sendEvent(receiver: widget, event: &event);
1211 }
1212
1213#if QT_CONFIG(graphicsview)
1214 for (auto scene : std::as_const(t&: scene_list))
1215 QCoreApplication::sendEvent(receiver: scene, event: &event);
1216#endif
1217
1218 // Palette has been reset back to the default application palette,
1219 // so we need to reinitialize the widget palettes from the theme.
1220 if (!className && !testAttribute(flag: Qt::AA_SetPalette))
1221 initializeWidgetPalettesFromTheme();
1222}
1223
1224void QApplicationPrivate::initializeWidgetPalettesFromTheme()
1225{
1226 QPlatformTheme *platformTheme = QGuiApplicationPrivate::platformTheme();
1227 if (!platformTheme)
1228 return;
1229
1230 widgetPalettes.clear();
1231
1232 struct ThemedWidget { const char *className; QPlatformTheme::Palette palette; };
1233
1234 static const ThemedWidget themedWidgets[] = {
1235 { .className: "QToolButton", .palette: QPlatformTheme::ToolButtonPalette },
1236 { .className: "QAbstractButton", .palette: QPlatformTheme::ButtonPalette },
1237 { .className: "QCheckBox", .palette: QPlatformTheme::CheckBoxPalette },
1238 { .className: "QRadioButton", .palette: QPlatformTheme::RadioButtonPalette },
1239 { .className: "QHeaderView", .palette: QPlatformTheme::HeaderPalette },
1240 { .className: "QAbstractItemView", .palette: QPlatformTheme::ItemViewPalette },
1241 { .className: "QMessageBoxLabel", .palette: QPlatformTheme::MessageBoxLabelPalette },
1242 { .className: "QTabBar", .palette: QPlatformTheme::TabBarPalette },
1243 { .className: "QLabel", .palette: QPlatformTheme::LabelPalette },
1244 { .className: "QGroupBox", .palette: QPlatformTheme::GroupBoxPalette },
1245 { .className: "QMenu", .palette: QPlatformTheme::MenuPalette },
1246 { .className: "QMenuBar", .palette: QPlatformTheme::MenuBarPalette },
1247 { .className: "QTextEdit", .palette: QPlatformTheme::TextEditPalette },
1248 { .className: "QTextControl", .palette: QPlatformTheme::TextEditPalette },
1249 { .className: "QLineEdit", .palette: QPlatformTheme::TextLineEditPalette },
1250 };
1251
1252 for (const auto themedWidget : themedWidgets) {
1253 if (auto *palette = platformTheme->palette(type: themedWidget.palette))
1254 QApplication::setPalette(palette: *palette, className: themedWidget.className);
1255 }
1256}
1257
1258/*!
1259 Returns the default application font.
1260
1261 \sa fontMetrics(), QWidget::font()
1262*/
1263QFont QApplication::font()
1264{
1265 return QGuiApplication::font();
1266}
1267
1268/*!
1269 \overload
1270
1271 Returns the default font for the \a widget. If a default font was not
1272 registered for the \a{widget}'s class, it returns the default font of
1273 its nearest registered superclass.
1274
1275 \sa fontMetrics(), setFont(), QWidget::setFont()
1276*/
1277
1278QFont QApplication::font(const QWidget *widget)
1279{
1280 typedef FontHash::const_iterator FontHashConstIt;
1281
1282 FontHash *hash = app_fonts();
1283
1284 if (widget && hash && hash->size()) {
1285#ifdef Q_OS_MAC
1286 // short circuit for small and mini controls
1287 if (widget->testAttribute(Qt::WA_MacSmallSize)) {
1288 return hash->value(QByteArrayLiteral("QSmallFont"));
1289 } else if (widget->testAttribute(Qt::WA_MacMiniSize)) {
1290 return hash->value(QByteArrayLiteral("QMiniFont"));
1291 }
1292#endif
1293 // Return the font for the nearest registered superclass
1294 const QMetaObject *metaObj = widget->metaObject();
1295 FontHashConstIt it = hash->constFind(key: metaObj->className());
1296 const FontHashConstIt cend = hash->constEnd();
1297 while (it == cend && metaObj != &QWidget::staticMetaObject) {
1298 metaObj = metaObj->superClass();
1299 it = hash->constFind(key: metaObj->className());
1300 }
1301 if (it != cend)
1302 return it.value();
1303 }
1304 return font();
1305}
1306
1307/*!
1308 \overload
1309
1310 Returns the font for widgets of the given \a className.
1311
1312 \sa setFont(), QWidget::font()
1313*/
1314QFont QApplication::font(const char *className)
1315{
1316 FontHash *hash = app_fonts();
1317 if (className && hash && hash->size()) {
1318 QHash<QByteArray, QFont>::ConstIterator it = hash->constFind(key: className);
1319 if (it != hash->constEnd())
1320 return *it;
1321 }
1322 return font();
1323}
1324
1325
1326/*!
1327 Changes the default application font to \a font. If \a className is passed,
1328 the change applies only to classes that inherit \a className (as reported
1329 by QObject::inherits()).
1330
1331 On application start-up, the default font depends on the window system. It
1332 can vary depending on both the window system version and the locale. This
1333 function lets you override the default font; but overriding may be a bad
1334 idea because, for example, some locales need extra large fonts to support
1335 their special characters.
1336
1337 \warning Do not use this function in conjunction with \l{Qt Style Sheets}.
1338 The font of an application can be customized using the "font" style sheet
1339 property. To set a bold font for all QPushButtons, set the application
1340 styleSheet() as "QPushButton { font: bold }"
1341
1342 \sa font(), fontMetrics(), QWidget::setFont()
1343*/
1344
1345void QApplication::setFont(const QFont &font, const char *className)
1346{
1347 FontHash *hash = app_fonts();
1348 if (!className) {
1349 QGuiApplication::setFont(font);
1350 if (hash && hash->size())
1351 hash->clear();
1352 } else if (hash) {
1353 hash->insert(key: className, value: font);
1354 }
1355 if (QApplicationPrivate::is_app_running && !QApplicationPrivate::is_app_closing) {
1356 QEvent e(QEvent::ApplicationFontChange);
1357 QWidgetList wids = QApplication::allWidgets();
1358 for (QWidgetList::ConstIterator it = wids.constBegin(), cend = wids.constEnd(); it != cend; ++it) {
1359 QWidget *w = *it;
1360 if (!w->isWindow() && w->inherits(classname: className)) // matching class
1361 sendEvent(receiver: w, event: &e);
1362 }
1363
1364#if QT_CONFIG(graphicsview)
1365 // Send to all scenes as well.
1366 QList<QGraphicsScene *> &scenes = qApp->d_func()->scene_list;
1367 for (QList<QGraphicsScene *>::ConstIterator it = scenes.constBegin();
1368 it != scenes.constEnd(); ++it) {
1369 QCoreApplication::sendEvent(receiver: *it, event: &e);
1370 }
1371#endif // QT_CONFIG(graphicsview)
1372 }
1373 if (!className && (!QApplicationPrivate::sys_font || !font.isCopyOf(*QApplicationPrivate::sys_font))) {
1374 if (!QApplicationPrivate::set_font)
1375 QApplicationPrivate::set_font = new QFont(font);
1376 else
1377 *QApplicationPrivate::set_font = font;
1378 }
1379}
1380
1381/*! \internal
1382*/
1383void QApplicationPrivate::setSystemFont(const QFont &font)
1384{
1385 if (!sys_font)
1386 sys_font = new QFont(font);
1387 else
1388 *sys_font = font;
1389
1390 if (!QApplicationPrivate::set_font)
1391 QApplication::setFont(font: *sys_font);
1392}
1393
1394/*! \internal
1395*/
1396QString QApplicationPrivate::desktopStyleKey()
1397{
1398#if defined(QT_BUILD_INTERNAL)
1399 // Allow auto-tests to override the desktop style
1400 if (qEnvironmentVariableIsSet(varName: "QT_DESKTOP_STYLE_KEY"))
1401 return QString::fromLocal8Bit(ba: qgetenv(varName: "QT_DESKTOP_STYLE_KEY"));
1402#endif
1403
1404 // The platform theme might return a style that is not available, find
1405 // first valid one.
1406 if (const QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme()) {
1407 const QStringList availableKeys = QStyleFactory::keys();
1408 const auto styles = theme->themeHint(hint: QPlatformTheme::StyleNames).toStringList();
1409 for (const QString &style : styles) {
1410 if (availableKeys.contains(str: style, cs: Qt::CaseInsensitive))
1411 return style;
1412 }
1413 }
1414 return QString();
1415}
1416
1417void QApplicationPrivate::notifyWindowIconChanged()
1418{
1419 QEvent ev(QEvent::ApplicationWindowIconChange);
1420 const QWidgetList list = QApplication::topLevelWidgets();
1421 QWindowList windowList = QGuiApplication::topLevelWindows();
1422
1423 // send to all top-level QWidgets
1424 for (auto *w : list) {
1425 windowList.removeOne(t: w->windowHandle());
1426 QCoreApplication::sendEvent(receiver: w, event: &ev);
1427 }
1428
1429 // in case there are any plain QWindows in this QApplication-using
1430 // application, also send the notification to them
1431 for (int i = 0; i < windowList.size(); ++i)
1432 QCoreApplication::sendEvent(receiver: windowList.at(i), event: &ev);
1433}
1434
1435/*!
1436 Returns a list of the top-level widgets (windows) in the application.
1437
1438 \note Some of the top-level widgets may be hidden, for example a tooltip if
1439 no tooltip is currently shown.
1440
1441 Example:
1442
1443 \snippet code/src_gui_kernel_qapplication.cpp 4
1444
1445 \sa allWidgets(), QWidget::isWindow(), QWidget::isHidden()
1446*/
1447QWidgetList QApplication::topLevelWidgets()
1448{
1449 QWidgetList list;
1450 if (QWidgetPrivate::allWidgets != nullptr) {
1451 const auto isTopLevelWidget = [] (const QWidget *w) {
1452 return w->isWindow() && w->windowType() != Qt::Desktop;
1453 };
1454 std::copy_if(first: QWidgetPrivate::allWidgets->cbegin(), last: QWidgetPrivate::allWidgets->cend(),
1455 result: std::back_inserter(x&: list), pred: isTopLevelWidget);
1456 }
1457 return list;
1458}
1459
1460/*!
1461 Returns a list of all the widgets in the application.
1462
1463 The list is empty (QList::isEmpty()) if there are no widgets.
1464
1465 \note Some of the widgets may be hidden.
1466
1467 Example:
1468 \snippet code/src_gui_kernel_qapplication.cpp 5
1469
1470 \sa topLevelWidgets(), QWidget::isVisible()
1471*/
1472
1473QWidgetList QApplication::allWidgets()
1474{
1475 if (QWidgetPrivate::allWidgets)
1476 return QWidgetPrivate::allWidgets->values();
1477 return QWidgetList();
1478}
1479
1480/*!
1481 Returns the application widget that has the keyboard input focus,
1482 or \nullptr if no widget in this application has the focus.
1483
1484 \sa QWidget::setFocus(), QWidget::hasFocus(), activeWindow(), focusChanged()
1485*/
1486
1487QWidget *QApplication::focusWidget()
1488{
1489 return QApplicationPrivate::focus_widget;
1490}
1491
1492void QApplicationPrivate::setFocusWidget(QWidget *focus, Qt::FocusReason reason)
1493{
1494#if QT_CONFIG(graphicsview)
1495 if (focus && focus->window()->graphicsProxyWidget())
1496 return;
1497#endif
1498
1499 hidden_focus_widget = nullptr;
1500
1501 if (focus != focus_widget) {
1502 if (focus && focus->isHidden()) {
1503 hidden_focus_widget = focus;
1504 return;
1505 }
1506
1507 if (focus && (reason == Qt::BacktabFocusReason || reason == Qt::TabFocusReason)
1508 && qt_in_tab_key_event)
1509 focus->window()->setAttribute(Qt::WA_KeyboardFocusChange);
1510 else if (focus && reason == Qt::ShortcutFocusReason) {
1511 focus->window()->setAttribute(Qt::WA_KeyboardFocusChange);
1512 }
1513 QWidget *prev = focus_widget;
1514 focus_widget = focus;
1515
1516 if (focus_widget)
1517 focus_widget->d_func()->setFocus_sys();
1518
1519 if (reason != Qt::NoFocusReason) {
1520
1521 //send events
1522 if (prev) {
1523#ifdef QT_KEYPAD_NAVIGATION
1524 if (QApplicationPrivate::keyboardNavigationEnabled()) {
1525 if (prev->hasEditFocus() && reason != Qt::PopupFocusReason)
1526 prev->setEditFocus(false);
1527 }
1528#endif
1529 QFocusEvent out(QEvent::FocusOut, reason);
1530 QPointer<QWidget> that = prev;
1531 QCoreApplication::sendEvent(receiver: prev, event: &out);
1532 if (that)
1533 QCoreApplication::sendEvent(receiver: that->style(), event: &out);
1534 }
1535 if (focus && QApplicationPrivate::focus_widget == focus) {
1536 QFocusEvent in(QEvent::FocusIn, reason);
1537 QPointer<QWidget> that = focus;
1538 QCoreApplication::sendEvent(receiver: focus, event: &in);
1539 if (that)
1540 QCoreApplication::sendEvent(receiver: that->style(), event: &in);
1541 }
1542 emit qApp->focusChanged(old: prev, now: focus_widget);
1543 }
1544 }
1545}
1546
1547
1548/*!
1549 Returns the application top-level window that has the keyboard input focus,
1550 or \nullptr if no application window has the focus. There might be an
1551 activeWindow() even if there is no focusWidget(), for example if no widget
1552 in that window accepts key events.
1553
1554 \sa QWidget::setFocus(), QWidget::hasFocus(), focusWidget()
1555*/
1556
1557QWidget *QApplication::activeWindow()
1558{
1559 return QApplicationPrivate::active_window;
1560}
1561
1562#if QT_DEPRECATED_SINCE(6,0)
1563/*!
1564 \deprecated Use the QFontMetricsF constructor instead.
1565 Returns display (screen) font metrics for the application font.
1566
1567 \sa font(), setFont(), QWidget::fontMetrics(), QPainter::fontMetrics()
1568*/
1569
1570QFontMetrics QApplication::fontMetrics()
1571{
1572 return QApplicationPrivate::desktop()->fontMetrics();
1573}
1574#endif
1575
1576bool QApplicationPrivate::tryCloseAllWidgetWindows(QWindowList *processedWindows)
1577{
1578 Q_ASSERT(processedWindows);
1579 while (QWidget *w = QApplication::activeModalWidget()) {
1580 if (!w->isVisible() || w->data->is_closing)
1581 break;
1582 QWindow *window = w->windowHandle();
1583 if (!window->close()) // Qt::WA_DeleteOnClose may cause deletion.
1584 return false;
1585 if (window)
1586 processedWindows->append(t: window);
1587 }
1588
1589retry:
1590 const QWidgetList list = QApplication::topLevelWidgets();
1591 for (auto *w : list) {
1592 if (w->isVisible() && w->windowType() != Qt::Desktop &&
1593 !w->testAttribute(attribute: Qt::WA_DontShowOnScreen) && !w->data->is_closing) {
1594 QWindow *window = w->windowHandle();
1595 if (!window->close()) // Qt::WA_DeleteOnClose may cause deletion.
1596 return false;
1597 if (window)
1598 processedWindows->append(t: window);
1599 goto retry;
1600 }
1601 }
1602 return true;
1603}
1604
1605/*!
1606 Closes all top-level windows.
1607
1608 This function is particularly useful for applications with many top-level
1609 windows.
1610
1611 The windows are closed in random order, until one window does not accept
1612 the close event. The application quits when the last window was successfully
1613 closed, unless \l quitOnLastWindowClosed is set to false. To trigger application
1614 termination from e.g. a menu, use QCoreApplication::quit() instead of this
1615 function.
1616
1617 \sa quitOnLastWindowClosed, lastWindowClosed(), QWidget::close(),
1618 QWidget::closeEvent(), lastWindowClosed(), QCoreApplication::quit(),
1619 topLevelWidgets(), QWidget::isWindow()
1620*/
1621void QApplication::closeAllWindows()
1622{
1623 QWindowList processedWindows;
1624 QApplicationPrivate::tryCloseAllWidgetWindows(processedWindows: &processedWindows);
1625}
1626
1627/*!
1628 Displays a simple message box about Qt. The message includes the version
1629 number of Qt being used by the application.
1630
1631 This is useful for inclusion in the \uicontrol Help menu of an application, as
1632 shown in the \l{mainwindows/menus}{Menus} example.
1633
1634 This function is a convenience slot for QMessageBox::aboutQt().
1635*/
1636void QApplication::aboutQt()
1637{
1638#if QT_CONFIG(messagebox)
1639 QMessageBox::aboutQt(parent: activeWindow());
1640#endif // QT_CONFIG(messagebox)
1641}
1642
1643/*!
1644 \since 4.1
1645 \fn void QApplication::focusChanged(QWidget *old, QWidget *now)
1646
1647 This signal is emitted when the widget that has keyboard focus changed from
1648 \a old to \a now, i.e., because the user pressed the tab-key, clicked into
1649 a widget or changed the active window. Both \a old and \a now can be \nullptr.
1650
1651
1652 The signal is emitted after both widget have been notified about the change
1653 through QFocusEvent.
1654
1655 \sa QWidget::setFocus(), QWidget::clearFocus(), Qt::FocusReason
1656*/
1657
1658/*!\reimp
1659
1660*/
1661bool QApplication::event(QEvent *e)
1662{
1663 Q_D(QApplication);
1664 switch (e->type()) {
1665 case QEvent::Quit:
1666 // FIXME: This logic first tries to close all windows, and then
1667 // checks whether it was successful, but the conditions used in
1668 // closeAllWindows() differ from the verification logic below.
1669 // We should build on the logic in tryCloseAllWidgetWindows().
1670 closeAllWindows();
1671 for (auto *w : topLevelWidgets()) {
1672 if (w->data->is_closing)
1673 continue;
1674 if (w->isVisible() && !(w->windowType() == Qt::Desktop) && !(w->windowType() == Qt::Popup) &&
1675 (!(w->windowType() == Qt::Dialog) || !w->parentWidget()) && !w->testAttribute(attribute: Qt::WA_DontShowOnScreen)) {
1676 e->ignore();
1677 return true;
1678 }
1679 }
1680 // Explicitly call QCoreApplication instead of QGuiApplication so that
1681 // we don't let QGuiApplication close any windows we skipped earlier in
1682 // closeAllWindows(). FIXME: Unify all this close magic through closeAllWindows.
1683 return QCoreApplication::event(e);
1684#ifndef Q_OS_WIN
1685 case QEvent::LocaleChange: {
1686 // on Windows the event propagation is taken care by the
1687 // WM_SETTINGCHANGE event handler.
1688 const QWidgetList list = topLevelWidgets();
1689 for (auto *w : list) {
1690 if (!(w->windowType() == Qt::Desktop)) {
1691 if (!w->testAttribute(attribute: Qt::WA_SetLocale))
1692 w->d_func()->setLocale_helper(l: QLocale(), forceUpdate: true);
1693 }
1694 }
1695 break;
1696 }
1697#endif
1698 case QEvent::Timer: {
1699 QTimerEvent *te = static_cast<QTimerEvent*>(e);
1700 Q_ASSERT(te != nullptr);
1701 if (te->timerId() == d->toolTipWakeUp.timerId()) {
1702 d->toolTipWakeUp.stop();
1703 if (d->toolTipWidget) {
1704 QWidget *w = d->toolTipWidget->window();
1705 // show tooltip if WA_AlwaysShowToolTips is set, or if
1706 // any ancestor of d->toolTipWidget is the active
1707 // window
1708 bool showToolTip = w->testAttribute(attribute: Qt::WA_AlwaysShowToolTips);
1709 while (w && !showToolTip) {
1710 showToolTip = w->isActiveWindow();
1711 w = w->parentWidget();
1712 w = w ? w->window() : nullptr;
1713 }
1714 if (showToolTip) {
1715 QHelpEvent e(QEvent::ToolTip, d->toolTipPos, d->toolTipGlobalPos);
1716 QCoreApplication::sendEvent(receiver: d->toolTipWidget, event: &e);
1717 if (e.isAccepted()) {
1718 QStyle *s = d->toolTipWidget->style();
1719 int sleepDelay = s->styleHint(stylehint: QStyle::SH_ToolTip_FallAsleepDelay, opt: nullptr, widget: d->toolTipWidget, returnData: nullptr);
1720 d->toolTipFallAsleep.start(msec: sleepDelay, obj: this);
1721 }
1722 }
1723 }
1724 } else if (te->timerId() == d->toolTipFallAsleep.timerId()) {
1725 d->toolTipFallAsleep.stop();
1726 }
1727 break;
1728 }
1729#if QT_CONFIG(whatsthis)
1730 case QEvent::EnterWhatsThisMode:
1731 QWhatsThis::enterWhatsThisMode();
1732 return true;
1733#endif
1734 case QEvent::LanguageChange:
1735 case QEvent::ApplicationFontChange:
1736 case QEvent::ApplicationPaletteChange: {
1737 // QGuiApplication::event does not account for the cases where
1738 // there is a top level widget without a window handle. So they
1739 // need to have the event posted here
1740 const QWidgetList list = topLevelWidgets();
1741 for (auto *w : list) {
1742 if (!w->windowHandle() && (w->windowType() != Qt::Desktop))
1743 postEvent(receiver: w, event: new QEvent(e->type()));
1744 }
1745 break;
1746 }
1747 default:
1748 break;
1749 }
1750
1751 return QGuiApplication::event(e);
1752}
1753
1754// ### FIXME: topLevelWindows does not contain QWidgets without a parent
1755// until QWidgetPrivate::create is called. So we have to override the
1756// QGuiApplication::notifyLayoutDirectionChange
1757// to do the right thing.
1758void QApplicationPrivate::notifyLayoutDirectionChange()
1759{
1760 const QWidgetList list = QApplication::topLevelWidgets();
1761 QWindowList windowList = QGuiApplication::topLevelWindows();
1762
1763 // send to all top-level QWidgets
1764 for (auto *w : list) {
1765 windowList.removeAll(t: w->windowHandle());
1766 QEvent ev(QEvent::ApplicationLayoutDirectionChange);
1767 QCoreApplication::sendEvent(receiver: w, event: &ev);
1768 }
1769
1770 // in case there are any plain QWindows in this QApplication-using
1771 // application, also send the notification to them
1772 for (int i = 0; i < windowList.size(); ++i) {
1773 QEvent ev(QEvent::ApplicationLayoutDirectionChange);
1774 QCoreApplication::sendEvent(receiver: windowList.at(i), event: &ev);
1775 }
1776}
1777
1778/*!
1779 \fn void QApplication::setActiveWindow(QWidget* active)
1780 \deprecated [6.5] Use QWidget::activateWindow() instead.
1781
1782 Sets the active window to the \a active widget in response to a system
1783 event. The function is called from the platform specific event handlers.
1784
1785 \warning This function does \e not set the keyboard focus to the active
1786 widget. Call QWidget::activateWindow() instead.
1787
1788 It sets the activeWindow() and focusWidget() attributes and sends proper
1789 \l{QEvent::WindowActivate}{WindowActivate}/\l{QEvent::WindowDeactivate}
1790 {WindowDeactivate} and \l{QEvent::FocusIn}{FocusIn}/\l{QEvent::FocusOut}
1791 {FocusOut} events to all appropriate widgets. The window will then be
1792 painted in active state (e.g. cursors in line edits will blink), and it
1793 will have tool tips enabled.
1794
1795 \sa activeWindow(), QWidget::activateWindow()
1796*/
1797#if QT_DEPRECATED_SINCE(6,5)
1798void QApplication::setActiveWindow(QWidget* act)
1799{
1800 QApplicationPrivate::setActiveWindow(act);
1801}
1802#endif
1803
1804void QApplicationPrivate::setActiveWindow(QWidget* act)
1805{
1806 QWidget* window = act?act->window():nullptr;
1807
1808 if (QApplicationPrivate::active_window == window)
1809 return;
1810
1811#if QT_CONFIG(graphicsview)
1812 if (window && window->graphicsProxyWidget()) {
1813 // Activate the proxy's view->viewport() ?
1814 return;
1815 }
1816#endif
1817
1818 QWidgetList toBeActivated;
1819 QWidgetList toBeDeactivated;
1820
1821 if (QApplicationPrivate::active_window) {
1822 if (QApplication::style()->styleHint(stylehint: QStyle::SH_Widget_ShareActivation, opt: nullptr, widget: QApplicationPrivate::active_window)) {
1823 const QWidgetList list = QApplication::topLevelWidgets();
1824 for (auto *w : list) {
1825 if (w->isVisible() && w->isActiveWindow())
1826 toBeDeactivated.append(t: w);
1827 }
1828 } else {
1829 toBeDeactivated.append(t: QApplicationPrivate::active_window);
1830 }
1831 }
1832
1833 if (QApplicationPrivate::focus_widget) {
1834 if (QApplicationPrivate::focus_widget->testAttribute(attribute: Qt::WA_InputMethodEnabled))
1835 QGuiApplication::inputMethod()->commit();
1836
1837 QFocusEvent focusAboutToChange(QEvent::FocusAboutToChange, Qt::ActiveWindowFocusReason);
1838 QCoreApplication::sendEvent(receiver: QApplicationPrivate::focus_widget, event: &focusAboutToChange);
1839 }
1840
1841 QApplicationPrivate::active_window = window;
1842
1843 if (QApplicationPrivate::active_window) {
1844 if (QApplication::style()->styleHint(stylehint: QStyle::SH_Widget_ShareActivation, opt: nullptr, widget: QApplicationPrivate::active_window)) {
1845 const QWidgetList list = QApplication::topLevelWidgets();
1846 for (auto *w : list) {
1847 if (w->isVisible() && w->isActiveWindow())
1848 toBeActivated.append(t: w);
1849 }
1850 } else {
1851 toBeActivated.append(t: QApplicationPrivate::active_window);
1852 }
1853
1854 }
1855
1856 // first the activation/deactivation events
1857 QEvent activationChange(QEvent::ActivationChange);
1858 QEvent windowActivate(QEvent::WindowActivate);
1859 QEvent windowDeactivate(QEvent::WindowDeactivate);
1860
1861 for (int i = 0; i < toBeActivated.size(); ++i) {
1862 QWidget *w = toBeActivated.at(i);
1863 QApplication::sendSpontaneousEvent(receiver: w, event: &windowActivate);
1864 QApplication::sendSpontaneousEvent(receiver: w, event: &activationChange);
1865 }
1866
1867 for(int i = 0; i < toBeDeactivated.size(); ++i) {
1868 QWidget *w = toBeDeactivated.at(i);
1869 QApplication::sendSpontaneousEvent(receiver: w, event: &windowDeactivate);
1870 QApplication::sendSpontaneousEvent(receiver: w, event: &activationChange);
1871 }
1872
1873 if (QApplicationPrivate::popupWidgets == nullptr) { // !inPopupMode()
1874 // then focus events
1875 if (!QApplicationPrivate::active_window && QApplicationPrivate::focus_widget) {
1876 QApplicationPrivate::setFocusWidget(focus: nullptr, reason: Qt::ActiveWindowFocusReason);
1877 } else if (QApplicationPrivate::active_window) {
1878 QWidget *w = QApplicationPrivate::active_window->focusWidget();
1879 if (w && w->isVisible() /*&& w->focusPolicy() != QWidget::NoFocus*/)
1880 w->setFocus(Qt::ActiveWindowFocusReason);
1881 else {
1882 w = QApplicationPrivate::focusNextPrevChild_helper(toplevel: QApplicationPrivate::active_window, next: true);
1883 if (w) {
1884 w->setFocus(Qt::ActiveWindowFocusReason);
1885 } else {
1886 w = QApplicationPrivate::focus_widget;
1887 if (!w && QApplicationPrivate::active_window->focusPolicy() != Qt::NoFocus) {
1888 QApplicationPrivate::active_window->setFocus(Qt::ActiveWindowFocusReason);
1889 } else if (!QApplicationPrivate::active_window->isAncestorOf(child: w)) {
1890 // If the focus widget is not in the activate_window, clear the focus
1891 QApplicationPrivate::setFocusWidget(focus: nullptr, reason: Qt::ActiveWindowFocusReason);
1892 }
1893 }
1894 }
1895 }
1896 }
1897}
1898
1899QWidget *qt_tlw_for_window(QWindow *wnd)
1900{
1901 // QTBUG-32177, wnd might be a QQuickView embedded via window container.
1902 while (wnd && !wnd->isTopLevel()) {
1903 QWindow *parent = wnd->parent();
1904 if (!parent)
1905 break;
1906
1907 // Don't end up in windows not belonging to this application
1908 if (parent->handle() && parent->handle()->isForeignWindow())
1909 break;
1910
1911 wnd = wnd->parent();
1912 }
1913 if (wnd) {
1914 const auto tlws = QApplication::topLevelWidgets();
1915 for (QWidget *tlw : tlws) {
1916 if (tlw->windowHandle() == wnd)
1917 return tlw;
1918 }
1919 }
1920 return nullptr;
1921}
1922
1923void QApplicationPrivate::notifyActiveWindowChange(QWindow *previous)
1924{
1925#ifndef Q_OS_MACOS
1926 // Some delayed focus event to ignore, unless we are on cocoa where
1927 // popups can be opened via right-click on inactive applications
1928 if (inPopupMode())
1929 return;
1930#endif
1931 QWindow *focusWindow = QGuiApplicationPrivate::focus_window;
1932 QWidget *focusWidget = qt_tlw_for_window(wnd: focusWindow);
1933 QApplicationPrivate::setActiveWindow(focusWidget);
1934 // QTBUG-37126, Active X controls may set the focus on native child widgets.
1935 if (focusWindow && focusWidget && focusWindow != focusWidget->windowHandle()) {
1936 if (QWidgetWindow *widgetWindow = qobject_cast<QWidgetWindow *>(object: focusWindow))
1937 if (QWidget *widget = widgetWindow->widget())
1938 if (widget->inherits(classname: "QAxHostWidget"))
1939 widget->setFocus(Qt::ActiveWindowFocusReason);
1940 }
1941
1942 // QApplication::setActiveWindow() will deliver window activation events for
1943 // QWidgetWindows. But for other subclasses of QWindow (like QQuickWindow), we
1944 // need to send them explicitly, like we do from the base class implementation.
1945 if (previous && !qobject_cast<QWidgetWindow *>(object: previous)) {
1946 QEvent de(QEvent::WindowDeactivate);
1947 QCoreApplication::sendEvent(receiver: previous, event: &de);
1948 }
1949
1950 if (focusWindow && !qobject_cast<QWidgetWindow *>(object: focusWindow)) {
1951 QEvent ae(QEvent::WindowActivate);
1952 QCoreApplication::sendEvent(receiver: focusWindow, event: &ae);
1953 }
1954
1955 // don't call base class to avoid double delivery of WindowActivate/Deactivate events
1956}
1957
1958/*!internal
1959 * Helper function that returns the new focus widget, but does not set the focus reason.
1960 * Returns \nullptr if a new focus widget could not be found.
1961 * Shared with QGraphicsProxyWidgetPrivate::findFocusChild()
1962*/
1963QWidget *QApplicationPrivate::focusNextPrevChild_helper(QWidget *toplevel, bool next,
1964 bool *wrappingOccurred)
1965{
1966 uint focus_flag = qt_tab_all_widgets() ? Qt::TabFocus : Qt::StrongFocus;
1967
1968 QWidget *f = toplevel->focusWidget();
1969 if (!f)
1970 f = toplevel;
1971
1972 QWidget *w = f;
1973 QWidget *test = f->d_func()->focus_next;
1974 bool seenWindow = false;
1975 bool focusWidgetAfterWindow = false;
1976 while (test && test != f) {
1977 if (test->isWindow())
1978 seenWindow = true;
1979
1980 // If the next focus widget has a focus proxy, we need to check to ensure
1981 // that the proxy is in the correct parent-child direction (according to
1982 // \a next). This is to ensure that we can tab in and out of compound widgets
1983 // without getting stuck in a tab-loop between parent and child.
1984 QWidget *focusProxy = test->d_func()->deepestFocusProxy();
1985 auto effectiveFocusPolicy = [](QWidget *widget) {
1986 return widget->isEnabled() ? widget->focusPolicy() : Qt::NoFocus;
1987 };
1988 const bool canTakeFocus = (effectiveFocusPolicy(focusProxy ? focusProxy : test)
1989 & focus_flag) == focus_flag;
1990 const bool composites = focusProxy ? (next ? focusProxy->isAncestorOf(child: test)
1991 : test->isAncestorOf(child: focusProxy))
1992 : false;
1993 if (canTakeFocus && !composites
1994 && test->isVisibleTo(toplevel) && test->isEnabled()
1995 && !(w->windowType() == Qt::SubWindow && !w->isAncestorOf(child: test))
1996 && (toplevel->windowType() != Qt::SubWindow || toplevel->isAncestorOf(child: test))
1997 && f != focusProxy) {
1998 w = test;
1999 if (seenWindow)
2000 focusWidgetAfterWindow = true;
2001 if (next)
2002 break;
2003 }
2004 test = test->d_func()->focus_next;
2005 }
2006
2007 if (wrappingOccurred != nullptr)
2008 *wrappingOccurred = next ? focusWidgetAfterWindow : !focusWidgetAfterWindow;
2009
2010 if (w == f) {
2011 if (qt_in_tab_key_event) {
2012 w->window()->setAttribute(Qt::WA_KeyboardFocusChange);
2013 w->update();
2014 }
2015 return nullptr;
2016 }
2017 return w;
2018}
2019
2020/*!
2021 \fn void QApplicationPrivate::dispatchEnterLeave(QWidget* enter, QWidget* leave, const QPointF &globalPosF)
2022 \internal
2023
2024 Creates the proper Enter/Leave event when widget \a enter is entered and
2025 widget \a leave is left.
2026 */
2027void QApplicationPrivate::dispatchEnterLeave(QWidget* enter, QWidget* leave, const QPointF &globalPosF)
2028{
2029#if 0
2030 if (leave) {
2031 QEvent e(QEvent::Leave);
2032 QCoreApplication::sendEvent(leave, & e);
2033 }
2034 if (enter) {
2035 const QPoint windowPos = enter->window()->mapFromGlobal(globalPos);
2036 QEnterEvent e(enter->mapFromGlobal(globalPos), windowPos, globalPos);
2037 QCoreApplication::sendEvent(enter, & e);
2038 }
2039 return;
2040#endif
2041
2042 if ((!enter && !leave) || (enter == leave))
2043 return;
2044
2045 QWidgetList leaveList;
2046 QWidgetList enterList;
2047
2048 bool sameWindow = leave && enter && leave->window() == enter->window();
2049 if (leave && !sameWindow) {
2050 auto *w = leave;
2051 do {
2052 leaveList.append(t: w);
2053 } while (!w->isWindow() && (w = w->parentWidget()));
2054 }
2055 if (enter && !sameWindow) {
2056 auto *w = enter;
2057 do {
2058 enterList.append(t: w);
2059 } while (!w->isWindow() && (w = w->parentWidget()));
2060 }
2061 if (sameWindow) {
2062 int enterDepth = 0;
2063 int leaveDepth = 0;
2064 auto *e = enter;
2065 while (!e->isWindow() && (e = e->parentWidget()))
2066 enterDepth++;
2067 auto *l = leave;
2068 while (!l->isWindow() && (l = l->parentWidget()))
2069 leaveDepth++;
2070 QWidget* wenter = enter;
2071 QWidget* wleave = leave;
2072 while (enterDepth > leaveDepth) {
2073 wenter = wenter->parentWidget();
2074 enterDepth--;
2075 }
2076 while (leaveDepth > enterDepth) {
2077 wleave = wleave->parentWidget();
2078 leaveDepth--;
2079 }
2080 while (!wenter->isWindow() && wenter != wleave) {
2081 wenter = wenter->parentWidget();
2082 wleave = wleave->parentWidget();
2083 }
2084
2085 for (auto *w = leave; w != wleave; w = w->parentWidget())
2086 leaveList.append(t: w);
2087
2088 for (auto *w = enter; w != wenter; w = w->parentWidget())
2089 enterList.append(t: w);
2090 }
2091
2092 QEvent leaveEvent(QEvent::Leave);
2093 for (int i = 0; i < leaveList.size(); ++i) {
2094 auto *w = leaveList.at(i);
2095 if (!QApplication::activeModalWidget() || QApplicationPrivate::tryModalHelper(widget: w, rettop: nullptr)) {
2096 QCoreApplication::sendEvent(receiver: w, event: &leaveEvent);
2097 if (w->testAttribute(attribute: Qt::WA_Hover) &&
2098 (!QApplication::activePopupWidget() || QApplication::activePopupWidget() == w->window())) {
2099 Q_ASSERT(instance());
2100 QHoverEvent he(QEvent::HoverLeave, QPointF(-1, -1), globalPosF, w->mapFromGlobal(globalPosF),
2101 QGuiApplication::keyboardModifiers());
2102 qApp->d_func()->notify_helper(receiver: w, e: &he);
2103 }
2104 }
2105 }
2106 if (!enterList.isEmpty()) {
2107 // Guard against QGuiApplicationPrivate::lastCursorPosition initialized to qInf(), qInf().
2108 const QPointF globalPos = qIsInf(d: globalPosF.x())
2109 ? QPointF(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX)
2110 : globalPosF;
2111 const QPointF windowPos = std::as_const(t&: enterList).back()->window()->mapFromGlobal(globalPos);
2112 for (auto it = enterList.crbegin(), end = enterList.crend(); it != end; ++it) {
2113 auto *w = *it;
2114 if (!QApplication::activeModalWidget() || QApplicationPrivate::tryModalHelper(widget: w, rettop: nullptr)) {
2115 const QPointF localPos = w->mapFromGlobal(globalPos);
2116 QEnterEvent enterEvent(localPos, windowPos, globalPos);
2117 QCoreApplication::sendEvent(receiver: w, event: &enterEvent);
2118 if (w->testAttribute(attribute: Qt::WA_Hover) &&
2119 (!QApplication::activePopupWidget() || QApplication::activePopupWidget() == w->window())) {
2120 QHoverEvent he(QEvent::HoverEnter, windowPos, QPointF(-1, -1), globalPos,
2121 QGuiApplication::keyboardModifiers());
2122 QMutableEventPoint::setPosition(p&: he.point(i: 0), arg: localPos);
2123 qApp->d_func()->notify_helper(receiver: w, e: &he);
2124 }
2125 }
2126 }
2127 }
2128
2129#ifndef QT_NO_CURSOR
2130 // Update cursor for alien/graphics widgets.
2131
2132 const bool enterOnAlien = (enter && (isAlien(widget: enter) || enter->testAttribute(attribute: Qt::WA_DontShowOnScreen)));
2133 // Whenever we leave an alien widget on X11/QPA, we need to reset its nativeParentWidget()'s cursor.
2134 // This is not required on Windows as the cursor is reset on every single mouse move.
2135 QWidget *parentOfLeavingCursor = nullptr;
2136 for (int i = 0; i < leaveList.size(); ++i) {
2137 auto *w = leaveList.at(i);
2138 if (!isAlien(widget: w))
2139 break;
2140 if (w->testAttribute(attribute: Qt::WA_SetCursor)) {
2141 QWidget *parent = w->parentWidget();
2142 while (parent && parent->d_func()->data.in_destructor)
2143 parent = parent->parentWidget();
2144 parentOfLeavingCursor = parent;
2145 //continue looping, we need to find the downest alien widget with a cursor.
2146 // (downest on the screen)
2147 }
2148 }
2149 //check that we will not call qt_x11_enforce_cursor twice with the same native widget
2150 if (parentOfLeavingCursor && (!enterOnAlien
2151 || parentOfLeavingCursor->effectiveWinId() != enter->effectiveWinId())) {
2152#if QT_CONFIG(graphicsview)
2153 if (!parentOfLeavingCursor->window()->graphicsProxyWidget())
2154#endif
2155 {
2156 if (enter == QApplicationPrivate::desktop()) {
2157 qt_qpa_set_cursor(w: enter, force: true);
2158 } else {
2159 qt_qpa_set_cursor(w: parentOfLeavingCursor, force: true);
2160 }
2161 }
2162 }
2163 if (enterOnAlien) {
2164 QWidget *cursorWidget = enter;
2165 while (!cursorWidget->isWindow() && !cursorWidget->isEnabled())
2166 cursorWidget = cursorWidget->parentWidget();
2167
2168 if (!cursorWidget)
2169 return;
2170
2171#if QT_CONFIG(graphicsview)
2172 if (cursorWidget->window()->graphicsProxyWidget()) {
2173 QWidgetPrivate::nearestGraphicsProxyWidget(origin: cursorWidget)->setCursor(cursorWidget->cursor());
2174 } else
2175#endif
2176 {
2177 qt_qpa_set_cursor(w: cursorWidget, force: true);
2178 }
2179 }
2180#endif
2181}
2182
2183/* exported for the benefit of testing tools */
2184Q_WIDGETS_EXPORT bool qt_tryModalHelper(QWidget *widget, QWidget **rettop)
2185{
2186 return QApplicationPrivate::tryModalHelper(widget, rettop);
2187}
2188
2189/*! \internal
2190 Returns \c true if \a widget is blocked by a modal window.
2191 */
2192bool QApplicationPrivate::isBlockedByModal(QWidget *widget)
2193{
2194 widget = widget->window();
2195 QWindow *window = widget->windowHandle();
2196 return window && self->isWindowBlocked(window);
2197}
2198
2199Qt::WindowModality QApplicationPrivate::defaultModality() const
2200{
2201 return Qt::ApplicationModal;
2202}
2203
2204bool QApplicationPrivate::windowNeverBlocked(QWindow *window) const
2205{
2206 QWidget *popupWidget = QApplication::activePopupWidget();
2207 QWindow *popupWindow = popupWidget ? popupWidget->windowHandle() : nullptr;
2208 return popupWindow == window || (!popupWindow && QWindowPrivate::get(window)->isPopup());
2209}
2210
2211/*!\internal
2212
2213 Called from qapplication_\e{platform}.cpp, returns \c true
2214 if the widget should accept the event.
2215 */
2216bool QApplicationPrivate::tryModalHelper(QWidget *widget, QWidget **rettop)
2217{
2218 QWidget *top = QApplication::activeModalWidget();
2219 if (rettop)
2220 *rettop = top;
2221
2222 // the active popup widget always gets the input event
2223 if (QApplication::activePopupWidget())
2224 return true;
2225
2226 return !isBlockedByModal(widget: widget->window());
2227}
2228
2229bool qt_try_modal(QWidget *widget, QEvent::Type type)
2230{
2231 QWidget * top = nullptr;
2232
2233 if (QApplicationPrivate::tryModalHelper(widget, rettop: &top))
2234 return true;
2235
2236 bool block_event = false;
2237
2238 switch (type) {
2239 case QEvent::MouseButtonPress: // disallow mouse/key events
2240 case QEvent::MouseButtonRelease:
2241 case QEvent::MouseMove:
2242 case QEvent::KeyPress:
2243 case QEvent::KeyRelease:
2244 block_event = true;
2245 break;
2246 default:
2247 break;
2248 }
2249
2250 if (block_event && top && top->parentWidget() == nullptr)
2251 top->raise();
2252
2253 return !block_event;
2254}
2255
2256bool QApplicationPrivate::modalState()
2257{
2258 return !self->modalWindowList.isEmpty();
2259}
2260
2261/*
2262 \internal
2263*/
2264QWidget *QApplicationPrivate::pickMouseReceiver(QWidget *candidate, const QPoint &windowPos,
2265 QPoint *pos, QEvent::Type type,
2266 Qt::MouseButtons buttons, QWidget *buttonDown,
2267 QWidget *alienWidget)
2268{
2269 Q_ASSERT(candidate);
2270
2271 QWidget *mouseGrabber = QWidget::mouseGrabber();
2272 if (((type == QEvent::MouseMove && buttons) || (type == QEvent::MouseButtonRelease))
2273 && !buttonDown && !mouseGrabber) {
2274 return nullptr;
2275 }
2276
2277 if (alienWidget && alienWidget->internalWinId())
2278 alienWidget = nullptr;
2279
2280 QWidget *receiver = candidate;
2281
2282 if (!mouseGrabber)
2283 mouseGrabber = (buttonDown && !isBlockedByModal(widget: buttonDown)) ? buttonDown : alienWidget;
2284
2285 if (mouseGrabber && mouseGrabber != candidate) {
2286 receiver = mouseGrabber;
2287 *pos = receiver->mapFromGlobal(candidate->mapToGlobal(windowPos));
2288 }
2289
2290 return receiver;
2291
2292}
2293
2294/*
2295 \internal
2296*/
2297bool QApplicationPrivate::sendMouseEvent(QWidget *receiver, QMouseEvent *event,
2298 QWidget *alienWidget, QWidget *nativeWidget,
2299 QWidget **buttonDown, QPointer<QWidget> &lastMouseReceiver,
2300 bool spontaneous, bool onlyDispatchEnterLeave)
2301{
2302 Q_ASSERT(receiver);
2303 Q_ASSERT(event);
2304 Q_ASSERT(nativeWidget);
2305 Q_ASSERT(buttonDown);
2306
2307 if (alienWidget && !isAlien(widget: alienWidget))
2308 alienWidget = nullptr;
2309
2310 QPointer<QWidget> receiverGuard = receiver;
2311 QPointer<QWidget> nativeGuard = nativeWidget;
2312 QPointer<QWidget> alienGuard = alienWidget;
2313 QPointer<QWidget> activePopupWidget = QApplication::activePopupWidget();
2314
2315 const bool graphicsWidget = nativeWidget->testAttribute(attribute: Qt::WA_DontShowOnScreen);
2316
2317 bool widgetUnderMouse = QRectF(receiver->rect()).contains(p: event->position());
2318
2319 // Clear the obsolete leaveAfterRelease value, if mouse button has been released but
2320 // leaveAfterRelease has not been updated.
2321 // This happens e.g. when modal dialog or popup is shown as a response to button click.
2322 if (leaveAfterRelease && !*buttonDown && !event->buttons())
2323 leaveAfterRelease = nullptr;
2324
2325 if (*buttonDown) {
2326 if (!graphicsWidget) {
2327 // Register the widget that shall receive a leave event
2328 // after the last button is released.
2329 if ((alienWidget || !receiver->internalWinId()) && !leaveAfterRelease && !QWidget::mouseGrabber())
2330 leaveAfterRelease = *buttonDown;
2331 if (event->type() == QEvent::MouseButtonRelease && !event->buttons())
2332 *buttonDown = nullptr;
2333 }
2334 } else if (lastMouseReceiver && widgetUnderMouse) {
2335 // Dispatch enter/leave if we move:
2336 // 1) from an alien widget to another alien widget or
2337 // from a native widget to an alien widget (first OR case)
2338 // 2) from an alien widget to a native widget (second OR case)
2339 if ((alienWidget && alienWidget != lastMouseReceiver)
2340 || (isAlien(widget: lastMouseReceiver) && !alienWidget)) {
2341 if (activePopupWidget) {
2342 if (!QWidget::mouseGrabber())
2343 dispatchEnterLeave(enter: alienWidget ? alienWidget : nativeWidget, leave: lastMouseReceiver, globalPosF: event->globalPosition());
2344 } else {
2345 dispatchEnterLeave(enter: receiver, leave: lastMouseReceiver, globalPosF: event->globalPosition());
2346 }
2347
2348 }
2349 }
2350
2351 // We need this quard in case someone opens a modal dialog / popup. If that's the case
2352 // leaveAfterRelease is set to null, but we shall not update lastMouseReceiver.
2353 const bool wasLeaveAfterRelease = leaveAfterRelease != nullptr;
2354 bool result = true;
2355 // This code is used for sending the synthetic enter/leave events for cases where it is needed
2356 // due to other events causing the widget under the mouse to change. However in those cases
2357 // we do not want to send the mouse event associated with this call, so this enables us to
2358 // not send the unneeded mouse event
2359 if (!onlyDispatchEnterLeave) {
2360 if (spontaneous)
2361 result = QApplication::sendSpontaneousEvent(receiver, event);
2362 else
2363 result = QCoreApplication::sendEvent(receiver, event);
2364 }
2365
2366 if (!graphicsWidget && leaveAfterRelease && event->type() == QEvent::MouseButtonRelease
2367 && !event->buttons() && QWidget::mouseGrabber() != leaveAfterRelease) {
2368 // Dispatch enter/leave if:
2369 // 1) the mouse grabber is an alien widget
2370 // 2) the button is released on an alien widget
2371 QWidget *enter = nullptr;
2372 if (nativeGuard)
2373 enter = alienGuard ? alienWidget : nativeWidget;
2374 else // The receiver is typically deleted on mouse release with drag'n'drop.
2375 enter = QApplication::widgetAt(p: event->globalPosition().toPoint());
2376 dispatchEnterLeave(enter, leave: leaveAfterRelease, globalPosF: event->globalPosition());
2377 leaveAfterRelease = nullptr;
2378 lastMouseReceiver = enter;
2379 } else if (!wasLeaveAfterRelease) {
2380 if (activePopupWidget) {
2381 if (!QWidget::mouseGrabber())
2382 lastMouseReceiver = alienGuard ? alienWidget : (nativeGuard ? nativeWidget : nullptr);
2383 } else {
2384 lastMouseReceiver = receiverGuard ? receiver : QApplication::widgetAt(p: event->globalPosition().toPoint());
2385 }
2386 }
2387
2388 return result;
2389}
2390
2391/*
2392 This function should only be called when the widget changes visibility, i.e.
2393 when the \a widget is shown, hidden or deleted. This function does nothing
2394 if the widget is a top-level or native, i.e. not an alien widget. In that
2395 case enter/leave events are generated by the underlying windowing system.
2396*/
2397extern QPointer<QWidget> qt_last_mouse_receiver;
2398extern Q_WIDGETS_EXPORT QWidget *qt_button_down;
2399void QApplicationPrivate::sendSyntheticEnterLeave(QWidget *widget)
2400{
2401#ifndef QT_NO_CURSOR
2402 if (!widget || widget->isWindow())
2403 return;
2404 const bool widgetInShow = widget->isVisible() && !widget->data->in_destructor;
2405 if (!widgetInShow && widget != qt_last_mouse_receiver)
2406 return; // Widget was not under the cursor when it was hidden/deleted.
2407
2408 if (widgetInShow && widget->parentWidget()->data->in_show)
2409 return; // Ignore recursive show.
2410
2411 QWidget *mouseGrabber = QWidget::mouseGrabber();
2412 if (mouseGrabber && mouseGrabber != widget)
2413 return; // Someone else has the grab; enter/leave should not occur.
2414
2415 QWidget *tlw = widget->window();
2416 if (tlw->data->in_destructor || tlw->data->is_closing)
2417 return; // Closing down the business.
2418
2419 if (widgetInShow && (!qt_last_mouse_receiver || qt_last_mouse_receiver->window() != tlw))
2420 return; // Mouse cursor not inside the widget's top-level.
2421
2422 const QPoint globalPos(QCursor::pos());
2423 QPoint windowPos = tlw->mapFromGlobal(globalPos);
2424
2425 // Find the current widget under the mouse. If this function was called from
2426 // the widget's destructor, we have to make sure childAt() doesn't take into
2427 // account widgets that are about to be destructed.
2428 QWidget *widgetUnderCursor = tlw->d_func()->childAt_helper(windowPos, widget->data->in_destructor);
2429 if (!widgetUnderCursor)
2430 widgetUnderCursor = tlw;
2431 QPoint pos = widgetUnderCursor->mapFrom(tlw, windowPos);
2432
2433 if (widgetInShow && widgetUnderCursor != widget && !widget->isAncestorOf(child: widgetUnderCursor))
2434 return; // Mouse cursor not inside the widget or any of its children.
2435
2436 if (widget->data->in_destructor && qt_button_down == widget)
2437 qt_button_down = nullptr;
2438
2439 // A mouse move is not actually sent, but we utilize the sendMouseEvent() call to send the
2440 // enter/leave events as appropriate
2441 QMouseEvent e(QEvent::MouseMove, pos, windowPos, globalPos, Qt::NoButton, Qt::NoButton, Qt::NoModifier);
2442 sendMouseEvent(receiver: widgetUnderCursor, event: &e, alienWidget: widgetUnderCursor, nativeWidget: tlw, buttonDown: &qt_button_down, lastMouseReceiver&: qt_last_mouse_receiver, spontaneous: true, onlyDispatchEnterLeave: true);
2443#else // !QT_NO_CURSOR
2444 Q_UNUSED(widget);
2445#endif // QT_NO_CURSOR
2446}
2447
2448/*!
2449 \internal
2450
2451 Returns the desktop widget (also called the root window).
2452
2453 The widget represents the entire virtual desktop, and its geometry will
2454 be the union of all screens.
2455*/
2456QWidget *QApplicationPrivate::desktop()
2457{
2458 CHECK_QAPP_INSTANCE(nullptr)
2459 if (!qt_desktopWidget || // not created yet
2460 !(qt_desktopWidget->windowType() == Qt::Desktop)) { // reparented away
2461 qt_desktopWidget = new QWidget(nullptr, Qt::Desktop);
2462 }
2463 return qt_desktopWidget;
2464}
2465
2466/*
2467 Sets the time after which a drag should start to \a ms ms.
2468
2469 \sa startDragTime()
2470*/
2471
2472void QApplication::setStartDragTime(int ms)
2473{
2474 QGuiApplication::styleHints()->setStartDragTime(ms);
2475}
2476
2477/*!
2478 \property QApplication::startDragTime
2479 \brief the time in milliseconds that a mouse button must be held down
2480 before a drag and drop operation will begin
2481
2482 If you support drag and drop in your application, and want to start a drag
2483 and drop operation after the user has held down a mouse button for a
2484 certain amount of time, you should use this property's value as the delay.
2485
2486 Qt also uses this delay internally, e.g. in QTextEdit and QLineEdit, for
2487 starting a drag.
2488
2489 The default value is 500 ms.
2490
2491 \sa startDragDistance(), {Drag and Drop in Qt}{Drag and Drop}
2492*/
2493
2494int QApplication::startDragTime()
2495{
2496 return QGuiApplication::styleHints()->startDragTime();
2497}
2498
2499/*
2500 Sets the distance after which a drag should start to \a l pixels.
2501
2502 \sa startDragDistance()
2503*/
2504
2505void QApplication::setStartDragDistance(int l)
2506{
2507 QGuiApplication::styleHints()->setStartDragDistance(l);
2508}
2509
2510/*!
2511 \property QApplication::startDragDistance
2512 \brief the minimum distance required for a drag and drop operation to start.
2513
2514 If you support drag and drop in your application, and want to start a drag
2515 and drop operation after the user has moved the cursor a certain distance
2516 with a button held down, you should use this property's value as the
2517 minimum distance required.
2518
2519 For example, if the mouse position of the click is stored in \c startPos
2520 and the current position (e.g. in the mouse move event) is \c currentPos,
2521 you can find out if a drag should be started with code like this:
2522
2523 \snippet code/src_gui_kernel_qapplication.cpp 7
2524
2525 Qt uses this value internally, e.g. in QFileDialog.
2526
2527 The default value (if the platform doesn't provide a different default)
2528 is 10 pixels.
2529
2530 \sa startDragTime(), QPoint::manhattanLength(), {Drag and Drop in Qt}{Drag and Drop}
2531*/
2532
2533int QApplication::startDragDistance()
2534{
2535 return QGuiApplication::styleHints()->startDragDistance();
2536}
2537
2538/*!
2539 Enters the main event loop and waits until exit() is called, then returns
2540 the value that was set to exit() (which is 0 if exit() is called via
2541 quit()).
2542
2543 It is necessary to call this function to start event handling. The main
2544 event loop receives events from the window system and dispatches these to
2545 the application widgets.
2546
2547 Generally, no user interaction can take place before calling exec(). As a
2548 special case, modal widgets like QMessageBox can be used before calling
2549 exec(), because modal widgets call exec() to start a local event loop.
2550
2551 To make your application perform idle processing, i.e., executing a special
2552 function whenever there are no pending events, use a QTimer with 0 timeout.
2553 More advanced idle processing schemes can be achieved using processEvents().
2554
2555 We recommend that you connect clean-up code to the
2556 \l{QCoreApplication::}{aboutToQuit()} signal, instead of putting it in your
2557 application's \c{main()} function. This is because, on some platforms the
2558 QApplication::exec() call may not return. For example, on the Windows
2559 platform, when the user logs off, the system terminates the process after Qt
2560 closes all top-level windows. Hence, there is \e{no guarantee} that the
2561 application will have time to exit its event loop and execute code at the
2562 end of the \c{main()} function, after the QApplication::exec() call.
2563
2564 \sa quitOnLastWindowClosed, QCoreApplication::quit(), QCoreApplication::exit(),
2565 QCoreApplication::processEvents(), QCoreApplication::exec()
2566*/
2567int QApplication::exec()
2568{
2569 return QGuiApplication::exec();
2570}
2571
2572/*! \reimp
2573 */
2574bool QApplication::notify(QObject *receiver, QEvent *e)
2575{
2576 Q_D(QApplication);
2577 // no events are delivered after ~QCoreApplication() has started
2578 if (QApplicationPrivate::is_app_closing)
2579 return true;
2580
2581 if (Q_UNLIKELY(!receiver)) { // serious error
2582 qWarning(msg: "QApplication::notify: Unexpected null receiver");
2583 return true;
2584 }
2585
2586#ifndef QT_NO_DEBUG
2587 QCoreApplicationPrivate::checkReceiverThread(receiver);
2588#endif
2589
2590 const bool isWindowType = receiver->isWindowType();
2591 const bool isWidgetType = receiver->isWidgetType();
2592 if (isWindowType
2593 && QGuiApplicationPrivate::sendQWindowEventToQPlatformWindow(window: static_cast<QWindow *>(receiver), event: e)) {
2594 return true; // Platform plugin ate the event
2595 }
2596
2597 QGuiApplicationPrivate::captureGlobalModifierState(e);
2598
2599#ifndef QT_NO_GESTURES
2600 // walk through parents and check for gestures
2601 if (d->gestureManager) {
2602 switch (e->type()) {
2603 case QEvent::Paint:
2604 case QEvent::MetaCall:
2605 case QEvent::DeferredDelete:
2606 case QEvent::DragEnter: case QEvent::DragMove: case QEvent::DragLeave:
2607 case QEvent::Drop: case QEvent::DragResponse:
2608 case QEvent::ChildAdded: case QEvent::ChildPolished:
2609 case QEvent::ChildRemoved:
2610 case QEvent::UpdateRequest:
2611 case QEvent::UpdateLater:
2612 case QEvent::LocaleChange:
2613 case QEvent::Style:
2614 case QEvent::IconDrag:
2615 case QEvent::StyleChange:
2616 case QEvent::GraphicsSceneDragEnter:
2617 case QEvent::GraphicsSceneDragMove:
2618 case QEvent::GraphicsSceneDragLeave:
2619 case QEvent::GraphicsSceneDrop:
2620 case QEvent::DynamicPropertyChange:
2621 case QEvent::NetworkReplyUpdated:
2622 break;
2623 default:
2624 if (d->gestureManager->thread() == QThread::currentThread()) {
2625 if (isWidgetType) {
2626 if (d->gestureManager->filterEvent(receiver: static_cast<QWidget *>(receiver), event: e))
2627 return true;
2628 } else {
2629 // a special case for events that go to QGesture objects.
2630 // We pass the object to the gesture manager and it'll figure
2631 // out if it's QGesture or not.
2632 if (d->gestureManager->filterEvent(receiver, event: e))
2633 return true;
2634 }
2635 }
2636 break;
2637 }
2638 }
2639#endif // QT_NO_GESTURES
2640
2641 switch (e->type()) {
2642 case QEvent::ApplicationDeactivate:
2643 case QEvent::OrientationChange:
2644 // Close all popups (triggers when switching applications
2645 // by pressing ALT-TAB on Windows, which is not receive as key event.
2646 // triggers when the screen rotates.)
2647 d->closeAllPopups();
2648 break;
2649 case QEvent::Wheel: // User input and window activation makes tooltips sleep
2650 case QEvent::ActivationChange:
2651 case QEvent::KeyPress:
2652 case QEvent::KeyRelease:
2653 case QEvent::FocusOut:
2654 case QEvent::FocusIn:
2655 case QEvent::MouseButtonPress:
2656 case QEvent::MouseButtonRelease:
2657 case QEvent::MouseButtonDblClick:
2658 d->toolTipFallAsleep.stop();
2659 Q_FALLTHROUGH();
2660 case QEvent::Leave:
2661 d->toolTipWakeUp.stop();
2662 default:
2663 break;
2664 }
2665
2666 switch (e->type()) {
2667 case QEvent::KeyPress: {
2668 QKeyEvent* keyEvent = static_cast<QKeyEvent*>(e);
2669 const int key = keyEvent->key();
2670 // When a key press is received which is not spontaneous then it needs to
2671 // be manually sent as a shortcut override event to ensure that any
2672 // matching shortcut is triggered first. This enables emulation/playback
2673 // of recorded events to still have the same effect.
2674 if (!e->spontaneous() && isWidgetType
2675 && qt_sendShortcutOverrideEvent(o: static_cast<QWidget *>(receiver), timestamp: keyEvent->timestamp(),
2676 k: key, mods: keyEvent->modifiers(), text: keyEvent->text(),
2677 autorep: keyEvent->isAutoRepeat(), count: keyEvent->count())) {
2678 return true;
2679 }
2680 qt_in_tab_key_event = (key == Qt::Key_Backtab
2681 || key == Qt::Key_Tab
2682 || key == Qt::Key_Left
2683 || key == Qt::Key_Up
2684 || key == Qt::Key_Right
2685 || key == Qt::Key_Down);
2686 }
2687 default:
2688 break;
2689 }
2690
2691 bool res = false;
2692 if (isWidgetType) {
2693 QWidget * w = static_cast<QWidget *>(receiver);
2694 switch (e->type()) {
2695 case QEvent::ShortcutOverride:
2696 case QEvent::KeyPress:
2697 case QEvent::KeyRelease: {
2698 QKeyEvent* key = static_cast<QKeyEvent*>(e);
2699 bool def = key->isAccepted();
2700 /*
2701 QLineEdit will emit a signal on Key_Return, but
2702 ignore the event, and sometimes the connected
2703 slot deletes the QLineEdit (common in itemview
2704 delegates), so we have to check if the widget
2705 was destroyed even if the event was ignored (to
2706 prevent a crash)
2707
2708 Note that we don't have to reset pr while
2709 propagating (because the original receiver will
2710 be destroyed if one of its ancestors is)
2711 */
2712 QPointer<QObject> pr = receiver;
2713 while (w) {
2714 if (def)
2715 key->accept();
2716 else
2717 key->ignore();
2718 res = d->notify_helper(receiver: w, e);
2719
2720 if (res && key->isAccepted())
2721 break;
2722 if (!pr || w->isWindow())
2723 break;
2724
2725 w = w->parentWidget();
2726 }
2727 qt_in_tab_key_event = false;
2728 break;
2729 }
2730 case QEvent::MouseButtonPress:
2731 case QEvent::MouseButtonRelease:
2732 case QEvent::MouseButtonDblClick:
2733 case QEvent::MouseMove: {
2734 QMouseEvent* mouse = static_cast<QMouseEvent*>(e);
2735 QPoint relpos = mouse->position().toPoint();
2736
2737 if (e->spontaneous()) {
2738 if (e->type() != QEvent::MouseMove)
2739 QApplicationPrivate::giveFocusAccordingToFocusPolicy(w, event: e, localPos: relpos);
2740
2741 // ### Qt 7 These dynamic tool tips should be an OPT-IN feature. Some platforms
2742 // like macOS (probably others too), can optimize their views by not
2743 // dispatching mouse move events. We have attributes to control hover,
2744 // and mouse tracking, but as long as we are deciding to implement this
2745 // feature without choice of opting-in or out, you ALWAYS have to have
2746 // tracking enabled. Therefore, the other properties give a false sense of
2747 // performance enhancement.
2748 if (e->type() == QEvent::MouseMove && mouse->buttons() == 0
2749 && w->rect().contains(p: relpos)) { // Outside due to mouse grab?
2750 d->toolTipWidget = w;
2751 d->toolTipPos = relpos;
2752 d->toolTipGlobalPos = mouse->globalPosition().toPoint();
2753 QStyle *s = d->toolTipWidget->style();
2754 int wakeDelay = s->styleHint(stylehint: QStyle::SH_ToolTip_WakeUpDelay, opt: nullptr, widget: d->toolTipWidget, returnData: nullptr);
2755 d->toolTipWakeUp.start(msec: d->toolTipFallAsleep.isActive() ? 20 : wakeDelay, obj: this);
2756 }
2757 }
2758
2759 bool eventAccepted = mouse->isAccepted();
2760
2761 QPointer<QWidget> pw = w;
2762 while (w) {
2763 QMouseEvent me(mouse->type(), relpos, mouse->scenePosition(), mouse->globalPosition().toPoint(),
2764 mouse->button(), mouse->buttons(), mouse->modifiers(), mouse->source(),
2765 mouse->pointingDevice());
2766 me.m_spont = mouse->spontaneous();
2767 me.setTimestamp(mouse->timestamp());
2768 QMutableSinglePointEvent::from(e&: me).setDoubleClick(QMutableSinglePointEvent::from(e: mouse)->isDoubleClick());
2769 // throw away any mouse-tracking-only mouse events
2770 if (!w->hasMouseTracking()
2771 && mouse->type() == QEvent::MouseMove && mouse->buttons() == 0) {
2772 // but still send them through all application event filters (normally done by notify_helper)
2773 d->sendThroughApplicationEventFilters(w, w == receiver ? mouse : &me);
2774 res = true;
2775 } else {
2776 w->setAttribute(Qt::WA_NoMouseReplay, on: false);
2777 res = d->notify_helper(receiver: w, e: w == receiver ? mouse : &me);
2778 e->m_spont = false;
2779 }
2780 eventAccepted = (w == receiver ? mouse : &me)->isAccepted();
2781 if (res && eventAccepted)
2782 break;
2783 if (w->isWindow() || w->testAttribute(attribute: Qt::WA_NoMousePropagation))
2784 break;
2785 relpos += w->pos();
2786 w = w->parentWidget();
2787 }
2788
2789 mouse->setAccepted(eventAccepted);
2790
2791 if (e->type() == QEvent::MouseMove) {
2792 if (!pw)
2793 break;
2794
2795 w = static_cast<QWidget *>(receiver);
2796 relpos = mouse->position().toPoint();
2797 QPoint diff = relpos - w->mapFromGlobal(mouse->globalPosition().toPoint());
2798 while (w) {
2799 if (w->testAttribute(attribute: Qt::WA_Hover) &&
2800 (!QApplication::activePopupWidget() || QApplication::activePopupWidget() == w->window())) {
2801 QHoverEvent he(QEvent::HoverMove, mouse->scenePosition(), mouse->globalPosition(), relpos - diff, mouse->modifiers());
2802 QMutableEventPoint::setPosition(p&: he.point(i: 0), arg: relpos);
2803 d->notify_helper(receiver: w, e: &he);
2804 }
2805 if (w->isWindow() || w->testAttribute(attribute: Qt::WA_NoMousePropagation))
2806 break;
2807 relpos += w->pos();
2808 w = w->parentWidget();
2809 }
2810 }
2811
2812 d->hoverGlobalPos = mouse->globalPosition().toPoint();
2813 break;
2814 }
2815#if QT_CONFIG(wheelevent)
2816 case QEvent::Wheel: {
2817 // QTBUG-40656, QTBUG-42731: ignore wheel events when a popup (QComboBox) is open.
2818 if (const QWidget *popup = QApplication::activePopupWidget()) {
2819 if (w->window() != popup)
2820 return true;
2821 }
2822
2823 QWheelEvent* wheel = static_cast<QWheelEvent*>(e);
2824 if (!wheel->spontaneous()) {
2825 /*
2826 Synthesized events shouldn't propagate, e.g. QScrollArea passes events from the
2827 viewport on to the scrollbars, which might ignore the event if there is no more
2828 space to scroll. If we would propagate, the event would come back to the viewport.
2829 */
2830 res = d->notify_helper(receiver: w, e: wheel);
2831 break;
2832 }
2833
2834 const Qt::ScrollPhase phase = wheel->phase();
2835 QPoint relpos = wheel->position().toPoint();
2836
2837 // Ideally, we should lock on a widget when it starts receiving wheel
2838 // events. This avoids other widgets to start receiving those events
2839 // as the mouse cursor hovers them. However, given the way common
2840 // wheeled mice work, there's no certain way of connecting different
2841 // wheel events as a stream. This results in the NoScrollPhase case,
2842 // where we just send the event from the original receiver and up its
2843 // hierarchy until the event gets accepted.
2844 //
2845 // In the case of more evolved input devices, like Apple's trackpad or
2846 // Magic Mouse, we receive the scroll phase information. This helps us
2847 // connect wheel events as a stream and therefore makes it easier to
2848 // lock on the widget onto which the scrolling was initiated.
2849 //
2850 // We assume that, when supported, the phase cycle follows the pattern:
2851 //
2852 // ScrollBegin (ScrollUpdate* ScrollMomentum* ScrollEnd)+
2853 //
2854 // This means that we can have scrolling sequences (starting with ScrollBegin)
2855 // or partial sequences (after a ScrollEnd and starting with ScrollUpdate).
2856
2857 // a widget has already grabbed the wheel for a sequence
2858 if (QApplicationPrivate::wheel_widget) {
2859 Q_ASSERT(phase != Qt::NoScrollPhase);
2860 w = QApplicationPrivate::wheel_widget;
2861 relpos = w->mapFromGlobal(wheel->globalPosition().toPoint());
2862 }
2863 /*
2864 Start or finish a scrolling sequence by grabbing/releasing the wheel via
2865 wheel_widget. The sequence might be partial (ie. not start with ScrollBegin),
2866 e.g. if the previous wheel_widget was destroyed mid-sequence.
2867 */
2868 switch (phase) {
2869 case Qt::ScrollEnd:
2870 QApplicationPrivate::wheel_widget = nullptr;
2871 break;
2872 case Qt::ScrollBegin:
2873 QApplicationPrivate::wheel_widget = w;
2874 Q_FALLTHROUGH();
2875 case Qt::ScrollUpdate:
2876 case Qt::ScrollMomentum:
2877 if (!QApplicationPrivate::wheel_widget)
2878 QApplicationPrivate::wheel_widget = w;
2879 Q_FALLTHROUGH();
2880 case Qt::NoScrollPhase:
2881 QApplicationPrivate::giveFocusAccordingToFocusPolicy(w, event: e, localPos: relpos);
2882 break;
2883 // no default: - we want warnings if we don't handle all phases explicitly
2884 }
2885
2886 QWheelEvent we(relpos, wheel->globalPosition(), wheel->pixelDelta(), wheel->angleDelta(), wheel->buttons(),
2887 wheel->modifiers(), phase, wheel->inverted(), wheel->source(), wheel->pointingDevice());
2888
2889 we.setTimestamp(wheel->timestamp());
2890 bool eventAccepted;
2891 do {
2892 // events are delivered as accepted and ignored by the default event handler
2893 // since we always send the same QWheelEvent object, we need to reset the accepted state
2894 we.setAccepted(true);
2895 we.m_spont = wheel->spontaneous() && w == receiver;
2896 res = d->notify_helper(receiver: w, e: &we);
2897 eventAccepted = we.isAccepted();
2898 if (res && eventAccepted)
2899 break;
2900 if (w->isWindow() || w->testAttribute(attribute: Qt::WA_NoMousePropagation))
2901 break;
2902
2903 QMutableEventPoint::setPosition(p&: we.point(i: 0), arg: we.position() + w->pos());
2904 w = w->parentWidget();
2905 } while (w);
2906 wheel->setAccepted(eventAccepted);
2907 break;
2908 }
2909#endif
2910#ifndef QT_NO_CONTEXTMENU
2911 case QEvent::ContextMenu: {
2912 QContextMenuEvent *context = static_cast<QContextMenuEvent*>(e);
2913 QPoint relpos = context->pos();
2914 bool eventAccepted = context->isAccepted();
2915 while (w) {
2916 QContextMenuEvent ce(context->reason(), relpos, context->globalPos(), context->modifiers());
2917 ce.m_spont = e->spontaneous();
2918 res = d->notify_helper(receiver: w, e: w == receiver ? context : &ce);
2919 eventAccepted = ((w == receiver) ? context : &ce)->isAccepted();
2920 e->m_spont = false;
2921
2922 if (res && eventAccepted)
2923 break;
2924 if (w->isWindow() || w->testAttribute(attribute: Qt::WA_NoMousePropagation))
2925 break;
2926
2927 relpos += w->pos();
2928 w = w->parentWidget();
2929 }
2930 context->setAccepted(eventAccepted);
2931 break;
2932 }
2933#endif // QT_NO_CONTEXTMENU
2934#if QT_CONFIG(tabletevent)
2935 case QEvent::TabletMove:
2936 case QEvent::TabletPress:
2937 case QEvent::TabletRelease: {
2938 QTabletEvent *tablet = static_cast<QTabletEvent*>(e);
2939 QPointF relpos = tablet->position();
2940 bool eventAccepted = tablet->isAccepted();
2941 while (w) {
2942 QTabletEvent te(tablet->type(), tablet->pointingDevice(), relpos, tablet->globalPosition(),
2943 tablet->pressure(), tablet->xTilt(), tablet->yTilt(),
2944 tablet->tangentialPressure(), tablet->rotation(), tablet->z(),
2945 tablet->modifiers(), tablet->button(), tablet->buttons());
2946 te.m_spont = e->spontaneous();
2947 te.setAccepted(false);
2948 res = d->notify_helper(receiver: w, e: w == receiver ? tablet : &te);
2949 eventAccepted = ((w == receiver) ? tablet : &te)->isAccepted();
2950 e->m_spont = false;
2951 if (res && eventAccepted)
2952 break;
2953 if (w->isWindow() || w->testAttribute(attribute: Qt::WA_NoMousePropagation))
2954 break;
2955
2956 relpos += w->pos();
2957 w = w->parentWidget();
2958 }
2959 tablet->setAccepted(eventAccepted);
2960 break;
2961 }
2962#endif // QT_CONFIG(tabletevent)
2963
2964#if QT_CONFIG(tooltip) || QT_CONFIG(whatsthis)
2965 case QEvent::ToolTip:
2966 case QEvent::WhatsThis:
2967 case QEvent::QueryWhatsThis: {
2968 QHelpEvent *help = static_cast<QHelpEvent*>(e);
2969 QPoint relpos = help->pos();
2970 bool eventAccepted = help->isAccepted();
2971 while (w) {
2972 QHelpEvent he(help->type(), relpos, help->globalPos());
2973 he.m_spont = e->spontaneous();
2974 res = d->notify_helper(receiver: w, e: w == receiver ? help : &he);
2975 e->m_spont = false;
2976 eventAccepted = (w == receiver ? help : &he)->isAccepted();
2977 if (res && eventAccepted)
2978 break;
2979 if (w->isWindow())
2980 break;
2981
2982 relpos += w->pos();
2983 w = w->parentWidget();
2984 }
2985 help->setAccepted(eventAccepted);
2986 break;
2987 }
2988#endif
2989#if QT_CONFIG(statustip) || QT_CONFIG(whatsthis)
2990 case QEvent::StatusTip:
2991 case QEvent::WhatsThisClicked:
2992 while (w) {
2993 res = d->notify_helper(receiver: w, e);
2994 if (res && e->isAccepted())
2995 break;
2996 if (w->isWindow())
2997 break;
2998 w = w->parentWidget();
2999 }
3000 break;
3001#endif
3002
3003#if QT_CONFIG(draganddrop)
3004 case QEvent::DragEnter: {
3005 QDragEnterEvent *dragEvent = static_cast<QDragEnterEvent *>(e);
3006#if QT_CONFIG(graphicsview)
3007 // QGraphicsProxyWidget handles its own propagation,
3008 // and we must not change QDragManagers currentTarget.
3009 const auto &extra = w->window()->d_func()->extra;
3010 if (extra && extra->proxyWidget) {
3011 res = d->notify_helper(receiver: w, e: dragEvent);
3012 break;
3013 }
3014#endif
3015 while (w) {
3016 if (w->isEnabled() && w->acceptDrops()) {
3017 res = d->notify_helper(receiver: w, e: dragEvent);
3018 if (res && dragEvent->isAccepted()) {
3019 QDragManager::self()->setCurrentTarget(target: w);
3020 break;
3021 }
3022 }
3023 if (w->isWindow())
3024 break;
3025 dragEvent->m_pos = w->mapToParent(dragEvent->m_pos);
3026 w = w->parentWidget();
3027 }
3028 break;
3029 }
3030 case QEvent::DragMove:
3031 case QEvent::Drop:
3032 case QEvent::DragLeave: {
3033#if QT_CONFIG(graphicsview)
3034 // QGraphicsProxyWidget handles its own propagation,
3035 // and we must not change QDragManagers currentTarget.
3036 const auto &extra = w->window()->d_func()->extra;
3037 bool isProxyWidget = extra && extra->proxyWidget;
3038 if (!isProxyWidget)
3039#endif
3040 w = qobject_cast<QWidget *>(o: QDragManager::self()->currentTarget());
3041
3042 if (!w)
3043 break;
3044 if (e->type() == QEvent::DragMove || e->type() == QEvent::Drop) {
3045 QDropEvent *dragEvent = static_cast<QDropEvent *>(e);
3046 QWidget *origReceiver = static_cast<QWidget *>(receiver);
3047 while (origReceiver && w != origReceiver) {
3048 dragEvent->m_pos = origReceiver->mapToParent(dragEvent->m_pos);
3049 origReceiver = origReceiver->parentWidget();
3050 }
3051 }
3052 res = d->notify_helper(receiver: w, e);
3053 if (e->type() != QEvent::DragMove
3054#if QT_CONFIG(graphicsview)
3055 && !isProxyWidget
3056#endif
3057 )
3058 QDragManager::self()->setCurrentTarget(target: nullptr, dropped: e->type() == QEvent::Drop);
3059 break;
3060 }
3061#endif // QT_CONFIG(draganddrop)
3062 case QEvent::TouchBegin: {
3063 // Note: TouchUpdate and TouchEnd events are never propagated
3064 QMutableTouchEvent *touchEvent = QMutableTouchEvent::from(e: static_cast<QTouchEvent *>(e));
3065 bool eventAccepted = touchEvent->isAccepted();
3066 bool acceptTouchEvents = w->testAttribute(attribute: Qt::WA_AcceptTouchEvents);
3067
3068 if (acceptTouchEvents && e->spontaneous()
3069 && touchEvent->device()->type() != QInputDevice::DeviceType::TouchPad) {
3070 const QPoint localPos = touchEvent->points()[0].position().toPoint();
3071 QApplicationPrivate::giveFocusAccordingToFocusPolicy(w, event: e, localPos);
3072 }
3073
3074#ifndef QT_NO_GESTURES
3075 QPointer<QWidget> gesturePendingWidget;
3076#endif
3077
3078 while (w) {
3079 // first, try to deliver the touch event
3080 acceptTouchEvents = w->testAttribute(attribute: Qt::WA_AcceptTouchEvents);
3081 touchEvent->setTarget(w);
3082 touchEvent->setAccepted(acceptTouchEvents);
3083 QPointer<QWidget> p = w;
3084 res = acceptTouchEvents && d->notify_helper(receiver: w, e: touchEvent);
3085 eventAccepted = touchEvent->isAccepted();
3086 if (p.isNull()) {
3087 // widget was deleted
3088 w = nullptr;
3089 } else {
3090 w->setAttribute(Qt::WA_WState_AcceptedTouchBeginEvent, on: res && eventAccepted);
3091 }
3092 touchEvent->m_spont = false;
3093 if (res && eventAccepted) {
3094 // the first widget to accept the TouchBegin gets an implicit grab.
3095 d->activateImplicitTouchGrab(widget: w, touchBeginEvent: touchEvent);
3096 break;
3097 }
3098#ifndef QT_NO_GESTURES
3099 if (gesturePendingWidget.isNull() && w && QGestureManager::gesturePending(o: w))
3100 gesturePendingWidget = w;
3101#endif
3102 if (!w || w->isWindow() || w->testAttribute(attribute: Qt::WA_NoMousePropagation))
3103 break;
3104
3105 const QPoint offset = w->pos();
3106 w = w->parentWidget();
3107 touchEvent->setTarget(w);
3108 for (int i = 0; i < touchEvent->pointCount(); ++i) {
3109 auto &pt = touchEvent->point(i);
3110 QMutableEventPoint::setPosition(p&: pt, arg: pt.position() + offset);
3111 }
3112 }
3113
3114#ifndef QT_NO_GESTURES
3115 if (!eventAccepted && !gesturePendingWidget.isNull()) {
3116 // the first widget subscribed to a gesture gets an implicit grab for all
3117 // points, also for events and event points that have not been accepted.
3118 d->activateImplicitTouchGrab(widget: gesturePendingWidget, touchBeginEvent: touchEvent, grabMode: QApplicationPrivate::GrabAllPoints);
3119 }
3120#endif
3121
3122 touchEvent->setAccepted(eventAccepted);
3123 break;
3124 }
3125 case QEvent::TouchUpdate:
3126 case QEvent::TouchEnd:
3127 // We may get here if the widget is subscribed to a gesture,
3128 // but has not accepted TouchBegin. Propagate touch events
3129 // only if TouchBegin has been accepted.
3130 if (w->testAttribute(attribute: Qt::WA_WState_AcceptedTouchBeginEvent))
3131 res = d->notify_helper(receiver: w, e);
3132 break;
3133 case QEvent::RequestSoftwareInputPanel:
3134 inputMethod()->show();
3135 break;
3136 case QEvent::CloseSoftwareInputPanel:
3137 inputMethod()->hide();
3138 break;
3139
3140#ifndef QT_NO_GESTURES
3141 case QEvent::NativeGesture:
3142 while (w) {
3143 e->ignore();
3144 res = d->notify_helper(receiver: w, e);
3145 if (res && e->isAccepted())
3146 break;
3147 if (w->isWindow())
3148 break;
3149 w = w->parentWidget();
3150 }
3151 break;
3152 case QEvent::Gesture:
3153 case QEvent::GestureOverride: {
3154 QGestureEvent *gestureEvent = static_cast<QGestureEvent *>(e);
3155 QList<QGesture *> allGestures = gestureEvent->gestures();
3156
3157 bool eventAccepted = gestureEvent->isAccepted();
3158 bool wasAccepted = eventAccepted;
3159 while (w) {
3160 // send only gestures the widget expects
3161 QList<QGesture *> gestures;
3162 QWidgetPrivate *wd = w->d_func();
3163 for (int i = 0; i < allGestures.size();) {
3164 QGesture *g = allGestures.at(i);
3165 Qt::GestureType type = g->gestureType();
3166 QMap<Qt::GestureType, Qt::GestureFlags>::iterator contextit =
3167 wd->gestureContext.find(key: type);
3168 bool deliver = contextit != wd->gestureContext.end() &&
3169 (g->state() == Qt::GestureStarted || w == receiver ||
3170 (contextit.value() & Qt::ReceivePartialGestures));
3171 if (deliver) {
3172 allGestures.removeAt(i);
3173 gestures.append(t: g);
3174 } else {
3175 ++i;
3176 }
3177 }
3178 if (!gestures.isEmpty()) { // we have gestures for this w
3179 QGestureEvent ge(gestures);
3180 ge.t = gestureEvent->t;
3181 ge.m_spont = gestureEvent->spontaneous();
3182 ge.m_accept = wasAccepted;
3183 ge.m_accepted = gestureEvent->m_accepted;
3184 res = d->notify_helper(receiver: w, e: &ge);
3185 gestureEvent->m_spont = false;
3186 eventAccepted = ge.isAccepted();
3187 for (int i = 0; i < gestures.size(); ++i) {
3188 QGesture *g = gestures.at(i);
3189 // Ignore res [event return value] because handling of multiple gestures
3190 // packed into a single QEvent depends on not consuming the event
3191 if (eventAccepted || ge.isAccepted(g)) {
3192 // if the gesture was accepted, mark the target widget for it
3193 gestureEvent->m_targetWidgets[g->gestureType()] = w;
3194 gestureEvent->setAccepted(g, true);
3195 } else {
3196 // if the gesture was explicitly ignored by the application,
3197 // put it back so a parent can get it
3198 allGestures.append(t: g);
3199 }
3200 }
3201 }
3202 if (allGestures.isEmpty()) // everything delivered
3203 break;
3204 if (w->isWindow())
3205 break;
3206 w = w->parentWidget();
3207 }
3208 for (QGesture *g : std::as_const(t&: allGestures))
3209 gestureEvent->setAccepted(g, false);
3210 gestureEvent->m_accept = false; // to make sure we check individual gestures
3211 break;
3212 }
3213#endif // QT_NO_GESTURES
3214#ifdef Q_OS_MAC
3215 // Enable touch events on enter, disable on leave.
3216 typedef void (*RegisterTouchWindowFn)(QWindow *, bool);
3217 case QEvent::Enter:
3218 if (w->testAttribute(Qt::WA_AcceptTouchEvents)) {
3219 RegisterTouchWindowFn registerTouchWindow = reinterpret_cast<RegisterTouchWindowFn>
3220 (platformNativeInterface()->nativeResourceFunctionForIntegration("registertouchwindow"));
3221 if (registerTouchWindow)
3222 registerTouchWindow(w->window()->windowHandle(), true);
3223 }
3224 res = d->notify_helper(receiver, e);
3225 break;
3226 case QEvent::Leave:
3227 if (w->testAttribute(Qt::WA_AcceptTouchEvents)) {
3228 RegisterTouchWindowFn registerTouchWindow = reinterpret_cast<RegisterTouchWindowFn>
3229 (platformNativeInterface()->nativeResourceFunctionForIntegration("registertouchwindow"));
3230 if (registerTouchWindow)
3231 registerTouchWindow(w->window()->windowHandle(), false);
3232 }
3233 res = d->notify_helper(receiver, e);
3234 break;
3235#endif
3236 default:
3237 res = d->notify_helper(receiver, e);
3238 break;
3239 }
3240 } else {
3241 res = d->notify_helper(receiver, e);
3242 }
3243
3244 return res;
3245}
3246
3247bool QApplicationPrivate::notify_helper(QObject *receiver, QEvent * e)
3248{
3249 // These tracepoints (and the whole function, actually) are very similar
3250 // to the ones in QCoreApplicationPrivate::notify_helper; the reason for their
3251 // duplication is because tracepoint symbols are not exported by QtCore.
3252 // If you adjust the tracepoints here, consider adjusting QCoreApplicationPrivate too.
3253 Q_TRACE(QApplication_notify_entry, receiver, e, e->type());
3254 bool consumed = false;
3255 bool filtered = false;
3256 Q_TRACE_EXIT(QApplication_notify_exit, consumed, filtered);
3257
3258 // send to all application event filters
3259 if (threadRequiresCoreApplication()
3260 && receiver->d_func()->threadData.loadRelaxed()->thread.loadAcquire() == mainThread()
3261 && sendThroughApplicationEventFilters(receiver, e)) {
3262 filtered = true;
3263 return filtered;
3264 }
3265
3266 if (receiver->isWidgetType()) {
3267 QWidget *widget = static_cast<QWidget *>(receiver);
3268
3269#if !defined(QT_NO_CURSOR)
3270 // toggle HasMouse widget state on enter and leave
3271 if ((e->type() == QEvent::Enter || e->type() == QEvent::DragEnter) &&
3272 (!QApplication::activePopupWidget() || QApplication::activePopupWidget() == widget->window()))
3273 widget->setAttribute(Qt::WA_UnderMouse, on: true);
3274 else if (e->type() == QEvent::Leave || e->type() == QEvent::DragLeave)
3275 widget->setAttribute(Qt::WA_UnderMouse, on: false);
3276#endif
3277
3278 if (QLayout *layout=widget->d_func()->layout) {
3279 layout->widgetEvent(e);
3280 }
3281 }
3282
3283 // send to all receiver event filters
3284 if (sendThroughObjectEventFilters(receiver, e)) {
3285 filtered = true;
3286 return filtered;
3287 }
3288
3289 // deliver the event
3290 consumed = receiver->event(event: e);
3291
3292 QCoreApplicationPrivate::setEventSpontaneous(e, spontaneous: false);
3293 return consumed;
3294}
3295
3296bool QApplicationPrivate::inPopupMode()
3297{
3298 return QApplicationPrivate::popupWidgets != nullptr;
3299}
3300
3301static void ungrabKeyboardForPopup(QWidget *popup)
3302{
3303 if (QWidget::keyboardGrabber())
3304 qt_widget_private(widget: QWidget::keyboardGrabber())->stealKeyboardGrab(grab: true);
3305 else
3306 qt_widget_private(widget: popup)->stealKeyboardGrab(grab: false);
3307}
3308
3309static void ungrabMouseForPopup(QWidget *popup)
3310{
3311 if (QWidget::mouseGrabber())
3312 qt_widget_private(widget: QWidget::mouseGrabber())->stealMouseGrab(grab: true);
3313 else
3314 qt_widget_private(widget: popup)->stealMouseGrab(grab: false);
3315}
3316
3317static bool popupGrabOk;
3318
3319static void grabForPopup(QWidget *popup)
3320{
3321 Q_ASSERT(popup->testAttribute(Qt::WA_WState_Created));
3322 popupGrabOk = qt_widget_private(widget: popup)->stealKeyboardGrab(grab: true);
3323 if (popupGrabOk) {
3324 popupGrabOk = qt_widget_private(widget: popup)->stealMouseGrab(grab: true);
3325 if (!popupGrabOk) {
3326 // transfer grab back to the keyboard grabber if any
3327 ungrabKeyboardForPopup(popup);
3328 }
3329 }
3330}
3331
3332extern QWidget *qt_popup_down;
3333extern bool qt_replay_popup_mouse_event;
3334extern bool qt_popup_down_closed;
3335
3336bool QApplicationPrivate::closeAllPopups()
3337{
3338 // Close all popups: In case some popup refuses to close,
3339 // we give up after 1024 attempts (to avoid an infinite loop).
3340 int maxiter = 1024;
3341 QWidget *popup;
3342 while ((popup = QApplication::activePopupWidget()) && maxiter--)
3343 popup->close(); // this will call QApplicationPrivate::closePopup
3344 return true;
3345}
3346
3347void QApplicationPrivate::closePopup(QWidget *popup)
3348{
3349 if (!popupWidgets)
3350 return;
3351 popupWidgets->removeAll(t: popup);
3352
3353 if (popup == qt_popup_down) {
3354 qt_button_down = nullptr;
3355 qt_popup_down_closed = true;
3356 qt_popup_down = nullptr;
3357 }
3358
3359 if (QApplicationPrivate::popupWidgets->size() == 0) { // this was the last popup
3360 delete QApplicationPrivate::popupWidgets;
3361 QApplicationPrivate::popupWidgets = nullptr;
3362 qt_popup_down_closed = false;
3363
3364 if (popupGrabOk) {
3365 popupGrabOk = false;
3366
3367 // TODO on multi-seat window systems, we have to know which mouse
3368 auto devPriv = QPointingDevicePrivate::get(q: QPointingDevice::primaryPointingDevice());
3369 auto mousePressPos = devPriv->pointById(id: 0)->eventPoint.globalPressPosition();
3370 if (popup->geometry().contains(p: mousePressPos.toPoint())
3371 || popup->testAttribute(attribute: Qt::WA_NoMouseReplay)) {
3372 // mouse release event or inside
3373 qt_replay_popup_mouse_event = false;
3374 } else { // mouse press event
3375 qt_replay_popup_mouse_event = true;
3376 }
3377
3378 // transfer grab back to mouse grabber if any, otherwise release the grab
3379 ungrabMouseForPopup(popup);
3380
3381 // transfer grab back to keyboard grabber if any, otherwise release the grab
3382 ungrabKeyboardForPopup(popup);
3383 }
3384
3385 if (active_window) {
3386 if (QWidget *fw = active_window->focusWidget()) {
3387 if (fw != QApplication::focusWidget()) {
3388 fw->setFocus(Qt::PopupFocusReason);
3389 } else {
3390 QFocusEvent e(QEvent::FocusIn, Qt::PopupFocusReason);
3391 QCoreApplication::sendEvent(receiver: fw, event: &e);
3392 }
3393 }
3394 }
3395
3396 } else {
3397 // A popup was closed, so the previous popup gets the focus.
3398 QWidget* aw = QApplicationPrivate::popupWidgets->constLast();
3399 if (QWidget *fw = aw->focusWidget())
3400 fw->setFocus(Qt::PopupFocusReason);
3401
3402 // can become nullptr due to setFocus() above
3403 if (QApplicationPrivate::popupWidgets &&
3404 QApplicationPrivate::popupWidgets->size() == 1) // grab mouse/keyboard
3405 grabForPopup(popup: aw);
3406 }
3407
3408}
3409
3410int openPopupCount = 0;
3411
3412void QApplicationPrivate::openPopup(QWidget *popup)
3413{
3414 openPopupCount++;
3415 if (!popupWidgets) // create list
3416 popupWidgets = new QWidgetList;
3417 popupWidgets->append(t: popup); // add to end of list
3418
3419 if (QApplicationPrivate::popupWidgets->size() == 1) // grab mouse/keyboard
3420 grabForPopup(popup);
3421
3422 // popups are not focus-handled by the window system (the first
3423 // popup grabbed the keyboard), so we have to do that manually: A
3424 // new popup gets the focus
3425 if (popup->focusWidget()) {
3426 popup->focusWidget()->setFocus(Qt::PopupFocusReason);
3427 } else if (popupWidgets->size() == 1) { // this was the first popup
3428 if (QWidget *fw = QApplication::focusWidget()) {
3429 QFocusEvent e(QEvent::FocusOut, Qt::PopupFocusReason);
3430 QCoreApplication::sendEvent(receiver: fw, event: &e);
3431 }
3432 }
3433}
3434
3435#ifdef QT_KEYPAD_NAVIGATION
3436/*!
3437 Sets the kind of focus navigation Qt should use to \a mode.
3438
3439 This feature is available in Qt for Embedded Linux only.
3440
3441 \since 4.6
3442*/
3443void QApplication::setNavigationMode(Qt::NavigationMode mode)
3444{
3445 QApplicationPrivate::navigationMode = mode;
3446}
3447
3448/*!
3449 Returns what kind of focus navigation Qt is using.
3450
3451 This feature is available in Qt for Embedded Linux only.
3452
3453 \since 4.6
3454*/
3455Qt::NavigationMode QApplication::navigationMode()
3456{
3457 return QApplicationPrivate::navigationMode;
3458}
3459#endif
3460
3461/*!
3462 \fn void QApplication::alert(QWidget *widget, int msec)
3463 \since 4.3
3464
3465 Causes an alert to be shown for \a widget if the window is not the active
3466 window. The alert is shown for \a msec milliseconds. If \a msec is zero (the
3467 default), then the alert is shown indefinitely until the window becomes
3468 active again.
3469
3470 Currently this function does nothing on Qt for Embedded Linux.
3471
3472 On \macos, this works more at the application level and will cause the
3473 application icon to bounce in the dock.
3474
3475 On Windows, this causes the window's taskbar entry to flash for a time. If
3476 \a msec is zero, the flashing will stop and the taskbar entry will turn a
3477 different color (currently orange).
3478
3479 On X11, this will cause the window to be marked as "demands attention", the
3480 window must not be hidden (i.e. not have hide() called on it, but be
3481 visible in some sort of way) in order for this to work.
3482*/
3483void QApplication::alert(QWidget *widget, int duration)
3484{
3485 if (widget) {
3486 if (widget->window()->isActiveWindow() && !(widget->window()->windowState() & Qt::WindowMinimized))
3487 return;
3488 if (QWindow *window= QApplicationPrivate::windowForWidget(widget))
3489 window->alert(msec: duration);
3490 } else {
3491 const auto topLevels = topLevelWidgets();
3492 for (QWidget *topLevel : topLevels)
3493 QApplication::alert(widget: topLevel, duration);
3494 }
3495}
3496
3497/*!
3498 \property QApplication::cursorFlashTime
3499 \brief the text cursor's flash (blink) time in milliseconds
3500
3501 The flash time is the time required to display, invert and restore the
3502 caret display. Usually the text cursor is displayed for half the cursor
3503 flash time, then hidden for the same amount of time, but this may vary.
3504
3505 The default value on X11 is 1000 milliseconds. On Windows, the
3506 \uicontrol{Control Panel} value is used and setting this property sets the cursor
3507 flash time for all applications.
3508
3509 We recommend that widgets do not cache this value as it may change at any
3510 time if the user changes the global desktop settings.
3511
3512 \note This property may hold a negative value, for instance if cursor
3513 blinking is disabled.
3514*/
3515void QApplication::setCursorFlashTime(int msecs)
3516{
3517 QGuiApplication::styleHints()->setCursorFlashTime(msecs);
3518}
3519
3520int QApplication::cursorFlashTime()
3521{
3522 return QGuiApplication::styleHints()->cursorFlashTime();
3523}
3524
3525/*!
3526 \property QApplication::doubleClickInterval
3527 \brief the time limit in milliseconds that distinguishes a double click
3528 from two consecutive mouse clicks
3529
3530 The default value on X11 is 400 milliseconds. On Windows and Mac OS, the
3531 operating system's value is used.
3532*/
3533void QApplication::setDoubleClickInterval(int ms)
3534{
3535 QGuiApplication::styleHints()->setMouseDoubleClickInterval(ms);
3536}
3537
3538int QApplication::doubleClickInterval()
3539{
3540 return QGuiApplication::styleHints()->mouseDoubleClickInterval();
3541}
3542
3543/*!
3544 \property QApplication::keyboardInputInterval
3545 \brief the time limit in milliseconds that distinguishes a key press
3546 from two consecutive key presses
3547 \since 4.2
3548
3549 The default value on X11 is 400 milliseconds. On Windows and Mac OS, the
3550 operating system's value is used.
3551*/
3552void QApplication::setKeyboardInputInterval(int ms)
3553{
3554 QGuiApplication::styleHints()->setKeyboardInputInterval(ms);
3555}
3556
3557int QApplication::keyboardInputInterval()
3558{
3559 return QGuiApplication::styleHints()->keyboardInputInterval();
3560}
3561
3562/*!
3563 \property QApplication::wheelScrollLines
3564 \brief the number of lines to scroll a widget, when the
3565 mouse wheel is rotated.
3566
3567 If the value exceeds the widget's number of visible lines, the widget
3568 should interpret the scroll operation as a single \e{page up} or
3569 \e{page down}. If the widget is an \l{QAbstractItemView}{item view class},
3570 then the result of scrolling one \e line depends on the setting of the
3571 widget's \l{QAbstractItemView::verticalScrollMode()}{scroll mode}. Scroll
3572 one \e line can mean \l{QAbstractItemView::ScrollPerItem}{scroll one item}
3573 or \l{QAbstractItemView::ScrollPerPixel}{scroll one pixel}.
3574
3575 By default, this property has a value of 3.
3576
3577 \sa QStyleHints::wheelScrollLines()
3578*/
3579#if QT_CONFIG(wheelevent)
3580int QApplication::wheelScrollLines()
3581{
3582 return styleHints()->wheelScrollLines();
3583}
3584
3585void QApplication::setWheelScrollLines(int lines)
3586{
3587 styleHints()->setWheelScrollLines(lines);
3588}
3589#endif
3590
3591static inline int uiEffectToFlag(Qt::UIEffect effect)
3592{
3593 switch (effect) {
3594 case Qt::UI_General:
3595 return QPlatformTheme::GeneralUiEffect;
3596 case Qt::UI_AnimateMenu:
3597 return QPlatformTheme::AnimateMenuUiEffect;
3598 case Qt::UI_FadeMenu:
3599 return QPlatformTheme::FadeMenuUiEffect;
3600 case Qt::UI_AnimateCombo:
3601 return QPlatformTheme::AnimateComboUiEffect;
3602 case Qt::UI_AnimateTooltip:
3603 return QPlatformTheme::AnimateTooltipUiEffect;
3604 case Qt::UI_FadeTooltip:
3605 return QPlatformTheme::FadeTooltipUiEffect;
3606 case Qt::UI_AnimateToolBox:
3607 return QPlatformTheme::AnimateToolBoxUiEffect;
3608 }
3609 return 0;
3610}
3611
3612/*!
3613 \fn void QApplication::setEffectEnabled(Qt::UIEffect effect, bool enable)
3614
3615 Enables the UI effect \a effect if \a enable is true, otherwise the effect
3616 will not be used.
3617
3618 \note All effects are disabled on screens running at less than 16-bit color
3619 depth.
3620
3621 \sa isEffectEnabled(), Qt::UIEffect, setDesktopSettingsAware()
3622*/
3623void QApplication::setEffectEnabled(Qt::UIEffect effect, bool enable)
3624{
3625 int effectFlags = uiEffectToFlag(effect);
3626 if (enable) {
3627 if (effectFlags & QPlatformTheme::FadeMenuUiEffect)
3628 effectFlags |= QPlatformTheme::AnimateMenuUiEffect;
3629 if (effectFlags & QPlatformTheme::FadeTooltipUiEffect)
3630 effectFlags |= QPlatformTheme::AnimateTooltipUiEffect;
3631 QApplicationPrivate::enabledAnimations |= effectFlags;
3632 } else {
3633 QApplicationPrivate::enabledAnimations &= ~effectFlags;
3634 }
3635}
3636
3637/*!
3638 \fn bool QApplication::isEffectEnabled(Qt::UIEffect effect)
3639
3640 Returns \c true if \a effect is enabled; otherwise returns \c false.
3641
3642 By default, Qt will try to use the desktop settings. To prevent this, call
3643 setDesktopSettingsAware(false).
3644
3645 \note All effects are disabled on screens running at less than 16-bit color
3646 depth.
3647
3648 \sa setEffectEnabled(), Qt::UIEffect
3649*/
3650bool QApplication::isEffectEnabled(Qt::UIEffect effect)
3651{
3652 CHECK_QAPP_INSTANCE(false)
3653 return QColormap::instance().depth() >= 16
3654 && (QApplicationPrivate::enabledAnimations & QPlatformTheme::GeneralUiEffect)
3655 && (QApplicationPrivate::enabledAnimations & uiEffectToFlag(effect));
3656}
3657
3658/*!
3659 \fn void QApplication::beep()
3660
3661 Sounds the bell, using the default volume and sound. The function is \e not
3662 available in Qt for Embedded Linux.
3663*/
3664void QApplication::beep()
3665{
3666 QGuiApplicationPrivate::platformIntegration()->beep();
3667}
3668
3669/*!
3670 \macro qApp
3671 \relates QApplication
3672
3673 A global pointer referring to the unique application object. It is
3674 equivalent to QCoreApplication::instance(), but cast as a QApplication pointer,
3675 so only valid when the unique application object is a QApplication.
3676
3677 \sa QCoreApplication::instance(), qGuiApp
3678*/
3679
3680bool qt_sendSpontaneousEvent(QObject *receiver, QEvent *event)
3681{
3682 return QGuiApplication::sendSpontaneousEvent(receiver, event);
3683}
3684
3685void QApplicationPrivate::giveFocusAccordingToFocusPolicy(QWidget *widget, QEvent *event, QPoint localPos)
3686{
3687 const bool setFocusOnRelease = QGuiApplication::styleHints()->setFocusOnTouchRelease();
3688 Qt::FocusPolicy focusPolicy = Qt::ClickFocus;
3689 static QPointer<QWidget> focusedWidgetOnTouchBegin = nullptr;
3690
3691 switch (event->type()) {
3692 case QEvent::MouseButtonPress:
3693 case QEvent::MouseButtonDblClick:
3694 case QEvent::TouchBegin:
3695 focusedWidgetOnTouchBegin = QApplication::focusWidget();
3696 if (setFocusOnRelease)
3697 return;
3698 break;
3699 case QEvent::MouseButtonRelease:
3700 case QEvent::TouchEnd:
3701 if (!setFocusOnRelease)
3702 return;
3703 if (focusedWidgetOnTouchBegin != QApplication::focusWidget()) {
3704 // Focus widget was changed while delivering press/move events.
3705 // To not interfere with application logic, we leave focus as-is
3706 return;
3707 }
3708 break;
3709 case QEvent::Wheel:
3710 focusPolicy = Qt::WheelFocus;
3711 break;
3712 default:
3713 return;
3714 }
3715
3716 QWidget *focusWidget = widget;
3717 while (focusWidget) {
3718 if (focusWidget->isEnabled()
3719 && focusWidget->rect().contains(p: localPos)
3720 && QApplicationPrivate::shouldSetFocus(w: focusWidget, policy: focusPolicy)) {
3721 focusWidget->setFocus(Qt::MouseFocusReason);
3722 break;
3723 }
3724 if (focusWidget->isWindow())
3725 break;
3726
3727 // find out whether this widget (or its proxy) already has focus
3728 QWidget *f = focusWidget;
3729 if (focusWidget->d_func()->extra && focusWidget->d_func()->extra->focus_proxy)
3730 f = focusWidget->d_func()->extra->focus_proxy;
3731 // if it has, stop here.
3732 // otherwise a click on the focused widget would remove its focus if ClickFocus isn't set
3733 if (f->hasFocus())
3734 break;
3735
3736 localPos += focusWidget->pos();
3737 focusWidget = focusWidget->parentWidget();
3738 }
3739}
3740
3741bool QApplicationPrivate::shouldSetFocus(QWidget *w, Qt::FocusPolicy policy)
3742{
3743 QWidget *f = w;
3744 while (f->d_func()->extra && f->d_func()->extra->focus_proxy)
3745 f = f->d_func()->extra->focus_proxy;
3746
3747 if ((w->focusPolicy() & policy) != policy)
3748 return false;
3749 if (w != f && (f->focusPolicy() & policy) != policy)
3750 return false;
3751 return true;
3752}
3753
3754bool QApplicationPrivate::updateTouchPointsForWidget(QWidget *widget, QTouchEvent *touchEvent)
3755{
3756 bool containsPress = false;
3757
3758 for (int i = 0; i < touchEvent->pointCount(); ++i) {
3759 auto &pt = touchEvent->point(i);
3760 QMutableEventPoint::setPosition(p&: pt, arg: widget->mapFromGlobal(pt.globalPosition()));
3761
3762 if (pt.state() == QEventPoint::State::Pressed)
3763 containsPress = true;
3764 }
3765 return containsPress;
3766}
3767
3768void QApplicationPrivate::initializeMultitouch()
3769{
3770 initializeMultitouch_sys();
3771}
3772
3773void QApplicationPrivate::initializeMultitouch_sys()
3774{
3775}
3776
3777void QApplicationPrivate::cleanupMultitouch()
3778{
3779 cleanupMultitouch_sys();
3780}
3781
3782void QApplicationPrivate::cleanupMultitouch_sys()
3783{
3784}
3785
3786QWidget *QApplicationPrivate::findClosestTouchPointTarget(const QPointingDevice *device, const QEventPoint &touchPoint)
3787{
3788 const QPointF globalPos = touchPoint.globalPosition();
3789 int closestTouchPointId = -1;
3790 QObject *closestTarget = nullptr;
3791 qreal closestDistance = 0;
3792 const QPointingDevicePrivate *devPriv = QPointingDevicePrivate::get(q: device);
3793 for (auto &epd : devPriv->activePoints.values()) {
3794 const auto &pt = epd.eventPoint;
3795 if (pt.id() != touchPoint.id()) {
3796 qreal dx = globalPos.x() - pt.globalPosition().x();
3797 qreal dy = globalPos.y() - pt.globalPosition().y();
3798 qreal distance = dx * dx + dy * dy;
3799 if (closestTouchPointId == -1 || distance < closestDistance) {
3800 closestTouchPointId = pt.id();
3801 closestDistance = distance;
3802 closestTarget = QMutableEventPoint::target(p: pt);
3803 }
3804 }
3805 }
3806 return static_cast<QWidget *>(closestTarget);
3807}
3808
3809void QApplicationPrivate::activateImplicitTouchGrab(QWidget *widget, QTouchEvent *touchEvent,
3810 ImplicitTouchGrabMode grabMode)
3811{
3812 if (touchEvent->type() != QEvent::TouchBegin)
3813 return;
3814
3815 // If the widget dispatched the event further (see QGraphicsProxyWidget), then
3816 // there might already be an implicit grabber. Don't override that. A widget that
3817 // has partially recognized a gesture needs to grab all points.
3818 for (int i = 0; i < touchEvent->pointCount(); ++i) {
3819 auto &ep = touchEvent->point(i);
3820 if (!QMutableEventPoint::target(p: ep) && (ep.isAccepted() || grabMode == GrabAllPoints))
3821 QMutableEventPoint::setTarget(p&: ep, arg: widget);
3822 }
3823 // TODO setExclusiveGrabber() to be consistent with Qt Quick?
3824}
3825
3826bool QApplicationPrivate::translateRawTouchEvent(QWidget *window, const QTouchEvent *te)
3827{
3828 QApplicationPrivate *d = self;
3829 // TODO get rid of this QPair
3830 typedef QPair<QEventPoint::State, QList<QEventPoint> > StatesAndTouchPoints;
3831 QHash<QWidget *, StatesAndTouchPoints> widgetsNeedingEvents;
3832
3833 const auto *device = te->pointingDevice();
3834 auto touchPoints = te->points(); // touch points will be mutated
3835 for (auto &touchPoint : touchPoints) {
3836 // update state
3837 QPointer<QObject> target;
3838 if (touchPoint.state() == QEventPoint::State::Pressed) {
3839 if (device->type() == QInputDevice::DeviceType::TouchPad) {
3840 // on touchpads, send all touch points to the same widget:
3841 // pick the first non-null target if possible
3842 target = QPointingDevicePrivate::get(q: device)->firstActiveTarget();
3843 }
3844
3845 if (target.isNull()) {
3846 // determine which widget this event will go to
3847 if (!window)
3848 window = QApplication::topLevelAt(pos: touchPoint.globalPosition().toPoint());
3849 if (!window)
3850 continue;
3851 target = window->childAt(p: window->mapFromGlobal(touchPoint.globalPosition().toPoint()));
3852 if (!target)
3853 target = window;
3854 }
3855
3856 bool usingClosestWidget = false;
3857 if (device->type() == QInputDevice::DeviceType::TouchScreen) {
3858 QWidget *closestWidget = d->findClosestTouchPointTarget(device, touchPoint);
3859 QWidget *widget = static_cast<QWidget *>(target.data());
3860 if (closestWidget
3861 && (widget->isAncestorOf(child: closestWidget) || closestWidget->isAncestorOf(child: widget))) {
3862 target = closestWidget;
3863 usingClosestWidget = true;
3864 }
3865 }
3866
3867 // on touch pads, implicitly grab all touch points
3868 // on touch screens, grab touch points that are redirected to the closest widget
3869 if (device->type() == QInputDevice::DeviceType::TouchPad || usingClosestWidget)
3870 QMutableEventPoint::setTarget(p&: touchPoint, arg: target);
3871 } else {
3872 target = QMutableEventPoint::target(p: touchPoint);
3873 if (!target)
3874 continue;
3875 }
3876 Q_ASSERT(!target.isNull());
3877
3878 QWidget *targetWidget = static_cast<QWidget *>(target.data());
3879
3880#ifdef Q_OS_MACOS
3881 // Single-touch events are normally not sent unless WA_TouchPadAcceptSingleTouchEvents is set.
3882 // In Qt 4 this check was in OS X-only code. That behavior is preserved here by the #ifdef.
3883 if (touchPoints.count() == 1
3884 && device->type() == QInputDevice::DeviceType::TouchPad
3885 && !targetWidget->testAttribute(Qt::WA_TouchPadAcceptSingleTouchEvents))
3886 continue;
3887#endif
3888
3889 StatesAndTouchPoints &maskAndPoints = widgetsNeedingEvents[targetWidget];
3890 maskAndPoints.first = QEventPoint::State(maskAndPoints.first | touchPoint.state());
3891 maskAndPoints.second.append(t: touchPoint);
3892 }
3893
3894 if (widgetsNeedingEvents.isEmpty())
3895 return false;
3896
3897 bool accepted = false;
3898 QHash<QWidget *, StatesAndTouchPoints>::ConstIterator it = widgetsNeedingEvents.constBegin();
3899 const QHash<QWidget *, StatesAndTouchPoints>::ConstIterator end = widgetsNeedingEvents.constEnd();
3900 for (; it != end; ++it) {
3901 const QPointer<QWidget> widget = it.key();
3902 if (!QApplicationPrivate::tryModalHelper(widget, rettop: nullptr))
3903 continue;
3904
3905 QEvent::Type eventType;
3906 switch (it.value().first) {
3907 case QEventPoint::State::Pressed:
3908 eventType = QEvent::TouchBegin;
3909 break;
3910 case QEventPoint::State::Released:
3911 eventType = QEvent::TouchEnd;
3912 break;
3913 case QEventPoint::State::Stationary:
3914 // don't send the event if nothing changed
3915 continue;
3916 default:
3917 eventType = QEvent::TouchUpdate;
3918 break;
3919 }
3920
3921 QMutableTouchEvent touchEvent(eventType, device, QGuiApplication::keyboardModifiers(),
3922 it.value().second);
3923 bool containsPress = updateTouchPointsForWidget(widget, touchEvent: &touchEvent);
3924 touchEvent.setTimestamp(te->timestamp());
3925 touchEvent.setTarget(widget);
3926
3927 if (containsPress)
3928 widget->setAttribute(Qt::WA_WState_AcceptedTouchBeginEvent);
3929
3930 switch (touchEvent.type()) {
3931 case QEvent::TouchBegin:
3932 {
3933 // if the TouchBegin handler recurses, we assume that means the event
3934 // has been implicitly accepted and continue to send touch events
3935 bool res = te->spontaneous() ? QApplication::sendSpontaneousEvent(receiver: widget, event: &touchEvent)
3936 : QApplication::sendEvent(receiver: widget, event: &touchEvent);
3937 if (res && touchEvent.isAccepted()) {
3938 accepted = true;
3939 if (!widget.isNull())
3940 widget->setAttribute(Qt::WA_WState_AcceptedTouchBeginEvent);
3941 }
3942 break;
3943 }
3944 default:
3945 if (widget->testAttribute(attribute: Qt::WA_WState_AcceptedTouchBeginEvent)
3946#ifndef QT_NO_GESTURES
3947 || QGestureManager::gesturePending(o: widget)
3948#endif
3949 ) {
3950 bool res = te->spontaneous() ? QApplication::sendSpontaneousEvent(receiver: widget, event: &touchEvent)
3951 : QApplication::sendEvent(receiver: widget, event: &touchEvent);
3952 if (res && touchEvent.isAccepted())
3953 accepted = true;
3954 // widget can be deleted on TouchEnd
3955 if (touchEvent.type() == QEvent::TouchEnd && !widget.isNull())
3956 widget->setAttribute(Qt::WA_WState_AcceptedTouchBeginEvent, on: false);
3957 }
3958 break;
3959 }
3960 }
3961 return accepted;
3962}
3963
3964void QApplicationPrivate::translateTouchCancel(const QPointingDevice *device, ulong timestamp)
3965{
3966 QMutableTouchEvent touchEvent(QEvent::TouchCancel, device, QGuiApplication::keyboardModifiers());
3967 touchEvent.setTimestamp(timestamp);
3968
3969 QSet<QWidget *> widgetsNeedingCancel;
3970 const QPointingDevicePrivate *devPriv = QPointingDevicePrivate::get(q: device);
3971 for (auto &epd : devPriv->activePoints.values()) {
3972 const auto &pt = epd.eventPoint;
3973 QObject *target = QMutableEventPoint::target(p: pt);
3974 if (target && target->isWidgetType())
3975 widgetsNeedingCancel.insert(value: static_cast<QWidget *>(target));
3976 }
3977 for (QSet<QWidget *>::const_iterator widIt = widgetsNeedingCancel.constBegin(),
3978 widItEnd = widgetsNeedingCancel.constEnd(); widIt != widItEnd; ++widIt) {
3979 QWidget *widget = *widIt;
3980 touchEvent.setTarget(widget);
3981 QApplication::sendSpontaneousEvent(receiver: widget, event: &touchEvent);
3982 }
3983}
3984
3985void QApplicationPrivate::handleThemeChanged()
3986{
3987 QGuiApplicationPrivate::handleThemeChanged();
3988
3989 qt_init_tooltip_palette();
3990}
3991
3992#if QT_CONFIG(draganddrop)
3993void QApplicationPrivate::notifyDragStarted(const QDrag *drag)
3994{
3995 QGuiApplicationPrivate::notifyDragStarted(drag);
3996 // QTBUG-26145
3997 // Prevent pickMouseReceiver() from using the widget where the drag was started after a drag operation...
3998 // QTBUG-56713
3999 // ...only if qt_button_down is not a QQuickWidget
4000 if (qt_button_down && !qt_button_down->inherits(classname: "QQuickWidget"))
4001 qt_button_down = nullptr;
4002}
4003#endif // QT_CONFIG(draganddrop)
4004
4005#ifndef QT_NO_GESTURES
4006QGestureManager* QGestureManager::instance(InstanceCreation ic)
4007{
4008 QApplicationPrivate *qAppPriv = QApplicationPrivate::instance();
4009 if (!qAppPriv)
4010 return nullptr;
4011 if (!qAppPriv->gestureManager && ic == ForceCreation)
4012 qAppPriv->gestureManager = new QGestureManager(qApp);
4013 return qAppPriv->gestureManager;
4014}
4015#endif // QT_NO_GESTURES
4016
4017QPixmap QApplicationPrivate::applyQIconStyleHelper(QIcon::Mode mode, const QPixmap& base) const
4018{
4019 QStyleOption opt(0);
4020 opt.palette = QGuiApplication::palette();
4021 return QApplication::style()->generatedIconPixmap(iconMode: mode, pixmap: base, opt: &opt);
4022}
4023
4024void *QApplication::resolveInterface(const char *name, int revision) const
4025{
4026 return QGuiApplication::resolveInterface(name, revision);
4027}
4028
4029QT_END_NAMESPACE
4030
4031#include "moc_qapplication.cpp"
4032

source code of qtbase/src/widgets/kernel/qapplication.cpp