case ABS_MT_PRESSURE:
t->pressure = e->value;
t->dirty = true;
- tp->queued |= TOUCHPAD_EVENT_MOTION;
+ tp->queued |= TOUCHPAD_EVENT_OTHERAXIS;
break;
}
}
}
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 */
if (tp->semi_mt && tp->nfingers_down != tp->old_nfingers_down)
return true;
tp->old_nfingers_down > tp->num_slots))
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
tp_unhover_touches(tp, time);
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++) {
t = tp_get_touch(tp, i);
TOUCHPAD_EVENT_MOTION = (1 << 0),
TOUCHPAD_EVENT_BUTTON_PRESS = (1 << 1),
TOUCHPAD_EVENT_BUTTON_RELEASE = (1 << 2),
+ TOUCHPAD_EVENT_OTHERAXIS = (1 << 3),
};
enum touchpad_model {
int upper_thumb_line;
int lower_thumb_line;
} 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) \
{ "LIBINPUT_MODEL_CYBORG_RAT", EVDEV_MODEL_CYBORG_RAT },
{ "LIBINPUT_MODEL_CYAPA", EVDEV_MODEL_CYAPA },
{ "LIBINPUT_MODEL_ALPS_RUSHMORE", EVDEV_MODEL_ALPS_RUSHMORE },
+ { "LIBINPUT_MODEL_LENOVO_T450_TOUCHPAD", EVDEV_MODEL_LENOVO_T450_TOUCHPAD },
{ NULL, EVDEV_MODEL_DEFAULT },
};
const struct model_map *m = model_map;
EVDEV_MODEL_CYBORG_RAT = (1 << 14),
EVDEV_MODEL_CYAPA = (1 << 15),
EVDEV_MODEL_ALPS_RUSHMORE = (1 << 16),
+ EVDEV_MODEL_LENOVO_T450_TOUCHPAD= (1 << 17),
};
struct mt_slot {
libinput:name:SynPS/2 Synaptics TouchPad:dmi:*svnLENOVO:*:pvrThinkPadX230*
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
##########################################