tp_init_accel(struct tp_dispatch *tp, double diagonal)
{
int res_x, res_y;
+ accel_profile_func_t profile;
res_x = tp->device->abs.absinfo_x->resolution;
res_y = tp->device->abs.absinfo_y->resolution;
tp->accel.y_scale_coeff = DEFAULT_ACCEL_NUMERATOR / diagonal;
}
- if (evdev_device_init_pointer_acceleration(
- tp->device,
- touchpad_accel_profile_linear) == -1)
+ switch (tp->device->model) {
+ case EVDEV_MODEL_LENOVO_X230:
+ profile = touchpad_lenovo_x230_accel_profile;
+ break;
+ default:
+ profile = touchpad_accel_profile_linear;
+ break;
+ }
+
+ if (evdev_device_init_pointer_acceleration(tp->device, profile) == -1)
return -1;
return 0;
const char *property;
enum evdev_device_model model;
} model_map[] = {
+ { "LIBINPUT_MODEL_LENOVO_X230", EVDEV_MODEL_LENOVO_X230 },
{ NULL, EVDEV_MODEL_DEFAULT },
};
const struct model_map *m = model_map;
return speed_out * TP_MAGIC_SLOWDOWN;
}
+
+double
+touchpad_lenovo_x230_accel_profile(struct motion_filter *filter,
+ void *data,
+ double speed_in,
+ uint64_t time)
+{
+ /* Keep the magic factor from touchpad_accel_profile_linear. */
+ const double TP_MAGIC_SLOWDOWN = 0.4;
+
+ /* Those touchpads presents an actual lower resolution that what is
+ * advertised. We see some jumps from the cursor due to the big steps
+ * in X and Y when we are receiving data.
+ * Apply a factor to minimize those jumps at low speed, and try
+ * keeping the same feeling as regular touchpads at high speed.
+ * It still feels slower but it is usable at least */
+ const double TP_MAGIC_LOW_RES_FACTOR = 4.0;
+ double speed_out;
+ struct pointer_accelerator *accel_filter =
+ (struct pointer_accelerator *)filter;
+
+ double s1, s2;
+ const double max_accel = accel_filter->accel *
+ TP_MAGIC_LOW_RES_FACTOR; /* unitless factor */
+ const double threshold = accel_filter->threshold /
+ TP_MAGIC_LOW_RES_FACTOR; /* units/ms */
+ const double incline = accel_filter->incline * TP_MAGIC_LOW_RES_FACTOR;
+
+ speed_in *= TP_MAGIC_SLOWDOWN / TP_MAGIC_LOW_RES_FACTOR;
+
+ s1 = min(1, speed_in * 5);
+ s2 = 1 + (speed_in - threshold) * incline;
+
+ speed_out = min(max_accel, s2 > 1 ? s2 : s1);
+
+ return speed_out * TP_MAGIC_SLOWDOWN / TP_MAGIC_LOW_RES_FACTOR;
+}