[PATCH libinput 2/8] evdev: Add middle button scrolling for trackpoints

Peter Hutterer peter.hutterer at who-t.net
Wed Sep 17 18:49:36 PDT 2014


On Tue, Sep 16, 2014 at 04:22:36PM +0200, Hans de Goede wrote:
> Most trackpoint users want to be able to scroll using the trackpoint with
> the middle button pressed, add support for this.
> 
> Signed-off-by: Hans de Goede <hdegoede at redhat.com>
> Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>
> ---
>  include/linux/input.h    |  1 +
>  src/evdev.c              | 56 ++++++++++++++++++++++++++++++++++++++++++++++++
>  src/evdev.h              |  5 +++++
>  test/litest-trackpoint.c |  2 ++
>  test/pointer.c           |  4 +++-
>  5 files changed, 67 insertions(+), 1 deletion(-)
> 
> diff --git a/include/linux/input.h b/include/linux/input.h
> index aa98ce7..39b550b 100644
> --- a/include/linux/input.h
> +++ b/include/linux/input.h
> @@ -163,6 +163,7 @@ struct input_keymap_entry {
>  #define INPUT_PROP_BUTTONPAD		0x02	/* has button(s) under pad */
>  #define INPUT_PROP_SEMI_MT		0x03	/* touch rectangle only */
>  #define INPUT_PROP_TOPBUTTONPAD		0x04	/* softbuttons at top of pad */
> +#define INPUT_PROP_POINTING_STICK	0x05	/* is a pointing stick */
>  
>  #define INPUT_PROP_MAX			0x1f
>  #define INPUT_PROP_CNT			(INPUT_PROP_MAX + 1)
> diff --git a/src/evdev.c b/src/evdev.c
> index 45020ba..85e4d71 100644
> --- a/src/evdev.c
> +++ b/src/evdev.c
> @@ -41,6 +41,7 @@
>  #include "libinput-private.h"
>  
>  #define DEFAULT_AXIS_STEP_DISTANCE 10
> +#define DEFAULT_MIDDLE_BUTTON_SCROLL_TIMEOUT 200
>  
>  enum evdev_key_type {
>  	EVDEV_KEY_TYPE_NONE,
> @@ -203,6 +204,15 @@ evdev_flush_pending_event(struct evdev_device *device, uint64_t time)
>  		device->rel.dx = 0;
>  		device->rel.dy = 0;
>  
> +		/* Use unaccelerated deltas for pointing stick scroll */
> +		if (device->scroll.has_middle_button_scroll &&
> +		    hw_is_key_down(device, BTN_MIDDLE)) {
> +			if (device->scroll.middle_button_scroll_active)
> +				evdev_post_scroll(device, time,
> +						  motion.dx, motion.dy);
> +			break;
> +		}
> +

Just to verify: the behaviour here is that the scrolling does not activate
until after the timeout, regardless of the number of motion events during
the timeout period. Is this intentional, or do we need a threshold here?

Cheers,
   Peter


>  		/* Apply pointer acceleration. */
>  		filter_dispatch(device->pointer.filter, &motion, device, time);
>  
> @@ -346,6 +356,37 @@ get_key_type(uint16_t code)
>  }
>  
>  static void
> +evdev_middle_button_scroll_timeout(uint64_t time, void *data)
> +{
> +	struct evdev_device *device = data;
> +
> +	device->scroll.middle_button_scroll_active = true;
> +}
> +
> +static void
> +evdev_middle_button_scroll_button(struct evdev_device *device,
> +				 uint64_t time, int is_press)
> +{
> +	if (is_press) {
> +		libinput_timer_set(&device->scroll.timer,
> +				time + DEFAULT_MIDDLE_BUTTON_SCROLL_TIMEOUT);
> +	} else {
> +		libinput_timer_cancel(&device->scroll.timer);
> +		if (device->scroll.middle_button_scroll_active) {
> +			evdev_stop_scroll(device, time);
> +			device->scroll.middle_button_scroll_active = false;
> +		} else {
> +			/* If the button is released quickly enough emit the
> +			 * button press/release events. */
> +			evdev_pointer_notify_button(device, time, BTN_MIDDLE,
> +					LIBINPUT_BUTTON_STATE_PRESSED);
> +			evdev_pointer_notify_button(device, time, BTN_MIDDLE,
> +					LIBINPUT_BUTTON_STATE_RELEASED);
> +		}
> +	}
> +}
> +
> +static void
>  evdev_process_touch_button(struct evdev_device *device,
>  			   uint64_t time, int value)
>  {
> @@ -405,6 +446,12 @@ evdev_process_key(struct evdev_device *device,
>  				   LIBINPUT_KEY_STATE_RELEASED);
>  		break;
>  	case EVDEV_KEY_TYPE_BUTTON:
> +		if (device->scroll.has_middle_button_scroll &&
> +		    e->code == BTN_MIDDLE) {
> +			evdev_middle_button_scroll_button(device, time,
> +							  e->value);
> +			break;
> +		}
>  		evdev_pointer_notify_button(
>  			device,
>  			time,
> @@ -946,6 +993,15 @@ evdev_configure_device(struct evdev_device *device)
>  			device->mt.slot = active_slot;
>  		}
>  	}
> +
> +	if (libevdev_has_property(evdev, INPUT_PROP_POINTING_STICK)) {
> +		libinput_timer_init(&device->scroll.timer,
> +				    device->base.seat->libinput,
> +				    evdev_middle_button_scroll_timeout,
> +				    device);
> +		device->scroll.has_middle_button_scroll = true;
> +	}
> +
>  	if (libevdev_has_event_code(evdev, EV_REL, REL_X) ||
>  	    libevdev_has_event_code(evdev, EV_REL, REL_Y))
>  		has_rel = 1;
> diff --git a/src/evdev.h b/src/evdev.h
> index 311dddc..e1506d2 100644
> --- a/src/evdev.h
> +++ b/src/evdev.h
> @@ -26,10 +26,12 @@
>  
>  #include "config.h"
>  
> +#include <stdbool.h>
>  #include "linux/input.h"
>  #include <libevdev/libevdev.h>
>  
>  #include "libinput-private.h"
> +#include "timer.h"
>  
>  enum evdev_event_type {
>  	EVDEV_NONE,
> @@ -96,6 +98,9 @@ struct evdev_device {
>  	} rel;
>  
>  	struct {
> +		struct libinput_timer timer;
> +		bool has_middle_button_scroll;
> +		bool middle_button_scroll_active;
>  		double threshold;
>  		uint32_t direction;
>  	} scroll;
> diff --git a/test/litest-trackpoint.c b/test/litest-trackpoint.c
> index 25a377c..40b9ed0 100644
> --- a/test/litest-trackpoint.c
> +++ b/test/litest-trackpoint.c
> @@ -49,6 +49,8 @@ static int events[] = {
>  	EV_KEY, BTN_MIDDLE,
>  	EV_REL, REL_X,
>  	EV_REL, REL_Y,
> +	INPUT_PROP_MAX, INPUT_PROP_POINTER,
> +	INPUT_PROP_MAX, INPUT_PROP_POINTING_STICK,
>  	-1, -1,
>  };
>  
> diff --git a/test/pointer.c b/test/pointer.c
> index 82c5245..f704372 100644
> --- a/test/pointer.c
> +++ b/test/pointer.c
> @@ -132,7 +132,9 @@ START_TEST(pointer_button)
>  		test_button_event(dev, BTN_RIGHT, 0);
>  	}
>  
> -	if (libevdev_has_event_code(dev->evdev, EV_KEY, BTN_MIDDLE)) {
> +	/* Skip middle button test on trackpoints (used for scrolling) */
> +	if (!libevdev_has_property(dev->evdev, INPUT_PROP_POINTING_STICK) &&
> +	    libevdev_has_event_code(dev->evdev, EV_KEY, BTN_MIDDLE)) {
>  		test_button_event(dev, BTN_MIDDLE, 1);
>  		test_button_event(dev, BTN_MIDDLE, 0);
>  	}
> -- 
> 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