#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)
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;
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))
}
}
+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)
{
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" : "",
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);
#include "config.h"
+#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <limits.h>
}
/*
- * 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
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));
+ }
+}