mirror of
https://gitlab.freedesktop.org/libinput/libinput.git
synced 2025-12-25 14:00:06 +01:00
touchpad: add quirk for the T450 and T460 generation hardware
The touchpad's sensors are too far apart (or the firmware interferes), causing in a jerky movement visible especially on slow motion. We get a bunch of normal motion events, then only ABS_MT_PRESSURE updates without x/y updates. After about one mm of movement x/y updates resume, with the first event covering the distance between the last motion event. That event is usually accelerated and thus causes a large jump. Subsequent events are sufficiently fine-grained again. This patch counts the number of non-motion events. Once we hit 10 in a row, we mark the first motion update as non-dirty, effectively discarding the motion and thus stopping the pointer jumps. https://bugs.freedesktop.org/show_bug.cgi?id=94379 Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net> Tested-by: Benjamin Tissoires <benjamin.tissoires@gmail.com>
This commit is contained in:
parent
5d904b6319
commit
a608d9dc2c
5 changed files with 49 additions and 4 deletions
|
|
@ -337,7 +337,7 @@ tp_process_absolute(struct tp_dispatch *tp,
|
||||||
case ABS_MT_PRESSURE:
|
case ABS_MT_PRESSURE:
|
||||||
t->pressure = e->value;
|
t->pressure = e->value;
|
||||||
t->dirty = true;
|
t->dirty = true;
|
||||||
tp->queued |= TOUCHPAD_EVENT_MOTION;
|
tp->queued |= TOUCHPAD_EVENT_OTHERAXIS;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -880,8 +880,10 @@ tp_position_fake_touches(struct tp_dispatch *tp)
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool
|
static inline bool
|
||||||
tp_need_motion_history_reset(struct tp_dispatch *tp)
|
tp_need_motion_history_reset(struct tp_dispatch *tp, uint64_t time)
|
||||||
{
|
{
|
||||||
|
bool rc = false;
|
||||||
|
|
||||||
/* semi-mt finger postions may "jump" when nfingers changes */
|
/* semi-mt finger postions may "jump" when nfingers changes */
|
||||||
if (tp->semi_mt && tp->nfingers_down != tp->old_nfingers_down)
|
if (tp->semi_mt && tp->nfingers_down != tp->old_nfingers_down)
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -894,7 +896,29 @@ tp_need_motion_history_reset(struct tp_dispatch *tp)
|
||||||
tp->old_nfingers_down > tp->num_slots))
|
tp->old_nfingers_down > tp->num_slots))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
return false;
|
/* Quirk: if we had multiple events without x/y axis
|
||||||
|
information, the next x/y event is going to be a jump. So we
|
||||||
|
reset that touch to non-dirty effectively swallowing that event
|
||||||
|
and restarting with the next event again.
|
||||||
|
*/
|
||||||
|
if (tp->device->model_flags & EVDEV_MODEL_LENOVO_T450_TOUCHPAD) {
|
||||||
|
if (tp->queued & TOUCHPAD_EVENT_MOTION) {
|
||||||
|
if (tp->quirks.nonmotion_event_count > 10) {
|
||||||
|
struct tp_touch *t;
|
||||||
|
|
||||||
|
tp_for_each_touch(tp, t)
|
||||||
|
t->dirty = false;
|
||||||
|
rc = true;
|
||||||
|
}
|
||||||
|
tp->quirks.nonmotion_event_count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((tp->queued & (TOUCHPAD_EVENT_OTHERAXIS|TOUCHPAD_EVENT_MOTION)) ==
|
||||||
|
TOUCHPAD_EVENT_OTHERAXIS)
|
||||||
|
tp->quirks.nonmotion_event_count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
@ -909,7 +933,7 @@ tp_process_state(struct tp_dispatch *tp, uint64_t time)
|
||||||
tp_unhover_touches(tp, time);
|
tp_unhover_touches(tp, time);
|
||||||
tp_position_fake_touches(tp);
|
tp_position_fake_touches(tp);
|
||||||
|
|
||||||
want_motion_reset = tp_need_motion_history_reset(tp);
|
want_motion_reset = tp_need_motion_history_reset(tp, time);
|
||||||
|
|
||||||
for (i = 0; i < tp->ntouches; i++) {
|
for (i = 0; i < tp->ntouches; i++) {
|
||||||
t = tp_get_touch(tp, i);
|
t = tp_get_touch(tp, i);
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,7 @@ enum touchpad_event {
|
||||||
TOUCHPAD_EVENT_MOTION = (1 << 0),
|
TOUCHPAD_EVENT_MOTION = (1 << 0),
|
||||||
TOUCHPAD_EVENT_BUTTON_PRESS = (1 << 1),
|
TOUCHPAD_EVENT_BUTTON_PRESS = (1 << 1),
|
||||||
TOUCHPAD_EVENT_BUTTON_RELEASE = (1 << 2),
|
TOUCHPAD_EVENT_BUTTON_RELEASE = (1 << 2),
|
||||||
|
TOUCHPAD_EVENT_OTHERAXIS = (1 << 3),
|
||||||
};
|
};
|
||||||
|
|
||||||
enum touchpad_model {
|
enum touchpad_model {
|
||||||
|
|
@ -353,6 +354,17 @@ struct tp_dispatch {
|
||||||
int upper_thumb_line;
|
int upper_thumb_line;
|
||||||
int lower_thumb_line;
|
int lower_thumb_line;
|
||||||
} thumb;
|
} thumb;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
/* A quirk used on the T450 series Synaptics hardware.
|
||||||
|
* Slowly moving the finger causes multiple events with only
|
||||||
|
* ABS_MT_PRESSURE but no x/y information. When the x/y
|
||||||
|
* event comes, it will be a jump of ~20 units. We use the
|
||||||
|
* below to count non-motion events to discard that first
|
||||||
|
* event with the jump.
|
||||||
|
*/
|
||||||
|
unsigned int nonmotion_event_count;
|
||||||
|
} quirks;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define tp_for_each_touch(_tp, _t) \
|
#define tp_for_each_touch(_tp, _t) \
|
||||||
|
|
|
||||||
|
|
@ -1680,6 +1680,7 @@ evdev_read_model_flags(struct evdev_device *device)
|
||||||
{ "LIBINPUT_MODEL_CYBORG_RAT", EVDEV_MODEL_CYBORG_RAT },
|
{ "LIBINPUT_MODEL_CYBORG_RAT", EVDEV_MODEL_CYBORG_RAT },
|
||||||
{ "LIBINPUT_MODEL_CYAPA", EVDEV_MODEL_CYAPA },
|
{ "LIBINPUT_MODEL_CYAPA", EVDEV_MODEL_CYAPA },
|
||||||
{ "LIBINPUT_MODEL_ALPS_RUSHMORE", EVDEV_MODEL_ALPS_RUSHMORE },
|
{ "LIBINPUT_MODEL_ALPS_RUSHMORE", EVDEV_MODEL_ALPS_RUSHMORE },
|
||||||
|
{ "LIBINPUT_MODEL_LENOVO_T450_TOUCHPAD", EVDEV_MODEL_LENOVO_T450_TOUCHPAD },
|
||||||
{ NULL, EVDEV_MODEL_DEFAULT },
|
{ NULL, EVDEV_MODEL_DEFAULT },
|
||||||
};
|
};
|
||||||
const struct model_map *m = model_map;
|
const struct model_map *m = model_map;
|
||||||
|
|
|
||||||
|
|
@ -113,6 +113,7 @@ enum evdev_device_model {
|
||||||
EVDEV_MODEL_CYBORG_RAT = (1 << 14),
|
EVDEV_MODEL_CYBORG_RAT = (1 << 14),
|
||||||
EVDEV_MODEL_CYAPA = (1 << 15),
|
EVDEV_MODEL_CYAPA = (1 << 15),
|
||||||
EVDEV_MODEL_ALPS_RUSHMORE = (1 << 16),
|
EVDEV_MODEL_ALPS_RUSHMORE = (1 << 16),
|
||||||
|
EVDEV_MODEL_LENOVO_T450_TOUCHPAD= (1 << 17),
|
||||||
};
|
};
|
||||||
|
|
||||||
struct mt_slot {
|
struct mt_slot {
|
||||||
|
|
|
||||||
|
|
@ -100,6 +100,13 @@ libinput:name:Cypress APA Trackpad (cyapa):dmi:*
|
||||||
libinput:name:SynPS/2 Synaptics TouchPad:dmi:*svnLENOVO:*:pvrThinkPadX230*
|
libinput:name:SynPS/2 Synaptics TouchPad:dmi:*svnLENOVO:*:pvrThinkPadX230*
|
||||||
LIBINPUT_MODEL_LENOVO_X230=1
|
LIBINPUT_MODEL_LENOVO_X230=1
|
||||||
|
|
||||||
|
# Lenovo T450/T460 and all other Lenovos of the *50 and *60 generation,
|
||||||
|
# including the X1 Carbon 3rd gen
|
||||||
|
libinput:name:SynPS/2 Synaptics TouchPad:dmi:*svnLENOVO:*:pvrThinkPad??50*:
|
||||||
|
libinput:name:SynPS/2 Synaptics TouchPad:dmi:*svnLENOVO:*:pvrThinkPad??60*:
|
||||||
|
libinput:name:SynPS/2 Synaptics TouchPad:dmi:*svnLENOVO:*:pvrThinkPadX1Carbon3rd:*
|
||||||
|
LIBINPUT_MODEL_LENOVO_T450_TOUCHPAD=1
|
||||||
|
|
||||||
##########################################
|
##########################################
|
||||||
# Synaptics
|
# Synaptics
|
||||||
##########################################
|
##########################################
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue