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