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 auto it = widgetPalettes.constFind(w->metaObject()->className());
1134 const auto cend = widgetPalettes.constEnd();
1135 if (it != cend)
1136 return *it;
1137 for (it = widgetPalettes.constBegin(); it != cend; ++it) {
1138 if (w->inherits(it.key()))
1139 return it.value();
1140 }
1141 }
1142 return palette();
1143}
1144
1145/*!
1146 \overload
1147
1148 Returns the palette for widgets of the given \a className.
1149
1150 \sa setPalette(), QWidget::palette()
1151*/
1152QPalette QApplication::palette(const char *className)
1153{
1154 auto &widgetPalettes = QApplicationPrivate::widgetPalettes;
1155 if (className && !widgetPalettes.isEmpty()) {
1156 auto it = widgetPalettes.constFind(className);
1157 if (it != widgetPalettes.constEnd())
1158 return *it;
1159 }
1160
1161 return QGuiApplication::palette();
1162}
1163
1164/*!
1165 Changes the application palette to \a palette.
1166
1167 If \a className is passed, the change applies only to widgets that inherit
1168 \a className (as reported by QObject::inherits()). If \a className is left
1169 0, the change affects all widgets, thus overriding any previously set class
1170 specific palettes.
1171
1172 The palette may be changed according to the current GUI style in
1173 QStyle::polish().
1174
1175 \warning Do not use this function in conjunction with \l{Qt Style Sheets}.
1176 When using style sheets, the palette of a widget can be customized using
1177 the "color", "background-color", "selection-color",
1178 "selection-background-color" and "alternate-background-color".
1179
1180 \note Some styles do not use the palette for all drawing, for instance, if
1181 they make use of native theme engines. This is the case for the
1182 Windows Vista and \macos styles.
1183
1184 \sa QWidget::setPalette(), palette(), QStyle::polish()
1185*/
1186void QApplication::setPalette(const QPalette &palette, const char* className)
1187{
1188 if (className) {
1189 QPalette polishedPalette = palette;
1190 if (QApplicationPrivate::app_style) {
1191 auto originalResolveMask = palette.resolveMask();
1192 QApplicationPrivate::app_style->polish(polishedPalette);
1193 polishedPalette.setResolveMask(originalResolveMask);
1194 }
1195
1196 QApplicationPrivate::widgetPalettes.insert(className, polishedPalette);
1197 if (qApp)
1198 qApp->d_func()->handlePaletteChanged(className);
1199 } else {
1200 QGuiApplication::setPalette(palette);
1201 }
1202}
1203
1204void QApplicationPrivate::handlePaletteChanged(const char *className)
1205{
1206 if (!is_app_running || is_app_closing)
1207 return;
1208
1209 // Setting the global application palette is documented to
1210 // reset any previously set class specific widget palettes.
1211 if (!className && !widgetPalettes.isEmpty())
1212 widgetPalettes.clear();
1213
1214 QGuiApplicationPrivate::handlePaletteChanged(className);
1215
1216 QEvent event(QEvent::ApplicationPaletteChange);
1217 const QWidgetList widgets = QApplication::allWidgets();
1218 for (auto widget : widgets) {
1219 if (!widget->isWindow() && widget->inherits(className))
1220 QCoreApplication::sendEvent(widget, &event);
1221 }
1222
1223#if QT_CONFIG(graphicsview)
1224 for (auto scene : std::as_const(scene_list))
1225 QCoreApplication::sendEvent(scene, &event);
1226#endif
1227
1228 // Palette has been reset back to the default application palette,
1229 // so we need to reinitialize the widget palettes from the theme.
1230 if (!className && !testAttribute(Qt::AA_SetPalette))
1231 initializeWidgetPalettesFromTheme();
1232}
1233
1234void QApplicationPrivate::initializeWidgetPalettesFromTheme()
1235{
1236 QPlatformTheme *platformTheme = QGuiApplicationPrivate::platformTheme();
1237 if (!platformTheme)
1238 return;
1239
1240 widgetPalettes.clear();
1241
1242 struct ThemedWidget { const char *className; QPlatformTheme::Palette palette; };
1243
1244 static const ThemedWidget themedWidgets[] = {
1245 { "QToolButton", QPlatformTheme::ToolButtonPalette },
1246 { "QAbstractButton", QPlatformTheme::ButtonPalette },
1247 { "QCheckBox", QPlatformTheme::CheckBoxPalette },
1248 { "QRadioButton", QPlatformTheme::RadioButtonPalette },
1249 { "QHeaderView", QPlatformTheme::HeaderPalette },
1250 { "QAbstractItemView", QPlatformTheme::ItemViewPalette },
1251 { "QMessageBoxLabel", QPlatformTheme::MessageBoxLabelPalette },
1252 { "QTabBar", QPlatformTheme::TabBarPalette },
1253 { "QLabel", QPlatformTheme::LabelPalette },
1254 { "QGroupBox", QPlatformTheme::GroupBoxPalette },
1255 { "QMenu", QPlatformTheme::MenuPalette },
1256 { "QMenuBar", QPlatformTheme::MenuBarPalette },
1257 { "QTextEdit", QPlatformTheme::TextEditPalette },
1258 { "QTextControl", QPlatformTheme::TextEditPalette },
1259 { "QLineEdit", QPlatformTheme::TextLineEditPalette },
1260 };
1261
1262 for (const auto themedWidget : themedWidgets) {
1263 if (auto *palette = platformTheme->palette(themedWidget.palette))
1264 QApplication::setPalette(*palette, themedWidget.className);
1265 }
1266}
1267
1268/*!
1269 Returns the default application font.
1270
1271 \sa fontMetrics(), QWidget::font()
1272*/
1273QFont QApplication::font()
1274{
1275 return QGuiApplication::font();
1276}
1277
1278/*!
1279 \overload
1280
1281 Returns the default font for the \a widget. If a default font was not
1282 registered for the \a{widget}'s class, it returns the default font of
1283 its nearest registered superclass.
1284
1285 \sa fontMetrics(), setFont(), QWidget::setFont()
1286*/
1287
1288QFont QApplication::font(const QWidget *widget)
1289{
1290 typedef FontHash::const_iterator FontHashConstIt;
1291
1292 FontHash *hash = app_fonts();
1293
1294 if (widget && hash && hash->size()) {
1295#ifdef Q_OS_MAC
1296 // short circuit for small and mini controls
1297 if (widget->testAttribute(Qt::WA_MacSmallSize)) {
1298 return hash->value(QByteArrayLiteral("QSmallFont"));
1299 } else if (widget->testAttribute(Qt::WA_MacMiniSize)) {
1300 return hash->value(QByteArrayLiteral("QMiniFont"));
1301 }
1302#endif
1303 // Return the font for the nearest registered superclass
1304 const QMetaObject *metaObj = widget->metaObject();
1305 FontHashConstIt it = hash->constFind(metaObj->className());
1306 const FontHashConstIt cend = hash->constEnd();
1307 while (it == cend && metaObj != &QWidget::staticMetaObject) {
1308 metaObj = metaObj->superClass();
1309 it = hash->constFind(metaObj->className());
1310 }
1311 if (it != cend)
1312 return it.value();
1313 }
1314 return font();
1315}
1316
1317/*!
1318 \overload
1319
1320 Returns the font for widgets of the given \a className.
1321
1322 \sa setFont(), QWidget::font()
1323*/
1324QFont QApplication::font(const char *className)
1325{
1326 FontHash *hash = app_fonts();
1327 if (className && hash && hash->size()) {
1328 QHash<QByteArray, QFont>::ConstIterator it = hash->constFind(className);
1329 if (it != hash->constEnd())
1330 return *it;
1331 }
1332 return font();
1333}
1334
1335
1336/*!
1337 Changes the default application font to \a font. If \a className is passed,
1338 the change applies only to classes that inherit \a className (as reported
1339 by QObject::inherits()).
1340
1341 On application start-up, the default font depends on the window system. It
1342 can vary depending on both the window system version and the locale. This
1343 function lets you override the default font; but overriding may be a bad
1344 idea because, for example, some locales need extra large fonts to support
1345 their special characters.
1346
1347 \warning Do not use this function in conjunction with \l{Qt Style Sheets}.
1348 The font of an application can be customized using the "font" style sheet
1349 property. To set a bold font for all QPushButtons, set the application
1350 styleSheet() as "QPushButton { font: bold }"
1351
1352 \sa font(), fontMetrics(), QWidget::setFont()
1353*/
1354
1355void QApplication::setFont(const QFont &font, const char *className)
1356{
1357 FontHash *hash = app_fonts();
1358 if (!className) {
1359 QGuiApplication::setFont(font);
1360 if (hash && hash->size())
1361 hash->clear();
1362 } else if (hash) {
1363 hash->insert(className, font);
1364 }
1365 if (QApplicationPrivate::is_app_running && !QApplicationPrivate::is_app_closing) {
1366 QEvent e(QEvent::ApplicationFontChange);
1367 QWidgetList wids = QApplication::allWidgets();
1368 for (QWidgetList::ConstIterator it = wids.constBegin(), cend = wids.constEnd(); it != cend; ++it) {
1369 QWidget *w = *it;
1370 if (!w->isWindow() && w->inherits(className)) // matching class
1371 sendEvent(w, &e);
1372 }
1373
1374#if QT_CONFIG(graphicsview)
1375 // Send to all scenes as well.
1376 QList<QGraphicsScene *> &scenes = qApp->d_func()->scene_list;
1377 for (QList<QGraphicsScene *>::ConstIterator it = scenes.constBegin();
1378 it != scenes.constEnd(); ++it) {
1379 QCoreApplication::sendEvent(*it, &e);
1380 }
1381#endif // QT_CONFIG(graphicsview)
1382 }
1383 if (!className && (!QApplicationPrivate::sys_font || !font.isCopyOf(*QApplicationPrivate::sys_font))) {
1384 if (!QApplicationPrivate::set_font)
1385 QApplicationPrivate::set_font = new QFont(font);
1386 else
1387 *QApplicationPrivate::set_font = font;
1388 }
1389}
1390
1391/*! \internal
1392*/
1393void QApplicationPrivate::setSystemFont(const QFont &font)
1394{
1395 if (!sys_font)
1396 sys_font = new QFont(font);
1397 else
1398 *sys_font = font;
1399
1400 if (!QApplicationPrivate::set_font)
1401 QApplication::setFont(*sys_font);
1402}
1403
1404/*! \internal
1405*/
1406QString QApplicationPrivate::desktopStyleKey()
1407{
1408#if defined(QT_BUILD_INTERNAL)
1409 // Allow auto-tests to override the desktop style
1410 if (QString env = qEnvironmentVariable("QT_DESKTOP_STYLE_KEY"); !env.isNull())
1411 return env;
1412#endif
1413
1414 // The platform theme might return a style that is not available, find
1415 // first valid one.
1416 if (const QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme()) {
1417 const QStringList availableKeys = QStyleFactory::keys();
1418 const auto styles = theme->themeHint(QPlatformTheme::StyleNames).toStringList();
1419 for (const QString &style : styles) {
1420 if (availableKeys.contains(style, Qt::CaseInsensitive))
1421 return style;
1422 }
1423 }
1424 return QString();
1425}
1426
1427void QApplicationPrivate::notifyWindowIconChanged()
1428{
1429 QEvent ev(QEvent::ApplicationWindowIconChange);
1430 const QWidgetList list = QApplication::topLevelWidgets();
1431 QWindowList windowList = QGuiApplication::topLevelWindows();
1432
1433 // send to all top-level QWidgets
1434 for (auto *w : list) {
1435 windowList.removeOne(w->windowHandle());
1436 QCoreApplication::sendEvent(w, &ev);
1437 }
1438
1439 // in case there are any plain QWindows in this QApplication-using
1440 // application, also send the notification to them
1441 for (QWindow *w : std::as_const(windowList))
1442 QCoreApplication::sendEvent(w, &ev);
1443}
1444
1445/*!
1446 Returns a list of the top-level widgets (windows) in the application.
1447
1448 \note Some of the top-level widgets may be hidden, for example a tooltip if
1449 no tooltip is currently shown.
1450
1451 Example:
1452
1453 \snippet code/src_gui_kernel_qapplication.cpp 4
1454
1455 \sa allWidgets(), QWidget::isWindow(), QWidget::isHidden()
1456*/
1457QWidgetList QApplication::topLevelWidgets()
1458{
1459 QWidgetList list;
1460 if (QWidgetPrivate::allWidgets != nullptr) {
1461 const auto isTopLevelWidget = [] (const QWidget *w) {
1462 return w->isWindow();
1463 };
1464 std::copy_if(QWidgetPrivate::allWidgets->cbegin(), QWidgetPrivate::allWidgets->cend(),
1465 std::back_inserter(list), isTopLevelWidget);
1466 }
1467 return list;
1468}
1469
1470/*!
1471 Returns a list of all the widgets in the application.
1472
1473 The list is empty (QList::isEmpty()) if there are no widgets.
1474
1475 \note Some of the widgets may be hidden.
1476
1477 Example:
1478 \snippet code/src_gui_kernel_qapplication.cpp 5
1479
1480 \sa topLevelWidgets(), QWidget::isVisible()
1481*/
1482
1483QWidgetList QApplication::allWidgets()
1484{
1485 if (QWidgetPrivate::allWidgets)
1486 return QWidgetPrivate::allWidgets->values();
1487 return QWidgetList();
1488}
1489
1490/*!
1491 Returns the application widget that has the keyboard input focus,
1492 or \nullptr if no widget in this application has the focus.
1493
1494 \sa QWidget::setFocus(), QWidget::hasFocus(), activeWindow(), focusChanged()
1495*/
1496
1497QWidget *QApplication::focusWidget()
1498{
1499 return QApplicationPrivate::focus_widget;
1500}
1501
1502void QApplicationPrivate::setFocusWidget(QWidget *focus, Qt::FocusReason reason)
1503{
1504#if QT_CONFIG(graphicsview)
1505 if (focus && focus->window()->graphicsProxyWidget())
1506 return;
1507#endif
1508
1509 hidden_focus_widget = nullptr;
1510
1511 if (focus != focus_widget) {
1512 if (focus && focus->isHidden()) {
1513 hidden_focus_widget = focus;
1514 return;
1515 }
1516
1517 if (focus) {
1518 if ((reason == Qt::BacktabFocusReason || reason == Qt::TabFocusReason)
1519 && qt_in_tab_key_event)
1520 focus->window()->setAttribute(Qt::WA_KeyboardFocusChange);
1521 else if (reason == Qt::ShortcutFocusReason) {
1522 focus->window()->setAttribute(Qt::WA_KeyboardFocusChange);
1523 } else {
1524 focus->window()->setAttribute(Qt::WA_KeyboardFocusChange, false);
1525 }
1526 }
1527 QWidget *prev = focus_widget;
1528 focus_widget = focus;
1529
1530 if (focus_widget)
1531 focus_widget->d_func()->setFocus_sys();
1532
1533 if (reason != Qt::NoFocusReason) {
1534
1535 //send events
1536 if (prev) {
1537#ifdef QT_KEYPAD_NAVIGATION
1538 if (QApplicationPrivate::keyboardNavigationEnabled()) {
1539 if (prev->hasEditFocus() && reason != Qt::PopupFocusReason)
1540 prev->setEditFocus(false);
1541 }
1542#endif
1543 QFocusEvent out(QEvent::FocusOut, reason);
1544 QPointer<QWidget> that = prev;
1545 QCoreApplication::sendEvent(prev, &out);
1546 if (that)
1547 QCoreApplication::sendEvent(that->style(), &out);
1548 }
1549 if (focus && QApplicationPrivate::focus_widget == focus) {
1550 QFocusEvent in(QEvent::FocusIn, reason);
1551 QPointer<QWidget> that = focus;
1552 QCoreApplication::sendEvent(focus, &in);
1553 if (that)
1554 QCoreApplication::sendEvent(that->style(), &in);
1555 }
1556 emit qApp->focusChanged(prev, focus_widget);
1557 }
1558 }
1559}
1560
1561
1562/*!
1563 Returns the application top-level window that has the keyboard input focus,
1564 or \nullptr if no application window has the focus. There might be an
1565 activeWindow() even if there is no focusWidget(), for example if no widget
1566 in that window accepts key events.
1567
1568 \sa QWidget::setFocus(), QWidget::hasFocus(), focusWidget()
1569*/
1570
1571QWidget *QApplication::activeWindow()
1572{
1573 return QApplicationPrivate::active_window;
1574}
1575
1576/*!
1577 \fn QFontMetrics QApplication::fontMetrics()
1578 \deprecated [6.0] Use QFontMetricsF(qApp->font()) instead.
1579
1580 Returns display (screen) font metrics for the application font. For more
1581 information about the difference between \l QFontMetrics and \l QFontMetricsF,
1582 see the detailed description of \l QFontMetrics.
1583
1584 \sa font(), setFont(), QWidget::fontMetrics(), QPainter::fontMetrics()
1585*/
1586
1587#if QT_DEPRECATED_SINCE(6,0)
1588QFontMetrics QApplication::fontMetrics()
1589{
1590 return QFontMetrics(qApp->font());
1591}
1592#endif
1593
1594bool QApplicationPrivate::tryCloseAllWidgetWindows(QWindowList *processedWindows)
1595{
1596 Q_ASSERT(processedWindows);
1597 while (QWidget *w = QApplication::activeModalWidget()) {
1598 if (!w->isVisible() || w->data->is_closing)
1599 break;
1600 QWindow *window = w->windowHandle();
1601 if (!window->close()) // Qt::WA_DeleteOnClose may cause deletion.
1602 return false;
1603 if (window)
1604 processedWindows->append(window);
1605 }
1606
1607retry:
1608 const QWidgetList list = QApplication::topLevelWidgets();
1609 for (auto *w : list) {
1610 if (w->isVisible() && !w->testAttribute(Qt::WA_DontShowOnScreen) && !w->data->is_closing) {
1611 QWindow *window = w->windowHandle();
1612 if (!window->close()) // Qt::WA_DeleteOnClose may cause deletion.
1613 return false;
1614 if (window)
1615 processedWindows->append(window);
1616 goto retry;
1617 }
1618 }
1619 return true;
1620}
1621
1622/*!
1623 Closes all top-level windows.
1624
1625 This function is particularly useful for applications with many top-level
1626 windows.
1627
1628 The windows are closed in random order, until one window does not accept
1629 the close event. The application quits when the last window was successfully
1630 closed, unless \l quitOnLastWindowClosed is set to false. To trigger application
1631 termination from e.g. a menu, use QCoreApplication::quit() instead of this
1632 function.
1633
1634 \sa quitOnLastWindowClosed, lastWindowClosed(), QWidget::close(),
1635 QWidget::closeEvent(), lastWindowClosed(), QCoreApplication::quit(),
1636 topLevelWidgets(), QWidget::isWindow()
1637*/
1638void QApplication::closeAllWindows()
1639{
1640 QWindowList processedWindows;
1641 QApplicationPrivate::tryCloseAllWidgetWindows(&processedWindows);
1642}
1643
1644/*!
1645 Displays a simple message box about Qt. The message includes the version
1646 number of Qt being used by the application.
1647
1648 This is useful for inclusion in the \uicontrol Help menu of an application, as
1649 shown in the \l{mainwindows/menus}{Menus} example.
1650
1651 This function is a convenience slot for QMessageBox::aboutQt().
1652*/
1653void QApplication::aboutQt()
1654{
1655#if QT_CONFIG(messagebox)
1656 QMessageBox::aboutQt(activeWindow());
1657#endif // QT_CONFIG(messagebox)
1658}
1659
1660/*!
1661 \since 4.1
1662 \fn void QApplication::focusChanged(QWidget *old, QWidget *now)
1663
1664 This signal is emitted when the widget that has keyboard focus changed from
1665 \a old to \a now, i.e., because the user pressed the tab-key, clicked into
1666 a widget or changed the active window. Both \a old and \a now can be \nullptr.
1667
1668
1669 The signal is emitted after both widget have been notified about the change
1670 through QFocusEvent.
1671
1672 \sa QWidget::setFocus(), QWidget::clearFocus(), Qt::FocusReason
1673*/
1674
1675/*!\reimp
1676
1677*/
1678bool QApplication::event(QEvent *e)
1679{
1680 Q_D(QApplication);
1681 switch (e->type()) {
1682 case QEvent::Quit:
1683 // FIXME: This logic first tries to close all windows, and then
1684 // checks whether it was successful, but the conditions used in
1685 // closeAllWindows() differ from the verification logic below.
1686 // We should build on the logic in tryCloseAllWidgetWindows().
1687 closeAllWindows();
1688 for (auto *w : topLevelWidgets()) {
1689 if (w->data->is_closing)
1690 continue;
1691 if (w->isVisible() && !(w->windowType() == Qt::Popup) &&
1692 (!(w->windowType() == Qt::Dialog) || !w->parentWidget()) && !w->testAttribute(Qt::WA_DontShowOnScreen)) {
1693 e->ignore();
1694 return true;
1695 }
1696 }
1697 // Explicitly call QCoreApplication instead of QGuiApplication so that
1698 // we don't let QGuiApplication close any windows we skipped earlier in
1699 // closeAllWindows(). FIXME: Unify all this close magic through closeAllWindows.
1700 return QCoreApplication::event(e);
1701#ifndef Q_OS_WIN
1702 case QEvent::LocaleChange: {
1703 // on Windows the event propagation is taken care by the
1704 // WM_SETTINGCHANGE event handler.
1705 const QWidgetList list = topLevelWidgets();
1706 for (auto *w : list) {
1707 if (!w->testAttribute(Qt::WA_SetLocale))
1708 w->d_func()->setLocale_helper(QLocale(), true);
1709 }
1710 break;
1711 }
1712#endif
1713 case QEvent::Timer: {
1714 QTimerEvent *te = static_cast<QTimerEvent*>(e);
1715 Q_ASSERT(te != nullptr);
1716 if (te->timerId() == d->toolTipWakeUp.timerId()) {
1717 d->toolTipWakeUp.stop();
1718 if (d->toolTipWidget) {
1719 QWidget *w = d->toolTipWidget->window();
1720 // show tooltip if WA_AlwaysShowToolTips is set, or if
1721 // any ancestor of d->toolTipWidget is the active
1722 // window
1723 bool showToolTip = w->testAttribute(Qt::WA_AlwaysShowToolTips);
1724 while (w && !showToolTip) {
1725 showToolTip = w->isActiveWindow();
1726 w = w->parentWidget();
1727 w = w ? w->window() : nullptr;
1728 }
1729 if (showToolTip) {
1730 QHelpEvent e(QEvent::ToolTip, d->toolTipPos, d->toolTipGlobalPos);
1731 QCoreApplication::sendEvent(d->toolTipWidget, &e);
1732 if (e.isAccepted()) {
1733 QStyle *s = d->toolTipWidget->style();
1734 int sleepDelay = s->styleHint(QStyle::SH_ToolTip_FallAsleepDelay, nullptr, d->toolTipWidget, nullptr);
1735 d->toolTipFallAsleep.start(sleepDelay, this);
1736 }
1737 }
1738 }
1739 } else if (te->timerId() == d->toolTipFallAsleep.timerId()) {
1740 d->toolTipFallAsleep.stop();
1741 }
1742 break;
1743 }
1744#if QT_CONFIG(whatsthis)
1745 case QEvent::EnterWhatsThisMode:
1746 QWhatsThis::enterWhatsThisMode();
1747 return true;
1748#endif
1749 case QEvent::LanguageChange:
1750 case QEvent::ApplicationFontChange:
1751 case QEvent::ApplicationPaletteChange: {
1752 // QGuiApplication::event does not account for the cases where
1753 // there is a top level widget without a window handle. So they
1754 // need to have the event posted here
1755 const QWidgetList list = topLevelWidgets();
1756 for (auto *w : list) {
1757 if (!w->windowHandle())
1758 postEvent(w, new QEvent(e->type()));
1759 }
1760 break;
1761 }
1762 default:
1763 break;
1764 }
1765
1766 return QGuiApplication::event(e);
1767}
1768
1769// ### FIXME: topLevelWindows does not contain QWidgets without a parent
1770// until QWidgetPrivate::create is called. So we have to override the
1771// QGuiApplication::notifyLayoutDirectionChange
1772// to do the right thing.
1773void QApplicationPrivate::notifyLayoutDirectionChange()
1774{
1775 const QWidgetList list = QApplication::topLevelWidgets();
1776 QWindowList windowList = QGuiApplication::topLevelWindows();
1777
1778 // send to all top-level QWidgets
1779 for (auto *w : list) {
1780 windowList.removeAll(w->windowHandle());
1781 QEvent ev(QEvent::ApplicationLayoutDirectionChange);
1782 QCoreApplication::sendEvent(w, &ev);
1783 }
1784
1785 // in case there are any plain QWindows in this QApplication-using
1786 // application, also send the notification to them
1787 for (QWindow *w: std::as_const(windowList)) {
1788 QEvent ev(QEvent::ApplicationLayoutDirectionChange);
1789 QCoreApplication::sendEvent(w, &ev);
1790 }
1791}
1792
1793/*!
1794 \fn void QApplication::setActiveWindow(QWidget* active)
1795 \deprecated [6.5] Use QWidget::activateWindow() instead.
1796
1797 Sets the active window to the \a active widget in response to a system
1798 event. The function is called from the platform specific event handlers.
1799
1800 \warning This function does \e not set the keyboard focus to the active
1801 widget. Call QWidget::activateWindow() instead.
1802
1803 It sets the activeWindow() and focusWidget() attributes and sends proper
1804 \l{QEvent::WindowActivate}{WindowActivate}/\l{QEvent::WindowDeactivate}
1805 {WindowDeactivate} and \l{QEvent::FocusIn}{FocusIn}/\l{QEvent::FocusOut}
1806 {FocusOut} events to all appropriate widgets. The window will then be
1807 painted in active state (e.g. cursors in line edits will blink), and it
1808 will have tool tips enabled.
1809
1810 \sa activeWindow(), QWidget::activateWindow()
1811*/
1812#if QT_DEPRECATED_SINCE(6,5)
1813void QApplication::setActiveWindow(QWidget* act)
1814{
1815 QApplicationPrivate::setActiveWindow(act);
1816}
1817#endif
1818
1819void QApplicationPrivate::setActiveWindow(QWidget* act)
1820{
1821 QWidget* window = act?act->window():nullptr;
1822
1823 if (QApplicationPrivate::active_window == window)
1824 return;
1825
1826#if QT_CONFIG(graphicsview)
1827 if (window && window->graphicsProxyWidget()) {
1828 // Activate the proxy's view->viewport() ?
1829 return;
1830 }
1831#endif
1832
1833 QWidgetList toBeActivated;
1834 QWidgetList toBeDeactivated;
1835
1836 if (QApplicationPrivate::active_window) {
1837 if (QApplication::style()->styleHint(QStyle::SH_Widget_ShareActivation, nullptr, QApplicationPrivate::active_window)) {
1838 const QWidgetList list = QApplication::topLevelWidgets();
1839 for (auto *w : list) {
1840 if (w->isVisible() && w->isActiveWindow())
1841 toBeDeactivated.append(w);
1842 }
1843 } else {
1844 toBeDeactivated.append(QApplicationPrivate::active_window);
1845 }
1846 }
1847
1848 if (QApplicationPrivate::focus_widget) {
1849 if (QApplicationPrivate::focus_widget->testAttribute(Qt::WA_InputMethodEnabled))
1850 QGuiApplication::inputMethod()->commit();
1851
1852 QFocusEvent focusAboutToChange(QEvent::FocusAboutToChange, Qt::ActiveWindowFocusReason);
1853 QCoreApplication::sendEvent(QApplicationPrivate::focus_widget, &focusAboutToChange);
1854 }
1855
1856 QApplicationPrivate::active_window = window;
1857
1858 if (QApplicationPrivate::active_window) {
1859 if (QApplication::style()->styleHint(QStyle::SH_Widget_ShareActivation, nullptr, QApplicationPrivate::active_window)) {
1860 const QWidgetList list = QApplication::topLevelWidgets();
1861 for (auto *w : list) {
1862 if (w->isVisible() && w->isActiveWindow())
1863 toBeActivated.append(w);
1864 }
1865 } else {
1866 toBeActivated.append(QApplicationPrivate::active_window);
1867 }
1868
1869 }
1870
1871 // first the activation/deactivation events
1872 QEvent activationChange(QEvent::ActivationChange);
1873 QEvent windowActivate(QEvent::WindowActivate);
1874 QEvent windowDeactivate(QEvent::WindowDeactivate);
1875
1876 for (QWidget *w : std::as_const(toBeActivated)) {
1877 QApplication::sendSpontaneousEvent(w, &windowActivate);
1878 QApplication::sendSpontaneousEvent(w, &activationChange);
1879 }
1880
1881 for (QWidget *w : std::as_const(toBeDeactivated)) {
1882 QApplication::sendSpontaneousEvent(w, &windowDeactivate);
1883 QApplication::sendSpontaneousEvent(w, &activationChange);
1884 }
1885
1886 if (!inPopupMode()) {
1887 // then focus events
1888 if (!QApplicationPrivate::active_window && QApplicationPrivate::focus_widget) {
1889 QApplicationPrivate::setFocusWidget(nullptr, Qt::ActiveWindowFocusReason);
1890 } else if (QApplicationPrivate::active_window) {
1891 QWidget *w = QApplicationPrivate::active_window->focusWidget();
1892 if (w && w->isVisible() /*&& w->focusPolicy() != QWidget::NoFocus*/)
1893 w->setFocus(Qt::ActiveWindowFocusReason);
1894 else {
1895 w = QApplicationPrivate::focusNextPrevChild_helper(QApplicationPrivate::active_window, true);
1896 if (w) {
1897 w->setFocus(Qt::ActiveWindowFocusReason);
1898 } else {
1899 w = QApplicationPrivate::focus_widget;
1900 if (!w && QApplicationPrivate::active_window->focusPolicy() != Qt::NoFocus) {
1901 QApplicationPrivate::active_window->setFocus(Qt::ActiveWindowFocusReason);
1902 } else if (!QApplicationPrivate::active_window->isAncestorOf(w)) {
1903 // If the focus widget is not in the activate_window, clear the focus
1904 QApplicationPrivate::setFocusWidget(nullptr, Qt::ActiveWindowFocusReason);
1905 }
1906 }
1907 }
1908 }
1909 }
1910}
1911
1913{
1914 // QTBUG-32177, wnd might be a QQuickView embedded via window container.
1915 while (wnd && !wnd->isTopLevel()) {
1916 QWindow *parent = wnd->parent();
1917 if (!parent)
1918 break;
1919
1920 // Don't end up in windows not belonging to this application
1921 if (parent->handle() && parent->handle()->isForeignWindow())
1922 break;
1923
1924 wnd = wnd->parent();
1925 }
1926 if (wnd) {
1927 const auto tlws = QApplication::topLevelWidgets();
1928 for (QWidget *tlw : tlws) {
1929 if (tlw->windowHandle() == wnd)
1930 return tlw;
1931 }
1932 }
1933 return nullptr;
1934}
1935
1936void QApplicationPrivate::notifyActiveWindowChange(QWindow *previous)
1937{
1938#ifndef Q_OS_MACOS
1939 // Some delayed focus event to ignore, unless we are on cocoa where
1940 // popups can be opened via right-click on inactive applications
1941 if (inPopupMode())
1942 return;
1943#endif
1944 QWindow *focusWindow = QGuiApplicationPrivate::focus_window;
1945 QWidget *focusWidget = qt_tlw_for_window(focusWindow);
1946 QApplicationPrivate::setActiveWindow(focusWidget);
1947 // QTBUG-37126, Active X controls may set the focus on native child widgets.
1948 if (focusWindow && focusWidget && focusWindow != focusWidget->windowHandle()) {
1949 if (QWidgetWindow *widgetWindow = qobject_cast<QWidgetWindow *>(focusWindow))
1950 if (QWidget *widget = widgetWindow->widget())
1951 if (widget->inherits("QAxHostWidget"))
1952 widget->setFocus(Qt::ActiveWindowFocusReason);
1953 }
1954
1955 // QApplication::setActiveWindow() will deliver window activation events for
1956 // QWidgetWindows. But for other subclasses of QWindow (like QQuickWindow), we
1957 // need to send them explicitly, like we do from the base class implementation.
1958 if (previous && !qobject_cast<QWidgetWindow *>(previous)) {
1959 QEvent de(QEvent::WindowDeactivate);
1960 QCoreApplication::sendEvent(previous, &de);
1961 }
1962
1963 if (focusWindow && !qobject_cast<QWidgetWindow *>(focusWindow)) {
1964 QEvent ae(QEvent::WindowActivate);
1965 QCoreApplication::sendEvent(focusWindow, &ae);
1966 }
1967
1968 // don't call base class to avoid double delivery of WindowActivate/Deactivate events
1969}
1970
1971/*!internal
1972 * Helper function that returns the new focus widget, but does not set the focus reason.
1973 * Returns \nullptr if a new focus widget could not be found.
1974 * Shared with QGraphicsProxyWidgetPrivate::findFocusChild()
1975*/
1976QWidget *QApplicationPrivate::focusNextPrevChild_helper(QWidget *toplevel, bool next,
1977 bool *wrappingOccurred)
1978{
1979 uint focus_flag = qt_tab_all_widgets() ? Qt::TabFocus : Qt::StrongFocus;
1980
1981 QWidget *f = toplevel->focusWidget();
1982 if (!f)
1983 f = toplevel;
1984
1985 QWidget *w = f;
1986 QWidget *test = f->nextInFocusChain();
1987 bool seenWindow = false;
1988 bool focusWidgetAfterWindow = false;
1989 while (test && test != f) {
1990 if (test->isWindow())
1991 seenWindow = true;
1992
1993 // If the next focus widget has a focus proxy, we need to check to ensure
1994 // that the proxy is in the correct parent-child direction (according to
1995 // \a next). This is to ensure that we can tab in and out of compound widgets
1996 // without getting stuck in a tab-loop between parent and child.
1997 QWidget *focusProxy = test->d_func()->deepestFocusProxy();
1998 auto effectiveFocusPolicy = [](QWidget *widget) {
1999 return widget->isEnabled() ? widget->focusPolicy() : Qt::NoFocus;
2000 };
2001 const bool canTakeFocus = (effectiveFocusPolicy(focusProxy ? focusProxy : test)
2002 & focus_flag) == focus_flag;
2003 const bool composites = focusProxy ? (next ? focusProxy->isAncestorOf(test)
2004 : test->isAncestorOf(focusProxy))
2005 : false;
2006 if (canTakeFocus && !composites
2007 && test->isVisibleTo(toplevel) && test->isEnabled()
2008 && !(w->windowType() == Qt::SubWindow && !w->isAncestorOf(test))
2009 && (toplevel->windowType() != Qt::SubWindow || toplevel->isAncestorOf(test))
2010 && f != focusProxy) {
2011 w = test;
2012 if (seenWindow)
2013 focusWidgetAfterWindow = true;
2014 if (next)
2015 break;
2016 }
2017 test = test->nextInFocusChain();
2018 }
2019
2020 if (wrappingOccurred != nullptr)
2021 *wrappingOccurred = next ? focusWidgetAfterWindow : !focusWidgetAfterWindow;
2022
2023 if (w == f) {
2024 if (qt_in_tab_key_event) {
2025 w->window()->setAttribute(Qt::WA_KeyboardFocusChange);
2026 w->update();
2027 }
2028 return nullptr;
2029 }
2030 return w;
2031}
2032
2033/*!
2034 \fn void QApplicationPrivate::dispatchEnterLeave(QWidget* enter, QWidget* leave, const QPointF &globalPosF)
2035 \internal
2036
2037 Creates the proper Enter/Leave event when widget \a enter is entered and
2038 widget \a leave is left.
2039 */
2040void QApplicationPrivate::dispatchEnterLeave(QWidget* enter, QWidget* leave, const QPointF &globalPosF)
2041{
2042 if ((!enter && !leave) || (enter == leave))
2043 return;
2044
2045 QWidgetList leaveList;
2046 QWidgetList enterList;
2047
2048 bool sameWindow = leave && enter && leave->window() == enter->window();
2049 if (leave && !sameWindow) {
2050 auto *w = leave;
2051 do {
2052 leaveList.append(w);
2053 } while (!w->isWindow() && (w = w->parentWidget()));
2054 }
2055 if (enter && !sameWindow) {
2056 auto *w = enter;
2057 do {
2058 enterList.append(w);
2059 } while (!w->isWindow() && (w = w->parentWidget()));
2060 }
2061 if (sameWindow) {
2062 int enterDepth = 0;
2063 int leaveDepth = 0;
2064 auto *e = enter;
2065 while (!e->isWindow() && (e = e->parentWidget()))
2066 enterDepth++;
2067 auto *l = leave;
2068 while (!l->isWindow() && (l = l->parentWidget()))
2069 leaveDepth++;
2070 QWidget* wenter = enter;
2071 QWidget* wleave = leave;
2072 while (enterDepth > leaveDepth) {
2073 wenter = wenter->parentWidget();
2074 enterDepth--;
2075 }
2076 while (leaveDepth > enterDepth) {
2077 wleave = wleave->parentWidget();
2078 leaveDepth--;
2079 }
2080 while (!wenter->isWindow() && wenter != wleave) {
2081 wenter = wenter->parentWidget();
2082 wleave = wleave->parentWidget();
2083 }
2084
2085 for (auto *w = leave; w != wleave; w = w->parentWidget())
2086 leaveList.append(w);
2087
2088 for (auto *w = enter; w != wenter; w = w->parentWidget())
2089 enterList.append(w);
2090 }
2091
2092 QEvent leaveEvent(QEvent::Leave);
2093 for (QWidget *w : std::as_const(leaveList)) {
2094 if (!QApplication::activeModalWidget() || QApplicationPrivate::tryModalHelper(w, nullptr)) {
2095 QCoreApplication::sendEvent(w, &leaveEvent);
2096 if (w->testAttribute(Qt::WA_Hover) &&
2097 (!QApplication::activePopupWidget() || QApplication::activePopupWidget() == w->window())) {
2098 Q_ASSERT(instance());
2099 QHoverEvent he(QEvent::HoverLeave, QPointF(-1, -1), globalPosF, w->mapFromGlobal(globalPosF),
2100 QGuiApplication::keyboardModifiers());
2101 qApp->d_func()->notify_helper(w, &he);
2102 }
2103 }
2104 }
2105 if (!enterList.isEmpty()) {
2106 // Guard against QGuiApplicationPrivate::lastCursorPosition initialized to qInf(), qInf().
2107 const QPointF globalPos = qIsInf(globalPosF.x())
2109 : globalPosF;
2110 const QPointF windowPos = std::as_const(enterList).back()->window()->mapFromGlobal(globalPos);
2111 for (auto it = enterList.crbegin(), end = enterList.crend(); it != end; ++it) {
2112 auto *w = *it;
2113 if (!QApplication::activeModalWidget() || QApplicationPrivate::tryModalHelper(w, nullptr)) {
2114 const QPointF localPos = w->mapFromGlobal(globalPos);
2115 QEnterEvent enterEvent(localPos, windowPos, globalPos);
2116 QCoreApplication::sendEvent(w, &enterEvent);
2117 if (w->testAttribute(Qt::WA_Hover) &&
2118 (!QApplication::activePopupWidget() || QApplication::activePopupWidget() == w->window())) {
2119 QHoverEvent he(QEvent::HoverEnter, windowPos, QPointF(-1, -1), globalPos,
2120 QGuiApplication::keyboardModifiers());
2121 QMutableEventPoint::setPosition(he.point(0), localPos);
2122 qApp->d_func()->notify_helper(w, &he);
2123 }
2124 }
2125 }
2126 }
2127
2128#ifndef QT_NO_CURSOR
2129 // Update cursor for alien/graphics widgets.
2130
2131 const bool enterOnAlien = (enter && (isAlien(enter) || enter->testAttribute(Qt::WA_DontShowOnScreen)));
2132 // Whenever we leave an alien widget on X11/QPA, we need to reset its nativeParentWidget()'s cursor.
2133 // This is not required on Windows as the cursor is reset on every single mouse move.
2134 QWidget *parentOfLeavingCursor = nullptr;
2135 for (QWidget *w : std::as_const(leaveList)) {
2136 if (!isAlien(w))
2137 break;
2138 if (w->testAttribute(Qt::WA_SetCursor)) {
2139 QWidget *parent = w->parentWidget();
2140 while (parent && parent->d_func()->data.in_destructor)
2141 parent = parent->parentWidget();
2142 parentOfLeavingCursor = parent;
2143 //continue looping, we need to find the downest alien widget with a cursor.
2144 // (downest on the screen)
2145 }
2146 }
2147 //check that we will not call qt_x11_enforce_cursor twice with the same native widget
2148 if (parentOfLeavingCursor && (!enterOnAlien
2149 || parentOfLeavingCursor->effectiveWinId() != enter->effectiveWinId())) {
2150#if QT_CONFIG(graphicsview)
2151 if (!parentOfLeavingCursor->window()->graphicsProxyWidget())
2152#endif
2153 {
2154 qt_qpa_set_cursor(parentOfLeavingCursor, true);
2155 }
2156 }
2157 if (enterOnAlien) {
2158 QWidget *cursorWidget = enter;
2159 while (!cursorWidget->isWindow() && !cursorWidget->isEnabled())
2160 cursorWidget = cursorWidget->parentWidget();
2161
2162 if (!cursorWidget)
2163 return;
2164
2165#if QT_CONFIG(graphicsview)
2166 if (cursorWidget->window()->graphicsProxyWidget()) {
2167 QWidgetPrivate::nearestGraphicsProxyWidget(cursorWidget)->setCursor(cursorWidget->cursor());
2168 } else
2169#endif
2170 {
2171 qt_qpa_set_cursor(cursorWidget, true);
2172 }
2173 }
2174#endif
2175}
2176
2177/* exported for the benefit of testing tools */
2178Q_WIDGETS_EXPORT bool qt_tryModalHelper(QWidget *widget, QWidget **rettop)
2179{
2180 return QApplicationPrivate::tryModalHelper(widget, rettop);
2181}
2182
2183/*! \internal
2184 Returns \c true if \a widget is blocked by a modal window.
2185 */
2186bool QApplicationPrivate::isBlockedByModal(QWidget *widget)
2187{
2188 widget = widget->window();
2189 QWindow *window = widget->windowHandle();
2190 return window && self->isWindowBlocked(window);
2191}
2192
2193Qt::WindowModality QApplicationPrivate::defaultModality() const
2194{
2195 return Qt::ApplicationModal;
2196}
2197
2198bool QApplicationPrivate::windowNeverBlocked(QWindow *window) const
2199{
2200 QWidget *popupWidget = QApplication::activePopupWidget();
2201 QWindow *popupWindow = popupWidget ? popupWidget->windowHandle() : nullptr;
2202 return popupWindow == window || (!popupWindow && QWindowPrivate::get(window)->isPopup());
2203}
2204
2205/*!\internal
2206
2207 Called from qapplication_\e{platform}.cpp, returns \c true
2208 if the widget should accept the event.
2209 */
2210bool QApplicationPrivate::tryModalHelper(QWidget *widget, QWidget **rettop)
2211{
2212 QWidget *top = QApplication::activeModalWidget();
2213 if (rettop)
2214 *rettop = top;
2215
2216 // the active popup widget always gets the input event
2217 if (QApplication::activePopupWidget())
2218 return true;
2219
2220 return !isBlockedByModal(widget->window());
2221}
2222
2223bool qt_try_modal(QWidget *widget, QEvent::Type type)
2224{
2225 QWidget * top = nullptr;
2226
2227 if (QApplicationPrivate::tryModalHelper(widget, &top))
2228 return true;
2229
2230 bool block_event = false;
2231
2232 switch (type) {
2233 case QEvent::MouseButtonPress: // disallow mouse/key events
2234 case QEvent::MouseButtonRelease:
2235 case QEvent::MouseMove:
2236 case QEvent::KeyPress:
2237 case QEvent::KeyRelease:
2238 block_event = true;
2239 break;
2240 default:
2241 break;
2242 }
2243
2244 if (block_event && top && top->parentWidget() == nullptr)
2245 top->raise();
2246
2247 return !block_event;
2248}
2249
2250bool QApplicationPrivate::modalState()
2251{
2252 return !self->modalWindowList.isEmpty();
2253}
2254
2255/*
2256 \internal
2257*/
2258QWidget *QApplicationPrivate::pickMouseReceiver(QWidget *candidate, const QPointF &windowPos,
2259 QPointF *pos, QEvent::Type type,
2260 Qt::MouseButtons buttons, QWidget *buttonDown,
2261 QWidget *alienWidget)
2262{
2263 Q_ASSERT(candidate);
2264
2265 QWidget *mouseGrabber = QWidget::mouseGrabber();
2266 if (((type == QEvent::MouseMove && buttons) || (type == QEvent::MouseButtonRelease))
2267 && !buttonDown && !mouseGrabber) {
2268 return nullptr;
2269 }
2270
2271 if (alienWidget && alienWidget->internalWinId())
2272 alienWidget = nullptr;
2273
2274 QWidget *receiver = candidate;
2275
2276 if (!mouseGrabber)
2277 mouseGrabber = (buttonDown && !isBlockedByModal(buttonDown)) ? buttonDown : alienWidget;
2278
2279 if (mouseGrabber && mouseGrabber != candidate) {
2280 receiver = mouseGrabber;
2281 *pos = receiver->mapFromGlobal(candidate->mapToGlobal(windowPos));
2282 }
2283
2284 return receiver;
2285
2286}
2287
2288/*
2289 \internal
2290*/
2291bool QApplicationPrivate::sendMouseEvent(QWidget *receiver, QMouseEvent *event,
2292 QWidget *alienWidget, QWidget *nativeWidget,
2293 QWidget **buttonDown, QPointer<QWidget> &lastMouseReceiver,
2294 bool spontaneous, bool onlyDispatchEnterLeave)
2295{
2296 Q_ASSERT(receiver);
2297 Q_ASSERT(event);
2298 Q_ASSERT(nativeWidget);
2299 Q_ASSERT(buttonDown);
2300
2301 if (alienWidget && !isAlien(alienWidget))
2302 alienWidget = nullptr;
2303
2304 QPointer<QWidget> receiverGuard = receiver;
2305 QPointer<QWidget> nativeGuard = nativeWidget;
2306 QPointer<QWidget> alienGuard = alienWidget;
2307 QPointer<QWidget> activePopupWidget = QApplication::activePopupWidget();
2308
2309 const bool graphicsWidget = nativeWidget->testAttribute(Qt::WA_DontShowOnScreen);
2310
2311 bool widgetUnderMouse = QRectF(receiver->rect()).contains(event->position());
2312
2313 // Clear the obsolete leaveAfterRelease value, if mouse button has been released but
2314 // leaveAfterRelease has not been updated.
2315 // This happens e.g. when modal dialog or popup is shown as a response to button click.
2316 if (leaveAfterRelease && !*buttonDown && !event->buttons())
2317 leaveAfterRelease = nullptr;
2318
2319 if (*buttonDown) {
2320 if (!graphicsWidget) {
2321 // Register the widget that shall receive a leave event
2322 // after the last button is released.
2323 if ((alienWidget || !receiver->internalWinId()) && !leaveAfterRelease && !QWidget::mouseGrabber())
2324 leaveAfterRelease = *buttonDown;
2325 if (event->type() == QEvent::MouseButtonRelease && !event->buttons())
2326 *buttonDown = nullptr;
2327 }
2328 } else if (lastMouseReceiver && widgetUnderMouse) {
2329 // Dispatch enter/leave if we move:
2330 // 1) from an alien widget to another alien widget or
2331 // from a native widget to an alien widget (first OR case)
2332 // 2) from an alien widget to a native widget (second OR case)
2333 if ((alienWidget && alienWidget != lastMouseReceiver)
2334 || (isAlien(lastMouseReceiver) && !alienWidget)) {
2335 if (activePopupWidget) {
2336 if (!QWidget::mouseGrabber())
2337 dispatchEnterLeave(alienWidget ? alienWidget : nativeWidget, lastMouseReceiver, event->globalPosition());
2338 } else {
2339 dispatchEnterLeave(receiver, lastMouseReceiver, event->globalPosition());
2340 }
2341
2342 }
2343 }
2344
2345 // We need this quard in case someone opens a modal dialog / popup. If that's the case
2346 // leaveAfterRelease is set to null, but we shall not update lastMouseReceiver.
2347 const bool wasLeaveAfterRelease = leaveAfterRelease != nullptr;
2348 bool result = true;
2349 // This code is used for sending the synthetic enter/leave events for cases where it is needed
2350 // due to other events causing the widget under the mouse to change. However in those cases
2351 // we do not want to send the mouse event associated with this call, so this enables us to
2352 // not send the unneeded mouse event
2353 if (!onlyDispatchEnterLeave) {
2354 if (spontaneous)
2355 result = QApplication::sendSpontaneousEvent(receiver, event);
2356 else
2357 result = QCoreApplication::sendEvent(receiver, event);
2358 }
2359
2360 if (!graphicsWidget && leaveAfterRelease && event->type() == QEvent::MouseButtonRelease
2361 && !event->buttons() && QWidget::mouseGrabber() != leaveAfterRelease) {
2362 // Dispatch enter/leave if:
2363 // 1) the mouse grabber is an alien widget
2364 // 2) the button is released on an alien widget
2365 QWidget *enter = nullptr;
2366 if (nativeGuard)
2367 enter = alienGuard ? alienWidget : nativeWidget;
2368 else // The receiver is typically deleted on mouse release with drag'n'drop.
2369 enter = QApplication::widgetAt(event->globalPosition().toPoint());
2370 dispatchEnterLeave(enter, leaveAfterRelease, event->globalPosition());
2371 leaveAfterRelease = nullptr;
2372 lastMouseReceiver = enter;
2373 } else if (!wasLeaveAfterRelease) {
2374 if (activePopupWidget) {
2375 if (!QWidget::mouseGrabber())
2376 lastMouseReceiver = alienGuard ? alienWidget : (nativeGuard ? nativeWidget : nullptr);
2377 } else {
2378 lastMouseReceiver = receiverGuard ? receiver : QApplication::widgetAt(event->globalPosition().toPoint());
2379 }
2380 }
2381
2382 return result;
2383}
2384
2385/*
2386 This function should only be called when the widget changes visibility, i.e.
2387 when the \a widget is shown, hidden or deleted. This function does nothing
2388 if the widget is a top-level or native, i.e. not an alien widget. In that
2389 case enter/leave events are generated by the underlying windowing system.
2390*/
2392extern Q_WIDGETS_EXPORT QWidget *qt_button_down;
2393void QApplicationPrivate::sendSyntheticEnterLeave(QWidget *widget)
2394{
2395#ifndef QT_NO_CURSOR
2396 if (!widget || widget->isWindow())
2397 return;
2398 const bool widgetInShow = widget->isVisible() && !widget->data->in_destructor;
2399 if (!widgetInShow && widget != qt_last_mouse_receiver)
2400 return; // Widget was not under the cursor when it was hidden/deleted.
2401
2402 if (widgetInShow && widget->parentWidget()->data->in_show)
2403 return; // Ignore recursive show.
2404
2405 QWidget *mouseGrabber = QWidget::mouseGrabber();
2406 if (mouseGrabber && mouseGrabber != widget)
2407 return; // Someone else has the grab; enter/leave should not occur.
2408
2409 QWidget *tlw = widget->window();
2410 if (tlw->data->in_destructor || tlw->data->is_closing)
2411 return; // Closing down the business.
2412
2413 if (widgetInShow && (!qt_last_mouse_receiver || qt_last_mouse_receiver->window() != tlw))
2414 return; // Mouse cursor not inside the widget's top-level.
2415
2416 const QPoint globalPos(QCursor::pos());
2417 QPoint windowPos = tlw->mapFromGlobal(globalPos);
2418
2419 // Find the current widget under the mouse. If this function was called from
2420 // the widget's destructor, we have to make sure childAt() doesn't take into
2421 // account widgets that are about to be destructed.
2422 QWidget *widgetUnderCursor = tlw->d_func()->childAt_helper(windowPos, widget->data->in_destructor);
2423 if (!widgetUnderCursor)
2424 widgetUnderCursor = tlw;
2425 QPoint pos = widgetUnderCursor->mapFrom(tlw, windowPos);
2426
2427 if (widgetInShow && widgetUnderCursor != widget && !widget->isAncestorOf(widgetUnderCursor))
2428 return; // Mouse cursor not inside the widget or any of its children.
2429
2430 if (widget->data->in_destructor && qt_button_down == widget)
2431 qt_button_down = nullptr;
2432
2433 // A mouse move is not actually sent, but we utilize the sendMouseEvent() call to send the
2434 // enter/leave events as appropriate
2435 QMouseEvent e(QEvent::MouseMove, pos, windowPos, globalPos, Qt::NoButton, Qt::NoButton, Qt::NoModifier);
2436 sendMouseEvent(widgetUnderCursor, &e, widgetUnderCursor, tlw, &qt_button_down, qt_last_mouse_receiver, true, true);
2437#else // !QT_NO_CURSOR
2438 Q_UNUSED(widget);
2439#endif // QT_NO_CURSOR
2440}
2441
2442/*
2443 Sets the time after which a drag should start to \a ms ms.
2444
2445 \sa startDragTime()
2446*/
2447
2448void QApplication::setStartDragTime(int ms)
2449{
2450 QGuiApplication::styleHints()->setStartDragTime(ms);
2451}
2452
2453/*!
2454 \property QApplication::startDragTime
2455 \brief the time in milliseconds that a mouse button must be held down
2456 before a drag and drop operation will begin
2457
2458 If you support drag and drop in your application, and want to start a drag
2459 and drop operation after the user has held down a mouse button for a
2460 certain amount of time, you should use this property's value as the delay.
2461
2462 Qt also uses this delay internally, e.g. in QTextEdit and QLineEdit, for
2463 starting a drag.
2464
2465 The default value is 500 ms.
2466
2467 \sa startDragDistance(), {Drag and Drop in Qt}{Drag and Drop}
2468*/
2469
2470int QApplication::startDragTime()
2471{
2472 return QGuiApplication::styleHints()->startDragTime();
2473}
2474
2475/*
2476 Sets the distance after which a drag should start to \a l pixels.
2477
2478 \sa startDragDistance()
2479*/
2480
2481void QApplication::setStartDragDistance(int l)
2482{
2483 QGuiApplication::styleHints()->setStartDragDistance(l);
2484}
2485
2486/*!
2487 \property QApplication::startDragDistance
2488 \brief the minimum distance required for a drag and drop operation to start.
2489
2490 If you support drag and drop in your application, and want to start a drag
2491 and drop operation after the user has moved the cursor a certain distance
2492 with a button held down, you should use this property's value as the
2493 minimum distance required.
2494
2495 For example, if the mouse position of the click is stored in \c startPos
2496 and the current position (e.g. in the mouse move event) is \c currentPos,
2497 you can find out if a drag should be started with code like this:
2498
2499 \snippet code/src_gui_kernel_qapplication.cpp 7
2500
2501 Qt uses this value internally, e.g. in QFileDialog.
2502
2503 The default value (if the platform doesn't provide a different default)
2504 is 10 pixels.
2505
2506 \sa startDragTime(), QPoint::manhattanLength(), {Drag and Drop in Qt}{Drag and Drop}
2507*/
2508
2509int QApplication::startDragDistance()
2510{
2511 return QGuiApplication::styleHints()->startDragDistance();
2512}
2513
2514/*!
2515 Enters the main event loop and waits until exit() is called, then returns
2516 the value that was set to exit() (which is 0 if exit() is called via
2517 quit()).
2518
2519 It is necessary to call this function to start event handling. The main
2520 event loop receives events from the window system and dispatches these to
2521 the application widgets.
2522
2523 Generally, no user interaction can take place before calling exec(). As a
2524 special case, modal widgets like QMessageBox can be used before calling
2525 exec(), because modal widgets call exec() to start a local event loop.
2526
2527 To make your application perform idle processing, i.e., executing a special
2528 function whenever there are no pending events, use a QChronoTimer with 0ns
2529 timeout. More advanced idle processing schemes can be achieved using
2530 processEvents().
2531
2532 We recommend that you connect clean-up code to the
2533 \l{QCoreApplication::}{aboutToQuit()} signal, instead of putting it in your
2534 application's \c{main()} function. This is because, on some platforms the
2535 QApplication::exec() call may not return. For example, on the Windows
2536 platform, when the user logs off, the system terminates the process after Qt
2537 closes all top-level windows. Hence, there is \e{no guarantee} that the
2538 application will have time to exit its event loop and execute code at the
2539 end of the \c{main()} function, after the QApplication::exec() call.
2540
2541 \sa quitOnLastWindowClosed, QCoreApplication::quit(), QCoreApplication::exit(),
2542 QCoreApplication::processEvents(), QCoreApplication::exec()
2543*/
2544int QApplication::exec()
2545{
2546 return QGuiApplication::exec();
2547}
2548
2549/*! \reimp
2550 */
2551bool QApplication::notify(QObject *receiver, QEvent *e)
2552{
2553 Q_D(QApplication);
2554 // no events are delivered after ~QCoreApplication() has started
2555 if (QApplicationPrivate::is_app_closing)
2556 return true;
2557
2558 if (Q_UNLIKELY(!receiver)) { // serious error
2559 qWarning("QApplication::notify: Unexpected null receiver");
2560 return true;
2561 }
2562
2563#ifndef QT_NO_DEBUG
2564 QCoreApplicationPrivate::checkReceiverThread(receiver);
2565#endif
2566
2567 const bool isWindowType = receiver->isWindowType();
2568 const bool isWidgetType = receiver->isWidgetType();
2569 if (isWindowType
2570 && QGuiApplicationPrivate::sendQWindowEventToQPlatformWindow(static_cast<QWindow *>(receiver), e)) {
2571 return true; // Platform plugin ate the event
2572 }
2573
2574 QGuiApplicationPrivate::captureGlobalModifierState(e);
2575
2576#ifndef QT_NO_GESTURES
2577 // walk through parents and check for gestures
2578 if (d->gestureManager) {
2579 switch (e->type()) {
2580 case QEvent::Paint:
2581 case QEvent::MetaCall:
2582 case QEvent::DeferredDelete:
2583 case QEvent::DragEnter: case QEvent::DragMove: case QEvent::DragLeave:
2584 case QEvent::Drop: case QEvent::DragResponse:
2585 case QEvent::ChildAdded: case QEvent::ChildPolished:
2586 case QEvent::ChildRemoved:
2587 case QEvent::UpdateRequest:
2588 case QEvent::UpdateLater:
2589 case QEvent::LocaleChange:
2590 case QEvent::Style:
2591 case QEvent::IconDrag:
2592 case QEvent::StyleChange:
2593 case QEvent::GraphicsSceneDragEnter:
2594 case QEvent::GraphicsSceneDragMove:
2595 case QEvent::GraphicsSceneDragLeave:
2596 case QEvent::GraphicsSceneDrop:
2597 case QEvent::DynamicPropertyChange:
2598 case QEvent::NetworkReplyUpdated:
2599 break;
2600 default:
2601 if (d->gestureManager->thread() == QThread::currentThread()) {
2602 if (isWidgetType) {
2603 if (d->gestureManager->filterEvent(static_cast<QWidget *>(receiver), e))
2604 return true;
2605 } else {
2606 // a special case for events that go to QGesture objects.
2607 // We pass the object to the gesture manager and it'll figure
2608 // out if it's QGesture or not.
2609 if (d->gestureManager->filterEvent(receiver, e))
2610 return true;
2611 }
2612 }
2613 break;
2614 }
2615 }
2616#endif // QT_NO_GESTURES
2617
2618 switch (e->type()) {
2619 case QEvent::ApplicationDeactivate:
2620 case QEvent::OrientationChange:
2621 // Close all popups (triggers when switching applications
2622 // by pressing ALT-TAB on Windows, which is not receive as key event.
2623 // triggers when the screen rotates.)
2624 d->closeAllPopups();
2625 break;
2626 case QEvent::Wheel: // User input and window activation makes tooltips sleep
2627 case QEvent::ActivationChange:
2628 case QEvent::KeyPress:
2629 case QEvent::KeyRelease:
2630 case QEvent::FocusOut:
2631 case QEvent::FocusIn:
2632 case QEvent::MouseButtonPress:
2633 case QEvent::MouseButtonRelease:
2634 case QEvent::MouseButtonDblClick:
2635 d->toolTipFallAsleep.stop();
2636 Q_FALLTHROUGH();
2637 case QEvent::Leave:
2638 d->toolTipWakeUp.stop();
2639 break;
2640 default:
2641 break;
2642 }
2643
2644 switch (e->type()) {
2645 case QEvent::KeyPress: {
2646 QKeyEvent* keyEvent = static_cast<QKeyEvent*>(e);
2647 const int key = keyEvent->key();
2648 // When a key press is received which is not spontaneous then it needs to
2649 // be manually sent as a shortcut override event to ensure that any
2650 // matching shortcut is triggered first. This enables emulation/playback
2651 // of recorded events to still have the same effect.
2652 if (!e->spontaneous() && isWidgetType
2653 && qt_sendShortcutOverrideEvent(static_cast<QWidget *>(receiver), keyEvent->timestamp(),
2654 key, keyEvent->modifiers(), keyEvent->text(),
2655 keyEvent->isAutoRepeat(), keyEvent->count())) {
2656 return true;
2657 }
2658 qt_in_tab_key_event = (key == Qt::Key_Backtab
2659 || key == Qt::Key_Tab
2660 || key == Qt::Key_Left
2661 || key == Qt::Key_Up
2662 || key == Qt::Key_Right
2663 || key == Qt::Key_Down);
2664 break;
2665 }
2666 default:
2667 break;
2668 }
2669
2670 bool res = false;
2671 if (isWidgetType) {
2672 QWidget * w = static_cast<QWidget *>(receiver);
2673 switch (e->type()) {
2674 case QEvent::ShortcutOverride:
2675 case QEvent::KeyPress:
2676 case QEvent::KeyRelease: {
2677 QKeyEvent* key = static_cast<QKeyEvent*>(e);
2678 bool def = key->isAccepted();
2679 /*
2680 QLineEdit will emit a signal on Key_Return, but
2681 ignore the event, and sometimes the connected
2682 slot deletes the QLineEdit (common in itemview
2683 delegates), so we have to check if the widget
2684 was destroyed even if the event was ignored (to
2685 prevent a crash)
2686
2687 Note that we don't have to reset pr while
2688 propagating (because the original receiver will
2689 be destroyed if one of its ancestors is)
2690 */
2691 QPointer<QObject> pr = receiver;
2692 while (w) {
2693 if (def)
2694 key->accept();
2695 else
2696 key->ignore();
2697 res = d->notify_helper(w, e);
2698
2699 if (res && key->isAccepted())
2700 break;
2701 if (!pr || w->isWindow())
2702 break;
2703
2704 w = w->parentWidget();
2705 }
2706 qt_in_tab_key_event = false;
2707 break;
2708 }
2709 case QEvent::MouseButtonPress:
2710 case QEvent::MouseButtonRelease:
2711 case QEvent::MouseButtonDblClick:
2712 case QEvent::MouseMove: {
2713 QMouseEvent* mouse = static_cast<QMouseEvent*>(e);
2714 QPoint relpos = mouse->position().toPoint();
2715
2716 if (e->spontaneous()) {
2717 if (e->type() != QEvent::MouseMove)
2718 QApplicationPrivate::giveFocusAccordingToFocusPolicy(w, e, relpos);
2719
2720 // ### Qt 7 These dynamic tool tips should be an OPT-IN feature. Some platforms
2721 // like macOS (probably others too), can optimize their views by not
2722 // dispatching mouse move events. We have attributes to control hover,
2723 // and mouse tracking, but as long as we are deciding to implement this
2724 // feature without choice of opting-in or out, you ALWAYS have to have
2725 // tracking enabled. Therefore, the other properties give a false sense of
2726 // performance enhancement.
2727 if (e->type() == QEvent::MouseMove && mouse->buttons() == 0
2728 && w->rect().contains(relpos)) { // Outside due to mouse grab?
2729 d->toolTipWidget = w;
2730 d->toolTipPos = relpos;
2731 d->toolTipGlobalPos = mouse->globalPosition().toPoint();
2732 QStyle *s = d->toolTipWidget->style();
2733 int wakeDelay = s->styleHint(QStyle::SH_ToolTip_WakeUpDelay, nullptr, d->toolTipWidget, nullptr);
2734 d->toolTipWakeUp.start(d->toolTipFallAsleep.isActive() ? 20 : wakeDelay, this);
2735 }
2736 }
2737
2738 bool eventAccepted = mouse->isAccepted();
2739
2740 QPointer<QWidget> pw = w;
2741 while (w) {
2742 QMouseEvent me(mouse->type(), relpos, mouse->scenePosition(), mouse->globalPosition(),
2743 mouse->button(), mouse->buttons(), mouse->modifiers(), mouse->source(),
2744 mouse->pointingDevice());
2745 me.m_spont = mouse->spontaneous();
2746 me.setTimestamp(mouse->timestamp());
2747 QMutableSinglePointEvent::setDoubleClick(&me, QMutableSinglePointEvent::isDoubleClick(mouse));
2748 // throw away any mouse-tracking-only mouse events
2749 if (!w->hasMouseTracking()
2750 && mouse->type() == QEvent::MouseMove && mouse->buttons() == 0) {
2751 // but still send them through all application event filters (normally done by notify_helper)
2752 d->sendThroughApplicationEventFilters(w, w == receiver ? mouse : &me);
2753 res = true;
2754 } else {
2755 w->setAttribute(Qt::WA_NoMouseReplay, false);
2756 res = d->notify_helper(w, w == receiver ? mouse : &me);
2757 e->m_spont = false;
2758 }
2759 eventAccepted = (w == receiver ? mouse : &me)->isAccepted();
2760 if (res && eventAccepted)
2761 break;
2762 if (w->isWindow() || w->testAttribute(Qt::WA_NoMousePropagation))
2763 break;
2764 relpos += w->pos();
2765 w = w->parentWidget();
2766 }
2767
2768 mouse->setAccepted(eventAccepted);
2769
2770 if (e->type() == QEvent::MouseMove) {
2771 if (!pw)
2772 break;
2773
2774 w = static_cast<QWidget *>(receiver);
2775 relpos = mouse->position().toPoint();
2776 QPoint diff = relpos - w->mapFromGlobal(mouse->globalPosition()).toPoint();
2777 while (w) {
2778 if (w->testAttribute(Qt::WA_Hover) &&
2779 (!QApplication::activePopupWidget() || QApplication::activePopupWidget() == w->window())) {
2780 QHoverEvent he(QEvent::HoverMove, mouse->scenePosition(), mouse->globalPosition(), relpos - diff, mouse->modifiers());
2781 QMutableEventPoint::setPosition(he.point(0), relpos);
2782 d->notify_helper(w, &he);
2783 }
2784 if (w->isWindow() || w->testAttribute(Qt::WA_NoMousePropagation))
2785 break;
2786 relpos += w->pos();
2787 w = w->parentWidget();
2788 }
2789 }
2790 break;
2791 }
2792#if QT_CONFIG(wheelevent)
2793 case QEvent::Wheel: {
2794 // QTBUG-40656, QTBUG-42731: ignore wheel events when a popup (QComboBox) is open.
2795 if (const QWidget *popup = QApplication::activePopupWidget()) {
2796 if (w->window() != popup)
2797 return true;
2798 }
2799
2800 QWheelEvent* wheel = static_cast<QWheelEvent*>(e);
2801 if (!wheel->spontaneous()) {
2802 /*
2803 Synthesized events shouldn't propagate, e.g. QScrollArea passes events from the
2804 viewport on to the scrollbars, which might ignore the event if there is no more
2805 space to scroll. If we would propagate, the event would come back to the viewport.
2806 */
2807 res = d->notify_helper(w, wheel);
2808 break;
2809 }
2810
2811 const Qt::ScrollPhase phase = wheel->phase();
2812 QPoint relpos = wheel->position().toPoint();
2813
2814 // Ideally, we should lock on a widget when it starts receiving wheel
2815 // events. This avoids other widgets to start receiving those events
2816 // as the mouse cursor hovers them. However, given the way common
2817 // wheeled mice work, there's no certain way of connecting different
2818 // wheel events as a stream. This results in the NoScrollPhase case,
2819 // where we just send the event from the original receiver and up its
2820 // hierarchy until the event gets accepted.
2821 //
2822 // In the case of more evolved input devices, like Apple's trackpad or
2823 // Magic Mouse, we receive the scroll phase information. This helps us
2824 // connect wheel events as a stream and therefore makes it easier to
2825 // lock on the widget onto which the scrolling was initiated.
2826 //
2827 // We assume that, when supported, the phase cycle follows the pattern:
2828 //
2829 // ScrollBegin (ScrollUpdate* ScrollMomentum* ScrollEnd)+
2830 //
2831 // This means that we can have scrolling sequences (starting with ScrollBegin)
2832 // or partial sequences (after a ScrollEnd and starting with ScrollUpdate).
2833
2834 // a widget has already grabbed the wheel for a sequence
2835 if (QApplicationPrivate::wheel_widget) {
2836 Q_ASSERT(phase != Qt::NoScrollPhase);
2837 w = QApplicationPrivate::wheel_widget;
2838 relpos = w->mapFromGlobal(wheel->globalPosition().toPoint());
2839 }
2840 /*
2841 Start or finish a scrolling sequence by grabbing/releasing the wheel via
2842 wheel_widget. The sequence might be partial (ie. not start with ScrollBegin),
2843 e.g. if the previous wheel_widget was destroyed mid-sequence.
2844 */
2845 switch (phase) {
2846 case Qt::ScrollEnd:
2847 QApplicationPrivate::wheel_widget = nullptr;
2848 break;
2849 case Qt::ScrollBegin:
2850 QApplicationPrivate::wheel_widget = w;
2851 Q_FALLTHROUGH();
2852 case Qt::ScrollUpdate:
2853 case Qt::ScrollMomentum:
2854 if (!QApplicationPrivate::wheel_widget)
2855 QApplicationPrivate::wheel_widget = w;
2856 Q_FALLTHROUGH();
2857 case Qt::NoScrollPhase:
2858 QApplicationPrivate::giveFocusAccordingToFocusPolicy(w, e, relpos);
2859 break;
2860 // no default: - we want warnings if we don't handle all phases explicitly
2861 }
2862
2863 QWheelEvent we(relpos, wheel->globalPosition(), wheel->pixelDelta(), wheel->angleDelta(), wheel->buttons(),
2864 wheel->modifiers(), phase, wheel->inverted(), wheel->source(), wheel->pointingDevice());
2865
2866 we.setTimestamp(wheel->timestamp());
2867 bool eventAccepted;
2868 do {
2869 // events are delivered as accepted and ignored by the default event handler
2870 // since we always send the same QWheelEvent object, we need to reset the accepted state
2871 we.setAccepted(true);
2872 we.m_spont = wheel->spontaneous() && w == receiver;
2873 res = d->notify_helper(w, &we);
2874 eventAccepted = we.isAccepted();
2875 if (res && eventAccepted)
2876 break;
2877 if (w->isWindow() || w->testAttribute(Qt::WA_NoMousePropagation))
2878 break;
2879
2880 QMutableEventPoint::setPosition(we.point(0), we.position() + w->pos());
2881 w = w->parentWidget();
2882 } while (w);
2883 wheel->setAccepted(eventAccepted);
2884 break;
2885 }
2886#endif
2887#ifndef QT_NO_CONTEXTMENU
2888 case QEvent::ContextMenu: {
2889 QContextMenuEvent *context = static_cast<QContextMenuEvent*>(e);
2890 QPoint relpos = context->pos();
2891 bool eventAccepted = context->isAccepted();
2892 while (w) {
2893 QContextMenuEvent ce(context->reason(), relpos, context->globalPos(), context->modifiers());
2894 ce.m_spont = e->spontaneous();
2895 res = d->notify_helper(w, w == receiver ? context : &ce);
2896 eventAccepted = ((w == receiver) ? context : &ce)->isAccepted();
2897 e->m_spont = false;
2898
2899 if (res && eventAccepted)
2900 break;
2901 if (w->isWindow() || w->testAttribute(Qt::WA_NoMousePropagation))
2902 break;
2903
2904 relpos += w->pos();
2905 w = w->parentWidget();
2906 }
2907 context->setAccepted(eventAccepted);
2908 break;
2909 }
2910#endif // QT_NO_CONTEXTMENU
2911#if QT_CONFIG(tabletevent)
2912 case QEvent::TabletMove:
2913 case QEvent::TabletPress:
2914 case QEvent::TabletRelease: {
2915 QTabletEvent *tablet = static_cast<QTabletEvent*>(e);
2916 QPointF relpos = tablet->position();
2917 bool eventAccepted = tablet->isAccepted();
2918 while (w) {
2919 QTabletEvent te(tablet->type(), tablet->pointingDevice(), relpos, tablet->globalPosition(),
2920 tablet->pressure(), tablet->xTilt(), tablet->yTilt(),
2921 tablet->tangentialPressure(), tablet->rotation(), tablet->z(),
2922 tablet->modifiers(), tablet->button(), tablet->buttons());
2923 te.m_spont = e->spontaneous();
2924 te.setTimestamp(tablet->timestamp());
2925 te.setAccepted(false);
2926 res = d->notify_helper(w, w == receiver ? tablet : &te);
2927 eventAccepted = ((w == receiver) ? tablet : &te)->isAccepted();
2928 e->m_spont = false;
2929 if (res && eventAccepted)
2930 break;
2931 if (w->isWindow() || w->testAttribute(Qt::WA_NoMousePropagation))
2932 break;
2933
2934 relpos += w->pos();
2935 w = w->parentWidget();
2936 }
2937 tablet->setAccepted(eventAccepted);
2938 break;
2939 }
2940#endif // QT_CONFIG(tabletevent)
2941
2942#if QT_CONFIG(tooltip) || QT_CONFIG(whatsthis)
2943 case QEvent::ToolTip:
2944 case QEvent::WhatsThis:
2945 case QEvent::QueryWhatsThis: {
2946 QHelpEvent *help = static_cast<QHelpEvent*>(e);
2947 QPoint relpos = help->pos();
2948 bool eventAccepted = help->isAccepted();
2949 while (w) {
2950 QHelpEvent he(help->type(), relpos, help->globalPos());
2951 he.m_spont = e->spontaneous();
2952 res = d->notify_helper(w, w == receiver ? help : &he);
2953 e->m_spont = false;
2954 eventAccepted = (w == receiver ? help : &he)->isAccepted();
2955 if (res && eventAccepted)
2956 break;
2957 if (w->isWindow())
2958 break;
2959
2960 relpos += w->pos();
2961 w = w->parentWidget();
2962 }
2963 help->setAccepted(eventAccepted);
2964 break;
2965 }
2966#endif
2967#if QT_CONFIG(statustip) || QT_CONFIG(whatsthis)
2968 case QEvent::StatusTip:
2969 case QEvent::WhatsThisClicked:
2970 while (w) {
2971 res = d->notify_helper(w, e);
2972 if (res && e->isAccepted())
2973 break;
2974 if (w->isWindow())
2975 break;
2976 w = w->parentWidget();
2977 }
2978 break;
2979#endif
2980
2981#if QT_CONFIG(draganddrop)
2982 case QEvent::DragEnter: {
2983 QDragEnterEvent *dragEvent = static_cast<QDragEnterEvent *>(e);
2984#if QT_CONFIG(graphicsview)
2985 // QGraphicsProxyWidget handles its own propagation,
2986 // and we must not change QDragManagers currentTarget.
2987 const auto &extra = w->window()->d_func()->extra;
2988 if (extra && extra->proxyWidget) {
2989 res = d->notify_helper(w, dragEvent);
2990 break;
2991 }
2992#endif
2993 while (w) {
2994 if (w->isEnabled() && w->acceptDrops()) {
2995 res = d->notify_helper(w, dragEvent);
2996 if (res && dragEvent->isAccepted()) {
2997 QDragManager::self()->setCurrentTarget(w);
2998 break;
2999 }
3000 }
3001 if (w->isWindow())
3002 break;
3003 dragEvent->m_pos = w->mapToParent(dragEvent->m_pos);
3004 w = w->parentWidget();
3005 }
3006 break;
3007 }
3008 case QEvent::DragMove:
3009 case QEvent::Drop:
3010 case QEvent::DragLeave: {
3011#if QT_CONFIG(graphicsview)
3012 // QGraphicsProxyWidget handles its own propagation,
3013 // and we must not change QDragManagers currentTarget.
3014 const auto &extra = w->window()->d_func()->extra;
3015 bool isProxyWidget = extra && extra->proxyWidget;
3016 if (!isProxyWidget)
3017#endif
3018 w = qobject_cast<QWidget *>(QDragManager::self()->currentTarget());
3019
3020 if (!w) {
3021 // The widget that received DragEnter didn't accept the event, so we have no
3022 // current drag target in the QDragManager. But DragLeave still needs to be
3023 // dispatched so that enter/leave events are in balance (and so that UnderMouse
3024 // gets cleared).
3025 if (e->type() == QEvent::DragLeave)
3026 w = static_cast<QWidget *>(receiver);
3027 else
3028 break;
3029 }
3030 if (e->type() == QEvent::DragMove || e->type() == QEvent::Drop) {
3031 QDropEvent *dragEvent = static_cast<QDropEvent *>(e);
3032 QWidget *origReceiver = static_cast<QWidget *>(receiver);
3033 while (origReceiver && w != origReceiver) {
3034 dragEvent->m_pos = origReceiver->mapToParent(dragEvent->m_pos);
3035 origReceiver = origReceiver->parentWidget();
3036 }
3037 }
3038 res = d->notify_helper(w, e);
3039 if (e->type() != QEvent::DragMove
3040#if QT_CONFIG(graphicsview)
3041 && !isProxyWidget
3042#endif
3043 )
3044 QDragManager::self()->setCurrentTarget(nullptr, e->type() == QEvent::Drop);
3045 break;
3046 }
3047#endif // QT_CONFIG(draganddrop)
3048 case QEvent::TouchBegin: {
3049 // Note: TouchUpdate and TouchEnd events are never propagated
3050 QTouchEvent *touchEvent = static_cast<QTouchEvent *>(e);
3051 bool eventAccepted = touchEvent->isAccepted();
3052 bool acceptTouchEvents = w->testAttribute(Qt::WA_AcceptTouchEvents);
3053
3054 if (acceptTouchEvents && e->spontaneous()
3055 && touchEvent->device()->type() != QInputDevice::DeviceType::TouchPad) {
3056 const QPoint localPos = touchEvent->points()[0].position().toPoint();
3057 QApplicationPrivate::giveFocusAccordingToFocusPolicy(w, e, localPos);
3058 }
3059
3060#ifndef QT_NO_GESTURES
3061 QPointer<QWidget> gesturePendingWidget;
3062#endif
3063
3064 while (w) {
3065 // first, try to deliver the touch event
3066 acceptTouchEvents = w->testAttribute(Qt::WA_AcceptTouchEvents);
3067 QMutableTouchEvent::setTarget(touchEvent, w);
3068 touchEvent->setAccepted(acceptTouchEvents);
3069 QPointer<QWidget> p = w;
3070 res = acceptTouchEvents && d->notify_helper(w, touchEvent);
3071 eventAccepted = touchEvent->isAccepted();
3072 if (p.isNull()) {
3073 // widget was deleted
3074 w = nullptr;
3075 } else {
3076 w->setAttribute(Qt::WA_WState_AcceptedTouchBeginEvent, res && eventAccepted);
3077 }
3078 touchEvent->m_spont = false;
3079 if (res && eventAccepted) {
3080 // the first widget to accept the TouchBegin gets an implicit grab.
3081 d->activateImplicitTouchGrab(w, touchEvent);
3082 break;
3083 }
3084#ifndef QT_NO_GESTURES
3085 if (gesturePendingWidget.isNull() && w && QGestureManager::gesturePending(w))
3086 gesturePendingWidget = w;
3087#endif
3088 if (!w || w->isWindow() || w->testAttribute(Qt::WA_NoMousePropagation))
3089 break;
3090
3091 const QPoint offset = w->pos();
3092 w = w->parentWidget();
3093 QMutableTouchEvent::setTarget(touchEvent, w);
3094 for (qsizetype cnt = touchEvent->pointCount(), i = 0; i < cnt; ++i) {
3095 auto &pt = touchEvent->point(i);
3096 QMutableEventPoint::setPosition(pt, pt.position() + offset);
3097 }
3098 }
3099
3100#ifndef QT_NO_GESTURES
3101 if (!eventAccepted && !gesturePendingWidget.isNull()) {
3102 // the first widget subscribed to a gesture gets an implicit grab for all
3103 // points, also for events and event points that have not been accepted.
3104 d->activateImplicitTouchGrab(gesturePendingWidget, touchEvent, QApplicationPrivate::GrabAllPoints);
3105 }
3106#endif
3107
3108 touchEvent->setAccepted(eventAccepted);
3109 break;
3110 }
3111 case QEvent::TouchUpdate:
3112 case QEvent::TouchEnd:
3113 // We may get here if the widget is subscribed to a gesture,
3114 // but has not accepted TouchBegin. Propagate touch events
3115 // only if TouchBegin has been accepted.
3116 if (w->testAttribute(Qt::WA_WState_AcceptedTouchBeginEvent))
3117 res = d->notify_helper(w, e);
3118 break;
3119 case QEvent::RequestSoftwareInputPanel:
3120 inputMethod()->show();
3121 break;
3122 case QEvent::CloseSoftwareInputPanel:
3123 inputMethod()->hide();
3124 break;
3125
3126#ifndef QT_NO_GESTURES
3127 case QEvent::NativeGesture:
3128 while (w) {
3129 e->ignore();
3130 res = d->notify_helper(w, e);
3131 if (res && e->isAccepted())
3132 break;
3133 if (w->isWindow())
3134 break;
3135 w = w->parentWidget();
3136 }
3137 break;
3138 case QEvent::Gesture:
3139 case QEvent::GestureOverride: {
3140 QGestureEvent *gestureEvent = static_cast<QGestureEvent *>(e);
3141 QList<QGesture *> allGestures = gestureEvent->gestures();
3142
3143 bool eventAccepted = gestureEvent->isAccepted();
3144 bool wasAccepted = eventAccepted;
3145 while (w) {
3146 // send only gestures the widget expects
3147 QList<QGesture *> gestures;
3148 QWidgetPrivate *wd = w->d_func();
3149 for (int i = 0; i < allGestures.size();) {
3150 QGesture *g = allGestures.at(i);
3151 Qt::GestureType type = g->gestureType();
3152 QMap<Qt::GestureType, Qt::GestureFlags>::iterator contextit =
3153 wd->gestureContext.find(type);
3154 bool deliver = contextit != wd->gestureContext.end() &&
3155 (g->state() == Qt::GestureStarted || w == receiver ||
3156 (contextit.value() & Qt::ReceivePartialGestures));
3157 if (deliver) {
3158 allGestures.removeAt(i);
3159 gestures.append(g);
3160 } else {
3161 ++i;
3162 }
3163 }
3164 if (!gestures.isEmpty()) { // we have gestures for this w
3165 QGestureEvent ge(gestures);
3166 ge.t = gestureEvent->t;
3167 ge.m_spont = gestureEvent->spontaneous();
3168 ge.m_accept = wasAccepted;
3169 ge.m_accepted = gestureEvent->m_accepted;
3170 res = d->notify_helper(w, &ge);
3171 gestureEvent->m_spont = false;
3172 eventAccepted = ge.isAccepted();
3173 for (QGesture *g : std::as_const(gestures)) {
3174 // Ignore res [event return value] because handling of multiple gestures
3175 // packed into a single QEvent depends on not consuming the event
3176 if (eventAccepted || ge.isAccepted(g)) {
3177 // if the gesture was accepted, mark the target widget for it
3178 gestureEvent->m_targetWidgets[g->gestureType()] = w;
3179 gestureEvent->setAccepted(g, true);
3180 } else {
3181 // if the gesture was explicitly ignored by the application,
3182 // put it back so a parent can get it
3183 allGestures.append(g);
3184 }
3185 }
3186 }
3187 if (allGestures.isEmpty()) // everything delivered
3188 break;
3189 if (w->isWindow())
3190 break;
3191 w = w->parentWidget();
3192 }
3193 for (QGesture *g : std::as_const(allGestures))
3194 gestureEvent->setAccepted(g, false);
3195 gestureEvent->m_accept = false; // to make sure we check individual gestures
3196 break;
3197 }
3198#endif // QT_NO_GESTURES
3199#ifdef Q_OS_MAC
3200 // Enable touch events on enter, disable on leave.
3201 typedef void (*RegisterTouchWindowFn)(QWindow *, bool);
3202 case QEvent::Enter:
3203 if (w->testAttribute(Qt::WA_AcceptTouchEvents)) {
3204 RegisterTouchWindowFn registerTouchWindow = reinterpret_cast<RegisterTouchWindowFn>(
3205 QFunctionPointer(platformNativeInterface()->nativeResourceFunctionForIntegration("registertouchwindow")));
3206 if (registerTouchWindow)
3207 registerTouchWindow(w->window()->windowHandle(), true);
3208 }
3209 res = d->notify_helper(receiver, e);
3210 break;
3211 case QEvent::Leave:
3212 if (w->testAttribute(Qt::WA_AcceptTouchEvents)) {
3213 RegisterTouchWindowFn registerTouchWindow = reinterpret_cast<RegisterTouchWindowFn>(
3214 QFunctionPointer(platformNativeInterface()->nativeResourceFunctionForIntegration("registertouchwindow")));
3215 if (registerTouchWindow)
3216 registerTouchWindow(w->window()->windowHandle(), false);
3217 }
3218 res = d->notify_helper(receiver, e);
3219 break;
3220#endif
3221 default:
3222 res = d->notify_helper(receiver, e);
3223 break;
3224 }
3225 } else {
3226 res = d->notify_helper(receiver, e);
3227 }
3228
3229 return res;
3230}
3231
3232bool QApplicationPrivate::notify_helper(QObject *receiver, QEvent * e)
3233{
3234 // These tracepoints (and the whole function, actually) are very similar
3235 // to the ones in QCoreApplicationPrivate::notify_helper; the reason for their
3236 // duplication is because tracepoint symbols are not exported by QtCore.
3237 // If you adjust the tracepoints here, consider adjusting QCoreApplicationPrivate too.
3238 Q_TRACE(QApplication_notify_entry, receiver, e, e->type());
3239 bool consumed = false;
3240 bool filtered = false;
3241 Q_TRACE_EXIT(QApplication_notify_exit, consumed, filtered);
3242
3243 // send to all application event filters
3244 QThreadData *threadData = receiver->d_func()->threadData.loadRelaxed();
3245 if (threadData->requiresCoreApplication
3246 && threadData->thread.loadAcquire() == mainThread()
3247 && sendThroughApplicationEventFilters(receiver, e)) {
3248 filtered = true;
3249 return filtered;
3250 }
3251
3252 if (receiver->isWidgetType()) {
3253 QWidget *widget = static_cast<QWidget *>(receiver);
3254
3255#if !defined(QT_NO_CURSOR)
3256 // toggle HasMouse widget state on enter and leave
3257 if ((e->type() == QEvent::Enter || e->type() == QEvent::DragEnter) &&
3258 (!QApplication::activePopupWidget() || QApplication::activePopupWidget() == widget->window()))
3259 widget->setAttribute(Qt::WA_UnderMouse, true);
3260 else if (e->type() == QEvent::Leave || e->type() == QEvent::DragLeave)
3261 widget->setAttribute(Qt::WA_UnderMouse, false);
3262#endif
3263
3264 if (QLayout *layout=widget->d_func()->layout) {
3265 layout->widgetEvent(e);
3266 }
3267 }
3268
3269 // send to all receiver event filters
3270 if (sendThroughObjectEventFilters(receiver, e)) {
3271 filtered = true;
3272 return filtered;
3273 }
3274
3275 // deliver the event
3276 consumed = receiver->event(e);
3277
3278 QCoreApplicationPrivate::setEventSpontaneous(e, false);
3279 return consumed;
3280}
3281
3282bool QApplicationPrivate::inPopupMode()
3283{
3284 return QGuiApplicationPrivate::activePopupWindow() != nullptr;
3285}
3286
3287static void ungrabKeyboardForPopup(QWidget *popup)
3288{
3289 qCDebug(lcWidgetPopup) << "ungrab keyboard for" << popup;
3290 if (QWidget::keyboardGrabber())
3291 qt_widget_private(QWidget::keyboardGrabber())->stealKeyboardGrab(true);
3292 else
3293 qt_widget_private(popup)->stealKeyboardGrab(false);
3294}
3295
3296static void ungrabMouseForPopup(QWidget *popup)
3297{
3298 qCDebug(lcWidgetPopup) << "ungrab mouse for" << popup;
3299 if (QWidget::mouseGrabber())
3300 qt_widget_private(QWidget::mouseGrabber())->stealMouseGrab(true);
3301 else
3302 qt_widget_private(popup)->stealMouseGrab(false);
3303}
3304
3305static bool popupGrabOk;
3306
3307static void grabForPopup(QWidget *popup)
3308{
3309 Q_ASSERT(popup->testAttribute(Qt::WA_WState_Created));
3310 popupGrabOk = qt_widget_private(popup)->stealKeyboardGrab(true);
3311 if (popupGrabOk) {
3312 popupGrabOk = qt_widget_private(popup)->stealMouseGrab(true);
3313 if (!popupGrabOk) {
3314 // transfer grab back to the keyboard grabber if any
3315 ungrabKeyboardForPopup(popup);
3316 }
3317 }
3318 qCDebug(lcWidgetPopup) << "grabbed mouse and keyboard?" << popupGrabOk << "for popup" << popup;
3319}
3320
3321void QApplicationPrivate::closePopup(QWidget *popup)
3322{
3323 QWindow *win = popup->windowHandle();
3324 if (!win)
3325 return;
3326 if (!QGuiApplicationPrivate::closePopup(win))
3327 return;
3328
3329 const QWindow *nextRemainingPopup = QGuiApplicationPrivate::activePopupWindow();
3330 if (!nextRemainingPopup) { // this was the last popup
3331
3332 if (popupGrabOk) {
3333 popupGrabOk = false;
3334
3335 if (active_window && active_window->windowHandle()
3336 && !popup->geometry().contains(QGuiApplicationPrivate::lastCursorPosition.toPoint())
3337 && !popup->testAttribute(Qt::WA_NoMouseReplay)) {
3338 QApplicationPrivate::replayMousePress = true;
3339 }
3340
3341 // transfer grab back to mouse grabber if any, otherwise release the grab
3342 ungrabMouseForPopup(popup);
3343
3344 // transfer grab back to keyboard grabber if any, otherwise release the grab
3345 ungrabKeyboardForPopup(popup);
3346 }
3347
3348 if (active_window) {
3349 if (QWidget *fw = active_window->focusWidget()) {
3350 if (fw != QApplication::focusWidget()) {
3351 fw->setFocus(Qt::PopupFocusReason);
3352 } else {
3353 QFocusEvent e(QEvent::FocusIn, Qt::PopupFocusReason);
3354 QCoreApplication::sendEvent(fw, &e);
3355 }
3356 }
3357 }
3358
3359 } else if (const auto *popupWin = qobject_cast<const QWidgetWindow *>(nextRemainingPopup)) {
3360 // A popup was closed, so the previous popup gets the focus.
3361 if (QWidget *fw = popupWin->widget()->focusWidget())
3362 fw->setFocus(Qt::PopupFocusReason);
3363
3364 // can become nullptr due to setFocus() above
3365 if (QGuiApplicationPrivate::popupCount() == 1) // grab mouse/keyboard
3366 grabForPopup(popupWin->widget());
3367 }
3368
3369}
3370
3371void QApplicationPrivate::openPopup(QWidget *popup)
3372{
3373 QGuiApplicationPrivate::activatePopup(popup->windowHandle());
3374
3375 if (QGuiApplicationPrivate::popupCount() == 1) // grab mouse/keyboard
3376 grabForPopup(popup);
3377
3378 // popups are not focus-handled by the window system (the first
3379 // popup grabbed the keyboard), so we have to do that manually: A
3380 // new popup gets the focus
3381 if (popup->focusWidget()) {
3382 popup->focusWidget()->setFocus(Qt::PopupFocusReason);
3383 } else if (QGuiApplicationPrivate::popupCount() == 1) { // this was the first popup
3384 if (QWidget *fw = QApplication::focusWidget()) {
3385 QFocusEvent e(QEvent::FocusOut, Qt::PopupFocusReason);
3386 QCoreApplication::sendEvent(fw, &e);
3387 }
3388 }
3389}
3390
3391#ifdef QT_KEYPAD_NAVIGATION
3392/*!
3393 Sets the kind of focus navigation Qt should use to \a mode.
3394
3395 This feature is available in Qt for Embedded Linux only.
3396
3397 \since 4.6
3398*/
3399void QApplication::setNavigationMode(Qt::NavigationMode mode)
3400{
3401 QApplicationPrivate::navigationMode = mode;
3402}
3403
3404/*!
3405 Returns what kind of focus navigation Qt is using.
3406
3407 This feature is available in Qt for Embedded Linux only.
3408
3409 \since 4.6
3410*/
3411Qt::NavigationMode QApplication::navigationMode()
3412{
3413 return QApplicationPrivate::navigationMode;
3414}
3415#endif
3416
3417/*!
3418 \fn void QApplication::alert(QWidget *widget, int msec)
3419 \since 4.3
3420
3421 Causes an alert to be shown for \a widget if the window is not the active
3422 window. The alert is shown for \a msec milliseconds. If \a msec is zero (the
3423 default), then the alert is shown indefinitely until the window becomes
3424 active again.
3425
3426 Currently this function does nothing on Qt for Embedded Linux.
3427
3428 On \macos, this works more at the application level and will cause the
3429 application icon to bounce in the dock.
3430
3431 On Windows, this causes the window's taskbar entry to flash for a time. If
3432 \a msec is zero, the flashing will stop and the taskbar entry will turn a
3433 different color (currently orange).
3434
3435 On X11, this will cause the window to be marked as "demands attention", the
3436 window must not be hidden (i.e. not have hide() called on it, but be
3437 visible in some sort of way) in order for this to work.
3438*/
3439void QApplication::alert(QWidget *widget, int duration)
3440{
3441 if (widget) {
3442 if (widget->window()->isActiveWindow() && !(widget->window()->windowState() & Qt::WindowMinimized))
3443 return;
3444 if (QWindow *window= QApplicationPrivate::windowForWidget(widget))
3445 window->alert(duration);
3446 } else {
3447 const auto topLevels = topLevelWidgets();
3448 for (QWidget *topLevel : topLevels)
3449 QApplication::alert(topLevel, duration);
3450 }
3451}
3452
3453/*!
3454 \property QApplication::cursorFlashTime
3455 \brief the text cursor's flash (blink) time in milliseconds
3456
3457 The flash time is the time required to display, invert and restore the
3458 caret display. Usually the text cursor is displayed for half the cursor
3459 flash time, then hidden for the same amount of time, but this may vary.
3460
3461 The default value on X11 is 1000 milliseconds. On Windows, the
3462 \uicontrol{Control Panel} value is used and setting this property sets the cursor
3463 flash time for all applications.
3464
3465 We recommend that widgets do not cache this value as it may change at any
3466 time if the user changes the global desktop settings.
3467
3468 \note This property may hold a negative value, for instance if cursor
3469 blinking is disabled.
3470*/
3471void QApplication::setCursorFlashTime(int msecs)
3472{
3473 QGuiApplication::styleHints()->setCursorFlashTime(msecs);
3474}
3475
3476int QApplication::cursorFlashTime()
3477{
3478 return QGuiApplication::styleHints()->cursorFlashTime();
3479}
3480
3481/*!
3482 \property QApplication::doubleClickInterval
3483 \brief the time limit in milliseconds that distinguishes a double click
3484 from two consecutive mouse clicks
3485
3486 The default value on X11 is 400 milliseconds. On Windows and Mac OS, the
3487 operating system's value is used.
3488*/
3489void QApplication::setDoubleClickInterval(int ms)
3490{
3491 QGuiApplication::styleHints()->setMouseDoubleClickInterval(ms);
3492}
3493
3494int QApplication::doubleClickInterval()
3495{
3496 return QGuiApplication::styleHints()->mouseDoubleClickInterval();
3497}
3498
3499/*!
3500 \property QApplication::keyboardInputInterval
3501 \brief the time limit in milliseconds that distinguishes a key press
3502 from two consecutive key presses
3503 \since 4.2
3504
3505 The default value on X11 is 400 milliseconds. On Windows and Mac OS, the
3506 operating system's value is used.
3507*/
3508void QApplication::setKeyboardInputInterval(int ms)
3509{
3510 QGuiApplication::styleHints()->setKeyboardInputInterval(ms);
3511}
3512
3513int QApplication::keyboardInputInterval()
3514{
3515 return QGuiApplication::styleHints()->keyboardInputInterval();
3516}
3517
3518/*!
3519 \property QApplication::wheelScrollLines
3520 \brief the number of lines to scroll a widget, when the
3521 mouse wheel is rotated.
3522
3523 If the value exceeds the widget's number of visible lines, the widget
3524 should interpret the scroll operation as a single \e{page up} or
3525 \e{page down}. If the widget is an \l{QAbstractItemView}{item view class},
3526 then the result of scrolling one \e line depends on the setting of the
3527 widget's \l{QAbstractItemView::verticalScrollMode()}{scroll mode}. Scroll
3528 one \e line can mean \l{QAbstractItemView::ScrollPerItem}{scroll one item}
3529 or \l{QAbstractItemView::ScrollPerPixel}{scroll one pixel}.
3530
3531 By default, this property has a value of 3.
3532
3533 \sa QStyleHints::wheelScrollLines()
3534*/
3535#if QT_CONFIG(wheelevent)
3536int QApplication::wheelScrollLines()
3537{
3538 return styleHints()->wheelScrollLines();
3539}
3540
3541void QApplication::setWheelScrollLines(int lines)
3542{
3543 styleHints()->setWheelScrollLines(lines);
3544}
3545#endif
3546
3547static inline int uiEffectToFlag(Qt::UIEffect effect)
3548{
3549 switch (effect) {
3550 case Qt::UI_General:
3551 return QPlatformTheme::GeneralUiEffect;
3552 case Qt::UI_AnimateMenu:
3553 return QPlatformTheme::AnimateMenuUiEffect;
3554 case Qt::UI_FadeMenu:
3555 return QPlatformTheme::FadeMenuUiEffect;
3556 case Qt::UI_AnimateCombo:
3557 return QPlatformTheme::AnimateComboUiEffect;
3558 case Qt::UI_AnimateTooltip:
3559 return QPlatformTheme::AnimateTooltipUiEffect;
3560 case Qt::UI_FadeTooltip:
3561 return QPlatformTheme::FadeTooltipUiEffect;
3562 case Qt::UI_AnimateToolBox:
3563 return QPlatformTheme::AnimateToolBoxUiEffect;
3564 }
3565 return 0;
3566}
3567
3568/*!
3569 \fn void QApplication::setEffectEnabled(Qt::UIEffect effect, bool enable)
3570
3571 Enables the UI effect \a effect if \a enable is true, otherwise the effect
3572 will not be used.
3573
3574 \note All effects are disabled on screens running at less than 16-bit color
3575 depth.
3576
3577 \sa isEffectEnabled(), Qt::UIEffect, setDesktopSettingsAware()
3578*/
3579void QApplication::setEffectEnabled(Qt::UIEffect effect, bool enable)
3580{
3581 int effectFlags = uiEffectToFlag(effect);
3582 if (enable) {
3583 if (effectFlags & QPlatformTheme::FadeMenuUiEffect)
3584 effectFlags |= QPlatformTheme::AnimateMenuUiEffect;
3585 if (effectFlags & QPlatformTheme::FadeTooltipUiEffect)
3586 effectFlags |= QPlatformTheme::AnimateTooltipUiEffect;
3587 QApplicationPrivate::enabledAnimations |= effectFlags;
3588 } else {
3589 QApplicationPrivate::enabledAnimations &= ~effectFlags;
3590 }
3591}
3592
3593/*!
3594 \fn bool QApplication::isEffectEnabled(Qt::UIEffect effect)
3595
3596 Returns \c true if \a effect is enabled; otherwise returns \c false.
3597
3598 By default, Qt will try to use the desktop settings. To prevent this, call
3599 setDesktopSettingsAware(false).
3600
3601 \note All effects are disabled on screens running at less than 16-bit color
3602 depth.
3603
3604 \sa setEffectEnabled(), Qt::UIEffect
3605*/
3606bool QApplication::isEffectEnabled(Qt::UIEffect effect)
3607{
3608 CHECK_QAPP_INSTANCE(false)
3609 const auto primaryScreenDepth = QGuiApplication::primaryScreen() ?
3610 QGuiApplication::primaryScreen()->depth() : 24;
3611 return primaryScreenDepth >= 16
3612 && (QApplicationPrivate::enabledAnimations & QPlatformTheme::GeneralUiEffect)
3613 && (QApplicationPrivate::enabledAnimations & uiEffectToFlag(effect));
3614}
3615
3616/*!
3617 \fn void QApplication::beep()
3618
3619 Sounds the bell, using the default volume and sound. The function is \e not
3620 available in Qt for Embedded Linux.
3621*/
3622void QApplication::beep()
3623{
3624 QGuiApplicationPrivate::platformIntegration()->beep();
3625}
3626
3627/*!
3628 \macro qApp
3629 \relates QApplication
3630
3631 A global pointer referring to the unique application object. It is
3632 equivalent to QCoreApplication::instance(), but cast as a QApplication pointer,
3633 so only valid when the unique application object is a QApplication.
3634
3635 \sa QCoreApplication::instance(), qGuiApp
3636*/
3637
3638bool qt_sendSpontaneousEvent(QObject *receiver, QEvent *event)
3639{
3640 return QGuiApplication::sendSpontaneousEvent(receiver, event);
3641}
3642
3643void QApplicationPrivate::giveFocusAccordingToFocusPolicy(QWidget *widget, QEvent *event, QPoint localPos)
3644{
3645 const bool setFocusOnRelease = QGuiApplication::styleHints()->setFocusOnTouchRelease();
3646 Qt::FocusPolicy focusPolicy = Qt::ClickFocus;
3647 static QPointer<QWidget> focusedWidgetOnTouchBegin = nullptr;
3648
3649 switch (event->type()) {
3650 case QEvent::MouseButtonPress:
3651 case QEvent::MouseButtonDblClick:
3652 case QEvent::TouchBegin:
3653 focusedWidgetOnTouchBegin = QApplication::focusWidget();
3654 if (setFocusOnRelease)
3655 return;
3656 break;
3657 case QEvent::MouseButtonRelease:
3658 case QEvent::TouchEnd:
3659 if (!setFocusOnRelease)
3660 return;
3661 if (focusedWidgetOnTouchBegin != QApplication::focusWidget()) {
3662 // Focus widget was changed while delivering press/move events.
3663 // To not interfere with application logic, we leave focus as-is
3664 return;
3665 }
3666 break;
3667 case QEvent::Wheel:
3668 focusPolicy = Qt::WheelFocus;
3669 break;
3670 default:
3671 return;
3672 }
3673
3674 QWidget *focusWidget = widget;
3675 while (focusWidget) {
3676 if (focusWidget->isEnabled()
3677 && focusWidget->rect().contains(localPos)
3678 && QApplicationPrivate::shouldSetFocus(focusWidget, focusPolicy)) {
3679 focusWidget->setFocus(Qt::MouseFocusReason);
3680 break;
3681 }
3682 if (focusWidget->isWindow())
3683 break;
3684
3685 // find out whether this widget (or its proxy) already has focus
3686 QWidget *f = focusWidget;
3687 if (focusWidget->d_func()->extra && focusWidget->d_func()->extra->focus_proxy)
3688 f = focusWidget->d_func()->extra->focus_proxy;
3689 // if it has, stop here.
3690 // otherwise a click on the focused widget would remove its focus if ClickFocus isn't set
3691 if (f->hasFocus())
3692 break;
3693
3694 localPos += focusWidget->pos();
3695 focusWidget = focusWidget->parentWidget();
3696 }
3697}
3698
3699bool QApplicationPrivate::shouldSetFocus(QWidget *w, Qt::FocusPolicy policy)
3700{
3701 QWidget *f = w;
3702 while (f->d_func()->extra && f->d_func()->extra->focus_proxy)
3703 f = f->d_func()->extra->focus_proxy;
3704
3705 if ((w->focusPolicy() & policy) != policy)
3706 return false;
3707 if (w != f && (f->focusPolicy() & policy) != policy)
3708 return false;
3709 return true;
3710}
3711
3712bool QApplicationPrivate::updateTouchPointsForWidget(QWidget *widget, QTouchEvent *touchEvent)
3713{
3714 bool containsPress = false;
3715
3716 for (qsizetype cnt = touchEvent->pointCount(), i = 0; i < cnt; ++i) {
3717 auto &pt = touchEvent->point(i);
3718 QMutableEventPoint::setPosition(pt, widget->mapFromGlobal(pt.globalPosition()));
3719
3720 if (pt.state() == QEventPoint::State::Pressed)
3721 containsPress = true;
3722 }
3723 return containsPress;
3724}
3725
3726void QApplicationPrivate::initializeMultitouch()
3727{
3728 initializeMultitouch_sys();
3729}
3730
3731void QApplicationPrivate::initializeMultitouch_sys()
3732{
3733}
3734
3735void QApplicationPrivate::cleanupMultitouch()
3736{
3737 cleanupMultitouch_sys();
3738}
3739
3740void QApplicationPrivate::cleanupMultitouch_sys()
3741{
3742}
3743
3744/*! \internal
3745 Check the target widgets of the active touchpoints of the given \a device,
3746 and choose the widget that is closest to any of the points. This widget
3747 will then get all the touchpoints, even if it would not otherwise be the
3748 target for some of them.
3749
3750 \sa translateRawTouchEvent()
3751*/
3752QWidget *QApplicationPrivate::findClosestTouchPointTarget(const QPointingDevice *device, const QEventPoint &touchPoint)
3753{
3754 const QPointF globalPos = touchPoint.globalPosition();
3755 int closestTouchPointId = -1;
3756 QObject *closestTarget = nullptr;
3757 qreal closestDistance = 0;
3758 const QPointingDevicePrivate *devPriv = QPointingDevicePrivate::get(device);
3759 for (auto &epd : devPriv->activePoints.values()) {
3760 const auto &pt = epd.eventPoint;
3761 if (pt.id() != touchPoint.id()) {
3762 qreal dx = globalPos.x() - pt.globalPosition().x();
3763 qreal dy = globalPos.y() - pt.globalPosition().y();
3764 qreal distance = dx * dx + dy * dy;
3765 // closestTouchPointId is -1 at the beginning.
3766 // closestTouchPointId may be 0 if
3767 // a synth-mouse eventPoint was found in activePoints: that's not relevant here.
3768 if (closestTouchPointId <= 0 || distance < closestDistance) {
3769 closestTouchPointId = pt.id();
3770 closestDistance = distance;
3771 closestTarget = QMutableEventPoint::target(pt);
3772 }
3773 }
3774 }
3775 return static_cast<QWidget *>(closestTarget);
3776}
3777
3778void QApplicationPrivate::activateImplicitTouchGrab(QWidget *widget, QTouchEvent *touchEvent,
3779 ImplicitTouchGrabMode grabMode)
3780{
3781 if (touchEvent->type() != QEvent::TouchBegin)
3782 return;
3783
3784 // If the widget dispatched the event further (see QGraphicsProxyWidget), then
3785 // there might already be an implicit grabber. Don't override that. A widget that
3786 // has partially recognized a gesture needs to grab all points.
3787 for (qsizetype cnt = touchEvent->pointCount(), i = 0; i < cnt; ++i) {
3788 auto &ep = touchEvent->point(i);
3789 if (!QMutableEventPoint::target(ep) && (ep.isAccepted() || grabMode == GrabAllPoints))
3790 QMutableEventPoint::setTarget(ep, widget);
3791 }
3792 // TODO setExclusiveGrabber() to be consistent with Qt Quick?
3793}
3794
3795bool QApplicationPrivate::translateRawTouchEvent(QWidget *window, const QTouchEvent *te)
3796{
3797 QApplicationPrivate *d = self;
3798 // TODO get rid of this std::pair
3799 typedef std::pair<QEventPoint::State, QList<QEventPoint> > StatesAndTouchPoints;
3800 QHash<QWidget *, StatesAndTouchPoints> widgetsNeedingEvents;
3801
3802 const auto *device = te->pointingDevice();
3803 auto touchPoints = te->points(); // touch points will be mutated
3804 for (auto &touchPoint : touchPoints) {
3805 // update state
3806 QPointer<QObject> target;
3807 if (touchPoint.state() == QEventPoint::State::Pressed) {
3808 if (device->type() == QInputDevice::DeviceType::TouchPad) {
3809 // on touchpads, send all touch points to the same widget:
3810 // pick the first non-null target if possible
3811 target = QPointingDevicePrivate::get(device)->firstActiveTarget();
3812 }
3813
3814 if (target.isNull()) {
3815 // determine which widget this event will go to
3816 if (!window)
3817 window = QApplication::topLevelAt(touchPoint.globalPosition().toPoint());
3818 if (!window)
3819 continue;
3820 target = window->childAt(window->mapFromGlobal(touchPoint.globalPosition()));
3821 if (!target)
3822 target = window;
3823 }
3824
3825 bool usingClosestWidget = false;
3826 if (device->type() == QInputDevice::DeviceType::TouchScreen) {
3827 QWidget *closestWidget = d->findClosestTouchPointTarget(device, touchPoint);
3828 QWidget *widget = static_cast<QWidget *>(target.data());
3829 if (closestWidget
3830 && (widget->isAncestorOf(closestWidget) || closestWidget->isAncestorOf(widget))) {
3831 target = closestWidget;
3832 usingClosestWidget = true;
3833 }
3834 }
3835
3836 // on touch pads, implicitly grab all touch points
3837 // on touch screens, grab touch points that are redirected to the closest widget
3838 if (device->type() == QInputDevice::DeviceType::TouchPad || usingClosestWidget)
3839 QMutableEventPoint::setTarget(touchPoint, target);
3840 } else {
3841 target = QMutableEventPoint::target(touchPoint);
3842 if (!target)
3843 continue;
3844 }
3845 Q_ASSERT(!target.isNull());
3846
3847 QWidget *targetWidget = static_cast<QWidget *>(target.data());
3848
3849#ifdef Q_OS_MACOS
3850 // Single-touch events are normally not sent unless WA_TouchPadAcceptSingleTouchEvents is set.
3851 // In Qt 4 this check was in OS X-only code. That behavior is preserved here by the #ifdef.
3852 if (touchPoints.count() == 1
3853 && device->type() == QInputDevice::DeviceType::TouchPad
3854 && !targetWidget->testAttribute(Qt::WA_TouchPadAcceptSingleTouchEvents))
3855 continue;
3856#endif
3857
3858 StatesAndTouchPoints &maskAndPoints = widgetsNeedingEvents[targetWidget];
3859 maskAndPoints.first = QEventPoint::State(maskAndPoints.first | touchPoint.state());
3860 maskAndPoints.second.append(touchPoint);
3861 }
3862
3863 if (widgetsNeedingEvents.isEmpty())
3864 return false;
3865
3866 bool accepted = false;
3867 QHash<QWidget *, StatesAndTouchPoints>::ConstIterator it = widgetsNeedingEvents.constBegin();
3868 const QHash<QWidget *, StatesAndTouchPoints>::ConstIterator end = widgetsNeedingEvents.constEnd();
3869 for (; it != end; ++it) {
3870 const QPointer<QWidget> widget = it.key();
3871 if (!QApplicationPrivate::tryModalHelper(widget, nullptr))
3872 continue;
3873
3874 QEvent::Type eventType;
3875 switch (it.value().first) {
3876 case QEventPoint::State::Pressed:
3877 eventType = QEvent::TouchBegin;
3878 break;
3879 case QEventPoint::State::Released:
3880 eventType = QEvent::TouchEnd;
3881 break;
3882 case QEventPoint::State::Stationary:
3883 // don't send the event if nothing changed
3884 continue;
3885 default:
3886 eventType = QEvent::TouchUpdate;
3887 break;
3888 }
3889
3890 QMutableTouchEvent touchEvent(eventType, device, QGuiApplication::keyboardModifiers(),
3891 it.value().second);
3892 bool containsPress = updateTouchPointsForWidget(widget, &touchEvent);
3893 touchEvent.setTimestamp(te->timestamp());
3894 touchEvent.setTarget(widget);
3895
3896 if (containsPress)
3897 widget->setAttribute(Qt::WA_WState_AcceptedTouchBeginEvent);
3898
3899 switch (touchEvent.type()) {
3900 case QEvent::TouchBegin:
3901 {
3902 // if the TouchBegin handler recurses, we assume that means the event
3903 // has been implicitly accepted and continue to send touch events
3904 bool res = te->spontaneous() ? QApplication::sendSpontaneousEvent(widget, &touchEvent)
3905 : QApplication::sendEvent(widget, &touchEvent);
3906 if (res && touchEvent.isAccepted()) {
3907 accepted = true;
3908 if (!widget.isNull())
3909 widget->setAttribute(Qt::WA_WState_AcceptedTouchBeginEvent);
3910 }
3911 break;
3912 }
3913 default:
3914 if (widget->testAttribute(Qt::WA_WState_AcceptedTouchBeginEvent)
3915#ifndef QT_NO_GESTURES
3916 || QGestureManager::gesturePending(widget)
3917#endif
3918 ) {
3919 bool res = te->spontaneous() ? QApplication::sendSpontaneousEvent(widget, &touchEvent)
3920 : QApplication::sendEvent(widget, &touchEvent);
3921 if (res && touchEvent.isAccepted())
3922 accepted = true;
3923 // widget can be deleted on TouchEnd
3924 if (touchEvent.type() == QEvent::TouchEnd && !widget.isNull())
3925 widget->setAttribute(Qt::WA_WState_AcceptedTouchBeginEvent, false);
3926 }
3927 break;
3928 }
3929 }
3930 return accepted;
3931}
3932
3933void QApplicationPrivate::translateTouchCancel(const QPointingDevice *device, ulong timestamp)
3934{
3935 QMutableTouchEvent touchEvent(QEvent::TouchCancel, device, QGuiApplication::keyboardModifiers());
3936 touchEvent.setTimestamp(timestamp);
3937
3938 QSet<QWidget *> widgetsNeedingCancel;
3939 const QPointingDevicePrivate *devPriv = QPointingDevicePrivate::get(device);
3940 for (auto &epd : devPriv->activePoints.values()) {
3941 const auto &pt = epd.eventPoint;
3942 QObject *target = QMutableEventPoint::target(pt);
3943 if (target && target->isWidgetType())
3944 widgetsNeedingCancel.insert(static_cast<QWidget *>(target));
3945 }
3946 for (QSet<QWidget *>::const_iterator widIt = widgetsNeedingCancel.constBegin(),
3947 widItEnd = widgetsNeedingCancel.constEnd(); widIt != widItEnd; ++widIt) {
3948 QWidget *widget = *widIt;
3949 touchEvent.setTarget(widget);
3950 QApplication::sendSpontaneousEvent(widget, &touchEvent);
3951 }
3952}
3953
3954void QApplicationPrivate::handleThemeChanged()
3955{
3956 QGuiApplicationPrivate::handleThemeChanged();
3957
3958 qt_init_tooltip_palette();
3959}
3960
3961#if QT_CONFIG(draganddrop)
3962void QApplicationPrivate::notifyDragStarted(const QDrag *drag)
3963{
3964 QGuiApplicationPrivate::notifyDragStarted(drag);
3965 // QTBUG-26145
3966 // Prevent pickMouseReceiver() from using the widget where the drag was started after a drag operation...
3967 // QTBUG-56713
3968 // ...only if qt_button_down is not a QQuickWidget
3969 if (qt_button_down && !qt_button_down->inherits("QQuickWidget"))
3970 qt_button_down = nullptr;
3971}
3972#endif // QT_CONFIG(draganddrop)
3973
3974#ifndef QT_NO_GESTURES
3975QGestureManager* QGestureManager::instance(InstanceCreation ic)
3976{
3977 QApplicationPrivate *qAppPriv = QApplicationPrivate::instance();
3978 if (!qAppPriv)
3979 return nullptr;
3980 if (!qAppPriv->gestureManager && ic == ForceCreation)
3981 qAppPriv->gestureManager = new QGestureManager(qApp);
3982 return qAppPriv->gestureManager;
3983}
3984#endif // QT_NO_GESTURES
3985
3986QPixmap QApplicationPrivate::applyQIconStyleHelper(QIcon::Mode mode, const QPixmap& base) const
3987{
3988 QStyleOption opt(0);
3989 opt.palette = QGuiApplication::palette();
3990 return QApplication::style()->generatedIconPixmap(mode, base, &opt);
3991}
3992
3993void *QApplication::resolveInterface(const char *name, int revision) const
3994{
3995 return QGuiApplication::resolveInterface(name, revision);
3996}
3997
3998QT_END_NAMESPACE
3999
4000#include "moc_qapplication.cpp"
friend class QWidget
Definition qpainter.h:431
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