#ifdef HAVE_DIX_CONFIG_H
#include <dix-config.h>
#endif
#include <X11/X.h>
#include "misc.h"
#include "resource.h"
#include <X11/Xproto.h>
#include <X11/Xatom.h>
#include "windowstr.h"
#include "inputstr.h"
#include "scrnintstr.h"
#include "cursorstr.h"
#include "dixstruct.h"
#include "ptrveloc.h"
#include "site.h"
#include "xkbsrv.h"
#include "privates.h"
#include "xace.h"
#include "mi.h"
#include "dispatch.h"
#include "swaprep.h"
#include "dixevents.h"
#include "mipointer.h"
#include "eventstr.h"
#include <X11/extensions/XI.h>
#include <X11/extensions/XI2.h>
#include <X11/extensions/XIproto.h>
#include <math.h>
#include <pixman.h>
#include "exglobals.h"
#include "exevents.h"
#include "xiquerydevice.h"
#include "xiproperty.h"
#include "enterleave.h"
#include "xserver-properties.h"
#include "xichangehierarchy.h"
static void RecalculateMasterButtons(DeviceIntPtr slave);
static void
DeviceSetTransform(DeviceIntPtr dev, float *transform)
{
struct pixman_f_transform scale;
double sx, sy;
int x, y;
sx = dev->valuator->axes[0].max_value - dev->valuator->axes[0].min_value;
sy = dev->valuator->axes[1].max_value - dev->valuator->axes[1].min_value;
pixman_f_transform_init_scale(&scale, sx, sy);
scale.m[0][2] = dev->valuator->axes[0].min_value;
scale.m[1][2] = dev->valuator->axes[1].min_value;
for (y=0; y<3; y++)
for (x=0; x<3; x++)
dev->transform.m[y][x] = *transform++;
pixman_f_transform_multiply(&dev->transform, &scale, &dev->transform);
pixman_f_transform_init_scale(&scale, 1.0 / sx, 1.0 / sy);
scale.m[0][2] = -dev->valuator->axes[0].min_value / sx;
scale.m[1][2] = -dev->valuator->axes[1].min_value / sy;
pixman_f_transform_multiply(&dev->transform, &dev->transform, &scale);
}
static int
DeviceSetProperty(DeviceIntPtr dev, Atom property, XIPropertyValuePtr prop,
BOOL checkonly)
{
if (property == XIGetKnownProperty(XI_PROP_ENABLED))
{
if (prop->format != 8 || prop->type != XA_INTEGER || prop->size != 1)
return BadValue;
if ((dev == inputInfo.pointer || dev == inputInfo.keyboard) &&
!(*(CARD8*)prop->data))
return BadAccess;
if (!checkonly)
{
if ((*((CARD8*)prop->data)) && !dev->enabled)
EnableDevice(dev, TRUE);
else if (!(*((CARD8*)prop->data)) && dev->enabled)
DisableDevice(dev, TRUE);
}
} else if (property == XIGetKnownProperty(XI_PROP_TRANSFORM))
{
float *f = (float*)prop->data;
int i;
if (prop->format != 32 || prop->size != 9 ||
prop->type != XIGetKnownProperty(XATOM_FLOAT))
return BadValue;
for (i=0; i<9; i++)
if (!isfinite(f[i]))
return BadValue;
if (!checkonly)
DeviceSetTransform(dev, f);
}
return Success;
}
static int
PairDevices(ClientPtr client, DeviceIntPtr ptr, DeviceIntPtr kbd)
{
if (!ptr)
return BadDevice;
if (!IsMaster(ptr) || !IsMaster(kbd))
return BadDevice;
if (ptr->spriteInfo->paired)
return BadDevice;
if (kbd->spriteInfo->spriteOwner)
{
free(kbd->spriteInfo->sprite);
kbd->spriteInfo->sprite = NULL;
kbd->spriteInfo->spriteOwner = FALSE;
}
kbd->spriteInfo->sprite = ptr->spriteInfo->sprite;
kbd->spriteInfo->paired = ptr;
ptr->spriteInfo->paired = kbd;
return Success;
}
static DeviceIntPtr
NextFreePointerDevice(void)
{
DeviceIntPtr dev;
for (dev = inputInfo.devices; dev; dev = dev->next)
if (IsMaster(dev) &&
dev->spriteInfo->spriteOwner &&
!dev->spriteInfo->paired)
return dev;
return NULL;
}
DeviceIntPtr
AddInputDevice(ClientPtr client, DeviceProc deviceProc, Bool autoStart)
{
DeviceIntPtr dev, *prev;
DeviceIntPtr devtmp;
int devid;
char devind[MAXDEVICES];
BOOL enabled;
float transform[9];
memset(devind, 0, sizeof(char)*MAXDEVICES);
for (devtmp = inputInfo.devices; devtmp; devtmp = devtmp->next)
devind[devtmp->id]++;
for (devtmp = inputInfo.off_devices; devtmp; devtmp = devtmp->next)
devind[devtmp->id]++;
for (devid = 2; devid < MAXDEVICES && devind[devid]; devid++)
;
if (devid >= MAXDEVICES)
return (DeviceIntPtr)NULL;
dev = _dixAllocateObjectWithPrivates(sizeof(DeviceIntRec) + sizeof(SpriteInfoRec),
sizeof(DeviceIntRec) + sizeof(SpriteInfoRec),
offsetof(DeviceIntRec, devPrivates), PRIVATE_DEVICE);
if (!dev)
return (DeviceIntPtr)NULL;
dev->id = devid;
dev->public.processInputProc = ProcessOtherEvent;
dev->public.realInputProc = ProcessOtherEvent;
dev->public.enqueueInputProc = EnqueueEvent;
dev->deviceProc = deviceProc;
dev->startup = autoStart;
dev->deviceGrab.grabTime = currentTime;
dev->deviceGrab.ActivateGrab = ActivateKeyboardGrab;
dev->deviceGrab.DeactivateGrab = DeactivateKeyboardGrab;
XkbSetExtension(dev, ProcessKeyboardEvent);
dev->coreEvents = TRUE;
dev->spriteInfo = (SpriteInfoPtr)&dev[1];
if (XaceHook(XACE_DEVICE_ACCESS, client, dev, DixCreateAccess)) {
free(dev);
return NULL;
}
inputInfo.numDevices++;
for (prev = &inputInfo.off_devices; *prev; prev = &(*prev)->next)
;
*prev = dev;
dev->next = NULL;
enabled = FALSE;
XIChangeDeviceProperty(dev, XIGetKnownProperty(XI_PROP_ENABLED),
XA_INTEGER, 8, PropModeReplace, 1, &enabled,
FALSE);
XISetDevicePropertyDeletable(dev, XIGetKnownProperty(XI_PROP_ENABLED), FALSE);
memset(transform, 0, sizeof(transform));
transform[0] = transform[4] = transform[8] = 1.0f;
XIChangeDeviceProperty(dev, XIGetKnownProperty(XI_PROP_TRANSFORM),
XIGetKnownProperty(XATOM_FLOAT), 32,
PropModeReplace, 9, transform, FALSE);
XISetDevicePropertyDeletable(dev, XIGetKnownProperty(XI_PROP_TRANSFORM),
FALSE);
XIRegisterPropertyHandler(dev, DeviceSetProperty, NULL, NULL);
return dev;
}
void
SendDevicePresenceEvent(int deviceid, int type)
{
DeviceIntRec dummyDev;
devicePresenceNotify ev;
memset(&dummyDev, 0, sizeof(DeviceIntRec));
ev.type = DevicePresenceNotify;
ev.time = currentTime.milliseconds;
ev.devchange = type;
ev.deviceid = deviceid;
dummyDev.id = XIAllDevices;
SendEventToAllWindows(&dummyDev, DevicePresenceNotifyMask,
(xEvent*)&ev, 1);
}
Bool
EnableDevice(DeviceIntPtr dev, BOOL sendevent)
{
DeviceIntPtr *prev;
int ret;
DeviceIntPtr other;
BOOL enabled;
int flags[MAXDEVICES] = {0};
for (prev = &inputInfo.off_devices;
*prev && (*prev != dev);
prev = &(*prev)->next)
;
if (!dev->spriteInfo->sprite)
{
if (IsMaster(dev))
{
if (dev->spriteInfo->spriteOwner)
{
InitializeSprite(dev, screenInfo.screens[0]->root);
EnterWindow(dev, screenInfo.screens[0]->root, NotifyAncestor);
}
else if ((other = NextFreePointerDevice()) == NULL)
{
ErrorF("[dix] cannot find pointer to pair with. "
"This is a bug.\n");
return FALSE;
} else
PairDevices(NULL, other, dev);
} else
{
if (dev->coreEvents)
other = (IsPointerDevice(dev)) ? inputInfo.pointer :
inputInfo.keyboard;
else
other = NULL;
AttachDevice(NULL, dev, other);
}
}
if ((*prev != dev) || !dev->inited ||
((ret = (*dev->deviceProc)(dev, DEVICE_ON)) != Success)) {
ErrorF("[dix] couldn't enable device %d\n", dev->id);
return FALSE;
}
dev->enabled = TRUE;
*prev = dev->next;
for (prev = &inputInfo.devices; *prev; prev = &(*prev)->next)
;
*prev = dev;
dev->next = NULL;
enabled = TRUE;
XIChangeDeviceProperty(dev, XIGetKnownProperty(XI_PROP_ENABLED),
XA_INTEGER, 8, PropModeReplace, 1, &enabled,
TRUE);
SendDevicePresenceEvent(dev->id, DeviceEnabled);
if (sendevent)
{
flags[dev->id] |= XIDeviceEnabled;
XISendDeviceHierarchyEvent(flags);
}
RecalculateMasterButtons(dev);
return TRUE;
}
Bool
DisableDevice(DeviceIntPtr dev, BOOL sendevent)
{
DeviceIntPtr *prev, other;
BOOL enabled;
int flags[MAXDEVICES] = {0};
for (prev = &inputInfo.devices;
*prev && (*prev != dev);
prev = &(*prev)->next)
;
if (*prev != dev)
return FALSE;
if (IsMaster(dev))
{
for (other = inputInfo.devices; other; other = other->next)
{
if (other->u.master == dev)
{
AttachDevice(NULL, other, NULL);
flags[other->id] |= XISlaveDetached;
}
}
}
else
{
for (other = inputInfo.devices; other; other = other->next)
{
if (IsMaster(other) && other->u.lastSlave == dev)
other->u.lastSlave = NULL;
}
}
if (IsMaster(dev) && dev->spriteInfo->sprite)
{
for (other = inputInfo.devices; other; other = other->next)
{
if (other->spriteInfo->paired == dev)
{
ErrorF("[dix] cannot disable device, still paired. "
"This is a bug. \n");
return FALSE;
}
}
}
(void)(*dev->deviceProc)(dev, DEVICE_OFF);
dev->enabled = FALSE;
OsBlockSignals();
for (other = inputInfo.devices; other; other = other->next)
{
if (other->last.slave == dev)
other->last.slave = NULL;
}
OsReleaseSignals();
LeaveWindow(dev);
SetFocusOut(dev);
*prev = dev->next;
dev->next = inputInfo.off_devices;
inputInfo.off_devices = dev;
enabled = FALSE;
XIChangeDeviceProperty(dev, XIGetKnownProperty(XI_PROP_ENABLED),
XA_INTEGER, 8, PropModeReplace, 1, &enabled,
TRUE);
SendDevicePresenceEvent(dev->id, DeviceDisabled);
if (sendevent)
{
flags[dev->id] = XIDeviceDisabled;
XISendDeviceHierarchyEvent(flags);
}
RecalculateMasterButtons(dev);
return TRUE;
}
int
ActivateDevice(DeviceIntPtr dev, BOOL sendevent)
{
int ret = Success;
ScreenPtr pScreen = screenInfo.screens[0];
if (!dev || !dev->deviceProc)
return BadImplementation;
ret = (*dev->deviceProc) (dev, DEVICE_INIT);
dev->inited = (ret == Success);
if (!dev->inited)
return ret;
if (IsMaster(dev) && dev->spriteInfo->spriteOwner)
if (!pScreen->DeviceCursorInitialize(dev, pScreen))
ret = BadAlloc;
SendDevicePresenceEvent(dev->id, DeviceAdded);
if (sendevent)
{
int flags[MAXDEVICES] = {0};
flags[dev->id] = XISlaveAdded;
XISendDeviceHierarchyEvent(flags);
}
return ret;
}
static void
CoreKeyboardBell(int volume, DeviceIntPtr pDev, pointer arg, int something)
{
KeybdCtrl *ctrl = arg;
DDXRingBell(volume, ctrl->bell_pitch, ctrl->bell_duration);
}
static void
CoreKeyboardCtl(DeviceIntPtr pDev, KeybdCtrl *ctrl)
{
return;
}
int
CoreKeyboardProc(DeviceIntPtr pDev, int what)
{
switch (what) {
case DEVICE_INIT:
if (!InitKeyboardDeviceStruct(pDev, NULL, CoreKeyboardBell,
CoreKeyboardCtl))
{
ErrorF("Keyboard initialization failed. This could be a missing "
"or incorrect setup of xkeyboard-config.\n");
return BadValue;
}
return Success;
case DEVICE_ON:
case DEVICE_OFF:
return Success;
case DEVICE_CLOSE:
return Success;
}
return BadMatch;
}
int
CorePointerProc(DeviceIntPtr pDev, int what)
{
#define NBUTTONS 10
#define NAXES 2
BYTE map[NBUTTONS + 1];
int i = 0;
Atom btn_labels[NBUTTONS] = {0};
Atom axes_labels[NAXES] = {0};
switch (what) {
case DEVICE_INIT:
for (i = 1; i <= NBUTTONS; i++)
map[i] = i;
btn_labels[0] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_LEFT);
btn_labels[1] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_MIDDLE);
btn_labels[2] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_RIGHT);
btn_labels[3] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_WHEEL_UP);
btn_labels[4] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_WHEEL_DOWN);
btn_labels[5] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_HWHEEL_LEFT);
btn_labels[6] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_HWHEEL_RIGHT);
axes_labels[0] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_X);
axes_labels[1] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_Y);
if (!InitPointerDeviceStruct((DevicePtr)pDev, map, NBUTTONS, btn_labels,
(PtrCtrlProcPtr)NoopDDA,
GetMotionHistorySize(), NAXES, axes_labels))
{
ErrorF("Could not initialize device '%s'. Out of memory.\n",
pDev->name);
return BadAlloc;
}
pDev->valuator->axisVal[0] = screenInfo.screens[0]->width / 2;
pDev->last.valuators[0] = pDev->valuator->axisVal[0];
pDev->valuator->axisVal[1] = screenInfo.screens[0]->height / 2;
pDev->last.valuators[1] = pDev->valuator->axisVal[1];
break;
case DEVICE_CLOSE:
break;
default:
break;
}
return Success;
#undef NBUTTONS
#undef NAXES
}
void
InitCoreDevices(void)
{
if (AllocDevicePair(serverClient, "Virtual core",
&inputInfo.pointer, &inputInfo.keyboard,
CorePointerProc, CoreKeyboardProc,
TRUE) != Success)
FatalError("Failed to allocate core devices");
if (ActivateDevice(inputInfo.pointer, TRUE) != Success ||
ActivateDevice(inputInfo.keyboard, TRUE) != Success)
FatalError("Failed to activate core devices.");
if (!EnableDevice(inputInfo.pointer, TRUE) ||
!EnableDevice(inputInfo.keyboard, TRUE))
FatalError("Failed to enable core devices.");
InitXTestDevices();
}
int
InitAndStartDevices(void)
{
DeviceIntPtr dev, next;
for (dev = inputInfo.off_devices; dev; dev = dev->next) {
DebugF("(dix) initialising device %d\n", dev->id);
if (!dev->inited)
ActivateDevice(dev, TRUE);
}
for (dev = inputInfo.off_devices; dev; dev = next)
{
DebugF("(dix) enabling device %d\n", dev->id);
next = dev->next;
if (dev->inited && dev->startup)
EnableDevice(dev, TRUE);
}
return Success;
}
static void
FreeDeviceClass(int type, pointer *class)
{
if (!(*class))
return;
switch(type)
{
case KeyClass:
{
KeyClassPtr* k = (KeyClassPtr*)class;
if ((*k)->xkbInfo)
{
XkbFreeInfo((*k)->xkbInfo);
(*k)->xkbInfo = NULL;
}
free((*k));
break;
}
case ButtonClass:
{
ButtonClassPtr *b = (ButtonClassPtr*)class;
free((*b)->xkb_acts);
free((*b));
break;
}
case ValuatorClass:
{
ValuatorClassPtr *v = (ValuatorClassPtr*)class;
free((*v)->motion);
free((*v));
break;
}
case FocusClass:
{
FocusClassPtr *f = (FocusClassPtr*)class;
free((*f)->trace);
free((*f));
break;
}
case ProximityClass:
{
ProximityClassPtr *p = (ProximityClassPtr*)class;
free((*p));
break;
}
}
*class = NULL;
}
static void
FreeFeedbackClass(int type, pointer *class)
{
if (!(*class))
return;
switch(type)
{
case KbdFeedbackClass:
{
KbdFeedbackPtr *kbdfeed = (KbdFeedbackPtr*)class;
KbdFeedbackPtr k, knext;
for (k = (*kbdfeed); k; k = knext) {
knext = k->next;
if (k->xkb_sli)
XkbFreeSrvLedInfo(k->xkb_sli);
free(k);
}
break;
}
case PtrFeedbackClass:
{
PtrFeedbackPtr *ptrfeed = (PtrFeedbackPtr*)class;
PtrFeedbackPtr p, pnext;
for (p = (*ptrfeed); p; p = pnext) {
pnext = p->next;
free(p);
}
break;
}
case IntegerFeedbackClass:
{
IntegerFeedbackPtr *intfeed = (IntegerFeedbackPtr*)class;
IntegerFeedbackPtr i, inext;
for (i = (*intfeed); i; i = inext) {
inext = i->next;
free(i);
}
break;
}
case StringFeedbackClass:
{
StringFeedbackPtr *stringfeed = (StringFeedbackPtr*)class;
StringFeedbackPtr s, snext;
for (s = (*stringfeed); s; s = snext) {
snext = s->next;
free(s->ctrl.symbols_supported);
free(s->ctrl.symbols_displayed);
free(s);
}
break;
}
case BellFeedbackClass:
{
BellFeedbackPtr *bell = (BellFeedbackPtr*)class;
BellFeedbackPtr b, bnext;
for (b = (*bell); b; b = bnext) {
bnext = b->next;
free(b);
}
break;
}
case LedFeedbackClass:
{
LedFeedbackPtr *leds = (LedFeedbackPtr*)class;
LedFeedbackPtr l, lnext;
for (l = (*leds); l; l = lnext) {
lnext = l->next;
if (l->xkb_sli)
XkbFreeSrvLedInfo(l->xkb_sli);
free(l);
}
break;
}
}
*class = NULL;
}
static void
FreeAllDeviceClasses(ClassesPtr classes)
{
if (!classes)
return;
FreeDeviceClass(KeyClass, (pointer)&classes->key);
FreeDeviceClass(ValuatorClass, (pointer)&classes->valuator);
FreeDeviceClass(ButtonClass, (pointer)&classes->button);
FreeDeviceClass(FocusClass, (pointer)&classes->focus);
FreeDeviceClass(ProximityClass, (pointer)&classes->proximity);
FreeFeedbackClass(KbdFeedbackClass, (pointer)&classes->kbdfeed);
FreeFeedbackClass(PtrFeedbackClass, (pointer)&classes->ptrfeed);
FreeFeedbackClass(IntegerFeedbackClass, (pointer)&classes->intfeed);
FreeFeedbackClass(StringFeedbackClass, (pointer)&classes->stringfeed);
FreeFeedbackClass(BellFeedbackClass, (pointer)&classes->bell);
FreeFeedbackClass(LedFeedbackClass, (pointer)&classes->leds);
}
static void
CloseDevice(DeviceIntPtr dev)
{
ScreenPtr screen = screenInfo.screens[0];
ClassesPtr classes;
int j;
if (!dev)
return;
XIDeleteAllDeviceProperties(dev);
if (dev->inited)
(void)(*dev->deviceProc)(dev, DEVICE_CLOSE);
if (IsMaster(dev) && dev->spriteInfo->sprite)
screen->DeviceCursorCleanup(dev, screen);
if(dev->valuator && dev->valuator->accelScheme.AccelCleanupProc)
dev->valuator->accelScheme.AccelCleanupProc(dev);
while (dev->xkb_interest)
XkbRemoveResourceClient((DevicePtr)dev,dev->xkb_interest->resource);
free(dev->name);
classes = (ClassesPtr)&dev->key;
FreeAllDeviceClasses(classes);
if (IsMaster(dev))
{
classes = dev->unused_classes;
FreeAllDeviceClasses(classes);
free(classes);
}
if (DevHasCursor(dev) && dev->spriteInfo->sprite) {
if (dev->spriteInfo->sprite->current)
FreeCursor(dev->spriteInfo->sprite->current, None);
free(dev->spriteInfo->sprite->spriteTrace);
free(dev->spriteInfo->sprite);
}
for (j = 0; j < currentMaxClients; j++)
{
if (clients[j] && clients[j]->clientPtr == dev)
{
clients[j]->clientPtr = NULL;
clients[j]->clientPtr = PickPointer(clients[j]);
}
}
free(dev->deviceGrab.sync.event);
free(dev->config_info);
dev->config_info = NULL;
dixFreeObjectWithPrivates(dev, PRIVATE_DEVICE);
}
static
void
CloseDeviceList(DeviceIntPtr *listHead)
{
Bool freedIds[MAXDEVICES];
DeviceIntPtr dev;
int i;
if (listHead == NULL)
return;
for (i = 0; i < MAXDEVICES; i++)
freedIds[i] = FALSE;
dev = *listHead;
while (dev != NULL)
{
freedIds[dev->id] = TRUE;
DeleteInputDeviceRequest(dev);
dev = *listHead;
while (dev != NULL && freedIds[dev->id])
dev = dev->next;
}
}
void
CloseDownDevices(void)
{
DeviceIntPtr dev;
for (dev = inputInfo.devices; dev; dev = dev->next)
{
if (!IsMaster(dev) && dev->u.master)
dev->u.master = NULL;
}
CloseDeviceList(&inputInfo.devices);
CloseDeviceList(&inputInfo.off_devices);
CloseDevice(inputInfo.pointer);
CloseDevice(inputInfo.keyboard);
inputInfo.devices = NULL;
inputInfo.off_devices = NULL;
inputInfo.keyboard = NULL;
inputInfo.pointer = NULL;
XkbDeleteRulesDflts();
}
void
UndisplayDevices(void)
{
DeviceIntPtr dev;
ScreenPtr screen = screenInfo.screens[0];
for (dev = inputInfo.devices; dev; dev = dev->next)
screen->DisplayCursor(dev, screen, NullCursor);
}
int
RemoveDevice(DeviceIntPtr dev, BOOL sendevent)
{
DeviceIntPtr prev,tmp,next;
int ret = BadMatch;
ScreenPtr screen = screenInfo.screens[0];
int deviceid;
int initialized;
int flags[MAXDEVICES] = {0};
DebugF("(dix) removing device %d\n", dev->id);
if (!dev || dev == inputInfo.keyboard || dev == inputInfo.pointer)
return BadImplementation;
initialized = dev->inited;
deviceid = dev->id;
if (initialized)
{
if (DevHasCursor(dev))
screen->DisplayCursor(dev, screen, NullCursor);
DisableDevice(dev, sendevent);
flags[dev->id] = XIDeviceDisabled;
}
prev = NULL;
for (tmp = inputInfo.devices; tmp; (prev = tmp), (tmp = next)) {
next = tmp->next;
if (tmp == dev) {
if (prev==NULL)
inputInfo.devices = next;
else
prev->next = next;
flags[tmp->id] = IsMaster(tmp) ? XIMasterRemoved : XISlaveRemoved;
CloseDevice(tmp);
ret = Success;
}
}
prev = NULL;
for (tmp = inputInfo.off_devices; tmp; (prev = tmp), (tmp = next)) {
next = tmp->next;
if (tmp == dev) {
flags[tmp->id] = IsMaster(tmp) ? XIMasterRemoved : XISlaveRemoved;
CloseDevice(tmp);
if (prev == NULL)
inputInfo.off_devices = next;
else
prev->next = next;
ret = Success;
}
}
if (ret == Success && initialized) {
inputInfo.numDevices--;
SendDevicePresenceEvent(deviceid, DeviceRemoved);
if (sendevent)
XISendDeviceHierarchyEvent(flags);
}
return ret;
}
int
NumMotionEvents(void)
{
return inputInfo.pointer->valuator->numMotionEvents;
}
int
dixLookupDevice(DeviceIntPtr *pDev, int id, ClientPtr client, Mask access_mode)
{
DeviceIntPtr dev;
int rc;
*pDev = NULL;
for (dev=inputInfo.devices; dev; dev=dev->next) {
if (dev->id == id)
goto found;
}
for (dev=inputInfo.off_devices; dev; dev=dev->next) {
if (dev->id == id)
goto found;
}
return BadDevice;
found:
rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, access_mode);
if (rc == Success)
*pDev = dev;
return rc;
}
void
QueryMinMaxKeyCodes(KeyCode *minCode, KeyCode *maxCode)
{
if (inputInfo.keyboard) {
*minCode = inputInfo.keyboard->key->xkbInfo->desc->min_key_code;
*maxCode = inputInfo.keyboard->key->xkbInfo->desc->max_key_code;
}
}
Bool
SetKeySymsMap(KeySymsPtr dst, KeySymsPtr src)
{
int i, j;
KeySym *tmp;
int rowDif = src->minKeyCode - dst->minKeyCode;
if (src->mapWidth < dst->mapWidth) {
for (i = src->minKeyCode; i <= src->maxKeyCode; i++) {
#define SI(r, c) (((r - src->minKeyCode) * src->mapWidth) + (c))
#define DI(r, c) (((r - dst->minKeyCode) * dst->mapWidth) + (c))
for (j = 0; j < src->mapWidth; j++)
dst->map[DI(i, j)] = src->map[SI(i, j)];
for (j = src->mapWidth; j < dst->mapWidth; j++)
dst->map[DI(i, j)] = NoSymbol;
#undef SI
#undef DI
}
return TRUE;
}
else if (src->mapWidth > dst->mapWidth) {
i = sizeof(KeySym) * src->mapWidth *
(dst->maxKeyCode - dst->minKeyCode + 1);
tmp = calloc(sizeof(KeySym), i);
if (!tmp)
return FALSE;
if (dst->map) {
for (i = 0; i <= dst->maxKeyCode-dst->minKeyCode; i++)
memmove(&tmp[i * src->mapWidth], &dst->map[i * dst->mapWidth],
dst->mapWidth * sizeof(KeySym));
free(dst->map);
}
dst->mapWidth = src->mapWidth;
dst->map = tmp;
}
else if (!dst->map) {
i = sizeof(KeySym) * src->mapWidth *
(dst->maxKeyCode - dst->minKeyCode + 1);
tmp = calloc(sizeof(KeySym), i);
if (!tmp)
return FALSE;
dst->map = tmp;
dst->mapWidth = src->mapWidth;
}
memmove(&dst->map[rowDif * dst->mapWidth], src->map,
(src->maxKeyCode - src->minKeyCode + 1) *
dst->mapWidth * sizeof(KeySym));
return TRUE;
}
Bool
InitButtonClassDeviceStruct(DeviceIntPtr dev, int numButtons, Atom* labels,
CARD8 *map)
{
ButtonClassPtr butc;
int i;
butc = calloc(1, sizeof(ButtonClassRec));
if (!butc)
return FALSE;
butc->numButtons = numButtons;
butc->sourceid = dev->id;
for (i = 1; i <= numButtons; i++)
butc->map[i] = map[i];
for (i = numButtons + 1; i < MAP_LENGTH; i++)
butc->map[i] = i;
memcpy(butc->labels, labels, numButtons * sizeof(Atom));
dev->button = butc;
return TRUE;
}
ValuatorClassPtr
AllocValuatorClass(ValuatorClassPtr src, int numAxes)
{
ValuatorClassPtr v;
union align_u { ValuatorClassRec valc; double d; } *align;
int size;
size = sizeof(union align_u) + numAxes * (sizeof(double) + sizeof(AxisInfo));
align = (union align_u *) realloc(src, size);
if (!align)
return NULL;
if (!src)
memset(align, 0, size);
v = &align->valc;
v->numAxes = numAxes;
v->axisVal = (double*)(align + 1);
v->axes = (AxisInfoPtr)(v->axisVal + numAxes);
return v;
}
Bool
InitValuatorClassDeviceStruct(DeviceIntPtr dev, int numAxes, Atom *labels,
int numMotionEvents, int mode)
{
int i;
ValuatorClassPtr valc;
if (!dev)
return FALSE;
if (numAxes > MAX_VALUATORS)
{
LogMessage(X_WARNING,
"Device '%s' has %d axes, only using first %d.\n",
dev->name, numAxes, MAX_VALUATORS);
numAxes = MAX_VALUATORS;
}
valc = AllocValuatorClass(NULL, numAxes);
if (!valc)
return FALSE;
valc->sourceid = dev->id;
valc->motion = NULL;
valc->first_motion = 0;
valc->last_motion = 0;
valc->numMotionEvents = numMotionEvents;
valc->motionHintWindow = NullWindow;
if (mode & OutOfProximity)
InitProximityClassDeviceStruct(dev);
dev->valuator = valc;
AllocateMotionHistory(dev);
for (i=0; i<numAxes; i++) {
InitValuatorAxisStruct(dev, i, labels[i], NO_AXIS_LIMITS, NO_AXIS_LIMITS,
0, 0, 0, mode);
valc->axisVal[i]=0;
}
dev->last.numValuators = numAxes;
if (IsMaster(dev) ||
IsXTestDevice(dev, NULL))
InitPointerAccelerationScheme(dev, PtrAccelNoOp);
else
InitPointerAccelerationScheme(dev, PtrAccelDefault);
return TRUE;
}
ValuatorAccelerationRec pointerAccelerationScheme[] = {
{PtrAccelNoOp, NULL, NULL, NULL},
{PtrAccelPredictable, acceleratePointerPredictable, NULL, AccelerationDefaultCleanup},
{PtrAccelLightweight, acceleratePointerLightweight, NULL, NULL},
{-1, NULL, NULL, NULL}
};
Bool
InitPointerAccelerationScheme(DeviceIntPtr dev,
int scheme)
{
int x, i = -1;
void* data = NULL;
ValuatorClassPtr val;
val = dev->valuator;
if(!val)
return FALSE;
if(IsMaster(dev) && scheme != PtrAccelNoOp)
return FALSE;
for(x = 0; pointerAccelerationScheme[x].number >= 0; x++) {
if(pointerAccelerationScheme[x].number == scheme){
i = x;
break;
}
}
if(-1 == i)
return FALSE;
if (val->accelScheme.AccelCleanupProc)
val->accelScheme.AccelCleanupProc(dev);
switch(scheme){
case PtrAccelPredictable:
{
DeviceVelocityPtr s;
s = malloc(sizeof(DeviceVelocityRec));
if(!s)
return FALSE;
InitVelocityData(s);
data = s;
break;
}
default:
break;
}
val->accelScheme = pointerAccelerationScheme[i];
val->accelScheme.accelData = data;
switch(scheme){
case PtrAccelPredictable:
InitializePredictableAccelerationProperties(dev);
break;
default:
break;
}
return TRUE;
}
Bool
InitAbsoluteClassDeviceStruct(DeviceIntPtr dev)
{
AbsoluteClassPtr abs;
abs = malloc(sizeof(AbsoluteClassRec));
if (!abs)
return FALSE;
abs->min_x = NO_AXIS_LIMITS;
abs->min_y = NO_AXIS_LIMITS;
abs->max_x = NO_AXIS_LIMITS;
abs->max_y = NO_AXIS_LIMITS;
abs->flip_x = 0;
abs->flip_y = 0;
abs->rotation = 0;
abs->button_threshold = 0;
abs->offset_x = 0;
abs->offset_y = 0;
abs->width = NO_AXIS_LIMITS;
abs->height = NO_AXIS_LIMITS;
abs->following = 0;
abs->screen = 0;
abs->sourceid = dev->id;
dev->absolute = abs;
return TRUE;
}
Bool
InitFocusClassDeviceStruct(DeviceIntPtr dev)
{
FocusClassPtr focc;
focc = malloc(sizeof(FocusClassRec));
if (!focc)
return FALSE;
focc->win = PointerRootWin;
focc->revert = None;
focc->time = currentTime;
focc->trace = (WindowPtr *)NULL;
focc->traceSize = 0;
focc->traceGood = 0;
focc->sourceid = dev->id;
dev->focus = focc;
return TRUE;
}
Bool
InitPtrFeedbackClassDeviceStruct(DeviceIntPtr dev, PtrCtrlProcPtr controlProc)
{
PtrFeedbackPtr feedc;
feedc = malloc(sizeof(PtrFeedbackClassRec));
if (!feedc)
return FALSE;
feedc->CtrlProc = controlProc;
feedc->ctrl = defaultPointerControl;
feedc->ctrl.id = 0;
if ( (feedc->next = dev->ptrfeed) )
feedc->ctrl.id = dev->ptrfeed->ctrl.id + 1;
dev->ptrfeed = feedc;
(*controlProc)(dev, &feedc->ctrl);
return TRUE;
}
static LedCtrl defaultLedControl = {
DEFAULT_LEDS, DEFAULT_LEDS_MASK, 0};
static BellCtrl defaultBellControl = {
DEFAULT_BELL,
DEFAULT_BELL_PITCH,
DEFAULT_BELL_DURATION,
0};
static IntegerCtrl defaultIntegerControl = {
DEFAULT_INT_RESOLUTION,
DEFAULT_INT_MIN_VALUE,
DEFAULT_INT_MAX_VALUE,
DEFAULT_INT_DISPLAYED,
0};
Bool
InitStringFeedbackClassDeviceStruct (
DeviceIntPtr dev, StringCtrlProcPtr controlProc,
int max_symbols, int num_symbols_supported, KeySym *symbols)
{
int i;
StringFeedbackPtr feedc;
feedc = malloc(sizeof(StringFeedbackClassRec));
if (!feedc)
return FALSE;
feedc->CtrlProc = controlProc;
feedc->ctrl.num_symbols_supported = num_symbols_supported;
feedc->ctrl.num_symbols_displayed = 0;
feedc->ctrl.max_symbols = max_symbols;
feedc->ctrl.symbols_supported = malloc(sizeof (KeySym) * num_symbols_supported);
feedc->ctrl.symbols_displayed = malloc(sizeof (KeySym) * max_symbols);
if (!feedc->ctrl.symbols_supported || !feedc->ctrl.symbols_displayed)
{
free(feedc->ctrl.symbols_supported);
free(feedc->ctrl.symbols_displayed);
free(feedc);
return FALSE;
}
for (i=0; i<num_symbols_supported; i++)
*(feedc->ctrl.symbols_supported+i) = *symbols++;
for (i=0; i<max_symbols; i++)
*(feedc->ctrl.symbols_displayed+i) = (KeySym) 0;
feedc->ctrl.id = 0;
if ( (feedc->next = dev->stringfeed) )
feedc->ctrl.id = dev->stringfeed->ctrl.id + 1;
dev->stringfeed = feedc;
(*controlProc)(dev, &feedc->ctrl);
return TRUE;
}
Bool
InitBellFeedbackClassDeviceStruct (DeviceIntPtr dev, BellProcPtr bellProc,
BellCtrlProcPtr controlProc)
{
BellFeedbackPtr feedc;
feedc = malloc(sizeof(BellFeedbackClassRec));
if (!feedc)
return FALSE;
feedc->CtrlProc = controlProc;
feedc->BellProc = bellProc;
feedc->ctrl = defaultBellControl;
feedc->ctrl.id = 0;
if ( (feedc->next = dev->bell) )
feedc->ctrl.id = dev->bell->ctrl.id + 1;
dev->bell = feedc;
(*controlProc)(dev, &feedc->ctrl);
return TRUE;
}
Bool
InitLedFeedbackClassDeviceStruct (DeviceIntPtr dev, LedCtrlProcPtr controlProc)
{
LedFeedbackPtr feedc;
feedc = malloc(sizeof(LedFeedbackClassRec));
if (!feedc)
return FALSE;
feedc->CtrlProc = controlProc;
feedc->ctrl = defaultLedControl;
feedc->ctrl.id = 0;
if ( (feedc->next = dev->leds) )
feedc->ctrl.id = dev->leds->ctrl.id + 1;
feedc->xkb_sli= NULL;
dev->leds = feedc;
(*controlProc)(dev, &feedc->ctrl);
return TRUE;
}
Bool
InitIntegerFeedbackClassDeviceStruct (DeviceIntPtr dev, IntegerCtrlProcPtr controlProc)
{
IntegerFeedbackPtr feedc;
feedc = malloc(sizeof(IntegerFeedbackClassRec));
if (!feedc)
return FALSE;
feedc->CtrlProc = controlProc;
feedc->ctrl = defaultIntegerControl;
feedc->ctrl.id = 0;
if ( (feedc->next = dev->intfeed) )
feedc->ctrl.id = dev->intfeed->ctrl.id + 1;
dev->intfeed = feedc;
(*controlProc)(dev, &feedc->ctrl);
return TRUE;
}
Bool
InitPointerDeviceStruct(DevicePtr device, CARD8 *map, int numButtons, Atom* btn_labels,
PtrCtrlProcPtr controlProc, int numMotionEvents,
int numAxes, Atom *axes_labels)
{
DeviceIntPtr dev = (DeviceIntPtr)device;
return(InitButtonClassDeviceStruct(dev, numButtons, btn_labels, map) &&
InitValuatorClassDeviceStruct(dev, numAxes, axes_labels,
numMotionEvents, Relative) &&
InitPtrFeedbackClassDeviceStruct(dev, controlProc));
}
Bool
BadDeviceMap(BYTE *buff, int length, unsigned low, unsigned high, XID *errval)
{
int i;
for (i = 0; i < length; i++)
if (buff[i])
{
if ((low > buff[i]) || (high < buff[i]))
{
*errval = buff[i];
return TRUE;
}
}
return FALSE;
}
int
ProcSetModifierMapping(ClientPtr client)
{
xSetModifierMappingReply rep;
int rc;
REQUEST(xSetModifierMappingReq);
REQUEST_AT_LEAST_SIZE(xSetModifierMappingReq);
if (client->req_len != ((stuff->numKeyPerModifier << 1) +
bytes_to_int32(sizeof(xSetModifierMappingReq))))
return BadLength;
rep.type = X_Reply;
rep.length = 0;
rep.sequenceNumber = client->sequence;
rc = change_modmap(client, PickKeyboard(client), (KeyCode *)&stuff[1],
stuff->numKeyPerModifier);
if (rc == MappingFailed || rc == -1)
return BadValue;
if (rc != Success && rc != MappingSuccess && rc != MappingFailed &&
rc != MappingBusy)
return rc;
rep.success = rc;
WriteReplyToClient(client, sizeof(xSetModifierMappingReply), &rep);
return Success;
}
int
ProcGetModifierMapping(ClientPtr client)
{
xGetModifierMappingReply rep;
int max_keys_per_mod = 0;
KeyCode *modkeymap = NULL;
REQUEST_SIZE_MATCH(xReq);
generate_modkeymap(client, PickKeyboard(client), &modkeymap,
&max_keys_per_mod);
memset(&rep, 0, sizeof(xGetModifierMappingReply));
rep.type = X_Reply;
rep.numKeyPerModifier = max_keys_per_mod;
rep.sequenceNumber = client->sequence;
rep.length = max_keys_per_mod << 1;
WriteReplyToClient(client, sizeof(xGetModifierMappingReply), &rep);
(void)WriteToClient(client, max_keys_per_mod * 8, (char *) modkeymap);
free(modkeymap);
return Success;
}
int
ProcChangeKeyboardMapping(ClientPtr client)
{
REQUEST(xChangeKeyboardMappingReq);
unsigned len;
KeySymsRec keysyms;
DeviceIntPtr pDev, tmp;
int rc;
REQUEST_AT_LEAST_SIZE(xChangeKeyboardMappingReq);
len = client->req_len - bytes_to_int32(sizeof(xChangeKeyboardMappingReq));
if (len != (stuff->keyCodes * stuff->keySymsPerKeyCode))
return BadLength;
pDev = PickKeyboard(client);
if ((stuff->firstKeyCode < pDev->key->xkbInfo->desc->min_key_code) ||
(stuff->firstKeyCode > pDev->key->xkbInfo->desc->max_key_code)) {
client->errorValue = stuff->firstKeyCode;
return BadValue;
}
if (((unsigned)(stuff->firstKeyCode + stuff->keyCodes - 1) >
pDev->key->xkbInfo->desc->max_key_code) ||
(stuff->keySymsPerKeyCode == 0)) {
client->errorValue = stuff->keySymsPerKeyCode;
return BadValue;
}
keysyms.minKeyCode = stuff->firstKeyCode;
keysyms.maxKeyCode = stuff->firstKeyCode + stuff->keyCodes - 1;
keysyms.mapWidth = stuff->keySymsPerKeyCode;
keysyms.map = (KeySym *) &stuff[1];
rc = XaceHook(XACE_DEVICE_ACCESS, client, pDev, DixManageAccess);
if (rc != Success)
return rc;
XkbApplyMappingChange(pDev, &keysyms, stuff->firstKeyCode,
stuff->keyCodes, NULL, client);
for (tmp = inputInfo.devices; tmp; tmp = tmp->next) {
if (IsMaster(tmp) || tmp->u.master != pDev)
continue;
if (!tmp->key)
continue;
rc = XaceHook(XACE_DEVICE_ACCESS, client, pDev, DixManageAccess);
if (rc != Success)
continue;
XkbApplyMappingChange(tmp, &keysyms, stuff->firstKeyCode,
stuff->keyCodes, NULL, client);
}
return Success;
}
int
ProcSetPointerMapping(ClientPtr client)
{
BYTE *map;
int ret;
int i, j;
DeviceIntPtr ptr = PickPointer(client);
xSetPointerMappingReply rep;
REQUEST(xSetPointerMappingReq);
REQUEST_AT_LEAST_SIZE(xSetPointerMappingReq);
if (client->req_len !=
bytes_to_int32(sizeof(xSetPointerMappingReq) + stuff->nElts))
return BadLength;
rep.type = X_Reply;
rep.length = 0;
rep.sequenceNumber = client->sequence;
rep.success = MappingSuccess;
map = (BYTE *)&stuff[1];
if (stuff->nElts != ptr->button->numButtons) {
client->errorValue = stuff->nElts;
return BadValue;
}
for (i = 0; i < stuff->nElts; i++) {
for (j = i + 1; j < stuff->nElts; j++) {
if (map[i] && map[i] == map[j]) {
client->errorValue = map[i];
return BadValue;
}
}
}
ret = ApplyPointerMapping(ptr, map, stuff->nElts, client);
if (ret == MappingBusy)
rep.success = ret;
else if (ret == -1)
return BadValue;
else if (ret != Success)
return ret;
WriteReplyToClient(client, sizeof(xSetPointerMappingReply), &rep);
return Success;
}
int
ProcGetKeyboardMapping(ClientPtr client)
{
xGetKeyboardMappingReply rep;
DeviceIntPtr kbd = PickKeyboard(client);
XkbDescPtr xkb;
KeySymsPtr syms;
int rc;
REQUEST(xGetKeyboardMappingReq);
REQUEST_SIZE_MATCH(xGetKeyboardMappingReq);
rc = XaceHook(XACE_DEVICE_ACCESS, client, kbd, DixGetAttrAccess);
if (rc != Success)
return rc;
xkb = kbd->key->xkbInfo->desc;
if ((stuff->firstKeyCode < xkb->min_key_code) ||
(stuff->firstKeyCode > xkb->max_key_code)) {
client->errorValue = stuff->firstKeyCode;
return BadValue;
}
if (stuff->firstKeyCode + stuff->count > xkb->max_key_code + 1) {
client->errorValue = stuff->count;
return BadValue;
}
syms = XkbGetCoreMap(kbd);
if (!syms)
return BadAlloc;
memset(&rep, 0, sizeof(xGetKeyboardMappingReply));
rep.type = X_Reply;
rep.sequenceNumber = client->sequence;
rep.keySymsPerKeyCode = syms->mapWidth;
rep.length = syms->mapWidth * stuff->count;
WriteReplyToClient(client, sizeof(xGetKeyboardMappingReply), &rep);
client->pSwapReplyFunc = (ReplySwapPtr) CopySwap32Write;
WriteSwappedDataToClient(client,
syms->mapWidth * stuff->count * sizeof(KeySym),
&syms->map[syms->mapWidth * (stuff->firstKeyCode -
syms->minKeyCode)]);
free(syms->map);
free(syms);
return Success;
}
int
ProcGetPointerMapping(ClientPtr client)
{
xGetPointerMappingReply rep;
DeviceIntPtr ptr = PickPointer(client);
ButtonClassPtr butc = ptr->button;
int rc;
REQUEST_SIZE_MATCH(xReq);
rc = XaceHook(XACE_DEVICE_ACCESS, client, ptr, DixGetAttrAccess);
if (rc != Success)
return rc;
rep.type = X_Reply;
rep.sequenceNumber = client->sequence;
rep.nElts = (butc) ? butc->numButtons : 0;
rep.length = ((unsigned)rep.nElts + (4-1))/4;
WriteReplyToClient(client, sizeof(xGetPointerMappingReply), &rep);
if (butc)
WriteToClient(client, (int)rep.nElts, (char *)&butc->map[1]);
return Success;
}
void
NoteLedState(DeviceIntPtr keybd, int led, Bool on)
{
KeybdCtrl *ctrl = &keybd->kbdfeed->ctrl;
if (on)
ctrl->leds |= ((Leds)1 << (led - 1));
else
ctrl->leds &= ~((Leds)1 << (led - 1));
}
int
Ones(unsigned long mask)
{
unsigned long y;
y = (mask >> 1) &033333333333;
y = mask - y - ((y >>1) & 033333333333);
return (((y + (y >> 3)) & 030707070707) % 077);
}
static int
DoChangeKeyboardControl (ClientPtr client, DeviceIntPtr keybd, XID *vlist,
BITS32 vmask)
{
#define DO_ALL (-1)
KeybdCtrl ctrl;
int t;
int led = DO_ALL;
int key = DO_ALL;
BITS32 index2;
int mask = vmask, i;
XkbEventCauseRec cause;
ctrl = keybd->kbdfeed->ctrl;
while (vmask) {
index2 = (BITS32) lowbit (vmask);
vmask &= ~index2;
switch (index2) {
case KBKeyClickPercent:
t = (INT8)*vlist;
vlist++;
if (t == -1) {
t = defaultKeyboardControl.click;
}
else if (t < 0 || t > 100) {
client->errorValue = t;
return BadValue;
}
ctrl.click = t;
break;
case KBBellPercent:
t = (INT8)*vlist;
vlist++;
if (t == -1) {
t = defaultKeyboardControl.bell;
}
else if (t < 0 || t > 100) {
client->errorValue = t;
return BadValue;
}
ctrl.bell = t;
break;
case KBBellPitch:
t = (INT16)*vlist;
vlist++;
if (t == -1) {
t = defaultKeyboardControl.bell_pitch;
}
else if (t < 0) {
client->errorValue = t;
return BadValue;
}
ctrl.bell_pitch = t;
break;
case KBBellDuration:
t = (INT16)*vlist;
vlist++;
if (t == -1)
t = defaultKeyboardControl.bell_duration;
else if (t < 0) {
client->errorValue = t;
return BadValue;
}
ctrl.bell_duration = t;
break;
case KBLed:
led = (CARD8)*vlist;
vlist++;
if (led < 1 || led > 32) {
client->errorValue = led;
return BadValue;
}
if (!(mask & KBLedMode))
return BadMatch;
break;
case KBLedMode:
t = (CARD8)*vlist;
vlist++;
if (t == LedModeOff) {
if (led == DO_ALL)
ctrl.leds = 0x0;
else
ctrl.leds &= ~(((Leds)(1)) << (led - 1));
}
else if (t == LedModeOn) {
if (led == DO_ALL)
ctrl.leds = ~0L;
else
ctrl.leds |= (((Leds)(1)) << (led - 1));
}
else {
client->errorValue = t;
return BadValue;
}
XkbSetCauseCoreReq(&cause,X_ChangeKeyboardControl,client);
XkbSetIndicators(keybd,((led == DO_ALL) ? ~0L : (1L<<(led-1))),
ctrl.leds, &cause);
ctrl.leds = keybd->kbdfeed->ctrl.leds;
break;
case KBKey:
key = (KeyCode)*vlist;
vlist++;
if ((KeyCode)key < keybd->key->xkbInfo->desc->min_key_code ||
(KeyCode)key > keybd->key->xkbInfo->desc->max_key_code) {
client->errorValue = key;
return BadValue;
}
if (!(mask & KBAutoRepeatMode))
return BadMatch;
break;
case KBAutoRepeatMode:
i = (key >> 3);
mask = (1 << (key & 7));
t = (CARD8)*vlist;
vlist++;
if (key != DO_ALL)
XkbDisableComputedAutoRepeats(keybd,key);
if (t == AutoRepeatModeOff) {
if (key == DO_ALL)
ctrl.autoRepeat = FALSE;
else
ctrl.autoRepeats[i] &= ~mask;
}
else if (t == AutoRepeatModeOn) {
if (key == DO_ALL)
ctrl.autoRepeat = TRUE;
else
ctrl.autoRepeats[i] |= mask;
}
else if (t == AutoRepeatModeDefault) {
if (key == DO_ALL)
ctrl.autoRepeat = defaultKeyboardControl.autoRepeat;
else
ctrl.autoRepeats[i] =
(ctrl.autoRepeats[i] & ~mask) |
(defaultKeyboardControl.autoRepeats[i] & mask);
}
else {
client->errorValue = t;
return BadValue;
}
break;
default:
client->errorValue = mask;
return BadValue;
}
}
keybd->kbdfeed->ctrl = ctrl;
XkbSetRepeatKeys(keybd, key, keybd->kbdfeed->ctrl.autoRepeat);
return Success;
#undef DO_ALL
}
int
ProcChangeKeyboardControl (ClientPtr client)
{
XID *vlist;
BITS32 vmask;
int ret = Success, error = Success;
DeviceIntPtr pDev = NULL, keyboard;
REQUEST(xChangeKeyboardControlReq);
REQUEST_AT_LEAST_SIZE(xChangeKeyboardControlReq);
vmask = stuff->mask;
vlist = (XID *)&stuff[1];
if (client->req_len != (sizeof(xChangeKeyboardControlReq)>>2)+Ones(vmask))
return BadLength;
keyboard = PickKeyboard(client);
for (pDev = inputInfo.devices; pDev; pDev = pDev->next) {
if ((pDev == keyboard ||
(!IsMaster(pDev) && GetMaster(pDev, MASTER_KEYBOARD) == keyboard))
&& pDev->kbdfeed && pDev->kbdfeed->CtrlProc) {
ret = XaceHook(XACE_DEVICE_ACCESS, client, pDev, DixManageAccess);
if (ret != Success)
return ret;
}
}
for (pDev = inputInfo.devices; pDev; pDev = pDev->next) {
if ((pDev == keyboard ||
(!IsMaster(pDev) && GetMaster(pDev, MASTER_KEYBOARD) == keyboard))
&& pDev->kbdfeed && pDev->kbdfeed->CtrlProc) {
ret = DoChangeKeyboardControl(client, pDev, vlist, vmask);
if (ret != Success)
error = ret;
}
}
return error;
}
int
ProcGetKeyboardControl (ClientPtr client)
{
int rc, i;
DeviceIntPtr kbd = PickKeyboard(client);
KeybdCtrl *ctrl = &kbd->kbdfeed->ctrl;
xGetKeyboardControlReply rep;
REQUEST_SIZE_MATCH(xReq);
rc = XaceHook(XACE_DEVICE_ACCESS, client, kbd, DixGetAttrAccess);
if (rc != Success)
return rc;
rep.type = X_Reply;
rep.length = 5;
rep.sequenceNumber = client->sequence;
rep.globalAutoRepeat = ctrl->autoRepeat;
rep.keyClickPercent = ctrl->click;
rep.bellPercent = ctrl->bell;
rep.bellPitch = ctrl->bell_pitch;
rep.bellDuration = ctrl->bell_duration;
rep.ledMask = ctrl->leds;
for (i = 0; i < 32; i++)
rep.map[i] = ctrl->autoRepeats[i];
WriteReplyToClient(client, sizeof(xGetKeyboardControlReply), &rep);
return Success;
}
int
ProcBell(ClientPtr client)
{
DeviceIntPtr dev, keybd = PickKeyboard(client);
int base = keybd->kbdfeed->ctrl.bell;
int newpercent;
int rc;
REQUEST(xBellReq);
REQUEST_SIZE_MATCH(xBellReq);
if (stuff->percent < -100 || stuff->percent > 100) {
client->errorValue = stuff->percent;
return BadValue;
}
newpercent = (base * stuff->percent) / 100;
if (stuff->percent < 0)
newpercent = base + newpercent;
else
newpercent = base - newpercent + stuff->percent;
for (dev = inputInfo.devices; dev; dev = dev->next) {
if ((dev == keybd ||
(!IsMaster(dev) && GetMaster(dev, MASTER_KEYBOARD) == keybd)) &&
dev->kbdfeed && dev->kbdfeed->BellProc) {
rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixBellAccess);
if (rc != Success)
return rc;
XkbHandleBell(FALSE, FALSE, dev, newpercent,
&dev->kbdfeed->ctrl, 0, None, NULL, client);
}
}
return Success;
}
int
ProcChangePointerControl(ClientPtr client)
{
DeviceIntPtr dev, mouse = PickPointer(client);
PtrCtrl ctrl;
int rc;
REQUEST(xChangePointerControlReq);
REQUEST_SIZE_MATCH(xChangePointerControlReq);
ctrl = mouse->ptrfeed->ctrl;
if ((stuff->doAccel != xTrue) && (stuff->doAccel != xFalse)) {
client->errorValue = stuff->doAccel;
return BadValue;
}
if ((stuff->doThresh != xTrue) && (stuff->doThresh != xFalse)) {
client->errorValue = stuff->doThresh;
return BadValue;
}
if (stuff->doAccel) {
if (stuff->accelNum == -1) {
ctrl.num = defaultPointerControl.num;
}
else if (stuff->accelNum < 0) {
client->errorValue = stuff->accelNum;
return BadValue;
}
else {
ctrl.num = stuff->accelNum;
}
if (stuff->accelDenum == -1) {
ctrl.den = defaultPointerControl.den;
}
else if (stuff->accelDenum <= 0) {
client->errorValue = stuff->accelDenum;
return BadValue;
}
else {
ctrl.den = stuff->accelDenum;
}
}
if (stuff->doThresh) {
if (stuff->threshold == -1) {
ctrl.threshold = defaultPointerControl.threshold;
}
else if (stuff->threshold < 0) {
client->errorValue = stuff->threshold;
return BadValue;
}
else {
ctrl.threshold = stuff->threshold;
}
}
for (dev = inputInfo.devices; dev; dev = dev->next) {
if ((dev == mouse ||
(!IsMaster(dev) && GetMaster(dev, MASTER_POINTER) == mouse)) &&
dev->ptrfeed) {
rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixManageAccess);
if (rc != Success)
return rc;
}
}
for (dev = inputInfo.devices; dev; dev = dev->next) {
if ((dev == mouse ||
(!IsMaster(dev) && GetMaster(dev, MASTER_POINTER) == mouse)) &&
dev->ptrfeed) {
dev->ptrfeed->ctrl = ctrl;
}
}
return Success;
}
int
ProcGetPointerControl(ClientPtr client)
{
DeviceIntPtr ptr = PickPointer(client);
PtrCtrl *ctrl = &ptr->ptrfeed->ctrl;
xGetPointerControlReply rep;
int rc;
REQUEST_SIZE_MATCH(xReq);
rc = XaceHook(XACE_DEVICE_ACCESS, client, ptr, DixGetAttrAccess);
if (rc != Success)
return rc;
rep.type = X_Reply;
rep.length = 0;
rep.sequenceNumber = client->sequence;
rep.threshold = ctrl->threshold;
rep.accelNumerator = ctrl->num;
rep.accelDenominator = ctrl->den;
WriteReplyToClient(client, sizeof(xGenericReply), &rep);
return Success;
}
void
MaybeStopHint(DeviceIntPtr dev, ClientPtr client)
{
GrabPtr grab = dev->deviceGrab.grab;
if ((grab && SameClient(grab, client) &&
((grab->eventMask & PointerMotionHintMask) ||
(grab->ownerEvents &&
(EventMaskForClient(dev->valuator->motionHintWindow, client) &
PointerMotionHintMask)))) ||
(!grab &&
(EventMaskForClient(dev->valuator->motionHintWindow, client) &
PointerMotionHintMask)))
dev->valuator->motionHintWindow = NullWindow;
}
int
ProcGetMotionEvents(ClientPtr client)
{
WindowPtr pWin;
xTimecoord * coords = (xTimecoord *) NULL;
xGetMotionEventsReply rep;
int i, count, xmin, xmax, ymin, ymax, rc;
unsigned long nEvents;
DeviceIntPtr mouse = PickPointer(client);
TimeStamp start, stop;
REQUEST(xGetMotionEventsReq);
REQUEST_SIZE_MATCH(xGetMotionEventsReq);
rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
if (rc != Success)
return rc;
rc = XaceHook(XACE_DEVICE_ACCESS, client, mouse, DixReadAccess);
if (rc != Success)
return rc;
if (mouse->valuator->motionHintWindow)
MaybeStopHint(mouse, client);
rep.type = X_Reply;
rep.sequenceNumber = client->sequence;
nEvents = 0;
start = ClientTimeToServerTime(stuff->start);
stop = ClientTimeToServerTime(stuff->stop);
if ((CompareTimeStamps(start, stop) != LATER) &&
(CompareTimeStamps(start, currentTime) != LATER) &&
mouse->valuator->numMotionEvents)
{
if (CompareTimeStamps(stop, currentTime) == LATER)
stop = currentTime;
count = GetMotionHistory(mouse, &coords, start.milliseconds,
stop.milliseconds, pWin->drawable.pScreen,
TRUE);
xmin = pWin->drawable.x - wBorderWidth (pWin);
xmax = pWin->drawable.x + (int)pWin->drawable.width +
wBorderWidth (pWin);
ymin = pWin->drawable.y - wBorderWidth (pWin);
ymax = pWin->drawable.y + (int)pWin->drawable.height +
wBorderWidth (pWin);
for (i = 0; i < count; i++)
if ((xmin <= coords[i].x) && (coords[i].x < xmax) &&
(ymin <= coords[i].y) && (coords[i].y < ymax))
{
coords[nEvents].time = coords[i].time;
coords[nEvents].x = coords[i].x - pWin->drawable.x;
coords[nEvents].y = coords[i].y - pWin->drawable.y;
nEvents++;
}
}
rep.length = nEvents * bytes_to_int32(sizeof(xTimecoord));
rep.nEvents = nEvents;
WriteReplyToClient(client, sizeof(xGetMotionEventsReply), &rep);
if (nEvents)
{
client->pSwapReplyFunc = (ReplySwapPtr) SwapTimeCoordWrite;
WriteSwappedDataToClient(client, nEvents * sizeof(xTimecoord),
(char *)coords);
}
free(coords);
return Success;
}
int
ProcQueryKeymap(ClientPtr client)
{
xQueryKeymapReply rep;
int rc, i;
DeviceIntPtr keybd = PickKeyboard(client);
CARD8 *down = keybd->key->down;
REQUEST_SIZE_MATCH(xReq);
rep.type = X_Reply;
rep.sequenceNumber = client->sequence;
rep.length = 2;
rc = XaceHook(XACE_DEVICE_ACCESS, client, keybd, DixReadAccess);
if (rc != Success && rc != BadAccess)
return rc;
for (i = 0; i<32; i++)
rep.map[i] = down[i];
if (rc == BadAccess)
memset(rep.map, 0, 32);
WriteReplyToClient(client, sizeof(xQueryKeymapReply), &rep);
return Success;
}
static void
RecalculateMasterButtons(DeviceIntPtr slave)
{
DeviceIntPtr dev, master;
int maxbuttons = 0;
if (!slave->button || IsMaster(slave))
return;
master = GetMaster(slave, MASTER_POINTER);
if (!master)
return;
for (dev = inputInfo.devices; dev; dev = dev->next)
{
if (IsMaster(dev) ||
dev->u.master != master ||
!dev->button)
continue;
maxbuttons = max(maxbuttons, dev->button->numButtons);
}
if (master->button && master->button->numButtons != maxbuttons)
{
int i;
DeviceChangedEvent event;
memset(&event, 0, sizeof(event));
master->button->numButtons = maxbuttons;
event.header = ET_Internal;
event.type = ET_DeviceChanged;
event.time = GetTimeInMillis();
event.deviceid = master->id;
event.flags = DEVCHANGE_POINTER_EVENT | DEVCHANGE_DEVICE_CHANGE;
event.buttons.num_buttons = maxbuttons;
memcpy(&event.buttons.names, master->button->labels, maxbuttons *
sizeof(Atom));
if (master->valuator)
{
event.num_valuators = master->valuator->numAxes;
for (i = 0; i < event.num_valuators; i++)
{
event.valuators[i].min = master->valuator->axes[i].min_value;
event.valuators[i].max = master->valuator->axes[i].max_value;
event.valuators[i].resolution = master->valuator->axes[i].resolution;
event.valuators[i].mode = master->valuator->axes[i].mode;
event.valuators[i].name = master->valuator->axes[i].label;
}
}
if (master->key)
{
event.keys.min_keycode = master->key->xkbInfo->desc->min_key_code;
event.keys.max_keycode = master->key->xkbInfo->desc->max_key_code;
}
XISendDeviceChangedEvent(master, master, &event);
}
}
int
AttachDevice(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr master)
{
ScreenPtr screen;
DeviceIntPtr oldmaster;
if (!dev || IsMaster(dev))
return BadDevice;
if (master && !IsMaster(master))
return BadDevice;
if (!dev->u.master && !master && dev->enabled)
return Success;
if (!dev->u.master && dev->spriteInfo->paired == dev)
{
screen = miPointerGetScreen(dev);
screen->DeviceCursorCleanup(dev, screen);
free(dev->spriteInfo->sprite);
}
oldmaster = dev->u.master;
dev->u.master = master;
if (!master)
{
WindowPtr currentRoot;
if (dev->spriteInfo->sprite)
currentRoot = GetCurrentRootWindow(dev);
else
currentRoot = screenInfo.screens[0]->root;
screen = currentRoot->drawable.pScreen;
screen->DeviceCursorInitialize(dev, screen);
dev->spriteInfo->sprite = NULL;
InitializeSprite(dev, currentRoot);
dev->spriteInfo->spriteOwner = FALSE;
dev->spriteInfo->paired = dev;
} else
{
dev->spriteInfo->sprite = master->spriteInfo->sprite;
dev->spriteInfo->paired = master;
dev->spriteInfo->spriteOwner = FALSE;
RecalculateMasterButtons(master);
}
return Success;
}
DeviceIntPtr
GetPairedDevice(DeviceIntPtr dev)
{
if (!IsMaster(dev) && dev->u.master)
dev = dev->u.master;
return dev->spriteInfo->paired;
}
DeviceIntPtr
GetMaster(DeviceIntPtr dev, int which)
{
DeviceIntPtr master;
if (IsMaster(dev))
master = dev;
else
master = dev->u.master;
if (master)
{
if (which == MASTER_KEYBOARD)
{
if (master->type != MASTER_KEYBOARD)
master = GetPairedDevice(master);
} else
{
if (master->type != MASTER_POINTER)
master = GetPairedDevice(master);
}
}
return master;
}
int
AllocDevicePair (ClientPtr client, char* name,
DeviceIntPtr* ptr,
DeviceIntPtr* keybd,
DeviceProc ptr_proc,
DeviceProc keybd_proc,
Bool master)
{
DeviceIntPtr pointer;
DeviceIntPtr keyboard;
*ptr = *keybd = NULL;
pointer = AddInputDevice(client, ptr_proc, TRUE);
if (!pointer)
return BadAlloc;
if (asprintf(&pointer->name, "%s pointer", name) == -1) {
pointer->name = NULL;
RemoveDevice(pointer, FALSE);
return BadAlloc;
}
pointer->public.processInputProc = ProcessOtherEvent;
pointer->public.realInputProc = ProcessOtherEvent;
XkbSetExtension(pointer, ProcessPointerEvent);
pointer->deviceGrab.ActivateGrab = ActivatePointerGrab;
pointer->deviceGrab.DeactivateGrab = DeactivatePointerGrab;
pointer->coreEvents = TRUE;
pointer->spriteInfo->spriteOwner = TRUE;
pointer->u.lastSlave = NULL;
pointer->last.slave = NULL;
pointer->type = (master) ? MASTER_POINTER : SLAVE;
keyboard = AddInputDevice(client, keybd_proc, TRUE);
if (!keyboard)
{
RemoveDevice(pointer, FALSE);
return BadAlloc;
}
if (asprintf(&keyboard->name, "%s keyboard", name) == -1) {
keyboard->name = NULL;
RemoveDevice(keyboard, FALSE);
RemoveDevice(pointer, FALSE);
return BadAlloc;
}
keyboard->public.processInputProc = ProcessOtherEvent;
keyboard->public.realInputProc = ProcessOtherEvent;
XkbSetExtension(keyboard, ProcessKeyboardEvent);
keyboard->deviceGrab.ActivateGrab = ActivateKeyboardGrab;
keyboard->deviceGrab.DeactivateGrab = DeactivateKeyboardGrab;
keyboard->coreEvents = TRUE;
keyboard->spriteInfo->spriteOwner = FALSE;
keyboard->u.lastSlave = NULL;
keyboard->last.slave = NULL;
keyboard->type = (master) ? MASTER_KEYBOARD : SLAVE;
pointer->unused_classes = calloc(1, sizeof(ClassesRec));
keyboard->unused_classes = calloc(1, sizeof(ClassesRec));
*ptr = pointer;
*keybd = keyboard;
return Success;
}
int valuator_get_mode(DeviceIntPtr dev, int axis)
{
return (dev->valuator->axes[axis].mode & DeviceMode);
}
void valuator_set_mode(DeviceIntPtr dev, int axis, int mode)
{
if (axis != VALUATOR_MODE_ALL_AXES)
dev->valuator->axes[axis].mode = mode;
else {
int i;
for (i = 0; i < dev->valuator->numAxes; i++)
dev->valuator->axes[i].mode = mode;
}
}