[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