mirror of
https://gitlab.freedesktop.org/libinput/libinput.git
synced 2026-05-07 13:08:04 +02:00
Merge branch 'wip/touchpad-apple-touch-major-v2'
This commit is contained in:
commit
688142c8a2
19 changed files with 864 additions and 41 deletions
|
|
@ -431,6 +431,14 @@ configure_file(input : 'tools/libinput-measure-touchpad-pressure.man',
|
||||||
install : true,
|
install : true,
|
||||||
install_dir : join_paths(get_option('mandir'), 'man1')
|
install_dir : join_paths(get_option('mandir'), 'man1')
|
||||||
)
|
)
|
||||||
|
install_data('tools/libinput-measure-touch-size',
|
||||||
|
install_dir : libinput_tool_path)
|
||||||
|
configure_file(input : 'tools/libinput-measure-touch-size.man',
|
||||||
|
output : 'libinput-measure-touch-size.1',
|
||||||
|
configuration : man_config,
|
||||||
|
install : true,
|
||||||
|
install_dir : join_paths(get_option('mandir'), 'man1')
|
||||||
|
)
|
||||||
|
|
||||||
if get_option('debug-gui')
|
if get_option('debug-gui')
|
||||||
dep_gtk = dependency('gtk+-3.0')
|
dep_gtk = dependency('gtk+-3.0')
|
||||||
|
|
|
||||||
|
|
@ -348,6 +348,16 @@ tp_process_absolute(struct tp_dispatch *tp,
|
||||||
t->dirty = true;
|
t->dirty = true;
|
||||||
tp->queued |= TOUCHPAD_EVENT_OTHERAXIS;
|
tp->queued |= TOUCHPAD_EVENT_OTHERAXIS;
|
||||||
break;
|
break;
|
||||||
|
case ABS_MT_TOUCH_MAJOR:
|
||||||
|
t->major = e->value;
|
||||||
|
t->dirty = true;
|
||||||
|
tp->queued |= TOUCHPAD_EVENT_OTHERAXIS;
|
||||||
|
break;
|
||||||
|
case ABS_MT_TOUCH_MINOR:
|
||||||
|
t->minor = e->value;
|
||||||
|
t->dirty = true;
|
||||||
|
tp->queued |= TOUCHPAD_EVENT_OTHERAXIS;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -735,6 +745,30 @@ tp_palm_detect_multifinger(struct tp_dispatch *tp, struct tp_touch *t, uint64_t
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline bool
|
||||||
|
tp_palm_detect_touch_size_triggered(struct tp_dispatch *tp,
|
||||||
|
struct tp_touch *t,
|
||||||
|
uint64_t time)
|
||||||
|
{
|
||||||
|
if (!tp->palm.use_size)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
/* If a finger size is large enough for palm, we stick with that and
|
||||||
|
* force the user to release and reset the finger */
|
||||||
|
if (t->palm.state != PALM_NONE && t->palm.state != PALM_TOUCH_SIZE)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (t->major > tp->palm.size_threshold ||
|
||||||
|
t->minor > tp->palm.size_threshold) {
|
||||||
|
evdev_log_debug(tp->device,
|
||||||
|
"palm: touch size exceeded\n");
|
||||||
|
t->palm.state = PALM_TOUCH_SIZE;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
static inline bool
|
static inline bool
|
||||||
tp_palm_detect_edge(struct tp_dispatch *tp,
|
tp_palm_detect_edge(struct tp_dispatch *tp,
|
||||||
struct tp_touch *t,
|
struct tp_touch *t,
|
||||||
|
|
@ -818,6 +852,9 @@ tp_palm_detect(struct tp_dispatch *tp, struct tp_touch *t, uint64_t time)
|
||||||
if (tp_palm_detect_tool_triggered(tp, t, time))
|
if (tp_palm_detect_tool_triggered(tp, t, time))
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
if (tp_palm_detect_touch_size_triggered(tp, t, time))
|
||||||
|
goto out;
|
||||||
|
|
||||||
if (tp_palm_detect_edge(tp, t, time))
|
if (tp_palm_detect_edge(tp, t, time))
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
|
@ -852,6 +889,9 @@ out:
|
||||||
case PALM_PRESSURE:
|
case PALM_PRESSURE:
|
||||||
palm_state = "pressure";
|
palm_state = "pressure";
|
||||||
break;
|
break;
|
||||||
|
case PALM_TOUCH_SIZE:
|
||||||
|
palm_state = "touch size";
|
||||||
|
break;
|
||||||
case PALM_NONE:
|
case PALM_NONE:
|
||||||
default:
|
default:
|
||||||
abort();
|
abort();
|
||||||
|
|
@ -1015,6 +1055,45 @@ tp_unhover_pressure(struct tp_dispatch *tp, uint64_t time)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
tp_unhover_size(struct tp_dispatch *tp, uint64_t time)
|
||||||
|
{
|
||||||
|
struct tp_touch *t;
|
||||||
|
int low = tp->touch_size.low,
|
||||||
|
high = tp->touch_size.high;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* We require 5 slots for size handling, so we don't need to care
|
||||||
|
* about fake touches here */
|
||||||
|
|
||||||
|
for (i = 0; i < (int)tp->num_slots; i++) {
|
||||||
|
t = tp_get_touch(tp, i);
|
||||||
|
|
||||||
|
if (t->state == TOUCH_NONE)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!t->dirty)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (t->state == TOUCH_HOVERING) {
|
||||||
|
if ((t->major > high && t->minor > low) ||
|
||||||
|
(t->major > low && t->minor > high)) {
|
||||||
|
evdev_log_debug(tp->device,
|
||||||
|
"touch-size: begin touch\n");
|
||||||
|
/* avoid jumps when landing a finger */
|
||||||
|
tp_motion_history_reset(t);
|
||||||
|
tp_begin_touch(tp, t, time);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (t->major < low || t->minor < low) {
|
||||||
|
evdev_log_debug(tp->device,
|
||||||
|
"touch-size: end touch\n");
|
||||||
|
tp_end_touch(tp, t, time);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
tp_unhover_fake_touches(struct tp_dispatch *tp, uint64_t time)
|
tp_unhover_fake_touches(struct tp_dispatch *tp, uint64_t time)
|
||||||
{
|
{
|
||||||
|
|
@ -1077,6 +1156,8 @@ tp_unhover_touches(struct tp_dispatch *tp, uint64_t time)
|
||||||
{
|
{
|
||||||
if (tp->pressure.use_pressure)
|
if (tp->pressure.use_pressure)
|
||||||
tp_unhover_pressure(tp, time);
|
tp_unhover_pressure(tp, time);
|
||||||
|
else if (tp->touch_size.use_touch_size)
|
||||||
|
tp_unhover_size(tp, time);
|
||||||
else
|
else
|
||||||
tp_unhover_fake_touches(tp, time);
|
tp_unhover_fake_touches(tp, time);
|
||||||
|
|
||||||
|
|
@ -1512,6 +1593,15 @@ tp_sync_touch(struct tp_dispatch *tp,
|
||||||
t->pressure = libevdev_get_event_value(evdev,
|
t->pressure = libevdev_get_event_value(evdev,
|
||||||
EV_ABS,
|
EV_ABS,
|
||||||
ABS_PRESSURE);
|
ABS_PRESSURE);
|
||||||
|
|
||||||
|
libevdev_fetch_slot_value(evdev,
|
||||||
|
slot,
|
||||||
|
ABS_MT_TOUCH_MAJOR,
|
||||||
|
&t->major);
|
||||||
|
libevdev_fetch_slot_value(evdev,
|
||||||
|
slot,
|
||||||
|
ABS_MT_TOUCH_MINOR,
|
||||||
|
&t->minor);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
@ -2353,10 +2443,14 @@ tp_init_palmdetect_edge(struct tp_dispatch *tp,
|
||||||
struct phys_coords mm = { 0.0, 0.0 };
|
struct phys_coords mm = { 0.0, 0.0 };
|
||||||
struct device_coords edges;
|
struct device_coords edges;
|
||||||
|
|
||||||
|
if (device->tags & EVDEV_TAG_EXTERNAL_TOUCHPAD &&
|
||||||
|
!tp_is_tpkb_combo_below(device))
|
||||||
|
return;
|
||||||
|
|
||||||
evdev_device_get_size(device, &width, &height);
|
evdev_device_get_size(device, &width, &height);
|
||||||
|
|
||||||
/* Enable palm detection on touchpads >= 70 mm. Anything smaller
|
/* Enable edge palm detection on touchpads >= 70 mm. Anything
|
||||||
probably won't need it, until we find out it does */
|
smaller probably won't need it, until we find out it does */
|
||||||
if (width < 70.0)
|
if (width < 70.0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
@ -2413,6 +2507,33 @@ tp_init_palmdetect_pressure(struct tp_dispatch *tp,
|
||||||
tp->palm.pressure_threshold);
|
tp->palm.pressure_threshold);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
tp_init_palmdetect_size(struct tp_dispatch *tp,
|
||||||
|
struct evdev_device *device)
|
||||||
|
{
|
||||||
|
const char *prop;
|
||||||
|
int threshold;
|
||||||
|
|
||||||
|
if (!tp->touch_size.use_touch_size)
|
||||||
|
return;
|
||||||
|
|
||||||
|
prop = udev_device_get_property_value(device->udev_device,
|
||||||
|
"LIBINPUT_ATTR_PALM_SIZE_THRESHOLD");
|
||||||
|
if (!prop)
|
||||||
|
return;
|
||||||
|
|
||||||
|
threshold = parse_palm_size_property(prop);
|
||||||
|
if (threshold == 0) {
|
||||||
|
evdev_log_bug_client(device,
|
||||||
|
"palm: ignoring invalid threshold %s\n",
|
||||||
|
prop);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
tp->palm.use_size = true;
|
||||||
|
tp->palm.size_threshold = threshold;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
tp_init_palmdetect(struct tp_dispatch *tp,
|
tp_init_palmdetect(struct tp_dispatch *tp,
|
||||||
struct evdev_device *device)
|
struct evdev_device *device)
|
||||||
|
|
@ -2435,6 +2556,7 @@ tp_init_palmdetect(struct tp_dispatch *tp,
|
||||||
|
|
||||||
tp_init_palmdetect_edge(tp, device);
|
tp_init_palmdetect_edge(tp, device);
|
||||||
tp_init_palmdetect_pressure(tp, device);
|
tp_init_palmdetect_pressure(tp, device);
|
||||||
|
tp_init_palmdetect_size(tp, device);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
@ -2612,7 +2734,7 @@ tp_init_pressure(struct tp_dispatch *tp,
|
||||||
prop = udev_device_get_property_value(device->udev_device,
|
prop = udev_device_get_property_value(device->udev_device,
|
||||||
"LIBINPUT_ATTR_PRESSURE_RANGE");
|
"LIBINPUT_ATTR_PRESSURE_RANGE");
|
||||||
if (prop) {
|
if (prop) {
|
||||||
if (!parse_pressure_range_property(prop, &hi, &lo)) {
|
if (!parse_range_property(prop, &hi, &lo)) {
|
||||||
evdev_log_bug_client(device,
|
evdev_log_bug_client(device,
|
||||||
"discarding invalid pressure range '%s'\n",
|
"discarding invalid pressure range '%s'\n",
|
||||||
prop);
|
prop);
|
||||||
|
|
@ -2648,10 +2770,59 @@ tp_init_pressure(struct tp_dispatch *tp,
|
||||||
"using pressure-based touch detection\n");
|
"using pressure-based touch detection\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
tp_init_touch_size(struct tp_dispatch *tp,
|
||||||
|
struct evdev_device *device)
|
||||||
|
{
|
||||||
|
const char *prop;
|
||||||
|
int lo, hi;
|
||||||
|
|
||||||
|
if (!libevdev_has_event_code(device->evdev,
|
||||||
|
EV_ABS,
|
||||||
|
ABS_MT_TOUCH_MAJOR)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (libevdev_get_num_slots(device->evdev) < 5) {
|
||||||
|
evdev_log_bug_libinput(device,
|
||||||
|
"Expected 5+ slots for touch size detection\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
prop = udev_device_get_property_value(device->udev_device,
|
||||||
|
"LIBINPUT_ATTR_TOUCH_SIZE_RANGE");
|
||||||
|
if (!prop)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!parse_range_property(prop, &hi, &lo)) {
|
||||||
|
evdev_log_bug_client(device,
|
||||||
|
"discarding invalid touch size range '%s'\n",
|
||||||
|
prop);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hi == 0 && lo == 0) {
|
||||||
|
evdev_log_info(device,
|
||||||
|
"touch size based touch detection disabled\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Thresholds apply for both major or minor */
|
||||||
|
tp->touch_size.low = lo;
|
||||||
|
tp->touch_size.high = hi;
|
||||||
|
tp->touch_size.use_touch_size = true;
|
||||||
|
|
||||||
|
evdev_log_debug(device, "using size-based touch detection\n");
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
tp_init(struct tp_dispatch *tp,
|
tp_init(struct tp_dispatch *tp,
|
||||||
struct evdev_device *device)
|
struct evdev_device *device)
|
||||||
{
|
{
|
||||||
|
bool use_touch_size = false;
|
||||||
|
|
||||||
tp->base.dispatch_type = DISPATCH_TOUCHPAD;
|
tp->base.dispatch_type = DISPATCH_TOUCHPAD;
|
||||||
tp->base.interface = &tp_interface;
|
tp->base.interface = &tp_interface;
|
||||||
tp->device = device;
|
tp->device = device;
|
||||||
|
|
@ -2666,7 +2837,11 @@ tp_init(struct tp_dispatch *tp,
|
||||||
|
|
||||||
evdev_device_init_abs_range_warnings(device);
|
evdev_device_init_abs_range_warnings(device);
|
||||||
|
|
||||||
tp_init_pressure(tp, device);
|
if (device->model_flags & EVDEV_MODEL_APPLE_TOUCHPAD)
|
||||||
|
use_touch_size = tp_init_touch_size(tp, device);
|
||||||
|
|
||||||
|
if (!use_touch_size)
|
||||||
|
tp_init_pressure(tp, device);
|
||||||
|
|
||||||
/* Set the dpi to that of the x axis, because that's what we normalize
|
/* Set the dpi to that of the x axis, because that's what we normalize
|
||||||
to when needed*/
|
to when needed*/
|
||||||
|
|
|
||||||
|
|
@ -59,6 +59,7 @@ enum touch_palm_state {
|
||||||
PALM_TRACKPOINT,
|
PALM_TRACKPOINT,
|
||||||
PALM_TOOL_PALM,
|
PALM_TOOL_PALM,
|
||||||
PALM_PRESSURE,
|
PALM_PRESSURE,
|
||||||
|
PALM_TOUCH_SIZE,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum button_event {
|
enum button_event {
|
||||||
|
|
@ -148,6 +149,7 @@ struct tp_touch {
|
||||||
uint64_t time;
|
uint64_t time;
|
||||||
int pressure;
|
int pressure;
|
||||||
bool is_tool_palm; /* MT_TOOL_PALM */
|
bool is_tool_palm; /* MT_TOOL_PALM */
|
||||||
|
int major, minor;
|
||||||
|
|
||||||
bool was_down; /* if distance == 0, false for pure hovering
|
bool was_down; /* if distance == 0, false for pure hovering
|
||||||
touches */
|
touches */
|
||||||
|
|
@ -248,6 +250,17 @@ struct tp_dispatch {
|
||||||
int low;
|
int low;
|
||||||
} pressure;
|
} pressure;
|
||||||
|
|
||||||
|
/* If touch size (either axis) goes above high -> touch down,
|
||||||
|
if touch size (either axis) goes below low -> touch up */
|
||||||
|
struct {
|
||||||
|
bool use_touch_size;
|
||||||
|
int high;
|
||||||
|
int low;
|
||||||
|
|
||||||
|
/* convert device units to angle */
|
||||||
|
double orientation_to_angle;
|
||||||
|
} touch_size;
|
||||||
|
|
||||||
struct device_coords hysteresis_margin;
|
struct device_coords hysteresis_margin;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
|
|
@ -348,6 +361,9 @@ struct tp_dispatch {
|
||||||
|
|
||||||
bool use_pressure;
|
bool use_pressure;
|
||||||
int pressure_threshold;
|
int pressure_threshold;
|
||||||
|
|
||||||
|
bool use_size;
|
||||||
|
int size_threshold;
|
||||||
} palm;
|
} palm;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
|
|
|
||||||
|
|
@ -1892,7 +1892,7 @@ evdev_process_event(struct evdev_device *device, struct input_event *e)
|
||||||
struct evdev_dispatch *dispatch = device->dispatch;
|
struct evdev_dispatch *dispatch = device->dispatch;
|
||||||
uint64_t time = tv2us(&e->time);
|
uint64_t time = tv2us(&e->time);
|
||||||
|
|
||||||
#if 0
|
#if 1
|
||||||
if (libevdev_event_is_code(e, EV_SYN, SYN_REPORT))
|
if (libevdev_event_is_code(e, EV_SYN, SYN_REPORT))
|
||||||
evdev_log_debug(device,
|
evdev_log_debug(device,
|
||||||
"-------------- EV_SYN ------------\n");
|
"-------------- EV_SYN ------------\n");
|
||||||
|
|
|
||||||
|
|
@ -379,7 +379,7 @@ parse_tpkbcombo_layout_poperty(const char *prop,
|
||||||
* @return true on success, false otherwise
|
* @return true on success, false otherwise
|
||||||
*/
|
*/
|
||||||
bool
|
bool
|
||||||
parse_pressure_range_property(const char *prop, int *hi, int *lo)
|
parse_range_property(const char *prop, int *hi, int *lo)
|
||||||
{
|
{
|
||||||
int first, second;
|
int first, second;
|
||||||
|
|
||||||
|
|
@ -431,6 +431,31 @@ parse_palm_pressure_property(const char *prop)
|
||||||
return threshold;
|
return threshold;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper function to parse the LIBINPUT_ATTR_PALM_SIZE_THRESHOLD property
|
||||||
|
* from udev. Property is of the form:
|
||||||
|
* LIBINPUT_ATTR_PALM_SIZE_THRESHOLD=<integer>
|
||||||
|
* Where the number indicates the minimum threshold to consider a touch to
|
||||||
|
* be a palm.
|
||||||
|
*
|
||||||
|
* @param prop The value of the udev property (without the
|
||||||
|
* LIBINPUT_ATTR_PALM_SIZE_THRESHOLD=)
|
||||||
|
* @return The pressure threshold or 0 on error
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
parse_palm_size_property(const char *prop)
|
||||||
|
{
|
||||||
|
int thr = 0;
|
||||||
|
|
||||||
|
if (!prop)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (!safe_atoi(prop, &thr) || thr < 0 || thr > 1024)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return thr;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the next word in a string pointed to by state before the first
|
* Return the next word in a string pointed to by state before the first
|
||||||
* separator character. Call repeatedly to tokenize a whole string.
|
* separator character. Call repeatedly to tokenize a whole string.
|
||||||
|
|
|
||||||
|
|
@ -413,8 +413,9 @@ int parse_mouse_wheel_click_count_property(const char *prop);
|
||||||
double parse_trackpoint_accel_property(const char *prop);
|
double parse_trackpoint_accel_property(const char *prop);
|
||||||
bool parse_dimension_property(const char *prop, size_t *width, size_t *height);
|
bool parse_dimension_property(const char *prop, size_t *width, size_t *height);
|
||||||
bool parse_calibration_property(const char *prop, float calibration[6]);
|
bool parse_calibration_property(const char *prop, float calibration[6]);
|
||||||
bool parse_pressure_range_property(const char *prop, int *hi, int *lo);
|
bool parse_range_property(const char *prop, int *hi, int *lo);
|
||||||
int parse_palm_pressure_property(const char *prop);
|
int parse_palm_pressure_property(const char *prop);
|
||||||
|
int parse_palm_size_property(const char *prop);
|
||||||
|
|
||||||
enum tpkbcombo_layout {
|
enum tpkbcombo_layout {
|
||||||
TPKBCOMBO_LAYOUT_UNKNOWN,
|
TPKBCOMBO_LAYOUT_UNKNOWN,
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,9 @@ static struct input_event down[] = {
|
||||||
{ .type = EV_ABS, .code = ABS_MT_TRACKING_ID, .value = LITEST_AUTO_ASSIGN },
|
{ .type = EV_ABS, .code = ABS_MT_TRACKING_ID, .value = LITEST_AUTO_ASSIGN },
|
||||||
{ .type = EV_ABS, .code = ABS_MT_POSITION_X, .value = LITEST_AUTO_ASSIGN },
|
{ .type = EV_ABS, .code = ABS_MT_POSITION_X, .value = LITEST_AUTO_ASSIGN },
|
||||||
{ .type = EV_ABS, .code = ABS_MT_POSITION_Y, .value = LITEST_AUTO_ASSIGN },
|
{ .type = EV_ABS, .code = ABS_MT_POSITION_Y, .value = LITEST_AUTO_ASSIGN },
|
||||||
|
{ .type = EV_ABS, .code = ABS_MT_ORIENTATION, .value = LITEST_AUTO_ASSIGN },
|
||||||
|
{ .type = EV_ABS, .code = ABS_MT_TOUCH_MAJOR, .value = LITEST_AUTO_ASSIGN },
|
||||||
|
{ .type = EV_ABS, .code = ABS_MT_TOUCH_MINOR, .value = LITEST_AUTO_ASSIGN },
|
||||||
{ .type = EV_SYN, .code = SYN_REPORT, .value = 0 },
|
{ .type = EV_SYN, .code = SYN_REPORT, .value = 0 },
|
||||||
{ .type = -1, .code = -1 },
|
{ .type = -1, .code = -1 },
|
||||||
};
|
};
|
||||||
|
|
@ -51,6 +54,9 @@ static struct input_event move[] = {
|
||||||
{ .type = EV_ABS, .code = ABS_PRESSURE, .value = LITEST_AUTO_ASSIGN },
|
{ .type = EV_ABS, .code = ABS_PRESSURE, .value = LITEST_AUTO_ASSIGN },
|
||||||
{ .type = EV_ABS, .code = ABS_MT_POSITION_X, .value = LITEST_AUTO_ASSIGN },
|
{ .type = EV_ABS, .code = ABS_MT_POSITION_X, .value = LITEST_AUTO_ASSIGN },
|
||||||
{ .type = EV_ABS, .code = ABS_MT_POSITION_Y, .value = LITEST_AUTO_ASSIGN },
|
{ .type = EV_ABS, .code = ABS_MT_POSITION_Y, .value = LITEST_AUTO_ASSIGN },
|
||||||
|
{ .type = EV_ABS, .code = ABS_MT_ORIENTATION, .value = LITEST_AUTO_ASSIGN },
|
||||||
|
{ .type = EV_ABS, .code = ABS_MT_TOUCH_MAJOR, .value = LITEST_AUTO_ASSIGN },
|
||||||
|
{ .type = EV_ABS, .code = ABS_MT_TOUCH_MINOR, .value = LITEST_AUTO_ASSIGN },
|
||||||
{ .type = EV_SYN, .code = SYN_REPORT, .value = 0 },
|
{ .type = EV_SYN, .code = SYN_REPORT, .value = 0 },
|
||||||
{ .type = -1, .code = -1 },
|
{ .type = -1, .code = -1 },
|
||||||
};
|
};
|
||||||
|
|
@ -63,6 +69,12 @@ get_axis_default(struct litest_device *d, unsigned int evcode, int32_t *value)
|
||||||
case ABS_MT_PRESSURE:
|
case ABS_MT_PRESSURE:
|
||||||
*value = 30;
|
*value = 30;
|
||||||
return 0;
|
return 0;
|
||||||
|
case ABS_MT_TOUCH_MAJOR:
|
||||||
|
case ABS_MT_TOUCH_MINOR:
|
||||||
|
*value = 200;
|
||||||
|
return 0;
|
||||||
|
case ABS_MT_ORIENTATION:
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -37,10 +37,11 @@ static struct input_event down[] = {
|
||||||
{ .type = EV_ABS, .code = ABS_Y, .value = LITEST_AUTO_ASSIGN },
|
{ .type = EV_ABS, .code = ABS_Y, .value = LITEST_AUTO_ASSIGN },
|
||||||
{ .type = EV_ABS, .code = ABS_MT_SLOT, .value = LITEST_AUTO_ASSIGN },
|
{ .type = EV_ABS, .code = ABS_MT_SLOT, .value = LITEST_AUTO_ASSIGN },
|
||||||
{ .type = EV_ABS, .code = ABS_MT_TRACKING_ID, .value = LITEST_AUTO_ASSIGN },
|
{ .type = EV_ABS, .code = ABS_MT_TRACKING_ID, .value = LITEST_AUTO_ASSIGN },
|
||||||
{ .type = EV_ABS, .code = ABS_MT_TOUCH_MAJOR, .value = 272 },
|
{ .type = EV_ABS, .code = ABS_MT_TOUCH_MAJOR, .value = LITEST_AUTO_ASSIGN },
|
||||||
{ .type = EV_ABS, .code = ABS_MT_TOUCH_MINOR, .value = 400 },
|
{ .type = EV_ABS, .code = ABS_MT_TOUCH_MINOR, .value = LITEST_AUTO_ASSIGN },
|
||||||
{ .type = EV_ABS, .code = ABS_MT_POSITION_X, .value = LITEST_AUTO_ASSIGN },
|
{ .type = EV_ABS, .code = ABS_MT_POSITION_X, .value = LITEST_AUTO_ASSIGN },
|
||||||
{ .type = EV_ABS, .code = ABS_MT_POSITION_Y, .value = LITEST_AUTO_ASSIGN },
|
{ .type = EV_ABS, .code = ABS_MT_POSITION_Y, .value = LITEST_AUTO_ASSIGN },
|
||||||
|
{ .type = EV_ABS, .code = ABS_MT_ORIENTATION, .value = LITEST_AUTO_ASSIGN },
|
||||||
{ .type = EV_SYN, .code = SYN_REPORT, .value = 0 },
|
{ .type = EV_SYN, .code = SYN_REPORT, .value = 0 },
|
||||||
{ .type = -1, .code = -1 },
|
{ .type = -1, .code = -1 },
|
||||||
};
|
};
|
||||||
|
|
@ -49,17 +50,34 @@ static struct input_event move[] = {
|
||||||
{ .type = EV_ABS, .code = ABS_MT_SLOT, .value = LITEST_AUTO_ASSIGN },
|
{ .type = EV_ABS, .code = ABS_MT_SLOT, .value = LITEST_AUTO_ASSIGN },
|
||||||
{ .type = EV_ABS, .code = ABS_X, .value = LITEST_AUTO_ASSIGN },
|
{ .type = EV_ABS, .code = ABS_X, .value = LITEST_AUTO_ASSIGN },
|
||||||
{ .type = EV_ABS, .code = ABS_Y, .value = LITEST_AUTO_ASSIGN },
|
{ .type = EV_ABS, .code = ABS_Y, .value = LITEST_AUTO_ASSIGN },
|
||||||
{ .type = EV_ABS, .code = ABS_MT_TOUCH_MAJOR, .value = 272 },
|
{ .type = EV_ABS, .code = ABS_MT_TOUCH_MAJOR, .value = LITEST_AUTO_ASSIGN },
|
||||||
{ .type = EV_ABS, .code = ABS_MT_TOUCH_MINOR, .value = 400 },
|
{ .type = EV_ABS, .code = ABS_MT_TOUCH_MINOR, .value = LITEST_AUTO_ASSIGN },
|
||||||
{ .type = EV_ABS, .code = ABS_MT_POSITION_X, .value = LITEST_AUTO_ASSIGN },
|
{ .type = EV_ABS, .code = ABS_MT_POSITION_X, .value = LITEST_AUTO_ASSIGN },
|
||||||
{ .type = EV_ABS, .code = ABS_MT_POSITION_Y, .value = LITEST_AUTO_ASSIGN },
|
{ .type = EV_ABS, .code = ABS_MT_POSITION_Y, .value = LITEST_AUTO_ASSIGN },
|
||||||
|
{ .type = EV_ABS, .code = ABS_MT_ORIENTATION, .value = LITEST_AUTO_ASSIGN },
|
||||||
{ .type = EV_SYN, .code = SYN_REPORT, .value = 0 },
|
{ .type = EV_SYN, .code = SYN_REPORT, .value = 0 },
|
||||||
{ .type = -1, .code = -1 },
|
{ .type = -1, .code = -1 },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static int
|
||||||
|
get_axis_default(struct litest_device *d, unsigned int evcode, int32_t *value)
|
||||||
|
{
|
||||||
|
switch (evcode) {
|
||||||
|
case ABS_MT_TOUCH_MAJOR:
|
||||||
|
case ABS_MT_TOUCH_MINOR:
|
||||||
|
*value = 200;
|
||||||
|
return 0;
|
||||||
|
case ABS_MT_ORIENTATION:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
static struct litest_device_interface interface = {
|
static struct litest_device_interface interface = {
|
||||||
.touch_down_events = down,
|
.touch_down_events = down,
|
||||||
.touch_move_events = move,
|
.touch_move_events = move,
|
||||||
|
|
||||||
|
.get_axis_default = get_axis_default,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct input_absinfo absinfo[] = {
|
static struct input_absinfo absinfo[] = {
|
||||||
|
|
|
||||||
|
|
@ -1642,6 +1642,8 @@ touch_up(struct litest_device *d, unsigned int slot)
|
||||||
{ .type = EV_ABS, .code = ABS_MT_SLOT, .value = LITEST_AUTO_ASSIGN },
|
{ .type = EV_ABS, .code = ABS_MT_SLOT, .value = LITEST_AUTO_ASSIGN },
|
||||||
{ .type = EV_ABS, .code = ABS_MT_TRACKING_ID, .value = -1 },
|
{ .type = EV_ABS, .code = ABS_MT_TRACKING_ID, .value = -1 },
|
||||||
{ .type = EV_ABS, .code = ABS_MT_PRESSURE, .value = 0 },
|
{ .type = EV_ABS, .code = ABS_MT_PRESSURE, .value = 0 },
|
||||||
|
{ .type = EV_ABS, .code = ABS_MT_TOUCH_MAJOR, .value = 0 },
|
||||||
|
{ .type = EV_ABS, .code = ABS_MT_TOUCH_MINOR, .value = 0 },
|
||||||
{ .type = EV_SYN, .code = SYN_REPORT, .value = 0 },
|
{ .type = EV_SYN, .code = SYN_REPORT, .value = 0 },
|
||||||
{ .type = -1, .code = -1 }
|
{ .type = -1, .code = -1 }
|
||||||
};
|
};
|
||||||
|
|
@ -2171,7 +2173,11 @@ litest_scale_axis(const struct litest_device *d,
|
||||||
const struct input_absinfo *abs;
|
const struct input_absinfo *abs;
|
||||||
|
|
||||||
litest_assert_double_ge(val, 0.0);
|
litest_assert_double_ge(val, 0.0);
|
||||||
litest_assert_double_le(val, 100.0);
|
/* major/minor must be able to beyond 100% for large fingers */
|
||||||
|
if (axis != ABS_MT_TOUCH_MAJOR &&
|
||||||
|
axis != ABS_MT_TOUCH_MINOR) {
|
||||||
|
litest_assert_double_le(val, 100.0);
|
||||||
|
}
|
||||||
|
|
||||||
abs = libevdev_get_abs_info(d->evdev, axis);
|
abs = libevdev_get_abs_info(d->evdev, axis);
|
||||||
litest_assert_notnull(abs);
|
litest_assert_notnull(abs);
|
||||||
|
|
@ -2192,8 +2198,12 @@ int
|
||||||
litest_scale(const struct litest_device *d, unsigned int axis, double val)
|
litest_scale(const struct litest_device *d, unsigned int axis, double val)
|
||||||
{
|
{
|
||||||
int min, max;
|
int min, max;
|
||||||
|
|
||||||
litest_assert_double_ge(val, 0.0);
|
litest_assert_double_ge(val, 0.0);
|
||||||
litest_assert_double_le(val, 100.0);
|
/* major/minor must be able to beyond 100% for large fingers */
|
||||||
|
if (axis != ABS_MT_TOUCH_MAJOR &&
|
||||||
|
axis != ABS_MT_TOUCH_MINOR)
|
||||||
|
litest_assert_double_le(val, 100.0);
|
||||||
|
|
||||||
if (axis <= ABS_Y) {
|
if (axis <= ABS_Y) {
|
||||||
min = d->interface->min[axis];
|
min = d->interface->min[axis];
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,8 @@
|
||||||
#include <libinput.h>
|
#include <libinput.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
|
#include "libinput-util.h"
|
||||||
|
|
||||||
extern void litest_setup_tests_udev(void);
|
extern void litest_setup_tests_udev(void);
|
||||||
extern void litest_setup_tests_path(void);
|
extern void litest_setup_tests_path(void);
|
||||||
extern void litest_setup_tests_pointer(void);
|
extern void litest_setup_tests_pointer(void);
|
||||||
|
|
@ -303,12 +305,12 @@ struct axis_replacement {
|
||||||
double value;
|
double value;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Same as litest_axis_set_value but allows for ranges outside 0..100%
|
||||||
|
*/
|
||||||
static inline void
|
static inline void
|
||||||
litest_axis_set_value(struct axis_replacement *axes, int code, double value)
|
litest_axis_set_value_unchecked(struct axis_replacement *axes, int code, double value)
|
||||||
{
|
{
|
||||||
litest_assert_double_ge(value, 0.0);
|
|
||||||
litest_assert_double_le(value, 100.0);
|
|
||||||
|
|
||||||
while (axes->evcode != -1) {
|
while (axes->evcode != -1) {
|
||||||
if (axes->evcode == code) {
|
if (axes->evcode == code) {
|
||||||
axes->value = value;
|
axes->value = value;
|
||||||
|
|
@ -320,6 +322,18 @@ litest_axis_set_value(struct axis_replacement *axes, int code, double value)
|
||||||
litest_abort_msg("Missing axis code %d\n", code);
|
litest_abort_msg("Missing axis code %d\n", code);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Takes a value in percent and sets the given axis to that code.
|
||||||
|
*/
|
||||||
|
static inline void
|
||||||
|
litest_axis_set_value(struct axis_replacement *axes, int code, double value)
|
||||||
|
{
|
||||||
|
litest_assert_double_ge(value, 0.0);
|
||||||
|
litest_assert_double_le(value, 100.0);
|
||||||
|
|
||||||
|
litest_axis_set_value_unchecked(axes, code, value);
|
||||||
|
}
|
||||||
|
|
||||||
/* A loop range, resolves to:
|
/* A loop range, resolves to:
|
||||||
for (i = lower; i < upper; i++)
|
for (i = lower; i < upper; i++)
|
||||||
*/
|
*/
|
||||||
|
|
@ -903,6 +917,22 @@ litest_disable_middleemu(struct litest_device *dev)
|
||||||
litest_assert_int_eq(status, expected);
|
litest_assert_int_eq(status, expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline bool
|
||||||
|
litest_touchpad_is_external(struct litest_device *dev)
|
||||||
|
{
|
||||||
|
struct udev_device *udev_device;
|
||||||
|
const char *prop;
|
||||||
|
bool is_external;
|
||||||
|
|
||||||
|
udev_device = libinput_device_get_udev_device(dev->libinput_device);
|
||||||
|
prop = udev_device_get_property_value(udev_device,
|
||||||
|
"ID_INPUT_TOUCHPAD_INTEGRATION");
|
||||||
|
is_external = prop && streq(prop, "external");
|
||||||
|
udev_device_unref(udev_device);
|
||||||
|
|
||||||
|
return is_external;
|
||||||
|
}
|
||||||
|
|
||||||
#undef ck_assert_double_eq
|
#undef ck_assert_double_eq
|
||||||
#undef ck_assert_double_ne
|
#undef ck_assert_double_ne
|
||||||
#undef ck_assert_double_lt
|
#undef ck_assert_double_lt
|
||||||
|
|
|
||||||
|
|
@ -61,22 +61,6 @@ START_TEST(device_sendevents_config_invalid)
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
static inline bool
|
|
||||||
touchpad_is_external(struct litest_device *dev)
|
|
||||||
{
|
|
||||||
struct udev_device *udev_device;
|
|
||||||
const char *prop;
|
|
||||||
bool is_external;
|
|
||||||
|
|
||||||
udev_device = libinput_device_get_udev_device(dev->libinput_device);
|
|
||||||
prop = udev_device_get_property_value(udev_device,
|
|
||||||
"ID_INPUT_TOUCHPAD_INTEGRATION");
|
|
||||||
is_external = prop && streq(prop, "external");
|
|
||||||
udev_device_unref(udev_device);
|
|
||||||
|
|
||||||
return is_external;
|
|
||||||
}
|
|
||||||
|
|
||||||
START_TEST(device_sendevents_config_touchpad)
|
START_TEST(device_sendevents_config_touchpad)
|
||||||
{
|
{
|
||||||
struct litest_device *dev = litest_current_device();
|
struct litest_device *dev = litest_current_device();
|
||||||
|
|
@ -87,7 +71,7 @@ START_TEST(device_sendevents_config_touchpad)
|
||||||
|
|
||||||
/* The wacom devices in the test suite are external */
|
/* The wacom devices in the test suite are external */
|
||||||
if (libevdev_get_id_vendor(dev->evdev) != VENDOR_ID_WACOM &&
|
if (libevdev_get_id_vendor(dev->evdev) != VENDOR_ID_WACOM &&
|
||||||
!touchpad_is_external(dev))
|
!litest_touchpad_is_external(dev))
|
||||||
expected |=
|
expected |=
|
||||||
LIBINPUT_CONFIG_SEND_EVENTS_DISABLED_ON_EXTERNAL_MOUSE;
|
LIBINPUT_CONFIG_SEND_EVENTS_DISABLED_ON_EXTERNAL_MOUSE;
|
||||||
|
|
||||||
|
|
@ -107,7 +91,7 @@ START_TEST(device_sendevents_config_touchpad_superset)
|
||||||
|
|
||||||
/* The wacom devices in the test suite are external */
|
/* The wacom devices in the test suite are external */
|
||||||
if (libevdev_get_id_vendor(dev->evdev) == VENDOR_ID_WACOM ||
|
if (libevdev_get_id_vendor(dev->evdev) == VENDOR_ID_WACOM ||
|
||||||
touchpad_is_external(dev))
|
litest_touchpad_is_external(dev))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
device = dev->libinput_device;
|
device = dev->libinput_device;
|
||||||
|
|
|
||||||
|
|
@ -1002,15 +1002,15 @@ START_TEST(calibration_prop_parser)
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
struct parser_test_pressure_range {
|
struct parser_test_range {
|
||||||
char *tag;
|
char *tag;
|
||||||
bool success;
|
bool success;
|
||||||
int hi, lo;
|
int hi, lo;
|
||||||
};
|
};
|
||||||
|
|
||||||
START_TEST(pressure_range_prop_parser)
|
START_TEST(range_prop_parser)
|
||||||
{
|
{
|
||||||
struct parser_test_pressure_range tests[] = {
|
struct parser_test_range tests[] = {
|
||||||
{ "10:8", true, 10, 8 },
|
{ "10:8", true, 10, 8 },
|
||||||
{ "100:-1", true, 100, -1 },
|
{ "100:-1", true, 100, -1 },
|
||||||
{ "-203813:-502023", true, -203813, -502023 },
|
{ "-203813:-502023", true, -203813, -502023 },
|
||||||
|
|
@ -1028,7 +1028,7 @@ START_TEST(pressure_range_prop_parser)
|
||||||
|
|
||||||
for (i = 0; tests[i].tag != NULL; i++) {
|
for (i = 0; tests[i].tag != NULL; i++) {
|
||||||
hi = lo = 0xad;
|
hi = lo = 0xad;
|
||||||
success = parse_pressure_range_property(tests[i].tag, &hi, &lo);
|
success = parse_range_property(tests[i].tag, &hi, &lo);
|
||||||
ck_assert(success == tests[i].success);
|
ck_assert(success == tests[i].success);
|
||||||
if (success) {
|
if (success) {
|
||||||
ck_assert_int_eq(hi, tests[i].hi);
|
ck_assert_int_eq(hi, tests[i].hi);
|
||||||
|
|
@ -1039,7 +1039,7 @@ START_TEST(pressure_range_prop_parser)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
success = parse_pressure_range_property(NULL, NULL, NULL);
|
success = parse_range_property(NULL, NULL, NULL);
|
||||||
ck_assert(success == false);
|
ck_assert(success == false);
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
@ -1373,7 +1373,7 @@ litest_setup_tests_misc(void)
|
||||||
litest_add_no_device("misc:parser", dimension_prop_parser);
|
litest_add_no_device("misc:parser", dimension_prop_parser);
|
||||||
litest_add_no_device("misc:parser", reliability_prop_parser);
|
litest_add_no_device("misc:parser", reliability_prop_parser);
|
||||||
litest_add_no_device("misc:parser", calibration_prop_parser);
|
litest_add_no_device("misc:parser", calibration_prop_parser);
|
||||||
litest_add_no_device("misc:parser", pressure_range_prop_parser);
|
litest_add_no_device("misc:parser", range_prop_parser);
|
||||||
litest_add_no_device("misc:parser", palm_pressure_parser);
|
litest_add_no_device("misc:parser", palm_pressure_parser);
|
||||||
litest_add_no_device("misc:parser", safe_atoi_test);
|
litest_add_no_device("misc:parser", safe_atoi_test);
|
||||||
litest_add_no_device("misc:parser", safe_atod_test);
|
litest_add_no_device("misc:parser", safe_atod_test);
|
||||||
|
|
|
||||||
|
|
@ -5273,6 +5273,144 @@ START_TEST(touchpad_pressure_tap_2fg_1fg_light)
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
|
static inline bool
|
||||||
|
touchpad_has_touch_size(struct litest_device *dev)
|
||||||
|
{
|
||||||
|
struct libevdev *evdev = dev->evdev;
|
||||||
|
|
||||||
|
if (!libevdev_has_event_code(evdev, EV_ABS, ABS_MT_TOUCH_MAJOR))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (libevdev_get_id_vendor(evdev) == VENDOR_ID_APPLE)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
START_TEST(touchpad_touch_size)
|
||||||
|
{
|
||||||
|
struct litest_device *dev = litest_current_device();
|
||||||
|
struct libinput *li = dev->libinput;
|
||||||
|
struct axis_replacement axes[] = {
|
||||||
|
{ ABS_MT_TOUCH_MAJOR, 0 },
|
||||||
|
{ ABS_MT_TOUCH_MINOR, 0 },
|
||||||
|
{ ABS_MT_ORIENTATION, 0 },
|
||||||
|
{ -1, 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!touchpad_has_touch_size(dev))
|
||||||
|
return;
|
||||||
|
|
||||||
|
litest_drain_events(li);
|
||||||
|
|
||||||
|
litest_axis_set_value(axes, ABS_MT_TOUCH_MAJOR, 1);
|
||||||
|
litest_axis_set_value(axes, ABS_MT_TOUCH_MINOR, 1);
|
||||||
|
litest_touch_down_extended(dev, 0, 50, 50, axes);
|
||||||
|
litest_touch_move_to_extended(dev, 0,
|
||||||
|
50, 50,
|
||||||
|
80, 80,
|
||||||
|
axes, 10, 1);
|
||||||
|
litest_touch_up(dev, 0);
|
||||||
|
litest_assert_empty_queue(li);
|
||||||
|
|
||||||
|
litest_axis_set_value(axes, ABS_MT_TOUCH_MAJOR, 15);
|
||||||
|
litest_axis_set_value(axes, ABS_MT_TOUCH_MINOR, 15);
|
||||||
|
litest_touch_down_extended(dev, 0, 50, 50, axes);
|
||||||
|
litest_touch_move_to_extended(dev, 0,
|
||||||
|
50, 50,
|
||||||
|
80, 80,
|
||||||
|
axes, 10, 1);
|
||||||
|
litest_touch_up(dev, 0);
|
||||||
|
litest_assert_only_typed_events(li,
|
||||||
|
LIBINPUT_EVENT_POINTER_MOTION);
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
START_TEST(touchpad_touch_size_2fg)
|
||||||
|
{
|
||||||
|
struct litest_device *dev = litest_current_device();
|
||||||
|
struct libinput *li = dev->libinput;
|
||||||
|
struct axis_replacement axes[] = {
|
||||||
|
{ ABS_MT_TOUCH_MAJOR, 0 },
|
||||||
|
{ ABS_MT_TOUCH_MINOR, 0 },
|
||||||
|
{ ABS_MT_ORIENTATION, 0 },
|
||||||
|
{ -1, 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!touchpad_has_touch_size(dev))
|
||||||
|
return;
|
||||||
|
|
||||||
|
litest_drain_events(li);
|
||||||
|
litest_axis_set_value(axes, ABS_MT_TOUCH_MAJOR, 15);
|
||||||
|
litest_axis_set_value(axes, ABS_MT_TOUCH_MINOR, 15);
|
||||||
|
litest_touch_down_extended(dev, 0, 50, 50, axes);
|
||||||
|
litest_touch_move_to_extended(dev, 0,
|
||||||
|
50, 50,
|
||||||
|
80, 80,
|
||||||
|
axes, 10, 1);
|
||||||
|
|
||||||
|
litest_assert_only_typed_events(li,
|
||||||
|
LIBINPUT_EVENT_POINTER_MOTION);
|
||||||
|
|
||||||
|
litest_axis_set_value(axes, ABS_MT_TOUCH_MAJOR, 1);
|
||||||
|
litest_axis_set_value(axes, ABS_MT_TOUCH_MINOR, 1);
|
||||||
|
litest_touch_down_extended(dev, 1, 70, 70, axes);
|
||||||
|
litest_touch_move_to_extended(dev, 1,
|
||||||
|
70, 70,
|
||||||
|
80, 90,
|
||||||
|
axes, 10, 1);
|
||||||
|
litest_assert_empty_queue(li);
|
||||||
|
|
||||||
|
litest_axis_set_value(axes, ABS_MT_TOUCH_MAJOR, 15);
|
||||||
|
litest_axis_set_value(axes, ABS_MT_TOUCH_MINOR, 15);
|
||||||
|
litest_touch_move_to_extended(dev, 0,
|
||||||
|
80, 80,
|
||||||
|
50, 50,
|
||||||
|
axes, 10, 1);
|
||||||
|
|
||||||
|
litest_assert_only_typed_events(li,
|
||||||
|
LIBINPUT_EVENT_POINTER_MOTION);
|
||||||
|
|
||||||
|
litest_touch_up(dev, 1);
|
||||||
|
litest_touch_up(dev, 0);
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
START_TEST(touchpad_palm_detect_touch_size)
|
||||||
|
{
|
||||||
|
struct litest_device *dev = litest_current_device();
|
||||||
|
struct libinput *li = dev->libinput;
|
||||||
|
struct axis_replacement axes[] = {
|
||||||
|
{ ABS_MT_TOUCH_MAJOR, 0 },
|
||||||
|
{ ABS_MT_TOUCH_MINOR, 0 },
|
||||||
|
{ -1, 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!touchpad_has_touch_size(dev) ||
|
||||||
|
litest_touchpad_is_external(dev))
|
||||||
|
return;
|
||||||
|
|
||||||
|
litest_drain_events(li);
|
||||||
|
litest_axis_set_value(axes, ABS_MT_TOUCH_MAJOR, 30);
|
||||||
|
litest_axis_set_value(axes, ABS_MT_TOUCH_MINOR, 30);
|
||||||
|
litest_touch_down_extended(dev, 0, 50, 50, axes);
|
||||||
|
litest_touch_move_to_extended(dev, 0,
|
||||||
|
50, 50,
|
||||||
|
80, 80,
|
||||||
|
axes, 10, 1);
|
||||||
|
litest_assert_only_typed_events(li,
|
||||||
|
LIBINPUT_EVENT_POINTER_MOTION);
|
||||||
|
|
||||||
|
litest_axis_set_value_unchecked(axes, ABS_MT_TOUCH_MAJOR, 90);
|
||||||
|
litest_axis_set_value(axes, ABS_MT_TOUCH_MINOR, 90);
|
||||||
|
litest_touch_move_to_extended(dev, 0,
|
||||||
|
80, 80,
|
||||||
|
50, 50,
|
||||||
|
axes, 10, 1);
|
||||||
|
litest_assert_empty_queue(li);
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
void
|
void
|
||||||
litest_setup_tests_touchpad(void)
|
litest_setup_tests_touchpad(void)
|
||||||
{
|
{
|
||||||
|
|
@ -5327,6 +5465,7 @@ litest_setup_tests_touchpad(void)
|
||||||
litest_add("touchpad:palm", touchpad_palm_detect_tool_palm, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH);
|
litest_add("touchpad:palm", touchpad_palm_detect_tool_palm, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH);
|
||||||
litest_add("touchpad:palm", touchpad_palm_detect_tool_palm_on_off, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH);
|
litest_add("touchpad:palm", touchpad_palm_detect_tool_palm_on_off, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH);
|
||||||
litest_add("touchpad:palm", touchpad_palm_detect_tool_palm_tap, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH);
|
litest_add("touchpad:palm", touchpad_palm_detect_tool_palm_tap, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH);
|
||||||
|
litest_add("touchpad:palm", touchpad_palm_detect_touch_size, LITEST_APPLE_CLICKPAD, LITEST_ANY);
|
||||||
|
|
||||||
litest_add("touchpad:palm", touchpad_palm_detect_pressure, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH);
|
litest_add("touchpad:palm", touchpad_palm_detect_pressure, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH);
|
||||||
litest_add("touchpad:palm", touchpad_palm_detect_pressure_late, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH);
|
litest_add("touchpad:palm", touchpad_palm_detect_pressure_late, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH);
|
||||||
|
|
@ -5434,4 +5573,7 @@ litest_setup_tests_touchpad(void)
|
||||||
litest_add("touchpad:pressure", touchpad_pressure_tap, LITEST_TOUCHPAD, LITEST_ANY);
|
litest_add("touchpad:pressure", touchpad_pressure_tap, LITEST_TOUCHPAD, LITEST_ANY);
|
||||||
litest_add("touchpad:pressure", touchpad_pressure_tap_2fg, LITEST_TOUCHPAD, LITEST_ANY);
|
litest_add("touchpad:pressure", touchpad_pressure_tap_2fg, LITEST_TOUCHPAD, LITEST_ANY);
|
||||||
litest_add("touchpad:pressure", touchpad_pressure_tap_2fg_1fg_light, LITEST_TOUCHPAD, LITEST_ANY);
|
litest_add("touchpad:pressure", touchpad_pressure_tap_2fg_1fg_light, LITEST_TOUCHPAD, LITEST_ANY);
|
||||||
|
|
||||||
|
litest_add("touchpad:touch-size", touchpad_touch_size, LITEST_APPLE_CLICKPAD, LITEST_ANY);
|
||||||
|
litest_add("touchpad:touch-size", touchpad_touch_size_2fg, LITEST_APPLE_CLICKPAD, LITEST_ANY);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
335
tools/libinput-measure-touch-size
Executable file
335
tools/libinput-measure-touch-size
Executable file
|
|
@ -0,0 +1,335 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
# vim: set expandtab shiftwidth=4:
|
||||||
|
# -*- Mode: python; coding: utf-8; indent-tabs-mode: nil -*- */
|
||||||
|
#
|
||||||
|
# Copyright © 2017 Red Hat, Inc.
|
||||||
|
#
|
||||||
|
# Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
# copy of this software and associated documentation files (the "Software"),
|
||||||
|
# to deal in the Software without restriction, including without limitation
|
||||||
|
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
# and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
# Software is furnished to do so, subject to the following conditions:
|
||||||
|
#
|
||||||
|
# The above copyright notice and this permission notice (including the next
|
||||||
|
# paragraph) shall be included in all copies or substantial portions of the
|
||||||
|
# Software.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
# DEALINGS IN THE SOFTWARE.
|
||||||
|
#
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import argparse
|
||||||
|
import evdev
|
||||||
|
import evdev.ecodes
|
||||||
|
import pyudev
|
||||||
|
|
||||||
|
|
||||||
|
class Range(object):
|
||||||
|
"""Class to keep a min/max of a value around"""
|
||||||
|
def __init__(self):
|
||||||
|
self.min = float('inf')
|
||||||
|
self.max = float('-inf')
|
||||||
|
|
||||||
|
def update(self, value):
|
||||||
|
self.min = min(self.min, value)
|
||||||
|
self.max = max(self.max, value)
|
||||||
|
|
||||||
|
|
||||||
|
class Touch(object):
|
||||||
|
"""A single data point of a sequence (i.e. one event frame)"""
|
||||||
|
|
||||||
|
def __init__(self, major=None, minor=None, orientation=None):
|
||||||
|
self._major = major
|
||||||
|
self._minor = minor
|
||||||
|
self._orientation = orientation
|
||||||
|
self.dirty = False
|
||||||
|
|
||||||
|
@property
|
||||||
|
def major(self):
|
||||||
|
return self._major
|
||||||
|
|
||||||
|
@major.setter
|
||||||
|
def major(self, major):
|
||||||
|
self._major = major
|
||||||
|
self.dirty = True
|
||||||
|
|
||||||
|
@property
|
||||||
|
def minor(self):
|
||||||
|
return self._minor
|
||||||
|
|
||||||
|
@minor.setter
|
||||||
|
def minor(self, minor):
|
||||||
|
self._minor = minor
|
||||||
|
self.dirty = True
|
||||||
|
|
||||||
|
@property
|
||||||
|
def orientation(self):
|
||||||
|
return self._orientation
|
||||||
|
|
||||||
|
@orientation.setter
|
||||||
|
def orientation(self, orientation):
|
||||||
|
self._orientation = orientation
|
||||||
|
self.dirty = True
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
s = "Touch: major {:3d}".format(self.major)
|
||||||
|
if self.minor is not None:
|
||||||
|
s += ", minor {:3d}".format(self.minor)
|
||||||
|
if self.orientation is not None:
|
||||||
|
s += ", orientation {:+3d}".format(self.orientation)
|
||||||
|
return s
|
||||||
|
|
||||||
|
|
||||||
|
class TouchSequence(object):
|
||||||
|
"""A touch sequence from beginning to end"""
|
||||||
|
|
||||||
|
def __init__(self, device, tracking_id):
|
||||||
|
self.device = device
|
||||||
|
self.tracking_id = tracking_id
|
||||||
|
self.points = []
|
||||||
|
|
||||||
|
self.is_active = True
|
||||||
|
|
||||||
|
self.is_down = False
|
||||||
|
self.was_down = False
|
||||||
|
self.is_palm = False
|
||||||
|
self.was_palm = False
|
||||||
|
|
||||||
|
self.major_range = Range()
|
||||||
|
self.minor_range = Range()
|
||||||
|
|
||||||
|
def append(self, touch):
|
||||||
|
"""Add a Touch to the sequence"""
|
||||||
|
self.points.append(touch)
|
||||||
|
self.major_range.update(touch.major)
|
||||||
|
self.minor_range.update(touch.minor)
|
||||||
|
|
||||||
|
if touch.major < self.device.up or \
|
||||||
|
touch.minor < self.device.up:
|
||||||
|
self.is_down = False
|
||||||
|
elif touch.major > self.device.down or \
|
||||||
|
touch.minor > self.device.down:
|
||||||
|
self.is_down = True
|
||||||
|
self.was_down = True
|
||||||
|
|
||||||
|
self.is_palm = touch.major > self.device.palm
|
||||||
|
if self.is_palm:
|
||||||
|
self.was_palm = True
|
||||||
|
|
||||||
|
def finalize(self):
|
||||||
|
"""Mark the TouchSequence as complete (finger is up)"""
|
||||||
|
self.is_active = False
|
||||||
|
|
||||||
|
def avg(self):
|
||||||
|
"""Average pressure value of this sequence"""
|
||||||
|
return int(sum([p.pressure for p in self.points])/len(self.points))
|
||||||
|
|
||||||
|
def median(self):
|
||||||
|
"""Median pressure value of this sequence"""
|
||||||
|
ps = sorted([p.pressure for p in self.points])
|
||||||
|
idx = int(len(self.points)/2)
|
||||||
|
return ps[idx]
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self._str_state() if self.is_active else self._str_summary()
|
||||||
|
|
||||||
|
def _str_summary(self):
|
||||||
|
if not self.points:
|
||||||
|
return "Sequence: no major/minor values recorded"
|
||||||
|
|
||||||
|
s = "Sequence: major: [{:3d}..{:3d}] ".format(
|
||||||
|
self.major_range.min, self.major_range.max
|
||||||
|
)
|
||||||
|
if self.device.has_minor:
|
||||||
|
s += "minor: [{:3d}..{:3d}] ".format(
|
||||||
|
self.minor_range.min, self.minor_range.max
|
||||||
|
)
|
||||||
|
if self.was_down:
|
||||||
|
s += " down"
|
||||||
|
if self.was_palm:
|
||||||
|
s += " palm"
|
||||||
|
|
||||||
|
return s
|
||||||
|
|
||||||
|
def _str_state(self):
|
||||||
|
touch = self.points[-1]
|
||||||
|
s = "{}, tags: {} {}".format(
|
||||||
|
touch,
|
||||||
|
"down" if self.is_down else " ",
|
||||||
|
"palm" if self.is_palm else " "
|
||||||
|
)
|
||||||
|
return s
|
||||||
|
|
||||||
|
|
||||||
|
class InvalidDeviceError(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class Device(object):
|
||||||
|
def __init__(self, path):
|
||||||
|
if path is None:
|
||||||
|
self.path = self.find_touch_device()
|
||||||
|
else:
|
||||||
|
self.path = path
|
||||||
|
|
||||||
|
self.device = evdev.InputDevice(self.path)
|
||||||
|
# capabilities returns a dict with the EV_* codes as key,
|
||||||
|
# each of which is a list of tuples of (code, AbsInfo)
|
||||||
|
#
|
||||||
|
# Get the abs list first (or empty list if missing),
|
||||||
|
# then extract the pressure absinfo from that
|
||||||
|
caps = self.device.capabilities(absinfo=True).get(
|
||||||
|
evdev.ecodes.EV_ABS, []
|
||||||
|
)
|
||||||
|
codes = [cap[0] for cap in caps]
|
||||||
|
|
||||||
|
if evdev.ecodes.ABS_MT_TOUCH_MAJOR not in codes:
|
||||||
|
raise InvalidDeviceError("device does not have ABS_MT_TOUCH_MAJOR")
|
||||||
|
|
||||||
|
self.has_minor = evdev.ecodes.ABS_MT_TOUCH_MINOR in codes
|
||||||
|
self.has_orientation = evdev.ecodes.ABS_MT_ORIENTATION in codes
|
||||||
|
|
||||||
|
self.up = 0
|
||||||
|
self.down = 0
|
||||||
|
self.palm = 0
|
||||||
|
|
||||||
|
self._init_thresholds_from_udev()
|
||||||
|
self.sequences = []
|
||||||
|
self.touch = Touch(0, 0)
|
||||||
|
|
||||||
|
def find_touch_device(self):
|
||||||
|
context = pyudev.Context()
|
||||||
|
for device in context.list_devices(subsystem='input'):
|
||||||
|
if not device.get('ID_INPUT_TOUCHPAD', 0) and \
|
||||||
|
not device.get('ID_INPUT_TOUCHSCREEN', 0):
|
||||||
|
continue
|
||||||
|
|
||||||
|
if not device.device_node or \
|
||||||
|
not device.device_node.startswith('/dev/input/event'):
|
||||||
|
continue
|
||||||
|
|
||||||
|
return device.device_node
|
||||||
|
|
||||||
|
print("Unable to find a touch device.", file=sys.stderr)
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
def _init_thresholds_from_udev(self):
|
||||||
|
context = pyudev.Context()
|
||||||
|
ud = pyudev.Devices.from_device_file(context, self.path)
|
||||||
|
v = ud.get('LIBINPUT_ATTR_TOUCH_SIZE_RANGE')
|
||||||
|
if v:
|
||||||
|
self.up, self.down = colon_tuple(v)
|
||||||
|
|
||||||
|
v = ud.get('LIBINPUT_ATTR_PALM_SIZE_THRESHOLD')
|
||||||
|
if v:
|
||||||
|
self.palm = int(v)
|
||||||
|
|
||||||
|
def start_new_sequence(self, tracking_id):
|
||||||
|
self.sequences.append(TouchSequence(self, tracking_id))
|
||||||
|
|
||||||
|
def current_sequence(self):
|
||||||
|
return self.sequences[-1]
|
||||||
|
|
||||||
|
def handle_key(self, event):
|
||||||
|
tapcodes = [evdev.ecodes.BTN_TOOL_DOUBLETAP,
|
||||||
|
evdev.ecodes.BTN_TOOL_TRIPLETAP,
|
||||||
|
evdev.ecodes.BTN_TOOL_QUADTAP,
|
||||||
|
evdev.ecodes.BTN_TOOL_QUINTTAP]
|
||||||
|
if event.code in tapcodes and event.value > 0:
|
||||||
|
print("\rThis tool cannot handle multiple fingers, "
|
||||||
|
"output will be invalid", file=sys.stderr)
|
||||||
|
|
||||||
|
def handle_abs(self, event):
|
||||||
|
if event.code == evdev.ecodes.ABS_MT_TRACKING_ID:
|
||||||
|
if event.value > -1:
|
||||||
|
self.start_new_sequence(event.value)
|
||||||
|
else:
|
||||||
|
s = self.current_sequence()
|
||||||
|
s.finalize()
|
||||||
|
print("\r{}".format(s))
|
||||||
|
elif event.code == evdev.ecodes.ABS_MT_TOUCH_MAJOR:
|
||||||
|
self.touch.major = event.value
|
||||||
|
elif event.code == evdev.ecodes.ABS_MT_TOUCH_MINOR:
|
||||||
|
self.touch.minor = event.value
|
||||||
|
elif event.code == evdev.ecodes.ABS_MT_ORIENTATION:
|
||||||
|
self.touch.orientation = event.value
|
||||||
|
|
||||||
|
def handle_syn(self, event):
|
||||||
|
if self.touch.dirty:
|
||||||
|
self.current_sequence().append(self.touch)
|
||||||
|
print("\r{}".format(self.current_sequence()), end="")
|
||||||
|
self.touch = Touch(major=self.touch.major,
|
||||||
|
minor=self.touch.minor,
|
||||||
|
orientation=self.touch.orientation)
|
||||||
|
|
||||||
|
def handle_event(self, event):
|
||||||
|
if event.type == evdev.ecodes.EV_ABS:
|
||||||
|
self.handle_abs(event)
|
||||||
|
elif event.type == evdev.ecodes.EV_KEY:
|
||||||
|
self.handle_key(event)
|
||||||
|
elif event.type == evdev.ecodes.EV_SYN:
|
||||||
|
self.handle_syn(event)
|
||||||
|
|
||||||
|
def read_events(self):
|
||||||
|
print("Ready for recording data.")
|
||||||
|
print("Touch sizes used: {}:{}".format(self.down, self.up))
|
||||||
|
print("Palm size used: {}".format(self.palm))
|
||||||
|
print("Place a single finger on the device to measure touch size.\n"
|
||||||
|
"Ctrl+C to exit\n")
|
||||||
|
|
||||||
|
for event in self.device.read_loop():
|
||||||
|
self.handle_event(event)
|
||||||
|
|
||||||
|
|
||||||
|
def colon_tuple(string):
|
||||||
|
try:
|
||||||
|
ts = string.split(':')
|
||||||
|
t = tuple([int(x) for x in ts])
|
||||||
|
if len(t) == 2 and t[0] >= t[1]:
|
||||||
|
return t
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
msg = "{} is not in format N:M (N >= M)".format(string)
|
||||||
|
raise argparse.ArgumentTypeError(msg)
|
||||||
|
|
||||||
|
|
||||||
|
def main(args):
|
||||||
|
parser = argparse.ArgumentParser(
|
||||||
|
description="Measure touch size and orientation"
|
||||||
|
)
|
||||||
|
parser.add_argument('path', metavar='/dev/input/event0',
|
||||||
|
nargs='?', type=str, help='Path to device (optional)')
|
||||||
|
parser.add_argument('--touch-thresholds', metavar='down:up',
|
||||||
|
type=colon_tuple,
|
||||||
|
help='Thresholds when a touch is logically down or up')
|
||||||
|
parser.add_argument('--palm-threshold', metavar='t',
|
||||||
|
type=int, help='Threshold when a touch is a palm')
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
try:
|
||||||
|
device = Device(args.path)
|
||||||
|
|
||||||
|
if args.touch_thresholds is not None:
|
||||||
|
device.down, device.up = args.touch_thresholds
|
||||||
|
|
||||||
|
if args.palm_threshold is not None:
|
||||||
|
device.palm = args.palm_threshold
|
||||||
|
|
||||||
|
device.read_events()
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
pass
|
||||||
|
except (PermissionError, OSError):
|
||||||
|
print("Error: failed to open device")
|
||||||
|
except InvalidDeviceError as e:
|
||||||
|
print("Error: {}".format(e))
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main(sys.argv)
|
||||||
57
tools/libinput-measure-touch-size.man
Normal file
57
tools/libinput-measure-touch-size.man
Normal file
|
|
@ -0,0 +1,57 @@
|
||||||
|
.TH libinput-measure-touch-size "1"
|
||||||
|
.SH NAME
|
||||||
|
libinput\-measure\-touch-size \- measure touch size and orientation of devices
|
||||||
|
.SH SYNOPSIS
|
||||||
|
.B libinput measure touch\-size [\-\-help] [options]
|
||||||
|
[\fI/dev/input/event0\fI]
|
||||||
|
.SH DESCRIPTION
|
||||||
|
.PP
|
||||||
|
The
|
||||||
|
.B "libinput measure touch\-size"
|
||||||
|
tool measures the size and orientation of a touch as provided by the kernel.
|
||||||
|
an interactive tool. When executed, the tool will prompt the user to
|
||||||
|
interact with the touch device. On termination, the tool prints a summary of the
|
||||||
|
values seen. This data should be attached to any
|
||||||
|
touch\-size\-related bug report.
|
||||||
|
.PP
|
||||||
|
This is a debugging tool only, its output may change at any time. Do not
|
||||||
|
rely on the output.
|
||||||
|
.PP
|
||||||
|
This tool usually needs to be run as root to have access to the
|
||||||
|
/dev/input/eventX nodes.
|
||||||
|
.SH OPTIONS
|
||||||
|
If a device node is given, this tool opens that device node. Otherwise, this
|
||||||
|
tool searches for the first node that looks like a touch-capable device and
|
||||||
|
uses that node.
|
||||||
|
.TP 8
|
||||||
|
.B \-\-help
|
||||||
|
Print help
|
||||||
|
.TP 8
|
||||||
|
.B \-\-touch\-thresholds=\fI"down:up"\fR
|
||||||
|
Set the logical touch size thresholds to
|
||||||
|
.I down
|
||||||
|
and
|
||||||
|
.I up,
|
||||||
|
respectively. When a touch exceeds the size in
|
||||||
|
.I down
|
||||||
|
it is considered logically down. If a touch is logically down and goes below
|
||||||
|
the size in
|
||||||
|
.I up,
|
||||||
|
it is considered logically up. The thresholds have to be in
|
||||||
|
device-specific pressure values and it is required that
|
||||||
|
.I down
|
||||||
|
>=
|
||||||
|
.I up.
|
||||||
|
.TP 8
|
||||||
|
.B \-\-palm\-threshold=\fIN\fR
|
||||||
|
Assume a palm threshold of
|
||||||
|
.I N.
|
||||||
|
The threshold has to be in device-specific pressure values.
|
||||||
|
.PP
|
||||||
|
If the touch-thresholds or the palm-threshold are not provided,
|
||||||
|
this tool uses the thresholds provided by the udev hwdb (if any) or the
|
||||||
|
built-in defaults.
|
||||||
|
.SH LIBINPUT
|
||||||
|
Part of the
|
||||||
|
.B libinput(1)
|
||||||
|
suite
|
||||||
|
|
@ -22,6 +22,9 @@ Print help
|
||||||
.SH FEATURES
|
.SH FEATURES
|
||||||
Features that can be measured include
|
Features that can be measured include
|
||||||
.TP 8
|
.TP 8
|
||||||
|
.B libinput\-measure\-touch\-size(1)
|
||||||
|
Measure touch size and orientation
|
||||||
|
.TP 8
|
||||||
.B libinput\-measure\-touchpad\-tap\-time(1)
|
.B libinput\-measure\-touchpad\-tap\-time(1)
|
||||||
Measure tap-to-click time
|
Measure tap-to-click time
|
||||||
.TP 8
|
.TP 8
|
||||||
|
|
|
||||||
|
|
@ -45,6 +45,9 @@ List all devices recognized by libinput
|
||||||
.B libinput\-measure(1)
|
.B libinput\-measure(1)
|
||||||
Measure various properties of devices
|
Measure various properties of devices
|
||||||
.TP 8
|
.TP 8
|
||||||
|
.B libinput\-measure\-touch\-size(1)
|
||||||
|
Measure touch size and orientation
|
||||||
|
.TP 8
|
||||||
.B libinput\-measure\-touchpad\-tap(1)
|
.B libinput\-measure\-touchpad\-tap(1)
|
||||||
Measure tap-to-click time
|
Measure tap-to-click time
|
||||||
.TP 8
|
.TP 8
|
||||||
|
|
|
||||||
|
|
@ -50,6 +50,8 @@ libinput:touchpad:input:b0003v05ACp*
|
||||||
libinput:touchpad:input:b0005v05ACp*
|
libinput:touchpad:input:b0005v05ACp*
|
||||||
LIBINPUT_MODEL_APPLE_TOUCHPAD=1
|
LIBINPUT_MODEL_APPLE_TOUCHPAD=1
|
||||||
LIBINPUT_ATTR_SIZE_HINT=104x75
|
LIBINPUT_ATTR_SIZE_HINT=104x75
|
||||||
|
LIBINPUT_ATTR_TOUCH_SIZE_RANGE=150:130
|
||||||
|
LIBINPUT_ATTR_PALM_SIZE_THRESHOLD=800
|
||||||
|
|
||||||
libinput:name:*Apple Inc. Apple Internal Keyboard*:dmi:*
|
libinput:name:*Apple Inc. Apple Internal Keyboard*:dmi:*
|
||||||
LIBINPUT_ATTR_KEYBOARD_INTEGRATION=internal
|
LIBINPUT_ATTR_KEYBOARD_INTEGRATION=internal
|
||||||
|
|
|
||||||
|
|
@ -108,6 +108,7 @@ def property_grammar():
|
||||||
('LIBINPUT_ATTR_SIZE_HINT', Group(dimension('SETTINGS*'))),
|
('LIBINPUT_ATTR_SIZE_HINT', Group(dimension('SETTINGS*'))),
|
||||||
('LIBINPUT_ATTR_RESOLUTION_HINT', Group(dimension('SETTINGS*'))),
|
('LIBINPUT_ATTR_RESOLUTION_HINT', Group(dimension('SETTINGS*'))),
|
||||||
('LIBINPUT_ATTR_PRESSURE_RANGE', Group(crange('SETTINGS*'))),
|
('LIBINPUT_ATTR_PRESSURE_RANGE', Group(crange('SETTINGS*'))),
|
||||||
|
('LIBINPUT_ATTR_TOUCH_SIZE_RANGE', Group(crange('SETTINGS*'))),
|
||||||
('LIBINPUT_ATTR_TPKBCOMBO_LAYOUT', Or(('below'))),
|
('LIBINPUT_ATTR_TPKBCOMBO_LAYOUT', Or(('below'))),
|
||||||
('LIBINPUT_ATTR_LID_SWITCH_RELIABILITY',
|
('LIBINPUT_ATTR_LID_SWITCH_RELIABILITY',
|
||||||
Or(('reliable', 'write_open'))),
|
Or(('reliable', 'write_open'))),
|
||||||
|
|
@ -118,6 +119,7 @@ def property_grammar():
|
||||||
|
|
||||||
tprops = (
|
tprops = (
|
||||||
('LIBINPUT_ATTR_PALM_PRESSURE_THRESHOLD', INTEGER('X')),
|
('LIBINPUT_ATTR_PALM_PRESSURE_THRESHOLD', INTEGER('X')),
|
||||||
|
('LIBINPUT_ATTR_PALM_SIZE_THRESHOLD', INTEGER('X')),
|
||||||
)
|
)
|
||||||
typed_props = [Literal(name)('NAME') - Suppress('=') - val
|
typed_props = [Literal(name)('NAME') - Suppress('=') - val
|
||||||
for name, val in tprops]
|
for name, val in tprops]
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue