debian/patches/130_fedora_fix_procxkbsetxyz_to_work_on_all.patch | 2245 ++++++++++ debian/patches/136_fedora_force_switchcorekeyboard_for_evdev.patch | 69 2 files changed, 2314 insertions(+)
New commits: commit 02def36766818699103799a478a44a3d0e17eac0 Author: Timo Aaltonen <[EMAIL PROTECTED]> Date: Wed Aug 6 13:56:10 2008 +0300 actually add the patches. diff --git a/debian/patches/130_fedora_fix_procxkbsetxyz_to_work_on_all.patch b/debian/patches/130_fedora_fix_procxkbsetxyz_to_work_on_all.patch new file mode 100644 index 0000000..13e197a --- /dev/null +++ b/debian/patches/130_fedora_fix_procxkbsetxyz_to_work_on_all.patch @@ -0,0 +1,2245 @@ +From 6d1201b05ed61aec508d5d9f88e3a2d33be39849 Mon Sep 17 00:00:00 2001 +From: Peter Hutterer <[EMAIL PROTECTED]> +Date: Thu, 31 Jul 2008 16:03:21 +0930 +Subject: [PATCH] xkb: fix up ProcXkbSetXYZ to work on all core devices. + +Simple principle: if the client requests an xkb change on the core keyboard, +apply the same change to all core-sending keyboard devices. This way, if you +change the layout on the VCK, you get the same layout on all devices. + +That's the theory anyway, the implementation makes you want to gauge your eyes +out. +--- + xkb/xkb.c | 1880 +++++++++++++++++++++++++++++++++++++++---------------------- + 1 files changed, 1210 insertions(+), 670 deletions(-) + +diff --git a/xkb/xkb.c b/xkb/xkb.c +index 07f57a7..cc2f77c 100644 +--- a/xkb/xkb.c ++++ b/xkb/xkb.c +@@ -24,6 +24,31 @@ THE USE OR PERFORMANCE OF THIS SOFTWARE. + + ********************************************************/ + ++/* Copyright © 2008 Red Hat, Inc. ++ ++Permission is hereby granted, free of charge, to any person obtaining a ++copy of this software and associated documentation files (the "Software"), ++to deal in the Software without restriction, including without limitation ++the rights to use, copy, modify, merge, publish, distribute, sublicense, ++and/or sell copies of the Software, and to permit persons to whom the ++Software is furnished to do so, subject to the following conditions: ++ ++The above copyright notice and this permission notice (including the next ++paragraph) shall be included in all copies or substantial portions of the ++Software. ++ ++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ++THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING ++FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER ++DEALINGS IN THE SOFTWARE. ++ ++Authors: Peter Hutterer ++ ++*/ ++ + #ifdef HAVE_DIX_CONFIG_H + #include <dix-config.h> + #endif +@@ -348,17 +373,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 +495,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 +518,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 +528,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); ++ } ++ } ++ rc = Success; /* reset to success, that's what we got for the VCK */ + } +- return Success; ++ ++ return rc; + } + + /***====================================================================***/ +@@ -2283,158 +2357,165 @@ XkbServerMapPtr srv = xkbi->desc->server; + return (char *)wire; + } + +-/* FIXME: Needs to set map on all core-sending devices. */ +-int +-ProcXkbSetMap(ClientPtr client) ++/** ++ * Check if the given request can be applied to the given device but don't ++ * actually do anything.. ++ */ ++static int ++_XkbSetMapChecks(ClientPtr client, DeviceIntPtr dev, xkbSetMapReq *req, char* values) + { +- DeviceIntPtr dev; +- XkbSrvInfoPtr xkbi; +- XkbDescPtr xkb; +- XkbChangesRec change; +- XkbEventCauseRec cause; +- int nTypes = 0,nActions,error; +- 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); ++ XkbSrvInfoPtr xkbi; ++ XkbDescPtr xkb; ++ int error; ++ int nTypes = 0, nActions; ++ CARD8 mapWidths[XkbMaxLegalKeyCode + 1]; ++ CARD16 symsPerKey[XkbMaxLegalKeyCode + 1]; + +- XkbSetCauseXkbReq(&cause,X_kbSetMap,client); + xkbi= dev->key->xkbInfo; + xkb = xkbi->desc; + +- if ((xkb->min_key_code!=stuff->minKeyCode)|| +- (xkb->max_key_code!=stuff->maxKeyCode)) { ++ if ((xkb->min_key_code != req->minKeyCode)|| ++ (xkb->max_key_code != req->maxKeyCode)) { + if (client->vMajor!=1) { /* pre 1.0 versions of Xlib have a bug */ +- stuff->minKeyCode= xkb->min_key_code; +- stuff->maxKeyCode= xkb->max_key_code; ++ req->minKeyCode= xkb->min_key_code; ++ req->maxKeyCode= xkb->max_key_code; + } + else { +- if (!XkbIsLegalKeycode(stuff->minKeyCode)) { +- client->errorValue= _XkbErrCode3(2,stuff->minKeyCode, +- stuff->maxKeyCode); ++ if (!XkbIsLegalKeycode(req->minKeyCode)) { ++ client->errorValue = _XkbErrCode3(2, req->minKeyCode, req->maxKeyCode); + return BadValue; + } +- if (stuff->minKeyCode>stuff->maxKeyCode) { +- client->errorValue= _XkbErrCode3(3,stuff->minKeyCode, +- stuff->maxKeyCode); ++ if (req->minKeyCode > req->maxKeyCode) { ++ client->errorValue = _XkbErrCode3(3, req->minKeyCode, req->maxKeyCode); + return BadMatch; + } + } + } + +- tmp = (char *)&stuff[1]; +- if ((stuff->present&XkbKeyTypesMask)&& +- (!CheckKeyTypes(client,xkb,stuff,(xkbKeyTypeWireDesc **)&tmp, ++ if ((req->present & XkbKeyTypesMask) && ++ (!CheckKeyTypes(client,xkb,req,(xkbKeyTypeWireDesc **)&values, + &nTypes,mapWidths))) { + client->errorValue = nTypes; + return BadValue; + } +- if ((stuff->present&XkbKeySymsMask)&& +- (!CheckKeySyms(client,xkb,stuff,nTypes,mapWidths,symsPerKey, +- (xkbSymMapWireDesc **)&tmp,&error))) { ++ if ((req->present & XkbKeySymsMask) && ++ (!CheckKeySyms(client,xkb,req,nTypes,mapWidths,symsPerKey, ++ (xkbSymMapWireDesc **)&values,&error))) { + client->errorValue = error; + return BadValue; + } + +- if ((stuff->present&XkbKeyActionsMask)&& +- (!CheckKeyActions(xkb,stuff,nTypes,mapWidths,symsPerKey, +- (CARD8 **)&tmp,&nActions))) { ++ if ((req->present & XkbKeyActionsMask) && ++ (!CheckKeyActions(xkb,req,nTypes,mapWidths,symsPerKey, ++ (CARD8 **)&values,&nActions))) { + client->errorValue = nActions; + return BadValue; + } + +- if ((stuff->present&XkbKeyBehaviorsMask)&& +- (!CheckKeyBehaviors(xkb,stuff,(xkbBehaviorWireDesc**)&tmp,&error))) { ++ if ((req->present & XkbKeyBehaviorsMask) && ++ (!CheckKeyBehaviors(xkb,req,(xkbBehaviorWireDesc**)&values,&error))) { + client->errorValue = error; + return BadValue; + } + +- if ((stuff->present&XkbVirtualModsMask)&& +- (!CheckVirtualMods(xkb,stuff,(CARD8 **)&tmp,&error))) { ++ if ((req->present & XkbVirtualModsMask) && ++ (!CheckVirtualMods(xkb,req,(CARD8 **)&values,&error))) { + client->errorValue= error; + return BadValue; + } +- if ((stuff->present&XkbExplicitComponentsMask)&& +- (!CheckKeyExplicit(xkb,stuff,(CARD8 **)&tmp,&error))) { ++ if ((req->present&XkbExplicitComponentsMask) && ++ (!CheckKeyExplicit(xkb,req,(CARD8 **)&values,&error))) { + client->errorValue= error; + return BadValue; + } +- if ((stuff->present&XkbModifierMapMask)&& +- (!CheckModifierMap(xkb,stuff,(CARD8 **)&tmp,&error))) { ++ if ((req->present&XkbModifierMapMask) && ++ (!CheckModifierMap(xkb,req,(CARD8 **)&values,&error))) { + client->errorValue= error; + return BadValue; + } +- if ((stuff->present&XkbVirtualModMapMask)&& +- (!CheckVirtualModMap(xkb,stuff,(xkbVModMapWireDesc **)&tmp,&error))) { ++ if ((req->present&XkbVirtualModMapMask) && ++ (!CheckVirtualModMap(xkb,req,(xkbVModMapWireDesc **)&values,&error))) { + client->errorValue= error; + return BadValue; + } +- if (((tmp-((char *)stuff))/4)!=stuff->length) { ++ ++ if (((values-((char *)req))/4)!= req->length) { + ErrorF("Internal error! Bad length in XkbSetMap (after check)\n"); +- client->errorValue = tmp-((char *)&stuff[1]); ++ client->errorValue = values-((char *)&req[1]); + return BadLength; + } +- bzero(&change,sizeof(change)); +- sentNKN= False; +- if ((xkb->min_key_code!=stuff->minKeyCode)|| +- (xkb->max_key_code!=stuff->maxKeyCode)) { ++ ++ return Success; ++} ++ ++/** ++ * 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; + xkbNewKeyboardNotify nkn; +- nkn.deviceID= nkn.oldDeviceID= dev->id; +- nkn.oldMinKeyCode= xkb->min_key_code; +- nkn.oldMaxKeyCode= xkb->max_key_code; +- status= XkbChangeKeycodeRange(xkb,stuff->minKeyCode,stuff->maxKeyCode, +- &change); +- if (status!=Success) +- return status; +- nkn.minKeyCode= xkb->min_key_code; +- nkn.maxKeyCode= xkb->max_key_code; +- nkn.requestMajor= XkbReqCode; +- nkn.requestMinor= X_kbSetMap; +- nkn.changed= XkbNKN_KeycodesMask; ++ nkn.deviceID = nkn.oldDeviceID = dev->id; ++ nkn.oldMinKeyCode = xkb->min_key_code; ++ nkn.oldMaxKeyCode = xkb->max_key_code; ++ status= XkbChangeKeycodeRange(xkb, req->minKeyCode, ++ req->maxKeyCode, &change); ++ if (status != Success) ++ return status; /* oh-oh. what about the other keyboards? */ ++ nkn.minKeyCode = xkb->min_key_code; ++ nkn.maxKeyCode = xkb->max_key_code; ++ nkn.requestMajor = XkbReqCode; ++ nkn.requestMinor = X_kbSetMap; ++ nkn.changed = XkbNKN_KeycodesMask; + XkbSendNewKeyboardNotify(dev,&nkn); +- sentNKN= True; +- } +- tmp = (char *)&stuff[1]; +- if (stuff->present&XkbKeyTypesMask) { +- tmp = SetKeyTypes(xkb,stuff,(xkbKeyTypeWireDesc *)tmp,&change); +- if (!tmp) goto allocFailure; +- } +- if (stuff->present&XkbKeySymsMask) { +- tmp = SetKeySyms(client,xkb,stuff,(xkbSymMapWireDesc *)tmp,&change,dev); +- if (!tmp) goto allocFailure; +- } +- if (stuff->present&XkbKeyActionsMask) { +- tmp = SetKeyActions(xkb,stuff,(CARD8 *)tmp,&change); +- if (!tmp) goto allocFailure; +- } +- if (stuff->present&XkbKeyBehaviorsMask) { +- tmp= SetKeyBehaviors(xkbi,stuff,(xkbBehaviorWireDesc *)tmp,&change); +- if (!tmp) goto allocFailure; +- } +- if (stuff->present&XkbVirtualModsMask) +- tmp= SetVirtualMods(xkbi,stuff,(CARD8 *)tmp,&change); +- if (stuff->present&XkbExplicitComponentsMask) +- tmp= SetKeyExplicit(xkbi,stuff,(CARD8 *)tmp,&change); +- if (stuff->present&XkbModifierMapMask) +- tmp= SetModifierMap(xkbi,stuff,(CARD8 *)tmp,&change); +- if (stuff->present&XkbVirtualModMapMask) +- tmp= SetVirtualModMap(xkbi,stuff,(xkbVModMapWireDesc *)tmp,&change); +- if (((tmp-((char *)stuff))/4)!=stuff->length) { ++ sentNKN = True; ++ } ++ ++ if (req->present&XkbKeyTypesMask) { ++ values = SetKeyTypes(xkb,req,(xkbKeyTypeWireDesc *)values,&change); ++ if (!values) goto allocFailure; ++ } ++ if (req->present&XkbKeySymsMask) { ++ values = SetKeySyms(client,xkb,req,(xkbSymMapWireDesc *)values,&change,dev); ++ if (!values) goto allocFailure; ++ } ++ if (req->present&XkbKeyActionsMask) { ++ values = SetKeyActions(xkb,req,(CARD8 *)values,&change); ++ if (!values) goto allocFailure; ++ } ++ if (req->present&XkbKeyBehaviorsMask) { ++ values= SetKeyBehaviors(xkbi,req,(xkbBehaviorWireDesc *)values,&change); ++ if (!values) goto allocFailure; ++ } ++ if (req->present&XkbVirtualModsMask) ++ values= SetVirtualMods(xkbi,req,(CARD8 *)values,&change); ++ if (req->present&XkbExplicitComponentsMask) ++ values= SetKeyExplicit(xkbi,req,(CARD8 *)values,&change); ++ if (req->present&XkbModifierMapMask) ++ values= SetModifierMap(xkbi,req,(CARD8 *)values,&change); ++ if (req->present&XkbVirtualModMapMask) ++ values= SetVirtualModMap(xkbi,req,(xkbVModMapWireDesc *)values,&change); ++ if (((values-((char *)req))/4)!=req->length) { + ErrorF("Internal error! Bad length in XkbSetMap (after set)\n"); +- client->errorValue = tmp-((char *)&stuff[1]); ++ client->errorValue = values-((char *)&req[1]); + return BadLength; + } +- if (stuff->flags&XkbSetMapRecomputeActions) { ++ if (req->flags&XkbSetMapRecomputeActions) { + KeyCode first,last,firstMM,lastMM; + if (change.map.num_key_syms>0) { + first= change.map.first_key_sym; +@@ -2467,11 +2548,82 @@ ProcXkbSetMap(ClientPtr client) + XkbSendNotification(dev,&change,&cause); + + XkbUpdateCoreDescription(dev,False); +- return client->noClientException; ++ return Success; + allocFailure: + 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->coreEvents) ++ { ++ 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->coreEvents) ++ { ++ 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 +@@ -2600,57 +2752,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; ++ XkbSrvInfoPtr xkbi; ++ XkbDescPtr xkb; ++ XkbCompatMapPtr compat; ++ int nGroups; ++ unsigned i,bit; + +- 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]; + 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); +@@ -2659,13 +2812,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; +@@ -2674,21 +2827,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; +@@ -2704,23 +2857,23 @@ ProcXkbSetCompatMap(ClientPtr client) + } + } + } +- i= XkbPaddedSize((data-((char *)stuff))); +- if ((i/4)!=stuff->length) { +- ErrorF("Internal length error on read in ProcXkbSetCompatMap\n"); ++ i= XkbPaddedSize((data-((char *)req))); ++ if ((i/4)!=req->length) { ++ ErrorF("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; +@@ -2734,6 +2887,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->coreEvents) ++ { ++ 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->coreEvents) ++ { ++ 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; + } + +@@ -2878,17 +3096,59 @@ XkbIndicatorPtr leds; + return XkbSendIndicatorMap(client,leds,&rep); + } + +-/* FIXME: Needs to set indicator map on all core-sending devices. */ ++/** ++ * Apply the given map to the given device. Which specifies which components ++ * to apply. ++ */ ++static int ++_XkbSetIndicatorMap(ClientPtr client, DeviceIntPtr dev, ++ int which, xkbIndicatorMapWireDesc *desc) ++{ ++ XkbSrvInfoPtr xkbi; ++ XkbSrvLedInfoPtr sli; ++ XkbEventCauseRec cause; ++ int i, bit; ++ ++ xkbi = dev->key->xkbInfo; ++ ++ sli= XkbFindSrvLedInfo(dev, XkbDfltXIClass, XkbDfltXIId, ++ XkbXI_IndicatorMapsMask); ++ if (!sli) ++ return BadAlloc; ++ ++ for (i = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) { ++ if (which & bit) { ++ sli->maps[i].flags = desc->flags; ++ sli->maps[i].which_groups = desc->whichGroups; ++ sli->maps[i].groups = desc->groups; ++ sli->maps[i].which_mods = desc->whichMods; ++ sli->maps[i].mods.mask = desc->mods; ++ sli->maps[i].mods.real_mods = desc->mods; ++ sli->maps[i].mods.vmods= desc->virtualMods; ++ sli->maps[i].ctrls = desc->ctrls; ++ if (desc->virtualMods!=0) { ++ unsigned tmp; ++ tmp= XkbMaskForVMask(xkbi->desc,desc->virtualMods); ++ sli->maps[i].mods.mask= desc->mods|tmp; ++ } ++ desc++; ++ } ++ } ++ ++ XkbSetCauseXkbReq(&cause,X_kbSetIndicatorMap,client); ++ XkbApplyLedMapChanges(dev,sli,which,NULL,NULL,&cause); ++ ++ return Success; ++} ++ + int + ProcXkbSetIndicatorMap(ClientPtr client) + { +- register int i,bit; +- int nIndicators; +- DeviceIntPtr dev; +- XkbSrvInfoPtr xkbi; +- xkbIndicatorMapWireDesc *from; +- XkbSrvLedInfoPtr sli; +- XkbEventCauseRec cause; ++ int i, bit; ++ int nIndicators; ++ DeviceIntPtr dev; ++ xkbIndicatorMapWireDesc *from; ++ int rc; + + REQUEST(xkbSetIndicatorMapReq); + REQUEST_AT_LEAST_SIZE(xkbSetIndicatorMapReq); +@@ -2898,8 +3158,6 @@ ProcXkbSetIndicatorMap(ClientPtr client) + + CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixSetAttrAccess); + -- To UNSUBSCRIBE, email to [EMAIL PROTECTED] with a subject of "unsubscribe". Trouble? Contact [EMAIL PROTECTED]