[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

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: