xkb: ProcXkbSetNamedIndicator 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:40:25 +09:30
parent a609dbed7c
commit 7e45c80204

189
xkb/xkb.c
View File

@ -3264,65 +3264,104 @@ ProcXkbGetNamedIndicator(ClientPtr client)
return client->noClientException; return client->noClientException;
} }
/* FIXME: Needs to set indicator on all core-sending devices. */
int /**
ProcXkbSetNamedIndicator(ClientPtr client) * Find the IM on the device.
* Returns the map, or NULL if the map doesn't exist.
* If the return value is NULL, led_return is undefined. Otherwise, led_return
* is set to the led index of the map.
*/
static XkbIndicatorMapPtr
_XkbFindNamedIndicatorMap(XkbSrvLedInfoPtr sli, Atom indicator,
int *led_return)
{ {
DeviceIntPtr dev,kbd;
XkbIndicatorMapPtr map; XkbIndicatorMapPtr map;
XkbSrvLedInfoPtr sli; int led;
register int led = 0;
unsigned extDevReason;
unsigned statec,namec,mapc;
XkbEventCauseRec cause;
xkbExtensionDeviceNotify ed;
XkbChangesRec changes;
REQUEST(xkbSetNamedIndicatorReq); /* search for the right indicator */
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);
extDevReason= 0;
sli= XkbFindSrvLedInfo(dev,stuff->ledClass,stuff->ledID,
XkbXI_IndicatorsMask);
if (!sli)
return BadAlloc;
statec= mapc= namec= 0;
map = NULL; map = NULL;
if (sli->names && sli->maps) { if (sli->names && sli->maps) {
for (led = 0; (led < XkbNumIndicators) && (map == NULL); led++) { for (led = 0; (led < XkbNumIndicators) && (map == NULL); led++) {
if (sli->names[led]==stuff->indicator) { if (sli->names[led] == indicator) {
map= &sli->maps[led]; map= &sli->maps[led];
break; break;
} }
} }
} }
if (map==NULL) {
if (!stuff->createMap) *led_return = led;
return client->noClientException; return map;
}
/**
* Creates an indicator map on the device. If dryRun is True, it only checks
* if creation is possible, but doesn't actually create it.
*/
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)
{
/* find first unused indicator maps and assign the name to it */
for (led = 0, map = NULL; (led < XkbNumIndicators) && (map == NULL); led++) { for (led = 0, map = NULL; (led < XkbNumIndicators) && (map == NULL); led++) {
if ((sli->names) && (sli->maps) && (sli->names[led] == None) && if ((sli->names) && (sli->maps) && (sli->names[led] == None) &&
(!XkbIM_InUse(&sli->maps[led]))) { (!XkbIM_InUse(&sli->maps[led])))
{
map = &sli->maps[led]; map = &sli->maps[led];
sli->names[led]= stuff->indicator; if (!dryRun)
sli->names[led] = indicator;
break; break;
} }
} }
if (map==NULL) }
return client->noClientException;
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) /* oh-oh */
return rc;
namec = mapc = statec = 0;
extDevReason = 0;
namec |= (1<<led); namec |= (1<<led);
sli->namesPresent |= ((stuff->indicator != None) ? (1 << led) : 0); sli->namesPresent |= ((stuff->indicator != None) ? (1 << led) : 0);
extDevReason |= XkbXI_IndicatorNamesMask; extDevReason |= XkbXI_IndicatorNamesMask;
}
if (stuff->setMap) { if (stuff->setMap) {
map->flags = stuff->flags; map->flags = stuff->flags;
@ -3335,11 +3374,14 @@ ProcXkbSetNamedIndicator(ClientPtr client)
map->ctrls = stuff->ctrls; map->ctrls = stuff->ctrls;
mapc|= (1<<led); mapc|= (1<<led);
} }
if ((stuff->setState)&&((map->flags&XkbIM_NoExplicit)==0)) {
if ((stuff->setState) && ((map->flags & XkbIM_NoExplicit) == 0))
{
if (stuff->on) sli->explicitState |= (1<<led); if (stuff->on) sli->explicitState |= (1<<led);
else sli->explicitState &= ~(1<<led); else sli->explicitState &= ~(1<<led);
statec |= ((sli->effectiveState ^ sli->explicitState) & (1 << led)); statec |= ((sli->effectiveState ^ sli->explicitState) & (1 << led));
} }
bzero((char *)&ed,sizeof(xkbExtensionDeviceNotify)); bzero((char *)&ed,sizeof(xkbExtensionDeviceNotify));
bzero((char *)&changes,sizeof(XkbChangesRec)); bzero((char *)&changes,sizeof(XkbChangesRec));
XkbSetCauseXkbReq(&cause,X_kbSetNamedIndicator,client); XkbSetCauseXkbReq(&cause,X_kbSetNamedIndicator,client);
@ -3354,6 +3396,73 @@ ProcXkbSetNamedIndicator(ClientPtr client)
if ((sli->flags&XkbSLI_HasOwnState)==0) if ((sli->flags&XkbSLI_HasOwnState)==0)
kbd = inputInfo.keyboard; kbd = inputInfo.keyboard;
XkbFlushLedEvents(dev, kbd, sli, &ed, &changes, &cause); 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);
/* Dry-run for checks */
rc = _XkbCreateIndicatorMap(dev, stuff->indicator,
stuff->ledClass, stuff->ledID,
&map, &led, TRUE);
if (rc != Success || !map) /* couldn't be created or didn't exist */
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) &&
(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;
}
}
}
/* All checks passed, let's do it */
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) &&
(XaceHook(XACE_DEVICE_ACCESS, client, other, DixSetAttrAccess) == Success))
{
_XkbSetNamedIndicator(client, other, stuff);
}
}
}
return client->noClientException; return client->noClientException;
} }