[PATCH xf86-input-libinput] Expose tablet pad modes as properties

Peter Hutterer peter.hutterer at who-t.net
Fri Jul 8 04:07:23 UTC 2016


There is not good wire protocol for pad modes so instead we just export the
information via properties. One property to tell us how many groups and how
many modes each group has. One property for the current mode of each group.
And three properties to tell us which group each button, ring and strip is in.

Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
---
First attempt, I don't really know how else to expose this, or, tbh, whether
it's even worth exposing...

 include/libinput-properties.h |  28 ++++++
 src/xf86libinput.c            | 208 +++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 233 insertions(+), 3 deletions(-)

diff --git a/include/libinput-properties.h b/include/libinput-properties.h
index d117729..c0a4471 100644
--- a/include/libinput-properties.h
+++ b/include/libinput-properties.h
@@ -142,4 +142,32 @@
  * If disabled, horizontal scroll events are discarded */
 #define LIBINPUT_PROP_HORIZ_SCROLL_ENABLED "libinput Horizonal Scroll Enabled"
 
+/* Number of modes each pad mode group has available: CARD8, one for each
+ * pad mode group, read-only.
+ */
+#define LIBINPUT_PROP_TABLET_PAD_MODE_GROUPS_AVAILABLE "libinput Pad Mode Groups Modes Available"
+
+/* Mode each pad mode group is currently in: CARD8, one for each pad mode
+ * group, read-only.
+ */
+#define LIBINPUT_PROP_TABLET_PAD_MODE_GROUPS "libinput Pad Mode Groups Modes"
+
+/* The association of each logical button with the pad mode group: INT8,
+ * one for each logical button. If set to -1 the button cannot be associated
+ * with a mode group. read-only
+ */
+#define LIBINPUT_PROP_TABLET_PAD_MODE_GROUP_BUTTONS "libinput Pad Mode Group Buttons"
+
+/* The association of each logical strip with the pad mode group: INT8,
+ * one for each logical strip. If set to -1 the strip cannot be associated
+ * with a mode group. read-only
+ */
+#define LIBINPUT_PROP_TABLET_PAD_MODE_GROUP_STRIPS "libinput Pad Mode Group Strips"
+
+/* The association of each logical ring with the pad mode group: INT8,
+ * one for each logical ring. If set to -1 the ring cannot be associated
+ * with a mode group. read-only
+ */
+#define LIBINPUT_PROP_TABLET_PAD_MODE_GROUP_RINGS "libinput Pad Mode Group Rings"
+
 #endif /* _LIBINPUT_PROPERTIES_H_ */
diff --git a/src/xf86libinput.c b/src/xf86libinput.c
index 45385f7..fff59b3 100644
--- a/src/xf86libinput.c
+++ b/src/xf86libinput.c
@@ -158,6 +158,8 @@ struct xf86libinput {
 	struct xorg_list shared_device_link;
 
 	struct libinput_tablet_tool *tablet_tool;
+
+	bool allow_mode_group_updates;
 };
 
 enum hotplug_when {
@@ -170,6 +172,9 @@ xf86libinput_create_subdevice(InputInfoPtr pInfo,
 			      uint32_t capabilities,
 			      enum hotplug_when,
 			      XF86OptionPtr extra_opts);
+static inline void
+update_mode_prop(InputInfoPtr pInfo,
+		 struct libinput_event_tablet_pad *event);
 
 static inline int
 use_server_fd(const InputInfoPtr pInfo) {
@@ -1558,18 +1563,24 @@ xf86libinput_handle_tablet_pad_button(InputInfoPtr pInfo,
 {
 	DeviceIntPtr dev = pInfo->dev;
 	struct xf86libinput *driver_data = pInfo->private;
-	int button;
+	struct libinput_tablet_pad_mode_group *group;
+	int button, b;
 	int is_press;
 
 	if ((driver_data->capabilities & CAP_TABLET_PAD) == 0)
 		return;
 
-	button = 1 + libinput_event_tablet_pad_get_button_number(event);
+	b = libinput_event_tablet_pad_get_button_number(event);
+	button = 1 + b;
 	if (button > 3)
 		button += 4; /* offset by scroll buttons */
 	is_press = (libinput_event_tablet_pad_get_button_state(event) == LIBINPUT_BUTTON_STATE_PRESSED);
 
 	xf86PostButtonEvent(dev, Relative, button, is_press, 0, 0);
+
+	group = libinput_event_tablet_pad_get_mode_group(event);
+	if (libinput_tablet_pad_mode_group_button_is_toggle(group, b))
+		update_mode_prop(pInfo, event);
 }
 
 static void
@@ -2749,6 +2760,11 @@ static Atom prop_middle_emulation;
 static Atom prop_middle_emulation_default;
 static Atom prop_disable_while_typing;
 static Atom prop_disable_while_typing_default;
+static Atom prop_mode_groups_available;
+static Atom prop_mode_groups;
+static Atom prop_mode_groups_buttons;
+static Atom prop_mode_groups_rings;
+static Atom prop_mode_groups_strips;
 
 /* driver properties */
 static Atom prop_draglock;
@@ -2759,6 +2775,52 @@ static Atom prop_float;
 static Atom prop_device;
 static Atom prop_product_id;
 
+static inline void
+update_mode_prop(InputInfoPtr pInfo,
+		 struct libinput_event_tablet_pad *event)
+{
+	struct xf86libinput *driver_data = pInfo->private;
+	struct libinput_tablet_pad_mode_group *group;
+	unsigned int mode;
+	unsigned int idx;
+	XIPropertyValuePtr val;
+	int rc;
+	unsigned char groups[4] = {0};
+
+	rc = XIGetDeviceProperty(pInfo->dev,
+				 prop_mode_groups,
+				 &val);
+	if (rc != Success ||
+	    val->format != 8 ||
+	    val->size <= 0)
+		return;
+
+	memcpy(groups, (unsigned char*)val->data, val->size);
+
+	group = libinput_event_tablet_pad_get_mode_group(event);
+	mode = libinput_event_tablet_pad_get_mode(event);
+	idx = libinput_tablet_pad_mode_group_get_index(group);
+	if (idx >= ARRAY_SIZE(groups))
+		return;
+
+	if (groups[idx] == mode)
+		return;
+
+	groups[idx] = mode;
+
+	driver_data->allow_mode_group_updates = true;
+	rc = XIChangeDeviceProperty(pInfo->dev,
+				    prop_mode_groups,
+				    XA_INTEGER, 8,
+				    PropModeReplace,
+				    val->size,
+				    groups,
+				    TRUE);
+	driver_data->allow_mode_group_updates = false;
+	if (rc != Success)
+		return;
+}
+
 static inline BOOL
 xf86libinput_check_device (DeviceIntPtr dev,
 			   Atom atom)
@@ -3410,6 +3472,15 @@ LibinputSetProperty(DeviceIntPtr dev, Atom atom, XIPropertyValuePtr val,
 		rc = LibinputSetPropertyDragLockButtons(dev, atom, val, checkonly);
 	else if (atom == prop_horiz_scroll)
 		rc = LibinputSetPropertyHorizScroll(dev, atom, val, checkonly);
+	else if (atom == prop_mode_groups) {
+		InputInfoPtr pInfo = dev->public.devicePrivate;
+		struct xf86libinput *driver_data = pInfo->private;
+
+		if (driver_data->allow_mode_group_updates)
+			return Success;
+		else
+			return BadAccess;
+	}
 	else if (atom == prop_device || atom == prop_product_id ||
 		 atom == prop_tap_default ||
 		 atom == prop_tap_drag_default ||
@@ -3427,7 +3498,11 @@ LibinputSetProperty(DeviceIntPtr dev, Atom atom, XIPropertyValuePtr val,
 		 atom == prop_click_method_default ||
 		 atom == prop_click_methods_available ||
 		 atom == prop_middle_emulation_default ||
-		 atom == prop_disable_while_typing_default)
+		 atom == prop_disable_while_typing_default ||
+		 atom == prop_mode_groups_available ||
+		 atom == prop_mode_groups_buttons ||
+		 atom == prop_mode_groups_rings ||
+		 atom == prop_mode_groups_strips)
 		return BadAccess; /* read-only */
 	else
 		return Success;
@@ -3972,6 +4047,132 @@ LibinputInitDisableWhileTypingProperty(DeviceIntPtr dev,
 }
 
 static void
+LibinputInitModeGroupProperties(DeviceIntPtr dev,
+				       struct xf86libinput *driver_data,
+				       struct libinput_device *device)
+{
+	struct libinput_tablet_pad_mode_group *group;
+	int ngroups, nmodes, mode;
+	int nbuttons, nstrips, nrings;
+	unsigned char groups[4] = {0},
+		      current[4] = {0},
+		      associations[MAX_BUTTONS] = {0};
+	int g, b, r, s;
+
+	if (!libinput_device_has_capability(device, LIBINPUT_DEVICE_CAP_TABLET_PAD))
+		return;
+
+	ngroups = libinput_device_tablet_pad_get_num_mode_groups(device);
+	if (ngroups <= 0)
+		return;
+
+	group = libinput_device_tablet_pad_get_mode_group(device, 0);
+	nmodes = libinput_tablet_pad_mode_group_get_num_modes(group);
+	if (ngroups == 1 && nmodes == 1)
+		return;
+
+	ngroups = min(ngroups, ARRAY_SIZE(groups));
+	for (g = 0; g < ngroups; g++) {
+		group = libinput_device_tablet_pad_get_mode_group(device, g);
+		nmodes = libinput_tablet_pad_mode_group_get_num_modes(group);
+		mode = libinput_tablet_pad_mode_group_get_mode(group);
+
+		groups[g] = nmodes;
+		current[g] = mode;
+	}
+
+	prop_mode_groups_available = LibinputMakeProperty(dev,
+							  LIBINPUT_PROP_TABLET_PAD_MODE_GROUPS_AVAILABLE,
+							  XA_INTEGER,
+							  8,
+							  ngroups,
+							  groups);
+	if (!prop_mode_groups_available)
+		return;
+
+	prop_mode_groups = LibinputMakeProperty(dev,
+						LIBINPUT_PROP_TABLET_PAD_MODE_GROUPS,
+						XA_INTEGER,
+						8,
+						ngroups,
+						current);
+	if (!prop_mode_groups)
+		return;
+
+	for (b = 0; b < ARRAY_SIZE(associations); b++)
+		associations[b] = -1;
+
+	nbuttons = libinput_device_tablet_pad_get_num_buttons(device);
+	for (b = 0; b < nbuttons; b++) {
+		/* logical buttons exclude scroll wheel buttons */
+		int lb = b <= 3 ? b : b + 4;
+		associations[lb] = -1;
+		for (g = 0; g < ngroups; g++) {
+			group = libinput_device_tablet_pad_get_mode_group(device, g);
+			if (libinput_tablet_pad_mode_group_has_button(group, b)) {
+				associations[lb] = g;
+				break;
+			}
+		}
+	}
+
+	prop_mode_groups_buttons = LibinputMakeProperty(dev,
+							LIBINPUT_PROP_TABLET_PAD_MODE_GROUP_BUTTONS,
+							XA_INTEGER,
+							8,
+							nbuttons,
+							associations);
+	if (!prop_mode_groups_buttons)
+		return;
+
+	nrings = libinput_device_tablet_pad_get_num_rings(device);
+	if (nrings) {
+		for (r = 0; r < nrings; r++) {
+			associations[r] = -1;
+			for (g = 0; g < ngroups; g++) {
+				group = libinput_device_tablet_pad_get_mode_group(device, g);
+				if (libinput_tablet_pad_mode_group_has_ring(group, r)) {
+					associations[r] = g;
+					break;
+				}
+			}
+		}
+
+		prop_mode_groups_rings = LibinputMakeProperty(dev,
+								LIBINPUT_PROP_TABLET_PAD_MODE_GROUP_RINGS,
+								XA_INTEGER,
+								8,
+								nrings,
+								associations);
+		if (!prop_mode_groups_rings)
+			return;
+	}
+
+	nstrips = libinput_device_tablet_pad_get_num_strips(device);
+	if (nstrips) {
+		for (s = 0; s < nstrips; s++) {
+			associations[r] = -1;
+			for (g = 0; g < ngroups; g++) {
+				group = libinput_device_tablet_pad_get_mode_group(device, g);
+				if (libinput_tablet_pad_mode_group_has_strip(group, s)) {
+					associations[s] = g;
+					break;
+				}
+			}
+		}
+
+		prop_mode_groups_strips = LibinputMakeProperty(dev,
+								LIBINPUT_PROP_TABLET_PAD_MODE_GROUP_STRIPS,
+								XA_INTEGER,
+								8,
+								nstrips,
+								associations);
+		if (!prop_mode_groups_strips)
+			return;
+	}
+}
+
+static void
 LibinputInitDragLockProperty(DeviceIntPtr dev,
 			     struct xf86libinput *driver_data)
 {
@@ -4042,6 +4243,7 @@ LibinputInitProperty(DeviceIntPtr dev)
 	LibinputInitClickMethodsProperty(dev, driver_data, device);
 	LibinputInitMiddleEmulationProperty(dev, driver_data, device);
 	LibinputInitDisableWhileTypingProperty(dev, driver_data, device);
+	LibinputInitModeGroupProperties(dev, driver_data, device);
 
 	/* Device node property, read-only  */
 	device_node = driver_data->path;
-- 
2.7.4



More information about the xorg-devel mailing list