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 (QWindow *w : std::as_const(windowList))
1436 QCoreApplication::sendEvent(w, &ev);
1437}
1438
1439/*!
1440 Returns a list of the top-level widgets (windows) in the application.
1441
1442 \note Some of the top-level widgets may be hidden, for example a tooltip if
1443 no tooltip is currently shown.
1444
1445 Example:
1446
1447 \snippet code/src_gui_kernel_qapplication.cpp 4
1448
1449 \sa allWidgets(), QWidget::isWindow(), QWidget::isHidden()
1450*/
1451QWidgetList QApplication::topLevelWidgets()
1452{
1453 QWidgetList list;
1454 if (QWidgetPrivate::allWidgets != nullptr) {
1455 const auto isTopLevelWidget = [] (const QWidget *w) {
1456 return w->isWindow();
1457 };
1458 std::copy_if(QWidgetPrivate::allWidgets->cbegin(), QWidgetPrivate::allWidgets->cend(),
1459 std::back_inserter(list), isTopLevelWidget);
1460 }
1461 return list;
1462}
1463
1464/*!
1465 Returns a list of all the widgets in the application.
1466
1467 The list is empty (QList::isEmpty()) if there are no widgets.
1468
1469 \note Some of the widgets may be hidden.
1470
1471 Example:
1472 \snippet code/src_gui_kernel_qapplication.cpp 5
1473
1474 \sa topLevelWidgets(), QWidget::isVisible()
1475*/
1476
1477QWidgetList QApplication::allWidgets()
1478{
1479 if (QWidgetPrivate::allWidgets)
1480 return QWidgetPrivate::allWidgets->values();
1481 return QWidgetList();
1482}
1483
1484/*!
1485 Returns the application widget that has the keyboard input focus,
1486 or \nullptr if no widget in this application has the focus.
1487
1488 \sa QWidget::setFocus(), QWidget::hasFocus(), activeWindow(), focusChanged()
1489*/
1490
1491QWidget *QApplication::focusWidget()
1492{
1493 return QApplicationPrivate::focus_widget;
1494}
1495
1496void QApplicationPrivate::setFocusWidget(QWidget *focus, Qt::FocusReason reason)
1497{
1498#if QT_CONFIG(graphicsview)
1499 if (focus && focus->window()->graphicsProxyWidget())
1500 return;
1501#endif
1502
1503 hidden_focus_widget = nullptr;
1504
1505 if (focus != focus_widget) {
1506 if (focus && focus->isHidden()) {
1507 hidden_focus_widget = focus;
1508 return;
1509 }
1510
1511 if (focus) {
1512 if ((reason == Qt::BacktabFocusReason || reason == Qt::TabFocusReason)
1513 && qt_in_tab_key_event)
1514 focus->window()->setAttribute(Qt::WA_KeyboardFocusChange);
1515 else if (reason == Qt::ShortcutFocusReason) {
1516 focus->window()->setAttribute(Qt::WA_KeyboardFocusChange);
1517 } else {
1518 focus->window()->setAttribute(Qt::WA_KeyboardFocusChange, false);
1519 }
1520 }
1521 QWidget *prev = focus_widget;
1522 focus_widget = focus;
1523
1524 if (focus_widget)
1525 focus_widget->d_func()->setFocus_sys();
1526
1527 if (reason != Qt::NoFocusReason) {
1528
1529 //send events
1530 if (prev) {
1531#ifdef QT_KEYPAD_NAVIGATION
1532 if (QApplicationPrivate::keyboardNavigationEnabled()) {
1533 if (prev->hasEditFocus() && reason != Qt::PopupFocusReason)
1534 prev->setEditFocus(false);
1535 }
1536#endif
1537 QFocusEvent out(QEvent::FocusOut, reason);
1538 QPointer<QWidget> that = prev;
1539 QCoreApplication::sendEvent(prev, &out);
1540 if (that)
1541 QCoreApplication::sendEvent(that->style(), &out);
1542 }
1543 if (focus && QApplicationPrivate::focus_widget == focus) {
1544 QFocusEvent in(QEvent::FocusIn, reason);
1545 QPointer<QWidget> that = focus;
1546 QCoreApplication::sendEvent(focus, &in);
1547 if (that)
1548 QCoreApplication::sendEvent(that->style(), &in);
1549 }
1550 emit qApp->focusChanged(prev, focus_widget);
1551 }
1552 }
1553}
1554
1555
1556/*!
1557 Returns the application top-level window that has the keyboard input focus,
1558 or \nullptr if no application window has the focus. There might be an
1559 activeWindow() even if there is no focusWidget(), for example if no widget
1560 in that window accepts key events.
1561
1562 \sa QWidget::setFocus(), QWidget::hasFocus(), focusWidget()
1563*/
1564
1565QWidget *QApplication::activeWindow()
1566{
1567 return QApplicationPrivate::active_window;
1568}
1569
1570/*!
1571 \fn QFontMetrics QApplication::fontMetrics()
1572 \deprecated [6.0] Use QFontMetricsF(qApp->font()) instead.
1573
1574 Returns display (screen) font metrics for the application font. For more
1575 information about the difference between \l QFontMetrics and \l QFontMetricsF,
1576 see the detailed description of \l QFontMetrics.
1577
1578 \sa font(), setFont(), QWidget::fontMetrics(), QPainter::fontMetrics()
1579*/
1580
1581#if QT_DEPRECATED_SINCE(6,0)
1582QFontMetrics QApplication::fontMetrics()
1583{
1584 return QFontMetrics(qApp->font());
1585}
1586#endif
1587
1588bool QApplicationPrivate::tryCloseAllWidgetWindows(QWindowList *processedWindows)
1589{
1590 Q_ASSERT(processedWindows);
1591 while (QWidget *w = QApplication::activeModalWidget()) {
1592 if (!w->isVisible() || w->data->is_closing)
1593 break;
1594 QWindow *window = w->windowHandle();
1595 if (!window->close()) // Qt::WA_DeleteOnClose may cause deletion.
1596 return false;
1597 if (window)
1598 processedWindows->append(window);
1599 }
1600
1601retry:
1602 const QWidgetList list = QApplication::topLevelWidgets();
1603 for (auto *w : list) {
1604 if (w->isVisible() && !w->testAttribute(Qt::WA_DontShowOnScreen) && !w->data->is_closing) {
1605 QWindow *window = w->windowHandle();
1606 if (!window->close()) // Qt::WA_DeleteOnClose may cause deletion.
1607 return false;
1608 if (window)
1609 processedWindows->append(window);
1610 goto retry;
1611 }
1612 }
1613 return true;
1614}
1615
1616/*!
1617 Closes all top-level windows.
1618
1619 This function is particularly useful for applications with many top-level
1620 windows.
1621
1622 The windows are closed in random order, until one window does not accept
1623 the close event. The application quits when the last window was successfully
1624 closed, unless \l quitOnLastWindowClosed is set to false. To trigger application
1625 termination from e.g. a menu, use QCoreApplication::quit() instead of this
1626 function.
1627
1628 \sa quitOnLastWindowClosed, lastWindowClosed(), QWidget::close(),
1629 QWidget::closeEvent(), lastWindowClosed(), QCoreApplication::quit(),
1630 topLevelWidgets(), QWidget::isWindow()
1631*/
1632void QApplication::closeAllWindows()
1633{
1634 QWindowList processedWindows;
1635 QApplicationPrivate::tryCloseAllWidgetWindows(&processedWindows);
1636}
1637
1638/*!
1639 Displays a simple message box about Qt. The message includes the version
1640 number of Qt being used by the application.
1641
1642 This is useful for inclusion in the \uicontrol Help menu of an application, as
1643 shown in the \l{mainwindows/menus}{Menus} example.
1644
1645 This function is a convenience slot for QMessageBox::aboutQt().
1646*/
1647void QApplication::aboutQt()
1648{
1649#if QT_CONFIG(messagebox)
1650 QMessageBox::aboutQt(activeWindow());
1651#endif // QT_CONFIG(messagebox)
1652}
1653
1654/*!
1655 \since 4.1
1656 \fn void QApplication::focusChanged(QWidget *old, QWidget *now)
1657
1658 This signal is emitted when the widget that has keyboard focus changed from
1659 \a old to \a now, i.e., because the user pressed the tab-key, clicked into
1660 a widget or changed the active window. Both \a old and \a now can be \nullptr.
1661
1662
1663 The signal is emitted after both widget have been notified about the change
1664 through QFocusEvent.
1665
1666 \sa QWidget::setFocus(), QWidget::clearFocus(), Qt::FocusReason
1667*/
1668
1669/*!\reimp
1670
1671*/
1672bool QApplication::event(QEvent *e)
1673{
1674 Q_D(QApplication);
1675 switch (e->type()) {
1676 case QEvent::Quit:
1677 // FIXME: This logic first tries to close all windows, and then
1678 // checks whether it was successful, but the conditions used in
1679 // closeAllWindows() differ from the verification logic below.
1680 // We should build on the logic in tryCloseAllWidgetWindows().
1681 closeAllWindows();
1682 for (auto *w : topLevelWidgets()) {
1683 if (w->data->is_closing)
1684 continue;
1685 if (w->isVisible() && !(w->windowType() == Qt::Popup) &&
1686 (!(w->windowType() == Qt::Dialog) || !w->parentWidget()) && !w->testAttribute(Qt::WA_DontShowOnScreen)) {
1687 e->ignore();
1688 return true;
1689 }
1690 }
1691 // Explicitly call QCoreApplication instead of QGuiApplication so that
1692 // we don't let QGuiApplication close any windows we skipped earlier in
1693 // closeAllWindows(). FIXME: Unify all this close magic through closeAllWindows.
1694 return QCoreApplication::event(e);
1695#ifndef Q_OS_WIN
1696 case QEvent::LocaleChange: {
1697 // on Windows the event propagation is taken care by the
1698 // WM_SETTINGCHANGE event handler.
1699 const QWidgetList list = topLevelWidgets();
1700 for (auto *w : list) {
1701 if (!w->testAttribute(Qt::WA_SetLocale))
1702 w->d_func()->setLocale_helper(QLocale(), true);
1703 }
1704 break;
1705 }
1706#endif
1707 case QEvent::Timer: {
1708 QTimerEvent *te = static_cast<QTimerEvent*>(e);
1709 Q_ASSERT(te != nullptr);
1710 if (te->timerId() == d->toolTipWakeUp.timerId()) {
1711 d->toolTipWakeUp.stop();
1712 if (d->toolTipWidget) {
1713 QWidget *w = d->toolTipWidget->window();
1714 // show tooltip if WA_AlwaysShowToolTips is set, or if
1715 // any ancestor of d->toolTipWidget is the active
1716 // window
1717 bool showToolTip = w->testAttribute(Qt::WA_AlwaysShowToolTips);
1718 while (w && !showToolTip) {
1719 showToolTip = w->isActiveWindow();
1720 w = w->parentWidget();
1721 w = w ? w->window() : nullptr;
1722 }
1723 if (showToolTip) {
1724 QHelpEvent e(QEvent::ToolTip, d->toolTipPos, d->toolTipGlobalPos);
1725 QCoreApplication::sendEvent(d->toolTipWidget, &e);
1726 if (e.isAccepted()) {
1727 QStyle *s = d->toolTipWidget->style();
1728 int sleepDelay = s->styleHint(QStyle::SH_ToolTip_FallAsleepDelay, nullptr, d->toolTipWidget, nullptr);
1729 d->toolTipFallAsleep.start(sleepDelay, this);
1730 }
1731 }
1732 }
1733 } else if (te->timerId() == d->toolTipFallAsleep.timerId()) {
1734 d->toolTipFallAsleep.stop();
1735 }
1736 break;
1737 }
1738#if QT_CONFIG(whatsthis)
1739 case QEvent::EnterWhatsThisMode:
1740 QWhatsThis::enterWhatsThisMode();
1741 return true;
1742#endif
1743 case QEvent::LanguageChange:
1744 case QEvent::ApplicationFontChange:
1745 case QEvent::ApplicationPaletteChange: {
1746 // QGuiApplication::event does not account for the cases where
1747 // there is a top level widget without a window handle. So they
1748 // need to have the event posted here
1749 const QWidgetList list = topLevelWidgets();
1750 for (auto *w : list) {
1751 if (!w->windowHandle())
1752 postEvent(w, new QEvent(e->type()));
1753 }
1754 break;
1755 }
1756 default:
1757 break;
1758 }
1759
1760 return QGuiApplication::event(e);
1761}
1762
1763// ### FIXME: topLevelWindows does not contain QWidgets without a parent
1764// until QWidgetPrivate::create is called. So we have to override the
1765// QGuiApplication::notifyLayoutDirectionChange
1766// to do the right thing.
1767void QApplicationPrivate::notifyLayoutDirectionChange()
1768{
1769 const QWidgetList list = QApplication::topLevelWidgets();
1770 QWindowList windowList = QGuiApplication::topLevelWindows();
1771
1772 // send to all top-level QWidgets
1773 for (auto *w : list) {
1774 windowList.removeAll(w->windowHandle());
1775 QEvent ev(QEvent::ApplicationLayoutDirectionChange);
1776 QCoreApplication::sendEvent(w, &ev);
1777 }
1778
1779 // in case there are any plain QWindows in this QApplication-using
1780 // application, also send the notification to them
1781 for (QWindow *w: std::as_const(windowList)) {
1782 QEvent ev(QEvent::ApplicationLayoutDirectionChange);
1783 QCoreApplication::sendEvent(w, &ev);
1784 }
1785}
1786
1787/*!
1788 \fn void QApplication::setActiveWindow(QWidget* active)
1789 \deprecated [6.5] Use QWidget::activateWindow() instead.
1790
1791 Sets the active window to the \a active widget in response to a system
1792 event. The function is called from the platform specific event handlers.
1793
1794 \warning This function does \e not set the keyboard focus to the active
1795 widget. Call QWidget::activateWindow() instead.
1796
1797 It sets the activeWindow() and focusWidget() attributes and sends proper
1798 \l{QEvent::WindowActivate}{WindowActivate}/\l{QEvent::WindowDeactivate}
1799 {WindowDeactivate} and \l{QEvent::FocusIn}{FocusIn}/\l{QEvent::FocusOut}
1800 {FocusOut} events to all appropriate widgets. The window will then be
1801 painted in active state (e.g. cursors in line edits will blink), and it
1802 will have tool tips enabled.
1803
1804 \sa activeWindow(), QWidget::activateWindow()
1805*/
1806#if QT_DEPRECATED_SINCE(6,5)
1807void QApplication::setActiveWindow(QWidget* act)
1808{
1809 QApplicationPrivate::setActiveWindow(act);
1810}
1811#endif
1812
1813void QApplicationPrivate::setActiveWindow(QWidget* act)
1814{
1815 QWidget* window = act?act->window():nullptr;
1816
1817 if (QApplicationPrivate::active_window == window)
1818 return;
1819
1820#if QT_CONFIG(graphicsview)
1821 if (window && window->graphicsProxyWidget()) {
1822 // Activate the proxy's view->viewport() ?
1823 return;
1824 }
1825#endif
1826
1827 QWidgetList toBeActivated;
1828 QWidgetList toBeDeactivated;
1829
1830 if (QApplicationPrivate::active_window) {
1831 if (QApplication::style()->styleHint(QStyle::SH_Widget_ShareActivation, nullptr, QApplicationPrivate::active_window)) {
1832 const QWidgetList list = QApplication::topLevelWidgets();
1833 for (auto *w : list) {
1834 if (w->isVisible() && w->isActiveWindow())
1835 toBeDeactivated.append(w);
1836 }
1837 } else {
1838 toBeDeactivated.append(QApplicationPrivate::active_window);
1839 }
1840 }
1841
1842 if (QApplicationPrivate::focus_widget) {
1843 if (QApplicationPrivate::focus_widget->testAttribute(Qt::WA_InputMethodEnabled))
1844 QGuiApplication::inputMethod()->commit();
1845
1846 QFocusEvent focusAboutToChange(QEvent::FocusAboutToChange, Qt::ActiveWindowFocusReason);
1847 QCoreApplication::sendEvent(QApplicationPrivate::focus_widget, &focusAboutToChange);
1848 }
1849
1850 QApplicationPrivate::active_window = window;
1851
1852 if (QApplicationPrivate::active_window) {
1853 if (QApplication::style()->styleHint(QStyle::SH_Widget_ShareActivation, nullptr, QApplicationPrivate::active_window)) {
1854 const QWidgetList list = QApplication::topLevelWidgets();
1855 for (auto *w : list) {
1856 if (w->isVisible() && w->isActiveWindow())
1857 toBeActivated.append(w);
1858 }
1859 } else {
1860 toBeActivated.append(QApplicationPrivate::active_window);
1861 }
1862
1863 }
1864
1865 // first the activation/deactivation events
1866 QEvent activationChange(QEvent::ActivationChange);
1867 QEvent windowActivate(QEvent::WindowActivate);
1868 QEvent windowDeactivate(QEvent::WindowDeactivate);
1869
1870 for (QWidget *w : std::as_const(toBeActivated)) {
1871 QApplication::sendSpontaneousEvent(w, &windowActivate);
1872 QApplication::sendSpontaneousEvent(w, &activationChange);
1873 }
1874
1875 for (QWidget *w : std::as_const(toBeDeactivated)) {
1876 QApplication::sendSpontaneousEvent(w, &windowDeactivate);
1877 QApplication::sendSpontaneousEvent(w, &activationChange);
1878 }
1879
1880 if (!inPopupMode()) {
1881 // then focus events
1882 if (!QApplicationPrivate::active_window && QApplicationPrivate::focus_widget) {
1883 QApplicationPrivate::setFocusWidget(nullptr, Qt::ActiveWindowFocusReason);
1884 } else if (QApplicationPrivate::active_window) {
1885 QWidget *w = QApplicationPrivate::active_window->focusWidget();
1886 if (w && w->isVisible() /*&& w->focusPolicy() != QWidget::NoFocus*/)
1887 w->setFocus(Qt::ActiveWindowFocusReason);
1888 else {
1889 w = QApplicationPrivate::focusNextPrevChild_helper(QApplicationPrivate::active_window, true);
1890 if (w) {
1891 w->setFocus(Qt::ActiveWindowFocusReason);
1892 } else {
1893 w = QApplicationPrivate::focus_widget;
1894 if (!w && QApplicationPrivate::active_window->focusPolicy() != Qt::NoFocus) {
1895 QApplicationPrivate::active_window->setFocus(Qt::ActiveWindowFocusReason);
1896 } else if (!QApplicationPrivate::active_window->isAncestorOf(w)) {
1897 // If the focus widget is not in the activate_window, clear the focus
1898 QApplicationPrivate::setFocusWidget(nullptr, Qt::ActiveWindowFocusReason);
1899 }
1900 }
1901 }
1902 }
1903 }
1904}
1905
1907{
1908 // QTBUG-32177, wnd might be a QQuickView embedded via window container.
1909 while (wnd && !wnd->isTopLevel()) {
1910 QWindow *parent = wnd->parent();
1911 if (!parent)
1912 break;
1913
1914 // Don't end up in windows not belonging to this application
1915 if (parent->handle() && parent->handle()->isForeignWindow())
1916 break;
1917
1918 wnd = wnd->parent();
1919 }
1920 if (wnd) {
1921 const auto tlws = QApplication::topLevelWidgets();
1922 for (QWidget *tlw : tlws) {
1923 if (tlw->windowHandle() == wnd)
1924 return tlw;
1925 }
1926 }
1927 return nullptr;
1928}
1929
1930void QApplicationPrivate::notifyActiveWindowChange(QWindow *previous)
1931{
1932#ifndef Q_OS_MACOS
1933 // Some delayed focus event to ignore, unless we are on cocoa where
1934 // popups can be opened via right-click on inactive applications
1935 if (inPopupMode())
1936 return;
1937#endif
1938 QWindow *focusWindow = QGuiApplicationPrivate::focus_window;
1939 QWidget *focusWidget = qt_tlw_for_window(focusWindow);
1940 QApplicationPrivate::setActiveWindow(focusWidget);
1941 // QTBUG-37126, Active X controls may set the focus on native child widgets.
1942 if (focusWindow && focusWidget && focusWindow != focusWidget->windowHandle()) {
1943 if (QWidgetWindow *widgetWindow = qobject_cast<QWidgetWindow *>(focusWindow))
1944 if (QWidget *widget = widgetWindow->widget())
1945 if (widget->inherits("QAxHostWidget"))
1946 widget->setFocus(Qt::ActiveWindowFocusReason);
1947 }
1948
1949 // QApplication::setActiveWindow() will deliver window activation events for
1950 // QWidgetWindows. But for other subclasses of QWindow (like QQuickWindow), we
1951 // need to send them explicitly, like we do from the base class implementation.
1952 if (previous && !qobject_cast<QWidgetWindow *>(previous)) {
1953 QEvent de(QEvent::WindowDeactivate);
1954 QCoreApplication::sendEvent(previous, &de);
1955 }
1956
1957 if (focusWindow && !qobject_cast<QWidgetWindow *>(focusWindow)) {
1958 QEvent ae(QEvent::WindowActivate);
1959 QCoreApplication::sendEvent(focusWindow, &ae);
1960 }
1961
1962 // don't call base class to avoid double delivery of WindowActivate/Deactivate events
1963}
1964
1965/*!internal
1966 * Helper function that returns the new focus widget, but does not set the focus reason.
1967 * Returns \nullptr if a new focus widget could not be found.
1968 * Shared with QGraphicsProxyWidgetPrivate::findFocusChild()
1969*/
1970QWidget *QApplicationPrivate::focusNextPrevChild_helper(QWidget *toplevel, bool next,
1971 bool *wrappingOccurred)
1972{
1973 uint focus_flag = qt_tab_all_widgets() ? Qt::TabFocus : Qt::StrongFocus;
1974
1975 QWidget *f = toplevel->focusWidget();
1976 if (!f)
1977 f = toplevel;
1978
1979 QWidget *w = f;
1980 QWidget *test = f->nextInFocusChain();
1981 bool seenWindow = false;
1982 bool focusWidgetAfterWindow = false;
1983 while (test && test != f) {
1984 if (test->isWindow())
1985 seenWindow = true;
1986
1987 // If the next focus widget has a focus proxy, we need to check to ensure
1988 // that the proxy is in the correct parent-child direction (according to
1989 // \a next). This is to ensure that we can tab in and out of compound widgets
1990 // without getting stuck in a tab-loop between parent and child.
1991 QWidget *focusProxy = test->d_func()->deepestFocusProxy();
1992 auto effectiveFocusPolicy = [](QWidget *widget) {
1993 return widget->isEnabled() ? widget->focusPolicy() : Qt::NoFocus;
1994 };
1995 const bool canTakeFocus = (effectiveFocusPolicy(focusProxy ? focusProxy : test)
1996 & focus_flag) == focus_flag;
1997 const bool composites = focusProxy ? (next ? focusProxy->isAncestorOf(test)
1998 : test->isAncestorOf(focusProxy))
1999 : false;
2000 if (canTakeFocus && !composites
2001 && test->isVisibleTo(toplevel) && test->isEnabled()
2002 && !(w->windowType() == Qt::SubWindow && !w->isAncestorOf(test))
2003 && (toplevel->windowType() != Qt::SubWindow || toplevel->isAncestorOf(test))
2004 && f != focusProxy) {
2005 w = test;
2006 if (seenWindow)
2007 focusWidgetAfterWindow = true;
2008 if (next)
2009 break;
2010 }
2011 test = test->nextInFocusChain();
2012 }
2013
2014 if (wrappingOccurred != nullptr)
2015 *wrappingOccurred = next ? focusWidgetAfterWindow : !focusWidgetAfterWindow;
2016
2017 if (w == f) {
2018 if (qt_in_tab_key_event) {
2019 w->window()->setAttribute(Qt::WA_KeyboardFocusChange);
2020 w->update();
2021 }
2022 return nullptr;
2023 }
2024 return w;
2025}
2026
2027/*!
2028 \fn void QApplicationPrivate::dispatchEnterLeave(QWidget* enter, QWidget* leave, const QPointF &globalPosF)
2029 \internal
2030
2031 Creates the proper Enter/Leave event when widget \a enter is entered and
2032 widget \a leave is left.
2033 */
2034void QApplicationPrivate::dispatchEnterLeave(QWidget* enter, QWidget* leave, const QPointF &globalPosF)
2035{
2036 if ((!enter && !leave) || (enter == leave))
2037 return;
2038
2039 QWidgetList leaveList;
2040 QWidgetList enterList;
2041
2042 bool sameWindow = leave && enter && leave->window() == enter->window();
2043 if (leave && !sameWindow) {
2044 auto *w = leave;
2045 do {
2046 leaveList.append(w);
2047 } while (!w->isWindow() && (w = w->parentWidget()));
2048 }
2049 if (enter && !sameWindow) {
2050 auto *w = enter;
2051 do {
2052 enterList.append(w);
2053 } while (!w->isWindow() && (w = w->parentWidget()));
2054 }
2055 if (sameWindow) {
2056 int enterDepth = 0;
2057 int leaveDepth = 0;
2058 auto *e = enter;
2059 while (!e->isWindow() && (e = e->parentWidget()))
2060 enterDepth++;
2061 auto *l = leave;
2062 while (!l->isWindow() && (l = l->parentWidget()))
2063 leaveDepth++;
2064 QWidget* wenter = enter;
2065 QWidget* wleave = leave;
2066 while (enterDepth > leaveDepth) {
2067 wenter = wenter->parentWidget();
2068 enterDepth--;
2069 }
2070 while (leaveDepth > enterDepth) {
2071 wleave = wleave->parentWidget();
2072 leaveDepth--;
2073 }
2074 while (!wenter->isWindow() && wenter != wleave) {
2075 wenter = wenter->parentWidget();
2076 wleave = wleave->parentWidget();
2077 }
2078
2079 for (auto *w = leave; w != wleave; w = w->parentWidget())
2080 leaveList.append(w);
2081
2082 for (auto *w = enter; w != wenter; w = w->parentWidget())
2083 enterList.append(w);
2084 }
2085
2086 QEvent leaveEvent(QEvent::Leave);
2087 for (QWidget *w : std::as_const(leaveList)) {
2088 if (!QApplication::activeModalWidget() || QApplicationPrivate::tryModalHelper(w, nullptr)) {
2089 QCoreApplication::sendEvent(w, &leaveEvent);
2090 if (w->testAttribute(Qt::WA_Hover) &&
2091 (!QApplication::activePopupWidget() || QApplication::activePopupWidget() == w->window())) {
2092 Q_ASSERT(instance());
2093 QHoverEvent he(QEvent::HoverLeave, QPointF(-1, -1), globalPosF, w->mapFromGlobal(globalPosF),
2094 QGuiApplication::keyboardModifiers());
2095 qApp->d_func()->notify_helper(w, &he);
2096 }
2097 }
2098 }
2099 if (!enterList.isEmpty()) {
2100 // Guard against QGuiApplicationPrivate::lastCursorPosition initialized to qInf(), qInf().
2101 const QPointF globalPos = qIsInf(globalPosF.x())
2103 : globalPosF;
2104 const QPointF windowPos = std::as_const(enterList).back()->window()->mapFromGlobal(globalPos);
2105 for (auto it = enterList.crbegin(), end = enterList.crend(); it != end; ++it) {
2106 auto *w = *it;
2107 if (!QApplication::activeModalWidget() || QApplicationPrivate::tryModalHelper(w, nullptr)) {
2108 const QPointF localPos = w->mapFromGlobal(globalPos);
2109 QEnterEvent enterEvent(localPos, windowPos, globalPos);
2110 QCoreApplication::sendEvent(w, &enterEvent);
2111 if (w->testAttribute(Qt::WA_Hover) &&
2112 (!QApplication::activePopupWidget() || QApplication::activePopupWidget() == w->window())) {
2113 QHoverEvent he(QEvent::HoverEnter, windowPos, QPointF(-1, -1), globalPos,
2114 QGuiApplication::keyboardModifiers());
2115 QMutableEventPoint::setPosition(he.point(0), localPos);
2116 qApp->d_func()->notify_helper(w, &he);
2117 }
2118 }
2119 }
2120 }
2121
2122#ifndef QT_NO_CURSOR
2123 // Update cursor for alien/graphics widgets.
2124
2125 const bool enterOnAlien = (enter && (isAlien(enter) || enter->testAttribute(Qt::WA_DontShowOnScreen)));
2126 // Whenever we leave an alien widget on X11/QPA, we need to reset its nativeParentWidget()'s cursor.
2127 // This is not required on Windows as the cursor is reset on every single mouse move.
2128 QWidget *parentOfLeavingCursor = nullptr;
2129 for (QWidget *w : std::as_const(leaveList)) {
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 (qsizetype cnt = touchEvent->pointCount(), i = 0; i < cnt; ++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 (QGesture *g : std::as_const(gestures)) {
3168 // Ignore res [event return value] because handling of multiple gestures
3169 // packed into a single QEvent depends on not consuming the event
3170 if (eventAccepted || ge.isAccepted(g)) {
3171 // if the gesture was accepted, mark the target widget for it
3172 gestureEvent->m_targetWidgets[g->gestureType()] = w;
3173 gestureEvent->setAccepted(g, true);
3174 } else {
3175 // if the gesture was explicitly ignored by the application,
3176 // put it back so a parent can get it
3177 allGestures.append(g);
3178 }
3179 }
3180 }
3181 if (allGestures.isEmpty()) // everything delivered
3182 break;
3183 if (w->isWindow())
3184 break;
3185 w = w->parentWidget();
3186 }
3187 for (QGesture *g : std::as_const(allGestures))
3188 gestureEvent->setAccepted(g, false);
3189 gestureEvent->m_accept = false; // to make sure we check individual gestures
3190 break;
3191 }
3192#endif // QT_NO_GESTURES
3193#ifdef Q_OS_MAC
3194 // Enable touch events on enter, disable on leave.
3195 typedef void (*RegisterTouchWindowFn)(QWindow *, bool);
3196 case QEvent::Enter:
3197 if (w->testAttribute(Qt::WA_AcceptTouchEvents)) {
3198 RegisterTouchWindowFn registerTouchWindow = reinterpret_cast<RegisterTouchWindowFn>(
3199 QFunctionPointer(platformNativeInterface()->nativeResourceFunctionForIntegration("registertouchwindow")));
3200 if (registerTouchWindow)
3201 registerTouchWindow(w->window()->windowHandle(), true);
3202 }
3203 res = d->notify_helper(receiver, e);
3204 break;
3205 case QEvent::Leave:
3206 if (w->testAttribute(Qt::WA_AcceptTouchEvents)) {
3207 RegisterTouchWindowFn registerTouchWindow = reinterpret_cast<RegisterTouchWindowFn>(
3208 QFunctionPointer(platformNativeInterface()->nativeResourceFunctionForIntegration("registertouchwindow")));
3209 if (registerTouchWindow)
3210 registerTouchWindow(w->window()->windowHandle(), false);
3211 }
3212 res = d->notify_helper(receiver, e);
3213 break;
3214#endif
3215 default:
3216 res = d->notify_helper(receiver, e);
3217 break;
3218 }
3219 } else {
3220 res = d->notify_helper(receiver, e);
3221 }
3222
3223 return res;
3224}
3225
3226bool QApplicationPrivate::notify_helper(QObject *receiver, QEvent * e)
3227{
3228 // These tracepoints (and the whole function, actually) are very similar
3229 // to the ones in QCoreApplicationPrivate::notify_helper; the reason for their
3230 // duplication is because tracepoint symbols are not exported by QtCore.
3231 // If you adjust the tracepoints here, consider adjusting QCoreApplicationPrivate too.
3232 Q_TRACE(QApplication_notify_entry, receiver, e, e->type());
3233 bool consumed = false;
3234 bool filtered = false;
3235 Q_TRACE_EXIT(QApplication_notify_exit, consumed, filtered);
3236
3237 // send to all application event filters
3238 QThreadData *threadData = receiver->d_func()->threadData.loadRelaxed();
3239 if (threadData->requiresCoreApplication
3240 && threadData->thread.loadAcquire() == mainThread()
3241 && sendThroughApplicationEventFilters(receiver, e)) {
3242 filtered = true;
3243 return filtered;
3244 }
3245
3246 if (receiver->isWidgetType()) {
3247 QWidget *widget = static_cast<QWidget *>(receiver);
3248
3249#if !defined(QT_NO_CURSOR)
3250 // toggle HasMouse widget state on enter and leave
3251 if ((e->type() == QEvent::Enter || e->type() == QEvent::DragEnter) &&
3252 (!QApplication::activePopupWidget() || QApplication::activePopupWidget() == widget->window()))
3253 widget->setAttribute(Qt::WA_UnderMouse, true);
3254 else if (e->type() == QEvent::Leave || e->type() == QEvent::DragLeave)
3255 widget->setAttribute(Qt::WA_UnderMouse, false);
3256#endif
3257
3258 if (QLayout *layout=widget->d_func()->layout) {
3259 layout->widgetEvent(e);
3260 }
3261 }
3262
3263 // send to all receiver event filters
3264 if (sendThroughObjectEventFilters(receiver, e)) {
3265 filtered = true;
3266 return filtered;
3267 }
3268
3269 // deliver the event
3270 consumed = receiver->event(e);
3271
3272 QCoreApplicationPrivate::setEventSpontaneous(e, false);
3273 return consumed;
3274}
3275
3276bool QApplicationPrivate::inPopupMode()
3277{
3278 return QGuiApplicationPrivate::activePopupWindow() != nullptr;
3279}
3280
3281static void ungrabKeyboardForPopup(QWidget *popup)
3282{
3283 qCDebug(lcWidgetPopup) << "ungrab keyboard for" << popup;
3284 if (QWidget::keyboardGrabber())
3285 qt_widget_private(QWidget::keyboardGrabber())->stealKeyboardGrab(true);
3286 else
3287 qt_widget_private(popup)->stealKeyboardGrab(false);
3288}
3289
3290static void ungrabMouseForPopup(QWidget *popup)
3291{
3292 qCDebug(lcWidgetPopup) << "ungrab mouse for" << popup;
3293 if (QWidget::mouseGrabber())
3294 qt_widget_private(QWidget::mouseGrabber())->stealMouseGrab(true);
3295 else
3296 qt_widget_private(popup)->stealMouseGrab(false);
3297}
3298
3299static bool popupGrabOk;
3300
3301static void grabForPopup(QWidget *popup)
3302{
3303 Q_ASSERT(popup->testAttribute(Qt::WA_WState_Created));
3304 popupGrabOk = qt_widget_private(popup)->stealKeyboardGrab(true);
3305 if (popupGrabOk) {
3306 popupGrabOk = qt_widget_private(popup)->stealMouseGrab(true);
3307 if (!popupGrabOk) {
3308 // transfer grab back to the keyboard grabber if any
3309 ungrabKeyboardForPopup(popup);
3310 }
3311 }
3312 qCDebug(lcWidgetPopup) << "grabbed mouse and keyboard?" << popupGrabOk << "for popup" << popup;
3313}
3314
3315void QApplicationPrivate::closePopup(QWidget *popup)
3316{
3317 QWindow *win = popup->windowHandle();
3318 if (!win)
3319 return;
3320 if (!QGuiApplicationPrivate::closePopup(win))
3321 return;
3322
3323 const QWindow *nextRemainingPopup = QGuiApplicationPrivate::activePopupWindow();
3324 if (!nextRemainingPopup) { // this was the last popup
3325
3326 if (popupGrabOk) {
3327 popupGrabOk = false;
3328
3329 if (active_window && active_window->windowHandle()
3330 && !popup->geometry().contains(QGuiApplicationPrivate::lastCursorPosition.toPoint())
3331 && !popup->testAttribute(Qt::WA_NoMouseReplay)) {
3332 QApplicationPrivate::replayMousePress = true;
3333 }
3334
3335 // transfer grab back to mouse grabber if any, otherwise release the grab
3336 ungrabMouseForPopup(popup);
3337
3338 // transfer grab back to keyboard grabber if any, otherwise release the grab
3339 ungrabKeyboardForPopup(popup);
3340 }
3341
3342 if (active_window) {
3343 if (QWidget *fw = active_window->focusWidget()) {
3344 if (fw != QApplication::focusWidget()) {
3345 fw->setFocus(Qt::PopupFocusReason);
3346 } else {
3347 QFocusEvent e(QEvent::FocusIn, Qt::PopupFocusReason);
3348 QCoreApplication::sendEvent(fw, &e);
3349 }
3350 }
3351 }
3352
3353 } else if (const auto *popupWin = qobject_cast<const QWidgetWindow *>(nextRemainingPopup)) {
3354 // A popup was closed, so the previous popup gets the focus.
3355 if (QWidget *fw = popupWin->widget()->focusWidget())
3356 fw->setFocus(Qt::PopupFocusReason);
3357
3358 // can become nullptr due to setFocus() above
3359 if (QGuiApplicationPrivate::popupCount() == 1) // grab mouse/keyboard
3360 grabForPopup(popupWin->widget());
3361 }
3362
3363}
3364
3365void QApplicationPrivate::openPopup(QWidget *popup)
3366{
3367 QGuiApplicationPrivate::activatePopup(popup->windowHandle());
3368
3369 if (QGuiApplicationPrivate::popupCount() == 1) // grab mouse/keyboard
3370 grabForPopup(popup);
3371
3372 // popups are not focus-handled by the window system (the first
3373 // popup grabbed the keyboard), so we have to do that manually: A
3374 // new popup gets the focus
3375 if (popup->focusWidget()) {
3376 popup->focusWidget()->setFocus(Qt::PopupFocusReason);
3377 } else if (QGuiApplicationPrivate::popupCount() == 1) { // this was the first popup
3378 if (QWidget *fw = QApplication::focusWidget()) {
3379 QFocusEvent e(QEvent::FocusOut, Qt::PopupFocusReason);
3380 QCoreApplication::sendEvent(fw, &e);
3381 }
3382 }
3383}
3384
3385#ifdef QT_KEYPAD_NAVIGATION
3386/*!
3387 Sets the kind of focus navigation Qt should use to \a mode.
3388
3389 This feature is available in Qt for Embedded Linux only.
3390
3391 \since 4.6
3392*/
3393void QApplication::setNavigationMode(Qt::NavigationMode mode)
3394{
3395 QApplicationPrivate::navigationMode = mode;
3396}
3397
3398/*!
3399 Returns what kind of focus navigation Qt is using.
3400
3401 This feature is available in Qt for Embedded Linux only.
3402
3403 \since 4.6
3404*/
3405Qt::NavigationMode QApplication::navigationMode()
3406{
3407 return QApplicationPrivate::navigationMode;
3408}
3409#endif
3410
3411/*!
3412 \fn void QApplication::alert(QWidget *widget, int msec)
3413 \since 4.3
3414
3415 Causes an alert to be shown for \a widget if the window is not the active
3416 window. The alert is shown for \a msec milliseconds. If \a msec is zero (the
3417 default), then the alert is shown indefinitely until the window becomes
3418 active again.
3419
3420 Currently this function does nothing on Qt for Embedded Linux.
3421
3422 On \macos, this works more at the application level and will cause the
3423 application icon to bounce in the dock.
3424
3425 On Windows, this causes the window's taskbar entry to flash for a time. If
3426 \a msec is zero, the flashing will stop and the taskbar entry will turn a
3427 different color (currently orange).
3428
3429 On X11, this will cause the window to be marked as "demands attention", the
3430 window must not be hidden (i.e. not have hide() called on it, but be
3431 visible in some sort of way) in order for this to work.
3432*/
3433void QApplication::alert(QWidget *widget, int duration)
3434{
3435 if (widget) {
3436 if (widget->window()->isActiveWindow() && !(widget->window()->windowState() & Qt::WindowMinimized))
3437 return;
3438 if (QWindow *window= QApplicationPrivate::windowForWidget(widget))
3439 window->alert(duration);
3440 } else {
3441 const auto topLevels = topLevelWidgets();
3442 for (QWidget *topLevel : topLevels)
3443 QApplication::alert(topLevel, duration);
3444 }
3445}
3446
3447/*!
3448 \property QApplication::cursorFlashTime
3449 \brief the text cursor's flash (blink) time in milliseconds
3450
3451 The flash time is the time required to display, invert and restore the
3452 caret display. Usually the text cursor is displayed for half the cursor
3453 flash time, then hidden for the same amount of time, but this may vary.
3454
3455 The default value on X11 is 1000 milliseconds. On Windows, the
3456 \uicontrol{Control Panel} value is used and setting this property sets the cursor
3457 flash time for all applications.
3458
3459 We recommend that widgets do not cache this value as it may change at any
3460 time if the user changes the global desktop settings.
3461
3462 \note This property may hold a negative value, for instance if cursor
3463 blinking is disabled.
3464*/
3465void QApplication::setCursorFlashTime(int msecs)
3466{
3467 QGuiApplication::styleHints()->setCursorFlashTime(msecs);
3468}
3469
3470int QApplication::cursorFlashTime()
3471{
3472 return QGuiApplication::styleHints()->cursorFlashTime();
3473}
3474
3475/*!
3476 \property QApplication::doubleClickInterval
3477 \brief the time limit in milliseconds that distinguishes a double click
3478 from two consecutive mouse clicks
3479
3480 The default value on X11 is 400 milliseconds. On Windows and Mac OS, the
3481 operating system's value is used.
3482*/
3483void QApplication::setDoubleClickInterval(int ms)
3484{
3485 QGuiApplication::styleHints()->setMouseDoubleClickInterval(ms);
3486}
3487
3488int QApplication::doubleClickInterval()
3489{
3490 return QGuiApplication::styleHints()->mouseDoubleClickInterval();
3491}
3492
3493/*!
3494 \property QApplication::keyboardInputInterval
3495 \brief the time limit in milliseconds that distinguishes a key press
3496 from two consecutive key presses
3497 \since 4.2
3498
3499 The default value on X11 is 400 milliseconds. On Windows and Mac OS, the
3500 operating system's value is used.
3501*/
3502void QApplication::setKeyboardInputInterval(int ms)
3503{
3504 QGuiApplication::styleHints()->setKeyboardInputInterval(ms);
3505}
3506
3507int QApplication::keyboardInputInterval()
3508{
3509 return QGuiApplication::styleHints()->keyboardInputInterval();
3510}
3511
3512/*!
3513 \property QApplication::wheelScrollLines
3514 \brief the number of lines to scroll a widget, when the
3515 mouse wheel is rotated.
3516
3517 If the value exceeds the widget's number of visible lines, the widget
3518 should interpret the scroll operation as a single \e{page up} or
3519 \e{page down}. If the widget is an \l{QAbstractItemView}{item view class},
3520 then the result of scrolling one \e line depends on the setting of the
3521 widget's \l{QAbstractItemView::verticalScrollMode()}{scroll mode}. Scroll
3522 one \e line can mean \l{QAbstractItemView::ScrollPerItem}{scroll one item}
3523 or \l{QAbstractItemView::ScrollPerPixel}{scroll one pixel}.
3524
3525 By default, this property has a value of 3.
3526
3527 \sa QStyleHints::wheelScrollLines()
3528*/
3529#if QT_CONFIG(wheelevent)
3530int QApplication::wheelScrollLines()
3531{
3532 return styleHints()->wheelScrollLines();
3533}
3534
3535void QApplication::setWheelScrollLines(int lines)
3536{
3537 styleHints()->setWheelScrollLines(lines);
3538}
3539#endif
3540
3541static inline int uiEffectToFlag(Qt::UIEffect effect)
3542{
3543 switch (effect) {
3544 case Qt::UI_General:
3545 return QPlatformTheme::GeneralUiEffect;
3546 case Qt::UI_AnimateMenu:
3547 return QPlatformTheme::AnimateMenuUiEffect;
3548 case Qt::UI_FadeMenu:
3549 return QPlatformTheme::FadeMenuUiEffect;
3550 case Qt::UI_AnimateCombo:
3551 return QPlatformTheme::AnimateComboUiEffect;
3552 case Qt::UI_AnimateTooltip:
3553 return QPlatformTheme::AnimateTooltipUiEffect;
3554 case Qt::UI_FadeTooltip:
3555 return QPlatformTheme::FadeTooltipUiEffect;
3556 case Qt::UI_AnimateToolBox:
3557 return QPlatformTheme::AnimateToolBoxUiEffect;
3558 }
3559 return 0;
3560}
3561
3562/*!
3563 \fn void QApplication::setEffectEnabled(Qt::UIEffect effect, bool enable)
3564
3565 Enables the UI effect \a effect if \a enable is true, otherwise the effect
3566 will not be used.
3567
3568 \note All effects are disabled on screens running at less than 16-bit color
3569 depth.
3570
3571 \sa isEffectEnabled(), Qt::UIEffect, setDesktopSettingsAware()
3572*/
3573void QApplication::setEffectEnabled(Qt::UIEffect effect, bool enable)
3574{
3575 int effectFlags = uiEffectToFlag(effect);
3576 if (enable) {
3577 if (effectFlags & QPlatformTheme::FadeMenuUiEffect)
3578 effectFlags |= QPlatformTheme::AnimateMenuUiEffect;
3579 if (effectFlags & QPlatformTheme::FadeTooltipUiEffect)
3580 effectFlags |= QPlatformTheme::AnimateTooltipUiEffect;
3581 QApplicationPrivate::enabledAnimations |= effectFlags;
3582 } else {
3583 QApplicationPrivate::enabledAnimations &= ~effectFlags;
3584 }
3585}
3586
3587/*!
3588 \fn bool QApplication::isEffectEnabled(Qt::UIEffect effect)
3589
3590 Returns \c true if \a effect is enabled; otherwise returns \c false.
3591
3592 By default, Qt will try to use the desktop settings. To prevent this, call
3593 setDesktopSettingsAware(false).
3594
3595 \note All effects are disabled on screens running at less than 16-bit color
3596 depth.
3597
3598 \sa setEffectEnabled(), Qt::UIEffect
3599*/
3600bool QApplication::isEffectEnabled(Qt::UIEffect effect)
3601{
3602 CHECK_QAPP_INSTANCE(false)
3603 const auto primaryScreenDepth = QGuiApplication::primaryScreen() ?
3604 QGuiApplication::primaryScreen()->depth() : 24;
3605 return primaryScreenDepth >= 16
3606 && (QApplicationPrivate::enabledAnimations & QPlatformTheme::GeneralUiEffect)
3607 && (QApplicationPrivate::enabledAnimations & uiEffectToFlag(effect));
3608}
3609
3610/*!
3611 \fn void QApplication::beep()
3612
3613 Sounds the bell, using the default volume and sound. The function is \e not
3614 available in Qt for Embedded Linux.
3615*/
3616void QApplication::beep()
3617{
3618 QGuiApplicationPrivate::platformIntegration()->beep();
3619}
3620
3621/*!
3622 \macro qApp
3623 \relates QApplication
3624
3625 A global pointer referring to the unique application object. It is
3626 equivalent to QCoreApplication::instance(), but cast as a QApplication pointer,
3627 so only valid when the unique application object is a QApplication.
3628
3629 \sa QCoreApplication::instance(), qGuiApp
3630*/
3631
3632bool qt_sendSpontaneousEvent(QObject *receiver, QEvent *event)
3633{
3634 return QGuiApplication::sendSpontaneousEvent(receiver, event);
3635}
3636
3637void QApplicationPrivate::giveFocusAccordingToFocusPolicy(QWidget *widget, QEvent *event, QPoint localPos)
3638{
3639 const bool setFocusOnRelease = QGuiApplication::styleHints()->setFocusOnTouchRelease();
3640 Qt::FocusPolicy focusPolicy = Qt::ClickFocus;
3641 static QPointer<QWidget> focusedWidgetOnTouchBegin = nullptr;
3642
3643 switch (event->type()) {
3644 case QEvent::MouseButtonPress:
3645 case QEvent::MouseButtonDblClick:
3646 case QEvent::TouchBegin:
3647 focusedWidgetOnTouchBegin = QApplication::focusWidget();
3648 if (setFocusOnRelease)
3649 return;
3650 break;
3651 case QEvent::MouseButtonRelease:
3652 case QEvent::TouchEnd:
3653 if (!setFocusOnRelease)
3654 return;
3655 if (focusedWidgetOnTouchBegin != QApplication::focusWidget()) {
3656 // Focus widget was changed while delivering press/move events.
3657 // To not interfere with application logic, we leave focus as-is
3658 return;
3659 }
3660 break;
3661 case QEvent::Wheel:
3662 focusPolicy = Qt::WheelFocus;
3663 break;
3664 default:
3665 return;
3666 }
3667
3668 QWidget *focusWidget = widget;
3669 while (focusWidget) {
3670 if (focusWidget->isEnabled()
3671 && focusWidget->rect().contains(localPos)
3672 && QApplicationPrivate::shouldSetFocus(focusWidget, focusPolicy)) {
3673 focusWidget->setFocus(Qt::MouseFocusReason);
3674 break;
3675 }
3676 if (focusWidget->isWindow())
3677 break;
3678
3679 // find out whether this widget (or its proxy) already has focus
3680 QWidget *f = focusWidget;
3681 if (focusWidget->d_func()->extra && focusWidget->d_func()->extra->focus_proxy)
3682 f = focusWidget->d_func()->extra->focus_proxy;
3683 // if it has, stop here.
3684 // otherwise a click on the focused widget would remove its focus if ClickFocus isn't set
3685 if (f->hasFocus())
3686 break;
3687
3688 localPos += focusWidget->pos();
3689 focusWidget = focusWidget->parentWidget();
3690 }
3691}
3692
3693bool QApplicationPrivate::shouldSetFocus(QWidget *w, Qt::FocusPolicy policy)
3694{
3695 QWidget *f = w;
3696 while (f->d_func()->extra && f->d_func()->extra->focus_proxy)
3697 f = f->d_func()->extra->focus_proxy;
3698
3699 if ((w->focusPolicy() & policy) != policy)
3700 return false;
3701 if (w != f && (f->focusPolicy() & policy) != policy)
3702 return false;
3703 return true;
3704}
3705
3706bool QApplicationPrivate::updateTouchPointsForWidget(QWidget *widget, QTouchEvent *touchEvent)
3707{
3708 bool containsPress = false;
3709
3710 for (qsizetype cnt = touchEvent->pointCount(), i = 0; i < cnt; ++i) {
3711 auto &pt = touchEvent->point(i);
3712 QMutableEventPoint::setPosition(pt, widget->mapFromGlobal(pt.globalPosition()));
3713
3714 if (pt.state() == QEventPoint::State::Pressed)
3715 containsPress = true;
3716 }
3717 return containsPress;
3718}
3719
3720void QApplicationPrivate::initializeMultitouch()
3721{
3722 initializeMultitouch_sys();
3723}
3724
3725void QApplicationPrivate::initializeMultitouch_sys()
3726{
3727}
3728
3729void QApplicationPrivate::cleanupMultitouch()
3730{
3731 cleanupMultitouch_sys();
3732}
3733
3734void QApplicationPrivate::cleanupMultitouch_sys()
3735{
3736}
3737
3738QWidget *QApplicationPrivate::findClosestTouchPointTarget(const QPointingDevice *device, const QEventPoint &touchPoint)
3739{
3740 const QPointF globalPos = touchPoint.globalPosition();
3741 int closestTouchPointId = -1;
3742 QObject *closestTarget = nullptr;
3743 qreal closestDistance = 0;
3744 const QPointingDevicePrivate *devPriv = QPointingDevicePrivate::get(device);
3745 for (auto &epd : devPriv->activePoints.values()) {
3746 const auto &pt = epd.eventPoint;
3747 if (pt.id() != touchPoint.id()) {
3748 qreal dx = globalPos.x() - pt.globalPosition().x();
3749 qreal dy = globalPos.y() - pt.globalPosition().y();
3750 qreal distance = dx * dx + dy * dy;
3751 if (closestTouchPointId == -1 || distance < closestDistance) {
3752 closestTouchPointId = pt.id();
3753 closestDistance = distance;
3754 closestTarget = QMutableEventPoint::target(pt);
3755 }
3756 }
3757 }
3758 return static_cast<QWidget *>(closestTarget);
3759}
3760
3761void QApplicationPrivate::activateImplicitTouchGrab(QWidget *widget, QTouchEvent *touchEvent,
3762 ImplicitTouchGrabMode grabMode)
3763{
3764 if (touchEvent->type() != QEvent::TouchBegin)
3765 return;
3766
3767 // If the widget dispatched the event further (see QGraphicsProxyWidget), then
3768 // there might already be an implicit grabber. Don't override that. A widget that
3769 // has partially recognized a gesture needs to grab all points.
3770 for (qsizetype cnt = touchEvent->pointCount(), i = 0; i < cnt; ++i) {
3771 auto &ep = touchEvent->point(i);
3772 if (!QMutableEventPoint::target(ep) && (ep.isAccepted() || grabMode == GrabAllPoints))
3773 QMutableEventPoint::setTarget(ep, widget);
3774 }
3775 // TODO setExclusiveGrabber() to be consistent with Qt Quick?
3776}
3777
3778bool QApplicationPrivate::translateRawTouchEvent(QWidget *window, const QTouchEvent *te)
3779{
3780 QApplicationPrivate *d = self;
3781 // TODO get rid of this std::pair
3782 typedef std::pair<QEventPoint::State, QList<QEventPoint> > StatesAndTouchPoints;
3783 QHash<QWidget *, StatesAndTouchPoints> widgetsNeedingEvents;
3784
3785 const auto *device = te->pointingDevice();
3786 auto touchPoints = te->points(); // touch points will be mutated
3787 for (auto &touchPoint : touchPoints) {
3788 // update state
3789 QPointer<QObject> target;
3790 if (touchPoint.state() == QEventPoint::State::Pressed) {
3791 if (device->type() == QInputDevice::DeviceType::TouchPad) {
3792 // on touchpads, send all touch points to the same widget:
3793 // pick the first non-null target if possible
3794 target = QPointingDevicePrivate::get(device)->firstActiveTarget();
3795 }
3796
3797 if (target.isNull()) {
3798 // determine which widget this event will go to
3799 if (!window)
3800 window = QApplication::topLevelAt(touchPoint.globalPosition().toPoint());
3801 if (!window)
3802 continue;
3803 target = window->childAt(window->mapFromGlobal(touchPoint.globalPosition()));
3804 if (!target)
3805 target = window;
3806 }
3807
3808 bool usingClosestWidget = false;
3809 if (device->type() == QInputDevice::DeviceType::TouchScreen) {
3810 QWidget *closestWidget = d->findClosestTouchPointTarget(device, touchPoint);
3811 QWidget *widget = static_cast<QWidget *>(target.data());
3812 if (closestWidget
3813 && (widget->isAncestorOf(closestWidget) || closestWidget->isAncestorOf(widget))) {
3814 target = closestWidget;
3815 usingClosestWidget = true;
3816 }
3817 }
3818
3819 // on touch pads, implicitly grab all touch points
3820 // on touch screens, grab touch points that are redirected to the closest widget
3821 if (device->type() == QInputDevice::DeviceType::TouchPad || usingClosestWidget)
3822 QMutableEventPoint::setTarget(touchPoint, target);
3823 } else {
3824 target = QMutableEventPoint::target(touchPoint);
3825 if (!target)
3826 continue;
3827 }
3828 Q_ASSERT(!target.isNull());
3829
3830 QWidget *targetWidget = static_cast<QWidget *>(target.data());
3831
3832#ifdef Q_OS_MACOS
3833 // Single-touch events are normally not sent unless WA_TouchPadAcceptSingleTouchEvents is set.
3834 // In Qt 4 this check was in OS X-only code. That behavior is preserved here by the #ifdef.
3835 if (touchPoints.count() == 1
3836 && device->type() == QInputDevice::DeviceType::TouchPad
3837 && !targetWidget->testAttribute(Qt::WA_TouchPadAcceptSingleTouchEvents))
3838 continue;
3839#endif
3840
3841 StatesAndTouchPoints &maskAndPoints = widgetsNeedingEvents[targetWidget];
3842 maskAndPoints.first = QEventPoint::State(maskAndPoints.first | touchPoint.state());
3843 maskAndPoints.second.append(touchPoint);
3844 }
3845
3846 if (widgetsNeedingEvents.isEmpty())
3847 return false;
3848
3849 bool accepted = false;
3850 QHash<QWidget *, StatesAndTouchPoints>::ConstIterator it = widgetsNeedingEvents.constBegin();
3851 const QHash<QWidget *, StatesAndTouchPoints>::ConstIterator end = widgetsNeedingEvents.constEnd();
3852 for (; it != end; ++it) {
3853 const QPointer<QWidget> widget = it.key();
3854 if (!QApplicationPrivate::tryModalHelper(widget, nullptr))
3855 continue;
3856
3857 QEvent::Type eventType;
3858 switch (it.value().first) {
3859 case QEventPoint::State::Pressed:
3860 eventType = QEvent::TouchBegin;
3861 break;
3862 case QEventPoint::State::Released:
3863 eventType = QEvent::TouchEnd;
3864 break;
3865 case QEventPoint::State::Stationary:
3866 // don't send the event if nothing changed
3867 continue;
3868 default:
3869 eventType = QEvent::TouchUpdate;
3870 break;
3871 }
3872
3873 QMutableTouchEvent touchEvent(eventType, device, QGuiApplication::keyboardModifiers(),
3874 it.value().second);
3875 bool containsPress = updateTouchPointsForWidget(widget, &touchEvent);
3876 touchEvent.setTimestamp(te->timestamp());
3877 touchEvent.setTarget(widget);
3878
3879 if (containsPress)
3880 widget->setAttribute(Qt::WA_WState_AcceptedTouchBeginEvent);
3881
3882 switch (touchEvent.type()) {
3883 case QEvent::TouchBegin:
3884 {
3885 // if the TouchBegin handler recurses, we assume that means the event
3886 // has been implicitly accepted and continue to send touch events
3887 bool res = te->spontaneous() ? QApplication::sendSpontaneousEvent(widget, &touchEvent)
3888 : QApplication::sendEvent(widget, &touchEvent);
3889 if (res && touchEvent.isAccepted()) {
3890 accepted = true;
3891 if (!widget.isNull())
3892 widget->setAttribute(Qt::WA_WState_AcceptedTouchBeginEvent);
3893 }
3894 break;
3895 }
3896 default:
3897 if (widget->testAttribute(Qt::WA_WState_AcceptedTouchBeginEvent)
3898#ifndef QT_NO_GESTURES
3899 || QGestureManager::gesturePending(widget)
3900#endif
3901 ) {
3902 bool res = te->spontaneous() ? QApplication::sendSpontaneousEvent(widget, &touchEvent)
3903 : QApplication::sendEvent(widget, &touchEvent);
3904 if (res && touchEvent.isAccepted())
3905 accepted = true;
3906 // widget can be deleted on TouchEnd
3907 if (touchEvent.type() == QEvent::TouchEnd && !widget.isNull())
3908 widget->setAttribute(Qt::WA_WState_AcceptedTouchBeginEvent, false);
3909 }
3910 break;
3911 }
3912 }
3913 return accepted;
3914}
3915
3916void QApplicationPrivate::translateTouchCancel(const QPointingDevice *device, ulong timestamp)
3917{
3918 QMutableTouchEvent touchEvent(QEvent::TouchCancel, device, QGuiApplication::keyboardModifiers());
3919 touchEvent.setTimestamp(timestamp);
3920
3921 QSet<QWidget *> widgetsNeedingCancel;
3922 const QPointingDevicePrivate *devPriv = QPointingDevicePrivate::get(device);
3923 for (auto &epd : devPriv->activePoints.values()) {
3924 const auto &pt = epd.eventPoint;
3925 QObject *target = QMutableEventPoint::target(pt);
3926 if (target && target->isWidgetType())
3927 widgetsNeedingCancel.insert(static_cast<QWidget *>(target));
3928 }
3929 for (QSet<QWidget *>::const_iterator widIt = widgetsNeedingCancel.constBegin(),
3930 widItEnd = widgetsNeedingCancel.constEnd(); widIt != widItEnd; ++widIt) {
3931 QWidget *widget = *widIt;
3932 touchEvent.setTarget(widget);
3933 QApplication::sendSpontaneousEvent(widget, &touchEvent);
3934 }
3935}
3936
3937void QApplicationPrivate::handleThemeChanged()
3938{
3939 QGuiApplicationPrivate::handleThemeChanged();
3940
3941 qt_init_tooltip_palette();
3942}
3943
3944#if QT_CONFIG(draganddrop)
3945void QApplicationPrivate::notifyDragStarted(const QDrag *drag)
3946{
3947 QGuiApplicationPrivate::notifyDragStarted(drag);
3948 // QTBUG-26145
3949 // Prevent pickMouseReceiver() from using the widget where the drag was started after a drag operation...
3950 // QTBUG-56713
3951 // ...only if qt_button_down is not a QQuickWidget
3952 if (qt_button_down && !qt_button_down->inherits("QQuickWidget"))
3953 qt_button_down = nullptr;
3954}
3955#endif // QT_CONFIG(draganddrop)
3956
3957#ifndef QT_NO_GESTURES
3958QGestureManager* QGestureManager::instance(InstanceCreation ic)
3959{
3960 QApplicationPrivate *qAppPriv = QApplicationPrivate::instance();
3961 if (!qAppPriv)
3962 return nullptr;
3963 if (!qAppPriv->gestureManager && ic == ForceCreation)
3964 qAppPriv->gestureManager = new QGestureManager(qApp);
3965 return qAppPriv->gestureManager;
3966}
3967#endif // QT_NO_GESTURES
3968
3969QPixmap QApplicationPrivate::applyQIconStyleHelper(QIcon::Mode mode, const QPixmap& base) const
3970{
3971 QStyleOption opt(0);
3972 opt.palette = QGuiApplication::palette();
3973 return QApplication::style()->generatedIconPixmap(mode, base, &opt);
3974}
3975
3976void *QApplication::resolveInterface(const char *name, int revision) const
3977{
3978 return QGuiApplication::resolveInterface(name, revision);
3979}
3980
3981QT_END_NAMESPACE
3982
3983#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