diff options
Diffstat (limited to 'src/gui/kernel/qwindowsysteminterface.cpp')
-rw-r--r-- | src/gui/kernel/qwindowsysteminterface.cpp | 1014 |
1 files changed, 479 insertions, 535 deletions
diff --git a/src/gui/kernel/qwindowsysteminterface.cpp b/src/gui/kernel/qwindowsysteminterface.cpp index 2de0131640..1875594300 100644 --- a/src/gui/kernel/qwindowsysteminterface.cpp +++ b/src/gui/kernel/qwindowsysteminterface.cpp @@ -1,47 +1,13 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtGui 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) 2020 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 "qwindowsysteminterface.h" #include <qpa/qplatformwindow.h> #include "qwindowsysteminterface_p.h" #include "private/qguiapplication_p.h" #include "private/qevent_p.h" -#include "private/qtouchdevice_p.h" +#include "private/qeventpoint_p.h" +#include "private/qpointingdevice_p.h" +#include "private/qscreen_p.h" #include <QAbstractEventDispatcher> #include <qpa/qplatformintegration.h> #include <qdebug.h> @@ -56,14 +22,16 @@ QT_BEGIN_NAMESPACE +using namespace Qt::StringLiterals; -QElapsedTimer QWindowSystemInterfacePrivate::eventTime; +Q_LOGGING_CATEGORY(lcQpaInputDevices, "qt.qpa.input.devices") + +Q_CONSTINIT QElapsedTimer QWindowSystemInterfacePrivate::eventTime; bool QWindowSystemInterfacePrivate::synchronousWindowSystemEvents = false; -bool QWindowSystemInterfacePrivate::platformFiltersEvents = false; bool QWindowSystemInterfacePrivate::TabletEvent::platformSynthesizesMouse = true; QWaitCondition QWindowSystemInterfacePrivate::eventsFlushed; -QMutex QWindowSystemInterfacePrivate::flushEventMutex; -QAtomicInt QWindowSystemInterfacePrivate::eventAccepted; +Q_CONSTINIT QMutex QWindowSystemInterfacePrivate::flushEventMutex; +Q_CONSTINIT QAtomicInt QWindowSystemInterfacePrivate::eventAccepted; QWindowSystemEventHandler *QWindowSystemInterfacePrivate::eventHandler; QWindowSystemInterfacePrivate::WindowSystemEventList QWindowSystemInterfacePrivate::windowSystemEventQueue; @@ -72,20 +40,45 @@ extern QPointer<QWindow> qt_last_mouse_receiver; // ------------------- QWindowSystemInterfacePrivate ------------------- +/*! + \internal + + The QWindowSystemHelper creates synchronously delivered events on the stack, unless + the calling thread is not the Gui thread. + + Asynchronously delivered events, and events created outside the Gui thread are + allocated on the heap. +*/ + +template<typename Delivery> +struct QWindowSystemHelper +{ + template<typename EventType, typename ...Args> + static bool handleEvent(Args ...); +}; + /* - Handles a window system event asynchronously by posting the event to Qt Gui. + Handles a window system event. - This function posts the event on the window system event queue and wakes the - Gui event dispatcher. Qt Gui will then handle the event asynchonously at a - later point. + By default this function posts the event on the window system event queue and + wakes the Gui event dispatcher. Qt Gui will then handle the event asynchronously + at a later point. The return value is not used in asynchronous mode and will + always be true. + + In synchronous mode Qt Gui will process the event immediately. The return value + indicates if Qt accepted the event. If the event is delivered from another thread + than the Qt main thread the window system event queue is flushed, which may deliver + other events as well. + + \sa flushWindowSystemEvents(), setSynchronousWindowSystemEvents() */ template<> -bool QWindowSystemInterfacePrivate::handleWindowSystemEvent<QWindowSystemInterface::AsynchronousDelivery>(WindowSystemEvent *ev) +template<typename EventType, typename ...Args> +bool QWindowSystemHelper<QWindowSystemInterface::DefaultDelivery>::handleEvent(Args ...args) { - windowSystemEventQueue.append(ev); - if (QAbstractEventDispatcher *dispatcher = QGuiApplicationPrivate::qt_qpa_core_dispatcher()) - dispatcher->wakeUp(); - return true; + return QWindowSystemInterfacePrivate::synchronousWindowSystemEvents + ? QWindowSystemHelper<QWindowSystemInterface::SynchronousDelivery>::handleEvent<EventType>(args...) + : QWindowSystemHelper<QWindowSystemInterface::AsynchronousDelivery>::handleEvent<EventType>(args...); } /* @@ -99,50 +92,53 @@ bool QWindowSystemInterfacePrivate::handleWindowSystemEvent<QWindowSystemInterfa well. */ template<> -bool QWindowSystemInterfacePrivate::handleWindowSystemEvent<QWindowSystemInterface::SynchronousDelivery>(WindowSystemEvent *ev) +template<typename EventType, typename ...Args> +bool QWindowSystemHelper<QWindowSystemInterface::SynchronousDelivery>::handleEvent(Args ...args) { - bool accepted = true; if (QThread::currentThread() == QGuiApplication::instance()->thread()) { - // Process the event immediately on the current thread and return the accepted state. - QGuiApplicationPrivate::processWindowSystemEvent(ev); - accepted = ev->eventAccepted; - delete ev; + EventType event(args...); + // Process the event immediately on the Gui thread and return the accepted state + if (QWindowSystemInterfacePrivate::eventHandler) { + if (!QWindowSystemInterfacePrivate::eventHandler->sendEvent(&event)) + return false; + } else { + QGuiApplicationPrivate::processWindowSystemEvent(&event); + } + return event.eventAccepted; } else { // Post the event on the Qt main thread queue and flush the queue. // This will wake up the Gui thread which will process the event. // Return the accepted state for the last event on the queue, // which is the event posted by this function. - handleWindowSystemEvent<QWindowSystemInterface::AsynchronousDelivery>(ev); - accepted = QWindowSystemInterface::flushWindowSystemEvents(); + QWindowSystemHelper<QWindowSystemInterface::AsynchronousDelivery>::handleEvent<EventType>(args...); + return QWindowSystemInterface::flushWindowSystemEvents(); } - return accepted; } /* - Handles a window system event. - - By default this function posts the event on the window system event queue and - wakes the Gui event dispatcher. Qt Gui will then handle the event asynchonously - at a later point. The return value is not used in asynchronous mode and will - always be true. - - In synchronous mode Qt Gui will process the event immediately. The return value - indicates if Qt accepted the event. If the event is delivered from another thread - than the Qt main thread the window system event queue is flushed, which may deliver - other events as well. + Handles a window system event asynchronously by posting the event to Qt Gui. - \sa flushWindowSystemEvents(), setSynchronousWindowSystemEvents() + This function posts the event on the window system event queue and wakes the + Gui event dispatcher. Qt Gui will then handle the event asynchronously at a + later point. */ template<> -bool QWindowSystemInterfacePrivate::handleWindowSystemEvent<QWindowSystemInterface::DefaultDelivery>(QWindowSystemInterfacePrivate::WindowSystemEvent *ev) +template<typename EventType, typename ...Args> +bool QWindowSystemHelper<QWindowSystemInterface::AsynchronousDelivery>::handleEvent(Args ...args) { - if (synchronousWindowSystemEvents) - return handleWindowSystemEvent<QWindowSystemInterface::SynchronousDelivery>(ev); - else - return handleWindowSystemEvent<QWindowSystemInterface::AsynchronousDelivery>(ev); + QWindowSystemInterfacePrivate::windowSystemEventQueue.append(new EventType(args...)); + if (QAbstractEventDispatcher *dispatcher = QGuiApplicationPrivate::qt_qpa_core_dispatcher()) + dispatcher->wakeUp(); + return true; +} + +template <typename EventType, typename Delivery = QWindowSystemInterface::DefaultDelivery, typename ...Args> +static bool handleWindowSystemEvent(Args ...args) +{ + return QWindowSystemHelper<Delivery>::template handleEvent<EventType>(args...); } -int QWindowSystemInterfacePrivate::windowSystemEventsQueued() +qsizetype QWindowSystemInterfacePrivate::windowSystemEventsQueued() { return windowSystemEventQueue.count(); } @@ -221,16 +217,14 @@ bool QWindowSystemEventHandler::sendEvent(QWindowSystemInterfacePrivate::WindowS QT_DEFINE_QPA_EVENT_HANDLER(void, handleEnterEvent, QWindow *window, const QPointF &local, const QPointF &global) { if (window) { - QWindowSystemInterfacePrivate::EnterEvent *e - = new QWindowSystemInterfacePrivate::EnterEvent(window, QHighDpi::fromNativeLocalPosition(local, window), QHighDpi::fromNativePixels(global, window)); - QWindowSystemInterfacePrivate::handleWindowSystemEvent<Delivery>(e); + handleWindowSystemEvent<QWindowSystemInterfacePrivate::EnterEvent, Delivery>(window, + QHighDpi::fromNativeLocalPosition(local, window), QHighDpi::fromNativeGlobalPosition(global, window)); } } QT_DEFINE_QPA_EVENT_HANDLER(void, handleLeaveEvent, QWindow *window) { - QWindowSystemInterfacePrivate::LeaveEvent *e = new QWindowSystemInterfacePrivate::LeaveEvent(window); - QWindowSystemInterfacePrivate::handleWindowSystemEvent<Delivery>(e); + handleWindowSystemEvent<QWindowSystemInterfacePrivate::LeaveEvent, Delivery>(window); } /*! @@ -246,11 +240,9 @@ void QWindowSystemInterface::handleEnterLeaveEvent(QWindow *enter, QWindow *leav handleEnterEvent(enter, local, global); } -QT_DEFINE_QPA_EVENT_HANDLER(void, handleWindowActivated, QWindow *window, Qt::FocusReason r) +QT_DEFINE_QPA_EVENT_HANDLER(void, handleFocusWindowChanged, QWindow *window, Qt::FocusReason r) { - QWindowSystemInterfacePrivate::ActivatedWindowEvent *e = - new QWindowSystemInterfacePrivate::ActivatedWindowEvent(window, r); - QWindowSystemInterfacePrivate::handleWindowSystemEvent<Delivery>(e); + handleWindowSystemEvent<QWindowSystemInterfacePrivate::FocusWindowEvent, Delivery>(window, r); } QT_DEFINE_QPA_EVENT_HANDLER(void, handleWindowStateChanged, QWindow *window, Qt::WindowStates newState, int oldState) @@ -259,38 +251,35 @@ QT_DEFINE_QPA_EVENT_HANDLER(void, handleWindowStateChanged, QWindow *window, Qt: if (oldState < Qt::WindowNoState) oldState = window->windowStates(); - QWindowSystemInterfacePrivate::WindowStateChangedEvent *e = - new QWindowSystemInterfacePrivate::WindowStateChangedEvent(window, newState, Qt::WindowStates(oldState)); - QWindowSystemInterfacePrivate::handleWindowSystemEvent<Delivery>(e); + handleWindowSystemEvent<QWindowSystemInterfacePrivate::WindowStateChangedEvent, Delivery>(window, newState, Qt::WindowStates(oldState)); } QT_DEFINE_QPA_EVENT_HANDLER(void, handleWindowScreenChanged, QWindow *window, QScreen *screen) { + handleWindowSystemEvent<QWindowSystemInterfacePrivate::WindowScreenChangedEvent, Delivery>(window, screen); +} - QWindowSystemInterfacePrivate::WindowScreenChangedEvent *e = - new QWindowSystemInterfacePrivate::WindowScreenChangedEvent(window, screen); - QWindowSystemInterfacePrivate::handleWindowSystemEvent<Delivery>(e); +QT_DEFINE_QPA_EVENT_HANDLER(void, handleWindowDevicePixelRatioChanged, QWindow *window) +{ + handleWindowSystemEvent<QWindowSystemInterfacePrivate::WindowDevicePixelRatioChangedEvent, Delivery>(window); } + QT_DEFINE_QPA_EVENT_HANDLER(void, handleSafeAreaMarginsChanged, QWindow *window) { - QWindowSystemInterfacePrivate::SafeAreaMarginsChangedEvent *e = - new QWindowSystemInterfacePrivate::SafeAreaMarginsChangedEvent(window); - QWindowSystemInterfacePrivate::handleWindowSystemEvent<Delivery>(e); + handleWindowSystemEvent<QWindowSystemInterfacePrivate::SafeAreaMarginsChangedEvent, Delivery>(window); } QT_DEFINE_QPA_EVENT_HANDLER(void, handleApplicationStateChanged, Qt::ApplicationState newState, bool forcePropagate) { Q_ASSERT(QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::ApplicationState)); - QWindowSystemInterfacePrivate::ApplicationStateChangedEvent *e = - new QWindowSystemInterfacePrivate::ApplicationStateChangedEvent(newState, forcePropagate); - QWindowSystemInterfacePrivate::handleWindowSystemEvent<Delivery>(e); + handleWindowSystemEvent<QWindowSystemInterfacePrivate::ApplicationStateChangedEvent, Delivery>(newState, forcePropagate); } QT_DEFINE_QPA_EVENT_HANDLER(bool, handleApplicationTermination) { - auto *e = new QWindowSystemInterfacePrivate::WindowSystemEvent(QWindowSystemInterfacePrivate::ApplicationTermination); - return QWindowSystemInterfacePrivate::handleWindowSystemEvent<Delivery>(e); + return handleWindowSystemEvent<QWindowSystemInterfacePrivate::WindowSystemEvent, Delivery>( + QWindowSystemInterfacePrivate::ApplicationTermination); } QWindowSystemInterfacePrivate::GeometryChangeEvent::GeometryChangeEvent(QWindow *window, const QRect &newGeometry) @@ -298,14 +287,16 @@ QWindowSystemInterfacePrivate::GeometryChangeEvent::GeometryChangeEvent(QWindow , window(window) , newGeometry(newGeometry) { - if (const QPlatformWindow *pw = window->handle()) - requestedGeometry = QHighDpi::fromNativePixels(pw->QPlatformWindow::geometry(), window); + if (const QPlatformWindow *pw = window->handle()) { + const auto nativeGeometry = pw->QPlatformWindow::geometry(); + requestedGeometry = QHighDpi::fromNativeWindowGeometry(nativeGeometry, window); + } } QT_DEFINE_QPA_EVENT_HANDLER(void, handleGeometryChange, QWindow *window, const QRect &newRect) { Q_ASSERT(window); - QWindowSystemInterfacePrivate::GeometryChangeEvent *e = new QWindowSystemInterfacePrivate::GeometryChangeEvent(window, QHighDpi::fromNativePixels(newRect, window)); + const auto newRectDi = QHighDpi::fromNativeWindowGeometry(newRect, window); if (window->handle()) { // Persist the new geometry so that QWindow::geometry() can be queried in the resize event window->handle()->QPlatformWindow::setGeometry(newRect); @@ -313,7 +304,7 @@ QT_DEFINE_QPA_EVENT_HANDLER(void, handleGeometryChange, QWindow *window, const Q // have its handle set up yet. Platforms that deliver events during window creation need // to handle the persistence manually, e.g. by overriding geometry(). } - QWindowSystemInterfacePrivate::handleWindowSystemEvent<Delivery>(e); + handleWindowSystemEvent<QWindowSystemInterfacePrivate::GeometryChangeEvent, Delivery>(window, newRectDi); } QWindowSystemInterfacePrivate::ExposeEvent::ExposeEvent(QWindow *window, const QRegion ®ion) @@ -341,18 +332,23 @@ QWindowSystemInterfacePrivate::ExposeEvent::ExposeEvent(QWindow *window, const Q This is required behavior on platforms where OpenGL swapbuffers stops blocking for obscured windows (like macOS). */ -QT_DEFINE_QPA_EVENT_HANDLER(void, handleExposeEvent, QWindow *window, const QRegion ®ion) +QT_DEFINE_QPA_EVENT_HANDLER(bool, handleExposeEvent, QWindow *window, const QRegion ®ion) { - QWindowSystemInterfacePrivate::ExposeEvent *e = - new QWindowSystemInterfacePrivate::ExposeEvent(window, QHighDpi::fromNativeLocalExposedRegion(region, window)); - QWindowSystemInterfacePrivate::handleWindowSystemEvent<Delivery>(e); + return handleWindowSystemEvent<QWindowSystemInterfacePrivate::ExposeEvent, Delivery>(window, + QHighDpi::fromNativeLocalExposedRegion(region, window)); } +QT_DEFINE_QPA_EVENT_HANDLER(bool, handlePaintEvent, QWindow *window, const QRegion ®ion) +{ + return handleWindowSystemEvent<QWindowSystemInterfacePrivate::PaintEvent, Delivery>(window, + QHighDpi::fromNativeLocalExposedRegion(region, window)); +} + + QT_DEFINE_QPA_EVENT_HANDLER(bool, handleCloseEvent, QWindow *window) { Q_ASSERT(window); - auto *event = new QWindowSystemInterfacePrivate::CloseEvent(window); - return QWindowSystemInterfacePrivate::handleWindowSystemEvent<Delivery>(event); + return handleWindowSystemEvent<QWindowSystemInterfacePrivate::CloseEvent, Delivery>(window); } /*! @@ -360,83 +356,67 @@ QT_DEFINE_QPA_EVENT_HANDLER(bool, handleCloseEvent, QWindow *window) \a w == 0 means that the event is in global coords only, \a local will be ignored in this case */ -#if QT_DEPRECATED_SINCE(5, 11) -QT_DEFINE_QPA_EVENT_HANDLER(void, handleMouseEvent, QWindow *window, const QPointF &local, const QPointF &global, Qt::MouseButtons b, - Qt::KeyboardModifiers mods, Qt::MouseEventSource source) -{ - handleMouseEvent<Delivery>(window, local, global, b, Qt::NoButton, QEvent::None, mods, source); -} -QT_DEFINE_QPA_EVENT_HANDLER(void, handleMouseEvent, QWindow *window, ulong timestamp, const QPointF &local, const QPointF &global, Qt::MouseButtons b, - Qt::KeyboardModifiers mods, Qt::MouseEventSource source) -{ - handleMouseEvent<Delivery>(window, timestamp, local, global, b, Qt::NoButton, QEvent::None, mods, source); -} - -void QWindowSystemInterface::handleFrameStrutMouseEvent(QWindow *window, const QPointF &local, const QPointF &global, Qt::MouseButtons b, - Qt::KeyboardModifiers mods, Qt::MouseEventSource source) +QT_DEFINE_QPA_EVENT_HANDLER(bool, handleMouseEvent, QWindow *window, + const QPointF &local, const QPointF &global, Qt::MouseButtons state, + Qt::MouseButton button, QEvent::Type type, Qt::KeyboardModifiers mods, + Qt::MouseEventSource source) { - handleFrameStrutMouseEvent(window, local, global, b, Qt::NoButton, QEvent::None, mods, source); + unsigned long time = QWindowSystemInterfacePrivate::eventTime.elapsed(); + return handleMouseEvent<Delivery>(window, time, local, global, state, button, type, mods, source); } -void QWindowSystemInterface::handleFrameStrutMouseEvent(QWindow *window, ulong timestamp, const QPointF &local, const QPointF &global, Qt::MouseButtons b, - Qt::KeyboardModifiers mods, Qt::MouseEventSource source) +QT_DEFINE_QPA_EVENT_HANDLER(bool, handleMouseEvent, QWindow *window, const QPointingDevice *device, + const QPointF &local, const QPointF &global, Qt::MouseButtons state, + Qt::MouseButton button, QEvent::Type type, Qt::KeyboardModifiers mods, + Qt::MouseEventSource source) { - handleFrameStrutMouseEvent(window, timestamp, local, global, b, Qt::NoButton, QEvent::None, mods, source); + unsigned long time = QWindowSystemInterfacePrivate::eventTime.elapsed(); + return handleMouseEvent<Delivery>(window, time, device, local, global, state, button, type, mods, source); } -#endif // QT_DEPRECATED_SINCE(5, 11) -QT_DEFINE_QPA_EVENT_HANDLER(void, handleMouseEvent, QWindow *window, +QT_DEFINE_QPA_EVENT_HANDLER(bool, handleMouseEvent, QWindow *window, ulong timestamp, const QPointF &local, const QPointF &global, Qt::MouseButtons state, Qt::MouseButton button, QEvent::Type type, Qt::KeyboardModifiers mods, Qt::MouseEventSource source) { - unsigned long time = QWindowSystemInterfacePrivate::eventTime.elapsed(); - handleMouseEvent<Delivery>(window, time, local, global, state, button, type, mods, source); + return handleMouseEvent<Delivery>(window, timestamp, QPointingDevice::primaryPointingDevice(), + local, global, state, button, type, mods, source); } -QT_DEFINE_QPA_EVENT_HANDLER(void, handleMouseEvent, QWindow *window, ulong timestamp, +QT_DEFINE_QPA_EVENT_HANDLER(bool, handleMouseEvent, QWindow *window, ulong timestamp, const QPointingDevice *device, const QPointF &local, const QPointF &global, Qt::MouseButtons state, Qt::MouseButton button, QEvent::Type type, Qt::KeyboardModifiers mods, Qt::MouseEventSource source) { - Q_ASSERT_X(type != QEvent::MouseButtonDblClick && type != QEvent::NonClientAreaMouseButtonDblClick, - "QWindowSystemInterface::handleMouseEvent", - "QTBUG-71263: Native double clicks are not implemented."); - auto localPos = QHighDpi::fromNativeLocalPosition(local, window); - auto globalPos = QHighDpi::fromNativePixels(global, window); - QWindowSystemInterfacePrivate::MouseEvent *e = - new QWindowSystemInterfacePrivate::MouseEvent(window, timestamp, localPos, globalPos, - state, mods, button, type, source); - QWindowSystemInterfacePrivate::handleWindowSystemEvent<Delivery>(e); -} + bool isNonClientArea = {}; -void QWindowSystemInterface::handleFrameStrutMouseEvent(QWindow *window, - const QPointF &local, const QPointF &global, - Qt::MouseButtons state, - Qt::MouseButton button, QEvent::Type type, - Qt::KeyboardModifiers mods, - Qt::MouseEventSource source) -{ - const unsigned long time = QWindowSystemInterfacePrivate::eventTime.elapsed(); - handleFrameStrutMouseEvent(window, time, local, global, state, button, type, mods, source); -} + switch (type) { + case QEvent::MouseButtonDblClick: + case QEvent::NonClientAreaMouseButtonDblClick: + Q_ASSERT_X(false, "QWindowSystemInterface::handleMouseEvent", + "QTBUG-71263: Native double clicks are not implemented."); + return false; + case QEvent::MouseMove: + case QEvent::MouseButtonPress: + case QEvent::MouseButtonRelease: + isNonClientArea = false; + break; + case QEvent::NonClientAreaMouseMove: + case QEvent::NonClientAreaMouseButtonPress: + case QEvent::NonClientAreaMouseButtonRelease: + isNonClientArea = true; + break; + default: + Q_UNREACHABLE(); + } -void QWindowSystemInterface::handleFrameStrutMouseEvent(QWindow *window, ulong timestamp, - const QPointF &local, const QPointF &global, - Qt::MouseButtons state, - Qt::MouseButton button, QEvent::Type type, - Qt::KeyboardModifiers mods, - Qt::MouseEventSource source) -{ auto localPos = QHighDpi::fromNativeLocalPosition(local, window); - auto globalPos = QHighDpi::fromNativePixels(global, window); + auto globalPos = QHighDpi::fromNativeGlobalPosition(global, window); - QWindowSystemInterfacePrivate::MouseEvent *e = - new QWindowSystemInterfacePrivate::MouseEvent(window, timestamp, localPos, globalPos, - state, mods, button, type, source, true); - QWindowSystemInterfacePrivate::handleWindowSystemEvent(e); + return handleWindowSystemEvent<QWindowSystemInterfacePrivate::MouseEvent, Delivery>(window, + timestamp, localPos, globalPos, state, mods, button, type, source, isNonClientArea, device); } bool QWindowSystemInterface::handleShortcutEvent(QWindow *window, ulong timestamp, int keyCode, Qt::KeyboardModifiers modifiers, quint32 nativeScanCode, @@ -453,13 +433,11 @@ bool QWindowSystemInterface::handleShortcutEvent(QWindow *window, ulong timestam // key event, so that the target that accepted the shortcut override event can handle it. Note that we only // do this if the shortcut map hasn't found a partial shortcut match yet. If it has, the shortcut can not be // overridden. - QWindowSystemInterfacePrivate::KeyEvent *shortcutOverrideEvent = new QWindowSystemInterfacePrivate::KeyEvent(window, timestamp, - QEvent::ShortcutOverride, keyCode, modifiers, nativeScanCode, nativeVirtualKey, nativeModifiers, text, autorepeat, count); - - { - if (QWindowSystemInterfacePrivate::handleWindowSystemEvent<SynchronousDelivery>(shortcutOverrideEvent)) - return false; - } + bool overridden = handleWindowSystemEvent<QWindowSystemInterfacePrivate::KeyEvent, SynchronousDelivery> + (window,timestamp, QEvent::ShortcutOverride, keyCode, modifiers, nativeScanCode, + nativeVirtualKey, nativeModifiers, text, autorepeat, count); + if (overridden) + return false; } // The shortcut event is dispatched as a QShortcutEvent, not a QKeyEvent, but we use @@ -470,16 +448,16 @@ bool QWindowSystemInterface::handleShortcutEvent(QWindow *window, ulong timestam return shortcutMap.tryShortcut(&keyEvent); #else - Q_UNUSED(window) - Q_UNUSED(timestamp) - Q_UNUSED(keyCode) - Q_UNUSED(modifiers) - Q_UNUSED(nativeScanCode) - Q_UNUSED(nativeVirtualKey) - Q_UNUSED(nativeModifiers) - Q_UNUSED(text) - Q_UNUSED(autorepeat) - Q_UNUSED(count) + Q_UNUSED(window); + Q_UNUSED(timestamp); + Q_UNUSED(keyCode); + Q_UNUSED(modifiers); + Q_UNUSED(nativeScanCode); + Q_UNUSED(nativeVirtualKey); + Q_UNUSED(nativeModifiers); + Q_UNUSED(text); + Q_UNUSED(autorepeat); + Q_UNUSED(count); return false; #endif } @@ -491,25 +469,19 @@ QT_DEFINE_QPA_EVENT_HANDLER(bool, handleKeyEvent, QWindow *window, QEvent::Type QT_DEFINE_QPA_EVENT_HANDLER(bool, handleKeyEvent, QWindow *window, ulong timestamp, QEvent::Type t, int k, Qt::KeyboardModifiers mods, const QString & text, bool autorep, ushort count) { -#if defined(Q_OS_OSX) - if (t == QEvent::KeyPress && QWindowSystemInterface::handleShortcutEvent(window, timestamp, k, mods, 0, 0, 0, text, autorep, count)) - return true; -#endif - - QWindowSystemInterfacePrivate::KeyEvent * e = - new QWindowSystemInterfacePrivate::KeyEvent(window, timestamp, t, k, mods, text, autorep, count); - return QWindowSystemInterfacePrivate::handleWindowSystemEvent<Delivery>(e); + return handleWindowSystemEvent<QWindowSystemInterfacePrivate::KeyEvent, Delivery>(window, + timestamp, t, k, mods, text, autorep, count); } bool QWindowSystemInterface::handleExtendedKeyEvent(QWindow *window, QEvent::Type type, int key, Qt::KeyboardModifiers modifiers, quint32 nativeScanCode, quint32 nativeVirtualKey, quint32 nativeModifiers, const QString& text, bool autorep, - ushort count, bool tryShortcutOverride) + ushort count) { unsigned long time = QWindowSystemInterfacePrivate::eventTime.elapsed(); return handleExtendedKeyEvent(window, time, type, key, modifiers, nativeScanCode, nativeVirtualKey, nativeModifiers, - text, autorep, count, tryShortcutOverride); + text, autorep, count); } bool QWindowSystemInterface::handleExtendedKeyEvent(QWindow *window, ulong timestamp, QEvent::Type type, int key, @@ -517,53 +489,28 @@ bool QWindowSystemInterface::handleExtendedKeyEvent(QWindow *window, ulong times quint32 nativeScanCode, quint32 nativeVirtualKey, quint32 nativeModifiers, const QString& text, bool autorep, - ushort count, bool tryShortcutOverride) + ushort count) { -#if defined(Q_OS_OSX) - if (tryShortcutOverride && type == QEvent::KeyPress && QWindowSystemInterface::handleShortcutEvent(window, - timestamp, key, modifiers, nativeScanCode, nativeVirtualKey, nativeModifiers, text, autorep, count)) { - return true; - } -#else - Q_UNUSED(tryShortcutOverride) -#endif - - QWindowSystemInterfacePrivate::KeyEvent * e = - new QWindowSystemInterfacePrivate::KeyEvent(window, timestamp, type, key, modifiers, - nativeScanCode, nativeVirtualKey, nativeModifiers, text, autorep, count); - return QWindowSystemInterfacePrivate::handleWindowSystemEvent(e); + return handleWindowSystemEvent<QWindowSystemInterfacePrivate::KeyEvent>(window, + timestamp, type, key, modifiers, nativeScanCode, nativeVirtualKey, nativeModifiers, text, autorep, count); } -QWindowSystemInterfacePrivate::WheelEvent::WheelEvent(QWindow *window, ulong time, const QPointF &local, const QPointF &global, QPoint pixelD, - QPoint angleD, int qt4D, Qt::Orientation qt4O, Qt::KeyboardModifiers mods, Qt::ScrollPhase phase, Qt::MouseEventSource src, bool inverted) - : InputEvent(window, time, Wheel, mods), pixelDelta(pixelD), angleDelta(angleD), qt4Delta(qt4D), - qt4Orientation(qt4O), localPos(local), globalPos(global), phase(phase), source(src), inverted(inverted) +bool QWindowSystemInterface::handleWheelEvent(QWindow *window, const QPointF &local, const QPointF &global, QPoint pixelDelta, QPoint angleDelta, Qt::KeyboardModifiers mods, Qt::ScrollPhase phase, Qt::MouseEventSource source) { -} - -#if QT_DEPRECATED_SINCE(5, 10) -void QWindowSystemInterface::handleWheelEvent(QWindow *window, const QPointF &local, const QPointF &global, int d, Qt::Orientation o, Qt::KeyboardModifiers mods) { unsigned long time = QWindowSystemInterfacePrivate::eventTime.elapsed(); -QT_WARNING_PUSH -QT_WARNING_DISABLE_DEPRECATED - handleWheelEvent(window, time, local, global, d, o, mods); -QT_WARNING_POP -} - -void QWindowSystemInterface::handleWheelEvent(QWindow *window, ulong timestamp, const QPointF &local, const QPointF &global, int d, Qt::Orientation o, Qt::KeyboardModifiers mods) -{ - QPoint point = (o == Qt::Vertical) ? QPoint(0, d) : QPoint(d, 0); - handleWheelEvent(window, timestamp, local, global, QPoint(), point, mods); + return handleWheelEvent(window, time, local, global, pixelDelta, angleDelta, mods, phase, source); } -#endif // QT_DEPRECATED_SINCE(5, 10) -void QWindowSystemInterface::handleWheelEvent(QWindow *window, const QPointF &local, const QPointF &global, QPoint pixelDelta, QPoint angleDelta, Qt::KeyboardModifiers mods, Qt::ScrollPhase phase, Qt::MouseEventSource source) +bool QWindowSystemInterface::handleWheelEvent(QWindow *window, ulong timestamp, const QPointF &local, const QPointF &global, QPoint pixelDelta, QPoint angleDelta, Qt::KeyboardModifiers mods, Qt::ScrollPhase phase, + Qt::MouseEventSource source, bool invertedScrolling) { - unsigned long time = QWindowSystemInterfacePrivate::eventTime.elapsed(); - handleWheelEvent(window, time, local, global, pixelDelta, angleDelta, mods, phase, source); + return handleWheelEvent(window, timestamp, QPointingDevice::primaryPointingDevice(), local, global, + pixelDelta, angleDelta, mods, phase, source, invertedScrolling); } -void QWindowSystemInterface::handleWheelEvent(QWindow *window, ulong timestamp, const QPointF &local, const QPointF &global, QPoint pixelDelta, QPoint angleDelta, Qt::KeyboardModifiers mods, Qt::ScrollPhase phase, +bool QWindowSystemInterface::handleWheelEvent(QWindow *window, ulong timestamp, const QPointingDevice *device, + const QPointF &local, const QPointF &global, QPoint pixelDelta, QPoint angleDelta, + Qt::KeyboardModifiers mods, Qt::ScrollPhase phase, Qt::MouseEventSource source, bool invertedScrolling) { // Qt 4 sends two separate wheel events for horizontal and vertical @@ -573,123 +520,117 @@ void QWindowSystemInterface::handleWheelEvent(QWindow *window, ulong timestamp, // In addition high-resolution pixel-based deltas are also supported. // Platforms that does not support these may pass a null point here. // Angle deltas must always be sent in addition to pixel deltas. - QWindowSystemInterfacePrivate::WheelEvent *e; // Pass Qt::ScrollBegin and Qt::ScrollEnd through // even if the wheel delta is null. if (angleDelta.isNull() && phase == Qt::ScrollUpdate) - return; + return false; // Simple case: vertical deltas only: if (angleDelta.y() != 0 && angleDelta.x() == 0) { - e = new QWindowSystemInterfacePrivate::WheelEvent(window, timestamp, QHighDpi::fromNativeLocalPosition(local, window), QHighDpi::fromNativePixels(global, window), pixelDelta, angleDelta, angleDelta.y(), Qt::Vertical, - mods, phase, source, invertedScrolling); - QWindowSystemInterfacePrivate::handleWindowSystemEvent(e); - return; + return handleWindowSystemEvent<QWindowSystemInterfacePrivate::WheelEvent>(window, + timestamp, QHighDpi::fromNativeLocalPosition(local, window), QHighDpi::fromNativeGlobalPosition(global, window), + pixelDelta, angleDelta, angleDelta.y(), Qt::Vertical, mods, phase, source, invertedScrolling, device); } // Simple case: horizontal deltas only: if (angleDelta.y() == 0 && angleDelta.x() != 0) { - e = new QWindowSystemInterfacePrivate::WheelEvent(window, timestamp, QHighDpi::fromNativeLocalPosition(local, window), QHighDpi::fromNativePixels(global, window), pixelDelta, angleDelta, angleDelta.x(), Qt::Horizontal, mods, phase, source, invertedScrolling); - QWindowSystemInterfacePrivate::handleWindowSystemEvent(e); - return; + return handleWindowSystemEvent<QWindowSystemInterfacePrivate::WheelEvent>(window, + timestamp, QHighDpi::fromNativeLocalPosition(local, window), QHighDpi::fromNativeGlobalPosition(global, window), + pixelDelta, angleDelta, angleDelta.x(), Qt::Horizontal, mods, phase, source, invertedScrolling, device); } + bool acceptVert; + bool acceptHorz; // Both horizontal and vertical deltas: Send two wheel events. // The first event contains the Qt 5 pixel and angle delta as points, // and in addition the Qt 4 compatibility vertical angle delta. - e = new QWindowSystemInterfacePrivate::WheelEvent(window, timestamp, QHighDpi::fromNativeLocalPosition(local, window), QHighDpi::fromNativePixels(global, window), pixelDelta, angleDelta, angleDelta.y(), Qt::Vertical, mods, phase, source, invertedScrolling); - QWindowSystemInterfacePrivate::handleWindowSystemEvent(e); + acceptVert = handleWindowSystemEvent<QWindowSystemInterfacePrivate::WheelEvent>(window, + timestamp, QHighDpi::fromNativeLocalPosition(local, window), QHighDpi::fromNativeGlobalPosition(global, window), + pixelDelta, angleDelta, angleDelta.y(), Qt::Vertical, mods, phase, source, invertedScrolling, device); // The second event contains null pixel and angle points and the // Qt 4 compatibility horizontal angle delta. - e = new QWindowSystemInterfacePrivate::WheelEvent(window, timestamp, QHighDpi::fromNativeLocalPosition(local, window), QHighDpi::fromNativePixels(global, window), QPoint(), QPoint(), angleDelta.x(), Qt::Horizontal, mods, phase, source, invertedScrolling); - QWindowSystemInterfacePrivate::handleWindowSystemEvent(e); -} + acceptHorz = handleWindowSystemEvent<QWindowSystemInterfacePrivate::WheelEvent>(window, + timestamp, QHighDpi::fromNativeLocalPosition(local, window), QHighDpi::fromNativeGlobalPosition(global, window), + QPoint(), QPoint(), angleDelta.x(), Qt::Horizontal, mods, phase, source, invertedScrolling, device); -void QWindowSystemInterface::registerTouchDevice(const QTouchDevice *device) -{ - QTouchDevicePrivate::registerDevice(device); -} - -void QWindowSystemInterface::unregisterTouchDevice(const QTouchDevice *device) -{ - QTouchDevicePrivate::unregisterDevice(device); + return acceptVert || acceptHorz; } -bool QWindowSystemInterface::isTouchDeviceRegistered(const QTouchDevice *device) -{ - return QTouchDevicePrivate::isRegistered(device); -} - -static int g_nextPointId = 1; - -// map from device-independent point id (arbitrary) to "Qt point" ids -static QBasicMutex pointIdMapMutex; -typedef QMap<quint64, int> PointIdMap; -Q_GLOBAL_STATIC(PointIdMap, g_pointIdMap) - /*! \internal - This function maps potentially arbitrary point ids \a pointId in the 32 bit - value space to start from 1 and increase incrementally for each touch point - held down. If all touch points are released it will reset the id back to 1 - for the following touch point. - - We can then assume that the touch points ids will never become too large, - and it will then put the device identifier \a deviceId in the upper 8 bits. - This leaves us with max 255 devices, and 16.7M taps without full release - before we run out of value space. + Register a new input \a device. + + It is expected that every platform plugin will discover available input + devices at startup, and whenever a new device is plugged in, if possible. + If that's not possible, then it at least must call this function before + sending an event whose QInputEvent::source() is this device. + + When a device is unplugged, the platform plugin should destroy the + corresponding QInputDevice instance. There is no unregisterInputDevice() + function, because it's enough for the destructor to call + QInputDevicePrivate::unregisterDevice(); while other parts of Qt can + connect to the QObject::destroyed() signal to be notified when a device is + unplugged or otherwise destroyed. */ -static int acquireCombinedPointId(quint8 deviceId, int pointId) +void QWindowSystemInterface::registerInputDevice(const QInputDevice *device) { - const auto locker = qt_scoped_lock(pointIdMapMutex); - - quint64 combinedId64 = (quint64(deviceId) << 32) + pointId; - auto it = g_pointIdMap->constFind(combinedId64); - int uid; - if (it == g_pointIdMap->constEnd()) { - uid = g_nextPointId++; - g_pointIdMap->insert(combinedId64, uid); - } else { - uid = *it; - } - return (deviceId << 24) + uid; + qCDebug(lcQpaInputDevices) << "register" << device; + QInputDevicePrivate::registerDevice(device); } -QList<QTouchEvent::TouchPoint> +/*! + \internal + Convert a list of \l QWindowSystemInterface::TouchPoint \a points to a list + of \e temporary QEventPoint instances, scaled (but not localized) + for delivery to the given \a window. + + This is called from QWindowSystemInterface::handleTouchEvent(): + that is too early to update the QEventPoint instances in QPointingDevice, + because we want those to hold "current" state from the applcation's + point of view. The QWindowSystemInterfacePrivate::TouchEvent, to which + the returned touchpoints will "belong", might go through the queue before + being processed; the application doesn't see the equivalent QTouchEvent + until later on. Therefore the responsibility to update the QEventPoint + instances in QPointingDevice is in QGuiApplication, not here. + + QGuiApplicationPrivate::processMouseEvent() also calls this function + when it synthesizes a touch event from a mouse event. But that's outside + the normal use case. + + It might be better if we change all the platform plugins to create + temporary instances of QEventPoint directly, and remove + QWindowSystemInterface::TouchPoint completely. Then we will no longer need + this function either. But that's only possible as long as QEventPoint + remains a Q_GADGET, not a QObject, so that it continues to be small and + suitable for temporary stack allocation. QEventPoint is a little bigger + than QWindowSystemInterface::TouchPoint, though. +*/ +QList<QEventPoint> QWindowSystemInterfacePrivate::fromNativeTouchPoints(const QList<QWindowSystemInterface::TouchPoint> &points, - const QWindow *window, quint8 deviceId, - QEvent::Type *type) + const QWindow *window, QEvent::Type *type) { - QList<QTouchEvent::TouchPoint> touchPoints; - Qt::TouchPointStates states; - QTouchEvent::TouchPoint p; + QList<QEventPoint> touchPoints; + QEventPoint::States states; - touchPoints.reserve(points.count()); + touchPoints.reserve(points.size()); QList<QWindowSystemInterface::TouchPoint>::const_iterator point = points.constBegin(); QList<QWindowSystemInterface::TouchPoint>::const_iterator end = points.constEnd(); while (point != end) { - p.setId(acquireCombinedPointId(deviceId, point->id)); - if (point->uniqueId >= 0) - p.setUniqueId(point->uniqueId); - p.setPressure(point->pressure); - p.setRotation(point->rotation); + QPointF globalPos = QHighDpi::fromNativePixels(point->area.center(), window); + QEventPoint p(point->id, point->state, globalPos, globalPos); states |= point->state; - p.setState(point->state); - - const QPointF screenPos = point->area.center(); - p.setScreenPos(QHighDpi::fromNativePixels(screenPos, window)); - p.setScreenRect(QHighDpi::fromNativePixels(point->area, window)); + if (point->uniqueId >= 0) + QMutableEventPoint::setUniqueId(p, QPointingDeviceUniqueId::fromNumericId(point->uniqueId)); + QMutableEventPoint::setPressure(p, point->pressure); + QMutableEventPoint::setRotation(p, point->rotation); + QMutableEventPoint::setEllipseDiameters(p, QHighDpi::fromNativePixels(point->area.size(), window)); + QMutableEventPoint::setVelocity(p, QHighDpi::fromNativePixels(point->velocity, window)); - // The local pos and rect are not set, they will be calculated + // The local pos is not set: it will be calculated // when the event gets processed by QGuiApplication. - p.setNormalizedPos(QHighDpi::fromNativePixels(point->normalPosition, window)); - p.setVelocity(QHighDpi::fromNativePixels(point->velocity, window)); - p.setFlags(point->flags); - p.setRawScreenPositions(QHighDpi::fromNativePixels(point->rawPositions, window)); - touchPoints.append(p); ++point; } @@ -697,99 +638,66 @@ QList<QTouchEvent::TouchPoint> // Determine the event type based on the combined point states. if (type) { *type = QEvent::TouchUpdate; - if (states == Qt::TouchPointPressed) + if (states == QEventPoint::State::Pressed) *type = QEvent::TouchBegin; - else if (states == Qt::TouchPointReleased) + else if (states == QEventPoint::State::Released) *type = QEvent::TouchEnd; } - if (states == Qt::TouchPointReleased) { - const auto locker = qt_scoped_lock(pointIdMapMutex); - - // All points on deviceId have been released. - // Remove all points associated with that device from g_pointIdMap. - // (On other devices, some touchpoints might still be pressed. - // But this function is only called with points from one device at a time.) - for (auto it = g_pointIdMap->begin(); it != g_pointIdMap->end();) { - if (it.key() >> 32 == quint64(deviceId)) - it = g_pointIdMap->erase(it); - else - ++it; - } - if (g_pointIdMap->isEmpty()) - g_nextPointId = 1; - } - return touchPoints; } -void QWindowSystemInterfacePrivate::clearPointIdMap() -{ - const auto locker = qt_scoped_lock(pointIdMapMutex); - g_pointIdMap->clear(); - g_nextPointId = 1; -} - -QList<QWindowSystemInterface::TouchPoint> - QWindowSystemInterfacePrivate::toNativeTouchPoints(const QList<QTouchEvent::TouchPoint>& pointList, - const QWindow *window) +QWindowSystemInterface::TouchPoint +QWindowSystemInterfacePrivate::toNativeTouchPoint(const QEventPoint &pt, const QWindow *window) { - QList<QWindowSystemInterface::TouchPoint> newList; - newList.reserve(pointList.size()); - for (const QTouchEvent::TouchPoint &pt : pointList) { - QWindowSystemInterface::TouchPoint p; - p.id = pt.id(); - p.flags = pt.flags(); - p.normalPosition = QHighDpi::toNativeLocalPosition(pt.normalizedPos(), window); - p.area = QHighDpi::toNativePixels(pt.screenRect(), window); - p.pressure = pt.pressure(); - p.state = pt.state(); - p.velocity = QHighDpi::toNativePixels(pt.velocity(), window); - p.rawPositions = QHighDpi::toNativePixels(pt.rawScreenPositions(), window); - newList.append(p); - } - return newList; + QWindowSystemInterface::TouchPoint p; + p.id = pt.id(); + QRectF area(QPointF(), pt.ellipseDiameters()); + area.moveCenter(pt.globalPosition()); + // TODO store ellipseDiameters in QWindowSystemInterface::TouchPoint or just use QEventPoint + p.area = QHighDpi::toNativePixels(area, window); + p.pressure = pt.pressure(); + p.state = pt.state(); + p.velocity = QHighDpi::toNativePixels(pt.velocity(), window); + return p; } -QT_DEFINE_QPA_EVENT_HANDLER(void, handleTouchEvent, QWindow *window, QTouchDevice *device, +QT_DEFINE_QPA_EVENT_HANDLER(bool, handleTouchEvent, QWindow *window, const QPointingDevice *device, const QList<TouchPoint> &points, Qt::KeyboardModifiers mods) { unsigned long time = QWindowSystemInterfacePrivate::eventTime.elapsed(); - handleTouchEvent<Delivery>(window, time, device, points, mods); + return handleTouchEvent<Delivery>(window, time, device, points, mods); } -QT_DEFINE_QPA_EVENT_HANDLER(void, handleTouchEvent, QWindow *window, ulong timestamp, QTouchDevice *device, +QT_DEFINE_QPA_EVENT_HANDLER(bool, handleTouchEvent, QWindow *window, ulong timestamp, const QPointingDevice *device, const QList<TouchPoint> &points, Qt::KeyboardModifiers mods) { if (!points.size()) // Touch events must have at least one point - return; + return false; - if (!QTouchDevicePrivate::isRegistered(device)) // Disallow passing bogus, non-registered devices. - return; + if (!QPointingDevicePrivate::isRegistered(device)) // Disallow passing bogus, non-registered devices. + return false; QEvent::Type type; - QList<QTouchEvent::TouchPoint> touchPoints = - QWindowSystemInterfacePrivate::fromNativeTouchPoints(points, window, QTouchDevicePrivate::get(device)->id, &type); + QList<QEventPoint> touchPoints = + QWindowSystemInterfacePrivate::fromNativeTouchPoints(points, window, &type); - QWindowSystemInterfacePrivate::TouchEvent *e = - new QWindowSystemInterfacePrivate::TouchEvent(window, timestamp, type, device, touchPoints, mods); - QWindowSystemInterfacePrivate::handleWindowSystemEvent<Delivery>(e); + return handleWindowSystemEvent<QWindowSystemInterfacePrivate::TouchEvent, Delivery>(window, + timestamp, type, device, touchPoints, mods); } -QT_DEFINE_QPA_EVENT_HANDLER(void, handleTouchCancelEvent, QWindow *window, QTouchDevice *device, +QT_DEFINE_QPA_EVENT_HANDLER(bool, handleTouchCancelEvent, QWindow *window, const QPointingDevice *device, Qt::KeyboardModifiers mods) { unsigned long time = QWindowSystemInterfacePrivate::eventTime.elapsed(); - handleTouchCancelEvent<Delivery>(window, time, device, mods); + return handleTouchCancelEvent<Delivery>(window, time, device, mods); } -QT_DEFINE_QPA_EVENT_HANDLER(void, handleTouchCancelEvent, QWindow *window, ulong timestamp, QTouchDevice *device, +QT_DEFINE_QPA_EVENT_HANDLER(bool, handleTouchCancelEvent, QWindow *window, ulong timestamp, const QPointingDevice *device, Qt::KeyboardModifiers mods) { - QWindowSystemInterfacePrivate::TouchEvent *e = - new QWindowSystemInterfacePrivate::TouchEvent(window, timestamp, QEvent::TouchCancel, device, - QList<QTouchEvent::TouchPoint>(), mods); - QWindowSystemInterfacePrivate::handleWindowSystemEvent<Delivery>(e); + return handleWindowSystemEvent<QWindowSystemInterfacePrivate::TouchEvent, Delivery>(window, + timestamp, QEvent::TouchCancel, device, QList<QEventPoint>(), mods); } /*! @@ -803,9 +711,9 @@ QT_DEFINE_QPA_EVENT_HANDLER(void, handleTouchCancelEvent, QWindow *window, ulong The screen should be deleted by calling QWindowSystemInterface::handleScreenRemoved(). */ -void QWindowSystemInterface::handleScreenAdded(QPlatformScreen *ps, bool isPrimary) +void QWindowSystemInterface::handleScreenAdded(QPlatformScreen *platformScreen, bool isPrimary) { - QScreen *screen = new QScreen(ps); + QScreen *screen = new QScreen(platformScreen); if (isPrimary) QGuiApplicationPrivate::screen_list.prepend(screen); @@ -813,6 +721,8 @@ void QWindowSystemInterface::handleScreenAdded(QPlatformScreen *ps, bool isPrima QGuiApplicationPrivate::screen_list.append(screen); QGuiApplicationPrivate::resetCachedDevicePixelRatio(); + QHighDpiScaling::updateHighDpiScaling(); + screen->d_func()->updateGeometry(); emit qGuiApp->screenAdded(screen); @@ -830,9 +740,45 @@ void QWindowSystemInterface::handleScreenAdded(QPlatformScreen *ps, bool isPrima */ void QWindowSystemInterface::handleScreenRemoved(QPlatformScreen *platformScreen) { - // Important to keep this order since the QSceen doesn't own the platform screen. - // The QScreen destructor will take care changing the primary screen, so no need here. - delete platformScreen->screen(); + QScreen *screen = platformScreen->screen(); + + // Remove screen + const bool wasPrimary = QGuiApplication::primaryScreen() == screen; + QGuiApplicationPrivate::screen_list.removeOne(screen); + QGuiApplicationPrivate::resetCachedDevicePixelRatio(); + + if (qGuiApp) { + QScreen *newPrimaryScreen = QGuiApplication::primaryScreen(); + if (wasPrimary && newPrimaryScreen) + emit qGuiApp->primaryScreenChanged(newPrimaryScreen); + + // Allow clients to manage windows that are affected by the screen going + // away, before we fall back to moving them to the primary screen. + emit qApp->screenRemoved(screen); + + if (!QGuiApplication::closingDown()) { + bool movingFromVirtualSibling = newPrimaryScreen + && newPrimaryScreen->handle()->virtualSiblings().contains(platformScreen); + + // Move any leftover windows to the primary screen + const auto allWindows = QGuiApplication::allWindows(); + for (QWindow *window : allWindows) { + if (!window->isTopLevel() || window->screen() != screen) + continue; + + const bool wasVisible = window->isVisible(); + window->setScreen(newPrimaryScreen); + + // Re-show window if moved from a virtual sibling screen. Otherwise + // leave it up to the application developer to show the window. + if (movingFromVirtualSibling) + window->setVisible(wasVisible); + } + } + } + + // Important to keep this order since the QSceen doesn't own the platform screen + delete screen; delete platformScreen; } @@ -845,7 +791,7 @@ void QWindowSystemInterface::handleScreenRemoved(QPlatformScreen *platformScreen void QWindowSystemInterface::handlePrimaryScreenChanged(QPlatformScreen *newPrimary) { QScreen *newPrimaryScreen = newPrimary->screen(); - int indexOfScreen = QGuiApplicationPrivate::screen_list.indexOf(newPrimaryScreen); + qsizetype indexOfScreen = QGuiApplicationPrivate::screen_list.indexOf(newPrimaryScreen); Q_ASSERT(indexOfScreen >= 0); if (indexOfScreen == 0) return; @@ -856,56 +802,39 @@ void QWindowSystemInterface::handlePrimaryScreenChanged(QPlatformScreen *newPrim void QWindowSystemInterface::handleScreenOrientationChange(QScreen *screen, Qt::ScreenOrientation orientation) { - QWindowSystemInterfacePrivate::ScreenOrientationEvent *e = - new QWindowSystemInterfacePrivate::ScreenOrientationEvent(screen, orientation); - QWindowSystemInterfacePrivate::handleWindowSystemEvent(e); + handleWindowSystemEvent<QWindowSystemInterfacePrivate::ScreenOrientationEvent>(screen, orientation); } void QWindowSystemInterface::handleScreenGeometryChange(QScreen *screen, const QRect &geometry, const QRect &availableGeometry) { - QWindowSystemInterfacePrivate::ScreenGeometryEvent *e = - new QWindowSystemInterfacePrivate::ScreenGeometryEvent(screen, QHighDpi::fromNativeScreenGeometry(geometry, screen), QHighDpi::fromNative(availableGeometry, screen, geometry.topLeft())); - QWindowSystemInterfacePrivate::handleWindowSystemEvent(e); + handleWindowSystemEvent<QWindowSystemInterfacePrivate::ScreenGeometryEvent>(screen, + QHighDpi::fromNativeScreenGeometry(geometry, screen), QHighDpi::fromNative(availableGeometry, + screen, geometry.topLeft())); } void QWindowSystemInterface::handleScreenLogicalDotsPerInchChange(QScreen *screen, qreal dpiX, qreal dpiY) { + // Keep QHighDpiScaling::m_active in sync with platform screen state, in + // order to make scaling calls made during DPI change use the new state. + // FIXME: Remove when QHighDpiScaling::m_active has been removed. + QHighDpiScaling::updateHighDpiScaling(); + const QDpi effectiveDpi = QPlatformScreen::overrideDpi(QDpi{dpiX, dpiY}); - auto e = new QWindowSystemInterfacePrivate::ScreenLogicalDotsPerInchEvent(screen, effectiveDpi.first, effectiveDpi.second); - QWindowSystemInterfacePrivate::handleWindowSystemEvent(e); + handleWindowSystemEvent<QWindowSystemInterfacePrivate::ScreenLogicalDotsPerInchEvent>(screen, + effectiveDpi.first, effectiveDpi.second); } void QWindowSystemInterface::handleScreenRefreshRateChange(QScreen *screen, qreal newRefreshRate) { - QWindowSystemInterfacePrivate::ScreenRefreshRateEvent *e = - new QWindowSystemInterfacePrivate::ScreenRefreshRateEvent(screen, newRefreshRate); - QWindowSystemInterfacePrivate::handleWindowSystemEvent(e); + handleWindowSystemEvent<QWindowSystemInterfacePrivate::ScreenRefreshRateEvent>(screen, newRefreshRate); } QT_DEFINE_QPA_EVENT_HANDLER(void, handleThemeChange, QWindow *window) { - QWindowSystemInterfacePrivate::ThemeChangeEvent *e = new QWindowSystemInterfacePrivate::ThemeChangeEvent(window); - QWindowSystemInterfacePrivate::handleWindowSystemEvent<Delivery>(e); + handleWindowSystemEvent<QWindowSystemInterfacePrivate::ThemeChangeEvent, Delivery>(window); } #if QT_CONFIG(draganddrop) -#if QT_DEPRECATED_SINCE(5, 11) -QPlatformDragQtResponse QWindowSystemInterface::handleDrag(QWindow *window, const QMimeData *dropData, - const QPoint &p, Qt::DropActions supportedActions) -{ - return QGuiApplicationPrivate::processDrag(window, dropData, p, supportedActions, - QGuiApplication::mouseButtons(), - QGuiApplication::keyboardModifiers()); -} - -QPlatformDropQtResponse QWindowSystemInterface::handleDrop(QWindow *window, const QMimeData *dropData, - const QPoint &p, Qt::DropActions supportedActions) -{ - return QGuiApplicationPrivate::processDrop(window, dropData, p, supportedActions, - QGuiApplication::mouseButtons(), - QGuiApplication::keyboardModifiers()); -} -#endif // QT_DEPRECATED_SINCE(5, 11) /*! Drag and drop events are sent immediately. @@ -937,11 +866,7 @@ QPlatformDropQtResponse QWindowSystemInterface::handleDrop(QWindow *window, cons \note This function can only be called from the GUI thread. */ -#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) bool QWindowSystemInterface::handleNativeEvent(QWindow *window, const QByteArray &eventType, void *message, qintptr *result) -#else -bool QWindowSystemInterface::handleNativeEvent(QWindow *window, const QByteArray &eventType, void *message, long *result) -#endif { return QGuiApplicationPrivate::processNativeEvent(window, eventType, message, result); } @@ -963,110 +888,143 @@ void QWindowSystemInterfacePrivate::TabletEvent::setPlatformSynthesizesMouse(boo platformSynthesizesMouse = v; } -void QWindowSystemInterface::handleTabletEvent(QWindow *window, ulong timestamp, const QPointF &local, const QPointF &global, +bool QWindowSystemInterface::handleTabletEvent(QWindow *window, ulong timestamp, const QPointingDevice *device, + const QPointF &local, const QPointF &global, + Qt::MouseButtons buttons, qreal pressure, int xTilt, int yTilt, + qreal tangentialPressure, qreal rotation, int z, + Qt::KeyboardModifiers modifiers) +{ + return handleWindowSystemEvent<QWindowSystemInterfacePrivate::TabletEvent>(window, + timestamp, + QHighDpi::fromNativeLocalPosition(local, window), + QHighDpi::fromNativeGlobalPosition(global, window), + device, buttons, pressure, + xTilt, yTilt, tangentialPressure, rotation, z, modifiers); +} + +bool QWindowSystemInterface::handleTabletEvent(QWindow *window, const QPointingDevice *device, + const QPointF &local, const QPointF &global, + Qt::MouseButtons buttons, qreal pressure, int xTilt, int yTilt, + qreal tangentialPressure, qreal rotation, int z, + Qt::KeyboardModifiers modifiers) +{ + const ulong time = QWindowSystemInterfacePrivate::eventTime.elapsed(); + return handleTabletEvent(window, time, device, local, global, + buttons, pressure, xTilt, yTilt, tangentialPressure, + rotation, z, modifiers); +} + +bool QWindowSystemInterface::handleTabletEvent(QWindow *window, ulong timestamp, const QPointF &local, const QPointF &global, int device, int pointerType, Qt::MouseButtons buttons, qreal pressure, int xTilt, int yTilt, qreal tangentialPressure, qreal rotation, int z, qint64 uid, Qt::KeyboardModifiers modifiers) { - QWindowSystemInterfacePrivate::TabletEvent *e = - new QWindowSystemInterfacePrivate::TabletEvent(window, timestamp, - QHighDpi::fromNativeLocalPosition(local, window), - QHighDpi::fromNativePixels(global, window), - device, pointerType, buttons, pressure, - xTilt, yTilt, tangentialPressure, rotation, z, uid, modifiers); - QWindowSystemInterfacePrivate::handleWindowSystemEvent(e); + const QPointingDevice *dev = QPointingDevicePrivate::tabletDevice(QInputDevice::DeviceType(device),QPointingDevice::PointerType(pointerType), + QPointingDeviceUniqueId::fromNumericId(uid)); + return handleTabletEvent(window, timestamp, dev, local, global, buttons, pressure, + xTilt, yTilt, tangentialPressure, rotation, z, modifiers); } -void QWindowSystemInterface::handleTabletEvent(QWindow *window, const QPointF &local, const QPointF &global, +bool QWindowSystemInterface::handleTabletEvent(QWindow *window, const QPointF &local, const QPointF &global, int device, int pointerType, Qt::MouseButtons buttons, qreal pressure, int xTilt, int yTilt, qreal tangentialPressure, qreal rotation, int z, qint64 uid, Qt::KeyboardModifiers modifiers) { ulong time = QWindowSystemInterfacePrivate::eventTime.elapsed(); - handleTabletEvent(window, time, local, global, device, pointerType, buttons, pressure, + return handleTabletEvent(window, time, local, global, device, pointerType, buttons, pressure, xTilt, yTilt, tangentialPressure, rotation, z, uid, modifiers); } -#if QT_DEPRECATED_SINCE(5, 10) -void QWindowSystemInterface::handleTabletEvent(QWindow *window, ulong timestamp, bool down, const QPointF &local, const QPointF &global, - int device, int pointerType, qreal pressure, int xTilt, int yTilt, - qreal tangentialPressure, qreal rotation, int z, qint64 uid, - Qt::KeyboardModifiers modifiers) +bool QWindowSystemInterface::handleTabletEnterLeaveProximityEvent(QWindow *window, ulong timestamp, const QPointingDevice *device, + bool inProximity, const QPointF &local, const QPointF &global, + Qt::MouseButtons buttons, int xTilt, int yTilt, + qreal tangentialPressure, qreal rotation, int z, + Qt::KeyboardModifiers modifiers) { - handleTabletEvent(window, timestamp, local, global, device, pointerType, (down ? Qt::LeftButton : Qt::NoButton), pressure, - xTilt, yTilt, tangentialPressure, rotation, z, uid, modifiers); + Q_UNUSED(window); + Q_UNUSED(local); + Q_UNUSED(global); + Q_UNUSED(buttons); + Q_UNUSED(xTilt); + Q_UNUSED(yTilt); + Q_UNUSED(tangentialPressure); + Q_UNUSED(rotation); + Q_UNUSED(z); + Q_UNUSED(modifiers); + return inProximity + ? handleWindowSystemEvent<QWindowSystemInterfacePrivate::TabletEnterProximityEvent>(timestamp, device) + : handleWindowSystemEvent<QWindowSystemInterfacePrivate::TabletLeaveProximityEvent>(timestamp, device); } -void QWindowSystemInterface::handleTabletEvent(QWindow *window, bool down, const QPointF &local, const QPointF &global, - int device, int pointerType, qreal pressure, int xTilt, int yTilt, - qreal tangentialPressure, qreal rotation, int z, qint64 uid, - Qt::KeyboardModifiers modifiers) +bool QWindowSystemInterface::handleTabletEnterLeaveProximityEvent(QWindow *window, const QPointingDevice *device, + bool inProximity, const QPointF &local, const QPointF &global, + Qt::MouseButtons buttons, int xTilt, int yTilt, + qreal tangentialPressure, qreal rotation, int z, + Qt::KeyboardModifiers modifiers) { - handleTabletEvent(window, local, global, device, pointerType, (down ? Qt::LeftButton : Qt::NoButton), pressure, - xTilt, yTilt, tangentialPressure, rotation, z, uid, modifiers); + const ulong time = QWindowSystemInterfacePrivate::eventTime.elapsed(); + return handleTabletEnterLeaveProximityEvent(window, time, device, inProximity, + local, global, buttons, xTilt, yTilt, + tangentialPressure, rotation, z, modifiers); } -#endif // QT_DEPRECATED_SINCE(5, 10) -void QWindowSystemInterface::handleTabletEnterProximityEvent(ulong timestamp, int device, int pointerType, qint64 uid) + +bool QWindowSystemInterface::handleTabletEnterProximityEvent(ulong timestamp, int deviceType, int pointerType, qint64 uid) { - QWindowSystemInterfacePrivate::TabletEnterProximityEvent *e = - new QWindowSystemInterfacePrivate::TabletEnterProximityEvent(timestamp, device, pointerType, uid); - QWindowSystemInterfacePrivate::handleWindowSystemEvent(e); + const QPointingDevice *device = QPointingDevicePrivate::tabletDevice(QInputDevice::DeviceType(deviceType), + QPointingDevice::PointerType(pointerType), + QPointingDeviceUniqueId::fromNumericId(uid)); + return handleWindowSystemEvent<QWindowSystemInterfacePrivate::TabletEnterProximityEvent>(timestamp, device); } -void QWindowSystemInterface::handleTabletEnterProximityEvent(int device, int pointerType, qint64 uid) +void QWindowSystemInterface::handleTabletEnterProximityEvent(int deviceType, int pointerType, qint64 uid) { ulong time = QWindowSystemInterfacePrivate::eventTime.elapsed(); - handleTabletEnterProximityEvent(time, device, pointerType, uid); + handleTabletEnterProximityEvent(time, deviceType, pointerType, uid); } -void QWindowSystemInterface::handleTabletLeaveProximityEvent(ulong timestamp, int device, int pointerType, qint64 uid) +bool QWindowSystemInterface::handleTabletLeaveProximityEvent(ulong timestamp, int deviceType, int pointerType, qint64 uid) { - QWindowSystemInterfacePrivate::TabletLeaveProximityEvent *e = - new QWindowSystemInterfacePrivate::TabletLeaveProximityEvent(timestamp, device, pointerType, uid); - QWindowSystemInterfacePrivate::handleWindowSystemEvent(e); + const QPointingDevice *device = QPointingDevicePrivate::tabletDevice(QInputDevice::DeviceType(deviceType), + QPointingDevice::PointerType(pointerType), + QPointingDeviceUniqueId::fromNumericId(uid)); + return handleWindowSystemEvent<QWindowSystemInterfacePrivate::TabletLeaveProximityEvent>(timestamp, device); } -void QWindowSystemInterface::handleTabletLeaveProximityEvent(int device, int pointerType, qint64 uid) +void QWindowSystemInterface::handleTabletLeaveProximityEvent(int deviceType, int pointerType, qint64 uid) { ulong time = QWindowSystemInterfacePrivate::eventTime.elapsed(); - handleTabletLeaveProximityEvent(time, device, pointerType, uid); + handleTabletLeaveProximityEvent(time, deviceType, pointerType, uid); } #ifndef QT_NO_GESTURES -void QWindowSystemInterface::handleGestureEvent(QWindow *window, QTouchDevice *device, ulong timestamp, Qt::NativeGestureType type, - QPointF &local, QPointF &global) +bool QWindowSystemInterface::handleGestureEvent(QWindow *window, ulong timestamp, const QPointingDevice *device, + Qt::NativeGestureType type, const QPointF &local, const QPointF &global, int fingerCount) { - QWindowSystemInterfacePrivate::GestureEvent *e = - new QWindowSystemInterfacePrivate::GestureEvent(window, timestamp, type, device, local, global); - QWindowSystemInterfacePrivate::handleWindowSystemEvent(e); + return handleGestureEventWithValueAndDelta(window, timestamp, device, type, {}, {}, local, global, fingerCount); } -void QWindowSystemInterface::handleGestureEventWithRealValue(QWindow *window, QTouchDevice *device, ulong timestamp, Qt::NativeGestureType type, - qreal value, QPointF &local, QPointF &global) +bool QWindowSystemInterface::handleGestureEventWithRealValue(QWindow *window, ulong timestamp, const QPointingDevice *device, + Qt::NativeGestureType type, qreal value, const QPointF &local, const QPointF &global, int fingerCount) { - QWindowSystemInterfacePrivate::GestureEvent *e = - new QWindowSystemInterfacePrivate::GestureEvent(window, timestamp, type, device, local, global); - e->realValue = value; - QWindowSystemInterfacePrivate::handleWindowSystemEvent(e); + return handleGestureEventWithValueAndDelta(window, timestamp, device, type, value, {}, local, global, fingerCount); } -void QWindowSystemInterface::handleGestureEventWithSequenceIdAndValue(QWindow *window, QTouchDevice *device, ulong timestamp, Qt::NativeGestureType type, - ulong sequenceId, quint64 value, QPointF &local, QPointF &global) +bool QWindowSystemInterface::handleGestureEventWithValueAndDelta(QWindow *window, ulong timestamp, const QPointingDevice *device, + Qt::NativeGestureType type, qreal value, const QPointF &delta, + const QPointF &local, const QPointF &global, int fingerCount) { - QWindowSystemInterfacePrivate::GestureEvent *e = - new QWindowSystemInterfacePrivate::GestureEvent(window, timestamp, type, device, local, global); - e->sequenceId = sequenceId; - e->intValue = value; - QWindowSystemInterfacePrivate::handleWindowSystemEvent(e); + auto localPos = QHighDpi::fromNativeLocalPosition(local, window); + auto globalPos = QHighDpi::fromNativeGlobalPosition(global, window); + + return handleWindowSystemEvent<QWindowSystemInterfacePrivate::GestureEvent>(window, + timestamp, type, device, fingerCount, localPos, globalPos, value, delta); } #endif // QT_NO_GESTURES void QWindowSystemInterface::handlePlatformPanelEvent(QWindow *w) { - QWindowSystemInterfacePrivate::PlatformPanelEvent *e = - new QWindowSystemInterfacePrivate::PlatformPanelEvent(w); - QWindowSystemInterfacePrivate::handleWindowSystemEvent(e); + handleWindowSystemEvent<QWindowSystemInterfacePrivate::PlatformPanelEvent>(w); } #ifndef QT_NO_CONTEXTMENU @@ -1074,19 +1032,16 @@ void QWindowSystemInterface::handleContextMenuEvent(QWindow *window, bool mouseT const QPoint &pos, const QPoint &globalPos, Qt::KeyboardModifiers modifiers) { - QWindowSystemInterfacePrivate::ContextMenuEvent *e = - new QWindowSystemInterfacePrivate::ContextMenuEvent(window, mouseTriggered, pos, - globalPos, modifiers); - QWindowSystemInterfacePrivate::handleWindowSystemEvent(e); + handleWindowSystemEvent<QWindowSystemInterfacePrivate::ContextMenuEvent>(window, + mouseTriggered, pos, globalPos, modifiers); } #endif #if QT_CONFIG(whatsthis) void QWindowSystemInterface::handleEnterWhatsThisEvent() { - QWindowSystemInterfacePrivate::WindowSystemEvent *e = - new QWindowSystemInterfacePrivate::WindowSystemEvent(QWindowSystemInterfacePrivate::EnterWhatsThisMode); - QWindowSystemInterfacePrivate::handleWindowSystemEvent(e); + handleWindowSystemEvent<QWindowSystemInterfacePrivate::WindowSystemEvent>( + QWindowSystemInterfacePrivate::EnterWhatsThisMode); } #endif @@ -1108,7 +1063,7 @@ Q_GUI_EXPORT QDebug operator<<(QDebug dbg, const QWindowSystemInterface::TouchPo */ bool QWindowSystemInterface::flushWindowSystemEvents(QEventLoop::ProcessEventsFlags flags) { - const int count = QWindowSystemInterfacePrivate::windowSystemEventQueue.count(); + const qsizetype count = QWindowSystemInterfacePrivate::windowSystemEventQueue.count(); if (!count) return false; if (!QGuiApplication::instance()) { @@ -1122,8 +1077,7 @@ bool QWindowSystemInterface::flushWindowSystemEvents(QEventLoop::ProcessEventsFl // Post a FlushEvents event which will trigger a call back to // deferredFlushWindowSystemEvents from the Gui thread. QMutexLocker locker(&QWindowSystemInterfacePrivate::flushEventMutex); - QWindowSystemInterfacePrivate::FlushEventsEvent *e = new QWindowSystemInterfacePrivate::FlushEventsEvent(flags); - QWindowSystemInterfacePrivate::handleWindowSystemEvent<AsynchronousDelivery>(e); + handleWindowSystemEvent<QWindowSystemInterfacePrivate::FlushEventsEvent, AsynchronousDelivery>(flags); QWindowSystemInterfacePrivate::eventsFlushed.wait(&QWindowSystemInterfacePrivate::flushEventMutex); } else { sendWindowSystemEvents(flags); @@ -1145,15 +1099,10 @@ bool QWindowSystemInterface::sendWindowSystemEvents(QEventLoop::ProcessEventsFla int nevents = 0; while (QWindowSystemInterfacePrivate::windowSystemEventsQueued()) { - QWindowSystemInterfacePrivate::WindowSystemEvent *event = nullptr; - - if (QWindowSystemInterfacePrivate::platformFiltersEvents) { - event = QWindowSystemInterfacePrivate::getWindowSystemEvent(); - } else { - event = flags & QEventLoop::ExcludeUserInputEvents ? + QWindowSystemInterfacePrivate::WindowSystemEvent *event = + flags & QEventLoop::ExcludeUserInputEvents ? QWindowSystemInterfacePrivate::getNonUserInputWindowSystemEvent() : QWindowSystemInterfacePrivate::getWindowSystemEvent(); - } if (!event) break; @@ -1192,21 +1141,6 @@ bool QWindowSystemInterface::nonUserInputEventsQueued() return QWindowSystemInterfacePrivate::nonUserInputEventsQueued(); } -/*! - Platforms that implement UserInputEvent filtering at native event level must - set this property to \c true. The default is \c false, which means that event - filtering logic is handled by QWindowSystemInterface. Doing the filtering in - platform plugins is necessary when supporting AbstractEventDispatcher::filterNativeEvent(), - which should respect flags that were passed to event dispatcher's processEvents() - call. - - \since 5.12 -*/ -void QWindowSystemInterface::setPlatformFiltersEvents(bool enable) -{ - QWindowSystemInterfacePrivate::platformFiltersEvents = enable; -} - // --------------------- QtTestLib support --------------------- // The following functions are used by testlib, and need to be synchronous to avoid @@ -1218,30 +1152,24 @@ Q_GUI_EXPORT void qt_handleMouseEvent(QWindow *window, const QPointF &local, con Qt::MouseButtons state, Qt::MouseButton button, QEvent::Type type, Qt::KeyboardModifiers mods, int timestamp) { - const qreal factor = QHighDpiScaling::factor(window); - QWindowSystemInterface::handleMouseEvent<QWindowSystemInterface::SynchronousDelivery>(window, - timestamp, local * factor, global * factor, state, button, type, mods); -} - -// Wrapper for compatibility with Qt < 5.11 -// ### Qt6: Remove -Q_GUI_EXPORT void qt_handleMouseEvent(QWindow *window, const QPointF &local, const QPointF &global, - Qt::MouseButtons b, Qt::KeyboardModifiers mods, int timestamp) -{ - const qreal factor = QHighDpiScaling::factor(window); + QPointF nativeLocal = QHighDpi::toNativeLocalPosition(local, window); + QPointF nativeGlobal = QHighDpi::toNativeGlobalPosition(global, window); QWindowSystemInterface::handleMouseEvent<QWindowSystemInterface::SynchronousDelivery>(window, - timestamp, local * factor, global * factor, b, Qt::NoButton, QEvent::None, mods); -} - -// Wrapper for compatibility with Qt < 5.6 -// ### Qt6: Remove -Q_GUI_EXPORT void qt_handleMouseEvent(QWindow *w, const QPointF &local, const QPointF &global, Qt::MouseButtons b, Qt::KeyboardModifiers mods = Qt::NoModifier) -{ - qt_handleMouseEvent(w, local, global, b, mods, QWindowSystemInterfacePrivate::eventTime.elapsed()); + timestamp, nativeLocal, nativeGlobal, state, button, type, mods); } +/* + Used by QTest::simulateEvent() to synthesize key events during testing +*/ Q_GUI_EXPORT void qt_handleKeyEvent(QWindow *window, QEvent::Type t, int k, Qt::KeyboardModifiers mods, const QString & text = QString(), bool autorep = false, ushort count = 1) { +#if defined(Q_OS_MACOS) + // FIXME: Move into QTest::simulateEvent() and align with QGuiApplicationPrivate::processKeyEvent() + auto timestamp = QWindowSystemInterfacePrivate::eventTime.elapsed(); + if (t == QEvent::KeyPress && QWindowSystemInterface::handleShortcutEvent(window, timestamp, k, mods, 0, 0, 0, text, autorep, count)) + return; +#endif + QWindowSystemInterface::handleKeyEvent<QWindowSystemInterface::SynchronousDelivery>(window, t, k, mods, text, autorep, count); } @@ -1271,35 +1199,51 @@ Q_GUI_EXPORT bool qt_sendShortcutOverrideEvent(QObject *o, ulong timestamp, int // Then as QShortcutEvent return shortcutMap.tryShortcut(&qevent); #else - Q_UNUSED(o) - Q_UNUSED(timestamp) - Q_UNUSED(k) - Q_UNUSED(mods) - Q_UNUSED(text) - Q_UNUSED(autorep) - Q_UNUSED(count) + Q_UNUSED(o); + Q_UNUSED(timestamp); + Q_UNUSED(k); + Q_UNUSED(mods); + Q_UNUSED(text); + Q_UNUSED(autorep); + Q_UNUSED(count); return false; #endif } +Q_GUI_EXPORT void qt_handleWheelEvent(QWindow *window, const QPointF &local, const QPointF &global, + QPoint pixelDelta, QPoint angleDelta, Qt::KeyboardModifiers mods, + Qt::ScrollPhase phase) +{ + QWindowSystemInterface::handleWheelEvent(window, local, global, pixelDelta, angleDelta, mods, phase); +} + namespace QTest { - Q_GUI_EXPORT QTouchDevice * createTouchDevice(QTouchDevice::DeviceType devType = QTouchDevice::TouchScreen) + Q_GUI_EXPORT QPointingDevice * createTouchDevice(QInputDevice::DeviceType devType, + QInputDevice::Capabilities caps) { - QTouchDevice *ret = new QTouchDevice(); - ret->setType(devType); - QWindowSystemInterface::registerTouchDevice(ret); + static qint64 nextId = 0x100000000; + QPointingDevice *ret = new QPointingDevice("test touch device"_L1, nextId++, + devType, QPointingDevice::PointerType::Finger, + caps, 8, 0); + QWindowSystemInterface::registerInputDevice(ret); return ret; } } -Q_GUI_EXPORT void qt_handleTouchEvent(QWindow *window, QTouchDevice *device, - const QList<QTouchEvent::TouchPoint> &points, - Qt::KeyboardModifiers mods = Qt::NoModifier) +Q_GUI_EXPORT bool qt_handleTouchEventv2(QWindow *window, const QPointingDevice *device, + const QList<QEventPoint> &points, + Qt::KeyboardModifiers mods) { - QWindowSystemInterface::handleTouchEvent<QWindowSystemInterface::SynchronousDelivery>(window, device, + return QWindowSystemInterface::handleTouchEvent<QWindowSystemInterface::SynchronousDelivery>(window, device, QWindowSystemInterfacePrivate::toNativeTouchPoints(points, window), mods); } +Q_GUI_EXPORT void qt_handleTouchEvent(QWindow *window, const QPointingDevice *device, + const QList<QEventPoint> &points, + Qt::KeyboardModifiers mods) +{ + qt_handleTouchEventv2(window, device, points, mods); +} QT_END_NAMESPACE |