[PATCH evdev v2] Add proximity support.

Chris Bagwell chris at cnpbagwell.com
Tue Oct 12 19:38:33 PDT 2010


Reviewed-by: Chris Bagwell <chris at cnpbagwell.com>

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
<peter.hutterer at who-t.net> 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 <peter.hutterer at who-t.net>
> ---
> 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
>
>


More information about the xorg-devel mailing list