[Bf-blender-cvs] [75ab57e] master: Fix T38190: Linux tablet: Issue with XInput/GHOST?

Bastien Montagne noreply at git.blender.org
Mon Jan 13 17:55:49 CET 2014


Commit: 75ab57efed93204659c626fa8d5aa94837984de4
Author: Bastien Montagne
Date:   Mon Jan 13 17:50:12 2014 +0100
https://developer.blender.org/rB75ab57efed93204659c626fa8d5aa94837984de4

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

===================================================================

M	intern/ghost/intern/GHOST_SystemX11.cpp

===================================================================

diff --git a/intern/ghost/intern/GHOST_SystemX11.cpp b/intern/ghost/intern/GHOST_SystemX11.cpp
index 3b12d91..1d625a5 100644
--- a/intern/ghost/intern/GHOST_SystemX11.cpp
+++ b/intern/ghost/intern/GHOST_SystemX11.cpp
@@ -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;




More information about the Bf-blender-cvs mailing list