diff options
Diffstat (limited to 'src/widgets/kernel/qapplication.cpp')
-rw-r--r-- | src/widgets/kernel/qapplication.cpp | 2314 |
1 files changed, 921 insertions, 1393 deletions
diff --git a/src/widgets/kernel/qapplication.cpp b/src/widgets/kernel/qapplication.cpp index f564475698..a1392e10dc 100644 --- a/src/widgets/kernel/qapplication.cpp +++ b/src/widgets/kernel/qapplication.cpp @@ -1,48 +1,11 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtWidgets module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include "qplatformdefs.h" #include "qabstracteventdispatcher.h" #include "qapplication.h" #include "qclipboard.h" #include "qcursor.h" -#include "qdesktopwidget.h" #include "qdir.h" #include "qevent.h" #include "qfile.h" @@ -58,7 +21,9 @@ #include "qstyle.h" #include "qstyleoption.h" #include "qstylefactory.h" +#if QT_CONFIG(tooltip) #include "qtooltip.h" +#endif #include "qtranslator.h" #include "qvariant.h" #include "qwidget.h" @@ -77,41 +42,50 @@ #include <QtGui/qstylehints.h> #include <QtGui/qinputmethod.h> #include <QtGui/private/qwindow_p.h> -#include <QtGui/qtouchdevice.h> +#include <QtGui/qpointingdevice.h> +#include <QtGui/private/qpointingdevice_p.h> #include <qpa/qplatformtheme.h> #if QT_CONFIG(whatsthis) #include <QtWidgets/QWhatsThis> #endif +#if QT_CONFIG(accessibility) +#include <QtGui/qaccessible_base.h> +#include "private/qaccessiblewidgetfactory_p.h" +#endif #include "private/qkeymapper_p.h" -#include "private/qaccessiblewidgetfactory_p.h" #include <qthread.h> #include <private/qthread_p.h> +#include <QtGui/private/qevent_p.h> +#include <QtGui/private/qeventpoint_p.h> #include <private/qfont_p.h> +#if QT_CONFIG(action) +#include <private/qaction_p.h> +#endif #include <stdlib.h> #include "qapplication_p.h" -#include "private/qevent_p.h" #include "qwidget_p.h" #include "qgesture.h" #include "private/qgesturemanager_p.h" #include <qpa/qplatformfontdatabase.h> -#ifdef Q_OS_WIN -#include <QtCore/qt_windows.h> // for qt_win_display_dc() -#endif - #include "qdatetime.h" #include <qpa/qplatformwindow.h> #include <qtwidgets_tracepoints_p.h> -//#define ALIEN_DEBUG +#ifdef Q_OS_MACOS +#include <QtCore/private/qcore_mac_p.h> +#endif + +#include <algorithm> +#include <iterator> static void initResources() { @@ -124,6 +98,15 @@ static void initResources() QT_BEGIN_NAMESPACE +using namespace Qt::StringLiterals; + +Q_TRACE_PREFIX(qtwidgets, + "#include <qcoreevent.h>" +); +Q_TRACE_METADATA(qtwidgets, "ENUM { AUTO, RANGE User ... MaxUser } QEvent::Type;"); +Q_TRACE_POINT(qtwidgets, QApplication_notify_entry, QObject *receiver, QEvent *event, QEvent::Type type); +Q_TRACE_POINT(qtwidgets, QApplication_notify_exit, bool consumed, bool filtered); + // Helper macro for static functions to check on the existence of the application class. #define CHECK_QAPP_INSTANCE(...) \ if (Q_LIKELY(QCoreApplication::instance())) { \ @@ -135,39 +118,18 @@ QT_BEGIN_NAMESPACE Q_CORE_EXPORT void qt_call_post_routines(); 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); -QApplicationPrivate *QApplicationPrivate::self = 0; - -static void initSystemPalette() -{ - if (!QApplicationPrivate::sys_pal) { - QPalette defaultPlatte; - if (QApplicationPrivate::app_style) - defaultPlatte = QApplicationPrivate::app_style->standardPalette(); - if (const QPalette *themePalette = QGuiApplicationPrivate::platformTheme()->palette()) { - QApplicationPrivate::setSystemPalette(themePalette->resolve(defaultPlatte)); - QApplicationPrivate::initializeWidgetPaletteHash(); - } else { - QApplicationPrivate::setSystemPalette(defaultPlatte); - } - } -} - -static void clearSystemPalette() -{ - delete QApplicationPrivate::sys_pal; - QApplicationPrivate::sys_pal = 0; -} +QApplicationPrivate *QApplicationPrivate::self = nullptr; bool QApplicationPrivate::autoSipEnabled = true; -QApplicationPrivate::QApplicationPrivate(int &argc, char **argv, int flags) - : QApplicationPrivateBase(argc, argv, flags) +QApplicationPrivate::QApplicationPrivate(int &argc, char **argv) + : QGuiApplicationPrivate(argc, argv) { application_type = QApplicationPrivate::Gui; #ifndef QT_NO_GESTURES - gestureManager = 0; - gestureWidget = 0; + gestureManager = nullptr; + gestureWidget = nullptr; #endif // QT_NO_GESTURES if (!self) @@ -177,7 +139,7 @@ QApplicationPrivate::QApplicationPrivate(int &argc, char **argv, int flags) QApplicationPrivate::~QApplicationPrivate() { if (self == this) - self = 0; + self = nullptr; } void QApplicationPrivate::createEventDispatcher() @@ -233,14 +195,10 @@ void QApplicationPrivate::createEventDispatcher() encapsulated in a QStyle object. This can be changed at runtime with setStyle(). - \li It specifies how the application is to allocate colors. See - setColorSpec() for details. - \li It provides localization of strings that are visible to the user via translate(). - \li It provides some magical objects like the desktop() and the - clipboard(). + \li It provides some magical objects like the clipboard(). \li It knows about the application's windows. You can ask which widget is at a certain position using widgetAt(), get a list of @@ -287,7 +245,6 @@ void QApplicationPrivate::createEventDispatcher() postEvent(), sendPostedEvents(), removePostedEvents(), - hasPendingEvents(), notify(). \row @@ -296,11 +253,6 @@ void QApplicationPrivate::createEventDispatcher() setStyle(). \row - \li Color usage - \li colorSpec(), - setColorSpec(). - - \row \li Text handling \li installTranslator(), removeTranslator() @@ -310,7 +262,6 @@ void QApplicationPrivate::createEventDispatcher() \li Widgets \li allWidgets(), topLevelWidgets(), - desktop(), activePopupWidget(), activeModalWidget(), clipboard(), @@ -334,29 +285,6 @@ void QApplicationPrivate::createEventDispatcher() \sa QCoreApplication, QAbstractEventDispatcher, QEventLoop, QSettings */ -// ### fixme: Qt 6: Remove ColorSpec and accessors. -/*! - \enum QApplication::ColorSpec - \obsolete - - \value NormalColor the default color allocation policy - \value CustomColor the same as NormalColor for X11; allocates colors - to a palette on demand under Windows - \value ManyColor the right choice for applications that use thousands of - colors - - See setColorSpec() for full details. -*/ - -/*! - \fn QApplication::setGraphicsSystem(const QString &) - \obsolete - - This call has no effect. - - Use the QPA framework instead. -*/ - /*! \fn QWidget *QApplication::topLevelAt(const QPoint &point) @@ -369,7 +297,7 @@ QWidget *QApplication::topLevelAt(const QPoint &pos) if (const QWidgetWindow *widgetWindow = qobject_cast<const QWidgetWindow *>(window)) return widgetWindow->widget(); } - return 0; + return nullptr; } /*! @@ -382,35 +310,30 @@ QWidget *QApplication::topLevelAt(const QPoint &pos) */ void qt_init_tooltip_palette(); -void qt_cleanup(); -QStyle *QApplicationPrivate::app_style = 0; // default application style +QStyle *QApplicationPrivate::app_style = nullptr; // default application style #ifndef QT_NO_STYLE_STYLESHEET QString QApplicationPrivate::styleSheet; // default application stylesheet #endif -QPointer<QWidget> QApplicationPrivate::leaveAfterRelease = 0; - -QPalette *QApplicationPrivate::sys_pal = 0; // default system palette -QPalette *QApplicationPrivate::set_pal = 0; // default palette set by programmer +QPointer<QWidget> QApplicationPrivate::leaveAfterRelease = nullptr; -QFont *QApplicationPrivate::sys_font = 0; // default system font -QFont *QApplicationPrivate::set_font = 0; // default font set by programmer +QFont *QApplicationPrivate::sys_font = nullptr; // default system font +QFont *QApplicationPrivate::set_font = nullptr; // default font set by programmer -QWidget *QApplicationPrivate::main_widget = 0; // main application widget -QWidget *QApplicationPrivate::focus_widget = 0; // has keyboard input focus -QWidget *QApplicationPrivate::hidden_focus_widget = 0; // will get keyboard input focus after show() -QWidget *QApplicationPrivate::active_window = 0; // toplevel with keyboard focus +QWidget *QApplicationPrivate::main_widget = nullptr; // main application widget +QWidget *QApplicationPrivate::focus_widget = nullptr; // has keyboard input focus +QWidget *QApplicationPrivate::hidden_focus_widget = nullptr; // will get keyboard input focus after show() +QWidget *QApplicationPrivate::active_window = nullptr; // toplevel with keyboard focus #if QT_CONFIG(wheelevent) QPointer<QWidget> QApplicationPrivate::wheel_widget; #endif bool qt_in_tab_key_event = false; int qt_antialiasing_threshold = -1; -QSize QApplicationPrivate::app_strut = QSize(0,0); // no default application strut int QApplicationPrivate::enabledAnimations = QPlatformTheme::GeneralUiEffect; bool QApplicationPrivate::widgetCount = false; #ifdef QT_KEYPAD_NAVIGATION Qt::NavigationMode QApplicationPrivate::navigationMode = Qt::NavigationModeKeypadTabOrder; -QWidget *QApplicationPrivate::oldEditFocus = 0; +QWidget *QApplicationPrivate::oldEditFocus = nullptr; #endif inline bool QApplicationPrivate::isAlien(QWidget *widget) @@ -424,16 +347,14 @@ bool Q_WIDGETS_EXPORT qt_tab_all_widgets() } // ######## move to QApplicationPrivate -// Default application palettes and fonts (per widget type) -Q_GLOBAL_STATIC(PaletteHash, app_palettes) +// Default fonts (per widget type) Q_GLOBAL_STATIC(FontHash, app_fonts) -// Exported accessors for use outside of this file -PaletteHash *qt_app_palettes_hash() { return app_palettes(); } +// Exported accessor for use outside of this file FontHash *qt_app_fonts_hash() { return app_fonts(); } -QWidgetList *QApplicationPrivate::popupWidgets = 0; // has keyboard input focus +QWidgetList *QApplicationPrivate::popupWidgets = nullptr; // has keyboard input focus -QDesktopWidget *qt_desktopWidget = 0; // root window widgets +QWidget *qt_desktopWidget = nullptr; // root window widgets /*! \internal @@ -443,15 +364,8 @@ void QApplicationPrivate::process_cmdline() if (styleOverride.isEmpty() && qEnvironmentVariableIsSet("QT_STYLE_OVERRIDE")) styleOverride = QString::fromLocal8Bit(qgetenv("QT_STYLE_OVERRIDE")); - if (!styleOverride.isEmpty()) { - if (app_style) { - delete app_style; - app_style = 0; - } - } - // process platform-indep command line - if (!qt_is_gui_used || !argc) + if (qt_is_tty_app || !argc) return; int i, j; @@ -471,10 +385,10 @@ void QApplicationPrivate::process_cmdline() // obsolete argument #ifndef QT_NO_STYLE_STYLESHEET } else if (strcmp(arg, "-stylesheet") == 0 && i < argc -1) { - styleSheet = QLatin1String("file:///"); + styleSheet = "file:///"_L1; styleSheet.append(QString::fromLocal8Bit(argv[++i])); } else if (strncmp(arg, "-stylesheet=", 12) == 0) { - styleSheet = QLatin1String("file:///"); + styleSheet = "file:///"_L1; styleSheet.append(QString::fromLocal8Bit(arg + 12)); #endif } else if (qstrcmp(arg, "-widgetcount") == 0) { @@ -484,8 +398,8 @@ void QApplicationPrivate::process_cmdline() } } - if(j < argc) { - argv[j] = 0; + if (j < argc) { + argv[j] = nullptr; argc = j; } } @@ -538,9 +452,9 @@ void QApplicationPrivate::process_cmdline() #ifdef Q_QDOC QApplication::QApplication(int &argc, char **argv) #else -QApplication::QApplication(int &argc, char **argv, int _internal) +QApplication::QApplication(int &argc, char **argv, int) #endif - : QGuiApplication(*new QApplicationPrivate(argc, argv, _internal)) + : QGuiApplication(*new QApplicationPrivate(argc, argv)) { Q_D(QApplication); d->init(); @@ -559,22 +473,19 @@ void QApplicationPrivate::init() initResources(); - qt_is_gui_used = (application_type != QApplicationPrivate::Tty); + qt_is_tty_app = (application_type == QApplicationPrivate::Tty); process_cmdline(); // Must be called before initialize() QColormap::initialize(); + initializeWidgetPalettesFromTheme(); qt_init_tooltip_palette(); QApplicationPrivate::initializeWidgetFontHash(); initialize(); eventDispatcher->startingUp(); -#ifdef QT_EVAL - extern void qt_gui_eval_init(QCoreApplicationPrivate::Type); - qt_gui_eval_init(application_type); -#endif -#ifndef QT_NO_ACCESSIBILITY +#if QT_CONFIG(accessibility) // factory for accessible interfaces for widgets shipped with Qt QAccessible::installFactory(&qAccessibleFactory); #endif @@ -583,21 +494,18 @@ void QApplicationPrivate::init() void qt_init_tooltip_palette() { -#ifndef QT_NO_TOOLTIP - if (const QPalette *toolTipPalette = QGuiApplicationPrivate::platformTheme()->palette(QPlatformTheme::ToolTipPalette)) - QToolTip::setPalette(*toolTipPalette); +#if QT_CONFIG(tooltip) + if (const QPalette *toolTipPalette = QGuiApplicationPrivate::platformTheme()->palette(QPlatformTheme::ToolTipPalette)) { + QPalette toolTipPal = *toolTipPalette; + toolTipPal.setResolveMask(0); + QToolTip::setPalette(toolTipPal); + } #endif } -#if QT_CONFIG(statemachine) -void qRegisterGuiStateMachine(); -void qUnregisterGuiStateMachine(); -#endif extern void qRegisterWidgetsVariant(); /*! - \fn void QApplicationPrivate::initialize() - Initializes the QApplication object, called from the constructors. */ void QApplicationPrivate::initialize() @@ -613,20 +521,30 @@ void QApplicationPrivate::initialize() // needed for widgets in QML QAbstractDeclarativeData::setWidgetParent = QWidgetPrivate::setWidgetParentHelper; - if (application_type != QApplicationPrivate::Tty) - (void) QApplication::style(); // trigger creation of application style -#if QT_CONFIG(statemachine) - // trigger registering of QStateMachine's GUI types - qRegisterGuiStateMachine(); -#endif + if (application_type != QApplicationPrivate::Tty) { + if (!styleOverride.isEmpty()) { + if (auto *style = QStyleFactory::create(styleOverride.toLower())) { + QApplication::setStyle(style); + } else { + qWarning("QApplication: invalid style override '%s' passed, ignoring it.\n" + "\tAvailable styles: %s", qPrintable(styleOverride), + qPrintable(QStyleFactory::keys().join(", "_L1))); + // Clear styleOverride so it is not picked by Qt Quick Controls (QTBUG-100563) + styleOverride.clear(); + } + } + + // Trigger default style if none was set already + Q_UNUSED(QApplication::style()); + } if (qEnvironmentVariableIntValue("QT_USE_NATIVE_WINDOWS") > 0) QCoreApplication::setAttribute(Qt::AA_NativeWindows); - if (qt_is_gui_used) + if (!qt_is_tty_app) initializeMultitouch(); - if (QApplication::desktopSettingsAware()) + if (QGuiApplication::desktopSettingsAware()) if (const QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme()) { QApplicationPrivate::enabledAnimations = theme->themeHint(QPlatformTheme::UiEffects).toInt(); } @@ -634,37 +552,6 @@ void QApplicationPrivate::initialize() is_app_running = true; // no longer starting up } -static void setPossiblePalette(const QPalette *palette, const char *className) -{ - if (palette == 0) - return; - QApplicationPrivate::setPalette_helper(*palette, className, false); -} - -void QApplicationPrivate::initializeWidgetPaletteHash() -{ - QPlatformTheme *platformTheme = QGuiApplicationPrivate::platformTheme(); - if (!platformTheme) - return; - app_palettes()->clear(); - - setPossiblePalette(platformTheme->palette(QPlatformTheme::ToolButtonPalette), "QToolButton"); - setPossiblePalette(platformTheme->palette(QPlatformTheme::ButtonPalette), "QAbstractButton"); - setPossiblePalette(platformTheme->palette(QPlatformTheme::CheckBoxPalette), "QCheckBox"); - setPossiblePalette(platformTheme->palette(QPlatformTheme::RadioButtonPalette), "QRadioButton"); - setPossiblePalette(platformTheme->palette(QPlatformTheme::HeaderPalette), "QHeaderView"); - setPossiblePalette(platformTheme->palette(QPlatformTheme::ItemViewPalette), "QAbstractItemView"); - setPossiblePalette(platformTheme->palette(QPlatformTheme::MessageBoxLabelPalette), "QMessageBoxLabel"); - setPossiblePalette(platformTheme->palette(QPlatformTheme::TabBarPalette), "QTabBar"); - setPossiblePalette(platformTheme->palette(QPlatformTheme::LabelPalette), "QLabel"); - setPossiblePalette(platformTheme->palette(QPlatformTheme::GroupBoxPalette), "QGroupBox"); - setPossiblePalette(platformTheme->palette(QPlatformTheme::MenuPalette), "QMenu"); - setPossiblePalette(platformTheme->palette(QPlatformTheme::MenuBarPalette), "QMenuBar"); - setPossiblePalette(platformTheme->palette(QPlatformTheme::TextEditPalette), "QTextEdit"); - setPossiblePalette(platformTheme->palette(QPlatformTheme::TextEditPalette), "QTextControl"); - setPossiblePalette(platformTheme->palette(QPlatformTheme::TextLineEditPalette), "QLineEdit"); -} - void QApplicationPrivate::initializeWidgetFontHash() { const QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme(); @@ -762,12 +649,12 @@ QWidget *QApplication::activePopupWidget() QWidget *QApplication::activeModalWidget() { QWidgetWindow *widgetWindow = qobject_cast<QWidgetWindow *>(modalWindow()); - return widgetWindow ? widgetWindow->widget() : 0; + return widgetWindow ? widgetWindow->widget() : nullptr; } /*! Cleans up any window system resources that were allocated by this - application. Sets the global variable \c qApp to 0. + application. Sets the global variable \c qApp to \nullptr. */ QApplication::~QApplication() @@ -785,12 +672,12 @@ QApplication::~QApplication() QApplicationPrivate::is_app_running = false; delete QWidgetPrivate::mapper; - QWidgetPrivate::mapper = 0; + QWidgetPrivate::mapper = nullptr; // delete all widgets if (QWidgetPrivate::allWidgets) { QWidgetSet *mySet = QWidgetPrivate::allWidgets; - QWidgetPrivate::allWidgets = 0; + QWidgetPrivate::allWidgets = nullptr; for (QWidgetSet::ConstIterator it = mySet->constBegin(), cend = mySet->constEnd(); it != cend; ++it) { QWidget *w = *it; if (!w->parent()) // window @@ -800,84 +687,45 @@ QApplication::~QApplication() } delete qt_desktopWidget; - qt_desktopWidget = 0; + qt_desktopWidget = nullptr; - delete QApplicationPrivate::app_pal; - QApplicationPrivate::app_pal = 0; - clearSystemPalette(); - delete QApplicationPrivate::set_pal; - QApplicationPrivate::set_pal = 0; - app_palettes()->clear(); + QApplicationPrivate::widgetPalettes.clear(); delete QApplicationPrivate::sys_font; - QApplicationPrivate::sys_font = 0; + QApplicationPrivate::sys_font = nullptr; delete QApplicationPrivate::set_font; - QApplicationPrivate::set_font = 0; + QApplicationPrivate::set_font = nullptr; app_fonts()->clear(); delete QApplicationPrivate::app_style; - QApplicationPrivate::app_style = 0; + QApplicationPrivate::app_style = nullptr; #if QT_CONFIG(draganddrop) - if (qt_is_gui_used) + if (!qt_is_tty_app) delete QDragManager::self(); #endif d->cleanupMultitouch(); - qt_cleanup(); + QPixmapCache::clear(); + QColormap::cleanup(); + + QApplicationPrivate::active_window = nullptr; //### this should not be necessary if (QApplicationPrivate::widgetCount) qDebug("Widgets left: %i Max widgets: %i \n", QWidgetPrivate::instanceCounter, QWidgetPrivate::maxInstances); QApplicationPrivate::obey_desktop_settings = true; - QApplicationPrivate::app_strut = QSize(0, 0); QApplicationPrivate::enabledAnimations = QPlatformTheme::GeneralUiEffect; QApplicationPrivate::widgetCount = false; - -#if QT_CONFIG(statemachine) - // trigger unregistering of QStateMachine's GUI types - qUnregisterGuiStateMachine(); -#endif -} - -#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) -#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT) -// #fixme: Remove. -static HDC displayDC = 0; // display device context - -Q_WIDGETS_EXPORT HDC qt_win_display_dc() // get display DC -{ - Q_ASSERT(qApp && qApp->thread() == QThread::currentThread()); - if (!displayDC) - displayDC = GetDC(0); - return displayDC; -} -#endif -#endif - -void qt_cleanup() -{ - QPixmapCache::clear(); - QColormap::cleanup(); - - QApplicationPrivate::active_window = 0; //### this should not be necessary -#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) -#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT) - if (displayDC) { - ReleaseDC(0, displayDC); - displayDC = 0; - } -#endif -#endif } /*! \fn QWidget *QApplication::widgetAt(const QPoint &point) - Returns the widget at global screen position \a point, or 0 if there is no - Qt widget there. + Returns the widget at global screen position \a point, or \nullptr + if there is no Qt widget there. This function can be slow. @@ -887,9 +735,9 @@ QWidget *QApplication::widgetAt(const QPoint &p) { QWidget *window = QApplication::topLevelAt(p); if (!window) - return 0; + return nullptr; - QWidget *child = 0; + QWidget *child = nullptr; if (!window->testAttribute(Qt::WA_TransparentForMouseEvents)) child = window->childAt(window->mapFromGlobal(p)); @@ -908,7 +756,7 @@ QWidget *QApplication::widgetAt(const QPoint &p) QRegion newmask = (oldmask.isEmpty() ? QRegion(window->rect()) : oldmask) - QRegion(wpoint.x(), wpoint.y(), 1, 1); window->setMask(newmask); - QWidget *recurse = 0; + QWidget *recurse = nullptr; if (QApplication::topLevelAt(p) != window) // verify recursion will terminate recurse = widgetAt(x, y); if (oldmask.isEmpty()) @@ -925,8 +773,8 @@ QWidget *QApplication::widgetAt(const QPoint &p) \overload - Returns the widget at global screen position (\a x, \a y), or 0 if there is - no Qt widget there. + Returns the widget at global screen position (\a x, \a y), or + \nullptr if there is no Qt widget there. */ /*! @@ -934,33 +782,54 @@ QWidget *QApplication::widgetAt(const QPoint &p) */ bool QApplication::compressEvent(QEvent *event, QObject *receiver, QPostEventList *postedEvents) { - if ((event->type() == QEvent::UpdateRequest - || event->type() == QEvent::LayoutRequest - || event->type() == QEvent::Resize - || event->type() == QEvent::Move - || event->type() == QEvent::LanguageChange)) { - for (QPostEventList::const_iterator it = postedEvents->constBegin(); it != postedEvents->constEnd(); ++it) { - const QPostEvent &cur = *it; - if (cur.receiver != receiver || cur.event == 0 || cur.event->type() != event->type()) - continue; - if (cur.event->type() == QEvent::LayoutRequest - || cur.event->type() == QEvent::UpdateRequest) { - ; - } else if (cur.event->type() == QEvent::Resize) { - ((QResizeEvent *)(cur.event))->s = ((QResizeEvent *)event)->s; - } else if (cur.event->type() == QEvent::Move) { - ((QMoveEvent *)(cur.event))->p = ((QMoveEvent *)event)->p; - } else if (cur.event->type() == QEvent::LanguageChange) { - ; - } else { - continue; - } - delete event; - return true; + // Only compress the following events: + const QEvent::Type type = event->type(); + switch (type) { + case QEvent::UpdateRequest: + case QEvent::UpdateLater: + case QEvent::LayoutRequest: + case QEvent::Resize: + case QEvent::Move: + case QEvent::LanguageChange: + break; + default: + return QGuiApplication::compressEvent(event, receiver, postedEvents); + } + + for (const auto &postedEvent : std::as_const(*postedEvents)) { + + // Continue, unless a valid event of the same type exists for the same receiver + if (postedEvent.receiver != receiver + || !postedEvent.event + || postedEvent.event->type() != type) { + continue; } - return false; + + // Handle type specific compression + switch (type) { + case QEvent::Resize: + static_cast<QResizeEvent *>(postedEvent.event)->m_size = + static_cast<const QResizeEvent *>(event)->size(); + break; + case QEvent::Move: + static_cast<QMoveEvent *>(postedEvent.event)->m_pos = + static_cast<const QMoveEvent *>(event)->pos(); + break; + case QEvent::UpdateLater: + static_cast<QUpdateLaterEvent *>(postedEvent.event)->m_region += + static_cast<const QUpdateLaterEvent *>(event)->region(); + break; + case QEvent::UpdateRequest: + case QEvent::LanguageChange: + case QEvent::LayoutRequest: + break; + default: + continue; + } + delete event; + return true; } - return QGuiApplication::compressEvent(event, receiver, postedEvents); + return false; } /*! @@ -1032,55 +901,42 @@ void QApplication::setStyleSheet(const QString& styleSheet) */ QStyle *QApplication::style() { - if (QApplicationPrivate::app_style) - return QApplicationPrivate::app_style; - if (!qobject_cast<QApplication *>(QCoreApplication::instance())) { - Q_ASSERT(!"No style available without QApplication!"); - return 0; - } - if (!QApplicationPrivate::app_style) { - // Compile-time search for default style - // - QStyle *&app_style = QApplicationPrivate::app_style; - - if (!QApplicationPrivate::styleOverride.isEmpty()) { - const QString style = QApplicationPrivate::styleOverride.toLower(); - app_style = QStyleFactory::create(style); - if (Q_UNLIKELY(!app_style)) { - qWarning("QApplication: invalid style override passed, ignoring it.\n" - " Available styles: %s", qPrintable(QStyleFactory::keys().join(QLatin1String(", ")))); - } + // Create default style + if (!qobject_cast<QApplication *>(QCoreApplication::instance())) { + Q_ASSERT(!"No style available without QApplication!"); + return nullptr; } - if (!app_style) - app_style = QStyleFactory::create(QApplicationPrivate::desktopStyleKey()); - if (!app_style) { + auto &defaultStyle = QApplicationPrivate::app_style; + + defaultStyle = QStyleFactory::create(QApplicationPrivate::desktopStyleKey()); + if (!defaultStyle) { const QStringList styles = QStyleFactory::keys(); for (const auto &style : styles) { - if ((app_style = QStyleFactory::create(style))) + if ((defaultStyle = QStyleFactory::create(style))) break; } } - if (!app_style) { + if (!defaultStyle) { Q_ASSERT(!"No styles available!"); - return 0; + return nullptr; } - } - // take ownership of the style - QApplicationPrivate::app_style->setParent(qApp); - initSystemPalette(); + // Take ownership of the style + defaultStyle->setParent(qApp); - if (QApplicationPrivate::set_pal) // repolish set palette with the new style - QApplication::setPalette(*QApplicationPrivate::set_pal); + QGuiApplicationPrivate::updatePalette(); #ifndef QT_NO_STYLE_STYLESHEET - if (!QApplicationPrivate::styleSheet.isEmpty()) { - qApp->setStyleSheet(QApplicationPrivate::styleSheet); - } else + if (!QApplicationPrivate::styleSheet.isEmpty()) { + qApp->setStyleSheet(QApplicationPrivate::styleSheet); + } else #endif - QApplicationPrivate::app_style->polish(qApp); + { + defaultStyle->polish(qApp); + } + } return QApplicationPrivate::app_style; } @@ -1141,19 +997,17 @@ void QApplication::setStyle(QStyle *style) QApplicationPrivate::app_style = style; QApplicationPrivate::app_style->setParent(qApp); // take ownership - // take care of possible palette requirements of certain gui - // styles. Do it before polishing the application since the style - // might call QApplication::setPalette() itself - if (QApplicationPrivate::set_pal) { - QApplication::setPalette(*QApplicationPrivate::set_pal); - } else if (QApplicationPrivate::sys_pal) { - clearSystemPalette(); - initSystemPalette(); - QApplicationPrivate::initializeWidgetFontHash(); - } else if (!QApplicationPrivate::sys_pal) { - // Initialize the sys_pal if it hasn't happened yet... - QApplicationPrivate::setSystemPalette(QApplicationPrivate::app_style->standardPalette()); - } + // Take care of possible palette requirements of certain + // styles. Do it before polishing the application since the + // style might call QApplication::setPalette() itself. + QGuiApplicationPrivate::updatePalette(); + + // The default widget font hash is based on the platform theme, + // not the style, but the widget fonts could in theory have been + // affected by polish of the previous style, without a proper + // cleanup in unpolish, so reset it now before polishing the + // new style. + QApplicationPrivate::initializeWidgetFontHash(); // initialize the application with the new style QApplicationPrivate::app_style->polish(qApp); @@ -1176,7 +1030,7 @@ void QApplication::setStyle(QStyle *style) QWidget *w = *it; if (w->windowType() != Qt::Desktop && !w->testAttribute(Qt::WA_SetStyle)) { QEvent e(QEvent::StyleChange); - QApplication::sendEvent(w, &e); + QCoreApplication::sendEvent(w, &e); w->update(); } } @@ -1193,7 +1047,7 @@ void QApplication::setStyle(QStyle *style) if (QApplicationPrivate::focus_widget) { QFocusEvent in(QEvent::FocusIn, Qt::OtherFocusReason); - QApplication::sendEvent(QApplicationPrivate::focus_widget->style(), &in); + QCoreApplication::sendEvent(QApplicationPrivate::focus_widget->style(), &in); QApplicationPrivate::focus_widget->update(); } } @@ -1204,7 +1058,7 @@ void QApplication::setStyle(QStyle *style) Requests a QStyle object for \a style from the QStyleFactory. The string must be one of the QStyleFactory::keys(), typically one of - "windows", "windowsvista", "fusion", or "macintosh". Style + "windows", "windowsvista", "fusion", or "macos". Style names are case insensitive. Returns \nullptr if an unknown \a style is passed, otherwise the QStyle object @@ -1218,114 +1072,45 @@ QStyle* QApplication::setStyle(const QString& style) { QStyle *s = QStyleFactory::create(style); if (!s) - return 0; + return nullptr; setStyle(s); return s; } -/*! - Returns the color specification. - \obsolete - - \sa QApplication::setColorSpec() -*/ +// Widget specific palettes +QApplicationPrivate::PaletteHash QApplicationPrivate::widgetPalettes; -int QApplication::colorSpec() +QPalette QApplicationPrivate::basePalette() const { - return QApplication::NormalColor; -} - -/*! - Sets the color specification for the application to \a spec. - \obsolete - - This call has no effect. - - The color specification controls how the application allocates colors when - run on a display with a limited amount of colors, e.g. 8 bit / 256 color - displays. - - The color specification must be set before you create the QApplication - object. - - The options are: - \list - \li QApplication::NormalColor. This is the default color allocation - strategy. Use this option if your application uses buttons, menus, - texts and pixmaps with few colors. With this option, the - application uses system global colors. This works fine for most - applications under X11, but on the Windows platform, it may cause - dithering of non-standard colors. - \li QApplication::CustomColor. Use this option if your application - needs a small number of custom colors. On X11, this option is the - same as NormalColor. On Windows, Qt creates a Windows palette, and - allocates colors to it on demand. - \li QApplication::ManyColor. Use this option if your application is - very color hungry, e.g., it requires thousands of colors. \br - Under X11 the effect is: - \list - \li For 256-color displays which have at best a 256 color true - color visual, the default visual is used, and colors are - allocated from a color cube. The color cube is the 6x6x6 - (216 color) "Web palette" (the red, green, and blue - components always have one of the following values: 0x00, - 0x33, 0x66, 0x99, 0xCC, or 0xFF), but the number of colors - can be changed by the \e -ncols option. The user can force - the application to use the true color visual with the - \l{QApplication::QApplication()}{-visual} option. - \li For 256-color displays which have a true color visual with - more than 256 colors, use that visual. Silicon Graphics X - servers this feature, for example. They provide an 8 bit - visual by default but can deliver true color when asked. - \endlist - On Windows, Qt creates a Windows palette, and fills it with a color - cube. - \endlist + // Start out with a palette based on the style, in case there's no theme + // available, or so that we can fill in missing roles in the theme. + QPalette palette = app_style ? app_style->standardPalette() : Qt::gray; - Be aware that the CustomColor and ManyColor choices may lead to colormap - flashing: The foreground application gets (most) of the available colors, - while the background windows will look less attractive. + // Prefer theme palette if available, but fill in missing roles from style + // for compatibility. Note that the style's standard palette is not prioritized + // over the theme palette, as the documented way of applying the style's palette + // is to set it explicitly using QApplication::setPalette(). + if (const QPalette *themePalette = platformTheme() ? platformTheme()->palette() : nullptr) + palette = themePalette->resolve(palette); - Example: + // This palette now is Qt-generated, so reset the resolve mask. This allows + // QStyle::polish implementations to respect palettes that are user provided, + // by checking if the palette has a brush set for a color that the style might + // otherwise overwrite. + palette.setResolveMask(0); - \snippet code/src_gui_kernel_qapplication.cpp 2 + // Finish off by letting the application style polish the palette. This will + // not result in the polished palette becoming a user-set palette, as the + // resulting base palette is only used as a fallback, with the resolve mask + // set to 0. + if (app_style) + app_style->polish(palette); - \sa colorSpec() -*/ - -void QApplication::setColorSpec(int spec) -{ - Q_UNUSED(spec) + return palette; } /*! - \property QApplication::globalStrut - \brief the minimum size that any GUI element that the user can interact - with should have - - For example, no button should be resized to be smaller than the global - strut size. The strut size should be considered when reimplementing GUI - controls that may be used on touch-screens or similar I/O devices. - - Example: - - \snippet code/src_gui_kernel_qapplication.cpp 3 - - By default, this property contains a QSize object with zero width and height. -*/ -QSize QApplication::globalStrut() -{ - return QApplicationPrivate::app_strut; -} - -void QApplication::setGlobalStrut(const QSize& strut) -{ - QApplicationPrivate::app_strut = strut; -} - - -/*! \fn QPalette QApplication::palette(const QWidget* widget) If a \a widget is passed, the default palette for the widget's class is @@ -1338,15 +1123,13 @@ void QApplication::setGlobalStrut(const QSize& strut) */ QPalette QApplication::palette(const QWidget* w) { - typedef PaletteHash::const_iterator PaletteHashConstIt; - - PaletteHash *hash = app_palettes(); - if (w && hash && hash->size()) { - PaletteHashConstIt it = hash->constFind(w->metaObject()->className()); - const PaletteHashConstIt cend = hash->constEnd(); + auto &widgetPalettes = QApplicationPrivate::widgetPalettes; + if (w && !widgetPalettes.isEmpty()) { + auto it = widgetPalettes.constFind(w->metaObject()->className()); + const auto cend = widgetPalettes.constEnd(); if (it != cend) return *it; - for (it = hash->constBegin(); it != cend; ++it) { + for (it = widgetPalettes.constBegin(); it != cend; ++it) { if (w->inherits(it.key())) return it.value(); } @@ -1363,57 +1146,18 @@ QPalette QApplication::palette(const QWidget* w) */ QPalette QApplication::palette(const char *className) { - if (!QApplicationPrivate::app_pal) - palette(); - PaletteHash *hash = app_palettes(); - if (className && hash && hash->size()) { - QHash<QByteArray, QPalette>::ConstIterator it = hash->constFind(className); - if (it != hash->constEnd()) + auto &widgetPalettes = QApplicationPrivate::widgetPalettes; + if (className && !widgetPalettes.isEmpty()) { + auto it = widgetPalettes.constFind(className); + if (it != widgetPalettes.constEnd()) return *it; } - return *QApplicationPrivate::app_pal; -} - -void QApplicationPrivate::setPalette_helper(const QPalette &palette, const char* className, bool clearWidgetPaletteHash) -{ - QPalette pal = palette; - - if (QApplicationPrivate::app_style) - QApplicationPrivate::app_style->polish(pal); // NB: non-const reference - - bool all = false; - PaletteHash *hash = app_palettes(); - if (!className) { - if (QApplicationPrivate::app_pal && pal.isCopyOf(*QApplicationPrivate::app_pal)) - return; - if (!QApplicationPrivate::app_pal) - QApplicationPrivate::app_pal = new QPalette(pal); - else - *QApplicationPrivate::app_pal = pal; - if (hash && hash->size()) { - all = true; - if (clearWidgetPaletteHash) - hash->clear(); - } - } else if (hash) { - hash->insert(className, pal); - } - if (QApplicationPrivate::is_app_running && !QApplicationPrivate::is_app_closing) { - // Send ApplicationPaletteChange to qApp itself, and to the widgets. - qApp->d_func()->sendApplicationPaletteChange(all, className); - } - if (!className && (!QApplicationPrivate::sys_pal || !palette.isCopyOf(*QApplicationPrivate::sys_pal))) { - if (!QApplicationPrivate::set_pal) - QApplicationPrivate::set_pal = new QPalette(palette); - else - *QApplicationPrivate::set_pal = palette; - QCoreApplication::setAttribute(Qt::AA_SetPalette); - } + return QGuiApplication::palette(); } /*! - Changes the default application palette to \a palette. + Changes the application palette to \a palette. If \a className is passed, the change applies only to widgets that inherit \a className (as reported by QObject::inherits()). If \a className is left @@ -1434,23 +1178,86 @@ void QApplicationPrivate::setPalette_helper(const QPalette &palette, const char* \sa QWidget::setPalette(), palette(), QStyle::polish() */ - void QApplication::setPalette(const QPalette &palette, const char* className) { - QApplicationPrivate::setPalette_helper(palette, className, /*clearWidgetPaletteHash=*/ true); + if (className) { + QPalette polishedPalette = palette; + if (QApplicationPrivate::app_style) { + auto originalResolveMask = palette.resolveMask(); + QApplicationPrivate::app_style->polish(polishedPalette); + polishedPalette.setResolveMask(originalResolveMask); + } + + QApplicationPrivate::widgetPalettes.insert(className, polishedPalette); + if (qApp) + qApp->d_func()->handlePaletteChanged(className); + } else { + QGuiApplication::setPalette(palette); + } } +void QApplicationPrivate::handlePaletteChanged(const char *className) +{ + if (!is_app_running || is_app_closing) + return; + + // Setting the global application palette is documented to + // reset any previously set class specific widget palettes. + if (!className && !widgetPalettes.isEmpty()) + widgetPalettes.clear(); + + QGuiApplicationPrivate::handlePaletteChanged(className); + + QEvent event(QEvent::ApplicationPaletteChange); + const QWidgetList widgets = QApplication::allWidgets(); + for (auto widget : widgets) { + if (!widget->isWindow() && widget->inherits(className)) + QCoreApplication::sendEvent(widget, &event); + } + +#if QT_CONFIG(graphicsview) + for (auto scene : std::as_const(scene_list)) + QCoreApplication::sendEvent(scene, &event); +#endif + // Palette has been reset back to the default application palette, + // so we need to reinitialize the widget palettes from the theme. + if (!className && !testAttribute(Qt::AA_SetPalette)) + initializeWidgetPalettesFromTheme(); +} -void QApplicationPrivate::setSystemPalette(const QPalette &pal) +void QApplicationPrivate::initializeWidgetPalettesFromTheme() { - if (!sys_pal) - sys_pal = new QPalette(pal); - else - *sys_pal = pal; + QPlatformTheme *platformTheme = QGuiApplicationPrivate::platformTheme(); + if (!platformTheme) + return; - if (!QApplicationPrivate::set_pal) - QApplication::setPalette(*sys_pal); + widgetPalettes.clear(); + + struct ThemedWidget { const char *className; QPlatformTheme::Palette palette; }; + + static const ThemedWidget themedWidgets[] = { + { "QToolButton", QPlatformTheme::ToolButtonPalette }, + { "QAbstractButton", QPlatformTheme::ButtonPalette }, + { "QCheckBox", QPlatformTheme::CheckBoxPalette }, + { "QRadioButton", QPlatformTheme::RadioButtonPalette }, + { "QHeaderView", QPlatformTheme::HeaderPalette }, + { "QAbstractItemView", QPlatformTheme::ItemViewPalette }, + { "QMessageBoxLabel", QPlatformTheme::MessageBoxLabelPalette }, + { "QTabBar", QPlatformTheme::TabBarPalette }, + { "QLabel", QPlatformTheme::LabelPalette }, + { "QGroupBox", QPlatformTheme::GroupBoxPalette }, + { "QMenu", QPlatformTheme::MenuPalette }, + { "QMenuBar", QPlatformTheme::MenuBarPalette }, + { "QTextEdit", QPlatformTheme::TextEditPalette }, + { "QTextControl", QPlatformTheme::TextEditPalette }, + { "QLineEdit", QPlatformTheme::TextLineEditPalette }, + }; + + for (const auto themedWidget : themedWidgets) { + if (auto *palette = platformTheme->palette(themedWidget.palette)) + QApplication::setPalette(*palette, themedWidget.className); + } } /*! @@ -1466,9 +1273,11 @@ QFont QApplication::font() /*! \overload - Returns the default font for the \a widget. + Returns the default font for the \a widget. If a default font was not + registered for the \a{widget}'s class, it returns the default font of + its nearest registered superclass. - \sa fontMetrics(), QWidget::setFont() + \sa fontMetrics(), setFont(), QWidget::setFont() */ QFont QApplication::font(const QWidget *widget) @@ -1486,14 +1295,16 @@ QFont QApplication::font(const QWidget *widget) return hash->value(QByteArrayLiteral("QMiniFont")); } #endif - FontHashConstIt it = hash->constFind(widget->metaObject()->className()); + // Return the font for the nearest registered superclass + const QMetaObject *metaObj = widget->metaObject(); + FontHashConstIt it = hash->constFind(metaObj->className()); const FontHashConstIt cend = hash->constEnd(); + while (it == cend && metaObj != &QWidget::staticMetaObject) { + metaObj = metaObj->superClass(); + it = hash->constFind(metaObj->className()); + } if (it != cend) return it.value(); - for (it = hash->constBegin(); it != cend; ++it) { - if (widget->inherits(it.key())) - return it.value(); - } } return font(); } @@ -1538,26 +1349,20 @@ QFont QApplication::font(const char *className) void QApplication::setFont(const QFont &font, const char *className) { - bool all = false; FontHash *hash = app_fonts(); if (!className) { QGuiApplication::setFont(font); - if (hash && hash->size()) { - all = true; + if (hash && hash->size()) hash->clear(); - } } else if (hash) { hash->insert(className, font); } if (QApplicationPrivate::is_app_running && !QApplicationPrivate::is_app_closing) { - // Send ApplicationFontChange to qApp itself, and to the widgets. QEvent e(QEvent::ApplicationFontChange); - QApplication::sendEvent(QApplication::instance(), &e); - QWidgetList wids = QApplication::allWidgets(); for (QWidgetList::ConstIterator it = wids.constBegin(), cend = wids.constEnd(); it != cend; ++it) { QWidget *w = *it; - if (all || (!className && w->isWindow()) || w->inherits(className)) // matching class + if (!w->isWindow() && w->inherits(className)) // matching class sendEvent(w, &e); } @@ -1566,7 +1371,7 @@ void QApplication::setFont(const QFont &font, const char *className) QList<QGraphicsScene *> &scenes = qApp->d_func()->scene_list; for (QList<QGraphicsScene *>::ConstIterator it = scenes.constBegin(); it != scenes.constEnd(); ++it) { - QApplication::sendEvent(*it, &e); + QCoreApplication::sendEvent(*it, &e); } #endif // QT_CONFIG(graphicsview) } @@ -1595,6 +1400,12 @@ void QApplicationPrivate::setSystemFont(const QFont &font) */ QString QApplicationPrivate::desktopStyleKey() { +#if defined(QT_BUILD_INTERNAL) + // Allow auto-tests to override the desktop style + if (qEnvironmentVariableIsSet("QT_DESKTOP_STYLE_KEY")) + return QString::fromLocal8Bit(qgetenv("QT_DESKTOP_STYLE_KEY")); +#endif + // The platform theme might return a style that is not available, find // first valid one. if (const QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme()) { @@ -1608,24 +1419,6 @@ QString QApplicationPrivate::desktopStyleKey() return QString(); } -#if QT_VERSION < 0x060000 // remove these forwarders in Qt 6 -/*! - \property QApplication::windowIcon - \brief the default window icon - - \sa QWidget::setWindowIcon(), {Setting the Application Icon} -*/ -QIcon QApplication::windowIcon() -{ - return QGuiApplication::windowIcon(); -} - -void QApplication::setWindowIcon(const QIcon &icon) -{ - QGuiApplication::setWindowIcon(icon); -} -#endif - void QApplicationPrivate::notifyWindowIconChanged() { QEvent ev(QEvent::ApplicationWindowIconChange); @@ -1659,12 +1452,12 @@ void QApplicationPrivate::notifyWindowIconChanged() QWidgetList QApplication::topLevelWidgets() { QWidgetList list; - QWidgetList all = allWidgets(); - - for (QWidgetList::ConstIterator it = all.constBegin(), cend = all.constEnd(); it != cend; ++it) { - QWidget *w = *it; - if (w->isWindow() && w->windowType() != Qt::Desktop) - list.append(w); + if (QWidgetPrivate::allWidgets != nullptr) { + const auto isTopLevelWidget = [] (const QWidget *w) { + return w->isWindow() && w->windowType() != Qt::Desktop; + }; + std::copy_if(QWidgetPrivate::allWidgets->cbegin(), QWidgetPrivate::allWidgets->cend(), + std::back_inserter(list), isTopLevelWidget); } return list; } @@ -1685,13 +1478,13 @@ QWidgetList QApplication::topLevelWidgets() QWidgetList QApplication::allWidgets() { if (QWidgetPrivate::allWidgets) - return QWidgetPrivate::allWidgets->toList(); + return QWidgetPrivate::allWidgets->values(); return QWidgetList(); } /*! - Returns the application widget that has the keyboard input focus, or 0 if - no widget in this application has the focus. + Returns the application widget that has the keyboard input focus, + or \nullptr if no widget in this application has the focus. \sa QWidget::setFocus(), QWidget::hasFocus(), activeWindow(), focusChanged() */ @@ -1708,7 +1501,7 @@ void QApplicationPrivate::setFocusWidget(QWidget *focus, Qt::FocusReason reason) return; #endif - hidden_focus_widget = 0; + hidden_focus_widget = nullptr; if (focus != focus_widget) { if (focus && focus->isHidden()) { @@ -1725,7 +1518,7 @@ void QApplicationPrivate::setFocusWidget(QWidget *focus, Qt::FocusReason reason) QWidget *prev = focus_widget; focus_widget = focus; - if(focus_widget) + if (focus_widget) focus_widget->d_func()->setFocus_sys(); if (reason != Qt::NoFocusReason) { @@ -1733,23 +1526,23 @@ void QApplicationPrivate::setFocusWidget(QWidget *focus, Qt::FocusReason reason) //send events if (prev) { #ifdef QT_KEYPAD_NAVIGATION - if (QApplication::keypadNavigationEnabled()) { + if (QApplicationPrivate::keyboardNavigationEnabled()) { if (prev->hasEditFocus() && reason != Qt::PopupFocusReason) prev->setEditFocus(false); } #endif QFocusEvent out(QEvent::FocusOut, reason); QPointer<QWidget> that = prev; - QApplication::sendEvent(prev, &out); + QCoreApplication::sendEvent(prev, &out); if (that) - QApplication::sendEvent(that->style(), &out); + QCoreApplication::sendEvent(that->style(), &out); } - if(focus && QApplicationPrivate::focus_widget == focus) { + if (focus && QApplicationPrivate::focus_widget == focus) { QFocusEvent in(QEvent::FocusIn, reason); QPointer<QWidget> that = focus; - QApplication::sendEvent(focus, &in); + QCoreApplication::sendEvent(focus, &in); if (that) - QApplication::sendEvent(that->style(), &in); + QCoreApplication::sendEvent(that->style(), &in); } emit qApp->focusChanged(prev, focus_widget); } @@ -1759,7 +1552,7 @@ void QApplicationPrivate::setFocusWidget(QWidget *focus, Qt::FocusReason reason) /*! Returns the application top-level window that has the keyboard input focus, - or 0 if no application window has the focus. There might be an + or \nullptr if no application window has the focus. There might be an activeWindow() even if there is no focusWidget(), for example if no widget in that window accepts key events. @@ -1771,7 +1564,9 @@ QWidget *QApplication::activeWindow() return QApplicationPrivate::active_window; } +#if QT_DEPRECATED_SINCE(6,0) /*! + \deprecated Use the QFontMetricsF constructor instead. Returns display (screen) font metrics for the application font. \sa font(), setFont(), QWidget::fontMetrics(), QPainter::fontMetrics() @@ -1779,8 +1574,9 @@ QWidget *QApplication::activeWindow() QFontMetrics QApplication::fontMetrics() { - return desktop()->fontMetrics(); + return QApplicationPrivate::desktop()->fontMetrics(); } +#endif bool QApplicationPrivate::tryCloseAllWidgetWindows(QWindowList *processedWindows) { @@ -1811,30 +1607,21 @@ retry: return true; } -bool QApplicationPrivate::tryCloseAllWindows() -{ - QWindowList processedWindows; - return QApplicationPrivate::tryCloseAllWidgetWindows(&processedWindows) - && QGuiApplicationPrivate::tryCloseRemainingWindows(processedWindows); -} - /*! Closes all top-level windows. This function is particularly useful for applications with many top-level - windows. It could, for example, be connected to a \uicontrol{Exit} entry in the - \uicontrol{File} menu: - - \snippet mainwindows/mdi/mainwindow.cpp 0 + windows. The windows are closed in random order, until one window does not accept - the close event. The application quits when the last window was - successfully closed; this can be turned off by setting - \l quitOnLastWindowClosed to false. + the close event. The application quits when the last window was successfully + closed, unless \l quitOnLastWindowClosed is set to false. To trigger application + termination from e.g. a menu, use QCoreApplication::quit() instead of this + function. \sa quitOnLastWindowClosed, lastWindowClosed(), QWidget::close(), - QWidget::closeEvent(), lastWindowClosed(), QCoreApplication::quit(), topLevelWidgets(), - QWidget::isWindow() + QWidget::closeEvent(), lastWindowClosed(), QCoreApplication::quit(), + topLevelWidgets(), QWidget::isWindow() */ void QApplication::closeAllWindows() { @@ -1864,8 +1651,8 @@ void QApplication::aboutQt() This signal is emitted when the widget that has keyboard focus changed from \a old to \a now, i.e., because the user pressed the tab-key, clicked into - a widget or changed the active window. Both \a old and \a now can be the - null-pointer. + a widget or changed the active window. Both \a old and \a now can be \nullptr. + The signal is emitted after both widget have been notified about the change through QFocusEvent. @@ -1879,24 +1666,28 @@ void QApplication::aboutQt() bool QApplication::event(QEvent *e) { Q_D(QApplication); - if(e->type() == QEvent::Close) { - QCloseEvent *ce = static_cast<QCloseEvent*>(e); - ce->accept(); + switch (e->type()) { + case QEvent::Quit: + // FIXME: This logic first tries to close all windows, and then + // checks whether it was successful, but the conditions used in + // closeAllWindows() differ from the verification logic below. + // We should build on the logic in tryCloseAllWidgetWindows(). closeAllWindows(); - - const QWidgetList list = topLevelWidgets(); - for (auto *w : list) { + for (auto *w : topLevelWidgets()) { + if (w->data->is_closing) + continue; if (w->isVisible() && !(w->windowType() == Qt::Desktop) && !(w->windowType() == Qt::Popup) && - (!(w->windowType() == Qt::Dialog) || !w->parentWidget())) { - ce->ignore(); - break; + (!(w->windowType() == Qt::Dialog) || !w->parentWidget()) && !w->testAttribute(Qt::WA_DontShowOnScreen)) { + e->ignore(); + return true; } } - if (ce->isAccepted()) { - return true; - } + // Explicitly call QCoreApplication instead of QGuiApplication so that + // we don't let QGuiApplication close any windows we skipped earlier in + // closeAllWindows(). FIXME: Unify all this close magic through closeAllWindows. + return QCoreApplication::event(e); #ifndef Q_OS_WIN - } else if (e->type() == QEvent::LocaleChange) { + case QEvent::LocaleChange: { // on Windows the event propagation is taken care by the // WM_SETTINGCHANGE event handler. const QWidgetList list = topLevelWidgets(); @@ -1906,10 +1697,12 @@ bool QApplication::event(QEvent *e) w->d_func()->setLocale_helper(QLocale(), true); } } + break; + } #endif - } else if (e->type() == QEvent::Timer) { + case QEvent::Timer: { QTimerEvent *te = static_cast<QTimerEvent*>(e); - Q_ASSERT(te != 0); + Q_ASSERT(te != nullptr); if (te->timerId() == d->toolTipWakeUp.timerId()) { d->toolTipWakeUp.stop(); if (d->toolTipWidget) { @@ -1921,14 +1714,14 @@ bool QApplication::event(QEvent *e) while (w && !showToolTip) { showToolTip = w->isActiveWindow(); w = w->parentWidget(); - w = w ? w->window() : 0; + w = w ? w->window() : nullptr; } if (showToolTip) { QHelpEvent e(QEvent::ToolTip, d->toolTipPos, d->toolTipGlobalPos); - QApplication::sendEvent(d->toolTipWidget, &e); + QCoreApplication::sendEvent(d->toolTipWidget, &e); if (e.isAccepted()) { QStyle *s = d->toolTipWidget->style(); - int sleepDelay = s->styleHint(QStyle::SH_ToolTip_FallAsleepDelay, 0, d->toolTipWidget, 0); + int sleepDelay = s->styleHint(QStyle::SH_ToolTip_FallAsleepDelay, nullptr, d->toolTipWidget, nullptr); d->toolTipFallAsleep.start(sleepDelay, this); } } @@ -1936,31 +1729,33 @@ bool QApplication::event(QEvent *e) } else if (te->timerId() == d->toolTipFallAsleep.timerId()) { d->toolTipFallAsleep.stop(); } + break; + } #if QT_CONFIG(whatsthis) - } else if (e->type() == QEvent::EnterWhatsThisMode) { + case QEvent::EnterWhatsThisMode: QWhatsThis::enterWhatsThisMode(); return true; #endif - } - - if(e->type() == QEvent::LanguageChange) { + case QEvent::LanguageChange: + case QEvent::ApplicationFontChange: + case QEvent::ApplicationPaletteChange: { + // QGuiApplication::event does not account for the cases where + // there is a top level widget without a window handle. So they + // need to have the event posted here const QWidgetList list = topLevelWidgets(); for (auto *w : list) { - if (!(w->windowType() == Qt::Desktop)) - postEvent(w, new QEvent(QEvent::LanguageChange)); + if (!w->windowHandle() && (w->windowType() != Qt::Desktop)) + postEvent(w, new QEvent(e->type())); } + break; + } + default: + break; } return QGuiApplication::event(e); } -/*! - \fn void QApplication::syncX() - Was used to synchronize with the X server in 4.x, here for source compatibility. - \internal - \obsolete -*/ - // ### FIXME: topLevelWindows does not contain QWidgets without a parent // until QWidgetPrivate::create is called. So we have to override the // QGuiApplication::notifyLayoutDirectionChange @@ -1987,6 +1782,7 @@ void QApplicationPrivate::notifyLayoutDirectionChange() /*! \fn void QApplication::setActiveWindow(QWidget* active) + \deprecated [6.5] Use QWidget::activateWindow() instead. Sets the active window to the \a active widget in response to a system event. The function is called from the platform specific event handlers. @@ -2003,9 +1799,16 @@ void QApplicationPrivate::notifyLayoutDirectionChange() \sa activeWindow(), QWidget::activateWindow() */ +#if QT_DEPRECATED_SINCE(6,5) void QApplication::setActiveWindow(QWidget* act) { - QWidget* window = act?act->window():0; + QApplicationPrivate::setActiveWindow(act); +} +#endif + +void QApplicationPrivate::setActiveWindow(QWidget* act) +{ + QWidget* window = act?act->window():nullptr; if (QApplicationPrivate::active_window == window) return; @@ -2021,8 +1824,8 @@ void QApplication::setActiveWindow(QWidget* act) QWidgetList toBeDeactivated; if (QApplicationPrivate::active_window) { - if (style()->styleHint(QStyle::SH_Widget_ShareActivation, 0, QApplicationPrivate::active_window)) { - const QWidgetList list = topLevelWidgets(); + if (QApplication::style()->styleHint(QStyle::SH_Widget_ShareActivation, nullptr, QApplicationPrivate::active_window)) { + const QWidgetList list = QApplication::topLevelWidgets(); for (auto *w : list) { if (w->isVisible() && w->isActiveWindow()) toBeDeactivated.append(w); @@ -2037,14 +1840,14 @@ void QApplication::setActiveWindow(QWidget* act) QGuiApplication::inputMethod()->commit(); QFocusEvent focusAboutToChange(QEvent::FocusAboutToChange, Qt::ActiveWindowFocusReason); - QApplication::sendEvent(QApplicationPrivate::focus_widget, &focusAboutToChange); + QCoreApplication::sendEvent(QApplicationPrivate::focus_widget, &focusAboutToChange); } QApplicationPrivate::active_window = window; if (QApplicationPrivate::active_window) { - if (style()->styleHint(QStyle::SH_Widget_ShareActivation, 0, QApplicationPrivate::active_window)) { - const QWidgetList list = topLevelWidgets(); + if (QApplication::style()->styleHint(QStyle::SH_Widget_ShareActivation, nullptr, QApplicationPrivate::active_window)) { + const QWidgetList list = QApplication::topLevelWidgets(); for (auto *w : list) { if (w->isVisible() && w->isActiveWindow()) toBeActivated.append(w); @@ -2062,20 +1865,20 @@ void QApplication::setActiveWindow(QWidget* act) for (int i = 0; i < toBeActivated.size(); ++i) { QWidget *w = toBeActivated.at(i); - sendSpontaneousEvent(w, &windowActivate); - sendSpontaneousEvent(w, &activationChange); + QApplication::sendSpontaneousEvent(w, &windowActivate); + QApplication::sendSpontaneousEvent(w, &activationChange); } for(int i = 0; i < toBeDeactivated.size(); ++i) { QWidget *w = toBeDeactivated.at(i); - sendSpontaneousEvent(w, &windowDeactivate); - sendSpontaneousEvent(w, &activationChange); + QApplication::sendSpontaneousEvent(w, &windowDeactivate); + QApplication::sendSpontaneousEvent(w, &activationChange); } - if (QApplicationPrivate::popupWidgets == 0) { // !inPopupMode() + if (QApplicationPrivate::popupWidgets == nullptr) { // !inPopupMode() // then focus events if (!QApplicationPrivate::active_window && QApplicationPrivate::focus_widget) { - QApplicationPrivate::setFocusWidget(0, Qt::ActiveWindowFocusReason); + QApplicationPrivate::setFocusWidget(nullptr, Qt::ActiveWindowFocusReason); } else if (QApplicationPrivate::active_window) { QWidget *w = QApplicationPrivate::active_window->focusWidget(); if (w && w->isVisible() /*&& w->focusPolicy() != QWidget::NoFocus*/) @@ -2085,12 +1888,13 @@ void QApplication::setActiveWindow(QWidget* act) if (w) { w->setFocus(Qt::ActiveWindowFocusReason); } else { - // If the focus widget is not in the activate_window, clear the focus w = QApplicationPrivate::focus_widget; - if (!w && QApplicationPrivate::active_window->focusPolicy() != Qt::NoFocus) - QApplicationPrivate::setFocusWidget(QApplicationPrivate::active_window, Qt::ActiveWindowFocusReason); - else if (!QApplicationPrivate::active_window->isAncestorOf(w)) - QApplicationPrivate::setFocusWidget(0, Qt::ActiveWindowFocusReason); + if (!w && QApplicationPrivate::active_window->focusPolicy() != Qt::NoFocus) { + QApplicationPrivate::active_window->setFocus(Qt::ActiveWindowFocusReason); + } else if (!QApplicationPrivate::active_window->isAncestorOf(w)) { + // If the focus widget is not in the activate_window, clear the focus + QApplicationPrivate::setFocusWidget(nullptr, Qt::ActiveWindowFocusReason); + } } } } @@ -2112,30 +1916,48 @@ QWidget *qt_tlw_for_window(QWindow *wnd) wnd = wnd->parent(); } if (wnd) { - const auto tlws = qApp->topLevelWidgets(); + const auto tlws = QApplication::topLevelWidgets(); for (QWidget *tlw : tlws) { if (tlw->windowHandle() == wnd) return tlw; } } - return 0; + return nullptr; } void QApplicationPrivate::notifyActiveWindowChange(QWindow *previous) { - Q_UNUSED(previous); - QWindow *wnd = QGuiApplicationPrivate::focus_window; - if (inPopupMode()) // some delayed focus event to ignore +#ifndef Q_OS_MACOS + // Some delayed focus event to ignore, unless we are on cocoa where + // popups can be opened via right-click on inactive applications + if (inPopupMode()) return; - QWidget *tlw = qt_tlw_for_window(wnd); - QApplication::setActiveWindow(tlw); +#endif + QWindow *focusWindow = QGuiApplicationPrivate::focus_window; + QWidget *focusWidget = qt_tlw_for_window(focusWindow); + QApplicationPrivate::setActiveWindow(focusWidget); // QTBUG-37126, Active X controls may set the focus on native child widgets. - if (wnd && tlw && wnd != tlw->windowHandle()) { - if (QWidgetWindow *widgetWindow = qobject_cast<QWidgetWindow *>(wnd)) + if (focusWindow && focusWidget && focusWindow != focusWidget->windowHandle()) { + if (QWidgetWindow *widgetWindow = qobject_cast<QWidgetWindow *>(focusWindow)) if (QWidget *widget = widgetWindow->widget()) if (widget->inherits("QAxHostWidget")) widget->setFocus(Qt::ActiveWindowFocusReason); } + + // QApplication::setActiveWindow() will deliver window activation events for + // QWidgetWindows. But for other subclasses of QWindow (like QQuickWindow), we + // need to send them explicitly, like we do from the base class implementation. + if (previous && !qobject_cast<QWidgetWindow *>(previous)) { + QEvent de(QEvent::WindowDeactivate); + QCoreApplication::sendEvent(previous, &de); + } + + if (focusWindow && !qobject_cast<QWidgetWindow *>(focusWindow)) { + QEvent ae(QEvent::WindowActivate); + QCoreApplication::sendEvent(focusWindow, &ae); + } + + // don't call base class to avoid double delivery of WindowActivate/Deactivate events } /*!internal @@ -2153,7 +1975,7 @@ QWidget *QApplicationPrivate::focusNextPrevChild_helper(QWidget *toplevel, bool f = toplevel; QWidget *w = f; - QWidget *test = f->d_func()->focus_next; + QWidget *test = f->nextInFocusChain(); bool seenWindow = false; bool focusWidgetAfterWindow = false; while (test && test != f) { @@ -2165,23 +1987,29 @@ QWidget *QApplicationPrivate::focusNextPrevChild_helper(QWidget *toplevel, bool // \a next). This is to ensure that we can tab in and out of compound widgets // without getting stuck in a tab-loop between parent and child. QWidget *focusProxy = test->d_func()->deepestFocusProxy(); - - if ((test->focusPolicy() & focus_flag) == focus_flag - && !(next && focusProxy && focusProxy->isAncestorOf(test)) - && !(!next && focusProxy && test->isAncestorOf(focusProxy)) + auto effectiveFocusPolicy = [](QWidget *widget) { + return widget->isEnabled() ? widget->focusPolicy() : Qt::NoFocus; + }; + const bool canTakeFocus = (effectiveFocusPolicy(focusProxy ? focusProxy : test) + & focus_flag) == focus_flag; + const bool composites = focusProxy ? (next ? focusProxy->isAncestorOf(test) + : test->isAncestorOf(focusProxy)) + : false; + if (canTakeFocus && !composites && test->isVisibleTo(toplevel) && test->isEnabled() && !(w->windowType() == Qt::SubWindow && !w->isAncestorOf(test)) - && (toplevel->windowType() != Qt::SubWindow || toplevel->isAncestorOf(test))) { + && (toplevel->windowType() != Qt::SubWindow || toplevel->isAncestorOf(test)) + && f != focusProxy) { w = test; if (seenWindow) focusWidgetAfterWindow = true; if (next) break; } - test = test->d_func()->focus_next; + test = test->nextInFocusChain(); } - if (wrappingOccurred != 0) + if (wrappingOccurred != nullptr) *wrappingOccurred = next ? focusWidgetAfterWindow : !focusWidgetAfterWindow; if (w == f) { @@ -2189,7 +2017,7 @@ QWidget *QApplicationPrivate::focusNextPrevChild_helper(QWidget *toplevel, bool w->window()->setAttribute(Qt::WA_KeyboardFocusChange); w->update(); } - return 0; + return nullptr; } return w; } @@ -2203,24 +2031,9 @@ QWidget *QApplicationPrivate::focusNextPrevChild_helper(QWidget *toplevel, bool */ void QApplicationPrivate::dispatchEnterLeave(QWidget* enter, QWidget* leave, const QPointF &globalPosF) { -#if 0 - if (leave) { - QEvent e(QEvent::Leave); - QApplication::sendEvent(leave, & e); - } - if (enter) { - const QPoint windowPos = enter->window()->mapFromGlobal(globalPos); - QEnterEvent e(enter->mapFromGlobal(globalPos), windowPos, globalPos); - QApplication::sendEvent(enter, & e); - } - return; -#endif - if ((!enter && !leave) || (enter == leave)) return; -#ifdef ALIEN_DEBUG - qDebug() << "QApplicationPrivate::dispatchEnterLeave, ENTER:" << enter << "LEAVE:" << leave; -#endif + QWidgetList leaveList; QWidgetList enterList; @@ -2271,33 +2084,34 @@ void QApplicationPrivate::dispatchEnterLeave(QWidget* enter, QWidget* leave, con QEvent leaveEvent(QEvent::Leave); for (int i = 0; i < leaveList.size(); ++i) { auto *w = leaveList.at(i); - if (!QApplication::activeModalWidget() || QApplicationPrivate::tryModalHelper(w, 0)) { - QApplication::sendEvent(w, &leaveEvent); + if (!QApplication::activeModalWidget() || QApplicationPrivate::tryModalHelper(w, nullptr)) { + QCoreApplication::sendEvent(w, &leaveEvent); if (w->testAttribute(Qt::WA_Hover) && (!QApplication::activePopupWidget() || QApplication::activePopupWidget() == w->window())) { Q_ASSERT(instance()); - QHoverEvent he(QEvent::HoverLeave, QPoint(-1, -1), w->mapFromGlobal(QApplicationPrivate::instance()->hoverGlobalPos), - QApplication::keyboardModifiers()); + QHoverEvent he(QEvent::HoverLeave, QPointF(-1, -1), globalPosF, w->mapFromGlobal(globalPosF), + QGuiApplication::keyboardModifiers()); qApp->d_func()->notify_helper(w, &he); } } } if (!enterList.isEmpty()) { // Guard against QGuiApplicationPrivate::lastCursorPosition initialized to qInf(), qInf(). - const QPoint globalPos = qIsInf(globalPosF.x()) - ? QPoint(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX) - : globalPosF.toPoint(); - const QPoint windowPos = qAsConst(enterList).back()->window()->mapFromGlobal(globalPos); + const QPointF globalPos = qIsInf(globalPosF.x()) + ? QPointF(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX) + : globalPosF; + const QPointF windowPos = std::as_const(enterList).back()->window()->mapFromGlobal(globalPos); for (auto it = enterList.crbegin(), end = enterList.crend(); it != end; ++it) { auto *w = *it; - if (!QApplication::activeModalWidget() || QApplicationPrivate::tryModalHelper(w, 0)) { + if (!QApplication::activeModalWidget() || QApplicationPrivate::tryModalHelper(w, nullptr)) { const QPointF localPos = w->mapFromGlobal(globalPos); - QEnterEvent enterEvent(localPos, windowPos, globalPosF); - QApplication::sendEvent(w, &enterEvent); + QEnterEvent enterEvent(localPos, windowPos, globalPos); + QCoreApplication::sendEvent(w, &enterEvent); if (w->testAttribute(Qt::WA_Hover) && (!QApplication::activePopupWidget() || QApplication::activePopupWidget() == w->window())) { - QHoverEvent he(QEvent::HoverEnter, localPos, QPoint(-1, -1), - QApplication::keyboardModifiers()); + QHoverEvent he(QEvent::HoverEnter, windowPos, QPointF(-1, -1), globalPos, + QGuiApplication::keyboardModifiers()); + QMutableEventPoint::setPosition(he.point(0), localPos); qApp->d_func()->notify_helper(w, &he); } } @@ -2310,7 +2124,7 @@ void QApplicationPrivate::dispatchEnterLeave(QWidget* enter, QWidget* leave, con const bool enterOnAlien = (enter && (isAlien(enter) || enter->testAttribute(Qt::WA_DontShowOnScreen))); // Whenever we leave an alien widget on X11/QPA, we need to reset its nativeParentWidget()'s cursor. // This is not required on Windows as the cursor is reset on every single mouse move. - QWidget *parentOfLeavingCursor = 0; + QWidget *parentOfLeavingCursor = nullptr; for (int i = 0; i < leaveList.size(); ++i) { auto *w = leaveList.at(i); if (!isAlien(w)) @@ -2331,7 +2145,7 @@ void QApplicationPrivate::dispatchEnterLeave(QWidget* enter, QWidget* leave, con if (!parentOfLeavingCursor->window()->graphicsProxyWidget()) #endif { - if (enter == QApplication::desktop()) { + if (enter == QApplicationPrivate::desktop()) { qt_qpa_set_cursor(enter, true); } else { qt_qpa_set_cursor(parentOfLeavingCursor, true); @@ -2374,107 +2188,16 @@ bool QApplicationPrivate::isBlockedByModal(QWidget *widget) return window && self->isWindowBlocked(window); } -bool QApplicationPrivate::isWindowBlocked(QWindow *window, QWindow **blockingWindow) const +Qt::WindowModality QApplicationPrivate::defaultModality() const { - QWindow *unused = 0; - if (Q_UNLIKELY(!window)) { - qWarning().nospace() << "window == 0 passed."; - return false; - } - if (!blockingWindow) - blockingWindow = &unused; + return Qt::ApplicationModal; +} - if (modalWindowList.isEmpty()) { - *blockingWindow = 0; - return false; - } +bool QApplicationPrivate::windowNeverBlocked(QWindow *window) const +{ QWidget *popupWidget = QApplication::activePopupWidget(); - QWindow *popupWindow = popupWidget ? popupWidget->windowHandle() : 0; - if (popupWindow == window || (!popupWindow && QWindowPrivate::get(window)->isPopup())) { - *blockingWindow = 0; - return false; - } - - for (int i = 0; i < modalWindowList.count(); ++i) { - QWindow *modalWindow = modalWindowList.at(i); - - // A window is not blocked by another modal window if the two are - // the same, or if the window is a child of the modal window. - if (window == modalWindow || modalWindow->isAncestorOf(window, QWindow::IncludeTransients)) { - *blockingWindow = 0; - return false; - } - - Qt::WindowModality windowModality = modalWindow->modality(); - QWidgetWindow *modalWidgetWindow = qobject_cast<QWidgetWindow *>(modalWindow); - if (windowModality == Qt::NonModal) { - // determine the modality type if it hasn't been set on the - // modalWindow's widget, this normally happens when waiting for a - // native dialog. use WindowModal if we are the child of a group - // leader; otherwise use ApplicationModal. - QWidget *m = modalWidgetWindow ? modalWidgetWindow->widget() : 0; - while (m && !m->testAttribute(Qt::WA_GroupLeader)) { - m = m->parentWidget(); - if (m) - m = m->window(); - } - windowModality = (m && m->testAttribute(Qt::WA_GroupLeader)) - ? Qt::WindowModal - : Qt::ApplicationModal; - } - - switch (windowModality) { - case Qt::ApplicationModal: - { - QWidgetWindow *widgetWindow = qobject_cast<QWidgetWindow *>(window); - QWidget *groupLeaderForWidget = widgetWindow ? widgetWindow->widget() : 0; - while (groupLeaderForWidget && !groupLeaderForWidget->testAttribute(Qt::WA_GroupLeader)) - groupLeaderForWidget = groupLeaderForWidget->parentWidget(); - - if (groupLeaderForWidget) { - // if \a widget has WA_GroupLeader, it can only be blocked by ApplicationModal children - QWidget *m = modalWidgetWindow ? modalWidgetWindow->widget() : 0; - while (m && m != groupLeaderForWidget && !m->testAttribute(Qt::WA_GroupLeader)) - m = m->parentWidget(); - if (m == groupLeaderForWidget) { - *blockingWindow = m->windowHandle(); - return true; - } - } else if (modalWindow != window) { - *blockingWindow = modalWindow; - return true; - } - break; - } - case Qt::WindowModal: - { - QWindow *w = window; - do { - QWindow *m = modalWindow; - do { - if (m == w) { - *blockingWindow = m; - return true; - } - QWindow *p = m->parent(); - if (!p) - p = m->transientParent(); - m = p; - } while (m); - QWindow *p = w->parent(); - if (!p) - p = w->transientParent(); - w = p; - } while (w); - break; - } - default: - Q_ASSERT_X(false, "QApplication", "internal error, a modal window cannot be modeless"); - break; - } - } - *blockingWindow = 0; - return false; + QWindow *popupWindow = popupWidget ? popupWidget->windowHandle() : nullptr; + return popupWindow == window || (!popupWindow && QWindowPrivate::get(window)->isPopup()); } /*!\internal @@ -2497,7 +2220,7 @@ bool QApplicationPrivate::tryModalHelper(QWidget *widget, QWidget **rettop) bool qt_try_modal(QWidget *widget, QEvent::Type type) { - QWidget * top = 0; + QWidget * top = nullptr; if (QApplicationPrivate::tryModalHelper(widget, &top)) return true; @@ -2505,12 +2228,6 @@ bool qt_try_modal(QWidget *widget, QEvent::Type type) bool block_event = false; switch (type) { -#if 0 - case QEvent::Focus: - if (!static_cast<QWSFocusEvent*>(event)->simpleData.get_focus) - break; - // drop through -#endif case QEvent::MouseButtonPress: // disallow mouse/key events case QEvent::MouseButtonRelease: case QEvent::MouseMove: @@ -2522,7 +2239,7 @@ bool qt_try_modal(QWidget *widget, QEvent::Type type) break; } - if (block_event && top && top->parentWidget() == 0) + if (block_event && top && top->parentWidget() == nullptr) top->raise(); return !block_event; @@ -2546,11 +2263,11 @@ QWidget *QApplicationPrivate::pickMouseReceiver(QWidget *candidate, const QPoint QWidget *mouseGrabber = QWidget::mouseGrabber(); if (((type == QEvent::MouseMove && buttons) || (type == QEvent::MouseButtonRelease)) && !buttonDown && !mouseGrabber) { - return 0; + return nullptr; } if (alienWidget && alienWidget->internalWinId()) - alienWidget = 0; + alienWidget = nullptr; QWidget *receiver = candidate; @@ -2560,9 +2277,6 @@ QWidget *QApplicationPrivate::pickMouseReceiver(QWidget *candidate, const QPoint if (mouseGrabber && mouseGrabber != candidate) { receiver = mouseGrabber; *pos = receiver->mapFromGlobal(candidate->mapToGlobal(windowPos)); -#ifdef ALIEN_DEBUG - qDebug() << " ** receiver adjusted to:" << receiver << "pos:" << pos; -#endif } return receiver; @@ -2583,7 +2297,7 @@ bool QApplicationPrivate::sendMouseEvent(QWidget *receiver, QMouseEvent *event, Q_ASSERT(buttonDown); if (alienWidget && !isAlien(alienWidget)) - alienWidget = 0; + alienWidget = nullptr; QPointer<QWidget> receiverGuard = receiver; QPointer<QWidget> nativeGuard = nativeWidget; @@ -2592,13 +2306,13 @@ bool QApplicationPrivate::sendMouseEvent(QWidget *receiver, QMouseEvent *event, const bool graphicsWidget = nativeWidget->testAttribute(Qt::WA_DontShowOnScreen); - bool widgetUnderMouse = QRectF(receiver->rect()).contains(event->localPos()); + bool widgetUnderMouse = QRectF(receiver->rect()).contains(event->position()); // Clear the obsolete leaveAfterRelease value, if mouse button has been released but // leaveAfterRelease has not been updated. // This happens e.g. when modal dialog or popup is shown as a response to button click. if (leaveAfterRelease && !*buttonDown && !event->buttons()) - leaveAfterRelease = 0; + leaveAfterRelease = nullptr; if (*buttonDown) { if (!graphicsWidget) { @@ -2607,7 +2321,7 @@ bool QApplicationPrivate::sendMouseEvent(QWidget *receiver, QMouseEvent *event, if ((alienWidget || !receiver->internalWinId()) && !leaveAfterRelease && !QWidget::mouseGrabber()) leaveAfterRelease = *buttonDown; if (event->type() == QEvent::MouseButtonRelease && !event->buttons()) - *buttonDown = 0; + *buttonDown = nullptr; } } else if (lastMouseReceiver && widgetUnderMouse) { // Dispatch enter/leave if we move: @@ -2618,24 +2332,17 @@ bool QApplicationPrivate::sendMouseEvent(QWidget *receiver, QMouseEvent *event, || (isAlien(lastMouseReceiver) && !alienWidget)) { if (activePopupWidget) { if (!QWidget::mouseGrabber()) - dispatchEnterLeave(alienWidget ? alienWidget : nativeWidget, lastMouseReceiver, event->screenPos()); + dispatchEnterLeave(alienWidget ? alienWidget : nativeWidget, lastMouseReceiver, event->globalPosition()); } else { - dispatchEnterLeave(receiver, lastMouseReceiver, event->screenPos()); + dispatchEnterLeave(receiver, lastMouseReceiver, event->globalPosition()); } } } -#ifdef ALIEN_DEBUG - qDebug() << "QApplicationPrivate::sendMouseEvent: receiver:" << receiver - << "pos:" << event->pos() << "alien" << alienWidget << "button down" - << *buttonDown << "last" << lastMouseReceiver << "leave after release" - << leaveAfterRelease; -#endif - // We need this quard in case someone opens a modal dialog / popup. If that's the case // leaveAfterRelease is set to null, but we shall not update lastMouseReceiver. - const bool wasLeaveAfterRelease = leaveAfterRelease != 0; + const bool wasLeaveAfterRelease = leaveAfterRelease != nullptr; bool result = true; // This code is used for sending the synthetic enter/leave events for cases where it is needed // due to other events causing the widget under the mouse to change. However in those cases @@ -2645,7 +2352,7 @@ bool QApplicationPrivate::sendMouseEvent(QWidget *receiver, QMouseEvent *event, if (spontaneous) result = QApplication::sendSpontaneousEvent(receiver, event); else - result = QApplication::sendEvent(receiver, event); + result = QCoreApplication::sendEvent(receiver, event); } if (!graphicsWidget && leaveAfterRelease && event->type() == QEvent::MouseButtonRelease @@ -2653,20 +2360,20 @@ bool QApplicationPrivate::sendMouseEvent(QWidget *receiver, QMouseEvent *event, // Dispatch enter/leave if: // 1) the mouse grabber is an alien widget // 2) the button is released on an alien widget - QWidget *enter = 0; + QWidget *enter = nullptr; if (nativeGuard) enter = alienGuard ? alienWidget : nativeWidget; else // The receiver is typically deleted on mouse release with drag'n'drop. - enter = QApplication::widgetAt(event->globalPos()); - dispatchEnterLeave(enter, leaveAfterRelease, event->screenPos()); - leaveAfterRelease = 0; + enter = QApplication::widgetAt(event->globalPosition().toPoint()); + dispatchEnterLeave(enter, leaveAfterRelease, event->globalPosition()); + leaveAfterRelease = nullptr; lastMouseReceiver = enter; } else if (!wasLeaveAfterRelease) { if (activePopupWidget) { if (!QWidget::mouseGrabber()) - lastMouseReceiver = alienGuard ? alienWidget : (nativeGuard ? nativeWidget : 0); + lastMouseReceiver = alienGuard ? alienWidget : (nativeGuard ? nativeWidget : nullptr); } else { - lastMouseReceiver = receiverGuard ? receiver : QApplication::widgetAt(event->globalPos()); + lastMouseReceiver = receiverGuard ? receiver : QApplication::widgetAt(event->globalPosition().toPoint()); } } @@ -2677,7 +2384,7 @@ bool QApplicationPrivate::sendMouseEvent(QWidget *receiver, QMouseEvent *event, This function should only be called when the widget changes visibility, i.e. when the \a widget is shown, hidden or deleted. This function does nothing if the widget is a top-level or native, i.e. not an alien widget. In that - case enter/leave events are genereated by the underlying windowing system. + case enter/leave events are generated by the underlying windowing system. */ extern QPointer<QWidget> qt_last_mouse_receiver; extern Q_WIDGETS_EXPORT QWidget *qt_button_down; @@ -2691,7 +2398,7 @@ void QApplicationPrivate::sendSyntheticEnterLeave(QWidget *widget) return; // Widget was not under the cursor when it was hidden/deleted. if (widgetInShow && widget->parentWidget()->data->in_show) - return; // Ingore recursive show. + return; // Ignore recursive show. QWidget *mouseGrabber = QWidget::mouseGrabber(); if (mouseGrabber && mouseGrabber != widget) @@ -2719,7 +2426,7 @@ void QApplicationPrivate::sendSyntheticEnterLeave(QWidget *widget) return; // Mouse cursor not inside the widget or any of its children. if (widget->data->in_destructor && qt_button_down == widget) - qt_button_down = 0; + qt_button_down = nullptr; // A mouse move is not actually sent, but we utilize the sendMouseEvent() call to send the // enter/leave events as appropriate @@ -2731,22 +2438,19 @@ void QApplicationPrivate::sendSyntheticEnterLeave(QWidget *widget) } /*! - Returns the desktop widget (also called the root window). + \internal - The desktop may be composed of multiple screens, so it would be incorrect, - for example, to attempt to \e center some widget in the desktop's geometry. - QDesktopWidget has various functions for obtaining useful geometries upon - the desktop, such as QDesktopWidget::screenGeometry() and - QDesktopWidget::availableGeometry(). + Returns the desktop widget (also called the root window). - On X11, it is also possible to draw on the desktop. + The widget represents the entire virtual desktop, and its geometry will + be the union of all screens. */ -QDesktopWidget *QApplication::desktop() +QWidget *QApplicationPrivate::desktop() { CHECK_QAPP_INSTANCE(nullptr) if (!qt_desktopWidget || // not created yet !(qt_desktopWidget->windowType() == Qt::Desktop)) { // reparented away - qt_desktopWidget = new QDesktopWidget(); + qt_desktopWidget = new QWidget(nullptr, Qt::Desktop); } return qt_desktopWidget; } @@ -2776,7 +2480,7 @@ void QApplication::setStartDragTime(int ms) The default value is 500 ms. - \sa startDragDistance(), {Drag and Drop} + \sa startDragDistance(), {Drag and Drop in Qt}{Drag and Drop} */ int QApplication::startDragTime() @@ -2797,6 +2501,7 @@ void QApplication::setStartDragDistance(int l) /*! \property QApplication::startDragDistance + \brief the minimum distance required for a drag and drop operation to start. If you support drag and drop in your application, and want to start a drag and drop operation after the user has moved the cursor a certain distance @@ -2814,7 +2519,7 @@ void QApplication::setStartDragDistance(int l) The default value (if the platform doesn't provide a different default) is 10 pixels. - \sa startDragTime(), QPoint::manhattanLength(), {Drag and Drop} + \sa startDragTime(), QPoint::manhattanLength(), {Drag and Drop in Qt}{Drag and Drop} */ int QApplication::startDragDistance() @@ -2836,8 +2541,9 @@ int QApplication::startDragDistance() exec(), because modal widgets call exec() to start a local event loop. To make your application perform idle processing, i.e., executing a special - function whenever there are no pending events, use a QTimer with 0 timeout. - More advanced idle processing schemes can be achieved using processEvents(). + function whenever there are no pending events, use a QChronoTimer with 0ns + timeout. More advanced idle processing schemes can be achieved using + processEvents(). We recommend that you connect clean-up code to the \l{QCoreApplication::}{aboutToQuit()} signal, instead of putting it in your @@ -2856,34 +2562,6 @@ int QApplication::exec() return QGuiApplication::exec(); } -bool QApplicationPrivate::shouldQuit() -{ - /* if there is no non-withdrawn primary window left (except - the ones without QuitOnClose), we emit the lastWindowClosed - signal */ - QWidgetList list = QApplication::topLevelWidgets(); - QWindowList processedWindows; - for (int i = 0; i < list.size(); ++i) { - QWidget *w = list.at(i); - if (QWindow *window = w->windowHandle()) { // Menus, popup widgets may not have a QWindow - processedWindows.push_back(window); - if (w->isVisible() && !w->parentWidget() && w->testAttribute(Qt::WA_QuitOnClose)) - return false; - } - } - return QGuiApplicationPrivate::shouldQuitInternal(processedWindows); -} - -static inline void closeAllPopups() -{ - // Close all popups: In case some popup refuses to close, - // we give up after 1024 attempts (to avoid an infinite loop). - int maxiter = 1024; - QWidget *popup; - while ((popup = QApplication::activePopupWidget()) && maxiter--) - popup->close(); -} - /*! \reimp */ bool QApplication::notify(QObject *receiver, QEvent *e) @@ -2899,67 +2577,17 @@ bool QApplication::notify(QObject *receiver, QEvent *e) } #ifndef QT_NO_DEBUG - d->checkReceiverThread(receiver); + QCoreApplicationPrivate::checkReceiverThread(receiver); #endif - if (receiver->isWindowType()) { - if (QGuiApplicationPrivate::sendQWindowEventToQPlatformWindow(static_cast<QWindow *>(receiver), e)) - return true; // Platform plugin ate the event + const bool isWindowType = receiver->isWindowType(); + const bool isWidgetType = receiver->isWidgetType(); + if (isWindowType + && QGuiApplicationPrivate::sendQWindowEventToQPlatformWindow(static_cast<QWindow *>(receiver), e)) { + return true; // Platform plugin ate the event } - if(e->spontaneous()) { - // Capture the current mouse and keyboard states. Doing so here is - // required in order to support Qt Test synthesized events. Real mouse - // and keyboard state updates from the platform plugin are managed by - // QGuiApplicationPrivate::process(Mouse|Wheel|Key|Touch|Tablet)Event(); - // ### FIXME: Qt Test should not call qapp->notify(), but rather route - // the events through the proper QPA interface. This is required to - // properly generate all other events such as enter/leave etc. - switch (e->type()) { - case QEvent::MouseButtonPress: - { - QMouseEvent *me = static_cast<QMouseEvent*>(e); - QApplicationPrivate::modifier_buttons = me->modifiers(); - QApplicationPrivate::mouse_buttons |= me->button(); - break; - } - case QEvent::MouseButtonDblClick: - { - QMouseEvent *me = static_cast<QMouseEvent*>(e); - QApplicationPrivate::modifier_buttons = me->modifiers(); - QApplicationPrivate::mouse_buttons |= me->button(); - break; - } - case QEvent::MouseButtonRelease: - { - QMouseEvent *me = static_cast<QMouseEvent*>(e); - QApplicationPrivate::modifier_buttons = me->modifiers(); - QApplicationPrivate::mouse_buttons &= ~me->button(); - break; - } - case QEvent::KeyPress: - case QEvent::KeyRelease: - case QEvent::MouseMove: -#if QT_CONFIG(wheelevent) - case QEvent::Wheel: -#endif - case QEvent::TouchBegin: - case QEvent::TouchUpdate: - case QEvent::TouchEnd: -#if QT_CONFIG(tabletevent) - case QEvent::TabletMove: - case QEvent::TabletPress: - case QEvent::TabletRelease: -#endif - { - QInputEvent *ie = static_cast<QInputEvent*>(e); - QApplicationPrivate::modifier_buttons = ie->modifiers(); - break; - } - default: - break; - } - } + QGuiApplicationPrivate::captureGlobalModifierState(e); #ifndef QT_NO_GESTURES // walk through parents and check for gestures @@ -2987,7 +2615,7 @@ bool QApplication::notify(QObject *receiver, QEvent *e) break; default: if (d->gestureManager->thread() == QThread::currentThread()) { - if (receiver->isWidgetType()) { + if (isWidgetType) { if (d->gestureManager->filterEvent(static_cast<QWidget *>(receiver), e)) return true; } else { @@ -3005,9 +2633,11 @@ bool QApplication::notify(QObject *receiver, QEvent *e) switch (e->type()) { case QEvent::ApplicationDeactivate: + case QEvent::OrientationChange: // Close all popups (triggers when switching applications // by pressing ALT-TAB on Windows, which is not receive as key event. - closeAllPopups(); + // triggers when the screen rotates.) + d->closeAllPopups(); break; case QEvent::Wheel: // User input and window activation makes tooltips sleep case QEvent::ActivationChange: @@ -3022,108 +2652,89 @@ bool QApplication::notify(QObject *receiver, QEvent *e) Q_FALLTHROUGH(); case QEvent::Leave: d->toolTipWakeUp.stop(); + break; default: break; } switch (e->type()) { - case QEvent::KeyPress: { - QKeyEvent* keyEvent = static_cast<QKeyEvent*>(e); - const int key = keyEvent->key(); - // When a key press is received which is not spontaneous then it needs to - // be manually sent as a shortcut override event to ensure that any - // matching shortcut is triggered first. This enables emulation/playback - // of recorded events to still have the same effect. - if (!e->spontaneous() && receiver->isWidgetType()) { - if (qt_sendShortcutOverrideEvent(qobject_cast<QWidget *>(receiver), keyEvent->timestamp(), - key, keyEvent->modifiers(), keyEvent->text(), - keyEvent->isAutoRepeat(), keyEvent->count())) - return true; - } - qt_in_tab_key_event = (key == Qt::Key_Backtab - || key == Qt::Key_Tab - || key == Qt::Key_Left - || key == Qt::Key_Up - || key == Qt::Key_Right - || key == Qt::Key_Down); + case QEvent::KeyPress: { + QKeyEvent* keyEvent = static_cast<QKeyEvent*>(e); + const int key = keyEvent->key(); + // When a key press is received which is not spontaneous then it needs to + // be manually sent as a shortcut override event to ensure that any + // matching shortcut is triggered first. This enables emulation/playback + // of recorded events to still have the same effect. + if (!e->spontaneous() && isWidgetType + && qt_sendShortcutOverrideEvent(static_cast<QWidget *>(receiver), keyEvent->timestamp(), + key, keyEvent->modifiers(), keyEvent->text(), + keyEvent->isAutoRepeat(), keyEvent->count())) { + return true; } - default: - break; + qt_in_tab_key_event = (key == Qt::Key_Backtab + || key == Qt::Key_Tab + || key == Qt::Key_Left + || key == Qt::Key_Up + || key == Qt::Key_Right + || key == Qt::Key_Down); + break; + } + default: + break; } bool res = false; - if (!receiver->isWidgetType()) { - res = d->notify_helper(receiver, e); - } else switch (e->type()) { - case QEvent::ShortcutOverride: - case QEvent::KeyPress: - case QEvent::KeyRelease: - { - bool isWidget = receiver->isWidgetType(); -#if QT_CONFIG(graphicsview) - const bool isGraphicsWidget = !isWidget && qobject_cast<QGraphicsWidget *>(receiver); -#endif + if (isWidgetType) { + QWidget * w = static_cast<QWidget *>(receiver); + switch (e->type()) { + case QEvent::ShortcutOverride: + case QEvent::KeyPress: + case QEvent::KeyRelease: { QKeyEvent* key = static_cast<QKeyEvent*>(e); bool def = key->isAccepted(); + /* + QLineEdit will emit a signal on Key_Return, but + ignore the event, and sometimes the connected + slot deletes the QLineEdit (common in itemview + delegates), so we have to check if the widget + was destroyed even if the event was ignored (to + prevent a crash) + + Note that we don't have to reset pr while + propagating (because the original receiver will + be destroyed if one of its ancestors is) + */ QPointer<QObject> pr = receiver; - while (receiver) { + while (w) { if (def) key->accept(); else key->ignore(); - QWidget *w = isWidget ? static_cast<QWidget *>(receiver) : 0; -#if QT_CONFIG(graphicsview) - QGraphicsWidget *gw = isGraphicsWidget ? static_cast<QGraphicsWidget *>(receiver) : 0; -#endif - res = d->notify_helper(receiver, e); - - if ((res && key->isAccepted()) - /* - QLineEdit will emit a signal on Key_Return, but - ignore the event, and sometimes the connected - slot deletes the QLineEdit (common in itemview - delegates), so we have to check if the widget - was destroyed even if the event was ignored (to - prevent a crash) - - note that we don't have to reset pw while - propagating (because the original receiver will - be destroyed if one of its ancestors is) - */ - || !pr - || (isWidget && (w->isWindow() || !w->parentWidget())) -#if QT_CONFIG(graphicsview) - || (isGraphicsWidget && (gw->isWindow() || !gw->parentWidget())) -#endif - ) { + res = d->notify_helper(w, e); + + if (res && key->isAccepted()) + break; + if (!pr || w->isWindow()) break; - } -#if QT_CONFIG(graphicsview) - receiver = w ? (QObject *)w->parentWidget() : (QObject *)gw->parentWidget(); -#else - receiver = w->parentWidget(); -#endif + w = w->parentWidget(); } qt_in_tab_key_event = false; + break; } - break; - case QEvent::MouseButtonPress: - case QEvent::MouseButtonRelease: - case QEvent::MouseButtonDblClick: - case QEvent::MouseMove: - { - QWidget* w = static_cast<QWidget *>(receiver); - + case QEvent::MouseButtonPress: + case QEvent::MouseButtonRelease: + case QEvent::MouseButtonDblClick: + case QEvent::MouseMove: { QMouseEvent* mouse = static_cast<QMouseEvent*>(e); - QPoint relpos = mouse->pos(); + QPoint relpos = mouse->position().toPoint(); if (e->spontaneous()) { if (e->type() != QEvent::MouseMove) QApplicationPrivate::giveFocusAccordingToFocusPolicy(w, e, relpos); - // ### Qt 5 These dynamic tool tips should be an OPT-IN feature. Some platforms - // like OS X (probably others too), can optimize their views by not + // ### Qt 7 These dynamic tool tips should be an OPT-IN feature. Some platforms + // like macOS (probably others too), can optimize their views by not // dispatching mouse move events. We have attributes to control hover, // and mouse tracking, but as long as we are deciding to implement this // feature without choice of opting-in or out, you ALWAYS have to have @@ -3133,9 +2744,9 @@ bool QApplication::notify(QObject *receiver, QEvent *e) && w->rect().contains(relpos)) { // Outside due to mouse grab? d->toolTipWidget = w; d->toolTipPos = relpos; - d->toolTipGlobalPos = mouse->globalPos(); + d->toolTipGlobalPos = mouse->globalPosition().toPoint(); QStyle *s = d->toolTipWidget->style(); - int wakeDelay = s->styleHint(QStyle::SH_ToolTip_WakeUpDelay, 0, d->toolTipWidget, 0); + int wakeDelay = s->styleHint(QStyle::SH_ToolTip_WakeUpDelay, nullptr, d->toolTipWidget, nullptr); d->toolTipWakeUp.start(d->toolTipFallAsleep.isActive() ? 20 : wakeDelay, this); } } @@ -3144,11 +2755,12 @@ bool QApplication::notify(QObject *receiver, QEvent *e) QPointer<QWidget> pw = w; while (w) { - QMouseEvent me(mouse->type(), relpos, mouse->windowPos(), mouse->globalPos(), - mouse->button(), mouse->buttons(), mouse->modifiers(), mouse->source()); - me.spont = mouse->spontaneous(); + QMouseEvent me(mouse->type(), relpos, mouse->scenePosition(), mouse->globalPosition().toPoint(), + mouse->button(), mouse->buttons(), mouse->modifiers(), mouse->source(), + mouse->pointingDevice()); + me.m_spont = mouse->spontaneous(); me.setTimestamp(mouse->timestamp()); - QGuiApplicationPrivate::setMouseEventFlags(&me, mouse->flags()); + QMutableSinglePointEvent::from(me).setDoubleClick(QMutableSinglePointEvent::from(mouse)->isDoubleClick()); // throw away any mouse-tracking-only mouse events if (!w->hasMouseTracking() && mouse->type() == QEvent::MouseMove && mouse->buttons() == 0) { @@ -3158,7 +2770,7 @@ bool QApplication::notify(QObject *receiver, QEvent *e) } else { w->setAttribute(Qt::WA_NoMouseReplay, false); res = d->notify_helper(w, w == receiver ? mouse : &me); - e->spont = false; + e->m_spont = false; } eventAccepted = (w == receiver ? mouse : &me)->isAccepted(); if (res && eventAccepted) @@ -3176,12 +2788,13 @@ bool QApplication::notify(QObject *receiver, QEvent *e) break; w = static_cast<QWidget *>(receiver); - relpos = mouse->pos(); - QPoint diff = relpos - w->mapFromGlobal(d->hoverGlobalPos); + relpos = mouse->position().toPoint(); + QPoint diff = relpos - w->mapFromGlobal(mouse->globalPosition().toPoint()); while (w) { if (w->testAttribute(Qt::WA_Hover) && (!QApplication::activePopupWidget() || QApplication::activePopupWidget() == w->window())) { - QHoverEvent he(QEvent::HoverMove, relpos, relpos - diff, mouse->modifiers()); + QHoverEvent he(QEvent::HoverMove, mouse->scenePosition(), mouse->globalPosition(), relpos - diff, mouse->modifiers()); + QMutableEventPoint::setPosition(he.point(0), relpos); d->notify_helper(w, &he); } if (w->isWindow() || w->testAttribute(Qt::WA_NoMousePropagation)) @@ -3191,14 +2804,11 @@ bool QApplication::notify(QObject *receiver, QEvent *e) } } - d->hoverGlobalPos = mouse->globalPos(); + d->hoverGlobalPos = mouse->globalPosition().toPoint(); + break; } - break; #if QT_CONFIG(wheelevent) - case QEvent::Wheel: - { - QWidget* w = static_cast<QWidget *>(receiver); - + case QEvent::Wheel: { // QTBUG-40656, QTBUG-42731: ignore wheel events when a popup (QComboBox) is open. if (const QWidget *popup = QApplication::activePopupWidget()) { if (w->window() != popup) @@ -3206,8 +2816,18 @@ bool QApplication::notify(QObject *receiver, QEvent *e) } QWheelEvent* wheel = static_cast<QWheelEvent*>(e); - const bool spontaneous = wheel->spontaneous(); + if (!wheel->spontaneous()) { + /* + Synthesized events shouldn't propagate, e.g. QScrollArea passes events from the + viewport on to the scrollbars, which might ignore the event if there is no more + space to scroll. If we would propagate, the event would come back to the viewport. + */ + res = d->notify_helper(w, wheel); + break; + } + const Qt::ScrollPhase phase = wheel->phase(); + QPoint relpos = wheel->position().toPoint(); // Ideally, we should lock on a widget when it starts receiving wheel // events. This avoids other widgets to start receiving those events @@ -3224,181 +2844,165 @@ bool QApplication::notify(QObject *receiver, QEvent *e) // // We assume that, when supported, the phase cycle follows the pattern: // - // ScrollBegin (ScrollUpdate* ScrollEnd)+ + // ScrollBegin (ScrollUpdate* ScrollMomentum* ScrollEnd)+ // // This means that we can have scrolling sequences (starting with ScrollBegin) // or partial sequences (after a ScrollEnd and starting with ScrollUpdate). - // If wheel_widget is null because it was deleted, we also take the same - // code path as an initial sequence. - if (phase == Qt::NoScrollPhase || phase == Qt::ScrollBegin || !QApplicationPrivate::wheel_widget) { - // A system-generated ScrollBegin event starts a new user scrolling - // sequence, so we reset wheel_widget in case no one accepts the event - // or if we didn't get (or missed) a ScrollEnd previously. - if (spontaneous && phase == Qt::ScrollBegin) - QApplicationPrivate::wheel_widget = nullptr; - - const QPoint &relpos = wheel->pos(); + // a widget has already grabbed the wheel for a sequence + if (QApplicationPrivate::wheel_widget) { + Q_ASSERT(phase != Qt::NoScrollPhase); + w = QApplicationPrivate::wheel_widget; + relpos = w->mapFromGlobal(wheel->globalPosition().toPoint()); + } + /* + Start or finish a scrolling sequence by grabbing/releasing the wheel via + wheel_widget. The sequence might be partial (ie. not start with ScrollBegin), + e.g. if the previous wheel_widget was destroyed mid-sequence. + */ + switch (phase) { + case Qt::ScrollEnd: + QApplicationPrivate::wheel_widget = nullptr; + break; + case Qt::ScrollBegin: + QApplicationPrivate::wheel_widget = w; + Q_FALLTHROUGH(); + case Qt::ScrollUpdate: + case Qt::ScrollMomentum: + if (!QApplicationPrivate::wheel_widget) + QApplicationPrivate::wheel_widget = w; + Q_FALLTHROUGH(); + case Qt::NoScrollPhase: + QApplicationPrivate::giveFocusAccordingToFocusPolicy(w, e, relpos); + break; + // no default: - we want warnings if we don't handle all phases explicitly + } - if (spontaneous && (phase == Qt::NoScrollPhase || phase == Qt::ScrollUpdate)) - QApplicationPrivate::giveFocusAccordingToFocusPolicy(w, e, relpos); + QWheelEvent we(relpos, wheel->globalPosition(), wheel->pixelDelta(), wheel->angleDelta(), wheel->buttons(), + wheel->modifiers(), phase, wheel->inverted(), wheel->source(), wheel->pointingDevice()); - QWheelEvent we(relpos, wheel->globalPos(), wheel->pixelDelta(), wheel->angleDelta(), wheel->delta(), wheel->orientation(), wheel->buttons(), - wheel->modifiers(), phase, wheel->source(), wheel->inverted()); - we.setTimestamp(wheel->timestamp()); - bool eventAccepted; - do { - we.spont = spontaneous && w == receiver; - we.ignore(); - res = d->notify_helper(w, &we); - eventAccepted = we.isAccepted(); - if (res && eventAccepted) { - // A new scrolling sequence or partial sequence starts and w has accepted - // the event. Therefore, we can set wheel_widget, but only if it's not - // the end of a sequence. - if (spontaneous && (phase == Qt::ScrollBegin || phase == Qt::ScrollUpdate)) - QApplicationPrivate::wheel_widget = w; - break; - } - if (w->isWindow() || w->testAttribute(Qt::WA_NoMousePropagation)) - break; + we.setTimestamp(wheel->timestamp()); + bool eventAccepted; + do { + // events are delivered as accepted and ignored by the default event handler + // since we always send the same QWheelEvent object, we need to reset the accepted state + we.setAccepted(true); + we.m_spont = wheel->spontaneous() && w == receiver; + res = d->notify_helper(w, &we); + eventAccepted = we.isAccepted(); + if (res && eventAccepted) + break; + if (w->isWindow() || w->testAttribute(Qt::WA_NoMousePropagation)) + break; - we.p += w->pos(); - w = w->parentWidget(); - } while (w); - wheel->setAccepted(eventAccepted); - } else if (!spontaneous) { - // wheel_widget may forward the wheel event to a delegate widget, - // either directly or indirectly (e.g. QAbstractScrollArea will - // forward to its QScrollBars through viewportEvent()). In that - // case, the event will not be spontaneous but synthesized, so - // we can send it straight to the receiver. - d->notify_helper(w, wheel); - } else { - // The phase is either ScrollUpdate or ScrollEnd, and wheel_widget - // is set. Since it accepted the wheel event previously, we continue - // sending those events until we get a ScrollEnd, which signifies - // the end of the natural scrolling sequence. - const QPoint &relpos = QApplicationPrivate::wheel_widget->mapFromGlobal(wheel->globalPos()); - QWheelEvent we(relpos, wheel->globalPos(), wheel->pixelDelta(), wheel->angleDelta(), wheel->delta(), wheel->orientation(), wheel->buttons(), - wheel->modifiers(), wheel->phase(), wheel->source()); - we.setTimestamp(wheel->timestamp()); - we.spont = true; - we.ignore(); - d->notify_helper(QApplicationPrivate::wheel_widget, &we); - wheel->setAccepted(we.isAccepted()); - if (phase == Qt::ScrollEnd) - QApplicationPrivate::wheel_widget = nullptr; - } + QMutableEventPoint::setPosition(we.point(0), we.position() + w->pos()); + w = w->parentWidget(); + } while (w); + wheel->setAccepted(eventAccepted); + break; } - break; #endif #ifndef QT_NO_CONTEXTMENU - case QEvent::ContextMenu: - { - QWidget* w = static_cast<QWidget *>(receiver); + case QEvent::ContextMenu: { QContextMenuEvent *context = static_cast<QContextMenuEvent*>(e); QPoint relpos = context->pos(); bool eventAccepted = context->isAccepted(); while (w) { QContextMenuEvent ce(context->reason(), relpos, context->globalPos(), context->modifiers()); - ce.spont = e->spontaneous(); + ce.m_spont = e->spontaneous(); res = d->notify_helper(w, w == receiver ? context : &ce); eventAccepted = ((w == receiver) ? context : &ce)->isAccepted(); - e->spont = false; + e->m_spont = false; - if ((res && eventAccepted) - || w->isWindow() || w->testAttribute(Qt::WA_NoMousePropagation)) + if (res && eventAccepted) + break; + if (w->isWindow() || w->testAttribute(Qt::WA_NoMousePropagation)) break; relpos += w->pos(); w = w->parentWidget(); } context->setAccepted(eventAccepted); + break; } - break; #endif // QT_NO_CONTEXTMENU #if QT_CONFIG(tabletevent) - case QEvent::TabletMove: - case QEvent::TabletPress: - case QEvent::TabletRelease: - { - QWidget *w = static_cast<QWidget *>(receiver); + case QEvent::TabletMove: + case QEvent::TabletPress: + case QEvent::TabletRelease: { QTabletEvent *tablet = static_cast<QTabletEvent*>(e); - QPointF relpos = tablet->posF(); + QPointF relpos = tablet->position(); bool eventAccepted = tablet->isAccepted(); while (w) { - QTabletEvent te(tablet->type(), relpos, tablet->globalPosF(), - tablet->device(), tablet->pointerType(), + QTabletEvent te(tablet->type(), tablet->pointingDevice(), relpos, tablet->globalPosition(), tablet->pressure(), tablet->xTilt(), tablet->yTilt(), tablet->tangentialPressure(), tablet->rotation(), tablet->z(), - tablet->modifiers(), tablet->uniqueId(), tablet->button(), tablet->buttons()); - te.spont = e->spontaneous(); + tablet->modifiers(), tablet->button(), tablet->buttons()); + te.m_spont = e->spontaneous(); + te.setTimestamp(tablet->timestamp()); te.setAccepted(false); res = d->notify_helper(w, w == receiver ? tablet : &te); eventAccepted = ((w == receiver) ? tablet : &te)->isAccepted(); - e->spont = false; - if ((res && eventAccepted) - || w->isWindow() - || w->testAttribute(Qt::WA_NoMousePropagation)) + e->m_spont = false; + if (res && eventAccepted) + break; + if (w->isWindow() || w->testAttribute(Qt::WA_NoMousePropagation)) break; relpos += w->pos(); w = w->parentWidget(); } tablet->setAccepted(eventAccepted); + break; } - break; #endif // QT_CONFIG(tabletevent) -#if !defined(QT_NO_TOOLTIP) || QT_CONFIG(whatsthis) - case QEvent::ToolTip: - case QEvent::WhatsThis: - case QEvent::QueryWhatsThis: - { - QWidget* w = static_cast<QWidget *>(receiver); +#if QT_CONFIG(tooltip) || QT_CONFIG(whatsthis) + case QEvent::ToolTip: + case QEvent::WhatsThis: + case QEvent::QueryWhatsThis: { QHelpEvent *help = static_cast<QHelpEvent*>(e); QPoint relpos = help->pos(); bool eventAccepted = help->isAccepted(); while (w) { QHelpEvent he(help->type(), relpos, help->globalPos()); - he.spont = e->spontaneous(); + he.m_spont = e->spontaneous(); res = d->notify_helper(w, w == receiver ? help : &he); - e->spont = false; + e->m_spont = false; eventAccepted = (w == receiver ? help : &he)->isAccepted(); - if ((res && eventAccepted) || w->isWindow()) + if (res && eventAccepted) + break; + if (w->isWindow()) break; relpos += w->pos(); w = w->parentWidget(); } help->setAccepted(eventAccepted); + break; } - break; #endif #if QT_CONFIG(statustip) || QT_CONFIG(whatsthis) - case QEvent::StatusTip: - case QEvent::WhatsThisClicked: - { - QWidget *w = static_cast<QWidget *>(receiver); + case QEvent::StatusTip: + case QEvent::WhatsThisClicked: while (w) { res = d->notify_helper(w, e); - if ((res && e->isAccepted()) || w->isWindow()) + if (res && e->isAccepted()) + break; + if (w->isWindow()) break; w = w->parentWidget(); } - } - break; + break; #endif #if QT_CONFIG(draganddrop) - case QEvent::DragEnter: { - QWidget* w = static_cast<QWidget *>(receiver); + case QEvent::DragEnter: { QDragEnterEvent *dragEvent = static_cast<QDragEnterEvent *>(e); #if QT_CONFIG(graphicsview) // QGraphicsProxyWidget handles its own propagation, // and we must not change QDragManagers currentTarget. - QWExtra *extra = w->window()->d_func()->extra; + const auto &extra = w->window()->d_func()->extra; if (extra && extra->proxyWidget) { res = d->notify_helper(w, dragEvent); break; @@ -3414,33 +3018,39 @@ bool QApplication::notify(QObject *receiver, QEvent *e) } if (w->isWindow()) break; - dragEvent->p = w->mapToParent(dragEvent->p.toPoint()); + dragEvent->m_pos = w->mapToParent(dragEvent->m_pos); w = w->parentWidget(); } + break; } - break; - case QEvent::DragMove: - case QEvent::Drop: - case QEvent::DragLeave: { - QWidget* w = static_cast<QWidget *>(receiver); + case QEvent::DragMove: + case QEvent::Drop: + case QEvent::DragLeave: { #if QT_CONFIG(graphicsview) // QGraphicsProxyWidget handles its own propagation, // and we must not change QDragManagers currentTarget. - QWExtra *extra = w->window()->d_func()->extra; + const auto &extra = w->window()->d_func()->extra; bool isProxyWidget = extra && extra->proxyWidget; if (!isProxyWidget) #endif w = qobject_cast<QWidget *>(QDragManager::self()->currentTarget()); if (!w) { + // The widget that received DragEnter didn't accept the event, so we have no + // current drag target in the QDragManager. But DragLeave still needs to be + // dispatched so that enter/leave events are in balance (and so that UnderMouse + // gets cleared). + if (e->type() == QEvent::DragLeave) + w = static_cast<QWidget *>(receiver); + else break; } if (e->type() == QEvent::DragMove || e->type() == QEvent::Drop) { QDropEvent *dragEvent = static_cast<QDropEvent *>(e); - QWidget *origReciver = static_cast<QWidget *>(receiver); - while (origReciver && w != origReciver) { - dragEvent->p = origReciver->mapToParent(dragEvent->p.toPoint()); - origReciver = origReciver->parentWidget(); + QWidget *origReceiver = static_cast<QWidget *>(receiver); + while (origReceiver && w != origReceiver) { + dragEvent->m_pos = origReceiver->mapToParent(dragEvent->m_pos); + origReceiver = origReceiver->parentWidget(); } } res = d->notify_helper(w, e); @@ -3449,112 +3059,102 @@ bool QApplication::notify(QObject *receiver, QEvent *e) && !isProxyWidget #endif ) - QDragManager::self()->setCurrentTarget(0, e->type() == QEvent::Drop); - } - break; -#endif - case QEvent::TouchBegin: - // Note: TouchUpdate and TouchEnd events are never propagated - { - QWidget *widget = static_cast<QWidget *>(receiver); - QTouchEvent *touchEvent = static_cast<QTouchEvent *>(e); - bool eventAccepted = touchEvent->isAccepted(); - bool acceptTouchEvents = widget->testAttribute(Qt::WA_AcceptTouchEvents); - - if (acceptTouchEvents && e->spontaneous()) { - const QPoint localPos = touchEvent->touchPoints()[0].pos().toPoint(); - QApplicationPrivate::giveFocusAccordingToFocusPolicy(widget, e, localPos); + QDragManager::self()->setCurrentTarget(nullptr, e->type() == QEvent::Drop); + break; } +#endif // QT_CONFIG(draganddrop) + case QEvent::TouchBegin: { + // Note: TouchUpdate and TouchEnd events are never propagated + QMutableTouchEvent *touchEvent = QMutableTouchEvent::from(static_cast<QTouchEvent *>(e)); + bool eventAccepted = touchEvent->isAccepted(); + bool acceptTouchEvents = w->testAttribute(Qt::WA_AcceptTouchEvents); + + if (acceptTouchEvents && e->spontaneous() + && touchEvent->device()->type() != QInputDevice::DeviceType::TouchPad) { + const QPoint localPos = touchEvent->points()[0].position().toPoint(); + QApplicationPrivate::giveFocusAccordingToFocusPolicy(w, e, localPos); + } #ifndef QT_NO_GESTURES - QPointer<QWidget> gesturePendingWidget; + QPointer<QWidget> gesturePendingWidget; #endif - while (widget) { - // first, try to deliver the touch event - acceptTouchEvents = widget->testAttribute(Qt::WA_AcceptTouchEvents); - touchEvent->setTarget(widget); - touchEvent->setAccepted(acceptTouchEvents); - QPointer<QWidget> p = widget; - res = acceptTouchEvents && d->notify_helper(widget, touchEvent); - eventAccepted = touchEvent->isAccepted(); - if (p.isNull()) { - // widget was deleted - widget = 0; - } else { - widget->setAttribute(Qt::WA_WState_AcceptedTouchBeginEvent, res && eventAccepted); - } - touchEvent->spont = false; - if (res && eventAccepted) { - // the first widget to accept the TouchBegin gets an implicit grab. - d->activateImplicitTouchGrab(widget, touchEvent); - break; - } + while (w) { + // first, try to deliver the touch event + acceptTouchEvents = w->testAttribute(Qt::WA_AcceptTouchEvents); + touchEvent->setTarget(w); + touchEvent->setAccepted(acceptTouchEvents); + QPointer<QWidget> p = w; + res = acceptTouchEvents && d->notify_helper(w, touchEvent); + eventAccepted = touchEvent->isAccepted(); + if (p.isNull()) { + // widget was deleted + w = nullptr; + } else { + w->setAttribute(Qt::WA_WState_AcceptedTouchBeginEvent, res && eventAccepted); + } + touchEvent->m_spont = false; + if (res && eventAccepted) { + // the first widget to accept the TouchBegin gets an implicit grab. + d->activateImplicitTouchGrab(w, touchEvent); + break; + } #ifndef QT_NO_GESTURES - if (gesturePendingWidget.isNull() && widget && QGestureManager::gesturePending(widget)) - gesturePendingWidget = widget; + if (gesturePendingWidget.isNull() && w && QGestureManager::gesturePending(w)) + gesturePendingWidget = w; #endif - if (p.isNull() || widget->isWindow() || widget->testAttribute(Qt::WA_NoMousePropagation)) - break; + if (!w || w->isWindow() || w->testAttribute(Qt::WA_NoMousePropagation)) + break; - QPoint offset = widget->pos(); - widget = widget->parentWidget(); - touchEvent->setTarget(widget); - for (int i = 0; i < touchEvent->_touchPoints.size(); ++i) { - QTouchEvent::TouchPoint &pt = touchEvent->_touchPoints[i]; - pt.d->pos = pt.pos() + offset; - pt.d->startPos = pt.startPos() + offset; - pt.d->lastPos = pt.lastPos() + offset; + const QPoint offset = w->pos(); + w = w->parentWidget(); + touchEvent->setTarget(w); + for (int i = 0; i < touchEvent->pointCount(); ++i) { + auto &pt = touchEvent->point(i); + QMutableEventPoint::setPosition(pt, pt.position() + offset); + } } - } #ifndef QT_NO_GESTURES - if (!eventAccepted && !gesturePendingWidget.isNull()) { - // the first widget subscribed to a gesture gets an implicit grab - d->activateImplicitTouchGrab(gesturePendingWidget, touchEvent); - } + if (!eventAccepted && !gesturePendingWidget.isNull()) { + // the first widget subscribed to a gesture gets an implicit grab for all + // points, also for events and event points that have not been accepted. + d->activateImplicitTouchGrab(gesturePendingWidget, touchEvent, QApplicationPrivate::GrabAllPoints); + } #endif - touchEvent->setAccepted(eventAccepted); - break; - } - case QEvent::TouchUpdate: - case QEvent::TouchEnd: - { - QWidget *widget = static_cast<QWidget *>(receiver); - // We may get here if the widget is subscribed to a gesture, - // but has not accepted TouchBegin. Propagate touch events - // only if TouchBegin has been accepted. - if (widget->testAttribute(Qt::WA_WState_AcceptedTouchBeginEvent)) - res = d->notify_helper(widget, e); - break; - } - case QEvent::RequestSoftwareInputPanel: - inputMethod()->show(); - break; - case QEvent::CloseSoftwareInputPanel: - inputMethod()->hide(); - break; + touchEvent->setAccepted(eventAccepted); + break; + } + case QEvent::TouchUpdate: + case QEvent::TouchEnd: + // We may get here if the widget is subscribed to a gesture, + // but has not accepted TouchBegin. Propagate touch events + // only if TouchBegin has been accepted. + if (w->testAttribute(Qt::WA_WState_AcceptedTouchBeginEvent)) + res = d->notify_helper(w, e); + break; + case QEvent::RequestSoftwareInputPanel: + inputMethod()->show(); + break; + case QEvent::CloseSoftwareInputPanel: + inputMethod()->hide(); + break; #ifndef QT_NO_GESTURES - case QEvent::NativeGesture: - { - // only propagate the first gesture event (after the GID_BEGIN) - QWidget *w = static_cast<QWidget *>(receiver); - while (w) { - e->ignore(); - res = d->notify_helper(w, e); - if ((res && e->isAccepted()) || w->isWindow()) - break; - w = w->parentWidget(); - } - break; - } - case QEvent::Gesture: - case QEvent::GestureOverride: - { - if (receiver->isWidgetType()) { - QWidget *w = static_cast<QWidget *>(receiver); + case QEvent::NativeGesture: + while (w) { + e->ignore(); + res = d->notify_helper(w, e); + if (res && e->isAccepted()) + break; + if (w->isWindow()) + break; + w = w->parentWidget(); + } + break; + case QEvent::Gesture: + case QEvent::GestureOverride: { QGestureEvent *gestureEvent = static_cast<QGestureEvent *>(e); QList<QGesture *> allGestures = gestureEvent->gestures(); @@ -3571,7 +3171,7 @@ bool QApplication::notify(QObject *receiver, QEvent *e) wd->gestureContext.find(type); bool deliver = contextit != wd->gestureContext.end() && (g->state() == Qt::GestureStarted || w == receiver || - (contextit.value() & Qt::ReceivePartialGestures)); + (contextit.value() & Qt::ReceivePartialGestures)); if (deliver) { allGestures.removeAt(i); gestures.append(g); @@ -3582,11 +3182,11 @@ bool QApplication::notify(QObject *receiver, QEvent *e) if (!gestures.isEmpty()) { // we have gestures for this w QGestureEvent ge(gestures); ge.t = gestureEvent->t; - ge.spont = gestureEvent->spont; + ge.m_spont = gestureEvent->spontaneous(); ge.m_accept = wasAccepted; ge.m_accepted = gestureEvent->m_accepted; res = d->notify_helper(w, &ge); - gestureEvent->spont = false; + gestureEvent->m_spont = false; eventAccepted = ge.isAccepted(); for (int i = 0; i < gestures.size(); ++i) { QGesture *g = gestures.at(i); @@ -3609,46 +3209,40 @@ bool QApplication::notify(QObject *receiver, QEvent *e) break; w = w->parentWidget(); } - for (QGesture *g : qAsConst(allGestures)) + for (QGesture *g : std::as_const(allGestures)) gestureEvent->setAccepted(g, false); gestureEvent->m_accept = false; // to make sure we check individual gestures - } else { - res = d->notify_helper(receiver, e); + break; } - break; - } #endif // QT_NO_GESTURES #ifdef Q_OS_MAC - // Enable touch events on enter, disable on leave. - typedef void (*RegisterTouchWindowFn)(QWindow *, bool); - case QEvent::Enter: - if (receiver->isWidgetType()) { - QWidget *w = static_cast<QWidget *>(receiver); + // Enable touch events on enter, disable on leave. + typedef void (*RegisterTouchWindowFn)(QWindow *, bool); + case QEvent::Enter: if (w->testAttribute(Qt::WA_AcceptTouchEvents)) { RegisterTouchWindowFn registerTouchWindow = reinterpret_cast<RegisterTouchWindowFn> (platformNativeInterface()->nativeResourceFunctionForIntegration("registertouchwindow")); if (registerTouchWindow) registerTouchWindow(w->window()->windowHandle(), true); } - } - res = d->notify_helper(receiver, e); - break; - case QEvent::Leave: - if (receiver->isWidgetType()) { - QWidget *w = static_cast<QWidget *>(receiver); + res = d->notify_helper(receiver, e); + break; + case QEvent::Leave: if (w->testAttribute(Qt::WA_AcceptTouchEvents)) { RegisterTouchWindowFn registerTouchWindow = reinterpret_cast<RegisterTouchWindowFn> (platformNativeInterface()->nativeResourceFunctionForIntegration("registertouchwindow")); if (registerTouchWindow) registerTouchWindow(w->window()->windowHandle(), false); } - } - res = d->notify_helper(receiver, e); - break; + res = d->notify_helper(receiver, e); + break; #endif - default: + default: + res = d->notify_helper(receiver, e); + break; + } + } else { res = d->notify_helper(receiver, e); - break; } return res; @@ -3667,7 +3261,7 @@ bool QApplicationPrivate::notify_helper(QObject *receiver, QEvent * e) // send to all application event filters if (threadRequiresCoreApplication() - && receiver->d_func()->threadData->thread == mainThread() + && receiver->d_func()->threadData.loadRelaxed()->thread.loadAcquire() == mainThread() && sendThroughApplicationEventFilters(receiver, e)) { filtered = true; return filtered; @@ -3705,7 +3299,7 @@ bool QApplicationPrivate::notify_helper(QObject *receiver, QEvent * e) bool QApplicationPrivate::inPopupMode() { - return QApplicationPrivate::popupWidgets != 0; + return QApplicationPrivate::popupWidgets != nullptr; } static void ungrabKeyboardForPopup(QWidget *popup) @@ -3741,6 +3335,18 @@ static void grabForPopup(QWidget *popup) extern QWidget *qt_popup_down; extern bool qt_replay_popup_mouse_event; +extern bool qt_popup_down_closed; + +bool QApplicationPrivate::closeAllPopups() +{ + // Close all popups: In case some popup refuses to close, + // we give up after 1024 attempts (to avoid an infinite loop). + int maxiter = 1024; + QWidget *popup; + while ((popup = QApplication::activePopupWidget()) && maxiter--) + popup->close(); // this will call QApplicationPrivate::closePopup + return true; +} void QApplicationPrivate::closePopup(QWidget *popup) { @@ -3749,19 +3355,23 @@ void QApplicationPrivate::closePopup(QWidget *popup) popupWidgets->removeAll(popup); if (popup == qt_popup_down) { - qt_button_down = 0; - qt_popup_down = 0; + qt_button_down = nullptr; + qt_popup_down_closed = true; + qt_popup_down = nullptr; } - if (QApplicationPrivate::popupWidgets->count() == 0) { // this was the last popup + if (QApplicationPrivate::popupWidgets->size() == 0) { // this was the last popup delete QApplicationPrivate::popupWidgets; - QApplicationPrivate::popupWidgets = 0; + QApplicationPrivate::popupWidgets = nullptr; + qt_popup_down_closed = false; if (popupGrabOk) { popupGrabOk = false; - if (popup->geometry().contains(QPoint(QGuiApplicationPrivate::mousePressX, - QGuiApplicationPrivate::mousePressY)) + // TODO on multi-seat window systems, we have to know which mouse + auto devPriv = QPointingDevicePrivate::get(QPointingDevice::primaryPointingDevice()); + auto mousePressPos = devPriv->pointById(0)->eventPoint.globalPressPosition(); + if (popup->geometry().contains(mousePressPos.toPoint()) || popup->testAttribute(Qt::WA_NoMouseReplay)) { // mouse release event or inside qt_replay_popup_mouse_event = false; @@ -3793,7 +3403,9 @@ void QApplicationPrivate::closePopup(QWidget *popup) if (QWidget *fw = aw->focusWidget()) fw->setFocus(Qt::PopupFocusReason); - if (QApplicationPrivate::popupWidgets->count() == 1) // grab mouse/keyboard + // can become nullptr due to setFocus() above + if (QApplicationPrivate::popupWidgets && + QApplicationPrivate::popupWidgets->size() == 1) // grab mouse/keyboard grabForPopup(aw); } @@ -3808,7 +3420,7 @@ void QApplicationPrivate::openPopup(QWidget *popup) popupWidgets = new QWidgetList; popupWidgets->append(popup); // add to end of list - if (QApplicationPrivate::popupWidgets->count() == 1) // grab mouse/keyboard + if (QApplicationPrivate::popupWidgets->size() == 1) // grab mouse/keyboard grabForPopup(popup); // popups are not focus-handled by the window system (the first @@ -3816,10 +3428,10 @@ void QApplicationPrivate::openPopup(QWidget *popup) // new popup gets the focus if (popup->focusWidget()) { popup->focusWidget()->setFocus(Qt::PopupFocusReason); - } else if (popupWidgets->count() == 1) { // this was the first popup + } else if (popupWidgets->size() == 1) { // this was the first popup if (QWidget *fw = QApplication::focusWidget()) { QFocusEvent e(QEvent::FocusOut, Qt::PopupFocusReason); - QApplication::sendEvent(fw, &e); + QCoreApplication::sendEvent(fw, &e); } } } @@ -3831,8 +3443,6 @@ void QApplicationPrivate::openPopup(QWidget *popup) This feature is available in Qt for Embedded Linux only. \since 4.6 - - \sa keypadNavigationEnabled() */ void QApplication::setNavigationMode(Qt::NavigationMode mode) { @@ -3845,56 +3455,11 @@ void QApplication::setNavigationMode(Qt::NavigationMode mode) This feature is available in Qt for Embedded Linux only. \since 4.6 - - \sa keypadNavigationEnabled() */ Qt::NavigationMode QApplication::navigationMode() { return QApplicationPrivate::navigationMode; } - -/*! - Sets whether Qt should use focus navigation suitable for use with a - minimal keypad. - - This feature is available in Qt for Embedded Linux, and Windows CE only. - - \note On Windows CE this feature is disabled by default for touch device - mkspecs. To enable keypad navigation, build Qt with - QT_KEYPAD_NAVIGATION defined. - - \deprecated - - \sa setNavigationMode() -*/ -void QApplication::setKeypadNavigationEnabled(bool enable) -{ - if (enable) { - QApplication::setNavigationMode(Qt::NavigationModeKeypadTabOrder); - } else { - QApplication::setNavigationMode(Qt::NavigationModeNone); - } -} - -/*! - Returns \c true if Qt is set to use keypad navigation; otherwise returns - false. The default value is false. - - This feature is available in Qt for Embedded Linux, and Windows CE only. - - \note On Windows CE this feature is disabled by default for touch device - mkspecs. To enable keypad navigation, build Qt with - QT_KEYPAD_NAVIGATION defined. - - \deprecated - - \sa navigationMode() -*/ -bool QApplication::keypadNavigationEnabled() -{ - return QApplicationPrivate::navigationMode == Qt::NavigationModeKeypadTabOrder || - QApplicationPrivate::navigationMode == Qt::NavigationModeKeypadDirectional; -} #endif /*! @@ -3902,7 +3467,7 @@ bool QApplication::keypadNavigationEnabled() \since 4.3 Causes an alert to be shown for \a widget if the window is not the active - window. The alert is shown for \a msec miliseconds. If \a msec is zero (the + window. The alert is shown for \a msec milliseconds. If \a msec is zero (the default), then the alert is shown indefinitely until the window becomes active again. @@ -3980,15 +3545,6 @@ int QApplication::doubleClickInterval() } /*! - \fn QApplication::keyboardInputDirection() - \since 4.2 - \deprecated - - Returns the current keyboard input direction. Replaced with QInputMethod::inputDirection() - \sa QInputMethod::inputDirection() -*/ - -/*! \property QApplication::keyboardInputInterval \brief the time limit in milliseconds that distinguishes a key press from two consecutive key presses @@ -4125,14 +3681,6 @@ void QApplication::beep() \sa QCoreApplication::instance(), qGuiApp */ -/*! - \fn QLocale QApplication::keyboardInputLocale() - \since 4.2 - \obsolete - - Returns the current keyboard input locale. Replaced with QInputMethod::locale() -*/ - bool qt_sendSpontaneousEvent(QObject *receiver, QEvent *event) { return QGuiApplication::sendSpontaneousEvent(receiver, event); @@ -4142,7 +3690,7 @@ void QApplicationPrivate::giveFocusAccordingToFocusPolicy(QWidget *widget, QEven { const bool setFocusOnRelease = QGuiApplication::styleHints()->setFocusOnTouchRelease(); Qt::FocusPolicy focusPolicy = Qt::ClickFocus; - static QPointer<QWidget> focusedWidgetOnTouchBegin = 0; + static QPointer<QWidget> focusedWidgetOnTouchBegin = nullptr; switch (event->type()) { case QEvent::MouseButtonPress: @@ -4210,18 +3758,12 @@ bool QApplicationPrivate::shouldSetFocus(QWidget *w, Qt::FocusPolicy policy) bool QApplicationPrivate::updateTouchPointsForWidget(QWidget *widget, QTouchEvent *touchEvent) { bool containsPress = false; - for (int i = 0; i < touchEvent->touchPoints().count(); ++i) { - QTouchEvent::TouchPoint &touchPoint = touchEvent->_touchPoints[i]; - // preserve the sub-pixel resolution - const QPointF screenPos = touchPoint.screenRect().center(); - const QPointF delta = screenPos - screenPos.toPoint(); + for (int i = 0; i < touchEvent->pointCount(); ++i) { + auto &pt = touchEvent->point(i); + QMutableEventPoint::setPosition(pt, widget->mapFromGlobal(pt.globalPosition())); - touchPoint.d->pos = widget->mapFromGlobal(screenPos.toPoint()) + delta; - touchPoint.d->startPos = widget->mapFromGlobal(touchPoint.startScreenPos().toPoint()) + delta; - touchPoint.d->lastPos = widget->mapFromGlobal(touchPoint.lastScreenPos().toPoint()) + delta; - - if (touchPoint.state() == Qt::TouchPointPressed) + if (pt.state() == QEventPoint::State::Pressed) containsPress = true; } return containsPress; @@ -4245,111 +3787,111 @@ void QApplicationPrivate::cleanupMultitouch_sys() { } -QWidget *QApplicationPrivate::findClosestTouchPointTarget(QTouchDevice *device, const QTouchEvent::TouchPoint &touchPoint) +QWidget *QApplicationPrivate::findClosestTouchPointTarget(const QPointingDevice *device, const QEventPoint &touchPoint) { - const QPointF screenPos = touchPoint.screenPos(); + const QPointF globalPos = touchPoint.globalPosition(); int closestTouchPointId = -1; - QObject *closestTarget = 0; - qreal closestDistance = qreal(0.); - QHash<ActiveTouchPointsKey, ActiveTouchPointsValue>::const_iterator it = activeTouchPoints.constBegin(), - ite = activeTouchPoints.constEnd(); - while (it != ite) { - if (it.key().device == device && it.key().touchPointId != touchPoint.id()) { - const QTouchEvent::TouchPoint &touchPoint = it->touchPoint; - qreal dx = screenPos.x() - touchPoint.screenPos().x(); - qreal dy = screenPos.y() - touchPoint.screenPos().y(); + QObject *closestTarget = nullptr; + qreal closestDistance = 0; + const QPointingDevicePrivate *devPriv = QPointingDevicePrivate::get(device); + for (auto &epd : devPriv->activePoints.values()) { + const auto &pt = epd.eventPoint; + if (pt.id() != touchPoint.id()) { + qreal dx = globalPos.x() - pt.globalPosition().x(); + qreal dy = globalPos.y() - pt.globalPosition().y(); qreal distance = dx * dx + dy * dy; if (closestTouchPointId == -1 || distance < closestDistance) { - closestTouchPointId = touchPoint.id(); + closestTouchPointId = pt.id(); closestDistance = distance; - closestTarget = it.value().target.data(); + closestTarget = QMutableEventPoint::target(pt); } } - ++it; } return static_cast<QWidget *>(closestTarget); } -void QApplicationPrivate::activateImplicitTouchGrab(QWidget *widget, QTouchEvent *touchEvent) +void QApplicationPrivate::activateImplicitTouchGrab(QWidget *widget, QTouchEvent *touchEvent, + ImplicitTouchGrabMode grabMode) { if (touchEvent->type() != QEvent::TouchBegin) return; - for (int i = 0, tc = touchEvent->touchPoints().count(); i < tc; ++i) { - const QTouchEvent::TouchPoint &touchPoint = touchEvent->touchPoints().at(i); - activeTouchPoints[QGuiApplicationPrivate::ActiveTouchPointsKey(touchEvent->device(), touchPoint.id())].target = widget; + // If the widget dispatched the event further (see QGraphicsProxyWidget), then + // there might already be an implicit grabber. Don't override that. A widget that + // has partially recognized a gesture needs to grab all points. + for (int i = 0; i < touchEvent->pointCount(); ++i) { + auto &ep = touchEvent->point(i); + if (!QMutableEventPoint::target(ep) && (ep.isAccepted() || grabMode == GrabAllPoints)) + QMutableEventPoint::setTarget(ep, widget); } + // TODO setExclusiveGrabber() to be consistent with Qt Quick? } -bool QApplicationPrivate::translateRawTouchEvent(QWidget *window, - QTouchDevice *device, - const QList<QTouchEvent::TouchPoint> &touchPoints, - ulong timestamp) +bool QApplicationPrivate::translateRawTouchEvent(QWidget *window, const QTouchEvent *te) { QApplicationPrivate *d = self; - typedef QPair<Qt::TouchPointStates, QList<QTouchEvent::TouchPoint> > StatesAndTouchPoints; + // TODO get rid of this QPair + typedef QPair<QEventPoint::State, QList<QEventPoint> > StatesAndTouchPoints; QHash<QWidget *, StatesAndTouchPoints> widgetsNeedingEvents; - for (int i = 0; i < touchPoints.count(); ++i) { - QTouchEvent::TouchPoint touchPoint = touchPoints.at(i); - // explicitly detach from the original touch point that we got, so even - // if the touchpoint structs are reused, we will make a copy that we'll - // deliver to the user (which might want to store the struct for later use). - touchPoint.d = touchPoint.d->detach(); - + const auto *device = te->pointingDevice(); + auto touchPoints = te->points(); // touch points will be mutated + for (auto &touchPoint : touchPoints) { // update state QPointer<QObject> target; - ActiveTouchPointsKey touchInfoKey(device, touchPoint.id()); - ActiveTouchPointsValue &touchInfo = d->activeTouchPoints[touchInfoKey]; - if (touchPoint.state() == Qt::TouchPointPressed) { - if (device->type() == QTouchDevice::TouchPad) { - // on touch-pads, send all touch points to the same widget - target = d->activeTouchPoints.isEmpty() - ? QPointer<QObject>() - : d->activeTouchPoints.constBegin().value().target; + if (touchPoint.state() == QEventPoint::State::Pressed) { + if (device->type() == QInputDevice::DeviceType::TouchPad) { + // on touchpads, send all touch points to the same widget: + // pick the first non-null target if possible + target = QPointingDevicePrivate::get(device)->firstActiveTarget(); } - if (!target) { + if (target.isNull()) { // determine which widget this event will go to if (!window) - window = QApplication::topLevelAt(touchPoint.screenPos().toPoint()); + window = QApplication::topLevelAt(touchPoint.globalPosition().toPoint()); if (!window) continue; - target = window->childAt(window->mapFromGlobal(touchPoint.screenPos().toPoint())); + target = window->childAt(window->mapFromGlobal(touchPoint.globalPosition().toPoint())); if (!target) target = window; } - if (device->type() == QTouchDevice::TouchScreen) { + bool usingClosestWidget = false; + if (device->type() == QInputDevice::DeviceType::TouchScreen) { QWidget *closestWidget = d->findClosestTouchPointTarget(device, touchPoint); QWidget *widget = static_cast<QWidget *>(target.data()); if (closestWidget && (widget->isAncestorOf(closestWidget) || closestWidget->isAncestorOf(widget))) { target = closestWidget; + usingClosestWidget = true; } } - touchInfo.target = target; + // on touch pads, implicitly grab all touch points + // on touch screens, grab touch points that are redirected to the closest widget + if (device->type() == QInputDevice::DeviceType::TouchPad || usingClosestWidget) + QMutableEventPoint::setTarget(touchPoint, target); } else { - target = touchInfo.target; + target = QMutableEventPoint::target(touchPoint); if (!target) continue; } - Q_ASSERT(target.data() != 0); + Q_ASSERT(!target.isNull()); QWidget *targetWidget = static_cast<QWidget *>(target.data()); -#ifdef Q_OS_OSX +#ifdef Q_OS_MACOS // Single-touch events are normally not sent unless WA_TouchPadAcceptSingleTouchEvents is set. // In Qt 4 this check was in OS X-only code. That behavior is preserved here by the #ifdef. if (touchPoints.count() == 1 - && device->type() == QTouchDevice::TouchPad + && device->type() == QInputDevice::DeviceType::TouchPad && !targetWidget->testAttribute(Qt::WA_TouchPadAcceptSingleTouchEvents)) continue; #endif StatesAndTouchPoints &maskAndPoints = widgetsNeedingEvents[targetWidget]; - maskAndPoints.first |= touchPoint.state(); + maskAndPoints.first = QEventPoint::State(maskAndPoints.first | touchPoint.state()); maskAndPoints.second.append(touchPoint); } @@ -4361,18 +3903,18 @@ bool QApplicationPrivate::translateRawTouchEvent(QWidget *window, const QHash<QWidget *, StatesAndTouchPoints>::ConstIterator end = widgetsNeedingEvents.constEnd(); for (; it != end; ++it) { const QPointer<QWidget> widget = it.key(); - if (!QApplicationPrivate::tryModalHelper(widget, 0)) + if (!QApplicationPrivate::tryModalHelper(widget, nullptr)) continue; QEvent::Type eventType; switch (it.value().first) { - case Qt::TouchPointPressed: + case QEventPoint::State::Pressed: eventType = QEvent::TouchBegin; break; - case Qt::TouchPointReleased: + case QEventPoint::State::Released: eventType = QEvent::TouchEnd; break; - case Qt::TouchPointStationary: + case QEventPoint::State::Stationary: // don't send the event if nothing changed continue; default: @@ -4380,14 +3922,10 @@ bool QApplicationPrivate::translateRawTouchEvent(QWidget *window, break; } - QTouchEvent touchEvent(eventType, - device, - QApplication::keyboardModifiers(), - it.value().first, - it.value().second); + QMutableTouchEvent touchEvent(eventType, device, QGuiApplication::keyboardModifiers(), + it.value().second); bool containsPress = updateTouchPointsForWidget(widget, &touchEvent); - touchEvent.setTimestamp(timestamp); - touchEvent.setWindow(window->windowHandle()); + touchEvent.setTimestamp(te->timestamp()); touchEvent.setTarget(widget); if (containsPress) @@ -4398,7 +3936,9 @@ bool QApplicationPrivate::translateRawTouchEvent(QWidget *window, { // if the TouchBegin handler recurses, we assume that means the event // has been implicitly accepted and continue to send touch events - if (QApplication::sendSpontaneousEvent(widget, &touchEvent) && touchEvent.isAccepted()) { + bool res = te->spontaneous() ? QApplication::sendSpontaneousEvent(widget, &touchEvent) + : QApplication::sendEvent(widget, &touchEvent); + if (res && touchEvent.isAccepted()) { accepted = true; if (!widget.isNull()) widget->setAttribute(Qt::WA_WState_AcceptedTouchBeginEvent); @@ -4411,7 +3951,9 @@ bool QApplicationPrivate::translateRawTouchEvent(QWidget *window, || QGestureManager::gesturePending(widget) #endif ) { - if (QApplication::sendSpontaneousEvent(widget, &touchEvent) && touchEvent.isAccepted()) + bool res = te->spontaneous() ? QApplication::sendSpontaneousEvent(widget, &touchEvent) + : QApplication::sendEvent(widget, &touchEvent); + if (res && touchEvent.isAccepted()) accepted = true; // widget can be deleted on TouchEnd if (touchEvent.type() == QEvent::TouchEnd && !widget.isNull()) @@ -4423,51 +3965,32 @@ bool QApplicationPrivate::translateRawTouchEvent(QWidget *window, return accepted; } -void QApplicationPrivate::translateTouchCancel(QTouchDevice *device, ulong timestamp) +void QApplicationPrivate::translateTouchCancel(const QPointingDevice *device, ulong timestamp) { - QTouchEvent touchEvent(QEvent::TouchCancel, device, QApplication::keyboardModifiers()); + QMutableTouchEvent touchEvent(QEvent::TouchCancel, device, QGuiApplication::keyboardModifiers()); touchEvent.setTimestamp(timestamp); - QHash<ActiveTouchPointsKey, ActiveTouchPointsValue>::const_iterator it - = self->activeTouchPoints.constBegin(), ite = self->activeTouchPoints.constEnd(); + QSet<QWidget *> widgetsNeedingCancel; - while (it != ite) { - QWidget *widget = static_cast<QWidget *>(it->target.data()); - if (widget) - widgetsNeedingCancel.insert(widget); - ++it; + const QPointingDevicePrivate *devPriv = QPointingDevicePrivate::get(device); + for (auto &epd : devPriv->activePoints.values()) { + const auto &pt = epd.eventPoint; + QObject *target = QMutableEventPoint::target(pt); + if (target && target->isWidgetType()) + widgetsNeedingCancel.insert(static_cast<QWidget *>(target)); } for (QSet<QWidget *>::const_iterator widIt = widgetsNeedingCancel.constBegin(), widItEnd = widgetsNeedingCancel.constEnd(); widIt != widItEnd; ++widIt) { QWidget *widget = *widIt; - touchEvent.setWindow(widget->windowHandle()); touchEvent.setTarget(widget); QApplication::sendSpontaneousEvent(widget, &touchEvent); } } -void QApplicationPrivate::notifyThemeChanged() +void QApplicationPrivate::handleThemeChanged() { - QGuiApplicationPrivate::notifyThemeChanged(); - clearSystemPalette(); - initSystemPalette(); - qt_init_tooltip_palette(); -} - -void QApplicationPrivate::sendApplicationPaletteChange(bool toAllWidgets, const char *className) -{ - QGuiApplicationPrivate::sendApplicationPaletteChange(); - - QEvent event(QEvent::ApplicationPaletteChange); - const QWidgetList widgets = QApplication::allWidgets(); - for (auto widget : widgets) { - if (toAllWidgets || (!className && widget->isWindow()) || (className && widget->inherits(className))) - QApplication::sendEvent(widget, &event); - } + QGuiApplicationPrivate::handleThemeChanged(); -#if QT_CONFIG(graphicsview) - for (auto scene : qAsConst(scene_list)) - QApplication::sendEvent(scene, &event); -#endif // QT_CONFIG(graphicsview) + qt_init_tooltip_palette(); } #if QT_CONFIG(draganddrop) @@ -4488,7 +4011,7 @@ QGestureManager* QGestureManager::instance(InstanceCreation ic) { QApplicationPrivate *qAppPriv = QApplicationPrivate::instance(); if (!qAppPriv) - return 0; + return nullptr; if (!qAppPriv->gestureManager && ic == ForceCreation) qAppPriv->gestureManager = new QGestureManager(qApp); return qAppPriv->gestureManager; @@ -4502,6 +4025,11 @@ QPixmap QApplicationPrivate::applyQIconStyleHelper(QIcon::Mode mode, const QPixm return QApplication::style()->generatedIconPixmap(mode, base, &opt); } +void *QApplication::resolveInterface(const char *name, int revision) const +{ + return QGuiApplication::resolveInterface(name, revision); +} + QT_END_NAMESPACE #include "moc_qapplication.cpp" |