On Thu, Apr 30, 2015 at 04:30:25PM -0400, Benjamin Tissoires wrote:
> From: Benjamin Tissoires <[email protected]>
> 
> 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 <[email protected]>
> ---
>  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?

> +
> +             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)

> +
>       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?

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.


> +             !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).

> +
> +             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.

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
> [email protected]
> http://lists.freedesktop.org/mailman/listinfo/wayland-devel

_______________________________________________
wayland-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/wayland-devel

Reply via email to