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.

[ChangeLog][Platform Specific Changes][X11 / XCB] QTabletEvent
coordinates now come from AbsX/AbsY valuators in the X11 event, in
more precise 32.32 fixed-point format, scaled to fit the virtual
desktop.  It's possible to revert to using the legacy 16.16-format
event_x/event_y coordinates as in previous releases by setting the
QT_XCB_TABLET_LEGACY_COORDINATES environment variable.

Task-number: QTBUG-45375
Fixes: QTBUG-48151
Change-Id: Ie701446b3586296bcb8fb09158f387ba6a7cbf07
Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io>
This commit is contained in:
Dmitry Kazakov 2019-03-10 14:48:58 +03:00 committed by Shawn Rutledge
parent 409e3eab09
commit e453222414

View File

@ -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);
@ -1220,6 +1225,17 @@ void QXcbConnection::xi2ReportTabletEvent(const void *event, TabletData *tabletD
QPointF global(fixed1616ToReal(ev->root_x), fixed1616ToReal(ev->root_y));
double pressure = 0, rotation = 0, tangentialPressure = 0;
int xTilt = 0, yTilt = 0;
static const bool useValuators = !qEnvironmentVariableIsSet("QT_XCB_TABLET_LEGACY_COORDINATES");
// Valuators' values are relative to the physical size of the current virtual
// screen. Therefore we cannot use QScreen/QWindow geometry and should use
// QPlatformWindow/QPlatformScreen instead.
QRect physicalScreenArea;
if (Q_LIKELY(useValuators)) {
const QList<QPlatformScreen *> siblings = window->screen()->handle()->virtualSiblings();
for (const QPlatformScreen *screen : siblings)
physicalScreenArea |= screen->geometry();
}
for (QHash<int, TabletData::ValuatorClassInfo>::iterator it = tabletData->valuatorInfo.begin(),
ite = tabletData->valuatorInfo.end(); it != ite; ++it) {
@ -1228,6 +1244,20 @@ 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:
if (Q_LIKELY(useValuators)) {
const qreal value = scaleOneValuator(normalizedValue, physicalScreenArea.x(), physicalScreenArea.width());
global.setX(value);
local.setX(value - window->handle()->geometry().x());
}
break;
case QXcbAtom::AbsY:
if (Q_LIKELY(useValuators)) {
qreal value = scaleOneValuator(normalizedValue, physicalScreenArea.y(), physicalScreenArea.height());
global.setY(value);
local.setY(value - window->handle()->geometry().y());
}
break;
case QXcbAtom::AbsPressure:
pressure = normalizedValue;
break;