Split the New functions so that structs can be allocated and buttons

detected, and then stuff that depends on _other_ areas.
(Specificly, axes and btn have a circular dependency on which one has to
run first, this solves that.)

Add button names, and a way to get a button number from a name.

Add a function for checking to see if a button exists, takes the number from the previous function.

Change the (unused) state array of pointers in the button struct to an array of pointers to functions for callback.

Implemented the 'touch' feature, on by default if BTN_DIGI_TOUCH exists,
won't, in rel mode, process x/y data unless it's down, and is used to
try and make 'pick up stencil, move to other side of digitizer, set back
down' not jump to the other side of the screen in rel mode.
(This doesn't work as well as it could, but I'm fairly sure that it's
due to the quality of the absolute input device I'm using, but feedback
would be really nice.)

FIXME: Update the manpage for this.
This commit is contained in:
Zephaniah E. Hull
2006-07-13 11:59:25 -04:00
parent 090d43acf3
commit dc88668839
4 changed files with 322 additions and 56 deletions

View File

@@ -228,6 +228,7 @@ EvdevSwitchMode (ClientPtr client, DeviceIntPtr device, int mode)
{
case Absolute:
case Relative:
xf86Msg(X_INFO, "%s: Switching mode to %d.\n", pInfo->name, mode);
if (state->abs)
state->mode = mode;
else
@@ -298,9 +299,13 @@ EvdevNew(evdevDriverPtr driver, evdevDevicePtr device)
}
/* XXX: Note, the order of these is important. */
EvdevAxesNew (pInfo);
EvdevBtnNew (pInfo);
/* XXX: Note, the order of these is (maybe) still important. */
EvdevAxesNew0 (pInfo);
EvdevBtnNew0 (pInfo);
EvdevAxesNew1 (pInfo);
EvdevBtnNew1 (pInfo);
if (device->state.can_grab)
EvdevKeyNew (pInfo);

View File

@@ -151,7 +151,7 @@ typedef struct {
int real_buttons;
int buttons;
CARD8 map[EVDEV_MAXBUTTONS];
int *state[EVDEV_MAXBUTTONS];
void (*callback[EVDEV_MAXBUTTONS])(InputInfoPtr pInfo, int button, int value);
} evdevBtnRec, *evdevBtnPtr;
typedef struct {
@@ -164,6 +164,9 @@ typedef struct {
int map[ABS_MAX];
int scale[2];
int screen; /* Screen number for this device. */
Bool use_touch;
Bool touch;
Bool reset;
} evdevAbsRec, *evdevAbsPtr;
typedef struct {
@@ -247,14 +250,18 @@ Bool evdevGetBits (int fd, evdevBitsPtr bits);
int EvdevBtnInit (DeviceIntPtr device);
int EvdevBtnOn (DeviceIntPtr device);
int EvdevBtnOff (DeviceIntPtr device);
int EvdevBtnNew(InputInfoPtr pInfo);
int EvdevBtnNew0(InputInfoPtr pInfo);
int EvdevBtnNew1(InputInfoPtr pInfo);
void EvdevBtnProcess (InputInfoPtr pInfo, struct input_event *ev);
void EvdevBtnPostFakeClicks(InputInfoPtr pInfo, int button, int count);
int EvdevBtnFind (InputInfoPtr pInfo, const char *button);
int EvdevBtnExists (InputInfoPtr pInfo, int button);
int EvdevAxesInit (DeviceIntPtr device);
int EvdevAxesOn (DeviceIntPtr device);
int EvdevAxesOff (DeviceIntPtr device);
int EvdevAxesNew(InputInfoPtr pInfo);
int EvdevAxesNew0(InputInfoPtr pInfo);
int EvdevAxesNew1(InputInfoPtr pInfo);
void EvdevAxesAbsProcess (InputInfoPtr pInfo, struct input_event *ev);
void EvdevAxesRelProcess (InputInfoPtr pInfo, struct input_event *ev);
void EvdevAxesSyn (InputInfoPtr pInfo);

View File

@@ -136,6 +136,8 @@ static char *abs_axis_names[] = {
NULL
};
static void EvdevAxesTouchCallback (InputInfoPtr pInfo, int button, int value);
static Bool
EvdevConvert(InputInfoPtr pInfo, int first, int num, int v0, int v1, int v2,
int v3, int v4, int v5, int *x, int *y)
@@ -149,7 +151,7 @@ EvdevConvert(InputInfoPtr pInfo, int first, int num, int v0, int v1, int v2,
}
static void
EvdevAxesRealSyn (InputInfoPtr pInfo, int absolute)
EvdevAxesRealSyn (InputInfoPtr pInfo, int absolute, int skip_xy)
{
evdevDevicePtr pEvdev = pInfo->private;
evdevStatePtr state = &pEvdev->state;
@@ -163,27 +165,60 @@ EvdevAxesRealSyn (InputInfoPtr pInfo, int absolute)
EvdevBtnPostFakeClicks (pInfo, btn, -state->axes->v[i]);
}
xf86PostMotionEvent(pInfo->dev, absolute, 0,
state->axes->axes,
axes->v[0x00], axes->v[0x01], axes->v[0x02], axes->v[0x03],
axes->v[0x04], axes->v[0x05], axes->v[0x06], axes->v[0x07],
axes->v[0x08], axes->v[0x09], axes->v[0x0a], axes->v[0x0b],
axes->v[0x0c], axes->v[0x0d], axes->v[0x0e], axes->v[0x0f],
axes->v[0x10], axes->v[0x11], axes->v[0x12], axes->v[0x13],
axes->v[0x14], axes->v[0x15], axes->v[0x16], axes->v[0x17],
axes->v[0x18], axes->v[0x19], axes->v[0x1a], axes->v[0x1b],
axes->v[0x1c], axes->v[0x1d], axes->v[0x1e], axes->v[0x1f],
axes->v[0x20], axes->v[0x21], axes->v[0x22], axes->v[0x23],
axes->v[0x24], axes->v[0x25], axes->v[0x26], axes->v[0x27],
axes->v[0x28], axes->v[0x29], axes->v[0x2a], axes->v[0x2b],
axes->v[0x2c], axes->v[0x2d], axes->v[0x2e], axes->v[0x2f],
axes->v[0x30], axes->v[0x31], axes->v[0x32], axes->v[0x33],
axes->v[0x34], axes->v[0x35], axes->v[0x36], axes->v[0x37],
axes->v[0x38], axes->v[0x39], axes->v[0x3a], axes->v[0x3b],
axes->v[0x3c], axes->v[0x3d], axes->v[0x3e], axes->v[0x3f]);
/*
if (skip_xy && (axes->v[0] || axes->v[1]))
xf86Msg(X_INFO, "%s: skip_xy: %d, x: %d, y: %d.\n", pInfo->name, skip_xy, axes->v[0], axes->v[1]);
*/
for (i = 0; i < ABS_MAX; i++)
state->axes->v[i] = 0;
/* FIXME: This is a truly evil kluge. */
if (skip_xy == 1 && state->axes->axes >= 2)
xf86PostMotionEvent(pInfo->dev, absolute, 2,
state->axes->axes - 2,
axes->v[0x02], axes->v[0x03],
axes->v[0x04], axes->v[0x05], axes->v[0x06], axes->v[0x07],
axes->v[0x08], axes->v[0x09], axes->v[0x0a], axes->v[0x0b],
axes->v[0x0c], axes->v[0x0d], axes->v[0x0e], axes->v[0x0f],
axes->v[0x10], axes->v[0x11], axes->v[0x12], axes->v[0x13],
axes->v[0x14], axes->v[0x15], axes->v[0x16], axes->v[0x17],
axes->v[0x18], axes->v[0x19], axes->v[0x1a], axes->v[0x1b],
axes->v[0x1c], axes->v[0x1d], axes->v[0x1e], axes->v[0x1f],
axes->v[0x20], axes->v[0x21], axes->v[0x22], axes->v[0x23],
axes->v[0x24], axes->v[0x25], axes->v[0x26], axes->v[0x27],
axes->v[0x28], axes->v[0x29], axes->v[0x2a], axes->v[0x2b],
axes->v[0x2c], axes->v[0x2d], axes->v[0x2e], axes->v[0x2f],
axes->v[0x30], axes->v[0x31], axes->v[0x32], axes->v[0x33],
axes->v[0x34], axes->v[0x35], axes->v[0x36], axes->v[0x37],
axes->v[0x38], axes->v[0x39], axes->v[0x3a], axes->v[0x3b],
axes->v[0x3c], axes->v[0x3d], axes->v[0x3e], axes->v[0x3f]);
else
xf86PostMotionEvent(pInfo->dev, absolute, 0,
state->axes->axes,
axes->v[0x00], axes->v[0x01], axes->v[0x02], axes->v[0x03],
axes->v[0x04], axes->v[0x05], axes->v[0x06], axes->v[0x07],
axes->v[0x08], axes->v[0x09], axes->v[0x0a], axes->v[0x0b],
axes->v[0x0c], axes->v[0x0d], axes->v[0x0e], axes->v[0x0f],
axes->v[0x10], axes->v[0x11], axes->v[0x12], axes->v[0x13],
axes->v[0x14], axes->v[0x15], axes->v[0x16], axes->v[0x17],
axes->v[0x18], axes->v[0x19], axes->v[0x1a], axes->v[0x1b],
axes->v[0x1c], axes->v[0x1d], axes->v[0x1e], axes->v[0x1f],
axes->v[0x20], axes->v[0x21], axes->v[0x22], axes->v[0x23],
axes->v[0x24], axes->v[0x25], axes->v[0x26], axes->v[0x27],
axes->v[0x28], axes->v[0x29], axes->v[0x2a], axes->v[0x2b],
axes->v[0x2c], axes->v[0x2d], axes->v[0x2e], axes->v[0x2f],
axes->v[0x30], axes->v[0x31], axes->v[0x32], axes->v[0x33],
axes->v[0x34], axes->v[0x35], axes->v[0x36], axes->v[0x37],
axes->v[0x38], axes->v[0x39], axes->v[0x3a], axes->v[0x3b],
axes->v[0x3c], axes->v[0x3d], axes->v[0x3e], axes->v[0x3f]);
if (!skip_xy)
for (i = 0; i < ABS_MAX; i++)
state->axes->v[i] = 0;
else if (skip_xy == 1)
for (i = 2; i < ABS_MAX; i++)
state->axes->v[i] = 0;
else if (skip_xy == 2)
for (i = 0; i < 2; i++)
state->axes->v[i] = 0;
}
static void
@@ -192,6 +227,7 @@ EvdevAxesAbsSyn (InputInfoPtr pInfo)
evdevDevicePtr pEvdev = pInfo->private;
evdevStatePtr state = &pEvdev->state;
int i, n;
Bool skip_xy = 0;
if (!state->axes || !state->abs || !state->abs->count)
return;
@@ -201,10 +237,21 @@ EvdevAxesAbsSyn (InputInfoPtr pInfo)
i = 0;
if (state->mode == Relative && state->abs->axes >= 2) {
for (i = 0; i < 2; i++)
state->axes->v[i] = state->abs->v[n][i] - state->abs->v[!n][i];
EvdevAxesRealSyn (pInfo, 0);
} else if (state->mode == Absolute && state->abs->screen >= 0 && state->abs->axes >= 2) {
if (!state->abs->use_touch || state->abs->touch) {
if (state->abs->reset) {
for (i = 0; i < 2; i++)
state->axes->v[i] = 0;
xf86Msg(X_INFO, "%s: Resetting.\n", pInfo->name);
state->abs->reset = 0;
} else
for (i = 0; i < 2; i++) {
state->axes->v[i] = state->abs->v[n][i] - state->abs->v[!n][i];
state->axes->v[i] /= 4;
}
EvdevAxesRealSyn (pInfo, 0, 2);
}
skip_xy = 1;
} else if (state->mode == Absolute && state->abs->screen != -1 && state->abs->axes >= 2) {
int conv_x, conv_y;
for (i = 0; i < 2; i++)
@@ -221,7 +268,7 @@ EvdevAxesAbsSyn (InputInfoPtr pInfo)
for (; i < ABS_MAX; i++)
state->axes->v[i] = state->abs->v[n][i];
EvdevAxesRealSyn (pInfo, 1);
EvdevAxesRealSyn (pInfo, 1, skip_xy);
state->abs->count = 0;
}
@@ -240,7 +287,7 @@ EvdevAxesRelSyn (InputInfoPtr pInfo)
state->rel->v[i] = 0;
}
EvdevAxesRealSyn (pInfo, 0);
EvdevAxesRealSyn (pInfo, 0, 0);
state->rel->count = 0;
}
@@ -310,12 +357,12 @@ EvdevAxesOff (DeviceIntPtr device)
}
static int
EvdevAxisAbsNew(InputInfoPtr pInfo)
EvdevAxisAbsNew0(InputInfoPtr pInfo)
{
evdevDevicePtr pEvdev = pInfo->private;
evdevStatePtr state = &pEvdev->state;
struct input_absinfo absinfo;
char *s, option[64];
char option[64];
int i, j, k = 0, real_axes;
real_axes = 0;
@@ -365,9 +412,41 @@ EvdevAxisAbsNew(InputInfoPtr pInfo)
state->abs->axes = state->abs->map[i];
}
if (state->abs->axes != real_axes)
xf86Msg(X_CONFIG, "%s: Configuring %d absolute axes.\n", pInfo->name,
state->abs->axes);
return Success;
}
static int
EvdevAxisAbsNew1(InputInfoPtr pInfo)
{
evdevDevicePtr pEvdev = pInfo->private;
evdevStatePtr state = &pEvdev->state;
char *s;
int k = 0;
if (!state->abs)
return !Success;
xf86Msg(X_CONFIG, "%s: Configuring %d absolute axes.\n", pInfo->name,
state->abs->axes);
{
int btn;
s = xf86SetStrOption(pInfo->options, "AbsoluteTouch", "DIGI_Touch");
btn = EvdevBtnFind (pInfo, s);
if (btn != -1) {
if (EvdevBtnExists (pInfo, btn)) {
state->abs->use_touch = 1;
xf86Msg(X_ERROR, "%s: Button: %d.\n", pInfo->name, btn);
xf86Msg(X_ERROR, "%s: state->btn: %p.\n", pInfo->name, state->btn);
state->btn->callback[btn] = &EvdevAxesTouchCallback;
} else {
xf86Msg(X_ERROR, "%s: AbsoluteTouch: '%s' does not exist.\n", pInfo->name, s);
}
} else {
xf86Msg(X_ERROR, "%s: AbsoluteTouch: '%s' is not a valid button name.\n", pInfo->name, s);
}
}
s = xf86SetStrOption(pInfo->options, "Mode", "Absolute");
if (!strcasecmp(s, "Absolute")) {
@@ -388,19 +467,20 @@ EvdevAxisAbsNew(InputInfoPtr pInfo)
if (k < screenInfo.numScreens && k >= 0) {
state->abs->screen = k;
xf86Msg(X_CONFIG, "%s: AbsoluteScreen: %d.\n", pInfo->name, k);
} else {
state->abs->screen = 0;
xf86Msg(X_CONFIG, "%s: AbsoluteScreen: %d is not a valid screen.\n", pInfo->name, k);
}
state->abs->scale[0] = screenInfo.screens[state->abs->screen]->width;
state->abs->scale[1] = screenInfo.screens[state->abs->screen]->height;
state->abs->scale[0] = screenInfo.screens[state->abs->screen]->width;
state->abs->scale[1] = screenInfo.screens[state->abs->screen]->height;
} else {
if (k != -1)
xf86Msg(X_CONFIG, "%s: AbsoluteScreen: %d is not a valid screen.\n", pInfo->name, k);
state->abs->screen = -1;
}
return Success;
}
static int
EvdevAxisRelNew(InputInfoPtr pInfo)
EvdevAxisRelNew0(InputInfoPtr pInfo)
{
evdevDevicePtr pEvdev = pInfo->private;
evdevStatePtr state = &pEvdev->state;
@@ -467,26 +547,57 @@ EvdevAxisRelNew(InputInfoPtr pInfo)
state->rel->axes = state->rel->map[i];
if (state->abs && (state->abs->axes >= 2) && (state->rel->axes < 2))
state->rel->axes = 2;
state->rel->axes += 2;
if (state->rel->axes != real_axes)
xf86Msg(X_CONFIG, "%s: Configuring %d relative axes.\n", pInfo->name,
state->rel->axes);
return Success;
}
static int
EvdevAxisRelNew1(InputInfoPtr pInfo)
{
evdevDevicePtr pEvdev = pInfo->private;
evdevStatePtr state = &pEvdev->state;
if (!state->rel)
return !Success;
xf86Msg(X_CONFIG, "%s: Configuring %d relative axes.\n", pInfo->name,
state->rel->axes);
return Success;
}
int
EvdevAxesNew (InputInfoPtr pInfo)
EvdevAxesNew0 (InputInfoPtr pInfo)
{
evdevDevicePtr pEvdev = pInfo->private;
evdevStatePtr state = &pEvdev->state;
int ret = Success;
state->axes = Xcalloc (sizeof (evdevAxesRec));
if (EvdevAxisAbsNew(pInfo) != Success)
if (EvdevAxisAbsNew0(pInfo) != Success)
ret = !Success;
if (EvdevAxisRelNew(pInfo) != Success)
if (EvdevAxisRelNew0(pInfo) != Success)
ret = !Success;
if (!state->abs && !state->rel) {
Xfree (state->axes);
state->axes = NULL;
}
return ret;
}
int
EvdevAxesNew1 (InputInfoPtr pInfo)
{
evdevDevicePtr pEvdev = pInfo->private;
evdevStatePtr state = &pEvdev->state;
int ret = Success;
state->axes = Xcalloc (sizeof (evdevAxesRec));
if (EvdevAxisAbsNew1(pInfo) != Success)
ret = !Success;
if (EvdevAxisRelNew1(pInfo) != Success)
ret = !Success;
if (!state->abs && !state->rel) {
Xfree (state->axes);
@@ -541,3 +652,16 @@ EvdevAxesInit (DeviceIntPtr device)
return Success;
}
static void
EvdevAxesTouchCallback (InputInfoPtr pInfo, int button, int value)
{
evdevDevicePtr pEvdev = pInfo->private;
evdevStatePtr state = &pEvdev->state;
xf86Msg(X_INFO, "%s: Touch callback; %d.\n", pInfo->name, value);
if (state->abs->use_touch) {
state->abs->touch = !!value;
if (value)
state->abs->reset = 1;
}
}

View File

@@ -51,6 +51,91 @@
#include <xf86Module.h>
static char *button_names[] = {
"MISC_0",
"MISC_1",
"MISC_2",
"MISC_3",
"MISC_4",
"MISC_5",
"MISC_6",
"MISC_7",
"MISC_8",
"MISC_9",
"MISC_10",
"MISC_11",
"MISC_12",
"MISC_13",
"MISC_14",
"MISC_15",
"MOUSE_LEFT",
"MOUSE_RIGHT",
"MOUSE_MIDDLE",
"MOUSE_SIDE",
"MOUSE_EXTRA",
"MOUSE_FORWARD",
"MOUSE_BACK",
"MOUSE_TASK",
"MOUSE_8",
"MOUSE_9",
"MOUSE_10",
"MOUSE_12",
"MOUSE_13",
"MOUSE_14",
"MOUSE_15",
"JOY_TRIGGER",
"JOY_THUMB",
"JOY_THUMB2",
"JOY_TOP",
"JOY_TOP2",
"JOY_PINKIE",
"JOY_BASE",
"JOY_BASE2",
"JOY_BASE3",
"JOY_BASE4",
"JOY_BASE5",
"JOY_BASE6",
"JOY_12",
"JOY_13",
"JOY_14",
"JOY_DEAD",
"GAME_A",
"GAME_B",
"GAME_C",
"GAME_X",
"GAME_Y",
"GAME_Z",
"GAME_TL",
"GAME_TR",
"GAME_TL2",
"GAME_TR2",
"GAME_SELECT",
"GAME_START",
"GAME_MODE",
"GAME_THUMBL",
"GAME_THUMBR",
"GAME_15",
"DIGI_TOOL_PEN",
"DIGI_TOOL_RUBBER",
"DIGI_TOOL_BRUSH",
"DIGI_TOOL_PENCIL",
"DIGI_TOOL_AIRBRUSH",
"DIGI_TOOL_FINGER",
"DIGI_TOOL_MOUSE",
"DIGI_TOOL_LENS",
"DIGI_8",
"DIGI_9",
"DIGI_TOUCH",
"DIGI_STYLUS",
"DIGI_STYLUS2",
"DIGI_TOOL_DOUBLETAP",
"DIGI_TOOL_TRIPLETAP",
"DIGI_15",
"WHEEL_GEAR_UP",
"WHEEL_GEAR_DOWN",
NULL
};
void
EvdevBtnPostFakeClicks(InputInfoPtr pInfo, int button, int count)
{
@@ -168,7 +253,7 @@ EvdevBtnCalcRemap (InputInfoPtr pInfo)
int
EvdevBtnNew(InputInfoPtr pInfo)
EvdevBtnNew0(InputInfoPtr pInfo)
{
evdevDevicePtr pEvdev = pInfo->private;
evdevStatePtr state = &pEvdev->state;
@@ -191,6 +276,18 @@ EvdevBtnNew(InputInfoPtr pInfo)
if (state->btn->real_buttons)
xf86Msg(X_INFO, "%s: Found %d mouse buttons\n", pInfo->name, state->btn->real_buttons);
return Success;
}
int
EvdevBtnNew1(InputInfoPtr pInfo)
{
evdevDevicePtr pEvdev = pInfo->private;
evdevStatePtr state = &pEvdev->state;
if (!state->btn)
return !Success;
EvdevBtnCalcRemap (pInfo);
if (state->btn->buttons)
@@ -221,7 +318,7 @@ EvdevBtnProcess (InputInfoPtr pInfo, struct input_event *ev)
if (!state->btn)
return;
button = ev->code - BTN_MISC;
button = ev->code;
if ((ev->code >= BTN_MOUSE) && (ev->code < BTN_JOYSTICK)) {
button -= BTN_MOUSE - BTN_MISC;
@@ -229,9 +326,42 @@ EvdevBtnProcess (InputInfoPtr pInfo, struct input_event *ev)
button += BTN_MOUSE - BTN_MISC;
}
if (state->btn->state[button])
*state->btn->state[button] = ev->value;
button -= BTN_MISC;
if (state->btn->callback[button])
state->btn->callback[button](pInfo, button, ev->value);
button = state->btn->map[button];
xf86PostButtonEvent (pInfo->dev, 0, button, ev->value, 0, 0);
}
int
EvdevBtnFind (InputInfoPtr pInfo, const char *button)
{
int i;
for (i = 0; button_names[i]; i++)
if (!strcasecmp(button, button_names[i]))
return i + 1;
return -1;
}
int
EvdevBtnExists (InputInfoPtr pInfo, int button)
{
evdevDevicePtr pEvdev = pInfo->private;
button += BTN_MISC;
xf86Msg(X_INFO, "%s: Checking button %s (%d)\n", pInfo->name, button_names[button - BTN_MISC], button);
if ((button >= BTN_MOUSE) && (button < BTN_JOYSTICK)) {
button -= BTN_MOUSE - BTN_MISC;
} else if ((button >= BTN_MISC) && (button < BTN_MOUSE)) {
button += BTN_MOUSE - BTN_MISC;
}
xf86Msg(X_INFO, "%s: Checking bit %d\n", pInfo->name, button);
return test_bit(button, pEvdev->bits.key);
}