[PATCH libinput 13/24] tablet: Emit LIBINPUT_EVENT_POINTER_TOOL_UPDATE events on tool changes

Carlos Garnacho carlosg at gnome.org
Mon Apr 21 10:11:22 PDT 2014


Tracking is done of serial/tool type, so it is only really notified on
tool changes.

Signed-off-by: Carlos Garnacho <carlosg at gnome.org>
---
 src/evdev-tablet.c | 109 ++++++++++++++++++++++++++++++++++++++++++++++++++---
 src/evdev-tablet.h |  10 +++++
 2 files changed, 113 insertions(+), 6 deletions(-)

diff --git a/src/evdev-tablet.c b/src/evdev-tablet.c
index 02877d9..fcd3396 100644
--- a/src/evdev-tablet.c
+++ b/src/evdev-tablet.c
@@ -52,6 +52,85 @@ tablet_process_absolute(struct tablet_dispatch *tablet,
 }
 
 static void
+tablet_update_tool(struct tablet_dispatch *tablet,
+		   uint32_t tool,
+		   uint32_t enabled)
+{
+	assert(tool != LIBINPUT_TOOL_NONE);
+
+	if (enabled && tool != tablet->state.tool) {
+		tablet->state.tool = tool;
+		tablet_set_status(tablet, TABLET_INTERACTED);
+	} else if (!enabled && tool == tablet->state.tool) {
+		tablet->state.tool = LIBINPUT_TOOL_NONE;
+		tablet_unset_status(tablet, TABLET_INTERACTED);
+	}
+}
+
+static void
+tablet_process_key(struct tablet_dispatch *tablet,
+		   struct evdev_device *device,
+		   struct input_event *e,
+		   uint32_t time)
+{
+	switch (e->code) {
+	case BTN_TOOL_PEN:
+	case BTN_TOOL_RUBBER:
+	case BTN_TOOL_BRUSH:
+	case BTN_TOOL_PENCIL:
+	case BTN_TOOL_AIRBRUSH:
+	case BTN_TOOL_FINGER:
+	case BTN_TOOL_MOUSE:
+	case BTN_TOOL_LENS:
+		/* These codes have an equivalent libinput_tool value */
+		tablet_update_tool(tablet, e->code, e->value);
+		break;
+	default:
+		break;
+	}
+}
+
+static void
+tablet_process_misc(struct tablet_dispatch *tablet,
+		    struct evdev_device *device,
+		    struct input_event *e,
+		    uint32_t time)
+{
+	switch (e->code) {
+	case MSC_SERIAL:
+		tablet->state.tool_serial = e->value;
+		break;
+	default:
+		log_info("Unhandled MSC event code 0x%x\n", e->code);
+		break;
+	}
+}
+
+static void
+tablet_check_notify_tool(struct tablet_dispatch *tablet,
+			 struct evdev_device *device,
+			 uint32_t time,
+			 int post_check)
+{
+	struct libinput_device *base = &device->base;
+
+	if (tablet->state.tool == tablet->prev_state.tool)
+		return;
+
+	if (tablet->state.tool == LIBINPUT_TOOL_NONE) {
+		/* Wait for post-check */
+		if (post_check)
+			return;
+	} else if (post_check) {
+		/* Already handled in pre-check */
+		return;
+	}
+
+	pointer_notify_tool_update(
+		base, time, tablet->state.tool, tablet->state.tool_serial);
+}
+
+static void
 tablet_flush(struct tablet_dispatch *tablet,
 	     struct evdev_device *device,
 	     uint32_t time)
@@ -59,14 +138,25 @@ tablet_flush(struct tablet_dispatch *tablet,
 	struct libinput_device *base = &device->base;
 	li_fixed_t x, y;
 
-	if (tablet_has_status(tablet, TABLET_UPDATED)) {
-		/* FIXME: apply hysteresis, calibration */
-		x = li_fixed_from_int(device->abs.x);
-		y = li_fixed_from_int(device->abs.y);
+	/* pre-update notifications */
+	tablet_check_notify_tool(tablet, device, time, 0);
+
+	if (tablet->state.tool != LIBINPUT_TOOL_NONE) {
+		if (tablet_has_status(tablet, TABLET_UPDATED)) {
+			/* FIXME: apply hysteresis, calibration */
+			x = li_fixed_from_int(device->abs.x);
+			y = li_fixed_from_int(device->abs.y);
 
-		pointer_notify_motion_absolute(base, time, x, y);
-		tablet_unset_status(tablet, TABLET_UPDATED);
+			pointer_notify_motion_absolute(base, time, x, y);
+			tablet_unset_status(tablet, TABLET_UPDATED);
+		}
 	}
+
+	/* post-update notifications */
+	tablet_check_notify_tool(tablet, device, time, 1);
+
+	/* replace previous state */
+	tablet->prev_state = tablet->state;
 }
 
 static void
@@ -82,6 +172,12 @@ tablet_process(struct evdev_dispatch *dispatch,
 	case EV_ABS:
 		tablet_process_absolute(tablet, device, e, time);
 		break;
+	case EV_KEY:
+		tablet_process_key(tablet, device, e, time);
+		break;
+	case EV_MSC:
+		tablet_process_misc(tablet, device, e, time);
+		break;
 	case EV_SYN:
 		tablet_flush(tablet, device, time);
 		break;
@@ -112,6 +208,7 @@ tablet_init(struct tablet_dispatch *tablet,
 	tablet->base.interface = &tablet_interface;
 	tablet->device = device;
 	tablet->status = TABLET_NONE;
+	tablet->state.tool = LIBINPUT_TOOL_NONE;
 
 	return 0;
 }
diff --git a/src/evdev-tablet.h b/src/evdev-tablet.h
index e1479fa..7b7b066 100644
--- a/src/evdev-tablet.h
+++ b/src/evdev-tablet.h
@@ -29,11 +29,21 @@
 enum tablet_status {
 	TABLET_NONE = 0,
 	TABLET_UPDATED = 1 << 0,
+	TABLET_INTERACTED = 1 << 1,
+};
+
+struct device_state {
+	enum libinput_tool tool;
+	int32_t tool_serial;
 };
 
 struct tablet_dispatch {
 	struct evdev_dispatch base;
 	struct evdev_device *device;
+
+	struct device_state state;
+	struct device_state prev_state;
+
 	enum tablet_status status;
 };
 
-- 
1.9.0



More information about the wayland-devel mailing list