Some tablets send axis values, then EV_SYN, and in the next event the BTN_TOOL_PEN/BTN_TOUCH, etc. For these tablets, the cursor doesn't move as coordinates while not in proximity are ignored.
Buffer coordinates received while out-of-proximity and if we get a proximity event without other coordinates, re-use the last ones received. X.Org Bug 29645 <http://bugs.freedesktop.org/show_bug.cgi?id=29645> Signed-off-by: Peter Hutterer <peter.hutte...@who-t.net> --- src/evdev.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/evdev.h | 1 + 2 files changed, 57 insertions(+), 0 deletions(-) diff --git a/src/evdev.c b/src/evdev.c index 634c174..0ef7170 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -481,6 +481,60 @@ EvdevProcessProximityEvent(InputInfoPtr pInfo, struct input_event *ev) } /** + * Proximity handling is rather weird because of tablet-specific issues. + * Some tablets, notably Wacoms, send a 0/0 coordinate in the same EV_SYN as + * the out-of-proximity notify. We need to ignore those, hence we only + * actually post valuator events when we're in proximity. + * + * Other tablets send the x/y coordinates, then EV_SYN, then the proximity + * event. For those, we need to remember x/y to post it when the proximity + * comes. + * + * If we're not in proximity and we get valuator events, remember that, they + * won't be posted though. If we move into proximity without valuators, use + * the last ones we got and let the rest of the code post them. + */ +static int +EvdevProcessProximityState(InputInfoPtr pInfo) +{ + EvdevPtr pEvdev = pInfo->private; + int prox_state = 0; + int i; + + /* no proximity change in the queue */ + if (!pEvdev->prox) + { + if (pEvdev->abs && !pEvdev->proximity) + pEvdev->abs_prox = pEvdev->abs; + return 0; + } + + for (i = 0; pEvdev->prox && i < pEvdev->num_queue; i++) + { + if (pEvdev->queue[i].type == EV_QUEUE_PROXIMITY) + { + prox_state = pEvdev->queue[i].val; + break; + } + } + + if ((prox_state && !pEvdev->proximity) || + (!prox_state && pEvdev->proximity)) + { + /* We're about to go into/out of proximity but have no abs events + * within the EV_SYN. Use the last coordinates we have. */ + if (!pEvdev->abs && pEvdev->abs_prox) + { + pEvdev->abs = pEvdev->abs_prox; + pEvdev->abs_prox = 0; + } + } + + pEvdev->proximity = prox_state; + return 1; +} + +/** * Take a button input event and process it accordingly. */ static void @@ -732,6 +786,8 @@ EvdevProcessSyncEvent(InputInfoPtr pInfo, struct input_event *ev) int v[MAX_VALUATORS] = {}; EvdevPtr pEvdev = pInfo->private; + EvdevProcessProximityState(pInfo); + EvdevProcessValuators(pInfo, v, &num_v, &first_v); EvdevPostProximityEvents(pInfo, TRUE, num_v, first_v, v); diff --git a/src/evdev.h b/src/evdev.h index 08f3c13..af93d41 100644 --- a/src/evdev.h +++ b/src/evdev.h @@ -133,6 +133,7 @@ typedef struct { int delta[REL_CNT]; unsigned int abs, rel, prox; + unsigned int abs_prox; /* valuators posted while out of prox? */ /* XKB stuff has to be per-device rather than per-driver */ #if GET_ABI_MAJOR(ABI_XINPUT_VERSION) < 5 -- 1.7.2.3 _______________________________________________ xorg-devel@lists.x.org: X.Org development Archives: http://lists.x.org/archives/xorg-devel Info: http://lists.x.org/mailman/listinfo/xorg-devel