#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <xf86.h>
#include <xf86Xinput.h>
#include <X11/Xatom.h>
#include "evdev.h"
#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 3
static const char *propname_dlock = "Drag Lock Buttons";
static Atom prop_dlock = 0;
void EvdevDragLockLockButton(InputInfoPtr pInfo, unsigned int button);
#endif
void
EvdevDragLockInit(InputInfoPtr pInfo)
{
EvdevPtr pEvdev = (EvdevPtr)pInfo->private;
char *option_string = NULL;
int meta_button = 0;
int lock_button = 0;
char *next_num = NULL;
char *end_str = NULL;
BOOL pairs = FALSE;
option_string = xf86CheckStrOption(pInfo->options, "DragLockButtons",NULL);
if (!option_string)
return;
next_num = option_string;
while (next_num != NULL) {
lock_button = 0;
meta_button = strtol(next_num, &end_str, 10);
if (next_num != end_str) {
next_num = end_str;
} else {
next_num = NULL;
}
if (meta_button != 0 && next_num != NULL ) {
lock_button = strtol(next_num, &end_str, 10);
if (next_num != end_str) {
next_num = end_str;
} else {
next_num = NULL;
}
}
if (meta_button != 0) {
if (lock_button == 0) {
if (!pairs) {
pEvdev->dragLock.meta = meta_button;
xf86Msg(X_CONFIG, "%s: DragLockButtons : "
"%i as meta\n",
pInfo->name, meta_button);
} else {
xf86Msg(X_ERROR, "%s: DragLockButtons : "
"Incomplete pair specifying button pairs %s\n",
pInfo->name, option_string);
}
} else {
if ((meta_button <= EVDEV_MAXBUTTONS) && (meta_button >= 0 ) &&
(lock_button <= EVDEV_MAXBUTTONS) && (lock_button >= 0)) {
xf86Msg(X_CONFIG, "%s: DragLockButtons : %i -> %i\n",
pInfo->name, meta_button, lock_button);
pEvdev->dragLock.lock_pair[meta_button - 1] = lock_button;
pairs=TRUE;
} else {
xf86Msg(X_CONFIG, "%s: DragLockButtons : "
"Invalid button pair %i -> %i\n",
pInfo->name, meta_button, lock_button);
}
}
} else {
xf86Msg(X_ERROR, "%s: Found DragLockButtons "
"with invalid lock button string : '%s'\n",
pInfo->name, option_string);
next_num = NULL;
}
if (next_num != NULL && *next_num == '\0')
next_num = NULL;
}
}
void
EvdevDragLockLockButton(InputInfoPtr pInfo, unsigned int button)
{
EvdevPtr pEvdev = (EvdevPtr)pInfo->private;
BOOL state=0;
state = pEvdev->dragLock.lock_state[button - 1] ? FALSE : TRUE;
pEvdev->dragLock.lock_state[button - 1] = state;
xf86PostButtonEvent(pInfo->dev, 0, button, state, 0, 0);
}
BOOL
EvdevDragLockFilterEvent(InputInfoPtr pInfo, unsigned int button, int value)
{
EvdevPtr pEvdev = (EvdevPtr)pInfo->private;
if (button == 0)
return FALSE;
if (pEvdev->dragLock.meta != 0) {
if (pEvdev->dragLock.meta == button) {
if (value)
pEvdev->dragLock.meta_state = TRUE;
return TRUE;
} else if (pEvdev->dragLock.meta_state) {
pEvdev->dragLock.meta_state = FALSE;
EvdevDragLockLockButton(pInfo, button);
return TRUE;
}
} else if (pEvdev->dragLock.lock_pair[button - 1] && value) {
EvdevDragLockLockButton(pInfo, pEvdev->dragLock.lock_pair[button - 1]);
return TRUE;
}
if (pEvdev->dragLock.lock_state[button - 1])
return TRUE;
return FALSE;
}
#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 3
void
EvdevDragLockInitProperty(DeviceIntPtr dev)
{
InputInfoPtr pInfo = dev->public.devicePrivate;
EvdevPtr pEvdev = pInfo->private;
if (!dev->button)
return;
prop_dlock = MakeAtom((char*)propname_dlock, strlen(propname_dlock), TRUE);
if (pEvdev->dragLock.meta)
{
XIChangeDeviceProperty(dev, prop_dlock, XA_INTEGER, 8,
PropModeReplace, 1, &pEvdev->dragLock.meta,
FALSE, FALSE, FALSE);
} else {
int highest = 0;
int i;
CARD8 pair[EVDEV_MAXBUTTONS] = {0};
for (i = 0; i < EVDEV_MAXBUTTONS; i++)
{
if (pEvdev->dragLock.lock_pair[i])
highest = i;
pair[i] = pEvdev->dragLock.lock_pair[i];
}
XIChangeDeviceProperty(dev, prop_dlock, XA_INTEGER, 8, PropModeReplace,
highest + 1, pair, FALSE, FALSE, FALSE);
}
return;
}
BOOL
EvdevDragLockSetProperty(DeviceIntPtr dev, Atom atom, XIPropertyValuePtr val)
{
InputInfoPtr pInfo = dev->public.devicePrivate;
EvdevPtr pEvdev = pInfo->private;
if (atom == prop_dlock)
{
int i;
if (val->format != 8 || val->type != XA_INTEGER)
return FALSE;
if (pEvdev->dragLock.meta)
{
if (pEvdev->dragLock.meta_state)
return FALSE;
} else
{
for (i = 0; i < EVDEV_MAXBUTTONS; i++)
if (pEvdev->dragLock.lock_state[i])
return FALSE;
}
if (val->size == 1)
{
int meta = *((CARD8*)val->data);
if (meta > EVDEV_MAXBUTTONS)
return FALSE;
pEvdev->dragLock.meta = meta;
memset(pEvdev->dragLock.lock_pair, 0, sizeof(pEvdev->dragLock.lock_pair));
} else
{
CARD8* vals = (CARD8*)val->data;
for (i = 0; i < val->size && i < EVDEV_MAXBUTTONS; i++)
if (vals[i] > EVDEV_MAXBUTTONS)
return FALSE;
pEvdev->dragLock.meta = 0;
memset(pEvdev->dragLock.lock_pair, 0, sizeof(pEvdev->dragLock.lock_pair));
for (i = 0; i < val->size && i < EVDEV_MAXBUTTONS; i++)
pEvdev->dragLock.lock_pair[i] = vals[i];
}
}
return TRUE;
}
#endif