Warning, /graphics/krita/3rdparty/ext_qt/0026-Fetch-mapped-screen-size-from-the-Wintab-driver.patch is written in an unsupported language. File is not indexed.
0001 From 59dcf9d1c5ba650e354e1c858a445ff44b8dd235 Mon Sep 17 00:00:00 2001 0002 From: Dmitry Kazakov <dimula73@gmail.com> 0003 Date: Sat, 13 Apr 2019 23:24:01 +0300 0004 Subject: [PATCH 07/47] Fetch mapped screen size from the Wintab driver 0005 0006 Some devices, like Microsoft Surface Pro 5, don't map tablet's 0007 input range to the entire virtual screen area, but map it to 0008 the primary display that has actual built-in tablet sensor. 0009 0010 In such cases we should fetch actualy mapped aread from Wintab's 0011 lcSys{Org,Ext}{X,Y} fields and use it for cursor mapping. 0012 0013 If one wants to fall back to the old screen size detection method, 0014 then an environment variable can be set: 0015 0016 QT_IGNORE_WINTAB_MAPPING=1 0017 0018 When the variable is set, the scaling is done via virtual desktop 0019 area only. 0020 0021 If the tablet driver is broken (e.g. Microsoft SP5, when primary 0022 display is set to an external monitor) the user might want to override 0023 mapping completely. Then the following variable can be used: 0024 0025 QT_WINTAB_DESKTOP_RECT=x;y;width;height 0026 0027 Change-Id: Idd8bcf0323ce0811d2ad8976eaed48ad13ac3af8 0028 --- 0029 .../windows/qwindowstabletsupport.cpp | 89 ++++++++++++++++++- 0030 .../platforms/windows/qwindowstabletsupport.h | 13 ++- 0031 2 files changed, 99 insertions(+), 3 deletions(-) 0032 0033 diff --git a/src/plugins/platforms/windows/qwindowstabletsupport.cpp b/src/plugins/platforms/windows/qwindowstabletsupport.cpp 0034 index 6a9fe28e75..15820533c4 100644 0035 --- a/src/plugins/platforms/windows/qwindowstabletsupport.cpp 0036 +++ b/src/plugins/platforms/windows/qwindowstabletsupport.cpp 0037 @@ -53,6 +53,7 @@ 0038 #include <QtCore/qdebug.h> 0039 #include <QtCore/qvarlengtharray.h> 0040 #include <QtCore/qmath.h> 0041 +#include <QtCore/qregularexpression.h> 0042 0043 #include <private/qguiapplication_p.h> 0044 #include <QtCore/private/qsystemlibrary_p.h> 0045 @@ -216,6 +217,10 @@ QWindowsTabletSupport::QWindowsTabletSupport(HWND window, HCTX context) 0046 // Some tablets don't support tilt, check if it is possible, 0047 if (QWindowsTabletSupport::m_winTab32DLL.wTInfo(WTI_DEVICES, DVC_ORIENTATION, &orientation)) 0048 m_tiltSupport = orientation[0].axResolution && orientation[1].axResolution; 0049 + 0050 + connect(qGuiApp, &QGuiApplication::primaryScreenChanged, 0051 + this, &QWindowsTabletSupport::slotPrimaryScreenChanged); 0052 + slotScreenGeometryChanged(); 0053 } 0054 0055 QWindowsTabletSupport::~QWindowsTabletSupport() 0056 @@ -394,6 +399,84 @@ QWindowsTabletDeviceData QWindowsTabletSupport::tabletInit(qint64 uniqueId, UINT 0057 return result; 0058 } 0059 0060 +void QWindowsTabletSupport::slotPrimaryScreenChanged(QScreen *screen) 0061 +{ 0062 + if (m_connectedScreen) 0063 + disconnect(m_connectedScreen, 0, this, 0); 0064 + 0065 + m_connectedScreen = screen; 0066 + 0067 + if (m_connectedScreen) 0068 + connect(m_connectedScreen, &QScreen::virtualGeometryChanged, 0069 + this, &QWindowsTabletSupport::slotScreenGeometryChanged); 0070 + 0071 + slotScreenGeometryChanged(); 0072 +} 0073 + 0074 +void QWindowsTabletSupport::slotScreenGeometryChanged() 0075 +{ 0076 + /** 0077 + * Some Wintab implementations map the tablet area to the entire 0078 + * virtual screen, but others (e.g. Microsoft SP5) don't. They 0079 + * may input range to a single (built-in) screen. The logic is 0080 + * quite obvious: when the screen has integrated tablet device, 0081 + * one cannot map this tablet device to another display. 0082 + * 0083 + * For such devices, we should always request mapped area from 0084 + * lcSys{Org,Ext}{X,Y} fields and use it accordingly. 0085 + */ 0086 + 0087 + LOGCONTEXT lc; 0088 + QWindowsTabletSupport::m_winTab32DLL.wTInfo(WTI_DEFSYSCTX, 0, &lc); 0089 + m_wintabScreenGeometry = QRect(lc.lcSysOrgX, lc.lcSysOrgY, lc.lcSysExtX, lc.lcSysExtY); 0090 + 0091 + qCDebug(lcQpaTablet) << "Updated tablet mapping: " << m_wintabScreenGeometry; 0092 + if (QGuiApplication::primaryScreen()) { 0093 + qCDebug(lcQpaTablet) << " real desktop geometry: " << QWindowsScreen::virtualGeometry(QGuiApplication::primaryScreen()->handle()); 0094 + } 0095 +} 0096 + 0097 +void QWindowsTabletSupport::updateEffectiveScreenGeometry() 0098 +{ 0099 + QRect customGeometry; 0100 + bool dontUseWintabDesktopRect = false; 0101 + 0102 + const QString geometry = qEnvironmentVariable("QT_WINTAB_DESKTOP_RECT"); 0103 + if (!geometry.isEmpty()) { 0104 + QString tmp = QString::fromLatin1("([+-]?\\d+);([+-]?\\d+);(\\d+);(\\d+)"); 0105 + 0106 + QRegularExpression rex(tmp); 0107 + QRegularExpressionMatch match = rex.match(geometry); 0108 + 0109 + if (match.hasMatch()) { 0110 + customGeometry.setRect(match.captured(1).toInt(), 0111 + match.captured(2).toInt(), 0112 + match.captured(3).toInt(), 0113 + match.captured(4).toInt()); 0114 + 0115 + qCDebug(lcQpaTablet) << "apply QT_WINTAB_DESKTOP_RECT:" << customGeometry; 0116 + } else { 0117 + qCWarning(lcQpaTablet) << "failed to parse QT_WINTAB_DESKTOP_RECT:" << geometry; 0118 + } 0119 + } 0120 + 0121 + if (qEnvironmentVariableIsSet("QT_IGNORE_WINTAB_MAPPING")) { 0122 + if (!customGeometry.isValid()) { 0123 + qCDebug(lcQpaTablet) << "fallback mapping is requested via QT_IGNORE_WINTAB_MAPPING"; 0124 + } else { 0125 + qCWarning(lcQpaTablet) << "ignoring QT_IGNORE_WINTAB_MAPPING, because QT_WINTAB_DESKTOP_RECT is set"; 0126 + } 0127 + dontUseWintabDesktopRect = true; 0128 + } 0129 + 0130 + m_effectiveScreenGeometry = 0131 + !customGeometry.isValid() ? 0132 + (dontUseWintabDesktopRect ? 0133 + QWindowsScreen::virtualGeometry(QGuiApplication::primaryScreen()->handle()) : 0134 + m_wintabScreenGeometry) : 0135 + customGeometry; 0136 +} 0137 + 0138 bool QWindowsTabletSupport::translateTabletProximityEvent(WPARAM /* wParam */, LPARAM lParam) 0139 { 0140 PACKET proximityBuffer[1]; // we are only interested in the first packet in this case 0141 @@ -421,6 +504,8 @@ bool QWindowsTabletSupport::translateTabletProximityEvent(WPARAM /* wParam */, L 0142 if (!totalPacks) 0143 return false; 0144 0145 + updateEffectiveScreenGeometry(); 0146 + 0147 const UINT currentCursor = proximityBuffer[0].pkCursor; 0148 UINT physicalCursorId; 0149 QWindowsTabletSupport::m_winTab32DLL.wTInfo(WTI_CURSORS + currentCursor, CSR_PHYSID, &physicalCursorId); 0150 @@ -537,8 +622,8 @@ bool QWindowsTabletSupport::translateTabletPacketEvent() 0151 // in which case we snap the position to the mouse position. 0152 // It seems there is no way to find out the mode programmatically, the LOGCONTEXT orgX/Y/Ext 0153 // area is always the virtual desktop. 0154 - const QRect virtualDesktopArea = 0155 - QWindowsScreen::virtualGeometry(QGuiApplication::primaryScreen()->handle()); 0156 + 0157 + const QRect virtualDesktopArea = m_effectiveScreenGeometry; 0158 0159 if (QWindowsContext::verbose > 1) { 0160 qCDebug(lcQpaTablet) << __FUNCTION__ << "processing" << packetCount 0161 diff --git a/src/plugins/platforms/windows/qwindowstabletsupport.h b/src/plugins/platforms/windows/qwindowstabletsupport.h 0162 index 8f97982308..fe7e7815d6 100644 0163 --- a/src/plugins/platforms/windows/qwindowstabletsupport.h 0164 +++ b/src/plugins/platforms/windows/qwindowstabletsupport.h 0165 @@ -45,7 +45,9 @@ 0166 0167 #include <QtCore/qvector.h> 0168 #include <QtCore/qpoint.h> 0169 +#include <QtCore/qrect.h> 0170 #include <QtCore/qhash.h> 0171 +#include <QtCore/qobject.h> 0172 0173 #include <wintab.h> 0174 0175 @@ -56,6 +58,7 @@ QT_BEGIN_NAMESPACE 0176 class QDebug; 0177 class QWindow; 0178 class QRect; 0179 +class QScreen; 0180 0181 struct QWindowsWinTab32DLL 0182 { 0183 @@ -108,7 +111,7 @@ struct QWindowsTabletDeviceData 0184 QDebug operator<<(QDebug d, const QWindowsTabletDeviceData &t); 0185 #endif 0186 0187 -class QWindowsTabletSupport 0188 +class QWindowsTabletSupport : public QObject 0189 { 0190 Q_DISABLE_COPY(QWindowsTabletSupport) 0191 0192 @@ -141,9 +144,14 @@ public: 0193 int absoluteRange() const { return m_absoluteRange; } 0194 void setAbsoluteRange(int a) { m_absoluteRange = a; } 0195 0196 +private Q_SLOTS: 0197 + void slotPrimaryScreenChanged(QScreen *screen); 0198 + void slotScreenGeometryChanged(); 0199 + 0200 private: 0201 unsigned options() const; 0202 QWindowsTabletDeviceData tabletInit(qint64 uniqueId, UINT cursorType) const; 0203 + void updateEffectiveScreenGeometry(); 0204 0205 static QWindowsWinTab32DLL m_winTab32DLL; 0206 const HWND m_window; 0207 @@ -154,6 +162,9 @@ private: 0208 int m_currentDevice = -1; 0209 Mode m_mode = PenMode; 0210 State m_state = PenUp; 0211 + QScreen *m_connectedScreen = 0; 0212 + QRect m_wintabScreenGeometry; 0213 + QRect m_effectiveScreenGeometry; 0214 }; 0215 0216 QT_END_NAMESPACE 0217 -- 0218 2.20.1.windows.1 0219