Windows QPA: Handle mouse input using legacy messages
This change reverts to using legacy mouse messages when handling mouse and touchpad input, while using pointer messages to handle touchscreen and pen input. The use of pointer messages to handle everything, added in 5.12.0, caused issues in some particular cases, due mainly to differences in behavior or bugs in the pointer messages, which required workarounds in the Windows QPA, which didn't work well in all cases and led to additional issues. For instance, DoDragDrop() does not work when called by pointer (or touch/pen) handlers, but only after OS-synthesized legacy mouse messages are generated. Also, in some cases pointer messages for mouse movement are generated as non-client for client area events. Modal loops like the ones in window resize/move and menu handling caused some issues with pointer messages, as well. Also, we have to handle the OS-synthesized legacy mouse message generated for touch and pen. Ignoring them while letting the gui layer synthesize mouse events for touch/pen may break Drag and Drop by triggering DoDragDrop() before legacy messages, which can result in a hang inside the DoDragDrop() modal loop. This change should fix most regressions related to pointer messages, while keeping the enhancements in pen and touch input. Fixes: QTBUG-73389 Fixes: QTBUG-72624 Fixes: QTBUG-72801 Fixes: QTBUG-73290 Fixes: QTBUG-72458 Fixes: QTBUG-73358 Fixes: QTBUG-72992 Change-Id: I919f78930d3965270ef2094401e827ab87174979 Reviewed-by: Friedemann Kleint <Friedemann.Kleint@qt.io>
This commit is contained in:
parent
80bcfa776f
commit
3850404114
@ -334,12 +334,8 @@ bool QWindowsContext::initTouch(unsigned integrationOptions)
|
|||||||
if (!touchDevice)
|
if (!touchDevice)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (d->m_systemInfo & QWindowsContext::SI_SupportsPointer) {
|
if (!(integrationOptions & QWindowsIntegration::DontPassOsMouseEventsSynthesizedFromTouch))
|
||||||
QWindowSystemInterfacePrivate::TabletEvent::setPlatformSynthesizesMouse(false);
|
touchDevice->setCapabilities(touchDevice->capabilities() | QTouchDevice::MouseEmulation);
|
||||||
} else {
|
|
||||||
if (!(integrationOptions & QWindowsIntegration::DontPassOsMouseEventsSynthesizedFromTouch))
|
|
||||||
touchDevice->setCapabilities(touchDevice->capabilities() | QTouchDevice::MouseEmulation);
|
|
||||||
}
|
|
||||||
|
|
||||||
QWindowSystemInterface::registerTouchDevice(touchDevice);
|
QWindowSystemInterface::registerTouchDevice(touchDevice);
|
||||||
|
|
||||||
@ -376,7 +372,6 @@ bool QWindowsContext::initPointer(unsigned integrationOptions)
|
|||||||
if (!QWindowsContext::user32dll.supportsPointerApi())
|
if (!QWindowsContext::user32dll.supportsPointerApi())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
QWindowsContext::user32dll.enableMouseInPointer(TRUE);
|
|
||||||
d->m_systemInfo |= QWindowsContext::SI_SupportsPointer;
|
d->m_systemInfo |= QWindowsContext::SI_SupportsPointer;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -1218,9 +1213,10 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message,
|
|||||||
case QtWindows::ExposeEvent:
|
case QtWindows::ExposeEvent:
|
||||||
return platformWindow->handleWmPaint(hwnd, message, wParam, lParam);
|
return platformWindow->handleWmPaint(hwnd, message, wParam, lParam);
|
||||||
case QtWindows::NonClientMouseEvent:
|
case QtWindows::NonClientMouseEvent:
|
||||||
if (!(d->m_systemInfo & QWindowsContext::SI_SupportsPointer) && platformWindow->frameStrutEventsEnabled())
|
if ((d->m_systemInfo & QWindowsContext::SI_SupportsPointer) && platformWindow->frameStrutEventsEnabled())
|
||||||
|
return sessionManagerInteractionBlocked() || d->m_pointerHandler.translateMouseEvent(platformWindow->window(), hwnd, et, msg, result);
|
||||||
|
else
|
||||||
return sessionManagerInteractionBlocked() || d->m_mouseHandler.translateMouseEvent(platformWindow->window(), hwnd, et, msg, result);
|
return sessionManagerInteractionBlocked() || d->m_mouseHandler.translateMouseEvent(platformWindow->window(), hwnd, et, msg, result);
|
||||||
break;
|
|
||||||
case QtWindows::NonClientPointerEvent:
|
case QtWindows::NonClientPointerEvent:
|
||||||
if ((d->m_systemInfo & QWindowsContext::SI_SupportsPointer) && platformWindow->frameStrutEventsEnabled())
|
if ((d->m_systemInfo & QWindowsContext::SI_SupportsPointer) && platformWindow->frameStrutEventsEnabled())
|
||||||
return sessionManagerInteractionBlocked() || d->m_pointerHandler.translatePointerEvent(platformWindow->window(), hwnd, et, msg, result);
|
return sessionManagerInteractionBlocked() || d->m_pointerHandler.translatePointerEvent(platformWindow->window(), hwnd, et, msg, result);
|
||||||
@ -1246,10 +1242,10 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message,
|
|||||||
window = window->parent();
|
window = window->parent();
|
||||||
if (!window)
|
if (!window)
|
||||||
return false;
|
return false;
|
||||||
if (!(d->m_systemInfo & QWindowsContext::SI_SupportsPointer))
|
if (d->m_systemInfo & QWindowsContext::SI_SupportsPointer)
|
||||||
return sessionManagerInteractionBlocked() || d->m_mouseHandler.translateMouseEvent(window, hwnd, et, msg, result);
|
|
||||||
else
|
|
||||||
return sessionManagerInteractionBlocked() || d->m_pointerHandler.translateMouseEvent(window, hwnd, et, msg, result);
|
return sessionManagerInteractionBlocked() || d->m_pointerHandler.translateMouseEvent(window, hwnd, et, msg, result);
|
||||||
|
else
|
||||||
|
return sessionManagerInteractionBlocked() || d->m_mouseHandler.translateMouseEvent(window, hwnd, et, msg, result);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case QtWindows::TouchEvent:
|
case QtWindows::TouchEvent:
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
**
|
**
|
||||||
** Copyright (C) 2018 The Qt Company Ltd.
|
** Copyright (C) 2019 The Qt Company Ltd.
|
||||||
** Contact: https://www.qt.io/licensing/
|
** Contact: https://www.qt.io/licensing/
|
||||||
**
|
**
|
||||||
** This file is part of the plugins of the Qt Toolkit.
|
** This file is part of the plugins of the Qt Toolkit.
|
||||||
@ -50,9 +50,6 @@
|
|||||||
#include "qwindowswindow.h"
|
#include "qwindowswindow.h"
|
||||||
#include "qwindowsintegration.h"
|
#include "qwindowsintegration.h"
|
||||||
#include "qwindowsscreen.h"
|
#include "qwindowsscreen.h"
|
||||||
#if QT_CONFIG(draganddrop)
|
|
||||||
# include "qwindowsdrag.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <QtGui/qguiapplication.h>
|
#include <QtGui/qguiapplication.h>
|
||||||
#include <QtGui/qscreen.h>
|
#include <QtGui/qscreen.h>
|
||||||
@ -78,111 +75,9 @@ enum {
|
|||||||
QT_PT_TOUCHPAD = 5, // MinGW is missing PT_TOUCHPAD
|
QT_PT_TOUCHPAD = 5, // MinGW is missing PT_TOUCHPAD
|
||||||
};
|
};
|
||||||
|
|
||||||
struct PointerTouchEventInfo {
|
|
||||||
QPointer<QWindow> window;
|
|
||||||
QList<QWindowSystemInterface::TouchPoint> points;
|
|
||||||
Qt::KeyboardModifiers modifiers;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct PointerTabletEventInfo {
|
|
||||||
QPointer<QWindow> window;
|
|
||||||
QPointF local;
|
|
||||||
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;
|
|
||||||
};
|
|
||||||
|
|
||||||
static QQueue<PointerTouchEventInfo> touchEventQueue;
|
|
||||||
static QQueue<PointerTabletEventInfo> tabletEventQueue;
|
|
||||||
|
|
||||||
static void enqueueTouchEvent(QWindow *window,
|
|
||||||
const QList<QWindowSystemInterface::TouchPoint> &points,
|
|
||||||
Qt::KeyboardModifiers modifiers)
|
|
||||||
{
|
|
||||||
PointerTouchEventInfo eventInfo;
|
|
||||||
eventInfo.window = window;
|
|
||||||
eventInfo.points = points;
|
|
||||||
eventInfo.modifiers = modifiers;
|
|
||||||
touchEventQueue.enqueue(eventInfo);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void enqueueTabletEvent(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)
|
|
||||||
{
|
|
||||||
PointerTabletEventInfo eventInfo;
|
|
||||||
eventInfo.window = window;
|
|
||||||
eventInfo.local = local;
|
|
||||||
eventInfo.global = global;
|
|
||||||
eventInfo.device = device;
|
|
||||||
eventInfo.pointerType = pointerType;
|
|
||||||
eventInfo.buttons = buttons;
|
|
||||||
eventInfo.pressure = pressure;
|
|
||||||
eventInfo.xTilt = xTilt;
|
|
||||||
eventInfo.yTilt = yTilt;
|
|
||||||
eventInfo.tangentialPressure = tangentialPressure;
|
|
||||||
eventInfo.rotation = rotation;
|
|
||||||
eventInfo.z = z;
|
|
||||||
eventInfo.uid = uid;
|
|
||||||
eventInfo.modifiers = modifiers;
|
|
||||||
tabletEventQueue.enqueue(eventInfo);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void flushTouchEvents(QTouchDevice *touchDevice)
|
|
||||||
{
|
|
||||||
while (!touchEventQueue.isEmpty()) {
|
|
||||||
PointerTouchEventInfo eventInfo = touchEventQueue.dequeue();
|
|
||||||
if (eventInfo.window) {
|
|
||||||
QWindowSystemInterface::handleTouchEvent(eventInfo.window,
|
|
||||||
touchDevice,
|
|
||||||
eventInfo.points,
|
|
||||||
eventInfo.modifiers);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void flushTabletEvents()
|
|
||||||
{
|
|
||||||
while (!tabletEventQueue.isEmpty()) {
|
|
||||||
PointerTabletEventInfo eventInfo = tabletEventQueue.dequeue();
|
|
||||||
if (eventInfo.window) {
|
|
||||||
QWindowSystemInterface::handleTabletEvent(eventInfo.window,
|
|
||||||
eventInfo.local,
|
|
||||||
eventInfo.global,
|
|
||||||
eventInfo.device,
|
|
||||||
eventInfo.pointerType,
|
|
||||||
eventInfo.buttons,
|
|
||||||
eventInfo.pressure,
|
|
||||||
eventInfo.xTilt,
|
|
||||||
eventInfo.yTilt,
|
|
||||||
eventInfo.tangentialPressure,
|
|
||||||
eventInfo.rotation,
|
|
||||||
eventInfo.z,
|
|
||||||
eventInfo.uid,
|
|
||||||
eventInfo.modifiers);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool QWindowsPointerHandler::translatePointerEvent(QWindow *window, HWND hwnd, QtWindows::WindowsEventType et, MSG msg, LRESULT *result)
|
bool QWindowsPointerHandler::translatePointerEvent(QWindow *window, HWND hwnd, QtWindows::WindowsEventType et, MSG msg, LRESULT *result)
|
||||||
{
|
{
|
||||||
*result = 0;
|
*result = 0;
|
||||||
|
|
||||||
// If we are inside the move/resize modal loop, let DefWindowProc() handle it (but process NC button release).
|
|
||||||
QWindowsWindow *platformWindow = static_cast<QWindowsWindow *>(window->handle());
|
|
||||||
if (msg.message != WM_NCPOINTERUP && platformWindow->testFlag(QWindowsWindow::ResizeMoveActive))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
const quint32 pointerId = GET_POINTERID_WPARAM(msg.wParam);
|
const quint32 pointerId = GET_POINTERID_WPARAM(msg.wParam);
|
||||||
|
|
||||||
POINTER_INPUT_TYPE pointerType;
|
POINTER_INPUT_TYPE pointerType;
|
||||||
@ -191,30 +86,12 @@ bool QWindowsPointerHandler::translatePointerEvent(QWindow *window, HWND hwnd, Q
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_lastPointerType = pointerType;
|
|
||||||
|
|
||||||
// Handle non-client pen/touch as generic mouse events for compatibility with QDockWindow.
|
|
||||||
if ((pointerType == QT_PT_TOUCH || pointerType == QT_PT_PEN) && (et & QtWindows::NonClientEventFlag)) {
|
|
||||||
POINTER_INFO pointerInfo;
|
|
||||||
if (!QWindowsContext::user32dll.getPointerInfo(pointerId, &pointerInfo)) {
|
|
||||||
qWarning() << "GetPointerInfo() failed:" << qt_error_string();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (pointerInfo.pointerFlags & (POINTER_FLAG_UP | POINTER_FLAG_DOWN))
|
|
||||||
return translateMouseTouchPadEvent(window, hwnd, et, msg, &pointerInfo);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (pointerType) {
|
switch (pointerType) {
|
||||||
case QT_PT_POINTER:
|
case QT_PT_POINTER:
|
||||||
case QT_PT_MOUSE:
|
case QT_PT_MOUSE:
|
||||||
case QT_PT_TOUCHPAD: {
|
case QT_PT_TOUCHPAD: {
|
||||||
POINTER_INFO pointerInfo;
|
// Let Mouse/TouchPad be handled using legacy messages.
|
||||||
if (!QWindowsContext::user32dll.getPointerInfo(pointerId, &pointerInfo)) {
|
return false;
|
||||||
qWarning() << "GetPointerInfo() failed:" << qt_error_string();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return translateMouseTouchPadEvent(window, hwnd, et, msg, &pointerInfo);
|
|
||||||
}
|
}
|
||||||
case QT_PT_TOUCH: {
|
case QT_PT_TOUCH: {
|
||||||
quint32 pointerCount = 0;
|
quint32 pointerCount = 0;
|
||||||
@ -290,76 +167,71 @@ bool QWindowsPointerHandler::translatePointerEvent(QWindow *window, HWND hwnd, Q
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void getMouseEventInfo(UINT message, POINTER_BUTTON_CHANGE_TYPE changeType, QEvent::Type *eventType, Qt::MouseButton *mouseButton)
|
namespace {
|
||||||
|
struct MouseEvent {
|
||||||
|
QEvent::Type type;
|
||||||
|
Qt::MouseButton button;
|
||||||
|
};
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
static inline Qt::MouseButton extraButton(WPARAM wParam) // for WM_XBUTTON...
|
||||||
{
|
{
|
||||||
static const QHash<POINTER_BUTTON_CHANGE_TYPE, Qt::MouseButton> buttonMapping {
|
return GET_XBUTTON_WPARAM(wParam) == XBUTTON1 ? Qt::BackButton : Qt::ForwardButton;
|
||||||
{POINTER_CHANGE_FIRSTBUTTON_DOWN, Qt::LeftButton},
|
|
||||||
{POINTER_CHANGE_FIRSTBUTTON_UP, Qt::LeftButton},
|
|
||||||
{POINTER_CHANGE_SECONDBUTTON_DOWN, Qt::RightButton},
|
|
||||||
{POINTER_CHANGE_SECONDBUTTON_UP, Qt::RightButton},
|
|
||||||
{POINTER_CHANGE_THIRDBUTTON_DOWN, Qt::MiddleButton},
|
|
||||||
{POINTER_CHANGE_THIRDBUTTON_UP, Qt::MiddleButton},
|
|
||||||
{POINTER_CHANGE_FOURTHBUTTON_DOWN, Qt::XButton1},
|
|
||||||
{POINTER_CHANGE_FOURTHBUTTON_UP, Qt::XButton1},
|
|
||||||
{POINTER_CHANGE_FIFTHBUTTON_DOWN, Qt::XButton2},
|
|
||||||
{POINTER_CHANGE_FIFTHBUTTON_UP, Qt::XButton2},
|
|
||||||
};
|
|
||||||
|
|
||||||
static const POINTER_BUTTON_CHANGE_TYPE downChanges[] = {
|
|
||||||
POINTER_CHANGE_FIRSTBUTTON_DOWN,
|
|
||||||
POINTER_CHANGE_SECONDBUTTON_DOWN,
|
|
||||||
POINTER_CHANGE_THIRDBUTTON_DOWN,
|
|
||||||
POINTER_CHANGE_FOURTHBUTTON_DOWN,
|
|
||||||
POINTER_CHANGE_FIFTHBUTTON_DOWN,
|
|
||||||
};
|
|
||||||
|
|
||||||
static const POINTER_BUTTON_CHANGE_TYPE upChanges[] = {
|
|
||||||
POINTER_CHANGE_FIRSTBUTTON_UP,
|
|
||||||
POINTER_CHANGE_SECONDBUTTON_UP,
|
|
||||||
POINTER_CHANGE_THIRDBUTTON_UP,
|
|
||||||
POINTER_CHANGE_FOURTHBUTTON_UP,
|
|
||||||
POINTER_CHANGE_FIFTHBUTTON_UP,
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!eventType || !mouseButton)
|
|
||||||
return;
|
|
||||||
|
|
||||||
const bool nonClient = message == WM_NCPOINTERUPDATE ||
|
|
||||||
message == WM_NCPOINTERDOWN ||
|
|
||||||
message == WM_NCPOINTERUP;
|
|
||||||
|
|
||||||
if (std::find(std::begin(downChanges),
|
|
||||||
std::end(downChanges), changeType) < std::end(downChanges)) {
|
|
||||||
*eventType = nonClient ? QEvent::NonClientAreaMouseButtonPress :
|
|
||||||
QEvent::MouseButtonPress;
|
|
||||||
} else if (std::find(std::begin(upChanges),
|
|
||||||
std::end(upChanges), changeType) < std::end(upChanges)) {
|
|
||||||
*eventType = nonClient ? QEvent::NonClientAreaMouseButtonRelease :
|
|
||||||
QEvent::MouseButtonRelease;
|
|
||||||
} else if (message == WM_POINTERWHEEL || message == WM_POINTERHWHEEL) {
|
|
||||||
*eventType = QEvent::Wheel;
|
|
||||||
} else {
|
|
||||||
*eventType = nonClient ? QEvent::NonClientAreaMouseMove :
|
|
||||||
QEvent::MouseMove;
|
|
||||||
}
|
|
||||||
|
|
||||||
*mouseButton = buttonMapping.value(changeType, Qt::NoButton);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static Qt::MouseButtons mouseButtonsFromPointerFlags(POINTER_FLAGS pointerFlags)
|
static inline MouseEvent eventFromMsg(const MSG &msg)
|
||||||
{
|
{
|
||||||
Qt::MouseButtons result = Qt::NoButton;
|
switch (msg.message) {
|
||||||
if (pointerFlags & POINTER_FLAG_FIRSTBUTTON)
|
case WM_MOUSEMOVE:
|
||||||
result |= Qt::LeftButton;
|
return {QEvent::MouseMove, Qt::NoButton};
|
||||||
if (pointerFlags & POINTER_FLAG_SECONDBUTTON)
|
case WM_LBUTTONDOWN:
|
||||||
result |= Qt::RightButton;
|
return {QEvent::MouseButtonPress, Qt::LeftButton};
|
||||||
if (pointerFlags & POINTER_FLAG_THIRDBUTTON)
|
case WM_LBUTTONUP:
|
||||||
result |= Qt::MiddleButton;
|
return {QEvent::MouseButtonRelease, Qt::LeftButton};
|
||||||
if (pointerFlags & POINTER_FLAG_FOURTHBUTTON)
|
case WM_LBUTTONDBLCLK: // Qt QPA does not handle double clicks, send as press
|
||||||
result |= Qt::XButton1;
|
return {QEvent::MouseButtonPress, Qt::LeftButton};
|
||||||
if (pointerFlags & POINTER_FLAG_FIFTHBUTTON)
|
case WM_MBUTTONDOWN:
|
||||||
result |= Qt::XButton2;
|
return {QEvent::MouseButtonPress, Qt::MidButton};
|
||||||
return result;
|
case WM_MBUTTONUP:
|
||||||
|
return {QEvent::MouseButtonRelease, Qt::MidButton};
|
||||||
|
case WM_MBUTTONDBLCLK:
|
||||||
|
return {QEvent::MouseButtonPress, Qt::MidButton};
|
||||||
|
case WM_RBUTTONDOWN:
|
||||||
|
return {QEvent::MouseButtonPress, Qt::RightButton};
|
||||||
|
case WM_RBUTTONUP:
|
||||||
|
return {QEvent::MouseButtonRelease, Qt::RightButton};
|
||||||
|
case WM_RBUTTONDBLCLK:
|
||||||
|
return {QEvent::MouseButtonPress, Qt::RightButton};
|
||||||
|
case WM_XBUTTONDOWN:
|
||||||
|
return {QEvent::MouseButtonPress, extraButton(msg.wParam)};
|
||||||
|
case WM_XBUTTONUP:
|
||||||
|
return {QEvent::MouseButtonRelease, extraButton(msg.wParam)};
|
||||||
|
case WM_XBUTTONDBLCLK:
|
||||||
|
return {QEvent::MouseButtonPress, extraButton(msg.wParam)};
|
||||||
|
case WM_NCMOUSEMOVE:
|
||||||
|
return {QEvent::NonClientAreaMouseMove, Qt::NoButton};
|
||||||
|
case WM_NCLBUTTONDOWN:
|
||||||
|
return {QEvent::NonClientAreaMouseButtonPress, Qt::LeftButton};
|
||||||
|
case WM_NCLBUTTONUP:
|
||||||
|
return {QEvent::NonClientAreaMouseButtonRelease, Qt::LeftButton};
|
||||||
|
case WM_NCLBUTTONDBLCLK:
|
||||||
|
return {QEvent::NonClientAreaMouseButtonPress, Qt::LeftButton};
|
||||||
|
case WM_NCMBUTTONDOWN:
|
||||||
|
return {QEvent::NonClientAreaMouseButtonPress, Qt::MidButton};
|
||||||
|
case WM_NCMBUTTONUP:
|
||||||
|
return {QEvent::NonClientAreaMouseButtonRelease, Qt::MidButton};
|
||||||
|
case WM_NCMBUTTONDBLCLK:
|
||||||
|
return {QEvent::NonClientAreaMouseButtonPress, Qt::MidButton};
|
||||||
|
case WM_NCRBUTTONDOWN:
|
||||||
|
return {QEvent::NonClientAreaMouseButtonPress, Qt::RightButton};
|
||||||
|
case WM_NCRBUTTONUP:
|
||||||
|
return {QEvent::NonClientAreaMouseButtonRelease, Qt::RightButton};
|
||||||
|
case WM_NCRBUTTONDBLCLK:
|
||||||
|
return {QEvent::NonClientAreaMouseButtonPress, Qt::RightButton};
|
||||||
|
default: // WM_MOUSELEAVE
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return {QEvent::None, Qt::NoButton};
|
||||||
}
|
}
|
||||||
|
|
||||||
static Qt::MouseButtons mouseButtonsFromKeyState(WPARAM keyState)
|
static Qt::MouseButtons mouseButtonsFromKeyState(WPARAM keyState)
|
||||||
@ -419,15 +291,6 @@ static bool isValidWheelReceiver(QWindow *candidate)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool isMenuWindow(QWindow *window)
|
|
||||||
{
|
|
||||||
if (window)
|
|
||||||
if (QObject *fo = window->focusObject())
|
|
||||||
if (fo->inherits("QMenu"))
|
|
||||||
return true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static QTouchDevice *createTouchDevice()
|
static QTouchDevice *createTouchDevice()
|
||||||
{
|
{
|
||||||
const int digitizers = GetSystemMetrics(SM_DIGITIZER);
|
const int digitizers = GetSystemMetrics(SM_DIGITIZER);
|
||||||
@ -553,71 +416,6 @@ void QWindowsPointerHandler::handleEnterLeave(QWindow *window,
|
|||||||
m_previousCaptureWindow = hasCapture ? window : nullptr;
|
m_previousCaptureWindow = hasCapture ? window : nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QWindowsPointerHandler::translateMouseTouchPadEvent(QWindow *window, HWND hwnd,
|
|
||||||
QtWindows::WindowsEventType et,
|
|
||||||
MSG msg, PVOID vPointerInfo)
|
|
||||||
{
|
|
||||||
POINTER_INFO *pointerInfo = static_cast<POINTER_INFO *>(vPointerInfo);
|
|
||||||
const QPoint globalPos = QPoint(pointerInfo->ptPixelLocation.x, pointerInfo->ptPixelLocation.y);
|
|
||||||
const QPoint localPos = QWindowsGeometryHint::mapFromGlobal(hwnd, globalPos);
|
|
||||||
const Qt::KeyboardModifiers keyModifiers = QWindowsKeyMapper::queryKeyboardModifiers();
|
|
||||||
const Qt::MouseButtons mouseButtons = mouseButtonsFromPointerFlags(pointerInfo->pointerFlags);
|
|
||||||
QWindow *currentWindowUnderPointer = getWindowUnderPointer(window, globalPos);
|
|
||||||
|
|
||||||
switch (msg.message) {
|
|
||||||
case WM_NCPOINTERDOWN:
|
|
||||||
case WM_NCPOINTERUP:
|
|
||||||
case WM_NCPOINTERUPDATE:
|
|
||||||
case WM_POINTERDOWN:
|
|
||||||
case WM_POINTERUP:
|
|
||||||
case WM_POINTERUPDATE: {
|
|
||||||
|
|
||||||
QEvent::Type eventType;
|
|
||||||
Qt::MouseButton button;
|
|
||||||
getMouseEventInfo(msg.message, pointerInfo->ButtonChangeType, &eventType, &button);
|
|
||||||
|
|
||||||
if (et & QtWindows::NonClientEventFlag) {
|
|
||||||
QWindowSystemInterface::handleFrameStrutMouseEvent(window, localPos, globalPos, mouseButtons, button, eventType,
|
|
||||||
keyModifiers, Qt::MouseEventNotSynthesized);
|
|
||||||
return false; // To allow window dragging, etc.
|
|
||||||
} else {
|
|
||||||
|
|
||||||
handleCaptureRelease(window, currentWindowUnderPointer, hwnd, eventType, mouseButtons);
|
|
||||||
handleEnterLeave(window, currentWindowUnderPointer, globalPos);
|
|
||||||
|
|
||||||
QWindowSystemInterface::handleMouseEvent(window, localPos, globalPos, mouseButtons, button, eventType,
|
|
||||||
keyModifiers, Qt::MouseEventNotSynthesized);
|
|
||||||
|
|
||||||
// The initial down click over the QSizeGrip area, which posts a resize WM_SYSCOMMAND
|
|
||||||
// has go to through DefWindowProc() for resizing to work, so we return false here,
|
|
||||||
// unless the click was on a menu, as it would mess with menu processing.
|
|
||||||
return msg.message != WM_POINTERDOWN || isMenuWindow(window);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case WM_POINTERHWHEEL:
|
|
||||||
case WM_POINTERWHEEL: {
|
|
||||||
|
|
||||||
if (!isValidWheelReceiver(window))
|
|
||||||
return true;
|
|
||||||
|
|
||||||
int delta = GET_WHEEL_DELTA_WPARAM(msg.wParam);
|
|
||||||
|
|
||||||
// Qt horizontal wheel rotation orientation is opposite to the one in WM_POINTERHWHEEL
|
|
||||||
if (msg.message == WM_POINTERHWHEEL)
|
|
||||||
delta = -delta;
|
|
||||||
|
|
||||||
const QPoint angleDelta = (msg.message == WM_POINTERHWHEEL || (keyModifiers & Qt::AltModifier)) ?
|
|
||||||
QPoint(delta, 0) : QPoint(0, delta);
|
|
||||||
|
|
||||||
QWindowSystemInterface::handleWheelEvent(window, localPos, globalPos, QPoint(), angleDelta, keyModifiers);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
case WM_POINTERLEAVE:
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool QWindowsPointerHandler::translateTouchEvent(QWindow *window, HWND hwnd,
|
bool QWindowsPointerHandler::translateTouchEvent(QWindow *window, HWND hwnd,
|
||||||
QtWindows::WindowsEventType et,
|
QtWindows::WindowsEventType et,
|
||||||
MSG msg, PVOID vTouchInfo, quint32 count)
|
MSG msg, PVOID vTouchInfo, quint32 count)
|
||||||
@ -653,15 +451,14 @@ bool QWindowsPointerHandler::translateTouchEvent(QWindow *window, HWND hwnd,
|
|||||||
|
|
||||||
QList<QWindowSystemInterface::TouchPoint> touchPoints;
|
QList<QWindowSystemInterface::TouchPoint> touchPoints;
|
||||||
|
|
||||||
bool primaryPointer = false;
|
|
||||||
bool pressRelease = false;
|
|
||||||
|
|
||||||
if (QWindowsContext::verbose > 1)
|
if (QWindowsContext::verbose > 1)
|
||||||
qCDebug(lcQpaEvents).noquote().nospace() << showbase
|
qCDebug(lcQpaEvents).noquote().nospace() << showbase
|
||||||
<< __FUNCTION__
|
<< __FUNCTION__
|
||||||
<< " message=" << hex << msg.message
|
<< " message=" << hex << msg.message
|
||||||
<< " count=" << dec << count;
|
<< " count=" << dec << count;
|
||||||
|
|
||||||
|
Qt::TouchPointStates allStates = 0;
|
||||||
|
|
||||||
for (quint32 i = 0; i < count; ++i) {
|
for (quint32 i = 0; i < count; ++i) {
|
||||||
if (QWindowsContext::verbose > 1)
|
if (QWindowsContext::verbose > 1)
|
||||||
qCDebug(lcQpaEvents).noquote().nospace() << showbase
|
qCDebug(lcQpaEvents).noquote().nospace() << showbase
|
||||||
@ -670,7 +467,13 @@ bool QWindowsPointerHandler::translateTouchEvent(QWindow *window, HWND hwnd,
|
|||||||
<< " flags=" << hex << touchInfo[i].pointerInfo.pointerFlags;
|
<< " flags=" << hex << touchInfo[i].pointerInfo.pointerFlags;
|
||||||
|
|
||||||
QWindowSystemInterface::TouchPoint touchPoint;
|
QWindowSystemInterface::TouchPoint touchPoint;
|
||||||
touchPoint.id = touchInfo[i].pointerInfo.pointerId;
|
const quint32 pointerId = touchInfo[i].pointerInfo.pointerId;
|
||||||
|
int id = m_touchInputIDToTouchPointID.value(pointerId, -1);
|
||||||
|
if (id == -1) {
|
||||||
|
id = m_touchInputIDToTouchPointID.size();
|
||||||
|
m_touchInputIDToTouchPointID.insert(pointerId, id);
|
||||||
|
}
|
||||||
|
touchPoint.id = id;
|
||||||
touchPoint.pressure = (touchInfo[i].touchMask & TOUCH_MASK_PRESSURE) ?
|
touchPoint.pressure = (touchInfo[i].touchMask & TOUCH_MASK_PRESSURE) ?
|
||||||
touchInfo[i].pressure / 1024.0 : 1.0;
|
touchInfo[i].pressure / 1024.0 : 1.0;
|
||||||
if (m_lastTouchPositions.contains(touchPoint.id))
|
if (m_lastTouchPositions.contains(touchPoint.id))
|
||||||
@ -691,32 +494,27 @@ bool QWindowsPointerHandler::translateTouchEvent(QWindow *window, HWND hwnd,
|
|||||||
if (touchInfo[i].pointerInfo.pointerFlags & POINTER_FLAG_DOWN) {
|
if (touchInfo[i].pointerInfo.pointerFlags & POINTER_FLAG_DOWN) {
|
||||||
touchPoint.state = Qt::TouchPointPressed;
|
touchPoint.state = Qt::TouchPointPressed;
|
||||||
m_lastTouchPositions.insert(touchPoint.id, touchPoint.normalPosition);
|
m_lastTouchPositions.insert(touchPoint.id, touchPoint.normalPosition);
|
||||||
pressRelease = true;
|
|
||||||
} else if (touchInfo[i].pointerInfo.pointerFlags & POINTER_FLAG_UP) {
|
} else if (touchInfo[i].pointerInfo.pointerFlags & POINTER_FLAG_UP) {
|
||||||
touchPoint.state = Qt::TouchPointReleased;
|
touchPoint.state = Qt::TouchPointReleased;
|
||||||
m_lastTouchPositions.remove(touchPoint.id);
|
m_lastTouchPositions.remove(touchPoint.id);
|
||||||
pressRelease = true;
|
|
||||||
} else {
|
} else {
|
||||||
touchPoint.state = stationaryTouchPoint ? Qt::TouchPointStationary : Qt::TouchPointMoved;
|
touchPoint.state = stationaryTouchPoint ? Qt::TouchPointStationary : Qt::TouchPointMoved;
|
||||||
m_lastTouchPositions.insert(touchPoint.id, touchPoint.normalPosition);
|
m_lastTouchPositions.insert(touchPoint.id, touchPoint.normalPosition);
|
||||||
}
|
}
|
||||||
if (touchInfo[i].pointerInfo.pointerFlags & POINTER_FLAG_PRIMARY)
|
allStates |= touchPoint.state;
|
||||||
primaryPointer = true;
|
|
||||||
|
|
||||||
touchPoints.append(touchPoint);
|
touchPoints.append(touchPoint);
|
||||||
|
|
||||||
// Avoid getting repeated messages for this frame if there are multiple pointerIds
|
// Avoid getting repeated messages for this frame if there are multiple pointerIds
|
||||||
QWindowsContext::user32dll.skipPointerFrameMessages(touchInfo[i].pointerInfo.pointerId);
|
QWindowsContext::user32dll.skipPointerFrameMessages(touchInfo[i].pointerInfo.pointerId);
|
||||||
}
|
}
|
||||||
if (primaryPointer && !pressRelease) {
|
|
||||||
// Postpone event delivery to avoid hanging inside DoDragDrop().
|
// all touch points released, forget the ids we've seen.
|
||||||
// Only the primary pointer will generate mouse messages.
|
if (allStates == Qt::TouchPointReleased)
|
||||||
enqueueTouchEvent(window, touchPoints, QWindowsKeyMapper::queryKeyboardModifiers());
|
m_touchInputIDToTouchPointID.clear();
|
||||||
} else {
|
|
||||||
flushTouchEvents(m_touchDevice);
|
QWindowSystemInterface::handleTouchEvent(window, m_touchDevice, touchPoints,
|
||||||
QWindowSystemInterface::handleTouchEvent(window, m_touchDevice, touchPoints,
|
QWindowsKeyMapper::queryKeyboardModifiers());
|
||||||
QWindowsKeyMapper::queryKeyboardModifiers());
|
|
||||||
}
|
|
||||||
return false; // Allow mouse messages to be generated.
|
return false; // Allow mouse messages to be generated.
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -807,10 +605,9 @@ bool QWindowsPointerHandler::translatePenEvent(QWindow *window, HWND hwnd, QtWin
|
|||||||
}
|
}
|
||||||
const Qt::KeyboardModifiers keyModifiers = QWindowsKeyMapper::queryKeyboardModifiers();
|
const Qt::KeyboardModifiers keyModifiers = QWindowsKeyMapper::queryKeyboardModifiers();
|
||||||
|
|
||||||
// Postpone event delivery to avoid hanging inside DoDragDrop().
|
QWindowSystemInterface::handleTabletEvent(target, localPos, hiResGlobalPos, device, type, mouseButtons,
|
||||||
enqueueTabletEvent(target, localPos, hiResGlobalPos, device, type, mouseButtons,
|
pressure, xTilt, yTilt, tangentialPressure, rotation, z,
|
||||||
pressure, xTilt, yTilt, tangentialPressure, rotation, z,
|
pointerId, keyModifiers);
|
||||||
pointerId, keyModifiers);
|
|
||||||
return false; // Allow mouse messages to be generated.
|
return false; // Allow mouse messages to be generated.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -835,18 +632,46 @@ static inline bool isMouseEventSynthesizedFromPenOrTouch()
|
|||||||
return ((::GetMessageExtraInfo() & SIGNATURE_MASK) == MI_WP_SIGNATURE);
|
return ((::GetMessageExtraInfo() & SIGNATURE_MASK) == MI_WP_SIGNATURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Process old-style mouse messages here.
|
bool QWindowsPointerHandler::translateMouseWheelEvent(QWindow *window,
|
||||||
bool QWindowsPointerHandler::translateMouseEvent(QWindow *window, HWND hwnd, QtWindows::WindowsEventType et, MSG msg, LRESULT *result)
|
QWindow *currentWindowUnderPointer,
|
||||||
|
MSG msg,
|
||||||
|
QPoint globalPos,
|
||||||
|
Qt::KeyboardModifiers keyModifiers)
|
||||||
{
|
{
|
||||||
// Generate enqueued events.
|
QWindow *receiver = currentWindowUnderPointer;
|
||||||
flushTouchEvents(m_touchDevice);
|
if (!isValidWheelReceiver(receiver))
|
||||||
flushTabletEvents();
|
receiver = window;
|
||||||
|
if (!isValidWheelReceiver(receiver))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
int delta = GET_WHEEL_DELTA_WPARAM(msg.wParam);
|
||||||
|
|
||||||
|
// Qt horizontal wheel rotation orientation is opposite to the one in WM_MOUSEHWHEEL
|
||||||
|
if (msg.message == WM_MOUSEHWHEEL)
|
||||||
|
delta = -delta;
|
||||||
|
|
||||||
|
const QPoint angleDelta = (msg.message == WM_MOUSEHWHEEL || (keyModifiers & Qt::AltModifier)) ?
|
||||||
|
QPoint(delta, 0) : QPoint(0, delta);
|
||||||
|
|
||||||
|
QPoint localPos = QWindowsGeometryHint::mapFromGlobal(receiver, globalPos);
|
||||||
|
|
||||||
|
QWindowSystemInterface::handleWheelEvent(window, localPos, globalPos, QPoint(), angleDelta, keyModifiers);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process legacy mouse messages here.
|
||||||
|
bool QWindowsPointerHandler::translateMouseEvent(QWindow *window,
|
||||||
|
HWND hwnd,
|
||||||
|
QtWindows::WindowsEventType et,
|
||||||
|
MSG msg,
|
||||||
|
LRESULT *result)
|
||||||
|
{
|
||||||
*result = 0;
|
*result = 0;
|
||||||
|
|
||||||
const QPoint eventPos(GET_X_LPARAM(msg.lParam), GET_Y_LPARAM(msg.lParam));
|
const QPoint eventPos(GET_X_LPARAM(msg.lParam), GET_Y_LPARAM(msg.lParam));
|
||||||
QPoint localPos;
|
QPoint localPos;
|
||||||
QPoint globalPos;
|
QPoint globalPos;
|
||||||
|
|
||||||
if ((et == QtWindows::MouseWheelEvent) || (et & QtWindows::NonClientEventFlag)) {
|
if ((et == QtWindows::MouseWheelEvent) || (et & QtWindows::NonClientEventFlag)) {
|
||||||
globalPos = eventPos;
|
globalPos = eventPos;
|
||||||
localPos = QWindowsGeometryHint::mapFromGlobal(hwnd, eventPos);
|
localPos = QWindowsGeometryHint::mapFromGlobal(hwnd, eventPos);
|
||||||
@ -857,46 +682,39 @@ bool QWindowsPointerHandler::translateMouseEvent(QWindow *window, HWND hwnd, QtW
|
|||||||
|
|
||||||
const Qt::KeyboardModifiers keyModifiers = QWindowsKeyMapper::queryKeyboardModifiers();
|
const Qt::KeyboardModifiers keyModifiers = QWindowsKeyMapper::queryKeyboardModifiers();
|
||||||
const Qt::MouseButtons mouseButtons = mouseButtonsFromKeyState(msg.wParam);
|
const Qt::MouseButtons mouseButtons = mouseButtonsFromKeyState(msg.wParam);
|
||||||
|
QWindow *currentWindowUnderPointer = getWindowUnderPointer(window, globalPos);
|
||||||
|
|
||||||
// Handle "press and hold for right-clicking".
|
if (et == QtWindows::MouseWheelEvent)
|
||||||
// We have to synthesize it here as it only comes from Windows as a fake RMB.
|
return translateMouseWheelEvent(window, currentWindowUnderPointer, msg, globalPos, keyModifiers);
|
||||||
// MS docs say we could use bit 7 from extraInfo to distinguish pen from touch,
|
|
||||||
// but on the Surface it is set for both. So we use the last pointer type.
|
// Windows sends a mouse move with no buttons pressed to signal "Enter"
|
||||||
if (isMouseEventSynthesizedFromPenOrTouch()) {
|
// when a window is shown over the cursor. Discard the event and only use
|
||||||
if ((msg.message == WM_RBUTTONDOWN || msg.message == WM_RBUTTONUP)
|
// it for generating QEvent::Enter to be consistent with other platforms -
|
||||||
&& (((m_lastPointerType == QT_PT_PEN)
|
// X11 and macOS.
|
||||||
&& QCoreApplication::testAttribute(Qt::AA_SynthesizeMouseForUnhandledTabletEvents))
|
bool discardEvent = false;
|
||||||
|| ((m_lastPointerType == QT_PT_TOUCH)
|
if (msg.message == WM_MOUSEMOVE) {
|
||||||
&& QCoreApplication::testAttribute(Qt::AA_SynthesizeMouseForUnhandledTouchEvents)))) {
|
static QPoint lastMouseMovePos;
|
||||||
QWindowSystemInterface::handleMouseEvent(window, localPos, globalPos, mouseButtons, Qt::RightButton,
|
if (msg.wParam == 0 && (m_windowUnderPointer.isNull() || globalPos == lastMouseMovePos))
|
||||||
(msg.message == WM_RBUTTONDOWN) ? QEvent::MouseButtonPress
|
discardEvent = true;
|
||||||
: QEvent::MouseButtonRelease,
|
lastMouseMovePos = globalPos;
|
||||||
keyModifiers, Qt::MouseEventSynthesizedBySystem);
|
|
||||||
}
|
|
||||||
// Messages synthesized from touch/pen are only used for flushing queues and press&hold.
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (et == QtWindows::MouseWheelEvent) {
|
Qt::MouseEventSource source = Qt::MouseEventNotSynthesized;
|
||||||
|
if (isMouseEventSynthesizedFromPenOrTouch()) {
|
||||||
|
if (QWindowsIntegration::instance()->options() & QWindowsIntegration::DontPassOsMouseEventsSynthesizedFromTouch)
|
||||||
|
return false;
|
||||||
|
source = Qt::MouseEventSynthesizedBySystem;
|
||||||
|
}
|
||||||
|
|
||||||
if (!isValidWheelReceiver(window))
|
const MouseEvent mouseEvent = eventFromMsg(msg);
|
||||||
return true;
|
|
||||||
|
|
||||||
int delta = GET_WHEEL_DELTA_WPARAM(msg.wParam);
|
if (mouseEvent.type >= QEvent::NonClientAreaMouseMove && mouseEvent.type <= QEvent::NonClientAreaMouseButtonDblClick) {
|
||||||
|
QWindowSystemInterface::handleFrameStrutMouseEvent(window, localPos, globalPos, mouseButtons,
|
||||||
// Qt horizontal wheel rotation orientation is opposite to the one in WM_MOUSEHWHEEL
|
mouseEvent.button, mouseEvent.type, keyModifiers, source);
|
||||||
if (msg.message == WM_MOUSEHWHEEL)
|
return false; // Allow further event processing
|
||||||
delta = -delta;
|
|
||||||
|
|
||||||
const QPoint angleDelta = (msg.message == WM_MOUSEHWHEEL || (keyModifiers & Qt::AltModifier)) ?
|
|
||||||
QPoint(delta, 0) : QPoint(0, delta);
|
|
||||||
|
|
||||||
QWindowSystemInterface::handleWheelEvent(window, localPos, globalPos, QPoint(), angleDelta, keyModifiers);
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (msg.message == WM_MOUSELEAVE) {
|
if (msg.message == WM_MOUSELEAVE) {
|
||||||
|
|
||||||
if (window == m_currentWindow) {
|
if (window == m_currentWindow) {
|
||||||
QWindow *leaveTarget = m_windowUnderPointer ? m_windowUnderPointer : m_currentWindow;
|
QWindow *leaveTarget = m_windowUnderPointer ? m_windowUnderPointer : m_currentWindow;
|
||||||
qCDebug(lcQpaEvents) << "Leaving window " << leaveTarget;
|
qCDebug(lcQpaEvents) << "Leaving window " << leaveTarget;
|
||||||
@ -904,14 +722,21 @@ bool QWindowsPointerHandler::translateMouseEvent(QWindow *window, HWND hwnd, QtW
|
|||||||
m_windowUnderPointer = nullptr;
|
m_windowUnderPointer = nullptr;
|
||||||
m_currentWindow = nullptr;
|
m_currentWindow = nullptr;
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
} else if (msg.message == WM_MOUSEMOVE) {
|
|
||||||
|
|
||||||
QWindow *currentWindowUnderPointer = getWindowUnderPointer(window, globalPos);
|
|
||||||
handleCaptureRelease(window, currentWindowUnderPointer, hwnd, QEvent::MouseMove, mouseButtons);
|
|
||||||
handleEnterLeave(window, currentWindowUnderPointer, globalPos);
|
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
|
handleCaptureRelease(window, currentWindowUnderPointer, hwnd, mouseEvent.type, mouseButtons);
|
||||||
|
handleEnterLeave(window, currentWindowUnderPointer, globalPos);
|
||||||
|
|
||||||
|
if (!discardEvent && mouseEvent.type != QEvent::None) {
|
||||||
|
QWindowSystemInterface::handleMouseEvent(window, localPos, globalPos, mouseButtons,
|
||||||
|
mouseEvent.button, mouseEvent.type, keyModifiers, source);
|
||||||
|
}
|
||||||
|
|
||||||
|
// QTBUG-48117, force synchronous handling for the extra buttons so that WM_APPCOMMAND
|
||||||
|
// is sent for unhandled WM_XBUTTONDOWN.
|
||||||
|
return (msg.message != WM_XBUTTONUP && msg.message != WM_XBUTTONDOWN && msg.message != WM_XBUTTONDBLCLK)
|
||||||
|
|| QWindowSystemInterface::flushWindowSystemEvents();
|
||||||
}
|
}
|
||||||
|
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
**
|
**
|
||||||
** Copyright (C) 2018 The Qt Company Ltd.
|
** Copyright (C) 2019 The Qt Company Ltd.
|
||||||
** Contact: https://www.qt.io/licensing/
|
** Contact: https://www.qt.io/licensing/
|
||||||
**
|
**
|
||||||
** This file is part of the plugins of the Qt Toolkit.
|
** This file is part of the plugins of the Qt Toolkit.
|
||||||
@ -66,19 +66,19 @@ public:
|
|||||||
void clearWindowUnderMouse() { m_windowUnderPointer = nullptr; }
|
void clearWindowUnderMouse() { m_windowUnderPointer = nullptr; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool translateMouseTouchPadEvent(QWindow *window, HWND hwnd, QtWindows::WindowsEventType et, MSG msg, PVOID vPointerInfo);
|
|
||||||
bool translateTouchEvent(QWindow *window, HWND hwnd, QtWindows::WindowsEventType et, MSG msg, PVOID vTouchInfo, unsigned int count);
|
bool translateTouchEvent(QWindow *window, HWND hwnd, QtWindows::WindowsEventType et, MSG msg, PVOID vTouchInfo, unsigned int count);
|
||||||
bool translatePenEvent(QWindow *window, HWND hwnd, QtWindows::WindowsEventType et, MSG msg, PVOID vPenInfo);
|
bool translatePenEvent(QWindow *window, HWND hwnd, QtWindows::WindowsEventType et, MSG msg, PVOID vPenInfo);
|
||||||
|
bool translateMouseWheelEvent(QWindow *window, QWindow *currentWindowUnderPointer, MSG msg, QPoint globalPos, Qt::KeyboardModifiers keyModifiers);
|
||||||
void handleCaptureRelease(QWindow *window, QWindow *currentWindowUnderPointer, HWND hwnd, QEvent::Type eventType, Qt::MouseButtons mouseButtons);
|
void handleCaptureRelease(QWindow *window, QWindow *currentWindowUnderPointer, HWND hwnd, QEvent::Type eventType, Qt::MouseButtons mouseButtons);
|
||||||
void handleEnterLeave(QWindow *window, QWindow *currentWindowUnderPointer, QPoint globalPos);
|
void handleEnterLeave(QWindow *window, QWindow *currentWindowUnderPointer, QPoint globalPos);
|
||||||
|
|
||||||
QTouchDevice *m_touchDevice = nullptr;
|
QTouchDevice *m_touchDevice = nullptr;
|
||||||
QHash<int, QPointF> m_lastTouchPositions;
|
QHash<int, QPointF> m_lastTouchPositions;
|
||||||
|
QHash<DWORD, int> m_touchInputIDToTouchPointID;
|
||||||
QPointer<QWindow> m_windowUnderPointer;
|
QPointer<QWindow> m_windowUnderPointer;
|
||||||
QPointer<QWindow> m_currentWindow;
|
QPointer<QWindow> m_currentWindow;
|
||||||
QWindow *m_previousCaptureWindow = nullptr;
|
QWindow *m_previousCaptureWindow = nullptr;
|
||||||
bool m_needsEnterOnPointerUpdate = false;
|
bool m_needsEnterOnPointerUpdate = false;
|
||||||
DWORD m_lastPointerType = 0;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
Loading…
x
Reference in New Issue
Block a user