On Tue, Sep 16, 2014 at 04:22:39PM +0200, Hans de Goede wrote:
> The touchpad top softbuttons such as found on the Lenove T440 are intended for
> use with the trackstick. Route their events through the trackstick, so that
> they can be used for e.g. middle button scrolling with the trackstick.
> 
> Note that sending top button events to a disabled trackpoint makes no sense
> (and will mess up internal state). Likely a user with a disabled trackpoint
> will still expect the top buttons to work, so rather than not sending events
> in that case, simply treat a suspendeded trackpoint as not being there, and
> send the events directly from the touchpad device.
> 
> Signed-off-by: Hans de Goede <[email protected]>

Reviewed-by: Peter Hutterer <[email protected]>
but see the notes below

> ---
>  doc/touchpad-softbutton-state-machine.svg | 200 
> +++++++++++++++++-------------
>  src/evdev-mt-touchpad-buttons.c           |  45 +++++--
>  src/evdev-mt-touchpad.c                   |  17 ++-
>  src/evdev-mt-touchpad.h                   |   1 +
>  4 files changed, 163 insertions(+), 100 deletions(-)
> 
> diff --git a/doc/touchpad-softbutton-state-machine.svg 
> b/doc/touchpad-softbutton-state-machine.svg
> index 1d569bf..ffa17a2 100644
> --- a/doc/touchpad-softbutton-state-machine.svg
> +++ b/doc/touchpad-softbutton-state-machine.svg
[...]
> diff --git a/src/evdev-mt-touchpad-buttons.c b/src/evdev-mt-touchpad-buttons.c
> index 02d3205..0fdabde 100644
> --- a/src/evdev-mt-touchpad-buttons.c
> +++ b/src/evdev-mt-touchpad-buttons.c
> @@ -675,16 +675,40 @@ tp_post_physical_buttons(struct tp_dispatch *tp, 
> uint64_t time)
>       return 0;
>  }
>  
> +static void
> +tp_notify_softbutton(struct tp_dispatch *tp,
> +                  uint64_t time,
> +                  uint32_t button,
> +                  uint32_t is_top,

just because I prefer it: I replaced this with is_topbutton, and
active_is_top with active_is_topbutton (simple sed, both times)

> +                  enum libinput_button_state state)
> +{
> +     /* If we've a trackpoint, send top buttons through the trackpoint */
> +     if (is_top && tp->buttons.trackpoint) {
> +             struct evdev_dispatch *dispatch = 
> tp->buttons.trackpoint->dispatch;
> +             struct input_event event;
> +
> +             event.type = EV_KEY,
> +             event.code = button,

I'm going to assume you meant ; here instead of ',' so I've replaced those
after applying.

> +             event.value = (state == LIBINPUT_BUTTON_STATE_PRESSED) ? 1 : 0;

for correctness, we should set the time here too, I've added

+               event.time.tv_sec = time/1000;
+               event.time.tv_usec = (time % 1000) * 1000;


patch coming up, just double-check it please.

Cheers,
   Peter

> +             dispatch->interface->process(dispatch, tp->buttons.trackpoint,
> +                                          &event, time);
> +             return;
> +     }
> +
> +     evdev_pointer_notify_button(tp->device, time, button, state);
> +}
> +
>  static int
>  tp_post_softbutton_buttons(struct tp_dispatch *tp, uint64_t time)
>  {
> -     uint32_t current, old, button;
> +     uint32_t current, old, button, is_top;
>       enum libinput_button_state state;
>       enum { AREA = 0x01, LEFT = 0x02, MIDDLE = 0x04, RIGHT = 0x08 };
>  
>       current = tp->buttons.state;
>       old = tp->buttons.old_state;
>       button = 0;
> +     is_top = 0;
>  
>       if (!tp->buttons.click_pending && current == old)
>               return 0;
> @@ -697,15 +721,18 @@ tp_post_softbutton_buttons(struct tp_dispatch *tp, 
> uint64_t time)
>                       case BUTTON_EVENT_IN_AREA:
>                               button |= AREA;
>                               break;
> -                     case BUTTON_EVENT_IN_BOTTOM_L:
>                       case BUTTON_EVENT_IN_TOP_L:
> +                             is_top = 1;
> +                     case BUTTON_EVENT_IN_BOTTOM_L:
>                               button |= LEFT;
>                               break;
>                       case BUTTON_EVENT_IN_TOP_M:
> +                             is_top = 1;
>                               button |= MIDDLE;
>                               break;
> -                     case BUTTON_EVENT_IN_BOTTOM_R:
>                       case BUTTON_EVENT_IN_TOP_R:
> +                             is_top = 1;
> +                     case BUTTON_EVENT_IN_BOTTOM_R:
>                               button |= RIGHT;
>                               break;
>                       default:
> @@ -727,21 +754,21 @@ tp_post_softbutton_buttons(struct tp_dispatch *tp, 
> uint64_t time)
>                       button = BTN_LEFT;
>  
>               tp->buttons.active = button;
> +             tp->buttons.active_is_top = is_top;
>               state = LIBINPUT_BUTTON_STATE_PRESSED;
>       } else {
>               button = tp->buttons.active;
> +             is_top = tp->buttons.active_is_top;
>               tp->buttons.active = 0;
> +             tp->buttons.active_is_top = 0;
>               state = LIBINPUT_BUTTON_STATE_RELEASED;
>       }
>  
>       tp->buttons.click_pending = false;
>  
> -     if (button) {
> -             evdev_pointer_notify_button(tp->device,
> -                                         time,
> -                                         button,
> -                                         state);
> -     }
> +     if (button)
> +             tp_notify_softbutton(tp, time, button, is_top, state);
> +
>       return 1;
>  }
>  
> diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c
> index a0ad8db..73e08c1 100644
> --- a/src/evdev-mt-touchpad.c
> +++ b/src/evdev-mt-touchpad.c
> @@ -643,8 +643,11 @@ tp_device_added(struct evdev_device *device,
>       struct tp_dispatch *tp = (struct tp_dispatch*)device->dispatch;
>  
>       if (tp->buttons.trackpoint == NULL &&
> -         (added_device->tags & EVDEV_TAG_TRACKPOINT))
> +         (added_device->tags & EVDEV_TAG_TRACKPOINT)) {
> +             /* Don't send any pending releases to the new trackpoint */
> +             tp->buttons.active_is_top = 0;
>               tp->buttons.trackpoint = added_device;
> +     }
>  
>       if (tp->sendevents.current_mode !=
>           LIBINPUT_CONFIG_SEND_EVENTS_DISABLED_ON_EXTERNAL_MOUSE)
> @@ -661,8 +664,14 @@ tp_device_removed(struct evdev_device *device,
>       struct tp_dispatch *tp = (struct tp_dispatch*)device->dispatch;
>       struct libinput_device *dev;
>  
> -     if (removed_device == tp->buttons.trackpoint)
> +     if (removed_device == tp->buttons.trackpoint) {
> +             /* Clear any pending releases for the trackpoint */
> +             if (tp->buttons.active && tp->buttons.active_is_top) {
> +                     tp->buttons.active = 0;
> +                     tp->buttons.active_is_top = 0;
> +             }
>               tp->buttons.trackpoint = NULL;
> +     }
>  
>       if (tp->sendevents.current_mode !=
>           LIBINPUT_CONFIG_SEND_EVENTS_DISABLED_ON_EXTERNAL_MOUSE)
> @@ -703,8 +712,8 @@ static struct evdev_dispatch_interface tp_interface = {
>       tp_destroy,
>       tp_device_added,
>       tp_device_removed,
> -     NULL, /* device_suspended */
> -     NULL, /* device_resumed */
> +     tp_device_removed, /* device_suspended, treat as remove */
> +     tp_device_added,   /* device_resumed, treat as add */
>       tp_tag_device,
>  };
>  
> diff --git a/src/evdev-mt-touchpad.h b/src/evdev-mt-touchpad.h
> index 4a16db9..15cca76 100644
> --- a/src/evdev-mt-touchpad.h
> +++ b/src/evdev-mt-touchpad.h
> @@ -183,6 +183,7 @@ struct tp_dispatch {
>               uint32_t old_state;
>               uint32_t motion_dist;           /* for pinned touches */
>               unsigned int active;            /* currently active button, for 
> release event */
> +             unsigned int active_is_top;     /* is active a top button? */
>  
>               /* Only used for clickpads. The software button areas are
>                * always 2 horizontal stripes across the touchpad.
> -- 
> 2.1.0
> 
> _______________________________________________
> 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