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
