diff options
Diffstat (limited to 'src/plugins/platforms/windows/qwindowsmousehandler.cpp')
-rw-r--r-- | src/plugins/platforms/windows/qwindowsmousehandler.cpp | 159 |
1 files changed, 56 insertions, 103 deletions
diff --git a/src/plugins/platforms/windows/qwindowsmousehandler.cpp b/src/plugins/platforms/windows/qwindowsmousehandler.cpp index b776efc942..9af9fba408 100644 --- a/src/plugins/platforms/windows/qwindowsmousehandler.cpp +++ b/src/plugins/platforms/windows/qwindowsmousehandler.cpp @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the plugins of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include "qwindowsmousehandler.h" #include "qwindowskeymapper.h" @@ -47,12 +11,13 @@ #include <qpa/qwindowsysteminterface.h> #include <QtGui/qguiapplication.h> #include <QtGui/qscreen.h> -#include <QtGui/qtouchdevice.h> +#include <QtGui/qpointingdevice.h> #include <QtGui/qwindow.h> #include <QtGui/qcursor.h> #include <QtCore/qdebug.h> -#include <QtCore/qscopedpointer.h> + +#include <memory> #include <windowsx.h> @@ -117,27 +82,6 @@ static inline void compressMouseMove(MSG *msg) } } -static inline QTouchDevice *createTouchDevice() -{ - const int digitizers = GetSystemMetrics(SM_DIGITIZER); - if (!(digitizers & (NID_INTEGRATED_TOUCH | NID_EXTERNAL_TOUCH))) - return nullptr; - const int tabletPc = GetSystemMetrics(SM_TABLETPC); - const int maxTouchPoints = GetSystemMetrics(SM_MAXIMUMTOUCHES); - qCDebug(lcQpaEvents) << "Digitizers:" << Qt::hex << Qt::showbase << (digitizers & ~NID_READY) - << "Ready:" << (digitizers & NID_READY) << Qt::dec << Qt::noshowbase - << "Tablet PC:" << tabletPc << "Max touch points:" << maxTouchPoints; - auto *result = new QTouchDevice; - result->setType(digitizers & NID_INTEGRATED_TOUCH - ? QTouchDevice::TouchScreen : QTouchDevice::TouchPad); - QTouchDevice::Capabilities capabilities = QTouchDevice::Position | QTouchDevice::Area | QTouchDevice::NormalizedPosition; - if (result->type() == QTouchDevice::TouchPad) - capabilities |= QTouchDevice::MouseEmulation; - result->setCapabilities(capabilities); - result->setMaximumTouchPoints(maxTouchPoints); - return result; -} - /*! \class QWindowsMouseHandler \brief Windows mouse handler @@ -145,16 +89,16 @@ static inline QTouchDevice *createTouchDevice() Dispatches mouse and touch events. Separate for code cleanliness. \internal - \ingroup qt-lighthouse-win */ QWindowsMouseHandler::QWindowsMouseHandler() = default; -QTouchDevice *QWindowsMouseHandler::ensureTouchDevice() +const QPointingDevice *QWindowsMouseHandler::primaryMouse() { - if (!m_touchDevice) - m_touchDevice = createTouchDevice(); - return m_touchDevice; + static QPointer<const QPointingDevice> result; + if (!result) + result = QPointingDevice::primaryPointingDevice(); + return result; } void QWindowsMouseHandler::clearEvents() @@ -172,7 +116,7 @@ Qt::MouseButtons QWindowsMouseHandler::queryMouseButtons() if (GetAsyncKeyState(VK_RBUTTON) < 0) result |= mouseSwapped ? Qt::LeftButton : Qt::RightButton; if (GetAsyncKeyState(VK_MBUTTON) < 0) - result |= Qt::MidButton; + result |= Qt::MiddleButton; if (GetAsyncKeyState(VK_XBUTTON1) < 0) result |= Qt::XButton1; if (GetAsyncKeyState(VK_XBUTTON2) < 0) @@ -180,7 +124,7 @@ Qt::MouseButtons QWindowsMouseHandler::queryMouseButtons() return result; } -static QPoint lastMouseMovePos; +Q_CONSTINIT static QPoint lastMouseMovePos; namespace { struct MouseEvent { @@ -216,11 +160,11 @@ static inline MouseEvent eventFromMsg(const MSG &msg) case WM_LBUTTONDBLCLK: // Qt QPA does not handle double clicks, send as press return {QEvent::MouseButtonPress, Qt::LeftButton}; case WM_MBUTTONDOWN: - return {QEvent::MouseButtonPress, Qt::MidButton}; + return {QEvent::MouseButtonPress, Qt::MiddleButton}; case WM_MBUTTONUP: - return {QEvent::MouseButtonRelease, Qt::MidButton}; + return {QEvent::MouseButtonRelease, Qt::MiddleButton}; case WM_MBUTTONDBLCLK: - return {QEvent::MouseButtonPress, Qt::MidButton}; + return {QEvent::MouseButtonPress, Qt::MiddleButton}; case WM_RBUTTONDOWN: return {QEvent::MouseButtonPress, Qt::RightButton}; case WM_RBUTTONUP: @@ -242,11 +186,11 @@ static inline MouseEvent eventFromMsg(const MSG &msg) case WM_NCLBUTTONDBLCLK: return {QEvent::NonClientAreaMouseButtonPress, Qt::LeftButton}; case WM_NCMBUTTONDOWN: - return {QEvent::NonClientAreaMouseButtonPress, Qt::MidButton}; + return {QEvent::NonClientAreaMouseButtonPress, Qt::MiddleButton}; case WM_NCMBUTTONUP: - return {QEvent::NonClientAreaMouseButtonRelease, Qt::MidButton}; + return {QEvent::NonClientAreaMouseButtonRelease, Qt::MiddleButton}; case WM_NCMBUTTONDBLCLK: - return {QEvent::NonClientAreaMouseButtonPress, Qt::MidButton}; + return {QEvent::NonClientAreaMouseButtonPress, Qt::MiddleButton}; case WM_NCRBUTTONDOWN: return {QEvent::NonClientAreaMouseButtonPress, Qt::RightButton}; case WM_NCRBUTTONUP: @@ -281,8 +225,13 @@ bool QWindowsMouseHandler::translateMouseEvent(QWindow *window, HWND hwnd, globalPosition = winEventPosition; clientPosition = QWindowsGeometryHint::mapFromGlobal(hwnd, globalPosition); } else { - clientPosition = winEventPosition; globalPosition = QWindowsGeometryHint::mapToGlobal(hwnd, winEventPosition); + auto targetHwnd = hwnd; + if (auto *pw = window->handle()) + targetHwnd = HWND(pw->winId()); + clientPosition = targetHwnd == hwnd + ? winEventPosition + : QWindowsGeometryHint::mapFromGlobal(targetHwnd, globalPosition); } // Windows sends a mouse move with no buttons pressed to signal "Enter" @@ -299,6 +248,8 @@ bool QWindowsMouseHandler::translateMouseEvent(QWindow *window, HWND hwnd, Qt::MouseEventSource source = Qt::MouseEventNotSynthesized; + const QPointingDevice *device = primaryMouse(); + // Check for events synthesized from touch. Lower byte is touch index, 0 means pen. static const bool passSynthesizedMouseEvents = !(QWindowsIntegration::instance()->options() & QWindowsIntegration::DontPassOsMouseEventsSynthesizedFromTouch); @@ -310,12 +261,15 @@ bool QWindowsMouseHandler::translateMouseEvent(QWindow *window, HWND hwnd, if ((extraInfo & signatureMask) == miWpSignature) { if (extraInfo & 0x80) { // Bit 7 indicates touch event, else tablet pen. source = Qt::MouseEventSynthesizedBySystem; + if (!m_touchDevice.isNull()) + device = m_touchDevice.data(); if (!passSynthesizedMouseEvents) return false; } } - const Qt::KeyboardModifiers keyModifiers = QWindowsKeyMapper::queryKeyboardModifiers(); + const auto *keyMapper = QWindowsContext::instance()->keyMapper(); + const Qt::KeyboardModifiers keyModifiers = keyMapper->queryKeyboardModifiers(); const MouseEvent mouseEvent = eventFromMsg(msg); Qt::MouseButtons buttons; @@ -333,19 +287,16 @@ bool QWindowsMouseHandler::translateMouseEvent(QWindow *window, HWND hwnd, if (m_lastEventType == QEvent::NonClientAreaMouseButtonPress && (mouseEvent.type == QEvent::NonClientAreaMouseMove || mouseEvent.type == QEvent::MouseMove) && (m_lastEventButton & buttons) == 0) { - if (mouseEvent.type == QEvent::NonClientAreaMouseMove) { - QWindowSystemInterface::handleFrameStrutMouseEvent(window, clientPosition, globalPosition, buttons, m_lastEventButton, - QEvent::NonClientAreaMouseButtonRelease, keyModifiers, source); - } else { - QWindowSystemInterface::handleMouseEvent(window, clientPosition, globalPosition, buttons, m_lastEventButton, - QEvent::MouseButtonRelease, keyModifiers, source); - } + auto releaseType = mouseEvent.type == QEvent::NonClientAreaMouseMove ? + QEvent::NonClientAreaMouseButtonRelease : QEvent::MouseButtonRelease; + QWindowSystemInterface::handleMouseEvent(window, msg.time, device, clientPosition, globalPosition, buttons, m_lastEventButton, + releaseType, keyModifiers, source); } m_lastEventType = mouseEvent.type; m_lastEventButton = mouseEvent.button; if (mouseEvent.type >= QEvent::NonClientAreaMouseMove && mouseEvent.type <= QEvent::NonClientAreaMouseButtonDblClick) { - QWindowSystemInterface::handleFrameStrutMouseEvent(window, clientPosition, + QWindowSystemInterface::handleMouseEvent(window, msg.time, device, clientPosition, globalPosition, buttons, mouseEvent.button, mouseEvent.type, keyModifiers, source); @@ -372,7 +323,7 @@ bool QWindowsMouseHandler::translateMouseEvent(QWindow *window, HWND hwnd, auto *platformWindow = static_cast<QWindowsWindow *>(window->handle()); - // If the window was recently resized via mouse doubleclick on the frame or title bar, + // If the window was recently resized via mouse double-click on the frame or title bar, // we don't get WM_LBUTTONDOWN or WM_LBUTTONDBLCLK for the second click, // but we will get at least one WM_MOUSEMOVE with left button down and the WM_LBUTTONUP, // which will result undesired mouse press and release events. @@ -495,7 +446,7 @@ bool QWindowsMouseHandler::translateMouseEvent(QWindow *window, HWND hwnd, } if (!discardEvent && mouseEvent.type != QEvent::None) { - QWindowSystemInterface::handleMouseEvent(window, winEventPosition, globalPosition, buttons, + QWindowSystemInterface::handleMouseEvent(window, msg.time, device, clientPosition, globalPosition, buttons, mouseEvent.button, mouseEvent.type, keyModifiers, source); } @@ -519,7 +470,7 @@ static bool isValidWheelReceiver(QWindow *candidate) return false; } -static void redirectWheelEvent(QWindow *window, const QPoint &globalPos, int delta, +static void redirectWheelEvent(QWindow *window, unsigned long timestamp, const QPoint &globalPos, int delta, Qt::Orientation orientation, Qt::KeyboardModifiers mods) { // Redirect wheel event to one of the following, in order of preference: @@ -540,6 +491,7 @@ static void redirectWheelEvent(QWindow *window, const QPoint &globalPos, int del if (handleEvent) { const QPoint point = (orientation == Qt::Vertical) ? QPoint(0, delta) : QPoint(delta, 0); QWindowSystemInterface::handleWheelEvent(receiver, + timestamp, QWindowsGeometryHint::mapFromGlobal(receiver, globalPos), globalPos, QPoint(), point, mods); } @@ -568,7 +520,7 @@ bool QWindowsMouseHandler::translateMouseWheelEvent(QWindow *window, HWND, delta = -delta; const QPoint globalPos(GET_X_LPARAM(msg.lParam), GET_Y_LPARAM(msg.lParam)); - redirectWheelEvent(window, globalPos, delta, orientation, mods); + redirectWheelEvent(window, msg.time, globalPos, delta, orientation, mods); return true; } @@ -599,7 +551,7 @@ bool QWindowsMouseHandler::translateScrollEvent(QWindow *window, HWND, return false; } - redirectWheelEvent(window, QCursor::pos(), delta, Qt::Horizontal, Qt::NoModifier); + redirectWheelEvent(window, msg.time, QCursor::pos(), delta, Qt::Horizontal, Qt::NoModifier); return true; } @@ -625,15 +577,14 @@ bool QWindowsMouseHandler::translateTouchEvent(QWindow *window, HWND, const QRect screenGeometry = screen->geometry(); const int winTouchPointCount = int(msg.wParam); - QScopedArrayPointer<TOUCHINPUT> winTouchInputs(new TOUCHINPUT[winTouchPointCount]); - memset(winTouchInputs.data(), 0, sizeof(TOUCHINPUT) * size_t(winTouchPointCount)); + const auto winTouchInputs = std::make_unique<TOUCHINPUT[]>(winTouchPointCount); QTouchPointList touchPoints; touchPoints.reserve(winTouchPointCount); - Qt::TouchPointStates allStates; + QEventPoint::States allStates; GetTouchInputInfo(reinterpret_cast<HTOUCHINPUT>(msg.lParam), - UINT(msg.wParam), winTouchInputs.data(), sizeof(TOUCHINPUT)); + UINT(msg.wParam), winTouchInputs.get(), sizeof(TOUCHINPUT)); for (int i = 0; i < winTouchPointCount; ++i) { const TOUCHINPUT &winTouchInput = winTouchInputs[i]; int id = m_touchInputIDToTouchPointID.value(winTouchInput.dwID, -1); @@ -657,15 +608,15 @@ bool QWindowsMouseHandler::translateTouchEvent(QWindow *window, HWND, touchPoint.normalPosition = normalPosition; if (winTouchInput.dwFlags & TOUCHEVENTF_DOWN) { - touchPoint.state = Qt::TouchPointPressed; + touchPoint.state = QEventPoint::State::Pressed; m_lastTouchPositions.insert(id, touchPoint.normalPosition); } else if (winTouchInput.dwFlags & TOUCHEVENTF_UP) { - touchPoint.state = Qt::TouchPointReleased; + touchPoint.state = QEventPoint::State::Released; m_lastTouchPositions.remove(id); } else { touchPoint.state = (stationaryTouchPoint - ? Qt::TouchPointStationary - : Qt::TouchPointMoved); + ? QEventPoint::State::Stationary + : QEventPoint::State::Updated); m_lastTouchPositions.insert(id, touchPoint.normalPosition); } @@ -677,13 +628,15 @@ bool QWindowsMouseHandler::translateTouchEvent(QWindow *window, HWND, CloseTouchInputHandle(reinterpret_cast<HTOUCHINPUT>(msg.lParam)); // all touch points released, forget the ids we've seen, they may not be reused - if (allStates == Qt::TouchPointReleased) + if (allStates == QEventPoint::State::Released) m_touchInputIDToTouchPointID.clear(); + const auto *keyMapper = QWindowsContext::instance()->keyMapper(); QWindowSystemInterface::handleTouchEvent(window, - m_touchDevice, + msg.time, + m_touchDevice.data(), touchPoints, - QWindowsKeyMapper::queryKeyboardModifiers()); + keyMapper->queryKeyboardModifiers()); return true; } @@ -691,9 +644,9 @@ bool QWindowsMouseHandler::translateGestureEvent(QWindow *window, HWND hwnd, QtWindows::WindowsEventType, MSG msg, LRESULT *) { - Q_UNUSED(window) - Q_UNUSED(hwnd) - Q_UNUSED(msg) + Q_UNUSED(window); + Q_UNUSED(hwnd); + Q_UNUSED(msg); return false; } |