mirror of
https://gitlab.freedesktop.org/libinput/libinput.git
synced 2026-02-04 05:50:26 +01:00
Add basic mouse pointer acceleration
This patch reimplements the simple smooth pointer acceleration profile from X.org xserver. The algorithm is identical to the classic profile with a non-zero pointer acceleration threshold. When support for changable parameters is in place, to get a pointer acceleration the same as the default classic profile of X.org a polynomial acceleration profile should be used for when the threshold parameter is zero. Signed-off-by: Jonas Ådahl <jadahl@gmail.com> Reviewed-by: Hans de Goede <hdegoede@redhat.com>
This commit is contained in:
parent
d4b66061b3
commit
505e92b1a5
4 changed files with 97 additions and 5 deletions
37
src/evdev.c
37
src/evdev.c
|
|
@ -32,9 +32,11 @@
|
|||
#include <mtdev-plumbing.h>
|
||||
#include <assert.h>
|
||||
#include <time.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "libinput.h"
|
||||
#include "evdev.h"
|
||||
#include "filter.h"
|
||||
#include "libinput-private.h"
|
||||
|
||||
#define DEFAULT_AXIS_STEP_DISTANCE li_fixed_from_int(10)
|
||||
|
|
@ -112,8 +114,10 @@ evdev_device_transform_y(struct evdev_device *device,
|
|||
static void
|
||||
evdev_flush_pending_event(struct evdev_device *device, uint64_t time)
|
||||
{
|
||||
struct motion_params motion;
|
||||
int32_t cx, cy;
|
||||
li_fixed_t x, y;
|
||||
li_fixed_t dx, dy;
|
||||
int slot;
|
||||
int seat_slot;
|
||||
struct libinput_device *base = &device->base;
|
||||
|
|
@ -125,12 +129,20 @@ evdev_flush_pending_event(struct evdev_device *device, uint64_t time)
|
|||
case EVDEV_NONE:
|
||||
return;
|
||||
case EVDEV_RELATIVE_MOTION:
|
||||
pointer_notify_motion(base,
|
||||
time,
|
||||
device->rel.dx,
|
||||
device->rel.dy);
|
||||
motion.dx = li_fixed_to_double(device->rel.dx);
|
||||
motion.dy = li_fixed_to_double(device->rel.dy);
|
||||
device->rel.dx = 0;
|
||||
device->rel.dy = 0;
|
||||
|
||||
/* Apply pointer acceleration. */
|
||||
filter_dispatch(device->pointer.filter, &motion, device, time);
|
||||
|
||||
dx = li_fixed_from_double(motion.dx);
|
||||
dy = li_fixed_from_double(motion.dy);
|
||||
if (dx == 0 && dy == 0)
|
||||
break;
|
||||
|
||||
pointer_notify_motion(base, time, dx, dy);
|
||||
break;
|
||||
case EVDEV_ABSOLUTE_MT_DOWN:
|
||||
if (!(device->seat_caps & EVDEV_DEVICE_TOUCH))
|
||||
|
|
@ -566,6 +578,18 @@ evdev_device_dispatch(void *data)
|
|||
}
|
||||
}
|
||||
|
||||
static int
|
||||
configure_pointer_acceleration(struct evdev_device *device)
|
||||
{
|
||||
device->pointer.filter =
|
||||
create_pointer_accelator_filter(
|
||||
pointer_accel_profile_smooth_simple);
|
||||
if (!device->pointer.filter)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
evdev_configure_device(struct evdev_device *device)
|
||||
{
|
||||
|
|
@ -676,7 +700,11 @@ evdev_configure_device(struct evdev_device *device)
|
|||
has_keyboard = 1;
|
||||
|
||||
if ((has_abs || has_rel) && has_button) {
|
||||
if (configure_pointer_acceleration(device) == -1)
|
||||
return -1;
|
||||
|
||||
device->seat_caps |= EVDEV_DEVICE_POINTER;
|
||||
|
||||
log_info("input device '%s', %s is a pointer caps =%s%s%s\n",
|
||||
device->devname, device->devnode,
|
||||
has_abs ? " absolute-motion" : "",
|
||||
|
|
@ -849,6 +877,7 @@ evdev_device_destroy(struct evdev_device *device)
|
|||
if (dispatch)
|
||||
dispatch->interface->destroy(dispatch);
|
||||
|
||||
motion_filter_destroy(device->pointer.filter);
|
||||
libinput_seat_unref(device->base.seat);
|
||||
libevdev_free(device->evdev);
|
||||
free(device->mt.slots);
|
||||
|
|
|
|||
|
|
@ -90,6 +90,10 @@ struct evdev_device {
|
|||
enum evdev_device_seat_capability seat_caps;
|
||||
|
||||
int is_mt;
|
||||
|
||||
struct {
|
||||
struct motion_filter *filter;
|
||||
} pointer;
|
||||
};
|
||||
|
||||
#define EVDEV_UNHANDLED_DEVICE ((struct evdev_device *) 1)
|
||||
|
|
|
|||
47
src/filter.c
47
src/filter.c
|
|
@ -22,6 +22,7 @@
|
|||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <limits.h>
|
||||
|
|
@ -38,7 +39,15 @@ filter_dispatch(struct motion_filter *filter,
|
|||
}
|
||||
|
||||
/*
|
||||
* Pointer acceleration filter
|
||||
* Default parameters for pointer acceleration profiles.
|
||||
*/
|
||||
|
||||
#define DEFAULT_CONSTANT_ACCELERATION 10.0
|
||||
#define DEFAULT_THRESHOLD 4.0
|
||||
#define DEFAULT_ACCELERATION 2.0
|
||||
|
||||
/*
|
||||
* Pointer acceleration filter constants
|
||||
*/
|
||||
|
||||
#define MAX_VELOCITY_DIFF 1.0
|
||||
|
|
@ -340,3 +349,39 @@ motion_filter_destroy(struct motion_filter *filter)
|
|||
|
||||
filter->interface->destroy(filter);
|
||||
}
|
||||
|
||||
static inline double
|
||||
calc_penumbral_gradient(double x)
|
||||
{
|
||||
x *= 2.0;
|
||||
x -= 1.0;
|
||||
return 0.5 + (x * sqrt(1.0 - x * x) + asin(x)) / M_PI;
|
||||
}
|
||||
|
||||
double
|
||||
pointer_accel_profile_smooth_simple(struct motion_filter *filter,
|
||||
void *data,
|
||||
double velocity,
|
||||
uint64_t time)
|
||||
{
|
||||
double threshold = DEFAULT_THRESHOLD;
|
||||
double accel = DEFAULT_ACCELERATION;
|
||||
double smooth_accel_coefficient;
|
||||
|
||||
velocity *= DEFAULT_CONSTANT_ACCELERATION;
|
||||
|
||||
if (velocity < 1.0)
|
||||
return calc_penumbral_gradient(0.5 + velocity * 0.5) * 2.0 - 1.0;
|
||||
if (threshold < 1.0)
|
||||
threshold = 1.0;
|
||||
if (velocity <= threshold)
|
||||
return 1;
|
||||
velocity /= threshold;
|
||||
if (velocity >= accel) {
|
||||
return accel;
|
||||
} else {
|
||||
smooth_accel_coefficient =
|
||||
calc_penumbral_gradient(velocity / accel);
|
||||
return 1.0 + (smooth_accel_coefficient * (accel - 1.0));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
14
src/filter.h
14
src/filter.h
|
|
@ -62,4 +62,18 @@ create_pointer_accelator_filter(accel_profile_func_t filter);
|
|||
void
|
||||
motion_filter_destroy(struct motion_filter *filter);
|
||||
|
||||
/*
|
||||
* Pointer acceleration profiles.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Profile similar which is similar to nonaccelerated but with a smooth
|
||||
* transition between accelerated and non-accelerated.
|
||||
*/
|
||||
double
|
||||
pointer_accel_profile_smooth_simple(struct motion_filter *filter,
|
||||
void *data,
|
||||
double velocity,
|
||||
uint64_t time);
|
||||
|
||||
#endif /* FILTER_H */
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue