diff options
author | Peter Hutterer <peter.hutterer@who-t.net> | 2008-08-01 16:37:39 +0930 |
---|---|---|
committer | Peter Hutterer <peter.hutterer@who-t.net> | 2008-08-06 11:12:24 +0930 |
commit | e8c2a3d7c996cb41c4c44ba67acae5ff9438fc06 (patch) | |
tree | 58d8b49c503b739b1b4d4f4dac058b109021dc24 | |
parent | 3c7740aa8f21c1fda4190a1bf5d6ce089db5e35b (diff) |
xkb: ProcXkbSetCompatMap 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.
-rw-r--r-- | xkb/xkb.c | 170 |
1 files changed, 118 insertions, 52 deletions
@@ -2727,57 +2727,58 @@ ProcXkbGetCompatMap(ClientPtr client) return XkbSendCompatMap(client,compat,&rep); } -/* FIXME: Needs to set compat map on all core-sending devices. */ -int -ProcXkbSetCompatMap(ClientPtr client) +/** + * Apply the given request on the given device. + * If dryRun is True, then value checks are performed, but the device isn't + * modified. + */ +static int +_XkbSetCompatMap(ClientPtr client, DeviceIntPtr dev, + xkbSetCompatMapReq *req, char* data, BOOL dryRun) { - DeviceIntPtr dev; - XkbSrvInfoPtr xkbi; - XkbDescPtr xkb; - XkbCompatMapPtr compat; - char * data; - int nGroups; - register unsigned i,bit; - - REQUEST(xkbSetCompatMapReq); - REQUEST_AT_LEAST_SIZE(xkbSetCompatMapReq); - - if (!(client->xkbClientFlags&_XkbClientInitialized)) - return BadAccess; - - CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess); + XkbSrvInfoPtr xkbi; + XkbDescPtr xkb; + XkbCompatMapPtr compat; + int nGroups; + unsigned i,bit; - data = (char *)&stuff[1]; xkbi = dev->key->xkbInfo; - xkb= xkbi->desc; - compat= xkb->compat; - if ((stuff->nSI>0)||(stuff->truncateSI)) { + xkb = xkbi->desc; + compat = xkb->compat; + + if ((req->nSI>0)||(req->truncateSI)) { xkbSymInterpretWireDesc *wire; - if (stuff->firstSI>compat->num_si) { + if (req->firstSI>compat->num_si) { client->errorValue = _XkbErrCode2(0x02,compat->num_si); return BadValue; } wire= (xkbSymInterpretWireDesc *)data; - wire+= stuff->nSI; + wire+= req->nSI; data = (char *)wire; } + nGroups= 0; - if (stuff->groups!=0) { + if (req->groups!=0) { for (i=0,bit=1;i<XkbNumKbdGroups;i++,bit<<=1) { - if ( stuff->groups&bit ) + if ( req->groups&bit ) nGroups++; } } data+= nGroups*SIZEOF(xkbModsWireDesc); - if (((data-((char *)stuff))/4)!=stuff->length) { + if (((data-((char *)req))/4)!=req->length) { return BadLength; } - data = (char *)&stuff[1]; - if (stuff->nSI>0) { + + /* Done all the checks we can do */ + if (dryRun) + return Success; + + data = (char *)&req[1]; + if (req->nSI>0) { xkbSymInterpretWireDesc *wire = (xkbSymInterpretWireDesc *)data; XkbSymInterpretPtr sym; - if ((unsigned)(stuff->firstSI+stuff->nSI)>compat->num_si) { - compat->num_si= stuff->firstSI+stuff->nSI; + 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); @@ -2786,13 +2787,13 @@ ProcXkbSetCompatMap(ClientPtr client) return BadAlloc; } } - else if (stuff->truncateSI) { - compat->num_si = stuff->firstSI+stuff->nSI; + else if (req->truncateSI) { + compat->num_si = req->firstSI+req->nSI; } - sym = &compat->sym_interpret[stuff->firstSI]; - for (i=0;i<stuff->nSI;i++,wire++,sym++) { + sym = &compat->sym_interpret[req->firstSI]; + for (i=0;i<req->nSI;i++,wire++,sym++) { if (client->swapped) { - register int n; + int n; swapl(&wire->sym,n); } sym->sym= wire->sym; @@ -2801,21 +2802,21 @@ ProcXkbSetCompatMap(ClientPtr client) sym->flags= wire->flags; sym->virtual_mod= wire->virtualMod; memcpy((char *)&sym->act,(char *)&wire->act, - SIZEOF(xkbActionWireDesc)); + SIZEOF(xkbActionWireDesc)); } data = (char *)wire; } - else if (stuff->truncateSI) { - compat->num_si = stuff->firstSI; + else if (req->truncateSI) { + compat->num_si = req->firstSI; } - if (stuff->groups!=0) { - register unsigned i,bit; + if (req->groups!=0) { + unsigned i, bit; xkbModsWireDesc *wire = (xkbModsWireDesc *)data; - for (i=0,bit=1;i<XkbNumKbdGroups;i++,bit<<=1) { - if (stuff->groups&bit) { + for (i = 0, bit = 1; i < XkbNumKbdGroups; i++, bit <<= 1) { + if (req->groups & bit) { if (client->swapped) { - register int n; + int n; swaps(&wire->virtualMods,n); } compat->groups[i].mask= wire->realMods; @@ -2831,23 +2832,23 @@ ProcXkbSetCompatMap(ClientPtr client) } } } - i= XkbPaddedSize((data-((char *)stuff))); - if ((i/4)!=stuff->length) { - ErrorF("[xkb] Internal length error on read in ProcXkbSetCompatMap\n"); + 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 = stuff->groups; - ev.firstSI = stuff->firstSI; - ev.nSI = stuff->nSI; + ev.changedGroups = req->groups; + ev.firstSI = req->firstSI; + ev.nSI = req->nSI; ev.nTotalSI = compat->num_si; XkbSendCompatMapNotify(dev,&ev); } - if (stuff->recomputeActions) { + if (req->recomputeActions) { XkbChangesRec change; unsigned check; XkbEventCauseRec cause; @@ -2861,6 +2862,71 @@ ProcXkbSetCompatMap(ClientPtr client) 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]; + + /* check first using a dry-run */ + 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) + { + /* dry-run */ + rc = _XkbSetCompatMap(client, other, stuff, data, TRUE); + if (rc != Success) + return rc; + } + } + } + } + + /* Yay, the dry-runs succeed. Let's apply */ + 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; + } + } + } + } + return client->noClientException; } |