summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPeter Hutterer <peter.hutterer@who-t.net>2018-03-05 08:26:47 +1000
committerPeter Hutterer <peter.hutterer@who-t.net>2018-03-05 08:26:47 +1000
commit440d94be57ffa7c826967e0a623700e7c7e759b7 (patch)
treeece04be95009d6561e270eaccfe1352fbe0b83c4 /src
parentf47eb2d796ef459c52394681083d0110d56b4ce3 (diff)
parent6ccd8e934f965150173866db265ca544031c6e6b (diff)
Merge branch 'wip/touchpad-maybe-end-state'
Diffstat (limited to 'src')
-rw-r--r--src/evdev-mt-touchpad-edge-scroll.c8
-rw-r--r--src/evdev-mt-touchpad.c101
-rw-r--r--src/evdev-mt-touchpad.h9
3 files changed, 93 insertions, 25 deletions
diff --git a/src/evdev-mt-touchpad-edge-scroll.c b/src/evdev-mt-touchpad-edge-scroll.c
index a29d9aff..b218415f 100644
--- a/src/evdev-mt-touchpad-edge-scroll.c
+++ b/src/evdev-mt-touchpad-edge-scroll.c
@@ -366,6 +366,14 @@ tp_edge_scroll_handle_state(struct tp_dispatch *tp, uint64_t time)
case TOUCH_UPDATE:
tp_edge_scroll_handle_event(tp, t, SCROLL_EVENT_MOTION);
break;
+ case TOUCH_MAYBE_END:
+ /* This shouldn't happen we transfer to TOUCH_END
+ * before processing state */
+ evdev_log_debug(tp->device,
+ "touch %d: unexpected state %d\n",
+ t->index,
+ t->state);
+ /* fallthrough */
case TOUCH_END:
tp_edge_scroll_handle_event(tp, t, SCROLL_EVENT_RELEASE);
break;
diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c
index cec4ba34..5416e3b4 100644
--- a/src/evdev-mt-touchpad.c
+++ b/src/evdev-mt-touchpad.c
@@ -342,22 +342,66 @@ tp_begin_touch(struct tp_dispatch *tp, struct tp_touch *t, uint64_t time)
}
/**
- * End a touch, even if the touch sequence is still active.
+ * Schedule a touch to be ended, based on either the events or some
+ * attributes of the touch (size, pressure). In some cases we need to
+ * resurrect a touch that has ended, so this doesn't actually end the touch
+ * yet. All the TOUCH_MAYBE_END touches get properly ended once the device
+ * state has been processed once and we know how many zombie touches we
+ * need.
*/
static inline void
-tp_end_touch(struct tp_dispatch *tp, struct tp_touch *t, uint64_t time)
+tp_maybe_end_touch(struct tp_dispatch *tp,
+ struct tp_touch *t,
+ uint64_t time)
{
switch (t->state) {
- case TOUCH_HOVERING:
- t->state = TOUCH_NONE;
- /* fallthough */
case TOUCH_NONE:
+ case TOUCH_MAYBE_END:
+ case TOUCH_HOVERING:
+ return;
case TOUCH_END:
+ evdev_log_bug_libinput(tp->device,
+ "touch %d: already in TOUCH_END\n",
+ t->index);
return;
case TOUCH_BEGIN:
case TOUCH_UPDATE:
break;
+ }
+
+ t->dirty = true;
+ t->state = TOUCH_MAYBE_END;
+
+ assert(tp->nfingers_down >= 1);
+ tp->nfingers_down--;
+}
+/**
+ * Inverse to tp_maybe_end_touch(), restores a touch back to its previous
+ * state.
+ */
+static inline void
+tp_recover_ended_touch(struct tp_dispatch *tp,
+ struct tp_touch *t)
+{
+ t->dirty = true;
+ t->state = TOUCH_UPDATE;
+ tp->nfingers_down++;
+}
+
+/**
+ * End a touch, even if the touch sequence is still active.
+ * Use tp_maybe_end_touch() instead.
+ */
+static inline void
+tp_end_touch(struct tp_dispatch *tp, struct tp_touch *t, uint64_t time)
+{
+ if (t->state != TOUCH_MAYBE_END) {
+ evdev_log_bug_libinput(tp->device,
+ "touch %d should be MAYBE_END, is %d\n",
+ t->index,
+ t->state);
+ return;
}
t->dirty = true;
@@ -366,8 +410,6 @@ tp_end_touch(struct tp_dispatch *tp, struct tp_touch *t, uint64_t time)
t->pinned.is_pinned = false;
t->time = time;
t->palm.time = 0;
- assert(tp->nfingers_down >= 1);
- tp->nfingers_down--;
tp->queued |= TOUCHPAD_EVENT_MOTION;
}
@@ -378,7 +420,7 @@ static inline void
tp_end_sequence(struct tp_dispatch *tp, struct tp_touch *t, uint64_t time)
{
t->has_ended = true;
- tp_end_touch(tp, t, time);
+ tp_maybe_end_touch(tp, t, time);
}
static void
@@ -525,13 +567,11 @@ tp_restore_synaptics_touches(struct tp_dispatch *tp,
for (i = 0; i < tp->num_slots; i++) {
struct tp_touch *t = tp_get_touch(tp, i);
- if (t->state != TOUCH_END)
+ if (t->state != TOUCH_MAYBE_END)
continue;
/* new touch, move it through begin to update immediately */
- tp_new_touch(tp, t, time);
- tp_begin_touch(tp, t, time);
- t->state = TOUCH_UPDATE;
+ tp_recover_ended_touch(tp, t);
}
}
@@ -1143,12 +1183,14 @@ tp_unhover_pressure(struct tp_dispatch *tp, uint64_t time)
tp_motion_history_reset(t);
tp_begin_touch(tp, t, time);
}
- } else {
+ /* don't unhover for pressure if we have too many
+ * fake fingers down, see comment below */
+ } else if (nfake_touches <= tp->num_slots) {
if (t->pressure < tp->pressure.low) {
evdev_log_debug(tp->device,
"pressure: end touch %d\n",
t->index);
- tp_end_touch(tp, t, time);
+ tp_maybe_end_touch(tp, t, time);
}
}
}
@@ -1185,10 +1227,11 @@ tp_unhover_pressure(struct tp_dispatch *tp, uint64_t time)
t = tp_get_touch(tp, i);
if (t->state == TOUCH_HOVERING ||
- t->state == TOUCH_NONE)
+ t->state == TOUCH_NONE ||
+ t->state == TOUCH_MAYBE_END)
continue;
- tp_end_touch(tp, t, time);
+ tp_maybe_end_touch(tp, t, time);
if (real_fingers_down > 0 &&
tp->nfingers_down == nfake_touches)
@@ -1232,7 +1275,7 @@ tp_unhover_size(struct tp_dispatch *tp, uint64_t time)
evdev_log_debug(tp->device,
"touch-size: end touch %d\n",
t->index);
- tp_end_touch(tp, t, time);
+ tp_maybe_end_touch(tp, t, time);
}
}
}
@@ -1286,7 +1329,7 @@ tp_unhover_fake_touches(struct tp_dispatch *tp, uint64_t time)
t->state == TOUCH_NONE)
continue;
- tp_end_touch(tp, t, time);
+ tp_maybe_end_touch(tp, t, time);
if (tp_fake_finger_is_touching(tp) &&
tp->nfingers_down == nfake_touches)
@@ -1455,6 +1498,21 @@ tp_detect_thumb_while_moving(struct tp_dispatch *tp)
}
static void
+tp_pre_process_state(struct tp_dispatch *tp, uint64_t time)
+{
+ struct tp_touch *t;
+
+ tp_process_fake_touches(tp, time);
+ tp_unhover_touches(tp, time);
+
+ tp_for_each_touch(tp, t) {
+ if (t->state == TOUCH_MAYBE_END)
+ tp_end_touch(tp, t, time);
+ }
+
+}
+
+static void
tp_process_state(struct tp_dispatch *tp, uint64_t time)
{
struct tp_touch *t;
@@ -1463,8 +1521,6 @@ tp_process_state(struct tp_dispatch *tp, uint64_t time)
bool have_new_touch = false;
unsigned int speed_exceeded_count = 0;
- tp_process_fake_touches(tp, time);
- tp_unhover_touches(tp, time);
tp_position_fake_touches(tp);
want_motion_reset = tp_need_motion_history_reset(tp);
@@ -1623,6 +1679,7 @@ static void
tp_handle_state(struct tp_dispatch *tp,
uint64_t time)
{
+ tp_pre_process_state(tp, time);
tp_process_state(tp, time);
tp_post_events(tp, time);
tp_post_process_state(tp, time);
@@ -3110,7 +3167,9 @@ tp_init_pressure(struct tp_dispatch *tp,
tp->pressure.low = lo;
evdev_log_debug(device,
- "using pressure-based touch detection\n");
+ "using pressure-based touch detection (%d:%d)\n",
+ lo,
+ hi);
}
static bool
diff --git a/src/evdev-mt-touchpad.h b/src/evdev-mt-touchpad.h
index 1fd8f1e3..f5daa338 100644
--- a/src/evdev-mt-touchpad.h
+++ b/src/evdev-mt-touchpad.h
@@ -46,10 +46,11 @@ enum touchpad_event {
enum touch_state {
TOUCH_NONE = 0,
- TOUCH_HOVERING,
- TOUCH_BEGIN,
- TOUCH_UPDATE,
- TOUCH_END
+ TOUCH_HOVERING = 1,
+ TOUCH_BEGIN = 2,
+ TOUCH_UPDATE = 3,
+ TOUCH_MAYBE_END = 4,
+ TOUCH_END = 5,
};
enum touch_palm_state {