[PATCH libinput 3/3] touchpad: add support for per-finger hovering information

Benjamin Tissoires benjamin.tissoires at gmail.com
Wed May 6 07:45:20 PDT 2015


On Wed, May 6, 2015 at 1:08 AM, Peter Hutterer <peter.hutterer at who-t.net> wrote:
> On Thu, Apr 30, 2015 at 04:30:25PM -0400, Benjamin Tissoires wrote:
>> From: Benjamin Tissoires <benjamin.tissoires at redhat.com>
>>
>> When the device supports true hovering, it reports this
>> information through ABS_MT_DISTANCE.
>> When this axis is available, we should rely on it to
>> (un)hover the touches as BTN_TOUCH is most of the time
>> unreliable (generated by the mouse emulation in the kernel).
>>
>> Signed-off-by: Benjamin Tissoires <benjamin.tissoires at gmail.com>
>> ---
>>  src/evdev-mt-touchpad.c   |   40 +++++++++++-
>>  src/evdev-mt-touchpad.h   |    2 +
>>  test/Makefile.am          |    1 +
>>  test/litest-atmel-hover.c |  149 ++++++++++++++++++++++++++++++++++++++++
>>  test/litest.c             |  153 +++++++++++++++++++++++++++++++++++++-----
>>  test/litest.h             |   26 +++++++-
>>  test/touchpad.c           |  166 +++++++++++++++++++++++++++++++++++++++++++++
>>  7 files changed, 519 insertions(+), 18 deletions(-)
>>  create mode 100644 test/litest-atmel-hover.c
>>
>> diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c
>> index d5ce880..5b7f291 100644
>> --- a/src/evdev-mt-touchpad.c
>> +++ b/src/evdev-mt-touchpad.c
>> @@ -300,6 +300,9 @@ 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);
>> @@ -520,7 +523,29 @@ tp_palm_detect(struct tp_dispatch *tp, struct tp_touch *t, uint64_t time)
>>  }
>>
>>  static void
>> -tp_unhover_touches(struct tp_dispatch *tp, uint64_t time)
>> +tp_unhover_abs_distance(struct tp_dispatch *tp, uint64_t time)
>> +{
>> +     struct tp_touch *t;
>> +     int i;
>> +
>> +     for (i = 0; i < (int)tp->ntouches; i++) {
>> +             t = tp_get_touch(tp, i);
>
> maybe a leftover, but can't we make i an unsigned int to save the cast?

Sure, will amend.

>
>> +
>> +             if (t->state == TOUCH_HOVERING) {
>> +                     if (t->distance == 0) {
>> +                             /* avoid jumps when landing a finger */
>> +                             tp_motion_history_reset(t);
>> +                             tp_begin_touch(tp, t, time);
>> +                     }
>> +             } else {
>> +                     if (t->distance > 0)
>> +                             tp_end_touch(tp, t, time);
>> +             }
>> +     }
>> +}
>> +
>> +static void
>> +tp_unhover_fake_touches(struct tp_dispatch *tp, uint64_t time)
>>  {
>>       struct tp_touch *t;
>>       unsigned int nfake_touches;
>> @@ -579,6 +604,16 @@ tp_unhover_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);
>> +     else
>> +             tp_unhover_fake_touches(tp, time);
>> +
>> +}
>> +
>> +static void
>>  tp_process_state(struct tp_dispatch *tp, uint64_t time)
>>  {
>>       struct tp_touch *t;
>> @@ -1184,6 +1219,9 @@ tp_init(struct tp_dispatch *tp,
>>                    device->abs.absinfo_y->minimum);
>>       diagonal = sqrt(width*width + height*height);
>>
>> +     tp->reports_distance = libevdev_has_event_code(device->evdev, EV_ABS,
>> +                                                    ABS_MT_DISTANCE);
>
> nitpick: if the line break is needed, one arg per line (i.e. EV_ABS goes on
> its own line)

OK

>
>> +
>>       tp->hysteresis_margin.x =
>>               diagonal / DEFAULT_HYSTERESIS_MARGIN_DENOMINATOR;
>>       tp->hysteresis_margin.y =
>> diff --git a/src/evdev-mt-touchpad.h b/src/evdev-mt-touchpad.h
>> index 97b17cd..ebba9df 100644
>> --- a/src/evdev-mt-touchpad.h
>> +++ b/src/evdev-mt-touchpad.h
>> @@ -129,6 +129,7 @@ struct tp_touch {
>>       bool dirty;
>>       struct device_coords point;
>>       uint64_t millis;
>> +     int distance;                           /* distance == 0 means touch */
>>
>>       struct {
>>               struct device_coords samples[TOUCHPAD_HISTORY_LENGTH];
>> @@ -183,6 +184,7 @@ struct tp_dispatch {
>>       unsigned int slot;                      /* current slot */
>>       bool has_mt;
>>       bool semi_mt;
>> +     bool reports_distance;                  /* does the device supports true hovering */
>>       enum touchpad_model model;
>>
>>       unsigned int num_slots;                 /* number of slots */
>> diff --git a/test/Makefile.am b/test/Makefile.am
>> index be0c5d9..a90fa78 100644
>> --- a/test/Makefile.am
>> +++ b/test/Makefile.am
>> @@ -14,6 +14,7 @@ liblitest_la_SOURCES = \
>>       litest.h \
>>       litest-int.h \
>>       litest-alps-semi-mt.c \
>> +     litest-atmel-hover.c \
>>       litest-bcm5974.c \
>>       litest-generic-singletouch.c \
>>       litest-keyboard.c \
>> diff --git a/test/litest-atmel-hover.c b/test/litest-atmel-hover.c
>> new file mode 100644
>> index 0000000..7da0901
>> --- /dev/null
>> +++ b/test/litest-atmel-hover.c
>> @@ -0,0 +1,149 @@
>> +/*
>> + * Copyright ?? 2015 Red Hat, Inc.
>> + *
>> + * Permission to use, copy, modify, distribute, and sell this software and its
>> + * documentation for any purpose is hereby granted without fee, provided that
>> + * the above copyright notice appear in all copies and that both that copyright
>> + * notice and this permission notice appear in supporting documentation, and
>> + * that the name of the copyright holders not be used in advertising or
>> + * publicity pertaining to distribution of the software without specific,
>> + * written prior permission.  The copyright holders make no representations
>> + * about the suitability of this software for any purpose.  It is provided "as
>> + * is" without express or implied warranty.
>> + *
>> + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
>> + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
>> + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
>> + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
>> + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
>> + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
>> + * OF THIS SOFTWARE.
>> + */
>> +
>> +#if HAVE_CONFIG_H
>> +#include "config.h"
>> +#endif
>> +
>> +#include <assert.h>
>> +
>> +#include "libinput-util.h"
>> +
>> +#include "litest.h"
>> +#include "litest-int.h"
>> +
>> +static void
>> +atmel_hover_create(struct litest_device *d);
>> +
>> +static void
>> +litest_atmel_hover_setup(void)
>> +{
>> +     struct litest_device *d = litest_create_device(LITEST_ATMEL_HOVER);
>> +     litest_set_current_device(d);
>> +}
>> +
>> +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 = LITEST_AUTO_ASSIGN  },
>> +     { .type = EV_ABS, .code = ABS_MT_SLOT, .value = LITEST_AUTO_ASSIGN },
>> +     { .type = EV_ABS, .code = ABS_MT_TRACKING_ID, .value = LITEST_AUTO_ASSIGN },
>> +     { .type = EV_ABS, .code = ABS_MT_POSITION_X, .value = LITEST_AUTO_ASSIGN },
>> +     { .type = EV_ABS, .code = ABS_MT_POSITION_Y, .value = LITEST_AUTO_ASSIGN },
>> +     { .type = EV_ABS, .code = ABS_MT_DISTANCE, .value = LITEST_AUTO_ASSIGN },
>> +     { .type = EV_ABS, .code = ABS_MT_PRESSURE, .value = LITEST_AUTO_ASSIGN  },
>> +     { .type = EV_SYN, .code = SYN_REPORT, .value = 0 },
>> +     { .type = -1, .code = -1 },
>> +};
>> +
>> +static struct input_event move[] = {
>> +     { .type = EV_ABS, .code = ABS_MT_SLOT, .value = LITEST_AUTO_ASSIGN },
>> +     { .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 = LITEST_AUTO_ASSIGN  },
>> +     { .type = EV_ABS, .code = ABS_MT_POSITION_X, .value = LITEST_AUTO_ASSIGN },
>> +     { .type = EV_ABS, .code = ABS_MT_POSITION_Y, .value = LITEST_AUTO_ASSIGN },
>> +     { .type = EV_ABS, .code = ABS_MT_DISTANCE, .value = LITEST_AUTO_ASSIGN },
>> +     { .type = EV_ABS, .code = ABS_MT_PRESSURE, .value = LITEST_AUTO_ASSIGN  },
>> +     { .type = EV_SYN, .code = SYN_REPORT, .value = 0 },
>> +     { .type = -1, .code = -1 },
>> +};
>> +
>> +static struct input_event up[] = {
>> +     { .type = EV_ABS, .code = ABS_MT_SLOT, .value = LITEST_AUTO_ASSIGN },
>> +     { .type = EV_ABS, .code = ABS_MT_TRACKING_ID, .value = -1 },
>> +     { .type = EV_ABS, .code = ABS_MT_DISTANCE, .value = 1 },
>> +     { .type = EV_ABS, .code = ABS_MT_PRESSURE, .value = 0  },
>> +     { .type = EV_SYN, .code = SYN_REPORT, .value = 0 },
>> +     { .type = -1, .code = -1 },
>> +};
>> +
>> +static struct litest_device_interface interface = {
>> +     .touch_down_events = down,
>> +     .touch_move_events = move,
>> +     .touch_up_events = up,
>> +};
>> +
>> +static struct input_id input_id = {
>> +     .bustype = 0x18,
>> +     .vendor = 0x0,
>> +     .product = 0x0,
>> +};
>> +
>> +static int events[] = {
>> +     EV_KEY, BTN_LEFT,
>> +     EV_KEY, BTN_TOOL_FINGER,
>> +     EV_KEY, BTN_TOUCH,
>> +     EV_KEY, BTN_TOOL_DOUBLETAP,
>> +     EV_KEY, BTN_TOOL_TRIPLETAP,
>> +     EV_KEY, BTN_TOOL_QUADTAP,
>> +     EV_KEY, BTN_TOOL_QUINTTAP,
>> +     INPUT_PROP_MAX, INPUT_PROP_POINTER,
>> +     INPUT_PROP_MAX, INPUT_PROP_BUTTONPAD,
>> +     -1, -1,
>> +};
>> +
>> +static struct input_absinfo absinfo[] = {
>> +     { ABS_X, 0, 960, 0, 0, 10 },
>> +     { ABS_Y, 0, 540, 0, 0, 10 },
>> +     { ABS_PRESSURE, 0, 255, 0, 0, 0 },
>> +     { ABS_MT_SLOT, 0, 9, 0, 0, 0 },
>> +     { ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0, 0 },
>> +     { ABS_MT_ORIENTATION, 0, 255, 0, 0, 0 },
>> +     { ABS_MT_POSITION_X, 0, 960, 0, 0, 10 },
>> +     { ABS_MT_POSITION_Y, 0, 540, 0, 0, 10 },
>> +     { ABS_MT_TOOL_TYPE, 0, 2, 0, 0, 0 },
>> +     { ABS_MT_TRACKING_ID, 0, 65535, 0, 0, 0 },
>> +     { ABS_MT_PRESSURE, 0, 255, 0, 0, 0 },
>> +     { ABS_MT_DISTANCE, 0, 1, 0, 0, 0 },
>> +     { .value = -1 }
>> +};
>> +
>> +struct litest_test_device litest_atmel_hover_device = {
>> +     .type = LITEST_ATMEL_HOVER,
>> +     .features = LITEST_TOUCHPAD | LITEST_BUTTON | LITEST_CLICKPAD | LITEST_HOVER,
>> +     .shortname = "atmel hover",
>> +     .setup = litest_atmel_hover_setup,
>> +     .interface = &interface,
>> +     .create = atmel_hover_create,
>> +
>> +     .name = "Atmel maXTouch Touchpad",
>> +     .id = &input_id,
>> +     .events = events,
>> +     .absinfo = absinfo,
>> +};
>> +
>> +static void
>> +atmel_hover_create(struct litest_device *d)
>> +{
>> +     struct litest_semi_mt *semi_mt = zalloc(sizeof(*semi_mt));
>> +     assert(semi_mt);
>> +
>> +     d->private = semi_mt;
>> +
>> +     d->uinput = litest_create_uinput_device_from_description(
>> +                     litest_atmel_hover_device.name,
>> +                     litest_atmel_hover_device.id,
>> +                     absinfo,
>> +                     events);
>> +     d->interface = &interface;
>> +}
>> diff --git a/test/litest.c b/test/litest.c
>> index 15fc87e..fa5095b 100644
>> --- a/test/litest.c
>> +++ b/test/litest.c
>> @@ -103,6 +103,7 @@ extern struct litest_test_device litest_wheel_only_device;
>>  extern struct litest_test_device litest_mouse_roccat_device;
>>  extern struct litest_test_device litest_ms_surface_cover_device;
>>  extern struct litest_test_device litest_logitech_trackball_device;
>> +extern struct litest_test_device litest_atmel_hover_device;
>>
>>  struct litest_test_device* devices[] = {
>>       &litest_synaptics_clickpad_device,
>> @@ -127,6 +128,7 @@ struct litest_test_device* devices[] = {
>>       &litest_mouse_roccat_device,
>>       &litest_ms_surface_cover_device,
>>       &litest_logitech_trackball_device,
>> +     &litest_atmel_hover_device,
>>       NULL,
>>  };
>>
>> @@ -794,7 +796,8 @@ litest_event(struct litest_device *d, unsigned int type,
>>  int
>>  litest_auto_assign_value(struct litest_device *d,
>>                        const struct input_event *ev,
>> -                      int slot, double x, double y)
>> +                      int slot, double x, double y,
>> +                      int touching)
>>  {
>>       static int tracking_id;
>>       int value = ev->value;
>> @@ -817,6 +820,9 @@ litest_auto_assign_value(struct litest_device *d,
>>       case ABS_MT_SLOT:
>>               value = slot;
>>               break;
>> +     case ABS_MT_DISTANCE:
>> +             value = touching ? 0 : 1;
>> +             break;
>>       }
>>
>>       return value;
>> @@ -833,9 +839,17 @@ send_btntool(struct litest_device *d)
>>       litest_event(d, EV_KEY, BTN_TOOL_QUINTTAP, d->ntouches_down == 5);
>>  }
>>
>> -void
>> -litest_touch_down(struct litest_device *d, unsigned int slot,
>> -               double x, double y)
>> +static inline int
>> +litest_validate_event(struct input_event *ev, int send_ev_syn)
>> +{
>> +     return !((int16_t)ev->type == EV_SYN &&
>> +             (int16_t)ev->code == SYN_REPORT &&
>
> are those casts needed?

Maybe not...

>
> also, this function is a bit awkwardly named: it doesn't validate as such,
> it just tells us when to filter syn events.
>
> and that brings us to the next bit: I think you can use
> litest_push_event_frame()/litest_pop_event_frame() instead of passing a
> parameter around. more on that in the tests below.
>

... but that is moot given that it will be removed by the use of push/pop :)

Speaking of which. I think the name is awful :) I had to refer to the
code to understand what that means. Maybe I am too biased by my OpenGL
background where push/pop meant "push/restore the current state of the
graphic pipeline". Here it is just: "prevent the syn event to be
sent"/"OK, now send it".

>
>> +             !send_ev_syn);
>> +}
>
>
>> +
>> +static void
>> +litest_slot_start(struct litest_device *d, unsigned int slot,
>> +                double x, double y, int touching, int sync)
>>  {
>>       struct input_event *ev;
>>
>> @@ -851,13 +865,22 @@ litest_touch_down(struct litest_device *d, unsigned int slot,
>>
>>       ev = d->interface->touch_down_events;
>>       while (ev && (int16_t)ev->type != -1 && (int16_t)ev->code != -1) {
>> -             int value = litest_auto_assign_value(d, ev, slot, x, y);
>> -             litest_event(d, ev->type, ev->code, value);
>> +             int value = litest_auto_assign_value(d, ev, slot, x, y, touching);
>> +
>> +             if (litest_validate_event(ev, sync))
>> +                     litest_event(d, ev->type, ev->code, value);
>>               ev++;
>>       }
>>  }
>>
>>  void
>> +litest_touch_down(struct litest_device *d, unsigned int slot,
>> +               double x, double y)
>> +{
>> +     litest_slot_start(d, slot, x, y, 1, 1);
>> +}
>> +
>> +void
>>  litest_touch_up(struct litest_device *d, unsigned int slot)
>>  {
>>       struct input_event *ev;
>> @@ -882,15 +905,15 @@ litest_touch_up(struct litest_device *d, unsigned int slot)
>>               ev = up;
>>
>>       while (ev && (int16_t)ev->type != -1 && (int16_t)ev->code != -1) {
>> -             int value = litest_auto_assign_value(d, ev, slot, 0, 0);
>> +             int value = litest_auto_assign_value(d, ev, slot, 0, 0, 0);
>>               litest_event(d, ev->type, ev->code, value);
>>               ev++;
>>       }
>>  }
>>
>> -void
>> -litest_touch_move(struct litest_device *d, unsigned int slot,
>> -               double x, double y)
>> +static void
>> +litest_slot_move(struct litest_device *d, unsigned int slot,
>> +                double x, double y, int touching, int sync)
>>  {
>>       struct input_event *ev;
>>
>> @@ -901,13 +924,21 @@ litest_touch_move(struct litest_device *d, unsigned int slot,
>>
>>       ev = d->interface->touch_move_events;
>>       while (ev && (int16_t)ev->type != -1 && (int16_t)ev->code != -1) {
>> -             int value = litest_auto_assign_value(d, ev, slot, x, y);
>> -             litest_event(d, ev->type, ev->code, value);
>> +             int value = litest_auto_assign_value(d, ev, slot, x, y, touching);
>> +             if (litest_validate_event(ev, sync))
>> +                     litest_event(d, ev->type, ev->code, value);
>>               ev++;
>>       }
>>  }
>>
>>  void
>> +litest_touch_move(struct litest_device *d, unsigned int slot,
>> +               double x, double y)
>> +{
>> +     litest_slot_move(d, slot, x, y, 1, 1);
>> +}
>> +
>> +void
>>  litest_touch_move_to(struct litest_device *d,
>>                    unsigned int slot,
>>                    double x_from, double y_from,
>> @@ -950,6 +981,96 @@ litest_touch_move_two_touches(struct litest_device *d,
>>  }
>>
>>  void
>> +litest_hover_start(struct litest_device *d, unsigned int slot,
>> +                double x, double y, int sync)
>> +{
>> +     litest_slot_start(d, slot, x, y, 0, sync);
>> +}
>> +
>> +void
>> +litest_hover_end(struct litest_device *d, unsigned int slot, int sync)
>> +{
>> +     struct input_event *ev;
>> +     struct input_event up[] = {
>> +             { .type = EV_ABS, .code = ABS_MT_SLOT, .value = LITEST_AUTO_ASSIGN },
>> +             { .type = EV_ABS, .code = ABS_MT_DISTANCE, .value = 1 },
>> +             { .type = EV_ABS, .code = ABS_MT_TRACKING_ID, .value = -1 },
>> +             { .type = EV_SYN, .code = SYN_REPORT, .value = 0 },
>> +             { .type = -1, .code = -1 }
>> +     };
>> +
>> +     assert(d->ntouches_down > 0);
>> +     d->ntouches_down--;
>> +
>> +     send_btntool(d);
>> +
>> +     if (d->interface->touch_up) {
>> +             d->interface->touch_up(d, slot);
>> +             return;
>> +     } else if (d->interface->touch_up_events) {
>> +             ev = d->interface->touch_up_events;
>> +     } else
>> +             ev = up;
>> +
>> +     while (ev && (int16_t)ev->type != -1 && (int16_t)ev->code != -1) {
>> +             int value = litest_auto_assign_value(d, ev, slot, 0, 0, 0);
>> +             if (litest_validate_event(ev, sync))
>> +                     litest_event(d, ev->type, ev->code, value);
>> +             ev++;
>> +     }
>> +}
>> +
>> +void
>> +litest_hover_move(struct litest_device *d, unsigned int slot,
>> +               double x, double y, int sync)
>> +{
>> +     litest_slot_move(d, slot, x, y, 0, sync);
>> +}
>> +
>> +void
>> +litest_hover_move_to(struct litest_device *d,
>> +                  unsigned int slot,
>> +                  double x_from, double y_from,
>> +                  double x_to, double y_to,
>> +                  int steps, int sleep_ms, int sync)
>> +{
>> +     for (int i = 0; i < steps - 1; i++) {
>> +             litest_hover_move(d, slot,
>> +                               x_from + (x_to - x_from)/steps * i,
>> +                               y_from + (y_to - y_from)/steps * i,
>> +                               sync);
>> +             if (sleep_ms) {
>> +                     libinput_dispatch(d->libinput);
>> +                     msleep(sleep_ms);
>> +                     libinput_dispatch(d->libinput);
>> +             }
>> +     }
>> +     litest_hover_move(d, slot, x_to, y_to, sync);
>> +}
>> +
>> +void
>> +litest_hover_move_two_touches(struct litest_device *d,
>> +                           double x0, double y0,
>> +                           double x1, double y1,
>> +                           double dx, double dy,
>> +                           int steps, int sleep_ms)
>> +{
>> +     for (int i = 0; i < steps - 1; i++) {
>> +             litest_hover_move(d, 0, x0 + dx / steps * i,
>> +                                     y0 + dy / steps * i, 0);
>> +             litest_hover_move(d, 1, x1 + dx / steps * i,
>> +                                     y1 + dy / steps * i, 1);
>> +             if (sleep_ms) {
>> +                     libinput_dispatch(d->libinput);
>> +                     msleep(sleep_ms);
>> +                     libinput_dispatch(d->libinput);
>> +             }
>> +     }
>> +     litest_hover_move(d, 0, x0 + dx, y0 + dy, 0);
>> +     litest_hover_move(d, 1, x1 + dx, y1 + dy, 1);
>> +}
>> +
>> +void
>>  litest_button_click(struct litest_device *d, unsigned int button, bool is_press)
>>  {
>>
>> @@ -1484,11 +1605,11 @@ send_abs_xy(struct litest_device *d, double x, double y)
>>       e.type = EV_ABS;
>>       e.code = ABS_X;
>>       e.value = LITEST_AUTO_ASSIGN;
>> -     val = litest_auto_assign_value(d, &e, 0, x, y);
>> +     val = litest_auto_assign_value(d, &e, 0, x, y, 1);
>>       litest_event(d, EV_ABS, ABS_X, val);
>>
>>       e.code = ABS_Y;
>> -     val = litest_auto_assign_value(d, &e, 0, x, y);
>> +     val = litest_auto_assign_value(d, &e, 0, x, y, 1);
>>       litest_event(d, EV_ABS, ABS_Y, val);
>>  }
>>
>> @@ -1501,12 +1622,12 @@ send_abs_mt_xy(struct litest_device *d, double x, double y)
>>       e.type = EV_ABS;
>>       e.code = ABS_MT_POSITION_X;
>>       e.value = LITEST_AUTO_ASSIGN;
>> -     val = litest_auto_assign_value(d, &e, 0, x, y);
>> +     val = litest_auto_assign_value(d, &e, 0, x, y, 1);
>>       litest_event(d, EV_ABS, ABS_MT_POSITION_X, val);
>>
>>       e.code = ABS_MT_POSITION_Y;
>>       e.value = LITEST_AUTO_ASSIGN;
>> -     val = litest_auto_assign_value(d, &e, 0, x, y);
>> +     val = litest_auto_assign_value(d, &e, 0, x, y, 1);
>>       litest_event(d, EV_ABS, ABS_MT_POSITION_Y, val);
>>  }
>>
>> diff --git a/test/litest.h b/test/litest.h
>> index 611cdf7..bb9ba03 100644
>> --- a/test/litest.h
>> +++ b/test/litest.h
>> @@ -57,6 +57,7 @@ enum litest_device_type {
>>       LITEST_WHEEL_ONLY = -21,
>>       LITEST_MOUSE_ROCCAT = -22,
>>       LITEST_LOGITECH_TRACKBALL = -23,
>> +     LITEST_ATMEL_HOVER = -24,
>>  };
>>
>>  enum litest_device_feature {
>> @@ -77,6 +78,7 @@ enum litest_device_feature {
>>       LITEST_FAKE_MT = 1 << 12,
>>       LITEST_ABSOLUTE = 1 << 13,
>>       LITEST_PROTOCOL_A = 1 << 14,
>> +     LITEST_HOVER = 1 << 15,
>>  };
>>
>>  struct litest_device {
>> @@ -141,7 +143,8 @@ void litest_event(struct litest_device *t,
>>                 int value);
>>  int litest_auto_assign_value(struct litest_device *d,
>>                            const struct input_event *ev,
>> -                          int slot, double x, double y);
>> +                          int slot, double x, double y,
>> +                          int touching);
>>  void litest_touch_up(struct litest_device *d, unsigned int slot);
>>  void litest_touch_move(struct litest_device *d,
>>                      unsigned int slot,
>> @@ -161,6 +164,27 @@ void litest_touch_move_two_touches(struct litest_device *d,
>>                                  double x1, double y1,
>>                                  double dx, double dy,
>>                                  int steps, int sleep_ms);
>> +void litest_hover_start(struct litest_device *d,
>> +                     unsigned int slot,
>> +                     double x,
>> +                     double y,
>> +                     int sync);
>> +void litest_hover_end(struct litest_device *d, unsigned int slot, int sync);
>> +void litest_hover_move(struct litest_device *d,
>> +                    unsigned int slot,
>> +                    double x,
>> +                    double y,
>> +                    int sync);
>> +void litest_hover_move_to(struct litest_device *d,
>> +                       unsigned int slot,
>> +                       double x_from, double y_from,
>> +                       double x_to, double y_to,
>> +                       int steps, int sleep_ms, int sync);
>> +void litest_hover_move_two_touches(struct litest_device *d,
>> +                                double x0, double y0,
>> +                                double x1, double y1,
>> +                                double dx, double dy,
>> +                                int steps, int sleep_ms);
>>  void litest_button_click(struct litest_device *d,
>>                        unsigned int button,
>>                        bool is_press);
>> diff --git a/test/touchpad.c b/test/touchpad.c
>> index 49f5023..f0be6d9 100644
>> --- a/test/touchpad.c
>> +++ b/test/touchpad.c
>> @@ -3834,6 +3834,165 @@ START_TEST(touchpad_semi_mt_hover_2fg_1fg_down)
>>  }
>>  END_TEST
>>
>> +START_TEST(touchpad_hover_noevent)
>> +{
>> +     struct litest_device *dev = litest_current_device();
>> +     struct libinput *li = dev->libinput;
>> +
>> +     litest_drain_events(li);
>> +
>> +     litest_hover_start(dev, 0, 50, 50, 1);
>> +     litest_hover_move_to(dev, 0, 50, 50, 70, 70, 10, 10, 1);
>> +     litest_hover_end(dev, 0, 1);
>> +
>> +     litest_assert_empty_queue(li);
>> +}
>> +END_TEST
>> +
>> +START_TEST(touchpad_hover_down)
>> +{
>> +     struct litest_device *dev = litest_current_device();
>> +     struct libinput *li = dev->libinput;
>> +
>> +     litest_drain_events(li);
>> +
>> +     /* hover the finger */
>> +     litest_hover_start(dev, 0, 50, 50, 1);
>> +
>> +     litest_hover_move_to(dev, 0, 50, 50, 70, 70, 10, 10, 1);
>> +
>> +     litest_assert_empty_queue(li);
>> +
>> +     /* touch the finger on the sensor */
>> +     litest_touch_move_to(dev, 0, 70, 70, 50, 50, 10, 10);
>> +
>> +     libinput_dispatch(li);
>> +
>> +     litest_assert_only_typed_events(li,
>> +                                     LIBINPUT_EVENT_POINTER_MOTION);
>> +
>> +     /* go back to hover */
>> +     litest_hover_move_to(dev, 0, 50, 50, 70, 70, 10, 10, 1);
>> +     litest_hover_end(dev, 0, 1);
>> +
>> +     litest_assert_empty_queue(li);
>> +}
>> +END_TEST
>> +
>> +START_TEST(touchpad_hover_down_hover_down)
>> +{
>> +     struct litest_device *dev = litest_current_device();
>> +     struct libinput *li = dev->libinput;
>> +     int i;
>> +
>> +     litest_drain_events(li);
>> +
>> +     litest_hover_start(dev, 0, 50, 50, 1);
>> +
>> +     for (i = 0; i < 3; i++) {
>> +
>> +             /* hover the finger */
>> +             litest_hover_move_to(dev, 0, 50, 50, 70, 70, 10, 10, 1);
>> +
>> +             litest_assert_empty_queue(li);
>> +
>> +             /* touch the finger */
>> +             litest_touch_move_to(dev, 0, 70, 70, 50, 50, 10, 10);
>
> pls add a touch_down() call before each touch_move_to, it makes it a lot
> more obvious that the finger is down now (goes for all tests).

Unfortunatelly, that is not possible (at least without making my brain
smoke due to overheat).
touch_down/hover_down are sent when a new slot has to be allocated. So
if we send a touch_down after a hover_start, we will receive a new
tracking ID and this is bad.

I'll try to think if I can do something better...

>
>> +
>> +             libinput_dispatch(li);
>> +
>> +             litest_assert_only_typed_events(li,
>> +                                             LIBINPUT_EVENT_POINTER_MOTION);
>> +     }
>> +
>> +     litest_hover_end(dev, 0, 1);
>> +
>> +     /* start a new touch to be sure */
>> +     litest_touch_down(dev, 0, 50, 50);
>> +     litest_touch_move_to(dev, 0, 50, 50, 70, 70, 10, 10);
>> +     litest_touch_up(dev, 0);
>> +
>> +     litest_assert_only_typed_events(li,
>> +                                     LIBINPUT_EVENT_POINTER_MOTION);
>> +}
>> +END_TEST
>> +
>> +START_TEST(touchpad_hover_down_up)
>> +{
>> +     struct litest_device *dev = litest_current_device();
>> +     struct libinput *li = dev->libinput;
>> +
>> +     litest_drain_events(li);
>> +
>> +     /* hover two fingers, and a touch */
>
> ok, here's where I think using the push/pop pairs will do the same job but
> be slightly nicer in terms of API.
>
> litest_push_event_frame();
>
>> +     litest_hover_start(dev, 0, 50, 50, 0);
>> +     litest_hover_start(dev, 1, 50, 50, 0);
>> +     litest_touch_down(dev, 2, 50, 50);
>
> litest_pop_event_frame();
>
>> +
>> +     litest_assert_empty_queue(li);
>> +
>> +     /* hover first finger, end second and third in same frame */
>
> litest_push_event_frame();
>
>> +     litest_hover_move(dev, 0, 70, 70, 0);
>> +     litest_hover_end(dev, 1, 0);
>> +     litest_touch_up(dev, 2);
>
> litest_push_event_frame();
>> +
>> +     litest_assert_empty_queue(li);
>> +
>> +     /* now move the finger */
>> +     litest_touch_move_to(dev, 0, 50, 50, 70, 70, 10, 10);
>> +
>> +     litest_touch_up(dev, 0);
>> +
>> +     litest_assert_only_typed_events(li,
>> +                                     LIBINPUT_EVENT_POINTER_MOTION);
>> +}
>> +END_TEST
>> +
>> +START_TEST(touchpad_hover_2fg_noevent)
>> +{
>> +     struct litest_device *dev = litest_current_device();
>> +     struct libinput *li = dev->libinput;
>> +
>> +     litest_drain_events(li);
>> +
>> +     /* hover two fingers */
>
> litest_push_event_frame();
>
>> +     litest_hover_start(dev, 0, 25, 25, 0);
>> +     litest_hover_start(dev, 1, 50, 50, 1);
>> +
> litest_pop_event_frame();
>
>> +     litest_hover_move_two_touches(dev, 25, 25, 50, 50, 50, 50, 10, 0);
>> +
>
> litest_push_event_frame();
>
>> +     litest_hover_end(dev, 0, 0);
>> +     litest_hover_end(dev, 1, 1);
>
> litest_pop_event_frame();
>> +
>> +     litest_assert_empty_queue(li);
>> +}
>> +END_TEST
>> +
>> +START_TEST(touchpad_hover_2fg_1fg_down)
>> +{
>> +     struct litest_device *dev = litest_current_device();
>> +     struct libinput *li = dev->libinput;
>> +     int i;
>> +
>> +     litest_drain_events(li);
>> +
>> +     /* hover two fingers */
>
> litest_push_event_frame();
>
>> +     litest_hover_start(dev, 0, 25, 25, 0);
>> +     litest_touch_down(dev, 1, 50, 50);
>
> litest_pop_event_frame();
>> +
>> +     for (i = 0; i < 10; i++) {
> litest_push_event_frame();
>> +             litest_hover_move(dev, 0, 25 + 5 * i, 25 + 5 * i, 0);
>> +             litest_touch_move(dev, 1, 50 + 5 * i, 50 - 5 * i);
>
> litest_pop_event_frame();
>
>> +     }
>> +
> litest_push_event_frame();
>> +     litest_hover_end(dev, 0, 0);
>> +     litest_touch_up(dev, 1);
>
> litest_pop_event_frame();
>
> right, so after adding these I think this should work. you can drop the
> extra parameter and just use the push/pop instead.

OK, thanks. Will do.

Cheers,
Benjamin

>
> Cheers,
>    Peter
>
>> +
>> +     litest_assert_only_typed_events(li,
>> +                                     LIBINPUT_EVENT_POINTER_MOTION);
>> +}
>> +END_TEST
>> +
>>  static void
>>  assert_btnevent_from_device(struct litest_device *device,
>>                           unsigned int button,
>> @@ -4241,6 +4400,13 @@ int main(int argc, char **argv) {
>>       litest_add_for_device("touchpad:semi-mt-hover", touchpad_semi_mt_hover_2fg_noevent, LITEST_SYNAPTICS_HOVER_SEMI_MT);
>>       litest_add_for_device("touchpad:semi-mt-hover", touchpad_semi_mt_hover_2fg_1fg_down, LITEST_SYNAPTICS_HOVER_SEMI_MT);
>>
>> +     litest_add("touchpad:hover", touchpad_hover_noevent, LITEST_TOUCHPAD|LITEST_HOVER, LITEST_ANY);
>> +     litest_add("touchpad:hover", touchpad_hover_down, LITEST_TOUCHPAD|LITEST_HOVER, LITEST_ANY);
>> +     litest_add("touchpad:hover", touchpad_hover_down_up, LITEST_TOUCHPAD|LITEST_HOVER, LITEST_ANY);
>> +     litest_add("touchpad:hover", touchpad_hover_down_hover_down, LITEST_TOUCHPAD|LITEST_HOVER, LITEST_ANY);
>> +     litest_add("touchpad:hover", touchpad_hover_2fg_noevent, LITEST_TOUCHPAD|LITEST_HOVER, LITEST_ANY);
>> +     litest_add("touchpad:hover", touchpad_hover_2fg_1fg_down, LITEST_TOUCHPAD|LITEST_HOVER, LITEST_ANY);
>> +
>>       litest_add_for_device("touchpad:trackpoint", touchpad_trackpoint_buttons, LITEST_SYNAPTICS_TRACKPOINT_BUTTONS);
>>       litest_add_for_device("touchpad:trackpoint", touchpad_trackpoint_mb_scroll, LITEST_SYNAPTICS_TRACKPOINT_BUTTONS);
>>       litest_add_for_device("touchpad:trackpoint", touchpad_trackpoint_mb_click, LITEST_SYNAPTICS_TRACKPOINT_BUTTONS);
>> --
>> 1.7.1
>>
>
>> _______________________________________________
>> wayland-devel mailing list
>> wayland-devel at lists.freedesktop.org
>> http://lists.freedesktop.org/mailman/listinfo/wayland-devel
>


More information about the wayland-devel mailing list