On Fri, Jun 13, 2014 at 04:27:49AM -0400, Stephen Chandler Paul wrote:
> Signed-off-by: Stephen Chandler Paul <[email protected]>
> ---
>  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 <[email protected]>

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
> [email protected]
> http://lists.freedesktop.org/mailman/listinfo/wayland-devel
> 
_______________________________________________
wayland-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/wayland-devel

Reply via email to