/************************************************************ Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts, and the Massachusetts Institute of Technology, Cambridge, 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 names of Digital or MIT 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. ********************************************************/ /* $Header: events.c,v 1.76 87/06/24 14:48:52 swick Exp $ */ #include "X.h" #include "misc.h" #include "resource.h" #define NEED←EVENTS #define NEED←REPLIES #include "Xproto.h" #include "windowstr.h" #include "inputstr.h" #include "scrnintstr.h" #include "cursorstr.h" #include "dixstruct.h" #include "opaque.h" extern WindowRec WindowTable[]; extern int swappedClients[]; extern Bool IsParent(); extern void DeactivatePointerGrab(); extern void DeactivateKeyboardGrab(); extern void SetPointerStateMasks(); extern void SetKeyboardStateMasks(); extern int DeliverEventsToWindow(); extern Bool MatchingGrab(); extern void DoFocusEvents(); extern void (* EventSwapVector[128]) (); extern void (* ReplySwapVector[256]) (); #define NoSuchEvent 0x80000000 /* so doesn't match NoEventMask */ #define StructureAndSubMask ( StructureNotifyMask | SubstructureNotifyMask ) #define AllButtonsMask ( \ Button1Mask | Button2Mask | Button3Mask | Button4Mask | Button5Mask ) #define MotionMask ( \ PointerMotionMask | PointerMotionHintMask | Button1MotionMask | \ Button2MotionMask | Button3MotionMask | Button4MotionMask | \ Button5MotionMask | ButtonMotionMask ) #define PropagateMask ( \ KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | \ MotionMask ) #define AllModifiersMask ( \ ShiftMask | LockMask | ControlMask | Mod1Mask | Mod2Mask | \ Mod3Mask | Mod4Mask | Mod5Mask ) #define Motion←Filter(state) (PointerMotionMask | \ (AllButtonsMask & state) | buttonMotionMask); #define WID(w) ((w) ? ((w)->wid) : 0) #define BitOn(ptr, bit) \ ((BYTE *) (ptr))[(bit)>>3] |= (1 << ((bit) & 7)) #define BitOff(ptr, bit) \ ((BYTE *) (ptr))[(bit)>>3] &= ~(1 << ((bit) & 7)) #define IsOn(ptr, bit) \ (((BYTE *) (ptr))[(bit)>>3] & (1 << ((bit) & 7))) extern debug←events; extern InputInfo inputInfo; extern KeySymsRec curKeySyms; extern GrabRec keybdGrab; /* used for active grabs */ extern GrabRec ptrGrab; #define MAX←QUEUED←EVENTS 100 extern struct { unsigned int num; QdEventRec pending, free; /* only forw, back used */ DeviceIntPtr replayDev; /* kludgy rock to put flag for */ WindowPtr replayWin; /* ComputeFreezes */ Bool playingEvents; } syncEvents; /* * The window trace information is used to avoid having to compute all the * windows between the root and the current pointer window each time a button * or key goes down. The grabs on each of those windows must be checked. */ extern WindowPtr *spriteTrace; #define ROOT spriteTrace[0] extern int spriteTraceSize; extern int spriteTraceGood; extern WindowPtr *focusTrace; extern int focusTraceSize; extern int focusTraceGood; extern CARD16 keyButtonState; extern int buttonsDown; /* number of buttons currently down */ extern Mask buttonMotionMask; typedef struct { int x, y; } HotSpot; extern struct { CursorPtr current; BoxRec hotLimits; /* logical constraints */ BoxRec physLimits; /* of hot spot due to hardware limits */ WindowPtr win; HotSpot hot; } sprite; /* info about the cursor sprite */ extern Bool lastWasMotion; extern void DoEnterLeaveEvents(); /* merely forward declarations */ extern WindowPtr XYToWindow(); extern Bool CheckKeyboardGrabs(); extern void NormalKeyboardEvent(); extern int DeliverDeviceEvents(); extern ScreenPtr currentScreen; extern CARD16 stateMasks[MAP←LENGTH]; /* only for default keyboard ? XXX */ extern int lastEventMask; #define CantBeFiltered NoEventMask extern int filters[128]; extern int PassiveClientGone(); void InitPointerDeviceStruct(device, map, mapLength, motionProc, controlProc) DevicePtr device; BYTE *map; int mapLength; void (*controlProc)(); int (*motionProc)(); { int i; DeviceIntPtr mouse = (DeviceIntPtr)device; mouse->grab = NullGrab; mouse->public.on = FALSE; mouse->u.ptr.mapLength = mapLength; mouse->u.ptr.map[0] = 0; for (i = 1; i <= mapLength; i++) mouse->u.ptr.map[i] = map[i]; mouse->u.ptr.ctrl = defaultPointerControl; mouse->u.ptr.GetMotionProc = motionProc; mouse->u.ptr.CtrlProc = controlProc; mouse->u.ptr.autoReleaseGrab = FALSE; if (mouse == inputInfo.pointer) SetPointerStateMasks(mouse); } void QueryMinMaxKeyCodes(minCode, maxCode) KeyCode *minCode, *maxCode; { *minCode = curKeySyms.minKeyCode; *maxCode = curKeySyms.maxKeyCode; } static void SetKeySymsMap(pKeySyms) KeySymsPtr pKeySyms; { int i, j; int rowDif = pKeySyms->minKeyCode - curKeySyms.minKeyCode; /* if keysym map size changes, grow map first */ if (pKeySyms->mapWidth < curKeySyms.mapWidth) { for (i = pKeySyms->minKeyCode; i <= pKeySyms->maxKeyCode; i++) { #define SI(r, c) (((r-pKeySyms->minKeyCode)*pKeySyms->mapWidth) + (c)) #define DI(r, c) (((r - curKeySyms.minKeyCode)*curKeySyms.mapWidth) + (c)) for (j = 0; j < pKeySyms->mapWidth; j++) curKeySyms.map[DI(i, j)] = pKeySyms->map[SI(i, j)]; for (j = pKeySyms->mapWidth; j < curKeySyms.mapWidth; j++) curKeySyms.map[DI(i, j)] = NoSymbol; #undef SI #undef DI } return; } else if (pKeySyms->mapWidth > curKeySyms.mapWidth) { KeySym *map; int bytes = sizeof(KeySym) * pKeySyms->mapWidth * (curKeySyms.maxKeyCode - curKeySyms.minKeyCode + 1); map = (KeySym *)Xalloc(bytes); bzero(map, bytes); if (curKeySyms.map) { for (i = 0; i <= curKeySyms.maxKeyCode-curKeySyms.minKeyCode; i++) bcopy( &curKeySyms.map[i*curKeySyms.mapWidth], &map[i*pKeySyms->mapWidth], curKeySyms.mapWidth * sizeof(KeySym)); Xfree(curKeySyms.map); } curKeySyms.mapWidth = pKeySyms->mapWidth; curKeySyms.map = map; } bcopy( pKeySyms->map, &curKeySyms.map[rowDif], (pKeySyms->maxKeyCode - pKeySyms->minKeyCode + 1) * (int)curKeySyms.mapWidth * sizeof(KeySym)); } void InitKeyboardDeviceStruct(device, pKeySyms, pModifiers, bellProc, controlProc) DevicePtr device; KeySymsPtr pKeySyms; ModifierMapPtr pModifiers; void (*bellProc)(); void (*controlProc)(); { #define SET←MOD(entry) (keybd->u.keybd.modMap.entry = pModifiers->entry) DeviceIntPtr keybd = (DeviceIntPtr)device; keybd->grab = NullGrab; keybd->public.on = FALSE; keybd->u.keybd.ctrl = defaultKeyboardControl; keybd->u.keybd.BellProc = bellProc; keybd->u.keybd.CtrlProc = controlProc; keybd->u.keybd.focus.win = PointerRootWin; keybd->u.keybd.focus.revert = None; keybd->u.keybd.focus.time = currentTime; keybd->u.keybd.passiveGrab = FALSE; curKeySyms.minKeyCode = pKeySyms->minKeyCode; curKeySyms.maxKeyCode = pKeySyms->maxKeyCode; SET←MOD(lock); SET←MOD(shiftA); SET←MOD(shiftB); SET←MOD(controlA); SET←MOD(controlB); SET←MOD(mod1A); SET←MOD(mod1B); SET←MOD(mod2A); SET←MOD(mod2B); SET←MOD(mod3A); SET←MOD(mod3B); SET←MOD(mod4A); SET←MOD(mod4B); SET←MOD(mod5A); SET←MOD(mod5B); if (keybd == inputInfo.keyboard) { SetKeyboardStateMasks(keybd); SetKeySymsMap(pKeySyms); (*keybd->u.keybd.CtrlProc)(keybd, &keybd->u.keybd.ctrl); } #undef SET←MOD } void InitOtherDeviceStruct(device, map, mapLength) DevicePtr device; BYTE *map; int mapLength; { int i; DeviceIntPtr other = (DeviceIntPtr)device; other->grab = NullGrab; other->public.on = FALSE; other->u.other.mapLength = mapLength; other->u.other.map[0] = 0; for (i = 1; i <= mapLength; i++) other->u.other.map[i] = map[i]; other->u.other.focus.win = NoneWin; other->u.other.focus.revert = None; other->u.other.focus.time = currentTime; } GrabPtr SetDeviceGrab(device, grab) DevicePtr device; GrabPtr grab; { register DeviceIntPtr dev = (DeviceIntPtr)device; GrabPtr oldGrab = dev->grab; dev->grab = grab; /* must not be deallocated */ return oldGrab; } /* * Devices can't be resources since the bit patterns don't fit very well. * For one, where the client field would be, is random bits and the client * object might not be defined. For another, the "server" bit might be on. */ #ifdef INPUT←EXTENSION DevicePtr LookupInputDevice(deviceID) Device deviceID; { int i; for (i = 0; i < inputInfo.numDevices; i++) if (inputInfo.devices[i]->public.deviceID == deviceID) return &(inputInfo.devices[i]->public); return NullDevice; } #endif /* INTPUT←EXTENSION */ DevicePtr LookupKeyboardDevice() { return &inputInfo.keyboard->public; } DevicePtr LookupPointerDevice() { return &inputInfo.pointer->public; } static int SendMappingNotify(request, firstKeyCode, count) BYTE request, firstKeyCode, count; { 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; } /* 0 is the server client */ for (i=1; i<currentMaxClients; i++) if (! clients[i]->clientGone) WriteEventToClient(clients[i], 1, (pointer)&event); } /* * n-sqared 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? */ static Bool BadDeviceMap(buff, length, low, high) BYTE *buff; int length; unsigned low, high; { int i, j; for (i = 0; i < length; i++) if (buff[i]) /* only check non-zero elements */ { if ((low > buff[i]) || (high < buff[i])) return TRUE; for (j = i + 1; j < length; j++) if (buff[i] == buff[j]) return TRUE; } return FALSE; } int ProcSetModifierMapping(client) ClientPtr client; { #define LEGAL←MOD(mod) \ if (modMap.mod != NoSymbol)\ {\ if (!LegalModifier(modMap.mod))\ {\ rep.success = MappingFailed;\ goto WriteMappingReply;\ }\ if ((inputInfo.keyboard->u.keybd.modMap.mod != modMap.mod) &&\ IsOn(inputInfo.keyboard->down, modMap.mod))\ {\ rep.success = MappingBusy;\ goto WriteMappingReply;\ }\ }\ xSetModifierMappingReply rep; REQUEST(xSetModifierMappingReq); ModifierMapRec modMap; REQUEST←SIZE←MATCH(xSetModifierMappingReq); modMap.lock = stuff->lock; modMap.shiftA = stuff->shiftA; modMap.shiftB = stuff->shiftB; modMap.controlA = stuff->controlA; modMap.controlB = stuff->controlB; modMap.mod1A = stuff->mod1A; modMap.mod1B = stuff->mod1B; modMap.mod2A = stuff->mod2A; modMap.mod2B = stuff->mod2B; modMap.mod3A = stuff->mod3A; modMap.mod3B = stuff->mod3B; modMap.mod4A = stuff->mod4A; modMap.mod4B = stuff->mod4B; modMap.mod5A = stuff->mod5A; modMap.mod5B = stuff->mod5B; if (BadDeviceMap ((BYTE *)&modMap, 15, curKeySyms.minKeyCode, curKeySyms.maxKeyCode)) return BadValue; rep.type = X←Reply; rep.length = 0; rep.sequenceNumber = client->sequence; rep.success = MappingSuccess; LEGAL←MOD(lock); LEGAL←MOD(shiftA); LEGAL←MOD(shiftB); LEGAL←MOD(controlA); LEGAL←MOD(controlB); LEGAL←MOD(mod1A); LEGAL←MOD(mod1B); LEGAL←MOD(mod2A); LEGAL←MOD(mod2B); LEGAL←MOD(mod3A); LEGAL←MOD(mod3B); LEGAL←MOD(mod4A); LEGAL←MOD(mod4B); LEGAL←MOD(mod5A); LEGAL←MOD(mod5B); WriteMappingReply: WriteReplyToClient(client, sizeof(xSetModifierMappingReply), &rep); if (rep.success == MappingSuccess) { inputInfo.keyboard->u.keybd.modMap = modMap; SetKeyboardStateMasks(inputInfo.keyboard); SendMappingNotify(MappingModifier, 0, 0); } return(client->noClientException); #undef LEGAL←MOD } int ProcGetModifierMapping(client) ClientPtr client; { xGetModifierMappingReply rep; REQUEST(xReq); REQUEST←SIZE←MATCH(xReq); rep.type = X←Reply; rep.length = 0; rep.sequenceNumber = client->sequence; rep.lock = inputInfo.keyboard->u.keybd.modMap.lock; rep.shiftA = inputInfo.keyboard->u.keybd.modMap.shiftA; rep.shiftB = inputInfo.keyboard->u.keybd.modMap.shiftB; rep.controlA = inputInfo.keyboard->u.keybd.modMap.controlA; rep.controlB = inputInfo.keyboard->u.keybd.modMap.controlB; rep.mod1A = inputInfo.keyboard->u.keybd.modMap.mod1A; rep.mod1B = inputInfo.keyboard->u.keybd.modMap.mod1B; rep.mod2A = inputInfo.keyboard->u.keybd.modMap.mod2A; rep.mod2B = inputInfo.keyboard->u.keybd.modMap.mod2B; rep.mod3A = inputInfo.keyboard->u.keybd.modMap.mod3A; rep.mod3B = inputInfo.keyboard->u.keybd.modMap.mod3B; rep.mod4A = inputInfo.keyboard->u.keybd.modMap.mod4A; rep.mod4B = inputInfo.keyboard->u.keybd.modMap.mod4B; rep.mod5A = inputInfo.keyboard->u.keybd.modMap.mod5A; rep.mod5B = inputInfo.keyboard->u.keybd.modMap.mod5B; WriteReplyToClient(client, sizeof(xGetModifierMappingReply), &rep); return client->noClientException; } int ProcChangeKeyboardMapping(client) ClientPtr client; { REQUEST(xChangeKeyboardMappingReq); int len; int count; KeySymsRec keysyms; REQUEST←AT←LEAST←SIZE(xChangeKeyboardMappingReq); len = stuff->length - (sizeof(xChangeKeyboardMappingReq) >> 2); if (len % stuff->keySymsPerKeyCode != 0) return BadLength; if ((stuff->firstKeyCode < curKeySyms.minKeyCode) || (stuff->firstKeyCode + len > curKeySyms.maxKeyCode) || (stuff->keySymsPerKeyCode == 0)) return BadValue; count = len / stuff->keySymsPerKeyCode; keysyms.minKeyCode = stuff->firstKeyCode; keysyms.maxKeyCode = stuff->firstKeyCode + count; keysyms.mapWidth = stuff->keySymsPerKeyCode; keysyms.map = (KeySym *)&stuff[1]; SetKeySymsMap(&keysyms); SendMappingNotify(MappingKeyboard, stuff->firstKeyCode, (BYTE) count); return client->noClientException; } int ProcSetPointerMapping(client) ClientPtr client; { REQUEST(xSetPointerMappingReq); BYTE *map; xSetPointerMappingReply rep; register int i; REQUEST←AT←LEAST←SIZE(xSetPointerMappingReq); if (stuff->length != (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]; if (stuff->nElts != inputInfo.pointer->u.ptr.mapLength) return BadValue; if (BadDeviceMap(&map[0], (int)stuff->nElts, 1, 255)) return BadValue; for (i=0; i < stuff->nElts; i++) if ((inputInfo.pointer->u.ptr.map[i + 1] != map[i]) && IsOn(inputInfo.pointer->down, i + 1)) { rep.success = MappingBusy; WriteReplyToClient(client, sizeof(xSetPointerMappingReply), &rep); return Success; } for (i = 0; i < stuff->nElts; i++) inputInfo.pointer->u.ptr.map[i + 1] = map[i]; SetPointerStateMasks((DevicePtr)inputInfo.pointer); WriteReplyToClient(client, sizeof(xSetPointerMappingReply), &rep); SendMappingNotify(MappingPointer, 0, 0); return Success; } int ProcGetKeyboardMapping(client) ClientPtr client; { xGetKeyboardMappingReply rep; REQUEST(xGetKeyboardMappingReq); REQUEST←SIZE←MATCH(xGetKeyboardMappingReq); if ((stuff->firstKeyCode < curKeySyms.minKeyCode) || (stuff->firstKeyCode > curKeySyms.maxKeyCode) || (stuff->firstKeyCode + stuff->count > curKeySyms.maxKeyCode + 1)) 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); WriteReplyToClient( client, curKeySyms.mapWidth * stuff->count * sizeof(KeySym), &curKeySyms.map[stuff->firstKeyCode - curKeySyms.minKeyCode]); return client->noClientException; } int ProcGetPointerMapping(client) ClientPtr client; { xGetPointerMappingReply rep; REQUEST(xReq); REQUEST←SIZE←MATCH(xReq); rep.type = X←Reply; rep.sequenceNumber = client->sequence; rep.nElts = inputInfo.pointer->u.ptr.mapLength; rep.length = (rep.nElts + (4-1))/4; WriteReplyToClient(client, sizeof(xGetPointerMappingReply), &rep); WriteReplyToClient(client, rep.nElts, &inputInfo.pointer->u.ptr.map[1]); return Success; } int Ones(mask) /* HACKMEM 169 */ Mask mask; { register int y; y = (mask >> 1) &033333333333; y = mask - y - ((y >>1) & 033333333333); return (((y + (y >> 3)) & 030707070707) % 077); } void NoteLedState(keybd, led, on) DeviceIntPtr keybd; int led; Bool on; { KeybdCtrl *ctrl = &keybd->u.keybd.ctrl; if (on) ctrl->leds |= (1 << (led - 1)); else ctrl->leds &= ~(1 << (led - 1)); /* assumes 32-bit longs XXX */ } int ProcChangeKeyboardControl (client) ClientPtr client; { #define DO←ALL 0xffffffff KeybdCtrl ctrl; DeviceIntPtr keybd = inputInfo.keyboard; long *vlist; int t; int led = DO←ALL; int key = DO←ALL; REQUEST(xChangeKeyboardControlReq); REQUEST←AT←LEAST←SIZE(xChangeKeyboardControlReq); if (stuff->length !=(sizeof(xChangeKeyboardControlReq)>>2) + Ones(stuff->mask)) return BadLength; vlist = (long *)&stuff[1]; /* first word of values */ ctrl = keybd->u.keybd.ctrl; if (stuff->mask & KBKeyClickPercent) { t = (INT8)*vlist; vlist++; if (t == -1) t = defaultKeyboardControl.click; else if (t < 0 || t > 100) return BadValue; ctrl.click = t; } if (stuff->mask & KBBellPercent) { t = (INT8)*vlist; vlist++; if (t == -1) t = defaultKeyboardControl.bell; else if (t < 0 || t > 100) return BadValue; ctrl.bell = t; } if (stuff->mask & KBBellPitch) { t = (INT16)*vlist; vlist++; if (t == -1) t = defaultKeyboardControl.bell←pitch; else if (t < 0) return BadValue; ctrl.bell←pitch = t; } if (stuff->mask & KBBellDuration) { t = (INT16)*vlist; vlist++; if (t == -1) t = defaultKeyboardControl.bell←duration; else if (t < 0) return BadValue; ctrl.bell←duration = t; } if (stuff->mask & KBLed) { led = (CARD8)*vlist; vlist++; if (led < 1 || led > 32) return BadValue; if (!(stuff->mask & KBLedMode)) return BadMatch; } if (stuff->mask & KBLedMode) { t = (CARD8)*vlist; vlist++; if (t == LedModeOff) { if (led == DO←ALL) ctrl.leds = 0x0; else ctrl.leds &= ~(1 << (led - 1)); /* assumes 32-bit longs XXX */ } else if (t == LedModeOn) { if (led == DO←ALL) ctrl.leds = DO←ALL; else ctrl.leds |= (1 << (led - 1)); } else return BadValue; } if (stuff->mask & KBKey) { key = (KeyCode)*vlist; vlist++; if (key < 8 || key > 255) return BadValue; if (!(stuff->mask & KBAutoRepeatMode)) return BadMatch; } if (stuff->mask & KBAutoRepeatMode) { int index = (key >> 3); int mask = (1 << (key & 7)); t = (CARD8)*vlist; vlist++; if (t == AutoRepeatModeOff) { if (key == DO←ALL) ctrl.autoRepeat = FALSE; else ctrl.autoRepeats[index] &= ~mask; } else if (t == AutoRepeatModeOn) { if (key == DO←ALL) ctrl.autoRepeat = TRUE; else ctrl.autoRepeats[index] |= mask; } else if (t == AutoRepeatModeDefault) { if (key == DO←ALL) ctrl.autoRepeat = defaultKeyboardControl.autoRepeat; else ctrl.autoRepeats[index] &= ~mask; ctrl.autoRepeats[index] = (ctrl.autoRepeats[index] & ~mask) | (defaultKeyboardControl.autoRepeats[index] & mask); } else return BadValue; } keybd->u.keybd.ctrl = ctrl; (*keybd->u.keybd.CtrlProc)(keybd, &keybd->u.keybd.ctrl); return Success; #undef DO←ALL } int ProcGetKeyboardControl (client) ClientPtr client; { int i; DeviceIntPtr keybd = inputInfo.keyboard; xGetKeyboardControlReply rep; REQUEST(xReq); REQUEST←SIZE←MATCH(xReq); rep.type = X←Reply; rep.length = 5; rep.sequenceNumber = client->sequence; rep.globalAutoRepeat = keybd->u.keybd.ctrl.autoRepeat; rep.keyClickPercent = keybd->u.keybd.ctrl.click; rep.bellPercent = keybd->u.keybd.ctrl.bell; rep.bellPitch = keybd->u.keybd.ctrl.bell←pitch; rep.bellDuration = keybd->u.keybd.ctrl.bell←duration; rep.ledMask = keybd->u.keybd.ctrl.leds; for (i = 0; i < 32; i++) rep.map[i] = keybd->u.keybd.ctrl.autoRepeats[i]; WriteReplyToClient(client, sizeof(xGetKeyboardControlReply), &rep); return Success; } int ProcBell(client) ClientPtr client; { register DeviceIntPtr keybd = inputInfo.keyboard; REQUEST(xBellReq); REQUEST←SIZE←MATCH(xBellReq); if (stuff->percent < -100 || stuff->percent > 100) return BadValue; (*keybd->u.keybd.BellProc)( min(100, max(0, stuff->percent + keybd->u.keybd.ctrl.bell)), keybd); return Success; } int ProcChangePointerControl(client) ClientPtr client; { DeviceIntPtr mouse = inputInfo.pointer; PtrCtrl ctrl; /* might get BadValue part way through */ REQUEST(xChangePointerControlReq); REQUEST←SIZE←MATCH(xChangePointerControlReq); ctrl = mouse->u.ptr.ctrl; 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; } mouse->u.ptr.ctrl = ctrl; (*mouse->u.ptr.CtrlProc)(mouse, &mouse->u.ptr.ctrl); return Success; } int ProcGetPointerControl(client) ClientPtr client; { register DeviceIntPtr mouse = inputInfo.pointer; REQUEST(xReq); xGetPointerControlReply rep; REQUEST←SIZE←MATCH(xReq); rep.type = X←Reply; rep.length = 0; rep.sequenceNumber = client->sequence; rep.threshold = mouse->u.ptr.ctrl.threshold; rep.accelNumerator = mouse->u.ptr.ctrl.num; rep.accelDenominator = mouse->u.ptr.ctrl.den; WriteReplyToClient(client, sizeof(xGenericReply), &rep); return Success; } int ProcGetMotionEvents(client) ClientPtr client; { WindowPtr pWin; xTimecoord * coords; xGetMotionEventsReply rep; int i, count, xmin, xmax, ymin, ymax; DeviceIntPtr mouse = inputInfo.pointer; TimeStamp start, stop; REQUEST(xGetMotionEventsReq); REQUEST←SIZE←MATCH(xGetMotionEventsReq); pWin = (WindowPtr) LookupID(stuff->window, RT←WINDOW, RC←CORE); if (!pWin) { client->errorValue = stuff->window; return BadWindow; } lastWasMotion = FALSE; rep.type = X←Reply; rep.sequenceNumber = client->sequence; rep.nEvents = 0; start = ClientTimeToServerTime(stuff->start); stop = ClientTimeToServerTime(stuff->stop); if (CompareTimeStamps(start, stop) == LATER) return Success; if (CompareTimeStamps(start, currentTime) == LATER) return Success; if (CompareTimeStamps(stop, currentTime) == LATER) stop = currentTime; if (inputInfo.numMotionEvents) { coords = (xTimecoord *) Xalloc( inputInfo.numMotionEvents * sizeof(xTimecoord)); count = (*mouse->u.ptr.GetMotionProc) ( mouse, coords, start.milliseconds, stop.milliseconds); xmin = pWin->absCorner.x - pWin->borderWidth; xmax = pWin->absCorner.x + pWin->clientWinSize.width + pWin->borderWidth; ymin = pWin->absCorner.y - pWin->borderWidth; ymax = pWin->absCorner.y + pWin->clientWinSize.height + pWin->borderWidth; for (i = 0; i < count; i++) if ((xmin <= coords[i].x) && (coords[i].x < xmax) && (ymin <= coords[i].y) && (coords[i].y < ymax)) { coords[rep.nEvents].x = coords[i].x - pWin->absCorner.x; coords[rep.nEvents].y = coords[i].y - pWin->absCorner.y; rep.nEvents++; } } rep.length = rep.nEvents * sizeof(xTimecoord) / 4; WriteReplyToClient(client, sizeof(xGetMotionEventsReply), &rep); if (inputInfo.numMotionEvents) { WriteReplyToClient( client, (int)rep.nEvents * sizeof(xTimecoord), coords); Xfree(coords); } return Success; } int ProcQueryPointer(client) ClientPtr client; { xQueryPointerReply rep; WindowPtr pWin, t; REQUEST(xResourceReq); REQUEST←SIZE←MATCH(xResourceReq); pWin = (WindowPtr)LookupID(stuff->id, RT←WINDOW, RC←CORE); if (!pWin) { client->errorValue = stuff->id; return BadWindow; } lastWasMotion = FALSE; rep.type = X←Reply; rep.sequenceNumber = client->sequence; rep.sameScreen = xTrue; /* XXX */ rep.mask = keyButtonState; rep.length = 0; rep.root = (ROOT)->wid; rep.rootX = sprite.hot.x; rep.rootY = sprite.hot.y; rep.winX = sprite.hot.x - pWin->absCorner.x; rep.winY = sprite.hot.y - pWin->absCorner.y; rep.child = None; for (t = sprite.win; t; t = t->parent) if (t->parent == pWin) { rep.child = t->wid; break; } WriteReplyToClient(client, sizeof(xQueryPointerReply), &rep); return(Success); } int ProcQueryKeymap(client) ClientPtr client; { xQueryKeymapReply rep; int i; rep.type = X←Reply; rep.sequenceNumber = client->sequence; rep.length = 2; for (i = 0; i<32; i++) rep.map[i] = inputInfo.keyboard->down[i]; WriteReplyToClient(client, sizeof(xQueryKeymapReply), &rep); return Success; } int ProcSendEvent(client) ClientPtr client; { WindowPtr pWin; WindowPtr effectiveFocus = NullWindow; /* only set if dest==InputFocus */ REQUEST(xSendEventReq); REQUEST←SIZE←MATCH(xSendEventReq); if (stuff->destination == PointerWindow) pWin = sprite.win; else if (stuff->destination == InputFocus) { WindowPtr inputFocus = inputInfo.keyboard->u.keybd.focus.win; if ((inputFocus == NoneWin) || (inputFocus == PointerRootWin)) return Success; if (IsParent(inputFocus, sprite.win)) { effectiveFocus = inputFocus; pWin = sprite.win; } else effectiveFocus = pWin = inputFocus; } else pWin = (WindowPtr)LookupID(stuff->destination, RT←WINDOW, RC←CORE); if (!pWin) { client->errorValue = stuff->destination; return BadWindow; } stuff->event.u.u.type |= 0x80; if (stuff->propagate) { for (;pWin; pWin = pWin->parent) { if (DeliverEventsToWindow( pWin, &stuff->event, 1, stuff->eventMask, NullGrab)) return Success; if (pWin == effectiveFocus) return Success; stuff->eventMask &= ~pWin->dontPropagateMask; } } else DeliverEventsToWindow( pWin, &stuff->event, 1, stuff->eventMask, NullGrab); return Success; } int ProcUngrabKey(client) ClientPtr client; { REQUEST(xUngrabKeyReq); WindowPtr pWin; GrabPtr grab; REQUEST←SIZE←MATCH(xUngrabKeyReq); pWin = (WindowPtr) LookupID(stuff->grabWindow, RT←WINDOW, RC←CORE); if (!pWin) { client->errorValue = stuff->grabWindow; return BadWindow; } for (grab = PASSIVEGRABS(pWin); grab; grab = grab->next) { if (MatchingGrab( (int)stuff->key, (int)stuff->modifiers, inputInfo.keyboard, grab, TRUE)) { if (client == grab->client) FreeResource(grab->resource, RC←NONE); /* * Might need to unlink multiple requests, the keys might * be put on individually, but taken off with an AnyMumble. */ } } return(Success); } int ProcGrabKey(client) ClientPtr client; { WindowPtr pWin; REQUEST(xGrabKeyReq); GrabPtr grab; Bool useOld = FALSE; REQUEST←SIZE←MATCH(xGrabKeyReq); if ((stuff->key > curKeySyms.maxKeyCode) || (stuff->key < curKeySyms.minKeyCode)) return BadValue; pWin = (WindowPtr)LookupID(stuff->grabWindow, RT←WINDOW, RC←CORE); client->errorValue = stuff->grabWindow; if (!pWin) { client->errorValue = stuff->grabWindow; return BadWindow; } for (grab = PASSIVEGRABS(pWin); grab; grab = grab->next) { if (MatchingGrab( (int)stuff->key, (int)stuff->modifiers, inputInfo.keyboard, grab, TRUE)) { if (client == grab->client) { useOld = TRUE; break; } else return BadAccess; } } if (!useOld) { grab = (GrabPtr)Xalloc(sizeof(GrabRec)); grab->next = PASSIVEGRABS(pWin); grab->resource = FakeClientID((int)client->index); pWin->passiveGrabs = (pointer)grab; AddResource(grab->resource, RT←FAKE, (pointer)pWin, PassiveClientGone, RC←CORE); } grab->client = client; grab->device = inputInfo.keyboard; grab->window = pWin; grab->eventMask = KeyPressMask | KeyReleaseMask; grab->ownerEvents = stuff->ownerEvents; grab->keyboardMode = stuff->keyboardMode; grab->pointerMode = stuff->pointerMode; grab->modifiers = stuff->modifiers; grab->u.keybd.key = stuff->key; return(Success); } int ProcGrabButton(client) ClientPtr client; { WindowPtr pWin, confineTo; REQUEST(xGrabButtonReq); GrabPtr grab; Bool useOld = FALSE; CursorPtr cursor; REQUEST←SIZE←MATCH(xGrabButtonReq); if ((stuff->pointerMode != GrabModeSync) && (stuff->pointerMode != GrabModeAsync) && (stuff->keyboardMode != GrabModeSync) && (stuff->keyboardMode != GrabModeAsync)) return BadValue; pWin = (WindowPtr) LookupID(stuff->grabWindow, RT←WINDOW, RC←CORE); if (!pWin) { client->errorValue = stuff->grabWindow; return BadWindow; } if (stuff->confineTo == None) confineTo = NullWindow; else { confineTo = (WindowPtr)LookupID(stuff->confineTo, RT←WINDOW, RC←CORE); if (!confineTo) { client->errorValue = stuff->confineTo; return BadWindow; } } if (stuff->cursor == None) cursor = NullCursor; else { cursor = (CursorPtr)LookupID(stuff->cursor, RT←CURSOR, RC←CORE); if (!cursor) { client->errorValue = stuff->cursor; return BadCursor; } } for (grab = PASSIVEGRABS(pWin); grab; grab = grab->next) { if (MatchingGrab( (int)stuff->button, (int)stuff->modifiers, inputInfo.pointer, grab, FALSE)) { if (client == grab->client) { useOld = TRUE; break; } else return BadAccess; } } if (!useOld) { grab = (GrabPtr)Xalloc(sizeof(GrabRec)); grab->next = PASSIVEGRABS(pWin); grab->resource = FakeClientID((int)client->index); pWin->passiveGrabs = (pointer)grab; AddResource(grab->resource, RT←FAKE, (pointer)pWin, PassiveClientGone, RC←CORE); } grab->client = client; grab->device = inputInfo.pointer; grab->window = pWin; grab->eventMask = stuff->eventMask | ButtonPress | ButtonRelease; grab->ownerEvents = stuff->ownerEvents; grab->keyboardMode = stuff->keyboardMode; grab->pointerMode = stuff->pointerMode; grab->modifiers = stuff->modifiers; grab->u.ptr.button = stuff->button; grab->u.ptr.confineTo = confineTo; grab->u.ptr.cursor = cursor; return(Success); } int ProcUngrabButton(client) ClientPtr client; { REQUEST(xUngrabButtonReq); WindowPtr pWin; GrabPtr grab; REQUEST←SIZE←MATCH(xUngrabButtonReq); pWin = (WindowPtr) LookupID(stuff->grabWindow, RT←WINDOW, RC←CORE); if (!pWin) { client->errorValue = stuff->grabWindow; return BadWindow; } for (grab = PASSIVEGRABS(pWin); grab; grab = grab->next) { if (MatchingGrab( (int)stuff->button, (int)stuff->modifiers, inputInfo.pointer, grab, FALSE)) { if (client == grab->client) FreeResource(grab->resource, RC←NONE); /* * Might need to unlink multiple requests, the buttons might * be put on individually, but taken off with an AnyMumble. */ } } return(Success); } void DeleteWindowFromAnyEvents(pWin, freeResources) WindowPtr pWin; Bool freeResources; { WindowPtr parent; FocusPtr focus = &inputInfo.keyboard->u.keybd.focus; DeviceIntPtr mouse = inputInfo.pointer; OtherClientsPtr oc; GrabPtr passive; if (pWin == focus->win) { switch (focus->revert) { case RevertToNone: DoFocusEvents(pWin, NoneWin, NotifyNormal); focus->win = NoneWin; case RevertToParent: for ( parent = pWin->parent; !parent->realized; parent = parent->parent); DoFocusEvents(pWin, parent, NotifyNormal); focus->win = parent; focus->revert = RevertToNone; case RevertToPointerRoot: DoFocusEvents(pWin, PointerRootWin, NotifyNormal); focus->win = PointerRootWin; } } if ((mouse->grab) && (mouse->grab->window == pWin)) DeactivatePointerGrab(mouse); if ((inputInfo.keyboard->grab) && (inputInfo.keyboard->grab->window == pWin)) DeactivateKeyboardGrab(inputInfo.keyboard); if (freeResources) { while (oc = OTHERCLIENTS(pWin)) FreeResource(oc->resource, RC←NONE); while (passive = PASSIVEGRABS(pWin)) FreeResource(passive->resource, RC←NONE); } } Mask EventMaskForClient(win, client, allMask) WindowPtr win; ClientPtr client; Mask *allMask; { OtherClientsPtr other; Mask him; if (win->client == client) him = win->eventMask; *allMask = win->eventMask; for (other = OTHERCLIENTS(win); other; other = other->next) { if (other->client == client) him = other->mask; *allMask |= other->mask; } return him; } int ProcRecolorCursor(client) ClientPtr client; { CursorPtr pCursor; int nscr; ScreenPtr pscr; REQUEST(xRecolorCursorReq); REQUEST←SIZE←MATCH(xRecolorCursorReq); pCursor = (CursorPtr)LookupID(stuff->cursor, RT←CURSOR, RC←CORE); if ( !pCursor) { client->errorValue = stuff->cursor; return (BadCursor); } pCursor->foreRed = stuff->foreRed; pCursor->foreGreen = stuff->foreGreen; pCursor->foreBlue = stuff->foreBlue; pCursor->backRed = stuff->backRed; pCursor->backGreen = stuff->backGreen; pCursor->backBlue = stuff->backBlue; for ( nscr=0, pscr=screenInfo.screen; nscr<screenInfo.numScreens; nscr++, pscr++) { ( *pscr->RecolorCursor)(pscr, pCursor, (pCursor == sprite.current) && (pscr == currentScreen)); } return (Success); } void WriteEventToClient(pClient, count, pbuf) ClientPtr pClient; int count; char *pbuf; { if(pClient->swapped) { int iEvent; for(iEvent = 0; iEvent < count; iEvent++) (*EventSwapVector[(((xEvent *)pbuf) + iEvent)->u.u.type]) (pClient, sizeof(xEvent), (xEvent *)pbuf); } else { WriteToClient(pClient, count * sizeof(xEvent), pbuf); } }