Fix T38190: Linux tablet: Issue with XInput/GHOST?

With edits by Campbell, thanks!

Looks like in some cases (driver dependent?), `XDeviceMotionEvent` get generated with only part of expected data
(e.g. only x coordinate, only pressure, etc.), data which did not change since last event being NULL.
We know which data to actually handle with `XDeviceMotionEvent.first_axis` and `XDeviceMotionEvent.axes_count` values.

Reviewed by: campbellbarton

Differential Revision: https://developer.blender.org/D208
This commit is contained in:
Bastien Montagne 2014-01-13 17:50:12 +01:00
parent 02386bd1e3
commit 75ab57efed
Notes: blender-bot 2023-02-14 11:21:34 +01:00
Referenced by issue #38190, Linux tablet: Issue with XInput/GHOST?
1 changed files with 31 additions and 8 deletions

View File

@ -1148,21 +1148,44 @@ GHOST_SystemX11::processEvent(XEvent *xe)
#ifdef WITH_X11_XINPUT
if (xe->type == m_xtablet.MotionEvent) {
XDeviceMotionEvent *data = (XDeviceMotionEvent *)xe;
const unsigned char axis_first = data->first_axis;
const unsigned char axes_end = axis_first + data->axes_count; /* after the last */
int axis_value;
/* stroke might begin without leading ProxyIn event,
* this happens when window is opened when stylus is already hovering
* around tablet surface */
setTabletMode(this, window, data->deviceid);
window->GetTabletData()->Pressure =
data->axis_data[2] / ((float)m_xtablet.PressureLevels);
/* Note: This event might be generated with incomplete dataset (don't exactly know why, looks like in
* some cases, if the value does not change, it is not included in subsequent XDeviceMotionEvent
* events). So we have to check which values this event actually contains!
*/
#define AXIS_VALUE_GET(axis, val) ((axis_first <= axis && axes_end > axis) && ((void)(val = data->axis_data[axis]), true))
if (AXIS_VALUE_GET(2, axis_value)) {
window->GetTabletData()->Pressure = axis_value / ((float)m_xtablet.PressureLevels);
}
/* the (short) cast and the & 0xffff is bizarre and unexplained anywhere,
* but I got garbage data without it. Found it in the xidump.c source --matt
*
* The '& 0xffff' just truncates the value to its two lowest bytes, this probably means
* some drivers do not properly set the whole int value? Since we convert to float afterward,
* I don't think we need to cast to short here, but do not have a device to check this. --mont29
*/
if (AXIS_VALUE_GET(3, axis_value)) {
window->GetTabletData()->Xtilt = (short)(axis_value & 0xffff) /
((float)m_xtablet.XtiltLevels);
}
if (AXIS_VALUE_GET(4, axis_value)) {
window->GetTabletData()->Ytilt = (short)(axis_value & 0xffff) /
((float)m_xtablet.YtiltLevels);
}
#undef AXIS_VALUE_GET
/* the (short) cast and the &0xffff is bizarre and unexplained anywhere,
* but I got garbage data without it. Found it in the xidump.c source --matt */
window->GetTabletData()->Xtilt =
(short)(data->axis_data[3] & 0xffff) / ((float)m_xtablet.XtiltLevels);
window->GetTabletData()->Ytilt =
(short)(data->axis_data[4] & 0xffff) / ((float)m_xtablet.YtiltLevels);
}
else if (xe->type == m_xtablet.ProxInEvent) {
XProximityNotifyEvent *data = (XProximityNotifyEvent *)xe;