mirror of
https://github.com/X11Libre/xf86-input-evdev.git
synced 2026-04-14 11:44:16 +00:00
Add proximity support.
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@who-t.net> Reviewed-by: Chris Bagwell <chris@cnpbagwell.com> Reviewed-by: Benjamin Tissoires <tissoire@cena.fr>
This commit is contained in:
118
src/evdev.c
118
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; 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;
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user