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