Merge branch 'master' into tablet-support

This commit is contained in:
Peter Hutterer 2015-10-21 19:19:01 +10:00
commit ab6a409cdc
21 changed files with 1561 additions and 814 deletions

View file

@ -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])

View file

@ -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

View file

@ -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;

View file

@ -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

View file

@ -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,

View file

@ -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);

View file

@ -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,

View file

@ -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;
}

View file

@ -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);

View file

@ -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,

View file

@ -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)
{

View file

@ -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
*

View file

@ -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;

View file

@ -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);

View file

@ -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++;
}
}

View file

@ -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);

View file

@ -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);

View file

@ -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");
}

View file

@ -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);
}
}

View file

@ -48,6 +48,7 @@ struct tools_options {
int scroll_button;
double speed;
int dwt;
enum libinput_config_accel_profile profile;
};
struct tools_context {