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