libinput: add hold gesture public API and tool support
authorJosé Expósito <jose.exposito89@gmail.com>
Thu, 27 May 2021 17:19:38 +0000 (19:19 +0200)
committerPeter Hutterer <peter.hutterer@who-t.net>
Wed, 9 Jun 2021 01:18:58 +0000 (01:18 +0000)
Add hold gestures to the public API and the private functions to notify them.
Also add hold gestures to debug-events and debug-gui.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Signed-off-by: José Expósito <jose.exposito89@gmail.com>
src/libinput-private.h
src/libinput.c
src/libinput.h
test/litest.c
tools/libinput-debug-events.c
tools/libinput-debug-gui.c

index 8ccd5dcf316752287a7634086e926e42eac8ccfe..8c7b77dd3172585781aa3e4bab8a3f19bcb52acf 100644 (file)
@@ -627,6 +627,17 @@ gesture_notify_pinch_end(struct libinput_device *device,
                         double scale,
                         bool cancelled);
 
+void
+gesture_notify_hold(struct libinput_device *device,
+                   uint64_t time,
+                   int finger_count);
+
+void
+gesture_notify_hold_end(struct libinput_device *device,
+                       uint64_t time,
+                       int finger_count,
+                       bool cancelled);
+
 void
 tablet_notify_axis(struct libinput_device *device,
                   uint64_t time,
index b4164e2d6445818010f1d4a11c931490b56c1a94..092762aab1705b67836462b2513420bb18783981 100644 (file)
@@ -106,6 +106,8 @@ event_type_to_str(enum libinput_event_type type)
        CASE_RETURN_STRING(LIBINPUT_EVENT_GESTURE_PINCH_BEGIN);
        CASE_RETURN_STRING(LIBINPUT_EVENT_GESTURE_PINCH_UPDATE);
        CASE_RETURN_STRING(LIBINPUT_EVENT_GESTURE_PINCH_END);
+       CASE_RETURN_STRING(LIBINPUT_EVENT_GESTURE_HOLD_BEGIN);
+       CASE_RETURN_STRING(LIBINPUT_EVENT_GESTURE_HOLD_END);
        CASE_RETURN_STRING(LIBINPUT_EVENT_SWITCH_TOGGLE);
        case LIBINPUT_EVENT_NONE:
                abort();
@@ -405,7 +407,9 @@ libinput_event_get_gesture_event(struct libinput_event *event)
                           LIBINPUT_EVENT_GESTURE_SWIPE_END,
                           LIBINPUT_EVENT_GESTURE_PINCH_BEGIN,
                           LIBINPUT_EVENT_GESTURE_PINCH_UPDATE,
-                          LIBINPUT_EVENT_GESTURE_PINCH_END);
+                          LIBINPUT_EVENT_GESTURE_PINCH_END,
+                          LIBINPUT_EVENT_GESTURE_HOLD_BEGIN,
+                          LIBINPUT_EVENT_GESTURE_HOLD_END);
 
        return (struct libinput_event_gesture *) event;
 }
@@ -892,7 +896,9 @@ libinput_event_gesture_get_time(struct libinput_event_gesture *event)
                           LIBINPUT_EVENT_GESTURE_PINCH_END,
                           LIBINPUT_EVENT_GESTURE_SWIPE_BEGIN,
                           LIBINPUT_EVENT_GESTURE_SWIPE_UPDATE,
-                          LIBINPUT_EVENT_GESTURE_SWIPE_END);
+                          LIBINPUT_EVENT_GESTURE_SWIPE_END,
+                          LIBINPUT_EVENT_GESTURE_HOLD_BEGIN,
+                          LIBINPUT_EVENT_GESTURE_HOLD_END);
 
        return us2ms(event->time);
 }
@@ -908,7 +914,9 @@ libinput_event_gesture_get_time_usec(struct libinput_event_gesture *event)
                           LIBINPUT_EVENT_GESTURE_PINCH_END,
                           LIBINPUT_EVENT_GESTURE_SWIPE_BEGIN,
                           LIBINPUT_EVENT_GESTURE_SWIPE_UPDATE,
-                          LIBINPUT_EVENT_GESTURE_SWIPE_END);
+                          LIBINPUT_EVENT_GESTURE_SWIPE_END,
+                          LIBINPUT_EVENT_GESTURE_HOLD_BEGIN,
+                          LIBINPUT_EVENT_GESTURE_HOLD_END);
 
        return event->time;
 }
@@ -924,7 +932,9 @@ libinput_event_gesture_get_finger_count(struct libinput_event_gesture *event)
                           LIBINPUT_EVENT_GESTURE_PINCH_END,
                           LIBINPUT_EVENT_GESTURE_SWIPE_BEGIN,
                           LIBINPUT_EVENT_GESTURE_SWIPE_UPDATE,
-                          LIBINPUT_EVENT_GESTURE_SWIPE_END);
+                          LIBINPUT_EVENT_GESTURE_SWIPE_END,
+                          LIBINPUT_EVENT_GESTURE_HOLD_BEGIN,
+                          LIBINPUT_EVENT_GESTURE_HOLD_END);
 
        return event->finger_count;
 }
@@ -936,7 +946,8 @@ libinput_event_gesture_get_cancelled(struct libinput_event_gesture *event)
                           event->base.type,
                           0,
                           LIBINPUT_EVENT_GESTURE_PINCH_END,
-                          LIBINPUT_EVENT_GESTURE_SWIPE_END);
+                          LIBINPUT_EVENT_GESTURE_SWIPE_END,
+                          LIBINPUT_EVENT_GESTURE_HOLD_END);
 
        return event->cancelled;
 }
@@ -2890,6 +2901,29 @@ gesture_notify_pinch_end(struct libinput_device *device,
                       finger_count, cancelled, &zero, &zero, scale, 0.0);
 }
 
+void
+gesture_notify_hold(struct libinput_device *device,
+                   uint64_t time,
+                   int finger_count)
+{
+       const struct normalized_coords zero = { 0.0, 0.0 };
+
+       gesture_notify(device, time, LIBINPUT_EVENT_GESTURE_HOLD_BEGIN,
+                      finger_count, 0, &zero, &zero, 0.0, 0.0);
+}
+
+void
+gesture_notify_hold_end(struct libinput_device *device,
+                       uint64_t time,
+                       int finger_count,
+                       bool cancelled)
+{
+       const struct normalized_coords zero = { 0.0, 0.0 };
+
+       gesture_notify(device, time, LIBINPUT_EVENT_GESTURE_HOLD_END,
+                      finger_count, cancelled, &zero, &zero, 0, 0.0);
+}
+
 void
 switch_notify_toggle(struct libinput_device *device,
                     uint64_t time,
index a15d62720581a5e0fea51bd94e9fa36547257b5c..46b38a4d271040aa1c7b06739688357d86ed248c 100644 (file)
@@ -896,6 +896,11 @@ enum libinput_event_type {
        LIBINPUT_EVENT_GESTURE_PINCH_BEGIN,
        LIBINPUT_EVENT_GESTURE_PINCH_UPDATE,
        LIBINPUT_EVENT_GESTURE_PINCH_END,
+       /**
+        * @since 1.19
+        */
+       LIBINPUT_EVENT_GESTURE_HOLD_BEGIN,
+       LIBINPUT_EVENT_GESTURE_HOLD_END,
 
        /**
         * @since 1.7
index a46324bb31244021378d23528295bc9722f4956b..cd97a51cc1654103a898d9eed5134eeecbe40206 100644 (file)
@@ -3130,6 +3130,12 @@ litest_event_type_str(enum libinput_event_type type)
        case LIBINPUT_EVENT_GESTURE_PINCH_END:
                str = "GESTURE PINCH END";
                break;
+       case LIBINPUT_EVENT_GESTURE_HOLD_BEGIN:
+               str = "GESTURE HOLD BEGIN";
+               break;
+       case LIBINPUT_EVENT_GESTURE_HOLD_END:
+               str = "GESTURE HOLD END";
+               break;
        case LIBINPUT_EVENT_TABLET_TOOL_AXIS:
                str = "TABLET TOOL AXIS";
                break;
index 358bca4824fe741dcee43018474851d8e38f3ae5..9ac2b0c681b603c427db450b20247a25779147c4 100644 (file)
@@ -119,6 +119,12 @@ print_event_header(struct libinput_event *ev)
        case LIBINPUT_EVENT_GESTURE_PINCH_END:
                type = "GESTURE_PINCH_END";
                break;
+       case LIBINPUT_EVENT_GESTURE_HOLD_BEGIN:
+               type = "GESTURE_HOLD_BEGIN";
+               break;
+       case LIBINPUT_EVENT_GESTURE_HOLD_END:
+               type = "GESTURE_HOLD_END";
+               break;
        case LIBINPUT_EVENT_TABLET_TOOL_AXIS:
                type = "TABLET_TOOL_AXIS";
                break;
@@ -657,7 +663,8 @@ print_gesture_event_without_coords(struct libinput_event *ev)
        type = libinput_event_get_type(ev);
 
        if (type == LIBINPUT_EVENT_GESTURE_SWIPE_END ||
-           type == LIBINPUT_EVENT_GESTURE_PINCH_END)
+           type == LIBINPUT_EVENT_GESTURE_PINCH_END ||
+           type == LIBINPUT_EVENT_GESTURE_HOLD_END)
            cancelled = libinput_event_gesture_get_cancelled(t);
 
        print_event_time(libinput_event_gesture_get_time(t));
@@ -879,6 +886,12 @@ handle_and_print_events(struct libinput *li)
                case LIBINPUT_EVENT_GESTURE_PINCH_END:
                        print_gesture_event_without_coords(ev);
                        break;
+               case LIBINPUT_EVENT_GESTURE_HOLD_BEGIN:
+                       print_gesture_event_without_coords(ev);
+                       break;
+               case LIBINPUT_EVENT_GESTURE_HOLD_END:
+                       print_gesture_event_without_coords(ev);
+                       break;
                case LIBINPUT_EVENT_TABLET_TOOL_AXIS:
                        print_tablet_axis_event(ev);
                        break;
index 0cca8870c4f4d2edad6eaa8a0a16f8b2b109de01..1b93bd1d2f42035a207c19ae72d0c0a6629e2b0a 100644 (file)
@@ -130,6 +130,11 @@ struct window {
                double x, y;
        } pinch;
 
+       struct {
+               int nfingers;
+               bool active;
+       } hold;
+
        struct {
                double x, y;
                double x_in, y_in;
@@ -311,19 +316,18 @@ draw_outline:
 static inline void
 draw_gestures(struct window *w, cairo_t *cr)
 {
-       int i;
        int offset;
 
        /* swipe */
        cairo_save(cr);
        cairo_translate(cr, w->swipe.x, w->swipe.y);
-       for (i = 0; i < w->swipe.nfingers; i++) {
+       for (int i = 0; i < w->swipe.nfingers; i++) {
                cairo_set_source_rgb(cr, .8, .8, .4);
                cairo_arc(cr, (i - 2) * 40, 0, 20, 0, 2 * M_PI);
                cairo_fill(cr);
        }
 
-       for (i = 0; i < 4; i++) { /* 4 fg max */
+       for (int i = 0; i < 4; i++) { /* 4 fg max */
                cairo_set_source_rgb(cr, 0, 0, 0);
                cairo_arc(cr, (i - 2) * 40, 0, 20, 0, 2 * M_PI);
                cairo_stroke(cr);
@@ -349,6 +353,29 @@ draw_gestures(struct window *w, cairo_t *cr)
        cairo_stroke(cr);
 
        cairo_restore(cr);
+
+       /* hold */
+       cairo_save(cr);
+       cairo_translate(cr, w->width/2, w->height/2 + 100);
+
+       for (int i = 4; i > 0; i--) { /* 4 fg max */
+               double r, g, b, hold_alpha;
+
+               r = .4 + .2 * (i % 2);
+               g = .2;
+               b = .2;
+               hold_alpha = (w->hold.active && i <= w->hold.nfingers) ? 1 : .5;
+
+               cairo_set_source_rgba(cr, r, g, b, hold_alpha);
+               cairo_arc(cr, 0, 0, 20 * i, 0, 2 * M_PI);
+               cairo_fill(cr);
+
+               cairo_set_source_rgba(cr, 0, 0, 0, hold_alpha);
+               cairo_arc(cr, 0, 0, 20 * i, 0, 2 * M_PI);
+               cairo_stroke(cr);
+       }
+
+       cairo_restore(cr);
 }
 
 static inline void
@@ -1311,6 +1338,28 @@ handle_event_pinch(struct libinput_event *ev, struct window *w)
        }
 }
 
+static void
+handle_event_hold(struct libinput_event *ev, struct window *w)
+{
+       struct libinput_event_gesture *g = libinput_event_get_gesture_event(ev);
+       int nfingers;
+
+       nfingers = libinput_event_gesture_get_finger_count(g);
+
+       switch (libinput_event_get_type(ev)) {
+       case LIBINPUT_EVENT_GESTURE_HOLD_BEGIN:
+               w->hold.nfingers = nfingers;
+               w->hold.active = true;
+               break;
+       case LIBINPUT_EVENT_GESTURE_HOLD_END:
+               w->hold.nfingers = nfingers;
+               w->hold.active = false;
+               break;
+       default:
+               abort();
+       }
+}
+
 static void
 handle_event_tablet(struct libinput_event *ev, struct window *w)
 {
@@ -1485,6 +1534,10 @@ handle_event_libinput(GIOChannel *source, GIOCondition condition, gpointer data)
                case LIBINPUT_EVENT_GESTURE_PINCH_END:
                        handle_event_pinch(ev, w);
                        break;
+               case LIBINPUT_EVENT_GESTURE_HOLD_BEGIN:
+               case LIBINPUT_EVENT_GESTURE_HOLD_END:
+                       handle_event_hold(ev, w);
+                       break;
                case LIBINPUT_EVENT_TABLET_TOOL_AXIS:
                case LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY:
                case LIBINPUT_EVENT_TABLET_TOOL_TIP: