From 7783886cca84f83200761051f84ccd290b1c4856 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Aug 05 2008 05:10:31 +0000 Subject: * Tue Aug 05 2008 Peter Hutterer 1.4.99.906-5 - xserver-1.5.0-xkb-fix-ProcXkbSetXYZ-to-work-on-all.patch: force xkb requests to apply to all extension devices. - drop call-SwitchCoreKeyboard.patch - xserver-1.5.0-force-SwitchCoreKeyboard-for-evdev.patch: force SwitchCoreKeyboard for evdev devices to push device keymap into core device. --- diff --git a/xorg-x11-server.spec b/xorg-x11-server.spec index 25147ab..333a6c7 100644 --- a/xorg-x11-server.spec +++ b/xorg-x11-server.spec @@ -19,7 +19,7 @@ Summary: X.Org X11 X server Name: xorg-x11-server Version: 1.4.99.906 -Release: 4%{?dist} +Release: 5%{?dist} URL: http://www.x.org License: MIT Group: User Interface/X @@ -63,7 +63,8 @@ Patch5007: xserver-1.5.0-bad-fbdev-thats-mine.patch Patch5011: xserver-1.4.99-endian.patch # evdev keyboard map fix -# Patch5012: xserver-1.5.0-call-SwitchCoreKeyboard-for-first-device.patch +Patch5013: xserver-1.5.0-xkb-fix-ProcXkbSetXYZ-to-work-on-all.patch +Patch5014: xserver-1.5.0-force-SwitchCoreKeyboard-for-evdev.patch %define moduledir %{_libdir}/xorg/modules %define drimoduledir %{_libdir}/dri @@ -488,10 +489,21 @@ rm -rf $RPM_BUILD_ROOT %changelog +* Tue Aug 05 2008 Peter Hutterer 1.4.99.906-5 +- xserver-1.5.0-xkb-fix-ProcXkbSetXYZ-to-work-on-all.patch: force xkb requests + to apply to all extension devices. +- drop call-SwitchCoreKeyboard.patch +- xserver-1.5.0-force-SwitchCoreKeyboard-for-evdev.patch: force + SwitchCoreKeyboard for evdev devices to push device keymap into core device. + * Mon Aug 04 2008 Adam Jackson 1.4.99.906-4 - 10-x11-keymap.fdi, fedora-setup-keyboard: Attempt to read keyboard settings from /etc/sysconfig/keyboard and stuff them into hal. +* Mon Aug 04 2008 Peter Hutterer 1.4.99.906-3 +- xserver-1.5.0-call-SwitchCoreKeyboard-for-first-device.patch: force a keymap + switch to push the device keymap into the core device. + * Thu Jul 31 2008 Adam Jackson 1.4.99.906-2 - Drop the evdev keyboarding patch. diff --git a/xserver-1.5.0-call-SwitchCoreKeyboard-for-first-device.patch b/xserver-1.5.0-call-SwitchCoreKeyboard-for-first-device.patch deleted file mode 100644 index 304d79e..0000000 --- a/xserver-1.5.0-call-SwitchCoreKeyboard-for-first-device.patch +++ /dev/null @@ -1,61 +0,0 @@ -From b2943b507261d1c68a6266b090ec44495d7796a1 Mon Sep 17 00:00:00 2001 -From: Peter Hutterer -Date: Mon, 28 Jul 2008 12:17:17 +0930 -Subject: [PATCH] xfree86: call SwitchCoreKeyboard for first physical device. - -The VCK's keymap is different to the (evdev) keyboard's keymap. Any changes to -the VCK are lost when the first key is pressed (see X.Org Bug 16364). By -calling SwitchCoreKeyboard for the first hotplugged keyboard, the keymap is -toggled already when the first apps start. - -This fixes GNOME, which stores the keycode instead of the keysym. -Fixes xmodmap, etc. settings in xinitrc or otherwise set before the first key -press. - -This breaks if the first hotplugged keyboard is not the actual keyboard the -user wants to use. ---- - hw/xfree86/common/xf86Xinput.c | 27 +++++++++++++++++++++++++++ - 1 files changed, 27 insertions(+), 0 deletions(-) - -diff --git a/hw/xfree86/common/xf86Xinput.c b/hw/xfree86/common/xf86Xinput.c -index 710e787..fe08626 100644 ---- a/hw/xfree86/common/xf86Xinput.c -+++ b/hw/xfree86/common/xf86Xinput.c -@@ -423,6 +423,33 @@ NewInputDeviceRequest (InputOption *options, DeviceIntPtr *pdev) - (!is_auto || xf86Info.autoEnableDevices)) - EnableDevice(dev); - -+ /* XXX: The VCK always starts with built-in defaults for keymap. These -+ * defaults are different to the evdev ones. When the first key is hit on -+ * an extension device, the keymap is copied into the VCK's and any -+ * changes made at runtime to the VCK map are lost. -+ * -+ * If this is the first real keyboard to activate, force a -+ * SwitchCoreKeyboard so the VCK has the same keymap as we do. -+ * -+ * Next time we hit a key, we don't change the map over anymore (see -+ * SwitchCoreKeyboard), and live happily ever after. -+ * Until we have 2 physical keyboards. Or the first real keyboard isn't -+ * actually the one we use. Oh well. -+ */ -+ if (dev->key) -+ { -+ DeviceIntPtr it; -+ -+ for (it = inputInfo.keyboard->next; it; it = it->next) -+ { -+ if (it->key && it != dev) -+ break; -+ } -+ -+ if (!it) /* no other keyboard found */ -+ SwitchCoreKeyboard(dev); -+ } -+ - *pdev = dev; - return Success; - --- -1.5.5.1 - diff --git a/xserver-1.5.0-force-SwitchCoreKeyboard-for-evdev.patch b/xserver-1.5.0-force-SwitchCoreKeyboard-for-evdev.patch new file mode 100644 index 0000000..2ac6095 --- /dev/null +++ b/xserver-1.5.0-force-SwitchCoreKeyboard-for-evdev.patch @@ -0,0 +1,69 @@ +From 638cab7e1dc3711f7fb04155bcdabf4b8895cc5e Mon Sep 17 00:00:00 2001 +From: Peter Hutterer +Date: Mon, 4 Aug 2008 17:08:36 +0930 +Subject: [PATCH] xfree86: force SwitchCoreKeyboard for evdev devices (updated). + +If an evdev keyboard device is added through the HAL mechanism, force a +SwitchCoreKeyboard to load the evdev map into the VCK. This way, by the time a +client starts the evdev keymap is already there, leading to less pain lateron. + +Works if: +- all keyboards are hotplugged through HAL, and/or +- the xorg.conf keyboard uses the kbd driver. + +Has no effect (i.e. busted keymaps) if: +- an evdev keyboard device has been specified in the xorg.conf. +- we don't have a device at startup and plug a device in after starting the + desktop environment. +- if the device we use isn't the first one reported by HAL. + +If HAL isn't set up, this patch is a noop. +--- + hw/xfree86/common/xf86Xinput.c | 31 +++++++++++++++++++++++++++++++ + 1 files changed, 31 insertions(+), 0 deletions(-) + +diff --git a/hw/xfree86/common/xf86Xinput.c b/hw/xfree86/common/xf86Xinput.c +index 710e787..dacc3dc 100644 +--- a/hw/xfree86/common/xf86Xinput.c ++++ b/hw/xfree86/common/xf86Xinput.c +@@ -423,6 +423,37 @@ NewInputDeviceRequest (InputOption *options, DeviceIntPtr *pdev) + (!is_auto || xf86Info.autoEnableDevices)) + EnableDevice(dev); + ++ /* XXX: The VCK always starts with built-in defaults for keymap. These ++ * defaults are different to the evdev ones. When the first key is hit on ++ * an extension device, the keymap is copied into the VCK's and any ++ * changes made at runtime to the VCK map are lost. ++ * ++ * Assumption: if we have at least one evdev keyboard device, we can ++ * ignore kbd devices. Force a SwitchCoreKeyboard so the VCK has the same ++ * keymap as we do. ++ * ++ * Next time we hit a key, we don't change the map over anymore (see ++ * SwitchCoreKeyboard), and live happily ever after. ++ * Until we have 2 physical keyboards. Or the first real keyboard isn't ++ * actually the one we use. Oh well. ++ * ++ */ ++ if (dev->key) ++ { ++ InputInfoPtr info; ++ ++ /* Search if there is one other keyboard that uses evdev. */ ++ for (info = xf86InputDevs; info; info = info->next) ++ { ++ if (info != pInfo && info->dev && info->dev->key && ++ (strcmp(info->drv->driverName, "evdev") == 0)) ++ break; ++ } ++ ++ if (!info) ++ SwitchCoreKeyboard(dev); ++ } ++ + *pdev = dev; + return Success; + +-- +1.5.5.1 + diff --git a/xserver-1.5.0-xkb-fix-ProcXkbSetXYZ-to-work-on-all.patch b/xserver-1.5.0-xkb-fix-ProcXkbSetXYZ-to-work-on-all.patch new file mode 100644 index 0000000..13e197a --- /dev/null +++ b/xserver-1.5.0-xkb-fix-ProcXkbSetXYZ-to-work-on-all.patch @@ -0,0 +1,2245 @@ +From 6d1201b05ed61aec508d5d9f88e3a2d33be39849 Mon Sep 17 00:00:00 2001 +From: Peter Hutterer +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 + #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;igroups&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;inSI;i++,wire++,sym++) { ++ sym = &compat->sym_interpret[req->firstSI]; ++ for (i=0;inSI;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;igroups&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); + +- xkbi= dev->key->xkbInfo; +- + if (stuff->which==0) + return client->noClientException; + +@@ -2912,16 +3170,11 @@ ProcXkbSetIndicatorMap(ClientPtr client) + return BadLength; + } + +- sli= XkbFindSrvLedInfo(dev,XkbDfltXIClass,XkbDfltXIId, +- XkbXI_IndicatorMapsMask); +- if (!sli) +- return BadAlloc; +- + from = (xkbIndicatorMapWireDesc *)&stuff[1]; + for (i=0,bit=1;iwhich&bit) { + if (client->swapped) { +- register int n; ++ int n; + swaps(&from->virtualMods,n); + swapl(&from->ctrls,n); + } +@@ -2932,28 +3185,25 @@ ProcXkbSetIndicatorMap(ClientPtr client) + } + + from = (xkbIndicatorMapWireDesc *)&stuff[1]; +- for (i=0,bit=1;iwhich&bit) { +- sli->maps[i].flags = from->flags; +- sli->maps[i].which_groups = from->whichGroups; +- sli->maps[i].groups = from->groups; +- sli->maps[i].which_mods = from->whichMods; +- sli->maps[i].mods.mask = from->mods; +- sli->maps[i].mods.real_mods = from->mods; +- sli->maps[i].mods.vmods= from->virtualMods; +- sli->maps[i].ctrls = from->ctrls; +- if (from->virtualMods!=0) { +- unsigned tmp; +- tmp= XkbMaskForVMask(xkbi->desc,from->virtualMods); +- sli->maps[i].mods.mask= from->mods|tmp; +- } +- from++; +- } ++ rc = _XkbSetIndicatorMap(client, dev, stuff->which, from); ++ 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, DixSetAttrAccess); ++ if (rc == Success) ++ _XkbSetIndicatorMap(client, other, stuff->which, from); ++ } ++ } + } + +- XkbSetCauseXkbReq(&cause,X_kbSetIndicatorMap,client); +- XkbApplyLedMapChanges(dev,sli,stuff->which,NULL,NULL,&cause); +- return client->noClientException; ++ return Success; + } + + /***====================================================================***/ +@@ -3039,96 +3289,205 @@ ProcXkbGetNamedIndicator(ClientPtr client) + return client->noClientException; + } + +-/* FIXME: Needs to set indicator on all core-sending devices. */ +-int +-ProcXkbSetNamedIndicator(ClientPtr client) +-{ +- DeviceIntPtr dev,kbd; +- XkbIndicatorMapPtr map; +- XkbSrvLedInfoPtr sli; +- register int led = 0; +- unsigned extDevReason; +- unsigned statec,namec,mapc; +- XkbEventCauseRec cause; +- xkbExtensionDeviceNotify ed; +- XkbChangesRec changes; +- +- REQUEST(xkbSetNamedIndicatorReq); +- REQUEST_SIZE_MATCH(xkbSetNamedIndicatorReq); +- +- if (!(client->xkbClientFlags&_XkbClientInitialized)) +- return BadAccess; +- +- CHK_LED_DEVICE(dev, stuff->deviceSpec, client, DixSetAttrAccess); +- CHK_ATOM_ONLY(stuff->indicator); +- CHK_MASK_LEGAL(0x10,stuff->whichGroups,XkbIM_UseAnyGroup); +- CHK_MASK_LEGAL(0x11,stuff->whichMods,XkbIM_UseAnyMods); +- +- extDevReason= 0; + +- sli= XkbFindSrvLedInfo(dev,stuff->ledClass,stuff->ledID, +- XkbXI_IndicatorsMask); +- if (!sli) +- return BadAlloc; ++/** ++ * Find the IM on the device. ++ * Returns the map, or NULL if the map doesn't exist. ++ * If the return value is NULL, led_return is undefined. Otherwise, led_return ++ * is set to the led index of the map. ++ */ ++static XkbIndicatorMapPtr ++_XkbFindNamedIndicatorMap(XkbSrvLedInfoPtr sli, Atom indicator, ++ int *led_return) ++{ ++ XkbIndicatorMapPtr map; ++ int led; + +- statec= mapc= namec= 0; +- map= NULL; ++ /* search for the right indicator */ ++ map = NULL; + if (sli->names && sli->maps) { +- for (led=0;(lednames[led]==stuff->indicator) { ++ for (led = 0; (led < XkbNumIndicators) && (map == NULL); led++) { ++ if (sli->names[led] == indicator) { + map= &sli->maps[led]; + break; + } + } + } +- if (map==NULL) { +- if (!stuff->createMap) +- return client->noClientException; +- for (led=0,map=NULL;(lednames)&&(sli->maps)&&(sli->names[led]==None)&& +- (!XkbIM_InUse(&sli->maps[led]))) { +- map= &sli->maps[led]; +- sli->names[led]= stuff->indicator; +- break; +- } +- } +- if (map==NULL) +- return client->noClientException; +- namec|= (1<namesPresent|= ((stuff->indicator!=None)?(1<names) && (sli->maps) && (sli->names[led] == None) && ++ (!XkbIM_InUse(&sli->maps[led]))) ++ { ++ map = &sli->maps[led]; ++ if (!dryRun) ++ sli->names[led] = indicator; ++ break; ++ } ++ } + } + ++ if (!map) ++ return BadAlloc; ++ ++ *led_return = led; ++ *map_return = map; ++ return Success; ++} ++ ++static int ++_XkbSetNamedIndicator(ClientPtr client, DeviceIntPtr dev, ++ xkbSetNamedIndicatorReq *stuff) ++{ ++ unsigned int extDevReason; ++ unsigned int statec, namec, mapc; ++ XkbSrvLedInfoPtr sli; ++ int led = 0; ++ XkbIndicatorMapPtr map; ++ DeviceIntPtr kbd; ++ XkbEventCauseRec cause; ++ xkbExtensionDeviceNotify ed; ++ XkbChangesRec changes; ++ int rc; ++ ++ rc = _XkbCreateIndicatorMap(dev, stuff->indicator, stuff->ledClass, ++ stuff->ledID, &map, &led, FALSE); ++ if (rc != Success || !map) /* oh-oh */ ++ return rc; ++ ++ namec = mapc = statec = 0; ++ extDevReason = 0; ++ ++ namec |= (1<namesPresent |= ((stuff->indicator != None) ? (1 << led) : 0); ++ extDevReason |= XkbXI_IndicatorNamesMask; ++ + if (stuff->setMap) { +- map->flags = stuff->flags; +- map->which_groups = stuff->whichGroups; +- map->groups = stuff->groups; +- map->which_mods = stuff->whichMods; +- map->mods.mask = stuff->realMods; +- map->mods.real_mods = stuff->realMods; +- map->mods.vmods= stuff->virtualMods; +- map->ctrls = stuff->ctrls; +- mapc|= (1<setState)&&((map->flags&XkbIM_NoExplicit)==0)) { +- if (stuff->on) sli->explicitState|= (1<explicitState&= ~(1<effectiveState^sli->explicitState)&(1<flags = stuff->flags; ++ map->which_groups = stuff->whichGroups; ++ map->groups = stuff->groups; ++ map->which_mods = stuff->whichMods; ++ map->mods.mask = stuff->realMods; ++ map->mods.real_mods = stuff->realMods; ++ map->mods.vmods= stuff->virtualMods; ++ map->ctrls = stuff->ctrls; ++ mapc|= (1<setState) && ((map->flags & XkbIM_NoExplicit) == 0)) ++ { ++ if (stuff->on) sli->explicitState |= (1<explicitState &= ~(1<effectiveState ^ sli->explicitState) & (1 << led)); + } ++ + bzero((char *)&ed,sizeof(xkbExtensionDeviceNotify)); + bzero((char *)&changes,sizeof(XkbChangesRec)); + XkbSetCauseXkbReq(&cause,X_kbSetNamedIndicator,client); + if (namec) +- XkbApplyLedNameChanges(dev,sli,namec,&ed,&changes,&cause); ++ XkbApplyLedNameChanges(dev,sli,namec,&ed,&changes,&cause); + if (mapc) +- XkbApplyLedMapChanges(dev,sli,mapc,&ed,&changes,&cause); ++ XkbApplyLedMapChanges(dev,sli,mapc,&ed,&changes,&cause); + if (statec) +- XkbApplyLedStateChanges(dev,sli,statec,&ed,&changes,&cause); ++ XkbApplyLedStateChanges(dev,sli,statec,&ed,&changes,&cause); + +- kbd= dev; ++ kbd = dev; + if ((sli->flags&XkbSLI_HasOwnState)==0) +- kbd = inputInfo.keyboard; +- XkbFlushLedEvents(dev,kbd,sli,&ed,&changes,&cause); ++ kbd = inputInfo.keyboard; ++ XkbFlushLedEvents(dev, kbd, sli, &ed, &changes, &cause); ++ ++ return Success; ++} ++ ++int ++ProcXkbSetNamedIndicator(ClientPtr client) ++{ ++ int rc; ++ DeviceIntPtr dev; ++ int led = 0; ++ XkbIndicatorMapPtr map; ++ ++ REQUEST(xkbSetNamedIndicatorReq); ++ REQUEST_SIZE_MATCH(xkbSetNamedIndicatorReq); ++ ++ if (!(client->xkbClientFlags&_XkbClientInitialized)) ++ return BadAccess; ++ ++ CHK_LED_DEVICE(dev, stuff->deviceSpec, client, DixSetAttrAccess); ++ CHK_ATOM_ONLY(stuff->indicator); ++ CHK_MASK_LEGAL(0x10,stuff->whichGroups,XkbIM_UseAnyGroup); ++ CHK_MASK_LEGAL(0x11,stuff->whichMods,XkbIM_UseAnyMods); ++ ++ /* Dry-run for checks */ ++ rc = _XkbCreateIndicatorMap(dev, stuff->indicator, ++ stuff->ledClass, stuff->ledID, ++ &map, &led, TRUE); ++ if (rc != Success || !map) /* couldn't be created or didn't exist */ ++ return rc; ++ ++ if (stuff->deviceSpec == XkbUseCoreKbd || ++ stuff->deviceSpec == XkbUseCorePtr) ++ { ++ DeviceIntPtr other; ++ for (other = inputInfo.devices; other; other = other->next) ++ { ++ if ((other != dev) && other->coreEvents && ++ (XaceHook(XACE_DEVICE_ACCESS, client, other, DixSetAttrAccess) == Success)) ++ { ++ rc = _XkbCreateIndicatorMap(other, stuff->indicator, ++ stuff->ledClass, stuff->ledID, ++ &map, &led, TRUE); ++ if (rc != Success || !map) ++ return rc; ++ } ++ } ++ } ++ ++ /* All checks passed, let's do it */ ++ rc = _XkbSetNamedIndicator(client, dev, stuff); ++ if (rc != Success) ++ return rc; ++ ++ if (stuff->deviceSpec == XkbUseCoreKbd || ++ stuff->deviceSpec == XkbUseCorePtr) ++ { ++ DeviceIntPtr other; ++ for (other = inputInfo.devices; other; other = other->next) ++ { ++ if ((other != dev) && other->coreEvents && ++ (XaceHook(XACE_DEVICE_ACCESS, client, other, DixSetAttrAccess) == Success)) ++ { ++ _XkbSetNamedIndicator(client, other, stuff); ++ } ++ } ++ } ++ + return client->noClientException; + } + +@@ -3528,17 +3887,323 @@ char * str; + return True; + } + +-/* FIXME: Needs to set names on all core-sending devices. */ +-int +-ProcXkbSetNames(ClientPtr client) ++/** ++ * Check the device-dependent data in the request against the device. Returns ++ * Success, or the appropriate error code. ++ */ ++static int ++_XkbSetNamesCheck(ClientPtr client, DeviceIntPtr dev, ++ xkbSetNamesReq *stuff, CARD32 *data) + { +- DeviceIntPtr dev; + XkbDescRec *xkb; + XkbNamesRec *names; +- xkbNamesNotify nn; + CARD32 *tmp; + Atom bad; + ++ tmp = data; ++ xkb = dev->key->xkbInfo->desc; ++ names = xkb->names; ++ ++ ++ if (stuff->which & XkbKeyTypeNamesMask) { ++ int i; ++ CARD32 *old; ++ if ( stuff->nTypes<1 ) { ++ client->errorValue = _XkbErrCode2(0x02,stuff->nTypes); ++ return BadValue; ++ } ++ if ((unsigned)(stuff->firstType+stuff->nTypes-1)>=xkb->map->num_types) { ++ client->errorValue = _XkbErrCode4(0x03,stuff->firstType, ++ stuff->nTypes, ++ xkb->map->num_types); ++ return BadValue; ++ } ++ if (((unsigned)stuff->firstType)<=XkbLastRequiredType) { ++ client->errorValue = _XkbErrCode2(0x04,stuff->firstType); ++ return BadAccess; ++ } ++ old= tmp; ++ tmp= _XkbCheckAtoms(tmp,stuff->nTypes,client->swapped,&bad); ++ if (!tmp) { ++ client->errorValue= bad; ++ return BadAtom; ++ } ++ for (i=0;inTypes;i++,old++) { ++ if (!_XkbCheckTypeName((Atom)*old,stuff->firstType+i)) ++ client->errorValue= _XkbErrCode2(0x05,i); ++ } ++ } ++ if (stuff->which&XkbKTLevelNamesMask) { ++ unsigned i; ++ XkbKeyTypePtr type; ++ CARD8 * width; ++ if ( stuff->nKTLevels<1 ) { ++ client->errorValue = _XkbErrCode2(0x05,stuff->nKTLevels); ++ return BadValue; ++ } ++ if ((unsigned)(stuff->firstKTLevel+stuff->nKTLevels-1)>= ++ xkb->map->num_types) { ++ client->errorValue = _XkbErrCode4(0x06,stuff->firstKTLevel, ++ stuff->nKTLevels,xkb->map->num_types); ++ return BadValue; ++ } ++ width = (CARD8 *)tmp; ++ tmp= (CARD32 *)(((char *)tmp)+XkbPaddedSize(stuff->nKTLevels)); ++ type = &xkb->map->types[stuff->firstKTLevel]; ++ for (i=0;inKTLevels;i++,type++) { ++ if (width[i]==0) ++ continue; ++ else if (width[i]!=type->num_levels) { ++ client->errorValue= _XkbErrCode4(0x07,i+stuff->firstKTLevel, ++ type->num_levels,width[i]); ++ return BadMatch; ++ } ++ tmp= _XkbCheckAtoms(tmp,width[i],client->swapped,&bad); ++ if (!tmp) { ++ client->errorValue= bad; ++ return BadAtom; ++ } ++ } ++ } ++ if (stuff->which&XkbIndicatorNamesMask) { ++ if (stuff->indicators==0) { ++ client->errorValue= 0x08; ++ return BadMatch; ++ } ++ tmp= _XkbCheckMaskedAtoms(tmp,XkbNumIndicators,stuff->indicators, ++ client->swapped,&bad); ++ if (!tmp) { ++ client->errorValue= bad; ++ return BadAtom; ++ } ++ } ++ if (stuff->which&XkbVirtualModNamesMask) { ++ if (stuff->virtualMods==0) { ++ client->errorValue= 0x09; ++ return BadMatch; ++ } ++ tmp= _XkbCheckMaskedAtoms(tmp,XkbNumVirtualMods, ++ (CARD32)stuff->virtualMods, ++ client->swapped,&bad); ++ if (!tmp) { ++ client->errorValue = bad; ++ return BadAtom; ++ } ++ } ++ if (stuff->which&XkbGroupNamesMask) { ++ if (stuff->groupNames==0) { ++ client->errorValue= 0x0a; ++ return BadMatch; ++ } ++ tmp= _XkbCheckMaskedAtoms(tmp,XkbNumKbdGroups, ++ (CARD32)stuff->groupNames, ++ client->swapped,&bad); ++ if (!tmp) { ++ client->errorValue = bad; ++ return BadAtom; ++ } ++ } ++ if (stuff->which&XkbKeyNamesMask) { ++ if (stuff->firstKey<(unsigned)xkb->min_key_code) { ++ client->errorValue= _XkbErrCode3(0x0b,xkb->min_key_code, ++ stuff->firstKey); ++ return BadValue; ++ } ++ if (((unsigned)(stuff->firstKey+stuff->nKeys-1)>xkb->max_key_code)|| ++ (stuff->nKeys<1)) { ++ client->errorValue= _XkbErrCode4(0x0c,xkb->max_key_code, ++ stuff->firstKey,stuff->nKeys); ++ return BadValue; ++ } ++ tmp+= stuff->nKeys; ++ } ++ if ((stuff->which&XkbKeyAliasesMask)&&(stuff->nKeyAliases>0)) { ++ tmp+= stuff->nKeyAliases*2; ++ } ++ if (stuff->which&XkbRGNamesMask) { ++ if ( stuff->nRadioGroups<1 ) { ++ client->errorValue= _XkbErrCode2(0x0d,stuff->nRadioGroups); ++ return BadValue; ++ } ++ tmp= _XkbCheckAtoms(tmp,stuff->nRadioGroups,client->swapped,&bad); ++ if (!tmp) { ++ client->errorValue= bad; ++ return BadAtom; ++ } ++ } ++ if ((tmp-((CARD32 *)stuff))!=stuff->length) { ++ client->errorValue = stuff->length; ++ return BadLength; ++ } ++ ++ ++ ++ return Success; ++} ++ ++static int ++_XkbSetNames(ClientPtr client, DeviceIntPtr dev, xkbSetNamesReq *stuff) ++{ ++ XkbDescRec *xkb; ++ XkbNamesRec *names; ++ CARD32 *tmp; ++ xkbNamesNotify nn; ++ ++ tmp = (CARD32 *)&stuff[1]; ++ xkb = dev->key->xkbInfo->desc; ++ names = xkb->names; ++ ++ if (XkbAllocNames(xkb,stuff->which,stuff->nRadioGroups, ++ stuff->nKeyAliases)!=Success) { ++ return BadAlloc; ++ } ++ ++ bzero(&nn,sizeof(xkbNamesNotify)); ++ nn.changed= stuff->which; ++ tmp = (CARD32 *)&stuff[1]; ++ if (stuff->which&XkbKeycodesNameMask) ++ names->keycodes= *tmp++; ++ if (stuff->which&XkbGeometryNameMask) ++ names->geometry= *tmp++; ++ if (stuff->which&XkbSymbolsNameMask) ++ names->symbols= *tmp++; ++ if (stuff->which&XkbPhysSymbolsNameMask) ++ names->phys_symbols= *tmp++; ++ if (stuff->which&XkbTypesNameMask) ++ names->types= *tmp++; ++ if (stuff->which&XkbCompatNameMask) ++ names->compat= *tmp++; ++ if ((stuff->which&XkbKeyTypeNamesMask)&&(stuff->nTypes>0)) { ++ register unsigned i; ++ register XkbKeyTypePtr type; ++ ++ type= &xkb->map->types[stuff->firstType]; ++ for (i=0;inTypes;i++,type++) { ++ type->name= *tmp++; ++ } ++ nn.firstType= stuff->firstType; ++ nn.nTypes= stuff->nTypes; ++ } ++ if (stuff->which&XkbKTLevelNamesMask) { ++ register XkbKeyTypePtr type; ++ register unsigned i; ++ CARD8 *width; ++ ++ width = (CARD8 *)tmp; ++ tmp= (CARD32 *)(((char *)tmp)+XkbPaddedSize(stuff->nKTLevels)); ++ type= &xkb->map->types[stuff->firstKTLevel]; ++ for (i=0;inKTLevels;i++,type++) { ++ if (width[i]>0) { ++ if (type->level_names) { ++ register unsigned n; ++ for (n=0;nlevel_names[n]= tmp[n]; ++ } ++ } ++ tmp+= width[i]; ++ } ++ } ++ nn.firstLevelName= 0; ++ nn.nLevelNames= stuff->nTypes; ++ } ++ if (stuff->which&XkbIndicatorNamesMask) { ++ tmp= _XkbCopyMaskedAtoms(tmp,names->indicators,XkbNumIndicators, ++ stuff->indicators); ++ nn.changedIndicators= stuff->indicators; ++ } ++ if (stuff->which&XkbVirtualModNamesMask) { ++ tmp= _XkbCopyMaskedAtoms(tmp,names->vmods,XkbNumVirtualMods, ++ stuff->virtualMods); ++ nn.changedVirtualMods= stuff->virtualMods; ++ } ++ if (stuff->which&XkbGroupNamesMask) { ++ tmp= _XkbCopyMaskedAtoms(tmp,names->groups,XkbNumKbdGroups, ++ stuff->groupNames); ++ nn.changedVirtualMods= stuff->groupNames; ++ } ++ if (stuff->which&XkbKeyNamesMask) { ++ memcpy((char*)&names->keys[stuff->firstKey],(char *)tmp, ++ stuff->nKeys*XkbKeyNameLength); ++ tmp+= stuff->nKeys; ++ nn.firstKey= stuff->firstKey; ++ nn.nKeys= stuff->nKeys; ++ } ++ if (stuff->which&XkbKeyAliasesMask) { ++ if (stuff->nKeyAliases>0) { ++ register int na= stuff->nKeyAliases; ++ if (XkbAllocNames(xkb,XkbKeyAliasesMask,0,na)!=Success) ++ return BadAlloc; ++ memcpy((char *)names->key_aliases,(char *)tmp, ++ stuff->nKeyAliases*sizeof(XkbKeyAliasRec)); ++ tmp+= stuff->nKeyAliases*2; ++ } ++ else if (names->key_aliases!=NULL) { ++ _XkbFree(names->key_aliases); ++ names->key_aliases= NULL; ++ names->num_key_aliases= 0; ++ } ++ nn.nAliases= names->num_key_aliases; ++ } ++ if (stuff->which&XkbRGNamesMask) { ++ if (stuff->nRadioGroups>0) { ++ register unsigned i,nrg; ++ nrg= stuff->nRadioGroups; ++ if (XkbAllocNames(xkb,XkbRGNamesMask,nrg,0)!=Success) ++ return BadAlloc; ++ ++ for (i=0;inRadioGroups;i++) { ++ names->radio_groups[i]= tmp[i]; ++ } ++ tmp+= stuff->nRadioGroups; ++ } ++ else if (names->radio_groups) { ++ _XkbFree(names->radio_groups); ++ names->radio_groups= NULL; ++ names->num_rg= 0; ++ } ++ nn.nRadioGroups= names->num_rg; ++ } ++ if (nn.changed) { ++ Bool needExtEvent; ++ needExtEvent= (nn.changed&XkbIndicatorNamesMask)!=0; ++ XkbSendNamesNotify(dev,&nn); ++ if (needExtEvent) { ++ XkbSrvLedInfoPtr sli; ++ xkbExtensionDeviceNotify edev; ++ register int i; ++ register unsigned bit; ++ ++ sli= XkbFindSrvLedInfo(dev,XkbDfltXIClass,XkbDfltXIId, ++ XkbXI_IndicatorsMask); ++ sli->namesPresent= 0; ++ for (i=0,bit=1;iindicators[i]!=None) ++ sli->namesPresent|= bit; ++ } ++ bzero(&edev,sizeof(xkbExtensionDeviceNotify)); ++ edev.reason= XkbXI_IndicatorNamesMask; ++ edev.ledClass= KbdFeedbackClass; ++ edev.ledID= dev->kbdfeed->ctrl.id; ++ edev.ledsDefined= sli->namesPresent|sli->mapsPresent; ++ edev.ledState= sli->effectiveState; ++ edev.firstBtn= 0; ++ edev.nBtns= 0; ++ edev.supported= XkbXI_AllFeaturesMask; ++ edev.unsupported= 0; ++ XkbSendExtensionDeviceNotify(dev,client,&edev); ++ } ++ } ++ return Success; ++} ++ ++int ++ProcXkbSetNames(ClientPtr client) ++{ ++ DeviceIntPtr dev; ++ CARD32 *tmp; ++ Atom bad; ++ int rc; ++ + REQUEST(xkbSetNamesReq); + REQUEST_AT_LEAST_SIZE(xkbSetNamesReq); + +@@ -3548,8 +4213,7 @@ ProcXkbSetNames(ClientPtr client) + CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess); + CHK_MASK_LEGAL(0x01,stuff->which,XkbAllNamesMask); + +- xkb = dev->key->xkbInfo->desc; +- names = xkb->names; ++ /* check device-independent stuff */ + tmp = (CARD32 *)&stuff[1]; + + if (stuff->which&XkbKeycodesNameMask) { +@@ -3594,277 +4258,54 @@ ProcXkbSetNames(ClientPtr client) + return BadAtom; + } + } +- if (stuff->which&XkbKeyTypeNamesMask) { +- register int i; +- CARD32 *old; +- if ( stuff->nTypes<1 ) { +- client->errorValue = _XkbErrCode2(0x02,stuff->nTypes); +- return BadValue; +- } +- if ((unsigned)(stuff->firstType+stuff->nTypes-1)>=xkb->map->num_types) { +- client->errorValue = _XkbErrCode4(0x03,stuff->firstType, +- stuff->nTypes, +- xkb->map->num_types); +- return BadValue; +- } +- if (((unsigned)stuff->firstType)<=XkbLastRequiredType) { +- client->errorValue = _XkbErrCode2(0x04,stuff->firstType); +- return BadAccess; +- } +- old= tmp; +- tmp= _XkbCheckAtoms(tmp,stuff->nTypes,client->swapped,&bad); +- if (!tmp) { +- client->errorValue= bad; +- return BadAtom; +- } +- for (i=0;inTypes;i++,old++) { +- if (!_XkbCheckTypeName((Atom)*old,stuff->firstType+i)) +- client->errorValue= _XkbErrCode2(0x05,i); +- } +- } +- if (stuff->which&XkbKTLevelNamesMask) { +- register unsigned i; +- XkbKeyTypePtr type; +- CARD8 * width; +- if ( stuff->nKTLevels<1 ) { +- client->errorValue = _XkbErrCode2(0x05,stuff->nKTLevels); +- return BadValue; +- } +- if ((unsigned)(stuff->firstKTLevel+stuff->nKTLevels-1)>= +- xkb->map->num_types) { +- client->errorValue = _XkbErrCode4(0x06,stuff->firstKTLevel, +- stuff->nKTLevels,xkb->map->num_types); +- return BadValue; +- } +- width = (CARD8 *)tmp; +- tmp= (CARD32 *)(((char *)tmp)+XkbPaddedSize(stuff->nKTLevels)); +- type = &xkb->map->types[stuff->firstKTLevel]; +- for (i=0;inKTLevels;i++,type++) { +- if (width[i]==0) +- continue; +- else if (width[i]!=type->num_levels) { +- client->errorValue= _XkbErrCode4(0x07,i+stuff->firstKTLevel, +- type->num_levels,width[i]); +- return BadMatch; +- } +- tmp= _XkbCheckAtoms(tmp,width[i],client->swapped,&bad); +- if (!tmp) { +- client->errorValue= bad; +- return BadAtom; +- } +- } +- } +- if (stuff->which&XkbIndicatorNamesMask) { +- if (stuff->indicators==0) { +- client->errorValue= 0x08; +- return BadMatch; +- } +- tmp= _XkbCheckMaskedAtoms(tmp,XkbNumIndicators,stuff->indicators, +- client->swapped,&bad); +- if (!tmp) { +- client->errorValue= bad; +- return BadAtom; +- } +- } +- if (stuff->which&XkbVirtualModNamesMask) { +- if (stuff->virtualMods==0) { +- client->errorValue= 0x09; +- return BadMatch; +- } +- tmp= _XkbCheckMaskedAtoms(tmp,XkbNumVirtualMods, +- (CARD32)stuff->virtualMods, +- client->swapped,&bad); +- if (!tmp) { +- client->errorValue = bad; +- return BadAtom; +- } +- } +- if (stuff->which&XkbGroupNamesMask) { +- if (stuff->groupNames==0) { +- client->errorValue= 0x0a; +- return BadMatch; +- } +- tmp= _XkbCheckMaskedAtoms(tmp,XkbNumKbdGroups, +- (CARD32)stuff->groupNames, +- client->swapped,&bad); +- if (!tmp) { +- client->errorValue = bad; +- return BadAtom; +- } +- } +- if (stuff->which&XkbKeyNamesMask) { +- if (stuff->firstKey<(unsigned)xkb->min_key_code) { +- client->errorValue= _XkbErrCode3(0x0b,xkb->min_key_code, +- stuff->firstKey); +- return BadValue; +- } +- if (((unsigned)(stuff->firstKey+stuff->nKeys-1)>xkb->max_key_code)|| +- (stuff->nKeys<1)) { +- client->errorValue= _XkbErrCode4(0x0c,xkb->max_key_code, +- stuff->firstKey,stuff->nKeys); +- return BadValue; +- } +- tmp+= stuff->nKeys; +- } +- if ((stuff->which&XkbKeyAliasesMask)&&(stuff->nKeyAliases>0)) { +- tmp+= stuff->nKeyAliases*2; +- } +- if (stuff->which&XkbRGNamesMask) { +- if ( stuff->nRadioGroups<1 ) { +- client->errorValue= _XkbErrCode2(0x0d,stuff->nRadioGroups); +- return BadValue; +- } +- tmp= _XkbCheckAtoms(tmp,stuff->nRadioGroups,client->swapped,&bad); +- if (!tmp) { +- client->errorValue= bad; +- return BadAtom; +- } +- } +- if ((tmp-((CARD32 *)stuff))!=stuff->length) { +- client->errorValue = stuff->length; +- return BadLength; +- } +- if (XkbAllocNames(xkb,stuff->which,stuff->nRadioGroups, +- stuff->nKeyAliases)!=Success) { +- return BadAlloc; ++ ++ /* start of device-dependent tests */ ++ rc = _XkbSetNamesCheck(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 = _XkbSetNamesCheck(client, other, stuff, tmp); ++ if (rc != Success) ++ return rc; ++ } ++ } ++ } + } + + /* everything is okay -- update names */ +- bzero(&nn,sizeof(xkbNamesNotify)); +- nn.changed= stuff->which; +- tmp = (CARD32 *)&stuff[1]; +- if (stuff->which&XkbKeycodesNameMask) +- names->keycodes= *tmp++; +- if (stuff->which&XkbGeometryNameMask) +- names->geometry= *tmp++; +- if (stuff->which&XkbSymbolsNameMask) +- names->symbols= *tmp++; +- if (stuff->which&XkbPhysSymbolsNameMask) +- names->phys_symbols= *tmp++; +- if (stuff->which&XkbTypesNameMask) +- names->types= *tmp++; +- if (stuff->which&XkbCompatNameMask) +- names->compat= *tmp++; +- if ((stuff->which&XkbKeyTypeNamesMask)&&(stuff->nTypes>0)) { +- register unsigned i; +- register XkbKeyTypePtr type; + +- type= &xkb->map->types[stuff->firstType]; +- for (i=0;inTypes;i++,type++) { +- type->name= *tmp++; +- } +- nn.firstType= stuff->firstType; +- nn.nTypes= stuff->nTypes; +- } +- if (stuff->which&XkbKTLevelNamesMask) { +- register XkbKeyTypePtr type; +- register unsigned i; +- CARD8 *width; +- +- width = (CARD8 *)tmp; +- tmp= (CARD32 *)(((char *)tmp)+XkbPaddedSize(stuff->nKTLevels)); +- type= &xkb->map->types[stuff->firstKTLevel]; +- for (i=0;inKTLevels;i++,type++) { +- if (width[i]>0) { +- if (type->level_names) { +- register unsigned n; +- for (n=0;nlevel_names[n]= tmp[n]; +- } +- } +- tmp+= width[i]; +- } +- } +- nn.firstLevelName= 0; +- nn.nLevelNames= stuff->nTypes; +- } +- if (stuff->which&XkbIndicatorNamesMask) { +- tmp= _XkbCopyMaskedAtoms(tmp,names->indicators,XkbNumIndicators, +- stuff->indicators); +- nn.changedIndicators= stuff->indicators; +- } +- if (stuff->which&XkbVirtualModNamesMask) { +- tmp= _XkbCopyMaskedAtoms(tmp,names->vmods,XkbNumVirtualMods, +- stuff->virtualMods); +- nn.changedVirtualMods= stuff->virtualMods; +- } +- if (stuff->which&XkbGroupNamesMask) { +- tmp= _XkbCopyMaskedAtoms(tmp,names->groups,XkbNumKbdGroups, +- stuff->groupNames); +- nn.changedVirtualMods= stuff->groupNames; +- } +- if (stuff->which&XkbKeyNamesMask) { +- memcpy((char*)&names->keys[stuff->firstKey],(char *)tmp, +- stuff->nKeys*XkbKeyNameLength); +- tmp+= stuff->nKeys; +- nn.firstKey= stuff->firstKey; +- nn.nKeys= stuff->nKeys; +- } +- if (stuff->which&XkbKeyAliasesMask) { +- if (stuff->nKeyAliases>0) { +- register int na= stuff->nKeyAliases; +- if (XkbAllocNames(xkb,XkbKeyAliasesMask,0,na)!=Success) +- return BadAlloc; +- memcpy((char *)names->key_aliases,(char *)tmp, +- stuff->nKeyAliases*sizeof(XkbKeyAliasRec)); +- tmp+= stuff->nKeyAliases*2; +- } +- else if (names->key_aliases!=NULL) { +- _XkbFree(names->key_aliases); +- names->key_aliases= NULL; +- names->num_key_aliases= 0; +- } +- nn.nAliases= names->num_key_aliases; +- } +- if (stuff->which&XkbRGNamesMask) { +- if (stuff->nRadioGroups>0) { +- register unsigned i,nrg; +- nrg= stuff->nRadioGroups; +- if (XkbAllocNames(xkb,XkbRGNamesMask,nrg,0)!=Success) +- return BadAlloc; ++ rc = _XkbSetNames(client, dev, stuff); ++ if (rc != Success) ++ return rc; + +- for (i=0;inRadioGroups;i++) { +- names->radio_groups[i]= tmp[i]; +- } +- tmp+= stuff->nRadioGroups; +- } +- else if (names->radio_groups) { +- _XkbFree(names->radio_groups); +- names->radio_groups= NULL; +- names->num_rg= 0; +- } +- nn.nRadioGroups= names->num_rg; +- } +- if (nn.changed) { +- Bool needExtEvent; +- needExtEvent= (nn.changed&XkbIndicatorNamesMask)!=0; +- XkbSendNamesNotify(dev,&nn); +- if (needExtEvent) { +- XkbSrvLedInfoPtr sli; +- xkbExtensionDeviceNotify edev; +- register int i; +- register unsigned bit; +- +- sli= XkbFindSrvLedInfo(dev,XkbDfltXIClass,XkbDfltXIId, +- XkbXI_IndicatorsMask); +- sli->namesPresent= 0; +- for (i=0,bit=1;iindicators[i]!=None) +- sli->namesPresent|= bit; +- } +- bzero(&edev,sizeof(xkbExtensionDeviceNotify)); +- edev.reason= XkbXI_IndicatorNamesMask; +- edev.ledClass= KbdFeedbackClass; +- edev.ledID= dev->kbdfeed->ctrl.id; +- edev.ledsDefined= sli->namesPresent|sli->mapsPresent; +- edev.ledState= sli->effectiveState; +- edev.firstBtn= 0; +- edev.nBtns= 0; +- edev.supported= XkbXI_AllFeaturesMask; +- edev.unsupported= 0; +- XkbSendExtensionDeviceNotify(dev,client,&edev); +- } ++ 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) ++ _XkbSetNames(client, other, stuff); ++ } ++ } + } ++ ++ /* everything is okay -- update names */ ++ + return client->noClientException; + } + +@@ -4826,60 +5267,49 @@ char * wire; + return Success; + } + +-/* FIXME: Needs to set geom on all core-sending devices. */ +-int +-ProcXkbSetGeometry(ClientPtr client) ++static int ++_XkbSetGeometry(ClientPtr client, DeviceIntPtr dev, xkbSetGeometryReq *stuff) + { +- DeviceIntPtr dev; +- XkbGeometryPtr geom,old; +- XkbGeometrySizesRec sizes; +- Status status; + XkbDescPtr xkb; + Bool new_name; + xkbNewKeyboardNotify nkn; +- +- REQUEST(xkbSetGeometryReq); +- REQUEST_AT_LEAST_SIZE(xkbSetGeometryReq); +- +- if (!(client->xkbClientFlags&_XkbClientInitialized)) +- return BadAccess; +- +- CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess); +- CHK_ATOM_OR_NONE(stuff->name); ++ XkbGeometryPtr geom,old; ++ XkbGeometrySizesRec sizes; ++ Status status; + + xkb= dev->key->xkbInfo->desc; + old= xkb->geom; + xkb->geom= NULL; + +- sizes.which= XkbGeomAllMask; ++ sizes.which= XkbGeomAllMask; + sizes.num_properties= stuff->nProperties; +- sizes.num_colors= stuff->nColors; +- sizes.num_shapes= stuff->nShapes; +- sizes.num_sections= stuff->nSections; +- sizes.num_doodads= stuff->nDoodads; ++ sizes.num_colors= stuff->nColors; ++ sizes.num_shapes= stuff->nShapes; ++ sizes.num_sections= stuff->nSections; ++ sizes.num_doodads= stuff->nDoodads; + sizes.num_key_aliases= stuff->nKeyAliases; + if ((status= XkbAllocGeometry(xkb,&sizes))!=Success) { +- xkb->geom= old; +- return status; ++ xkb->geom= old; ++ return status; + } + geom= xkb->geom; + geom->name= stuff->name; + geom->width_mm= stuff->widthMM; + geom->height_mm= stuff->heightMM; + if ((status= _CheckSetGeom(geom,stuff,client))!=Success) { +- XkbFreeGeometry(geom,XkbGeomAllMask,True); +- xkb->geom= old; +- return status; ++ XkbFreeGeometry(geom,XkbGeomAllMask,True); ++ xkb->geom= old; ++ return status; + } + new_name= (xkb->names->geometry!=geom->name); + xkb->names->geometry= geom->name; + if (old) +- XkbFreeGeometry(old,XkbGeomAllMask,True); ++ XkbFreeGeometry(old,XkbGeomAllMask,True); + if (new_name) { +- xkbNamesNotify nn; +- bzero(&nn,sizeof(xkbNamesNotify)); +- nn.changed= XkbGeometryNameMask; +- XkbSendNamesNotify(dev,&nn); ++ xkbNamesNotify nn; ++ bzero(&nn,sizeof(xkbNamesNotify)); ++ nn.changed= XkbGeometryNameMask; ++ XkbSendNamesNotify(dev,&nn); + } + nkn.deviceID= nkn.oldDeviceID= dev->id; + nkn.minKeyCode= nkn.oldMinKeyCode= xkb->min_key_code; +@@ -4891,6 +5321,43 @@ ProcXkbSetGeometry(ClientPtr client) + return Success; + } + ++int ++ProcXkbSetGeometry(ClientPtr client) ++{ ++ DeviceIntPtr dev; ++ Status status; ++ int rc; ++ ++ REQUEST(xkbSetGeometryReq); ++ REQUEST_AT_LEAST_SIZE(xkbSetGeometryReq); ++ ++ if (!(client->xkbClientFlags&_XkbClientInitialized)) ++ return BadAccess; ++ ++ CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess); ++ CHK_ATOM_OR_NONE(stuff->name); ++ ++ rc = _XkbSetGeometry(client, dev, stuff); ++ 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) ++ _XkbSetGeometry(client, other, stuff); ++ } ++ } ++ } ++ ++ return Success; ++} ++ + /***====================================================================***/ + + int +@@ -5972,25 +6439,15 @@ DeviceIntPtr kbd; + return (char *)ledWire; + } + +-/* FIXME: Needs to set info on all core-sending devices. */ +-int +-ProcXkbSetDeviceInfo(ClientPtr client) +-{ +-DeviceIntPtr dev; +-unsigned change; +-char * wire; +-xkbExtensionDeviceNotify ed; + +- REQUEST(xkbSetDeviceInfoReq); +- REQUEST_AT_LEAST_SIZE(xkbSetDeviceInfoReq); +- +- if (!(client->xkbClientFlags&_XkbClientInitialized)) +- return BadAccess; ++static int ++_XkbSetDeviceInfo(ClientPtr client, DeviceIntPtr dev, ++ xkbSetDeviceInfoReq *stuff) ++{ ++ unsigned change; ++ char *wire; + +- change= stuff->change; +- +- CHK_ANY_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess); +- CHK_MASK_LEGAL(0x01,change,XkbXI_AllFeaturesMask); ++ change = stuff->change; + + wire= (char *)&stuff[1]; + if (change&XkbXI_ButtonActionsMask) { +@@ -6015,6 +6472,17 @@ xkbExtensionDeviceNotify ed; + if (((wire-((char *)stuff))/4)!=stuff->length) + return BadLength; + ++ return Success; ++} ++ ++static int ++_XkbSetDeviceInfoCheck(ClientPtr client, DeviceIntPtr dev, ++ xkbSetDeviceInfoReq *stuff) ++{ ++ unsigned change; ++ char *wire; ++ xkbExtensionDeviceNotify ed; ++ + bzero((char *)&ed,SIZEOF(xkbExtensionDeviceNotify)); + ed.deviceID= dev->id; + wire= (char *)&stuff[1]; +@@ -6055,6 +6523,78 @@ xkbExtensionDeviceNotify ed; + } + if ((stuff->change)&&(ed.reason)) + XkbSendExtensionDeviceNotify(dev,client,&ed); ++ return Success; ++} ++ ++int ++ProcXkbSetDeviceInfo(ClientPtr client) ++{ ++ unsigned int change; ++ DeviceIntPtr dev; ++ int loop = 0; ++ int rc; ++ ++ REQUEST(xkbSetDeviceInfoReq); ++ REQUEST_AT_LEAST_SIZE(xkbSetDeviceInfoReq); ++ ++ if (!(client->xkbClientFlags&_XkbClientInitialized)) ++ return BadAccess; ++ ++ change = stuff->change; ++ ++ CHK_ANY_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess); ++ CHK_MASK_LEGAL(0x01,change,XkbXI_AllFeaturesMask); ++ ++ rc = _XkbSetDeviceInfoCheck(client, dev, stuff); ++ ++ if (rc != Success) ++ return rc; ++ ++ if (stuff->deviceSpec == XkbUseCoreKbd || stuff->deviceSpec == XkbUseCorePtr) ++ { ++ DeviceIntPtr other; ++ for (other = inputInfo.devices; other; other = other->next) ++ { ++ if (((other != dev) && other->coreEvents) && ++ ((stuff->deviceSpec == XkbUseCoreKbd && other->key) || ++ (stuff->deviceSpec == XkbUseCorePtr && other->button))) ++ { ++ rc = XaceHook(XACE_DEVICE_ACCESS, client, other, DixManageAccess); ++ if (rc == Success) ++ { ++ rc = _XkbSetDeviceInfoCheck(client, other, stuff); ++ if (rc != Success) ++ return rc; ++ } ++ } ++ } ++ } ++ ++ /* checks done, apply */ ++ rc = _XkbSetDeviceInfo(client, dev, stuff); ++ if (rc != Success) ++ return rc; ++ ++ if (stuff->deviceSpec == XkbUseCoreKbd || stuff->deviceSpec == XkbUseCorePtr) ++ { ++ DeviceIntPtr other; ++ for (other = inputInfo.devices; other; other = other->next) ++ { ++ if (((other != dev) && other->coreEvents) && ++ ((stuff->deviceSpec == XkbUseCoreKbd && other->key) || ++ (stuff->deviceSpec == XkbUseCorePtr && other->button))) ++ { ++ rc = XaceHook(XACE_DEVICE_ACCESS, client, other, DixManageAccess); ++ if (rc == Success) ++ { ++ rc = _XkbSetDeviceInfo(client, other, stuff); ++ if (rc != Success) ++ return rc; ++ } ++ } ++ } ++ } ++ + return client->noClientException; + } + +-- +1.5.5.1 +