[PATCH libinput] tablet: Handle button-events

Stephen Chandler Paul thatslyude at gmail.com
Fri Jun 13 01:27:49 PDT 2014


Signed-off-by: Stephen Chandler Paul <thatslyude at gmail.com>
---
 src/evdev-tablet.c     | 113 +++++++++++++++++++++++++++++++++++++++++++++++++
 src/evdev-tablet.h     |  12 +++++-
 src/libinput-private.h |   5 +++
 src/libinput.c         |  55 ++++++++++++++++++++++++
 src/libinput.h         |  51 +++++++++++++++++++++-
 5 files changed, 233 insertions(+), 3 deletions(-)

diff --git a/src/evdev-tablet.c b/src/evdev-tablet.c
index 9511860..9fbffcc 100644
--- a/src/evdev-tablet.c
+++ b/src/evdev-tablet.c
@@ -32,6 +32,11 @@
 #define tablet_unset_status(tablet_,s_) (tablet_->status &= ~(s_))
 #define tablet_has_status(tablet_,s_) (!!(tablet_->status & s_))
 
+#define tablet_get_pressed_buttons(tablet_,field_) \
+       ((tablet_)->button_state.field_ & ~((tablet_)->prev_button_state.field_))
+#define tablet_get_released_buttons(tablet_,field_) \
+       ((tablet_)->prev_button_state.field_ & ~((tablet_)->button_state.field_))
+
 static void
 tablet_process_absolute(struct tablet_dispatch *tablet,
 			struct evdev_device *device,
@@ -110,6 +115,37 @@ tablet_notify_axes(struct tablet_dispatch *tablet,
 }
 
 static void
+tablet_update_button(struct tablet_dispatch *tablet,
+		     uint32_t evcode,
+		     uint32_t enable)
+{
+	uint32_t button, *flags;
+
+	/* XXX: This really depends on the expected buttons fitting in the mask */
+	if (evcode >= BTN_MISC && evcode <= BTN_TASK) {
+		flags = &tablet->button_state.pad_buttons;
+		button = evcode - BTN_MISC;
+	} else if (evcode >= BTN_TOUCH && evcode <= BTN_STYLUS2) {
+		flags = &tablet->button_state.stylus_buttons;
+		button = evcode - BTN_TOUCH;
+	} else {
+		log_info("Unhandled button %s (%#x)\n",
+			 libevdev_event_code_get_name(EV_KEY, evcode), evcode);
+		return;
+	}
+
+	if (enable) {
+		(*flags) |= 1 << button;
+		tablet_set_status(tablet, TABLET_BUTTONS_PRESSED);
+	} else {
+		(*flags) &= ~(1 << button);
+		tablet_set_status(tablet, TABLET_BUTTONS_RELEASED);
+	}
+
+	assert(button < 32);
+}
+
+static void
 tablet_process_key(struct tablet_dispatch *tablet,
 		   struct evdev_device *device,
 		   struct input_event *e,
@@ -127,7 +163,11 @@ tablet_process_key(struct tablet_dispatch *tablet,
 		/* These codes have an equivalent libinput_tool value */
 		tablet_update_tool(tablet, e->code, e->value);
 		break;
+	case BTN_TOUCH:
+	case BTN_STYLUS:
+	case BTN_STYLUS2:
 	default:
+		tablet_update_button(tablet, e->code, e->value);
 		break;
 	}
 }
@@ -182,11 +222,67 @@ tablet_notify_tool(struct tablet_dispatch *tablet,
 }
 
 static void
+tablet_notify_button_mask(struct tablet_dispatch *tablet,
+			  struct evdev_device *device,
+			  uint32_t time,
+			  uint32_t buttons,
+			  uint32_t button_base,
+			  enum libinput_button_state state)
+{
+	struct libinput_device *base = &device->base;
+	int32_t num_button = 0;
+
+	while (buttons) {
+		int enabled;
+
+		num_button++;
+		enabled = (buttons & 1);
+		buttons >>= 1;
+
+		if (!enabled)
+			continue;
+
+		tablet_notify_button(base,
+				     time,
+				     num_button + button_base - 1,
+				     state);
+	}
+}
+
+static void
+tablet_notify_buttons(struct tablet_dispatch *tablet,
+		      struct evdev_device *device,
+		      uint32_t time,
+		      enum libinput_button_state state)
+{
+	uint32_t pad_buttons, stylus_buttons;
+
+	if (state == LIBINPUT_BUTTON_STATE_PRESSED) {
+		pad_buttons = tablet_get_pressed_buttons(tablet, pad_buttons);
+		stylus_buttons =
+			tablet_get_pressed_buttons(tablet, stylus_buttons);
+	} else {
+		pad_buttons = tablet_get_released_buttons(tablet, pad_buttons);
+		stylus_buttons =
+			tablet_get_released_buttons(tablet, stylus_buttons);
+	}
+
+	tablet_notify_button_mask(tablet, device, time,
+				  pad_buttons, BTN_MISC, state);
+	tablet_notify_button_mask(tablet, device, time,
+				  stylus_buttons, BTN_TOUCH, state);
+}
+
+static void
 tablet_flush(struct tablet_dispatch *tablet,
 	     struct evdev_device *device,
 	     uint32_t time)
 {
 	if (tablet_has_status(tablet, TABLET_TOOL_LEAVING_PROXIMITY)) {
+		/* Release all stylus buttons */
+		tablet->button_state.stylus_buttons = 0;
+		tablet_set_status(tablet, TABLET_BUTTONS_RELEASED);
+
 		memset(&tablet->changed_axes, 0, sizeof(tablet->changed_axes));
 		memset(&tablet->axes, 0, sizeof(tablet->axes));
 
@@ -203,11 +299,28 @@ tablet_flush(struct tablet_dispatch *tablet,
 		}
 	}
 
+	if (tablet_has_status(tablet, TABLET_BUTTONS_RELEASED)) {
+		tablet_notify_buttons(tablet, device, time,
+				      LIBINPUT_BUTTON_STATE_RELEASED);
+		tablet_unset_status(tablet, TABLET_BUTTONS_RELEASED);
+	}
+
+	if (tablet_has_status(tablet, TABLET_BUTTONS_PRESSED)) {
+		tablet_notify_buttons(tablet, device, time,
+				      LIBINPUT_BUTTON_STATE_PRESSED);
+		tablet_unset_status(tablet, TABLET_BUTTONS_PRESSED);
+	}
+
 	/* We want button releases to be sent before the proximity out event */
 	if (tablet_has_status(tablet, TABLET_TOOL_LEAVING_PROXIMITY)) {
 		tablet_notify_proximity_out(&device->base, time);
 		tablet_unset_status(tablet, TABLET_TOOL_LEAVING_PROXIMITY);
 	}
+
+	/* Update state */
+	memcpy(&tablet->prev_button_state,
+	       &tablet->button_state,
+	       sizeof(tablet->button_state));
 }
 
 static void
diff --git a/src/evdev-tablet.h b/src/evdev-tablet.h
index 4727ed8..f309173 100644
--- a/src/evdev-tablet.h
+++ b/src/evdev-tablet.h
@@ -31,7 +31,14 @@ enum tablet_status {
 	TABLET_NONE = 0,
 	TABLET_AXES_UPDATED = 1 << 0,
 	TABLET_TOOL_UPDATED = 1 << 1,
-	TABLET_TOOL_LEAVING_PROXIMITY = 1 << 2
+	TABLET_TOOL_LEAVING_PROXIMITY = 1 << 2,
+	TABLET_BUTTONS_PRESSED = 1 << 3,
+	TABLET_BUTTONS_RELEASED = 1 << 4
+};
+
+struct button_state {
+	uint32_t pad_buttons; /* bitmask of evcode - BTN_MISC */
+	uint32_t stylus_buttons; /* bitmask of evcode - BTN_TOUCH */
 };
 
 struct tablet_dispatch {
@@ -42,6 +49,9 @@ struct tablet_dispatch {
 	const struct input_absinfo *absinfo[LIBINPUT_TABLET_AXIS_CNT];
 	double axes[LIBINPUT_TABLET_AXIS_CNT];
 
+	struct button_state button_state;
+	struct button_state prev_button_state;
+
 	enum libinput_tool_type current_tool_type;
 	uint32_t current_tool_serial;
 };
diff --git a/src/libinput-private.h b/src/libinput-private.h
index 3830bd9..3630f74 100644
--- a/src/libinput-private.h
+++ b/src/libinput-private.h
@@ -219,6 +219,11 @@ tablet_notify_proximity_out(struct libinput_device *device,
 			    uint32_t time);
 
 void
+tablet_notify_button(struct libinput_device *device,
+		     uint32_t time,
+		     int32_t button,
+		     enum libinput_button_state state);
+void
 touch_notify_frame(struct libinput_device *device,
 		   uint32_t time);
 #endif /* LIBINPUT_PRIVATE_H */
diff --git a/src/libinput.c b/src/libinput.c
index fc77c9e..873fe8b 100644
--- a/src/libinput.c
+++ b/src/libinput.c
@@ -82,6 +82,9 @@ struct libinput_event_touch {
 
 struct libinput_event_tablet {
 	struct libinput_event base;
+	uint32_t button;
+	enum libinput_button_state state;
+	uint32_t seat_button_count;
 	uint32_t time;
 	double *axes;
 	unsigned char changed_axes[NCHARS(LIBINPUT_TABLET_AXIS_CNT)];
@@ -202,6 +205,7 @@ libinput_event_get_pointer_event(struct libinput_event *event)
 	case LIBINPUT_EVENT_TABLET_AXIS:
 	case LIBINPUT_EVENT_TABLET_TOOL_UPDATE:
 	case LIBINPUT_EVENT_TABLET_PROXIMITY_OUT:
+	case LIBINPUT_EVENT_TABLET_BUTTON:
 		break;
 	}
 
@@ -231,6 +235,7 @@ libinput_event_get_keyboard_event(struct libinput_event *event)
 	case LIBINPUT_EVENT_TABLET_AXIS:
 	case LIBINPUT_EVENT_TABLET_TOOL_UPDATE:
 	case LIBINPUT_EVENT_TABLET_PROXIMITY_OUT:
+	case LIBINPUT_EVENT_TABLET_BUTTON:
 		break;
 	}
 
@@ -260,6 +265,7 @@ libinput_event_get_touch_event(struct libinput_event *event)
 	case LIBINPUT_EVENT_TABLET_AXIS:
 	case LIBINPUT_EVENT_TABLET_TOOL_UPDATE:
 	case LIBINPUT_EVENT_TABLET_PROXIMITY_OUT:
+	case LIBINPUT_EVENT_TABLET_BUTTON:
 		break;
 	}
 
@@ -288,6 +294,7 @@ libinput_event_get_tablet_event(struct libinput_event *event)
 	case LIBINPUT_EVENT_TABLET_AXIS:
 	case LIBINPUT_EVENT_TABLET_TOOL_UPDATE:
 	case LIBINPUT_EVENT_TABLET_PROXIMITY_OUT:
+	case LIBINPUT_EVENT_TABLET_BUTTON:
 		return (struct libinput_event_tablet *) event;
 	}
 
@@ -316,6 +323,7 @@ libinput_event_get_device_notify_event(struct libinput_event *event)
 	case LIBINPUT_EVENT_TABLET_AXIS:
 	case LIBINPUT_EVENT_TABLET_TOOL_UPDATE:
 	case LIBINPUT_EVENT_TABLET_PROXIMITY_OUT:
+	case LIBINPUT_EVENT_TABLET_BUTTON:
 		break;
 	}
 
@@ -531,6 +539,24 @@ libinput_event_tablet_get_time(struct libinput_event_tablet *event)
 	return event->time;
 }
 
+LIBINPUT_EXPORT uint32_t
+libinput_event_tablet_get_button(struct libinput_event_tablet *event)
+{
+	return event->button;
+}
+
+LIBINPUT_EXPORT enum libinput_button_state
+libinput_event_tablet_get_button_state(struct libinput_event_tablet *event)
+{
+	return event->state;
+}
+
+LIBINPUT_EXPORT uint32_t
+libinput_event_tablet_get_seat_button_count(struct libinput_event_tablet *event)
+{
+	return event->seat_button_count;
+}
+
 LIBINPUT_EXPORT enum libinput_tool_type
 libinput_tool_get_type(struct libinput_tool *tool)
 {
@@ -1224,6 +1250,35 @@ tablet_notify_proximity_out(struct libinput_device *device,
 			  &proximity_out_update_event->base);
 }
 
+void
+tablet_notify_button(struct libinput_device *device,
+		     uint32_t time,
+		     int32_t button,
+		     enum libinput_button_state state)
+{
+	struct libinput_event_tablet *button_event;
+	int32_t seat_button_count;
+
+	button_event = zalloc(sizeof *button_event);
+	if (!button_event)
+		return;
+
+	seat_button_count = update_seat_button_count(device->seat,
+						     button,
+						     state);
+
+	*button_event = (struct libinput_event_tablet) {
+		.time = time,
+		.button = button,
+		.state = state,
+		.seat_button_count = seat_button_count,
+	};
+
+	post_device_event(device,
+			  LIBINPUT_EVENT_TABLET_BUTTON,
+			  &button_event->base);
+}
+
 static void
 libinput_post_event(struct libinput *libinput,
 		    struct libinput_event *event)
diff --git a/src/libinput.h b/src/libinput.h
index 73c84be..64f460c 100644
--- a/src/libinput.h
+++ b/src/libinput.h
@@ -264,7 +264,8 @@ enum libinput_event_type {
 	 * Signals that a device with the @ref LIBINPUT_DEVICE_CAP_TABLET
 	 * capability has detected that there is no longer a tool in use.
 	 */
-	LIBINPUT_EVENT_TABLET_PROXIMITY_OUT
+	LIBINPUT_EVENT_TABLET_PROXIMITY_OUT,
+	LIBINPUT_EVENT_TABLET_BUTTON
 };
 
 struct libinput;
@@ -294,7 +295,8 @@ struct libinput_event_touch;
  *
  * Tablet event representing an axis update, button press, or tool update. Valid
  * event types for this event are @ref LIBINPUT_EVENT_TABLET_AXIS, @ref
- * LIBINPUT_EVENT_TABLET_TOOL_UPDATE and @ref LIBINPUT_EVENT_TABLET_TOOL_UPDATE.
+ * LIBINPUT_EVENT_TABLET_TOOL_UPDATE, @ref LIBINPUT_EVENT_TABLET_TOOL_UPDATE and
+ * @ref LIBINPUT_EVENT_TABLET_BUTTON.
  */
 struct libinput_event_tablet;
 
@@ -930,6 +932,51 @@ libinput_event_tablet_get_tool(struct libinput_event_tablet *event);
 /**
  * @ingroup event_tablet
  *
+ * Return the button that triggered this event.
+ * For tablet events that are not of type LIBINPUT_EVENT_TABLET_BUTTON, this
+ * function returns 0.
+ *
+ * @note It is an application bug to call this function for events other than
+ * LIBINPUT_EVENT_TABLET_BUTTON.
+ *
+ * @param event The libinput tablet event
+ * @return the button triggering this event
+ */
+uint32_t
+libinput_event_tablet_get_button(struct libinput_event_tablet *event);
+
+/**
+ * @ingroup event_tablet
+ *
+ * Return the button state of the event.
+ *
+ * @note It is an application bug to call this function for events other than
+ * LIBINPUT_EVENT_TABLET_BUTTON.
+ *
+ * @param event The libinput tablet event
+ * @return the button state triggering this event
+ */
+enum libinput_button_state
+libinput_event_tablet_get_button_state(struct libinput_event_tablet *event);
+
+/**
+ * @ingroup event_tablet
+ *
+ * For the button of a LIBINPUT_EVENT_TABLET_BUTTON event, return the total
+ * number of buttons pressed on all devices on the associated seat after the
+ * the event was triggered.
+ *
+ " @note It is an application bug to call this function for events other than
+ * LIBINPUT_EVENT_TABLET_BUTTON. For other events, this function returns 0.
+ *
+ * @return the seat wide pressed button count for the key of this event
+ */
+uint32_t
+libinput_event_tablet_get_seat_button_count(struct libinput_event_tablet *event);
+
+/**
+ * @ingroup event_tablet
+ *
  * @param event The libinput tablet event
  * @return The event time for this event
  */
-- 
1.8.5.5



More information about the wayland-devel mailing list