diff options
Diffstat (limited to 'src/gui/kernel/qwindowsysteminterface.cpp')
-rw-r--r-- | src/gui/kernel/qwindowsysteminterface.cpp | 572 |
1 files changed, 270 insertions, 302 deletions
diff --git a/src/gui/kernel/qwindowsysteminterface.cpp b/src/gui/kernel/qwindowsysteminterface.cpp index 2f26d38dde..1875594300 100644 --- a/src/gui/kernel/qwindowsysteminterface.cpp +++ b/src/gui/kernel/qwindowsysteminterface.cpp @@ -1,47 +1,13 @@ -/**************************************************************************** -** -** Copyright (C) 2020 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/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; + Q_LOGGING_CATEGORY(lcQpaInputDevices, "qt.qpa.input.devices") -QElapsedTimer QWindowSystemInterfacePrivate::eventTime; +Q_CONSTINIT QElapsedTimer QWindowSystemInterfacePrivate::eventTime; bool QWindowSystemInterfacePrivate::synchronousWindowSystemEvents = 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::fromNativeGlobalPosition(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) @@ -308,7 +297,6 @@ QT_DEFINE_QPA_EVENT_HANDLER(void, handleGeometryChange, QWindow *window, const Q { Q_ASSERT(window); const auto newRectDi = QHighDpi::fromNativeWindowGeometry(newRect, window); - auto e = new QWindowSystemInterfacePrivate::GeometryChangeEvent(window, newRectDi); if (window->handle()) { // Persist the new geometry so that QWindow::geometry() can be queried in the resize event window->handle()->QPlatformWindow::setGeometry(newRect); @@ -316,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) @@ -346,24 +334,21 @@ QWindowSystemInterfacePrivate::ExposeEvent::ExposeEvent(QWindow *window, const Q */ QT_DEFINE_QPA_EVENT_HANDLER(bool, handleExposeEvent, QWindow *window, const QRegion ®ion) { - QWindowSystemInterfacePrivate::ExposeEvent *e = - new QWindowSystemInterfacePrivate::ExposeEvent(window, QHighDpi::fromNativeLocalExposedRegion(region, window)); - return 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) { - QWindowSystemInterfacePrivate::PaintEvent *e = - new QWindowSystemInterfacePrivate::PaintEvent(window, QHighDpi::fromNativeLocalExposedRegion(region, window)); - return QWindowSystemInterfacePrivate::handleWindowSystemEvent<Delivery>(e); + 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); } /*! @@ -404,65 +389,34 @@ QT_DEFINE_QPA_EVENT_HANDLER(bool, handleMouseEvent, QWindow *window, ulong times 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::fromNativeGlobalPosition(global, window); - QWindowSystemInterfacePrivate::MouseEvent *e = - new QWindowSystemInterfacePrivate::MouseEvent(window, timestamp, localPos, globalPos, - state, mods, button, type, source, false, device); - return QWindowSystemInterfacePrivate::handleWindowSystemEvent<Delivery>(e); -} + bool isNonClientArea = {}; -bool 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(); - return handleFrameStrutMouseEvent(window, time, local, global, state, button, type, mods, source); -} - -bool QWindowSystemInterface::handleFrameStrutMouseEvent(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) -{ - const unsigned long time = QWindowSystemInterfacePrivate::eventTime.elapsed(); - return handleFrameStrutMouseEvent(window, time, device, local, global, state, button, type, mods, source); -} - -bool 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) -{ - return handleFrameStrutMouseEvent(window, timestamp, QPointingDevice::primaryPointingDevice(), - 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(); + } -bool QWindowSystemInterface::handleFrameStrutMouseEvent(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) -{ auto localPos = QHighDpi::fromNativeLocalPosition(local, window); auto globalPos = QHighDpi::fromNativeGlobalPosition(global, window); - QWindowSystemInterfacePrivate::MouseEvent *e = - new QWindowSystemInterfacePrivate::MouseEvent(window, timestamp, localPos, globalPos, - state, mods, button, type, source, true, device); - return 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, @@ -479,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 @@ -517,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_MACOS) - 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, @@ -543,21 +489,10 @@ 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_MACOS) - 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); } bool QWindowSystemInterface::handleWheelEvent(QWindow *window, const QPointF &local, const QPointF &global, QPoint pixelDelta, QPoint angleDelta, Qt::KeyboardModifiers mods, Qt::ScrollPhase phase, Qt::MouseEventSource source) @@ -585,7 +520,6 @@ bool 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. @@ -594,16 +528,16 @@ bool QWindowSystemInterface::handleWheelEvent(QWindow *window, ulong timestamp, // Simple case: vertical deltas only: if (angleDelta.y() != 0 && angleDelta.x() == 0) { - e = new QWindowSystemInterfacePrivate::WheelEvent(window, timestamp, QHighDpi::fromNativeLocalPosition(local, window), QHighDpi::fromNativeGlobalPosition(global, window), - pixelDelta, angleDelta, angleDelta.y(), Qt::Vertical, mods, phase, source, invertedScrolling, device); - return QWindowSystemInterfacePrivate::handleWindowSystemEvent(e); + 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::fromNativeGlobalPosition(global, window), - pixelDelta, angleDelta, angleDelta.x(), Qt::Horizontal, mods, phase, source, invertedScrolling, device); - return QWindowSystemInterfacePrivate::handleWindowSystemEvent(e); + 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; @@ -611,15 +545,16 @@ bool QWindowSystemInterface::handleWheelEvent(QWindow *window, ulong timestamp, // 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::fromNativeGlobalPosition(global, window), - pixelDelta, angleDelta, angleDelta.y(), Qt::Vertical, mods, phase, source, invertedScrolling, device); - acceptVert = 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::fromNativeGlobalPosition(global, window), - QPoint(), QPoint(), angleDelta.x(), Qt::Horizontal, mods, phase, source, invertedScrolling, device); - acceptHorz = 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); + return acceptVert || acceptHorz; } @@ -679,19 +614,19 @@ QList<QEventPoint> 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) { QPointF globalPos = QHighDpi::fromNativePixels(point->area.center(), window); - QMutableEventPoint p(point->id, point->state, globalPos, globalPos); + QEventPoint p(point->id, point->state, globalPos, globalPos); states |= point->state; if (point->uniqueId >= 0) - p.setUniqueId(QPointingDeviceUniqueId::fromNumericId(point->uniqueId)); - p.setPressure(point->pressure); - p.setRotation(point->rotation); - p.setEllipseDiameters(QHighDpi::fromNativePixels(point->area.size(), window)); - p.setVelocity(QHighDpi::fromNativePixels(point->velocity, window)); + 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 is not set: it will be calculated // when the event gets processed by QGuiApplication. @@ -746,9 +681,9 @@ QT_DEFINE_QPA_EVENT_HANDLER(bool, handleTouchEvent, QWindow *window, ulong times QEvent::Type type; QList<QEventPoint> touchPoints = QWindowSystemInterfacePrivate::fromNativeTouchPoints(points, window, &type); - QWindowSystemInterfacePrivate::TouchEvent *e = - new QWindowSystemInterfacePrivate::TouchEvent(window, timestamp, type, device, touchPoints, mods); - return QWindowSystemInterfacePrivate::handleWindowSystemEvent<Delivery>(e); + + return handleWindowSystemEvent<QWindowSystemInterfacePrivate::TouchEvent, Delivery>(window, + timestamp, type, device, touchPoints, mods); } QT_DEFINE_QPA_EVENT_HANDLER(bool, handleTouchCancelEvent, QWindow *window, const QPointingDevice *device, @@ -761,10 +696,8 @@ QT_DEFINE_QPA_EVENT_HANDLER(bool, handleTouchCancelEvent, QWindow *window, const 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<QEventPoint>(), mods); - return QWindowSystemInterfacePrivate::handleWindowSystemEvent<Delivery>(e); + return handleWindowSystemEvent<QWindowSystemInterfacePrivate::TouchEvent, Delivery>(window, + timestamp, QEvent::TouchCancel, device, QList<QEventPoint>(), mods); } /*! @@ -778,9 +711,9 @@ QT_DEFINE_QPA_EVENT_HANDLER(bool, 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); @@ -788,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); @@ -805,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; } @@ -820,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; @@ -831,36 +802,36 @@ 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) @@ -895,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); } @@ -927,13 +894,12 @@ bool QWindowSystemInterface::handleTabletEvent(QWindow *window, ulong timestamp, qreal tangentialPressure, qreal rotation, int z, Qt::KeyboardModifiers modifiers) { - QWindowSystemInterfacePrivate::TabletEvent *e = - new QWindowSystemInterfacePrivate::TabletEvent(window, timestamp, - QHighDpi::fromNativeLocalPosition(local, window), - QHighDpi::fromNativeGlobalPosition(global, window), - device, buttons, pressure, - xTilt, yTilt, tangentialPressure, rotation, z, modifiers); - return QWindowSystemInterfacePrivate::handleWindowSystemEvent(e); + 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, @@ -985,15 +951,9 @@ bool QWindowSystemInterface::handleTabletEnterLeaveProximityEvent(QWindow *windo Q_UNUSED(rotation); Q_UNUSED(z); Q_UNUSED(modifiers); - if (inProximity) { - QWindowSystemInterfacePrivate::TabletEnterProximityEvent *e = - new QWindowSystemInterfacePrivate::TabletEnterProximityEvent(timestamp, device); - return QWindowSystemInterfacePrivate::handleWindowSystemEvent(e); - } else { - QWindowSystemInterfacePrivate::TabletLeaveProximityEvent *e = - new QWindowSystemInterfacePrivate::TabletLeaveProximityEvent(timestamp, device); - return QWindowSystemInterfacePrivate::handleWindowSystemEvent(e); - } + return inProximity + ? handleWindowSystemEvent<QWindowSystemInterfacePrivate::TabletEnterProximityEvent>(timestamp, device) + : handleWindowSystemEvent<QWindowSystemInterfacePrivate::TabletLeaveProximityEvent>(timestamp, device); } bool QWindowSystemInterface::handleTabletEnterLeaveProximityEvent(QWindow *window, const QPointingDevice *device, @@ -1014,9 +974,7 @@ bool QWindowSystemInterface::handleTabletEnterProximityEvent(ulong timestamp, in const QPointingDevice *device = QPointingDevicePrivate::tabletDevice(QInputDevice::DeviceType(deviceType), QPointingDevice::PointerType(pointerType), QPointingDeviceUniqueId::fromNumericId(uid)); - QWindowSystemInterfacePrivate::TabletEnterProximityEvent *e = - new QWindowSystemInterfacePrivate::TabletEnterProximityEvent(timestamp, device); - return QWindowSystemInterfacePrivate::handleWindowSystemEvent(e); + return handleWindowSystemEvent<QWindowSystemInterfacePrivate::TabletEnterProximityEvent>(timestamp, device); } void QWindowSystemInterface::handleTabletEnterProximityEvent(int deviceType, int pointerType, qint64 uid) @@ -1030,9 +988,7 @@ bool QWindowSystemInterface::handleTabletLeaveProximityEvent(ulong timestamp, in const QPointingDevice *device = QPointingDevicePrivate::tabletDevice(QInputDevice::DeviceType(deviceType), QPointingDevice::PointerType(pointerType), QPointingDeviceUniqueId::fromNumericId(uid)); - QWindowSystemInterfacePrivate::TabletLeaveProximityEvent *e = - new QWindowSystemInterfacePrivate::TabletLeaveProximityEvent(timestamp, device); - return QWindowSystemInterfacePrivate::handleWindowSystemEvent(e); + return handleWindowSystemEvent<QWindowSystemInterfacePrivate::TabletLeaveProximityEvent>(timestamp, device); } void QWindowSystemInterface::handleTabletLeaveProximityEvent(int deviceType, int pointerType, qint64 uid) @@ -1043,39 +999,32 @@ void QWindowSystemInterface::handleTabletLeaveProximityEvent(int deviceType, int #ifndef QT_NO_GESTURES bool QWindowSystemInterface::handleGestureEvent(QWindow *window, ulong timestamp, const QPointingDevice *device, - Qt::NativeGestureType type, const QPointF &local, const QPointF &global) + Qt::NativeGestureType type, const QPointF &local, const QPointF &global, int fingerCount) { - QWindowSystemInterfacePrivate::GestureEvent *e = - new QWindowSystemInterfacePrivate::GestureEvent(window, timestamp, type, device, local, global); - return QWindowSystemInterfacePrivate::handleWindowSystemEvent(e); + return handleGestureEventWithValueAndDelta(window, timestamp, device, type, {}, {}, local, global, fingerCount); } bool QWindowSystemInterface::handleGestureEventWithRealValue(QWindow *window, ulong timestamp, const QPointingDevice *device, - Qt::NativeGestureType type, qreal value, const QPointF &local, const QPointF &global) + 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; - return QWindowSystemInterfacePrivate::handleWindowSystemEvent(e); + return handleGestureEventWithValueAndDelta(window, timestamp, device, type, value, {}, local, global, fingerCount); } -bool QWindowSystemInterface::handleGestureEventWithSequenceIdAndValue(QWindow *window, ulong timestamp, const QPointingDevice *device, - Qt::NativeGestureType type, ulong sequenceId, quint64 value, - const QPointF &local, const 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; - return 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 @@ -1083,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 @@ -1117,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()) { @@ -1131,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); @@ -1213,8 +1158,18 @@ Q_GUI_EXPORT void qt_handleMouseEvent(QWindow *window, const QPointF &local, con 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); } @@ -1255,13 +1210,20 @@ Q_GUI_EXPORT bool qt_sendShortcutOverrideEvent(QObject *o, ulong timestamp, int #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 QPointingDevice * createTouchDevice(QInputDevice::DeviceType devType = QInputDevice::DeviceType::TouchScreen, - QInputDevice::Capabilities caps = QInputDevice::Capability::Position) + Q_GUI_EXPORT QPointingDevice * createTouchDevice(QInputDevice::DeviceType devType, + QInputDevice::Capabilities caps) { static qint64 nextId = 0x100000000; - QPointingDevice *ret = new QPointingDevice(QLatin1String("test touch device"), nextId++, + QPointingDevice *ret = new QPointingDevice("test touch device"_L1, nextId++, devType, QPointingDevice::PointerType::Finger, caps, 8, 0); QWindowSystemInterface::registerInputDevice(ret); @@ -1269,13 +1231,19 @@ namespace QTest } } -Q_GUI_EXPORT void qt_handleTouchEvent(QWindow *window, const QPointingDevice *device, +Q_GUI_EXPORT bool qt_handleTouchEventv2(QWindow *window, const QPointingDevice *device, const QList<QEventPoint> &points, - Qt::KeyboardModifiers mods = Qt::NoModifier) + 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 |