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.cpp1799
1 files changed, 678 insertions, 1121 deletions
diff --git a/src/widgets/kernel/qapplication.cpp b/src/widgets/kernel/qapplication.cpp
index 129569a466..5e1d792319 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,45 +42,51 @@
#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>
+#ifdef Q_OS_MACOS
+#include <QtCore/private/qcore_mac_p.h>
+#endif
+
#include <algorithm>
#include <iterator>
-//#define ALIEN_DEBUG
-
static void initResources()
{
Q_INIT_RESOURCE(qstyle);
@@ -127,6 +98,17 @@ static void initResources()
QT_BEGIN_NAMESPACE
+Q_STATIC_LOGGING_CATEGORY(lcWidgetPopup, "qt.widgets.popup");
+
+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())) { \
@@ -142,8 +124,8 @@ 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;
@@ -218,8 +200,7 @@ void QApplicationPrivate::createEventDispatcher()
\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
@@ -266,7 +247,6 @@ void QApplicationPrivate::createEventDispatcher()
postEvent(),
sendPostedEvents(),
removePostedEvents(),
- hasPendingEvents(),
notify().
\row
@@ -284,7 +264,6 @@ void QApplicationPrivate::createEventDispatcher()
\li Widgets
\li allWidgets(),
topLevelWidgets(),
- desktop(),
activePopupWidget(),
activeModalWidget(),
clipboard(),
@@ -308,22 +287,6 @@ void QApplicationPrivate::createEventDispatcher()
\sa QCoreApplication, QAbstractEventDispatcher, QEventLoop, QSettings
*/
-#if QT_DEPRECATED_SINCE(5, 8)
-// ### 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.
-*/
-#endif
-
/*!
\fn QWidget *QApplication::topLevelAt(const QPoint &point)
@@ -349,7 +312,6 @@ QWidget *QApplication::topLevelAt(const QPoint &pos)
*/
void qt_init_tooltip_palette();
-void qt_cleanup();
QStyle *QApplicationPrivate::app_style = nullptr; // default application style
#ifndef QT_NO_STYLE_STYLESHEET
@@ -369,12 +331,11 @@ 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)
@@ -393,9 +354,7 @@ Q_GLOBAL_STATIC(FontHash, app_fonts)
// Exported accessor for use outside of this file
FontHash *qt_app_fonts_hash() { return app_fonts(); }
-QWidgetList *QApplicationPrivate::popupWidgets = nullptr; // has keyboard input focus
-
-QDesktopWidget *qt_desktopWidget = nullptr; // root window widgets
+QWidget *qt_desktopWidget = nullptr; // root window widgets
/*!
\internal
@@ -406,7 +365,7 @@ void QApplicationPrivate::process_cmdline()
styleOverride = QString::fromLocal8Bit(qgetenv("QT_STYLE_OVERRIDE"));
// process platform-indep command line
- if (!qt_is_gui_used || !argc)
+ if (qt_is_tty_app || !argc)
return;
int i, j;
@@ -426,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) {
@@ -439,7 +398,7 @@ void QApplicationPrivate::process_cmdline()
}
}
- if(j < argc) {
+ if (j < argc) {
argv[j] = nullptr;
argc = j;
}
@@ -493,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();
@@ -514,7 +473,7 @@ 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()
@@ -526,7 +485,7 @@ void QApplicationPrivate::init()
initialize();
eventDispatcher->startingUp();
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
// factory for accessible interfaces for widgets shipped with Qt
QAccessible::installFactory(&qAccessibleFactory);
#endif
@@ -535,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()
@@ -572,22 +528,20 @@ void QApplicationPrivate::initialize()
} else {
qWarning("QApplication: invalid style override '%s' passed, ignoring it.\n"
"\tAvailable styles: %s", qPrintable(styleOverride),
- qPrintable(QStyleFactory::keys().join(QLatin1String(", "))));
+ 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 QT_CONFIG(statemachine)
- // trigger registering of QStateMachine's GUI types
- qRegisterGuiStateMachine();
-#endif
if (qEnvironmentVariableIntValue("QT_USE_NATIVE_WINDOWS") > 0)
QCoreApplication::setAttribute(Qt::AA_NativeWindows);
- if (qt_is_gui_used)
+ if (!qt_is_tty_app)
initializeMultitouch();
if (QGuiApplication::desktopSettingsAware())
@@ -673,8 +627,8 @@ void QApplicationPrivate::initializeWidgetFontHash()
QWidget *QApplication::activePopupWidget()
{
- return QApplicationPrivate::popupWidgets && !QApplicationPrivate::popupWidgets->isEmpty() ?
- QApplicationPrivate::popupWidgets->constLast() : nullptr;
+ auto *win = qobject_cast<QWidgetWindow *>(QGuiApplicationPrivate::activePopupWindow());
+ return win ? win->widget() : nullptr;
}
@@ -747,58 +701,24 @@ QApplication::~QApplication()
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 = nullptr; //### 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
}
/*!
@@ -862,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 == nullptr || 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;
}
/*!
@@ -985,10 +926,7 @@ QStyle *QApplication::style()
// Take ownership of the style
defaultStyle->setParent(qApp);
- if (testAttribute(Qt::AA_SetPalette))
- defaultStyle->polish(*QGuiApplicationPrivate::app_pal);
- else
- QApplicationPrivate::initializeWidgetPalettesFromTheme();
+ QGuiApplicationPrivate::updatePalette();
#ifndef QT_NO_STYLE_STYLESHEET
if (!QApplicationPrivate::styleSheet.isEmpty()) {
@@ -1059,13 +997,10 @@ 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 (testAttribute(Qt::AA_SetPalette))
- QApplicationPrivate::app_style->polish(*QGuiApplicationPrivate::app_pal);
- else
- QApplicationPrivate::initializeWidgetPalettesFromTheme();
+ // 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
@@ -1123,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
@@ -1143,109 +1078,6 @@ QStyle* QApplication::setStyle(const QString& style)
return s;
}
-#if QT_DEPRECATED_SINCE(5, 8)
-/*!
- Returns the color specification.
- \obsolete
-
- \sa QApplication::setColorSpec()
-*/
-
-int QApplication::colorSpec()
-{
- 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
-
- 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.
-
- Example:
-
- \snippet code/src_gui_kernel_qapplication.cpp 2
-
- \sa colorSpec()
-*/
-
-void QApplication::setColorSpec(int spec)
-{
- Q_UNUSED(spec)
-}
-#endif
-
-/*!
- \property QApplication::globalStrut
- \brief the minimum size that any GUI element that the user can interact
- with should have
- \deprecated
-
- 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;
-}
-
// Widget specific palettes
QApplicationPrivate::PaletteHash QApplicationPrivate::widgetPalettes;
@@ -1262,6 +1094,19 @@ QPalette QApplicationPrivate::basePalette() const
if (const QPalette *themePalette = platformTheme() ? platformTheme()->palette() : nullptr)
palette = themePalette->resolve(palette);
+ // 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);
+
+ // 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);
+
return palette;
}
@@ -1335,17 +1180,19 @@ QPalette QApplication::palette(const char *className)
*/
void QApplication::setPalette(const QPalette &palette, const char* className)
{
- QPalette polishedPalette = palette;
-
- if (QApplicationPrivate::app_style)
- QApplicationPrivate::app_style->polish(polishedPalette);
-
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(polishedPalette);
+ QGuiApplication::setPalette(palette);
}
}
@@ -1356,23 +1203,20 @@ void QApplicationPrivate::handlePaletteChanged(const char *className)
// Setting the global application palette is documented to
// reset any previously set class specific widget palettes.
- bool sendPaletteChangeToAllWidgets = false;
- if (!className && !widgetPalettes.isEmpty()) {
- sendPaletteChangeToAllWidgets = true;
+ if (!className && !widgetPalettes.isEmpty())
widgetPalettes.clear();
- }
QGuiApplicationPrivate::handlePaletteChanged(className);
QEvent event(QEvent::ApplicationPaletteChange);
const QWidgetList widgets = QApplication::allWidgets();
for (auto widget : widgets) {
- if (sendPaletteChangeToAllWidgets || (!className && widget->isWindow()) || (className && widget->inherits(className)))
+ if (!widget->isWindow() && widget->inherits(className))
QCoreApplication::sendEvent(widget, &event);
}
#if QT_CONFIG(graphicsview)
- for (auto scene : qAsConst(scene_list))
+ for (auto scene : std::as_const(scene_list))
QCoreApplication::sendEvent(scene, &event);
#endif
@@ -1429,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)
@@ -1449,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();
}
@@ -1501,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);
- QCoreApplication::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);
}
@@ -1558,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()) {
@@ -1571,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);
@@ -1688,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) {
@@ -1696,7 +1526,7 @@ 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);
}
@@ -1707,7 +1537,7 @@ void QApplicationPrivate::setFocusWidget(QWidget *focus, Qt::FocusReason reason)
if (that)
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;
QCoreApplication::sendEvent(focus, &in);
@@ -1734,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()
@@ -1742,8 +1574,9 @@ QWidget *QApplication::activeWindow()
QFontMetrics QApplication::fontMetrics()
{
- return desktop()->fontMetrics();
+ return QApplicationPrivate::desktop()->fontMetrics();
}
+#endif
bool QApplicationPrivate::tryCloseAllWidgetWindows(QWindowList *processedWindows)
{
@@ -1774,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()
{
@@ -1842,9 +1666,16 @@ void QApplication::aboutQt()
bool QApplication::event(QEvent *e)
{
Q_D(QApplication);
- if (e->type() == QEvent::Quit) {
+ 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();
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()) && !w->testAttribute(Qt::WA_DontShowOnScreen)) {
e->ignore();
@@ -1856,7 +1687,7 @@ bool QApplication::event(QEvent *e)
// 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();
@@ -1866,8 +1697,10 @@ 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 != nullptr);
if (te->timerId() == d->toolTipWakeUp.timerId()) {
@@ -1896,19 +1729,28 @@ 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);
@@ -1940,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.
@@ -1956,8 +1799,15 @@ void QApplicationPrivate::notifyLayoutDirectionChange()
\sa activeWindow(), QWidget::activateWindow()
*/
+#if QT_DEPRECATED_SINCE(6,5)
void QApplication::setActiveWindow(QWidget* act)
{
+ QApplicationPrivate::setActiveWindow(act);
+}
+#endif
+
+void QApplicationPrivate::setActiveWindow(QWidget* act)
+{
QWidget* window = act?act->window():nullptr;
if (QApplicationPrivate::active_window == window)
@@ -1974,8 +1824,8 @@ void QApplication::setActiveWindow(QWidget* act)
QWidgetList toBeDeactivated;
if (QApplicationPrivate::active_window) {
- if (style()->styleHint(QStyle::SH_Widget_ShareActivation, nullptr, 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);
@@ -1996,8 +1846,8 @@ void QApplication::setActiveWindow(QWidget* act)
QApplicationPrivate::active_window = window;
if (QApplicationPrivate::active_window) {
- if (style()->styleHint(QStyle::SH_Widget_ShareActivation, nullptr, 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);
@@ -2015,17 +1865,17 @@ 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 == nullptr) { // !inPopupMode()
+ if (!inPopupMode()) {
// then focus events
if (!QApplicationPrivate::active_window && QApplicationPrivate::focus_widget) {
QApplicationPrivate::setFocusWidget(nullptr, Qt::ActiveWindowFocusReason);
@@ -2038,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))
+ 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);
+ }
}
}
}
@@ -2076,19 +1927,37 @@ QWidget *qt_tlw_for_window(QWindow *wnd)
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
@@ -2106,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) {
@@ -2118,10 +1987,15 @@ 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))
@@ -2132,7 +2006,7 @@ QWidget *QApplicationPrivate::focusNextPrevChild_helper(QWidget *toplevel, bool
if (next)
break;
}
- test = test->d_func()->focus_next;
+ test = test->nextInFocusChain();
}
if (wrappingOccurred != nullptr)
@@ -2157,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);
- QCoreApplication::sendEvent(leave, & e);
- }
- if (enter) {
- const QPoint windowPos = enter->window()->mapFromGlobal(globalPos);
- QEnterEvent e(enter->mapFromGlobal(globalPos), windowPos, globalPos);
- QCoreApplication::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;
@@ -2230,7 +2089,7 @@ void QApplicationPrivate::dispatchEnterLeave(QWidget* enter, QWidget* leave, con
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),
+ QHoverEvent he(QEvent::HoverLeave, QPointF(-1, -1), globalPosF, w->mapFromGlobal(globalPosF),
QGuiApplication::keyboardModifiers());
qApp->d_func()->notify_helper(w, &he);
}
@@ -2238,20 +2097,21 @@ void QApplicationPrivate::dispatchEnterLeave(QWidget* enter, QWidget* leave, con
}
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, nullptr)) {
const QPointF localPos = w->mapFromGlobal(globalPos);
- QEnterEvent enterEvent(localPos, windowPos, globalPosF);
+ 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),
+ QHoverEvent he(QEvent::HoverEnter, windowPos, QPointF(-1, -1), globalPos,
QGuiApplication::keyboardModifiers());
+ QMutableEventPoint::setPosition(he.point(0), localPos);
qApp->d_func()->notify_helper(w, &he);
}
}
@@ -2285,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);
@@ -2328,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 = nullptr;
- if (Q_UNLIKELY(!window)) {
- qWarning().nospace() << "window == 0 passed.";
- return false;
- }
- if (!blockingWindow)
- blockingWindow = &unused;
+ return Qt::ApplicationModal;
+}
- if (modalWindowList.isEmpty()) {
- *blockingWindow = nullptr;
- return false;
- }
+bool QApplicationPrivate::windowNeverBlocked(QWindow *window) const
+{
QWidget *popupWidget = QApplication::activePopupWidget();
QWindow *popupWindow = popupWidget ? popupWidget->windowHandle() : nullptr;
- if (popupWindow == window || (!popupWindow && QWindowPrivate::get(window)->isPopup())) {
- *blockingWindow = nullptr;
- 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 = nullptr;
- 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() : nullptr;
- 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() : nullptr;
- 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() : nullptr;
- 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 = nullptr;
- return false;
+ return popupWindow == window || (!popupWindow && QWindowPrivate::get(window)->isPopup());
}
/*!\internal
@@ -2459,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:
@@ -2514,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;
@@ -2546,7 +2306,7 @@ 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.
@@ -2572,21 +2332,14 @@ 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 != nullptr;
@@ -2611,8 +2364,8 @@ bool QApplicationPrivate::sendMouseEvent(QWidget *receiver, QMouseEvent *event,
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());
+ enter = QApplication::widgetAt(event->globalPosition().toPoint());
+ dispatchEnterLeave(enter, leaveAfterRelease, event->globalPosition());
leaveAfterRelease = nullptr;
lastMouseReceiver = enter;
} else if (!wasLeaveAfterRelease) {
@@ -2620,7 +2373,7 @@ bool QApplicationPrivate::sendMouseEvent(QWidget *receiver, QMouseEvent *event,
if (!QWidget::mouseGrabber())
lastMouseReceiver = alienGuard ? alienWidget : (nativeGuard ? nativeWidget : nullptr);
} else {
- lastMouseReceiver = receiverGuard ? receiver : QApplication::widgetAt(event->globalPos());
+ lastMouseReceiver = receiverGuard ? receiver : QApplication::widgetAt(event->globalPosition().toPoint());
}
}
@@ -2631,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;
@@ -2645,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)
@@ -2685,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;
}
@@ -2730,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()
@@ -2751,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
@@ -2768,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()
@@ -2790,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
@@ -2810,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)
@@ -2856,64 +2580,14 @@ bool QApplication::notify(QObject *receiver, QEvent *e)
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
@@ -2941,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 {
@@ -2959,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:
@@ -2976,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) : nullptr;
-#if QT_CONFIG(graphicsview)
- QGraphicsWidget *gw = isGraphicsWidget ? static_cast<QGraphicsWidget *>(receiver) : nullptr;
-#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
@@ -3087,7 +2744,7 @@ 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, nullptr, d->toolTipWidget, nullptr);
d->toolTipWakeUp.start(d->toolTipFallAsleep.isActive() ? 20 : wakeDelay, this);
@@ -3098,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) {
@@ -3112,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)
@@ -3130,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))
@@ -3145,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)
@@ -3160,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
@@ -3178,192 +2844,160 @@ 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;
- QPoint relpos = wheel->position().toPoint();
+ // 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());
-#if QT_DEPRECATED_SINCE(5, 14)
-QT_WARNING_PUSH
-QT_WARNING_DISABLE_DEPRECATED
- QWheelEvent we(relpos, wheel->globalPos(), wheel->pixelDelta(), wheel->angleDelta(), wheel->delta(), wheel->orientation(), wheel->buttons(),
- wheel->modifiers(), phase, wheel->source(), wheel->inverted());
-QT_WARNING_POP
-#else
- QWheelEvent we(relpos, wheel->globalPosition(), wheel->pixelDelta(), wheel->angleDelta(), wheel->buttons(),
- wheel->modifiers(), phase, wheel->inverted(), wheel->source());
-#endif
- 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->globalPosition().toPoint());
-#if QT_DEPRECATED_SINCE(5, 0)
-QT_WARNING_PUSH
-QT_WARNING_DISABLE_DEPRECATED
- QWheelEvent we(relpos, wheel->globalPos(), wheel->pixelDelta(), wheel->angleDelta(), wheel->delta(), wheel->orientation(), wheel->buttons(),
- wheel->modifiers(), wheel->phase(), wheel->source());
-QT_WARNING_POP
-#else
- QWheelEvent we(relpos, wheel->globalPosition(), wheel->pixelDelta(), wheel->angleDelta(), wheel->buttons(),
- wheel->modifiers(), wheel->phase(), wheel->inverted(), wheel->source());
-#endif
- 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,
@@ -3384,15 +3018,14 @@ QT_WARNING_POP
}
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.
@@ -3403,14 +3036,21 @@ QT_WARNING_POP
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);
@@ -3420,111 +3060,101 @@ QT_WARNING_POP
#endif
)
QDragManager::self()->setCurrentTarget(nullptr, e->type() == QEvent::Drop);
+ break;
}
- 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);
- }
+#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 = nullptr;
- } 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();
@@ -3541,7 +3171,7 @@ QT_WARNING_POP
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);
@@ -3552,11 +3182,11 @@ QT_WARNING_POP
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);
@@ -3579,46 +3209,40 @@ QT_WARNING_POP
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;
@@ -3675,11 +3299,12 @@ bool QApplicationPrivate::notify_helper(QObject *receiver, QEvent * e)
bool QApplicationPrivate::inPopupMode()
{
- return QApplicationPrivate::popupWidgets != nullptr;
+ return QGuiApplicationPrivate::activePopupWindow() != nullptr;
}
static void ungrabKeyboardForPopup(QWidget *popup)
{
+ qCDebug(lcWidgetPopup) << "ungrab keyboard for" << popup;
if (QWidget::keyboardGrabber())
qt_widget_private(QWidget::keyboardGrabber())->stealKeyboardGrab(true);
else
@@ -3688,6 +3313,7 @@ static void ungrabKeyboardForPopup(QWidget *popup)
static void ungrabMouseForPopup(QWidget *popup)
{
+ qCDebug(lcWidgetPopup) << "ungrab mouse for" << popup;
if (QWidget::mouseGrabber())
qt_widget_private(QWidget::mouseGrabber())->stealMouseGrab(true);
else
@@ -3707,38 +3333,23 @@ static void grabForPopup(QWidget *popup)
ungrabKeyboardForPopup(popup);
}
}
+ qCDebug(lcWidgetPopup) << "grabbed mouse and keyboard?" << popupGrabOk << "for popup" << popup;
}
-extern QWidget *qt_popup_down;
-extern bool qt_replay_popup_mouse_event;
-
void QApplicationPrivate::closePopup(QWidget *popup)
{
- if (!popupWidgets)
+ QWindow *win = popup->windowHandle();
+ if (!win)
+ return;
+ if (!QGuiApplicationPrivate::closePopup(win))
return;
- popupWidgets->removeAll(popup);
-
- if (popup == qt_popup_down) {
- qt_button_down = nullptr;
- qt_popup_down = nullptr;
- }
- if (QApplicationPrivate::popupWidgets->count() == 0) { // this was the last popup
- delete QApplicationPrivate::popupWidgets;
- QApplicationPrivate::popupWidgets = nullptr;
+ const QWindow *nextRemainingPopup = QGuiApplicationPrivate::activePopupWindow();
+ if (!nextRemainingPopup) { // this was the last popup
if (popupGrabOk) {
popupGrabOk = false;
- if (popup->geometry().contains(QPoint(QGuiApplicationPrivate::mousePressX,
- QGuiApplicationPrivate::mousePressY))
- || popup->testAttribute(Qt::WA_NoMouseReplay)) {
- // mouse release event or inside
- qt_replay_popup_mouse_event = false;
- } else { // mouse press event
- qt_replay_popup_mouse_event = true;
- }
-
// transfer grab back to mouse grabber if any, otherwise release the grab
ungrabMouseForPopup(popup);
@@ -3757,30 +3368,23 @@ void QApplicationPrivate::closePopup(QWidget *popup)
}
}
- } else {
+ } else if (const auto *popupWin = qobject_cast<const QWidgetWindow *>(nextRemainingPopup)) {
// A popup was closed, so the previous popup gets the focus.
- QWidget* aw = QApplicationPrivate::popupWidgets->constLast();
- if (QWidget *fw = aw->focusWidget())
+ if (QWidget *fw = popupWin->widget()->focusWidget())
fw->setFocus(Qt::PopupFocusReason);
// can become nullptr due to setFocus() above
- if (QApplicationPrivate::popupWidgets &&
- QApplicationPrivate::popupWidgets->count() == 1) // grab mouse/keyboard
- grabForPopup(aw);
+ if (QGuiApplicationPrivate::popupCount() == 1) // grab mouse/keyboard
+ grabForPopup(popupWin->widget());
}
}
-int openPopupCount = 0;
-
void QApplicationPrivate::openPopup(QWidget *popup)
{
- openPopupCount++;
- if (!popupWidgets) // create list
- popupWidgets = new QWidgetList;
- popupWidgets->append(popup); // add to end of list
+ QGuiApplicationPrivate::activatePopup(popup->windowHandle());
- if (QApplicationPrivate::popupWidgets->count() == 1) // grab mouse/keyboard
+ if (QGuiApplicationPrivate::popupCount() == 1) // grab mouse/keyboard
grabForPopup(popup);
// popups are not focus-handled by the window system (the first
@@ -3788,7 +3392,7 @@ 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 (QGuiApplicationPrivate::popupCount() == 1) { // this was the first popup
if (QWidget *fw = QApplication::focusWidget()) {
QFocusEvent e(QEvent::FocusOut, Qt::PopupFocusReason);
QCoreApplication::sendEvent(fw, &e);
@@ -3820,51 +3424,6 @@ Qt::NavigationMode QApplication::navigationMode()
{
return QApplicationPrivate::navigationMode;
}
-
-# if QT_DEPRECATED_SINCE(5, 13)
-/*!
- 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
#endif
/*!
@@ -3872,7 +3431,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.
@@ -4163,18 +3722,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();
- 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;
+ for (int i = 0; i < touchEvent->pointCount(); ++i) {
+ auto &pt = touchEvent->point(i);
+ QMutableEventPoint::setPosition(pt, widget->mapFromGlobal(pt.globalPosition()));
- if (touchPoint.state() == Qt::TouchPointPressed)
+ if (pt.state() == QEventPoint::State::Pressed)
containsPress = true;
}
return containsPress;
@@ -4198,111 +3751,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 = nullptr;
- 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();
+ 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() != nullptr);
+ 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);
}
@@ -4319,13 +3872,13 @@ bool QApplicationPrivate::translateRawTouchEvent(QWidget *window,
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:
@@ -4333,14 +3886,10 @@ bool QApplicationPrivate::translateRawTouchEvent(QWidget *window,
break;
}
- QTouchEvent touchEvent(eventType,
- device,
- QGuiApplication::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)
@@ -4351,7 +3900,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);
@@ -4364,7 +3915,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())
@@ -4376,31 +3929,30 @@ 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, QGuiApplication::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();
+ QGuiApplicationPrivate::handleThemeChanged();
qt_init_tooltip_palette();
}
@@ -4437,6 +3989,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"