xkb: ProcXkbSetMap 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:
parent
31afd51dd4
commit
3c7740aa8f
270
xkb/xkb.c
270
xkb/xkb.c
|
@ -2332,158 +2332,165 @@ XkbServerMapPtr srv = xkbi->desc->server;
|
||||||
return (char *)wire;
|
return (char *)wire;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* FIXME: Needs to set map on all core-sending devices. */
|
/**
|
||||||
int
|
* Check if the given request can be applied to the given device but don't
|
||||||
ProcXkbSetMap(ClientPtr client)
|
* actually do anything..
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
_XkbSetMapChecks(ClientPtr client, DeviceIntPtr dev, xkbSetMapReq *req, char* values)
|
||||||
{
|
{
|
||||||
DeviceIntPtr dev;
|
XkbSrvInfoPtr xkbi;
|
||||||
XkbSrvInfoPtr xkbi;
|
XkbDescPtr xkb;
|
||||||
XkbDescPtr xkb;
|
int error;
|
||||||
XkbChangesRec change;
|
int nTypes = 0, nActions;
|
||||||
XkbEventCauseRec cause;
|
CARD8 mapWidths[XkbMaxLegalKeyCode + 1];
|
||||||
int nTypes = 0,nActions,error;
|
CARD16 symsPerKey[XkbMaxLegalKeyCode + 1];
|
||||||
char * tmp;
|
|
||||||
CARD8 mapWidths[XkbMaxLegalKeyCode+1];
|
|
||||||
CARD16 symsPerKey[XkbMaxLegalKeyCode+1];
|
|
||||||
Bool sentNKN;
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
XkbSetCauseXkbReq(&cause,X_kbSetMap,client);
|
|
||||||
xkbi= dev->key->xkbInfo;
|
xkbi= dev->key->xkbInfo;
|
||||||
xkb = xkbi->desc;
|
xkb = xkbi->desc;
|
||||||
|
|
||||||
if ((xkb->min_key_code!=stuff->minKeyCode)||
|
if ((xkb->min_key_code != req->minKeyCode)||
|
||||||
(xkb->max_key_code!=stuff->maxKeyCode)) {
|
(xkb->max_key_code != req->maxKeyCode)) {
|
||||||
if (client->vMajor!=1) { /* pre 1.0 versions of Xlib have a bug */
|
if (client->vMajor!=1) { /* pre 1.0 versions of Xlib have a bug */
|
||||||
stuff->minKeyCode= xkb->min_key_code;
|
req->minKeyCode= xkb->min_key_code;
|
||||||
stuff->maxKeyCode= xkb->max_key_code;
|
req->maxKeyCode= xkb->max_key_code;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (!XkbIsLegalKeycode(stuff->minKeyCode)) {
|
if (!XkbIsLegalKeycode(req->minKeyCode)) {
|
||||||
client->errorValue= _XkbErrCode3(2,stuff->minKeyCode,
|
client->errorValue = _XkbErrCode3(2, req->minKeyCode, req->maxKeyCode);
|
||||||
stuff->maxKeyCode);
|
|
||||||
return BadValue;
|
return BadValue;
|
||||||
}
|
}
|
||||||
if (stuff->minKeyCode>stuff->maxKeyCode) {
|
if (req->minKeyCode > req->maxKeyCode) {
|
||||||
client->errorValue= _XkbErrCode3(3,stuff->minKeyCode,
|
client->errorValue = _XkbErrCode3(3, req->minKeyCode, req->maxKeyCode);
|
||||||
stuff->maxKeyCode);
|
|
||||||
return BadMatch;
|
return BadMatch;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tmp = (char *)&stuff[1];
|
if ((req->present & XkbKeyTypesMask) &&
|
||||||
if ((stuff->present&XkbKeyTypesMask)&&
|
(!CheckKeyTypes(client,xkb,req,(xkbKeyTypeWireDesc **)&values,
|
||||||
(!CheckKeyTypes(client,xkb,stuff,(xkbKeyTypeWireDesc **)&tmp,
|
|
||||||
&nTypes,mapWidths))) {
|
&nTypes,mapWidths))) {
|
||||||
client->errorValue = nTypes;
|
client->errorValue = nTypes;
|
||||||
return BadValue;
|
return BadValue;
|
||||||
}
|
}
|
||||||
if ((stuff->present&XkbKeySymsMask)&&
|
if ((req->present & XkbKeySymsMask) &&
|
||||||
(!CheckKeySyms(client,xkb,stuff,nTypes,mapWidths,symsPerKey,
|
(!CheckKeySyms(client,xkb,req,nTypes,mapWidths,symsPerKey,
|
||||||
(xkbSymMapWireDesc **)&tmp,&error))) {
|
(xkbSymMapWireDesc **)&values,&error))) {
|
||||||
client->errorValue = error;
|
client->errorValue = error;
|
||||||
return BadValue;
|
return BadValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((stuff->present&XkbKeyActionsMask)&&
|
if ((req->present & XkbKeyActionsMask) &&
|
||||||
(!CheckKeyActions(xkb,stuff,nTypes,mapWidths,symsPerKey,
|
(!CheckKeyActions(xkb,req,nTypes,mapWidths,symsPerKey,
|
||||||
(CARD8 **)&tmp,&nActions))) {
|
(CARD8 **)&values,&nActions))) {
|
||||||
client->errorValue = nActions;
|
client->errorValue = nActions;
|
||||||
return BadValue;
|
return BadValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((stuff->present&XkbKeyBehaviorsMask)&&
|
if ((req->present & XkbKeyBehaviorsMask) &&
|
||||||
(!CheckKeyBehaviors(xkb,stuff,(xkbBehaviorWireDesc**)&tmp,&error))) {
|
(!CheckKeyBehaviors(xkb,req,(xkbBehaviorWireDesc**)&values,&error))) {
|
||||||
client->errorValue = error;
|
client->errorValue = error;
|
||||||
return BadValue;
|
return BadValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((stuff->present&XkbVirtualModsMask)&&
|
if ((req->present & XkbVirtualModsMask) &&
|
||||||
(!CheckVirtualMods(xkb,stuff,(CARD8 **)&tmp,&error))) {
|
(!CheckVirtualMods(xkb,req,(CARD8 **)&values,&error))) {
|
||||||
client->errorValue= error;
|
client->errorValue= error;
|
||||||
return BadValue;
|
return BadValue;
|
||||||
}
|
}
|
||||||
if ((stuff->present&XkbExplicitComponentsMask)&&
|
if ((req->present&XkbExplicitComponentsMask) &&
|
||||||
(!CheckKeyExplicit(xkb,stuff,(CARD8 **)&tmp,&error))) {
|
(!CheckKeyExplicit(xkb,req,(CARD8 **)&values,&error))) {
|
||||||
client->errorValue= error;
|
client->errorValue= error;
|
||||||
return BadValue;
|
return BadValue;
|
||||||
}
|
}
|
||||||
if ((stuff->present&XkbModifierMapMask)&&
|
if ((req->present&XkbModifierMapMask) &&
|
||||||
(!CheckModifierMap(xkb,stuff,(CARD8 **)&tmp,&error))) {
|
(!CheckModifierMap(xkb,req,(CARD8 **)&values,&error))) {
|
||||||
client->errorValue= error;
|
client->errorValue= error;
|
||||||
return BadValue;
|
return BadValue;
|
||||||
}
|
}
|
||||||
if ((stuff->present&XkbVirtualModMapMask)&&
|
if ((req->present&XkbVirtualModMapMask) &&
|
||||||
(!CheckVirtualModMap(xkb,stuff,(xkbVModMapWireDesc **)&tmp,&error))) {
|
(!CheckVirtualModMap(xkb,req,(xkbVModMapWireDesc **)&values,&error))) {
|
||||||
client->errorValue= error;
|
client->errorValue= error;
|
||||||
return BadValue;
|
return BadValue;
|
||||||
}
|
}
|
||||||
if (((tmp-((char *)stuff))/4)!=stuff->length) {
|
|
||||||
|
if (((values-((char *)req))/4)!= req->length) {
|
||||||
ErrorF("[xkb] Internal error! Bad length in XkbSetMap (after check)\n");
|
ErrorF("[xkb] Internal error! Bad length in XkbSetMap (after check)\n");
|
||||||
client->errorValue = tmp-((char *)&stuff[1]);
|
client->errorValue = values-((char *)&req[1]);
|
||||||
return BadLength;
|
return BadLength;
|
||||||
}
|
}
|
||||||
bzero(&change,sizeof(change));
|
|
||||||
sentNKN= False;
|
return Success;
|
||||||
if ((xkb->min_key_code!=stuff->minKeyCode)||
|
}
|
||||||
(xkb->max_key_code!=stuff->maxKeyCode)) {
|
|
||||||
|
/**
|
||||||
|
* Apply the given request on the given device.
|
||||||
|
*/
|
||||||
|
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;
|
Status status;
|
||||||
xkbNewKeyboardNotify nkn;
|
xkbNewKeyboardNotify nkn;
|
||||||
nkn.deviceID= nkn.oldDeviceID= dev->id;
|
nkn.deviceID = nkn.oldDeviceID = dev->id;
|
||||||
nkn.oldMinKeyCode= xkb->min_key_code;
|
nkn.oldMinKeyCode = xkb->min_key_code;
|
||||||
nkn.oldMaxKeyCode= xkb->max_key_code;
|
nkn.oldMaxKeyCode = xkb->max_key_code;
|
||||||
status= XkbChangeKeycodeRange(xkb,stuff->minKeyCode,stuff->maxKeyCode,
|
status= XkbChangeKeycodeRange(xkb, req->minKeyCode,
|
||||||
&change);
|
req->maxKeyCode, &change);
|
||||||
if (status!=Success)
|
if (status != Success)
|
||||||
return status;
|
return status; /* oh-oh. what about the other keyboards? */
|
||||||
nkn.minKeyCode= xkb->min_key_code;
|
nkn.minKeyCode = xkb->min_key_code;
|
||||||
nkn.maxKeyCode= xkb->max_key_code;
|
nkn.maxKeyCode = xkb->max_key_code;
|
||||||
nkn.requestMajor= XkbReqCode;
|
nkn.requestMajor = XkbReqCode;
|
||||||
nkn.requestMinor= X_kbSetMap;
|
nkn.requestMinor = X_kbSetMap;
|
||||||
nkn.changed= XkbNKN_KeycodesMask;
|
nkn.changed = XkbNKN_KeycodesMask;
|
||||||
XkbSendNewKeyboardNotify(dev,&nkn);
|
XkbSendNewKeyboardNotify(dev,&nkn);
|
||||||
sentNKN= True;
|
sentNKN = True;
|
||||||
}
|
}
|
||||||
tmp = (char *)&stuff[1];
|
|
||||||
if (stuff->present&XkbKeyTypesMask) {
|
if (req->present&XkbKeyTypesMask) {
|
||||||
tmp = SetKeyTypes(xkb,stuff,(xkbKeyTypeWireDesc *)tmp,&change);
|
values = SetKeyTypes(xkb,req,(xkbKeyTypeWireDesc *)values,&change);
|
||||||
if (!tmp) goto allocFailure;
|
if (!values) goto allocFailure;
|
||||||
}
|
}
|
||||||
if (stuff->present&XkbKeySymsMask) {
|
if (req->present&XkbKeySymsMask) {
|
||||||
tmp = SetKeySyms(client,xkb,stuff,(xkbSymMapWireDesc *)tmp,&change,dev);
|
values = SetKeySyms(client,xkb,req,(xkbSymMapWireDesc *)values,&change,dev);
|
||||||
if (!tmp) goto allocFailure;
|
if (!values) goto allocFailure;
|
||||||
}
|
}
|
||||||
if (stuff->present&XkbKeyActionsMask) {
|
if (req->present&XkbKeyActionsMask) {
|
||||||
tmp = SetKeyActions(xkb,stuff,(CARD8 *)tmp,&change);
|
values = SetKeyActions(xkb,req,(CARD8 *)values,&change);
|
||||||
if (!tmp) goto allocFailure;
|
if (!values) goto allocFailure;
|
||||||
}
|
}
|
||||||
if (stuff->present&XkbKeyBehaviorsMask) {
|
if (req->present&XkbKeyBehaviorsMask) {
|
||||||
tmp= SetKeyBehaviors(xkbi,stuff,(xkbBehaviorWireDesc *)tmp,&change);
|
values= SetKeyBehaviors(xkbi,req,(xkbBehaviorWireDesc *)values,&change);
|
||||||
if (!tmp) goto allocFailure;
|
if (!values) goto allocFailure;
|
||||||
}
|
}
|
||||||
if (stuff->present&XkbVirtualModsMask)
|
if (req->present&XkbVirtualModsMask)
|
||||||
tmp= SetVirtualMods(xkbi,stuff,(CARD8 *)tmp,&change);
|
values= SetVirtualMods(xkbi,req,(CARD8 *)values,&change);
|
||||||
if (stuff->present&XkbExplicitComponentsMask)
|
if (req->present&XkbExplicitComponentsMask)
|
||||||
tmp= SetKeyExplicit(xkbi,stuff,(CARD8 *)tmp,&change);
|
values= SetKeyExplicit(xkbi,req,(CARD8 *)values,&change);
|
||||||
if (stuff->present&XkbModifierMapMask)
|
if (req->present&XkbModifierMapMask)
|
||||||
tmp= SetModifierMap(xkbi,stuff,(CARD8 *)tmp,&change);
|
values= SetModifierMap(xkbi,req,(CARD8 *)values,&change);
|
||||||
if (stuff->present&XkbVirtualModMapMask)
|
if (req->present&XkbVirtualModMapMask)
|
||||||
tmp= SetVirtualModMap(xkbi,stuff,(xkbVModMapWireDesc *)tmp,&change);
|
values= SetVirtualModMap(xkbi,req,(xkbVModMapWireDesc *)values,&change);
|
||||||
if (((tmp-((char *)stuff))/4)!=stuff->length) {
|
if (((values-((char *)req))/4)!=req->length) {
|
||||||
ErrorF("[xkb] Internal error! Bad length in XkbSetMap (after set)\n");
|
ErrorF("[xkb] Internal error! Bad length in XkbSetMap (after set)\n");
|
||||||
client->errorValue = tmp-((char *)&stuff[1]);
|
client->errorValue = values-((char *)&req[1]);
|
||||||
return BadLength;
|
return BadLength;
|
||||||
}
|
}
|
||||||
if (stuff->flags&XkbSetMapRecomputeActions) {
|
if (req->flags&XkbSetMapRecomputeActions) {
|
||||||
KeyCode first,last,firstMM,lastMM;
|
KeyCode first,last,firstMM,lastMM;
|
||||||
if (change.map.num_key_syms>0) {
|
if (change.map.num_key_syms>0) {
|
||||||
first= change.map.first_key_sym;
|
first= change.map.first_key_sym;
|
||||||
|
@ -2516,11 +2523,82 @@ ProcXkbSetMap(ClientPtr client)
|
||||||
XkbSendNotification(dev,&change,&cause);
|
XkbSendNotification(dev,&change,&cause);
|
||||||
|
|
||||||
XkbUpdateCoreDescription(dev,False);
|
XkbUpdateCoreDescription(dev,False);
|
||||||
return client->noClientException;
|
return Success;
|
||||||
allocFailure:
|
allocFailure:
|
||||||
return BadAlloc;
|
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];
|
||||||
|
|
||||||
|
/* Check if we can to the SetMap on the requested device. If this
|
||||||
|
succeeds, do the same thing for all extension devices (if needed).
|
||||||
|
If any of them fails, fail. */
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We know now that we will succed with the SetMap. In theory anyway. */
|
||||||
|
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);
|
||||||
|
/* ignore rc. if the SetMap failed although the check above
|
||||||
|
reported true there isn't much we can do. we still need to
|
||||||
|
set all other devices, hoping that at least they stay in
|
||||||
|
sync. */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return client->noClientException;
|
||||||
|
}
|
||||||
|
|
||||||
/***====================================================================***/
|
/***====================================================================***/
|
||||||
|
|
||||||
static Status
|
static Status
|
||||||
|
|
Loading…
Reference in New Issue