Commit 2e037a98 authored by Dmitry Kazakov's avatar Dmitry Kazakov

Fix tablet support in Qt's XCB (on X11 and OSX)

It applies the patches to Qt that synthesize Enter/Leave events
when the tablet event is accepted by the receiver.
parent 9fa12502
From 999992ae79d1bc17bc4d7cbd49a8cd94cfce4e22 Mon Sep 17 00:00:00 2001
From: Dmitry Kazakov <dimula73@gmail.com>
Date: Sun, 10 Mar 2019 14:48:58 +0300
Subject: [PATCH] Fix tablet jitter on X11
We should get the correct stylus position from the valuators,
not from the X11-provided global position. Global position is rounded
to the nearest FP16 values, which is not enough for smooth painting.
---
src/plugins/platforms/xcb/qxcbconnection_xi2.cpp | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
diff --git a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp
index 04ddd3c..8b79f2d 100644
--- a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp
+++ b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp
@@ -1208,6 +1208,11 @@ bool QXcbConnection::xi2HandleTabletEvent(const void *event, TabletData *tabletD
return handled;
}
+inline qreal scaleOneValuator(qreal normValue, qreal screenMin, qreal screenSize)
+{
+ return screenMin + normValue * screenSize;
+}
+
void QXcbConnection::xi2ReportTabletEvent(const void *event, TabletData *tabletData)
{
auto *ev = reinterpret_cast<const qt_xcb_input_device_event_t *>(event);
@@ -1221,6 +1226,8 @@ void QXcbConnection::xi2ReportTabletEvent(const void *event, TabletData *tabletD
double pressure = 0, rotation = 0, tangentialPressure = 0;
int xTilt = 0, yTilt = 0;
+ const QRect screenArea = window->screen()->virtualGeometry();
+
for (QHash<int, TabletData::ValuatorClassInfo>::iterator it = tabletData->valuatorInfo.begin(),
ite = tabletData->valuatorInfo.end(); it != ite; ++it) {
int valuator = it.key();
@@ -1228,6 +1235,18 @@ void QXcbConnection::xi2ReportTabletEvent(const void *event, TabletData *tabletD
xi2GetValuatorValueIfSet(event, classInfo.number, &classInfo.curVal);
double normalizedValue = (classInfo.curVal - classInfo.minVal) / (classInfo.maxVal - classInfo.minVal);
switch (valuator) {
+ case QXcbAtom::AbsX: {
+ const qreal value = scaleOneValuator(normalizedValue, screenArea.x(), screenArea.width());
+ global.rx() = value;
+ local.rx() = value - window->geometry().x();
+ break;
+ }
+ case QXcbAtom::AbsY: {
+ qreal value = scaleOneValuator(normalizedValue, screenArea.y(), screenArea.height());
+ global.ry() = value;
+ local.ry() = value - window->geometry().y();
+ break;
+ }
case QXcbAtom::AbsPressure:
pressure = normalizedValue;
break;
--
2.7.4
From 421860a79b6cab0ca67884314aadd9a2e2ece55f Mon Sep 17 00:00:00 2001
From: Dmitry Kazakov <dimula73@gmail.com>
Date: Sun, 10 Mar 2019 14:51:28 +0300
Subject: [PATCH] Add an ID for recognition of UGEE tablets
---
src/plugins/platforms/xcb/qxcbconnection_xi2.cpp | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp
index 8b79f2d..b8a83ba 100644
--- a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp
+++ b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp
@@ -240,6 +240,10 @@ void QXcbConnection::xi2SetupDevice(void *info, bool removeExisting)
} else if (name.contains("uc-logic") && isTablet) {
tabletData.pointerType = QTabletEvent::Pen;
dbgType = QLatin1String("pen");
+ } else if (name.contains("ugee")) {
+ isTablet = true;
+ tabletData.pointerType = QTabletEvent::Pen;
+ dbgType = QLatin1String("pen");
} else {
isTablet = false;
}
--
2.7.4
From 2365cd9067491214b4bc27b193813d9a5f527755 Mon Sep 17 00:00:00 2001
From: Dmitry Kazakov <dimula73@gmail.com>
Date: Sun, 10 Mar 2019 19:41:33 +0300
Subject: [PATCH] Synthesize Enter/LeaveEvent when QTabletEvent is accepted by
the receiver
When the tablet event is accepted, then Qt doesn't synthesize a mouse
event, it means that QApplicationPrivate::sendMouseEvent() will not be
called, and, therefore, enter/leave events will not be dispatched.
The patch looks a bit hackish. Ideally, the synthesize should happen
in QGuiApplicationPrivate::processTabletEvent(), which takes the decision
about synthesizing mouse events. But there is not enough information
on this level: neither qt_last_mouse_receiver nor the reciever widget
are known at this stage.
---
src/widgets/kernel/qwidgetwindow.cpp | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/src/widgets/kernel/qwidgetwindow.cpp b/src/widgets/kernel/qwidgetwindow.cpp
index 991a05f..cafb79e 100644
--- a/src/widgets/kernel/qwidgetwindow.cpp
+++ b/src/widgets/kernel/qwidgetwindow.cpp
@@ -1053,6 +1053,11 @@ void QWidgetWindow::handleTabletEvent(QTabletEvent *event)
event->setAccepted(ev.isAccepted());
}
+ if (event->isAccepted() && widget != qt_last_mouse_receiver) {
+ QApplicationPrivate::dispatchEnterLeave(widget, qt_last_mouse_receiver, event->globalPos());
+ qt_last_mouse_receiver = widget;
+ }
+
if (event->type() == QEvent::TabletRelease && event->buttons() == Qt::NoButton)
qt_tablet_target = 0;
}
--
2.7.4
......@@ -58,9 +58,12 @@ elseif (NOT APPLE)
DOWNLOAD_DIR ${EXTERNALS_DOWNLOAD_DIR}
URL https://download.qt.io/archive/qt/5.12/5.12.1/single/qt-everywhere-src-5.12.1.tar.xz
URL_HASH SHA1=018b7467faeda9979fe6b4a435214903c3a20018
URL_MD5 c5e275ab0ed7ee61d0f4b82cd471770d
PATCH_COMMAND ${PATCH_COMMAND} -p1 -d qtbase -i ${CMAKE_CURRENT_SOURCE_DIR}/0010-Fix-tablet-jitter-on-X11.patch
COMMAND ${PATCH_COMMAND} -p1 -d qtbase -i ${CMAKE_CURRENT_SOURCE_DIR}/0011-Add-an-ID-for-recognition-of-UGEE-tablets.patch
COMMAND ${PATCH_COMMAND} -p1 -d qtbase -i ${CMAKE_CURRENT_SOURCE_DIR}/0012-Synthesize-Enter-LeaveEvent-when-QTabletEvent-is-acc.patch
CONFIGURE_COMMAND <SOURCE_DIR>/configure -prefix ${EXTPREFIX_qt} -opensource -confirm-license -verbose -nomake examples -skip qt3d -skip qtactiveqt -skip qtcanvas3d -skip qtconnectivity -skip qtgraphicaleffects -skip qtlocation -skip qtwayland -skip qtwebchannel -skip qtwebengine -skip qtwebsockets -skip qtwebview -skip qtandroidextras -skip qtserialport -skip qtdatavis3d -skip qtvirtualkeyboard -skip qtspeech -skip qtsensors -skip qtgamepad -skip qtscxml -skip qtremoteobjects -skip qtxmlpatterns -skip qtnetworkauth -skip qtcharts -skip qtdatavis3d -skip qtgamepad -skip qtpurchasing -skip qtscxml -skip qtserialbus -skip qtspeech -skip qtvirtualkeyboard -xcb
INSTALL_DIR ${EXTPREFIX_qt}
......@@ -162,6 +165,7 @@ else( APPLE )
# NOTE: but no one's holding their breath.
set(ext_qt_PATCH_COMMAND ${PATCH_COMMAND} -p1 -i ${CMAKE_CURRENT_SOURCE_DIR}/macdeploy-qt.diff
COMMAND ${PATCH_COMMAND} -p1 -b -d <SOURCE_DIR>/qtbase -i ${CMAKE_CURRENT_SOURCE_DIR}/mac_standardpaths_qtbug-61159.diff
COMMAND ${PATCH_COMMAND} -p1 -d qtbase -i ${CMAKE_CURRENT_SOURCE_DIR}/0012-Synthesize-Enter-LeaveEvent-when-QTabletEvent-is-acc.patch
#COMMAND ${PATCH_COMMAND} -p1 -b -d <SOURCE_DIR>/qtbase/mkspecs/features/mac -i ${CMAKE_CURRENT_SOURCE_DIR}/mac-default.patch
)
message(STATUS "${EXTPREFIX_qt}:Additional patches injected.")
......@@ -169,7 +173,9 @@ else( APPLE )
# No extra patches will be applied
# NOTE: defaults for some untested scenarios like xcrun fails and xcode_version < 8.
# NOTE: that is uncharted territory and (hopefully) a very unlikely scenario...
set(ext_qt_PATCH_COMMAND ${PATCH_COMMAND} -p1 -i ${CMAKE_CURRENT_SOURCE_DIR}/macdeploy-qt.diff)
set(ext_qt_PATCH_COMMAND ${PATCH_COMMAND} -p1 -i ${CMAKE_CURRENT_SOURCE_DIR}/macdeploy-qt.diff
COMMAND ${PATCH_COMMAND} -p1 -d qtbase -i ${CMAKE_CURRENT_SOURCE_DIR}/0012-Synthesize-Enter-LeaveEvent-when-QTabletEvent-is-acc.patch
)
endif()
# Qt is big - try and parallelize if at all possible
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment