[PATCH libinput 2/4] evdev: hook up left-handed configuration option

Peter Hutterer peter.hutterer at who-t.net
Mon Sep 22 23:09:19 PDT 2014


Two separate flags needed, want_left_handed and left_handed to avoid switching
to left_handed while a button is still down. Since each backend has a
different way of determining whether buttons are down, let them set a function
to do exactly that. Then call that function whenever a button release event is
posted to switch the device to right/left-handed if applicable.

Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
---
 src/evdev.c | 93 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
 src/evdev.h | 28 +++++++++++++++++++
 2 files changed, 118 insertions(+), 3 deletions(-)

diff --git a/src/evdev.c b/src/evdev.c
index 4c0669c..d8e3e5a 100644
--- a/src/evdev.c
+++ b/src/evdev.c
@@ -115,8 +115,14 @@ evdev_pointer_notify_button(struct evdev_device *device,
 	down_count = update_key_down_count(device, button, state);
 
 	if ((state == LIBINPUT_BUTTON_STATE_PRESSED && down_count == 1) ||
-	    (state == LIBINPUT_BUTTON_STATE_RELEASED && down_count == 0))
+	    (state == LIBINPUT_BUTTON_STATE_RELEASED && down_count == 0)) {
 		pointer_notify_button(&device->base, time, button, state);
+
+		if (state == LIBINPUT_BUTTON_STATE_RELEASED &&
+		    device->buttons.change_to_left_handed)
+			device->buttons.change_to_left_handed(device);
+	}
+
 }
 
 void
@@ -455,7 +461,7 @@ evdev_process_key(struct evdev_device *device,
 		evdev_pointer_notify_button(
 			device,
 			time,
-			e->code,
+			evdev_to_left_handed(device, e->code),
 			e->value ? LIBINPUT_BUTTON_STATE_PRESSED :
 				   LIBINPUT_BUTTON_STATE_RELEASED);
 		break;
@@ -754,15 +760,93 @@ evdev_sendevents_get_default_mode(struct libinput_device *device)
 	return LIBINPUT_CONFIG_SEND_EVENTS_ENABLED;
 }
 
+static int
+evdev_left_handed_has(struct libinput_device *device)
+{
+	/* This is only hooked up when we have left-handed configuration, so we
+	 * can hardcode 1 here */
+	return 1;
+}
+
+static void
+evdev_change_to_left_handed(struct evdev_device *device)
+{
+	unsigned int button;
+
+	if (device->buttons.want_left_handed == device->buttons.left_handed)
+		return;
+
+	for (button = BTN_LEFT; button < BTN_JOYSTICK; button++) {
+		if (libevdev_has_event_code(device->evdev, EV_KEY, button) &&
+		    hw_is_key_down(device, button))
+			return;
+	}
+
+	device->buttons.left_handed = device->buttons.want_left_handed;
+}
+
+static enum libinput_config_status
+evdev_left_handed_set(struct libinput_device *device, int left_handed)
+{
+	struct evdev_device *evdev_device = (struct evdev_device *)device;
+
+	evdev_device->buttons.want_left_handed = left_handed ? true : false;
+
+	evdev_device->buttons.change_to_left_handed(evdev_device);
+
+	return LIBINPUT_CONFIG_STATUS_SUCCESS;
+}
+
+static int
+evdev_left_handed_get(struct libinput_device *device)
+{
+	struct evdev_device *evdev_device = (struct evdev_device *)device;
+
+	/* return the wanted configuration, even if it hasn't taken
+	 * effect yet! */
+	return evdev_device->buttons.want_left_handed;
+}
+
+static int
+evdev_left_handed_get_default(struct libinput_device *device)
+{
+	return 0;
+}
+
+int
+evdev_init_left_handed(struct evdev_device *device,
+		       void (*change_to_left_handed)(struct evdev_device *))
+{
+	device->buttons.config_left_handed.has = evdev_left_handed_has;
+	device->buttons.config_left_handed.set = evdev_left_handed_set;
+	device->buttons.config_left_handed.get = evdev_left_handed_get;
+	device->buttons.config_left_handed.get_default = evdev_left_handed_get_default;
+	device->base.config.left_handed = &device->buttons.config_left_handed;
+	device->buttons.left_handed = false;
+	device->buttons.want_left_handed = false;
+	device->buttons.change_to_left_handed = change_to_left_handed;
+
+	return 0;
+}
+
 static struct evdev_dispatch *
 fallback_dispatch_create(struct libinput_device *device)
 {
 	struct evdev_dispatch *dispatch = zalloc(sizeof *dispatch);
+	struct evdev_device *evdev_device = (struct evdev_device *)device;
+
 	if (dispatch == NULL)
 		return NULL;
 
 	dispatch->interface = &fallback_interface;
 
+	if (evdev_device->buttons.want_left_handed &&
+	    evdev_init_left_handed(evdev_device,
+				   evdev_change_to_left_handed) == -1) {
+		free(dispatch);
+		return NULL;
+	}
+
 	device->config.calibration = &dispatch->calibration;
 
 	dispatch->calibration.has_matrix = evdev_calibration_has_matrix;
@@ -1101,6 +1185,9 @@ evdev_configure_device(struct evdev_device *device)
 			 has_abs ? " absolute-motion" : "",
 			 has_rel ? " relative-motion": "",
 			 has_button ? " button" : "");
+
+		/* want left-handed config option */
+		device->buttons.want_left_handed = true;
 	}
 	if (has_keyboard) {
 		device->seat_caps |= EVDEV_DEVICE_KEYBOARD;
@@ -1461,7 +1548,7 @@ release_pressed_keys(struct evdev_device *device)
 				evdev_pointer_notify_button(
 					device,
 					time,
-					code,
+					evdev_to_left_handed(device, code),
 					LIBINPUT_BUTTON_STATE_RELEASED);
 				break;
 			}
diff --git a/src/evdev.h b/src/evdev.h
index d4b8ee6..c0d6577 100644
--- a/src/evdev.h
+++ b/src/evdev.h
@@ -124,6 +124,17 @@ struct evdev_device {
 	/* Key counter used for multiplexing button events internally in
 	 * libinput. */
 	uint8_t key_count[KEY_CNT];
+
+	struct {
+		struct libinput_device_config_left_handed config_left_handed;
+		/* left-handed currently enabled */
+		bool left_handed;
+		/* set during device init if we want left_handed config,
+		 * used at runtime to delay the effect until buttons are up */
+		bool want_left_handed;
+		/* Checks if buttons are down and commits the setting */
+		void (*change_to_left_handed)(struct evdev_device *device);
+	} buttons;
 };
 
 #define EVDEV_UNHANDLED_DEVICE ((struct evdev_device *) 1)
@@ -279,4 +290,21 @@ evdev_convert_to_mm(const struct input_absinfo *absinfo, double v)
 	return value/absinfo->resolution;
 }
 
+int
+evdev_init_left_handed(struct evdev_device *device,
+		       void (*change_to_left_handed)(struct evdev_device *));
+
+static inline uint32_t
+evdev_to_left_handed(struct evdev_device *device,
+		     uint32_t button)
+{
+	if (device->buttons.left_handed) {
+		if (button == BTN_LEFT)
+			return BTN_RIGHT;
+		else if (button == BTN_RIGHT)
+			return BTN_LEFT;
+	}
+	return button;
+}
+
 #endif /* EVDEV_H */
-- 
1.9.3



More information about the wayland-devel mailing list