[PATCH xf86-input-libinput 2/2] Add properties to change the click method (#89332)

Peter Hutterer peter.hutterer at who-t.net
Wed Feb 25 23:07:57 PST 2015


X.Org Bug 89332 <http://bugs.freedesktop.org/show_bug.cgi?id=89332>

Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
---
 include/libinput-properties.h |   8 +++
 man/libinput.man              |   8 +++
 src/libinput.c                | 160 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 176 insertions(+)

diff --git a/include/libinput-properties.h b/include/libinput-properties.h
index bbc85d0..1d7b416 100644
--- a/include/libinput-properties.h
+++ b/include/libinput-properties.h
@@ -58,4 +58,12 @@
 /* Scroll button for button scrolling: 32-bit int, 1 value */
 #define LIBINPUT_PROP_SCROLL_BUTTON "libinput Button Scrolling Button"
 
+/* Click method: BOOL read-only, 2 values in order buttonareas, clickfinger
+   shows available click methods */
+#define LIBINPUT_PROP_CLICK_METHODS_AVAILABLE "libinput Click Methods Available"
+
+/* Click method: BOOL, 2 values in order buttonareas, clickfinger
+   only one enabled at a time at max */
+#define LIBINPUT_PROP_CLICK_METHOD_ENABLED "libinput Click Method Enabled"
+
 #endif /* _LIBINPUT_PROPERTIES_H_ */
diff --git a/man/libinput.man b/man/libinput.man
index 692d56a..f4e9bed 100644
--- a/man/libinput.man
+++ b/man/libinput.man
@@ -53,6 +53,14 @@ A string of 9 space-separated floating point numbers.
 Sets the calibration matrix to the 3x3 matrix where the first row is (abc),
 the second row is (def) and the third row is (ghi).
 .TP 7
+.BI "Option \*qClickMethod\*q \*q" string \*q
+Enables a click method. Permitted values are
+.BI none,
+.BI buttonareas,
+.BI clickfinger.
+Not all devices support all methods, if an option is unsupported, the
+default click method for this device is used.
+.TP 7
 .BI "Option \*qLeftHanded\*q \*q" bool \*q
 Enables left-handed button orientation, i.e. swapping left and right buttons.
 .TP 7
diff --git a/src/libinput.c b/src/libinput.c
index 9be17b4..5bcb995 100644
--- a/src/libinput.c
+++ b/src/libinput.c
@@ -94,6 +94,7 @@ struct xf86libinput {
 		float speed;
 		float matrix[9];
 		enum libinput_config_scroll_method scroll_method;
+		enum libinput_config_click_method click_method;
 	} options;
 };
 
@@ -291,6 +292,23 @@ LibinputApplyConfig(DeviceIntPtr dev)
 				    "Failed to set ScrollButton to %d\n",
 				    driver_data->options.scroll_button);
 	}
+
+	if (libinput_device_config_click_set_method(device,
+						    driver_data->options.click_method) != LIBINPUT_CONFIG_STATUS_SUCCESS) {
+		const char *method;
+
+		switch (driver_data->options.click_method) {
+		case LIBINPUT_CONFIG_CLICK_METHOD_NONE: method = "none"; break;
+		case LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS: method = "buttonareas"; break;
+		case LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER: method = "clickfinger"; break;
+		default:
+			method = "unknown"; break;
+		}
+
+		xf86IDrvMsg(pInfo, X_ERROR,
+			    "Failed to set click method to %s\n",
+			    method);
+	}
 }
 
 static int
@@ -948,6 +966,7 @@ xf86libinput_parse_options(InputInfoPtr pInfo,
 			   struct libinput_device *device)
 {
 	uint32_t scroll_methods;
+	uint32_t click_methods;
 
 	if (libinput_device_config_tap_get_finger_count(device) > 0) {
 		BOOL tap = xf86SetBoolOption(pInfo->options,
@@ -1118,6 +1137,31 @@ xf86libinput_parse_options(InputInfoPtr pInfo,
 		driver_data->options.scroll_button = scroll_button;
 	}
 
+	click_methods = libinput_device_config_click_get_methods(device);
+	if (click_methods != LIBINPUT_CONFIG_CLICK_METHOD_NONE) {
+		enum libinput_config_click_method m;
+		char *method = xf86SetStrOption(pInfo->options,
+						"ClickMethod",
+						NULL);
+
+		if (!method)
+			m = libinput_device_config_click_get_method(device);
+		else if (strncasecmp(method, "buttonareas", 11) == 0)
+			m = LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS;
+		else if (strncasecmp(method, "clickfinger", 11) == 0)
+			m = LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER;
+		else if (strncasecmp(method, "none", 4) == 0)
+			m = LIBINPUT_CONFIG_CLICK_METHOD_NONE;
+		else {
+			xf86IDrvMsg(pInfo, X_ERROR,
+				    "Unknown click method '%s'. Using default.\n",
+				    method);
+			m = libinput_device_config_click_get_method(device);
+		}
+
+		driver_data->options.click_method = m;
+		free(method);
+	}
 }
 
 static int
@@ -1287,6 +1331,8 @@ static Atom prop_left_handed;
 static Atom prop_scroll_methods_available;
 static Atom prop_scroll_method_enabled;
 static Atom prop_scroll_button;
+static Atom prop_click_methods_available;
+static Atom prop_click_method_enabled;
 
 /* general properties */
 static Atom prop_float;
@@ -1593,6 +1639,48 @@ LibinputSetPropertyScrollButton(DeviceIntPtr dev,
 	return Success;
 }
 
+static inline int
+LibinputSetPropertyClickMethod(DeviceIntPtr dev,
+			       Atom atom,
+			       XIPropertyValuePtr val,
+			       BOOL checkonly)
+{
+	InputInfoPtr pInfo = dev->public.devicePrivate;
+	struct xf86libinput *driver_data = pInfo->private;
+	struct libinput_device *device = driver_data->device;
+	BOOL* data;
+	uint32_t modes = 0;
+
+	if (val->format != 8 || val->size != 2 || val->type != XA_INTEGER)
+		return BadMatch;
+
+	data = (BOOL*)val->data;
+
+	if (data[0])
+		modes |= LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS;
+	if (data[1])
+		modes |= LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER;
+
+	if (checkonly) {
+		uint32_t supported;
+
+		if (__builtin_popcount(modes) > 1)
+			return BadValue;
+
+		if (!xf86libinput_check_device(dev, atom))
+			return BadMatch;
+
+		supported = libinput_device_config_click_get_methods(device);
+		if (modes && (modes & supported) == 0)
+			return BadValue;
+	} else {
+		driver_data->options.click_method = modes;
+	}
+
+	return Success;
+}
+
+
 static int
 LibinputSetProperty(DeviceIntPtr dev, Atom atom, XIPropertyValuePtr val,
                  BOOL checkonly)
@@ -1620,6 +1708,10 @@ LibinputSetProperty(DeviceIntPtr dev, Atom atom, XIPropertyValuePtr val,
 		rc = LibinputSetPropertyScrollMethods(dev, atom, val, checkonly);
 	else if (atom == prop_scroll_button)
 		rc = LibinputSetPropertyScrollButton(dev, atom, val, checkonly);
+	else if (atom == prop_click_methods_available)
+		return BadAccess; /* read-only */
+	else if (atom == prop_click_method_enabled)
+		rc = LibinputSetPropertyClickMethod(dev, atom, val, checkonly);
 	else if (atom == prop_device || atom == prop_product_id)
 		return BadAccess; /* read-only */
 	else
@@ -1884,6 +1976,73 @@ LibinputInitScrollMethodsProperty(DeviceIntPtr dev,
 }
 
 static void
+LibinputInitClickMethodsProperty(DeviceIntPtr dev,
+				 struct xf86libinput *driver_data,
+				 struct libinput_device *device)
+{
+	uint32_t click_methods;
+	enum libinput_config_click_method method;
+	BOOL methods[2] = {FALSE};
+	int rc;
+
+	click_methods = libinput_device_config_click_get_methods(device);
+	if (click_methods == LIBINPUT_CONFIG_CLICK_METHOD_NONE)
+		return;
+
+	if (click_methods & LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS)
+		methods[0] = TRUE;
+	if (click_methods & LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER)
+		methods[1] = TRUE;
+
+	prop_click_methods_available =
+		MakeAtom(LIBINPUT_PROP_CLICK_METHODS_AVAILABLE,
+			 strlen(LIBINPUT_PROP_CLICK_METHODS_AVAILABLE),
+			 TRUE);
+	rc = XIChangeDeviceProperty(dev,
+				    prop_click_methods_available,
+				    XA_INTEGER, 8,
+				    PropModeReplace,
+				    ARRAY_SIZE(methods),
+				    &methods, FALSE);
+	if (rc != Success)
+		return;
+	XISetDevicePropertyDeletable(dev,
+				     prop_click_methods_available,
+				     FALSE);
+
+	memset(methods, 0, sizeof(methods));
+
+	method = libinput_device_config_click_get_method(device);
+	switch(method) {
+	case LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS:
+		methods[0] = TRUE;
+		break;
+	case LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER:
+		methods[1] = TRUE;
+		break;
+	default:
+		break;
+	}
+
+	prop_click_method_enabled =
+		MakeAtom(LIBINPUT_PROP_CLICK_METHOD_ENABLED,
+			 strlen(LIBINPUT_PROP_CLICK_METHOD_ENABLED),
+			 TRUE);
+	rc = XIChangeDeviceProperty(dev,
+				    prop_click_method_enabled,
+				    XA_INTEGER, 8,
+				    PropModeReplace,
+				    ARRAY_SIZE(methods),
+				    &methods, FALSE);
+	if (rc != Success)
+		return;
+
+	XISetDevicePropertyDeletable(dev,
+				     prop_click_method_enabled,
+				     FALSE);
+}
+
+static void
 LibinputInitProperty(DeviceIntPtr dev)
 {
 	InputInfoPtr pInfo  = dev->public.devicePrivate;
@@ -1902,6 +2061,7 @@ LibinputInitProperty(DeviceIntPtr dev)
 	LibinputInitSendEventsProperty(dev, driver_data, device);
 	LibinputInitLeftHandedProperty(dev, driver_data, device);
 	LibinputInitScrollMethodsProperty(dev, driver_data, device);
+	LibinputInitClickMethodsProperty(dev, driver_data, device);
 
 	/* Device node property, read-only  */
 	device_node = driver_data->path;
-- 
2.1.0



More information about the xorg-devel mailing list