xkb: ProcXkbBell 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.
(cherry picked from commit 31afd51dd4)
This commit is contained in:
Peter Hutterer 2008-08-01 16:32:37 +09:30 committed by Peter Hutterer
parent 50382652af
commit 2fa7edd30d

229
xkb/xkb.c
View File

@ -348,17 +348,119 @@ ProcXkbSelectEvents(ClientPtr client)
}
/***====================================================================***/
/**
* Ring a bell on the given device for the given client.
*/
static int
_XkbBell(ClientPtr client, DeviceIntPtr dev, WindowPtr pWin,
int bellClass, int bellID, int pitch, int duration,
int percent, int forceSound, int eventOnly, Atom name)
{
int base;
pointer ctrl;
int oldPitch, oldDuration;
int newPercent;
if (bellClass == KbdFeedbackClass) {
KbdFeedbackPtr k;
if (bellID==XkbDfltXIId)
k= dev->kbdfeed;
else {
for (k=dev->kbdfeed; k; k=k->next) {
if (k->ctrl.id == bellID)
break;
}
}
if (!k) {
client->errorValue = _XkbErrCode2(0x5,bellID);
return BadValue;
}
base = k->ctrl.bell;
ctrl = (pointer) &(k->ctrl);
oldPitch= k->ctrl.bell_pitch;
oldDuration= k->ctrl.bell_duration;
if (pitch!=0) {
if (pitch==-1)
k->ctrl.bell_pitch= defaultKeyboardControl.bell_pitch;
else k->ctrl.bell_pitch= pitch;
}
if (duration!=0) {
if (duration==-1)
k->ctrl.bell_duration= defaultKeyboardControl.bell_duration;
else k->ctrl.bell_duration= duration;
}
}
else if (bellClass == BellFeedbackClass) {
BellFeedbackPtr b;
if (bellID==XkbDfltXIId)
b= dev->bell;
else {
for (b=dev->bell; b; b=b->next) {
if (b->ctrl.id == bellID)
break;
}
}
if (!b) {
client->errorValue = _XkbErrCode2(0x6,bellID);
return BadValue;
}
base = b->ctrl.percent;
ctrl = (pointer) &(b->ctrl);
oldPitch= b->ctrl.pitch;
oldDuration= b->ctrl.duration;
if (pitch!=0) {
if (pitch==-1)
b->ctrl.pitch= defaultKeyboardControl.bell_pitch;
else b->ctrl.pitch= pitch;
}
if (duration!=0) {
if (duration==-1)
b->ctrl.duration= defaultKeyboardControl.bell_duration;
else b->ctrl.duration= duration;
}
}
else {
client->errorValue = _XkbErrCode2(0x7, bellClass);;
return BadValue;
}
newPercent = (base * percent)/100;
if (percent < 0)
newPercent = base + newPercent;
else newPercent = base - newPercent + percent;
XkbHandleBell(forceSound, eventOnly,
dev, newPercent, ctrl, bellClass,
name, pWin, client);
if ((pitch!=0)||(duration!=0)) {
if (bellClass == KbdFeedbackClass) {
KbdFeedbackPtr k;
k= (KbdFeedbackPtr)ctrl;
if (pitch!=0)
k->ctrl.bell_pitch= oldPitch;
if (duration!=0)
k->ctrl.bell_duration= oldDuration;
}
else {
BellFeedbackPtr b;
b= (BellFeedbackPtr)ctrl;
if (pitch!=0)
b->ctrl.pitch= oldPitch;
if (duration!=0)
b->ctrl.duration= oldDuration;
}
}
return Success;
}
/* FIXME: Needs to ding on all core-sending devices. */
int
ProcXkbBell(ClientPtr client)
{
REQUEST(xkbBellReq);
DeviceIntPtr dev;
WindowPtr pWin;
int rc, base;
int newPercent,oldPitch,oldDuration;
pointer ctrl;
int rc;
REQUEST_SIZE_MATCH(xkbBellReq);
@ -368,6 +470,7 @@ ProcXkbBell(ClientPtr client)
CHK_BELL_DEVICE(dev, stuff->deviceSpec, client, DixBellAccess);
CHK_ATOM_OR_NONE(stuff->name);
/* device-independent checks request for sane values */
if ((stuff->forceSound)&&(stuff->eventOnly)) {
client->errorValue=_XkbErrCode3(0x1,stuff->forceSound,stuff->eventOnly);
return BadMatch;
@ -390,68 +493,7 @@ ProcXkbBell(ClientPtr client)
stuff->bellClass= KbdFeedbackClass;
else stuff->bellClass= BellFeedbackClass;
}
if (stuff->bellClass == KbdFeedbackClass) {
KbdFeedbackPtr k;
if (stuff->bellID==XkbDfltXIId)
k= dev->kbdfeed;
else {
for (k=dev->kbdfeed; k; k=k->next) {
if (k->ctrl.id == stuff->bellID)
break;
}
}
if (!k) {
client->errorValue= _XkbErrCode2(0x5,stuff->bellID);
return BadValue;
}
base = k->ctrl.bell;
ctrl = (pointer) &(k->ctrl);
oldPitch= k->ctrl.bell_pitch;
oldDuration= k->ctrl.bell_duration;
if (stuff->pitch!=0) {
if (stuff->pitch==-1)
k->ctrl.bell_pitch= defaultKeyboardControl.bell_pitch;
else k->ctrl.bell_pitch= stuff->pitch;
}
if (stuff->duration!=0) {
if (stuff->duration==-1)
k->ctrl.bell_duration= defaultKeyboardControl.bell_duration;
else k->ctrl.bell_duration= stuff->duration;
}
}
else if (stuff->bellClass == BellFeedbackClass) {
BellFeedbackPtr b;
if (stuff->bellID==XkbDfltXIId)
b= dev->bell;
else {
for (b=dev->bell; b; b=b->next) {
if (b->ctrl.id == stuff->bellID)
break;
}
}
if (!b) {
client->errorValue = _XkbErrCode2(0x6,stuff->bellID);
return BadValue;
}
base = b->ctrl.percent;
ctrl = (pointer) &(b->ctrl);
oldPitch= b->ctrl.pitch;
oldDuration= b->ctrl.duration;
if (stuff->pitch!=0) {
if (stuff->pitch==-1)
b->ctrl.pitch= defaultKeyboardControl.bell_pitch;
else b->ctrl.pitch= stuff->pitch;
}
if (stuff->duration!=0) {
if (stuff->duration==-1)
b->ctrl.duration= defaultKeyboardControl.bell_duration;
else b->ctrl.duration= stuff->duration;
}
}
else {
client->errorValue = _XkbErrCode2(0x7,stuff->bellClass);;
return BadValue;
}
if (stuff->window!=None) {
rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
if (rc != Success) {
@ -461,32 +503,39 @@ ProcXkbBell(ClientPtr client)
}
else pWin= NULL;
newPercent= (base*stuff->percent)/100;
if (stuff->percent < 0)
newPercent= base+newPercent;
else newPercent= base-newPercent+stuff->percent;
XkbHandleBell(stuff->forceSound, stuff->eventOnly,
dev, newPercent, ctrl, stuff->bellClass,
stuff->name, pWin, client);
if ((stuff->pitch!=0)||(stuff->duration!=0)) {
if (stuff->bellClass == KbdFeedbackClass) {
KbdFeedbackPtr k;
k= (KbdFeedbackPtr)ctrl;
if (stuff->pitch!=0)
k->ctrl.bell_pitch= oldPitch;
if (stuff->duration!=0)
k->ctrl.bell_duration= oldDuration;
}
else {
BellFeedbackPtr b;
b= (BellFeedbackPtr)ctrl;
if (stuff->pitch!=0)
b->ctrl.pitch= oldPitch;
if (stuff->duration!=0)
b->ctrl.duration= oldDuration;
/* Client wants to ring a bell on the core keyboard?
Ring the bell on the core keyboard (which does nothing, but if that
fails the client is screwed anyway), and then on all extension devices.
Fail if the core keyboard fails but not the extension devices. this
may cause some keyboards to ding and others to stay silent. Fix
your client to use explicit keyboards to avoid this.
dev is the device the client requested.
*/
rc = _XkbBell(client, dev, pWin, stuff->bellClass, stuff->bellID,
stuff->pitch, stuff->duration, stuff->percent,
stuff->forceSound, stuff->eventOnly, stuff->name);
if ((rc == Success) && ((stuff->deviceSpec == XkbUseCoreKbd) ||
(stuff->deviceSpec == XkbUseCorePtr)))
{
DeviceIntPtr other;
for (other = inputInfo.devices; other; other = other->next)
{
if ((other != dev) && other->key && other->coreEvents)
{
rc = XaceHook(XACE_DEVICE_ACCESS, client, other, DixBellAccess);
if (rc == Success)
_XkbBell(client, other, pWin, stuff->bellClass,
stuff->bellID, stuff->pitch, stuff->duration,
stuff->percent, stuff->forceSound,
stuff->eventOnly, stuff->name);
}
}
return Success;
rc = Success; /* reset to success, that's what we got for the VCK */
}
return rc;
}
/***====================================================================***/