/************************************************************ Copyright 1987, 1998 The Open Group Permission to use, copy, modify, distribute, and sell this software and its documentation for any purpose is hereby granted without fee, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation. The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Except as contained in this notice, the name of The Open Group shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from The Open Group. Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. All Rights Reserved Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation, and that the name of Digital not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ********************************************************/ #ifdef HAVE_DIX_CONFIG_H #include #endif #include #include "misc.h" #include "resource.h" #define NEED_EVENTS #define NEED_REPLIES #include #include "windowstr.h" #include "inputstr.h" #include "scrnintstr.h" #include "cursorstr.h" #include "dixstruct.h" #include "site.h" #ifndef XKB_IN_SERVER #define XKB_IN_SERVER #endif #ifdef XKB #include #endif #include "xace.h" #include "dispatch.h" #include "swaprep.h" #include "dixevents.h" #include #include "exglobals.h" #include "exevents.h" int CoreDevicePrivatesIndex = 0, CoreDevicePrivatesGeneration = -1; /* The client that is allowed to change pointer-keyboard pairings. */ static ClientPtr pairingClient = NULL; DeviceIntPtr AddInputDevice(DeviceProc deviceProc, Bool autoStart) { register DeviceIntPtr dev, *prev; /* not a typo */ if (inputInfo.numDevices >= MAX_DEVICES) return (DeviceIntPtr)NULL; dev = (DeviceIntPtr) xcalloc(sizeof(DeviceIntRec), 1); if (!dev) return (DeviceIntPtr)NULL; dev->name = (char *)NULL; dev->type = 0; dev->id = inputInfo.numDevices; inputInfo.numDevices++; dev->public.on = FALSE; dev->public.processInputProc = (ProcessInputProc)NoopDDA; dev->public.realInputProc = (ProcessInputProc)NoopDDA; dev->public.enqueueInputProc = EnqueueEvent; dev->deviceProc = deviceProc; dev->startup = autoStart; dev->sync.frozen = FALSE; dev->sync.other = NullGrab; dev->sync.state = NOT_GRABBED; dev->sync.event = (xEvent *) NULL; dev->sync.evcount = 0; dev->grab = NullGrab; dev->grabTime = currentTime; dev->fromPassiveGrab = FALSE; dev->key = (KeyClassPtr)NULL; dev->valuator = (ValuatorClassPtr)NULL; dev->button = (ButtonClassPtr)NULL; dev->focus = (FocusClassPtr)NULL; dev->proximity = (ProximityClassPtr)NULL; dev->absolute = (AbsoluteClassPtr)NULL; dev->kbdfeed = (KbdFeedbackPtr)NULL; dev->ptrfeed = (PtrFeedbackPtr)NULL; dev->intfeed = (IntegerFeedbackPtr)NULL; dev->stringfeed = (StringFeedbackPtr)NULL; dev->bell = (BellFeedbackPtr)NULL; dev->leds = (LedFeedbackPtr)NULL; #ifdef XKB dev->xkb_interest = NULL; #endif dev->nPrivates = 0; dev->devPrivates = NULL; dev->unwrapProc = NULL; dev->coreEvents = TRUE; dev->inited = FALSE; dev->enabled = FALSE; for (prev = &inputInfo.off_devices; *prev; prev = &(*prev)->next) ; *prev = dev; dev->next = NULL; return dev; } Bool EnableDevice(register DeviceIntPtr dev) { register DeviceIntPtr *prev; int ret; for (prev = &inputInfo.off_devices; *prev && (*prev != dev); prev = &(*prev)->next) ; if ((*prev != dev) || !dev->inited || ((ret = (*dev->deviceProc)(dev, DEVICE_ON)) != Success)) { ErrorF("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; return TRUE; } Bool DisableDevice(register DeviceIntPtr dev) { register DeviceIntPtr *prev; for (prev = &inputInfo.devices; *prev && (*prev != dev); prev = &(*prev)->next) ; if (*prev != dev) return FALSE; (void)(*dev->deviceProc)(dev, DEVICE_OFF); dev->enabled = FALSE; *prev = dev->next; dev->next = inputInfo.off_devices; inputInfo.off_devices = dev; return TRUE; } int ActivateDevice(DeviceIntPtr dev) { int ret = Success; devicePresenceNotify ev; DeviceIntRec dummyDev; if (!dev || !dev->deviceProc) return BadImplementation; ret = (*dev->deviceProc) (dev, DEVICE_INIT); dev->inited = (ret == Success); ev.type = DevicePresenceNotify; ev.time = currentTime.milliseconds; ev.devchange = 0; ev.deviceid = 0; dummyDev.id = 0; SendEventToAllWindows(&dummyDev, DevicePresenceNotifyMask, (xEvent *) &ev, 1); 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; } static int CoreKeyboardProc(DeviceIntPtr pDev, int what) { CARD8 *modMap; KeySymsRec keySyms; #ifdef XKB XkbComponentNamesRec names; #endif switch (what) { case DEVICE_INIT: keySyms.minKeyCode = 8; keySyms.maxKeyCode = 255; keySyms.mapWidth = 4; keySyms.map = (KeySym *)xcalloc(sizeof(KeySym), (keySyms.maxKeyCode - keySyms.minKeyCode) * keySyms.mapWidth); if (!keySyms.map) { ErrorF("Couldn't allocate core keymap\n"); return BadAlloc; } modMap = (CARD8 *)xalloc(MAP_LENGTH); if (!modMap) { ErrorF("Couldn't allocate core modifier map\n"); return BadAlloc; } bzero((char *)modMap, MAP_LENGTH); #ifdef XKB if (!noXkbExtension) { bzero(&names, sizeof(names)); XkbSetRulesDflts("base", "pc105", "us", NULL, NULL); XkbInitKeyboardDeviceStruct(pDev, &names, &keySyms, modMap, CoreKeyboardBell, CoreKeyboardCtl); } else #endif { /* FIXME Our keymap here isn't exactly useful. */ InitKeyboardDeviceStruct((DevicePtr)pDev, &keySyms, modMap, CoreKeyboardBell, CoreKeyboardCtl); } xfree(keySyms.map); xfree(modMap); break; case DEVICE_CLOSE: pDev->devPrivates[CoreDevicePrivatesIndex].ptr = NULL; break; default: break; } return Success; } static int CorePointerProc(DeviceIntPtr pDev, int what) { BYTE map[33]; int i = 0; switch (what) { case DEVICE_INIT: for (i = 1; i <= 32; i++) map[i] = i; InitPointerDeviceStruct((DevicePtr)pDev, map, 32, GetMotionHistory, (PtrCtrlProcPtr)NoopDDA, GetMotionHistorySize(), 2); pDev->valuator->axisVal[0] = screenInfo.screens[0]->width / 2; pDev->valuator->lastx = pDev->valuator->axisVal[0]; pDev->valuator->axisVal[1] = screenInfo.screens[0]->height / 2; pDev->valuator->lasty = pDev->valuator->axisVal[1]; break; case DEVICE_CLOSE: pDev->devPrivates[CoreDevicePrivatesIndex].ptr = NULL; break; default: break; } return Success; } void InitCoreDevices() { register DeviceIntPtr dev; if (CoreDevicePrivatesGeneration != serverGeneration) { CoreDevicePrivatesIndex = AllocateDevicePrivateIndex(); CoreDevicePrivatesGeneration = serverGeneration; } if (!inputInfo.keyboard) { dev = AddInputDevice(CoreKeyboardProc, TRUE); if (!dev) FatalError("Failed to allocate core keyboard"); dev->name = strdup("Virtual core keyboard"); #ifdef XKB dev->public.processInputProc = CoreProcessKeyboardEvent; dev->public.realInputProc = CoreProcessKeyboardEvent; if (!noXkbExtension) XkbSetExtension(dev, ProcessKeyboardEvent); #else dev->public.processInputProc = ProcessKeyboardEvent; dev->public.realInputProc = ProcessKeyboardEvent; #endif dev->ActivateGrab = ActivateKeyboardGrab; dev->DeactivateGrab = DeactivateKeyboardGrab; dev->coreEvents = FALSE; dev->spriteOwner = FALSE; if (!AllocateDevicePrivate(dev, CoreDevicePrivatesIndex)) FatalError("Couldn't allocate keyboard devPrivates\n"); dev->devPrivates[CoreDevicePrivatesIndex].ptr = NULL; (void)ActivateDevice(dev); inputInfo.keyboard = dev; } if (!inputInfo.pointer) { dev = AddInputDevice(CorePointerProc, TRUE); if (!dev) FatalError("Failed to allocate core pointer"); dev->name = strdup("Virtual core pointer"); #ifdef XKB dev->public.processInputProc = CoreProcessPointerEvent; dev->public.realInputProc = CoreProcessPointerEvent; if (!noXkbExtension) XkbSetExtension(dev, ProcessPointerEvent); #else dev->public.processInputProc = ProcessPointerEvent; dev->public.realInputProc = ProcessPointerEvent; #endif dev->ActivateGrab = ActivatePointerGrab; dev->DeactivateGrab = DeactivatePointerGrab; dev->coreEvents = FALSE; if (!AllocateDevicePrivate(dev, CoreDevicePrivatesIndex)) FatalError("Couldn't allocate pointer devPrivates\n"); dev->devPrivates[CoreDevicePrivatesIndex].ptr = NULL; InitializeSprite(dev, NullWindow); (void)ActivateDevice(dev); inputInfo.pointer = dev; /* the core keyboard is initialised by now. set the keyboard's sprite * to the core pointer's sprite. */ PairDevices(pairingClient, inputInfo.pointer, inputInfo.keyboard); } } int InitAndStartDevices() { register DeviceIntPtr dev, next; for (dev = inputInfo.off_devices; dev; dev = dev->next) { DebugF("(dix) initialising device %d\n", dev->id); ActivateDevice(dev); } for (dev = inputInfo.off_devices; dev; dev = next) { DebugF("(dix) enabling device %d\n", dev->id); next = dev->next; if (dev->inited && dev->startup) (void)EnableDevice(dev); } for (dev = inputInfo.devices; dev && (dev != inputInfo.keyboard); dev = dev->next) if (!dev || (dev != inputInfo.keyboard)) { ErrorF("No core keyboard\n"); return BadImplementation; } for (dev = inputInfo.devices; dev && (dev != inputInfo.pointer); dev = dev->next) ; if (!dev || (dev != inputInfo.pointer)) { ErrorF("No core pointer\n"); return BadImplementation; } return Success; } static void CloseDevice(register DeviceIntPtr dev) { KbdFeedbackPtr k, knext; PtrFeedbackPtr p, pnext; IntegerFeedbackPtr i, inext; StringFeedbackPtr s, snext; BellFeedbackPtr b, bnext; LedFeedbackPtr l, lnext; int j; if (dev->inited) (void)(*dev->deviceProc)(dev, DEVICE_CLOSE); xfree(dev->name); if (dev->key) { #ifdef XKB if (dev->key->xkbInfo) XkbFreeInfo(dev->key->xkbInfo); #endif xfree(dev->key->curKeySyms.map); xfree(dev->key->modifierKeyMap); xfree(dev->key); } if (dev->valuator) xfree(dev->valuator); if (dev->button) { #ifdef XKB if (dev->button->xkb_acts) xfree(dev->button->xkb_acts); #endif xfree(dev->button); } if (dev->focus) { xfree(dev->focus->trace); xfree(dev->focus); } if (dev->proximity) xfree(dev->proximity); for (k = dev->kbdfeed; k; k = knext) { knext = k->next; #ifdef XKB if (k->xkb_sli) XkbFreeSrvLedInfo(k->xkb_sli); #endif xfree(k); } for (p = dev->ptrfeed; p; p = pnext) { pnext = p->next; xfree(p); } for (i = dev->intfeed; i; i = inext) { inext = i->next; xfree(i); } for (s = dev->stringfeed; s; s = snext) { snext = s->next; xfree(s->ctrl.symbols_supported); xfree(s->ctrl.symbols_displayed); xfree(s); } for (b = dev->bell; b; b = bnext) { bnext = b->next; xfree(b); } for (l = dev->leds; l; l = lnext) { lnext = l->next; #ifdef XKB if (l->xkb_sli) XkbFreeSrvLedInfo(l->xkb_sli); #endif xfree(l); } #ifdef XKB while (dev->xkb_interest) XkbRemoveResourceClient((DevicePtr)dev,dev->xkb_interest->resource); #endif if (DevHasCursor(dev)) xfree((pointer)dev->pSprite); /* a client may have the device set as client pointer */ for (j = 0; j < currentMaxClients; j++) { if (clients[j]->clientPtr == dev) PickPointer(clients[j]); } xfree(dev->sync.event); xfree(dev); } void CloseDownDevices() { register DeviceIntPtr dev, next; for (dev = inputInfo.devices; dev; dev = next) { next = dev->next; CloseDevice(dev); } for (dev = inputInfo.off_devices; dev; dev = next) { next = dev->next; CloseDevice(dev); } inputInfo.devices = NULL; inputInfo.off_devices = NULL; inputInfo.keyboard = NULL; inputInfo.pointer = NULL; } int RemoveDevice(DeviceIntPtr dev) { DeviceIntPtr prev,tmp,next; int ret = BadMatch; devicePresenceNotify ev; DeviceIntRec dummyDev; DebugF("(dix) removing device %d\n", dev->id); if (!dev || dev == inputInfo.keyboard || dev == inputInfo.pointer) return BadImplementation; prev = NULL; for (tmp = inputInfo.devices; tmp; (prev = tmp), (tmp = next)) { next = tmp->next; if (tmp == dev) { CloseDevice(tmp); if (prev==NULL) inputInfo.devices = next; else prev->next = next; ret = Success; } } prev = NULL; for (tmp = inputInfo.off_devices; tmp; (prev = tmp), (tmp = next)) { next = tmp->next; if (tmp == dev) { CloseDevice(tmp); if (prev == NULL) inputInfo.off_devices = next; else prev->next = next; ret = Success; } } if (ret == Success) { ev.type = DevicePresenceNotify; ev.time = currentTime.milliseconds; ev.devchange = 0; ev.deviceid = 0; dummyDev.id = 0; SendEventToAllWindows(&dummyDev, DevicePresenceNotifyMask, (xEvent *) &ev, 1); } return ret; } int NumMotionEvents() { /* only called to fill data in initial connection reply. * VCP is ok here, it is the only fixed device we have. */ return inputInfo.pointer->valuator->numMotionEvents; } void RegisterPointerDevice(DeviceIntPtr device) { RegisterOtherDevice(device); } void RegisterKeyboardDevice(DeviceIntPtr device) { RegisterOtherDevice(device); } _X_EXPORT DevicePtr LookupKeyboardDevice() { return inputInfo.keyboard ? &inputInfo.keyboard->public : NULL; } _X_EXPORT DevicePtr LookupPointerDevice() { return inputInfo.pointer ? &inputInfo.pointer->public : NULL; } DevicePtr LookupDevice(int id) { DeviceIntPtr dev; for (dev=inputInfo.devices; dev; dev=dev->next) { if (dev->id == (CARD8)id) return (DevicePtr)dev; } for (dev=inputInfo.off_devices; dev; dev=dev->next) { if (dev->id == (CARD8)id) return (DevicePtr)dev; } return NULL; } void QueryMinMaxKeyCodes(KeyCode *minCode, KeyCode *maxCode) { if (inputInfo.keyboard) { *minCode = inputInfo.keyboard->key->curKeySyms.minKeyCode; *maxCode = inputInfo.keyboard->key->curKeySyms.maxKeyCode; } } Bool SetKeySymsMap(register KeySymsPtr dst, register KeySymsPtr src) { int i, j; int rowDif = src->minKeyCode - dst->minKeyCode; /* if keysym map size changes, grow map first */ 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) { KeySym *map; int bytes = sizeof(KeySym) * src->mapWidth * (dst->maxKeyCode - dst->minKeyCode + 1); map = (KeySym *)xalloc(bytes); if (!map) return FALSE; bzero((char *)map, bytes); if (dst->map) { for (i = 0; i <= dst->maxKeyCode-dst->minKeyCode; i++) memmove((char *)&map[i*src->mapWidth], (char *)&dst->map[i*dst->mapWidth], dst->mapWidth * sizeof(KeySym)); xfree(dst->map); } dst->mapWidth = src->mapWidth; dst->map = map; } memmove((char *)&dst->map[rowDif * dst->mapWidth], (char *)src->map, (int)(src->maxKeyCode - src->minKeyCode + 1) * dst->mapWidth * sizeof(KeySym)); return TRUE; } static Bool InitModMap(register KeyClassPtr keyc) { int i, j; CARD8 keysPerModifier[8]; CARD8 mask; keyc->maxKeysPerModifier = 0; for (i = 0; i < 8; i++) keysPerModifier[i] = 0; for (i = 8; i < MAP_LENGTH; i++) { for (j = 0, mask = 1; j < 8; j++, mask <<= 1) { if (mask & keyc->modifierMap[i]) { if (++keysPerModifier[j] > keyc->maxKeysPerModifier) keyc->maxKeysPerModifier = keysPerModifier[j]; } } } keyc->modifierKeyMap = (KeyCode *)xalloc(8*keyc->maxKeysPerModifier); if (!keyc->modifierKeyMap && keyc->maxKeysPerModifier) return (FALSE); bzero((char *)keyc->modifierKeyMap, 8*(int)keyc->maxKeysPerModifier); for (i = 0; i < 8; i++) keysPerModifier[i] = 0; for (i = 8; i < MAP_LENGTH; i++) { for (j = 0, mask = 1; j < 8; j++, mask <<= 1) { if (mask & keyc->modifierMap[i]) { keyc->modifierKeyMap[(j*keyc->maxKeysPerModifier) + keysPerModifier[j]] = i; keysPerModifier[j]++; } } } return TRUE; } _X_EXPORT Bool InitKeyClassDeviceStruct(DeviceIntPtr dev, KeySymsPtr pKeySyms, CARD8 pModifiers[]) { int i; register KeyClassPtr keyc; keyc = (KeyClassPtr)xalloc(sizeof(KeyClassRec)); if (!keyc) return FALSE; keyc->curKeySyms.map = (KeySym *)NULL; keyc->curKeySyms.mapWidth = 0; keyc->curKeySyms.minKeyCode = pKeySyms->minKeyCode; keyc->curKeySyms.maxKeyCode = pKeySyms->maxKeyCode; keyc->modifierKeyMap = (KeyCode *)NULL; keyc->state = 0; keyc->prev_state = 0; if (pModifiers) memmove((char *)keyc->modifierMap, (char *)pModifiers, MAP_LENGTH); else bzero((char *)keyc->modifierMap, MAP_LENGTH); bzero((char *)keyc->down, DOWN_LENGTH); for (i = 0; i < 8; i++) keyc->modifierKeyCount[i] = 0; if (!SetKeySymsMap(&keyc->curKeySyms, pKeySyms) || !InitModMap(keyc)) { xfree(keyc->curKeySyms.map); xfree(keyc->modifierKeyMap); xfree(keyc); return FALSE; } dev->key = keyc; #ifdef XKB dev->key->xkbInfo= NULL; if (!noXkbExtension) XkbInitDevice(dev); #endif return TRUE; } _X_EXPORT Bool InitButtonClassDeviceStruct(register DeviceIntPtr dev, int numButtons, CARD8 *map) { register ButtonClassPtr butc; int i; butc = (ButtonClassPtr)xalloc(sizeof(ButtonClassRec)); if (!butc) return FALSE; butc->numButtons = numButtons; for (i = 1; i <= numButtons; i++) butc->map[i] = map[i]; butc->buttonsDown = 0; butc->state = 0; butc->motionMask = 0; bzero((char *)butc->down, DOWN_LENGTH); #ifdef XKB butc->xkb_acts= NULL; #endif dev->button = butc; return TRUE; } _X_EXPORT Bool InitValuatorClassDeviceStruct(DeviceIntPtr dev, int numAxes, ValuatorMotionProcPtr motionProc, int numMotionEvents, int mode) { int i; register ValuatorClassPtr valc; if (!dev) return FALSE; valc = (ValuatorClassPtr)xalloc(sizeof(ValuatorClassRec) + numAxes * sizeof(AxisInfo) + numAxes * sizeof(unsigned int)); if (!valc) return FALSE; valc->motion = NULL; valc->first_motion = 0; valc->last_motion = 0; valc->GetMotionProc = motionProc; valc->numMotionEvents = numMotionEvents; valc->motionHintWindow = NullWindow; valc->numAxes = numAxes; valc->mode = mode; valc->axes = (AxisInfoPtr)(valc + 1); valc->axisVal = (int *)(valc->axes + numAxes); valc->lastx = 0; valc->lasty = 0; valc->dxremaind = 0; valc->dyremaind = 0; dev->valuator = valc; /* biggest hack ever. */ if (motionProc == GetMotionHistory) AllocateMotionHistory(dev); for (i=0; iaxisVal[i]=0; } return TRUE; } _X_EXPORT Bool InitAbsoluteClassDeviceStruct(DeviceIntPtr dev) { register AbsoluteClassPtr abs; abs = (AbsoluteClassPtr)xalloc(sizeof(AbsoluteClassRec)); if (!abs) return FALSE; /* we don't do anything sensible with these, but should */ abs->min_x = -1; abs->min_y = -1; abs->max_x = -1; abs->max_y = -1; 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 = -1; abs->height = -1; abs->following = 0; dev->absolute = abs; return TRUE; } _X_EXPORT Bool InitFocusClassDeviceStruct(DeviceIntPtr dev) { register FocusClassPtr focc; focc = (FocusClassPtr)xalloc(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; dev->focus = focc; return TRUE; } _X_EXPORT Bool InitKbdFeedbackClassDeviceStruct(DeviceIntPtr dev, BellProcPtr bellProc, KbdCtrlProcPtr controlProc) { register KbdFeedbackPtr feedc; feedc = (KbdFeedbackPtr)xalloc(sizeof(KbdFeedbackClassRec)); if (!feedc) return FALSE; feedc->BellProc = bellProc; feedc->CtrlProc = controlProc; #ifdef XKB defaultKeyboardControl.autoRepeat = TRUE; #endif feedc->ctrl = defaultKeyboardControl; feedc->ctrl.id = 0; if ((feedc->next = dev->kbdfeed) != 0) feedc->ctrl.id = dev->kbdfeed->ctrl.id + 1; dev->kbdfeed = feedc; #ifdef XKB feedc->xkb_sli= NULL; if (!noXkbExtension) XkbFinishDeviceInit(dev); #endif (*dev->kbdfeed->CtrlProc)(dev,&dev->kbdfeed->ctrl); return TRUE; } _X_EXPORT Bool InitPtrFeedbackClassDeviceStruct(DeviceIntPtr dev, PtrCtrlProcPtr controlProc) { register PtrFeedbackPtr feedc; feedc = (PtrFeedbackPtr)xalloc(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; } LedCtrl defaultLedControl = { DEFAULT_LEDS, DEFAULT_LEDS_MASK, 0}; BellCtrl defaultBellControl = { DEFAULT_BELL, DEFAULT_BELL_PITCH, DEFAULT_BELL_DURATION, 0}; IntegerCtrl defaultIntegerControl = { DEFAULT_INT_RESOLUTION, DEFAULT_INT_MIN_VALUE, DEFAULT_INT_MAX_VALUE, DEFAULT_INT_DISPLAYED, 0}; _X_EXPORT Bool InitStringFeedbackClassDeviceStruct ( DeviceIntPtr dev, StringCtrlProcPtr controlProc, int max_symbols, int num_symbols_supported, KeySym *symbols) { int i; register StringFeedbackPtr feedc; feedc = (StringFeedbackPtr)xalloc(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 = (KeySym *) xalloc (sizeof (KeySym) * num_symbols_supported); feedc->ctrl.symbols_displayed = (KeySym *) xalloc (sizeof (KeySym) * max_symbols); if (!feedc->ctrl.symbols_supported || !feedc->ctrl.symbols_displayed) { if (feedc->ctrl.symbols_supported) xfree(feedc->ctrl.symbols_supported); if (feedc->ctrl.symbols_displayed) xfree(feedc->ctrl.symbols_displayed); xfree(feedc); return FALSE; } for (i=0; ictrl.symbols_supported+i) = *symbols++; for (i=0; ictrl.symbols_displayed+i) = (KeySym) NULL; 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; } _X_EXPORT Bool InitBellFeedbackClassDeviceStruct (DeviceIntPtr dev, BellProcPtr bellProc, BellCtrlProcPtr controlProc) { register BellFeedbackPtr feedc; feedc = (BellFeedbackPtr)xalloc(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; } _X_EXPORT Bool InitLedFeedbackClassDeviceStruct (DeviceIntPtr dev, LedCtrlProcPtr controlProc) { register LedFeedbackPtr feedc; feedc = (LedFeedbackPtr)xalloc(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; #ifdef XKB feedc->xkb_sli= NULL; #endif dev->leds = feedc; (*controlProc)(dev, &feedc->ctrl); return TRUE; } _X_EXPORT Bool InitIntegerFeedbackClassDeviceStruct (DeviceIntPtr dev, IntegerCtrlProcPtr controlProc) { register IntegerFeedbackPtr feedc; feedc = (IntegerFeedbackPtr)xalloc(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; } _X_EXPORT Bool InitPointerDeviceStruct(DevicePtr device, CARD8 *map, int numButtons, ValuatorMotionProcPtr motionProc, PtrCtrlProcPtr controlProc, int numMotionEvents, int numAxes) { DeviceIntPtr dev = (DeviceIntPtr)device; return(InitButtonClassDeviceStruct(dev, numButtons, map) && InitValuatorClassDeviceStruct(dev, numAxes, motionProc, numMotionEvents, 0) && InitPtrFeedbackClassDeviceStruct(dev, controlProc)); } _X_EXPORT Bool InitKeyboardDeviceStruct(DevicePtr device, KeySymsPtr pKeySyms, CARD8 pModifiers[], BellProcPtr bellProc, KbdCtrlProcPtr controlProc) { DeviceIntPtr dev = (DeviceIntPtr)device; return(InitKeyClassDeviceStruct(dev, pKeySyms, pModifiers) && InitFocusClassDeviceStruct(dev) && InitKbdFeedbackClassDeviceStruct(dev, bellProc, controlProc)); } _X_EXPORT void SendMappingNotify(DeviceIntPtr pDev, unsigned request, unsigned firstKeyCode, unsigned count, ClientPtr client) { int i; xEvent event; event.u.u.type = MappingNotify; event.u.mappingNotify.request = request; if (request == MappingKeyboard) { event.u.mappingNotify.firstKeyCode = firstKeyCode; event.u.mappingNotify.count = count; } #ifdef XKB if (!noXkbExtension && ((request == MappingKeyboard) || (request == MappingModifier))) { XkbApplyMappingChange(pDev,request,firstKeyCode,count, client); } #endif /* 0 is the server client */ for (i=1; iclientState == ClientStateRunning) { #ifdef XKB if (!noXkbExtension && (request == MappingKeyboard) && (clients[i]->xkbClientFlags != 0) && (clients[i]->mapNotifyMask&XkbKeySymsMask)) continue; #endif event.u.u.sequenceNumber = clients[i]->sequence; WriteEventsToClient(clients[i], 1, &event); } } } /* * n-squared algorithm. n < 255 and don't want to copy the whole thing and * sort it to do the checking. How often is it called? Just being lazy? */ Bool BadDeviceMap(register BYTE *buff, int length, unsigned low, unsigned high, XID *errval) { register int i, j; for (i = 0; i < length; i++) if (buff[i]) /* only check non-zero elements */ { if ((low > buff[i]) || (high < buff[i])) { *errval = buff[i]; return TRUE; } for (j = i + 1; j < length; j++) if (buff[i] == buff[j]) { *errval = buff[i]; return TRUE; } } return FALSE; } Bool AllModifierKeysAreUp(dev, map1, per1, map2, per2) register DeviceIntPtr dev; register CARD8 *map1, *map2; int per1, per2; { register int i, j, k; register CARD8 *down = dev->key->down; for (i = 8; --i >= 0; map2 += per2) { for (j = per1; --j >= 0; map1++) { if (*map1 && BitIsOn(down, *map1)) { for (k = per2; (--k >= 0) && (*map1 != map2[k]);) ; if (k < 0) return FALSE; } } } return TRUE; } static int DoSetModifierMapping(ClientPtr client, KeyCode *inputMap, int numKeyPerModifier) { DeviceIntPtr pDev = NULL; int i = 0, inputMapLen = numKeyPerModifier * 8; for (pDev = inputInfo.devices; pDev; pDev = pDev->next) { if ((pDev->coreEvents || pDev == inputInfo.keyboard) && pDev->key) { for (i = 0; i < inputMapLen; i++) { /* Check that all the new modifiers fall within the advertised * keycode range, and are okay with the DDX. */ if (inputMap[i] && ((inputMap[i] < pDev->key->curKeySyms.minKeyCode || inputMap[i] > pDev->key->curKeySyms.maxKeyCode) || !LegalModifier(inputMap[i], pDev))) { client->errorValue = inputMap[i]; return BadValue; } } if (!XaceHook(XACE_DEVICE_ACCESS, client, pDev, TRUE)) return BadAccess; /* None of the modifiers (old or new) may be down while we change * the map. */ if (!AllModifierKeysAreUp(pDev, pDev->key->modifierKeyMap, pDev->key->maxKeysPerModifier, inputMap, numKeyPerModifier) || !AllModifierKeysAreUp(pDev, inputMap, numKeyPerModifier, pDev->key->modifierKeyMap, pDev->key->maxKeysPerModifier)) { return MappingBusy; } } } for (pDev = inputInfo.devices; pDev; pDev = pDev->next) { if ((pDev->coreEvents || pDev == inputInfo.keyboard) && pDev->key) { bzero(pDev->key->modifierMap, MAP_LENGTH); /* Annoyingly, we lack a modifierKeyMap size, so we have to just free * and re-alloc it every time. */ if (pDev->key->modifierKeyMap) xfree(pDev->key->modifierKeyMap); if (inputMapLen) { pDev->key->modifierKeyMap = (KeyCode *) xalloc(inputMapLen); if (!pDev->key->modifierKeyMap) return BadAlloc; memcpy(pDev->key->modifierKeyMap, inputMap, inputMapLen); pDev->key->maxKeysPerModifier = numKeyPerModifier; for (i = 0; i < inputMapLen; i++) { if (inputMap[i]) { pDev->key->modifierMap[inputMap[i]] |= (1 << (((unsigned int)i) / numKeyPerModifier)); } } } else { pDev->key->modifierKeyMap = NULL; } } } return Success; } int ProcSetModifierMapping(ClientPtr client) { xSetModifierMappingReply rep; REQUEST(xSetModifierMappingReq); REQUEST_AT_LEAST_SIZE(xSetModifierMappingReq); if (client->req_len != ((stuff->numKeyPerModifier << 1) + (sizeof (xSetModifierMappingReq) >> 2))) return BadLength; rep.type = X_Reply; rep.length = 0; rep.sequenceNumber = client->sequence; rep.success = DoSetModifierMapping(client, (KeyCode *)&stuff[1], stuff->numKeyPerModifier); /* FIXME: Send mapping notifies for all the extended devices as well. */ SendMappingNotify(inputInfo.keyboard, MappingModifier, 0, 0, client); WriteReplyToClient(client, sizeof(xSetModifierMappingReply), &rep); return client->noClientException; } int ProcGetModifierMapping(ClientPtr client) { xGetModifierMappingReply rep; register KeyClassPtr keyc = inputInfo.keyboard->key; REQUEST_SIZE_MATCH(xReq); rep.type = X_Reply; rep.numKeyPerModifier = keyc->maxKeysPerModifier; rep.sequenceNumber = client->sequence; /* length counts 4 byte quantities - there are 8 modifiers 1 byte big */ rep.length = keyc->maxKeysPerModifier << 1; WriteReplyToClient(client, sizeof(xGetModifierMappingReply), &rep); /* Use the (modified by DDX) map that SetModifierMapping passed in */ (void)WriteToClient(client, (int)(keyc->maxKeysPerModifier << 3), (char *)keyc->modifierKeyMap); return client->noClientException; } int ProcChangeKeyboardMapping(ClientPtr client) { REQUEST(xChangeKeyboardMappingReq); unsigned len; KeySymsRec keysyms; KeySymsPtr curKeySyms = &inputInfo.keyboard->key->curKeySyms; DeviceIntPtr pDev = NULL; REQUEST_AT_LEAST_SIZE(xChangeKeyboardMappingReq); len = client->req_len - (sizeof(xChangeKeyboardMappingReq) >> 2); if (len != (stuff->keyCodes * stuff->keySymsPerKeyCode)) return BadLength; if ((stuff->firstKeyCode < curKeySyms->minKeyCode) || (stuff->firstKeyCode > curKeySyms->maxKeyCode)) { client->errorValue = stuff->firstKeyCode; return BadValue; } if (((unsigned)(stuff->firstKeyCode + stuff->keyCodes - 1) > curKeySyms->maxKeyCode) || (stuff->keySymsPerKeyCode == 0)) { client->errorValue = stuff->keySymsPerKeyCode; return BadValue; } for (pDev = inputInfo.devices; pDev; pDev = pDev->next) { if ((pDev->coreEvents || pDev == inputInfo.keyboard) && pDev->key) { if (!XaceHook(XACE_DEVICE_ACCESS, client, pDev, TRUE)) return BadAccess; } } keysyms.minKeyCode = stuff->firstKeyCode; keysyms.maxKeyCode = stuff->firstKeyCode + stuff->keyCodes - 1; keysyms.mapWidth = stuff->keySymsPerKeyCode; keysyms.map = (KeySym *)&stuff[1]; for (pDev = inputInfo.devices; pDev; pDev = pDev->next) { if ((pDev->coreEvents || pDev == inputInfo.keyboard) && pDev->key) { if (!SetKeySymsMap(&pDev->key->curKeySyms, &keysyms)) return BadAlloc; } } /* FIXME: Send mapping notifies for all the extended devices as well. */ SendMappingNotify(inputInfo.keyboard, MappingKeyboard, stuff->firstKeyCode, stuff->keyCodes, client); return client->noClientException; } static int DoSetPointerMapping(DeviceIntPtr device, BYTE *map, int n) { int i = 0; DeviceIntPtr dev = NULL; if (!device || !device->button) return BadDevice; for (dev = inputInfo.devices; dev; dev = dev->next) { if ((dev->coreEvents || dev == inputInfo.pointer) && dev->button) { for (i = 0; i < n; i++) { if ((device->button->map[i + 1] != map[i]) && BitIsOn(device->button->down, i + 1)) { return MappingBusy; } } } } for (dev = inputInfo.devices; dev; dev = dev->next) { if ((dev->coreEvents || dev == inputInfo.pointer) && dev->button) { for (i = 0; i < n; i++) dev->button->map[i + 1] = map[i]; } } return Success; } int ProcSetPointerMapping(ClientPtr client) { REQUEST(xSetPointerMappingReq); BYTE *map; int ret; DeviceIntPtr ptr = PickPointer(client); xSetPointerMappingReply rep; REQUEST_AT_LEAST_SIZE(xSetPointerMappingReq); if (client->req_len != (sizeof(xSetPointerMappingReq)+stuff->nElts+3) >> 2) return BadLength; rep.type = X_Reply; rep.length = 0; rep.sequenceNumber = client->sequence; rep.success = MappingSuccess; map = (BYTE *)&stuff[1]; /* So we're bounded here by the number of core buttons. This check * probably wants disabling through XFixes. */ /* MPX: With ClientPointer, we can return the right number of buttons. * Let's just hope nobody changed ClientPointer between GetPointerMapping * and SetPointerMapping */ if (stuff->nElts != ptr->button->numButtons) { client->errorValue = stuff->nElts; return BadValue; } if (BadDeviceMap(&map[0], (int)stuff->nElts, 1, 255, &client->errorValue)) return BadValue; ret = DoSetPointerMapping(ptr, map, stuff->nElts); if (ret != Success) { rep.success = ret; WriteReplyToClient(client, sizeof(xSetPointerMappingReply), &rep); return Success; } /* FIXME: Send mapping notifies for all the extended devices as well. */ SendMappingNotify(ptr, MappingPointer, 0, 0, client); WriteReplyToClient(client, sizeof(xSetPointerMappingReply), &rep); return Success; } int ProcGetKeyboardMapping(ClientPtr client) { xGetKeyboardMappingReply rep; REQUEST(xGetKeyboardMappingReq); DeviceIntPtr kbd = PickKeyboard(client); KeySymsPtr curKeySyms = &kbd->key->curKeySyms; REQUEST_SIZE_MATCH(xGetKeyboardMappingReq); if ((stuff->firstKeyCode < curKeySyms->minKeyCode) || (stuff->firstKeyCode > curKeySyms->maxKeyCode)) { client->errorValue = stuff->firstKeyCode; return BadValue; } if (stuff->firstKeyCode + stuff->count > (unsigned)(curKeySyms->maxKeyCode + 1)) { client->errorValue = stuff->count; return BadValue; } rep.type = X_Reply; rep.sequenceNumber = client->sequence; rep.keySymsPerKeyCode = curKeySyms->mapWidth; /* length is a count of 4 byte quantities and KeySyms are 4 bytes */ rep.length = (curKeySyms->mapWidth * stuff->count); WriteReplyToClient(client, sizeof(xGetKeyboardMappingReply), &rep); client->pSwapReplyFunc = (ReplySwapPtr) CopySwap32Write; WriteSwappedDataToClient( client, curKeySyms->mapWidth * stuff->count * sizeof(KeySym), &curKeySyms->map[(stuff->firstKeyCode - curKeySyms->minKeyCode) * curKeySyms->mapWidth]); return client->noClientException; } int ProcGetPointerMapping(ClientPtr client) { xGetPointerMappingReply rep; /* Apps may get different values each time they call GetPointerMapping as * the ClientPointer could change. */ ButtonClassPtr butc = PickPointer(client)->button; REQUEST_SIZE_MATCH(xReq); rep.type = X_Reply; rep.sequenceNumber = client->sequence; rep.nElts = butc->numButtons; rep.length = ((unsigned)rep.nElts + (4-1))/4; WriteReplyToClient(client, sizeof(xGetPointerMappingReply), &rep); (void)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)); } _X_EXPORT int Ones(unsigned long mask) /* HACKMEM 169 */ { register 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; 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; } #ifdef XKB if (!noXkbExtension) { XkbEventCauseRec cause; XkbSetCauseCoreReq(&cause,X_ChangeKeyboardControl,client); XkbSetIndicators(keybd,((led == DO_ALL) ? ~0L : (1L<<(led-1))), ctrl.leds, &cause); ctrl.leds = keybd->kbdfeed->ctrl.leds; } #endif break; case KBKey: key = (KeyCode)*vlist; vlist++; if ((KeyCode)key < inputInfo.keyboard->key->curKeySyms.minKeyCode || (KeyCode)key > inputInfo.keyboard->key->curKeySyms.maxKeyCode) { client->errorValue = key; return BadValue; } if (!(mask & KBAutoRepeatMode)) return BadMatch; break; case KBAutoRepeatMode: i = (key >> 3); mask = (1 << (key & 7)); t = (CARD8)*vlist; vlist++; #ifdef XKB if (!noXkbExtension && key != DO_ALL) XkbDisableComputedAutoRepeats(keybd,key); #endif 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; #ifdef XKB /* The XKB RepeatKeys control and core protocol global autorepeat */ /* value are linked */ if (!noXkbExtension) XkbSetRepeatKeys(keybd, key, keybd->kbdfeed->ctrl.autoRepeat); else #endif (*keybd->kbdfeed->CtrlProc)(keybd, &keybd->kbdfeed->ctrl); return Success; #undef DO_ALL } int ProcChangeKeyboardControl (ClientPtr client) { XID *vlist; BITS32 vmask; int ret = Success, error = Success; DeviceIntPtr pDev = NULL; 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; for (pDev = inputInfo.devices; pDev; pDev = pDev->next) { if ((pDev->coreEvents || pDev == inputInfo.keyboard) && pDev->kbdfeed && pDev->kbdfeed->CtrlProc) { if (!XaceHook(XACE_DEVICE_ACCESS, client, pDev, TRUE)) return BadAccess; } } for (pDev = inputInfo.devices; pDev; pDev = pDev->next) { if ((pDev->coreEvents || pDev == inputInfo.keyboard) && pDev->kbdfeed && pDev->kbdfeed->CtrlProc) { ret = DoChangeKeyboardControl(client, pDev, vlist, vmask); if (ret != Success) error = ret; } } return error; } int ProcGetKeyboardControl (ClientPtr client) { int i; register KeybdCtrl *ctrl = &inputInfo.keyboard->kbdfeed->ctrl; xGetKeyboardControlReply rep; REQUEST_SIZE_MATCH(xReq); 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) { register DeviceIntPtr keybd = inputInfo.keyboard; int base = keybd->kbdfeed->ctrl.bell; int newpercent; REQUEST(xBellReq); REQUEST_SIZE_MATCH(xBellReq); if (!keybd->kbdfeed->BellProc) return BadDevice; 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 (keybd = inputInfo.devices; keybd; keybd = keybd->next) { if ((keybd->coreEvents || keybd == inputInfo.keyboard) && keybd->kbdfeed && keybd->kbdfeed->BellProc) { #ifdef XKB if (!noXkbExtension) XkbHandleBell(FALSE, FALSE, keybd, newpercent, &keybd->kbdfeed->ctrl, 0, None, NULL, client); else #endif (*keybd->kbdfeed->BellProc)(newpercent, keybd, &keybd->kbdfeed->ctrl, 0); } } return Success; } int ProcChangePointerControl(ClientPtr client) { DeviceIntPtr mouse = PickPointer(client); PtrCtrl ctrl; /* might get BadValue part way through */ REQUEST(xChangePointerControlReq); REQUEST_SIZE_MATCH(xChangePointerControlReq); if (!mouse->ptrfeed->CtrlProc) return BadDevice; 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 (mouse = inputInfo.devices; mouse; mouse = mouse->next) { if ((mouse->coreEvents || mouse == PickPointer(client)) && mouse->ptrfeed && mouse->ptrfeed->CtrlProc) { mouse->ptrfeed->ctrl = ctrl; (*mouse->ptrfeed->CtrlProc)(mouse, &mouse->ptrfeed->ctrl); } } return Success; } int ProcGetPointerControl(ClientPtr client) { DeviceIntPtr ptr = PickPointer(client); PtrCtrl *ctrl = &ptr->ptrfeed->ctrl; xGetPointerControlReply rep; REQUEST_SIZE_MATCH(xReq); 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(register DeviceIntPtr dev, ClientPtr client) { GrabPtr grab = dev->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, DixUnknownAccess); 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; coords = (xTimecoord *)ALLOCATE_LOCAL(mouse->valuator->numMotionEvents * sizeof(xTimecoord)); if (!coords) return BadAlloc; count = (*mouse->valuator->GetMotionProc) (mouse, coords, start.milliseconds, stop.milliseconds, pWin->drawable.pScreen); 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 * (sizeof(xTimecoord) >> 2); rep.nEvents = nEvents; WriteReplyToClient(client, sizeof(xGetMotionEventsReply), &rep); if (nEvents) { client->pSwapReplyFunc = (ReplySwapPtr) SwapTimeCoordWrite; WriteSwappedDataToClient(client, nEvents * sizeof(xTimecoord), (char *)coords); } if (coords) DEALLOCATE_LOCAL(coords); return Success; } int ProcQueryKeymap(ClientPtr client) { xQueryKeymapReply rep; int i; CARD8 *down = inputInfo.keyboard->key->down; REQUEST_SIZE_MATCH(xReq); rep.type = X_Reply; rep.sequenceNumber = client->sequence; rep.length = 2; if (XaceHook(XACE_DEVICE_ACCESS, client, inputInfo.keyboard, TRUE)) for (i = 0; i<32; i++) rep.map[i] = down[i]; else bzero((char *)&rep.map[0], 32); WriteReplyToClient(client, sizeof(xQueryKeymapReply), &rep); return Success; } /* Pair the keyboard to the pointer device. Keyboard events will follow the * pointer sprite. */ int PairDevices(ClientPtr client, DeviceIntPtr ptr, DeviceIntPtr kbd) { if (!pairingClient) RegisterPairingClient(client); else if (pairingClient != client) return BadAccess; if (kbd->spriteOwner) { xfree(kbd->pSprite); kbd->pSprite = NULL; kbd->spriteOwner = FALSE; } kbd->pSprite = ptr->pSprite; return Success; } /* Return the pointer that is paired with the given keyboard. If no pointer is * paired, return the virtual core pointer */ DeviceIntPtr GetPairedPointer(DeviceIntPtr kbd) { DeviceIntPtr ptr = inputInfo.devices; while(ptr) { if (ptr->pSprite == kbd->pSprite && ptr->spriteOwner) { return ptr; } ptr = ptr->next; } return inputInfo.pointer; } /* * Register a client to be able to pair devices. */ Bool RegisterPairingClient(ClientPtr client) { if (!pairingClient) { pairingClient = client; } else if (pairingClient != client) { return False; } return True; } /* * Unregister pairing client; */ Bool UnregisterPairingClient(ClientPtr client) { if (pairingClient) { if ( pairingClient == client) { pairingClient = NULL; } else return False; } return True; } /* Guess a pointer that could be a good one for pairing. Any pointer that is * not yet paired with keyboard is considered a good one. * If no pointer is found, the last real pointer is chosen. If that doesn't * work either, we take the core pointer. */ DeviceIntPtr GuessFreePointerDevice() { DeviceIntPtr it, it2; DeviceIntPtr lastRealPtr = NULL; it = inputInfo.devices; while(it) { /* found device with a sprite? */ if (it != inputInfo.pointer && it->spriteOwner) { lastRealPtr = it; it2 = inputInfo.devices; while(it2) { /* something paired with it? */ if (it != it2 && it2->pSprite == it->pSprite) break; it2 = it2->next; } if (it2) break; /* woohoo! no pairing set up for 'it' yet */ return it; } it = it->next; } return (lastRealPtr) ? lastRealPtr : inputInfo.pointer; }