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 <[email protected]>
> Reviewed-by: Peter Hutterer <[email protected]>
> ---
>  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
> [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