mirror of
https://gitlab.freedesktop.org/libinput/libinput.git
synced 2026-03-23 00:20:43 +01:00
touchpad: set the finger pin distance to 5mm where possible
On touchpads with resolutions, use a 5mm motion threshold before we unpin the finger (allow motion events while a clickpad button is down). This should remove any erroneous finger movements while clicking, at the cost of having to move the finger a bit more for a single-finger click-and-drag (use two fingers already!) And drop the finger drifting, it was per-event based rather than time-based. So unless the motion threshold was hit in a single event it was possible to move the finger around the whole touchpad without ever unpinning it. Drop the finger drifting altogether, if the touchpad drifts by more than 5mm we have other issues. https://bugzilla.redhat.com/show_bug.cgi?id=1230462 Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net> Reviewed-by: Hans de Goede <hdegoede@redhat.com>
This commit is contained in:
parent
b48ecd186d
commit
8025b374d5
5 changed files with 75 additions and 13 deletions
|
|
@ -31,7 +31,6 @@
|
|||
|
||||
#include "evdev-mt-touchpad.h"
|
||||
|
||||
#define DEFAULT_BUTTON_MOTION_THRESHOLD 0.02 /* 2% of size */
|
||||
#define DEFAULT_BUTTON_ENTER_TIMEOUT 100 /* ms */
|
||||
#define DEFAULT_BUTTON_LEAVE_TIMEOUT 300 /* ms */
|
||||
|
||||
|
|
@ -709,11 +708,19 @@ tp_init_buttons(struct tp_dispatch *tp,
|
|||
absinfo_x = device->abs.absinfo_x;
|
||||
absinfo_y = device->abs.absinfo_y;
|
||||
|
||||
width = abs(absinfo_x->maximum - absinfo_x->minimum);
|
||||
height = abs(absinfo_y->maximum - absinfo_y->minimum);
|
||||
diagonal = sqrt(width*width + height*height);
|
||||
|
||||
tp->buttons.motion_dist = diagonal * DEFAULT_BUTTON_MOTION_THRESHOLD;
|
||||
/* pinned-finger motion threshold, see tp_unpin_finger.
|
||||
The MAGIC for resolution-less touchpads ends up as 2% of the diagonal */
|
||||
if (device->abs.fake_resolution) {
|
||||
const int BUTTON_MOTION_MAGIC = 0.007;
|
||||
width = abs(absinfo_x->maximum - absinfo_x->minimum);
|
||||
height = abs(absinfo_y->maximum - absinfo_y->minimum);
|
||||
diagonal = sqrt(width*width + height*height);
|
||||
tp->buttons.motion_dist.x_scale_coeff = diagonal * BUTTON_MOTION_MAGIC;
|
||||
tp->buttons.motion_dist.y_scale_coeff = diagonal * BUTTON_MOTION_MAGIC;
|
||||
} else {
|
||||
tp->buttons.motion_dist.x_scale_coeff = 1.0/absinfo_x->resolution;
|
||||
tp->buttons.motion_dist.y_scale_coeff = 1.0/absinfo_y->resolution;
|
||||
}
|
||||
|
||||
tp->buttons.config_method.get_methods = tp_button_config_click_get_methods;
|
||||
tp->buttons.config_method.set_method = tp_button_config_click_set_method;
|
||||
|
|
|
|||
|
|
@ -431,17 +431,15 @@ tp_unpin_finger(struct tp_dispatch *tp, struct tp_touch *t)
|
|||
return;
|
||||
|
||||
xdist = abs(t->point.x - t->pinned.center.x);
|
||||
xdist *= tp->buttons.motion_dist.x_scale_coeff;
|
||||
ydist = abs(t->point.y - t->pinned.center.y);
|
||||
ydist *= tp->buttons.motion_dist.y_scale_coeff;
|
||||
|
||||
if (xdist * xdist + ydist * ydist >=
|
||||
tp->buttons.motion_dist * tp->buttons.motion_dist) {
|
||||
/* 3mm movement -> unpin */
|
||||
if (vector_length(xdist, ydist) >= 3.0) {
|
||||
t->pinned.is_pinned = false;
|
||||
return;
|
||||
}
|
||||
|
||||
/* The finger may slowly drift, adjust the center */
|
||||
t->pinned.center.x = (t->point.x + t->pinned.center.x)/2;
|
||||
t->pinned.center.y = (t->point.y + t->pinned.center.y)/2;
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
|||
|
|
@ -223,7 +223,10 @@ struct tp_dispatch {
|
|||
bool click_pending;
|
||||
uint32_t state;
|
||||
uint32_t old_state;
|
||||
uint32_t motion_dist; /* for pinned touches */
|
||||
struct {
|
||||
double x_scale_coeff;
|
||||
double y_scale_coeff;
|
||||
} motion_dist; /* for pinned touches */
|
||||
unsigned int active; /* currently active button, for release event */
|
||||
bool active_is_topbutton; /* is active a top button? */
|
||||
|
||||
|
|
|
|||
|
|
@ -284,4 +284,10 @@ int parse_mouse_dpi_property(const char *prop);
|
|||
int parse_mouse_wheel_click_angle_property(const char *prop);
|
||||
double parse_trackpoint_accel_property(const char *prop);
|
||||
|
||||
static inline double
|
||||
vector_length(double x, double y)
|
||||
{
|
||||
return sqrt(x * x + y * y);
|
||||
}
|
||||
|
||||
#endif /* LIBINPUT_UTIL_H */
|
||||
|
|
|
|||
|
|
@ -2153,6 +2153,53 @@ START_TEST(clickpad_click_n_drag)
|
|||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(clickpad_finger_pin)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput *li = dev->libinput;
|
||||
struct libevdev *evdev = dev->evdev;
|
||||
const struct input_absinfo *abs;
|
||||
|
||||
abs = libevdev_get_abs_info(evdev, ABS_MT_POSITION_X);
|
||||
ck_assert_notnull(abs);
|
||||
if (abs->resolution == 0)
|
||||
return;
|
||||
|
||||
litest_drain_events(li);
|
||||
|
||||
/* make sure the movement generates pointer events when
|
||||
not pinned */
|
||||
litest_touch_down(dev, 0, 50, 50);
|
||||
litest_touch_move_to(dev, 0, 50, 50, 52, 52, 10, 1);
|
||||
litest_touch_move_to(dev, 0, 52, 52, 48, 48, 10, 1);
|
||||
litest_touch_move_to(dev, 0, 48, 48, 50, 50, 10, 1);
|
||||
litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_MOTION);
|
||||
|
||||
litest_button_click(dev, BTN_LEFT, true);
|
||||
litest_drain_events(li);
|
||||
|
||||
litest_touch_move_to(dev, 0, 50, 50, 52, 52, 10, 1);
|
||||
litest_touch_move_to(dev, 0, 52, 52, 48, 48, 10, 1);
|
||||
litest_touch_move_to(dev, 0, 48, 48, 50, 50, 10, 1);
|
||||
|
||||
litest_assert_empty_queue(li);
|
||||
|
||||
litest_button_click(dev, BTN_LEFT, false);
|
||||
litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_BUTTON);
|
||||
|
||||
/* still pinned after release */
|
||||
litest_touch_move_to(dev, 0, 50, 50, 52, 52, 10, 1);
|
||||
litest_touch_move_to(dev, 0, 52, 52, 48, 48, 10, 1);
|
||||
litest_touch_move_to(dev, 0, 48, 48, 50, 50, 10, 1);
|
||||
|
||||
litest_assert_empty_queue(li);
|
||||
|
||||
/* move to unpin */
|
||||
litest_touch_move_to(dev, 0, 50, 50, 70, 70, 10, 1);
|
||||
litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_MOTION);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(clickpad_softbutton_left)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
|
|
@ -5144,6 +5191,7 @@ litest_setup_tests(void)
|
|||
litest_add("touchpad:click", touchpad_btn_left, LITEST_TOUCHPAD|LITEST_BUTTON, LITEST_CLICKPAD);
|
||||
litest_add("touchpad:click", clickpad_btn_left, LITEST_CLICKPAD, LITEST_ANY);
|
||||
litest_add("touchpad:click", clickpad_click_n_drag, LITEST_CLICKPAD, LITEST_SINGLE_TOUCH);
|
||||
litest_add("touchpad:click", clickpad_finger_pin, LITEST_CLICKPAD, LITEST_ANY);
|
||||
|
||||
litest_add("touchpad:softbutton", clickpad_softbutton_left, LITEST_CLICKPAD, LITEST_APPLE_CLICKPAD);
|
||||
litest_add("touchpad:softbutton", clickpad_softbutton_right, LITEST_CLICKPAD, LITEST_APPLE_CLICKPAD);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue