mirror of
https://gitlab.freedesktop.org/libinput/libinput.git
synced 2026-01-07 17:00:16 +01:00
Merge branch 'master' into tablet-support
This commit is contained in:
commit
ab6a409cdc
21 changed files with 1561 additions and 814 deletions
|
|
@ -2,7 +2,7 @@ AC_PREREQ([2.64])
|
|||
|
||||
m4_define([libinput_major_version], [1])
|
||||
m4_define([libinput_minor_version], [0])
|
||||
m4_define([libinput_micro_version], [0])
|
||||
m4_define([libinput_micro_version], [901])
|
||||
m4_define([libinput_version],
|
||||
[libinput_major_version.libinput_minor_version.libinput_micro_version])
|
||||
|
||||
|
|
|
|||
|
|
@ -9,6 +9,16 @@ This page explains the high-level concepts used in the code. It aims to
|
|||
provide an overview for developers and is not necessarily useful for
|
||||
users.
|
||||
|
||||
@section ptraccel-profiles Pointer acceleration profiles
|
||||
|
||||
The profile decides the general method of pointer acceleration.
|
||||
libinput currently supports two profiles: "adaptive" and "flat". The aptive
|
||||
profile is the default profile for all devices and takes the current speed
|
||||
of the device into account when deciding on acceleration. The flat profile
|
||||
is simply a constant factor applied to all device deltas, regardless of the
|
||||
speed of motion (see @ref ptraccel-profile-flat). Most of this document
|
||||
describes the adaptive pointer acceleration.
|
||||
|
||||
@section ptraccel-velocity Velocity calculation
|
||||
|
||||
The device's speed of movement is measured across multiple input events
|
||||
|
|
@ -107,4 +117,11 @@ The image above shows the trackpoint acceleration profile in comparison to the
|
|||
@ref ptraccel-linear. The constant acceleration factor, usually applied by
|
||||
udev, shapes the acceleration profile.
|
||||
|
||||
@section ptraccel-profile-flat The flat pointer acceleration profile
|
||||
|
||||
In a flat profile, the acceleration factor is constant regardless of the
|
||||
velocity of the pointer and each delta (dx, dy) results in an accelerated delta
|
||||
(dx * factor, dy * factor). This provides 1:1 movement between the device
|
||||
and the pointer on-screen.
|
||||
|
||||
*/
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
Before Width: | Height: | Size: 122 KiB After Width: | Height: | Size: 134 KiB |
|
|
@ -69,6 +69,7 @@ tap_state_to_str(enum tp_tap_state state)
|
|||
CASE_RETURN_STRING(TAP_STATE_TAPPED);
|
||||
CASE_RETURN_STRING(TAP_STATE_TOUCH_2);
|
||||
CASE_RETURN_STRING(TAP_STATE_TOUCH_2_HOLD);
|
||||
CASE_RETURN_STRING(TAP_STATE_TOUCH_2_RELEASE);
|
||||
CASE_RETURN_STRING(TAP_STATE_TOUCH_3);
|
||||
CASE_RETURN_STRING(TAP_STATE_TOUCH_3_HOLD);
|
||||
CASE_RETURN_STRING(TAP_STATE_DRAGGING);
|
||||
|
|
@ -275,12 +276,8 @@ tp_tap_touch2_handle_event(struct tp_dispatch *tp,
|
|||
tp_tap_set_timer(tp, time);
|
||||
break;
|
||||
case TAP_EVENT_RELEASE:
|
||||
tp->tap.state = TAP_STATE_HOLD;
|
||||
if (t->tap.state == TAP_TOUCH_STATE_TOUCH) {
|
||||
tp_tap_notify(tp, time, 2, LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
tp_tap_notify(tp, time, 2, LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
}
|
||||
tp_tap_clear_timer(tp);
|
||||
tp->tap.state = TAP_STATE_TOUCH_2_RELEASE;
|
||||
tp_tap_set_timer(tp, time);
|
||||
break;
|
||||
case TAP_EVENT_MOTION:
|
||||
tp_tap_clear_timer(tp);
|
||||
|
|
@ -322,6 +319,35 @@ tp_tap_touch2_hold_handle_event(struct tp_dispatch *tp,
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
tp_tap_touch2_release_handle_event(struct tp_dispatch *tp,
|
||||
struct tp_touch *t,
|
||||
enum tap_event event, uint64_t time)
|
||||
{
|
||||
|
||||
switch (event) {
|
||||
case TAP_EVENT_TOUCH:
|
||||
tp->tap.state = TAP_STATE_TOUCH_2_HOLD;
|
||||
t->tap.state = TAP_TOUCH_STATE_DEAD;
|
||||
tp_tap_clear_timer(tp);
|
||||
break;
|
||||
case TAP_EVENT_RELEASE:
|
||||
tp_tap_notify(tp, time, 2, LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
tp_tap_notify(tp, time, 2, LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
tp->tap.state = TAP_STATE_IDLE;
|
||||
break;
|
||||
case TAP_EVENT_MOTION:
|
||||
case TAP_EVENT_TIMEOUT:
|
||||
tp->tap.state = TAP_STATE_HOLD;
|
||||
break;
|
||||
case TAP_EVENT_BUTTON:
|
||||
tp->tap.state = TAP_STATE_DEAD;
|
||||
break;
|
||||
case TAP_EVENT_THUMB:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
tp_tap_touch3_handle_event(struct tp_dispatch *tp,
|
||||
struct tp_touch *t,
|
||||
|
|
@ -570,21 +596,11 @@ tp_tap_multitap_down_handle_event(struct tp_dispatch *tp,
|
|||
break;
|
||||
case TAP_EVENT_TOUCH:
|
||||
tp->tap.state = TAP_STATE_DRAGGING_2;
|
||||
tp_tap_notify(tp,
|
||||
tp->tap.multitap_last_time,
|
||||
1,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
tp_tap_notify(tp, time, 1, LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
tp_tap_clear_timer(tp);
|
||||
break;
|
||||
case TAP_EVENT_MOTION:
|
||||
case TAP_EVENT_TIMEOUT:
|
||||
tp->tap.state = TAP_STATE_DRAGGING;
|
||||
tp_tap_notify(tp,
|
||||
tp->tap.multitap_last_time,
|
||||
1,
|
||||
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||
tp_tap_notify(tp, time, 1, LIBINPUT_BUTTON_STATE_PRESSED);
|
||||
tp_tap_clear_timer(tp);
|
||||
break;
|
||||
case TAP_EVENT_BUTTON:
|
||||
|
|
@ -649,6 +665,9 @@ tp_tap_handle_event(struct tp_dispatch *tp,
|
|||
case TAP_STATE_TOUCH_2_HOLD:
|
||||
tp_tap_touch2_hold_handle_event(tp, t, event, time);
|
||||
break;
|
||||
case TAP_STATE_TOUCH_2_RELEASE:
|
||||
tp_tap_touch2_release_handle_event(tp, t, event, time);
|
||||
break;
|
||||
case TAP_STATE_TOUCH_3:
|
||||
tp_tap_touch3_handle_event(tp, t, event, time);
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -1519,11 +1519,38 @@ tp_init_slots(struct tp_dispatch *tp,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
tp_accel_config_get_profiles(struct libinput_device *libinput_device)
|
||||
{
|
||||
return LIBINPUT_CONFIG_ACCEL_PROFILE_NONE;
|
||||
}
|
||||
|
||||
static enum libinput_config_status
|
||||
tp_accel_config_set_profile(struct libinput_device *libinput_device,
|
||||
enum libinput_config_accel_profile profile)
|
||||
{
|
||||
return LIBINPUT_CONFIG_STATUS_UNSUPPORTED;
|
||||
}
|
||||
|
||||
static enum libinput_config_accel_profile
|
||||
tp_accel_config_get_profile(struct libinput_device *libinput_device)
|
||||
{
|
||||
return LIBINPUT_CONFIG_ACCEL_PROFILE_NONE;
|
||||
}
|
||||
|
||||
static enum libinput_config_accel_profile
|
||||
tp_accel_config_get_default_profile(struct libinput_device *libinput_device)
|
||||
{
|
||||
return LIBINPUT_CONFIG_ACCEL_PROFILE_NONE;
|
||||
}
|
||||
|
||||
static int
|
||||
tp_init_accel(struct tp_dispatch *tp, double diagonal)
|
||||
{
|
||||
struct evdev_device *device = tp->device;
|
||||
int res_x, res_y;
|
||||
struct motion_filter *filter;
|
||||
int rc;
|
||||
|
||||
res_x = tp->device->abs.absinfo_x->resolution;
|
||||
res_y = tp->device->abs.absinfo_y->resolution;
|
||||
|
|
@ -1546,7 +1573,18 @@ tp_init_accel(struct tp_dispatch *tp, double diagonal)
|
|||
if (!filter)
|
||||
return -1;
|
||||
|
||||
return evdev_device_init_pointer_acceleration(tp->device, filter);
|
||||
rc = evdev_device_init_pointer_acceleration(tp->device, filter);
|
||||
if (rc != 0)
|
||||
return rc;
|
||||
|
||||
/* we override the profile hooks for accel configuration with hooks
|
||||
* that don't allow selection of profiles */
|
||||
device->pointer.config.get_profiles = tp_accel_config_get_profiles;
|
||||
device->pointer.config.set_profile = tp_accel_config_set_profile;
|
||||
device->pointer.config.get_profile = tp_accel_config_get_profile;
|
||||
device->pointer.config.get_default_profile = tp_accel_config_get_default_profile;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
|
|
|
|||
|
|
@ -97,6 +97,7 @@ enum tp_tap_state {
|
|||
TAP_STATE_TAPPED,
|
||||
TAP_STATE_TOUCH_2,
|
||||
TAP_STATE_TOUCH_2_HOLD,
|
||||
TAP_STATE_TOUCH_2_RELEASE,
|
||||
TAP_STATE_TOUCH_3,
|
||||
TAP_STATE_TOUCH_3_HOLD,
|
||||
TAP_STATE_DRAGGING_OR_DOUBLETAP,
|
||||
|
|
|
|||
143
src/evdev.c
143
src/evdev.c
|
|
@ -1386,6 +1386,27 @@ evdev_device_dispatch(void *data)
|
|||
}
|
||||
}
|
||||
|
||||
static inline int
|
||||
evdev_init_accel(struct evdev_device *device,
|
||||
enum libinput_config_accel_profile which)
|
||||
{
|
||||
struct motion_filter *filter;
|
||||
|
||||
if (which == LIBINPUT_CONFIG_ACCEL_PROFILE_FLAT)
|
||||
filter = create_pointer_accelerator_filter_flat(device->dpi);
|
||||
else if (device->tags & EVDEV_TAG_TRACKPOINT)
|
||||
filter = create_pointer_accelerator_filter_trackpoint(device->dpi);
|
||||
else if (device->dpi < DEFAULT_MOUSE_DPI)
|
||||
filter = create_pointer_accelerator_filter_linear_low_dpi(device->dpi);
|
||||
else
|
||||
filter = create_pointer_accelerator_filter_linear(device->dpi);
|
||||
|
||||
if (!filter)
|
||||
return -1;
|
||||
|
||||
return evdev_device_init_pointer_acceleration(device, filter);
|
||||
}
|
||||
|
||||
static int
|
||||
evdev_accel_config_available(struct libinput_device *device)
|
||||
{
|
||||
|
|
@ -1419,20 +1440,83 @@ evdev_accel_config_get_default_speed(struct libinput_device *device)
|
|||
return 0.0;
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
evdev_accel_config_get_profiles(struct libinput_device *libinput_device)
|
||||
{
|
||||
struct evdev_device *device = (struct evdev_device*)libinput_device;
|
||||
|
||||
if (!device->pointer.filter)
|
||||
return LIBINPUT_CONFIG_ACCEL_PROFILE_NONE;
|
||||
|
||||
return LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE |
|
||||
LIBINPUT_CONFIG_ACCEL_PROFILE_FLAT;
|
||||
}
|
||||
|
||||
static enum libinput_config_status
|
||||
evdev_accel_config_set_profile(struct libinput_device *libinput_device,
|
||||
enum libinput_config_accel_profile profile)
|
||||
{
|
||||
struct evdev_device *device = (struct evdev_device*)libinput_device;
|
||||
struct motion_filter *filter;
|
||||
double speed;
|
||||
|
||||
filter = device->pointer.filter;
|
||||
if (filter_get_type(filter) == profile)
|
||||
return LIBINPUT_CONFIG_STATUS_SUCCESS;
|
||||
|
||||
speed = filter_get_speed(filter);
|
||||
device->pointer.filter = NULL;
|
||||
|
||||
if (evdev_init_accel(device, profile) == 0) {
|
||||
evdev_accel_config_set_speed(libinput_device, speed);
|
||||
filter_destroy(filter);
|
||||
} else {
|
||||
device->pointer.filter = filter;
|
||||
}
|
||||
|
||||
return LIBINPUT_CONFIG_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static enum libinput_config_accel_profile
|
||||
evdev_accel_config_get_profile(struct libinput_device *libinput_device)
|
||||
{
|
||||
struct evdev_device *device = (struct evdev_device*)libinput_device;
|
||||
|
||||
return filter_get_type(device->pointer.filter);
|
||||
}
|
||||
|
||||
static enum libinput_config_accel_profile
|
||||
evdev_accel_config_get_default_profile(struct libinput_device *libinput_device)
|
||||
{
|
||||
struct evdev_device *device = (struct evdev_device*)libinput_device;
|
||||
|
||||
if (!device->pointer.filter)
|
||||
return LIBINPUT_CONFIG_ACCEL_PROFILE_NONE;
|
||||
|
||||
/* No device has a flat profile as default */
|
||||
return LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE;
|
||||
}
|
||||
|
||||
int
|
||||
evdev_device_init_pointer_acceleration(struct evdev_device *device,
|
||||
struct motion_filter *filter)
|
||||
{
|
||||
device->pointer.filter = filter;
|
||||
|
||||
device->pointer.config.available = evdev_accel_config_available;
|
||||
device->pointer.config.set_speed = evdev_accel_config_set_speed;
|
||||
device->pointer.config.get_speed = evdev_accel_config_get_speed;
|
||||
device->pointer.config.get_default_speed = evdev_accel_config_get_default_speed;
|
||||
device->base.config.accel = &device->pointer.config;
|
||||
if (device->base.config.accel == NULL) {
|
||||
device->pointer.config.available = evdev_accel_config_available;
|
||||
device->pointer.config.set_speed = evdev_accel_config_set_speed;
|
||||
device->pointer.config.get_speed = evdev_accel_config_get_speed;
|
||||
device->pointer.config.get_default_speed = evdev_accel_config_get_default_speed;
|
||||
device->pointer.config.get_profiles = evdev_accel_config_get_profiles;
|
||||
device->pointer.config.set_profile = evdev_accel_config_set_profile;
|
||||
device->pointer.config.get_profile = evdev_accel_config_get_profile;
|
||||
device->pointer.config.get_default_profile = evdev_accel_config_get_default_profile;
|
||||
device->base.config.accel = &device->pointer.config;
|
||||
|
||||
evdev_accel_config_set_speed(&device->base,
|
||||
evdev_accel_config_get_default_speed(&device->base));
|
||||
evdev_accel_config_set_speed(&device->base,
|
||||
evdev_accel_config_get_default_speed(&device->base));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1869,24 +1953,6 @@ evdev_configure_mt_device(struct evdev_device *device)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static inline int
|
||||
evdev_init_accel(struct evdev_device *device)
|
||||
{
|
||||
struct motion_filter *filter;
|
||||
|
||||
if (device->tags & EVDEV_TAG_TRACKPOINT)
|
||||
filter = create_pointer_accelerator_filter_trackpoint(device->dpi);
|
||||
else if (device->dpi < DEFAULT_MOUSE_DPI)
|
||||
filter = create_pointer_accelerator_filter_linear_low_dpi(device->dpi);
|
||||
else
|
||||
filter = create_pointer_accelerator_filter_linear(device->dpi);
|
||||
|
||||
if (!filter)
|
||||
return -1;
|
||||
|
||||
return evdev_device_init_pointer_acceleration(device, filter);
|
||||
}
|
||||
|
||||
static int
|
||||
evdev_configure_device(struct evdev_device *device)
|
||||
{
|
||||
|
|
@ -1919,6 +1985,13 @@ evdev_configure_device(struct evdev_device *device)
|
|||
udev_tags & EVDEV_UDEV_TAG_ACCELEROMETER ? " Accelerometer" : "",
|
||||
udev_tags & EVDEV_UDEV_TAG_BUTTONSET ? " Buttonset" : "");
|
||||
|
||||
if (udev_tags & EVDEV_UDEV_TAG_ACCELEROMETER) {
|
||||
log_info(libinput,
|
||||
"input device '%s', %s is an accelerometer, ignoring\n",
|
||||
device->devname, devnode);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* libwacom *adds* TABLET, TOUCHPAD but leaves JOYSTICK in place, so
|
||||
make sure we only ignore real joystick devices */
|
||||
if ((udev_tags & EVDEV_UDEV_TAG_JOYSTICK) == udev_tags) {
|
||||
|
|
@ -1998,7 +2071,7 @@ evdev_configure_device(struct evdev_device *device)
|
|||
|
||||
if (libevdev_has_event_code(evdev, EV_REL, REL_X) &&
|
||||
libevdev_has_event_code(evdev, EV_REL, REL_Y) &&
|
||||
evdev_init_accel(device) == -1)
|
||||
evdev_init_accel(device, LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE) == -1)
|
||||
return -1;
|
||||
|
||||
device->seat_caps |= EVDEV_DEVICE_POINTER;
|
||||
|
|
@ -2098,27 +2171,17 @@ static int
|
|||
evdev_set_device_group(struct evdev_device *device,
|
||||
struct udev_device *udev_device)
|
||||
{
|
||||
struct libinput *libinput = device->base.seat->libinput;
|
||||
struct libinput_device_group *group = NULL;
|
||||
const char *udev_group;
|
||||
|
||||
udev_group = udev_device_get_property_value(udev_device,
|
||||
"LIBINPUT_DEVICE_GROUP");
|
||||
if (udev_group) {
|
||||
struct libinput_device *d;
|
||||
|
||||
list_for_each(d, &device->base.seat->devices_list, link) {
|
||||
const char *identifier = d->group->identifier;
|
||||
|
||||
if (identifier &&
|
||||
strcmp(identifier, udev_group) == 0) {
|
||||
group = d->group;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (udev_group)
|
||||
group = libinput_device_group_find_group(libinput, udev_group);
|
||||
|
||||
if (!group) {
|
||||
group = libinput_device_group_create(udev_group);
|
||||
group = libinput_device_group_create(libinput, udev_group);
|
||||
if (!group)
|
||||
return 1;
|
||||
libinput_device_set_device_group(&device->base, group);
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@
|
|||
#include "filter.h"
|
||||
|
||||
struct motion_filter_interface {
|
||||
enum libinput_config_accel_profile type;
|
||||
struct normalized_coords (*filter)(
|
||||
struct motion_filter *filter,
|
||||
const struct normalized_coords *unaccelerated,
|
||||
|
|
|
|||
132
src/filter.c
132
src/filter.c
|
|
@ -76,13 +76,14 @@ void
|
|||
filter_restart(struct motion_filter *filter,
|
||||
void *data, uint64_t time)
|
||||
{
|
||||
filter->interface->restart(filter, data, time);
|
||||
if (filter->interface->restart)
|
||||
filter->interface->restart(filter, data, time);
|
||||
}
|
||||
|
||||
void
|
||||
filter_destroy(struct motion_filter *filter)
|
||||
{
|
||||
if (!filter)
|
||||
if (!filter || !filter->interface->destroy)
|
||||
return;
|
||||
|
||||
filter->interface->destroy(filter);
|
||||
|
|
@ -101,6 +102,12 @@ filter_get_speed(struct motion_filter *filter)
|
|||
return filter->speed_adjustment;
|
||||
}
|
||||
|
||||
enum libinput_config_accel_profile
|
||||
filter_get_type(struct motion_filter *filter)
|
||||
{
|
||||
return filter->interface->type;
|
||||
}
|
||||
|
||||
/*
|
||||
* Default parameters for pointer acceleration profiles.
|
||||
*/
|
||||
|
|
@ -114,6 +121,8 @@ filter_get_speed(struct motion_filter *filter)
|
|||
#define X230_THRESHOLD v_ms2us(0.4) /* in units/us */
|
||||
#define X230_ACCELERATION 2.0 /* unitless factor */
|
||||
#define X230_INCLINE 1.1 /* unitless factor */
|
||||
#define X230_MAGIC_SLOWDOWN 0.4 /* unitless */
|
||||
#define X230_TP_MAGIC_LOW_RES_FACTOR 4.0 /* unitless */
|
||||
|
||||
/*
|
||||
* Pointer acceleration filter constants
|
||||
|
|
@ -147,6 +156,13 @@ struct pointer_accelerator {
|
|||
double dpi_factor;
|
||||
};
|
||||
|
||||
struct pointer_accelerator_flat {
|
||||
struct motion_filter base;
|
||||
|
||||
double factor;
|
||||
double dpi_factor;
|
||||
};
|
||||
|
||||
static void
|
||||
feed_trackers(struct pointer_accelerator *accel,
|
||||
const struct normalized_coords *delta,
|
||||
|
|
@ -420,6 +436,21 @@ accelerator_filter_x230(struct motion_filter *filter,
|
|||
return accelerated;
|
||||
}
|
||||
|
||||
static struct normalized_coords
|
||||
accelerator_filter_constant_x230(struct motion_filter *filter,
|
||||
const struct normalized_coords *unaccelerated,
|
||||
void *data, uint64_t time)
|
||||
{
|
||||
struct normalized_coords normalized;
|
||||
const double factor =
|
||||
X230_MAGIC_SLOWDOWN/X230_TP_MAGIC_LOW_RES_FACTOR;
|
||||
|
||||
normalized.x = factor * unaccelerated->x;
|
||||
normalized.y = factor * unaccelerated->y;
|
||||
|
||||
return normalized;
|
||||
}
|
||||
|
||||
static struct normalized_coords
|
||||
touchpad_constant_filter(struct motion_filter *filter,
|
||||
const struct normalized_coords *unaccelerated,
|
||||
|
|
@ -631,26 +662,22 @@ touchpad_lenovo_x230_accel_profile(struct motion_filter *filter,
|
|||
double speed_in,
|
||||
uint64_t time)
|
||||
{
|
||||
/* Keep the magic factor from touchpad_accel_profile_linear. */
|
||||
const double X230_MAGIC_SLOWDOWN = 0.4; /* unitless */
|
||||
|
||||
/* 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; /* unitless */
|
||||
double factor; /* unitless */
|
||||
struct pointer_accelerator *accel_filter =
|
||||
(struct pointer_accelerator *)filter;
|
||||
|
||||
double f1, f2; /* unitless */
|
||||
const double max_accel = accel_filter->accel *
|
||||
TP_MAGIC_LOW_RES_FACTOR; /* unitless factor */
|
||||
X230_TP_MAGIC_LOW_RES_FACTOR; /* unitless factor */
|
||||
const double threshold = accel_filter->threshold /
|
||||
TP_MAGIC_LOW_RES_FACTOR; /* units/us */
|
||||
const double incline = accel_filter->incline * TP_MAGIC_LOW_RES_FACTOR;
|
||||
X230_TP_MAGIC_LOW_RES_FACTOR; /* units/us */
|
||||
const double incline = accel_filter->incline * X230_TP_MAGIC_LOW_RES_FACTOR;
|
||||
|
||||
/* Note: the magic values in this function are obtained by
|
||||
* trial-and-error. No other meaning should be interpreted.
|
||||
|
|
@ -658,14 +685,14 @@ touchpad_lenovo_x230_accel_profile(struct motion_filter *filter,
|
|||
* pointer_accel_profile_linear(), look at the git history of that
|
||||
* function for an explaination of what the min/max/etc. does.
|
||||
*/
|
||||
speed_in *= X230_MAGIC_SLOWDOWN / TP_MAGIC_LOW_RES_FACTOR;
|
||||
speed_in *= X230_MAGIC_SLOWDOWN / X230_TP_MAGIC_LOW_RES_FACTOR;
|
||||
|
||||
f1 = min(1, v_us2ms(speed_in) * 5);
|
||||
f2 = 1 + (v_us2ms(speed_in) - v_us2ms(threshold)) * incline;
|
||||
|
||||
factor = min(max_accel, f2 > 1 ? f2 : f1);
|
||||
|
||||
return factor * X230_MAGIC_SLOWDOWN / TP_MAGIC_LOW_RES_FACTOR;
|
||||
return factor * X230_MAGIC_SLOWDOWN / X230_TP_MAGIC_LOW_RES_FACTOR;
|
||||
}
|
||||
|
||||
double
|
||||
|
|
@ -701,6 +728,7 @@ trackpoint_accel_profile(struct motion_filter *filter,
|
|||
}
|
||||
|
||||
struct motion_filter_interface accelerator_interface = {
|
||||
.type = LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE,
|
||||
.filter = accelerator_filter,
|
||||
.filter_constant = accelerator_filter_noop,
|
||||
.restart = accelerator_restart,
|
||||
|
|
@ -748,6 +776,7 @@ create_pointer_accelerator_filter_linear(int dpi)
|
|||
}
|
||||
|
||||
struct motion_filter_interface accelerator_interface_low_dpi = {
|
||||
.type = LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE,
|
||||
.filter = accelerator_filter_low_dpi,
|
||||
.filter_constant = accelerator_filter_noop,
|
||||
.restart = accelerator_restart,
|
||||
|
|
@ -771,6 +800,7 @@ create_pointer_accelerator_filter_linear_low_dpi(int dpi)
|
|||
}
|
||||
|
||||
struct motion_filter_interface accelerator_interface_touchpad = {
|
||||
.type = LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE,
|
||||
.filter = accelerator_filter,
|
||||
.filter_constant = touchpad_constant_filter,
|
||||
.restart = accelerator_restart,
|
||||
|
|
@ -794,8 +824,9 @@ create_pointer_accelerator_filter_touchpad(int dpi)
|
|||
}
|
||||
|
||||
struct motion_filter_interface accelerator_interface_x230 = {
|
||||
.type = LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE,
|
||||
.filter = accelerator_filter_x230,
|
||||
.filter_constant = accelerator_filter_noop,
|
||||
.filter_constant = accelerator_filter_constant_x230,
|
||||
.restart = accelerator_restart,
|
||||
.destroy = accelerator_destroy,
|
||||
.set_speed = accelerator_set_speed,
|
||||
|
|
@ -832,6 +863,7 @@ create_pointer_accelerator_filter_lenovo_x230(int dpi)
|
|||
}
|
||||
|
||||
struct motion_filter_interface accelerator_interface_trackpoint = {
|
||||
.type = LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE,
|
||||
.filter = accelerator_filter_trackpoint,
|
||||
.filter_constant = accelerator_filter_noop,
|
||||
.restart = accelerator_restart,
|
||||
|
|
@ -856,3 +888,79 @@ create_pointer_accelerator_filter_trackpoint(int dpi)
|
|||
|
||||
return &filter->base;
|
||||
}
|
||||
|
||||
static struct normalized_coords
|
||||
accelerator_filter_flat(struct motion_filter *filter,
|
||||
const struct normalized_coords *unaccelerated,
|
||||
void *data, uint64_t time)
|
||||
{
|
||||
struct pointer_accelerator_flat *accel_filter =
|
||||
(struct pointer_accelerator_flat *)filter;
|
||||
double factor; /* unitless factor */
|
||||
struct normalized_coords accelerated;
|
||||
struct normalized_coords unnormalized;
|
||||
|
||||
/* You want flat acceleration, you get flat acceleration for the
|
||||
* device */
|
||||
unnormalized.x = unaccelerated->x * accel_filter->dpi_factor;
|
||||
unnormalized.y = unaccelerated->y * accel_filter->dpi_factor;
|
||||
factor = accel_filter->factor;
|
||||
|
||||
accelerated.x = factor * unnormalized.x;
|
||||
accelerated.y = factor * unnormalized.y;
|
||||
|
||||
return accelerated;
|
||||
}
|
||||
|
||||
static bool
|
||||
accelerator_set_speed_flat(struct motion_filter *filter,
|
||||
double speed_adjustment)
|
||||
{
|
||||
struct pointer_accelerator_flat *accel_filter =
|
||||
(struct pointer_accelerator_flat *)filter;
|
||||
|
||||
assert(speed_adjustment >= -1.0 && speed_adjustment <= 1.0);
|
||||
|
||||
/* Speed rage is 0-200% of the nominal speed, with 0 mapping to the
|
||||
* nominal speed. Anything above 200 is pointless, we're already
|
||||
* skipping over ever second pixel at 200% speed.
|
||||
*/
|
||||
|
||||
accel_filter->factor = 1 + speed_adjustment;
|
||||
filter->speed_adjustment = speed_adjustment;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void
|
||||
accelerator_destroy_flat(struct motion_filter *filter)
|
||||
{
|
||||
struct pointer_accelerator_flat *accel =
|
||||
(struct pointer_accelerator_flat *) filter;
|
||||
|
||||
free(accel);
|
||||
}
|
||||
|
||||
struct motion_filter_interface accelerator_interface_flat = {
|
||||
.type = LIBINPUT_CONFIG_ACCEL_PROFILE_FLAT,
|
||||
.filter = accelerator_filter_flat,
|
||||
.filter_constant = accelerator_filter_noop,
|
||||
.restart = NULL,
|
||||
.destroy = accelerator_destroy_flat,
|
||||
.set_speed = accelerator_set_speed_flat,
|
||||
};
|
||||
|
||||
struct motion_filter *
|
||||
create_pointer_accelerator_filter_flat(int dpi)
|
||||
{
|
||||
struct pointer_accelerator_flat *filter;
|
||||
|
||||
filter = zalloc(sizeof *filter);
|
||||
if (filter == NULL)
|
||||
return NULL;
|
||||
|
||||
filter->base.interface = &accelerator_interface_flat;
|
||||
filter->dpi_factor = dpi/(double)DEFAULT_MOUSE_DPI;
|
||||
|
||||
return &filter->base;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -74,12 +74,17 @@ filter_set_speed(struct motion_filter *filter,
|
|||
double
|
||||
filter_get_speed(struct motion_filter *filter);
|
||||
|
||||
enum libinput_config_accel_profile
|
||||
filter_get_type(struct motion_filter *filter);
|
||||
|
||||
typedef double (*accel_profile_func_t)(struct motion_filter *filter,
|
||||
void *data,
|
||||
double velocity,
|
||||
uint64_t time);
|
||||
|
||||
/* Pointer acceleration types */
|
||||
struct motion_filter *
|
||||
create_pointer_accelerator_filter_flat(int dpi);
|
||||
|
||||
struct motion_filter *
|
||||
create_pointer_accelerator_filter_linear(int dpi);
|
||||
|
|
|
|||
|
|
@ -95,6 +95,8 @@ struct libinput {
|
|||
enum libinput_log_priority log_priority;
|
||||
void *user_data;
|
||||
int refcount;
|
||||
|
||||
struct list device_group_list;
|
||||
};
|
||||
|
||||
typedef void (*libinput_seat_destroy_func) (struct libinput_seat *seat);
|
||||
|
|
@ -152,6 +154,12 @@ struct libinput_device_config_accel {
|
|||
double speed);
|
||||
double (*get_speed)(struct libinput_device *device);
|
||||
double (*get_default_speed)(struct libinput_device *device);
|
||||
|
||||
uint32_t (*get_profiles)(struct libinput_device *device);
|
||||
enum libinput_config_status (*set_profile)(struct libinput_device *device,
|
||||
enum libinput_config_accel_profile);
|
||||
enum libinput_config_accel_profile (*get_profile)(struct libinput_device *device);
|
||||
enum libinput_config_accel_profile (*get_default_profile)(struct libinput_device *device);
|
||||
};
|
||||
|
||||
struct libinput_device_config_natural_scroll {
|
||||
|
|
@ -228,6 +236,8 @@ struct libinput_device_group {
|
|||
int refcount;
|
||||
void *user_data;
|
||||
char *identifier; /* unique identifier or NULL for singletons */
|
||||
|
||||
struct list link;
|
||||
};
|
||||
|
||||
struct libinput_device {
|
||||
|
|
@ -336,7 +346,12 @@ libinput_device_init(struct libinput_device *device,
|
|||
struct libinput_seat *seat);
|
||||
|
||||
struct libinput_device_group *
|
||||
libinput_device_group_create(const char *identifier);
|
||||
libinput_device_group_create(struct libinput *libinput,
|
||||
const char *identifier);
|
||||
|
||||
struct libinput_device_group *
|
||||
libinput_device_group_find_group(struct libinput *libinput,
|
||||
const char *identifier);
|
||||
|
||||
void
|
||||
libinput_device_set_device_group(struct libinput_device *device,
|
||||
|
|
|
|||
|
|
@ -225,6 +225,9 @@ libinput_log_set_handler(struct libinput *libinput,
|
|||
libinput->log_handler = log_handler;
|
||||
}
|
||||
|
||||
static void
|
||||
libinput_device_group_destroy(struct libinput_device_group *group);
|
||||
|
||||
static void
|
||||
libinput_post_event(struct libinput *libinput,
|
||||
struct libinput_event *event);
|
||||
|
|
@ -1206,6 +1209,7 @@ libinput_init(struct libinput *libinput,
|
|||
libinput->refcount = 1;
|
||||
list_init(&libinput->source_destroy_list);
|
||||
list_init(&libinput->seat_list);
|
||||
list_init(&libinput->device_group_list);
|
||||
list_init(&libinput->tool_list);
|
||||
|
||||
if (libinput_timer_subsys_init(libinput) != 0) {
|
||||
|
|
@ -1247,6 +1251,7 @@ libinput_unref(struct libinput *libinput)
|
|||
struct libinput_device *device, *next_device;
|
||||
struct libinput_seat *seat, *next_seat;
|
||||
struct libinput_tool *tool, *next_tool;
|
||||
struct libinput_device_group *group, *next_group;
|
||||
|
||||
if (libinput == NULL)
|
||||
return NULL;
|
||||
|
|
@ -1274,6 +1279,13 @@ libinput_unref(struct libinput *libinput)
|
|||
libinput_seat_destroy(seat);
|
||||
}
|
||||
|
||||
list_for_each_safe(group,
|
||||
next_group,
|
||||
&libinput->device_group_list,
|
||||
link) {
|
||||
libinput_device_group_destroy(group);
|
||||
}
|
||||
|
||||
list_for_each_safe(tool, next_tool, &libinput->tool_list, link) {
|
||||
libinput_tool_unref(tool);
|
||||
}
|
||||
|
|
@ -2349,7 +2361,8 @@ libinput_device_group_ref(struct libinput_device_group *group)
|
|||
}
|
||||
|
||||
struct libinput_device_group *
|
||||
libinput_device_group_create(const char *identifier)
|
||||
libinput_device_group_create(struct libinput *libinput,
|
||||
const char *identifier)
|
||||
{
|
||||
struct libinput_device_group *group;
|
||||
|
||||
|
|
@ -2362,13 +2375,32 @@ libinput_device_group_create(const char *identifier)
|
|||
group->identifier = strdup(identifier);
|
||||
if (!group->identifier) {
|
||||
free(group);
|
||||
group = NULL;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
list_init(&group->link);
|
||||
list_insert(&libinput->device_group_list, &group->link);
|
||||
|
||||
return group;
|
||||
}
|
||||
|
||||
struct libinput_device_group *
|
||||
libinput_device_group_find_group(struct libinput *libinput,
|
||||
const char *identifier)
|
||||
{
|
||||
struct libinput_device_group *g = NULL;
|
||||
|
||||
list_for_each(g, &libinput->device_group_list, link) {
|
||||
if (identifier && g->identifier &&
|
||||
streq(g->identifier, identifier)) {
|
||||
return g;
|
||||
}
|
||||
}
|
||||
|
||||
return g;
|
||||
}
|
||||
|
||||
void
|
||||
libinput_device_set_device_group(struct libinput_device *device,
|
||||
struct libinput_device_group *group)
|
||||
|
|
@ -2380,6 +2412,7 @@ libinput_device_set_device_group(struct libinput_device *device,
|
|||
static void
|
||||
libinput_device_group_destroy(struct libinput_device_group *group)
|
||||
{
|
||||
list_remove(&group->link);
|
||||
free(group->identifier);
|
||||
free(group);
|
||||
}
|
||||
|
|
@ -2599,7 +2632,6 @@ libinput_device_config_accel_set_speed(struct libinput_device *device,
|
|||
|
||||
return device->config.accel->set_speed(device, speed);
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT double
|
||||
libinput_device_config_accel_get_speed(struct libinput_device *device)
|
||||
{
|
||||
|
|
@ -2618,6 +2650,52 @@ libinput_device_config_accel_get_default_speed(struct libinput_device *device)
|
|||
return device->config.accel->get_default_speed(device);
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT uint32_t
|
||||
libinput_device_config_accel_get_profiles(struct libinput_device *device)
|
||||
{
|
||||
if (!libinput_device_config_accel_is_available(device))
|
||||
return 0;
|
||||
|
||||
return device->config.accel->get_profiles(device);
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT enum libinput_config_accel_profile
|
||||
libinput_device_config_accel_get_profile(struct libinput_device *device)
|
||||
{
|
||||
if (!libinput_device_config_accel_is_available(device))
|
||||
return LIBINPUT_CONFIG_ACCEL_PROFILE_NONE;
|
||||
|
||||
return device->config.accel->get_profile(device);
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT enum libinput_config_accel_profile
|
||||
libinput_device_config_accel_get_default_profile(struct libinput_device *device)
|
||||
{
|
||||
if (!libinput_device_config_accel_is_available(device))
|
||||
return LIBINPUT_CONFIG_ACCEL_PROFILE_NONE;
|
||||
|
||||
return device->config.accel->get_profile(device);
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT enum libinput_config_status
|
||||
libinput_device_config_accel_set_profile(struct libinput_device *device,
|
||||
enum libinput_config_accel_profile profile)
|
||||
{
|
||||
switch (profile) {
|
||||
case LIBINPUT_CONFIG_ACCEL_PROFILE_FLAT:
|
||||
case LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE:
|
||||
break;
|
||||
default:
|
||||
return LIBINPUT_CONFIG_STATUS_INVALID;
|
||||
}
|
||||
|
||||
if (!libinput_device_config_accel_is_available(device) ||
|
||||
(libinput_device_config_accel_get_profiles(device) & profile) == 0)
|
||||
return LIBINPUT_CONFIG_STATUS_UNSUPPORTED;
|
||||
|
||||
return device->config.accel->set_profile(device, profile);
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT int
|
||||
libinput_device_config_scroll_has_natural_scroll(struct libinput_device *device)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1954,6 +1954,26 @@ libinput_ref(struct libinput *libinput);
|
|||
* destroyed, if the last reference was dereferenced. If so, the context is
|
||||
* invalid and may not be interacted with.
|
||||
*
|
||||
* @bug When the refcount reaches zero, libinput_unref() releases resources
|
||||
* even if a caller still holds refcounted references to related resources
|
||||
* (e.g. a libinput_device). When libinput_unref() returns
|
||||
* NULL, the caller must consider any resources related to that context
|
||||
* invalid. See https://bugs.freedesktop.org/show_bug.cgi?id=91872.
|
||||
* Example code:
|
||||
* @code
|
||||
* li = libinput_path_create_context(&interface, NULL);
|
||||
* device = libinput_path_add_device(li, "/dev/input/event0");
|
||||
* // get extra reference to device
|
||||
* libinput_device_ref(device);
|
||||
*
|
||||
* // refcount reaches 0, so *all* resources are cleaned up,
|
||||
* // including device
|
||||
* libinput_unref(li);
|
||||
*
|
||||
* // INCORRECT: device has been cleaned up and must not be used
|
||||
* // li = libinput_device_get_context(device);
|
||||
* @endcode
|
||||
*
|
||||
* @param libinput A previously initialized libinput context
|
||||
* @return NULL if context was destroyed otherwise the passed context
|
||||
*/
|
||||
|
|
@ -3034,6 +3054,80 @@ libinput_device_config_accel_get_speed(struct libinput_device *device);
|
|||
double
|
||||
libinput_device_config_accel_get_default_speed(struct libinput_device *device);
|
||||
|
||||
enum libinput_config_accel_profile {
|
||||
/**
|
||||
* Placeholder for devices that don't have a configurable pointer
|
||||
* acceleration profile.
|
||||
*/
|
||||
LIBINPUT_CONFIG_ACCEL_PROFILE_NONE = 0,
|
||||
/**
|
||||
* A flat acceleration profile. Pointer motion is accelerated by a
|
||||
* constant (device-specific) factor, depending on the current
|
||||
* speed.
|
||||
*
|
||||
* @see libinput_device_config_accel_set_speed
|
||||
*/
|
||||
LIBINPUT_CONFIG_ACCEL_PROFILE_FLAT = (1 << 0),
|
||||
|
||||
/**
|
||||
* An adaptive acceleration profile. Pointer acceleration depends
|
||||
* on the input speed. This is the default profile for most devices.
|
||||
*/
|
||||
LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE = (1 << 1),
|
||||
};
|
||||
|
||||
/**
|
||||
* @ingroup config
|
||||
*
|
||||
* Returns a bitmask of the configurable acceleration modes available on
|
||||
* this device.
|
||||
*
|
||||
* @param device The device to configure
|
||||
*
|
||||
* @return A bitmask of all configurable modes availble on this device.
|
||||
*/
|
||||
uint32_t
|
||||
libinput_device_config_accel_get_profiles(struct libinput_device *device);
|
||||
|
||||
/**
|
||||
* @ingroup config
|
||||
*
|
||||
* Set the pointer acceleration profile of this pointer device to the given
|
||||
* mode.
|
||||
*
|
||||
* @param device The device to configure
|
||||
* @param mode The mode to set the device to.
|
||||
*
|
||||
* @return A config status code
|
||||
*/
|
||||
enum libinput_config_status
|
||||
libinput_device_config_accel_set_profile(struct libinput_device *device,
|
||||
enum libinput_config_accel_profile mode);
|
||||
|
||||
/**
|
||||
* @ingroup config
|
||||
*
|
||||
* Get the current pointer acceleration profile for this pointer device.
|
||||
*
|
||||
* @param device The device to configure
|
||||
*
|
||||
* @return The currently configured pointer acceleration profile.
|
||||
*/
|
||||
enum libinput_config_accel_profile
|
||||
libinput_device_config_accel_get_profile(struct libinput_device *device);
|
||||
|
||||
/**
|
||||
* @ingroup config
|
||||
*
|
||||
* Return the default pointer acceleration profile for this pointer device.
|
||||
*
|
||||
* @param device The device to configure
|
||||
*
|
||||
* @return The default acceleration profile for this device.
|
||||
*/
|
||||
enum libinput_config_accel_profile
|
||||
libinput_device_config_accel_get_default_profile(struct libinput_device *device);
|
||||
|
||||
/**
|
||||
* @ingroup config
|
||||
*
|
||||
|
|
|
|||
|
|
@ -174,6 +174,13 @@ LIBINPUT_0.21.0 {
|
|||
libinput_event_touch_get_time_usec;
|
||||
} LIBINPUT_0.20.0;
|
||||
|
||||
LIBINPUT_1.1 {
|
||||
libinput_device_config_accel_get_profile;
|
||||
libinput_device_config_accel_get_profiles;
|
||||
libinput_device_config_accel_get_default_profile;
|
||||
libinput_device_config_accel_set_profile;
|
||||
} LIBINPUT_0.21.0;
|
||||
|
||||
/* tablet APIs, they are not part of any stable API promise yet.
|
||||
* keep them separate */
|
||||
LIBINPUT_TABLET_SUPPORT {
|
||||
|
|
@ -201,4 +208,4 @@ LIBINPUT_TABLET_SUPPORT {
|
|||
libinput_tool_ref;
|
||||
libinput_tool_set_user_data;
|
||||
libinput_tool_unref;
|
||||
} LIBINPUT_0.21.0;
|
||||
} LIBINPUT_1.1;
|
||||
|
|
|
|||
|
|
@ -674,6 +674,22 @@ START_TEST(device_context)
|
|||
}
|
||||
END_TEST
|
||||
|
||||
static int open_restricted(const char *path, int flags, void *data)
|
||||
{
|
||||
int fd;
|
||||
fd = open(path, flags);
|
||||
return fd < 0 ? -errno : fd;
|
||||
}
|
||||
static void close_restricted(int fd, void *data)
|
||||
{
|
||||
close(fd);
|
||||
}
|
||||
|
||||
const struct libinput_interface simple_interface = {
|
||||
.open_restricted = open_restricted,
|
||||
.close_restricted = close_restricted,
|
||||
};
|
||||
|
||||
START_TEST(device_group_get)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
|
|
@ -722,6 +738,36 @@ START_TEST(device_group_ref)
|
|||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(device_group_leak)
|
||||
{
|
||||
struct libinput *li;
|
||||
struct libinput_device *device;
|
||||
struct libevdev_uinput *uinput;
|
||||
struct libinput_device_group *group;
|
||||
|
||||
uinput = litest_create_uinput_device("test device", NULL,
|
||||
EV_KEY, BTN_LEFT,
|
||||
EV_KEY, BTN_RIGHT,
|
||||
EV_REL, REL_X,
|
||||
EV_REL, REL_Y,
|
||||
-1);
|
||||
|
||||
li = libinput_path_create_context(&simple_interface, NULL);
|
||||
device = libinput_path_add_device(li,
|
||||
libevdev_uinput_get_devnode(uinput));
|
||||
|
||||
group = libinput_device_get_device_group(device);
|
||||
libinput_device_group_ref(group);
|
||||
|
||||
libinput_path_remove_device(device);
|
||||
|
||||
libevdev_uinput_destroy(uinput);
|
||||
libinput_unref(li);
|
||||
|
||||
/* the device group leaks, check valgrind */
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(abs_device_no_absx)
|
||||
{
|
||||
struct libevdev_uinput *uinput;
|
||||
|
|
@ -949,6 +995,34 @@ START_TEST(device_wheel_only)
|
|||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(device_accelerometer)
|
||||
{
|
||||
struct libinput *li;
|
||||
struct libevdev_uinput *uinput;
|
||||
struct libinput_device *device;
|
||||
|
||||
struct input_absinfo absinfo[] = {
|
||||
{ ABS_X, 0, 10, 0, 0, 10 },
|
||||
{ ABS_Y, 0, 10, 0, 0, 10 },
|
||||
{ ABS_Z, 0, 10, 0, 0, 10 },
|
||||
{ -1, -1, -1, -1, -1, -1 }
|
||||
};
|
||||
|
||||
li = litest_create_context();
|
||||
litest_disable_log_handler(li);
|
||||
|
||||
uinput = litest_create_uinput_abs_device("test device", NULL,
|
||||
absinfo,
|
||||
-1);
|
||||
device = libinput_path_add_device(li,
|
||||
libevdev_uinput_get_devnode(uinput));
|
||||
litest_assert_ptr_null(device);
|
||||
libevdev_uinput_destroy(uinput);
|
||||
litest_restore_log_handler(li);
|
||||
libinput_unref(li);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(device_udev_tag_alps)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
|
|
@ -1227,6 +1301,7 @@ litest_setup_tests(void)
|
|||
|
||||
litest_add("device:group", device_group_get, LITEST_ANY, LITEST_ANY);
|
||||
litest_add_no_device("device:group", device_group_ref);
|
||||
litest_add_no_device("device:group", device_group_leak);
|
||||
|
||||
litest_add_no_device("device:invalid devices", abs_device_no_absx);
|
||||
litest_add_no_device("device:invalid devices", abs_device_no_absy);
|
||||
|
|
@ -1238,6 +1313,7 @@ litest_setup_tests(void)
|
|||
litest_add_no_device("device:invalid devices", abs_mt_device_missing_res);
|
||||
|
||||
litest_add("device:wheel", device_wheel_only, LITEST_WHEEL, LITEST_RELATIVE|LITEST_ABSOLUTE|LITEST_TABLET);
|
||||
litest_add_no_device("device:accelerometer", device_accelerometer);
|
||||
|
||||
litest_add("device:udev tags", device_udev_tag_alps, LITEST_TOUCHPAD, LITEST_ANY);
|
||||
litest_add("device:udev tags", device_udev_tag_wacom, LITEST_TOUCHPAD, LITEST_ANY);
|
||||
|
|
|
|||
|
|
@ -790,11 +790,9 @@ litest_log_handler(struct libinput *libinput,
|
|||
fprintf(stderr, "litest %s: ", priority);
|
||||
vfprintf(stderr, format, args);
|
||||
|
||||
#if 0
|
||||
if (strstr(format, "client bug: ") ||
|
||||
strstr(format, "libinput bug: "))
|
||||
litest_abort_msg("libinput bug triggered, aborting.\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
static int
|
||||
|
|
@ -942,13 +940,15 @@ merge_events(const int *orig, const int *override)
|
|||
static inline void
|
||||
litest_copy_file(const char *dest, const char *src, const char *header)
|
||||
{
|
||||
int in, out;
|
||||
int in, out, length;
|
||||
|
||||
out = open(dest, O_CREAT|O_WRONLY, 0644);
|
||||
litest_assert_int_gt(out, -1);
|
||||
|
||||
if (header)
|
||||
write(out, header, strlen(header));
|
||||
if (header) {
|
||||
length = strlen(header);
|
||||
litest_assert_int_eq(write(out, header, length), length);
|
||||
}
|
||||
|
||||
in = open(src, O_RDONLY);
|
||||
litest_assert_int_gt(in, -1);
|
||||
|
|
@ -1304,7 +1304,6 @@ litest_auto_assign_value(struct litest_device *d,
|
|||
value = touching ? 0 : 1;
|
||||
break;
|
||||
default:
|
||||
value = -1;
|
||||
if (!axis_replacement_value(axes, ev->code, &value) &&
|
||||
d->interface->get_axis_default)
|
||||
d->interface->get_axis_default(d, ev->code, &value);
|
||||
|
|
@ -1354,8 +1353,8 @@ litest_slot_start(struct litest_device *d,
|
|||
y,
|
||||
axes,
|
||||
touching);
|
||||
|
||||
litest_event(d, ev->type, ev->code, value);
|
||||
if (value != LITEST_AUTO_ASSIGN)
|
||||
litest_event(d, ev->type, ev->code, value);
|
||||
ev++;
|
||||
}
|
||||
}
|
||||
|
|
@ -1440,7 +1439,8 @@ litest_slot_move(struct litest_device *d,
|
|||
y,
|
||||
axes,
|
||||
touching);
|
||||
litest_event(d, ev->type, ev->code, value);
|
||||
if (value != LITEST_AUTO_ASSIGN)
|
||||
litest_event(d, ev->type, ev->code, value);
|
||||
ev++;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
114
test/pointer.c
114
test/pointer.c
|
|
@ -1029,6 +1029,116 @@ START_TEST(pointer_accel_direction_change)
|
|||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(pointer_accel_profile_defaults)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput_device *device = dev->libinput_device;
|
||||
enum libinput_config_status status;
|
||||
enum libinput_config_accel_profile profile;
|
||||
uint32_t profiles;
|
||||
|
||||
ck_assert(libinput_device_config_accel_is_available(device));
|
||||
|
||||
profile = libinput_device_config_accel_get_default_profile(device);
|
||||
ck_assert_int_eq(profile, LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE);
|
||||
|
||||
profile = libinput_device_config_accel_get_profile(device);
|
||||
ck_assert_int_eq(profile, LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE);
|
||||
|
||||
profiles = libinput_device_config_accel_get_profiles(device);
|
||||
ck_assert(profiles & LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE);
|
||||
ck_assert(profiles & LIBINPUT_CONFIG_ACCEL_PROFILE_FLAT);
|
||||
|
||||
status = libinput_device_config_accel_set_profile(device,
|
||||
LIBINPUT_CONFIG_ACCEL_PROFILE_FLAT);
|
||||
ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
|
||||
profile = libinput_device_config_accel_get_profile(device);
|
||||
ck_assert_int_eq(profile, LIBINPUT_CONFIG_ACCEL_PROFILE_FLAT);
|
||||
|
||||
status = libinput_device_config_accel_set_profile(device,
|
||||
LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE);
|
||||
ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
|
||||
profile = libinput_device_config_accel_get_profile(device);
|
||||
ck_assert_int_eq(profile, LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(pointer_accel_profile_defaults_noprofile)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput_device *device = dev->libinput_device;
|
||||
enum libinput_config_status status;
|
||||
enum libinput_config_accel_profile profile;
|
||||
uint32_t profiles;
|
||||
|
||||
ck_assert(libinput_device_config_accel_is_available(device));
|
||||
|
||||
profile = libinput_device_config_accel_get_default_profile(device);
|
||||
ck_assert_int_eq(profile, LIBINPUT_CONFIG_ACCEL_PROFILE_NONE);
|
||||
|
||||
profile = libinput_device_config_accel_get_profile(device);
|
||||
ck_assert_int_eq(profile, LIBINPUT_CONFIG_ACCEL_PROFILE_NONE);
|
||||
|
||||
profiles = libinput_device_config_accel_get_profiles(device);
|
||||
ck_assert_int_eq(profiles, LIBINPUT_CONFIG_ACCEL_PROFILE_NONE);
|
||||
|
||||
status = libinput_device_config_accel_set_profile(device,
|
||||
LIBINPUT_CONFIG_ACCEL_PROFILE_FLAT);
|
||||
ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_UNSUPPORTED);
|
||||
profile = libinput_device_config_accel_get_profile(device);
|
||||
ck_assert_int_eq(profile, LIBINPUT_CONFIG_ACCEL_PROFILE_NONE);
|
||||
|
||||
status = libinput_device_config_accel_set_profile(device,
|
||||
LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE);
|
||||
ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_UNSUPPORTED);
|
||||
profile = libinput_device_config_accel_get_profile(device);
|
||||
ck_assert_int_eq(profile, LIBINPUT_CONFIG_ACCEL_PROFILE_NONE);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(pointer_accel_profile_invalid)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput_device *device = dev->libinput_device;
|
||||
enum libinput_config_status status;
|
||||
|
||||
ck_assert(libinput_device_config_accel_is_available(device));
|
||||
|
||||
status = libinput_device_config_accel_set_profile(device,
|
||||
LIBINPUT_CONFIG_ACCEL_PROFILE_NONE);
|
||||
ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_INVALID);
|
||||
|
||||
status = libinput_device_config_accel_set_profile(device,
|
||||
LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE + 1);
|
||||
ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_INVALID);
|
||||
|
||||
status = libinput_device_config_accel_set_profile(device,
|
||||
LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE |LIBINPUT_CONFIG_ACCEL_PROFILE_FLAT);
|
||||
ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_INVALID);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(pointer_accel_profile_flat_motion_relative)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput_device *device = dev->libinput_device;
|
||||
|
||||
libinput_device_config_accel_set_profile(device,
|
||||
LIBINPUT_CONFIG_ACCEL_PROFILE_FLAT);
|
||||
litest_drain_events(dev->libinput);
|
||||
|
||||
test_relative_event(dev, 1, 0);
|
||||
test_relative_event(dev, 1, 1);
|
||||
test_relative_event(dev, 1, -1);
|
||||
test_relative_event(dev, 0, 1);
|
||||
|
||||
test_relative_event(dev, -1, 0);
|
||||
test_relative_event(dev, -1, 1);
|
||||
test_relative_event(dev, -1, -1);
|
||||
test_relative_event(dev, 0, -1);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(middlebutton)
|
||||
{
|
||||
struct litest_device *device = litest_current_device();
|
||||
|
|
@ -1479,6 +1589,10 @@ litest_setup_tests(void)
|
|||
litest_add("pointer:accel", pointer_accel_defaults_absolute, LITEST_ABSOLUTE, LITEST_RELATIVE);
|
||||
litest_add("pointer:accel", pointer_accel_defaults_absolute_relative, LITEST_ABSOLUTE|LITEST_RELATIVE, LITEST_ANY);
|
||||
litest_add("pointer:accel", pointer_accel_direction_change, LITEST_RELATIVE, LITEST_ANY);
|
||||
litest_add("pointer:accel", pointer_accel_profile_defaults, LITEST_RELATIVE, LITEST_TOUCHPAD);
|
||||
litest_add("pointer:accel", pointer_accel_profile_defaults_noprofile, LITEST_TOUCHPAD, LITEST_ANY);
|
||||
litest_add("pointer:accel", pointer_accel_profile_invalid, LITEST_RELATIVE, LITEST_ANY);
|
||||
litest_add("pointer:accel", pointer_accel_profile_flat_motion_relative, LITEST_RELATIVE, LITEST_TOUCHPAD);
|
||||
|
||||
litest_add("pointer:middlebutton", middlebutton, LITEST_BUTTON, LITEST_ANY);
|
||||
litest_add("pointer:middlebutton", middlebutton_timeout, LITEST_BUTTON, LITEST_ANY);
|
||||
|
|
|
|||
|
|
@ -191,7 +191,7 @@ START_TEST(touchpad_1fg_multitap_n_drag_move)
|
|||
litest_touch_move_to(dev, 0, 50, 50, 70, 50, 10, 4);
|
||||
libinput_dispatch(li);
|
||||
|
||||
for (ntaps = 0; ntaps <= range; ntaps++) {
|
||||
for (ntaps = 0; ntaps < range; ntaps++) {
|
||||
event = libinput_get_event(li);
|
||||
ptrev = litest_is_button_event(event,
|
||||
BTN_LEFT,
|
||||
|
|
@ -261,7 +261,7 @@ START_TEST(touchpad_1fg_multitap_n_drag_2fg)
|
|||
litest_touch_down(dev, 1, 70, 50);
|
||||
libinput_dispatch(li);
|
||||
|
||||
for (ntaps = 0; ntaps <= range; ntaps++) {
|
||||
for (ntaps = 0; ntaps < range; ntaps++) {
|
||||
event = libinput_get_event(li);
|
||||
ptrev = litest_is_button_event(event,
|
||||
BTN_LEFT,
|
||||
|
|
@ -393,7 +393,7 @@ START_TEST(touchpad_1fg_multitap_n_drag_timeout)
|
|||
litest_timeout_tap();
|
||||
libinput_dispatch(li);
|
||||
|
||||
for (ntaps = 0; ntaps <= range; ntaps++) {
|
||||
for (ntaps = 0; ntaps < range; ntaps++) {
|
||||
event = libinput_get_event(li);
|
||||
ptrev = litest_is_button_event(event,
|
||||
BTN_LEFT,
|
||||
|
|
@ -464,7 +464,7 @@ START_TEST(touchpad_1fg_multitap_n_drag_tap)
|
|||
litest_timeout_tap();
|
||||
libinput_dispatch(li);
|
||||
|
||||
for (ntaps = 0; ntaps <= range; ntaps++) {
|
||||
for (ntaps = 0; ntaps < range; ntaps++) {
|
||||
event = libinput_get_event(li);
|
||||
ptrev = litest_is_button_event(event,
|
||||
BTN_LEFT,
|
||||
|
|
@ -537,7 +537,7 @@ START_TEST(touchpad_1fg_multitap_n_drag_tap_click)
|
|||
litest_timeout_tap();
|
||||
libinput_dispatch(li);
|
||||
|
||||
for (ntaps = 0; ntaps <= range; ntaps++) {
|
||||
for (ntaps = 0; ntaps < range; ntaps++) {
|
||||
event = libinput_get_event(li);
|
||||
ptrev = litest_is_button_event(event,
|
||||
BTN_LEFT,
|
||||
|
|
@ -966,6 +966,50 @@ START_TEST(touchpad_2fg_tap_inverted)
|
|||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(touchpad_2fg_tap_n_hold_first)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput *li = dev->libinput;
|
||||
|
||||
litest_enable_tap(dev->libinput_device);
|
||||
|
||||
litest_drain_events(dev->libinput);
|
||||
|
||||
litest_touch_down(dev, 0, 50, 50);
|
||||
litest_touch_down(dev, 1, 70, 70);
|
||||
litest_touch_up(dev, 1);
|
||||
|
||||
libinput_dispatch(li);
|
||||
|
||||
litest_assert_empty_queue(li);
|
||||
litest_timeout_tap();
|
||||
|
||||
litest_assert_empty_queue(li);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(touchpad_2fg_tap_n_hold_second)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput *li = dev->libinput;
|
||||
|
||||
litest_enable_tap(dev->libinput_device);
|
||||
|
||||
litest_drain_events(dev->libinput);
|
||||
|
||||
litest_touch_down(dev, 0, 50, 50);
|
||||
litest_touch_down(dev, 1, 70, 70);
|
||||
litest_touch_up(dev, 0);
|
||||
|
||||
libinput_dispatch(li);
|
||||
|
||||
litest_assert_empty_queue(li);
|
||||
litest_timeout_tap();
|
||||
|
||||
litest_assert_empty_queue(li);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(touchpad_2fg_tap_quickrelease)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
|
|
@ -1755,6 +1799,8 @@ litest_setup_tests(void)
|
|||
litest_add("touchpad:tap", touchpad_2fg_tap_n_drag_3fg, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH);
|
||||
litest_add("touchpad:tap", touchpad_2fg_tap, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH|LITEST_SEMI_MT);
|
||||
litest_add("touchpad:tap", touchpad_2fg_tap_inverted, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH);
|
||||
litest_add("touchpad:tap", touchpad_2fg_tap_n_hold_first, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH);
|
||||
litest_add("touchpad:tap", touchpad_2fg_tap_n_hold_second, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH);
|
||||
litest_add("touchpad:tap", touchpad_2fg_tap_quickrelease, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH|LITEST_SEMI_MT);
|
||||
litest_add("touchpad:tap", touchpad_1fg_tap_click, LITEST_TOUCHPAD|LITEST_BUTTON, LITEST_CLICKPAD);
|
||||
litest_add("touchpad:tap", touchpad_2fg_tap_click, LITEST_TOUCHPAD|LITEST_BUTTON, LITEST_SINGLE_TOUCH|LITEST_CLICKPAD);
|
||||
|
|
|
|||
|
|
@ -172,6 +172,35 @@ click_defaults(struct libinput_device *device)
|
|||
return str;
|
||||
}
|
||||
|
||||
static char*
|
||||
accel_profiles(struct libinput_device *device)
|
||||
{
|
||||
uint32_t profiles;
|
||||
char *str;
|
||||
enum libinput_config_accel_profile profile;
|
||||
|
||||
if (!libinput_device_config_accel_is_available(device)) {
|
||||
xasprintf(&str, "n/a");
|
||||
return str;
|
||||
}
|
||||
|
||||
profiles = libinput_device_config_accel_get_profiles(device);
|
||||
if (profiles == LIBINPUT_CONFIG_ACCEL_PROFILE_NONE) {
|
||||
xasprintf(&str, "none");
|
||||
return str;
|
||||
}
|
||||
|
||||
profile = libinput_device_config_accel_get_default_profile(device);
|
||||
xasprintf(&str,
|
||||
"%s%s%s%s",
|
||||
(profile == LIBINPUT_CONFIG_ACCEL_PROFILE_FLAT) ? "*" : "",
|
||||
(profiles & LIBINPUT_CONFIG_ACCEL_PROFILE_FLAT) ? "flat" : "",
|
||||
(profile == LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE) ? "*" : "",
|
||||
(profiles & LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE) ? "adaptive" : "");
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
static const char *
|
||||
dwt_default(struct libinput_device *device)
|
||||
{
|
||||
|
|
@ -252,6 +281,10 @@ print_device_notify(struct libinput_event *ev)
|
|||
|
||||
printf("Disable-w-typing: %s\n", dwt_default(dev));
|
||||
|
||||
str = accel_profiles(dev);
|
||||
printf("Accel profiles: %s\n", str);
|
||||
free(str);
|
||||
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -59,6 +59,7 @@ enum options {
|
|||
OPT_SCROLL_METHOD,
|
||||
OPT_SCROLL_BUTTON,
|
||||
OPT_SPEED,
|
||||
OPT_PROFILE,
|
||||
};
|
||||
|
||||
static void
|
||||
|
|
@ -94,6 +95,7 @@ tools_usage()
|
|||
"--set-click-method=[none|clickfinger|buttonareas] .... set the desired click method\n"
|
||||
"--set-scroll-method=[none|twofinger|edge|button] ... set the desired scroll method\n"
|
||||
"--set-scroll-button=BTN_MIDDLE ... set the button to the given button code\n"
|
||||
"--set-profile=[adaptive|flat].... set pointer acceleration profile\n"
|
||||
"--set-speed=<value>.... set pointer acceleration speed\n"
|
||||
"\n"
|
||||
"These options apply to all applicable devices, if a feature\n"
|
||||
|
|
@ -126,6 +128,7 @@ tools_init_context(struct tools_context *context)
|
|||
options->backend = BACKEND_UDEV;
|
||||
options->seat = "seat0";
|
||||
options->speed = 0.0;
|
||||
options->profile = LIBINPUT_CONFIG_ACCEL_PROFILE_NONE;
|
||||
}
|
||||
|
||||
int
|
||||
|
|
@ -157,6 +160,7 @@ tools_parse_args(int argc, char **argv, struct tools_context *context)
|
|||
{ "set-click-method", 1, 0, OPT_CLICK_METHOD },
|
||||
{ "set-scroll-method", 1, 0, OPT_SCROLL_METHOD },
|
||||
{ "set-scroll-button", 1, 0, OPT_SCROLL_BUTTON },
|
||||
{ "set-profile", 1, 0, OPT_PROFILE },
|
||||
{ "speed", 1, 0, OPT_SPEED },
|
||||
{ 0, 0, 0, 0}
|
||||
};
|
||||
|
|
@ -288,6 +292,20 @@ tools_parse_args(int argc, char **argv, struct tools_context *context)
|
|||
}
|
||||
options->speed = atof(optarg);
|
||||
break;
|
||||
case OPT_PROFILE:
|
||||
if (!optarg) {
|
||||
tools_usage();
|
||||
return 1;
|
||||
}
|
||||
if (streq(optarg, "adaptive")) {
|
||||
options->profile = LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE;
|
||||
} else if (streq(optarg, "flat")) {
|
||||
options->profile = LIBINPUT_CONFIG_ACCEL_PROFILE_FLAT;
|
||||
} else {
|
||||
tools_usage();
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
tools_usage();
|
||||
return 1;
|
||||
|
|
@ -445,7 +463,11 @@ tools_device_apply_config(struct libinput_device *device,
|
|||
libinput_device_config_scroll_set_button(device,
|
||||
options->scroll_button);
|
||||
|
||||
if (libinput_device_config_accel_is_available(device))
|
||||
if (libinput_device_config_accel_is_available(device)) {
|
||||
libinput_device_config_accel_set_speed(device,
|
||||
options->speed);
|
||||
if (options->profile != LIBINPUT_CONFIG_ACCEL_PROFILE_NONE)
|
||||
libinput_device_config_accel_set_profile(device,
|
||||
options->profile);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -48,6 +48,7 @@ struct tools_options {
|
|||
int scroll_button;
|
||||
double speed;
|
||||
int dwt;
|
||||
enum libinput_config_accel_profile profile;
|
||||
};
|
||||
|
||||
struct tools_context {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue