summaryrefslogtreecommitdiffstats
path: root/src/widgets/kernel/qapplication.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/widgets/kernel/qapplication.cpp')
-rw-r--r--src/widgets/kernel/qapplication.cpp2314
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"