xorg-server: Changes to 'ubuntu'
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 <tjaalton@cc.hut.fi>
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 <peter.hutterer@who-t.net>
+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);
+
Reply to: