[PATCH libinput] tablet: Handle button-events
Peter Hutterer
peter.hutterer at who-t.net
Sun Jun 15 22:49:12 PDT 2014
On Fri, Jun 13, 2014 at 04:27:49AM -0400, Stephen Chandler Paul wrote:
> 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;
rename flags to mask, that's a more common name for this approach.
> +
> + /* 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);
you need the assert before you're setting the mask, just move it up by those
couple of lines.
Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>
Cheers,
Peter
> +}
> +
> +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
>
> _______________________________________________
> wayland-devel mailing list
> wayland-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/wayland-devel
>
More information about the wayland-devel
mailing list