[PATCH weston] evdev: Mouse speed and acceleration

Daniel Stone daniel at fooishbar.org
Wed Jul 17 10:53:42 PDT 2013


Hi,
Did anything happen with these? Additionally, the tuning seems a
little hostile: if we have a subset of known-good values, we should
probably mostly stick to those.  Really, I'd just love to see a 1-10
'speed' configuration item that just does the right thing, rather than
having to guess the magic number.

Cheers,
Daniel

On 3 April 2013 05:17, Daniel Stone <daniel at fooishbar.org> wrote:
> Hi Martin,
> By and large this looks good to me, although the main comment I have
> is that this should probably be using the acceleration mechanism in
> src/filter.c.
>
> Cheers,
> Daniel
>
> On 29 March 2013 20:47, Martin Minarik <minarik11 at student.fiit.stuba.sk> wrote:
>> Acceleration: After examining, I don't like the X acceleration
>> approach. X employs a so called velocity approximation (?)
>> algorithm. It is quite a complex way to get an approximation of
>> a simple thing, the velocity, when we can compute the velocity
>> directly.
>>
>> Configuring: Please, tune the values in mouse_init().
>>
>> The tune speed coefficient is simply a multiplier of how fast
>> the mouse moves. The 1.0 is the real (raw) device speed.
>> These tune speed coefficients feel very natural to use:
>>
>>  0.03125 0.0625 0.25 0.5 0.75 1.0 1.5 2.0 2.5 3.0 3.5
>>
>> The acceleration boost factor (at 1.0 speed coefficient):
>>
>>  0.01 - NO effect
>>  0.02 - small effect
>>  0.06 - medium effect
>>  0.10 - pretty strong
>>  0.13 - TOO strong
>>
>> This patch does not introduce smoothing.
>> ---
>>  src/Makefile.am   |    4 +
>>  src/evdev-mouse.c |  240 +++++++++++++++++++++++++++++++++++++++++++++++++++++
>>  src/evdev.c       |    3 +
>>  src/evdev.h       |    3 +
>>  4 files changed, 250 insertions(+)
>>  create mode 100644 src/evdev-mouse.c
>>
>> diff --git a/src/Makefile.am b/src/Makefile.am
>> index d56daa0..2c8b3eb 100644
>> --- a/src/Makefile.am
>> +++ b/src/Makefile.am
>> @@ -138,6 +138,7 @@ drm_backend_la_SOURCES =                    \
>>         udev-seat.h                             \
>>         evdev.c                                 \
>>         evdev.h                                 \
>> +       evdev-mouse.c                           \
>>         evdev-touchpad.c                        \
>>         launcher-util.c                         \
>>         launcher-util.h                         \
>> @@ -177,7 +178,9 @@ rpi_backend_la_SOURCES =                    \
>>         tty.c                                   \
>>         evdev.c                                 \
>>         evdev.h                                 \
>> +       evdev-mouse.c                           \
>>         evdev-touchpad.c
>> +
>>  endif
>>
>>  if ENABLE_HEADLESS_COMPOSITOR
>> @@ -211,6 +214,7 @@ fbdev_backend_la_SOURCES = \
>>         evdev.c \
>>         evdev.h \
>>         evdev-touchpad.c \
>> +       evdev-mouse.c \
>>         launcher-util.c
>>  endif
>>
>> diff --git a/src/evdev-mouse.c b/src/evdev-mouse.c
>> new file mode 100644
>> index 0000000..b4915cd
>> --- /dev/null
>> +++ b/src/evdev-mouse.c
>> @@ -0,0 +1,240 @@
>> +#include <stdlib.h>
>> +#include <stdbool.h>
>> +
>> +#include "compositor.h"
>> +#include "evdev.h"
>> +
>> +#define DEFAULT_AXIS_STEP_DISTANCE wl_fixed_from_int(10)
>> +#define MOUSE_VELOCITY_SAMPLING_INTERVAL 20
>> +
>> +struct mouse_motion {
>> +       int32_t dx;
>> +       int32_t dy;
>> +};
>> +
>> +struct mouse_dispatch {
>> +       struct evdev_dispatch base;
>> +       struct evdev_device *device;
>> +
>> +       double actual_speed;
>> +
>> +       struct mouse_motion motion_sample;
>> +       uint32_t motion_time_next_sample;
>> +       uint32_t motion_time_out;
>> +       unsigned long int last_velocity_sq;
>> +
>> +       /* tuneable */
>> +       bool tune_is_acceleration;
>> +       double tune_acceleration_boost;
>> +       double tune_speed_coefficient;
>> +};
>> +
>> +static inline void
>> +mouse_process_relative(struct mouse_dispatch *mouse,
>> +                      struct evdev_device *device,
>> +                      struct input_event *event, uint32_t time)
>> +{
>> +       switch (event->code) {
>> +       case REL_X:
>> +               if (mouse->tune_is_acceleration)
>> +                       mouse->motion_sample.dx += event->value;
>> +               device->rel.dx += wl_fixed_from_double(
>> +                               (double) event->value * mouse->actual_speed);
>> +
>> +               device->pending_events |= EVDEV_RELATIVE_MOTION;
>> +               break;
>> +       case REL_Y:
>> +               if (mouse->tune_is_acceleration)
>> +                       mouse->motion_sample.dy += event->value;
>> +               device->rel.dy += wl_fixed_from_double(
>> +                               (double) event->value * mouse->actual_speed);
>> +
>> +               device->pending_events |= EVDEV_RELATIVE_MOTION;
>> +               break;
>> +       case REL_WHEEL:
>> +               switch (event->value) {
>> +               case -1:
>> +                       /* Scroll down */
>> +               case 1:
>> +                       /* Scroll up */
>> +                       notify_axis(device->seat,
>> +                                   time,
>> +                                   WL_POINTER_AXIS_VERTICAL_SCROLL,
>> +                                   -1 * event->value * DEFAULT_AXIS_STEP_DISTANCE);
>> +                       break;
>> +               default:
>> +                       break;
>> +               }
>> +               break;
>> +       case REL_HWHEEL:
>> +               switch (event->value) {
>> +               case -1:
>> +                       /* Scroll left */
>> +               case 1:
>> +                       /* Scroll right */
>> +                       notify_axis(device->seat,
>> +                                   time,
>> +                                   WL_POINTER_AXIS_HORIZONTAL_SCROLL,
>> +                                   event->value * DEFAULT_AXIS_STEP_DISTANCE);
>> +                       break;
>> +               default:
>> +                       break;
>> +
>> +               }
>> +       }
>> +}
>> +
>> +static inline void
>> +mouse_process_key(struct mouse_dispatch *mouse,
>> +           struct evdev_device *device,
>> +           struct input_event *e,
>> +           uint32_t time)
>> +{
>> +       if (e->value == 2)
>> +               return;
>> +
>> +       switch (e->code) {
>> +       case BTN_LEFT:
>> +       case BTN_RIGHT:
>> +       case BTN_MIDDLE:
>> +       case BTN_SIDE:
>> +       case BTN_EXTRA:
>> +       case BTN_FORWARD:
>> +       case BTN_BACK:
>> +       case BTN_TASK:
>> +               notify_button(device->seat,
>> +                             time, e->code,
>> +                             e->value ? WL_POINTER_BUTTON_STATE_PRESSED :
>> +                                        WL_POINTER_BUTTON_STATE_RELEASED);
>> +               break;
>> +
>> +       default:
>> +               notify_key(device->seat,
>> +                          time, e->code,
>> +                          e->value ? WL_KEYBOARD_KEY_STATE_PRESSED :
>> +                                     WL_KEYBOARD_KEY_STATE_RELEASED,
>> +                          STATE_UPDATE_AUTOMATIC);
>> +               break;
>> +       }
>> +}
>> +
>> +static void
>> +mouse_reset_acceleration(struct mouse_dispatch *mouse, uint32_t time)
>> +{
>> +       struct mouse_motion *m = &mouse->motion_sample;
>> +       unsigned const int interval = MOUSE_VELOCITY_SAMPLING_INTERVAL;
>> +
>> +       mouse->last_velocity_sq = 0;
>> +       mouse->actual_speed = mouse->tune_speed_coefficient;
>> +       mouse->motion_time_out = 2 * interval + time;
>> +       mouse->motion_time_next_sample = interval + time;
>> +
>> +       m->dx = 0;
>> +       m->dy = 0;
>> +}
>> +
>> +static void
>> +mouse_recompute_acceleration(struct mouse_dispatch *mouse, uint32_t time)
>> +{
>> +       struct mouse_motion *m = &mouse->motion_sample;
>> +       unsigned const int interval = MOUSE_VELOCITY_SAMPLING_INTERVAL;
>> +
>> +       unsigned long int velocity_sq;
>> +       const double no_decceleration = 1.0;
>> +       double acceleration;
>> +
>> +       velocity_sq = m->dx * m->dx + m->dy * m->dy;
>> +
>> +       if (velocity_sq > mouse->last_velocity_sq)
>> +               acceleration = pow(velocity_sq - mouse->last_velocity_sq,
>> +                       mouse->tune_acceleration_boost);
>> +       else
>> +               acceleration = no_decceleration;
>> +
>> +       mouse->last_velocity_sq = velocity_sq;
>> +       mouse->actual_speed = mouse->tune_speed_coefficient * acceleration;
>> +       mouse->motion_time_out += interval;
>> +       mouse->motion_time_next_sample += interval;
>> +
>> +       m->dx = 0;
>> +       m->dy = 0;
>> +}
>> +
>> +static void
>> +mouse_process(struct evdev_dispatch *dispatch,
>> +                struct evdev_device *device,
>> +                struct input_event *event,
>> +                uint32_t time)
>> +{
>> +       struct mouse_dispatch *mouse =
>> +               (struct mouse_dispatch *) dispatch;
>> +
>> +       switch (event->type) {
>> +       case EV_REL:
>> +               mouse_process_relative(mouse, device, event, time);
>> +               break;
>> +       case EV_KEY:
>> +               mouse_process_key(mouse, device, event, time);
>> +               break;
>> +       case EV_SYN:
>> +               device->pending_events |= EVDEV_SYN;
>> +
>> +               if ((mouse->tune_is_acceleration) &&
>> +                  (time > mouse->motion_time_next_sample)) {
>> +                       if (time > mouse->motion_time_out)
>> +                               mouse_reset_acceleration(mouse, time);
>> +                       else
>> +                               mouse_recompute_acceleration(mouse, time);
>> +               }
>> +               break;
>> +       }
>> +}
>> +
>> +static void
>> +mouse_destroy(struct evdev_dispatch *dispatch)
>> +{
>> +       struct mouse_dispatch *mouse =
>> +               (struct mouse_dispatch *) dispatch;
>> +
>> +       free(mouse);
>> +}
>> +
>> +struct evdev_dispatch_interface mouse_interface = {
>> +       mouse_process,
>> +       mouse_destroy
>> +};
>> +
>> +static int
>> +mouse_init(struct mouse_dispatch *mouse,
>> +             struct evdev_device *device)
>> +{
>> +       mouse->base.interface = &mouse_interface;
>> +       mouse->device = device;
>> +
>> +       /* Configure mouse velocity, acceleration */
>> +       mouse->tune_is_acceleration = true;
>> +       mouse->tune_acceleration_boost = 0.03;
>> +       mouse->tune_speed_coefficient = 2.00;
>> +
>> +       /* Prepare velocity tracking */
>> +       mouse_reset_acceleration(mouse, 0);
>> +
>> +       return 0;
>> +}
>> +
>> +struct evdev_dispatch *
>> +evdev_mouse_create(struct evdev_device *device)
>> +{
>> +       struct mouse_dispatch *mouse;
>> +
>> +       mouse = malloc(sizeof *mouse);
>> +       if (mouse == NULL)
>> +               return NULL;
>> +
>> +       if (mouse_init(mouse, device) != 0) {
>> +               free(mouse);
>> +               return NULL;
>> +       }
>> +
>> +       return &mouse->base;
>> +}
>> diff --git a/src/evdev.c b/src/evdev.c
>> index d2954b5..bbad5ad 100644
>> --- a/src/evdev.c
>> +++ b/src/evdev.c
>> @@ -459,6 +459,9 @@ evdev_handle_device(struct evdev_device *device)
>>                     !TEST_BIT(key_bits, BTN_TOOL_PEN) &&
>>                     has_abs)
>>                         device->dispatch = evdev_touchpad_create(device);
>> +               else if (TEST_BIT(key_bits, BTN_LEFT) && !has_abs)
>> +                       device->dispatch = evdev_mouse_create(device);
>> +
>>                 for (i = KEY_ESC; i < KEY_MAX; i++) {
>>                         if (i >= BTN_MISC && i < KEY_OK)
>>                                 continue;
>> diff --git a/src/evdev.h b/src/evdev.h
>> index eb5c868..f670682 100644
>> --- a/src/evdev.h
>> +++ b/src/evdev.h
>> @@ -111,6 +111,9 @@ struct evdev_dispatch {
>>  struct evdev_dispatch *
>>  evdev_touchpad_create(struct evdev_device *device);
>>
>> +struct evdev_dispatch *
>> +evdev_mouse_create(struct evdev_device *device);
>> +
>>  void
>>  evdev_led_update(struct evdev_device *device, enum weston_led leds);
>>
>> --
>> 1.7.10.4
>>
>> _______________________________________________
>> 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