Commit 66ac659e authored by Peter Hutterer's avatar Peter Hutterer Committed by Matt Mayfield
Browse files

touchpad: add support for size-based thumb detection

Fixes #97

Signed-off-by: Peter Hutterer's avatarPeter Hutterer <peter.hutterer@who-t.net>
parent a1effa16
...@@ -34,6 +34,7 @@ MatchProduct=0x030E ...@@ -34,6 +34,7 @@ MatchProduct=0x030E
AttrSizeHint=130x110 AttrSizeHint=130x110
AttrTouchSizeRange=20:10 AttrTouchSizeRange=20:10
AttrPalmSizeThreshold=900 AttrPalmSizeThreshold=900
AttrThumbSizeThreshold=800
[Apple Touchpad OneButton] [Apple Touchpad OneButton]
MatchUdevType=touchpad MatchUdevType=touchpad
......
...@@ -1135,6 +1135,10 @@ tp_thumb_detect(struct tp_dispatch *tp, struct tp_touch *t, uint64_t time) ...@@ -1135,6 +1135,10 @@ tp_thumb_detect(struct tp_dispatch *tp, struct tp_touch *t, uint64_t time)
if (tp->thumb.use_pressure && if (tp->thumb.use_pressure &&
t->pressure > tp->thumb.pressure_threshold) t->pressure > tp->thumb.pressure_threshold)
t->thumb.state = THUMB_STATE_YES; t->thumb.state = THUMB_STATE_YES;
else if (tp->thumb.use_size &&
(t->major > tp->thumb.size_threshold ||
t->minor > tp->thumb.size_threshold))
t->thumb.state = THUMB_STATE_YES;
else if (t->point.y > tp->thumb.lower_thumb_line && else if (t->point.y > tp->thumb.lower_thumb_line &&
tp->scroll.method != LIBINPUT_CONFIG_SCROLL_EDGE && tp->scroll.method != LIBINPUT_CONFIG_SCROLL_EDGE &&
t->thumb.first_touch_time + THUMB_MOVE_TIMEOUT < time) t->thumb.first_touch_time + THUMB_MOVE_TIMEOUT < time)
...@@ -3126,11 +3130,21 @@ tp_init_thumb(struct tp_dispatch *tp) ...@@ -3126,11 +3130,21 @@ tp_init_thumb(struct tp_dispatch *tp)
} }
} }
if (libevdev_has_event_code(device->evdev, EV_ABS, ABS_MT_TOUCH_MAJOR)) {
if (quirks_get_uint32(q,
QUIRK_ATTR_THUMB_SIZE_THRESHOLD,
&threshold)) {
tp->thumb.use_size = true;
tp->thumb.size_threshold = threshold;
}
}
quirks_unref(q); quirks_unref(q);
evdev_log_debug(device, evdev_log_debug(device,
"thumb: enabled thumb detection%s\n", "thumb: enabled thumb detection%s%s\n",
tp->thumb.use_pressure ? " (+pressure)" : ""); tp->thumb.use_pressure ? " (+pressure)" : "",
tp->thumb.use_size ? " (+size)" : "");
} }
static bool static bool
......
...@@ -446,6 +446,9 @@ struct tp_dispatch { ...@@ -446,6 +446,9 @@ struct tp_dispatch {
bool use_pressure; bool use_pressure;
int pressure_threshold; int pressure_threshold;
bool use_size;
int size_threshold;
} thumb; } thumb;
struct { struct {
......
...@@ -268,6 +268,7 @@ quirk_get_name(enum quirk q) ...@@ -268,6 +268,7 @@ quirk_get_name(enum quirk q)
case QUIRK_ATTR_TRACKPOINT_MULTIPLIER: return "AttrTrackpointMultiplier"; case QUIRK_ATTR_TRACKPOINT_MULTIPLIER: return "AttrTrackpointMultiplier";
case QUIRK_ATTR_THUMB_PRESSURE_THRESHOLD: return "AttrThumbPressureThreshold"; case QUIRK_ATTR_THUMB_PRESSURE_THRESHOLD: return "AttrThumbPressureThreshold";
case QUIRK_ATTR_USE_VELOCITY_AVERAGING: return "AttrUseVelocityAveraging"; case QUIRK_ATTR_USE_VELOCITY_AVERAGING: return "AttrUseVelocityAveraging";
case QUIRK_ATTR_THUMB_SIZE_THRESHOLD: return "AttrThumbSizeThreshold";
default: default:
abort(); abort();
} }
...@@ -736,6 +737,13 @@ parse_attr(struct quirks_context *ctx, ...@@ -736,6 +737,13 @@ parse_attr(struct quirks_context *ctx,
p->type = PT_UINT; p->type = PT_UINT;
p->value.u = v; p->value.u = v;
rc = true; rc = true;
} else if (streq(key, quirk_get_name(QUIRK_ATTR_THUMB_SIZE_THRESHOLD))) {
p->id = QUIRK_ATTR_THUMB_SIZE_THRESHOLD;
if (!safe_atou(value, &v))
goto out;
p->type = PT_UINT;
p->value.u = v;
rc = true;
} else { } else {
qlog_error(ctx, "Unknown key %s in %s\n", key, s->name); qlog_error(ctx, "Unknown key %s in %s\n", key, s->name);
} }
......
...@@ -96,6 +96,7 @@ enum quirk { ...@@ -96,6 +96,7 @@ enum quirk {
QUIRK_ATTR_TRACKPOINT_MULTIPLIER, QUIRK_ATTR_TRACKPOINT_MULTIPLIER,
QUIRK_ATTR_THUMB_PRESSURE_THRESHOLD, QUIRK_ATTR_THUMB_PRESSURE_THRESHOLD,
QUIRK_ATTR_USE_VELOCITY_AVERAGING, QUIRK_ATTR_USE_VELOCITY_AVERAGING,
QUIRK_ATTR_THUMB_SIZE_THRESHOLD,
}; };
/** /**
......
...@@ -108,6 +108,8 @@ class TouchSequence(object): ...@@ -108,6 +108,8 @@ class TouchSequence(object):
self.was_down = False self.was_down = False
self.is_palm = False self.is_palm = False
self.was_palm = False self.was_palm = False
self.is_thumb = False
self.was_thumb = False
self.major_range = Range() self.major_range = Range()
self.minor_range = Range() self.minor_range = Range()
...@@ -130,6 +132,10 @@ class TouchSequence(object): ...@@ -130,6 +132,10 @@ class TouchSequence(object):
if self.is_palm: if self.is_palm:
self.was_palm = True self.was_palm = True
self.is_thumb = self.device.thumb != 0 and touch.major > self.device.thumb
if self.is_thumb:
self.was_thumb = True
def finalize(self): def finalize(self):
"""Mark the TouchSequence as complete (finger is up)""" """Mark the TouchSequence as complete (finger is up)"""
self.is_active = False self.is_active = False
...@@ -152,15 +158,18 @@ class TouchSequence(object): ...@@ -152,15 +158,18 @@ class TouchSequence(object):
s += " down" s += " down"
if self.was_palm: if self.was_palm:
s += " palm" s += " palm"
if self.was_thumb:
s += " thumb"
return s return s
def _str_state(self): def _str_state(self):
touch = self.points[-1] touch = self.points[-1]
s = "{}, tags: {} {}".format( s = "{}, tags: {} {} {}".format(
touch, touch,
"down" if self.is_down else " ", "down" if self.is_down else " ",
"palm" if self.is_palm else " " "palm" if self.is_palm else " ",
"thumb" if self.is_thumb else " "
) )
return s return s
...@@ -199,6 +208,7 @@ class Device(object): ...@@ -199,6 +208,7 @@ class Device(object):
self.up = 0 self.up = 0
self.down = 0 self.down = 0
self.palm = 0 self.palm = 0
self.thumb = 0
self._init_thresholds_from_quirks() self._init_thresholds_from_quirks()
self.sequences = [] self.sequences = []
...@@ -235,6 +245,8 @@ class Device(object): ...@@ -235,6 +245,8 @@ class Device(object):
self.palm = int(q[1]) self.palm = int(q[1])
elif q[0] == 'AttrTouchSizeRange': elif q[0] == 'AttrTouchSizeRange':
self.down, self.up = colon_tuple(q[1]) self.down, self.up = colon_tuple(q[1])
elif q[0] == 'AttrThumbSizeThreshold':
self.thumb = int(q[1])
def start_new_sequence(self, tracking_id): def start_new_sequence(self, tracking_id):
self.sequences.append(TouchSequence(self, tracking_id)) self.sequences.append(TouchSequence(self, tracking_id))
...@@ -286,6 +298,7 @@ class Device(object): ...@@ -286,6 +298,7 @@ class Device(object):
print("Ready for recording data.") print("Ready for recording data.")
print("Touch sizes used: {}:{}".format(self.down, self.up)) print("Touch sizes used: {}:{}".format(self.down, self.up))
print("Palm size used: {}".format(self.palm)) print("Palm size used: {}".format(self.palm))
print("Thumb size used: {}".format(self.thumb))
print("Place a single finger on the device to measure touch size.\n" print("Place a single finger on the device to measure touch size.\n"
"Ctrl+C to exit\n") "Ctrl+C to exit\n")
......
...@@ -640,6 +640,7 @@ tools_list_device_quirks(struct quirks_context *ctx, ...@@ -640,6 +640,7 @@ tools_list_device_quirks(struct quirks_context *ctx,
QUIRK_ATTR_TRACKPOINT_MULTIPLIER, QUIRK_ATTR_TRACKPOINT_MULTIPLIER,
QUIRK_ATTR_THUMB_PRESSURE_THRESHOLD, QUIRK_ATTR_THUMB_PRESSURE_THRESHOLD,
QUIRK_ATTR_USE_VELOCITY_AVERAGING, QUIRK_ATTR_USE_VELOCITY_AVERAGING,
QUIRK_ATTR_THUMB_SIZE_THRESHOLD,
}; };
enum quirk *q; enum quirk *q;
...@@ -707,6 +708,7 @@ tools_list_device_quirks(struct quirks_context *ctx, ...@@ -707,6 +708,7 @@ tools_list_device_quirks(struct quirks_context *ctx,
case QUIRK_ATTR_PALM_SIZE_THRESHOLD: case QUIRK_ATTR_PALM_SIZE_THRESHOLD:
case QUIRK_ATTR_PALM_PRESSURE_THRESHOLD: case QUIRK_ATTR_PALM_PRESSURE_THRESHOLD:
case QUIRK_ATTR_THUMB_PRESSURE_THRESHOLD: case QUIRK_ATTR_THUMB_PRESSURE_THRESHOLD:
case QUIRK_ATTR_THUMB_SIZE_THRESHOLD:
quirks_get_uint32(quirks, *q, &v); quirks_get_uint32(quirks, *q, &v);
snprintf(buf, sizeof(buf), "%s=%u", name, v); snprintf(buf, sizeof(buf), "%s=%u", name, v);
callback(userdata, buf); callback(userdata, buf);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment