xkb: ProcXkbSetNames should work on all attached SDs.

If called with XkbUseCoreKbd, run through all attached SDs and replicate the
call. This way, we keep the SDs in sync with the MD as long as core clients
control the MDs.
This commit is contained in:
Peter Hutterer 2008-08-01 16:41:08 +09:30
parent 7e45c80204
commit 5ba87c3327

622
xkb/xkb.c
View File

@ -3862,16 +3862,322 @@ char * str;
return True;
}
/* FIXME: Needs to set names on all core-sending devices. */
/**
* Check the device-dependent data in the request against the device. Returns
* Success, or the appropriate error code.
*/
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;
XkbDescRec *xkb;
XkbNamesRec *names;
xkbNamesNotify nn;
CARD32 *tmp;
Atom bad;
Atom bad;
int rc;
REQUEST(xkbSetNamesReq);
REQUEST_AT_LEAST_SIZE(xkbSetNamesReq);
@ -3882,8 +4188,7 @@ ProcXkbSetNames(ClientPtr client)
CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess);
CHK_MASK_LEGAL(0x01,stuff->which,XkbAllNamesMask);
xkb = dev->key->xkbInfo->desc;
names = xkb->names;
/* check device-independent stuff */
tmp = (CARD32 *)&stuff[1];
if (stuff->which&XkbKeycodesNameMask) {
@ -3928,277 +4233,54 @@ ProcXkbSetNames(ClientPtr client)
return BadAtom;
}
}
if (stuff->which&XkbKeyTypeNamesMask) {
register 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) {
register 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;
}
if (XkbAllocNames(xkb,stuff->which,stuff->nRadioGroups,
stuff->nKeyAliases)!=Success) {
return BadAlloc;
/* start of device-dependent tests */
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;
}
}
}
}
/* everything is okay -- update names */
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;
rc = _XkbSetNames(client, dev, stuff);
if (rc != Success)
return rc;
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;
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))
{
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;
rc = XaceHook(XACE_DEVICE_ACCESS, client, other, DixManageAccess);
if (rc == Success)
_XkbSetNames(client, other, stuff);
}
}
}
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);
}
}
/* everything is okay -- update names */
return client->noClientException;
}