[PATCH libinput 5/8] touchpad: Route top softbuttons through the trackstick if we've one

Peter Hutterer peter.hutterer at who-t.net
Wed Sep 17 20:17:29 PDT 2014


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 <hdegoede at redhat.com>

Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>
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
> wayland-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/wayland-devel
> 


More information about the wayland-devel mailing list