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.cpp972
1 files changed, 445 insertions, 527 deletions
diff --git a/src/widgets/kernel/qapplication.cpp b/src/widgets/kernel/qapplication.cpp
index b1341d1015..de7d93ce20 100644
--- a/src/widgets/kernel/qapplication.cpp
+++ b/src/widgets/kernel/qapplication.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** 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"
@@ -84,14 +48,18 @@
#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>
@@ -112,11 +80,13 @@
#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);
@@ -128,6 +98,15 @@ static void initResources()
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
+Q_TRACE_PREFIX(qtwidgets,
+ "#include <qcoreevent.h>"
+);
+Q_TRACE_METADATA(qtwidgets, "ENUM { AUTO, RANGE User ... MaxUser } QEvent::Type;");
+Q_TRACE_POINT(qtwidgets, QApplication_notify_entry, QObject *receiver, QEvent *event, QEvent::Type type);
+Q_TRACE_POINT(qtwidgets, QApplication_notify_exit, bool consumed, bool filtered);
+
// Helper macro for static functions to check on the existence of the application class.
#define CHECK_QAPP_INSTANCE(...) \
if (Q_LIKELY(QCoreApplication::instance())) { \
@@ -143,8 +122,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;
@@ -331,7 +310,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
@@ -387,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;
@@ -407,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) {
@@ -474,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();
@@ -495,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()
@@ -507,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
@@ -517,8 +495,11 @@ void QApplicationPrivate::init()
void qt_init_tooltip_palette()
{
#if QT_CONFIG(tooltip)
- if (const QPalette *toolTipPalette = QGuiApplicationPrivate::platformTheme()->palette(QPlatformTheme::ToolTipPalette))
- QToolTip::setPalette(*toolTipPalette);
+ if (const QPalette *toolTipPalette = QGuiApplicationPrivate::platformTheme()->palette(QPlatformTheme::ToolTipPalette)) {
+ QPalette toolTipPal = *toolTipPalette;
+ toolTipPal.setResolveMask(0);
+ QToolTip::setPalette(toolTipPal);
+ }
#endif
}
@@ -547,7 +528,9 @@ 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();
}
}
@@ -558,7 +541,7 @@ void QApplicationPrivate::initialize()
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())
@@ -718,13 +701,16 @@ 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);
@@ -735,14 +721,6 @@ QApplication::~QApplication()
QApplicationPrivate::widgetCount = false;
}
-void qt_cleanup()
-{
- QPixmapCache::clear();
- QColormap::cleanup();
-
- QApplicationPrivate::active_window = nullptr; //### this should not be necessary
-}
-
/*!
\fn QWidget *QApplication::widgetAt(const QPoint &point)
@@ -804,35 +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) {
- static_cast<QResizeEvent *>(cur.event)->m_size =
- static_cast<const QResizeEvent *>(event)->size();
- } else if (cur.event->type() == QEvent::Move) {
- static_cast<QMoveEvent *>(cur.event)->m_pos =
- static_cast<const QMoveEvent *>(event)->pos();
- } 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;
}
/*!
@@ -1213,7 +1210,7 @@ void QApplicationPrivate::handlePaletteChanged(const char *className)
}
#if QT_CONFIG(graphicsview)
- for (auto scene : qAsConst(scene_list))
+ for (auto scene : std::as_const(scene_list))
QCoreApplication::sendEvent(scene, &event);
#endif
@@ -1563,7 +1560,7 @@ QWidget *QApplication::activeWindow()
#if QT_DEPRECATED_SINCE(6,0)
/*!
- \obsolete Use the QFontMetricsF constructor instead
+ \deprecated Use the QFontMetricsF constructor instead.
Returns display (screen) font metrics for the application font.
\sa font(), setFont(), QWidget::fontMetrics(), QPainter::fontMetrics()
@@ -1663,7 +1660,8 @@ 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.
@@ -1683,7 +1681,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();
@@ -1693,8 +1691,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()) {
@@ -1723,15 +1723,16 @@ 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 || e->type() == QEvent::ApplicationFontChange ||
- e->type() == QEvent::ApplicationPaletteChange) {
+ 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
@@ -1740,6 +1741,10 @@ bool QApplication::event(QEvent *e)
if (!w->windowHandle() && (w->windowType() != Qt::Desktop))
postEvent(w, new QEvent(e->type()));
}
+ break;
+ }
+ default:
+ break;
}
return QGuiApplication::event(e);
@@ -1771,6 +1776,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.
@@ -1787,8 +1793,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)
@@ -1805,8 +1818,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);
@@ -1827,8 +1840,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);
@@ -1846,14 +1859,14 @@ 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()
@@ -1908,19 +1921,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
@@ -1938,7 +1969,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) {
@@ -1950,7 +1981,10 @@ 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();
- const bool canTakeFocus = ((focusProxy ? focusProxy->focusPolicy() : test->focusPolicy())
+ 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))
@@ -1966,7 +2000,7 @@ QWidget *QApplicationPrivate::focusNextPrevChild_helper(QWidget *toplevel, bool
if (next)
break;
}
- test = test->d_func()->focus_next;
+ test = test->nextInFocusChain();
}
if (wrappingOccurred != nullptr)
@@ -1991,24 +2025,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;
@@ -2064,7 +2083,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);
}
@@ -2072,20 +2091,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);
}
}
@@ -2162,80 +2182,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();
- if (windowModality == Qt::NonModal) {
- // If modality type hasn't been set on the modalWindow's widget, as
- // when waiting for a native dialog, use ApplicationModal.
- windowModality = Qt::ApplicationModal;
- }
-
- switch (windowModality) {
- case Qt::ApplicationModal:
- 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
@@ -2266,12 +2222,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:
@@ -2321,9 +2271,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;
@@ -2387,13 +2334,6 @@ bool QApplicationPrivate::sendMouseEvent(QWidget *receiver, QMouseEvent *event,
}
}
-#ifdef ALIEN_DEBUG
- qDebug() << "QApplicationPrivate::sendMouseEvent: receiver:" << receiver
- << "pos:" << event->position() << "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;
@@ -2438,7 +2378,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;
@@ -2452,7 +2392,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)
@@ -2534,7 +2474,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()
@@ -2573,7 +2513,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()
@@ -2595,8 +2535,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
@@ -2615,34 +2556,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)
@@ -2661,9 +2574,11 @@ 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
}
QGuiApplicationPrivate::captureGlobalModifierState(e);
@@ -2694,7 +2609,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 {
@@ -2712,9 +2627,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:
@@ -2729,99 +2646,80 @@ 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->position().toPoint();
@@ -2829,8 +2727,8 @@ bool QApplication::notify(QObject *receiver, QEvent *e)
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
@@ -2885,11 +2783,12 @@ bool QApplication::notify(QObject *receiver, QEvent *e)
w = static_cast<QWidget *>(receiver);
relpos = mouse->position().toPoint();
- QPoint diff = relpos - w->mapFromGlobal(d->hoverGlobalPos);
+ 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))
@@ -2900,13 +2799,10 @@ bool QApplication::notify(QObject *receiver, QEvent *e)
}
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)
@@ -2916,9 +2812,9 @@ bool QApplication::notify(QObject *receiver, QEvent *e)
QWheelEvent* wheel = static_cast<QWheelEvent*>(e);
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.
+ 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;
@@ -2982,6 +2878,9 @@ bool QApplication::notify(QObject *receiver, QEvent *e)
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();
@@ -2990,17 +2889,15 @@ bool QApplication::notify(QObject *receiver, QEvent *e)
if (w->isWindow() || w->testAttribute(Qt::WA_NoMousePropagation))
break;
- QMutableSinglePointEvent::from(we).mutablePoint().setPosition(we.position() + w->pos());
+ 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();
@@ -3011,23 +2908,22 @@ bool QApplication::notify(QObject *receiver, QEvent *e)
eventAccepted = ((w == receiver) ? context : &ce)->isAccepted();
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->position();
bool eventAccepted = tablet->isAccepted();
@@ -3037,29 +2933,28 @@ bool QApplication::notify(QObject *receiver, QEvent *e)
tablet->tangentialPressure(), tablet->rotation(), tablet->z(),
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->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();
}
tablet->setAccepted(eventAccepted);
+ break;
}
- break;
#endif // QT_CONFIG(tabletevent)
#if QT_CONFIG(tooltip) || QT_CONFIG(whatsthis)
- case QEvent::ToolTip:
- case QEvent::WhatsThis:
- case QEvent::QueryWhatsThis:
- {
- QWidget* w = static_cast<QWidget *>(receiver);
+ case QEvent::ToolTip:
+ case QEvent::WhatsThis:
+ case QEvent::QueryWhatsThis: {
QHelpEvent *help = static_cast<QHelpEvent*>(e);
QPoint relpos = help->pos();
bool eventAccepted = help->isAccepted();
@@ -3069,34 +2964,34 @@ bool QApplication::notify(QObject *receiver, QEvent *e)
res = d->notify_helper(w, w == receiver ? help : &he);
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,
@@ -3120,12 +3015,11 @@ bool QApplication::notify(QObject *receiver, QEvent *e)
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.
@@ -3136,14 +3030,21 @@ bool QApplication::notify(QObject *receiver, QEvent *e)
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->m_pos = origReciver->mapToParent(dragEvent->m_pos);
- 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);
@@ -3153,109 +3054,101 @@ bool QApplication::notify(QObject *receiver, QEvent *e)
#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);
- QMutableTouchEvent *touchEvent = QMutableTouchEvent::from(static_cast<QTouchEvent *>(e));
- bool eventAccepted = touchEvent->isAccepted();
- bool acceptTouchEvents = widget->testAttribute(Qt::WA_AcceptTouchEvents);
-
- if (acceptTouchEvents && e->spontaneous()) {
- const QPoint localPos = touchEvent->points()[0].position().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->m_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->pointCount(); ++i) {
- auto &pt = QMutableEventPoint::from(touchEvent->point(i));
- pt.setPosition(pt.position() + 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();
@@ -3272,7 +3165,7 @@ bool QApplication::notify(QObject *receiver, QEvent *e)
wd->gestureContext.find(type);
bool deliver = contextit != wd->gestureContext.end() &&
(g->state() == Qt::GestureStarted || w == receiver ||
- (contextit.value() & Qt::ReceivePartialGestures));
+ (contextit.value() & Qt::ReceivePartialGestures));
if (deliver) {
allGestures.removeAt(i);
gestures.append(g);
@@ -3310,46 +3203,40 @@ bool QApplication::notify(QObject *receiver, QEvent *e)
break;
w = w->parentWidget();
}
- for (QGesture *g : qAsConst(allGestures))
+ for (QGesture *g : std::as_const(allGestures))
gestureEvent->setAccepted(g, false);
gestureEvent->m_accept = false; // to make sure we check individual gestures
- } else {
- res = d->notify_helper(receiver, e);
+ break;
}
- break;
- }
#endif // QT_NO_GESTURES
#ifdef Q_OS_MAC
- // Enable touch events on enter, disable on leave.
- typedef void (*RegisterTouchWindowFn)(QWindow *, bool);
- case QEvent::Enter:
- if (receiver->isWidgetType()) {
- QWidget *w = static_cast<QWidget *>(receiver);
+ // Enable touch events on enter, disable on leave.
+ typedef void (*RegisterTouchWindowFn)(QWindow *, bool);
+ case QEvent::Enter:
if (w->testAttribute(Qt::WA_AcceptTouchEvents)) {
RegisterTouchWindowFn registerTouchWindow = reinterpret_cast<RegisterTouchWindowFn>
(platformNativeInterface()->nativeResourceFunctionForIntegration("registertouchwindow"));
if (registerTouchWindow)
registerTouchWindow(w->window()->windowHandle(), true);
}
- }
- res = d->notify_helper(receiver, e);
- break;
- case QEvent::Leave:
- if (receiver->isWidgetType()) {
- QWidget *w = static_cast<QWidget *>(receiver);
+ res = d->notify_helper(receiver, e);
+ break;
+ case QEvent::Leave:
if (w->testAttribute(Qt::WA_AcceptTouchEvents)) {
RegisterTouchWindowFn registerTouchWindow = reinterpret_cast<RegisterTouchWindowFn>
(platformNativeInterface()->nativeResourceFunctionForIntegration("registertouchwindow"));
if (registerTouchWindow)
registerTouchWindow(w->window()->windowHandle(), false);
}
- }
- res = d->notify_helper(receiver, e);
- break;
+ res = d->notify_helper(receiver, e);
+ break;
#endif
- default:
+ default:
+ res = d->notify_helper(receiver, e);
+ break;
+ }
+ } else {
res = d->notify_helper(receiver, e);
- break;
}
return res;
@@ -3444,6 +3331,17 @@ extern QWidget *qt_popup_down;
extern bool qt_replay_popup_mouse_event;
extern bool qt_popup_down_closed;
+bool QApplicationPrivate::closeAllPopups()
+{
+ // Close all popups: In case some popup refuses to close,
+ // we give up after 1024 attempts (to avoid an infinite loop).
+ int maxiter = 1024;
+ QWidget *popup;
+ while ((popup = QApplication::activePopupWidget()) && maxiter--)
+ popup->close(); // this will call QApplicationPrivate::closePopup
+ return true;
+}
+
void QApplicationPrivate::closePopup(QWidget *popup)
{
if (!popupWidgets)
@@ -3456,7 +3354,7 @@ void QApplicationPrivate::closePopup(QWidget *popup)
qt_popup_down = nullptr;
}
- if (QApplicationPrivate::popupWidgets->count() == 0) { // this was the last popup
+ if (QApplicationPrivate::popupWidgets->size() == 0) { // this was the last popup
delete QApplicationPrivate::popupWidgets;
QApplicationPrivate::popupWidgets = nullptr;
qt_popup_down_closed = false;
@@ -3501,7 +3399,7 @@ void QApplicationPrivate::closePopup(QWidget *popup)
// can become nullptr due to setFocus() above
if (QApplicationPrivate::popupWidgets &&
- QApplicationPrivate::popupWidgets->count() == 1) // grab mouse/keyboard
+ QApplicationPrivate::popupWidgets->size() == 1) // grab mouse/keyboard
grabForPopup(aw);
}
@@ -3516,7 +3414,7 @@ void QApplicationPrivate::openPopup(QWidget *popup)
popupWidgets = new QWidgetList;
popupWidgets->append(popup); // add to end of list
- if (QApplicationPrivate::popupWidgets->count() == 1) // grab mouse/keyboard
+ if (QApplicationPrivate::popupWidgets->size() == 1) // grab mouse/keyboard
grabForPopup(popup);
// popups are not focus-handled by the window system (the first
@@ -3524,7 +3422,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 (popupWidgets->size() == 1) { // this was the first popup
if (QWidget *fw = QApplication::focusWidget()) {
QFocusEvent e(QEvent::FocusOut, Qt::PopupFocusReason);
QCoreApplication::sendEvent(fw, &e);
@@ -3563,7 +3461,7 @@ Qt::NavigationMode QApplication::navigationMode()
\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.
@@ -3856,8 +3754,8 @@ bool QApplicationPrivate::updateTouchPointsForWidget(QWidget *widget, QTouchEven
bool containsPress = false;
for (int i = 0; i < touchEvent->pointCount(); ++i) {
- auto &pt = QMutableEventPoint::from(touchEvent->point(i));
- pt.setPosition(widget->mapFromGlobal(pt.globalPosition()));
+ auto &pt = touchEvent->point(i);
+ QMutableEventPoint::setPosition(pt, widget->mapFromGlobal(pt.globalPosition()));
if (pt.state() == QEventPoint::State::Pressed)
containsPress = true;
@@ -3899,33 +3797,39 @@ QWidget *QApplicationPrivate::findClosestTouchPointTarget(const QPointingDevice
if (closestTouchPointId == -1 || distance < closestDistance) {
closestTouchPointId = pt.id();
closestDistance = distance;
- closestTarget = static_cast<const QMutableEventPoint &>(pt).target();
+ closestTarget = QMutableEventPoint::target(pt);
}
}
}
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; i < touchEvent->pointCount(); ++i)
- QMutableEventPoint::from(touchEvent->point(i)).setTarget(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,
- const QPointingDevice *device,
- QList<QEventPoint> &touchPoints,
- ulong timestamp)
+bool QApplicationPrivate::translateRawTouchEvent(QWidget *window, const QTouchEvent *te)
{
QApplicationPrivate *d = self;
// TODO get rid of this QPair
typedef QPair<QEventPoint::State, QList<QEventPoint> > StatesAndTouchPoints;
QHash<QWidget *, StatesAndTouchPoints> widgetsNeedingEvents;
+ const auto *device = te->pointingDevice();
+ auto touchPoints = te->points(); // touch points will be mutated
for (auto &touchPoint : touchPoints) {
// update state
QPointer<QObject> target;
@@ -3947,18 +3851,23 @@ bool QApplicationPrivate::translateRawTouchEvent(QWidget *window,
target = window;
}
+ 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;
}
}
- QMutableEventPoint::from(touchPoint).setTarget(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 = QMutableEventPoint::from(touchPoint).target();
+ target = QMutableEventPoint::target(touchPoint);
if (!target)
continue;
}
@@ -4010,7 +3919,7 @@ bool QApplicationPrivate::translateRawTouchEvent(QWidget *window,
QMutableTouchEvent touchEvent(eventType, device, QGuiApplication::keyboardModifiers(),
it.value().second);
bool containsPress = updateTouchPointsForWidget(widget, &touchEvent);
- touchEvent.setTimestamp(timestamp);
+ touchEvent.setTimestamp(te->timestamp());
touchEvent.setTarget(widget);
if (containsPress)
@@ -4021,7 +3930,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);
@@ -4034,7 +3945,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())
@@ -4055,7 +3968,7 @@ void QApplicationPrivate::translateTouchCancel(const QPointingDevice *device, ul
const QPointingDevicePrivate *devPriv = QPointingDevicePrivate::get(device);
for (auto &epd : devPriv->activePoints.values()) {
const auto &pt = epd.eventPoint;
- QObject *target = static_cast<const QMutableEventPoint &>(pt).target();
+ QObject *target = QMutableEventPoint::target(pt);
if (target && target->isWidgetType())
widgetsNeedingCancel.insert(static_cast<QWidget *>(target));
}
@@ -4067,9 +3980,9 @@ void QApplicationPrivate::translateTouchCancel(const QPointingDevice *device, ul
}
}
-void QApplicationPrivate::notifyThemeChanged()
+void QApplicationPrivate::handleThemeChanged()
{
- QGuiApplicationPrivate::notifyThemeChanged();
+ QGuiApplicationPrivate::handleThemeChanged();
qt_init_tooltip_palette();
}
@@ -4106,6 +4019,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"