[PATCH libinput 05/23] Emit LIBINPUT_TABLET_EVENT_TOOL_UPDATE events on tool changes
Stephen Chandler Paul
thatslyude at gmail.com
Thu Jun 12 20:28:26 PDT 2014
Signed-off-by: Stephen Chandler Paul <thatslyude at gmail.com>
---
src/evdev-tablet.c | 100 +++++++++++++++++++++++++++++++++++++++++++++++++
src/evdev-tablet.h | 6 ++-
src/libinput-private.h | 5 +++
src/libinput.c | 40 ++++++++++++++++++++
src/libinput.h | 35 ++++++++++++++++-
5 files changed, 183 insertions(+), 3 deletions(-)
diff --git a/src/evdev-tablet.c b/src/evdev-tablet.c
index 5c73bcb..52b3c93 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_))
+static struct list tool_list = {
+ .next = &tool_list,
+ .prev = &tool_list
+};
+
static void
tablet_process_absolute(struct tablet_dispatch *tablet,
struct evdev_device *device,
@@ -63,6 +68,19 @@ tablet_process_absolute(struct tablet_dispatch *tablet,
}
static void
+tablet_update_tool(struct tablet_dispatch *tablet,
+ int32_t tool,
+ bool enabled)
+{
+ assert(tool != LIBINPUT_TOOL_NONE);
+
+ if (enabled && tool != tablet->current_tool_type) {
+ tablet->current_tool_type = tool;
+ tablet_set_status(tablet, TABLET_TOOL_UPDATED);
+ }
+}
+
+static void
tablet_notify_axes(struct tablet_dispatch *tablet,
struct evdev_device *device,
uint32_t time)
@@ -95,10 +113,85 @@ tablet_notify_axes(struct tablet_dispatch *tablet,
}
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->current_tool_serial = e->value;
+ break;
+ default:
+ log_info("Unhandled MSC event code %#x\n", e->code);
+ break;
+ }
+}
+
+static void
+tablet_notify_tool(struct tablet_dispatch *tablet,
+ struct evdev_device *device,
+ uint32_t time)
+{
+ struct libinput_device *base = &device->base;
+ struct libinput_tool *tool;
+ struct libinput_tool *new_tool = NULL;
+
+ /* Check if we already have the tool in our list of tools */
+ list_for_each(tool, &tool_list, link) {
+ if (tablet->current_tool_type == tool->type &&
+ tablet->current_tool_serial == tool->serial) {
+ new_tool = tool;
+ break;
+ }
+ }
+
+ /* If we didn't already have the tool in our list of tools, add it */
+ if (new_tool == NULL) {
+ new_tool = zalloc(sizeof *new_tool);
+ *new_tool = (struct libinput_tool) {
+ .type = tablet->current_tool_type,
+ .serial = tablet->current_tool_serial,
+ .refcount = 1,
+ };
+
+ list_insert(&tool_list, &new_tool->link);
+ }
+
+ tablet_notify_tool_update(base, time, new_tool);
+}
+
+static void
tablet_flush(struct tablet_dispatch *tablet,
struct evdev_device *device,
uint32_t time)
{
+ if (tablet_has_status(tablet, TABLET_TOOL_UPDATED))
+ tablet_notify_tool(tablet, device, time);
+
if (tablet_has_status(tablet, TABLET_AXES_UPDATED)) {
tablet_notify_axes(tablet, device, time);
tablet_unset_status(tablet, TABLET_AXES_UPDATED);
@@ -118,6 +211,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;
@@ -148,6 +247,7 @@ tablet_init(struct tablet_dispatch *tablet,
tablet->base.interface = &tablet_interface;
tablet->device = device;
tablet->status = TABLET_NONE;
+ tablet->current_tool_type = LIBINPUT_TOOL_NONE;
return 0;
}
diff --git a/src/evdev-tablet.h b/src/evdev-tablet.h
index d832c17..dd5988c 100644
--- a/src/evdev-tablet.h
+++ b/src/evdev-tablet.h
@@ -29,7 +29,8 @@
enum tablet_status {
TABLET_NONE = 0,
- TABLET_AXES_UPDATED = 1 << 0
+ TABLET_AXES_UPDATED = 1 << 0,
+ TABLET_TOOL_UPDATED = 1 << 1
};
struct tablet_dispatch {
@@ -39,6 +40,9 @@ struct tablet_dispatch {
unsigned char changed_axes[NCHARS(LIBINPUT_TABLET_AXIS_CNT)];
const struct input_absinfo *absinfo[LIBINPUT_TABLET_AXIS_CNT];
double axes[LIBINPUT_TABLET_AXIS_CNT];
+
+ enum libinput_tool_type current_tool_type;
+ uint32_t current_tool_serial;
};
static inline enum libinput_tablet_axis
diff --git a/src/libinput-private.h b/src/libinput-private.h
index 83906f5..c2ff194 100644
--- a/src/libinput-private.h
+++ b/src/libinput-private.h
@@ -208,6 +208,11 @@ tablet_notify_axis(struct libinput_device *device,
double *axes);
void
+tablet_notify_tool_update(struct libinput_device *device,
+ uint32_t time,
+ struct libinput_tool *tool);
+
+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 def3e91..d5f4ec3 100644
--- a/src/libinput.c
+++ b/src/libinput.c
@@ -85,6 +85,7 @@ struct libinput_event_tablet {
uint32_t time;
double *axes;
unsigned char changed_axes[NCHARS(LIBINPUT_TABLET_AXIS_CNT)];
+ struct libinput_tool *tool;
};
static void
@@ -199,6 +200,7 @@ libinput_event_get_pointer_event(struct libinput_event *event)
case LIBINPUT_EVENT_TOUCH_CANCEL:
case LIBINPUT_EVENT_TOUCH_FRAME:
case LIBINPUT_EVENT_TABLET_AXIS:
+ case LIBINPUT_EVENT_TABLET_TOOL_UPDATE:
break;
}
@@ -226,6 +228,7 @@ libinput_event_get_keyboard_event(struct libinput_event *event)
case LIBINPUT_EVENT_TOUCH_CANCEL:
case LIBINPUT_EVENT_TOUCH_FRAME:
case LIBINPUT_EVENT_TABLET_AXIS:
+ case LIBINPUT_EVENT_TABLET_TOOL_UPDATE:
break;
}
@@ -253,6 +256,7 @@ libinput_event_get_touch_event(struct libinput_event *event)
case LIBINPUT_EVENT_TOUCH_FRAME:
return (struct libinput_event_touch *) event;
case LIBINPUT_EVENT_TABLET_AXIS:
+ case LIBINPUT_EVENT_TABLET_TOOL_UPDATE:
break;
}
@@ -279,6 +283,7 @@ libinput_event_get_tablet_event(struct libinput_event *event)
case LIBINPUT_EVENT_TOUCH_FRAME:
break;
case LIBINPUT_EVENT_TABLET_AXIS:
+ case LIBINPUT_EVENT_TABLET_TOOL_UPDATE:
return (struct libinput_event_tablet *) event;
}
@@ -305,6 +310,7 @@ libinput_event_get_device_notify_event(struct libinput_event *event)
case LIBINPUT_EVENT_TOUCH_CANCEL:
case LIBINPUT_EVENT_TOUCH_FRAME:
case LIBINPUT_EVENT_TABLET_AXIS:
+ case LIBINPUT_EVENT_TABLET_TOOL_UPDATE:
break;
}
@@ -508,6 +514,12 @@ libinput_event_tablet_get_y_transformed(struct libinput_event_tablet *event,
height);
}
+LIBINPUT_EXPORT struct libinput_tool *
+libinput_event_tablet_get_tool(struct libinput_event_tablet *event)
+{
+ return event->tool;
+}
+
LIBINPUT_EXPORT uint32_t
libinput_event_tablet_get_time(struct libinput_event_tablet *event)
{
@@ -673,6 +685,13 @@ libinput_event_destroy(struct libinput_event *event)
if (event->device)
libinput_device_unref(event->device);
+ else if (event->type == LIBINPUT_EVENT_TABLET_TOOL_UPDATE) {
+ struct libinput_event_tablet *tevent =
+ (struct libinput_event_tablet*)event;
+
+ libinput_tool_unref(tevent->tool);
+ }
+
free(event);
}
@@ -1159,6 +1178,27 @@ tablet_notify_axis(struct libinput_device *device,
&axis_event->base);
}
+void
+tablet_notify_tool_update(struct libinput_device *device,
+ uint32_t time,
+ struct libinput_tool *tool)
+{
+ struct libinput_event_tablet *tool_update_event;
+
+ tool_update_event = zalloc(sizeof *tool_update_event);
+ if (!tool_update_event)
+ return;
+
+ *tool_update_event = (struct libinput_event_tablet) {
+ .time = time,
+ .tool = tool,
+ };
+
+ post_device_event(device,
+ LIBINPUT_EVENT_TABLET_TOOL_UPDATE,
+ &tool_update_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 c0c9fae..9615f1d 100644
--- a/src/libinput.h
+++ b/src/libinput.h
@@ -254,7 +254,12 @@ enum libinput_event_type {
*/
LIBINPUT_EVENT_TOUCH_FRAME,
- LIBINPUT_EVENT_TABLET_AXIS = 600
+ LIBINPUT_EVENT_TABLET_AXIS = 600,
+ /**
+ * Signals that a device with the @ref LIBINPUT_DEVICE_CAP_TABLET
+ * capability has changed its tool.
+ */
+ LIBINPUT_EVENT_TABLET_TOOL_UPDATE
};
struct libinput;
@@ -283,7 +288,8 @@ struct libinput_event_touch;
* @struct libinput_event_tablet
*
* Tablet event representing an axis update, button press, or tool update. Valid
- * event types for this event are @ref LIBINPUT_EVENT_TABLET_AXIS.
+ * event types for this event are @ref LIBINPUT_EVENT_TABLET_AXIS, and
+ * @ref LIBINPUT_EVENT_TABLET_TOOL_UPDATE.
*/
struct libinput_event_tablet;
@@ -891,6 +897,31 @@ libinput_event_tablet_get_x_transformed(struct libinput_event_tablet *event,
double
libinput_event_tablet_get_y_transformed(struct libinput_event_tablet *event,
uint32_t height);
+
+/**
+ * @ingroup event_tablet
+ *
+ * Return the new tool in use for this event.
+ * For tablet events that are not of type @ref
+ * LIBINPUT_EVENT_TABLET_TOOL_UPDATE, this function returns NULL. By default,
+ * the lifetime of each tool is binded to the lifetime of the event, so the tool
+ * will be destroyed when the event is destroyed. However, the lifetime of the
+ * tool may be extended by using libinput_tool_ref() to increment the reference
+ * count of the tool. Whenever libinput detects that the tool is in proximity of
+ * any tablet that's connected, it will return the same libinput_tool object.
+ *
+ * @note It is an application bug to call this function for events other than
+ * @ref LIBINPUT_EVENT_TABLET_TOOL_UPDATE.
+ *
+ * @note On tablets where the serial number of tools is not reported, each tool
+ * cannot be guaranteed to be unique.
+ *
+ * @param event The libinput tablet event
+ * @return The new tool triggering this event
+ */
+struct libinput_tool *
+libinput_event_tablet_get_tool(struct libinput_event_tablet *event);
+
/**
* @ingroup event_tablet
*
--
1.8.5.5
More information about the wayland-devel
mailing list