/************************************************************
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);
}
}