Hi,

First of all patches 1-9 and 11 looks good to me and are:

Reviewed-by: Hans de Goede <hdego...@redhat.com>

I've some remarks inline on this one.

On 30-01-17 01:58, Peter Hutterer wrote:
Don't rely on BTN_TOUCH for "finger down", the value for that is hardcoded in
the kernel and not always suitable. Some devices need a different value to
avoid reacting to accidental touches or hovering fingers.

Implement a basic Schmitt trigger, same as we have in the synaptics driver. We
also take the default values from there but these will likely see some
updates.

A special case is when we have more fingers down than slots. Since we can't
detect the pressure on fake fingers (we only get a bit for 'is down') we
assume that *all* fingers are down with sufficient pressure. It's too much of
a niche case to have this work any other way.

This patch drops the handling of ABS_DISTANCE because it's simply not needed
anymore.

Signed-off-by: Peter Hutterer <peter.hutte...@who-t.net>
---
 src/evdev-mt-touchpad.c              | 129 +++++++++++++++++++++++++++++------
 src/evdev-mt-touchpad.h              |  10 ++-
 test/litest-device-alps-dualpoint.c  |  14 ++++
 test/litest-device-alps-semi-mt.c    |  14 ++++
 test/litest-device-atmel-hover.c     |  14 ++++
 test/litest-device-synaptics-hover.c |  14 ++++
 test/litest-device-synaptics-st.c    |  15 +++-
 7 files changed, 185 insertions(+), 25 deletions(-)

diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c
index a47c59f..ff9ec41 100644
--- a/src/evdev-mt-touchpad.c
+++ b/src/evdev-mt-touchpad.c
@@ -322,9 +322,6 @@ tp_process_absolute(struct tp_dispatch *tp,
        case ABS_MT_SLOT:
                tp->slot = e->value;
                break;
-       case ABS_MT_DISTANCE:
-               t->distance = e->value;
-               break;
        case ABS_MT_TRACKING_ID:
                if (e->value != -1)
                        tp_new_touch(tp, t, time);
@@ -365,6 +362,11 @@ tp_process_absolute_st(struct tp_dispatch *tp,
                t->dirty = true;
                tp->queued |= TOUCHPAD_EVENT_MOTION;
                break;
+       case ABS_PRESSURE:
+               t->pressure = e->value;
+               t->dirty = true;
+               tp->queued |= TOUCHPAD_EVENT_OTHERAXIS;
+               break;
        }
 }

@@ -795,26 +797,72 @@ out:
 }

 static void
-tp_unhover_abs_distance(struct tp_dispatch *tp, uint64_t time)
+tp_unhover_pressure(struct tp_dispatch *tp, uint64_t time)
 {
        struct tp_touch *t;
-       unsigned int i;
+       int i;
+       unsigned int nfake_touches;
+       unsigned int real_fingers_down = 0;

-       for (i = 0; i < tp->ntouches; i++) {
+       nfake_touches = tp_fake_finger_count(tp);
+       if (nfake_touches == FAKE_FINGER_OVERFLOW)
+               nfake_touches = 0;
+
+       for (i = 0; i < (int)tp->num_slots; i++) {
                t = tp_get_touch(tp, i);

-               if (!t->dirty)
-                       continue;
+               if (t->dirty) {
+                       if (t->state == TOUCH_HOVERING) {
+                               if (t->pressure >= tp->pressure.high) {
+                                       /* avoid jumps when landing a finger */
+                                       tp_motion_history_reset(t);
+                                       tp_begin_touch(tp, t, time);
+                               }
+                       } else {
+                               if (t->pressure < tp->pressure.low)
+                                       tp_end_touch(tp, t, time);
+                       }
+               }
+
+               if (t->state == TOUCH_BEGIN ||
+                   t->state == TOUCH_UPDATE)
+                       real_fingers_down++;
+       }

+       if (nfake_touches <= tp->num_slots ||
+           tp->nfingers_down == 0)
+               return;

Maybe:

        if (tp->nfingers_down >= nfake_touches ||
            tp->nfingers_down == 0)
                return;

Otherwise this:

+
+       /* if we have more fake fingers down than slots, we assume
+        * _all_ fingers have enough pressure, even if some of the slotted
+        * ones don't. Anything else gets insane quickly.
+        */
+       for (i = 0; i < (int)tp->ntouches; i++) {
+               t = tp_get_touch(tp, i);
                if (t->state == TOUCH_HOVERING) {
<snip removed bit>
+                       /* avoid jumps when landing a finger */
+                       tp_motion_history_reset(t);
+                       tp_begin_touch(tp, t, time);
+
+                       if (tp->nfingers_down >= nfake_touches)
+                               break;
+               }
+       }

Will always unhover one more hovering touch even if we
already have enough, I don't know if we can have more touches
in down + hovering state then nfake_touches but otherwise
the

                        if (tp->nfingers_down >= nfake_touches)
                                break;

Is not necessary.

+
+       if (tp->nfingers_down > nfake_touches ||
+           real_fingers_down == 0) {
+               for (i = tp->ntouches - 1; i >= 0; i--) {
+                       t = tp_get_touch(tp, i);
+
+                       if (t->state == TOUCH_HOVERING ||
+                           t->state == TOUCH_NONE)
+                               continue;
+
+                       tp_end_touch(tp, t, time);
+
+                       if (real_fingers_down > 0  &&
+                           tp->nfingers_down == nfake_touches)
+                               break;
                }
        }
 }
@@ -881,8 +929,8 @@ tp_unhover_fake_touches(struct tp_dispatch *tp, uint64_t 
time)
 static void
 tp_unhover_touches(struct tp_dispatch *tp, uint64_t time)
 {
-       if (tp->reports_distance)
-               tp_unhover_abs_distance(tp, time);
+       if (tp->pressure.use_pressure)
+               tp_unhover_pressure(tp, time);
        else
                tp_unhover_fake_touches(tp, time);

@@ -926,6 +974,7 @@ tp_position_fake_touches(struct tp_dispatch *tp)
                        continue;

                t->point = topmost->point;
+               t->pressure = topmost->pressure;
                if (!t->dirty)
                        t->dirty = topmost->dirty;
        }
@@ -1747,7 +1796,13 @@ tp_sync_touch(struct tp_dispatch *tp,
                                       &t->point.y))
                t->point.y = libevdev_get_event_value(evdev, EV_ABS, ABS_Y);

-       libevdev_fetch_slot_value(evdev, slot, ABS_MT_DISTANCE, &t->distance);
+       if (!libevdev_fetch_slot_value(evdev,
+                                      slot,
+                                      ABS_MT_PRESSURE,
+                                      &t->pressure))
+               t->pressure = libevdev_get_event_value(evdev,
+                                                      EV_ABS,
+                                                      ABS_PRESSURE);
 }

 static inline void
@@ -2271,6 +2326,38 @@ tp_init_hysteresis(struct tp_dispatch *tp)
        return;
 }

+static void
+tp_init_pressure(struct tp_dispatch *tp,
+                struct evdev_device *device)
+{
+       const struct input_absinfo *abs;
+       unsigned int range;
+       unsigned int code = ABS_PRESSURE;
+
+       if (tp->has_mt)
+               code = ABS_MT_PRESSURE;
+
+       if (!libevdev_has_event_code(device->evdev, EV_ABS, code)) {
+               tp->pressure.use_pressure = false;
+               return;
+       }
+
+       tp->pressure.use_pressure = true;
+
+       abs = libevdev_get_abs_info(device->evdev, code);
+       assert(abs);
+
+       range = abs->maximum - abs->minimum;
+
+       /* Approximately the synaptics defaults */
+       tp->pressure.high = abs->minimum + 0.12 * range;
+       tp->pressure.low = abs->minimum + 0.10 * range;
+
+       log_debug(evdev_libinput_context(device),
+                 "%s: using pressure-based touch detection\n",
+                 device->devname);
+}
+
 static int
 tp_init(struct tp_dispatch *tp,
        struct evdev_device *device)
@@ -2288,9 +2375,7 @@ tp_init(struct tp_dispatch *tp,

        evdev_device_init_abs_range_warnings(device);

-       tp->reports_distance = libevdev_has_event_code(device->evdev,
-                                                      EV_ABS,
-                                                      ABS_MT_DISTANCE);
+       tp_init_pressure(tp, device);

        /* Set the dpi to that of the x axis, because that's what we normalize
           to when needed*/
diff --git a/src/evdev-mt-touchpad.h b/src/evdev-mt-touchpad.h
index abe885f..eae0af9 100644
--- a/src/evdev-mt-touchpad.h
+++ b/src/evdev-mt-touchpad.h
@@ -153,7 +153,6 @@ struct tp_touch {
        bool dirty;
        struct device_coords point;
        uint64_t millis;
-       int distance;                           /* distance == 0 means touch */
        int pressure;

        bool was_down; /* if distance == 0, false for pure hovering
@@ -232,7 +231,6 @@ struct tp_dispatch {
        unsigned int slot;                      /* current slot */
        bool has_mt;
        bool semi_mt;
-       bool reports_distance;                  /* does the device support true 
hovering */

        /* true if we're reading events (i.e. not suspended) but we're
         * ignoring them */
@@ -248,6 +246,14 @@ struct tp_dispatch {
         */
        unsigned int fake_touches;

+       /* if pressure goes above high -> touch down,
+          if pressure then goes below low -> touch up */
+       struct {
+               bool use_pressure;
+               int high;
+               int low;
+       } pressure;
+
        struct device_coords hysteresis_margin;

        struct {
diff --git a/test/litest-device-alps-dualpoint.c 
b/test/litest-device-alps-dualpoint.c
index de025e5..90fdbca 100644
--- a/test/litest-device-alps-dualpoint.c
+++ b/test/litest-device-alps-dualpoint.c
@@ -60,9 +60,23 @@ static struct input_event move[] = {
        { .type = -1, .code = -1 },
 };

+static int
+get_axis_default(struct litest_device *d, unsigned int evcode, int32_t *value)
+{
+       switch (evcode) {
+       case ABS_PRESSURE:
+       case ABS_MT_PRESSURE:
+               *value = 30;
+               return 0;
+       }
+       return 1;
+}
+
 static struct litest_device_interface interface = {
        .touch_down_events = down,
        .touch_move_events = move,
+
+       .get_axis_default = get_axis_default,
 };

 static struct input_id input_id = {
diff --git a/test/litest-device-alps-semi-mt.c 
b/test/litest-device-alps-semi-mt.c
index d78adca..de0eb3a 100644
--- a/test/litest-device-alps-semi-mt.c
+++ b/test/litest-device-alps-semi-mt.c
@@ -60,9 +60,23 @@ static struct input_event move[] = {
        { .type = -1, .code = -1 },
 };

+static int
+get_axis_default(struct litest_device *d, unsigned int evcode, int32_t *value)
+{
+       switch (evcode) {
+       case ABS_PRESSURE:
+       case ABS_MT_PRESSURE:
+               *value = 30;
+               return 0;
+       }
+       return 1;
+}
+
 static struct litest_device_interface interface = {
        .touch_down_events = down,
        .touch_move_events = move,
+
+       .get_axis_default = get_axis_default,
 };

 static struct input_id input_id = {
diff --git a/test/litest-device-atmel-hover.c b/test/litest-device-atmel-hover.c
index c856d08..942744e 100644
--- a/test/litest-device-atmel-hover.c
+++ b/test/litest-device-atmel-hover.c
@@ -76,10 +76,24 @@ static struct input_event up[] = {
        { .type = -1, .code = -1 },
 };

+static int
+get_axis_default(struct litest_device *d, unsigned int evcode, int32_t *value)
+{
+       switch (evcode) {
+       case ABS_PRESSURE:
+       case ABS_MT_PRESSURE:
+               *value = 30;
+               return 0;
+       }
+       return 1;
+}
+
 static struct litest_device_interface interface = {
        .touch_down_events = down,
        .touch_move_events = move,
        .touch_up_events = up,
+
+       .get_axis_default = get_axis_default,
 };

 static struct input_id input_id = {
diff --git a/test/litest-device-synaptics-hover.c 
b/test/litest-device-synaptics-hover.c
index 8439f10..9c0c7bd 100644
--- a/test/litest-device-synaptics-hover.c
+++ b/test/litest-device-synaptics-hover.c
@@ -60,9 +60,23 @@ static struct input_event move[] = {
        { .type = -1, .code = -1 },
 };

+static int
+get_axis_default(struct litest_device *d, unsigned int evcode, int32_t *value)
+{
+       switch (evcode) {
+       case ABS_PRESSURE:
+       case ABS_MT_PRESSURE:
+               *value = 30;
+               return 0;
+       }
+       return 1;
+}
+
 static struct litest_device_interface interface = {
        .touch_down_events = down,
        .touch_move_events = move,
+
+       .get_axis_default = get_axis_default,
 };

 static struct input_id input_id = {
diff --git a/test/litest-device-synaptics-st.c 
b/test/litest-device-synaptics-st.c
index 7e45d56..bbde1ef 100644
--- a/test/litest-device-synaptics-st.c
+++ b/test/litest-device-synaptics-st.c
@@ -36,7 +36,7 @@ litest_synaptics_touchpad_setup(void)
 static struct input_event down[] = {
        { .type = EV_ABS, .code = ABS_X, .value = LITEST_AUTO_ASSIGN },
        { .type = EV_ABS, .code = ABS_Y, .value = LITEST_AUTO_ASSIGN },
-       { .type = EV_ABS, .code = ABS_PRESSURE, .value = 30  },
+       { .type = EV_ABS, .code = ABS_PRESSURE, .value = LITEST_AUTO_ASSIGN  },
        { .type = EV_ABS, .code = ABS_TOOL_WIDTH, .value = 7  },
        { .type = EV_SYN, .code = SYN_REPORT, .value = 0 },
        { .type = -1, .code = -1 },
@@ -54,10 +54,23 @@ struct input_event up[] = {
        { .type = -1, .code = -1 },
 };

+static int
+get_axis_default(struct litest_device *d, unsigned int evcode, int32_t *value)
+{
+       switch (evcode) {
+       case ABS_PRESSURE:
+               *value = 30;
+               return 0;
+       }
+       return 1;
+}
+
 static struct litest_device_interface interface = {
        .touch_down_events = down,
        .touch_move_events = move,
        .touch_up_events = up,
+
+       .get_axis_default = get_axis_default,
 };

 static struct input_absinfo absinfo[] = {


Otherwise looks good.

Regards,

Hans
_______________________________________________
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/wayland-devel

Reply via email to