[PATCH evdev 7/8] Store per-slot touch state
Benjamin Tissoires
benjamin.tissoires at gmail.com
Wed Jan 9 10:21:21 PST 2013
The previous implementation considers that a new slot means a TouchBegin,
and the deletion of the slot a TouchEnd. However, this is not compliant
with the mt evdev specification as the touch state is given by
ABS_MT_DISTANCE == 0.
Before Win 8 specification, no known multitouch devices present in
proximity events (like the hovering of Wacom stylus). But since this
specification exists, there may be devices exposing ABS_MT_DISTANCE.
The modification here consists in storing the current touch state of
each slot, to be able to detect if we need to forward Begin/End/Update
event by just setting the touch property to true or false.
The benefit of it is that we can now easily add proximity support
and several touch begin/end within the same slot.
Signed-off-by: Benjamin Tissoires <benjamin.tissoires at gmail.com>
---
src/evdev.c | 47 +++++++++++++++++++++++++++++++----------------
src/evdev.h | 8 +++++++-
2 files changed, 38 insertions(+), 17 deletions(-)
diff --git a/src/evdev.c b/src/evdev.c
index 8d7853b..256037c 100644
--- a/src/evdev.c
+++ b/src/evdev.c
@@ -736,21 +736,33 @@ EvdevProcessTouch(InputInfoPtr pInfo)
EvdevPtr pEvdev = pInfo->private;
int type;
int slot_index = last_mt_vals_slot(pEvdev);
+ EvdevMTState *mt_state;
if (slot_index < 0 || !pEvdev->mt_mask)
return;
+ mt_state = &pEvdev->mt_state[slot_index];
+
/* If the ABS_MT_SLOT is the first event we get after EV_SYN, skip this */
if (pEvdev->slot_state == SLOTSTATE_EMPTY)
return;
if (pEvdev->slot_state == SLOTSTATE_CLOSE)
- type = XI_TouchEnd;
+ mt_state->touch = FALSE;
else if (pEvdev->slot_state == SLOTSTATE_OPEN)
- type = XI_TouchBegin;
- else
- type = XI_TouchUpdate;
+ mt_state->touch = TRUE;
+ type = XI_TouchUpdate;
+
+ if (mt_state->touch != mt_state->touch_state) {
+ /* We are getting in/out of touch */
+ if (mt_state->touch)
+ type = XI_TouchBegin;
+ else
+ type = XI_TouchEnd;
+
+ mt_state->touch_state = mt_state->touch;
+ }
EvdevQueueTouchEvent(pInfo, slot_index, pEvdev->mt_mask, type);
@@ -794,6 +806,7 @@ EvdevProcessTouchEvent(InputInfoPtr pInfo, struct input_event *ev)
{
EvdevPtr pEvdev = pInfo->private;
int map;
+ EvdevMTState *mt_state;
if (!EvdevIsMTDevice(pEvdev))
return;
@@ -813,19 +826,21 @@ EvdevProcessTouchEvent(InputInfoPtr pInfo, struct input_event *ev)
return;
}
+ mt_state = &pEvdev->mt_state[slot_index];
+
if (pEvdev->slot_state == SLOTSTATE_EMPTY)
pEvdev->slot_state = SLOTSTATE_UPDATE;
if (ev->code == ABS_MT_TRACKING_ID) {
if (ev->value >= 0) {
pEvdev->slot_state = SLOTSTATE_OPEN;
valuator_mask_copy(pEvdev->mt_mask,
- pEvdev->last_mt_vals[slot_index]);
+ mt_state->last_vals);
} else
pEvdev->slot_state = SLOTSTATE_CLOSE;
} else {
map = pEvdev->axis_map[ev->code];
valuator_mask_set(pEvdev->mt_mask, map, ev->value);
- valuator_mask_set(pEvdev->last_mt_vals[slot_index], map, ev->value);
+ valuator_mask_set(mt_state->last_vals, map, ev->value);
}
}
}
@@ -1098,12 +1113,12 @@ EvdevFreeMasks(EvdevPtr pEvdev)
valuator_mask_free(&pEvdev->prox);
#ifdef MULTITOUCH
valuator_mask_free(&pEvdev->mt_mask);
- if (pEvdev->last_mt_vals)
+ if (pEvdev->mt_state)
{
for (i = 0; i < num_slots(pEvdev); i++)
- valuator_mask_free(&pEvdev->last_mt_vals[i]);
- free(pEvdev->last_mt_vals);
- pEvdev->last_mt_vals = NULL;
+ valuator_mask_free(&pEvdev->mt_state[i].last_vals);
+ free(pEvdev->mt_state);
+ pEvdev->mt_state = NULL;
}
for (i = 0; i < EVDEV_MAXQUEUE; i++)
valuator_mask_free(&pEvdev->queue[i].touchMask);
@@ -1333,17 +1348,17 @@ EvdevAddAbsValuatorClass(DeviceIntPtr device)
goto out;
}
- pEvdev->last_mt_vals = calloc(num_slots(pEvdev), sizeof(ValuatorMask *));
- if (!pEvdev->last_mt_vals) {
+ pEvdev->mt_state = calloc(num_slots(pEvdev), sizeof(EvdevMTState));
+ if (!pEvdev->mt_state) {
xf86IDrvMsg(pInfo, X_ERROR,
- "%s: failed to allocate MT last values mask array.\n",
+ "%s: failed to allocate MT state.\n",
device->name);
goto out;
}
for (i = 0; i < num_slots(pEvdev); i++) {
- pEvdev->last_mt_vals[i] = valuator_mask_new(num_mt_axes_total);
- if (!pEvdev->last_mt_vals[i]) {
+ pEvdev->mt_state[i].last_vals = valuator_mask_new(num_mt_axes_total);
+ if (!pEvdev->mt_state[i].last_vals) {
xf86IDrvMsg(pInfo, X_ERROR,
"%s: failed to allocate MT last values mask.\n",
device->name);
@@ -1439,7 +1454,7 @@ EvdevAddAbsValuatorClass(DeviceIntPtr device)
strerror(errno));
}
for (i = 0; i < num_touches; i++)
- valuator_mask_set(pEvdev->last_mt_vals[i],
+ valuator_mask_set(pEvdev->mt_state[i].last_vals,
pEvdev->axis_map[axis],
mt_request_data[i]);
}
diff --git a/src/evdev.h b/src/evdev.h
index 2901886..6195c79 100644
--- a/src/evdev.h
+++ b/src/evdev.h
@@ -150,6 +150,12 @@ typedef struct {
} EventQueueRec, *EventQueuePtr;
typedef struct {
+ ValuatorMask *last_vals;
+ int touch; /* per-slot incoming touch state */
+ int touch_state; /* per-slot current touch state */
+} EvdevMTState;
+
+typedef struct {
unsigned short id_vendor;
unsigned short id_product;
@@ -163,11 +169,11 @@ typedef struct {
ValuatorMask *old_vals; /* old values for calculating relative motion */
ValuatorMask *prox; /* last values set while not in proximity */
ValuatorMask *mt_mask;
- ValuatorMask **last_mt_vals;
int cur_slot;
enum SlotState slot_state;
#ifdef MULTITOUCH
struct mtdev *mtdev;
+ EvdevMTState *mt_state;
#endif
int flags;
--
1.8.0.2
More information about the xorg-devel
mailing list