touchscreen: Add flick gesture detector

rockbox-gerrit-noreply--- via rockbox-cvs <[email protected]>
Newsgroups gmane.comp.systems.archos.rockbox.cvs
Message-ID <[email protected]>
commit 814747492c0bc8dfb6a8ce196e338b12929b3d53
Author: Aidan MacDonald <[email protected]>
Date:   Tue Jul 12 23:21:56 2022 +0100

    touchscreen: Add flick gesture detector
    
    Add a low-overhead detector for flick gestures, which are quick
    swiping motions from the screen edges.
    
    Change-Id: I3ef2dad328fdf566923575d437376e100a2ab8df

diff --git a/apps/gesture.c b/apps/gesture.c
index 752f007896..c12d3b7593 100644
--- a/apps/gesture.c
+++ b/apps/gesture.c
@@ -180,3 +180,59 @@ bool gesture_vel_get(struct gesture_vel *gv, int *xvel, int *yvel)
 
     return gv->cnt >= ARRAYLEN(gv->xsamp);
 }
+
+/*
+ * flick detector
+ */
+
+int gesture_flick_get_in_vp(const struct gesture_event *gevt,
+                            const struct viewport *vp)
+{
+    const int vp_height = vp ? vp->height : LCD_HEIGHT;
+    const int vp_width = vp ? vp->width : LCD_WIDTH;
+
+    /* margin at edge where flicks must originate */
+    const int margin = touchscreen_get_scroll_threshold() * 2;
+
+    /* minimum distance from edge before a flick is reported */
+    const int x_dist = 1 + vp_width/4;
+    const int y_dist = 1 + vp_height/4;
+
+    /* a flick only triggers if the velocity along the main axis
+     * exceeds the minimum and the velocity on the other axis is
+     * below the maximum */
+    const int xv_min = 2*vp_width;
+    const int xv_max = vp_width;
+    const int yv_min = 2*vp_height;
+    const int yv_max = vp_height;
+
+    /* a flick is only detected if it occurs within this timeout */
+    const long timeout = HZ/2;
+
+    long dt = gevt->last_tick - gevt->start_tick;
+    if (dt <= 0 || dt > timeout)
+        return GESTURE_FLICK_NONE;
+
+    int xvel = (gevt->x - gevt->ox) * HZ / dt;
+    int yvel = (gevt->y - gevt->oy) * HZ / dt;
+
+    if (gevt->ox < margin && gevt->x >= x_dist &&
+        xvel >= xv_min && abs(yvel) <= yv_max)
+        return GESTURE_FLICK_LEFT;
+
+    if (gevt->ox >= LCD_WIDTH - margin &&
+        gevt->x < LCD_WIDTH - x_dist &&
+        xvel <= -xv_min && abs(yvel) <= yv_max)
+        return GESTURE_FLICK_RIGHT;
+
+    if (gevt->oy < margin && gevt->y >= y_dist &&
+        yvel >= yv_min && abs(xvel) <= xv_max)
+        return GESTURE_FLICK_TOP;
+
+    if (gevt->oy >= LCD_HEIGHT - margin &&
+        gevt->y < LCD_HEIGHT - y_dist &&
+        yvel <= -yv_min && abs(xvel) < xv_max)
+        return GESTURE_FLICK_BOTTOM;
+
+    return GESTURE_FLICK_NONE;
+}
diff --git a/apps/gesture.h b/apps/gesture.h
index a4fb5428dc..948d037d1f 100644
--- a/apps/gesture.h
+++ b/apps/gesture.h
@@ -133,4 +133,24 @@ void gesture_vel_reset(struct gesture_vel *gv);
 void gesture_vel_process(struct gesture_vel *gv, const struct touchevent *ev);
 bool gesture_vel_get(struct gesture_vel *gv, int *xvel, int *yvel);
 
+/* Flick detection */
+enum gesture_flick_id
+{
+    /* The enum refers to originating edge: GESTURE_FLICK_LEFT
+     * means a flick from the left edge moving rightward. */
+    GESTURE_FLICK_NONE = 0,
+    GESTURE_FLICK_TOP,
+    GESTURE_FLICK_BOTTOM,
+    GESTURE_FLICK_LEFT,
+    GESTURE_FLICK_RIGHT,
+};
+
+int gesture_flick_get_in_vp(const struct gesture_event *gevt,
+                            const struct viewport *vp);
+
+static inline int gesture_flick_get(const struct gesture_event *gevt)
+{
+    return gesture_flick_get_in_vp(gevt, NULL);
+}
+
 #endif /* _GESTURE_H_ */
-- 
rockbox-cvs mailing list
[email protected]
https://lists.haxx.se/mailman/listinfo/rockbox-cvs
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.