Re: [PATCH v2 libinput] Fix premature flushing of evdev event on mx4 touchscreen

2015-10-19 Thread Peter Hutterer
sorry for the delay, travelling and only slowly catching up with email.

On Mon, Sep 07, 2015 at 09:57:44PM +0200, Andreas Pokorny wrote:
> The mx4 touchscreen driver emits BTN_TOUCH and BTN_TOOL_FINGER key events
> on a new contact. Prior to this patch only the BTN_TOUCH event was filtered
> out. Now the whole range of BTN_ events for tool types and certain builtin
> multi finger gestures are marked as non-key type.
> 
> Signed-off-by: Andreas Pokorny 

Reviewed-by: Peter Hutterer 

Cheers,
   Peter

> ---
>  src/evdev.c  |  10 +++---
>  test/touch.c | 110 
> +++
>  2 files changed, 115 insertions(+), 5 deletions(-)
> 
> diff --git a/src/evdev.c b/src/evdev.c
> index 04df275..3e22aa9 100644
> --- a/src/evdev.c
> +++ b/src/evdev.c
> @@ -557,7 +557,7 @@ evdev_flush_pending_event(struct evdev_device *device, 
> uint64_t time)
>  static enum evdev_key_type
>  get_key_type(uint16_t code)
>  {
> - if (code == BTN_TOUCH)
> + if (code >= BTN_DIGI && code <= BTN_TOOL_QUADTAP)
>   return EVDEV_KEY_TYPE_NONE;
>  
>   if (code >= KEY_ESC && code <= KEY_MICMUTE)
> @@ -630,16 +630,16 @@ evdev_process_key(struct evdev_device *device,
>   if (e->value == 2)
>   return;
>  
> - if (e->code == BTN_TOUCH) {
> - if (!device->is_mt)
> + type = get_key_type(e->code);
> +
> + if (type == EVDEV_KEY_TYPE_NONE) {
> + if (e->code == BTN_TOUCH && !device->is_mt)
>   evdev_process_touch_button(device, time, e->value);
>   return;
>   }
>  
>   evdev_flush_pending_event(device, time);
>  
> - type = get_key_type(e->code);
> -
>   /* Ignore key release events from the kernel for keys that libinput
>* never got a pressed event for. */
>   if (e->value == 0) {
> diff --git a/test/touch.c b/test/touch.c
> index 875d94d..0e7f893 100644
> --- a/test/touch.c
> +++ b/test/touch.c
> @@ -912,6 +912,114 @@ START_TEST(touch_point_no_minor_or_orientation)
>  }
>  END_TEST
>  
> +START_TEST(touchscreen_with_btn_tool_finger_on_down)
> +{
> + struct libevdev_uinput *uinput;
> + struct libinput *li;
> + struct libinput_device *device;
> + struct libinput_event *event;
> + struct libinput_event_touch *tev;
> + const struct input_absinfo abs[] = {
> + { ABS_X, 0, 1152, 0, 0, 0 },
> + { ABS_Y, 0, 1920, 0, 0, 0 },
> + { ABS_MT_SLOT, 0, 9, 0, 0, 0 },
> + { ABS_MT_TRACKING_ID, 0, 65535, 0, 0, 0 },
> + { ABS_MT_POSITION_X, 0, 1152, 0, 0, 0 },
> + { ABS_MT_POSITION_Y, 0, 1920, 0, 0, 0 },
> + { ABS_MT_TOUCH_MAJOR, 0, 23, 0, 0, 0 },
> + { ABS_MT_TOUCH_MINOR, 0, 23, 0, 0, 0 },
> + { -1, -1, -1, -1, -1, -1 }
> + };
> + const struct input_event input_sequence[] = {
> + { {0}, EV_ABS, ABS_MT_SLOT, 0},
> + { {0}, EV_ABS, ABS_MT_TRACKING_ID, 9},
> + { {0}, EV_KEY, BTN_TOUCH, 1},
> + { {0}, EV_KEY, BTN_TOOL_FINGER, 1},
> + { {0}, EV_ABS, ABS_MT_POSITION_X, 128},
> + { {0}, EV_ABS, ABS_MT_POSITION_Y, 240},
> + { {0}, EV_ABS, ABS_MT_TOUCH_MAJOR, 5},
> + { {0}, EV_ABS, ABS_MT_TOUCH_MINOR, 4},
> + { {0}, EV_SYN, SYN_REPORT, 0},
> + { {0}, EV_ABS, ABS_MT_TOUCH_MAJOR, 6},
> + { {0}, EV_SYN, SYN_REPORT, 0},
> + { {0}, EV_ABS, ABS_MT_TRACKING_ID, -1},
> + { {0}, EV_KEY, BTN_TOUCH, 0},
> + { {0}, EV_KEY, BTN_TOOL_FINGER, 0},
> + { {0}, EV_SYN, SYN_REPORT, 0}
> + };
> + const int num_events = ARRAY_LENGTH(input_sequence);
> + const int width = 1152;
> + const int height = 1920;
> + int x, y, major, minor;
> +
> + uinput = litest_create_uinput_abs_device(
> + "test device",
> + NULL, abs,
> + EV_KEY, BTN_TOUCH,
> + EV_KEY, BTN_TOOL_FINGER,
> + INPUT_PROP_MAX, INPUT_PROP_DIRECT,
> + -1, -1);
> +
> + li = litest_create_context();
> + device = libinput_path_add_device(li,
> +   libevdev_uinput_get_devnode(uinput));
> + ck_assert(device != NULL);
> + device = libinput_device_ref(device);
> + litest_drain_events(li);
> +
> + for (int i = 0; i!=num_events; ++i)
> + libevdev_uinput_write_event(uinput,
> + input_sequence[i].type,
> + input_sequence[i].code,
> + input_sequence[i].value);
> +
> + litest_wait_for_event(li);
> +
> + event = libinput_get_event(li);
> + tev = litest_is_touch_event(event, LIBINPUT_EVENT_TOUCH_DOWN);
> + x = round(libinput_event_touch_get_x_transformed(tev, width));
> + y = round(libinput_event_touch_get_y_transformed(tev, height)),
> + major = round(
>

[PATCH v2 libinput] Fix premature flushing of evdev event on mx4 touchscreen

2015-09-07 Thread Andreas Pokorny
The mx4 touchscreen driver emits BTN_TOUCH and BTN_TOOL_FINGER key events
on a new contact. Prior to this patch only the BTN_TOUCH event was filtered
out. Now the whole range of BTN_ events for tool types and certain builtin
multi finger gestures are marked as non-key type.

Signed-off-by: Andreas Pokorny 
---
 src/evdev.c  |  10 +++---
 test/touch.c | 110 +++
 2 files changed, 115 insertions(+), 5 deletions(-)

diff --git a/src/evdev.c b/src/evdev.c
index 04df275..3e22aa9 100644
--- a/src/evdev.c
+++ b/src/evdev.c
@@ -557,7 +557,7 @@ evdev_flush_pending_event(struct evdev_device *device, 
uint64_t time)
 static enum evdev_key_type
 get_key_type(uint16_t code)
 {
-   if (code == BTN_TOUCH)
+   if (code >= BTN_DIGI && code <= BTN_TOOL_QUADTAP)
return EVDEV_KEY_TYPE_NONE;
 
if (code >= KEY_ESC && code <= KEY_MICMUTE)
@@ -630,16 +630,16 @@ evdev_process_key(struct evdev_device *device,
if (e->value == 2)
return;
 
-   if (e->code == BTN_TOUCH) {
-   if (!device->is_mt)
+   type = get_key_type(e->code);
+
+   if (type == EVDEV_KEY_TYPE_NONE) {
+   if (e->code == BTN_TOUCH && !device->is_mt)
evdev_process_touch_button(device, time, e->value);
return;
}
 
evdev_flush_pending_event(device, time);
 
-   type = get_key_type(e->code);
-
/* Ignore key release events from the kernel for keys that libinput
 * never got a pressed event for. */
if (e->value == 0) {
diff --git a/test/touch.c b/test/touch.c
index 875d94d..0e7f893 100644
--- a/test/touch.c
+++ b/test/touch.c
@@ -912,6 +912,114 @@ START_TEST(touch_point_no_minor_or_orientation)
 }
 END_TEST
 
+START_TEST(touchscreen_with_btn_tool_finger_on_down)
+{
+   struct libevdev_uinput *uinput;
+   struct libinput *li;
+   struct libinput_device *device;
+   struct libinput_event *event;
+   struct libinput_event_touch *tev;
+   const struct input_absinfo abs[] = {
+   { ABS_X, 0, 1152, 0, 0, 0 },
+   { ABS_Y, 0, 1920, 0, 0, 0 },
+   { ABS_MT_SLOT, 0, 9, 0, 0, 0 },
+   { ABS_MT_TRACKING_ID, 0, 65535, 0, 0, 0 },
+   { ABS_MT_POSITION_X, 0, 1152, 0, 0, 0 },
+   { ABS_MT_POSITION_Y, 0, 1920, 0, 0, 0 },
+   { ABS_MT_TOUCH_MAJOR, 0, 23, 0, 0, 0 },
+   { ABS_MT_TOUCH_MINOR, 0, 23, 0, 0, 0 },
+   { -1, -1, -1, -1, -1, -1 }
+   };
+   const struct input_event input_sequence[] = {
+   { {0}, EV_ABS, ABS_MT_SLOT, 0},
+   { {0}, EV_ABS, ABS_MT_TRACKING_ID, 9},
+   { {0}, EV_KEY, BTN_TOUCH, 1},
+   { {0}, EV_KEY, BTN_TOOL_FINGER, 1},
+   { {0}, EV_ABS, ABS_MT_POSITION_X, 128},
+   { {0}, EV_ABS, ABS_MT_POSITION_Y, 240},
+   { {0}, EV_ABS, ABS_MT_TOUCH_MAJOR, 5},
+   { {0}, EV_ABS, ABS_MT_TOUCH_MINOR, 4},
+   { {0}, EV_SYN, SYN_REPORT, 0},
+   { {0}, EV_ABS, ABS_MT_TOUCH_MAJOR, 6},
+   { {0}, EV_SYN, SYN_REPORT, 0},
+   { {0}, EV_ABS, ABS_MT_TRACKING_ID, -1},
+   { {0}, EV_KEY, BTN_TOUCH, 0},
+   { {0}, EV_KEY, BTN_TOOL_FINGER, 0},
+   { {0}, EV_SYN, SYN_REPORT, 0}
+   };
+   const int num_events = ARRAY_LENGTH(input_sequence);
+   const int width = 1152;
+   const int height = 1920;
+   int x, y, major, minor;
+
+   uinput = litest_create_uinput_abs_device(
+   "test device",
+   NULL, abs,
+   EV_KEY, BTN_TOUCH,
+   EV_KEY, BTN_TOOL_FINGER,
+   INPUT_PROP_MAX, INPUT_PROP_DIRECT,
+   -1, -1);
+
+   li = litest_create_context();
+   device = libinput_path_add_device(li,
+ libevdev_uinput_get_devnode(uinput));
+   ck_assert(device != NULL);
+   device = libinput_device_ref(device);
+   litest_drain_events(li);
+
+   for (int i = 0; i!=num_events; ++i)
+   libevdev_uinput_write_event(uinput,
+   input_sequence[i].type,
+   input_sequence[i].code,
+   input_sequence[i].value);
+
+   litest_wait_for_event(li);
+
+   event = libinput_get_event(li);
+   tev = litest_is_touch_event(event, LIBINPUT_EVENT_TOUCH_DOWN);
+   x = round(libinput_event_touch_get_x_transformed(tev, width));
+   y = round(libinput_event_touch_get_y_transformed(tev, height)),
+   major = round(
+   libinput_event_touch_get_major_transformed(tev, width, height));
+   minor = round(
+   libinput_event_touch_get_minor_transformed(tev, width, height));
+   ck_assert_int_eq(x, 128);
+   ck_assert_int_eq(y, 240);
+   ck_assert_int_