021fc5cb2c
The former <X11/extensions/XKBsrv.h> has been pulled into the server now as include/xkbsrv.h, and the world updated to look for it in the new place, since it made no sense to define server API in an extension header. Any further work along this line will need to do similar things with XKBgeom.h and friends.
1928 lines
51 KiB
C
1928 lines
51 KiB
C
/************************************************************
|
|
|
|
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 <dix-config.h>
|
|
#endif
|
|
|
|
#include <X11/X.h>
|
|
#include "misc.h"
|
|
#include "resource.h"
|
|
#define NEED_EVENTS
|
|
#define NEED_REPLIES
|
|
#include <X11/Xproto.h>
|
|
#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 <xkbsrv.h>
|
|
#endif
|
|
#include "xace.h"
|
|
|
|
#include "dispatch.h"
|
|
#include "swaprep.h"
|
|
#include "dixevents.h"
|
|
|
|
#include <X11/extensions/XIproto.h>
|
|
#include "exglobals.h"
|
|
#include "exevents.h"
|
|
|
|
int CoreDevicePrivatesIndex = 0, CoreDevicePrivatesGeneration = -1;
|
|
|
|
DeviceIntPtr
|
|
AddInputDevice(DeviceProc deviceProc, Bool autoStart)
|
|
{
|
|
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(DeviceIntPtr dev)
|
|
{
|
|
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(DeviceIntPtr dev)
|
|
{
|
|
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()
|
|
{
|
|
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;
|
|
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;
|
|
(void)ActivateDevice(dev);
|
|
inputInfo.pointer = dev;
|
|
}
|
|
}
|
|
|
|
int
|
|
InitAndStartDevices()
|
|
{
|
|
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(DeviceIntPtr dev)
|
|
{
|
|
KbdFeedbackPtr k, knext;
|
|
PtrFeedbackPtr p, pnext;
|
|
IntegerFeedbackPtr i, inext;
|
|
StringFeedbackPtr s, snext;
|
|
BellFeedbackPtr b, bnext;
|
|
LedFeedbackPtr l, lnext;
|
|
|
|
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 (dev->devPrivates)
|
|
xfree(dev->devPrivates);
|
|
|
|
xfree(dev->sync.event);
|
|
xfree(dev);
|
|
}
|
|
|
|
void
|
|
CloseDownDevices()
|
|
{
|
|
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()
|
|
{
|
|
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(KeySymsPtr dst, 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(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;
|
|
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(DeviceIntPtr dev, int numButtons,
|
|
CARD8 *map)
|
|
{
|
|
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;
|
|
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; i<numAxes; i++) {
|
|
InitValuatorAxisStruct(dev, i, 0, -1, 0, 0, 0);
|
|
valc->axisVal[i]=0;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
_X_EXPORT Bool
|
|
InitAbsoluteClassDeviceStruct(DeviceIntPtr dev)
|
|
{
|
|
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)
|
|
{
|
|
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)
|
|
{
|
|
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)
|
|
{
|
|
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;
|
|
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; i<num_symbols_supported; i++)
|
|
*(feedc->ctrl.symbols_supported+i) = *symbols++;
|
|
for (i=0; i<max_symbols; i++)
|
|
*(feedc->ctrl.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)
|
|
{
|
|
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)
|
|
{
|
|
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)
|
|
{
|
|
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(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(inputInfo.keyboard,request,firstKeyCode,count,
|
|
client);
|
|
}
|
|
#endif
|
|
|
|
/* 0 is the server client */
|
|
for (i=1; i<currentMaxClients; i++)
|
|
{
|
|
if (clients[i] && clients[i]->clientState == 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(BYTE *buff, int length, unsigned low, unsigned high, XID *errval)
|
|
{
|
|
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)
|
|
DeviceIntPtr dev;
|
|
CARD8 *map1, *map2;
|
|
int per1, per2;
|
|
{
|
|
int i, j, k;
|
|
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(MappingModifier, 0, 0, client);
|
|
WriteReplyToClient(client, sizeof(xSetModifierMappingReply), &rep);
|
|
return client->noClientException;
|
|
}
|
|
|
|
int
|
|
ProcGetModifierMapping(ClientPtr client)
|
|
{
|
|
xGetModifierMappingReply rep;
|
|
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(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;
|
|
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. */
|
|
if (stuff->nElts != inputInfo.pointer->button->numButtons) {
|
|
client->errorValue = stuff->nElts;
|
|
return BadValue;
|
|
}
|
|
if (BadDeviceMap(&map[0], (int)stuff->nElts, 1, 255, &client->errorValue))
|
|
return BadValue;
|
|
|
|
ret = DoSetPointerMapping(inputInfo.pointer, 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(MappingPointer, 0, 0, client);
|
|
WriteReplyToClient(client, sizeof(xSetPointerMappingReply), &rep);
|
|
return Success;
|
|
}
|
|
|
|
int
|
|
ProcGetKeyboardMapping(ClientPtr client)
|
|
{
|
|
xGetKeyboardMappingReply rep;
|
|
REQUEST(xGetKeyboardMappingReq);
|
|
KeySymsPtr curKeySyms = &inputInfo.keyboard->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;
|
|
ButtonClassPtr butc = inputInfo.pointer->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 */
|
|
{
|
|
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;
|
|
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)
|
|
{
|
|
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 = inputInfo.pointer;
|
|
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 == inputInfo.pointer) &&
|
|
mouse->ptrfeed && mouse->ptrfeed->CtrlProc) {
|
|
mouse->ptrfeed->ctrl = ctrl;
|
|
(*mouse->ptrfeed->CtrlProc)(mouse, &mouse->ptrfeed->ctrl);
|
|
}
|
|
}
|
|
|
|
return Success;
|
|
}
|
|
|
|
int
|
|
ProcGetPointerControl(ClientPtr client)
|
|
{
|
|
PtrCtrl *ctrl = &inputInfo.pointer->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(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 = inputInfo.pointer;
|
|
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;
|
|
}
|