Warning, /graphics/krita/3rdparty/ext_qt/0051-Add-workaround-for-handling-table-press-correctly-in.patch is written in an unsupported language. File is not indexed.
0001 From d27aa35ac1cf870157e957eae4c58ab69662b665 Mon Sep 17 00:00:00 2001 0002 From: Dmitry Kazakov <dimula73@gmail.com> 0003 Date: Wed, 15 May 2019 19:54:52 +0300 0004 Subject: [PATCH 12/47] Add workaround for handling table press correctly in 0005 WinInk mode 0006 0007 Original problem: widgets do not get synthesized mouse-down and 0008 mouse-press events until the stylus is released 0009 0010 Reason: if the app accepts the event, WndProc should report 0011 that to the system (by returning true). This is the only way to 0012 prevent Windows from starting some system-wide gestures, like 0013 click+hold -> right button click. If we ignore the event, then 0014 OS postpones all synthesized mouse events until the entire gesture 0015 is completed. 0016 0017 The patch implements a "hackish" workaround for the original problem 0018 by using the following rules: 0019 0020 1) All tablet-move events are ignored (without synthesized mouse events 0021 OS doesn't generate any Enter/Leave events) 0022 0023 2) All not-accepted tablet press- and release-events and also reported as 0024 ignored (without it D&D doesn't work). 0025 0026 3) All accepted tablet press- and release-events are reported as "accepted", 0027 **but** we artificially synthesize mouse events for them. 0028 0029 TODO: there are still one problem: 0030 0031 1) Perhaps this synthesizeMouseEvent() is not needed at all. But we should 0032 first check if Qt relies on these synthesized messages anywhere in the 0033 code or not. 0034 0035 See bug: https://bugs.kde.org/show_bug.cgi?id=406668 0036 --- 0037 src/gui/kernel/qguiapplication.cpp | 1 + 0038 src/gui/kernel/qwindowsysteminterface.cpp | 20 ++--- 0039 src/gui/kernel/qwindowsysteminterface.h | 8 +- 0040 .../windows/qwindowspointerhandler.cpp | 88 ++++++++++++++++++- 0041 4 files changed, 99 insertions(+), 18 deletions(-) 0042 0043 diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp 0044 index 0f574ff526..a86bd22588 100644 0045 --- a/src/gui/kernel/qguiapplication.cpp 0046 +++ b/src/gui/kernel/qguiapplication.cpp 0047 @@ -2593,6 +2593,7 @@ void QGuiApplicationPrivate::processTabletEvent(QWindowSystemInterfacePrivate::T 0048 tabletEvent.setTimestamp(e->timestamp); 0049 QGuiApplication::sendSpontaneousEvent(window, &tabletEvent); 0050 pointData.state = e->buttons; 0051 + e->eventAccepted = tabletEvent.isAccepted(); 0052 if (!tabletEvent.isAccepted() 0053 && !QWindowSystemInterfacePrivate::TabletEvent::platformSynthesizesMouse 0054 && qApp->testAttribute(Qt::AA_SynthesizeMouseForUnhandledTabletEvents)) { 0055 diff --git a/src/gui/kernel/qwindowsysteminterface.cpp b/src/gui/kernel/qwindowsysteminterface.cpp 0056 index 2900cb40ea..62f309a1da 100644 0057 --- a/src/gui/kernel/qwindowsysteminterface.cpp 0058 +++ b/src/gui/kernel/qwindowsysteminterface.cpp 0059 @@ -954,7 +954,7 @@ void QWindowSystemInterfacePrivate::TabletEvent::setPlatformSynthesizesMouse(boo 0060 platformSynthesizesMouse = v; 0061 } 0062 0063 -void QWindowSystemInterface::handleTabletEvent(QWindow *window, ulong timestamp, const QPointF &local, const QPointF &global, 0064 +bool QWindowSystemInterface::handleTabletEvent(QWindow *window, ulong timestamp, const QPointF &local, const QPointF &global, 0065 int device, int pointerType, Qt::MouseButtons buttons, qreal pressure, int xTilt, int yTilt, 0066 qreal tangentialPressure, qreal rotation, int z, qint64 uid, 0067 Qt::KeyboardModifiers modifiers) 0068 @@ -965,36 +965,36 @@ void QWindowSystemInterface::handleTabletEvent(QWindow *window, ulong timestamp, 0069 QHighDpi::fromNativePixels(global, window), 0070 device, pointerType, buttons, pressure, 0071 xTilt, yTilt, tangentialPressure, rotation, z, uid, modifiers); 0072 - QWindowSystemInterfacePrivate::handleWindowSystemEvent(e); 0073 + return QWindowSystemInterfacePrivate::handleWindowSystemEvent<QWindowSystemInterface::SynchronousDelivery>(e); 0074 } 0075 0076 -void QWindowSystemInterface::handleTabletEvent(QWindow *window, const QPointF &local, const QPointF &global, 0077 +bool QWindowSystemInterface::handleTabletEvent(QWindow *window, const QPointF &local, const QPointF &global, 0078 int device, int pointerType, Qt::MouseButtons buttons, qreal pressure, int xTilt, int yTilt, 0079 qreal tangentialPressure, qreal rotation, int z, qint64 uid, 0080 Qt::KeyboardModifiers modifiers) 0081 { 0082 ulong time = QWindowSystemInterfacePrivate::eventTime.elapsed(); 0083 - handleTabletEvent(window, time, local, global, device, pointerType, buttons, pressure, 0084 + return handleTabletEvent(window, time, local, global, device, pointerType, buttons, pressure, 0085 xTilt, yTilt, tangentialPressure, rotation, z, uid, modifiers); 0086 } 0087 0088 #if QT_DEPRECATED_SINCE(5, 10) 0089 -void QWindowSystemInterface::handleTabletEvent(QWindow *window, ulong timestamp, bool down, const QPointF &local, const QPointF &global, 0090 +bool QWindowSystemInterface::handleTabletEvent(QWindow *window, ulong timestamp, bool down, const QPointF &local, const QPointF &global, 0091 int device, int pointerType, qreal pressure, int xTilt, int yTilt, 0092 qreal tangentialPressure, qreal rotation, int z, qint64 uid, 0093 Qt::KeyboardModifiers modifiers) 0094 { 0095 - handleTabletEvent(window, timestamp, local, global, device, pointerType, (down ? Qt::LeftButton : Qt::NoButton), pressure, 0096 - xTilt, yTilt, tangentialPressure, rotation, z, uid, modifiers); 0097 + return handleTabletEvent(window, timestamp, local, global, device, pointerType, (down ? Qt::LeftButton : Qt::NoButton), pressure, 0098 + xTilt, yTilt, tangentialPressure, rotation, z, uid, modifiers); 0099 } 0100 0101 -void QWindowSystemInterface::handleTabletEvent(QWindow *window, bool down, const QPointF &local, const QPointF &global, 0102 +bool QWindowSystemInterface::handleTabletEvent(QWindow *window, bool down, const QPointF &local, const QPointF &global, 0103 int device, int pointerType, qreal pressure, int xTilt, int yTilt, 0104 qreal tangentialPressure, qreal rotation, int z, qint64 uid, 0105 Qt::KeyboardModifiers modifiers) 0106 { 0107 - handleTabletEvent(window, local, global, device, pointerType, (down ? Qt::LeftButton : Qt::NoButton), pressure, 0108 - xTilt, yTilt, tangentialPressure, rotation, z, uid, modifiers); 0109 + return handleTabletEvent(window, local, global, device, pointerType, (down ? Qt::LeftButton : Qt::NoButton), pressure, 0110 + xTilt, yTilt, tangentialPressure, rotation, z, uid, modifiers); 0111 } 0112 #endif // QT_DEPRECATED_SINCE(5, 10) 0113 0114 diff --git a/src/gui/kernel/qwindowsysteminterface.h b/src/gui/kernel/qwindowsysteminterface.h 0115 index 66af163f05..8d1e7597a1 100644 0116 --- a/src/gui/kernel/qwindowsysteminterface.h 0117 +++ b/src/gui/kernel/qwindowsysteminterface.h 0118 @@ -247,20 +247,20 @@ public: 0119 static void handleFileOpenEvent(const QString& fileName); 0120 static void handleFileOpenEvent(const QUrl &url); 0121 0122 - static void handleTabletEvent(QWindow *window, ulong timestamp, const QPointF &local, const QPointF &global, 0123 + static bool handleTabletEvent(QWindow *window, ulong timestamp, const QPointF &local, const QPointF &global, 0124 int device, int pointerType, Qt::MouseButtons buttons, qreal pressure, int xTilt, int yTilt, 0125 qreal tangentialPressure, qreal rotation, int z, qint64 uid, 0126 Qt::KeyboardModifiers modifiers = Qt::NoModifier); 0127 - static void handleTabletEvent(QWindow *window, const QPointF &local, const QPointF &global, 0128 + static bool handleTabletEvent(QWindow *window, const QPointF &local, const QPointF &global, 0129 int device, int pointerType, Qt::MouseButtons buttons, qreal pressure, int xTilt, int yTilt, 0130 qreal tangentialPressure, qreal rotation, int z, qint64 uid, 0131 Qt::KeyboardModifiers modifiers = Qt::NoModifier); 0132 #if QT_DEPRECATED_SINCE(5, 10) 0133 - QT_DEPRECATED static void handleTabletEvent(QWindow *window, ulong timestamp, bool down, const QPointF &local, const QPointF &global, 0134 + QT_DEPRECATED static bool handleTabletEvent(QWindow *window, ulong timestamp, bool down, const QPointF &local, const QPointF &global, 0135 int device, int pointerType, qreal pressure, int xTilt, int yTilt, 0136 qreal tangentialPressure, qreal rotation, int z, qint64 uid, 0137 Qt::KeyboardModifiers modifiers = Qt::NoModifier); 0138 - QT_DEPRECATED static void handleTabletEvent(QWindow *window, bool down, const QPointF &local, const QPointF &global, 0139 + QT_DEPRECATED static bool handleTabletEvent(QWindow *window, bool down, const QPointF &local, const QPointF &global, 0140 int device, int pointerType, qreal pressure, int xTilt, int yTilt, 0141 qreal tangentialPressure, qreal rotation, int z, qint64 uid, 0142 Qt::KeyboardModifiers modifiers = Qt::NoModifier); 0143 diff --git a/src/plugins/platforms/windows/qwindowspointerhandler.cpp b/src/plugins/platforms/windows/qwindowspointerhandler.cpp 0144 index 71a09304c5..07a5722de9 100644 0145 --- a/src/plugins/platforms/windows/qwindowspointerhandler.cpp 0146 +++ b/src/plugins/platforms/windows/qwindowspointerhandler.cpp 0147 @@ -543,6 +543,58 @@ bool QWindowsPointerHandler::translateTouchEvent(QWindow *window, HWND hwnd, 0148 return false; // Allow mouse messages to be generated. 0149 } 0150 0151 +void synthesizeMouseEvent(QEvent::Type type, Qt::MouseButton button, const POINTER_PEN_INFO &penInfo) 0152 +{ 0153 + // Update the cursor position 0154 + BOOL result = SetCursorPos(penInfo.pointerInfo.ptPixelLocationRaw.x, penInfo.pointerInfo.ptPixelLocationRaw.y); 0155 + if (!result) { 0156 + qCDebug(lcQpaEvents).noquote().nospace() << showbase 0157 + << __FUNCTION__ << "SetCursorPos failed, err" << GetLastError(); 0158 + return; 0159 + } 0160 + // Send mousebutton down/up events. Windows stores the button state. 0161 + DWORD inputDataFlags = 0; 0162 + switch (type) { 0163 + case QEvent::TabletPress: 0164 + switch (button) { 0165 + case Qt::LeftButton: 0166 + inputDataFlags = MOUSEEVENTF_LEFTDOWN; 0167 + break; 0168 + case Qt::RightButton: 0169 + inputDataFlags = MOUSEEVENTF_RIGHTDOWN; 0170 + break; 0171 + default: 0172 + return; 0173 + } 0174 + break; 0175 + case QEvent::TabletRelease: 0176 + switch (button) { 0177 + case Qt::LeftButton: 0178 + inputDataFlags = MOUSEEVENTF_LEFTUP; 0179 + break; 0180 + case Qt::RightButton: 0181 + inputDataFlags = MOUSEEVENTF_RIGHTUP; 0182 + break; 0183 + default: 0184 + return; 0185 + } 0186 + break; 0187 + case QEvent::TabletMove: 0188 + default: 0189 + return; 0190 + } 0191 + INPUT inputData = {}; 0192 + inputData.type = INPUT_MOUSE; 0193 + inputData.mi.dwFlags = inputDataFlags; 0194 + inputData.mi.dwExtraInfo = 0xFF515700 | 0x01; // https://msdn.microsoft.com/en-us/library/windows/desktop/ms703320%28v=vs.85%29.aspx 0195 + UINT result2 = SendInput(1, &inputData, sizeof(inputData)); 0196 + if (result2 != 1) { 0197 + qCDebug(lcQpaEvents).noquote().nospace() << showbase 0198 + << __FUNCTION__ << "SendInput failed, err" << GetLastError(); 0199 + return; 0200 + } 0201 +} 0202 + 0203 bool QWindowsPointerHandler::translatePenEvent(QWindow *window, HWND hwnd, QtWindows::WindowsEventType et, 0204 MSG msg, PVOID vPenInfo) 0205 { 0206 @@ -633,10 +685,38 @@ bool QWindowsPointerHandler::translatePenEvent(QWindow *window, HWND hwnd, QtWin 0207 } 0208 const Qt::KeyboardModifiers keyModifiers = QWindowsKeyMapper::queryKeyboardModifiers(); 0209 0210 - QWindowSystemInterface::handleTabletEvent(target, localPos, hiResGlobalPos, device, type, mouseButtons, 0211 - pressure, xTilt, yTilt, tangentialPressure, rotation, z, 0212 - sourceDevice, keyModifiers); 0213 - return false; // Allow mouse messages to be generated. 0214 + const Qt::MouseButtons oldButtons = QGuiApplicationPrivate::tabletDevicePoint(sourceDevice).state; 0215 + 0216 + const bool accepted = 0217 + QWindowSystemInterface::handleTabletEvent(target, localPos, hiResGlobalPos, device, type, mouseButtons, 0218 + pressure, xTilt, yTilt, tangentialPressure, rotation, z, 0219 + sourceDevice, keyModifiers); 0220 + 0221 + const Qt::MouseButtons changedButtons = 0222 + oldButtons ^ QGuiApplicationPrivate::tabletDevicePoint(sourceDevice).state; 0223 + 0224 + Qt::MouseButton pressedButton = Qt::NoButton; 0225 + 0226 + const QVector<Qt::MouseButton> supportedButtons = 0227 + {Qt::LeftButton, Qt::RightButton, Qt::MiddleButton}; 0228 + 0229 + for (Qt::MouseButton button : supportedButtons) { 0230 + if (changedButtons & button) { 0231 + pressedButton = button; 0232 + break; 0233 + } 0234 + } 0235 + 0236 + if (accepted && pressedButton != Qt::NoButton && 0237 + (msg.message == WM_POINTERDOWN || msg.message == WM_POINTERUP)) { 0238 + 0239 + QEvent::Type type = (msg.message == WM_POINTERDOWN) ? QEvent::TabletPress : QEvent::TabletRelease; 0240 + 0241 + synthesizeMouseEvent(type, pressedButton, *penInfo); 0242 + return true; 0243 + } else { 0244 + return false; // Allow mouse messages to be generated by OS 0245 + } 0246 } 0247 } 0248 return true; 0249 -- 0250 2.20.1.windows.1 0251