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