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