Commit 1318ffad authored by Peter Hutterer's avatar Peter Hutterer

tablet: split out tip handling into a separate event

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's avatarPeter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: default avatarHans de Goede <hdegoede@redhat.com>
parent 30dbd671
......@@ -476,6 +476,13 @@ tablet_notify_proximity(struct libinput_device *device,
unsigned char *changed_axes,
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,
......
......@@ -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)
{
......@@ -1969,6 +1983,34 @@ tablet_notify_proximity(struct libinput_device *device,
&proximity_event->base);
}
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,
......
......@@ -216,6 +216,20 @@ enum libinput_tool_proximity_state {
LIBINPUT_TOOL_PROXIMITY_IN = 1,
};
/**
* @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
*
......@@ -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,
......@@ -1499,6 +1526,20 @@ libinput_event_tablet_get_tool(struct libinput_event_tablet *event);
enum libinput_tool_proximity_state
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
*
......
......@@ -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;
......
......@@ -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",
......
......@@ -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
......
......@@ -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;
......@@ -278,6 +281,18 @@ print_pointer_button_event(struct libinput_event *ev)
libinput_event_pointer_get_seat_button_count(p));
}
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)
{
......@@ -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;
......
......@@ -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;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment