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