#ifdef HAVE_DIX_CONFIG_H
#include <dix-config.h>
#endif
#include <stdio.h>
#include <X11/X.h>
#define NEED_EVENTS
#define NEED_REPLIES
#include <X11/Xproto.h>
#include "misc.h"
#include "inputstr.h"
#define XKBSRV_NEED_FILE_FUNCS
#include <xkbsrv.h>
#include "extnsionst.h"
#include "xace.h"
#include "xkb.h"
#include <X11/extensions/XI.h>
int XkbEventBase;
static int XkbErrorBase;
int XkbReqCode;
int XkbKeyboardErrorCode;
CARD32 xkbDebugFlags = 0;
static CARD32 xkbDebugCtrls = 0;
static RESTYPE RT_XKBCLIENT;
#define CHK_DEVICE(dev, id, client, access_mode, lf) {\
int why;\
int rc = lf(&(dev), id, client, access_mode, &why);\
if (rc != Success) {\
client->errorValue = _XkbErrCode2(why, id);\
return rc;\
}\
}
#define CHK_KBD_DEVICE(dev, id, client, mode) \
CHK_DEVICE(dev, id, client, mode, _XkbLookupKeyboard)
#define CHK_LED_DEVICE(dev, id, client, mode) \
CHK_DEVICE(dev, id, client, mode, _XkbLookupLedDevice)
#define CHK_BELL_DEVICE(dev, id, client, mode) \
CHK_DEVICE(dev, id, client, mode, _XkbLookupBellDevice)
#define CHK_ANY_DEVICE(dev, id, client, mode) \
CHK_DEVICE(dev, id, client, mode, _XkbLookupAnyDevice)
#define CHK_ATOM_ONLY2(a,ev,er) {\
if (((a)==None)||(!ValidAtom((a)))) {\
(ev)= (XID)(a);\
return er;\
}\
}
#define CHK_ATOM_ONLY(a) \
CHK_ATOM_ONLY2(a,client->errorValue,BadAtom)
#define CHK_ATOM_OR_NONE3(a,ev,er,ret) {\
if (((a)!=None)&&(!ValidAtom((a)))) {\
(ev)= (XID)(a);\
(er)= BadAtom;\
return ret;\
}\
}
#define CHK_ATOM_OR_NONE2(a,ev,er) {\
if (((a)!=None)&&(!ValidAtom((a)))) {\
(ev)= (XID)(a);\
return er;\
}\
}
#define CHK_ATOM_OR_NONE(a) \
CHK_ATOM_OR_NONE2(a,client->errorValue,BadAtom)
#define CHK_MASK_LEGAL3(err,mask,legal,ev,er,ret) {\
if ((mask)&(~(legal))) { \
(ev)= _XkbErrCode2((err),((mask)&(~(legal))));\
(er)= BadValue;\
return ret;\
}\
}
#define CHK_MASK_LEGAL2(err,mask,legal,ev,er) {\
if ((mask)&(~(legal))) { \
(ev)= _XkbErrCode2((err),((mask)&(~(legal))));\
return er;\
}\
}
#define CHK_MASK_LEGAL(err,mask,legal) \
CHK_MASK_LEGAL2(err,mask,legal,client->errorValue,BadValue)
#define CHK_MASK_MATCH(err,affect,value) {\
if ((value)&(~(affect))) { \
client->errorValue= _XkbErrCode2((err),((value)&(~(affect))));\
return BadMatch;\
}\
}
#define CHK_MASK_OVERLAP(err,m1,m2) {\
if ((m1)&(m2)) { \
client->errorValue= _XkbErrCode2((err),((m1)&(m2)));\
return BadMatch;\
}\
}
#define CHK_KEY_RANGE2(err,first,num,x,ev,er) {\
if (((unsigned)(first)+(num)-1)>(x)->max_key_code) {\
(ev)=_XkbErrCode4(err,(first),(num),(x)->max_key_code);\
return er;\
}\
else if ( (first)<(x)->min_key_code ) {\
(ev)=_XkbErrCode3(err+1,(first),xkb->min_key_code);\
return er;\
}\
}
#define CHK_KEY_RANGE(err,first,num,x) \
CHK_KEY_RANGE2(err,first,num,x,client->errorValue,BadValue)
#define CHK_REQ_KEY_RANGE2(err,first,num,r,ev,er) {\
if (((unsigned)(first)+(num)-1)>(r)->maxKeyCode) {\
(ev)=_XkbErrCode4(err,(first),(num),(r)->maxKeyCode);\
return er;\
}\
else if ( (first)<(r)->minKeyCode ) {\
(ev)=_XkbErrCode3(err+1,(first),(r)->minKeyCode);\
return er;\
}\
}
#define CHK_REQ_KEY_RANGE(err,first,num,r) \
CHK_REQ_KEY_RANGE2(err,first,num,r,client->errorValue,BadValue)
int
ProcXkbUseExtension(ClientPtr client)
{
REQUEST(xkbUseExtensionReq);
xkbUseExtensionReply rep;
register int n;
int supported;
REQUEST_SIZE_MATCH(xkbUseExtensionReq);
if (stuff->wantedMajor != XkbMajorVersion) {
supported= ((XkbMajorVersion==1)&&
(stuff->wantedMajor==0)&&(stuff->wantedMinor==65));
}
else supported = 1;
if ((supported) && (!(client->xkbClientFlags&_XkbClientInitialized))) {
client->xkbClientFlags= _XkbClientInitialized;
client->vMajor= stuff->wantedMajor;
client->vMinor= stuff->wantedMinor;
}
else if (xkbDebugFlags&0x1) {
ErrorF("[xkb] Rejecting client %d (0x%lx) (wants %d.%02d, have %d.%02d)\n",
client->index,
(long)client->clientAsMask,
stuff->wantedMajor,stuff->wantedMinor,
XkbMajorVersion,XkbMinorVersion);
}
rep.type = X_Reply;
rep.supported = supported;
rep.length = 0;
rep.sequenceNumber = client->sequence;
rep.serverMajor = XkbMajorVersion;
rep.serverMinor = XkbMinorVersion;
if ( client->swapped ) {
swaps(&rep.sequenceNumber, n);
swaps(&rep.serverMajor, n);
swaps(&rep.serverMinor, n);
}
WriteToClient(client,SIZEOF(xkbUseExtensionReply), (char *)&rep);
return client->noClientException;
}
int
ProcXkbSelectEvents(ClientPtr client)
{
unsigned legal;
DeviceIntPtr dev;
XkbInterestPtr masks;
REQUEST(xkbSelectEventsReq);
REQUEST_AT_LEAST_SIZE(xkbSelectEventsReq);
if (!(client->xkbClientFlags&_XkbClientInitialized))
return BadAccess;
CHK_ANY_DEVICE(dev, stuff->deviceSpec, client, DixUseAccess);
if (((stuff->affectWhich&XkbMapNotifyMask)!=0)&&(stuff->affectMap)) {
client->mapNotifyMask&= ~stuff->affectMap;
client->mapNotifyMask|= (stuff->affectMap&stuff->map);
}
if ((stuff->affectWhich&(~XkbMapNotifyMask))==0)
return client->noClientException;
masks = XkbFindClientResource((DevicePtr)dev,client);
if (!masks){
XID id = FakeClientID(client->index);
AddResource(id,RT_XKBCLIENT,dev);
masks= XkbAddClientResource((DevicePtr)dev,client,id);
}
if (masks) {
union {
CARD8 *c8;
CARD16 *c16;
CARD32 *c32;
} from,to;
register unsigned bit,ndx,maskLeft,dataLeft,size;
from.c8= (CARD8 *)&stuff[1];
dataLeft= (stuff->length*4)-SIZEOF(xkbSelectEventsReq);
maskLeft= (stuff->affectWhich&(~XkbMapNotifyMask));
for (ndx=0,bit=1; (maskLeft!=0); ndx++, bit<<=1) {
if ((bit&maskLeft)==0)
continue;
maskLeft&= ~bit;
switch (ndx) {
case XkbNewKeyboardNotify:
to.c16= &client->newKeyboardNotifyMask;
legal= XkbAllNewKeyboardEventsMask;
size= 2;
break;
case XkbStateNotify:
to.c16= &masks->stateNotifyMask;
legal= XkbAllStateEventsMask;
size= 2;
break;
case XkbControlsNotify:
to.c32= &masks->ctrlsNotifyMask;
legal= XkbAllControlEventsMask;
size= 4;
break;
case XkbIndicatorStateNotify:
to.c32= &masks->iStateNotifyMask;
legal= XkbAllIndicatorEventsMask;
size= 4;
break;
case XkbIndicatorMapNotify:
to.c32= &masks->iMapNotifyMask;
legal= XkbAllIndicatorEventsMask;
size= 4;
break;
case XkbNamesNotify:
to.c16= &masks->namesNotifyMask;
legal= XkbAllNameEventsMask;
size= 2;
break;
case XkbCompatMapNotify:
to.c8= &masks->compatNotifyMask;
legal= XkbAllCompatMapEventsMask;
size= 1;
break;
case XkbBellNotify:
to.c8= &masks->bellNotifyMask;
legal= XkbAllBellEventsMask;
size= 1;
break;
case XkbActionMessage:
to.c8= &masks->actionMessageMask;
legal= XkbAllActionMessagesMask;
size= 1;
break;
case XkbAccessXNotify:
to.c16= &masks->accessXNotifyMask;
legal= XkbAllAccessXEventsMask;
size= 2;
break;
case XkbExtensionDeviceNotify:
to.c16= &masks->extDevNotifyMask;
legal= XkbAllExtensionDeviceEventsMask;
size= 2;
break;
default:
client->errorValue = _XkbErrCode2(33,bit);
return BadValue;
}
if (stuff->clear&bit) {
if (size==2) to.c16[0]= 0;
else if (size==4) to.c32[0]= 0;
else to.c8[0]= 0;
}
else if (stuff->selectAll&bit) {
if (size==2) to.c16[0]= ~0;
else if (size==4) to.c32[0]= ~0;
else to.c8[0]= ~0;
}
else {
if (dataLeft<(size*2))
return BadLength;
if (size==2) {
CHK_MASK_MATCH(ndx,from.c16[0],from.c16[1]);
CHK_MASK_LEGAL(ndx,from.c16[0],legal);
to.c16[0]&= ~from.c16[0];
to.c16[0]|= (from.c16[0]&from.c16[1]);
}
else if (size==4) {
CHK_MASK_MATCH(ndx,from.c32[0],from.c32[1]);
CHK_MASK_LEGAL(ndx,from.c32[0],legal);
to.c32[0]&= ~from.c32[0];
to.c32[0]|= (from.c32[0]&from.c32[1]);
}
else {
CHK_MASK_MATCH(ndx,from.c8[0],from.c8[1]);
CHK_MASK_LEGAL(ndx,from.c8[0],legal);
to.c8[0]&= ~from.c8[0];
to.c8[0]|= (from.c8[0]&from.c8[1]);
size= 2;
}
from.c8+= (size*2);
dataLeft-= (size*2);
}
}
if (dataLeft>2) {
ErrorF("[xkb] Extra data (%d bytes) after SelectEvents\n",dataLeft);
return BadLength;
}
return client->noClientException;
}
return BadAlloc;
}
static int
_XkbBell(ClientPtr client, DeviceIntPtr dev, WindowPtr pWin,
int bellClass, int bellID, int pitch, int duration,
int percent, int forceSound, int eventOnly, Atom name)
{
int base;
pointer ctrl;
int oldPitch, oldDuration;
int newPercent;
if (bellClass == KbdFeedbackClass) {
KbdFeedbackPtr k;
if (bellID==XkbDfltXIId)
k= dev->kbdfeed;
else {
for (k=dev->kbdfeed; k; k=k->next) {
if (k->ctrl.id == bellID)
break;
}
}
if (!k) {
client->errorValue = _XkbErrCode2(0x5,bellID);
return BadValue;
}
base = k->ctrl.bell;
ctrl = (pointer) &(k->ctrl);
oldPitch= k->ctrl.bell_pitch;
oldDuration= k->ctrl.bell_duration;
if (pitch!=0) {
if (pitch==-1)
k->ctrl.bell_pitch= defaultKeyboardControl.bell_pitch;
else k->ctrl.bell_pitch= pitch;
}
if (duration!=0) {
if (duration==-1)
k->ctrl.bell_duration= defaultKeyboardControl.bell_duration;
else k->ctrl.bell_duration= duration;
}
}
else if (bellClass == BellFeedbackClass) {
BellFeedbackPtr b;
if (bellID==XkbDfltXIId)
b= dev->bell;
else {
for (b=dev->bell; b; b=b->next) {
if (b->ctrl.id == bellID)
break;
}
}
if (!b) {
client->errorValue = _XkbErrCode2(0x6,bellID);
return BadValue;
}
base = b->ctrl.percent;
ctrl = (pointer) &(b->ctrl);
oldPitch= b->ctrl.pitch;
oldDuration= b->ctrl.duration;
if (pitch!=0) {
if (pitch==-1)
b->ctrl.pitch= defaultKeyboardControl.bell_pitch;
else b->ctrl.pitch= pitch;
}
if (duration!=0) {
if (duration==-1)
b->ctrl.duration= defaultKeyboardControl.bell_duration;
else b->ctrl.duration= duration;
}
}
else {
client->errorValue = _XkbErrCode2(0x7, bellClass);
return BadValue;
}
newPercent = (base * percent)/100;
if (percent < 0)
newPercent = base + newPercent;
else newPercent = base - newPercent + percent;
XkbHandleBell(forceSound, eventOnly,
dev, newPercent, ctrl, bellClass,
name, pWin, client);
if ((pitch!=0)||(duration!=0)) {
if (bellClass == KbdFeedbackClass) {
KbdFeedbackPtr k;
k= (KbdFeedbackPtr)ctrl;
if (pitch!=0)
k->ctrl.bell_pitch= oldPitch;
if (duration!=0)
k->ctrl.bell_duration= oldDuration;
}
else {
BellFeedbackPtr b;
b= (BellFeedbackPtr)ctrl;
if (pitch!=0)
b->ctrl.pitch= oldPitch;
if (duration!=0)
b->ctrl.duration= oldDuration;
}
}
return Success;
}
int
ProcXkbBell(ClientPtr client)
{
REQUEST(xkbBellReq);
DeviceIntPtr dev;
WindowPtr pWin;
int rc;
REQUEST_SIZE_MATCH(xkbBellReq);
if (!(client->xkbClientFlags&_XkbClientInitialized))
return BadAccess;
CHK_BELL_DEVICE(dev, stuff->deviceSpec, client, DixBellAccess);
CHK_ATOM_OR_NONE(stuff->name);
if ((stuff->forceSound)&&(stuff->eventOnly)) {
client->errorValue=_XkbErrCode3(0x1,stuff->forceSound,stuff->eventOnly);
return BadMatch;
}
if (stuff->percent < -100 || stuff->percent > 100) {
client->errorValue = _XkbErrCode2(0x2,stuff->percent);
return BadValue;
}
if (stuff->duration<-1) {
client->errorValue = _XkbErrCode2(0x3,stuff->duration);
return BadValue;
}
if (stuff->pitch<-1) {
client->errorValue = _XkbErrCode2(0x4,stuff->pitch);
return BadValue;
}
if (stuff->bellClass == XkbDfltXIClass) {
if (dev->kbdfeed!=NULL)
stuff->bellClass= KbdFeedbackClass;
else stuff->bellClass= BellFeedbackClass;
}
if (stuff->window!=None) {
rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
if (rc != Success) {
client->errorValue= stuff->window;
return rc;
}
}
else pWin= NULL;
rc = _XkbBell(client, dev, pWin, stuff->bellClass, stuff->bellID,
stuff->pitch, stuff->duration, stuff->percent,
stuff->forceSound, stuff->eventOnly, stuff->name);
if ((rc == Success) && ((stuff->deviceSpec == XkbUseCoreKbd) ||
(stuff->deviceSpec == XkbUseCorePtr)))
{
DeviceIntPtr other;
for (other = inputInfo.devices; other; other = other->next)
{
if ((other != dev) && other->key && !other->isMaster && (other->u.master == dev))
{
rc = XaceHook(XACE_DEVICE_ACCESS, client, other, DixBellAccess);
if (rc == Success)
_XkbBell(client, other, pWin, stuff->bellClass,
stuff->bellID, stuff->pitch, stuff->duration,
stuff->percent, stuff->forceSound,
stuff->eventOnly, stuff->name);
}
}
rc = Success;
}
return rc;
}
int
ProcXkbGetState(ClientPtr client)
{
REQUEST(xkbGetStateReq);
DeviceIntPtr dev;
xkbGetStateReply rep;
XkbStateRec *xkb;
REQUEST_SIZE_MATCH(xkbGetStateReq);
if (!(client->xkbClientFlags&_XkbClientInitialized))
return BadAccess;
CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess);
xkb= &dev->key->xkbInfo->state;
bzero(&rep,sizeof(xkbGetStateReply));
rep.type= X_Reply;
rep.sequenceNumber= client->sequence;
rep.length = 0;
rep.deviceID = dev->id;
rep.mods = dev->key->state&0xff;
rep.baseMods = xkb->base_mods;
rep.lockedMods = xkb->locked_mods;
rep.latchedMods = xkb->latched_mods;
rep.group = xkb->group;
rep.baseGroup = xkb->base_group;
rep.latchedGroup = xkb->latched_group;
rep.lockedGroup = xkb->locked_group;
rep.compatState = xkb->compat_state;
rep.ptrBtnState = xkb->ptr_buttons;
if (client->swapped) {
register int n;
swaps(&rep.sequenceNumber,n);
swaps(&rep.ptrBtnState,n);
}
WriteToClient(client, SIZEOF(xkbGetStateReply), (char *)&rep);
return client->noClientException;
}
int
ProcXkbLatchLockState(ClientPtr client)
{
int status;
DeviceIntPtr dev, tmpd;
XkbStateRec oldState,*newState;
CARD16 changed;
xkbStateNotify sn;
XkbEventCauseRec cause;
REQUEST(xkbLatchLockStateReq);
REQUEST_SIZE_MATCH(xkbLatchLockStateReq);
if (!(client->xkbClientFlags & _XkbClientInitialized))
return BadAccess;
CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixSetAttrAccess);
CHK_MASK_MATCH(0x01, stuff->affectModLocks, stuff->modLocks);
CHK_MASK_MATCH(0x01, stuff->affectModLatches, stuff->modLatches);
status = Success;
for (tmpd = inputInfo.devices; tmpd; tmpd = tmpd->next) {
if ((dev == inputInfo.keyboard && tmpd->key && tmpd->coreEvents) ||
tmpd == dev) {
if (!tmpd->key->xkbInfo)
continue;
oldState = tmpd->key->xkbInfo->state;
newState = &tmpd->key->xkbInfo->state;
if (stuff->affectModLocks) {
newState->locked_mods &= ~stuff->affectModLocks;
newState->locked_mods |= (stuff->affectModLocks & stuff->modLocks);
}
if (status == Success && stuff->lockGroup)
newState->locked_group = stuff->groupLock;
if (status == Success && stuff->affectModLatches)
status = XkbLatchModifiers(tmpd, stuff->affectModLatches,
stuff->modLatches);
if (status == Success && stuff->latchGroup)
status = XkbLatchGroup(tmpd, stuff->groupLatch);
if (status != Success)
return status;
XkbComputeDerivedState(tmpd->key->xkbInfo);
tmpd->key->state = XkbStateFieldFromRec(newState);
changed = XkbStateChangedFlags(&oldState, newState);
if (changed) {
sn.keycode = 0;
sn.eventType = 0;
sn.requestMajor = XkbReqCode;
sn.requestMinor = X_kbLatchLockState;
sn.changed = changed;
XkbSendStateNotify(tmpd, &sn);
changed = XkbIndicatorsToUpdate(tmpd, changed, False);
if (changed) {
XkbSetCauseXkbReq(&cause, X_kbLatchLockState, client);
XkbUpdateIndicators(tmpd, changed, True, NULL, &cause);
}
}
}
}
return client->noClientException;
}
int
ProcXkbGetControls(ClientPtr client)
{
xkbGetControlsReply rep;
XkbControlsPtr xkb;
DeviceIntPtr dev;
register int n;
REQUEST(xkbGetControlsReq);
REQUEST_SIZE_MATCH(xkbGetControlsReq);
if (!(client->xkbClientFlags&_XkbClientInitialized))
return BadAccess;
CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess);
xkb = dev->key->xkbInfo->desc->ctrls;
rep.type = X_Reply;
rep.length = (SIZEOF(xkbGetControlsReply)-
SIZEOF(xGenericReply)) >> 2;
rep.sequenceNumber = client->sequence;
rep.deviceID = ((DeviceIntPtr)dev)->id;
rep.numGroups = xkb->num_groups;
rep.groupsWrap = xkb->groups_wrap;
rep.internalMods = xkb->internal.mask;
rep.ignoreLockMods = xkb->ignore_lock.mask;
rep.internalRealMods = xkb->internal.real_mods;
rep.ignoreLockRealMods = xkb->ignore_lock.real_mods;
rep.internalVMods = xkb->internal.vmods;
rep.ignoreLockVMods = xkb->ignore_lock.vmods;
rep.enabledCtrls = xkb->enabled_ctrls;
rep.repeatDelay = xkb->repeat_delay;
rep.repeatInterval = xkb->repeat_interval;
rep.slowKeysDelay = xkb->slow_keys_delay;
rep.debounceDelay = xkb->debounce_delay;
rep.mkDelay = xkb->mk_delay;
rep.mkInterval = xkb->mk_interval;
rep.mkTimeToMax = xkb->mk_time_to_max;
rep.mkMaxSpeed = xkb->mk_max_speed;
rep.mkCurve = xkb->mk_curve;
rep.mkDfltBtn = xkb->mk_dflt_btn;
rep.axTimeout = xkb->ax_timeout;
rep.axtCtrlsMask = xkb->axt_ctrls_mask;
rep.axtCtrlsValues = xkb->axt_ctrls_values;
rep.axtOptsMask = xkb->axt_opts_mask;
rep.axtOptsValues = xkb->axt_opts_values;
rep.axOptions = xkb->ax_options;
memcpy(rep.perKeyRepeat,xkb->per_key_repeat,XkbPerKeyBitArraySize);
if (client->swapped) {
swaps(&rep.sequenceNumber, n);
swapl(&rep.length,n);
swaps(&rep.internalVMods, n);
swaps(&rep.ignoreLockVMods, n);
swapl(&rep.enabledCtrls, n);
swaps(&rep.repeatDelay, n);
swaps(&rep.repeatInterval, n);
swaps(&rep.slowKeysDelay, n);
swaps(&rep.debounceDelay, n);
swaps(&rep.mkDelay, n);
swaps(&rep.mkInterval, n);
swaps(&rep.mkTimeToMax, n);
swaps(&rep.mkMaxSpeed, n);
swaps(&rep.mkCurve, n);
swaps(&rep.axTimeout, n);
swapl(&rep.axtCtrlsMask, n);
swapl(&rep.axtCtrlsValues, n);
swaps(&rep.axtOptsMask, n);
swaps(&rep.axtOptsValues, n);
swaps(&rep.axOptions, n);
}
WriteToClient(client, SIZEOF(xkbGetControlsReply), (char *)&rep);
return(client->noClientException);
}
int
ProcXkbSetControls(ClientPtr client)
{
DeviceIntPtr dev, tmpd;
XkbSrvInfoPtr xkbi;
XkbControlsPtr ctrl;
XkbControlsRec new,old;
xkbControlsNotify cn;
XkbEventCauseRec cause;
XkbSrvLedInfoPtr sli;
REQUEST(xkbSetControlsReq);
REQUEST_SIZE_MATCH(xkbSetControlsReq);
if (!(client->xkbClientFlags & _XkbClientInitialized))
return BadAccess;
CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess);
CHK_MASK_LEGAL(0x01, stuff->changeCtrls, XkbAllControlsMask);
for (tmpd = inputInfo.keyboard; tmpd; tmpd = tmpd->next) {
if ((dev == inputInfo.keyboard && tmpd->key && tmpd->coreEvents) ||
tmpd == dev) {
xkbi = tmpd->key->xkbInfo;
ctrl = xkbi->desc->ctrls;
new = *ctrl;
XkbSetCauseXkbReq(&cause, X_kbSetControls, client);
if (stuff->changeCtrls & XkbInternalModsMask) {
CHK_MASK_MATCH(0x02, stuff->affectInternalMods,
stuff->internalMods);
CHK_MASK_MATCH(0x03, stuff->affectInternalVMods,
stuff->internalVMods);
new.internal.real_mods &= ~(stuff->affectInternalMods);
new.internal.real_mods |= (stuff->affectInternalMods &
stuff->internalMods);
new.internal.vmods &= ~(stuff->affectInternalVMods);
new.internal.vmods |= (stuff->affectInternalVMods &
stuff->internalVMods);
new.internal.mask = new.internal.real_mods |
XkbMaskForVMask(xkbi->desc,
new.internal.vmods);
}
if (stuff->changeCtrls & XkbIgnoreLockModsMask) {
CHK_MASK_MATCH(0x4, stuff->affectIgnoreLockMods,
stuff->ignoreLockMods);
CHK_MASK_MATCH(0x5, stuff->affectIgnoreLockVMods,
stuff->ignoreLockVMods);
new.ignore_lock.real_mods &= ~(stuff->affectIgnoreLockMods);
new.ignore_lock.real_mods |= (stuff->affectIgnoreLockMods &
stuff->ignoreLockMods);
new.ignore_lock.vmods &= ~(stuff->affectIgnoreLockVMods);
new.ignore_lock.vmods |= (stuff->affectIgnoreLockVMods &
stuff->ignoreLockVMods);
new.ignore_lock.mask = new.ignore_lock.real_mods |
XkbMaskForVMask(xkbi->desc,
new.ignore_lock.vmods);
}
CHK_MASK_MATCH(0x06, stuff->affectEnabledCtrls,
stuff->enabledCtrls);
if (stuff->affectEnabledCtrls) {
CHK_MASK_LEGAL(0x07, stuff->affectEnabledCtrls,
XkbAllBooleanCtrlsMask);
new.enabled_ctrls &= ~(stuff->affectEnabledCtrls);
new.enabled_ctrls |= (stuff->affectEnabledCtrls &
stuff->enabledCtrls);
}
if (stuff->changeCtrls & XkbRepeatKeysMask) {
if (stuff->repeatDelay < 1 || stuff->repeatInterval < 1) {
client->errorValue = _XkbErrCode3(0x08, stuff->repeatDelay,
stuff->repeatInterval);
return BadValue;
}
new.repeat_delay = stuff->repeatDelay;
new.repeat_interval = stuff->repeatInterval;
}
if (stuff->changeCtrls & XkbSlowKeysMask) {
if (stuff->slowKeysDelay < 1) {
client->errorValue = _XkbErrCode2(0x09,
stuff->slowKeysDelay);
return BadValue;
}
new.slow_keys_delay = stuff->slowKeysDelay;
}
if (stuff->changeCtrls & XkbBounceKeysMask) {
if (stuff->debounceDelay < 1) {
client->errorValue = _XkbErrCode2(0x0A,
stuff->debounceDelay);
return BadValue;
}
new.debounce_delay = stuff->debounceDelay;
}
if (stuff->changeCtrls & XkbMouseKeysMask) {
if (stuff->mkDfltBtn > XkbMaxMouseKeysBtn) {
client->errorValue = _XkbErrCode2(0x0B, stuff->mkDfltBtn);
return BadValue;
}
new.mk_dflt_btn = stuff->mkDfltBtn;
}
if (stuff->changeCtrls & XkbMouseKeysAccelMask) {
if (stuff->mkDelay < 1 || stuff->mkInterval < 1 ||
stuff->mkTimeToMax < 1 || stuff->mkMaxSpeed < 1 ||
stuff->mkCurve < -1000) {
client->errorValue = _XkbErrCode2(0x0C,0);
return BadValue;
}
new.mk_delay = stuff->mkDelay;
new.mk_interval = stuff->mkInterval;
new.mk_time_to_max = stuff->mkTimeToMax;
new.mk_max_speed = stuff->mkMaxSpeed;
new.mk_curve = stuff->mkCurve;
AccessXComputeCurveFactor(xkbi, &new);
}
if (stuff->changeCtrls & XkbGroupsWrapMask) {
unsigned act, num;
act = XkbOutOfRangeGroupAction(stuff->groupsWrap);
switch (act) {
case XkbRedirectIntoRange:
num = XkbOutOfRangeGroupNumber(stuff->groupsWrap);
if (num >= new.num_groups) {
client->errorValue = _XkbErrCode3(0x0D, new.num_groups,
num);
return BadValue;
}
case XkbWrapIntoRange:
case XkbClampIntoRange:
break;
default:
client->errorValue = _XkbErrCode2(0x0E, act);
return BadValue;
}
new.groups_wrap= stuff->groupsWrap;
}
CHK_MASK_LEGAL(0x0F, stuff->axOptions, XkbAX_AllOptionsMask);
if (stuff->changeCtrls & XkbAccessXKeysMask) {
new.ax_options = stuff->axOptions & XkbAX_AllOptionsMask;
}
else {
if (stuff->changeCtrls & XkbStickyKeysMask) {
new.ax_options &= ~(XkbAX_SKOptionsMask);
new.ax_options |= (stuff->axOptions & XkbAX_SKOptionsMask);
}
if (stuff->changeCtrls & XkbAccessXFeedbackMask) {
new.ax_options &= ~(XkbAX_FBOptionsMask);
new.ax_options |= (stuff->axOptions & XkbAX_FBOptionsMask);
}
}
if (stuff->changeCtrls & XkbAccessXTimeoutMask) {
if (stuff->axTimeout < 1) {
client->errorValue = _XkbErrCode2(0x10, stuff->axTimeout);
return BadValue;
}
CHK_MASK_MATCH(0x11, stuff->axtCtrlsMask,
stuff->axtCtrlsValues);
CHK_MASK_LEGAL(0x12, stuff->axtCtrlsMask,
XkbAllBooleanCtrlsMask);
CHK_MASK_MATCH(0x13, stuff->axtOptsMask, stuff->axtOptsValues);
CHK_MASK_LEGAL(0x14, stuff->axtOptsMask, XkbAX_AllOptionsMask);
new.ax_timeout = stuff->axTimeout;
new.axt_ctrls_mask = stuff->axtCtrlsMask;
new.axt_ctrls_values = (stuff->axtCtrlsValues &
stuff->axtCtrlsMask);
new.axt_opts_mask = stuff->axtOptsMask;
new.axt_opts_values = (stuff->axtOptsValues &
stuff->axtOptsMask);
}
if (stuff->changeCtrls & XkbPerKeyRepeatMask)
memcpy(new.per_key_repeat, stuff->perKeyRepeat,
XkbPerKeyBitArraySize);
old= *ctrl;
*ctrl= new;
XkbDDXChangeControls(tmpd, &old, ctrl);
if (XkbComputeControlsNotify(tmpd, &old, ctrl, &cn, False)) {
cn.keycode = 0;
cn.eventType = 0;
cn.requestMajor = XkbReqCode;
cn.requestMinor = X_kbSetControls;
XkbSendControlsNotify(tmpd, &cn);
}
sli = XkbFindSrvLedInfo(tmpd, XkbDfltXIClass, XkbDfltXIId, 0);
if (sli)
XkbUpdateIndicators(tmpd, sli->usesControls, True, NULL,
&cause);
if ((old.enabled_ctrls & XkbStickyKeysMask) &&
!(ctrl->enabled_ctrls & XkbStickyKeysMask))
XkbClearAllLatchesAndLocks(tmpd, xkbi, True, &cause);
}
}
return client->noClientException;
}
static int
XkbSizeKeyTypes(XkbDescPtr xkb,xkbGetMapReply *rep)
{
XkbKeyTypeRec *type;
unsigned i,len;
len= 0;
if (((rep->present&XkbKeyTypesMask)==0)||(rep->nTypes<1)||
(!xkb)||(!xkb->map)||(!xkb->map->types)) {
rep->present&= ~XkbKeyTypesMask;
rep->firstType= rep->nTypes= 0;
return 0;
}
type= &xkb->map->types[rep->firstType];
for (i=0;i<rep->nTypes;i++,type++){
len+= SIZEOF(xkbKeyTypeWireDesc);
if (type->map_count>0) {
len+= (type->map_count*SIZEOF(xkbKTMapEntryWireDesc));
if (type->preserve)
len+= (type->map_count*SIZEOF(xkbModsWireDesc));
}
}
return len;
}
static char *
XkbWriteKeyTypes( XkbDescPtr xkb,
xkbGetMapReply * rep,
char * buf,
ClientPtr client)
{
XkbKeyTypePtr type;
unsigned i;
xkbKeyTypeWireDesc *wire;
type= &xkb->map->types[rep->firstType];
for (i=0;i<rep->nTypes;i++,type++) {
register unsigned n;
wire= (xkbKeyTypeWireDesc *)buf;
wire->mask = type->mods.mask;
wire->realMods = type->mods.real_mods;
wire->virtualMods = type->mods.vmods;
wire->numLevels = type->num_levels;
wire->nMapEntries = type->map_count;
wire->preserve = (type->preserve!=NULL);
if (client->swapped) {
register int n;
swaps(&wire->virtualMods,n);
}
buf= (char *)&wire[1];
if (wire->nMapEntries>0) {
xkbKTMapEntryWireDesc * wire;
XkbKTMapEntryPtr entry;
wire= (xkbKTMapEntryWireDesc *)buf;
entry= type->map;
for (n=0;n<type->map_count;n++,wire++,entry++) {
wire->active= entry->active;
wire->mask= entry->mods.mask;
wire->level= entry->level;
wire->realMods= entry->mods.real_mods;
wire->virtualMods= entry->mods.vmods;
if (client->swapped) {
register int n;
swaps(&wire->virtualMods,n);
}
}
buf= (char *)wire;
if (type->preserve!=NULL) {
xkbModsWireDesc * pwire;
XkbModsPtr preserve;
pwire= (xkbModsWireDesc *)buf;
preserve= type->preserve;
for (n=0;n<type->map_count;n++,pwire++,preserve++) {
pwire->mask= preserve->mask;
pwire->realMods= preserve->real_mods;
pwire->virtualMods= preserve->vmods;
if (client->swapped) {
register int n;
swaps(&pwire->virtualMods,n);
}
}
buf= (char *)pwire;
}
}
}
return buf;
}
static int
XkbSizeKeySyms(XkbDescPtr xkb,xkbGetMapReply *rep)
{
XkbSymMapPtr symMap;
unsigned i,len;
unsigned nSyms,nSymsThisKey;
if (((rep->present&XkbKeySymsMask)==0)||(rep->nKeySyms<1)||
(!xkb)||(!xkb->map)||(!xkb->map->key_sym_map)) {
rep->present&= ~XkbKeySymsMask;
rep->firstKeySym= rep->nKeySyms= 0;
rep->totalSyms= 0;
return 0;
}
len= rep->nKeySyms*SIZEOF(xkbSymMapWireDesc);
symMap = &xkb->map->key_sym_map[rep->firstKeySym];
for (i=nSyms=0;i<rep->nKeySyms;i++,symMap++) {
if (symMap->offset!=0) {
nSymsThisKey= XkbNumGroups(symMap->group_info)*symMap->width;
nSyms+= nSymsThisKey;
}
}
len+= nSyms*4;
rep->totalSyms= nSyms;
return len;
}
static int
XkbSizeVirtualMods(XkbDescPtr xkb,xkbGetMapReply *rep)
{
register unsigned i,nMods,bit;
if (((rep->present&XkbVirtualModsMask)==0)||(rep->virtualMods==0)||
(!xkb)||(!xkb->server)) {
rep->present&= ~XkbVirtualModsMask;
rep->virtualMods= 0;
return 0;
}
for (i=nMods=0,bit=1;i<XkbNumVirtualMods;i++,bit<<=1) {
if (rep->virtualMods&bit)
nMods++;
}
return XkbPaddedSize(nMods);
}
static char *
XkbWriteKeySyms(XkbDescPtr xkb,xkbGetMapReply *rep,char *buf,ClientPtr client)
{
register KeySym * pSym;
XkbSymMapPtr symMap;
xkbSymMapWireDesc * outMap;
register unsigned i;
symMap = &xkb->map->key_sym_map[rep->firstKeySym];
for (i=0;i<rep->nKeySyms;i++,symMap++) {
outMap = (xkbSymMapWireDesc *)buf;
outMap->ktIndex[0] = symMap->kt_index[0];
outMap->ktIndex[1] = symMap->kt_index[1];
outMap->ktIndex[2] = symMap->kt_index[2];
outMap->ktIndex[3] = symMap->kt_index[3];
outMap->groupInfo = symMap->group_info;
outMap->width= symMap->width;
outMap->nSyms = symMap->width*XkbNumGroups(symMap->group_info);
buf= (char *)&outMap[1];
if (outMap->nSyms==0)
continue;
pSym = &xkb->map->syms[symMap->offset];
memcpy((char *)buf,(char *)pSym,outMap->nSyms*4);
if (client->swapped) {
register int n,nSyms= outMap->nSyms;
swaps(&outMap->nSyms,n);
while (nSyms-->0) {
swapl(buf,n);
buf+= 4;
}
}
else buf+= outMap->nSyms*4;
}
return buf;
}
static int
XkbSizeKeyActions(XkbDescPtr xkb,xkbGetMapReply *rep)
{
unsigned i,len,nActs;
register KeyCode firstKey;
if (((rep->present&XkbKeyActionsMask)==0)||(rep->nKeyActs<1)||
(!xkb)||(!xkb->server)||(!xkb->server->key_acts)) {
rep->present&= ~XkbKeyActionsMask;
rep->firstKeyAct= rep->nKeyActs= 0;
rep->totalActs= 0;
return 0;
}
firstKey= rep->firstKeyAct;
for (nActs=i=0;i<rep->nKeyActs;i++) {
if (xkb->server->key_acts[i+firstKey]!=0)
nActs+= XkbKeyNumActions(xkb,i+firstKey);
}
len= XkbPaddedSize(rep->nKeyActs)+(nActs*SIZEOF(xkbActionWireDesc));
rep->totalActs= nActs;
return len;
}
static char *
XkbWriteKeyActions(XkbDescPtr xkb,xkbGetMapReply *rep,char *buf,
ClientPtr client)
{
unsigned i;
CARD8 * numDesc;
XkbAnyAction * actDesc;
numDesc = (CARD8 *)buf;
for (i=0;i<rep->nKeyActs;i++) {
if (xkb->server->key_acts[i+rep->firstKeyAct]==0)
numDesc[i] = 0;
else numDesc[i] = XkbKeyNumActions(xkb,(i+rep->firstKeyAct));
}
buf+= XkbPaddedSize(rep->nKeyActs);
actDesc = (XkbAnyAction *)buf;
for (i=0;i<rep->nKeyActs;i++) {
if (xkb->server->key_acts[i+rep->firstKeyAct]!=0) {
unsigned int num;
num = XkbKeyNumActions(xkb,(i+rep->firstKeyAct));
memcpy((char *)actDesc,
(char*)XkbKeyActionsPtr(xkb,(i+rep->firstKeyAct)),
num*SIZEOF(xkbActionWireDesc));
actDesc+= num;
}
}
buf = (char *)actDesc;
return buf;
}
static int
XkbSizeKeyBehaviors(XkbDescPtr xkb,xkbGetMapReply *rep)
{
unsigned i,len,nBhvr;
XkbBehavior * bhv;
if (((rep->present&XkbKeyBehaviorsMask)==0)||(rep->nKeyBehaviors<1)||
(!xkb)||(!xkb->server)||(!xkb->server->behaviors)) {
rep->present&= ~XkbKeyBehaviorsMask;
rep->firstKeyBehavior= rep->nKeyBehaviors= 0;
rep->totalKeyBehaviors= 0;
return 0;
}
bhv= &xkb->server->behaviors[rep->firstKeyBehavior];
for (nBhvr=i=0;i<rep->nKeyBehaviors;i++,bhv++) {
if (bhv->type!=XkbKB_Default)
nBhvr++;
}
len= nBhvr*SIZEOF(xkbBehaviorWireDesc);
rep->totalKeyBehaviors= nBhvr;
return len;
}
static char *
XkbWriteKeyBehaviors(XkbDescPtr xkb,xkbGetMapReply *rep,char *buf,
ClientPtr client)
{
unsigned i;
xkbBehaviorWireDesc *wire;
XkbBehavior *pBhvr;
wire = (xkbBehaviorWireDesc *)buf;
pBhvr= &xkb->server->behaviors[rep->firstKeyBehavior];
for (i=0;i<rep->nKeyBehaviors;i++,pBhvr++) {
if (pBhvr->type!=XkbKB_Default) {
wire->key= i+rep->firstKeyBehavior;
wire->type= pBhvr->type;
wire->data= pBhvr->data;
wire++;
}
}
buf = (char *)wire;
return buf;
}
static int
XkbSizeExplicit(XkbDescPtr xkb,xkbGetMapReply *rep)
{
unsigned i,len,nRtrn;
if (((rep->present&XkbExplicitComponentsMask)==0)||(rep->nKeyExplicit<1)||
(!xkb)||(!xkb->server)||(!xkb->server->explicit)) {
rep->present&= ~XkbExplicitComponentsMask;
rep->firstKeyExplicit= rep->nKeyExplicit= 0;
rep->totalKeyExplicit= 0;
return 0;
}
for (nRtrn=i=0;i<rep->nKeyExplicit;i++) {
if (xkb->server->explicit[i+rep->firstKeyExplicit]!=0)
nRtrn++;
}
rep->totalKeyExplicit= nRtrn;
len= XkbPaddedSize(nRtrn*2);
return len;
}
static char *
XkbWriteExplicit(XkbDescPtr xkb,xkbGetMapReply *rep,char *buf,ClientPtr client)
{
unsigned i;
char * start;
unsigned char * pExp;
start= buf;
pExp= &xkb->server->explicit[rep->firstKeyExplicit];
for (i=0;i<rep->nKeyExplicit;i++,pExp++) {
if (*pExp!=0) {
*buf++= i+rep->firstKeyExplicit;
*buf++= *pExp;
}
}
i= XkbPaddedSize(buf-start)-(buf-start);
return buf+i;
}
static int
XkbSizeModifierMap(XkbDescPtr xkb,xkbGetMapReply *rep)
{
unsigned i,len,nRtrn;
if (((rep->present&XkbModifierMapMask)==0)||(rep->nModMapKeys<1)||
(!xkb)||(!xkb->map)||(!xkb->map->modmap)) {
rep->present&= ~XkbModifierMapMask;
rep->firstModMapKey= rep->nModMapKeys= 0;
rep->totalModMapKeys= 0;
return 0;
}
for (nRtrn=i=0;i<rep->nModMapKeys;i++) {
if (xkb->map->modmap[i+rep->firstModMapKey]!=0)
nRtrn++;
}
rep->totalModMapKeys= nRtrn;
len= XkbPaddedSize(nRtrn*2);
return len;
}
static char *
XkbWriteModifierMap(XkbDescPtr xkb,xkbGetMapReply *rep,char *buf,
ClientPtr client)
{
unsigned i;
char * start;
unsigned char * pMap;
start= buf;
pMap= &xkb->map->modmap[rep->firstModMapKey];
for (i=0;i<rep->nModMapKeys;i++,pMap++) {
if (*pMap!=0) {
*buf++= i+rep->firstModMapKey;
*buf++= *pMap;
}
}
i= XkbPaddedSize(buf-start)-(buf-start);
return buf+i;
}
static int
XkbSizeVirtualModMap(XkbDescPtr xkb,xkbGetMapReply *rep)
{
unsigned i,len,nRtrn;
if (((rep->present&XkbVirtualModMapMask)==0)||(rep->nVModMapKeys<1)||
(!xkb)||(!xkb->server)||(!xkb->server->vmodmap)) {
rep->present&= ~XkbVirtualModMapMask;
rep->firstVModMapKey= rep->nVModMapKeys= 0;
rep->totalVModMapKeys= 0;
return 0;
}
for (nRtrn=i=0;i<rep->nVModMapKeys;i++) {
if (xkb->server->vmodmap[i+rep->firstVModMapKey]!=0)
nRtrn++;
}
rep->totalVModMapKeys= nRtrn;
len= nRtrn*SIZEOF(xkbVModMapWireDesc);
return len;
}
static char *
XkbWriteVirtualModMap(XkbDescPtr xkb,xkbGetMapReply *rep,char *buf,
ClientPtr client)
{
unsigned i;
xkbVModMapWireDesc * wire;
unsigned short * pMap;
wire= (xkbVModMapWireDesc *)buf;
pMap= &xkb->server->vmodmap[rep->firstVModMapKey];
for (i=0;i<rep->nVModMapKeys;i++,pMap++) {
if (*pMap!=0) {
wire->key= i+rep->firstVModMapKey;
wire->vmods= *pMap;
wire++;
}
}
return (char *)wire;
}
static Status
XkbComputeGetMapReplySize(XkbDescPtr xkb,xkbGetMapReply *rep)
{
int len;
rep->minKeyCode= xkb->min_key_code;
rep->maxKeyCode= xkb->max_key_code;
len= XkbSizeKeyTypes(xkb,rep);
len+= XkbSizeKeySyms(xkb,rep);
len+= XkbSizeKeyActions(xkb,rep);
len+= XkbSizeKeyBehaviors(xkb,rep);
len+= XkbSizeVirtualMods(xkb,rep);
len+= XkbSizeExplicit(xkb,rep);
len+= XkbSizeModifierMap(xkb,rep);
len+= XkbSizeVirtualModMap(xkb,rep);
rep->length+= (len/4);
return Success;
}
static int
XkbSendMap(ClientPtr client,XkbDescPtr xkb,xkbGetMapReply *rep)
{
unsigned i,len;
char *desc,*start;
len= (rep->length*4)-(SIZEOF(xkbGetMapReply)-SIZEOF(xGenericReply));
start= desc= (char *)xalloc(len);
if (!start)
return BadAlloc;
if ( rep->nTypes>0 )
desc = XkbWriteKeyTypes(xkb,rep,desc,client);
if ( rep->nKeySyms>0 )
desc = XkbWriteKeySyms(xkb,rep,desc,client);
if ( rep->nKeyActs>0 )
desc = XkbWriteKeyActions(xkb,rep,desc,client);
if ( rep->totalKeyBehaviors>0 )
desc = XkbWriteKeyBehaviors(xkb,rep,desc,client);
if ( rep->virtualMods ) {
register int sz,bit;
for (i=sz=0,bit=1;i<XkbNumVirtualMods;i++,bit<<=1) {
if (rep->virtualMods&bit) {
desc[sz++]= xkb->server->vmods[i];
}
}
desc+= XkbPaddedSize(sz);
}
if ( rep->totalKeyExplicit>0 )
desc= XkbWriteExplicit(xkb,rep,desc,client);
if ( rep->totalModMapKeys>0 )
desc= XkbWriteModifierMap(xkb,rep,desc,client);
if ( rep->totalVModMapKeys>0 )
desc= XkbWriteVirtualModMap(xkb,rep,desc,client);
if ((desc-start)!=(len)) {
ErrorF("[xkb] BOGUS LENGTH in write keyboard desc, expected %d, got %ld\n",
len, (unsigned long)(desc-start));
}
if (client->swapped) {
register int n;
swaps(&rep->sequenceNumber,n);
swapl(&rep->length,n);
swaps(&rep->present,n);
swaps(&rep->totalSyms,n);
swaps(&rep->totalActs,n);
}
WriteToClient(client, (i=SIZEOF(xkbGetMapReply)), (char *)rep);
WriteToClient(client, len, start);
xfree((char *)start);
return client->noClientException;
}
int
ProcXkbGetMap(ClientPtr client)
{
DeviceIntPtr dev;
xkbGetMapReply rep;
XkbDescRec *xkb;
int n,status;
REQUEST(xkbGetMapReq);
REQUEST_SIZE_MATCH(xkbGetMapReq);
if (!(client->xkbClientFlags&_XkbClientInitialized))
return BadAccess;
CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess);
CHK_MASK_OVERLAP(0x01,stuff->full,stuff->partial);
CHK_MASK_LEGAL(0x02,stuff->full,XkbAllMapComponentsMask);
CHK_MASK_LEGAL(0x03,stuff->partial,XkbAllMapComponentsMask);
xkb= dev->key->xkbInfo->desc;
bzero(&rep,sizeof(xkbGetMapReply));
rep.type= X_Reply;
rep.sequenceNumber= client->sequence;
rep.length = (SIZEOF(xkbGetMapReply)-SIZEOF(xGenericReply))>>2;
rep.deviceID = dev->id;
rep.present = stuff->partial|stuff->full;
rep.minKeyCode = xkb->min_key_code;
rep.maxKeyCode = xkb->max_key_code;
if ( stuff->full&XkbKeyTypesMask ) {
rep.firstType = 0;
rep.nTypes = xkb->map->num_types;
}
else if (stuff->partial&XkbKeyTypesMask) {
if (((unsigned)stuff->firstType+stuff->nTypes)>xkb->map->num_types) {
client->errorValue = _XkbErrCode4(0x04,xkb->map->num_types,
stuff->firstType,stuff->nTypes);
return BadValue;
}
rep.firstType = stuff->firstType;
rep.nTypes = stuff->nTypes;
}
else rep.nTypes = 0;
rep.totalTypes = xkb->map->num_types;
n= XkbNumKeys(xkb);
if ( stuff->full&XkbKeySymsMask ) {
rep.firstKeySym = xkb->min_key_code;
rep.nKeySyms = n;
}
else if (stuff->partial&XkbKeySymsMask) {
CHK_KEY_RANGE(0x05,stuff->firstKeySym,stuff->nKeySyms,xkb);
rep.firstKeySym = stuff->firstKeySym;
rep.nKeySyms = stuff->nKeySyms;
}
else rep.nKeySyms = 0;
rep.totalSyms= 0;
if ( stuff->full&XkbKeyActionsMask ) {
rep.firstKeyAct= xkb->min_key_code;
rep.nKeyActs= n;
}
else if (stuff->partial&XkbKeyActionsMask) {
CHK_KEY_RANGE(0x07,stuff->firstKeyAct,stuff->nKeyActs,xkb);
rep.firstKeyAct= stuff->firstKeyAct;
rep.nKeyActs= stuff->nKeyActs;
}
else rep.nKeyActs= 0;
rep.totalActs= 0;
if ( stuff->full&XkbKeyBehaviorsMask ) {
rep.firstKeyBehavior = xkb->min_key_code;
rep.nKeyBehaviors = n;
}
else if (stuff->partial&XkbKeyBehaviorsMask) {
CHK_KEY_RANGE(0x09,stuff->firstKeyBehavior,stuff->nKeyBehaviors,xkb);
rep.firstKeyBehavior= stuff->firstKeyBehavior;
rep.nKeyBehaviors= stuff->nKeyBehaviors;
}
else rep.nKeyBehaviors = 0;
rep.totalKeyBehaviors= 0;
if (stuff->full&XkbVirtualModsMask)
rep.virtualMods= ~0;
else if (stuff->partial&XkbVirtualModsMask)
rep.virtualMods= stuff->virtualMods;
if (stuff->full&XkbExplicitComponentsMask) {
rep.firstKeyExplicit= xkb->min_key_code;
rep.nKeyExplicit= n;
}
else if (stuff->partial&XkbExplicitComponentsMask) {
CHK_KEY_RANGE(0x0B,stuff->firstKeyExplicit,stuff->nKeyExplicit,xkb);
rep.firstKeyExplicit= stuff->firstKeyExplicit;
rep.nKeyExplicit= stuff->nKeyExplicit;
}
else rep.nKeyExplicit = 0;
rep.totalKeyExplicit= 0;
if (stuff->full&XkbModifierMapMask) {
rep.firstModMapKey= xkb->min_key_code;
rep.nModMapKeys= n;
}
else if (stuff->partial&XkbModifierMapMask) {
CHK_KEY_RANGE(0x0D,stuff->firstModMapKey,stuff->nModMapKeys,xkb);
rep.firstModMapKey= stuff->firstModMapKey;
rep.nModMapKeys= stuff->nModMapKeys;
}
else rep.nModMapKeys = 0;
rep.totalModMapKeys= 0;
if (stuff->full&XkbVirtualModMapMask) {
rep.firstVModMapKey= xkb->min_key_code;
rep.nVModMapKeys= n;
}
else if (stuff->partial&XkbVirtualModMapMask) {
CHK_KEY_RANGE(0x0F,stuff->firstVModMapKey,stuff->nVModMapKeys,xkb);
rep.firstVModMapKey= stuff->firstVModMapKey;
rep.nVModMapKeys= stuff->nVModMapKeys;
}
else rep.nVModMapKeys = 0;
rep.totalVModMapKeys= 0;
if ((status=XkbComputeGetMapReplySize(xkb,&rep))!=Success)
return status;
return XkbSendMap(client,xkb,&rep);
}
static int
CheckKeyTypes( ClientPtr client,
XkbDescPtr xkb,
xkbSetMapReq * req,
xkbKeyTypeWireDesc **wireRtrn,
int * nMapsRtrn,
CARD8 * mapWidthRtrn)
{
unsigned nMaps;
register unsigned i,n;
register CARD8 * map;
register xkbKeyTypeWireDesc *wire = *wireRtrn;
if (req->firstType>((unsigned)xkb->map->num_types)) {
*nMapsRtrn = _XkbErrCode3(0x01,req->firstType,xkb->map->num_types);
return 0;
}
if (req->flags&XkbSetMapResizeTypes) {
nMaps = req->firstType+req->nTypes;
if (nMaps<XkbNumRequiredTypes) {
*nMapsRtrn= _XkbErrCode4(0x02,req->firstType,req->nTypes,4);
return 0;
}
}
else if (req->present&XkbKeyTypesMask) {
nMaps = xkb->map->num_types;
if ((req->firstType+req->nTypes)>nMaps) {
*nMapsRtrn = req->firstType+req->nTypes;
return 0;
}
}
else {
*nMapsRtrn = xkb->map->num_types;
for (i=0;i<xkb->map->num_types;i++) {
mapWidthRtrn[i] = xkb->map->types[i].num_levels;
}
return 1;
}
for (i=0;i<req->firstType;i++) {
mapWidthRtrn[i] = xkb->map->types[i].num_levels;
}
for (i=0;i<req->nTypes;i++) {
unsigned width;
if (client->swapped) {
register int s;
swaps(&wire->virtualMods,s);
}
n= i+req->firstType;
width= wire->numLevels;
if (width<1) {
*nMapsRtrn= _XkbErrCode3(0x04,n,width);
return 0;
}
else if ((n==XkbOneLevelIndex)&&(width!=1)) {
*nMapsRtrn= _XkbErrCode3(0x05,n,width);
return 0;
}
else if ((width!=2)&&
((n==XkbTwoLevelIndex)||(n==XkbKeypadIndex)||
(n==XkbAlphabeticIndex))) {
*nMapsRtrn= _XkbErrCode3(0x05,n,width);
return 0;
}
if (wire->nMapEntries>0) {
xkbKTSetMapEntryWireDesc * mapWire;
xkbModsWireDesc * preWire;
mapWire= (xkbKTSetMapEntryWireDesc *)&wire[1];
preWire= (xkbModsWireDesc *)&mapWire[wire->nMapEntries];
for (n=0;n<wire->nMapEntries;n++) {
if (client->swapped) {
register int s;
swaps(&mapWire[n].virtualMods,s);
}
if (mapWire[n].realMods&(~wire->realMods)) {
*nMapsRtrn= _XkbErrCode4(0x06,n,mapWire[n].realMods,
wire->realMods);
return 0;
}
if (mapWire[n].virtualMods&(~wire->virtualMods)) {
*nMapsRtrn= _XkbErrCode3(0x07,n,mapWire[n].virtualMods);
return 0;
}
if (mapWire[n].level>=wire->numLevels) {
*nMapsRtrn= _XkbErrCode4(0x08,n,wire->numLevels,
mapWire[n].level);
return 0;
}
if (wire->preserve) {
if (client->swapped) {
register int s;
swaps(&preWire[n].virtualMods,s);
}
if (preWire[n].realMods&(~mapWire[n].realMods)) {
*nMapsRtrn= _XkbErrCode4(0x09,n,preWire[n].realMods,
mapWire[n].realMods);
return 0;
}
if (preWire[n].virtualMods&(~mapWire[n].virtualMods)) {
*nMapsRtrn=_XkbErrCode3(0x0a,n,preWire[n].virtualMods);
return 0;
}
}
}
if (wire->preserve)
map= (CARD8 *)&preWire[wire->nMapEntries];
else map= (CARD8 *)&mapWire[wire->nMapEntries];
}
else map= (CARD8 *)&wire[1];
mapWidthRtrn[i+req->firstType] = wire->numLevels;
wire= (xkbKeyTypeWireDesc *)map;
}
for (i=req->firstType+req->nTypes;i<nMaps;i++) {
mapWidthRtrn[i] = xkb->map->types[i].num_levels;
}
*nMapsRtrn = nMaps;
*wireRtrn = wire;
return 1;
}
static int
CheckKeySyms( ClientPtr client,
XkbDescPtr xkb,
xkbSetMapReq * req,
int nTypes,
CARD8 * mapWidths,
CARD16 * symsPerKey,
xkbSymMapWireDesc ** wireRtrn,
int * errorRtrn)
{
register unsigned i;
XkbSymMapPtr map;
xkbSymMapWireDesc* wire = *wireRtrn;
if (!(XkbKeySymsMask&req->present))
return 1;
CHK_REQ_KEY_RANGE2(0x11,req->firstKeySym,req->nKeySyms,req,(*errorRtrn),0);
map = &xkb->map->key_sym_map[xkb->min_key_code];
for (i=xkb->min_key_code;i<(unsigned)req->firstKeySym;i++,map++) {
register int g,ng,w;
ng= XkbNumGroups(map->group_info);
for (w=g=0;g<ng;g++) {
if (map->kt_index[g]>=(unsigned)nTypes) {
*errorRtrn = _XkbErrCode4(0x13,i,g,map->kt_index[g]);
return 0;
}
if (mapWidths[map->kt_index[g]]>w)
w= mapWidths[map->kt_index[g]];
}
symsPerKey[i] = w*ng;
}
for (i=0;i<req->nKeySyms;i++) {
KeySym *pSyms;
register unsigned nG;
if (client->swapped) {
swaps(&wire->nSyms,nG);
}
nG = XkbNumGroups(wire->groupInfo);
if (nG>XkbNumKbdGroups) {
*errorRtrn = _XkbErrCode3(0x14,i+req->firstKeySym,nG);
return 0;
}
if (nG>0) {
register int g,w;
for (g=w=0;g<nG;g++) {
if (wire->ktIndex[g]>=(unsigned)nTypes) {
*errorRtrn= _XkbErrCode4(0x15,i+req->firstKeySym,g,
wire->ktIndex[g]);
return 0;
}
if (mapWidths[wire->ktIndex[g]]>w)
w= mapWidths[wire->ktIndex[g]];
}
if (wire->width!=w) {
*errorRtrn= _XkbErrCode3(0x16,i+req->firstKeySym,wire->width);
return 0;
}
w*= nG;
symsPerKey[i+req->firstKeySym] = w;
if (w!=wire->nSyms) {
*errorRtrn=_XkbErrCode4(0x16,i+req->firstKeySym,wire->nSyms,w);
return 0;
}
}
else if (wire->nSyms!=0) {
*errorRtrn = _XkbErrCode3(0x17,i+req->firstKeySym,wire->nSyms);
return 0;
}
pSyms = (KeySym *)&wire[1];
wire = (xkbSymMapWireDesc *)&pSyms[wire->nSyms];
}
map = &xkb->map->key_sym_map[i];
for (;i<=(unsigned)xkb->max_key_code;i++,map++) {
register int g,nG,w;
nG= XkbKeyNumGroups(xkb,i);
for (w=g=0;g<nG;g++) {
if (map->kt_index[g]>=(unsigned)nTypes) {
*errorRtrn = _XkbErrCode4(0x18,i,g,map->kt_index[g]);
return 0;
}
if (mapWidths[map->kt_index[g]]>w)
w= mapWidths[map->kt_index[g]];
}
symsPerKey[i] = w*nG;
}
*wireRtrn = wire;
return 1;
}
static int
CheckKeyActions( XkbDescPtr xkb,
xkbSetMapReq * req,
int nTypes,
CARD8 * mapWidths,
CARD16 * symsPerKey,
CARD8 ** wireRtrn,
int * nActsRtrn)
{
int nActs;
CARD8 * wire = *wireRtrn;
register unsigned i;
if (!(XkbKeyActionsMask&req->present))
return 1;
CHK_REQ_KEY_RANGE2(0x21,req->firstKeyAct,req->nKeyActs,req,(*nActsRtrn),0);
for (nActs=i=0;i<req->nKeyActs;i++) {
if (wire[0]!=0) {
if (wire[0]==symsPerKey[i+req->firstKeyAct])
nActs+= wire[0];
else {
*nActsRtrn= _XkbErrCode3(0x23,i+req->firstKeyAct,wire[0]);
return 0;
}
}
wire++;
}
if (req->nKeyActs%4)
wire+= 4-(req->nKeyActs%4);
*wireRtrn = (CARD8 *)(((XkbAnyAction *)wire)+nActs);
*nActsRtrn = nActs;
return 1;
}
static int
CheckKeyBehaviors( XkbDescPtr xkb,
xkbSetMapReq * req,
xkbBehaviorWireDesc ** wireRtrn,
int * errorRtrn)
{
register xkbBehaviorWireDesc * wire = *wireRtrn;
register XkbServerMapPtr server = xkb->server;
register unsigned i;
unsigned first,last;
if (((req->present&XkbKeyBehaviorsMask)==0)||(req->nKeyBehaviors<1)) {
req->present&= ~XkbKeyBehaviorsMask;
req->nKeyBehaviors= 0;
return 1;
}
first= req->firstKeyBehavior;
last= req->firstKeyBehavior+req->nKeyBehaviors-1;
if (first<req->minKeyCode) {
*errorRtrn = _XkbErrCode3(0x31,first,req->minKeyCode);
return 0;
}
if (last>req->maxKeyCode) {
*errorRtrn = _XkbErrCode3(0x32,last,req->maxKeyCode);
return 0;
}
for (i=0;i<req->totalKeyBehaviors;i++,wire++) {
if ((wire->key<first)||(wire->key>last)) {
*errorRtrn = _XkbErrCode4(0x33,first,last,wire->key);
return 0;
}
if ((wire->type&XkbKB_Permanent)&&
((server->behaviors[wire->key].type!=wire->type)||
(server->behaviors[wire->key].data!=wire->data))) {
*errorRtrn = _XkbErrCode3(0x33,wire->key,wire->type);
return 0;
}
if ((wire->type==XkbKB_RadioGroup)&&
((wire->data&(~XkbKB_RGAllowNone))>XkbMaxRadioGroups)) {
*errorRtrn= _XkbErrCode4(0x34,wire->key,wire->data,
XkbMaxRadioGroups);
return 0;
}
if ((wire->type==XkbKB_Overlay1)||(wire->type==XkbKB_Overlay2)) {
CHK_KEY_RANGE2(0x35,wire->key,1,xkb,*errorRtrn,0);
}
}
*wireRtrn = wire;
return 1;
}
static int
CheckVirtualMods( XkbDescRec * xkb,
xkbSetMapReq * req,
CARD8 ** wireRtrn,
int * errorRtrn)
{
register CARD8 *wire = *wireRtrn;
register unsigned i,nMods,bit;
if (((req->present&XkbVirtualModsMask)==0)||(req->virtualMods==0))
return 1;
for (i=nMods=0,bit=1;i<XkbNumVirtualMods;i++,bit<<=1) {
if (req->virtualMods&bit)
nMods++;
}
*wireRtrn= (wire+XkbPaddedSize(nMods));
return 1;
}
static int
CheckKeyExplicit( XkbDescPtr xkb,
xkbSetMapReq * req,
CARD8 ** wireRtrn,
int * errorRtrn)
{
register CARD8 * wire = *wireRtrn;
CARD8 * start;
register unsigned i;
int first,last;
if (((req->present&XkbExplicitComponentsMask)==0)||(req->nKeyExplicit<1)) {
req->present&= ~XkbExplicitComponentsMask;
req->nKeyExplicit= 0;
return 1;
}
first= req->firstKeyExplicit;
last= first+req->nKeyExplicit-1;
if (first<req->minKeyCode) {
*errorRtrn = _XkbErrCode3(0x51,first,req->minKeyCode);
return 0;
}
if (last>req->maxKeyCode) {
*errorRtrn = _XkbErrCode3(0x52,last,req->maxKeyCode);
return 0;
}
start= wire;
for (i=0;i<req->totalKeyExplicit;i++,wire+=2) {
if ((wire[0]<first)||(wire[0]>last)) {
*errorRtrn = _XkbErrCode4(0x53,first,last,wire[0]);
return 0;
}
if (wire[1]&(~XkbAllExplicitMask)) {
*errorRtrn= _XkbErrCode3(0x52,~XkbAllExplicitMask,wire[1]);
return 0;
}
}
wire+= XkbPaddedSize(wire-start)-(wire-start);
*wireRtrn= wire;
return 1;
}
static int
CheckModifierMap(XkbDescPtr xkb,xkbSetMapReq *req,CARD8 **wireRtrn,int *errRtrn)
{
register CARD8 * wire = *wireRtrn;
CARD8 * start;
register unsigned i;
int first,last;
if (((req->present&XkbModifierMapMask)==0)||(req->nModMapKeys<1)) {
req->present&= ~XkbModifierMapMask;
req->nModMapKeys= 0;
return 1;
}
first= req->firstModMapKey;
last= first+req->nModMapKeys-1;
if (first<req->minKeyCode) {
*errRtrn = _XkbErrCode3(0x61,first,req->minKeyCode);
return 0;
}
if (last>req->maxKeyCode) {
*errRtrn = _XkbErrCode3(0x62,last,req->maxKeyCode);
return 0;
}
start= wire;
for (i=0;i<req->totalModMapKeys;i++,wire+=2) {
if ((wire[0]<first)||(wire[0]>last)) {
*errRtrn = _XkbErrCode4(0x63,first,last,wire[0]);
return 0;
}
}
wire+= XkbPaddedSize(wire-start)-(wire-start);
*wireRtrn= wire;
return 1;
}
static int
CheckVirtualModMap( XkbDescPtr xkb,
xkbSetMapReq *req,
xkbVModMapWireDesc **wireRtrn,
int *errRtrn)
{
register xkbVModMapWireDesc * wire = *wireRtrn;
register unsigned i;
int first,last;
if (((req->present&XkbVirtualModMapMask)==0)||(req->nVModMapKeys<1)) {
req->present&= ~XkbVirtualModMapMask;
req->nVModMapKeys= 0;
return 1;
}
first= req->firstVModMapKey;
last= first+req->nVModMapKeys-1;
if (first<req->minKeyCode) {
*errRtrn = _XkbErrCode3(0x71,first,req->minKeyCode);
return 0;
}
if (last>req->maxKeyCode) {
*errRtrn = _XkbErrCode3(0x72,last,req->maxKeyCode);
return 0;
}
for (i=0;i<req->totalVModMapKeys;i++,wire++) {
if ((wire->key<first)||(wire->key>last)) {
*errRtrn = _XkbErrCode4(0x73,first,last,wire->key);
return 0;
}
}
*wireRtrn= wire;
return 1;
}
static char *
SetKeyTypes( XkbDescPtr xkb,
xkbSetMapReq * req,
xkbKeyTypeWireDesc * wire,
XkbChangesPtr changes)
{
register unsigned i;
unsigned first,last;
CARD8 *map;
if ((unsigned)(req->firstType+req->nTypes)>xkb->map->size_types) {
i= req->firstType+req->nTypes;
if (XkbAllocClientMap(xkb,XkbKeyTypesMask,i)!=Success) {
return NULL;
}
}
if ((unsigned)(req->firstType+req->nTypes)>xkb->map->num_types)
xkb->map->num_types= req->firstType+req->nTypes;
for (i=0;i<req->nTypes;i++) {
XkbKeyTypePtr pOld;
register unsigned n;
if (XkbResizeKeyType(xkb,i+req->firstType,wire->nMapEntries,
wire->preserve,wire->numLevels)!=Success) {
return NULL;
}
pOld = &xkb->map->types[i+req->firstType];
map = (CARD8 *)&wire[1];
pOld->mods.real_mods = wire->realMods;
pOld->mods.vmods= wire->virtualMods;
pOld->num_levels = wire->numLevels;
pOld->map_count= wire->nMapEntries;
pOld->mods.mask= pOld->mods.real_mods|
XkbMaskForVMask(xkb,pOld->mods.vmods);
if (wire->nMapEntries) {
xkbKTSetMapEntryWireDesc *mapWire;
xkbModsWireDesc *preWire;
unsigned tmp;
mapWire= (xkbKTSetMapEntryWireDesc *)map;
preWire= (xkbModsWireDesc *)&mapWire[wire->nMapEntries];
for (n=0;n<wire->nMapEntries;n++) {
pOld->map[n].active= 1;
pOld->map[n].mods.mask= mapWire[n].realMods;
pOld->map[n].mods.real_mods= mapWire[n].realMods;
pOld->map[n].mods.vmods= mapWire[n].virtualMods;
pOld->map[n].level= mapWire[n].level;
if (mapWire[n].virtualMods!=0) {
tmp= XkbMaskForVMask(xkb,mapWire[n].virtualMods);
pOld->map[n].active= (tmp!=0);
pOld->map[n].mods.mask|= tmp;
}
if (wire->preserve) {
pOld->preserve[n].real_mods= preWire[n].realMods;
pOld->preserve[n].vmods= preWire[n].virtualMods;
tmp= XkbMaskForVMask(xkb,preWire[n].virtualMods);
pOld->preserve[n].mask= preWire[n].realMods|tmp;
}
}
if (wire->preserve)
map= (CARD8 *)&preWire[wire->nMapEntries];
else map= (CARD8 *)&mapWire[wire->nMapEntries];
}
else map= (CARD8 *)&wire[1];
wire = (xkbKeyTypeWireDesc *)map;
}
first= req->firstType;
last= first+req->nTypes-1;
if (changes->map.changed&XkbKeyTypesMask) {
int oldLast;
oldLast= changes->map.first_type+changes->map.num_types-1;
if (changes->map.first_type<first)
first= changes->map.first_type;
if (oldLast>last)
last= oldLast;
}
changes->map.changed|= XkbKeyTypesMask;
changes->map.first_type = first;
changes->map.num_types = (last-first)+1;
return (char *)wire;
}
static char *
SetKeySyms( ClientPtr client,
XkbDescPtr xkb,
xkbSetMapReq * req,
xkbSymMapWireDesc * wire,
XkbChangesPtr changes,
DeviceIntPtr dev)
{
register unsigned i,s;
XkbSymMapPtr oldMap;
KeySym * newSyms;
KeySym * pSyms;
unsigned first,last;
oldMap = &xkb->map->key_sym_map[req->firstKeySym];
for (i=0;i<req->nKeySyms;i++,oldMap++) {
pSyms = (KeySym *)&wire[1];
if (wire->nSyms>0) {
newSyms = XkbResizeKeySyms(xkb,i+req->firstKeySym,wire->nSyms);
for (s=0;s<wire->nSyms;s++) {
newSyms[s]= pSyms[s];
}
if (client->swapped) {
int n;
for (s=0;s<wire->nSyms;s++) {
swapl(&newSyms[s],n);
}
}
}
oldMap->kt_index[0] = wire->ktIndex[0];
oldMap->kt_index[1] = wire->ktIndex[1];
oldMap->kt_index[2] = wire->ktIndex[2];
oldMap->kt_index[3] = wire->ktIndex[3];
oldMap->group_info = wire->groupInfo;
oldMap->width = wire->width;
wire= (xkbSymMapWireDesc *)&pSyms[wire->nSyms];
}
first= req->firstKeySym;
last= first+req->nKeySyms-1;
if (changes->map.changed&XkbKeySymsMask) {
int oldLast= (changes->map.first_key_sym+changes->map.num_key_syms-1);
if (changes->map.first_key_sym<first)
first= changes->map.first_key_sym;
if (oldLast>last)
last= oldLast;
}
changes->map.changed|= XkbKeySymsMask;
changes->map.first_key_sym = first;
changes->map.num_key_syms = (last-first+1);
s= 0;
for (i=xkb->min_key_code;i<=xkb->max_key_code;i++) {
if (XkbKeyNumGroups(xkb,i)>s)
s= XkbKeyNumGroups(xkb,i);
}
if (s!=xkb->ctrls->num_groups) {
xkbControlsNotify cn;
XkbControlsRec old;
cn.keycode= 0;
cn.eventType= 0;
cn.requestMajor= XkbReqCode;
cn.requestMinor= X_kbSetMap;
old= *xkb->ctrls;
xkb->ctrls->num_groups= s;
if (XkbComputeControlsNotify(dev,&old,xkb->ctrls,&cn,False))
XkbSendControlsNotify(dev,&cn);
}
return (char *)wire;
}
static char *
SetKeyActions( XkbDescPtr xkb,
xkbSetMapReq * req,
CARD8 * wire,
XkbChangesPtr changes)
{
register unsigned i,first,last;
CARD8 * nActs = wire;
XkbAction * newActs;
wire+= XkbPaddedSize(req->nKeyActs);
for (i=0;i<req->nKeyActs;i++) {
if (nActs[i]==0)
xkb->server->key_acts[i+req->firstKeyAct]= 0;
else {
newActs= XkbResizeKeyActions(xkb,i+req->firstKeyAct,nActs[i]);
memcpy((char *)newActs,(char *)wire,
nActs[i]*SIZEOF(xkbActionWireDesc));
wire+= nActs[i]*SIZEOF(xkbActionWireDesc);
}
}
first= req->firstKeyAct;
last= (first+req->nKeyActs-1);
if (changes->map.changed&XkbKeyActionsMask) {
int oldLast;
oldLast= changes->map.first_key_act+changes->map.num_key_acts-1;
if (changes->map.first_key_act<first)
first= changes->map.first_key_act;
if (oldLast>last)
last= oldLast;
}
changes->map.changed|= XkbKeyActionsMask;
changes->map.first_key_act= first;
changes->map.num_key_acts= (last-first+1);
return (char *)wire;
}
static char *
SetKeyBehaviors( XkbSrvInfoPtr xkbi,
xkbSetMapReq *req,
xkbBehaviorWireDesc *wire,
XkbChangesPtr changes)
{
register unsigned i;
int maxRG = -1;
XkbDescPtr xkb = xkbi->desc;
XkbServerMapPtr server = xkb->server;
unsigned first,last;
first= req->firstKeyBehavior;
last= req->firstKeyBehavior+req->nKeyBehaviors-1;
bzero(&server->behaviors[first],req->nKeyBehaviors*sizeof(XkbBehavior));
for (i=0;i<req->totalKeyBehaviors;i++) {
if ((server->behaviors[wire->key].type&XkbKB_Permanent)==0) {
server->behaviors[wire->key].type= wire->type;
server->behaviors[wire->key].data= wire->data;
if ((wire->type==XkbKB_RadioGroup)&&(((int)wire->data)>maxRG))
maxRG= wire->data + 1;
}
wire++;
}
if (maxRG>(int)xkbi->nRadioGroups) {
int sz = maxRG*sizeof(XkbRadioGroupRec);
if (xkbi->radioGroups)
xkbi->radioGroups=(XkbRadioGroupPtr)_XkbRealloc(xkbi->radioGroups,sz);
else xkbi->radioGroups= (XkbRadioGroupPtr)_XkbCalloc(1, sz);
if (xkbi->radioGroups) {
if (xkbi->nRadioGroups)
bzero(&xkbi->radioGroups[xkbi->nRadioGroups],
(maxRG-xkbi->nRadioGroups)*sizeof(XkbRadioGroupRec));
xkbi->nRadioGroups= maxRG;
}
else xkbi->nRadioGroups= 0;
}
if (changes->map.changed&XkbKeyBehaviorsMask) {
unsigned oldLast;
oldLast= changes->map.first_key_behavior+
changes->map.num_key_behaviors-1;
if (changes->map.first_key_behavior<req->firstKeyBehavior)
first= changes->map.first_key_behavior;
if (oldLast>last)
last= oldLast;
}
changes->map.changed|= XkbKeyBehaviorsMask;
changes->map.first_key_behavior = first;
changes->map.num_key_behaviors = (last-first+1);
return (char *)wire;
}
static char *
SetVirtualMods(XkbSrvInfoPtr xkbi,xkbSetMapReq *req,CARD8 *wire,
XkbChangesPtr changes)
{
register int i,bit,nMods;
XkbServerMapPtr srv = xkbi->desc->server;
if (((req->present&XkbVirtualModsMask)==0)||(req->virtualMods==0))
return (char *)wire;
for (i=nMods=0,bit=1;i<XkbNumVirtualMods;i++,bit<<=1) {
if (req->virtualMods&bit) {
if (srv->vmods[i]!=wire[nMods]) {
changes->map.changed|= XkbVirtualModsMask;
changes->map.vmods|= bit;
srv->vmods[i]= wire[nMods];
}
nMods++;
}
}
return (char *)(wire+XkbPaddedSize(nMods));
}
static char *
SetKeyExplicit(XkbSrvInfoPtr xkbi,xkbSetMapReq *req,CARD8 *wire,
XkbChangesPtr changes)
{
register unsigned i,first,last;
XkbServerMapPtr xkb = xkbi->desc->server;
CARD8 * start;
start= wire;
first= req->firstKeyExplicit;
last= req->firstKeyExplicit+req->nKeyExplicit-1;
bzero(&xkb->explicit[first],req->nKeyExplicit);
for (i=0;i<req->totalKeyExplicit;i++,wire+= 2) {
xkb->explicit[wire[0]]= wire[1];
}
if (first>0) {
if (changes->map.changed&XkbExplicitComponentsMask) {
int oldLast;
oldLast= changes->map.first_key_explicit+
changes->map.num_key_explicit-1;
if (changes->map.first_key_explicit<first)
first= changes->map.first_key_explicit;
if (oldLast>last)
last= oldLast;
}
changes->map.first_key_explicit= first;
changes->map.num_key_explicit= (last-first)+1;
}
wire+= XkbPaddedSize(wire-start)-(wire-start);
return (char *)wire;
}
static char *
SetModifierMap( XkbSrvInfoPtr xkbi,
xkbSetMapReq * req,
CARD8 * wire,
XkbChangesPtr changes)
{
register unsigned i,first,last;
XkbClientMapPtr xkb = xkbi->desc->map;
CARD8 * start;
start= wire;
first= req->firstModMapKey;
last= req->firstModMapKey+req->nModMapKeys-1;
bzero(&xkb->modmap[first],req->nModMapKeys);
for (i=0;i<req->totalModMapKeys;i++,wire+= 2) {
xkb->modmap[wire[0]]= wire[1];
}
if (first>0) {
if (changes->map.changed&XkbModifierMapMask) {
int oldLast;
oldLast= changes->map.first_modmap_key+
changes->map.num_modmap_keys-1;
if (changes->map.first_modmap_key<first)
first= changes->map.first_modmap_key;
if (oldLast>last)
last= oldLast;
}
changes->map.first_modmap_key= first;
changes->map.num_modmap_keys= (last-first)+1;
}
wire+= XkbPaddedSize(wire-start)-(wire-start);
return (char *)wire;
}
static char *
SetVirtualModMap( XkbSrvInfoPtr xkbi,
xkbSetMapReq * req,
xkbVModMapWireDesc * wire,
XkbChangesPtr changes)
{
register unsigned i,first,last;
XkbServerMapPtr srv = xkbi->desc->server;
first= req->firstVModMapKey;
last= req->firstVModMapKey+req->nVModMapKeys-1;
bzero(&srv->vmodmap[first],req->nVModMapKeys*sizeof(unsigned short));
for (i=0;i<req->totalVModMapKeys;i++,wire++) {
srv->vmodmap[wire->key]= wire->vmods;
}
if (first>0) {
if (changes->map.changed&XkbVirtualModMapMask) {
int oldLast;
oldLast= changes->map.first_vmodmap_key+
changes->map.num_vmodmap_keys-1;
if (changes->map.first_vmodmap_key<first)
first= changes->map.first_vmodmap_key;
if (oldLast>last)
last= oldLast;
}
changes->map.first_vmodmap_key= first;
changes->map.num_vmodmap_keys= (last-first)+1;
}
return (char *)wire;
}
static int
_XkbSetMapChecks(ClientPtr client, DeviceIntPtr dev, xkbSetMapReq *req, char* values)
{
XkbSrvInfoPtr xkbi;
XkbDescPtr xkb;
int error;
int nTypes = 0, nActions;
CARD8 mapWidths[XkbMaxLegalKeyCode + 1];
CARD16 symsPerKey[XkbMaxLegalKeyCode + 1];
xkbi= dev->key->xkbInfo;
xkb = xkbi->desc;
if ((xkb->min_key_code != req->minKeyCode)||
(xkb->max_key_code != req->maxKeyCode)) {
if (client->vMajor!=1) {
req->minKeyCode= xkb->min_key_code;
req->maxKeyCode= xkb->max_key_code;
}
else {
if (!XkbIsLegalKeycode(req->minKeyCode)) {
client->errorValue = _XkbErrCode3(2, req->minKeyCode, req->maxKeyCode);
return BadValue;
}
if (req->minKeyCode > req->maxKeyCode) {
client->errorValue = _XkbErrCode3(3, req->minKeyCode, req->maxKeyCode);
return BadMatch;
}
}
}
if ((req->present & XkbKeyTypesMask) &&
(!CheckKeyTypes(client,xkb,req,(xkbKeyTypeWireDesc **)&values,
&nTypes,mapWidths))) {
client->errorValue = nTypes;
return BadValue;
}
if ((req->present & XkbKeySymsMask) &&
(!CheckKeySyms(client,xkb,req,nTypes,mapWidths,symsPerKey,
(xkbSymMapWireDesc **)&values,&error))) {
client->errorValue = error;
return BadValue;
}
if ((req->present & XkbKeyActionsMask) &&
(!CheckKeyActions(xkb,req,nTypes,mapWidths,symsPerKey,
(CARD8 **)&values,&nActions))) {
client->errorValue = nActions;
return BadValue;
}
if ((req->present & XkbKeyBehaviorsMask) &&
(!CheckKeyBehaviors(xkb,req,(xkbBehaviorWireDesc**)&values,&error))) {
client->errorValue = error;
return BadValue;
}
if ((req->present & XkbVirtualModsMask) &&
(!CheckVirtualMods(xkb,req,(CARD8 **)&values,&error))) {
client->errorValue= error;
return BadValue;
}
if ((req->present&XkbExplicitComponentsMask) &&
(!CheckKeyExplicit(xkb,req,(CARD8 **)&values,&error))) {
client->errorValue= error;
return BadValue;
}
if ((req->present&XkbModifierMapMask) &&
(!CheckModifierMap(xkb,req,(CARD8 **)&values,&error))) {
client->errorValue= error;
return BadValue;
}
if ((req->present&XkbVirtualModMapMask) &&
(!CheckVirtualModMap(xkb,req,(xkbVModMapWireDesc **)&values,&error))) {
client->errorValue= error;
return BadValue;
}
if (((values-((char *)req))/4)!= req->length) {
ErrorF("[xkb] Internal error! Bad length in XkbSetMap (after check)\n");
client->errorValue = values-((char *)&req[1]);
return BadLength;
}
return Success;
}
static int
_XkbSetMap(ClientPtr client, DeviceIntPtr dev, xkbSetMapReq *req, char *values)
{
XkbEventCauseRec cause;
XkbChangesRec change;
Bool sentNKN;
XkbSrvInfoPtr xkbi;
XkbDescPtr xkb;
xkbi= dev->key->xkbInfo;
xkb = xkbi->desc;
XkbSetCauseXkbReq(&cause,X_kbSetMap,client);
bzero(&change, sizeof(change));
sentNKN = False;
if ((xkb->min_key_code!=req->minKeyCode)||
(xkb->max_key_code!=req->maxKeyCode)) {
Status status;
xkbNewKeyboardNotify nkn;
nkn.deviceID = nkn.oldDeviceID = dev->id;
nkn.oldMinKeyCode = xkb->min_key_code;
nkn.oldMaxKeyCode = xkb->max_key_code;
status= XkbChangeKeycodeRange(xkb, req->minKeyCode,
req->maxKeyCode, &change);
if (status != Success)
return status;
nkn.minKeyCode = xkb->min_key_code;
nkn.maxKeyCode = xkb->max_key_code;
nkn.requestMajor = XkbReqCode;
nkn.requestMinor = X_kbSetMap;
nkn.changed = XkbNKN_KeycodesMask;
XkbSendNewKeyboardNotify(dev,&nkn);
sentNKN = True;
}
if (req->present&XkbKeyTypesMask) {
values = SetKeyTypes(xkb,req,(xkbKeyTypeWireDesc *)values,&change);
if (!values) goto allocFailure;
}
if (req->present&XkbKeySymsMask) {
values = SetKeySyms(client,xkb,req,(xkbSymMapWireDesc *)values,&change,dev);
if (!values) goto allocFailure;
}
if (req->present&XkbKeyActionsMask) {
values = SetKeyActions(xkb,req,(CARD8 *)values,&change);
if (!values) goto allocFailure;
}
if (req->present&XkbKeyBehaviorsMask) {
values= SetKeyBehaviors(xkbi,req,(xkbBehaviorWireDesc *)values,&change);
if (!values) goto allocFailure;
}
if (req->present&XkbVirtualModsMask)
values= SetVirtualMods(xkbi,req,(CARD8 *)values,&change);
if (req->present&XkbExplicitComponentsMask)
values= SetKeyExplicit(xkbi,req,(CARD8 *)values,&change);
if (req->present&XkbModifierMapMask)
values= SetModifierMap(xkbi,req,(CARD8 *)values,&change);
if (req->present&XkbVirtualModMapMask)
values= SetVirtualModMap(xkbi,req,(xkbVModMapWireDesc *)values,&change);
if (((values-((char *)req))/4)!=req->length) {
ErrorF("[xkb] Internal error! Bad length in XkbSetMap (after set)\n");
client->errorValue = values-((char *)&req[1]);
return BadLength;
}
if (req->flags&XkbSetMapRecomputeActions) {
KeyCode first,last,firstMM,lastMM;
if (change.map.num_key_syms>0) {
first= change.map.first_key_sym;
last= first+change.map.num_key_syms-1;
}
else first= last= 0;
if (change.map.num_modmap_keys>0) {
firstMM= change.map.first_modmap_key;
lastMM= first+change.map.num_modmap_keys-1;
}
else firstMM= lastMM= 0;
if ((last>0) && (lastMM>0)) {
if (firstMM<first)
first= firstMM;
if (lastMM>last)
last= lastMM;
}
else if (lastMM>0) {
first= firstMM;
last= lastMM;
}
if (last>0) {
unsigned check= 0;
XkbUpdateActions(dev,first,(last-first+1),&change,&check,&cause);
if (check)
XkbCheckSecondaryEffects(xkbi,check,&change,&cause);
}
}
if (!sentNKN)
XkbSendNotification(dev,&change,&cause);
XkbUpdateCoreDescription(dev,False);
return Success;
allocFailure:
return BadAlloc;
}
int
ProcXkbSetMap(ClientPtr client)
{
DeviceIntPtr dev;
char * tmp;
int rc;
REQUEST(xkbSetMapReq);
REQUEST_AT_LEAST_SIZE(xkbSetMapReq);
if (!(client->xkbClientFlags&_XkbClientInitialized))
return BadAccess;
CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess);
CHK_MASK_LEGAL(0x01,stuff->present,XkbAllMapComponentsMask);
tmp = (char *)&stuff[1];
rc = _XkbSetMapChecks(client, dev, stuff, tmp);
if (rc != Success)
return rc;
if (stuff->deviceSpec == XkbUseCoreKbd)
{
DeviceIntPtr other;
for (other = inputInfo.devices; other; other = other->next)
{
if ((other != dev) && other->key && !other->isMaster && (other->u.master == dev))
{
rc = XaceHook(XACE_DEVICE_ACCESS, client, other, DixManageAccess);
if (rc == Success)
{
rc = _XkbSetMapChecks(client, other, stuff, tmp);
if (rc != Success)
return rc;
}
}
}
}
rc = _XkbSetMap(client, dev, stuff, tmp);
if (rc != Success)
return rc;
if (stuff->deviceSpec == XkbUseCoreKbd)
{
DeviceIntPtr other;
for (other = inputInfo.devices; other; other = other->next)
{
if ((other != dev) && other->key && !other->isMaster && (other->u.master == dev))
{
rc = XaceHook(XACE_DEVICE_ACCESS, client, other, DixManageAccess);
if (rc == Success)
_XkbSetMap(client, other, stuff, tmp);
}
}
}
return client->noClientException;
}
static Status
XkbComputeGetCompatMapReplySize( XkbCompatMapPtr compat,
xkbGetCompatMapReply * rep)
{
unsigned size,nGroups;
nGroups= 0;
if (rep->groups!=0) {
register int i,bit;
for (i=0,bit=1;i<XkbNumKbdGroups;i++,bit<<=1) {
if (rep->groups&bit)
nGroups++;
}
}
size= nGroups*SIZEOF(xkbModsWireDesc);
size+= (rep->nSI*SIZEOF(xkbSymInterpretWireDesc));
rep->length= size/4;
return Success;
}
static int
XkbSendCompatMap( ClientPtr client,
XkbCompatMapPtr compat,
xkbGetCompatMapReply * rep)
{
char * data;
int size;
size= rep->length*4;
if (size>0) {
data = (char *)xalloc(size);
if (data) {
register unsigned i,bit;
xkbModsWireDesc * grp;
XkbSymInterpretPtr sym= &compat->sym_interpret[rep->firstSI];
xkbSymInterpretWireDesc *wire = (xkbSymInterpretWireDesc *)data;
for (i=0;i<rep->nSI;i++,sym++,wire++) {
wire->sym= sym->sym;
wire->mods= sym->mods;
wire->match= sym->match;
wire->virtualMod= sym->virtual_mod;
wire->flags= sym->flags;
memcpy((char*)&wire->act,(char*)&sym->act,sz_xkbActionWireDesc);
if (client->swapped) {
register int n;
swapl(&wire->sym,n);
}
}
if (rep->groups) {
grp = (xkbModsWireDesc *)wire;
for (i=0,bit=1;i<XkbNumKbdGroups;i++,bit<<=1) {
if (rep->groups&bit) {
grp->mask= compat->groups[i].mask;
grp->realMods= compat->groups[i].real_mods;
grp->virtualMods= compat->groups[i].vmods;
if (client->swapped) {
register int n;
swaps(&grp->virtualMods,n);
}
grp++;
}
}
wire= (xkbSymInterpretWireDesc*)grp;
}
}
else return BadAlloc;
}
else data= NULL;
if (client->swapped) {
register int n;
swaps(&rep->sequenceNumber,n);
swapl(&rep->length,n);
swaps(&rep->firstSI,n);
swaps(&rep->nSI,n);
swaps(&rep->nTotalSI,n);
}
WriteToClient(client, SIZEOF(xkbGetCompatMapReply), (char *)rep);
if (data) {
WriteToClient(client, size, data);
xfree((char *)data);
}
return client->noClientException;
}
int
ProcXkbGetCompatMap(ClientPtr client)
{
xkbGetCompatMapReply rep;
DeviceIntPtr dev;
XkbDescPtr xkb;
XkbCompatMapPtr compat;
REQUEST(xkbGetCompatMapReq);
REQUEST_SIZE_MATCH(xkbGetCompatMapReq);
if (!(client->xkbClientFlags&_XkbClientInitialized))
return BadAccess;
CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess);
xkb = dev->key->xkbInfo->desc;
compat= xkb->compat;
rep.type = X_Reply;
rep.deviceID = dev->id;
rep.sequenceNumber = client->sequence;
rep.length = 0;
rep.firstSI = stuff->firstSI;
rep.nSI = stuff->nSI;
if (stuff->getAllSI) {
rep.firstSI = 0;
rep.nSI = compat->num_si;
}
else if ((((unsigned)stuff->nSI)>0)&&
((unsigned)(stuff->firstSI+stuff->nSI-1)>=compat->num_si)) {
client->errorValue = _XkbErrCode2(0x05,compat->num_si);
return BadValue;
}
rep.nTotalSI = compat->num_si;
rep.groups= stuff->groups;
XkbComputeGetCompatMapReplySize(compat,&rep);
return XkbSendCompatMap(client,compat,&rep);
}
static int
_XkbSetCompatMap(ClientPtr client, DeviceIntPtr dev,
xkbSetCompatMapReq *req, char* data, BOOL dryRun)
{
XkbSrvInfoPtr xkbi;
XkbDescPtr xkb;
XkbCompatMapPtr compat;
int nGroups;
unsigned i,bit;
xkbi = dev->key->xkbInfo;
xkb = xkbi->desc;
compat = xkb->compat;
if ((req->nSI>0)||(req->truncateSI)) {
xkbSymInterpretWireDesc *wire;
if (req->firstSI>compat->num_si) {
client->errorValue = _XkbErrCode2(0x02,compat->num_si);
return BadValue;
}
wire= (xkbSymInterpretWireDesc *)data;
wire+= req->nSI;
data = (char *)wire;
}
nGroups= 0;
if (req->groups!=0) {
for (i=0,bit=1;i<XkbNumKbdGroups;i++,bit<<=1) {
if ( req->groups&bit )
nGroups++;
}
}
data+= nGroups*SIZEOF(xkbModsWireDesc);
if (((data-((char *)req))/4)!=req->length) {
return BadLength;
}
if (dryRun)
return Success;
data = (char *)&req[1];
if (req->nSI>0) {
xkbSymInterpretWireDesc *wire = (xkbSymInterpretWireDesc *)data;
XkbSymInterpretPtr sym;
if ((unsigned)(req->firstSI+req->nSI)>compat->num_si) {
compat->num_si= req->firstSI+req->nSI;
compat->sym_interpret= _XkbTypedRealloc(compat->sym_interpret,
compat->num_si,
XkbSymInterpretRec);
if (!compat->sym_interpret) {
compat->num_si= 0;
return BadAlloc;
}
}
else if (req->truncateSI) {
compat->num_si = req->firstSI+req->nSI;
}
sym = &compat->sym_interpret[req->firstSI];
for (i=0;i<req->nSI;i++,wire++,sym++) {
if (client->swapped) {
int n;
swapl(&wire->sym,n);
}
sym->sym= wire->sym;
sym->mods= wire->mods;
sym->match= wire->match;
sym->flags= wire->flags;
sym->virtual_mod= wire->virtualMod;
memcpy((char *)&sym->act,(char *)&wire->act,
SIZEOF(xkbActionWireDesc));
}
data = (char *)wire;
}
else if (req->truncateSI) {
compat->num_si = req->firstSI;
}
if (req->groups!=0) {
unsigned i, bit;
xkbModsWireDesc *wire = (xkbModsWireDesc *)data;
for (i = 0, bit = 1; i < XkbNumKbdGroups; i++, bit <<= 1) {
if (req->groups & bit) {
if (client->swapped) {
int n;
swaps(&wire->virtualMods,n);
}
compat->groups[i].mask= wire->realMods;
compat->groups[i].real_mods= wire->realMods;
compat->groups[i].vmods= wire->virtualMods;
if (wire->virtualMods!=0) {
unsigned tmp;
tmp= XkbMaskForVMask(xkb,wire->virtualMods);
compat->groups[i].mask|= tmp;
}
data+= SIZEOF(xkbModsWireDesc);
wire= (xkbModsWireDesc *)data;
}
}
}
i= XkbPaddedSize((data-((char *)req)));
if ((i/4)!=req->length) {
ErrorF("[xkb] Internal length error on read in _XkbSetCompatMap\n");
return BadLength;
}
if (dev->xkb_interest) {
xkbCompatMapNotify ev;
ev.deviceID = dev->id;
ev.changedGroups = req->groups;
ev.firstSI = req->firstSI;
ev.nSI = req->nSI;
ev.nTotalSI = compat->num_si;
XkbSendCompatMapNotify(dev,&ev);
}
if (req->recomputeActions) {
XkbChangesRec change;
unsigned check;
XkbEventCauseRec cause;
XkbSetCauseXkbReq(&cause,X_kbSetCompatMap,client);
bzero(&change,sizeof(XkbChangesRec));
XkbUpdateActions(dev,xkb->min_key_code,XkbNumKeys(xkb),&change,&check,
&cause);
if (check)
XkbCheckSecondaryEffects(xkbi,check,&change,&cause);
XkbUpdateCoreDescription(dev,False);
XkbSendNotification(dev,&change,&cause);
}
return Success;
}
int
ProcXkbSetCompatMap(ClientPtr client)
{
DeviceIntPtr dev;
char *data;
int rc;
REQUEST(xkbSetCompatMapReq);
REQUEST_AT_LEAST_SIZE(xkbSetCompatMapReq);
if (!(client->xkbClientFlags&_XkbClientInitialized))
return BadAccess;
CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess);
data = (char *)&stuff[1];
rc = _XkbSetCompatMap(client, dev, stuff, data, TRUE);
if (rc != Success)
return rc;
if (stuff->deviceSpec == XkbUseCoreKbd)
{
DeviceIntPtr other;
for (other = inputInfo.devices; other; other = other->next)
{
if ((other != dev) && other->key && !other->isMaster && (other->u.master == dev))
{
rc = XaceHook(XACE_DEVICE_ACCESS, client, other, DixManageAccess);
if (rc == Success)
{
rc = _XkbSetCompatMap(client, other, stuff, data, TRUE);
if (rc != Success)
return rc;
}
}
}
}
rc = _XkbSetCompatMap(client, dev, stuff, data, FALSE);
if (rc != Success)
return rc;
if (stuff->deviceSpec == XkbUseCoreKbd)
{
DeviceIntPtr other;
for (other = inputInfo.devices; other; other = other->next)
{
if ((other != dev) && other->key && !other->isMaster && (other->u.master == dev))
{
rc = XaceHook(XACE_DEVICE_ACCESS, client, other, DixManageAccess);
if (rc == Success)
{
rc = _XkbSetCompatMap(client, other, stuff, data, FALSE);
if (rc != Success)
return rc;
}
}
}
}
return client->noClientException;
}
int
ProcXkbGetIndicatorState(ClientPtr client)
{
xkbGetIndicatorStateReply rep;
XkbSrvLedInfoPtr sli;
DeviceIntPtr dev;
register int i;
REQUEST(xkbGetIndicatorStateReq);
REQUEST_SIZE_MATCH(xkbGetIndicatorStateReq);
if (!(client->xkbClientFlags&_XkbClientInitialized))
return BadAccess;
CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixReadAccess);
sli= XkbFindSrvLedInfo(dev,XkbDfltXIClass,XkbDfltXIId,
XkbXI_IndicatorStateMask);
if (!sli)
return BadAlloc;
rep.type = X_Reply;
rep.sequenceNumber = client->sequence;
rep.length = 0;
rep.deviceID = dev->id;
rep.state = sli->effectiveState;
if (client->swapped) {
swaps(&rep.sequenceNumber,i);
swapl(&rep.state,i);
}
WriteToClient(client, SIZEOF(xkbGetIndicatorStateReply), (char *)&rep);
return client->noClientException;
}
static Status
XkbComputeGetIndicatorMapReplySize(
XkbIndicatorPtr indicators,
xkbGetIndicatorMapReply *rep)
{
register int i,bit;
int nIndicators;
rep->realIndicators = indicators->phys_indicators;
for (i=nIndicators=0,bit=1;i<XkbNumIndicators;i++,bit<<=1) {
if (rep->which&bit)
nIndicators++;
}
rep->length = (nIndicators*SIZEOF(xkbIndicatorMapWireDesc))/4;
return Success;
}
static int
XkbSendIndicatorMap( ClientPtr client,
XkbIndicatorPtr indicators,
xkbGetIndicatorMapReply * rep)
{
int length;
CARD8 * map;
register int i;
register unsigned bit;
length = rep->length*4;
if (length>0) {
CARD8 *to;
to= map= (CARD8 *)xalloc(length);
if (map) {
xkbIndicatorMapWireDesc *wire = (xkbIndicatorMapWireDesc *)to;
for (i=0,bit=1;i<XkbNumIndicators;i++,bit<<=1) {
if (rep->which&bit) {
wire->flags= indicators->maps[i].flags;
wire->whichGroups= indicators->maps[i].which_groups;
wire->groups= indicators->maps[i].groups;
wire->whichMods= indicators->maps[i].which_mods;
wire->mods= indicators->maps[i].mods.mask;
wire->realMods= indicators->maps[i].mods.real_mods;
wire->virtualMods= indicators->maps[i].mods.vmods;
wire->ctrls= indicators->maps[i].ctrls;
if (client->swapped) {
register int n;
swaps(&wire->virtualMods,n);
swapl(&wire->ctrls,n);
}
wire++;
}
}
to = (CARD8 *)wire;
if ((to-map)!=length) {
client->errorValue = _XkbErrCode2(0xff,length);
return BadLength;
}
}
else return BadAlloc;
}
else map = NULL;
if (client->swapped) {
swaps(&rep->sequenceNumber,i);
swapl(&rep->length,i);
swapl(&rep->which,i);
swapl(&rep->realIndicators,i);
}
WriteToClient(client, SIZEOF(xkbGetIndicatorMapReply), (char *)rep);
if (map) {
WriteToClient(client, length, (char *)map);
xfree((char *)map);
}
return client->noClientException;
}
int
ProcXkbGetIndicatorMap(ClientPtr client)
{
xkbGetIndicatorMapReply rep;
DeviceIntPtr dev;
XkbDescPtr xkb;
XkbIndicatorPtr leds;
REQUEST(xkbGetIndicatorMapReq);
REQUEST_SIZE_MATCH(xkbGetIndicatorMapReq);
if (!(client->xkbClientFlags&_XkbClientInitialized))
return BadAccess;
CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess);
xkb= dev->key->xkbInfo->desc;
leds= xkb->indicators;
rep.type = X_Reply;
rep.sequenceNumber = client->sequence;
rep.length = 0;
rep.deviceID = dev->id;
rep.which = stuff->which;
XkbComputeGetIndicatorMapReplySize(leds,&rep);
return XkbSendIndicatorMap(client,leds,&rep);
}
static int
_XkbSetIndicatorMap(ClientPtr client, DeviceIntPtr dev,
int which, xkbIndicatorMapWireDesc *desc)
{
XkbSrvInfoPtr xkbi;
XkbSrvLedInfoPtr sli;
XkbEventCauseRec cause;
int i, bit;
xkbi = dev->key->xkbInfo;
sli= XkbFindSrvLedInfo(dev, XkbDfltXIClass, XkbDfltXIId,
XkbXI_IndicatorMapsMask);
if (!sli)
return BadAlloc;
for (i = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) {
if (which & bit) {
sli->maps[i].flags = desc->flags;
sli->maps[i].which_groups = desc->whichGroups;
sli->maps[i].groups = desc->groups;
sli->maps[i].which_mods = desc->whichMods;
sli->maps[i].mods.mask = desc->mods;
sli->maps[i].mods.real_mods = desc->mods;
sli->maps[i].mods.vmods= desc->virtualMods;
sli->maps[i].ctrls = desc->ctrls;
if (desc->virtualMods!=0) {
unsigned tmp;
tmp= XkbMaskForVMask(xkbi->desc,desc->virtualMods);
sli->maps[i].mods.mask= desc->mods|tmp;
}
desc++;
}
}
XkbSetCauseXkbReq(&cause,X_kbSetIndicatorMap,client);
XkbApplyLedMapChanges(dev,sli,which,NULL,NULL,&cause);
return Success;
}
int
ProcXkbSetIndicatorMap(ClientPtr client)
{
int i, bit;
int nIndicators;
DeviceIntPtr dev;
xkbIndicatorMapWireDesc *from;
int rc;
REQUEST(xkbSetIndicatorMapReq);
REQUEST_AT_LEAST_SIZE(xkbSetIndicatorMapReq);
if (!(client->xkbClientFlags&_XkbClientInitialized))
return BadAccess;
CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixSetAttrAccess);
if (stuff->which==0)
return client->noClientException;
for (nIndicators=i=0,bit=1;i<XkbNumIndicators;i++,bit<<=1) {
if (stuff->which&bit)
nIndicators++;
}
if (stuff->length!=((SIZEOF(xkbSetIndicatorMapReq)+
(nIndicators*SIZEOF(xkbIndicatorMapWireDesc)))/4)) {
return BadLength;
}
from = (xkbIndicatorMapWireDesc *)&stuff[1];
for (i=0,bit=1;i<XkbNumIndicators;i++,bit<<=1) {
if (stuff->which&bit) {
if (client->swapped) {
int n;
swaps(&from->virtualMods,n);
swapl(&from->ctrls,n);
}
CHK_MASK_LEGAL(i,from->whichGroups,XkbIM_UseAnyGroup);
CHK_MASK_LEGAL(i,from->whichMods,XkbIM_UseAnyMods);
from++;
}
}
from = (xkbIndicatorMapWireDesc *)&stuff[1];
rc = _XkbSetIndicatorMap(client, dev, stuff->which, from);
if (rc != Success)
return rc;
if (stuff->deviceSpec == XkbUseCoreKbd)
{
DeviceIntPtr other;
for (other = inputInfo.devices; other; other = other->next)
{
if ((other != dev) && other->key && !other->isMaster && (other->u.master == dev))
{
rc = XaceHook(XACE_DEVICE_ACCESS, client, other, DixSetAttrAccess);
if (rc == Success)
_XkbSetIndicatorMap(client, other, stuff->which, from);
}
}
}
return Success;
}
int
ProcXkbGetNamedIndicator(ClientPtr client)
{
DeviceIntPtr dev;
xkbGetNamedIndicatorReply rep;
register int i = 0;
XkbSrvLedInfoPtr sli;
XkbIndicatorMapPtr map = NULL;
REQUEST(xkbGetNamedIndicatorReq);
REQUEST_SIZE_MATCH(xkbGetNamedIndicatorReq);
if (!(client->xkbClientFlags&_XkbClientInitialized))
return BadAccess;
CHK_LED_DEVICE(dev, stuff->deviceSpec, client, DixReadAccess);
CHK_ATOM_ONLY(stuff->indicator);
sli= XkbFindSrvLedInfo(dev,stuff->ledClass,stuff->ledID,0);
if (!sli)
return BadAlloc;
i= 0;
map= NULL;
if ((sli->names)&&(sli->maps)) {
for (i=0;i<XkbNumIndicators;i++) {
if (stuff->indicator==sli->names[i]) {
map= &sli->maps[i];
break;
}
}
}
rep.type= X_Reply;
rep.length = 0;
rep.sequenceNumber = client->sequence;
rep.deviceID = dev->id;
rep.indicator= stuff->indicator;
if (map!=NULL) {
rep.found= True;
rep.on= ((sli->effectiveState&(1<<i))!=0);
rep.realIndicator= ((sli->physIndicators&(1<<i))!=0);
rep.ndx= i;
rep.flags= map->flags;
rep.whichGroups= map->which_groups;
rep.groups= map->groups;
rep.whichMods= map->which_mods;
rep.mods= map->mods.mask;
rep.realMods= map->mods.real_mods;
rep.virtualMods= map->mods.vmods;
rep.ctrls= map->ctrls;
rep.supported= True;
}
else {
rep.found= False;
rep.on= False;
rep.realIndicator= False;
rep.ndx= XkbNoIndicator;
rep.flags= 0;
rep.whichGroups= 0;
rep.groups= 0;
rep.whichMods= 0;
rep.mods= 0;
rep.realMods= 0;
rep.virtualMods= 0;
rep.ctrls= 0;
rep.supported= True;
}
if ( client->swapped ) {
register int n;
swapl(&rep.length,n);
swaps(&rep.sequenceNumber,n);
swapl(&rep.indicator,n);
swaps(&rep.virtualMods,n);
swapl(&rep.ctrls,n);
}
WriteToClient(client,SIZEOF(xkbGetNamedIndicatorReply), (char *)&rep);
return client->noClientException;
}
static XkbIndicatorMapPtr
_XkbFindNamedIndicatorMap(XkbSrvLedInfoPtr sli, Atom indicator,
int *led_return)
{
XkbIndicatorMapPtr map;
int led;
map = NULL;
if (sli->names && sli->maps) {
for (led = 0; (led < XkbNumIndicators) && (map == NULL); led++) {
if (sli->names[led] == indicator) {
map= &sli->maps[led];
break;
}
}
}
*led_return = led;
return map;
}
static int
_XkbCreateIndicatorMap(DeviceIntPtr dev, Atom indicator,
int ledClass, int ledID,
XkbIndicatorMapPtr *map_return, int *led_return,
Bool dryRun)
{
XkbSrvLedInfoPtr sli;
XkbIndicatorMapPtr map;
int led;
sli = XkbFindSrvLedInfo(dev, ledClass, ledID, XkbXI_IndicatorsMask);
if (!sli)
return BadAlloc;
map = _XkbFindNamedIndicatorMap(sli, indicator, &led);
if (!map)
{
for (led = 0, map = NULL; (led < XkbNumIndicators) && (map == NULL); led++) {
if ((sli->names) && (sli->maps) && (sli->names[led] == None) &&
(!XkbIM_InUse(&sli->maps[led])))
{
map = &sli->maps[led];
if (!dryRun)
sli->names[led] = indicator;
break;
}
}
}
if (!map)
return BadAlloc;
*led_return = led;
*map_return = map;
return Success;
}
static int
_XkbSetNamedIndicator(ClientPtr client, DeviceIntPtr dev,
xkbSetNamedIndicatorReq *stuff)
{
unsigned int extDevReason;
unsigned int statec, namec, mapc;
XkbSrvLedInfoPtr sli;
int led = 0;
XkbIndicatorMapPtr map;
DeviceIntPtr kbd;
XkbEventCauseRec cause;
xkbExtensionDeviceNotify ed;
XkbChangesRec changes;
int rc;
rc = _XkbCreateIndicatorMap(dev, stuff->indicator, stuff->ledClass,
stuff->ledID, &map, &led, FALSE);
if (rc != Success || !map)
return rc;
sli = XkbFindSrvLedInfo(dev, stuff->ledClass, stuff->ledID,
XkbXI_IndicatorsMask);
if (!sli)
return BadAlloc;
namec = mapc = statec = 0;
extDevReason = 0;
namec |= (1<<led);
sli->namesPresent |= ((stuff->indicator != None) ? (1 << led) : 0);
extDevReason |= XkbXI_IndicatorNamesMask;
if (stuff->setMap) {
map->flags = stuff->flags;
map->which_groups = stuff->whichGroups;
map->groups = stuff->groups;
map->which_mods = stuff->whichMods;
map->mods.mask = stuff->realMods;
map->mods.real_mods = stuff->realMods;
map->mods.vmods= stuff->virtualMods;
map->ctrls = stuff->ctrls;
mapc|= (1<<led);
}
if ((stuff->setState) && ((map->flags & XkbIM_NoExplicit) == 0))
{
if (stuff->on) sli->explicitState |= (1<<led);
else sli->explicitState &= ~(1<<led);
statec |= ((sli->effectiveState ^ sli->explicitState) & (1 << led));
}
bzero((char *)&ed,sizeof(xkbExtensionDeviceNotify));
bzero((char *)&changes,sizeof(XkbChangesRec));
XkbSetCauseXkbReq(&cause,X_kbSetNamedIndicator,client);
if (namec)
XkbApplyLedNameChanges(dev,sli,namec,&ed,&changes,&cause);
if (mapc)
XkbApplyLedMapChanges(dev,sli,mapc,&ed,&changes,&cause);
if (statec)
XkbApplyLedStateChanges(dev,sli,statec,&ed,&changes,&cause);
kbd = dev;
if ((sli->flags&XkbSLI_HasOwnState)==0)
kbd = inputInfo.keyboard;
XkbFlushLedEvents(dev, kbd, sli, &ed, &changes, &cause);
return Success;
}
int
ProcXkbSetNamedIndicator(ClientPtr client)
{
int rc;
DeviceIntPtr dev;
int led = 0;
XkbIndicatorMapPtr map;
REQUEST(xkbSetNamedIndicatorReq);
REQUEST_SIZE_MATCH(xkbSetNamedIndicatorReq);
if (!(client->xkbClientFlags&_XkbClientInitialized))
return BadAccess;
CHK_LED_DEVICE(dev, stuff->deviceSpec, client, DixSetAttrAccess);
CHK_ATOM_ONLY(stuff->indicator);
CHK_MASK_LEGAL(0x10,stuff->whichGroups,XkbIM_UseAnyGroup);
CHK_MASK_LEGAL(0x11,stuff->whichMods,XkbIM_UseAnyMods);
rc = _XkbCreateIndicatorMap(dev, stuff->indicator,
stuff->ledClass, stuff->ledID,
&map, &led, TRUE);
if (rc != Success || !map)
return rc;
if (stuff->deviceSpec == XkbUseCoreKbd ||
stuff->deviceSpec == XkbUseCorePtr)
{
DeviceIntPtr other;
for (other = inputInfo.devices; other; other = other->next)
{
if ((other != dev) && !other->isMaster && (other->u.master == dev) &&
(other->kbdfeed || other->leds) &&
(XaceHook(XACE_DEVICE_ACCESS, client, other, DixSetAttrAccess) == Success))
{
rc = _XkbCreateIndicatorMap(other, stuff->indicator,
stuff->ledClass, stuff->ledID,
&map, &led, TRUE);
if (rc != Success || !map)
return rc;
}
}
}
rc = _XkbSetNamedIndicator(client, dev, stuff);
if (rc != Success)
return rc;
if (stuff->deviceSpec == XkbUseCoreKbd ||
stuff->deviceSpec == XkbUseCorePtr)
{
DeviceIntPtr other;
for (other = inputInfo.devices; other; other = other->next)
{
if ((other != dev) && !other->isMaster && (other->u.master == dev) &&
(other->kbdfeed || other->leds) &&
(XaceHook(XACE_DEVICE_ACCESS, client, other, DixSetAttrAccess) == Success))
{
_XkbSetNamedIndicator(client, other, stuff);
}
}
}
return client->noClientException;
}
static CARD32
_XkbCountAtoms(Atom *atoms,int maxAtoms,int *count)
{
register unsigned int i,bit,nAtoms;
register CARD32 atomsPresent;
for (i=nAtoms=atomsPresent=0,bit=1;i<maxAtoms;i++,bit<<=1) {
if (atoms[i]!=None) {
atomsPresent|= bit;
nAtoms++;
}
}
if (count)
*count= nAtoms;
return atomsPresent;
}
static char *
_XkbWriteAtoms(char *wire,Atom *atoms,int maxAtoms,int swap)
{
register unsigned int i;
Atom *atm;
atm = (Atom *)wire;
for (i=0;i<maxAtoms;i++) {
if (atoms[i]!=None) {
*atm= atoms[i];
if (swap) {
register int n;
swapl(atm,n);
}
atm++;
}
}
return (char *)atm;
}
static Status
XkbComputeGetNamesReplySize(XkbDescPtr xkb,xkbGetNamesReply *rep)
{
register unsigned which,length;
register int i;
rep->minKeyCode= xkb->min_key_code;
rep->maxKeyCode= xkb->max_key_code;
which= rep->which;
length= 0;
if (xkb->names!=NULL) {
if (which&XkbKeycodesNameMask) length++;
if (which&XkbGeometryNameMask) length++;
if (which&XkbSymbolsNameMask) length++;
if (which&XkbPhysSymbolsNameMask) length++;
if (which&XkbTypesNameMask) length++;
if (which&XkbCompatNameMask) length++;
}
else which&= ~XkbComponentNamesMask;
if (xkb->map!=NULL) {
if (which&XkbKeyTypeNamesMask)
length+= xkb->map->num_types;
rep->nTypes= xkb->map->num_types;
if (which&XkbKTLevelNamesMask) {
XkbKeyTypePtr pType = xkb->map->types;
int nKTLevels = 0;
length+= XkbPaddedSize(xkb->map->num_types)/4;
for (i=0;i<xkb->map->num_types;i++,pType++) {
if (pType->level_names!=NULL)
nKTLevels+= pType->num_levels;
}
rep->nKTLevels= nKTLevels;
length+= nKTLevels;
}
}
else {
rep->nTypes= 0;
rep->nKTLevels= 0;
which&= ~(XkbKeyTypeNamesMask|XkbKTLevelNamesMask);
}
rep->minKeyCode= xkb->min_key_code;
rep->maxKeyCode= xkb->max_key_code;
rep->indicators= 0;
rep->virtualMods= 0;
rep->groupNames= 0;
if (xkb->names!=NULL) {
if (which&XkbIndicatorNamesMask) {
int nLeds;
rep->indicators=
_XkbCountAtoms(xkb->names->indicators,XkbNumIndicators,&nLeds);
length+= nLeds;
if (nLeds==0)
which&= ~XkbIndicatorNamesMask;
}
if (which&XkbVirtualModNamesMask) {
int nVMods;
rep->virtualMods=
_XkbCountAtoms(xkb->names->vmods,XkbNumVirtualMods,&nVMods);
length+= nVMods;
if (nVMods==0)
which&= ~XkbVirtualModNamesMask;
}
if (which&XkbGroupNamesMask) {
int nGroups;
rep->groupNames=
_XkbCountAtoms(xkb->names->groups,XkbNumKbdGroups,&nGroups);
length+= nGroups;
if (nGroups==0)
which&= ~XkbGroupNamesMask;
}
if ((which&XkbKeyNamesMask)&&(xkb->names->keys))
length+= rep->nKeys;
else which&= ~XkbKeyNamesMask;
if ((which&XkbKeyAliasesMask)&&
(xkb->names->key_aliases)&&(xkb->names->num_key_aliases>0)) {
rep->nKeyAliases= xkb->names->num_key_aliases;
length+= rep->nKeyAliases*2;
}
else {
which&= ~XkbKeyAliasesMask;
rep->nKeyAliases= 0;
}
if ((which&XkbRGNamesMask)&&(xkb->names->num_rg>0))
length+= xkb->names->num_rg;
else which&= ~XkbRGNamesMask;
}
else {
which&= ~(XkbIndicatorNamesMask|XkbVirtualModNamesMask);
which&= ~(XkbGroupNamesMask|XkbKeyNamesMask|XkbKeyAliasesMask);
which&= ~XkbRGNamesMask;
}
rep->length= length;
rep->which= which;
return Success;
}
static int
XkbSendNames(ClientPtr client,XkbDescPtr xkb,xkbGetNamesReply *rep)
{
register unsigned i,length,which;
char * start;
char * desc;
register int n;
length= rep->length*4;
which= rep->which;
if (client->swapped) {
swaps(&rep->sequenceNumber,n);
swapl(&rep->length,n);
swapl(&rep->which,n);
swaps(&rep->virtualMods,n);
swapl(&rep->indicators,n);
}
start = desc = (char *)xalloc(length);
if ( !start )
return BadAlloc;
if (xkb->names) {
if (which&XkbKeycodesNameMask) {
*((CARD32 *)desc)= xkb->names->keycodes;
if (client->swapped) {
swapl(desc,n);
}
desc+= 4;
}
if (which&XkbGeometryNameMask) {
*((CARD32 *)desc)= xkb->names->geometry;
if (client->swapped) {
swapl(desc,n);
}
desc+= 4;
}
if (which&XkbSymbolsNameMask) {
*((CARD32 *)desc)= xkb->names->symbols;
if (client->swapped) {
swapl(desc,n);
}
desc+= 4;
}
if (which&XkbPhysSymbolsNameMask) {
register CARD32 *atm= (CARD32 *)desc;
atm[0]= (CARD32)xkb->names->phys_symbols;
if (client->swapped) {
swapl(&atm[0],n);
}
desc+= 4;
}
if (which&XkbTypesNameMask) {
*((CARD32 *)desc)= (CARD32)xkb->names->types;
if (client->swapped) {
swapl(desc,n);
}
desc+= 4;
}
if (which&XkbCompatNameMask) {
*((CARD32 *)desc)= (CARD32)xkb->names->compat;
if (client->swapped) {
swapl(desc,n);
}
desc+= 4;
}
if (which&XkbKeyTypeNamesMask) {
register CARD32 *atm= (CARD32 *)desc;
register XkbKeyTypePtr type= xkb->map->types;
for (i=0;i<xkb->map->num_types;i++,atm++,type++) {
*atm= (CARD32)type->name;
if (client->swapped) {
swapl(atm,n);
}
}
desc= (char *)atm;
}
if (which&XkbKTLevelNamesMask && xkb->map) {
XkbKeyTypePtr type = xkb->map->types;
register CARD32 *atm;
for (i=0;i<rep->nTypes;i++,type++) {
*desc++ = type->num_levels;
}
desc+= XkbPaddedSize(rep->nTypes)-rep->nTypes;
atm= (CARD32 *)desc;
type = xkb->map->types;
for (i=0;i<xkb->map->num_types;i++,type++) {
register unsigned l;
if (type->level_names) {
for (l=0;l<type->num_levels;l++,atm++) {
*atm= type->level_names[l];
if (client->swapped) {
swapl(atm,n);
}
}
desc+= type->num_levels*4;
}
}
}
if (which&XkbIndicatorNamesMask) {
desc= _XkbWriteAtoms(desc,xkb->names->indicators,XkbNumIndicators,
client->swapped);
}
if (which&XkbVirtualModNamesMask) {
desc= _XkbWriteAtoms(desc,xkb->names->vmods,XkbNumVirtualMods,
client->swapped);
}
if (which&XkbGroupNamesMask) {
desc= _XkbWriteAtoms(desc,xkb->names->groups,XkbNumKbdGroups,
client->swapped);
}
if (which&XkbKeyNamesMask) {
for (i=0;i<rep->nKeys;i++,desc+= sizeof(XkbKeyNameRec)) {
*((XkbKeyNamePtr)desc)= xkb->names->keys[i+rep->firstKey];
}
}
if (which&XkbKeyAliasesMask) {
XkbKeyAliasPtr pAl;
pAl= xkb->names->key_aliases;
for (i=0;i<rep->nKeyAliases;i++,pAl++,desc+=2*XkbKeyNameLength) {
*((XkbKeyAliasPtr)desc)= *pAl;
}
}
if ((which&XkbRGNamesMask)&&(rep->nRadioGroups>0)) {
register CARD32 *atm= (CARD32 *)desc;
for (i=0;i<rep->nRadioGroups;i++,atm++) {
*atm= (CARD32)xkb->names->radio_groups[i];
if (client->swapped) {
swapl(atm,n);
}
}
desc+= rep->nRadioGroups*4;
}
}
if ((desc-start)!=(length)) {
ErrorF("[xkb] BOGUS LENGTH in write names, expected %d, got %ld\n",
length, (unsigned long)(desc-start));
}
WriteToClient(client, SIZEOF(xkbGetNamesReply), (char *)rep);
WriteToClient(client, length, start);
xfree((char *)start);
return client->noClientException;
}
int
ProcXkbGetNames(ClientPtr client)
{
DeviceIntPtr dev;
XkbDescPtr xkb;
xkbGetNamesReply rep;
REQUEST(xkbGetNamesReq);
REQUEST_SIZE_MATCH(xkbGetNamesReq);
if (!(client->xkbClientFlags&_XkbClientInitialized))
return BadAccess;
CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess);
CHK_MASK_LEGAL(0x01,stuff->which,XkbAllNamesMask);
xkb = dev->key->xkbInfo->desc;
rep.type= X_Reply;
rep.sequenceNumber= client->sequence;
rep.length = 0;
rep.deviceID = dev->id;
rep.which = stuff->which;
rep.nTypes = xkb->map->num_types;
rep.firstKey = xkb->min_key_code;
rep.nKeys = XkbNumKeys(xkb);
if (xkb->names!=NULL) {
rep.nKeyAliases= xkb->names->num_key_aliases;
rep.nRadioGroups = xkb->names->num_rg;
}
else {
rep.nKeyAliases= rep.nRadioGroups= 0;
}
XkbComputeGetNamesReplySize(xkb,&rep);
return XkbSendNames(client,xkb,&rep);
}
static CARD32 *
_XkbCheckAtoms(CARD32 *wire,int nAtoms,int swapped,Atom *pError)
{
register int i;
for (i=0;i<nAtoms;i++,wire++) {
if (swapped) {
register int n;
swapl(wire,n);
}
if ((((Atom)*wire)!=None)&&(!ValidAtom((Atom)*wire))) {
*pError= ((Atom)*wire);
return NULL;
}
}
return wire;
}
static CARD32 *
_XkbCheckMaskedAtoms(CARD32 *wire,int nAtoms,CARD32 present,int swapped,
Atom *pError)
{
register unsigned i,bit;
for (i=0,bit=1;(i<nAtoms)&&(present);i++,bit<<=1) {
if ((present&bit)==0)
continue;
if (swapped) {
register int n;
swapl(wire,n);
}
if ((((Atom)*wire)!=None)&&(!ValidAtom(((Atom)*wire)))) {
*pError= (Atom)*wire;
return NULL;
}
wire++;
}
return wire;
}
static Atom *
_XkbCopyMaskedAtoms( Atom *wire,
Atom *dest,
int nAtoms,
CARD32 present)
{
register int i,bit;
for (i=0,bit=1;(i<nAtoms)&&(present);i++,bit<<=1) {
if ((present&bit)==0)
continue;
dest[i]= *wire++;
}
return wire;
}
static Bool
_XkbCheckTypeName(Atom name,int typeNdx)
{
char * str;
str= NameForAtom(name);
if ((strcmp(str,"ONE_LEVEL")==0)||(strcmp(str,"TWO_LEVEL")==0)||
(strcmp(str,"ALPHABETIC")==0)||(strcmp(str,"KEYPAD")==0))
return False;
return True;
}
static int
_XkbSetNamesCheck(ClientPtr client, DeviceIntPtr dev,
xkbSetNamesReq *stuff, CARD32 *data)
{
XkbDescRec *xkb;
XkbNamesRec *names;
CARD32 *tmp;
Atom bad;
tmp = data;
xkb = dev->key->xkbInfo->desc;
names = xkb->names;
if (stuff->which & XkbKeyTypeNamesMask) {
int i;
CARD32 *old;
if ( stuff->nTypes<1 ) {
client->errorValue = _XkbErrCode2(0x02,stuff->nTypes);
return BadValue;
}
if ((unsigned)(stuff->firstType+stuff->nTypes-1)>=xkb->map->num_types) {
client->errorValue = _XkbErrCode4(0x03,stuff->firstType,
stuff->nTypes,
xkb->map->num_types);
return BadValue;
}
if (((unsigned)stuff->firstType)<=XkbLastRequiredType) {
client->errorValue = _XkbErrCode2(0x04,stuff->firstType);
return BadAccess;
}
old= tmp;
tmp= _XkbCheckAtoms(tmp,stuff->nTypes,client->swapped,&bad);
if (!tmp) {
client->errorValue= bad;
return BadAtom;
}
for (i=0;i<stuff->nTypes;i++,old++) {
if (!_XkbCheckTypeName((Atom)*old,stuff->firstType+i))
client->errorValue= _XkbErrCode2(0x05,i);
}
}
if (stuff->which&XkbKTLevelNamesMask) {
unsigned i;
XkbKeyTypePtr type;
CARD8 * width;
if ( stuff->nKTLevels<1 ) {
client->errorValue = _XkbErrCode2(0x05,stuff->nKTLevels);
return BadValue;
}
if ((unsigned)(stuff->firstKTLevel+stuff->nKTLevels-1)>=
xkb->map->num_types) {
client->errorValue = _XkbErrCode4(0x06,stuff->firstKTLevel,
stuff->nKTLevels,xkb->map->num_types);
return BadValue;
}
width = (CARD8 *)tmp;
tmp= (CARD32 *)(((char *)tmp)+XkbPaddedSize(stuff->nKTLevels));
type = &xkb->map->types[stuff->firstKTLevel];
for (i=0;i<stuff->nKTLevels;i++,type++) {
if (width[i]==0)
continue;
else if (width[i]!=type->num_levels) {
client->errorValue= _XkbErrCode4(0x07,i+stuff->firstKTLevel,
type->num_levels,width[i]);
return BadMatch;
}
tmp= _XkbCheckAtoms(tmp,width[i],client->swapped,&bad);
if (!tmp) {
client->errorValue= bad;
return BadAtom;
}
}
}
if (stuff->which&XkbIndicatorNamesMask) {
if (stuff->indicators==0) {
client->errorValue= 0x08;
return BadMatch;
}
tmp= _XkbCheckMaskedAtoms(tmp,XkbNumIndicators,stuff->indicators,
client->swapped,&bad);
if (!tmp) {
client->errorValue= bad;
return BadAtom;
}
}
if (stuff->which&XkbVirtualModNamesMask) {
if (stuff->virtualMods==0) {
client->errorValue= 0x09;
return BadMatch;
}
tmp= _XkbCheckMaskedAtoms(tmp,XkbNumVirtualMods,
(CARD32)stuff->virtualMods,
client->swapped,&bad);
if (!tmp) {
client->errorValue = bad;
return BadAtom;
}
}
if (stuff->which&XkbGroupNamesMask) {
if (stuff->groupNames==0) {
client->errorValue= 0x0a;
return BadMatch;
}
tmp= _XkbCheckMaskedAtoms(tmp,XkbNumKbdGroups,
(CARD32)stuff->groupNames,
client->swapped,&bad);
if (!tmp) {
client->errorValue = bad;
return BadAtom;
}
}
if (stuff->which&XkbKeyNamesMask) {
if (stuff->firstKey<(unsigned)xkb->min_key_code) {
client->errorValue= _XkbErrCode3(0x0b,xkb->min_key_code,
stuff->firstKey);
return BadValue;
}
if (((unsigned)(stuff->firstKey+stuff->nKeys-1)>xkb->max_key_code)||
(stuff->nKeys<1)) {
client->errorValue= _XkbErrCode4(0x0c,xkb->max_key_code,
stuff->firstKey,stuff->nKeys);
return BadValue;
}
tmp+= stuff->nKeys;
}
if ((stuff->which&XkbKeyAliasesMask)&&(stuff->nKeyAliases>0)) {
tmp+= stuff->nKeyAliases*2;
}
if (stuff->which&XkbRGNamesMask) {
if ( stuff->nRadioGroups<1 ) {
client->errorValue= _XkbErrCode2(0x0d,stuff->nRadioGroups);
return BadValue;
}
tmp= _XkbCheckAtoms(tmp,stuff->nRadioGroups,client->swapped,&bad);
if (!tmp) {
client->errorValue= bad;
return BadAtom;
}
}
if ((tmp-((CARD32 *)stuff))!=stuff->length) {
client->errorValue = stuff->length;
return BadLength;
}
return Success;
}
static int
_XkbSetNames(ClientPtr client, DeviceIntPtr dev, xkbSetNamesReq *stuff)
{
XkbDescRec *xkb;
XkbNamesRec *names;
CARD32 *tmp;
xkbNamesNotify nn;
tmp = (CARD32 *)&stuff[1];
xkb = dev->key->xkbInfo->desc;
names = xkb->names;
if (XkbAllocNames(xkb,stuff->which,stuff->nRadioGroups,
stuff->nKeyAliases)!=Success) {
return BadAlloc;
}
bzero(&nn,sizeof(xkbNamesNotify));
nn.changed= stuff->which;
tmp = (CARD32 *)&stuff[1];
if (stuff->which&XkbKeycodesNameMask)
names->keycodes= *tmp++;
if (stuff->which&XkbGeometryNameMask)
names->geometry= *tmp++;
if (stuff->which&XkbSymbolsNameMask)
names->symbols= *tmp++;
if (stuff->which&XkbPhysSymbolsNameMask)
names->phys_symbols= *tmp++;
if (stuff->which&XkbTypesNameMask)
names->types= *tmp++;
if (stuff->which&XkbCompatNameMask)
names->compat= *tmp++;
if ((stuff->which&XkbKeyTypeNamesMask)&&(stuff->nTypes>0)) {
register unsigned i;
register XkbKeyTypePtr type;
type= &xkb->map->types[stuff->firstType];
for (i=0;i<stuff->nTypes;i++,type++) {
type->name= *tmp++;
}
nn.firstType= stuff->firstType;
nn.nTypes= stuff->nTypes;
}
if (stuff->which&XkbKTLevelNamesMask) {
register XkbKeyTypePtr type;
register unsigned i;
CARD8 *width;
width = (CARD8 *)tmp;
tmp= (CARD32 *)(((char *)tmp)+XkbPaddedSize(stuff->nKTLevels));
type= &xkb->map->types[stuff->firstKTLevel];
for (i=0;i<stuff->nKTLevels;i++,type++) {
if (width[i]>0) {
if (type->level_names) {
register unsigned n;
for (n=0;n<width[i];n++) {
type->level_names[n]= tmp[n];
}
}
tmp+= width[i];
}
}
nn.firstLevelName= 0;
nn.nLevelNames= stuff->nTypes;
}
if (stuff->which&XkbIndicatorNamesMask) {
tmp= _XkbCopyMaskedAtoms(tmp,names->indicators,XkbNumIndicators,
stuff->indicators);
nn.changedIndicators= stuff->indicators;
}
if (stuff->which&XkbVirtualModNamesMask) {
tmp= _XkbCopyMaskedAtoms(tmp,names->vmods,XkbNumVirtualMods,
stuff->virtualMods);
nn.changedVirtualMods= stuff->virtualMods;
}
if (stuff->which&XkbGroupNamesMask) {
tmp= _XkbCopyMaskedAtoms(tmp,names->groups,XkbNumKbdGroups,
stuff->groupNames);
nn.changedVirtualMods= stuff->groupNames;
}
if (stuff->which&XkbKeyNamesMask) {
memcpy((char*)&names->keys[stuff->firstKey],(char *)tmp,
stuff->nKeys*XkbKeyNameLength);
tmp+= stuff->nKeys;
nn.firstKey= stuff->firstKey;
nn.nKeys= stuff->nKeys;
}
if (stuff->which&XkbKeyAliasesMask) {
if (stuff->nKeyAliases>0) {
register int na= stuff->nKeyAliases;
if (XkbAllocNames(xkb,XkbKeyAliasesMask,0,na)!=Success)
return BadAlloc;
memcpy((char *)names->key_aliases,(char *)tmp,
stuff->nKeyAliases*sizeof(XkbKeyAliasRec));
tmp+= stuff->nKeyAliases*2;
}
else if (names->key_aliases!=NULL) {
_XkbFree(names->key_aliases);
names->key_aliases= NULL;
names->num_key_aliases= 0;
}
nn.nAliases= names->num_key_aliases;
}
if (stuff->which&XkbRGNamesMask) {
if (stuff->nRadioGroups>0) {
register unsigned i,nrg;
nrg= stuff->nRadioGroups;
if (XkbAllocNames(xkb,XkbRGNamesMask,nrg,0)!=Success)
return BadAlloc;
for (i=0;i<stuff->nRadioGroups;i++) {
names->radio_groups[i]= tmp[i];
}
tmp+= stuff->nRadioGroups;
}
else if (names->radio_groups) {
_XkbFree(names->radio_groups);
names->radio_groups= NULL;
names->num_rg= 0;
}
nn.nRadioGroups= names->num_rg;
}
if (nn.changed) {
Bool needExtEvent;
needExtEvent= (nn.changed&XkbIndicatorNamesMask)!=0;
XkbSendNamesNotify(dev,&nn);
if (needExtEvent) {
XkbSrvLedInfoPtr sli;
xkbExtensionDeviceNotify edev;
register int i;
register unsigned bit;
sli= XkbFindSrvLedInfo(dev,XkbDfltXIClass,XkbDfltXIId,
XkbXI_IndicatorsMask);
sli->namesPresent= 0;
for (i=0,bit=1;i<XkbNumIndicators;i++,bit<<=1) {
if (names->indicators[i]!=None)
sli->namesPresent|= bit;
}
bzero(&edev,sizeof(xkbExtensionDeviceNotify));
edev.reason= XkbXI_IndicatorNamesMask;
edev.ledClass= KbdFeedbackClass;
edev.ledID= dev->kbdfeed->ctrl.id;
edev.ledsDefined= sli->namesPresent|sli->mapsPresent;
edev.ledState= sli->effectiveState;
edev.firstBtn= 0;
edev.nBtns= 0;
edev.supported= XkbXI_AllFeaturesMask;
edev.unsupported= 0;
XkbSendExtensionDeviceNotify(dev,client,&edev);
}
}
return Success;
}
int
ProcXkbSetNames(ClientPtr client)
{
DeviceIntPtr dev;
CARD32 *tmp;
Atom bad;
int rc;
REQUEST(xkbSetNamesReq);
REQUEST_AT_LEAST_SIZE(xkbSetNamesReq);
if (!(client->xkbClientFlags&_XkbClientInitialized))
return BadAccess;
CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess);
CHK_MASK_LEGAL(0x01,stuff->which,XkbAllNamesMask);
tmp = (CARD32 *)&stuff[1];
if (stuff->which&XkbKeycodesNameMask) {
tmp= _XkbCheckAtoms(tmp,1,client->swapped,&bad);
if (!tmp) {
client->errorValue = bad;
return BadAtom;
}
}
if (stuff->which&XkbGeometryNameMask) {
tmp= _XkbCheckAtoms(tmp,1,client->swapped,&bad);
if (!tmp) {
client->errorValue = bad;
return BadAtom;
}
}
if (stuff->which&XkbSymbolsNameMask) {
tmp= _XkbCheckAtoms(tmp,1,client->swapped,&bad);
if (!tmp) {
client->errorValue = bad;
return BadAtom;
}
}
if (stuff->which&XkbPhysSymbolsNameMask) {
tmp= _XkbCheckAtoms(tmp,1,client->swapped,&bad);
if (!tmp) {
client->errorValue= bad;
return BadAtom;
}
}
if (stuff->which&XkbTypesNameMask) {
tmp= _XkbCheckAtoms(tmp,1,client->swapped,&bad);
if (!tmp) {
client->errorValue = bad;
return BadAtom;
}
}
if (stuff->which&XkbCompatNameMask) {
tmp= _XkbCheckAtoms(tmp,1,client->swapped,&bad);
if (!tmp) {
client->errorValue = bad;
return BadAtom;
}
}
rc = _XkbSetNamesCheck(client, dev, stuff, tmp);
if (rc != Success)
return rc;
if (stuff->deviceSpec == XkbUseCoreKbd)
{
DeviceIntPtr other;
for (other = inputInfo.devices; other; other = other->next)
{
if ((other != dev) && other->key && !other->isMaster && (other->u.master == dev))
{
rc = XaceHook(XACE_DEVICE_ACCESS, client, other, DixManageAccess);
if (rc == Success)
{
rc = _XkbSetNamesCheck(client, other, stuff, tmp);
if (rc != Success)
return rc;
}
}
}
}
rc = _XkbSetNames(client, dev, stuff);
if (rc != Success)
return rc;
if (stuff->deviceSpec == XkbUseCoreKbd)
{
DeviceIntPtr other;
for (other = inputInfo.devices; other; other = other->next)
{
if ((other != dev) && other->key && !other->isMaster && (other->u.master == dev))
{
rc = XaceHook(XACE_DEVICE_ACCESS, client, other, DixManageAccess);
if (rc == Success)
_XkbSetNames(client, other, stuff);
}
}
}
return client->noClientException;
}
#include "xkbgeom.h"
#define XkbSizeCountedString(s) ((s)?((((2+strlen(s))+3)/4)*4):4)
static char *
XkbWriteCountedString(char *wire,char *str,Bool swap)
{
CARD16 len,*pLen;
len= (str?strlen(str):0);
pLen= (CARD16 *)wire;
*pLen= len;
if (swap) {
register int n;
swaps(pLen,n);
}
memcpy(&wire[2],str,len);
wire+= ((2+len+3)/4)*4;
return wire;
}
static int
XkbSizeGeomProperties(XkbGeometryPtr geom)
{
register int i,size;
XkbPropertyPtr prop;
for (size=i=0,prop=geom->properties;i<geom->num_properties;i++,prop++) {
size+= XkbSizeCountedString(prop->name);
size+= XkbSizeCountedString(prop->value);
}
return size;
}
static char *
XkbWriteGeomProperties(char *wire,XkbGeometryPtr geom,Bool swap)
{
register int i;
register XkbPropertyPtr prop;
for (i=0,prop=geom->properties;i<geom->num_properties;i++,prop++) {
wire= XkbWriteCountedString(wire,prop->name,swap);
wire= XkbWriteCountedString(wire,prop->value,swap);
}
return wire;
}
static int
XkbSizeGeomKeyAliases(XkbGeometryPtr geom)
{
return geom->num_key_aliases*(2*XkbKeyNameLength);
}
static char *
XkbWriteGeomKeyAliases(char *wire,XkbGeometryPtr geom,Bool swap)
{
register int sz;
sz= geom->num_key_aliases*(XkbKeyNameLength*2);
if (sz>0) {
memcpy(wire,(char *)geom->key_aliases,sz);
wire+= sz;
}
return wire;
}
static int
XkbSizeGeomColors(XkbGeometryPtr geom)
{
register int i,size;
register XkbColorPtr color;
for (i=size=0,color=geom->colors;i<geom->num_colors;i++,color++) {
size+= XkbSizeCountedString(color->spec);
}
return size;
}
static char *
XkbWriteGeomColors(char *wire,XkbGeometryPtr geom,Bool swap)
{
register int i;
register XkbColorPtr color;
for (i=0,color=geom->colors;i<geom->num_colors;i++,color++) {
wire= XkbWriteCountedString(wire,color->spec,swap);
}
return wire;
}
static int
XkbSizeGeomShapes(XkbGeometryPtr geom)
{
register int i,size;
register XkbShapePtr shape;
for (i=size=0,shape=geom->shapes;i<geom->num_shapes;i++,shape++) {
register int n;
register XkbOutlinePtr ol;
size+= SIZEOF(xkbShapeWireDesc);
for (n=0,ol=shape->outlines;n<shape->num_outlines;n++,ol++) {
size+= SIZEOF(xkbOutlineWireDesc);
size+= ol->num_points*SIZEOF(xkbPointWireDesc);
}
}
return size;
}
static char *
XkbWriteGeomShapes(char *wire,XkbGeometryPtr geom,Bool swap)
{
int i;
XkbShapePtr shape;
xkbShapeWireDesc * shapeWire;
for (i=0,shape=geom->shapes;i<geom->num_shapes;i++,shape++) {
register int o;
XkbOutlinePtr ol;
xkbOutlineWireDesc * olWire;
shapeWire= (xkbShapeWireDesc *)wire;
shapeWire->name= shape->name;
shapeWire->nOutlines= shape->num_outlines;
if (shape->primary!=NULL)
shapeWire->primaryNdx= XkbOutlineIndex(shape,shape->primary);
else shapeWire->primaryNdx= XkbNoShape;
if (shape->approx!=NULL)
shapeWire->approxNdx= XkbOutlineIndex(shape,shape->approx);
else shapeWire->approxNdx= XkbNoShape;
if (swap) {
register int n;
swapl(&shapeWire->name,n);
}
wire= (char *)&shapeWire[1];
for (o=0,ol=shape->outlines;o<shape->num_outlines;o++,ol++) {
register int p;
XkbPointPtr pt;
xkbPointWireDesc * ptWire;
olWire= (xkbOutlineWireDesc *)wire;
olWire->nPoints= ol->num_points;
olWire->cornerRadius= ol->corner_radius;
wire= (char *)&olWire[1];
ptWire= (xkbPointWireDesc *)wire;
for (p=0,pt=ol->points;p<ol->num_points;p++,pt++) {
ptWire[p].x= pt->x;
ptWire[p].y= pt->y;
if (swap) {
register int n;
swaps(&ptWire[p].x,n);
swaps(&ptWire[p].y,n);
}
}
wire= (char *)&ptWire[ol->num_points];
}
}
return wire;
}
static int
XkbSizeGeomDoodads(int num_doodads,XkbDoodadPtr doodad)
{
register int i,size;
for (i=size=0;i<num_doodads;i++,doodad++) {
size+= SIZEOF(xkbAnyDoodadWireDesc);
if (doodad->any.type==XkbTextDoodad) {
size+= XkbSizeCountedString(doodad->text.text);
size+= XkbSizeCountedString(doodad->text.font);
}
else if (doodad->any.type==XkbLogoDoodad) {
size+= XkbSizeCountedString(doodad->logo.logo_name);
}
}
return size;
}
static char *
XkbWriteGeomDoodads(char *wire,int num_doodads,XkbDoodadPtr doodad,Bool swap)
{
register int i;
xkbDoodadWireDesc * doodadWire;
for (i=0;i<num_doodads;i++,doodad++) {
doodadWire= (xkbDoodadWireDesc *)wire;
wire= (char *)&doodadWire[1];
bzero(doodadWire,SIZEOF(xkbDoodadWireDesc));
doodadWire->any.name= doodad->any.name;
doodadWire->any.type= doodad->any.type;
doodadWire->any.priority= doodad->any.priority;
doodadWire->any.top= doodad->any.top;
doodadWire->any.left= doodad->any.left;
if (swap) {
register int n;
swapl(&doodadWire->any.name,n);
swaps(&doodadWire->any.top,n);
swaps(&doodadWire->any.left,n);
}
switch (doodad->any.type) {
case XkbOutlineDoodad:
case XkbSolidDoodad:
doodadWire->shape.angle= doodad->shape.angle;
doodadWire->shape.colorNdx= doodad->shape.color_ndx;
doodadWire->shape.shapeNdx= doodad->shape.shape_ndx;
if (swap) {
register int n;
swaps(&doodadWire->shape.angle,n);
}
break;
case XkbTextDoodad:
doodadWire->text.angle= doodad->text.angle;
doodadWire->text.width= doodad->text.width;
doodadWire->text.height= doodad->text.height;
doodadWire->text.colorNdx= doodad->text.color_ndx;
if (swap) {
register int n;
swaps(&doodadWire->text.angle,n);
swaps(&doodadWire->text.width,n);
swaps(&doodadWire->text.height,n);
}
wire= XkbWriteCountedString(wire,doodad->text.text,swap);
wire= XkbWriteCountedString(wire,doodad->text.font,swap);
break;
case XkbIndicatorDoodad:
doodadWire->indicator.shapeNdx= doodad->indicator.shape_ndx;
doodadWire->indicator.onColorNdx=doodad->indicator.on_color_ndx;
doodadWire->indicator.offColorNdx=
doodad->indicator.off_color_ndx;
break;
case XkbLogoDoodad:
doodadWire->logo.angle= doodad->logo.angle;
doodadWire->logo.colorNdx= doodad->logo.color_ndx;
doodadWire->logo.shapeNdx= doodad->logo.shape_ndx;
wire= XkbWriteCountedString(wire,doodad->logo.logo_name,swap);
break;
default:
ErrorF("[xkb] Unknown doodad type %d in XkbWriteGeomDoodads\n",
doodad->any.type);
ErrorF("[xkb] Ignored\n");
break;
}
}
return wire;
}
static char *
XkbWriteGeomOverlay(char *wire,XkbOverlayPtr ol,Bool swap)
{
register int r;
XkbOverlayRowPtr row;
xkbOverlayWireDesc * olWire;
olWire= (xkbOverlayWireDesc *)wire;
olWire->name= ol->name;
olWire->nRows= ol->num_rows;
if (swap) {
register int n;
swapl(&olWire->name,n);
}
wire= (char *)&olWire[1];
for (r=0,row=ol->rows;r<ol->num_rows;r++,row++) {
unsigned int k;
XkbOverlayKeyPtr key;
xkbOverlayRowWireDesc * rowWire;
rowWire= (xkbOverlayRowWireDesc *)wire;
rowWire->rowUnder= row->row_under;
rowWire->nKeys= row->num_keys;
wire= (char *)&rowWire[1];
for (k=0,key=row->keys;k<row->num_keys;k++,key++) {
xkbOverlayKeyWireDesc * keyWire;
keyWire= (xkbOverlayKeyWireDesc *)wire;
memcpy(keyWire->over,key->over.name,XkbKeyNameLength);
memcpy(keyWire->under,key->under.name,XkbKeyNameLength);
wire= (char *)&keyWire[1];
}
}
return wire;
}
static int
XkbSizeGeomSections(XkbGeometryPtr geom)
{
register int i,size;
XkbSectionPtr section;
for (i=size=0,section=geom->sections;i<geom->num_sections;i++,section++) {
size+= SIZEOF(xkbSectionWireDesc);
if (section->rows) {
int r;
XkbRowPtr row;
for (r=0,row=section->rows;r<section->num_rows;row++,r++) {
size+= SIZEOF(xkbRowWireDesc);
size+= row->num_keys*SIZEOF(xkbKeyWireDesc);
}
}
if (section->doodads)
size+= XkbSizeGeomDoodads(section->num_doodads,section->doodads);
if (section->overlays) {
int o;
XkbOverlayPtr ol;
for (o=0,ol=section->overlays;o<section->num_overlays;o++,ol++) {
int r;
XkbOverlayRowPtr row;
size+= SIZEOF(xkbOverlayWireDesc);
for (r=0,row=ol->rows;r<ol->num_rows;r++,row++) {
size+= SIZEOF(xkbOverlayRowWireDesc);
size+= row->num_keys*SIZEOF(xkbOverlayKeyWireDesc);
}
}
}
}
return size;
}
static char *
XkbWriteGeomSections(char *wire,XkbGeometryPtr geom,Bool swap)
{
register int i;
XkbSectionPtr section;
xkbSectionWireDesc * sectionWire;
for (i=0,section=geom->sections;i<geom->num_sections;i++,section++) {
sectionWire= (xkbSectionWireDesc *)wire;
sectionWire->name= section->name;
sectionWire->top= section->top;
sectionWire->left= section->left;
sectionWire->width= section->width;
sectionWire->height= section->height;
sectionWire->angle= section->angle;
sectionWire->priority= section->priority;
sectionWire->nRows= section->num_rows;
sectionWire->nDoodads= section->num_doodads;
sectionWire->nOverlays= section->num_overlays;
sectionWire->pad= 0;
if (swap) {
register int n;
swapl(§ionWire->name,n);
swaps(§ionWire->top,n);
swaps(§ionWire->left,n);
swaps(§ionWire->width,n);
swaps(§ionWire->height,n);
swaps(§ionWire->angle,n);
}
wire= (char *)§ionWire[1];
if (section->rows) {
int r;
XkbRowPtr row;
xkbRowWireDesc * rowWire;
for (r=0,row=section->rows;r<section->num_rows;r++,row++) {
rowWire= (xkbRowWireDesc *)wire;
rowWire->top= row->top;
rowWire->left= row->left;
rowWire->nKeys= row->num_keys;
rowWire->vertical= row->vertical;
rowWire->pad= 0;
if (swap) {
register int n;
swaps(&rowWire->top,n);
swaps(&rowWire->left,n);
}
wire= (char *)&rowWire[1];
if (row->keys) {
int k;
XkbKeyPtr key;
xkbKeyWireDesc * keyWire;
keyWire= (xkbKeyWireDesc *)wire;
for (k=0,key=row->keys;k<row->num_keys;k++,key++) {
memcpy(keyWire[k].name,key->name.name,XkbKeyNameLength);
keyWire[k].gap= key->gap;
keyWire[k].shapeNdx= key->shape_ndx;
keyWire[k].colorNdx= key->color_ndx;
if (swap) {
register int n;
swaps(&keyWire[k].gap,n);
}
}
wire= (char *)&keyWire[row->num_keys];
}
}
}
if (section->doodads) {
wire= XkbWriteGeomDoodads(wire,
section->num_doodads,section->doodads,
swap);
}
if (section->overlays) {
register int o;
for (o=0;o<section->num_overlays;o++) {
wire= XkbWriteGeomOverlay(wire,§ion->overlays[o],swap);
}
}
}
return wire;
}
static Status
XkbComputeGetGeometryReplySize( XkbGeometryPtr geom,
xkbGetGeometryReply * rep,
Atom name)
{
int len;
if (geom!=NULL) {
len= XkbSizeCountedString(geom->label_font);
len+= XkbSizeGeomProperties(geom);
len+= XkbSizeGeomColors(geom);
len+= XkbSizeGeomShapes(geom);
len+= XkbSizeGeomSections(geom);
len+= XkbSizeGeomDoodads(geom->num_doodads,geom->doodads);
len+= XkbSizeGeomKeyAliases(geom);
rep->length= len/4;
rep->found= True;
rep->name= geom->name;
rep->widthMM= geom->width_mm;
rep->heightMM= geom->height_mm;
rep->nProperties= geom->num_properties;
rep->nColors= geom->num_colors;
rep->nShapes= geom->num_shapes;
rep->nSections= geom->num_sections;
rep->nDoodads= geom->num_doodads;
rep->nKeyAliases= geom->num_key_aliases;
rep->baseColorNdx= XkbGeomColorIndex(geom,geom->base_color);
rep->labelColorNdx= XkbGeomColorIndex(geom,geom->label_color);
}
else {
rep->length= 0;
rep->found= False;
rep->name= name;
rep->widthMM= rep->heightMM= 0;
rep->nProperties= rep->nColors= rep->nShapes= 0;
rep->nSections= rep->nDoodads= 0;
rep->nKeyAliases= 0;
rep->labelColorNdx= rep->baseColorNdx= 0;
}
return Success;
}
static int
XkbSendGeometry( ClientPtr client,
XkbGeometryPtr geom,
xkbGetGeometryReply * rep,
Bool freeGeom)
{
char *desc,*start;
int len;
if (geom!=NULL) {
len= rep->length*4;
start= desc= (char *)xalloc(len);
if (!start)
return BadAlloc;
desc= XkbWriteCountedString(desc,geom->label_font,client->swapped);
if ( rep->nProperties>0 )
desc = XkbWriteGeomProperties(desc,geom,client->swapped);
if ( rep->nColors>0 )
desc = XkbWriteGeomColors(desc,geom,client->swapped);
if ( rep->nShapes>0 )
desc = XkbWriteGeomShapes(desc,geom,client->swapped);
if ( rep->nSections>0 )
desc = XkbWriteGeomSections(desc,geom,client->swapped);
if ( rep->nDoodads>0 )
desc = XkbWriteGeomDoodads(desc,geom->num_doodads,geom->doodads,
client->swapped);
if ( rep->nKeyAliases>0 )
desc = XkbWriteGeomKeyAliases(desc,geom,client->swapped);
if ((desc-start)!=(len)) {
ErrorF("[xkb] BOGUS LENGTH in XkbSendGeometry, expected %d, got %ld\n",
len, (unsigned long)(desc-start));
}
}
else {
len= 0;
start= NULL;
}
if (client->swapped) {
register int n;
swaps(&rep->sequenceNumber,n);
swapl(&rep->length,n);
swapl(&rep->name,n);
swaps(&rep->widthMM,n);
swaps(&rep->heightMM,n);
swaps(&rep->nProperties,n);
swaps(&rep->nColors,n);
swaps(&rep->nShapes,n);
swaps(&rep->nSections,n);
swaps(&rep->nDoodads,n);
swaps(&rep->nKeyAliases,n);
}
WriteToClient(client, SIZEOF(xkbGetGeometryReply), (char *)rep);
if (len>0)
WriteToClient(client, len, start);
if (start!=NULL)
xfree((char *)start);
if (freeGeom)
XkbFreeGeometry(geom,XkbGeomAllMask,True);
return client->noClientException;
}
int
ProcXkbGetGeometry(ClientPtr client)
{
DeviceIntPtr dev;
xkbGetGeometryReply rep;
XkbGeometryPtr geom;
Bool shouldFree;
Status status;
REQUEST(xkbGetGeometryReq);
REQUEST_SIZE_MATCH(xkbGetGeometryReq);
if (!(client->xkbClientFlags&_XkbClientInitialized))
return BadAccess;
CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess);
CHK_ATOM_OR_NONE(stuff->name);
geom= XkbLookupNamedGeometry(dev,stuff->name,&shouldFree);
rep.type= X_Reply;
rep.deviceID= dev->id;
rep.sequenceNumber= client->sequence;
rep.length= 0;
status= XkbComputeGetGeometryReplySize(geom,&rep,stuff->name);
if (status!=Success)
return status;
else return XkbSendGeometry(client,geom,&rep,shouldFree);
}
static char *
_GetCountedString(char **wire_inout,Bool swap)
{
char * wire,*str;
CARD16 len,*plen;
wire= *wire_inout;
plen= (CARD16 *)wire;
if (swap) {
register int n;
swaps(plen,n);
}
len= *plen;
str= (char *)_XkbAlloc(len+1);
if (str) {
memcpy(str,&wire[2],len);
str[len]= '\0';
}
wire+= XkbPaddedSize(len+2);
*wire_inout= wire;
return str;
}
static Status
_CheckSetDoodad( char ** wire_inout,
XkbGeometryPtr geom,
XkbSectionPtr section,
ClientPtr client)
{
char * wire;
xkbDoodadWireDesc * dWire;
XkbDoodadPtr doodad;
dWire= (xkbDoodadWireDesc *)(*wire_inout);
wire= (char *)&dWire[1];
if (client->swapped) {
register int n;
swapl(&dWire->any.name,n);
swaps(&dWire->any.top,n);
swaps(&dWire->any.left,n);
swaps(&dWire->any.angle,n);
}
CHK_ATOM_ONLY(dWire->any.name);
doodad= XkbAddGeomDoodad(geom,section,dWire->any.name);
if (!doodad)
return BadAlloc;
doodad->any.type= dWire->any.type;
doodad->any.priority= dWire->any.priority;
doodad->any.top= dWire->any.top;
doodad->any.left= dWire->any.left;
doodad->any.angle= dWire->any.angle;
switch (doodad->any.type) {
case XkbOutlineDoodad:
case XkbSolidDoodad:
if (dWire->shape.colorNdx>=geom->num_colors) {
client->errorValue= _XkbErrCode3(0x40,geom->num_colors,
dWire->shape.colorNdx);
return BadMatch;
}
if (dWire->shape.shapeNdx>=geom->num_shapes) {
client->errorValue= _XkbErrCode3(0x41,geom->num_shapes,
dWire->shape.shapeNdx);
return BadMatch;
}
doodad->shape.color_ndx= dWire->shape.colorNdx;
doodad->shape.shape_ndx= dWire->shape.shapeNdx;
break;
case XkbTextDoodad:
if (dWire->text.colorNdx>=geom->num_colors) {
client->errorValue= _XkbErrCode3(0x42,geom->num_colors,
dWire->text.colorNdx);
return BadMatch;
}
if (client->swapped) {
register int n;
swaps(&dWire->text.width,n);
swaps(&dWire->text.height,n);
}
doodad->text.width= dWire->text.width;
doodad->text.height= dWire->text.height;
doodad->text.color_ndx= dWire->text.colorNdx;
doodad->text.text= _GetCountedString(&wire,client->swapped);
doodad->text.font= _GetCountedString(&wire,client->swapped);
break;
case XkbIndicatorDoodad:
if (dWire->indicator.onColorNdx>=geom->num_colors) {
client->errorValue= _XkbErrCode3(0x43,geom->num_colors,
dWire->indicator.onColorNdx);
return BadMatch;
}
if (dWire->indicator.offColorNdx>=geom->num_colors) {
client->errorValue= _XkbErrCode3(0x44,geom->num_colors,
dWire->indicator.offColorNdx);
return BadMatch;
}
if (dWire->indicator.shapeNdx>=geom->num_shapes) {
client->errorValue= _XkbErrCode3(0x45,geom->num_shapes,
dWire->indicator.shapeNdx);
return BadMatch;
}
doodad->indicator.shape_ndx= dWire->indicator.shapeNdx;
doodad->indicator.on_color_ndx= dWire->indicator.onColorNdx;
doodad->indicator.off_color_ndx= dWire->indicator.offColorNdx;
break;
case XkbLogoDoodad:
if (dWire->logo.colorNdx>=geom->num_colors) {
client->errorValue= _XkbErrCode3(0x46,geom->num_colors,
dWire->logo.colorNdx);
return BadMatch;
}
if (dWire->logo.shapeNdx>=geom->num_shapes) {
client->errorValue= _XkbErrCode3(0x47,geom->num_shapes,
dWire->logo.shapeNdx);
return BadMatch;
}
doodad->logo.color_ndx= dWire->logo.colorNdx;
doodad->logo.shape_ndx= dWire->logo.shapeNdx;
doodad->logo.logo_name= _GetCountedString(&wire,client->swapped);
break;
default:
client->errorValue= _XkbErrCode2(0x4F,dWire->any.type);
return BadValue;
}
*wire_inout= wire;
return Success;
}
static Status
_CheckSetOverlay( char ** wire_inout,
XkbGeometryPtr geom,
XkbSectionPtr section,
ClientPtr client)
{
register int r;
char * wire;
XkbOverlayPtr ol;
xkbOverlayWireDesc * olWire;
xkbOverlayRowWireDesc * rWire;
wire= *wire_inout;
olWire= (xkbOverlayWireDesc *)wire;
if (client->swapped) {
register int n;
swapl(&olWire->name,n);
}
CHK_ATOM_ONLY(olWire->name);
ol= XkbAddGeomOverlay(section,olWire->name,olWire->nRows);
rWire= (xkbOverlayRowWireDesc *)&olWire[1];
for (r=0;r<olWire->nRows;r++) {
register int k;
xkbOverlayKeyWireDesc * kWire;
XkbOverlayRowPtr row;
if (rWire->rowUnder>section->num_rows) {
client->errorValue= _XkbErrCode4(0x20,r,section->num_rows,
rWire->rowUnder);
return BadMatch;
}
row= XkbAddGeomOverlayRow(ol,rWire->rowUnder,rWire->nKeys);
kWire= (xkbOverlayKeyWireDesc *)&rWire[1];
for (k=0;k<rWire->nKeys;k++,kWire++) {
if (XkbAddGeomOverlayKey(ol,row,
(char *)kWire->over,(char *)kWire->under)==NULL) {
client->errorValue= _XkbErrCode3(0x21,r,k);
return BadMatch;
}
}
rWire= (xkbOverlayRowWireDesc *)kWire;
}
olWire= (xkbOverlayWireDesc *)rWire;
wire= (char *)olWire;
*wire_inout= wire;
return Success;
}
static Status
_CheckSetSections( XkbGeometryPtr geom,
xkbSetGeometryReq * req,
char ** wire_inout,
ClientPtr client)
{
Status status;
register int s;
char * wire;
xkbSectionWireDesc * sWire;
XkbSectionPtr section;
wire= *wire_inout;
if (req->nSections<1)
return Success;
sWire= (xkbSectionWireDesc *)wire;
for (s=0;s<req->nSections;s++) {
register int r;
xkbRowWireDesc * rWire;
if (client->swapped) {
register int n;
swapl(&sWire->name,n);
swaps(&sWire->top,n);
swaps(&sWire->left,n);
swaps(&sWire->width,n);
swaps(&sWire->height,n);
swaps(&sWire->angle,n);
}
CHK_ATOM_ONLY(sWire->name);
section= XkbAddGeomSection(geom,sWire->name,sWire->nRows,
sWire->nDoodads,sWire->nOverlays);
if (!section)
return BadAlloc;
section->priority= sWire->priority;
section->top= sWire->top;
section->left= sWire->left;
section->width= sWire->width;
section->height= sWire->height;
section->angle= sWire->angle;
rWire= (xkbRowWireDesc *)&sWire[1];
for (r=0;r<sWire->nRows;r++) {
register int k;
XkbRowPtr row;
xkbKeyWireDesc * kWire;
if (client->swapped) {
register int n;
swaps(&rWire->top,n);
swaps(&rWire->left,n);
}
row= XkbAddGeomRow(section,rWire->nKeys);
if (!row)
return BadAlloc;
row->top= rWire->top;
row->left= rWire->left;
row->vertical= rWire->vertical;
kWire= (xkbKeyWireDesc *)&rWire[1];
for (k=0;k<rWire->nKeys;k++) {
XkbKeyPtr key;
key= XkbAddGeomKey(row);
if (!key)
return BadAlloc;
memcpy(key->name.name,kWire[k].name,XkbKeyNameLength);
key->gap= kWire[k].gap;
key->shape_ndx= kWire[k].shapeNdx;
key->color_ndx= kWire[k].colorNdx;
if (key->shape_ndx>=geom->num_shapes) {
client->errorValue= _XkbErrCode3(0x10,key->shape_ndx,
geom->num_shapes);
return BadMatch;
}
if (key->color_ndx>=geom->num_colors) {
client->errorValue= _XkbErrCode3(0x11,key->color_ndx,
geom->num_colors);
return BadMatch;
}
}
rWire= (xkbRowWireDesc *)&kWire[rWire->nKeys];
}
wire= (char *)rWire;
if (sWire->nDoodads>0) {
register int d;
for (d=0;d<sWire->nDoodads;d++) {
status=_CheckSetDoodad(&wire,geom,section,client);
if (status!=Success)
return status;
}
}
if (sWire->nOverlays>0) {
register int o;
for (o=0;o<sWire->nOverlays;o++) {
status= _CheckSetOverlay(&wire,geom,section,client);
if (status!=Success)
return status;
}
}
sWire= (xkbSectionWireDesc *)wire;
}
wire= (char *)sWire;
*wire_inout= wire;
return Success;
}
static Status
_CheckSetShapes( XkbGeometryPtr geom,
xkbSetGeometryReq * req,
char ** wire_inout,
ClientPtr client)
{
register int i;
char * wire;
wire= *wire_inout;
if (req->nShapes<1) {
client->errorValue= _XkbErrCode2(0x06,req->nShapes);
return BadValue;
}
else {
xkbShapeWireDesc * shapeWire;
XkbShapePtr shape;
register int o;
shapeWire= (xkbShapeWireDesc *)wire;
for (i=0;i<req->nShapes;i++) {
xkbOutlineWireDesc * olWire;
XkbOutlinePtr ol;
shape= XkbAddGeomShape(geom,shapeWire->name,shapeWire->nOutlines);
if (!shape)
return BadAlloc;
olWire= (xkbOutlineWireDesc *)(&shapeWire[1]);
for (o=0;o<shapeWire->nOutlines;o++) {
register int p;
XkbPointPtr pt;
xkbPointWireDesc * ptWire;
ol= XkbAddGeomOutline(shape,olWire->nPoints);
if (!ol)
return BadAlloc;
ol->corner_radius= olWire->cornerRadius;
ptWire= (xkbPointWireDesc *)&olWire[1];
for (p=0,pt=ol->points;p<olWire->nPoints;p++,pt++) {
pt->x= ptWire[p].x;
pt->y= ptWire[p].y;
if (client->swapped) {
register int n;
swaps(&pt->x,n);
swaps(&pt->y,n);
}
}
ol->num_points= olWire->nPoints;
olWire= (xkbOutlineWireDesc *)(&ptWire[olWire->nPoints]);
}
if (shapeWire->primaryNdx!=XkbNoShape)
shape->primary= &shape->outlines[shapeWire->primaryNdx];
if (shapeWire->approxNdx!=XkbNoShape)
shape->approx= &shape->outlines[shapeWire->approxNdx];
shapeWire= (xkbShapeWireDesc *)olWire;
}
wire= (char *)shapeWire;
}
if (geom->num_shapes!=req->nShapes) {
client->errorValue= _XkbErrCode3(0x07,geom->num_shapes,req->nShapes);
return BadMatch;
}
*wire_inout= wire;
return Success;
}
static Status
_CheckSetGeom( XkbGeometryPtr geom,
xkbSetGeometryReq * req,
ClientPtr client)
{
register int i;
Status status;
char * wire;
wire= (char *)&req[1];
geom->label_font= _GetCountedString(&wire,client->swapped);
for (i=0;i<req->nProperties;i++) {
char *name,*val;
name= _GetCountedString(&wire,client->swapped);
if (!name)
return BadAlloc;
val= _GetCountedString(&wire,client->swapped);
if (!val) {
xfree(name);
return BadAlloc;
}
if (XkbAddGeomProperty(geom,name,val)==NULL) {
xfree(name);
xfree(val);
return BadAlloc;
}
xfree(name);
xfree(val);
}
if (req->nColors<2) {
client->errorValue= _XkbErrCode3(0x01,2,req->nColors);
return BadValue;
}
if (req->baseColorNdx>req->nColors) {
client->errorValue=_XkbErrCode3(0x03,req->nColors,req->baseColorNdx);
return BadMatch;
}
if (req->labelColorNdx>req->nColors) {
client->errorValue= _XkbErrCode3(0x03,req->nColors,req->labelColorNdx);
return BadMatch;
}
if (req->labelColorNdx==req->baseColorNdx) {
client->errorValue= _XkbErrCode3(0x04,req->baseColorNdx,
req->labelColorNdx);
return BadMatch;
}
for (i=0;i<req->nColors;i++) {
char *name;
name= _GetCountedString(&wire,client->swapped);
if (!name)
return BadAlloc;
if (!XkbAddGeomColor(geom,name,geom->num_colors)) {
xfree(name);
return BadAlloc;
}
xfree(name);
}
if (req->nColors!=geom->num_colors) {
client->errorValue= _XkbErrCode3(0x05,req->nColors,geom->num_colors);
return BadMatch;
}
geom->label_color= &geom->colors[req->labelColorNdx];
geom->base_color= &geom->colors[req->baseColorNdx];
if ((status=_CheckSetShapes(geom,req,&wire,client))!=Success)
return status;
if ((status=_CheckSetSections(geom,req,&wire,client))!=Success)
return status;
for (i=0;i<req->nDoodads;i++) {
status=_CheckSetDoodad(&wire,geom,NULL,client);
if (status!=Success)
return status;
}
for (i=0;i<req->nKeyAliases;i++) {
if (XkbAddGeomKeyAlias(geom,&wire[XkbKeyNameLength],wire)==NULL)
return BadAlloc;
wire+= 2*XkbKeyNameLength;
}
return Success;
}
static int
_XkbSetGeometry(ClientPtr client, DeviceIntPtr dev, xkbSetGeometryReq *stuff)
{
XkbDescPtr xkb;
Bool new_name;
xkbNewKeyboardNotify nkn;
XkbGeometryPtr geom,old;
XkbGeometrySizesRec sizes;
Status status;
xkb= dev->key->xkbInfo->desc;
old= xkb->geom;
xkb->geom= NULL;
sizes.which= XkbGeomAllMask;
sizes.num_properties= stuff->nProperties;
sizes.num_colors= stuff->nColors;
sizes.num_shapes= stuff->nShapes;
sizes.num_sections= stuff->nSections;
sizes.num_doodads= stuff->nDoodads;
sizes.num_key_aliases= stuff->nKeyAliases;
if ((status= XkbAllocGeometry(xkb,&sizes))!=Success) {
xkb->geom= old;
return status;
}
geom= xkb->geom;
geom->name= stuff->name;
geom->width_mm= stuff->widthMM;
geom->height_mm= stuff->heightMM;
if ((status= _CheckSetGeom(geom,stuff,client))!=Success) {
XkbFreeGeometry(geom,XkbGeomAllMask,True);
xkb->geom= old;
return status;
}
new_name= (xkb->names->geometry!=geom->name);
xkb->names->geometry= geom->name;
if (old)
XkbFreeGeometry(old,XkbGeomAllMask,True);
if (new_name) {
xkbNamesNotify nn;
bzero(&nn,sizeof(xkbNamesNotify));
nn.changed= XkbGeometryNameMask;
XkbSendNamesNotify(dev,&nn);
}
nkn.deviceID= nkn.oldDeviceID= dev->id;
nkn.minKeyCode= nkn.oldMinKeyCode= xkb->min_key_code;
nkn.maxKeyCode= nkn.oldMaxKeyCode= xkb->max_key_code;
nkn.requestMajor= XkbReqCode;
nkn.requestMinor= X_kbSetGeometry;
nkn.changed= XkbNKN_GeometryMask;
XkbSendNewKeyboardNotify(dev,&nkn);
return Success;
}
int
ProcXkbSetGeometry(ClientPtr client)
{
DeviceIntPtr dev;
int rc;
REQUEST(xkbSetGeometryReq);
REQUEST_AT_LEAST_SIZE(xkbSetGeometryReq);
if (!(client->xkbClientFlags&_XkbClientInitialized))
return BadAccess;
CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess);
CHK_ATOM_OR_NONE(stuff->name);
rc = _XkbSetGeometry(client, dev, stuff);
if (rc != Success)
return rc;
if (stuff->deviceSpec == XkbUseCoreKbd)
{
DeviceIntPtr other;
for (other = inputInfo.devices; other; other = other->next)
{
if ((other != dev) && other->key && !other->isMaster && (other->u.master == dev))
{
rc = XaceHook(XACE_DEVICE_ACCESS, client, other, DixManageAccess);
if (rc == Success)
_XkbSetGeometry(client, other, stuff);
}
}
}
return Success;
}
int
ProcXkbPerClientFlags(ClientPtr client)
{
DeviceIntPtr dev;
xkbPerClientFlagsReply rep;
XkbInterestPtr interest;
Mask access_mode = DixGetAttrAccess | DixSetAttrAccess;
REQUEST(xkbPerClientFlagsReq);
REQUEST_SIZE_MATCH(xkbPerClientFlagsReq);
if (!(client->xkbClientFlags&_XkbClientInitialized))
return BadAccess;
CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, access_mode);
CHK_MASK_LEGAL(0x01,stuff->change,XkbPCF_AllFlagsMask);
CHK_MASK_MATCH(0x02,stuff->change,stuff->value);
interest = XkbFindClientResource((DevicePtr)dev,client);
rep.type= X_Reply;
rep.length = 0;
rep.sequenceNumber = client->sequence;
if (stuff->change) {
client->xkbClientFlags&= ~stuff->change;
client->xkbClientFlags|= stuff->value;
}
if (stuff->change&XkbPCF_AutoResetControlsMask) {
Bool want;
want= stuff->value&XkbPCF_AutoResetControlsMask;
if (interest && !want) {
interest->autoCtrls= interest->autoCtrlValues= 0;
}
else if (want && (!interest)) {
XID id = FakeClientID(client->index);
AddResource(id,RT_XKBCLIENT,dev);
interest= XkbAddClientResource((DevicePtr)dev,client,id);
if (!interest)
return BadAlloc;
}
if (interest && want ) {
register unsigned affect;
affect= stuff->ctrlsToChange;
CHK_MASK_LEGAL(0x03,affect,XkbAllBooleanCtrlsMask);
CHK_MASK_MATCH(0x04,affect,stuff->autoCtrls);
CHK_MASK_MATCH(0x05,stuff->autoCtrls,stuff->autoCtrlValues);
interest->autoCtrls&= ~affect;
interest->autoCtrlValues&= ~affect;
interest->autoCtrls|= stuff->autoCtrls&affect;
interest->autoCtrlValues|= stuff->autoCtrlValues&affect;
}
}
rep.supported = XkbPCF_AllFlagsMask;
rep.value= client->xkbClientFlags&XkbPCF_AllFlagsMask;
if (interest) {
rep.autoCtrls= interest->autoCtrls;
rep.autoCtrlValues= interest->autoCtrlValues;
}
else {
rep.autoCtrls= rep.autoCtrlValues= 0;
}
if ( client->swapped ) {
register int n;
swaps(&rep.sequenceNumber, n);
swapl(&rep.supported,n);
swapl(&rep.value,n);
swapl(&rep.autoCtrls,n);
swapl(&rep.autoCtrlValues,n);
}
WriteToClient(client,SIZEOF(xkbPerClientFlagsReply), (char *)&rep);
return client->noClientException;
}
static unsigned char componentSpecLegal[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0xa7, 0xff, 0x87,
0xfe, 0xff, 0xff, 0x87, 0xfe, 0xff, 0xff, 0x07,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0x7f, 0xff
};
static unsigned char componentExprLegal[] = {
0x00, 0x00, 0x00, 0x00, 0x20, 0xaf, 0xff, 0x87,
0xfe, 0xff, 0xff, 0x87, 0xfe, 0xff, 0xff, 0x17,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0x7f, 0xff
};
static char *
GetComponentSpec(unsigned char **pWire,Bool allowExpr,int *errRtrn)
{
int len;
register int i;
unsigned char *wire,*str,*tmp,*legal;
if (allowExpr) legal= &componentExprLegal[0];
else legal= &componentSpecLegal[0];
wire= *pWire;
len= (*(unsigned char *)wire++);
if (len>0) {
str= (unsigned char *)_XkbCalloc(1, len+1);
if (str) {
tmp= str;
for (i=0;i<len;i++) {
if (legal[(*wire)/8]&(1<<((*wire)%8)))
*tmp++= *wire++;
else wire++;
}
if (tmp!=str)
*tmp++= '\0';
else {
_XkbFree(str);
str= NULL;
}
}
else {
*errRtrn= BadAlloc;
}
}
else {
str= NULL;
}
*pWire= wire;
return (char *)str;
}
int
ProcXkbListComponents(ClientPtr client)
{
DeviceIntPtr dev;
xkbListComponentsReply rep;
unsigned len;
int status;
unsigned char * str;
XkbSrvListInfoRec list;
REQUEST(xkbListComponentsReq);
REQUEST_AT_LEAST_SIZE(xkbListComponentsReq);
if (!(client->xkbClientFlags&_XkbClientInitialized))
return BadAccess;
CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess);
status= Success;
str= (unsigned char *)&stuff[1];
bzero(&list,sizeof(XkbSrvListInfoRec));
list.maxRtrn= stuff->maxNames;
list.pattern[_XkbListKeymaps]= GetComponentSpec(&str,False,&status);
list.pattern[_XkbListKeycodes]= GetComponentSpec(&str,False,&status);
list.pattern[_XkbListTypes]= GetComponentSpec(&str,False,&status);
list.pattern[_XkbListCompat]= GetComponentSpec(&str,False,&status);
list.pattern[_XkbListSymbols]= GetComponentSpec(&str,False,&status);
list.pattern[_XkbListGeometry]= GetComponentSpec(&str,False,&status);
if (status!=Success)
return status;
len= str-((unsigned char *)stuff);
if ((XkbPaddedSize(len)/4)!=stuff->length)
return BadLength;
if ((status=XkbDDXList(dev,&list,client))!=Success) {
if (list.pool) {
_XkbFree(list.pool);
list.pool= NULL;
}
return status;
}
bzero(&rep,sizeof(xkbListComponentsReply));
rep.type= X_Reply;
rep.deviceID = dev->id;
rep.sequenceNumber = client->sequence;
rep.length = XkbPaddedSize(list.nPool)/4;
rep.nKeymaps = list.nFound[_XkbListKeymaps];
rep.nKeycodes = list.nFound[_XkbListKeycodes];
rep.nTypes = list.nFound[_XkbListTypes];
rep.nCompatMaps = list.nFound[_XkbListCompat];
rep.nSymbols = list.nFound[_XkbListSymbols];
rep.nGeometries = list.nFound[_XkbListGeometry];
rep.extra= 0;
if (list.nTotal>list.maxRtrn)
rep.extra = (list.nTotal-list.maxRtrn);
if (client->swapped) {
register int n;
swaps(&rep.sequenceNumber,n);
swapl(&rep.length,n);
swaps(&rep.nKeymaps,n);
swaps(&rep.nKeycodes,n);
swaps(&rep.nTypes,n);
swaps(&rep.nCompatMaps,n);
swaps(&rep.nSymbols,n);
swaps(&rep.nGeometries,n);
swaps(&rep.extra,n);
}
WriteToClient(client,SIZEOF(xkbListComponentsReply),(char *)&rep);
if (list.nPool && list.pool) {
WriteToClient(client,XkbPaddedSize(list.nPool), (char *)list.pool);
_XkbFree(list.pool);
list.pool= NULL;
}
return client->noClientException;
}
int
ProcXkbGetKbdByName(ClientPtr client)
{
DeviceIntPtr dev;
DeviceIntPtr tmpd;
xkbGetKbdByNameReply rep;
xkbGetMapReply mrep;
xkbGetCompatMapReply crep;
xkbGetIndicatorMapReply irep;
xkbGetNamesReply nrep;
xkbGetGeometryReply grep;
XkbComponentNamesRec names;
XkbDescPtr xkb, new;
unsigned char * str;
char mapFile[PATH_MAX];
unsigned len;
unsigned fwant,fneed,reported;
int status;
Bool geom_changed;
XkbSrvLedInfoPtr old_sli;
XkbSrvLedInfoPtr sli;
Mask access_mode = DixGetAttrAccess | DixManageAccess;
REQUEST(xkbGetKbdByNameReq);
REQUEST_AT_LEAST_SIZE(xkbGetKbdByNameReq);
if (!(client->xkbClientFlags&_XkbClientInitialized))
return BadAccess;
CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, access_mode);
xkb = dev->key->xkbInfo->desc;
status= Success;
str= (unsigned char *)&stuff[1];
names.keymap= GetComponentSpec(&str,True,&status);
names.keycodes= GetComponentSpec(&str,True,&status);
names.types= GetComponentSpec(&str,True,&status);
names.compat= GetComponentSpec(&str,True,&status);
names.symbols= GetComponentSpec(&str,True,&status);
names.geometry= GetComponentSpec(&str,True,&status);
if (status!=Success)
return status;
len= str-((unsigned char *)stuff);
if ((XkbPaddedSize(len)/4)!=stuff->length)
return BadLength;
CHK_MASK_LEGAL(0x01,stuff->want,XkbGBN_AllComponentsMask);
CHK_MASK_LEGAL(0x02,stuff->need,XkbGBN_AllComponentsMask);
if (stuff->load)
fwant= XkbGBN_AllComponentsMask;
else fwant= stuff->want|stuff->need;
if ((!names.compat)&&
(fwant&(XkbGBN_CompatMapMask|XkbGBN_IndicatorMapMask))) {
names.compat= _XkbDupString("%");
}
if ((!names.types)&&(fwant&(XkbGBN_TypesMask))) {
names.types= _XkbDupString("%");
}
if ((!names.symbols)&&(fwant&XkbGBN_SymbolsMask)) {
names.symbols= _XkbDupString("%");
}
geom_changed= ((names.geometry!=NULL)&&(strcmp(names.geometry,"%")!=0));
if ((!names.geometry)&&(fwant&XkbGBN_GeometryMask)) {
names.geometry= _XkbDupString("%");
geom_changed= False;
}
bzero(mapFile,PATH_MAX);
rep.type= X_Reply;
rep.deviceID = dev->id;
rep.sequenceNumber = client->sequence;
rep.length = 0;
rep.minKeyCode = xkb->min_key_code;
rep.maxKeyCode = xkb->max_key_code;
rep.loaded= False;
fwant= XkbConvertGetByNameComponents(True,stuff->want)|XkmVirtualModsMask;
fneed= XkbConvertGetByNameComponents(True,stuff->need);
rep.reported= XkbConvertGetByNameComponents(False,fwant|fneed);
if (stuff->load) {
fneed|= XkmKeymapRequired;
fwant|= XkmKeymapLegal;
}
if ((fwant|fneed)&XkmSymbolsMask) {
fneed|= XkmKeyNamesIndex|XkmTypesIndex;
fwant|= XkmIndicatorsIndex;
}
rep.found = XkbDDXLoadKeymapByNames(dev,&names,fwant,fneed,&new,
mapFile,PATH_MAX);
rep.newKeyboard= False;
rep.pad1= rep.pad2= rep.pad3= rep.pad4= 0;
stuff->want|= stuff->need;
if (new==NULL)
rep.reported= 0;
else {
if (stuff->load)
rep.loaded= True;
if (stuff->load ||
((rep.reported&XkbGBN_SymbolsMask) && (new->compat))) {
XkbChangesRec changes;
bzero(&changes,sizeof(changes));
XkbUpdateDescActions(new,
new->min_key_code,XkbNumKeys(new),
&changes);
}
if (new->map==NULL)
rep.reported&= ~(XkbGBN_SymbolsMask|XkbGBN_TypesMask);
else if (rep.reported&(XkbGBN_SymbolsMask|XkbGBN_TypesMask)) {
mrep.type= X_Reply;
mrep.deviceID = dev->id;
mrep.sequenceNumber= client->sequence;
mrep.length = ((SIZEOF(xkbGetMapReply)-SIZEOF(xGenericReply))>>2);
mrep.minKeyCode = new->min_key_code;
mrep.maxKeyCode = new->max_key_code;
mrep.present = 0;
mrep.totalSyms = mrep.totalActs =
mrep.totalKeyBehaviors= mrep.totalKeyExplicit=
mrep.totalModMapKeys= mrep.totalVModMapKeys= 0;
if (rep.reported&(XkbGBN_TypesMask|XkbGBN_ClientSymbolsMask)) {
mrep.present|= XkbKeyTypesMask;
mrep.firstType = 0;
mrep.nTypes = mrep.totalTypes= new->map->num_types;
}
else {
mrep.firstType = mrep.nTypes= 0;
mrep.totalTypes= 0;
}
if (rep.reported&XkbGBN_ClientSymbolsMask) {
mrep.present|= (XkbKeySymsMask|XkbModifierMapMask);
mrep.firstKeySym = mrep.firstModMapKey= new->min_key_code;
mrep.nKeySyms = mrep.nModMapKeys= XkbNumKeys(new);
}
else {
mrep.firstKeySym= mrep.firstModMapKey= 0;
mrep.nKeySyms= mrep.nModMapKeys= 0;
}
if (rep.reported&XkbGBN_ServerSymbolsMask) {
mrep.present|= XkbAllServerInfoMask;
mrep.virtualMods= ~0;
mrep.firstKeyAct = mrep.firstKeyBehavior =
mrep.firstKeyExplicit = new->min_key_code;
mrep.nKeyActs = mrep.nKeyBehaviors =
mrep.nKeyExplicit = XkbNumKeys(new);
mrep.firstVModMapKey= new->min_key_code;
mrep.nVModMapKeys= XkbNumKeys(new);
}
else {
mrep.virtualMods= 0;
mrep.firstKeyAct= mrep.firstKeyBehavior=
mrep.firstKeyExplicit = 0;
mrep.nKeyActs= mrep.nKeyBehaviors= mrep.nKeyExplicit= 0;
}
XkbComputeGetMapReplySize(new,&mrep);
rep.length+= SIZEOF(xGenericReply)/4+mrep.length;
}
if (new->compat==NULL)
rep.reported&= ~XkbGBN_CompatMapMask;
else if (rep.reported&XkbGBN_CompatMapMask) {
crep.type= X_Reply;
crep.deviceID= dev->id;
crep.sequenceNumber= client->sequence;
crep.length= 0;
crep.groups= XkbAllGroupsMask;
crep.firstSI= 0;
crep.nSI= crep.nTotalSI= new->compat->num_si;
XkbComputeGetCompatMapReplySize(new->compat,&crep);
rep.length+= SIZEOF(xGenericReply)/4+crep.length;
}
if (new->indicators==NULL)
rep.reported&= ~XkbGBN_IndicatorMapMask;
else if (rep.reported&XkbGBN_IndicatorMapMask) {
irep.type= X_Reply;
irep.deviceID= dev->id;
irep.sequenceNumber= client->sequence;
irep.length= 0;
irep.which= XkbAllIndicatorsMask;
XkbComputeGetIndicatorMapReplySize(new->indicators,&irep);
rep.length+= SIZEOF(xGenericReply)/4+irep.length;
}
if (new->names==NULL)
rep.reported&= ~(XkbGBN_OtherNamesMask|XkbGBN_KeyNamesMask);
else if (rep.reported&(XkbGBN_OtherNamesMask|XkbGBN_KeyNamesMask)) {
nrep.type= X_Reply;
nrep.deviceID= dev->id;
nrep.sequenceNumber= client->sequence;
nrep.length= 0;
nrep.minKeyCode= new->min_key_code;
nrep.maxKeyCode= new->max_key_code;
if (rep.reported&XkbGBN_OtherNamesMask) {
nrep.which= XkbAllNamesMask;
if (new->map!=NULL)
nrep.nTypes= new->map->num_types;
else nrep.nTypes= 0;
nrep.nKTLevels= 0;
nrep.groupNames= XkbAllGroupsMask;
nrep.virtualMods= XkbAllVirtualModsMask;
nrep.indicators= XkbAllIndicatorsMask;
nrep.nRadioGroups= new->names->num_rg;
}
else {
nrep.which= 0;
nrep.nTypes= 0;
nrep.nKTLevels= 0;
nrep.groupNames= 0;
nrep.virtualMods= 0;
nrep.indicators= 0;
nrep.nRadioGroups= 0;
}
if (rep.reported&XkbGBN_KeyNamesMask) {
nrep.which|= XkbKeyNamesMask;
nrep.firstKey= new->min_key_code;
nrep.nKeys= XkbNumKeys(new);
nrep.nKeyAliases= new->names->num_key_aliases;
if (nrep.nKeyAliases)
nrep.which|= XkbKeyAliasesMask;
}
else {
nrep.which&= ~(XkbKeyNamesMask|XkbKeyAliasesMask);
nrep.firstKey= nrep.nKeys= 0;
nrep.nKeyAliases= 0;
}
XkbComputeGetNamesReplySize(new,&nrep);
rep.length+= SIZEOF(xGenericReply)/4+nrep.length;
}
if (new->geom==NULL)
rep.reported&= ~XkbGBN_GeometryMask;
else if (rep.reported&XkbGBN_GeometryMask) {
grep.type= X_Reply;
grep.deviceID= dev->id;
grep.sequenceNumber= client->sequence;
grep.length= 0;
grep.found= True;
grep.pad= 0;
grep.widthMM= grep.heightMM= 0;
grep.nProperties= grep.nColors= grep.nShapes= 0;
grep.nSections= grep.nDoodads= 0;
grep.baseColorNdx= grep.labelColorNdx= 0;
XkbComputeGetGeometryReplySize(new->geom,&grep,None);
rep.length+= SIZEOF(xGenericReply)/4+grep.length;
}
}
reported= rep.reported;
if ( client->swapped ) {
register int n;
swaps(&rep.sequenceNumber,n);
swapl(&rep.length,n);
swaps(&rep.found,n);
swaps(&rep.reported,n);
}
WriteToClient(client,SIZEOF(xkbGetKbdByNameReply), (char *)&rep);
if (reported&(XkbGBN_SymbolsMask|XkbGBN_TypesMask))
XkbSendMap(client,new,&mrep);
if (reported&XkbGBN_CompatMapMask)
XkbSendCompatMap(client,new->compat,&crep);
if (reported&XkbGBN_IndicatorMapMask)
XkbSendIndicatorMap(client,new->indicators,&irep);
if (reported&(XkbGBN_KeyNamesMask|XkbGBN_OtherNamesMask))
XkbSendNames(client,new,&nrep);
if (reported&XkbGBN_GeometryMask)
XkbSendGeometry(client,new->geom,&grep,False);
if (rep.loaded) {
XkbDescPtr old_xkb;
xkbNewKeyboardNotify nkn;
int i,nG,nTG;
old_xkb= xkb;
xkb= new;
dev->key->xkbInfo->desc= xkb;
new= old_xkb;
*xkb->ctrls= *old_xkb->ctrls;
for (nG=nTG=0,i=xkb->min_key_code;i<=xkb->max_key_code;i++) {
nG= XkbKeyNumGroups(xkb,i);
if (nG>=XkbNumKbdGroups) {
nTG= XkbNumKbdGroups;
break;
}
if (nG>nTG) {
nTG= nG;
}
}
xkb->ctrls->num_groups= nTG;
for (tmpd = inputInfo.devices; tmpd; tmpd = tmpd->next) {
if (tmpd == dev ||
(dev->id == inputInfo.keyboard->id && tmpd->key &&
tmpd->coreEvents)) {
memcpy(tmpd->key->modifierMap, xkb->map->modmap,
xkb->max_key_code + 1);
if (tmpd != dev)
XkbCopyKeymap(dev->key->xkbInfo->desc,
tmpd->key->xkbInfo->desc, True);
XkbUpdateCoreDescription(tmpd, True);
if (tmpd->kbdfeed && tmpd->kbdfeed->xkb_sli) {
old_sli = tmpd->kbdfeed->xkb_sli;
tmpd->kbdfeed->xkb_sli = NULL;
sli = XkbAllocSrvLedInfo(tmpd, tmpd->kbdfeed, NULL, 0);
if (sli) {
sli->explicitState = old_sli->explicitState;
sli->effectiveState = old_sli->effectiveState;
}
tmpd->kbdfeed->xkb_sli = sli;
XkbFreeSrvLedInfo(old_sli);
}
}
}
nkn.deviceID= nkn.oldDeviceID= dev->id;
nkn.minKeyCode= new->min_key_code;
nkn.maxKeyCode= new->max_key_code;
nkn.oldMinKeyCode= xkb->min_key_code;
nkn.oldMaxKeyCode= xkb->max_key_code;
nkn.requestMajor= XkbReqCode;
nkn.requestMinor= X_kbGetKbdByName;
nkn.changed= XkbNKN_KeycodesMask;
if (geom_changed)
nkn.changed|= XkbNKN_GeometryMask;
XkbSendNewKeyboardNotify(dev,&nkn);
}
if ((new!=NULL)&&(new!=xkb)) {
XkbFreeKeyboard(new,XkbAllComponentsMask,True);
new= NULL;
}
if (names.keymap) { _XkbFree(names.keymap); names.keymap= NULL; }
if (names.keycodes) { _XkbFree(names.keycodes); names.keycodes= NULL; }
if (names.types) { _XkbFree(names.types); names.types= NULL; }
if (names.compat) { _XkbFree(names.compat); names.compat= NULL; }
if (names.symbols) { _XkbFree(names.symbols); names.symbols= NULL; }
if (names.geometry) { _XkbFree(names.geometry); names.geometry= NULL; }
return client->noClientException;
}
static int
ComputeDeviceLedInfoSize( DeviceIntPtr dev,
unsigned int what,
XkbSrvLedInfoPtr sli)
{
int nNames,nMaps;
register unsigned n,bit;
if (sli==NULL)
return 0;
nNames= nMaps= 0;
if ((what&XkbXI_IndicatorNamesMask)==0)
sli->namesPresent= 0;
if ((what&XkbXI_IndicatorMapsMask)==0)
sli->mapsPresent= 0;
for (n=0,bit=1;n<XkbNumIndicators;n++,bit<<=1) {
if (sli->names && sli->names[n]!=None) {
sli->namesPresent|= bit;
nNames++;
}
if (sli->maps && XkbIM_InUse(&sli->maps[n])) {
sli->mapsPresent|= bit;
nMaps++;
}
}
return (nNames*4)+(nMaps*SIZEOF(xkbIndicatorMapWireDesc));
}
static int
CheckDeviceLedFBs( DeviceIntPtr dev,
int class,
int id,
xkbGetDeviceInfoReply * rep,
ClientPtr client)
{
int nFBs= 0;
int length= 0;
Bool classOk;
if (class==XkbDfltXIClass) {
if (dev->kbdfeed) class= KbdFeedbackClass;
else if (dev->leds) class= LedFeedbackClass;
else {
client->errorValue= _XkbErrCode2(XkbErr_BadClass,class);
return XkbKeyboardErrorCode;
}
}
classOk= False;
if ((dev->kbdfeed)&&((class==KbdFeedbackClass)||(class==XkbAllXIClasses))) {
KbdFeedbackPtr kf;
classOk= True;
for (kf= dev->kbdfeed;(kf);kf=kf->next) {
if ((id!=XkbAllXIIds)&&(id!=XkbDfltXIId)&&(id!=kf->ctrl.id))
continue;
nFBs++;
length+= SIZEOF(xkbDeviceLedsWireDesc);
if (!kf->xkb_sli)
kf->xkb_sli= XkbAllocSrvLedInfo(dev,kf,NULL,0);
length+= ComputeDeviceLedInfoSize(dev,rep->present,kf->xkb_sli);
if (id!=XkbAllXIIds)
break;
}
}
if ((dev->leds)&&((class==LedFeedbackClass)||(class==XkbAllXIClasses))) {
LedFeedbackPtr lf;
classOk= True;
for (lf= dev->leds;(lf);lf=lf->next) {
if ((id!=XkbAllXIIds)&&(id!=XkbDfltXIId)&&(id!=lf->ctrl.id))
continue;
nFBs++;
length+= SIZEOF(xkbDeviceLedsWireDesc);
if (!lf->xkb_sli)
lf->xkb_sli= XkbAllocSrvLedInfo(dev,NULL,lf,0);
length+= ComputeDeviceLedInfoSize(dev,rep->present,lf->xkb_sli);
if (id!=XkbAllXIIds)
break;
}
}
if (nFBs>0) {
if (rep->supported&XkbXI_IndicatorsMask) {
rep->nDeviceLedFBs= nFBs;
rep->length+= (length/4);
}
return Success;
}
if (classOk) client->errorValue= _XkbErrCode2(XkbErr_BadId,id);
else client->errorValue= _XkbErrCode2(XkbErr_BadClass,class);
return XkbKeyboardErrorCode;
}
static int
SendDeviceLedInfo( XkbSrvLedInfoPtr sli,
ClientPtr client)
{
xkbDeviceLedsWireDesc wire;
int length;
length= 0;
wire.ledClass= sli->class;
wire.ledID= sli->id;
wire.namesPresent= sli->namesPresent;
wire.mapsPresent= sli->mapsPresent;
wire.physIndicators= sli->physIndicators;
wire.state= sli->effectiveState;
if (client->swapped) {
register int n;
swaps(&wire.ledClass,n);
swaps(&wire.ledID,n);
swapl(&wire.namesPresent,n);
swapl(&wire.mapsPresent,n);
swapl(&wire.physIndicators,n);
swapl(&wire.state,n);
}
WriteToClient(client,SIZEOF(xkbDeviceLedsWireDesc),(char *)&wire);
length+= SIZEOF(xkbDeviceLedsWireDesc);
if (sli->namesPresent|sli->mapsPresent) {
register unsigned i,bit;
if (sli->namesPresent) {
CARD32 awire;
for (i=0,bit=1;i<XkbNumIndicators;i++,bit<<=1) {
if (sli->namesPresent&bit) {
awire= (CARD32)sli->names[i];
if (client->swapped) {
register int n;
swapl(&awire,n);
}
WriteToClient(client,4,(char *)&awire);
length+= 4;
}
}
}
if (sli->mapsPresent) {
for (i=0,bit=1;i<XkbNumIndicators;i++,bit<<=1) {
xkbIndicatorMapWireDesc iwire;
if (sli->mapsPresent&bit) {
iwire.flags= sli->maps[i].flags;
iwire.whichGroups= sli->maps[i].which_groups;
iwire.groups= sli->maps[i].groups;
iwire.whichMods= sli->maps[i].which_mods;
iwire.mods= sli->maps[i].mods.mask;
iwire.realMods= sli->maps[i].mods.real_mods;
iwire.virtualMods= sli->maps[i].mods.vmods;
iwire.ctrls= sli->maps[i].ctrls;
if (client->swapped) {
register int n;
swaps(&iwire.virtualMods,n);
swapl(&iwire.ctrls,n);
}
WriteToClient(client,SIZEOF(xkbIndicatorMapWireDesc),
(char *)&iwire);
length+= SIZEOF(xkbIndicatorMapWireDesc);
}
}
}
}
return length;
}
static int
SendDeviceLedFBs( DeviceIntPtr dev,
int class,
int id,
unsigned wantLength,
ClientPtr client)
{
int length= 0;
if (class==XkbDfltXIClass) {
if (dev->kbdfeed) class= KbdFeedbackClass;
else if (dev->leds) class= LedFeedbackClass;
}
if ((dev->kbdfeed)&&
((class==KbdFeedbackClass)||(class==XkbAllXIClasses))) {
KbdFeedbackPtr kf;
for (kf= dev->kbdfeed;(kf);kf=kf->next) {
if ((id==XkbAllXIIds)||(id==XkbDfltXIId)||(id==kf->ctrl.id)) {
length+= SendDeviceLedInfo(kf->xkb_sli,client);
if (id!=XkbAllXIIds)
break;
}
}
}
if ((dev->leds)&&
((class==LedFeedbackClass)||(class==XkbAllXIClasses))) {
LedFeedbackPtr lf;
for (lf= dev->leds;(lf);lf=lf->next) {
if ((id==XkbAllXIIds)||(id==XkbDfltXIId)||(id==lf->ctrl.id)) {
length+= SendDeviceLedInfo(lf->xkb_sli,client);
if (id!=XkbAllXIIds)
break;
}
}
}
if (length==wantLength)
return Success;
else return BadLength;
}
int
ProcXkbGetDeviceInfo(ClientPtr client)
{
DeviceIntPtr dev;
xkbGetDeviceInfoReply rep;
int status,nDeviceLedFBs;
unsigned length,nameLen;
CARD16 ledClass,ledID;
unsigned wanted,supported;
char * str;
REQUEST(xkbGetDeviceInfoReq);
REQUEST_SIZE_MATCH(xkbGetDeviceInfoReq);
if (!(client->xkbClientFlags&_XkbClientInitialized))
return BadAccess;
wanted= stuff->wanted;
CHK_ANY_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess);
CHK_MASK_LEGAL(0x01,wanted,XkbXI_AllDeviceFeaturesMask);
if ((!dev->button)||((stuff->nBtns<1)&&(!stuff->allBtns)))
wanted&= ~XkbXI_ButtonActionsMask;
if ((!dev->kbdfeed)&&(!dev->leds))
wanted&= ~XkbXI_IndicatorsMask;
nameLen= XkbSizeCountedString(dev->name);
bzero((char *)&rep,SIZEOF(xkbGetDeviceInfoReply));
rep.type = X_Reply;
rep.deviceID= dev->id;
rep.sequenceNumber = client->sequence;
rep.length = nameLen/4;
rep.present = wanted;
rep.supported = XkbXI_AllDeviceFeaturesMask;
rep.unsupported = 0;
rep.firstBtnWanted = rep.nBtnsWanted = 0;
rep.firstBtnRtrn = rep.nBtnsRtrn = 0;
if (dev->button)
rep.totalBtns= dev->button->numButtons;
else rep.totalBtns= 0;
rep.devType= dev->type;
rep.hasOwnState= (dev->key && dev->key->xkbInfo);
rep.nDeviceLedFBs = 0;
if (dev->kbdfeed) rep.dfltKbdFB= dev->kbdfeed->ctrl.id;
else rep.dfltKbdFB= XkbXINone;
if (dev->leds) rep.dfltLedFB= dev->leds->ctrl.id;
else rep.dfltLedFB= XkbXINone;
ledClass= stuff->ledClass;
ledID= stuff->ledID;
rep.firstBtnWanted= rep.nBtnsWanted= 0;
rep.firstBtnRtrn= rep.nBtnsRtrn= 0;
if (wanted&XkbXI_ButtonActionsMask) {
if (stuff->allBtns) {
stuff->firstBtn= 0;
stuff->nBtns= dev->button->numButtons;
}
if ((stuff->firstBtn+stuff->nBtns)>dev->button->numButtons) {
client->errorValue = _XkbErrCode4(0x02,dev->button->numButtons,
stuff->firstBtn,
stuff->nBtns);
return BadValue;
}
else {
rep.firstBtnWanted= stuff->firstBtn;
rep.nBtnsWanted= stuff->nBtns;
if (dev->button->xkb_acts!=NULL) {
XkbAction *act;
register int i;
rep.firstBtnRtrn= stuff->firstBtn;
rep.nBtnsRtrn= stuff->nBtns;
act= &dev->button->xkb_acts[rep.firstBtnWanted];
for (i=0;i<rep.nBtnsRtrn;i++,act++) {
if (act->type!=XkbSA_NoAction)
break;
}
rep.firstBtnRtrn+= i;
rep.nBtnsRtrn-= i;
act= &dev->button->xkb_acts[rep.firstBtnRtrn+rep.nBtnsRtrn-1];
for (i=0;i<rep.nBtnsRtrn;i++,act--) {
if (act->type!=XkbSA_NoAction)
break;
}
rep.nBtnsRtrn-= i;
}
rep.length+= (rep.nBtnsRtrn*SIZEOF(xkbActionWireDesc))/4;
}
}
if (wanted&XkbXI_IndicatorsMask) {
status= CheckDeviceLedFBs(dev,ledClass,ledID,&rep,client);
if (status!=Success)
return status;
}
length= rep.length*4;
supported= rep.supported;
nDeviceLedFBs = rep.nDeviceLedFBs;
if (client->swapped) {
register int n;
swaps(&rep.sequenceNumber,n);
swapl(&rep.length,n);
swaps(&rep.present,n);
swaps(&rep.supported,n);
swaps(&rep.unsupported,n);
swaps(&rep.nDeviceLedFBs,n);
swapl(&rep.type,n);
}
WriteToClient(client,SIZEOF(xkbGetDeviceInfoReply), (char *)&rep);
str= (char*) xalloc(nameLen);
if (!str)
return BadAlloc;
XkbWriteCountedString(str,dev->name,client->swapped);
WriteToClient(client,nameLen,str);
xfree(str);
length-= nameLen;
if (rep.nBtnsRtrn>0) {
int sz;
xkbActionWireDesc * awire;
sz= rep.nBtnsRtrn*SIZEOF(xkbActionWireDesc);
awire= (xkbActionWireDesc *)&dev->button->xkb_acts[rep.firstBtnRtrn];
WriteToClient(client,sz,(char *)awire);
length-= sz;
}
if (nDeviceLedFBs>0) {
status= SendDeviceLedFBs(dev,ledClass,ledID,length,client);
if (status!=Success)
return status;
}
else if (length!=0) {
ErrorF("[xkb] Internal Error! BadLength in ProcXkbGetDeviceInfo\n");
ErrorF("[xkb] Wrote %d fewer bytes than expected\n",length);
return BadLength;
}
if (stuff->wanted&(~supported)) {
xkbExtensionDeviceNotify ed;
bzero((char *)&ed,SIZEOF(xkbExtensionDeviceNotify));
ed.ledClass= ledClass;
ed.ledID= ledID;
ed.ledsDefined= 0;
ed.ledState= 0;
ed.firstBtn= ed.nBtns= 0;
ed.reason= XkbXI_UnsupportedFeatureMask;
ed.supported= supported;
ed.unsupported= stuff->wanted&(~supported);
XkbSendExtensionDeviceNotify(dev,client,&ed);
}
return client->noClientException;
}
static char *
CheckSetDeviceIndicators( char * wire,
DeviceIntPtr dev,
int num,
int * status_rtrn,
ClientPtr client)
{
xkbDeviceLedsWireDesc * ledWire;
int i;
XkbSrvLedInfoPtr sli;
ledWire= (xkbDeviceLedsWireDesc *)wire;
for (i=0;i<num;i++) {
if (client->swapped) {
register int n;
swaps(&ledWire->ledClass,n);
swaps(&ledWire->ledID,n);
swapl(&ledWire->namesPresent,n);
swapl(&ledWire->mapsPresent,n);
swapl(&ledWire->physIndicators,n);
}
sli= XkbFindSrvLedInfo(dev,ledWire->ledClass,ledWire->ledID,
XkbXI_IndicatorsMask);
if (sli!=NULL) {
register int n;
register unsigned bit;
int nMaps,nNames;
CARD32 *atomWire;
xkbIndicatorMapWireDesc *mapWire;
nMaps= nNames= 0;
for (n=0,bit=1;n<XkbNumIndicators;n++,bit<<=1) {
if (ledWire->namesPresent&bit)
nNames++;
if (ledWire->mapsPresent&bit)
nMaps++;
}
atomWire= (CARD32 *)&ledWire[1];
if (nNames>0) {
for (n=0;n<nNames;n++) {
if (client->swapped) {
register int t;
swapl(atomWire,t);
}
CHK_ATOM_OR_NONE3(((Atom)(*atomWire)),client->errorValue,
*status_rtrn,NULL);
atomWire++;
}
}
mapWire= (xkbIndicatorMapWireDesc *)atomWire;
if (nMaps>0) {
for (n=0;n<nMaps;n++) {
if (client->swapped) {
register int t;
swaps(&mapWire->virtualMods,t);
swapl(&mapWire->ctrls,t);
}
CHK_MASK_LEGAL3(0x21,mapWire->whichGroups,
XkbIM_UseAnyGroup,
client->errorValue,
*status_rtrn,NULL);
CHK_MASK_LEGAL3(0x22,mapWire->whichMods,XkbIM_UseAnyMods,
client->errorValue,
*status_rtrn,NULL);
mapWire++;
}
}
ledWire= (xkbDeviceLedsWireDesc *)mapWire;
}
else {
return (char *)ledWire;
}
}
return (char *)ledWire;
}
static char *
SetDeviceIndicators( char * wire,
DeviceIntPtr dev,
unsigned changed,
int num,
int * status_rtrn,
ClientPtr client,
xkbExtensionDeviceNotify *ev)
{
xkbDeviceLedsWireDesc * ledWire;
int i;
XkbEventCauseRec cause;
unsigned namec,mapc,statec;
xkbExtensionDeviceNotify ed;
XkbChangesRec changes;
DeviceIntPtr kbd;
bzero((char *)&ed,sizeof(xkbExtensionDeviceNotify));
bzero((char *)&changes,sizeof(XkbChangesRec));
XkbSetCauseXkbReq(&cause,X_kbSetDeviceInfo,client);
ledWire= (xkbDeviceLedsWireDesc *)wire;
for (i=0;i<num;i++) {
register int n;
register unsigned bit;
CARD32 * atomWire;
xkbIndicatorMapWireDesc * mapWire;
XkbSrvLedInfoPtr sli;
namec= mapc= statec= 0;
sli= XkbFindSrvLedInfo(dev,ledWire->ledClass,ledWire->ledID,
XkbXI_IndicatorMapsMask);
if (!sli) {
return (char *)ledWire;
}
atomWire= (CARD32 *)&ledWire[1];
if (changed&XkbXI_IndicatorNamesMask) {
namec= sli->namesPresent|ledWire->namesPresent;
bzero((char *)sli->names,XkbNumIndicators*sizeof(Atom));
}
if (ledWire->namesPresent) {
sli->namesPresent= ledWire->namesPresent;
bzero((char *)sli->names,XkbNumIndicators*sizeof(Atom));
for (n=0,bit=1;n<XkbNumIndicators;n++,bit<<=1) {
if (ledWire->namesPresent&bit) {
sli->names[n]= (Atom)*atomWire;
if (sli->names[n]==None)
ledWire->namesPresent&= ~bit;
atomWire++;
}
}
}
mapWire= (xkbIndicatorMapWireDesc *)atomWire;
if (changed&XkbXI_IndicatorMapsMask) {
mapc= sli->mapsPresent|ledWire->mapsPresent;
sli->mapsPresent= ledWire->mapsPresent;
bzero((char*)sli->maps,XkbNumIndicators*sizeof(XkbIndicatorMapRec));
}
if (ledWire->mapsPresent) {
for (n=0,bit=1;n<XkbNumIndicators;n++,bit<<=1) {
if (ledWire->mapsPresent&bit) {
sli->maps[n].flags= mapWire->flags;
sli->maps[n].which_groups= mapWire->whichGroups;
sli->maps[n].groups= mapWire->groups;
sli->maps[n].which_mods= mapWire->whichMods;
sli->maps[n].mods.mask= mapWire->mods;
sli->maps[n].mods.real_mods=mapWire->realMods;
sli->maps[n].mods.vmods= mapWire->virtualMods;
sli->maps[n].ctrls= mapWire->ctrls;
mapWire++;
}
}
}
if (changed&XkbXI_IndicatorStateMask) {
statec= sli->effectiveState^ledWire->state;
sli->explicitState&= ~statec;
sli->explicitState|= (ledWire->state&statec);
}
if (namec)
XkbApplyLedNameChanges(dev,sli,namec,&ed,&changes,&cause);
if (mapc)
XkbApplyLedMapChanges(dev,sli,mapc,&ed,&changes,&cause);
if (statec)
XkbApplyLedStateChanges(dev,sli,statec,&ed,&changes,&cause);
kbd= dev;
if ((sli->flags&XkbSLI_HasOwnState)==0)
kbd = inputInfo.keyboard;
XkbFlushLedEvents(dev,kbd,sli,&ed,&changes,&cause);
ledWire= (xkbDeviceLedsWireDesc *)mapWire;
}
return (char *)ledWire;
}
static int
_XkbSetDeviceInfo(ClientPtr client, DeviceIntPtr dev,
xkbSetDeviceInfoReq *stuff)
{
char *wire;
wire= (char *)&stuff[1];
if (stuff->change&XkbXI_ButtonActionsMask) {
if (!dev->button) {
client->errorValue = _XkbErrCode2(XkbErr_BadClass,ButtonClass);
return XkbKeyboardErrorCode;
}
if ((stuff->firstBtn+stuff->nBtns)>dev->button->numButtons) {
client->errorValue= _XkbErrCode4(0x02,stuff->firstBtn,stuff->nBtns,
dev->button->numButtons);
return BadMatch;
}
wire+= (stuff->nBtns*SIZEOF(xkbActionWireDesc));
}
if (stuff->change&XkbXI_IndicatorsMask) {
int status= Success;
wire= CheckSetDeviceIndicators(wire,dev,stuff->nDeviceLedFBs,
&status,client);
if (status!=Success)
return status;
}
if (((wire-((char *)stuff))/4)!=stuff->length)
return BadLength;
return Success;
}
static int
_XkbSetDeviceInfoCheck(ClientPtr client, DeviceIntPtr dev,
xkbSetDeviceInfoReq *stuff)
{
char *wire;
xkbExtensionDeviceNotify ed;
bzero((char *)&ed,SIZEOF(xkbExtensionDeviceNotify));
ed.deviceID= dev->id;
wire= (char *)&stuff[1];
if (stuff->change&XkbXI_ButtonActionsMask) {
int nBtns,sz,i;
XkbAction * acts;
DeviceIntPtr kbd;
nBtns= dev->button->numButtons;
acts= dev->button->xkb_acts;
if (acts==NULL) {
acts= _XkbTypedCalloc(nBtns,XkbAction);
if (!acts)
return BadAlloc;
dev->button->xkb_acts= acts;
}
sz= stuff->nBtns*SIZEOF(xkbActionWireDesc);
memcpy((char *)&acts[stuff->firstBtn],(char *)wire,sz);
wire+= sz;
ed.reason|= XkbXI_ButtonActionsMask;
ed.firstBtn= stuff->firstBtn;
ed.nBtns= stuff->nBtns;
if (dev->key) kbd= dev;
else kbd= inputInfo.keyboard;
acts= &dev->button->xkb_acts[stuff->firstBtn];
for (i=0;i<stuff->nBtns;i++,acts++) {
if (acts->type!=XkbSA_NoAction)
XkbSetActionKeyMods(kbd->key->xkbInfo->desc,acts,0);
}
}
if (stuff->change&XkbXI_IndicatorsMask) {
int status= Success;
wire= SetDeviceIndicators(wire,dev,stuff->change,
stuff->nDeviceLedFBs, &status,client,&ed);
if (status!=Success)
return status;
}
if ((stuff->change)&&(ed.reason))
XkbSendExtensionDeviceNotify(dev,client,&ed);
return Success;
}
int
ProcXkbSetDeviceInfo(ClientPtr client)
{
DeviceIntPtr dev;
int rc;
REQUEST(xkbSetDeviceInfoReq);
REQUEST_AT_LEAST_SIZE(xkbSetDeviceInfoReq);
if (!(client->xkbClientFlags&_XkbClientInitialized))
return BadAccess;
CHK_ANY_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess);
CHK_MASK_LEGAL(0x01,stuff->change,XkbXI_AllFeaturesMask);
rc = _XkbSetDeviceInfoCheck(client, dev, stuff);
if (rc != Success)
return rc;
if (stuff->deviceSpec == XkbUseCoreKbd || stuff->deviceSpec == XkbUseCorePtr)
{
DeviceIntPtr other;
for (other = inputInfo.devices; other; other = other->next)
{
if (((other != dev) && !other->isMaster && (other->u.master == dev)) &&
((stuff->deviceSpec == XkbUseCoreKbd && other->key) ||
(stuff->deviceSpec == XkbUseCorePtr && other->button)))
{
rc = XaceHook(XACE_DEVICE_ACCESS, client, other, DixManageAccess);
if (rc == Success)
{
rc = _XkbSetDeviceInfoCheck(client, other, stuff);
if (rc != Success)
return rc;
}
}
}
}
rc = _XkbSetDeviceInfo(client, dev, stuff);
if (rc != Success)
return rc;
if (stuff->deviceSpec == XkbUseCoreKbd || stuff->deviceSpec == XkbUseCorePtr)
{
DeviceIntPtr other;
for (other = inputInfo.devices; other; other = other->next)
{
if (((other != dev) && !other->isMaster && (other->u.master == dev)) &&
((stuff->deviceSpec == XkbUseCoreKbd && other->key) ||
(stuff->deviceSpec == XkbUseCorePtr && other->button)))
{
rc = XaceHook(XACE_DEVICE_ACCESS, client, other, DixManageAccess);
if (rc == Success)
{
rc = _XkbSetDeviceInfo(client, other, stuff);
if (rc != Success)
return rc;
}
}
}
}
return client->noClientException;
}
int
ProcXkbSetDebuggingFlags(ClientPtr client)
{
CARD32 newFlags,newCtrls,extraLength;
xkbSetDebuggingFlagsReply rep;
int rc;
REQUEST(xkbSetDebuggingFlagsReq);
REQUEST_AT_LEAST_SIZE(xkbSetDebuggingFlagsReq);
rc = XaceHook(XACE_SERVER_ACCESS, client, DixDebugAccess);
if (rc != Success)
return rc;
newFlags= xkbDebugFlags&(~stuff->affectFlags);
newFlags|= (stuff->flags&stuff->affectFlags);
newCtrls= xkbDebugCtrls&(~stuff->affectCtrls);
newCtrls|= (stuff->ctrls&stuff->affectCtrls);
if (xkbDebugFlags || newFlags || stuff->msgLength) {
ErrorF("[xkb] XkbDebug: Setting debug flags to 0x%lx\n",(long)newFlags);
if (newCtrls!=xkbDebugCtrls)
ErrorF("[xkb] XkbDebug: Setting debug controls to 0x%lx\n",(long)newCtrls);
}
extraLength= (stuff->length<<2)-sz_xkbSetDebuggingFlagsReq;
if (stuff->msgLength>0) {
char *msg;
if (extraLength<XkbPaddedSize(stuff->msgLength)) {
ErrorF("[xkb] XkbDebug: msgLength= %d, length= %ld (should be %d)\n",
stuff->msgLength,(long)extraLength,
XkbPaddedSize(stuff->msgLength));
return BadLength;
}
msg= (char *)&stuff[1];
if (msg[stuff->msgLength-1]!='\0') {
ErrorF("[xkb] XkbDebug: message not null-terminated\n");
return BadValue;
}
ErrorF("[xkb] XkbDebug: %s\n",msg);
}
xkbDebugFlags = newFlags;
xkbDebugCtrls = newCtrls;
XkbDisableLockActions= (xkbDebugCtrls&XkbDF_DisableLocks);
rep.type= X_Reply;
rep.length = 0;
rep.sequenceNumber = client->sequence;
rep.currentFlags = newFlags;
rep.currentCtrls = newCtrls;
rep.supportedFlags = ~0;
rep.supportedCtrls = ~0;
if ( client->swapped ) {
register int n;
swaps(&rep.sequenceNumber, n);
swapl(&rep.currentFlags, n);
swapl(&rep.currentCtrls, n);
swapl(&rep.supportedFlags, n);
swapl(&rep.supportedCtrls, n);
}
WriteToClient(client,SIZEOF(xkbSetDebuggingFlagsReply), (char *)&rep);
return client->noClientException;
}
static int
ProcXkbDispatch (ClientPtr client)
{
REQUEST(xReq);
switch (stuff->data)
{
case X_kbUseExtension:
return ProcXkbUseExtension(client);
case X_kbSelectEvents:
return ProcXkbSelectEvents(client);
case X_kbBell:
return ProcXkbBell(client);
case X_kbGetState:
return ProcXkbGetState(client);
case X_kbLatchLockState:
return ProcXkbLatchLockState(client);
case X_kbGetControls:
return ProcXkbGetControls(client);
case X_kbSetControls:
return ProcXkbSetControls(client);
case X_kbGetMap:
return ProcXkbGetMap(client);
case X_kbSetMap:
return ProcXkbSetMap(client);
case X_kbGetCompatMap:
return ProcXkbGetCompatMap(client);
case X_kbSetCompatMap:
return ProcXkbSetCompatMap(client);
case X_kbGetIndicatorState:
return ProcXkbGetIndicatorState(client);
case X_kbGetIndicatorMap:
return ProcXkbGetIndicatorMap(client);
case X_kbSetIndicatorMap:
return ProcXkbSetIndicatorMap(client);
case X_kbGetNamedIndicator:
return ProcXkbGetNamedIndicator(client);
case X_kbSetNamedIndicator:
return ProcXkbSetNamedIndicator(client);
case X_kbGetNames:
return ProcXkbGetNames(client);
case X_kbSetNames:
return ProcXkbSetNames(client);
case X_kbGetGeometry:
return ProcXkbGetGeometry(client);
case X_kbSetGeometry:
return ProcXkbSetGeometry(client);
case X_kbPerClientFlags:
return ProcXkbPerClientFlags(client);
case X_kbListComponents:
return ProcXkbListComponents(client);
case X_kbGetKbdByName:
return ProcXkbGetKbdByName(client);
case X_kbGetDeviceInfo:
return ProcXkbGetDeviceInfo(client);
case X_kbSetDeviceInfo:
return ProcXkbSetDeviceInfo(client);
case X_kbSetDebuggingFlags:
return ProcXkbSetDebuggingFlags(client);
default:
return BadRequest;
}
}
static int
XkbClientGone(pointer data,XID id)
{
DevicePtr pXDev = (DevicePtr)data;
if (!XkbRemoveResourceClient(pXDev,id)) {
ErrorF("[xkb] Internal Error! bad RemoveResourceClient in XkbClientGone\n");
}
return 1;
}
void
XkbExtensionInit(void)
{
ExtensionEntry *extEntry;
if ((extEntry = AddExtension(XkbName, XkbNumberEvents, XkbNumberErrors,
ProcXkbDispatch, SProcXkbDispatch,
NULL, StandardMinorOpcode))) {
XkbReqCode = (unsigned char)extEntry->base;
XkbEventBase = (unsigned char)extEntry->eventBase;
XkbErrorBase = (unsigned char)extEntry->errorBase;
XkbKeyboardErrorCode = XkbErrorBase+XkbKeyboard;
RT_XKBCLIENT = CreateNewResourceType(XkbClientGone);
}
return;
}