summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Hutterer <peter.hutterer@who-t.net>2008-08-01 16:37:39 +0930
committerPeter Hutterer <peter.hutterer@who-t.net>2008-08-06 11:12:24 +0930
commite8c2a3d7c996cb41c4c44ba67acae5ff9438fc06 (patch)
tree58d8b49c503b739b1b4d4f4dac058b109021dc24
parent3c7740aa8f21c1fda4190a1bf5d6ce089db5e35b (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.c170
1 files changed, 118 insertions, 52 deletions
diff --git a/xkb/xkb.c b/xkb/xkb.c
index 722c13bce..ea11e6f76 100644
--- a/xkb/xkb.c
+++ b/xkb/xkb.c
@@ -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;
}