File u_02-Add-delay-between-button-press-and-release-to-kiosk-mode.patch of Package xf86-input-evdev

From: Egbert Eich <eich@linux-0ems.fritz.box>
Date: Mon Apr 18 23:26:25 2016 +0200
Subject: [PATCH 2/2]Add delay between button press and release to kiosk mode.
Patch-mainline: to be upstreamed
References: FATE#320263
Signed-off-by: Egbert Eich <eich@suse.com>

This allows to notice the visual feedback of a UI on a button
press.

Signed-off-by: Egbert Eich <eich@linux-0ems.fritz.box>
---
 include/evdev-properties.h |   1 +
 man/evdev.man              |  15 ++++
 src/evdev.c                |   4 +
 src/evdev.h                |  11 ++-
 src/kioskTouch.c           | 201 ++++++++++++++++++++++++++++++++++++++++++---
 5 files changed, 220 insertions(+), 12 deletions(-)

diff --git a/include/evdev-properties.h b/include/evdev-properties.h
index 29f2bd9..9f17b66 100644
--- a/include/evdev-properties.h
+++ b/include/evdev-properties.h
@@ -94,4 +94,5 @@
 /* Kiosk Touch mode */
 #define EVDEV_PROP_KIOSK_TOUCH "Evdev Kiosk Touch Mode"
 #define EVDEV_PROP_KIOSK_BUTTON "Evdev Kiosk Touch Button"
+#define EVDEV_PROP_KIOSK_BUTTON_DELAY "Evdev Kiosk Touch Button Delay"
 #endif
diff --git a/man/evdev.man b/man/evdev.man
index 404a88d..a9f67a0 100644
--- a/man/evdev.man
+++ b/man/evdev.man
@@ -258,6 +258,18 @@ Specifies the Kiosk Touch button number to use. Button
 range: 0-255.
 Default: "0". Property:
 "Evdev Kiosk Touch Button".
+.TP 7
+.BI "Option \*qKioskTouchButtonDelay\*q \*q" "N" \*q
+Specifies the delay between a button press and release event in ms. A delay
+will help to notice a visual feedback on a button press event. During the
+delay no motion events are generated. Instead the final location is stored
+and a motion event to this location is sent after the button release has been
+sent at the end of the delay period.
+Button
+.I N
+range: 0-65535.
+Default: "0". Property:
+"Evdev Kiosk Touch Button Delay".
 
 .SH SUPPORTED PROPERTIES
 The following properties are provided by the
@@ -307,6 +319,9 @@ value.
 .TP 7
 .BI "Evdev Kiosk Touch Button"
 1 8-bit positive value.
+.TP 7
+.BI "Evdev Kiosk Touch Button Delay"
+1 16-bit positive value.
 
 .SH AUTHORS
 Kristian Høgsberg, Peter Hutterer
diff --git a/src/evdev.c b/src/evdev.c
index a72a866..ab0ed31 100644
--- a/src/evdev.c
+++ b/src/evdev.c
@@ -482,6 +482,7 @@ EvdevProcessValuators(InputInfoPtr pInfo)
         EvdevSwapAbsValuators(pEvdev, pEvdev->abs_vals);
         EvdevApplyCalibration(pEvdev, pEvdev->abs_vals);
         Evdev3BEmuProcessAbsMotion(pInfo, pEvdev->abs_vals);
+	EvdevKioskTouchMotionEvents(pInfo, pEvdev->abs_vals);
     }
 }
 
@@ -1966,6 +1967,7 @@ EvdevOn(DeviceIntPtr device)
     xf86AddEnabledDevice(pInfo);
     EvdevMBEmuOn(pInfo);
     Evdev3BEmuOn(pInfo);
+    EvdevKioskTouchOn(pInfo);
     pEvdev->flags |= EVDEV_INITIALIZED;
     device->public.on = TRUE;
 
@@ -1995,6 +1997,7 @@ EvdevProc(DeviceIntPtr device, int what)
         {
             EvdevMBEmuFinalize(pInfo);
             Evdev3BEmuFinalize(pInfo);
+            EvdevKioskTouchFinalize(pInfo);
         }
         if (pInfo->fd != -1)
         {
@@ -2011,6 +2014,7 @@ EvdevProc(DeviceIntPtr device, int what)
 	xf86IDrvMsg(pInfo, X_INFO, "Close\n");
         EvdevCloseDevice(pInfo);
         EvdevFreeMasks(pEvdev);
+	EvdevKioskTouchClose(pInfo);
         pEvdev->min_maj = 0;
 	break;
 
diff --git a/src/evdev.h b/src/evdev.h
index 27c1cb2..4a01e37 100644
--- a/src/evdev.h
+++ b/src/evdev.h
@@ -225,7 +225,12 @@ typedef struct {
         /* 0: 0ff, 1: click on touch, 2: click on release */
         unsigned int        button_queued;
         unsigned int        button;
+        unsigned int        delay;
+        unsigned int        delay_queued;
         unsigned int        state;
+        int                 old_v[2];
+        ValuatorMask       *vals;
+        Time                expires;
     } kioskTouch;
 
     /* run-time calibration */
@@ -303,7 +308,11 @@ void EvdevAppleInitProperty(DeviceIntPtr);
 
 /* Kiosk Touch */
 void EvdevKioskTouchPreInit(InputInfoPtr pInfo);
-BOOL EvdevKioskTouchFilterButton(InputInfoPtr pInfo, unsigned int button, int value);
 void EvdevKioskTouchInitProperty(DeviceIntPtr);
+BOOL EvdevKioskTouchFilterButton(InputInfoPtr pInfo, unsigned int button, int value);
 BOOL EvdevKioskTouchFilterTouch(EvdevPtr pEvdev);
+void EvdevKioskTouchOn(InputInfoPtr pInfo);
+void EvdevKioskTouchFinalize(InputInfoPtr pInfo);
+void EvdevKioskTouchMotionEvents(InputInfoPtr pInfo, ValuatorMask *vals);
+void EvdevKioskTouchClose(InputInfoPtr pInfo);
 #endif
diff --git a/src/kioskTouch.c b/src/kioskTouch.c
index d32f386..f0dd3cb 100644
--- a/src/kioskTouch.c
+++ b/src/kioskTouch.c
@@ -42,8 +42,11 @@
 
 static Atom prop_ktouch        = 0; /* Kiosk touch emulation on/off property */
 static Atom prop_ktouch_button = 0; /* Kiosk touch emulation button property */
+static Atom prop_ktouch_button_delay = 0; /* Kiosk touch emulation button delay property */
 
 #define KTOUCH_STATE_ACTIVE 1U << 0
+#define KTOUCH_STATE_DELAY 1U << 1
+#define KTOUCH_STATE_DELAY_MOTION 1U << 2
 
 void
 EvdevKioskTouchPreInit(InputInfoPtr pInfo)
@@ -75,18 +78,21 @@ EvdevKioskTouchPreInit(InputInfoPtr pInfo)
          val = 0;
     }
     pEvdev->kioskTouch.button = pEvdev->kioskTouch.button_queued = val;
+    val = xf86SetIntOption(pInfo->options, "KioskTouchButtonDelay", 0);
+    pEvdev->kioskTouch.delay = pEvdev->kioskTouch.delay_queued = val;
     pEvdev->kioskTouch.state = 0;
-    xf86Msg(X_INFO, "%s: KioskTouchpad mode initialized to %s - button: %d\n",
+    xf86Msg(X_INFO, "%s: KioskTouchpad mode initialized to %s - button: %d delay: %d\n",
             pInfo->name, (pEvdev->kioskTouch.mode == 0) ? "disabled" :
             (pEvdev->kioskTouch.mode == 1 ? "click-on-touch" : "click-on-release"),
-            pEvdev->kioskTouch.button);
+            pEvdev->kioskTouch.button, pEvdev->kioskTouch.delay);
 }
 
 static void
 EvdevKioskTouchSwitchQueued(EvdevPtr pEvdev)
 {
     if (pEvdev->kioskTouch.mode != pEvdev->kioskTouch.mode_queued ||
-        pEvdev->kioskTouch.button != pEvdev->kioskTouch.button_queued) {
+        pEvdev->kioskTouch.button != pEvdev->kioskTouch.button_queued ||
+        pEvdev->kioskTouch.delay != pEvdev->kioskTouch.delay_queued) {
         if (pEvdev->kioskTouch.state & KTOUCH_STATE_ACTIVE)
             return;
         if (pEvdev->mt_mask) {
@@ -98,6 +104,7 @@ EvdevKioskTouchSwitchQueued(EvdevPtr pEvdev)
         }
         pEvdev->kioskTouch.mode = pEvdev->kioskTouch.mode_queued;
         pEvdev->kioskTouch.button = pEvdev->kioskTouch.button_queued;
+        pEvdev->kioskTouch.delay = pEvdev->kioskTouch.delay_queued;
     }
 }
 
@@ -108,6 +115,33 @@ EvdevKioskTouchFilterTouch(EvdevPtr pEvdev)
     return (pEvdev->kioskTouch.mode > 0) ? TRUE : FALSE;
 }
 
+static BOOL
+EvdevKioskTouchStopButtonTimer(InputInfoPtr pInfo, BOOL queue)
+{
+    EvdevPtr     pEvdev = (EvdevPtr)pInfo->private;
+
+    if ((pEvdev->kioskTouch.state & KTOUCH_STATE_DELAY) == 0)
+        return FALSE;
+
+    pEvdev->kioskTouch.state &= ~KTOUCH_STATE_DELAY;
+    if (queue) {
+        if (pEvdev->kioskTouch.state & KTOUCH_STATE_DELAY_MOTION) {
+            EvdevPostButtonEvent(pInfo, pEvdev->kioskTouch.button, BUTTON_RELEASE);
+            valuator_mask_copy(pEvdev->abs_vals, pEvdev->kioskTouch.vals);
+            valuator_mask_zero(pEvdev->kioskTouch.vals);
+        } else
+            EvdevQueueButtonEvent(pInfo, pEvdev->kioskTouch.button, 0);
+    } else {
+        EvdevPostButtonEvent(pInfo, pEvdev->kioskTouch.button, BUTTON_RELEASE);
+        if (pEvdev->kioskTouch.state & KTOUCH_STATE_DELAY_MOTION) {
+            xf86PostMotionEventM(pInfo->dev, Absolute, pEvdev->kioskTouch.vals);
+            valuator_mask_zero(pEvdev->kioskTouch.vals);
+        }
+    }
+    pEvdev->kioskTouch.state &= ~KTOUCH_STATE_DELAY_MOTION;
+    return TRUE;
+}
+
 BOOL
 EvdevKioskTouchFilterButton(InputInfoPtr pInfo, unsigned int button, int value)
 {
@@ -118,28 +152,46 @@ EvdevKioskTouchFilterButton(InputInfoPtr pInfo, unsigned int button, int value)
         if (value == 1)
             pEvdev->kioskTouch.state = KTOUCH_STATE_ACTIVE;
         else
-            pEvdev->kioskTouch.state = 0;
+            pEvdev->kioskTouch.state &= ~KTOUCH_STATE_ACTIVE;
         switch (pEvdev->kioskTouch.mode) {
         case 0:
-            DEBUG((ErrorF("%s: mode 1 button %d value %d\n", \
+            DEBUG((ErrorF("%s: mode 0 button %d value %d\n", \
                           __func__, button, value)))
             return FALSE;
         case 1:
             if (value == 1) {
-                DEBUG((ErrorF("%s: Sending ButtonDown/ButtonUp\n",__func__)))
-                EvdevQueueButtonClicks(pInfo, button, 1);
+                DEBUG((ErrorF("%s: Sending ButtonDown\n",__func__)))
+                EvdevQueueButtonEvent(pInfo, button, 1);
+                if (pEvdev->kioskTouch.delay > 0) {
+                    pEvdev->kioskTouch.state |= KTOUCH_STATE_DELAY;
+                    pEvdev->kioskTouch.expires = GetTimeInMillis ()
+                        + pEvdev->kioskTouch.delay;
+                } else {
+                    DEBUG((ErrorF("%s: Sending ButtonUp\n",__func__)));
+                    EvdevQueueButtonEvent(pInfo, button, 0);
+                }
             } else if (value == 0) {
+                DEBUG((ErrorF("%s: EvdevKioskTouchFilterButton: Filter Button UP\n",__func__)));
+                if (pEvdev->kioskTouch.state & KTOUCH_STATE_DELAY)
+                    EvdevKioskTouchStopButtonTimer(pInfo, TRUE);
                 pEvdev->kioskTouch.state = 0;
             }
             return TRUE;
         case 2:
             DEBUG((ErrorF("%s: mode 2 button %d value %d\n", \
-                          __func__, button, value)))
-            if (value == 1)
+                          __func__, button, value)));
+            if (value == 1) {
+                EvdevKioskTouchStopButtonTimer(pInfo, TRUE);
                 return TRUE;
-            else if (value == 0) {
-                DEBUG((ErrorF("%s: Sending ButtonDown\n",__func__)))
+            } else if (value == 0) {
                 EvdevQueueButtonEvent(pInfo, button, 1);
+                if (pEvdev->kioskTouch.delay > 0) {
+                    pEvdev->kioskTouch.state |= KTOUCH_STATE_DELAY;
+                    pEvdev->kioskTouch.expires = GetTimeInMillis ()
+                        + pEvdev->kioskTouch.delay;
+                    return TRUE;
+                } else
+                    DEBUG((ErrorF("%s: Sending ButtonDown\n",__func__)));
            }
             return FALSE;
         default:
@@ -150,6 +202,104 @@ EvdevKioskTouchFilterButton(InputInfoPtr pInfo, unsigned int button, int value)
     return FALSE;
 }
 
+void EvdevKioskTouchMotionEvents(InputInfoPtr pInfo, ValuatorMask *vals)
+{
+    EvdevPtr pEvdev = (EvdevPtr)pInfo->private;
+
+    if (pEvdev->kioskTouch.mode == 1) {
+        int val;
+        if ((pEvdev->kioskTouch.state & KTOUCH_STATE_DELAY_MOTION) == 0) {
+            valuator_mask_fetch(vals, 0, &pEvdev->kioskTouch.old_v[0]);
+            valuator_mask_fetch(vals, 1, &pEvdev->kioskTouch.old_v[1]);
+        }
+        if (pEvdev->kioskTouch.state & KTOUCH_STATE_DELAY) {
+            if (valuator_mask_fetch(vals, 0, &val)) {
+                valuator_mask_set(pEvdev->kioskTouch.vals, 0, val);
+                valuator_mask_set(vals, 0, pEvdev->kioskTouch.old_v[0]);
+            }
+            if (valuator_mask_fetch(vals, 1, &val)) {
+                valuator_mask_set(pEvdev->kioskTouch.vals, 1, val);
+                valuator_mask_set(vals, 1, pEvdev->kioskTouch.old_v[1]);
+            }
+            pEvdev->kioskTouch.state |= KTOUCH_STATE_DELAY_MOTION;
+        } else {
+            valuator_mask_fetch(vals, 0, &pEvdev->kioskTouch.old_v[0]);
+            valuator_mask_fetch(vals, 1, &pEvdev->kioskTouch.old_v[1]);
+        }
+    }
+}
+
+static void
+EvdevKioskTouchWakeupHandler(pointer data,
+                             int i,
+                             pointer LastSelectMask)
+{
+    InputInfoPtr pInfo = (InputInfoPtr)data;
+    EvdevPtr     pEvdev = (EvdevPtr)pInfo->private;
+    int ms;
+
+    if (pEvdev->kioskTouch.state & KTOUCH_STATE_DELAY) {
+        ms = pEvdev->kioskTouch.expires - GetTimeInMillis();
+        if (ms <= 0) {
+            int        sigstate;
+
+            sigstate = xf86BlockSIGIO ();
+            pEvdev->kioskTouch.state &= ~KTOUCH_STATE_DELAY;
+            DEBUG((ErrorF("Delayed ButtonUP\n")));
+            EvdevPostButtonEvent(pInfo, pEvdev->kioskTouch.button, BUTTON_RELEASE);
+            if (pEvdev->kioskTouch.state & KTOUCH_STATE_DELAY_MOTION) {
+                xf86PostMotionEventM(pInfo->dev, Absolute, pEvdev->kioskTouch.vals);
+                valuator_mask_zero(pEvdev->kioskTouch.vals);
+                pEvdev->kioskTouch.state &= ~KTOUCH_STATE_DELAY_MOTION;
+            }
+            xf86UnblockSIGIO (sigstate);
+        }
+    }
+}
+
+static void
+EvdevKioskTouchBlockHandler(pointer data,
+                            struct timeval **waitTime,
+                            pointer LastSelectMask)
+{
+    InputInfoPtr pInfo = (InputInfoPtr)data;
+    EvdevPtr     pEvdev = (EvdevPtr)pInfo->private;
+    int ms;
+
+    if (pEvdev->kioskTouch.state & KTOUCH_STATE_DELAY) {
+        ms = pEvdev->kioskTouch.expires - GetTimeInMillis ();
+        if (ms <= 0)
+            ms = 0;
+        AdjustWaitForDelay (waitTime, ms);
+    }
+}
+
+void
+EvdevKioskTouchOn(InputInfoPtr pInfo)
+{
+    EvdevPtr     pEvdev = (EvdevPtr)pInfo->private;
+
+    if (pEvdev->kioskTouch.mode == -1)
+        return;
+
+    RegisterBlockAndWakeupHandlers (EvdevKioskTouchBlockHandler,
+                                    EvdevKioskTouchWakeupHandler,
+                                    (pointer)pInfo);
+}
+
+void
+EvdevKioskTouchFinalize(InputInfoPtr pInfo)
+{
+    EvdevPtr     pEvdev = (EvdevPtr)pInfo->private;
+
+    if (pEvdev->kioskTouch.mode == -1)
+        return;
+
+    RemoveBlockAndWakeupHandlers (EvdevKioskTouchBlockHandler,
+                                  EvdevKioskTouchWakeupHandler,
+                                  (pointer)pInfo);
+}
+
 static int
 EvdevKioskTouchSetProperty(DeviceIntPtr dev, Atom atom, XIPropertyValuePtr val,
                            BOOL checkonly)
@@ -171,6 +321,13 @@ EvdevKioskTouchSetProperty(DeviceIntPtr dev, Atom atom, XIPropertyValuePtr val,
 
         if (!checkonly)
             pEvdev->kioskTouch.button_queued = *((unsigned char*)val->data);
+    } else if (atom == prop_ktouch_button_delay) {
+
+        if (val->format != 16 || val->size != 1 || val->type != XA_INTEGER)
+            return BadMatch;
+
+        if (!checkonly)
+            pEvdev->kioskTouch.delay_queued = *((CARD16*)val->data);
     }
 
     return Success;
@@ -183,10 +340,14 @@ EvdevKioskTouchInitProperty(DeviceIntPtr dev)
     EvdevPtr     pEvdev = pInfo->private;
     int          rc;
 
+    /* This doesn't really belong to property handling, however it is convenient to do
+     * here and avoids another function to be called */
     if (pEvdev->mt_mask && !libevdev_has_event_code(pEvdev->dev, EV_KEY, BTN_TOUCH)) {
         xf86Msg(X_WARNING, "%s: MultiTouch device has no BTN_TOUCH event: "
                 "no Kiosk Mode support\n", pInfo->name);
         pEvdev->kioskTouch.mode = -1;
+    } else {
+        pEvdev->kioskTouch.vals = valuator_mask_new(2);
     }
 
     if (pEvdev->kioskTouch.mode < 0)
@@ -211,5 +372,23 @@ EvdevKioskTouchInitProperty(DeviceIntPtr dev)
         return;
     XISetDevicePropertyDeletable(dev, prop_ktouch_button, FALSE);
 
+    prop_ktouch_button_delay =
+        MakeAtom(EVDEV_PROP_KIOSK_BUTTON_DELAY, strlen(EVDEV_PROP_KIOSK_BUTTON_DELAY), TRUE);
+    rc = XIChangeDeviceProperty(dev, prop_ktouch_button_delay, XA_INTEGER, 16,
+                                PropModeReplace, 1,
+                                &pEvdev->kioskTouch.delay,
+                                FALSE);
+    if (rc != Success)
+        return;
+    XISetDevicePropertyDeletable(dev, prop_ktouch_button_delay, FALSE);
+
     XIRegisterPropertyHandler(dev, EvdevKioskTouchSetProperty, NULL, NULL);
 }
+
+void
+EvdevKioskTouchClose(InputInfoPtr pInfo)
+{
+    EvdevPtr     pEvdev = pInfo->private;
+
+    valuator_mask_free(&pEvdev->kioskTouch.vals);
+}
openSUSE Build Service is sponsored by