[PATCH libinput 7/8] tablet: split out tip handling into a separate event
Peter Hutterer
peter.hutterer at who-t.net
Wed Nov 11 13:13:01 PST 2015
The tablet tip works like a button in the kernel but is otherwise not really
a button. Split it into an explicit tip up/down event instead.
Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
---
src/libinput-private.h | 7 +++++++
src/libinput.c | 42 ++++++++++++++++++++++++++++++++++++++++++
src/libinput.h | 41 +++++++++++++++++++++++++++++++++++++++++
src/libinput.sym | 1 +
test/litest.c | 8 ++++++++
test/tablet.c | 4 +++-
tools/event-debug.c | 18 ++++++++++++++++++
tools/event-gui.c | 34 ++++++++++++++++++++++++++++++++++
8 files changed, 154 insertions(+), 1 deletion(-)
diff --git a/src/libinput-private.h b/src/libinput-private.h
index 3d61222..0e7ddff 100644
--- a/src/libinput-private.h
+++ b/src/libinput-private.h
@@ -477,6 +477,13 @@ tablet_notify_proximity(struct libinput_device *device,
double *axes);
void
+tablet_notify_tip(struct libinput_device *device,
+ uint64_t time,
+ struct libinput_tool *tool,
+ enum libinput_tool_tip_state tip_state,
+ double *axes);
+
+void
tablet_notify_button(struct libinput_device *device,
uint64_t time,
struct libinput_tool *tool,
diff --git a/src/libinput.c b/src/libinput.c
index 79e4863..c47f9fc 100644
--- a/src/libinput.c
+++ b/src/libinput.c
@@ -137,6 +137,7 @@ struct libinput_event_tablet {
unsigned char changed_axes[NCHARS(LIBINPUT_TABLET_AXIS_MAX + 1)];
struct libinput_tool *tool;
enum libinput_tool_proximity_state proximity_state;
+ enum libinput_tool_tip_state tip_state;
};
static void
@@ -313,6 +314,7 @@ libinput_event_get_tablet_event(struct libinput_event *event)
NULL,
LIBINPUT_EVENT_TABLET_AXIS,
LIBINPUT_EVENT_TABLET_PROXIMITY,
+ LIBINPUT_EVENT_TABLET_TIP,
LIBINPUT_EVENT_TABLET_BUTTON);
return (struct libinput_event_tablet *) event;
@@ -918,6 +920,7 @@ libinput_event_tablet_axis_has_changed(struct libinput_event_tablet *event,
event->base.type,
0,
LIBINPUT_EVENT_TABLET_AXIS,
+ LIBINPUT_EVENT_TABLET_TIP,
LIBINPUT_EVENT_TABLET_PROXIMITY);
return (NCHARS(axis) <= sizeof(event->changed_axes)) ?
@@ -935,6 +938,7 @@ libinput_event_tablet_get_axis_value(struct libinput_event_tablet *event,
event->base.type,
0,
LIBINPUT_EVENT_TABLET_AXIS,
+ LIBINPUT_EVENT_TABLET_TIP,
LIBINPUT_EVENT_TABLET_PROXIMITY);
switch(axis) {
@@ -968,6 +972,7 @@ libinput_event_tablet_get_axis_delta(struct libinput_event_tablet *event,
event->base.type,
0,
LIBINPUT_EVENT_TABLET_AXIS,
+ LIBINPUT_EVENT_TABLET_TIP,
LIBINPUT_EVENT_TABLET_PROXIMITY);
switch(axis) {
@@ -999,6 +1004,7 @@ libinput_event_tablet_get_axis_delta_discrete(
event->base.type,
0,
LIBINPUT_EVENT_TABLET_AXIS,
+ LIBINPUT_EVENT_TABLET_TIP,
LIBINPUT_EVENT_TABLET_PROXIMITY);
switch(axis) {
@@ -1028,6 +1034,7 @@ libinput_event_tablet_get_x_transformed(struct libinput_event_tablet *event,
event->base.type,
0,
LIBINPUT_EVENT_TABLET_AXIS,
+ LIBINPUT_EVENT_TABLET_TIP,
LIBINPUT_EVENT_TABLET_PROXIMITY);
return evdev_device_transform_x(device,
@@ -1046,6 +1053,7 @@ libinput_event_tablet_get_y_transformed(struct libinput_event_tablet *event,
event->base.type,
0,
LIBINPUT_EVENT_TABLET_AXIS,
+ LIBINPUT_EVENT_TABLET_TIP,
LIBINPUT_EVENT_TABLET_PROXIMITY);
return evdev_device_transform_y(device,
@@ -1065,6 +1073,12 @@ libinput_event_tablet_get_proximity_state(struct libinput_event_tablet *event)
return event->proximity_state;
}
+LIBINPUT_EXPORT enum libinput_tool_tip_state
+libinput_event_tablet_get_tip_state(struct libinput_event_tablet *event)
+{
+ return event->tip_state;
+}
+
LIBINPUT_EXPORT uint32_t
libinput_event_tablet_get_time(struct libinput_event_tablet *event)
{
@@ -1970,6 +1984,34 @@ tablet_notify_proximity(struct libinput_device *device,
}
void
+tablet_notify_tip(struct libinput_device *device,
+ uint64_t time,
+ struct libinput_tool *tool,
+ enum libinput_tool_tip_state tip_state,
+ double *axes)
+{
+ struct libinput_event_tablet *tip_event;
+
+ tip_event = zalloc(sizeof *tip_event);
+ if (!tip_event)
+ return;
+
+ *tip_event = (struct libinput_event_tablet) {
+ .time = time,
+ .tool = tool,
+ .tip_state = tip_state,
+ };
+ memcpy(tip_event->axes,
+ axes,
+ sizeof(tip_event->axes));
+
+ post_device_event(device,
+ time,
+ LIBINPUT_EVENT_TABLET_TIP,
+ &tip_event->base);
+}
+
+void
tablet_notify_button(struct libinput_device *device,
uint64_t time,
struct libinput_tool *tool,
diff --git a/src/libinput.h b/src/libinput.h
index c5f9da7..dc7e7d8 100644
--- a/src/libinput.h
+++ b/src/libinput.h
@@ -217,6 +217,20 @@ enum libinput_tool_proximity_state {
};
/**
+ * @ingroup device
+ *
+ * The tip contact state for a tool on a device. The device must have
+ * the @ref LIBINPUT_DEVICE_CAP_TABLET capability.
+ *
+ * The tip contact state of a tool is a binary state signalling whether the tool is
+ * touching the surface of the tablet device.
+ */
+enum libinput_tool_tip_state {
+ LIBINPUT_TOOL_TIP_UP = 0,
+ LIBINPUT_TOOL_TIP_DOWN = 1,
+};
+
+/**
* @ingroup base
*
* Event type for events returned by libinput_get_event().
@@ -301,6 +315,19 @@ enum libinput_event_type {
* proximity out event.
*/
LIBINPUT_EVENT_TABLET_PROXIMITY,
+ /**
+ * Signals that a tool has come in contact with the surface of a
+ * device with the @ref LIBINPUT_DEVICE_CAP_TABLET capability.
+ *
+ * On devices without distance proximity detection, the @ref
+ * LIBINPUT_EVENT_TABLET_TIP is sent immediately after @ref
+ * LIBINPUT_EVENT_TABLET_PROXIMITY for the tip down event, and
+ * immediately before for the tip up event.
+ *
+ * If a button and/or axis state change occurs at the same time as a
+ * tip state change, the order of events is device-dependent.
+ */
+ LIBINPUT_EVENT_TABLET_TIP,
LIBINPUT_EVENT_TABLET_BUTTON,
LIBINPUT_EVENT_GESTURE_SWIPE_BEGIN = 800,
@@ -1502,6 +1529,20 @@ libinput_event_tablet_get_proximity_state(struct libinput_event_tablet *event);
/**
* @ingroup event_tablet
*
+ * Returns the new tip state of a tool from a tip event.
+ * Used to check whether or not a tool came in contact with the tablet
+ * surface or left contact with the tablet surface during an
+ * event of type @ref LIBINPUT_EVENT_TABLET_TIP.
+ *
+ * @param event The libinput tablet event
+ * @return The new tip state of the tool from the event.
+ */
+enum libinput_tool_tip_state
+libinput_event_tablet_get_tip_state(struct libinput_event_tablet *event);
+
+/**
+ * @ingroup event_tablet
+ *
* Return the button that triggered this event.
* For tablet events that are not of type @ref LIBINPUT_EVENT_TABLET_BUTTON, this
* function returns 0.
diff --git a/src/libinput.sym b/src/libinput.sym
index 1c297c7..33d5b33 100644
--- a/src/libinput.sym
+++ b/src/libinput.sym
@@ -195,6 +195,7 @@ LIBINPUT_TABLET_SUPPORT {
libinput_event_tablet_get_proximity_state;
libinput_event_tablet_get_seat_button_count;
libinput_event_tablet_get_time;
+ libinput_event_tablet_get_tip_state;
libinput_event_tablet_get_tool;
libinput_event_tablet_get_x_transformed;
libinput_event_tablet_get_y_transformed;
diff --git a/test/litest.c b/test/litest.c
index ce2a6a7..4bbabb2 100644
--- a/test/litest.c
+++ b/test/litest.c
@@ -1887,6 +1887,9 @@ litest_event_type_str(struct libinput_event *event)
case LIBINPUT_EVENT_TABLET_PROXIMITY:
str = "TABLET PROX";
break;
+ case LIBINPUT_EVENT_TABLET_TIP:
+ str = "TABLET TIP";
+ break;
case LIBINPUT_EVENT_TABLET_BUTTON:
str = "TABLET BUTTON";
break;
@@ -1949,6 +1952,11 @@ litest_print_event(struct libinput_event *event)
fprintf(stderr, "proximity %d\n",
libinput_event_tablet_get_proximity_state(t));
break;
+ case LIBINPUT_EVENT_TABLET_TIP:
+ t = libinput_event_get_tablet_event(event);
+ fprintf(stderr, "tip %d\n",
+ libinput_event_tablet_get_tip_state(t));
+ break;
case LIBINPUT_EVENT_TABLET_BUTTON:
t = libinput_event_get_tablet_event(event);
fprintf(stderr, "button %d state %d\n",
diff --git a/test/tablet.c b/test/tablet.c
index 5dcb9d3..444290c 100644
--- a/test/tablet.c
+++ b/test/tablet.c
@@ -118,7 +118,7 @@ START_TEST(proximity_out_clear_buttons)
/* Test that proximity out events send button releases for any currently
* pressed stylus buttons
*/
- for (button = BTN_TOUCH; button <= BTN_STYLUS2; button++) {
+ for (button = BTN_TOUCH + 1; button <= BTN_STYLUS2; button++) {
bool button_released = false;
uint32_t event_button;
enum libinput_button_state state;
@@ -155,6 +155,8 @@ START_TEST(proximity_out_clear_buttons)
libevdev_event_code_get_name(EV_KEY, button),
event_button);
}
+
+ litest_assert_empty_queue(li);
}
END_TEST
diff --git a/tools/event-debug.c b/tools/event-debug.c
index 05fb1a7..f0ae1dc 100644
--- a/tools/event-debug.c
+++ b/tools/event-debug.c
@@ -115,6 +115,9 @@ print_event_header(struct libinput_event *ev)
case LIBINPUT_EVENT_TABLET_PROXIMITY:
type = "TABLET_PROXIMITY";
break;
+ case LIBINPUT_EVENT_TABLET_TIP:
+ type = "TABLET_TIP";
+ break;
case LIBINPUT_EVENT_TABLET_BUTTON:
type = "TABLET_BUTTON";
break;
@@ -279,6 +282,18 @@ print_pointer_button_event(struct libinput_event *ev)
}
static void
+print_tablet_tip_event(struct libinput_event *ev)
+{
+ struct libinput_event_tablet *p = libinput_event_get_tablet_event(ev);
+ enum libinput_tool_tip_state state;
+
+ print_event_time(libinput_event_tablet_get_time(p));
+
+ state = libinput_event_tablet_get_tip_state(p);
+ printf("%s\n", state == LIBINPUT_TOOL_TIP_DOWN ? "down" : "up");
+}
+
+static void
print_tablet_button_event(struct libinput_event *ev)
{
struct libinput_event_tablet *p = libinput_event_get_tablet_event(ev);
@@ -667,6 +682,9 @@ handle_and_print_events(struct libinput *li)
case LIBINPUT_EVENT_TABLET_PROXIMITY:
print_proximity_event(ev);
break;
+ case LIBINPUT_EVENT_TABLET_TIP:
+ print_tablet_tip_event(ev);
+ break;
case LIBINPUT_EVENT_TABLET_BUTTON:
print_tablet_button_event(ev);
break;
diff --git a/tools/event-gui.c b/tools/event-gui.c
index c07213f..a7d8dd9 100644
--- a/tools/event-gui.c
+++ b/tools/event-gui.c
@@ -88,6 +88,8 @@ struct window {
struct {
double x, y;
double x_in, y_in;
+ double x_down, y_down;
+ double x_up, y_up;
double pressure;
double distance;
double tilt_x, tilt_y;
@@ -234,6 +236,20 @@ draw(GtkWidget *widget, cairo_t *cr, gpointer data)
cairo_save(cr);
}
+ if (w->tool.x_down && w->tool.y_down) {
+ cairo_rectangle(cr, w->tool.x_down - 10, w->tool.y_down - 10, 20, 20);
+ cairo_stroke(cr);
+ cairo_restore(cr);
+ cairo_save(cr);
+ }
+
+ if (w->tool.x_up && w->tool.y_up) {
+ cairo_rectangle(cr, w->tool.x_up - 10, w->tool.y_up - 10, 20, 20);
+ cairo_stroke(cr);
+ cairo_restore(cr);
+ cairo_save(cr);
+ }
+
if (w->tool.pressure)
cairo_set_source_rgb(cr, .8, .8, .2);
@@ -584,6 +600,7 @@ static void
handle_event_tablet(struct libinput_event *ev, struct window *w)
{
struct libinput_event_tablet *t = libinput_event_get_tablet_event(ev);
+ double x, y;
switch (libinput_event_get_type(ev)) {
case LIBINPUT_EVENT_TABLET_PROXIMITY:
@@ -591,6 +608,10 @@ handle_event_tablet(struct libinput_event *ev, struct window *w)
LIBINPUT_TOOL_PROXIMITY_OUT) {
w->tool.x_in = 0;
w->tool.y_in = 0;
+ w->tool.x_down = 0;
+ w->tool.y_down = 0;
+ w->tool.x_up = 0;
+ w->tool.y_up = 0;
} else {
w->tool.x_in = libinput_event_tablet_get_x_transformed(t,
w->width);
@@ -612,6 +633,18 @@ handle_event_tablet(struct libinput_event *ev, struct window *w)
w->tool.tilt_y = libinput_event_tablet_get_axis_value(t,
LIBINPUT_TABLET_AXIS_TILT_Y);
break;
+ case LIBINPUT_EVENT_TABLET_TIP:
+ x = libinput_event_tablet_get_x_transformed(t, w->width);
+ y = libinput_event_tablet_get_y_transformed(t, w->height);
+ if (libinput_event_tablet_get_tip_state(t) ==
+ LIBINPUT_TOOL_TIP_DOWN) {
+ w->tool.x_down = x;
+ w->tool.y_down = y;
+ } else {
+ w->tool.x_up = x;
+ w->tool.y_up = y;
+ }
+ break;
case LIBINPUT_EVENT_TABLET_BUTTON:
break;
default:
@@ -676,6 +709,7 @@ handle_event_libinput(GIOChannel *source, GIOCondition condition, gpointer data)
break;
case LIBINPUT_EVENT_TABLET_AXIS:
case LIBINPUT_EVENT_TABLET_PROXIMITY:
+ case LIBINPUT_EVENT_TABLET_TIP:
case LIBINPUT_EVENT_TABLET_BUTTON:
handle_event_tablet(ev, w);
break;
--
2.4.3
More information about the wayland-devel
mailing list