Reviewed-by: Chris Bagwell <[email protected]> I'm not up to speed with queuing in evdev driver. Mostly I was concentrating EvdevProcessProximityState() and looked like it covers all cases.
Chris On Tue, Oct 12, 2010 at 8:44 PM, Peter Hutterer <[email protected]> wrote: > When one of the tools comes into proximity, queue up a proximity event and > send it accordingly. > > Includes special handling for tablets that do not send axes with tools > (#29645) > > 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 <[email protected]> > --- > As Benjamin pointed out, patch 2/3 of the previous set was incorrect by > itself (rebase -i got the better of me). Because I can't be bothered to > untangle the two, fix up a commit just to undo half of it in the next one > anyway, I just squashed the two together. > > src/evdev.c | 118 > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- > src/evdev.h | 5 ++- > 2 files changed, 121 insertions(+), 2 deletions(-) > > diff --git a/src/evdev.c b/src/evdev.c > index 9e1fb10..0ef7170 100644 > --- a/src/evdev.c > +++ b/src/evdev.c > @@ -322,7 +322,18 @@ EvdevQueueButtonEvent(InputInfoPtr pInfo, int button, > int value) > pQueue->key = button; > pQueue->val = value; > } > +} > > +void > +EvdevQueueProximityEvent(InputInfoPtr pInfo, int value) > +{ > + EventQueuePtr pQueue; > + if ((pQueue = EvdevNextInQueue(pInfo))) > + { > + pQueue->type = EV_QUEUE_PROXIMITY; > + pQueue->key = 0; > + pQueue->val = value; > + } > } > > /** > @@ -459,6 +470,70 @@ EvdevProcessValuators(InputInfoPtr pInfo, int > v[MAX_VALUATORS], int *num_v, > } > } > > +static void > +EvdevProcessProximityEvent(InputInfoPtr pInfo, struct input_event *ev) > +{ > + EvdevPtr pEvdev = pInfo->private; > + > + pEvdev->prox = 1; > + > + EvdevQueueProximityEvent(pInfo, ev->value); > +} > + > +/** > + * 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. > */ > @@ -583,6 +658,7 @@ EvdevProcessKeyEvent(InputInfoPtr pInfo, struct > input_event *ev) > return; > > switch (ev->code) { > + /* keep this list in sync with InitProximityClassDeviceStruct */ > case BTN_TOOL_PEN: > case BTN_TOOL_RUBBER: > case BTN_TOOL_BRUSH: > @@ -591,7 +667,7 @@ EvdevProcessKeyEvent(InputInfoPtr pInfo, struct > input_event *ev) > case BTN_TOOL_FINGER: > case BTN_TOOL_MOUSE: > case BTN_TOOL_LENS: > - pEvdev->proximity = value ? ev->code : 0; > + EvdevProcessProximityEvent(pInfo, ev); > break; > > case BTN_TOUCH: > @@ -645,6 +721,27 @@ EvdevPostAbsoluteMotionEvents(InputInfoPtr pInfo, int > num_v, int first_v, > } > } > > +static void > +EvdevPostProximityEvents(InputInfoPtr pInfo, int which, int num_v, int > first_v, > + int v[MAX_VALUATORS]) > +{ > + int i; > + EvdevPtr pEvdev = pInfo->private; > + > + for (i = 0; pEvdev->prox && i < pEvdev->num_queue; i++) { > + switch (pEvdev->queue[i].type) { > + case EV_QUEUE_KEY: > + case EV_QUEUE_BTN: > + break; > + case EV_QUEUE_PROXIMITY: > + if (pEvdev->queue[i].val == which) > + xf86PostProximityEventP(pInfo->dev, which, first_v, > num_v, > + v + first_v); > + break; > + } > + } > +} > + > /** > * Post the queued key/button events. > */ > @@ -672,6 +769,8 @@ static void EvdevPostQueuedEvents(InputInfoPtr pInfo, int > num_v, int first_v, > xf86PostButtonEvent(pInfo->dev, 0, pEvdev->queue[i].key, > pEvdev->queue[i].val, 0, 0); > break; > + case EV_QUEUE_PROXIMITY: > + break; > } > } > } > @@ -687,17 +786,23 @@ 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); > EvdevPostRelativeMotionEvents(pInfo, num_v, first_v, v); > EvdevPostAbsoluteMotionEvents(pInfo, num_v, first_v, v); > EvdevPostQueuedEvents(pInfo, num_v, first_v, v); > + EvdevPostProximityEvents(pInfo, FALSE, num_v, first_v, v); > > memset(pEvdev->delta, 0, sizeof(pEvdev->delta)); > memset(pEvdev->queue, 0, sizeof(pEvdev->queue)); > pEvdev->num_queue = 0; > pEvdev->abs = 0; > pEvdev->rel = 0; > + pEvdev->prox = 0; > + > } > > /** > @@ -1226,6 +1331,17 @@ EvdevAddAbsClass(DeviceIntPtr device) > > free(atoms); > > + /* keep this list in sync with EvdevProcessKeyEvent */ > + if (TestBit(BTN_TOOL_PEN, pEvdev->key_bitmask) || > + TestBit(BTN_TOOL_RUBBER, pEvdev->key_bitmask) || > + TestBit(BTN_TOOL_BRUSH, pEvdev->key_bitmask) || > + TestBit(BTN_TOOL_PENCIL, pEvdev->key_bitmask) || > + TestBit(BTN_TOOL_AIRBRUSH, pEvdev->key_bitmask) || > + TestBit(BTN_TOOL_FINGER, pEvdev->key_bitmask) || > + TestBit(BTN_TOOL_MOUSE, pEvdev->key_bitmask) || > + TestBit(BTN_TOOL_LENS, pEvdev->key_bitmask)) > + InitProximityClassDeviceStruct(device); > + > if (!InitPtrFeedbackClassDeviceStruct(device, EvdevPtrCtrlProc)) > return !Success; > > diff --git a/src/evdev.h b/src/evdev.h > index b382670..af93d41 100644 > --- a/src/evdev.h > +++ b/src/evdev.h > @@ -109,6 +109,7 @@ typedef struct { > enum { > EV_QUEUE_KEY, /* xf86PostKeyboardEvent() */ > EV_QUEUE_BTN, /* xf86PostButtonEvent() */ > + EV_QUEUE_PROXIMITY, /* xf86PostProximityEvent() */ > } type; > int key; /* May be either a key code or button number. */ > int val; /* State of the key/button; pressed or released. */ > @@ -131,7 +132,8 @@ typedef struct { > BOOL invert_y; > > int delta[REL_CNT]; > - unsigned int abs, rel; > + 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 > @@ -198,6 +200,7 @@ typedef struct { > /* Event posting functions */ > void EvdevQueueKbdEvent(InputInfoPtr pInfo, struct input_event *ev, int > value); > void EvdevQueueButtonEvent(InputInfoPtr pInfo, int button, int value); > +void EvdevQueueProximityEvent(InputInfoPtr pInfo, int value); > void EvdevPostButtonEvent(InputInfoPtr pInfo, int button, int value); > void EvdevQueueButtonClicks(InputInfoPtr pInfo, int button, int count); > void EvdevPostRelativeMotionEvents(InputInfoPtr pInfo, int num_v, int > first_v, > -- > 1.7.2.3 > > _______________________________________________ [email protected]: X.Org development Archives: http://lists.x.org/archives/xorg-devel Info: http://lists.x.org/mailman/listinfo/xorg-devel
