105b261ecSmrg/************************************************************ 205b261ecSmrgCopyright (c) 1993 by Silicon Graphics Computer Systems, Inc. 305b261ecSmrg 405b261ecSmrgPermission to use, copy, modify, and distribute this 505b261ecSmrgsoftware and its documentation for any purpose and without 605b261ecSmrgfee is hereby granted, provided that the above copyright 705b261ecSmrgnotice appear in all copies and that both that copyright 805b261ecSmrgnotice and this permission notice appear in supporting 9f7df2e56Smrgdocumentation, and that the name of Silicon Graphics not be 10f7df2e56Smrgused in advertising or publicity pertaining to distribution 1105b261ecSmrgof the software without specific prior written permission. 12f7df2e56SmrgSilicon Graphics makes no representation about the suitability 1305b261ecSmrgof this software for any purpose. It is provided "as is" 1405b261ecSmrgwithout any express or implied warranty. 1505b261ecSmrg 16f7df2e56SmrgSILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS 17f7df2e56SmrgSOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 1805b261ecSmrgAND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON 19f7df2e56SmrgGRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL 20f7df2e56SmrgDAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 21f7df2e56SmrgDATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 2205b261ecSmrgOR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH 2305b261ecSmrgTHE USE OR PERFORMANCE OF THIS SOFTWARE. 2405b261ecSmrg 2505b261ecSmrg********************************************************/ 2605b261ecSmrg 2705b261ecSmrg#ifdef HAVE_DIX_CONFIG_H 2805b261ecSmrg#include <dix-config.h> 2905b261ecSmrg#endif 3005b261ecSmrg 3105b261ecSmrg#include <stdio.h> 3205b261ecSmrg#include <X11/X.h> 3305b261ecSmrg#include <X11/Xproto.h> 3405b261ecSmrg#include "misc.h" 3505b261ecSmrg#include "inputstr.h" 3605b261ecSmrg#define XKBSRV_NEED_FILE_FUNCS 3705b261ecSmrg#include <xkbsrv.h> 3805b261ecSmrg#include "extnsionst.h" 39f7df2e56Smrg#include "extinit.h" 404642e01fSmrg#include "xace.h" 4105b261ecSmrg#include "xkb.h" 426747b715Smrg#include "protocol-versions.h" 4305b261ecSmrg 4405b261ecSmrg#include <X11/extensions/XI.h> 456747b715Smrg#include <X11/extensions/XKMformat.h> 4605b261ecSmrg 47f7df2e56Smrgint XkbEventBase; 48f7df2e56Smrgstatic int XkbErrorBase; 49f7df2e56Smrgint XkbReqCode; 50f7df2e56Smrgint XkbKeyboardErrorCode; 51f7df2e56SmrgCARD32 xkbDebugFlags = 0; 52f7df2e56Smrgstatic CARD32 xkbDebugCtrls = 0; 5305b261ecSmrg 54f7df2e56Smrgstatic RESTYPE RT_XKBCLIENT; 5505b261ecSmrg 5605b261ecSmrg/***====================================================================***/ 5705b261ecSmrg 584642e01fSmrg#define CHK_DEVICE(dev, id, client, access_mode, lf) {\ 5905b261ecSmrg int why;\ 60f7df2e56Smrg int tmprc = lf(&(dev), id, client, access_mode, &why);\ 61f7df2e56Smrg if (tmprc != Success) {\ 624642e01fSmrg client->errorValue = _XkbErrCode2(why, id);\ 63f7df2e56Smrg return tmprc;\ 6405b261ecSmrg }\ 6505b261ecSmrg} 6605b261ecSmrg 674642e01fSmrg#define CHK_KBD_DEVICE(dev, id, client, mode) \ 684642e01fSmrg CHK_DEVICE(dev, id, client, mode, _XkbLookupKeyboard) 694642e01fSmrg#define CHK_LED_DEVICE(dev, id, client, mode) \ 704642e01fSmrg CHK_DEVICE(dev, id, client, mode, _XkbLookupLedDevice) 714642e01fSmrg#define CHK_BELL_DEVICE(dev, id, client, mode) \ 724642e01fSmrg CHK_DEVICE(dev, id, client, mode, _XkbLookupBellDevice) 734642e01fSmrg#define CHK_ANY_DEVICE(dev, id, client, mode) \ 744642e01fSmrg CHK_DEVICE(dev, id, client, mode, _XkbLookupAnyDevice) 7505b261ecSmrg 7605b261ecSmrg#define CHK_ATOM_ONLY2(a,ev,er) {\ 7705b261ecSmrg if (((a)==None)||(!ValidAtom((a)))) {\ 7805b261ecSmrg (ev)= (XID)(a);\ 7905b261ecSmrg return er;\ 8005b261ecSmrg }\ 8105b261ecSmrg} 8205b261ecSmrg#define CHK_ATOM_ONLY(a) \ 8305b261ecSmrg CHK_ATOM_ONLY2(a,client->errorValue,BadAtom) 8405b261ecSmrg 8505b261ecSmrg#define CHK_ATOM_OR_NONE3(a,ev,er,ret) {\ 8605b261ecSmrg if (((a)!=None)&&(!ValidAtom((a)))) {\ 8705b261ecSmrg (ev)= (XID)(a);\ 8805b261ecSmrg (er)= BadAtom;\ 8905b261ecSmrg return ret;\ 9005b261ecSmrg }\ 9105b261ecSmrg} 9205b261ecSmrg#define CHK_ATOM_OR_NONE2(a,ev,er) {\ 9305b261ecSmrg if (((a)!=None)&&(!ValidAtom((a)))) {\ 9405b261ecSmrg (ev)= (XID)(a);\ 9505b261ecSmrg return er;\ 9605b261ecSmrg }\ 9705b261ecSmrg} 9805b261ecSmrg#define CHK_ATOM_OR_NONE(a) \ 9905b261ecSmrg CHK_ATOM_OR_NONE2(a,client->errorValue,BadAtom) 10005b261ecSmrg 10105b261ecSmrg#define CHK_MASK_LEGAL3(err,mask,legal,ev,er,ret) {\ 10205b261ecSmrg if ((mask)&(~(legal))) { \ 10305b261ecSmrg (ev)= _XkbErrCode2((err),((mask)&(~(legal))));\ 10405b261ecSmrg (er)= BadValue;\ 10505b261ecSmrg return ret;\ 10605b261ecSmrg }\ 10705b261ecSmrg} 10805b261ecSmrg#define CHK_MASK_LEGAL2(err,mask,legal,ev,er) {\ 10905b261ecSmrg if ((mask)&(~(legal))) { \ 11005b261ecSmrg (ev)= _XkbErrCode2((err),((mask)&(~(legal))));\ 11105b261ecSmrg return er;\ 11205b261ecSmrg }\ 11305b261ecSmrg} 11405b261ecSmrg#define CHK_MASK_LEGAL(err,mask,legal) \ 11505b261ecSmrg CHK_MASK_LEGAL2(err,mask,legal,client->errorValue,BadValue) 11605b261ecSmrg 11705b261ecSmrg#define CHK_MASK_MATCH(err,affect,value) {\ 11805b261ecSmrg if ((value)&(~(affect))) { \ 11905b261ecSmrg client->errorValue= _XkbErrCode2((err),((value)&(~(affect))));\ 12005b261ecSmrg return BadMatch;\ 12105b261ecSmrg }\ 12205b261ecSmrg} 12305b261ecSmrg#define CHK_MASK_OVERLAP(err,m1,m2) {\ 12405b261ecSmrg if ((m1)&(m2)) { \ 12505b261ecSmrg client->errorValue= _XkbErrCode2((err),((m1)&(m2)));\ 12605b261ecSmrg return BadMatch;\ 12705b261ecSmrg }\ 12805b261ecSmrg} 12905b261ecSmrg#define CHK_KEY_RANGE2(err,first,num,x,ev,er) {\ 13005b261ecSmrg if (((unsigned)(first)+(num)-1)>(x)->max_key_code) {\ 13105b261ecSmrg (ev)=_XkbErrCode4(err,(first),(num),(x)->max_key_code);\ 13205b261ecSmrg return er;\ 13305b261ecSmrg }\ 13405b261ecSmrg else if ( (first)<(x)->min_key_code ) {\ 13505b261ecSmrg (ev)=_XkbErrCode3(err+1,(first),xkb->min_key_code);\ 13605b261ecSmrg return er;\ 13705b261ecSmrg }\ 13805b261ecSmrg} 13905b261ecSmrg#define CHK_KEY_RANGE(err,first,num,x) \ 14005b261ecSmrg CHK_KEY_RANGE2(err,first,num,x,client->errorValue,BadValue) 14105b261ecSmrg 14205b261ecSmrg#define CHK_REQ_KEY_RANGE2(err,first,num,r,ev,er) {\ 14305b261ecSmrg if (((unsigned)(first)+(num)-1)>(r)->maxKeyCode) {\ 14405b261ecSmrg (ev)=_XkbErrCode4(err,(first),(num),(r)->maxKeyCode);\ 14505b261ecSmrg return er;\ 14605b261ecSmrg }\ 14705b261ecSmrg else if ( (first)<(r)->minKeyCode ) {\ 14805b261ecSmrg (ev)=_XkbErrCode3(err+1,(first),(r)->minKeyCode);\ 14905b261ecSmrg return er;\ 15005b261ecSmrg }\ 15105b261ecSmrg} 15205b261ecSmrg#define CHK_REQ_KEY_RANGE(err,first,num,r) \ 15305b261ecSmrg CHK_REQ_KEY_RANGE2(err,first,num,r,client->errorValue,BadValue) 15405b261ecSmrg 155806e81e9Smrgstatic Bool 156806e81e9Smrg_XkbCheckRequestBounds(ClientPtr client, void *stuff, void *from, void *to) { 157806e81e9Smrg char *cstuff = (char *)stuff; 158806e81e9Smrg char *cfrom = (char *)from; 159806e81e9Smrg char *cto = (char *)to; 160806e81e9Smrg 161806e81e9Smrg return cfrom < cto && 162806e81e9Smrg cfrom >= cstuff && 163806e81e9Smrg cfrom < cstuff + ((size_t)client->req_len << 2) && 164806e81e9Smrg cto >= cstuff && 165806e81e9Smrg cto <= cstuff + ((size_t)client->req_len << 2); 166806e81e9Smrg} 167806e81e9Smrg 16805b261ecSmrg/***====================================================================***/ 16905b261ecSmrg 17005b261ecSmrgint 17105b261ecSmrgProcXkbUseExtension(ClientPtr client) 17205b261ecSmrg{ 17305b261ecSmrg REQUEST(xkbUseExtensionReq); 174f7df2e56Smrg xkbUseExtensionReply rep; 175f7df2e56Smrg int supported; 17605b261ecSmrg 17705b261ecSmrg REQUEST_SIZE_MATCH(xkbUseExtensionReq); 1786747b715Smrg if (stuff->wantedMajor != SERVER_XKB_MAJOR_VERSION) { 179f7df2e56Smrg /* pre-release version 0.65 is compatible with 1.00 */ 180f7df2e56Smrg supported = ((SERVER_XKB_MAJOR_VERSION == 1) && 181f7df2e56Smrg (stuff->wantedMajor == 0) && (stuff->wantedMinor == 65)); 182f7df2e56Smrg } 183f7df2e56Smrg else 184f7df2e56Smrg supported = 1; 185f7df2e56Smrg 186f7df2e56Smrg if ((supported) && (!(client->xkbClientFlags & _XkbClientInitialized))) { 187f7df2e56Smrg client->xkbClientFlags = _XkbClientInitialized; 1887e31ba66Smrg if (stuff->wantedMajor == 0) 1897e31ba66Smrg client->xkbClientFlags |= _XkbClientIsAncient; 190f7df2e56Smrg } 191f7df2e56Smrg else if (xkbDebugFlags & 0x1) { 192f7df2e56Smrg ErrorF 193f7df2e56Smrg ("[xkb] Rejecting client %d (0x%lx) (wants %d.%02d, have %d.%02d)\n", 194f7df2e56Smrg client->index, (long) client->clientAsMask, stuff->wantedMajor, 195f7df2e56Smrg stuff->wantedMinor, SERVER_XKB_MAJOR_VERSION, 196f7df2e56Smrg SERVER_XKB_MINOR_VERSION); 197f7df2e56Smrg } 198f7df2e56Smrg rep = (xkbUseExtensionReply) { 199f7df2e56Smrg .type = X_Reply, 200f7df2e56Smrg .supported = supported, 201f7df2e56Smrg .sequenceNumber = client->sequence, 202f7df2e56Smrg .length = 0, 203f7df2e56Smrg .serverMajor = SERVER_XKB_MAJOR_VERSION, 204f7df2e56Smrg .serverMinor = SERVER_XKB_MINOR_VERSION 205f7df2e56Smrg }; 206f7df2e56Smrg if (client->swapped) { 207f7df2e56Smrg swaps(&rep.sequenceNumber); 208f7df2e56Smrg swaps(&rep.serverMajor); 209f7df2e56Smrg swaps(&rep.serverMinor); 21005b261ecSmrg } 211f7df2e56Smrg WriteToClient(client, SIZEOF(xkbUseExtensionReply), &rep); 2126747b715Smrg return Success; 21305b261ecSmrg} 21405b261ecSmrg 21505b261ecSmrg/***====================================================================***/ 21605b261ecSmrg 21705b261ecSmrgint 21805b261ecSmrgProcXkbSelectEvents(ClientPtr client) 21905b261ecSmrg{ 220f7df2e56Smrg unsigned legal; 221f7df2e56Smrg DeviceIntPtr dev; 222f7df2e56Smrg XkbInterestPtr masks; 223f7df2e56Smrg 22405b261ecSmrg REQUEST(xkbSelectEventsReq); 22505b261ecSmrg 22605b261ecSmrg REQUEST_AT_LEAST_SIZE(xkbSelectEventsReq); 22705b261ecSmrg 228f7df2e56Smrg if (!(client->xkbClientFlags & _XkbClientInitialized)) 229f7df2e56Smrg return BadAccess; 23005b261ecSmrg 2314642e01fSmrg CHK_ANY_DEVICE(dev, stuff->deviceSpec, client, DixUseAccess); 23205b261ecSmrg 233f7df2e56Smrg if (((stuff->affectWhich & XkbMapNotifyMask) != 0) && (stuff->affectMap)) { 234f7df2e56Smrg client->mapNotifyMask &= ~stuff->affectMap; 235f7df2e56Smrg client->mapNotifyMask |= (stuff->affectMap & stuff->map); 23605b261ecSmrg } 237f7df2e56Smrg if ((stuff->affectWhich & (~XkbMapNotifyMask)) == 0) 238f7df2e56Smrg return Success; 239f7df2e56Smrg 240f7df2e56Smrg masks = XkbFindClientResource((DevicePtr) dev, client); 241f7df2e56Smrg if (!masks) { 242f7df2e56Smrg XID id = FakeClientID(client->index); 24305b261ecSmrg 244f7df2e56Smrg if (!AddResource(id, RT_XKBCLIENT, dev)) 245f7df2e56Smrg return BadAlloc; 246f7df2e56Smrg masks = XkbAddClientResource((DevicePtr) dev, client, id); 24705b261ecSmrg } 24805b261ecSmrg if (masks) { 249f7df2e56Smrg union { 250f7df2e56Smrg CARD8 *c8; 251f7df2e56Smrg CARD16 *c16; 252f7df2e56Smrg CARD32 *c32; 253f7df2e56Smrg } from, to; 254f7df2e56Smrg register unsigned bit, ndx, maskLeft, dataLeft, size; 255f7df2e56Smrg 256f7df2e56Smrg from.c8 = (CARD8 *) &stuff[1]; 257f7df2e56Smrg dataLeft = (stuff->length * 4) - SIZEOF(xkbSelectEventsReq); 258f7df2e56Smrg maskLeft = (stuff->affectWhich & (~XkbMapNotifyMask)); 259f7df2e56Smrg for (ndx = 0, bit = 1; (maskLeft != 0); ndx++, bit <<= 1) { 260f7df2e56Smrg if ((bit & maskLeft) == 0) 261f7df2e56Smrg continue; 262f7df2e56Smrg maskLeft &= ~bit; 263f7df2e56Smrg switch (ndx) { 264f7df2e56Smrg case XkbNewKeyboardNotify: 265f7df2e56Smrg to.c16 = &client->newKeyboardNotifyMask; 266f7df2e56Smrg legal = XkbAllNewKeyboardEventsMask; 267f7df2e56Smrg size = 2; 268f7df2e56Smrg break; 269f7df2e56Smrg case XkbStateNotify: 270f7df2e56Smrg to.c16 = &masks->stateNotifyMask; 271f7df2e56Smrg legal = XkbAllStateEventsMask; 272f7df2e56Smrg size = 2; 273f7df2e56Smrg break; 274f7df2e56Smrg case XkbControlsNotify: 275f7df2e56Smrg to.c32 = &masks->ctrlsNotifyMask; 276f7df2e56Smrg legal = XkbAllControlEventsMask; 277f7df2e56Smrg size = 4; 278f7df2e56Smrg break; 279f7df2e56Smrg case XkbIndicatorStateNotify: 280f7df2e56Smrg to.c32 = &masks->iStateNotifyMask; 281f7df2e56Smrg legal = XkbAllIndicatorEventsMask; 282f7df2e56Smrg size = 4; 283f7df2e56Smrg break; 284f7df2e56Smrg case XkbIndicatorMapNotify: 285f7df2e56Smrg to.c32 = &masks->iMapNotifyMask; 286f7df2e56Smrg legal = XkbAllIndicatorEventsMask; 287f7df2e56Smrg size = 4; 288f7df2e56Smrg break; 289f7df2e56Smrg case XkbNamesNotify: 290f7df2e56Smrg to.c16 = &masks->namesNotifyMask; 291f7df2e56Smrg legal = XkbAllNameEventsMask; 292f7df2e56Smrg size = 2; 293f7df2e56Smrg break; 294f7df2e56Smrg case XkbCompatMapNotify: 295f7df2e56Smrg to.c8 = &masks->compatNotifyMask; 296f7df2e56Smrg legal = XkbAllCompatMapEventsMask; 297f7df2e56Smrg size = 1; 298f7df2e56Smrg break; 299f7df2e56Smrg case XkbBellNotify: 300f7df2e56Smrg to.c8 = &masks->bellNotifyMask; 301f7df2e56Smrg legal = XkbAllBellEventsMask; 302f7df2e56Smrg size = 1; 303f7df2e56Smrg break; 304f7df2e56Smrg case XkbActionMessage: 305f7df2e56Smrg to.c8 = &masks->actionMessageMask; 306f7df2e56Smrg legal = XkbAllActionMessagesMask; 307f7df2e56Smrg size = 1; 308f7df2e56Smrg break; 309f7df2e56Smrg case XkbAccessXNotify: 310f7df2e56Smrg to.c16 = &masks->accessXNotifyMask; 311f7df2e56Smrg legal = XkbAllAccessXEventsMask; 312f7df2e56Smrg size = 2; 313f7df2e56Smrg break; 314f7df2e56Smrg case XkbExtensionDeviceNotify: 315f7df2e56Smrg to.c16 = &masks->extDevNotifyMask; 316f7df2e56Smrg legal = XkbAllExtensionDeviceEventsMask; 317f7df2e56Smrg size = 2; 318f7df2e56Smrg break; 319f7df2e56Smrg default: 320f7df2e56Smrg client->errorValue = _XkbErrCode2(33, bit); 321f7df2e56Smrg return BadValue; 322f7df2e56Smrg } 323f7df2e56Smrg 324f7df2e56Smrg if (stuff->clear & bit) { 325f7df2e56Smrg if (size == 2) 326f7df2e56Smrg to.c16[0] = 0; 327f7df2e56Smrg else if (size == 4) 328f7df2e56Smrg to.c32[0] = 0; 329f7df2e56Smrg else 330f7df2e56Smrg to.c8[0] = 0; 331f7df2e56Smrg } 332f7df2e56Smrg else if (stuff->selectAll & bit) { 333f7df2e56Smrg if (size == 2) 334f7df2e56Smrg to.c16[0] = ~0; 335f7df2e56Smrg else if (size == 4) 336f7df2e56Smrg to.c32[0] = ~0; 337f7df2e56Smrg else 338f7df2e56Smrg to.c8[0] = ~0; 339f7df2e56Smrg } 340f7df2e56Smrg else { 341f7df2e56Smrg if (dataLeft < (size * 2)) 342f7df2e56Smrg return BadLength; 343f7df2e56Smrg if (size == 2) { 344f7df2e56Smrg CHK_MASK_MATCH(ndx, from.c16[0], from.c16[1]); 345f7df2e56Smrg CHK_MASK_LEGAL(ndx, from.c16[0], legal); 346f7df2e56Smrg to.c16[0] &= ~from.c16[0]; 347f7df2e56Smrg to.c16[0] |= (from.c16[0] & from.c16[1]); 348f7df2e56Smrg } 349f7df2e56Smrg else if (size == 4) { 350f7df2e56Smrg CHK_MASK_MATCH(ndx, from.c32[0], from.c32[1]); 351f7df2e56Smrg CHK_MASK_LEGAL(ndx, from.c32[0], legal); 352f7df2e56Smrg to.c32[0] &= ~from.c32[0]; 353f7df2e56Smrg to.c32[0] |= (from.c32[0] & from.c32[1]); 354f7df2e56Smrg } 355f7df2e56Smrg else { 356f7df2e56Smrg CHK_MASK_MATCH(ndx, from.c8[0], from.c8[1]); 357f7df2e56Smrg CHK_MASK_LEGAL(ndx, from.c8[0], legal); 358f7df2e56Smrg to.c8[0] &= ~from.c8[0]; 359f7df2e56Smrg to.c8[0] |= (from.c8[0] & from.c8[1]); 360f7df2e56Smrg size = 2; 361f7df2e56Smrg } 362f7df2e56Smrg from.c8 += (size * 2); 363f7df2e56Smrg dataLeft -= (size * 2); 364f7df2e56Smrg } 365f7df2e56Smrg } 366f7df2e56Smrg if (dataLeft > 2) { 367f7df2e56Smrg ErrorF("[xkb] Extra data (%d bytes) after SelectEvents\n", 368f7df2e56Smrg dataLeft); 369f7df2e56Smrg return BadLength; 370f7df2e56Smrg } 371f7df2e56Smrg return Success; 37205b261ecSmrg } 37305b261ecSmrg return BadAlloc; 37405b261ecSmrg} 37505b261ecSmrg 37605b261ecSmrg/***====================================================================***/ 3774642e01fSmrg/** 3784642e01fSmrg * Ring a bell on the given device for the given client. 3794642e01fSmrg */ 3804642e01fSmrgstatic int 3814642e01fSmrg_XkbBell(ClientPtr client, DeviceIntPtr dev, WindowPtr pWin, 3824642e01fSmrg int bellClass, int bellID, int pitch, int duration, 3834642e01fSmrg int percent, int forceSound, int eventOnly, Atom name) 3844642e01fSmrg{ 385f7df2e56Smrg int base; 386f7df2e56Smrg void *ctrl; 387f7df2e56Smrg int oldPitch, oldDuration; 388f7df2e56Smrg int newPercent; 3894642e01fSmrg 3904642e01fSmrg if (bellClass == KbdFeedbackClass) { 391f7df2e56Smrg KbdFeedbackPtr k; 392f7df2e56Smrg 393f7df2e56Smrg if (bellID == XkbDfltXIId) 394f7df2e56Smrg k = dev->kbdfeed; 3954642e01fSmrg else { 396f7df2e56Smrg for (k = dev->kbdfeed; k; k = k->next) { 3974642e01fSmrg if (k->ctrl.id == bellID) 3984642e01fSmrg break; 3994642e01fSmrg } 4004642e01fSmrg } 4014642e01fSmrg if (!k) { 402f7df2e56Smrg client->errorValue = _XkbErrCode2(0x5, bellID); 4034642e01fSmrg return BadValue; 4044642e01fSmrg } 4054642e01fSmrg base = k->ctrl.bell; 406f7df2e56Smrg ctrl = (void *) &(k->ctrl); 407f7df2e56Smrg oldPitch = k->ctrl.bell_pitch; 408f7df2e56Smrg oldDuration = k->ctrl.bell_duration; 409f7df2e56Smrg if (pitch != 0) { 410f7df2e56Smrg if (pitch == -1) 411f7df2e56Smrg k->ctrl.bell_pitch = defaultKeyboardControl.bell_pitch; 412f7df2e56Smrg else 413f7df2e56Smrg k->ctrl.bell_pitch = pitch; 4144642e01fSmrg } 415f7df2e56Smrg if (duration != 0) { 416f7df2e56Smrg if (duration == -1) 417f7df2e56Smrg k->ctrl.bell_duration = defaultKeyboardControl.bell_duration; 418f7df2e56Smrg else 419f7df2e56Smrg k->ctrl.bell_duration = duration; 4204642e01fSmrg } 4214642e01fSmrg } 4224642e01fSmrg else if (bellClass == BellFeedbackClass) { 423f7df2e56Smrg BellFeedbackPtr b; 424f7df2e56Smrg 425f7df2e56Smrg if (bellID == XkbDfltXIId) 426f7df2e56Smrg b = dev->bell; 4274642e01fSmrg else { 428f7df2e56Smrg for (b = dev->bell; b; b = b->next) { 4294642e01fSmrg if (b->ctrl.id == bellID) 4304642e01fSmrg break; 4314642e01fSmrg } 4324642e01fSmrg } 4334642e01fSmrg if (!b) { 434f7df2e56Smrg client->errorValue = _XkbErrCode2(0x6, bellID); 4354642e01fSmrg return BadValue; 4364642e01fSmrg } 4374642e01fSmrg base = b->ctrl.percent; 438f7df2e56Smrg ctrl = (void *) &(b->ctrl); 439f7df2e56Smrg oldPitch = b->ctrl.pitch; 440f7df2e56Smrg oldDuration = b->ctrl.duration; 441f7df2e56Smrg if (pitch != 0) { 442f7df2e56Smrg if (pitch == -1) 443f7df2e56Smrg b->ctrl.pitch = defaultKeyboardControl.bell_pitch; 444f7df2e56Smrg else 445f7df2e56Smrg b->ctrl.pitch = pitch; 4464642e01fSmrg } 447f7df2e56Smrg if (duration != 0) { 448f7df2e56Smrg if (duration == -1) 449f7df2e56Smrg b->ctrl.duration = defaultKeyboardControl.bell_duration; 450f7df2e56Smrg else 451f7df2e56Smrg b->ctrl.duration = duration; 4524642e01fSmrg } 4534642e01fSmrg } 4544642e01fSmrg else { 4554642e01fSmrg client->errorValue = _XkbErrCode2(0x7, bellClass); 4564642e01fSmrg return BadValue; 4574642e01fSmrg } 4584642e01fSmrg 459f7df2e56Smrg newPercent = (base * percent) / 100; 4604642e01fSmrg if (percent < 0) 461f7df2e56Smrg newPercent = base + newPercent; 462f7df2e56Smrg else 463f7df2e56Smrg newPercent = base - newPercent + percent; 4644642e01fSmrg 4654642e01fSmrg XkbHandleBell(forceSound, eventOnly, 466f7df2e56Smrg dev, newPercent, ctrl, bellClass, name, pWin, client); 467f7df2e56Smrg if ((pitch != 0) || (duration != 0)) { 4684642e01fSmrg if (bellClass == KbdFeedbackClass) { 469f7df2e56Smrg KbdFeedbackPtr k; 470f7df2e56Smrg 471f7df2e56Smrg k = (KbdFeedbackPtr) ctrl; 472f7df2e56Smrg if (pitch != 0) 473f7df2e56Smrg k->ctrl.bell_pitch = oldPitch; 474f7df2e56Smrg if (duration != 0) 475f7df2e56Smrg k->ctrl.bell_duration = oldDuration; 4764642e01fSmrg } 4774642e01fSmrg else { 478f7df2e56Smrg BellFeedbackPtr b; 479f7df2e56Smrg 480f7df2e56Smrg b = (BellFeedbackPtr) ctrl; 481f7df2e56Smrg if (pitch != 0) 482f7df2e56Smrg b->ctrl.pitch = oldPitch; 483f7df2e56Smrg if (duration != 0) 484f7df2e56Smrg b->ctrl.duration = oldDuration; 4854642e01fSmrg } 4864642e01fSmrg } 4874642e01fSmrg 4884642e01fSmrg return Success; 4894642e01fSmrg} 49005b261ecSmrg 49105b261ecSmrgint 49205b261ecSmrgProcXkbBell(ClientPtr client) 49305b261ecSmrg{ 49405b261ecSmrg REQUEST(xkbBellReq); 49505b261ecSmrg DeviceIntPtr dev; 496f7df2e56Smrg WindowPtr pWin; 4974642e01fSmrg int rc; 49805b261ecSmrg 49905b261ecSmrg REQUEST_SIZE_MATCH(xkbBellReq); 50005b261ecSmrg 501f7df2e56Smrg if (!(client->xkbClientFlags & _XkbClientInitialized)) 502f7df2e56Smrg return BadAccess; 50305b261ecSmrg 5044642e01fSmrg CHK_BELL_DEVICE(dev, stuff->deviceSpec, client, DixBellAccess); 50505b261ecSmrg CHK_ATOM_OR_NONE(stuff->name); 50605b261ecSmrg 5074642e01fSmrg /* device-independent checks request for sane values */ 508f7df2e56Smrg if ((stuff->forceSound) && (stuff->eventOnly)) { 509f7df2e56Smrg client->errorValue = 510f7df2e56Smrg _XkbErrCode3(0x1, stuff->forceSound, stuff->eventOnly); 511f7df2e56Smrg return BadMatch; 51205b261ecSmrg } 51305b261ecSmrg if (stuff->percent < -100 || stuff->percent > 100) { 514f7df2e56Smrg client->errorValue = _XkbErrCode2(0x2, stuff->percent); 515f7df2e56Smrg return BadValue; 51605b261ecSmrg } 517f7df2e56Smrg if (stuff->duration < -1) { 518f7df2e56Smrg client->errorValue = _XkbErrCode2(0x3, stuff->duration); 519f7df2e56Smrg return BadValue; 52005b261ecSmrg } 521f7df2e56Smrg if (stuff->pitch < -1) { 522f7df2e56Smrg client->errorValue = _XkbErrCode2(0x4, stuff->pitch); 523f7df2e56Smrg return BadValue; 52405b261ecSmrg } 52505b261ecSmrg 52605b261ecSmrg if (stuff->bellClass == XkbDfltXIClass) { 527f7df2e56Smrg if (dev->kbdfeed != NULL) 528f7df2e56Smrg stuff->bellClass = KbdFeedbackClass; 529f7df2e56Smrg else 530f7df2e56Smrg stuff->bellClass = BellFeedbackClass; 53105b261ecSmrg } 5324642e01fSmrg 533f7df2e56Smrg if (stuff->window != None) { 534f7df2e56Smrg rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess); 535f7df2e56Smrg if (rc != Success) { 536f7df2e56Smrg client->errorValue = stuff->window; 537f7df2e56Smrg return rc; 538f7df2e56Smrg } 53905b261ecSmrg } 540f7df2e56Smrg else 541f7df2e56Smrg pWin = NULL; 54205b261ecSmrg 5434642e01fSmrg /* Client wants to ring a bell on the core keyboard? 5444642e01fSmrg Ring the bell on the core keyboard (which does nothing, but if that 5454642e01fSmrg fails the client is screwed anyway), and then on all extension devices. 5464642e01fSmrg Fail if the core keyboard fails but not the extension devices. this 5474642e01fSmrg may cause some keyboards to ding and others to stay silent. Fix 5484642e01fSmrg your client to use explicit keyboards to avoid this. 5494642e01fSmrg 5504642e01fSmrg dev is the device the client requested. 5514642e01fSmrg */ 5524642e01fSmrg rc = _XkbBell(client, dev, pWin, stuff->bellClass, stuff->bellID, 5534642e01fSmrg stuff->pitch, stuff->duration, stuff->percent, 5544642e01fSmrg stuff->forceSound, stuff->eventOnly, stuff->name); 5554642e01fSmrg 5564642e01fSmrg if ((rc == Success) && ((stuff->deviceSpec == XkbUseCoreKbd) || 557f7df2e56Smrg (stuff->deviceSpec == XkbUseCorePtr))) { 5584642e01fSmrg DeviceIntPtr other; 559f7df2e56Smrg 560f7df2e56Smrg for (other = inputInfo.devices; other; other = other->next) { 561f7df2e56Smrg if ((other != dev) && other->key && !IsMaster(other) && 562f7df2e56Smrg GetMaster(other, MASTER_KEYBOARD) == dev) { 5634642e01fSmrg rc = XaceHook(XACE_DEVICE_ACCESS, client, other, DixBellAccess); 5644642e01fSmrg if (rc == Success) 5654642e01fSmrg _XkbBell(client, other, pWin, stuff->bellClass, 5664642e01fSmrg stuff->bellID, stuff->pitch, stuff->duration, 5674642e01fSmrg stuff->percent, stuff->forceSound, 5684642e01fSmrg stuff->eventOnly, stuff->name); 5694642e01fSmrg } 5704642e01fSmrg } 571f7df2e56Smrg rc = Success; /* reset to success, that's what we got for the VCK */ 57205b261ecSmrg } 5734642e01fSmrg 5744642e01fSmrg return rc; 57505b261ecSmrg} 57605b261ecSmrg 57705b261ecSmrg/***====================================================================***/ 57805b261ecSmrg 57905b261ecSmrgint 58005b261ecSmrgProcXkbGetState(ClientPtr client) 58105b261ecSmrg{ 58205b261ecSmrg REQUEST(xkbGetStateReq); 583f7df2e56Smrg DeviceIntPtr dev; 584f7df2e56Smrg xkbGetStateReply rep; 585f7df2e56Smrg XkbStateRec *xkb; 58605b261ecSmrg 58705b261ecSmrg REQUEST_SIZE_MATCH(xkbGetStateReq); 58805b261ecSmrg 589f7df2e56Smrg if (!(client->xkbClientFlags & _XkbClientInitialized)) 590f7df2e56Smrg return BadAccess; 59105b261ecSmrg 5926747b715Smrg CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess); 59305b261ecSmrg 594f7df2e56Smrg xkb = &dev->key->xkbInfo->state; 595f7df2e56Smrg rep = (xkbGetStateReply) { 596f7df2e56Smrg .type = X_Reply, 597f7df2e56Smrg .deviceID = dev->id, 598f7df2e56Smrg .sequenceNumber = client->sequence, 599f7df2e56Smrg .length = 0, 600f7df2e56Smrg .mods = XkbStateFieldFromRec(xkb) & 0xff, 601f7df2e56Smrg .baseMods = xkb->base_mods, 602f7df2e56Smrg .latchedMods = xkb->latched_mods, 603f7df2e56Smrg .lockedMods = xkb->locked_mods, 604f7df2e56Smrg .group = xkb->group, 605f7df2e56Smrg .lockedGroup = xkb->locked_group, 606f7df2e56Smrg .baseGroup = xkb->base_group, 607f7df2e56Smrg .latchedGroup = xkb->latched_group, 608f7df2e56Smrg .compatState = xkb->compat_state, 609f7df2e56Smrg .ptrBtnState = xkb->ptr_buttons 610f7df2e56Smrg }; 61105b261ecSmrg if (client->swapped) { 612f7df2e56Smrg swaps(&rep.sequenceNumber); 613f7df2e56Smrg swaps(&rep.ptrBtnState); 61405b261ecSmrg } 615f7df2e56Smrg WriteToClient(client, SIZEOF(xkbGetStateReply), &rep); 6166747b715Smrg return Success; 61705b261ecSmrg} 61805b261ecSmrg 61905b261ecSmrg/***====================================================================***/ 62005b261ecSmrg 62105b261ecSmrgint 62205b261ecSmrgProcXkbLatchLockState(ClientPtr client) 62305b261ecSmrg{ 62405b261ecSmrg int status; 62505b261ecSmrg DeviceIntPtr dev, tmpd; 626f7df2e56Smrg XkbStateRec oldState, *newState; 62705b261ecSmrg CARD16 changed; 62805b261ecSmrg xkbStateNotify sn; 62905b261ecSmrg XkbEventCauseRec cause; 63005b261ecSmrg 63105b261ecSmrg REQUEST(xkbLatchLockStateReq); 63205b261ecSmrg REQUEST_SIZE_MATCH(xkbLatchLockStateReq); 63305b261ecSmrg 63405b261ecSmrg if (!(client->xkbClientFlags & _XkbClientInitialized)) 635f7df2e56Smrg return BadAccess; 63605b261ecSmrg 6374642e01fSmrg CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixSetAttrAccess); 63805b261ecSmrg CHK_MASK_MATCH(0x01, stuff->affectModLocks, stuff->modLocks); 63905b261ecSmrg CHK_MASK_MATCH(0x01, stuff->affectModLatches, stuff->modLatches); 64005b261ecSmrg 64105b261ecSmrg status = Success; 64205b261ecSmrg 64305b261ecSmrg for (tmpd = inputInfo.devices; tmpd; tmpd = tmpd->next) { 644f7df2e56Smrg if ((tmpd == dev) || 645f7df2e56Smrg (!IsMaster(tmpd) && GetMaster(tmpd, MASTER_KEYBOARD) == dev)) { 6466747b715Smrg if (!tmpd->key || !tmpd->key->xkbInfo) 64705b261ecSmrg continue; 64805b261ecSmrg 64905b261ecSmrg oldState = tmpd->key->xkbInfo->state; 65005b261ecSmrg newState = &tmpd->key->xkbInfo->state; 65105b261ecSmrg if (stuff->affectModLocks) { 65205b261ecSmrg newState->locked_mods &= ~stuff->affectModLocks; 653f7df2e56Smrg newState->locked_mods |= 654f7df2e56Smrg (stuff->affectModLocks & stuff->modLocks); 65505b261ecSmrg } 65605b261ecSmrg if (status == Success && stuff->lockGroup) 65705b261ecSmrg newState->locked_group = stuff->groupLock; 65805b261ecSmrg if (status == Success && stuff->affectModLatches) 65905b261ecSmrg status = XkbLatchModifiers(tmpd, stuff->affectModLatches, 66005b261ecSmrg stuff->modLatches); 66105b261ecSmrg if (status == Success && stuff->latchGroup) 66205b261ecSmrg status = XkbLatchGroup(tmpd, stuff->groupLatch); 66305b261ecSmrg 66405b261ecSmrg if (status != Success) 66505b261ecSmrg return status; 66605b261ecSmrg 66705b261ecSmrg XkbComputeDerivedState(tmpd->key->xkbInfo); 66805b261ecSmrg 66905b261ecSmrg changed = XkbStateChangedFlags(&oldState, newState); 67005b261ecSmrg if (changed) { 67105b261ecSmrg sn.keycode = 0; 67205b261ecSmrg sn.eventType = 0; 67305b261ecSmrg sn.requestMajor = XkbReqCode; 67405b261ecSmrg sn.requestMinor = X_kbLatchLockState; 67505b261ecSmrg sn.changed = changed; 67605b261ecSmrg XkbSendStateNotify(tmpd, &sn); 6776747b715Smrg changed = XkbIndicatorsToUpdate(tmpd, changed, FALSE); 67805b261ecSmrg if (changed) { 67905b261ecSmrg XkbSetCauseXkbReq(&cause, X_kbLatchLockState, client); 6806747b715Smrg XkbUpdateIndicators(tmpd, changed, TRUE, NULL, &cause); 681f7df2e56Smrg } 68205b261ecSmrg } 68305b261ecSmrg } 68405b261ecSmrg } 68505b261ecSmrg 6866747b715Smrg return Success; 68705b261ecSmrg} 68805b261ecSmrg 68905b261ecSmrg/***====================================================================***/ 69005b261ecSmrg 69105b261ecSmrgint 69205b261ecSmrgProcXkbGetControls(ClientPtr client) 69305b261ecSmrg{ 69405b261ecSmrg xkbGetControlsReply rep; 695f7df2e56Smrg XkbControlsPtr xkb; 696f7df2e56Smrg DeviceIntPtr dev; 69705b261ecSmrg 69805b261ecSmrg REQUEST(xkbGetControlsReq); 69905b261ecSmrg REQUEST_SIZE_MATCH(xkbGetControlsReq); 70005b261ecSmrg 701f7df2e56Smrg if (!(client->xkbClientFlags & _XkbClientInitialized)) 702f7df2e56Smrg return BadAccess; 70305b261ecSmrg 7044642e01fSmrg CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess); 705f7df2e56Smrg 70605b261ecSmrg xkb = dev->key->xkbInfo->desc->ctrls; 707f7df2e56Smrg rep = (xkbGetControlsReply) { 708f7df2e56Smrg .type = X_Reply, 709f7df2e56Smrg .deviceID = ((DeviceIntPtr) dev)->id, 710f7df2e56Smrg .sequenceNumber = client->sequence, 711f7df2e56Smrg .length = bytes_to_int32(SIZEOF(xkbGetControlsReply) - 712f7df2e56Smrg SIZEOF(xGenericReply)), 713f7df2e56Smrg .mkDfltBtn = xkb->mk_dflt_btn, 714f7df2e56Smrg .numGroups = xkb->num_groups, 715f7df2e56Smrg .groupsWrap = xkb->groups_wrap, 716f7df2e56Smrg .internalMods = xkb->internal.mask, 717f7df2e56Smrg .ignoreLockMods = xkb->ignore_lock.mask, 718f7df2e56Smrg .internalRealMods = xkb->internal.real_mods, 719f7df2e56Smrg .ignoreLockRealMods = xkb->ignore_lock.real_mods, 720f7df2e56Smrg .internalVMods = xkb->internal.vmods, 721f7df2e56Smrg .ignoreLockVMods = xkb->ignore_lock.vmods, 722f7df2e56Smrg .repeatDelay = xkb->repeat_delay, 723f7df2e56Smrg .repeatInterval = xkb->repeat_interval, 724f7df2e56Smrg .slowKeysDelay = xkb->slow_keys_delay, 725f7df2e56Smrg .debounceDelay = xkb->debounce_delay, 726f7df2e56Smrg .mkDelay = xkb->mk_delay, 727f7df2e56Smrg .mkInterval = xkb->mk_interval, 728f7df2e56Smrg .mkTimeToMax = xkb->mk_time_to_max, 729f7df2e56Smrg .mkMaxSpeed = xkb->mk_max_speed, 730f7df2e56Smrg .mkCurve = xkb->mk_curve, 731f7df2e56Smrg .axOptions = xkb->ax_options, 732f7df2e56Smrg .axTimeout = xkb->ax_timeout, 733f7df2e56Smrg .axtOptsMask = xkb->axt_opts_mask, 734f7df2e56Smrg .axtOptsValues = xkb->axt_opts_values, 735f7df2e56Smrg .axtCtrlsMask = xkb->axt_ctrls_mask, 736f7df2e56Smrg .axtCtrlsValues = xkb->axt_ctrls_values, 737f7df2e56Smrg .enabledCtrls = xkb->enabled_ctrls, 738f7df2e56Smrg }; 739f7df2e56Smrg memcpy(rep.perKeyRepeat, xkb->per_key_repeat, XkbPerKeyBitArraySize); 74005b261ecSmrg if (client->swapped) { 741f7df2e56Smrg swaps(&rep.sequenceNumber); 742f7df2e56Smrg swapl(&rep.length); 743f7df2e56Smrg swaps(&rep.internalVMods); 744f7df2e56Smrg swaps(&rep.ignoreLockVMods); 745f7df2e56Smrg swapl(&rep.enabledCtrls); 746f7df2e56Smrg swaps(&rep.repeatDelay); 747f7df2e56Smrg swaps(&rep.repeatInterval); 748f7df2e56Smrg swaps(&rep.slowKeysDelay); 749f7df2e56Smrg swaps(&rep.debounceDelay); 750f7df2e56Smrg swaps(&rep.mkDelay); 751f7df2e56Smrg swaps(&rep.mkInterval); 752f7df2e56Smrg swaps(&rep.mkTimeToMax); 753f7df2e56Smrg swaps(&rep.mkMaxSpeed); 754f7df2e56Smrg swaps(&rep.mkCurve); 755f7df2e56Smrg swaps(&rep.axTimeout); 756f7df2e56Smrg swapl(&rep.axtCtrlsMask); 757f7df2e56Smrg swapl(&rep.axtCtrlsValues); 758f7df2e56Smrg swaps(&rep.axtOptsMask); 759f7df2e56Smrg swaps(&rep.axtOptsValues); 760f7df2e56Smrg swaps(&rep.axOptions); 761f7df2e56Smrg } 762f7df2e56Smrg WriteToClient(client, SIZEOF(xkbGetControlsReply), &rep); 7636747b715Smrg return Success; 76405b261ecSmrg} 76505b261ecSmrg 76605b261ecSmrgint 76705b261ecSmrgProcXkbSetControls(ClientPtr client) 76805b261ecSmrg{ 769f7df2e56Smrg DeviceIntPtr dev, tmpd; 770f7df2e56Smrg XkbSrvInfoPtr xkbi; 771f7df2e56Smrg XkbControlsPtr ctrl; 772f7df2e56Smrg XkbControlsRec new, old; 773f7df2e56Smrg xkbControlsNotify cn; 774f7df2e56Smrg XkbEventCauseRec cause; 775f7df2e56Smrg XkbSrvLedInfoPtr sli; 77605b261ecSmrg 77705b261ecSmrg REQUEST(xkbSetControlsReq); 77805b261ecSmrg REQUEST_SIZE_MATCH(xkbSetControlsReq); 77905b261ecSmrg 78005b261ecSmrg if (!(client->xkbClientFlags & _XkbClientInitialized)) 781f7df2e56Smrg return BadAccess; 78205b261ecSmrg 7834642e01fSmrg CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess); 78405b261ecSmrg CHK_MASK_LEGAL(0x01, stuff->changeCtrls, XkbAllControlsMask); 78505b261ecSmrg 7866747b715Smrg for (tmpd = inputInfo.devices; tmpd; tmpd = tmpd->next) { 7876747b715Smrg if (!tmpd->key || !tmpd->key->xkbInfo) 7886747b715Smrg continue; 789f7df2e56Smrg if ((tmpd == dev) || 790f7df2e56Smrg (!IsMaster(tmpd) && GetMaster(tmpd, MASTER_KEYBOARD) == dev)) { 79105b261ecSmrg xkbi = tmpd->key->xkbInfo; 79205b261ecSmrg ctrl = xkbi->desc->ctrls; 79305b261ecSmrg new = *ctrl; 79405b261ecSmrg XkbSetCauseXkbReq(&cause, X_kbSetControls, client); 79505b261ecSmrg 79605b261ecSmrg if (stuff->changeCtrls & XkbInternalModsMask) { 79705b261ecSmrg CHK_MASK_MATCH(0x02, stuff->affectInternalMods, 79805b261ecSmrg stuff->internalMods); 79905b261ecSmrg CHK_MASK_MATCH(0x03, stuff->affectInternalVMods, 80005b261ecSmrg stuff->internalVMods); 80105b261ecSmrg 80205b261ecSmrg new.internal.real_mods &= ~(stuff->affectInternalMods); 80305b261ecSmrg new.internal.real_mods |= (stuff->affectInternalMods & 80405b261ecSmrg stuff->internalMods); 80505b261ecSmrg new.internal.vmods &= ~(stuff->affectInternalVMods); 80605b261ecSmrg new.internal.vmods |= (stuff->affectInternalVMods & 80705b261ecSmrg stuff->internalVMods); 80805b261ecSmrg new.internal.mask = new.internal.real_mods | 809f7df2e56Smrg XkbMaskForVMask(xkbi->desc, new.internal.vmods); 81005b261ecSmrg } 81105b261ecSmrg 81205b261ecSmrg if (stuff->changeCtrls & XkbIgnoreLockModsMask) { 81305b261ecSmrg CHK_MASK_MATCH(0x4, stuff->affectIgnoreLockMods, 81405b261ecSmrg stuff->ignoreLockMods); 81505b261ecSmrg CHK_MASK_MATCH(0x5, stuff->affectIgnoreLockVMods, 81605b261ecSmrg stuff->ignoreLockVMods); 81705b261ecSmrg 81805b261ecSmrg new.ignore_lock.real_mods &= ~(stuff->affectIgnoreLockMods); 81905b261ecSmrg new.ignore_lock.real_mods |= (stuff->affectIgnoreLockMods & 82005b261ecSmrg stuff->ignoreLockMods); 82105b261ecSmrg new.ignore_lock.vmods &= ~(stuff->affectIgnoreLockVMods); 82205b261ecSmrg new.ignore_lock.vmods |= (stuff->affectIgnoreLockVMods & 82305b261ecSmrg stuff->ignoreLockVMods); 82405b261ecSmrg new.ignore_lock.mask = new.ignore_lock.real_mods | 825f7df2e56Smrg XkbMaskForVMask(xkbi->desc, new.ignore_lock.vmods); 82605b261ecSmrg } 82705b261ecSmrg 82805b261ecSmrg CHK_MASK_MATCH(0x06, stuff->affectEnabledCtrls, 82905b261ecSmrg stuff->enabledCtrls); 83005b261ecSmrg if (stuff->affectEnabledCtrls) { 83105b261ecSmrg CHK_MASK_LEGAL(0x07, stuff->affectEnabledCtrls, 83205b261ecSmrg XkbAllBooleanCtrlsMask); 83305b261ecSmrg 83405b261ecSmrg new.enabled_ctrls &= ~(stuff->affectEnabledCtrls); 83505b261ecSmrg new.enabled_ctrls |= (stuff->affectEnabledCtrls & 83605b261ecSmrg stuff->enabledCtrls); 83705b261ecSmrg } 83805b261ecSmrg 83905b261ecSmrg if (stuff->changeCtrls & XkbRepeatKeysMask) { 84005b261ecSmrg if (stuff->repeatDelay < 1 || stuff->repeatInterval < 1) { 84105b261ecSmrg client->errorValue = _XkbErrCode3(0x08, stuff->repeatDelay, 84205b261ecSmrg stuff->repeatInterval); 84305b261ecSmrg return BadValue; 84405b261ecSmrg } 84505b261ecSmrg 84605b261ecSmrg new.repeat_delay = stuff->repeatDelay; 84705b261ecSmrg new.repeat_interval = stuff->repeatInterval; 84805b261ecSmrg } 84905b261ecSmrg 85005b261ecSmrg if (stuff->changeCtrls & XkbSlowKeysMask) { 85105b261ecSmrg if (stuff->slowKeysDelay < 1) { 85205b261ecSmrg client->errorValue = _XkbErrCode2(0x09, 85305b261ecSmrg stuff->slowKeysDelay); 85405b261ecSmrg return BadValue; 85505b261ecSmrg } 85605b261ecSmrg 85705b261ecSmrg new.slow_keys_delay = stuff->slowKeysDelay; 85805b261ecSmrg } 85905b261ecSmrg 86005b261ecSmrg if (stuff->changeCtrls & XkbBounceKeysMask) { 86105b261ecSmrg if (stuff->debounceDelay < 1) { 86205b261ecSmrg client->errorValue = _XkbErrCode2(0x0A, 86305b261ecSmrg stuff->debounceDelay); 86405b261ecSmrg return BadValue; 86505b261ecSmrg } 86605b261ecSmrg 86705b261ecSmrg new.debounce_delay = stuff->debounceDelay; 86805b261ecSmrg } 86905b261ecSmrg 87005b261ecSmrg if (stuff->changeCtrls & XkbMouseKeysMask) { 87105b261ecSmrg if (stuff->mkDfltBtn > XkbMaxMouseKeysBtn) { 87205b261ecSmrg client->errorValue = _XkbErrCode2(0x0B, stuff->mkDfltBtn); 87305b261ecSmrg return BadValue; 87405b261ecSmrg } 87505b261ecSmrg 87605b261ecSmrg new.mk_dflt_btn = stuff->mkDfltBtn; 87705b261ecSmrg } 87805b261ecSmrg 87905b261ecSmrg if (stuff->changeCtrls & XkbMouseKeysAccelMask) { 88005b261ecSmrg if (stuff->mkDelay < 1 || stuff->mkInterval < 1 || 88105b261ecSmrg stuff->mkTimeToMax < 1 || stuff->mkMaxSpeed < 1 || 88205b261ecSmrg stuff->mkCurve < -1000) { 883f7df2e56Smrg client->errorValue = _XkbErrCode2(0x0C, 0); 88405b261ecSmrg return BadValue; 88505b261ecSmrg } 88605b261ecSmrg 88705b261ecSmrg new.mk_delay = stuff->mkDelay; 88805b261ecSmrg new.mk_interval = stuff->mkInterval; 88905b261ecSmrg new.mk_time_to_max = stuff->mkTimeToMax; 89005b261ecSmrg new.mk_max_speed = stuff->mkMaxSpeed; 89105b261ecSmrg new.mk_curve = stuff->mkCurve; 89205b261ecSmrg AccessXComputeCurveFactor(xkbi, &new); 89305b261ecSmrg } 89405b261ecSmrg 89505b261ecSmrg if (stuff->changeCtrls & XkbGroupsWrapMask) { 89605b261ecSmrg unsigned act, num; 89705b261ecSmrg 89805b261ecSmrg act = XkbOutOfRangeGroupAction(stuff->groupsWrap); 89905b261ecSmrg switch (act) { 90005b261ecSmrg case XkbRedirectIntoRange: 90105b261ecSmrg num = XkbOutOfRangeGroupNumber(stuff->groupsWrap); 90205b261ecSmrg if (num >= new.num_groups) { 90305b261ecSmrg client->errorValue = _XkbErrCode3(0x0D, new.num_groups, 90405b261ecSmrg num); 90505b261ecSmrg return BadValue; 90605b261ecSmrg } 90705b261ecSmrg case XkbWrapIntoRange: 90805b261ecSmrg case XkbClampIntoRange: 90905b261ecSmrg break; 91005b261ecSmrg default: 91105b261ecSmrg client->errorValue = _XkbErrCode2(0x0E, act); 91205b261ecSmrg return BadValue; 91305b261ecSmrg } 91405b261ecSmrg 915f7df2e56Smrg new.groups_wrap = stuff->groupsWrap; 91605b261ecSmrg } 91705b261ecSmrg 91805b261ecSmrg CHK_MASK_LEGAL(0x0F, stuff->axOptions, XkbAX_AllOptionsMask); 91905b261ecSmrg if (stuff->changeCtrls & XkbAccessXKeysMask) { 92005b261ecSmrg new.ax_options = stuff->axOptions & XkbAX_AllOptionsMask; 92105b261ecSmrg } 92205b261ecSmrg else { 92305b261ecSmrg if (stuff->changeCtrls & XkbStickyKeysMask) { 92405b261ecSmrg new.ax_options &= ~(XkbAX_SKOptionsMask); 92505b261ecSmrg new.ax_options |= (stuff->axOptions & XkbAX_SKOptionsMask); 92605b261ecSmrg } 927f7df2e56Smrg 92805b261ecSmrg if (stuff->changeCtrls & XkbAccessXFeedbackMask) { 92905b261ecSmrg new.ax_options &= ~(XkbAX_FBOptionsMask); 93005b261ecSmrg new.ax_options |= (stuff->axOptions & XkbAX_FBOptionsMask); 93105b261ecSmrg } 93205b261ecSmrg } 93305b261ecSmrg 93405b261ecSmrg if (stuff->changeCtrls & XkbAccessXTimeoutMask) { 93505b261ecSmrg if (stuff->axTimeout < 1) { 93605b261ecSmrg client->errorValue = _XkbErrCode2(0x10, stuff->axTimeout); 93705b261ecSmrg return BadValue; 93805b261ecSmrg } 93905b261ecSmrg CHK_MASK_MATCH(0x11, stuff->axtCtrlsMask, 94005b261ecSmrg stuff->axtCtrlsValues); 94105b261ecSmrg CHK_MASK_LEGAL(0x12, stuff->axtCtrlsMask, 94205b261ecSmrg XkbAllBooleanCtrlsMask); 94305b261ecSmrg CHK_MASK_MATCH(0x13, stuff->axtOptsMask, stuff->axtOptsValues); 94405b261ecSmrg CHK_MASK_LEGAL(0x14, stuff->axtOptsMask, XkbAX_AllOptionsMask); 94505b261ecSmrg new.ax_timeout = stuff->axTimeout; 94605b261ecSmrg new.axt_ctrls_mask = stuff->axtCtrlsMask; 94705b261ecSmrg new.axt_ctrls_values = (stuff->axtCtrlsValues & 94805b261ecSmrg stuff->axtCtrlsMask); 94905b261ecSmrg new.axt_opts_mask = stuff->axtOptsMask; 95005b261ecSmrg new.axt_opts_values = (stuff->axtOptsValues & 95105b261ecSmrg stuff->axtOptsMask); 95205b261ecSmrg } 95305b261ecSmrg 9549ace9065Smrg if (stuff->changeCtrls & XkbPerKeyRepeatMask) { 95505b261ecSmrg memcpy(new.per_key_repeat, stuff->perKeyRepeat, 95605b261ecSmrg XkbPerKeyBitArraySize); 9579ace9065Smrg if (xkbi->repeatKey && 9589ace9065Smrg !BitIsOn(new.per_key_repeat, xkbi->repeatKey)) { 9599ace9065Smrg AccessXCancelRepeatKey(xkbi, xkbi->repeatKey); 9609ace9065Smrg } 9619ace9065Smrg } 96205b261ecSmrg 963f7df2e56Smrg old = *ctrl; 964f7df2e56Smrg *ctrl = new; 96505b261ecSmrg XkbDDXChangeControls(tmpd, &old, ctrl); 96605b261ecSmrg 9676747b715Smrg if (XkbComputeControlsNotify(tmpd, &old, ctrl, &cn, FALSE)) { 96805b261ecSmrg cn.keycode = 0; 96905b261ecSmrg cn.eventType = 0; 97005b261ecSmrg cn.requestMajor = XkbReqCode; 97105b261ecSmrg cn.requestMinor = X_kbSetControls; 97205b261ecSmrg XkbSendControlsNotify(tmpd, &cn); 97305b261ecSmrg } 97405b261ecSmrg 97505b261ecSmrg sli = XkbFindSrvLedInfo(tmpd, XkbDfltXIClass, XkbDfltXIId, 0); 97605b261ecSmrg if (sli) 9776747b715Smrg XkbUpdateIndicators(tmpd, sli->usesControls, TRUE, NULL, 97805b261ecSmrg &cause); 97905b261ecSmrg 98005b261ecSmrg /* If sticky keys were disabled, clear all locks and latches */ 98105b261ecSmrg if ((old.enabled_ctrls & XkbStickyKeysMask) && 98205b261ecSmrg !(ctrl->enabled_ctrls & XkbStickyKeysMask)) 9836747b715Smrg XkbClearAllLatchesAndLocks(tmpd, xkbi, TRUE, &cause); 98405b261ecSmrg } 98505b261ecSmrg } 98605b261ecSmrg 9876747b715Smrg return Success; 98805b261ecSmrg} 98905b261ecSmrg 99005b261ecSmrg/***====================================================================***/ 99105b261ecSmrg 99205b261ecSmrgstatic int 993f7df2e56SmrgXkbSizeKeyTypes(XkbDescPtr xkb, xkbGetMapReply * rep) 99405b261ecSmrg{ 995f7df2e56Smrg XkbKeyTypeRec *type; 996f7df2e56Smrg unsigned i, len; 997f7df2e56Smrg 998f7df2e56Smrg len = 0; 999f7df2e56Smrg if (((rep->present & XkbKeyTypesMask) == 0) || (rep->nTypes < 1) || 1000f7df2e56Smrg (!xkb) || (!xkb->map) || (!xkb->map->types)) { 1001f7df2e56Smrg rep->present &= ~XkbKeyTypesMask; 1002f7df2e56Smrg rep->firstType = rep->nTypes = 0; 1003f7df2e56Smrg return 0; 1004f7df2e56Smrg } 1005f7df2e56Smrg type = &xkb->map->types[rep->firstType]; 1006f7df2e56Smrg for (i = 0; i < rep->nTypes; i++, type++) { 1007f7df2e56Smrg len += SIZEOF(xkbKeyTypeWireDesc); 1008f7df2e56Smrg if (type->map_count > 0) { 1009f7df2e56Smrg len += (type->map_count * SIZEOF(xkbKTMapEntryWireDesc)); 1010f7df2e56Smrg if (type->preserve) 1011f7df2e56Smrg len += (type->map_count * SIZEOF(xkbModsWireDesc)); 1012f7df2e56Smrg } 101305b261ecSmrg } 101405b261ecSmrg return len; 101505b261ecSmrg} 101605b261ecSmrg 101705b261ecSmrgstatic char * 1018f7df2e56SmrgXkbWriteKeyTypes(XkbDescPtr xkb, 1019f7df2e56Smrg xkbGetMapReply * rep, char *buf, ClientPtr client) 102005b261ecSmrg{ 1021f7df2e56Smrg XkbKeyTypePtr type; 1022f7df2e56Smrg unsigned i; 102305b261ecSmrg xkbKeyTypeWireDesc *wire; 102405b261ecSmrg 1025f7df2e56Smrg type = &xkb->map->types[rep->firstType]; 1026f7df2e56Smrg for (i = 0; i < rep->nTypes; i++, type++) { 1027f7df2e56Smrg register unsigned n; 1028f7df2e56Smrg 1029f7df2e56Smrg wire = (xkbKeyTypeWireDesc *) buf; 1030f7df2e56Smrg wire->mask = type->mods.mask; 1031f7df2e56Smrg wire->realMods = type->mods.real_mods; 1032f7df2e56Smrg wire->virtualMods = type->mods.vmods; 1033f7df2e56Smrg wire->numLevels = type->num_levels; 1034f7df2e56Smrg wire->nMapEntries = type->map_count; 1035f7df2e56Smrg wire->preserve = (type->preserve != NULL); 1036f7df2e56Smrg if (client->swapped) { 1037f7df2e56Smrg swaps(&wire->virtualMods); 1038f7df2e56Smrg } 1039f7df2e56Smrg 1040f7df2e56Smrg buf = (char *) &wire[1]; 1041f7df2e56Smrg if (wire->nMapEntries > 0) { 1042f7df2e56Smrg xkbKTMapEntryWireDesc *ewire; 1043f7df2e56Smrg XkbKTMapEntryPtr entry; 1044f7df2e56Smrg 1045f7df2e56Smrg ewire = (xkbKTMapEntryWireDesc *) buf; 1046f7df2e56Smrg entry = type->map; 1047f7df2e56Smrg for (n = 0; n < type->map_count; n++, ewire++, entry++) { 1048f7df2e56Smrg ewire->active = entry->active; 1049f7df2e56Smrg ewire->mask = entry->mods.mask; 1050f7df2e56Smrg ewire->level = entry->level; 1051f7df2e56Smrg ewire->realMods = entry->mods.real_mods; 1052f7df2e56Smrg ewire->virtualMods = entry->mods.vmods; 1053f7df2e56Smrg if (client->swapped) { 1054f7df2e56Smrg swaps(&ewire->virtualMods); 1055f7df2e56Smrg } 1056f7df2e56Smrg } 1057f7df2e56Smrg buf = (char *) ewire; 1058f7df2e56Smrg if (type->preserve != NULL) { 1059f7df2e56Smrg xkbModsWireDesc *pwire; 1060f7df2e56Smrg XkbModsPtr preserve; 1061f7df2e56Smrg 1062f7df2e56Smrg pwire = (xkbModsWireDesc *) buf; 1063f7df2e56Smrg preserve = type->preserve; 1064f7df2e56Smrg for (n = 0; n < type->map_count; n++, pwire++, preserve++) { 1065f7df2e56Smrg pwire->mask = preserve->mask; 1066f7df2e56Smrg pwire->realMods = preserve->real_mods; 1067f7df2e56Smrg pwire->virtualMods = preserve->vmods; 1068f7df2e56Smrg if (client->swapped) { 1069f7df2e56Smrg swaps(&pwire->virtualMods); 1070f7df2e56Smrg } 1071f7df2e56Smrg } 1072f7df2e56Smrg buf = (char *) pwire; 1073f7df2e56Smrg } 1074f7df2e56Smrg } 107505b261ecSmrg } 107605b261ecSmrg return buf; 107705b261ecSmrg} 107805b261ecSmrg 107905b261ecSmrgstatic int 1080f7df2e56SmrgXkbSizeKeySyms(XkbDescPtr xkb, xkbGetMapReply * rep) 108105b261ecSmrg{ 1082f7df2e56Smrg XkbSymMapPtr symMap; 1083f7df2e56Smrg unsigned i, len; 1084f7df2e56Smrg unsigned nSyms, nSymsThisKey; 1085f7df2e56Smrg 1086f7df2e56Smrg if (((rep->present & XkbKeySymsMask) == 0) || (rep->nKeySyms < 1) || 1087f7df2e56Smrg (!xkb) || (!xkb->map) || (!xkb->map->key_sym_map)) { 1088f7df2e56Smrg rep->present &= ~XkbKeySymsMask; 1089f7df2e56Smrg rep->firstKeySym = rep->nKeySyms = 0; 1090f7df2e56Smrg rep->totalSyms = 0; 1091f7df2e56Smrg return 0; 1092f7df2e56Smrg } 1093f7df2e56Smrg len = rep->nKeySyms * SIZEOF(xkbSymMapWireDesc); 109405b261ecSmrg symMap = &xkb->map->key_sym_map[rep->firstKeySym]; 1095f7df2e56Smrg for (i = nSyms = 0; i < rep->nKeySyms; i++, symMap++) { 1096d566a54bSmrg nSymsThisKey = XkbNumGroups(symMap->group_info) * symMap->width; 1097d566a54bSmrg if (nSymsThisKey == 0) 1098d566a54bSmrg continue; 1099d566a54bSmrg nSyms += nSymsThisKey; 1100f7df2e56Smrg } 1101f7df2e56Smrg len += nSyms * 4; 1102f7df2e56Smrg rep->totalSyms = nSyms; 110305b261ecSmrg return len; 110405b261ecSmrg} 110505b261ecSmrg 110605b261ecSmrgstatic int 1107f7df2e56SmrgXkbSizeVirtualMods(XkbDescPtr xkb, xkbGetMapReply * rep) 110805b261ecSmrg{ 1109f7df2e56Smrg register unsigned i, nMods, bit; 111005b261ecSmrg 1111f7df2e56Smrg if (((rep->present & XkbVirtualModsMask) == 0) || (rep->virtualMods == 0) || 1112f7df2e56Smrg (!xkb) || (!xkb->server)) { 1113f7df2e56Smrg rep->present &= ~XkbVirtualModsMask; 1114f7df2e56Smrg rep->virtualMods = 0; 1115f7df2e56Smrg return 0; 111605b261ecSmrg } 1117f7df2e56Smrg for (i = nMods = 0, bit = 1; i < XkbNumVirtualMods; i++, bit <<= 1) { 1118f7df2e56Smrg if (rep->virtualMods & bit) 1119f7df2e56Smrg nMods++; 112005b261ecSmrg } 112105b261ecSmrg return XkbPaddedSize(nMods); 112205b261ecSmrg} 112305b261ecSmrg 112405b261ecSmrgstatic char * 1125f7df2e56SmrgXkbWriteKeySyms(XkbDescPtr xkb, xkbGetMapReply * rep, char *buf, 1126f7df2e56Smrg ClientPtr client) 112705b261ecSmrg{ 1128f7df2e56Smrg register KeySym *pSym; 1129f7df2e56Smrg XkbSymMapPtr symMap; 1130f7df2e56Smrg xkbSymMapWireDesc *outMap; 1131f7df2e56Smrg register unsigned i; 113205b261ecSmrg 113305b261ecSmrg symMap = &xkb->map->key_sym_map[rep->firstKeySym]; 1134f7df2e56Smrg for (i = 0; i < rep->nKeySyms; i++, symMap++) { 1135f7df2e56Smrg outMap = (xkbSymMapWireDesc *) buf; 1136f7df2e56Smrg outMap->ktIndex[0] = symMap->kt_index[0]; 1137f7df2e56Smrg outMap->ktIndex[1] = symMap->kt_index[1]; 1138f7df2e56Smrg outMap->ktIndex[2] = symMap->kt_index[2]; 1139f7df2e56Smrg outMap->ktIndex[3] = symMap->kt_index[3]; 1140f7df2e56Smrg outMap->groupInfo = symMap->group_info; 1141f7df2e56Smrg outMap->width = symMap->width; 1142f7df2e56Smrg outMap->nSyms = symMap->width * XkbNumGroups(symMap->group_info); 1143f7df2e56Smrg buf = (char *) &outMap[1]; 1144f7df2e56Smrg if (outMap->nSyms == 0) 1145f7df2e56Smrg continue; 1146f7df2e56Smrg 1147f7df2e56Smrg pSym = &xkb->map->syms[symMap->offset]; 1148f7df2e56Smrg memcpy((char *) buf, (char *) pSym, outMap->nSyms * 4); 1149f7df2e56Smrg if (client->swapped) { 1150f7df2e56Smrg register int nSyms = outMap->nSyms; 1151f7df2e56Smrg 1152f7df2e56Smrg swaps(&outMap->nSyms); 1153f7df2e56Smrg while (nSyms-- > 0) { 1154f7df2e56Smrg swapl((int *) buf); 1155f7df2e56Smrg buf += 4; 1156f7df2e56Smrg } 1157f7df2e56Smrg } 1158f7df2e56Smrg else 1159f7df2e56Smrg buf += outMap->nSyms * 4; 116005b261ecSmrg } 116105b261ecSmrg return buf; 116205b261ecSmrg} 116305b261ecSmrg 116405b261ecSmrgstatic int 1165f7df2e56SmrgXkbSizeKeyActions(XkbDescPtr xkb, xkbGetMapReply * rep) 116605b261ecSmrg{ 1167f7df2e56Smrg unsigned i, len, nActs; 1168f7df2e56Smrg register KeyCode firstKey; 1169f7df2e56Smrg 1170f7df2e56Smrg if (((rep->present & XkbKeyActionsMask) == 0) || (rep->nKeyActs < 1) || 1171f7df2e56Smrg (!xkb) || (!xkb->server) || (!xkb->server->key_acts)) { 1172f7df2e56Smrg rep->present &= ~XkbKeyActionsMask; 1173f7df2e56Smrg rep->firstKeyAct = rep->nKeyActs = 0; 1174f7df2e56Smrg rep->totalActs = 0; 1175f7df2e56Smrg return 0; 1176f7df2e56Smrg } 1177f7df2e56Smrg firstKey = rep->firstKeyAct; 1178f7df2e56Smrg for (nActs = i = 0; i < rep->nKeyActs; i++) { 1179f7df2e56Smrg if (xkb->server->key_acts[i + firstKey] != 0) 1180f7df2e56Smrg nActs += XkbKeyNumActions(xkb, i + firstKey); 1181f7df2e56Smrg } 1182f7df2e56Smrg len = XkbPaddedSize(rep->nKeyActs) + (nActs * SIZEOF(xkbActionWireDesc)); 1183f7df2e56Smrg rep->totalActs = nActs; 118405b261ecSmrg return len; 118505b261ecSmrg} 118605b261ecSmrg 118705b261ecSmrgstatic char * 1188f7df2e56SmrgXkbWriteKeyActions(XkbDescPtr xkb, xkbGetMapReply * rep, char *buf, 1189f7df2e56Smrg ClientPtr client) 119005b261ecSmrg{ 1191f7df2e56Smrg unsigned i; 1192f7df2e56Smrg CARD8 *numDesc; 1193f7df2e56Smrg XkbAnyAction *actDesc; 1194f7df2e56Smrg 1195f7df2e56Smrg numDesc = (CARD8 *) buf; 1196f7df2e56Smrg for (i = 0; i < rep->nKeyActs; i++) { 1197f7df2e56Smrg if (xkb->server->key_acts[i + rep->firstKeyAct] == 0) 1198f7df2e56Smrg numDesc[i] = 0; 1199f7df2e56Smrg else 1200f7df2e56Smrg numDesc[i] = XkbKeyNumActions(xkb, (i + rep->firstKeyAct)); 1201f7df2e56Smrg } 1202f7df2e56Smrg buf += XkbPaddedSize(rep->nKeyActs); 1203f7df2e56Smrg 1204f7df2e56Smrg actDesc = (XkbAnyAction *) buf; 1205f7df2e56Smrg for (i = 0; i < rep->nKeyActs; i++) { 1206f7df2e56Smrg if (xkb->server->key_acts[i + rep->firstKeyAct] != 0) { 1207f7df2e56Smrg unsigned int num; 1208f7df2e56Smrg 1209f7df2e56Smrg num = XkbKeyNumActions(xkb, (i + rep->firstKeyAct)); 1210f7df2e56Smrg memcpy((char *) actDesc, 1211f7df2e56Smrg (char *) XkbKeyActionsPtr(xkb, (i + rep->firstKeyAct)), 1212f7df2e56Smrg num * SIZEOF(xkbActionWireDesc)); 1213f7df2e56Smrg actDesc += num; 1214f7df2e56Smrg } 1215f7df2e56Smrg } 1216f7df2e56Smrg buf = (char *) actDesc; 121705b261ecSmrg return buf; 121805b261ecSmrg} 121905b261ecSmrg 122005b261ecSmrgstatic int 1221f7df2e56SmrgXkbSizeKeyBehaviors(XkbDescPtr xkb, xkbGetMapReply * rep) 122205b261ecSmrg{ 1223f7df2e56Smrg unsigned i, len, nBhvr; 1224f7df2e56Smrg XkbBehavior *bhv; 1225f7df2e56Smrg 1226f7df2e56Smrg if (((rep->present & XkbKeyBehaviorsMask) == 0) || (rep->nKeyBehaviors < 1) 1227f7df2e56Smrg || (!xkb) || (!xkb->server) || (!xkb->server->behaviors)) { 1228f7df2e56Smrg rep->present &= ~XkbKeyBehaviorsMask; 1229f7df2e56Smrg rep->firstKeyBehavior = rep->nKeyBehaviors = 0; 1230f7df2e56Smrg rep->totalKeyBehaviors = 0; 1231f7df2e56Smrg return 0; 1232f7df2e56Smrg } 1233f7df2e56Smrg bhv = &xkb->server->behaviors[rep->firstKeyBehavior]; 1234f7df2e56Smrg for (nBhvr = i = 0; i < rep->nKeyBehaviors; i++, bhv++) { 1235f7df2e56Smrg if (bhv->type != XkbKB_Default) 1236f7df2e56Smrg nBhvr++; 1237f7df2e56Smrg } 1238f7df2e56Smrg len = nBhvr * SIZEOF(xkbBehaviorWireDesc); 1239f7df2e56Smrg rep->totalKeyBehaviors = nBhvr; 124005b261ecSmrg return len; 124105b261ecSmrg} 124205b261ecSmrg 124305b261ecSmrgstatic char * 1244f7df2e56SmrgXkbWriteKeyBehaviors(XkbDescPtr xkb, xkbGetMapReply * rep, char *buf, 1245f7df2e56Smrg ClientPtr client) 124605b261ecSmrg{ 1247f7df2e56Smrg unsigned i; 1248f7df2e56Smrg xkbBehaviorWireDesc *wire; 1249f7df2e56Smrg XkbBehavior *pBhvr; 1250f7df2e56Smrg 1251f7df2e56Smrg wire = (xkbBehaviorWireDesc *) buf; 1252f7df2e56Smrg pBhvr = &xkb->server->behaviors[rep->firstKeyBehavior]; 1253f7df2e56Smrg for (i = 0; i < rep->nKeyBehaviors; i++, pBhvr++) { 1254f7df2e56Smrg if (pBhvr->type != XkbKB_Default) { 1255f7df2e56Smrg wire->key = i + rep->firstKeyBehavior; 1256f7df2e56Smrg wire->type = pBhvr->type; 1257f7df2e56Smrg wire->data = pBhvr->data; 1258f7df2e56Smrg wire++; 1259f7df2e56Smrg } 1260f7df2e56Smrg } 1261f7df2e56Smrg buf = (char *) wire; 126205b261ecSmrg return buf; 126305b261ecSmrg} 126405b261ecSmrg 126505b261ecSmrgstatic int 1266f7df2e56SmrgXkbSizeExplicit(XkbDescPtr xkb, xkbGetMapReply * rep) 126705b261ecSmrg{ 1268f7df2e56Smrg unsigned i, len, nRtrn; 1269f7df2e56Smrg 1270f7df2e56Smrg if (((rep->present & XkbExplicitComponentsMask) == 0) || 1271f7df2e56Smrg (rep->nKeyExplicit < 1) || (!xkb) || (!xkb->server) || 1272f7df2e56Smrg (!xkb->server->explicit)) { 1273f7df2e56Smrg rep->present &= ~XkbExplicitComponentsMask; 1274f7df2e56Smrg rep->firstKeyExplicit = rep->nKeyExplicit = 0; 1275f7df2e56Smrg rep->totalKeyExplicit = 0; 1276f7df2e56Smrg return 0; 1277f7df2e56Smrg } 1278f7df2e56Smrg for (nRtrn = i = 0; i < rep->nKeyExplicit; i++) { 1279f7df2e56Smrg if (xkb->server->explicit[i + rep->firstKeyExplicit] != 0) 1280f7df2e56Smrg nRtrn++; 1281f7df2e56Smrg } 1282f7df2e56Smrg rep->totalKeyExplicit = nRtrn; 1283f7df2e56Smrg len = XkbPaddedSize(nRtrn * 2); /* two bytes per non-zero explicit component */ 128405b261ecSmrg return len; 128505b261ecSmrg} 128605b261ecSmrg 128705b261ecSmrgstatic char * 1288f7df2e56SmrgXkbWriteExplicit(XkbDescPtr xkb, xkbGetMapReply * rep, char *buf, 1289f7df2e56Smrg ClientPtr client) 129005b261ecSmrg{ 1291f7df2e56Smrg unsigned i; 1292f7df2e56Smrg char *start; 1293f7df2e56Smrg unsigned char *pExp; 1294f7df2e56Smrg 1295f7df2e56Smrg start = buf; 1296f7df2e56Smrg pExp = &xkb->server->explicit[rep->firstKeyExplicit]; 1297f7df2e56Smrg for (i = 0; i < rep->nKeyExplicit; i++, pExp++) { 1298f7df2e56Smrg if (*pExp != 0) { 1299f7df2e56Smrg *buf++ = i + rep->firstKeyExplicit; 1300f7df2e56Smrg *buf++ = *pExp; 1301f7df2e56Smrg } 1302f7df2e56Smrg } 1303f7df2e56Smrg i = XkbPaddedSize(buf - start) - (buf - start); /* pad to word boundary */ 1304f7df2e56Smrg return buf + i; 130505b261ecSmrg} 130605b261ecSmrg 130705b261ecSmrgstatic int 1308f7df2e56SmrgXkbSizeModifierMap(XkbDescPtr xkb, xkbGetMapReply * rep) 130905b261ecSmrg{ 1310f7df2e56Smrg unsigned i, len, nRtrn; 131105b261ecSmrg 1312f7df2e56Smrg if (((rep->present & XkbModifierMapMask) == 0) || (rep->nModMapKeys < 1) || 1313f7df2e56Smrg (!xkb) || (!xkb->map) || (!xkb->map->modmap)) { 1314f7df2e56Smrg rep->present &= ~XkbModifierMapMask; 1315f7df2e56Smrg rep->firstModMapKey = rep->nModMapKeys = 0; 1316f7df2e56Smrg rep->totalModMapKeys = 0; 1317f7df2e56Smrg return 0; 131805b261ecSmrg } 1319f7df2e56Smrg for (nRtrn = i = 0; i < rep->nModMapKeys; i++) { 1320f7df2e56Smrg if (xkb->map->modmap[i + rep->firstModMapKey] != 0) 1321f7df2e56Smrg nRtrn++; 132205b261ecSmrg } 1323f7df2e56Smrg rep->totalModMapKeys = nRtrn; 1324f7df2e56Smrg len = XkbPaddedSize(nRtrn * 2); /* two bytes per non-zero modmap component */ 132505b261ecSmrg return len; 132605b261ecSmrg} 132705b261ecSmrg 132805b261ecSmrgstatic char * 1329f7df2e56SmrgXkbWriteModifierMap(XkbDescPtr xkb, xkbGetMapReply * rep, char *buf, 1330f7df2e56Smrg ClientPtr client) 133105b261ecSmrg{ 1332f7df2e56Smrg unsigned i; 1333f7df2e56Smrg char *start; 1334f7df2e56Smrg unsigned char *pMap; 1335f7df2e56Smrg 1336f7df2e56Smrg start = buf; 1337f7df2e56Smrg pMap = &xkb->map->modmap[rep->firstModMapKey]; 1338f7df2e56Smrg for (i = 0; i < rep->nModMapKeys; i++, pMap++) { 1339f7df2e56Smrg if (*pMap != 0) { 1340f7df2e56Smrg *buf++ = i + rep->firstModMapKey; 1341f7df2e56Smrg *buf++ = *pMap; 1342f7df2e56Smrg } 1343f7df2e56Smrg } 1344f7df2e56Smrg i = XkbPaddedSize(buf - start) - (buf - start); /* pad to word boundary */ 1345f7df2e56Smrg return buf + i; 134605b261ecSmrg} 134705b261ecSmrg 134805b261ecSmrgstatic int 1349f7df2e56SmrgXkbSizeVirtualModMap(XkbDescPtr xkb, xkbGetMapReply * rep) 135005b261ecSmrg{ 1351f7df2e56Smrg unsigned i, len, nRtrn; 135205b261ecSmrg 1353f7df2e56Smrg if (((rep->present & XkbVirtualModMapMask) == 0) || (rep->nVModMapKeys < 1) 1354f7df2e56Smrg || (!xkb) || (!xkb->server) || (!xkb->server->vmodmap)) { 1355f7df2e56Smrg rep->present &= ~XkbVirtualModMapMask; 1356f7df2e56Smrg rep->firstVModMapKey = rep->nVModMapKeys = 0; 1357f7df2e56Smrg rep->totalVModMapKeys = 0; 1358f7df2e56Smrg return 0; 135905b261ecSmrg } 1360f7df2e56Smrg for (nRtrn = i = 0; i < rep->nVModMapKeys; i++) { 1361f7df2e56Smrg if (xkb->server->vmodmap[i + rep->firstVModMapKey] != 0) 1362f7df2e56Smrg nRtrn++; 136305b261ecSmrg } 1364f7df2e56Smrg rep->totalVModMapKeys = nRtrn; 1365f7df2e56Smrg len = nRtrn * SIZEOF(xkbVModMapWireDesc); 136605b261ecSmrg return len; 136705b261ecSmrg} 136805b261ecSmrg 136905b261ecSmrgstatic char * 1370f7df2e56SmrgXkbWriteVirtualModMap(XkbDescPtr xkb, xkbGetMapReply * rep, char *buf, 1371f7df2e56Smrg ClientPtr client) 137205b261ecSmrg{ 1373f7df2e56Smrg unsigned i; 1374f7df2e56Smrg xkbVModMapWireDesc *wire; 1375f7df2e56Smrg unsigned short *pMap; 1376f7df2e56Smrg 1377f7df2e56Smrg wire = (xkbVModMapWireDesc *) buf; 1378f7df2e56Smrg pMap = &xkb->server->vmodmap[rep->firstVModMapKey]; 1379f7df2e56Smrg for (i = 0; i < rep->nVModMapKeys; i++, pMap++) { 1380f7df2e56Smrg if (*pMap != 0) { 1381f7df2e56Smrg wire->key = i + rep->firstVModMapKey; 1382f7df2e56Smrg wire->vmods = *pMap; 1383f7df2e56Smrg wire++; 1384f7df2e56Smrg } 1385f7df2e56Smrg } 1386f7df2e56Smrg return (char *) wire; 138705b261ecSmrg} 138805b261ecSmrg 138905b261ecSmrgstatic Status 1390f7df2e56SmrgXkbComputeGetMapReplySize(XkbDescPtr xkb, xkbGetMapReply * rep) 139105b261ecSmrg{ 1392f7df2e56Smrg int len; 1393f7df2e56Smrg 1394f7df2e56Smrg rep->minKeyCode = xkb->min_key_code; 1395f7df2e56Smrg rep->maxKeyCode = xkb->max_key_code; 1396f7df2e56Smrg len = XkbSizeKeyTypes(xkb, rep); 1397f7df2e56Smrg len += XkbSizeKeySyms(xkb, rep); 1398f7df2e56Smrg len += XkbSizeKeyActions(xkb, rep); 1399f7df2e56Smrg len += XkbSizeKeyBehaviors(xkb, rep); 1400f7df2e56Smrg len += XkbSizeVirtualMods(xkb, rep); 1401f7df2e56Smrg len += XkbSizeExplicit(xkb, rep); 1402f7df2e56Smrg len += XkbSizeModifierMap(xkb, rep); 1403f7df2e56Smrg len += XkbSizeVirtualModMap(xkb, rep); 1404f7df2e56Smrg rep->length += (len / 4); 140505b261ecSmrg return Success; 140605b261ecSmrg} 140705b261ecSmrg 140805b261ecSmrgstatic int 1409f7df2e56SmrgXkbSendMap(ClientPtr client, XkbDescPtr xkb, xkbGetMapReply * rep) 141005b261ecSmrg{ 1411f7df2e56Smrg unsigned i, len; 1412f7df2e56Smrg char *desc, *start; 141305b261ecSmrg 1414f7df2e56Smrg len = (rep->length * 4) - (SIZEOF(xkbGetMapReply) - SIZEOF(xGenericReply)); 1415f7df2e56Smrg start = desc = calloc(1, len); 141605b261ecSmrg if (!start) 1417f7df2e56Smrg return BadAlloc; 1418f7df2e56Smrg if (rep->nTypes > 0) 1419f7df2e56Smrg desc = XkbWriteKeyTypes(xkb, rep, desc, client); 1420f7df2e56Smrg if (rep->nKeySyms > 0) 1421f7df2e56Smrg desc = XkbWriteKeySyms(xkb, rep, desc, client); 1422f7df2e56Smrg if (rep->nKeyActs > 0) 1423f7df2e56Smrg desc = XkbWriteKeyActions(xkb, rep, desc, client); 1424f7df2e56Smrg if (rep->totalKeyBehaviors > 0) 1425f7df2e56Smrg desc = XkbWriteKeyBehaviors(xkb, rep, desc, client); 1426f7df2e56Smrg if (rep->virtualMods) { 1427f7df2e56Smrg register int sz, bit; 1428f7df2e56Smrg 1429f7df2e56Smrg for (i = sz = 0, bit = 1; i < XkbNumVirtualMods; i++, bit <<= 1) { 1430f7df2e56Smrg if (rep->virtualMods & bit) { 1431f7df2e56Smrg desc[sz++] = xkb->server->vmods[i]; 1432f7df2e56Smrg } 1433f7df2e56Smrg } 1434f7df2e56Smrg desc += XkbPaddedSize(sz); 1435f7df2e56Smrg } 1436f7df2e56Smrg if (rep->totalKeyExplicit > 0) 1437f7df2e56Smrg desc = XkbWriteExplicit(xkb, rep, desc, client); 1438f7df2e56Smrg if (rep->totalModMapKeys > 0) 1439f7df2e56Smrg desc = XkbWriteModifierMap(xkb, rep, desc, client); 1440f7df2e56Smrg if (rep->totalVModMapKeys > 0) 1441f7df2e56Smrg desc = XkbWriteVirtualModMap(xkb, rep, desc, client); 1442f7df2e56Smrg if ((desc - start) != (len)) { 1443f7df2e56Smrg ErrorF 1444f7df2e56Smrg ("[xkb] BOGUS LENGTH in write keyboard desc, expected %d, got %ld\n", 1445f7df2e56Smrg len, (unsigned long) (desc - start)); 144605b261ecSmrg } 144705b261ecSmrg if (client->swapped) { 1448f7df2e56Smrg swaps(&rep->sequenceNumber); 1449f7df2e56Smrg swapl(&rep->length); 1450f7df2e56Smrg swaps(&rep->present); 1451f7df2e56Smrg swaps(&rep->totalSyms); 1452f7df2e56Smrg swaps(&rep->totalActs); 1453f7df2e56Smrg } 1454f7df2e56Smrg WriteToClient(client, (i = SIZEOF(xkbGetMapReply)), rep); 145505b261ecSmrg WriteToClient(client, len, start); 1456f7df2e56Smrg free((char *) start); 14576747b715Smrg return Success; 145805b261ecSmrg} 145905b261ecSmrg 146005b261ecSmrgint 146105b261ecSmrgProcXkbGetMap(ClientPtr client) 146205b261ecSmrg{ 1463f7df2e56Smrg DeviceIntPtr dev; 1464f7df2e56Smrg xkbGetMapReply rep; 1465f7df2e56Smrg XkbDescRec *xkb; 1466f7df2e56Smrg int n, status; 146705b261ecSmrg 146805b261ecSmrg REQUEST(xkbGetMapReq); 146905b261ecSmrg REQUEST_SIZE_MATCH(xkbGetMapReq); 1470f7df2e56Smrg 1471f7df2e56Smrg if (!(client->xkbClientFlags & _XkbClientInitialized)) 1472f7df2e56Smrg return BadAccess; 147305b261ecSmrg 14744642e01fSmrg CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess); 1475f7df2e56Smrg CHK_MASK_OVERLAP(0x01, stuff->full, stuff->partial); 1476f7df2e56Smrg CHK_MASK_LEGAL(0x02, stuff->full, XkbAllMapComponentsMask); 1477f7df2e56Smrg CHK_MASK_LEGAL(0x03, stuff->partial, XkbAllMapComponentsMask); 1478f7df2e56Smrg 1479f7df2e56Smrg xkb = dev->key->xkbInfo->desc; 1480f7df2e56Smrg rep = (xkbGetMapReply) { 1481f7df2e56Smrg .type = X_Reply, 1482f7df2e56Smrg .deviceID = dev->id, 1483f7df2e56Smrg .sequenceNumber = client->sequence, 1484f7df2e56Smrg .length = (SIZEOF(xkbGetMapReply) - SIZEOF(xGenericReply)) >> 2, 1485f7df2e56Smrg .present = stuff->partial | stuff->full, 1486f7df2e56Smrg .minKeyCode = xkb->min_key_code, 1487f7df2e56Smrg .maxKeyCode = xkb->max_key_code 1488f7df2e56Smrg }; 1489f7df2e56Smrg 1490f7df2e56Smrg if (stuff->full & XkbKeyTypesMask) { 1491f7df2e56Smrg rep.firstType = 0; 1492f7df2e56Smrg rep.nTypes = xkb->map->num_types; 1493f7df2e56Smrg } 1494f7df2e56Smrg else if (stuff->partial & XkbKeyTypesMask) { 1495f7df2e56Smrg if (((unsigned) stuff->firstType + stuff->nTypes) > xkb->map->num_types) { 1496f7df2e56Smrg client->errorValue = _XkbErrCode4(0x04, xkb->map->num_types, 1497f7df2e56Smrg stuff->firstType, stuff->nTypes); 1498f7df2e56Smrg return BadValue; 1499f7df2e56Smrg } 1500f7df2e56Smrg rep.firstType = stuff->firstType; 1501f7df2e56Smrg rep.nTypes = stuff->nTypes; 1502f7df2e56Smrg } 1503f7df2e56Smrg else 1504f7df2e56Smrg rep.nTypes = 0; 150505b261ecSmrg rep.totalTypes = xkb->map->num_types; 150605b261ecSmrg 1507f7df2e56Smrg n = XkbNumKeys(xkb); 1508f7df2e56Smrg if (stuff->full & XkbKeySymsMask) { 1509f7df2e56Smrg rep.firstKeySym = xkb->min_key_code; 1510f7df2e56Smrg rep.nKeySyms = n; 1511f7df2e56Smrg } 1512f7df2e56Smrg else if (stuff->partial & XkbKeySymsMask) { 1513f7df2e56Smrg CHK_KEY_RANGE(0x05, stuff->firstKeySym, stuff->nKeySyms, xkb); 1514f7df2e56Smrg rep.firstKeySym = stuff->firstKeySym; 1515f7df2e56Smrg rep.nKeySyms = stuff->nKeySyms; 1516f7df2e56Smrg } 1517f7df2e56Smrg else 1518f7df2e56Smrg rep.nKeySyms = 0; 1519f7df2e56Smrg rep.totalSyms = 0; 1520f7df2e56Smrg 1521f7df2e56Smrg if (stuff->full & XkbKeyActionsMask) { 1522f7df2e56Smrg rep.firstKeyAct = xkb->min_key_code; 1523f7df2e56Smrg rep.nKeyActs = n; 1524f7df2e56Smrg } 1525f7df2e56Smrg else if (stuff->partial & XkbKeyActionsMask) { 1526f7df2e56Smrg CHK_KEY_RANGE(0x07, stuff->firstKeyAct, stuff->nKeyActs, xkb); 1527f7df2e56Smrg rep.firstKeyAct = stuff->firstKeyAct; 1528f7df2e56Smrg rep.nKeyActs = stuff->nKeyActs; 1529f7df2e56Smrg } 1530f7df2e56Smrg else 1531f7df2e56Smrg rep.nKeyActs = 0; 1532f7df2e56Smrg rep.totalActs = 0; 1533f7df2e56Smrg 1534f7df2e56Smrg if (stuff->full & XkbKeyBehaviorsMask) { 1535f7df2e56Smrg rep.firstKeyBehavior = xkb->min_key_code; 1536f7df2e56Smrg rep.nKeyBehaviors = n; 1537f7df2e56Smrg } 1538f7df2e56Smrg else if (stuff->partial & XkbKeyBehaviorsMask) { 1539f7df2e56Smrg CHK_KEY_RANGE(0x09, stuff->firstKeyBehavior, stuff->nKeyBehaviors, xkb); 1540f7df2e56Smrg rep.firstKeyBehavior = stuff->firstKeyBehavior; 1541f7df2e56Smrg rep.nKeyBehaviors = stuff->nKeyBehaviors; 1542f7df2e56Smrg } 1543f7df2e56Smrg else 1544f7df2e56Smrg rep.nKeyBehaviors = 0; 1545f7df2e56Smrg rep.totalKeyBehaviors = 0; 1546f7df2e56Smrg 1547f7df2e56Smrg if (stuff->full & XkbVirtualModsMask) 1548f7df2e56Smrg rep.virtualMods = ~0; 1549f7df2e56Smrg else if (stuff->partial & XkbVirtualModsMask) 1550f7df2e56Smrg rep.virtualMods = stuff->virtualMods; 1551f7df2e56Smrg 1552f7df2e56Smrg if (stuff->full & XkbExplicitComponentsMask) { 1553f7df2e56Smrg rep.firstKeyExplicit = xkb->min_key_code; 1554f7df2e56Smrg rep.nKeyExplicit = n; 1555f7df2e56Smrg } 1556f7df2e56Smrg else if (stuff->partial & XkbExplicitComponentsMask) { 1557f7df2e56Smrg CHK_KEY_RANGE(0x0B, stuff->firstKeyExplicit, stuff->nKeyExplicit, xkb); 1558f7df2e56Smrg rep.firstKeyExplicit = stuff->firstKeyExplicit; 1559f7df2e56Smrg rep.nKeyExplicit = stuff->nKeyExplicit; 1560f7df2e56Smrg } 1561f7df2e56Smrg else 1562f7df2e56Smrg rep.nKeyExplicit = 0; 1563f7df2e56Smrg rep.totalKeyExplicit = 0; 1564f7df2e56Smrg 1565f7df2e56Smrg if (stuff->full & XkbModifierMapMask) { 1566f7df2e56Smrg rep.firstModMapKey = xkb->min_key_code; 1567f7df2e56Smrg rep.nModMapKeys = n; 1568f7df2e56Smrg } 1569f7df2e56Smrg else if (stuff->partial & XkbModifierMapMask) { 1570f7df2e56Smrg CHK_KEY_RANGE(0x0D, stuff->firstModMapKey, stuff->nModMapKeys, xkb); 1571f7df2e56Smrg rep.firstModMapKey = stuff->firstModMapKey; 1572f7df2e56Smrg rep.nModMapKeys = stuff->nModMapKeys; 1573f7df2e56Smrg } 1574f7df2e56Smrg else 1575f7df2e56Smrg rep.nModMapKeys = 0; 1576f7df2e56Smrg rep.totalModMapKeys = 0; 1577f7df2e56Smrg 1578f7df2e56Smrg if (stuff->full & XkbVirtualModMapMask) { 1579f7df2e56Smrg rep.firstVModMapKey = xkb->min_key_code; 1580f7df2e56Smrg rep.nVModMapKeys = n; 1581f7df2e56Smrg } 1582f7df2e56Smrg else if (stuff->partial & XkbVirtualModMapMask) { 1583f7df2e56Smrg CHK_KEY_RANGE(0x0F, stuff->firstVModMapKey, stuff->nVModMapKeys, xkb); 1584f7df2e56Smrg rep.firstVModMapKey = stuff->firstVModMapKey; 1585f7df2e56Smrg rep.nVModMapKeys = stuff->nVModMapKeys; 1586f7df2e56Smrg } 1587f7df2e56Smrg else 1588f7df2e56Smrg rep.nVModMapKeys = 0; 1589f7df2e56Smrg rep.totalVModMapKeys = 0; 1590f7df2e56Smrg 1591f7df2e56Smrg if ((status = XkbComputeGetMapReplySize(xkb, &rep)) != Success) 1592f7df2e56Smrg return status; 1593f7df2e56Smrg return XkbSendMap(client, xkb, &rep); 159405b261ecSmrg} 159505b261ecSmrg 159605b261ecSmrg/***====================================================================***/ 159705b261ecSmrg 159805b261ecSmrgstatic int 1599f7df2e56SmrgCheckKeyTypes(ClientPtr client, 1600f7df2e56Smrg XkbDescPtr xkb, 1601f7df2e56Smrg xkbSetMapReq * req, 1602f7df2e56Smrg xkbKeyTypeWireDesc ** wireRtrn, 16035a112b11Smrg int *nMapsRtrn, CARD8 *mapWidthRtrn, Bool doswap) 160405b261ecSmrg{ 1605f7df2e56Smrg unsigned nMaps; 1606f7df2e56Smrg register unsigned i, n; 1607f7df2e56Smrg register CARD8 *map; 1608f7df2e56Smrg register xkbKeyTypeWireDesc *wire = *wireRtrn; 1609f7df2e56Smrg 1610f7df2e56Smrg if (req->firstType > ((unsigned) xkb->map->num_types)) { 1611f7df2e56Smrg *nMapsRtrn = _XkbErrCode3(0x01, req->firstType, xkb->map->num_types); 1612f7df2e56Smrg return 0; 1613f7df2e56Smrg } 1614f7df2e56Smrg if (req->flags & XkbSetMapResizeTypes) { 1615f7df2e56Smrg nMaps = req->firstType + req->nTypes; 1616f7df2e56Smrg if (nMaps < XkbNumRequiredTypes) { /* canonical types must be there */ 1617f7df2e56Smrg *nMapsRtrn = _XkbErrCode4(0x02, req->firstType, req->nTypes, 4); 1618f7df2e56Smrg return 0; 1619f7df2e56Smrg } 1620f7df2e56Smrg } 1621f7df2e56Smrg else if (req->present & XkbKeyTypesMask) { 1622f7df2e56Smrg nMaps = xkb->map->num_types; 1623f7df2e56Smrg if ((req->firstType + req->nTypes) > nMaps) { 1624f7df2e56Smrg *nMapsRtrn = req->firstType + req->nTypes; 1625f7df2e56Smrg return 0; 1626f7df2e56Smrg } 162705b261ecSmrg } 162805b261ecSmrg else { 1629f7df2e56Smrg *nMapsRtrn = xkb->map->num_types; 1630f7df2e56Smrg for (i = 0; i < xkb->map->num_types; i++) { 1631f7df2e56Smrg mapWidthRtrn[i] = xkb->map->types[i].num_levels; 1632f7df2e56Smrg } 1633f7df2e56Smrg return 1; 1634f7df2e56Smrg } 1635f7df2e56Smrg 1636f7df2e56Smrg for (i = 0; i < req->firstType; i++) { 1637f7df2e56Smrg mapWidthRtrn[i] = xkb->map->types[i].num_levels; 1638f7df2e56Smrg } 1639f7df2e56Smrg for (i = 0; i < req->nTypes; i++) { 1640f7df2e56Smrg unsigned width; 1641f7df2e56Smrg 16425a112b11Smrg if (client->swapped && doswap) { 1643f7df2e56Smrg swaps(&wire->virtualMods); 1644f7df2e56Smrg } 1645f7df2e56Smrg n = i + req->firstType; 1646f7df2e56Smrg width = wire->numLevels; 1647f7df2e56Smrg if (width < 1) { 1648f7df2e56Smrg *nMapsRtrn = _XkbErrCode3(0x04, n, width); 1649f7df2e56Smrg return 0; 1650f7df2e56Smrg } 1651f7df2e56Smrg else if ((n == XkbOneLevelIndex) && (width != 1)) { /* must be width 1 */ 1652f7df2e56Smrg *nMapsRtrn = _XkbErrCode3(0x05, n, width); 1653f7df2e56Smrg return 0; 1654f7df2e56Smrg } 1655f7df2e56Smrg else if ((width != 2) && 1656f7df2e56Smrg ((n == XkbTwoLevelIndex) || (n == XkbKeypadIndex) || 1657f7df2e56Smrg (n == XkbAlphabeticIndex))) { 1658f7df2e56Smrg /* TWO_LEVEL, ALPHABETIC and KEYPAD must be width 2 */ 1659f7df2e56Smrg *nMapsRtrn = _XkbErrCode3(0x05, n, width); 1660f7df2e56Smrg return 0; 1661f7df2e56Smrg } 1662f7df2e56Smrg if (wire->nMapEntries > 0) { 1663f7df2e56Smrg xkbKTSetMapEntryWireDesc *mapWire; 1664f7df2e56Smrg xkbModsWireDesc *preWire; 1665f7df2e56Smrg 1666f7df2e56Smrg mapWire = (xkbKTSetMapEntryWireDesc *) &wire[1]; 1667f7df2e56Smrg preWire = (xkbModsWireDesc *) &mapWire[wire->nMapEntries]; 1668f7df2e56Smrg for (n = 0; n < wire->nMapEntries; n++) { 16695a112b11Smrg if (client->swapped && doswap) { 1670f7df2e56Smrg swaps(&mapWire[n].virtualMods); 1671f7df2e56Smrg } 1672f7df2e56Smrg if (mapWire[n].realMods & (~wire->realMods)) { 1673f7df2e56Smrg *nMapsRtrn = _XkbErrCode4(0x06, n, mapWire[n].realMods, 1674f7df2e56Smrg wire->realMods); 1675f7df2e56Smrg return 0; 1676f7df2e56Smrg } 1677f7df2e56Smrg if (mapWire[n].virtualMods & (~wire->virtualMods)) { 1678f7df2e56Smrg *nMapsRtrn = _XkbErrCode3(0x07, n, mapWire[n].virtualMods); 1679f7df2e56Smrg return 0; 1680f7df2e56Smrg } 1681f7df2e56Smrg if (mapWire[n].level >= wire->numLevels) { 1682f7df2e56Smrg *nMapsRtrn = _XkbErrCode4(0x08, n, wire->numLevels, 1683f7df2e56Smrg mapWire[n].level); 1684f7df2e56Smrg return 0; 1685f7df2e56Smrg } 1686f7df2e56Smrg if (wire->preserve) { 16875a112b11Smrg if (client->swapped && doswap) { 1688f7df2e56Smrg swaps(&preWire[n].virtualMods); 1689f7df2e56Smrg } 1690f7df2e56Smrg if (preWire[n].realMods & (~mapWire[n].realMods)) { 1691f7df2e56Smrg *nMapsRtrn = _XkbErrCode4(0x09, n, preWire[n].realMods, 1692f7df2e56Smrg mapWire[n].realMods); 1693f7df2e56Smrg return 0; 1694f7df2e56Smrg } 1695f7df2e56Smrg if (preWire[n].virtualMods & (~mapWire[n].virtualMods)) { 1696f7df2e56Smrg *nMapsRtrn = 1697f7df2e56Smrg _XkbErrCode3(0x0a, n, preWire[n].virtualMods); 1698f7df2e56Smrg return 0; 1699f7df2e56Smrg } 1700f7df2e56Smrg } 1701f7df2e56Smrg } 1702f7df2e56Smrg if (wire->preserve) 1703f7df2e56Smrg map = (CARD8 *) &preWire[wire->nMapEntries]; 1704f7df2e56Smrg else 1705f7df2e56Smrg map = (CARD8 *) &mapWire[wire->nMapEntries]; 1706f7df2e56Smrg } 1707f7df2e56Smrg else 1708f7df2e56Smrg map = (CARD8 *) &wire[1]; 1709f7df2e56Smrg mapWidthRtrn[i + req->firstType] = wire->numLevels; 1710f7df2e56Smrg wire = (xkbKeyTypeWireDesc *) map; 1711f7df2e56Smrg } 1712f7df2e56Smrg for (i = req->firstType + req->nTypes; i < nMaps; i++) { 1713f7df2e56Smrg mapWidthRtrn[i] = xkb->map->types[i].num_levels; 171405b261ecSmrg } 171505b261ecSmrg *nMapsRtrn = nMaps; 171605b261ecSmrg *wireRtrn = wire; 171705b261ecSmrg return 1; 171805b261ecSmrg} 171905b261ecSmrg 172005b261ecSmrgstatic int 1721f7df2e56SmrgCheckKeySyms(ClientPtr client, 1722f7df2e56Smrg XkbDescPtr xkb, 1723f7df2e56Smrg xkbSetMapReq * req, 1724f7df2e56Smrg int nTypes, 1725f7df2e56Smrg CARD8 *mapWidths, 17265a112b11Smrg CARD16 *symsPerKey, xkbSymMapWireDesc ** wireRtrn, int *errorRtrn, Bool doswap) 172705b261ecSmrg{ 1728f7df2e56Smrg register unsigned i; 1729f7df2e56Smrg XkbSymMapPtr map; 1730f7df2e56Smrg xkbSymMapWireDesc *wire = *wireRtrn; 1731f7df2e56Smrg 1732f7df2e56Smrg if (!(XkbKeySymsMask & req->present)) 1733f7df2e56Smrg return 1; 1734f7df2e56Smrg CHK_REQ_KEY_RANGE2(0x11, req->firstKeySym, req->nKeySyms, req, (*errorRtrn), 1735f7df2e56Smrg 0); 1736f7df2e56Smrg for (i = 0; i < req->nKeySyms; i++) { 1737f7df2e56Smrg KeySym *pSyms; 1738f7df2e56Smrg register unsigned nG; 1739f7df2e56Smrg 17405a112b11Smrg if (client->swapped && doswap) { 1741f7df2e56Smrg swaps(&wire->nSyms); 1742f7df2e56Smrg } 1743f7df2e56Smrg nG = XkbNumGroups(wire->groupInfo); 1744f7df2e56Smrg if (nG > XkbNumKbdGroups) { 1745f7df2e56Smrg *errorRtrn = _XkbErrCode3(0x14, i + req->firstKeySym, nG); 1746f7df2e56Smrg return 0; 1747f7df2e56Smrg } 1748f7df2e56Smrg if (nG > 0) { 1749f7df2e56Smrg register int g, w; 1750f7df2e56Smrg 1751f7df2e56Smrg for (g = w = 0; g < nG; g++) { 1752f7df2e56Smrg if (wire->ktIndex[g] >= (unsigned) nTypes) { 1753f7df2e56Smrg *errorRtrn = _XkbErrCode4(0x15, i + req->firstKeySym, g, 1754f7df2e56Smrg wire->ktIndex[g]); 1755f7df2e56Smrg return 0; 1756f7df2e56Smrg } 1757f7df2e56Smrg if (mapWidths[wire->ktIndex[g]] > w) 1758f7df2e56Smrg w = mapWidths[wire->ktIndex[g]]; 1759f7df2e56Smrg } 1760f7df2e56Smrg if (wire->width != w) { 1761f7df2e56Smrg *errorRtrn = 1762f7df2e56Smrg _XkbErrCode3(0x16, i + req->firstKeySym, wire->width); 1763f7df2e56Smrg return 0; 1764f7df2e56Smrg } 1765f7df2e56Smrg w *= nG; 1766f7df2e56Smrg symsPerKey[i + req->firstKeySym] = w; 1767f7df2e56Smrg if (w != wire->nSyms) { 1768f7df2e56Smrg *errorRtrn = 1769f7df2e56Smrg _XkbErrCode4(0x16, i + req->firstKeySym, wire->nSyms, w); 1770f7df2e56Smrg return 0; 1771f7df2e56Smrg } 1772f7df2e56Smrg } 1773f7df2e56Smrg else if (wire->nSyms != 0) { 1774f7df2e56Smrg *errorRtrn = _XkbErrCode3(0x17, i + req->firstKeySym, wire->nSyms); 1775f7df2e56Smrg return 0; 1776f7df2e56Smrg } 1777f7df2e56Smrg pSyms = (KeySym *) &wire[1]; 1778f7df2e56Smrg wire = (xkbSymMapWireDesc *) &pSyms[wire->nSyms]; 177905b261ecSmrg } 178005b261ecSmrg 178105b261ecSmrg map = &xkb->map->key_sym_map[i]; 1782f7df2e56Smrg for (; i <= (unsigned) xkb->max_key_code; i++, map++) { 1783f7df2e56Smrg register int g, nG, w; 1784f7df2e56Smrg 1785f7df2e56Smrg nG = XkbKeyNumGroups(xkb, i); 1786f7df2e56Smrg for (w = g = 0; g < nG; g++) { 1787f7df2e56Smrg if (map->kt_index[g] >= (unsigned) nTypes) { 1788f7df2e56Smrg *errorRtrn = _XkbErrCode4(0x18, i, g, map->kt_index[g]); 1789f7df2e56Smrg return 0; 1790f7df2e56Smrg } 1791f7df2e56Smrg if (mapWidths[map->kt_index[g]] > w) 1792f7df2e56Smrg w = mapWidths[map->kt_index[g]]; 1793f7df2e56Smrg } 1794f7df2e56Smrg symsPerKey[i] = w * nG; 179505b261ecSmrg } 179605b261ecSmrg *wireRtrn = wire; 179705b261ecSmrg return 1; 179805b261ecSmrg} 179905b261ecSmrg 180005b261ecSmrgstatic int 1801f7df2e56SmrgCheckKeyActions(XkbDescPtr xkb, 1802f7df2e56Smrg xkbSetMapReq * req, 1803f7df2e56Smrg int nTypes, 1804f7df2e56Smrg CARD8 *mapWidths, 1805f7df2e56Smrg CARD16 *symsPerKey, CARD8 **wireRtrn, int *nActsRtrn) 180605b261ecSmrg{ 1807f7df2e56Smrg int nActs; 1808f7df2e56Smrg CARD8 *wire = *wireRtrn; 1809f7df2e56Smrg register unsigned i; 1810f7df2e56Smrg 1811f7df2e56Smrg if (!(XkbKeyActionsMask & req->present)) 1812f7df2e56Smrg return 1; 1813f7df2e56Smrg CHK_REQ_KEY_RANGE2(0x21, req->firstKeyAct, req->nKeyActs, req, (*nActsRtrn), 1814f7df2e56Smrg 0); 1815f7df2e56Smrg for (nActs = i = 0; i < req->nKeyActs; i++) { 1816f7df2e56Smrg if (wire[0] != 0) { 1817f7df2e56Smrg if (wire[0] == symsPerKey[i + req->firstKeyAct]) 1818f7df2e56Smrg nActs += wire[0]; 1819f7df2e56Smrg else { 1820f7df2e56Smrg *nActsRtrn = _XkbErrCode3(0x23, i + req->firstKeyAct, wire[0]); 1821f7df2e56Smrg return 0; 1822f7df2e56Smrg } 1823f7df2e56Smrg } 1824f7df2e56Smrg wire++; 1825f7df2e56Smrg } 1826f7df2e56Smrg if (req->nKeyActs % 4) 1827f7df2e56Smrg wire += 4 - (req->nKeyActs % 4); 1828f7df2e56Smrg *wireRtrn = (CARD8 *) (((XkbAnyAction *) wire) + nActs); 182905b261ecSmrg *nActsRtrn = nActs; 183005b261ecSmrg return 1; 183105b261ecSmrg} 183205b261ecSmrg 183305b261ecSmrgstatic int 1834f7df2e56SmrgCheckKeyBehaviors(XkbDescPtr xkb, 1835f7df2e56Smrg xkbSetMapReq * req, 1836f7df2e56Smrg xkbBehaviorWireDesc ** wireRtrn, int *errorRtrn) 183705b261ecSmrg{ 1838f7df2e56Smrg register xkbBehaviorWireDesc *wire = *wireRtrn; 1839f7df2e56Smrg register XkbServerMapPtr server = xkb->server; 1840f7df2e56Smrg register unsigned i; 1841f7df2e56Smrg unsigned first, last; 1842f7df2e56Smrg 1843f7df2e56Smrg if (((req->present & XkbKeyBehaviorsMask) == 0) || (req->nKeyBehaviors < 1)) { 1844f7df2e56Smrg req->present &= ~XkbKeyBehaviorsMask; 1845f7df2e56Smrg req->nKeyBehaviors = 0; 1846f7df2e56Smrg return 1; 1847f7df2e56Smrg } 1848f7df2e56Smrg first = req->firstKeyBehavior; 1849f7df2e56Smrg last = req->firstKeyBehavior + req->nKeyBehaviors - 1; 1850f7df2e56Smrg if (first < req->minKeyCode) { 1851f7df2e56Smrg *errorRtrn = _XkbErrCode3(0x31, first, req->minKeyCode); 1852f7df2e56Smrg return 0; 1853f7df2e56Smrg } 1854f7df2e56Smrg if (last > req->maxKeyCode) { 1855f7df2e56Smrg *errorRtrn = _XkbErrCode3(0x32, last, req->maxKeyCode); 1856f7df2e56Smrg return 0; 1857f7df2e56Smrg } 1858f7df2e56Smrg 1859f7df2e56Smrg for (i = 0; i < req->totalKeyBehaviors; i++, wire++) { 1860f7df2e56Smrg if ((wire->key < first) || (wire->key > last)) { 1861f7df2e56Smrg *errorRtrn = _XkbErrCode4(0x33, first, last, wire->key); 1862f7df2e56Smrg return 0; 1863f7df2e56Smrg } 1864f7df2e56Smrg if ((wire->type & XkbKB_Permanent) && 1865f7df2e56Smrg ((server->behaviors[wire->key].type != wire->type) || 1866f7df2e56Smrg (server->behaviors[wire->key].data != wire->data))) { 1867f7df2e56Smrg *errorRtrn = _XkbErrCode3(0x33, wire->key, wire->type); 1868f7df2e56Smrg return 0; 1869f7df2e56Smrg } 1870f7df2e56Smrg if ((wire->type == XkbKB_RadioGroup) && 1871f7df2e56Smrg ((wire->data & (~XkbKB_RGAllowNone)) > XkbMaxRadioGroups)) { 1872f7df2e56Smrg *errorRtrn = _XkbErrCode4(0x34, wire->key, wire->data, 1873f7df2e56Smrg XkbMaxRadioGroups); 1874f7df2e56Smrg return 0; 1875f7df2e56Smrg } 1876f7df2e56Smrg if ((wire->type == XkbKB_Overlay1) || (wire->type == XkbKB_Overlay2)) { 1877f7df2e56Smrg CHK_KEY_RANGE2(0x35, wire->key, 1, xkb, *errorRtrn, 0); 1878f7df2e56Smrg } 187905b261ecSmrg } 188005b261ecSmrg *wireRtrn = wire; 188105b261ecSmrg return 1; 188205b261ecSmrg} 188305b261ecSmrg 188405b261ecSmrgstatic int 1885f7df2e56SmrgCheckVirtualMods(XkbDescRec * xkb, 1886f7df2e56Smrg xkbSetMapReq * req, CARD8 **wireRtrn, int *errorRtrn) 188705b261ecSmrg{ 1888f7df2e56Smrg register CARD8 *wire = *wireRtrn; 1889f7df2e56Smrg register unsigned i, nMods, bit; 189005b261ecSmrg 1891f7df2e56Smrg if (((req->present & XkbVirtualModsMask) == 0) || (req->virtualMods == 0)) 1892f7df2e56Smrg return 1; 1893f7df2e56Smrg for (i = nMods = 0, bit = 1; i < XkbNumVirtualMods; i++, bit <<= 1) { 1894f7df2e56Smrg if (req->virtualMods & bit) 1895f7df2e56Smrg nMods++; 189605b261ecSmrg } 1897f7df2e56Smrg *wireRtrn = (wire + XkbPaddedSize(nMods)); 189805b261ecSmrg return 1; 189905b261ecSmrg} 190005b261ecSmrg 190105b261ecSmrgstatic int 1902f7df2e56SmrgCheckKeyExplicit(XkbDescPtr xkb, 1903f7df2e56Smrg xkbSetMapReq * req, CARD8 **wireRtrn, int *errorRtrn) 190405b261ecSmrg{ 1905f7df2e56Smrg register CARD8 *wire = *wireRtrn; 1906f7df2e56Smrg CARD8 *start; 1907f7df2e56Smrg register unsigned i; 1908f7df2e56Smrg int first, last; 1909f7df2e56Smrg 1910f7df2e56Smrg if (((req->present & XkbExplicitComponentsMask) == 0) || 1911f7df2e56Smrg (req->nKeyExplicit < 1)) { 1912f7df2e56Smrg req->present &= ~XkbExplicitComponentsMask; 1913f7df2e56Smrg req->nKeyExplicit = 0; 1914f7df2e56Smrg return 1; 1915f7df2e56Smrg } 1916f7df2e56Smrg first = req->firstKeyExplicit; 1917f7df2e56Smrg last = first + req->nKeyExplicit - 1; 1918f7df2e56Smrg if (first < req->minKeyCode) { 1919f7df2e56Smrg *errorRtrn = _XkbErrCode3(0x51, first, req->minKeyCode); 1920f7df2e56Smrg return 0; 1921f7df2e56Smrg } 1922f7df2e56Smrg if (last > req->maxKeyCode) { 1923f7df2e56Smrg *errorRtrn = _XkbErrCode3(0x52, last, req->maxKeyCode); 1924f7df2e56Smrg return 0; 1925f7df2e56Smrg } 1926f7df2e56Smrg start = wire; 1927f7df2e56Smrg for (i = 0; i < req->totalKeyExplicit; i++, wire += 2) { 1928f7df2e56Smrg if ((wire[0] < first) || (wire[0] > last)) { 1929f7df2e56Smrg *errorRtrn = _XkbErrCode4(0x53, first, last, wire[0]); 1930f7df2e56Smrg return 0; 1931f7df2e56Smrg } 1932f7df2e56Smrg if (wire[1] & (~XkbAllExplicitMask)) { 1933f7df2e56Smrg *errorRtrn = _XkbErrCode3(0x52, ~XkbAllExplicitMask, wire[1]); 1934f7df2e56Smrg return 0; 1935f7df2e56Smrg } 1936f7df2e56Smrg } 1937f7df2e56Smrg wire += XkbPaddedSize(wire - start) - (wire - start); 1938f7df2e56Smrg *wireRtrn = wire; 193905b261ecSmrg return 1; 194005b261ecSmrg} 194105b261ecSmrg 194205b261ecSmrgstatic int 1943f7df2e56SmrgCheckModifierMap(XkbDescPtr xkb, xkbSetMapReq * req, CARD8 **wireRtrn, 1944f7df2e56Smrg int *errRtrn) 194505b261ecSmrg{ 1946f7df2e56Smrg register CARD8 *wire = *wireRtrn; 1947f7df2e56Smrg CARD8 *start; 1948f7df2e56Smrg register unsigned i; 1949f7df2e56Smrg int first, last; 1950f7df2e56Smrg 1951f7df2e56Smrg if (((req->present & XkbModifierMapMask) == 0) || (req->nModMapKeys < 1)) { 1952f7df2e56Smrg req->present &= ~XkbModifierMapMask; 1953f7df2e56Smrg req->nModMapKeys = 0; 1954f7df2e56Smrg return 1; 1955f7df2e56Smrg } 1956f7df2e56Smrg first = req->firstModMapKey; 1957f7df2e56Smrg last = first + req->nModMapKeys - 1; 1958f7df2e56Smrg if (first < req->minKeyCode) { 1959f7df2e56Smrg *errRtrn = _XkbErrCode3(0x61, first, req->minKeyCode); 1960f7df2e56Smrg return 0; 1961f7df2e56Smrg } 1962f7df2e56Smrg if (last > req->maxKeyCode) { 1963f7df2e56Smrg *errRtrn = _XkbErrCode3(0x62, last, req->maxKeyCode); 1964f7df2e56Smrg return 0; 1965f7df2e56Smrg } 1966f7df2e56Smrg start = wire; 1967f7df2e56Smrg for (i = 0; i < req->totalModMapKeys; i++, wire += 2) { 1968f7df2e56Smrg if ((wire[0] < first) || (wire[0] > last)) { 1969f7df2e56Smrg *errRtrn = _XkbErrCode4(0x63, first, last, wire[0]); 1970f7df2e56Smrg return 0; 1971f7df2e56Smrg } 1972f7df2e56Smrg } 1973f7df2e56Smrg wire += XkbPaddedSize(wire - start) - (wire - start); 1974f7df2e56Smrg *wireRtrn = wire; 197505b261ecSmrg return 1; 197605b261ecSmrg} 197705b261ecSmrg 197805b261ecSmrgstatic int 1979f7df2e56SmrgCheckVirtualModMap(XkbDescPtr xkb, 1980f7df2e56Smrg xkbSetMapReq * req, 1981f7df2e56Smrg xkbVModMapWireDesc ** wireRtrn, int *errRtrn) 198205b261ecSmrg{ 1983f7df2e56Smrg register xkbVModMapWireDesc *wire = *wireRtrn; 1984f7df2e56Smrg register unsigned i; 1985f7df2e56Smrg int first, last; 1986f7df2e56Smrg 1987f7df2e56Smrg if (((req->present & XkbVirtualModMapMask) == 0) || (req->nVModMapKeys < 1)) { 1988f7df2e56Smrg req->present &= ~XkbVirtualModMapMask; 1989f7df2e56Smrg req->nVModMapKeys = 0; 1990f7df2e56Smrg return 1; 1991f7df2e56Smrg } 1992f7df2e56Smrg first = req->firstVModMapKey; 1993f7df2e56Smrg last = first + req->nVModMapKeys - 1; 1994f7df2e56Smrg if (first < req->minKeyCode) { 1995f7df2e56Smrg *errRtrn = _XkbErrCode3(0x71, first, req->minKeyCode); 1996f7df2e56Smrg return 0; 1997f7df2e56Smrg } 1998f7df2e56Smrg if (last > req->maxKeyCode) { 1999f7df2e56Smrg *errRtrn = _XkbErrCode3(0x72, last, req->maxKeyCode); 2000f7df2e56Smrg return 0; 2001f7df2e56Smrg } 2002f7df2e56Smrg for (i = 0; i < req->totalVModMapKeys; i++, wire++) { 2003f7df2e56Smrg if ((wire->key < first) || (wire->key > last)) { 2004f7df2e56Smrg *errRtrn = _XkbErrCode4(0x73, first, last, wire->key); 2005f7df2e56Smrg return 0; 2006f7df2e56Smrg } 2007f7df2e56Smrg } 2008f7df2e56Smrg *wireRtrn = wire; 200905b261ecSmrg return 1; 201005b261ecSmrg} 201105b261ecSmrg 201205b261ecSmrgstatic char * 2013f7df2e56SmrgSetKeyTypes(XkbDescPtr xkb, 2014f7df2e56Smrg xkbSetMapReq * req, 2015f7df2e56Smrg xkbKeyTypeWireDesc * wire, XkbChangesPtr changes) 201605b261ecSmrg{ 2017f7df2e56Smrg register unsigned i; 2018f7df2e56Smrg unsigned first, last; 2019f7df2e56Smrg CARD8 *map; 2020f7df2e56Smrg 2021f7df2e56Smrg if ((unsigned) (req->firstType + req->nTypes) > xkb->map->size_types) { 2022f7df2e56Smrg i = req->firstType + req->nTypes; 2023f7df2e56Smrg if (XkbAllocClientMap(xkb, XkbKeyTypesMask, i) != Success) { 2024f7df2e56Smrg return NULL; 2025f7df2e56Smrg } 2026f7df2e56Smrg } 2027f7df2e56Smrg if ((unsigned) (req->firstType + req->nTypes) > xkb->map->num_types) 2028f7df2e56Smrg xkb->map->num_types = req->firstType + req->nTypes; 2029f7df2e56Smrg 2030f7df2e56Smrg for (i = 0; i < req->nTypes; i++) { 2031f7df2e56Smrg XkbKeyTypePtr pOld; 2032f7df2e56Smrg register unsigned n; 2033f7df2e56Smrg 2034f7df2e56Smrg if (XkbResizeKeyType(xkb, i + req->firstType, wire->nMapEntries, 2035f7df2e56Smrg wire->preserve, wire->numLevels) != Success) { 2036f7df2e56Smrg return NULL; 2037f7df2e56Smrg } 2038f7df2e56Smrg pOld = &xkb->map->types[i + req->firstType]; 2039f7df2e56Smrg map = (CARD8 *) &wire[1]; 2040f7df2e56Smrg 2041f7df2e56Smrg pOld->mods.real_mods = wire->realMods; 2042f7df2e56Smrg pOld->mods.vmods = wire->virtualMods; 2043f7df2e56Smrg pOld->num_levels = wire->numLevels; 2044f7df2e56Smrg pOld->map_count = wire->nMapEntries; 2045f7df2e56Smrg 2046f7df2e56Smrg pOld->mods.mask = pOld->mods.real_mods | 2047f7df2e56Smrg XkbMaskForVMask(xkb, pOld->mods.vmods); 2048f7df2e56Smrg 2049f7df2e56Smrg if (wire->nMapEntries) { 2050f7df2e56Smrg xkbKTSetMapEntryWireDesc *mapWire; 2051f7df2e56Smrg xkbModsWireDesc *preWire; 2052f7df2e56Smrg unsigned tmp; 2053f7df2e56Smrg 2054f7df2e56Smrg mapWire = (xkbKTSetMapEntryWireDesc *) map; 2055f7df2e56Smrg preWire = (xkbModsWireDesc *) &mapWire[wire->nMapEntries]; 2056f7df2e56Smrg for (n = 0; n < wire->nMapEntries; n++) { 2057f7df2e56Smrg pOld->map[n].active = 1; 2058f7df2e56Smrg pOld->map[n].mods.mask = mapWire[n].realMods; 2059f7df2e56Smrg pOld->map[n].mods.real_mods = mapWire[n].realMods; 2060f7df2e56Smrg pOld->map[n].mods.vmods = mapWire[n].virtualMods; 2061f7df2e56Smrg pOld->map[n].level = mapWire[n].level; 2062f7df2e56Smrg if (mapWire[n].virtualMods != 0) { 2063f7df2e56Smrg tmp = XkbMaskForVMask(xkb, mapWire[n].virtualMods); 2064f7df2e56Smrg pOld->map[n].active = (tmp != 0); 2065f7df2e56Smrg pOld->map[n].mods.mask |= tmp; 2066f7df2e56Smrg } 2067f7df2e56Smrg if (wire->preserve) { 2068f7df2e56Smrg pOld->preserve[n].real_mods = preWire[n].realMods; 2069f7df2e56Smrg pOld->preserve[n].vmods = preWire[n].virtualMods; 2070f7df2e56Smrg tmp = XkbMaskForVMask(xkb, preWire[n].virtualMods); 2071f7df2e56Smrg pOld->preserve[n].mask = preWire[n].realMods | tmp; 2072f7df2e56Smrg } 2073f7df2e56Smrg } 2074f7df2e56Smrg if (wire->preserve) 2075f7df2e56Smrg map = (CARD8 *) &preWire[wire->nMapEntries]; 2076f7df2e56Smrg else 2077f7df2e56Smrg map = (CARD8 *) &mapWire[wire->nMapEntries]; 2078f7df2e56Smrg } 2079f7df2e56Smrg else 2080f7df2e56Smrg map = (CARD8 *) &wire[1]; 2081f7df2e56Smrg wire = (xkbKeyTypeWireDesc *) map; 2082f7df2e56Smrg } 2083f7df2e56Smrg first = req->firstType; 2084f7df2e56Smrg last = first + req->nTypes - 1; /* last changed type */ 2085f7df2e56Smrg if (changes->map.changed & XkbKeyTypesMask) { 2086f7df2e56Smrg int oldLast; 2087f7df2e56Smrg 2088f7df2e56Smrg oldLast = changes->map.first_type + changes->map.num_types - 1; 2089f7df2e56Smrg if (changes->map.first_type < first) 2090f7df2e56Smrg first = changes->map.first_type; 2091f7df2e56Smrg if (oldLast > last) 2092f7df2e56Smrg last = oldLast; 2093f7df2e56Smrg } 2094f7df2e56Smrg changes->map.changed |= XkbKeyTypesMask; 209505b261ecSmrg changes->map.first_type = first; 2096f7df2e56Smrg changes->map.num_types = (last - first) + 1; 2097f7df2e56Smrg return (char *) wire; 209805b261ecSmrg} 209905b261ecSmrg 210005b261ecSmrgstatic char * 2101f7df2e56SmrgSetKeySyms(ClientPtr client, 2102f7df2e56Smrg XkbDescPtr xkb, 2103f7df2e56Smrg xkbSetMapReq * req, 2104f7df2e56Smrg xkbSymMapWireDesc * wire, XkbChangesPtr changes, DeviceIntPtr dev) 210505b261ecSmrg{ 2106f7df2e56Smrg register unsigned i, s; 2107f7df2e56Smrg XkbSymMapPtr oldMap; 2108f7df2e56Smrg KeySym *newSyms; 2109f7df2e56Smrg KeySym *pSyms; 2110f7df2e56Smrg unsigned first, last; 211105b261ecSmrg 211205b261ecSmrg oldMap = &xkb->map->key_sym_map[req->firstKeySym]; 2113f7df2e56Smrg for (i = 0; i < req->nKeySyms; i++, oldMap++) { 2114f7df2e56Smrg pSyms = (KeySym *) &wire[1]; 2115f7df2e56Smrg if (wire->nSyms > 0) { 2116f7df2e56Smrg newSyms = XkbResizeKeySyms(xkb, i + req->firstKeySym, wire->nSyms); 2117f7df2e56Smrg for (s = 0; s < wire->nSyms; s++) { 2118f7df2e56Smrg newSyms[s] = pSyms[s]; 2119f7df2e56Smrg } 2120f7df2e56Smrg if (client->swapped) { 2121f7df2e56Smrg for (s = 0; s < wire->nSyms; s++) { 2122f7df2e56Smrg swapl(&newSyms[s]); 2123f7df2e56Smrg } 2124f7df2e56Smrg } 2125f7df2e56Smrg } 21264e185dc0Smrg if (XkbKeyHasActions(xkb, i + req->firstKeySym)) 21274e185dc0Smrg XkbResizeKeyActions(xkb, i + req->firstKeySym, 21284e185dc0Smrg XkbNumGroups(wire->groupInfo) * wire->width); 2129f7df2e56Smrg oldMap->kt_index[0] = wire->ktIndex[0]; 2130f7df2e56Smrg oldMap->kt_index[1] = wire->ktIndex[1]; 2131f7df2e56Smrg oldMap->kt_index[2] = wire->ktIndex[2]; 2132f7df2e56Smrg oldMap->kt_index[3] = wire->ktIndex[3]; 2133f7df2e56Smrg oldMap->group_info = wire->groupInfo; 2134f7df2e56Smrg oldMap->width = wire->width; 2135f7df2e56Smrg wire = (xkbSymMapWireDesc *) &pSyms[wire->nSyms]; 2136f7df2e56Smrg } 2137f7df2e56Smrg first = req->firstKeySym; 2138f7df2e56Smrg last = first + req->nKeySyms - 1; 2139f7df2e56Smrg if (changes->map.changed & XkbKeySymsMask) { 2140f7df2e56Smrg int oldLast = 2141f7df2e56Smrg (changes->map.first_key_sym + changes->map.num_key_syms - 1); 2142f7df2e56Smrg if (changes->map.first_key_sym < first) 2143f7df2e56Smrg first = changes->map.first_key_sym; 2144f7df2e56Smrg if (oldLast > last) 2145f7df2e56Smrg last = oldLast; 2146f7df2e56Smrg } 2147f7df2e56Smrg changes->map.changed |= XkbKeySymsMask; 214805b261ecSmrg changes->map.first_key_sym = first; 2149f7df2e56Smrg changes->map.num_key_syms = (last - first + 1); 2150f7df2e56Smrg 2151f7df2e56Smrg s = 0; 2152f7df2e56Smrg for (i = xkb->min_key_code; i <= xkb->max_key_code; i++) { 2153f7df2e56Smrg if (XkbKeyNumGroups(xkb, i) > s) 2154f7df2e56Smrg s = XkbKeyNumGroups(xkb, i); 2155f7df2e56Smrg } 2156f7df2e56Smrg if (s != xkb->ctrls->num_groups) { 2157f7df2e56Smrg xkbControlsNotify cn; 2158f7df2e56Smrg XkbControlsRec old; 2159f7df2e56Smrg 2160f7df2e56Smrg cn.keycode = 0; 2161f7df2e56Smrg cn.eventType = 0; 2162f7df2e56Smrg cn.requestMajor = XkbReqCode; 2163f7df2e56Smrg cn.requestMinor = X_kbSetMap; 2164f7df2e56Smrg old = *xkb->ctrls; 2165f7df2e56Smrg xkb->ctrls->num_groups = s; 2166f7df2e56Smrg if (XkbComputeControlsNotify(dev, &old, xkb->ctrls, &cn, FALSE)) 2167f7df2e56Smrg XkbSendControlsNotify(dev, &cn); 2168f7df2e56Smrg } 2169f7df2e56Smrg return (char *) wire; 217005b261ecSmrg} 217105b261ecSmrg 217205b261ecSmrgstatic char * 2173f7df2e56SmrgSetKeyActions(XkbDescPtr xkb, 2174f7df2e56Smrg xkbSetMapReq * req, CARD8 *wire, XkbChangesPtr changes) 217505b261ecSmrg{ 2176f7df2e56Smrg register unsigned i, first, last; 2177f7df2e56Smrg CARD8 *nActs = wire; 2178f7df2e56Smrg XkbAction *newActs; 2179f7df2e56Smrg 2180f7df2e56Smrg wire += XkbPaddedSize(req->nKeyActs); 2181f7df2e56Smrg for (i = 0; i < req->nKeyActs; i++) { 2182f7df2e56Smrg if (nActs[i] == 0) 2183f7df2e56Smrg xkb->server->key_acts[i + req->firstKeyAct] = 0; 2184f7df2e56Smrg else { 2185f7df2e56Smrg newActs = XkbResizeKeyActions(xkb, i + req->firstKeyAct, nActs[i]); 2186f7df2e56Smrg memcpy((char *) newActs, (char *) wire, 2187f7df2e56Smrg nActs[i] * SIZEOF(xkbActionWireDesc)); 2188f7df2e56Smrg wire += nActs[i] * SIZEOF(xkbActionWireDesc); 2189f7df2e56Smrg } 2190f7df2e56Smrg } 2191f7df2e56Smrg first = req->firstKeyAct; 2192f7df2e56Smrg last = (first + req->nKeyActs - 1); 2193f7df2e56Smrg if (changes->map.changed & XkbKeyActionsMask) { 2194f7df2e56Smrg int oldLast; 2195f7df2e56Smrg 2196f7df2e56Smrg oldLast = changes->map.first_key_act + changes->map.num_key_acts - 1; 2197f7df2e56Smrg if (changes->map.first_key_act < first) 2198f7df2e56Smrg first = changes->map.first_key_act; 2199f7df2e56Smrg if (oldLast > last) 2200f7df2e56Smrg last = oldLast; 2201f7df2e56Smrg } 2202f7df2e56Smrg changes->map.changed |= XkbKeyActionsMask; 2203f7df2e56Smrg changes->map.first_key_act = first; 2204f7df2e56Smrg changes->map.num_key_acts = (last - first + 1); 2205f7df2e56Smrg return (char *) wire; 220605b261ecSmrg} 220705b261ecSmrg 220805b261ecSmrgstatic char * 2209f7df2e56SmrgSetKeyBehaviors(XkbSrvInfoPtr xkbi, 2210f7df2e56Smrg xkbSetMapReq * req, 2211f7df2e56Smrg xkbBehaviorWireDesc * wire, XkbChangesPtr changes) 221205b261ecSmrg{ 2213f7df2e56Smrg register unsigned i; 2214f7df2e56Smrg int maxRG = -1; 2215f7df2e56Smrg XkbDescPtr xkb = xkbi->desc; 2216f7df2e56Smrg XkbServerMapPtr server = xkb->server; 2217f7df2e56Smrg unsigned first, last; 2218f7df2e56Smrg 2219f7df2e56Smrg first = req->firstKeyBehavior; 2220f7df2e56Smrg last = req->firstKeyBehavior + req->nKeyBehaviors - 1; 2221f7df2e56Smrg memset(&server->behaviors[first], 0, 2222f7df2e56Smrg req->nKeyBehaviors * sizeof(XkbBehavior)); 2223f7df2e56Smrg for (i = 0; i < req->totalKeyBehaviors; i++) { 2224f7df2e56Smrg if ((server->behaviors[wire->key].type & XkbKB_Permanent) == 0) { 2225f7df2e56Smrg server->behaviors[wire->key].type = wire->type; 2226f7df2e56Smrg server->behaviors[wire->key].data = wire->data; 2227f7df2e56Smrg if ((wire->type == XkbKB_RadioGroup) && 2228f7df2e56Smrg (((int) wire->data) > maxRG)) 2229f7df2e56Smrg maxRG = wire->data + 1; 2230f7df2e56Smrg } 2231f7df2e56Smrg wire++; 2232f7df2e56Smrg } 2233f7df2e56Smrg 2234f7df2e56Smrg if (maxRG > (int) xkbi->nRadioGroups) { 223505b261ecSmrg if (xkbi->radioGroups) 2236f7df2e56Smrg xkbi->radioGroups = reallocarray(xkbi->radioGroups, maxRG, 2237f7df2e56Smrg sizeof(XkbRadioGroupRec)); 2238f7df2e56Smrg else 2239f7df2e56Smrg xkbi->radioGroups = calloc(maxRG, sizeof(XkbRadioGroupRec)); 224005b261ecSmrg if (xkbi->radioGroups) { 2241f7df2e56Smrg if (xkbi->nRadioGroups) 2242f7df2e56Smrg memset(&xkbi->radioGroups[xkbi->nRadioGroups], 0, 2243f7df2e56Smrg (maxRG - xkbi->nRadioGroups) * sizeof(XkbRadioGroupRec)); 2244f7df2e56Smrg xkbi->nRadioGroups = maxRG; 224505b261ecSmrg } 2246f7df2e56Smrg else 2247f7df2e56Smrg xkbi->nRadioGroups = 0; 224805b261ecSmrg /* should compute members here */ 224905b261ecSmrg } 2250f7df2e56Smrg if (changes->map.changed & XkbKeyBehaviorsMask) { 2251f7df2e56Smrg unsigned oldLast; 2252f7df2e56Smrg 2253f7df2e56Smrg oldLast = changes->map.first_key_behavior + 2254f7df2e56Smrg changes->map.num_key_behaviors - 1; 2255f7df2e56Smrg if (changes->map.first_key_behavior < req->firstKeyBehavior) 2256f7df2e56Smrg first = changes->map.first_key_behavior; 2257f7df2e56Smrg if (oldLast > last) 2258f7df2e56Smrg last = oldLast; 225905b261ecSmrg } 2260f7df2e56Smrg changes->map.changed |= XkbKeyBehaviorsMask; 226105b261ecSmrg changes->map.first_key_behavior = first; 2262f7df2e56Smrg changes->map.num_key_behaviors = (last - first + 1); 2263f7df2e56Smrg return (char *) wire; 226405b261ecSmrg} 226505b261ecSmrg 226605b261ecSmrgstatic char * 2267f7df2e56SmrgSetVirtualMods(XkbSrvInfoPtr xkbi, xkbSetMapReq * req, CARD8 *wire, 2268f7df2e56Smrg XkbChangesPtr changes) 226905b261ecSmrg{ 2270f7df2e56Smrg register int i, bit, nMods; 2271f7df2e56Smrg XkbServerMapPtr srv = xkbi->desc->server; 2272f7df2e56Smrg 2273f7df2e56Smrg if (((req->present & XkbVirtualModsMask) == 0) || (req->virtualMods == 0)) 2274f7df2e56Smrg return (char *) wire; 2275f7df2e56Smrg for (i = nMods = 0, bit = 1; i < XkbNumVirtualMods; i++, bit <<= 1) { 2276f7df2e56Smrg if (req->virtualMods & bit) { 2277f7df2e56Smrg if (srv->vmods[i] != wire[nMods]) { 2278f7df2e56Smrg changes->map.changed |= XkbVirtualModsMask; 2279f7df2e56Smrg changes->map.vmods |= bit; 2280f7df2e56Smrg srv->vmods[i] = wire[nMods]; 2281f7df2e56Smrg } 2282f7df2e56Smrg nMods++; 2283f7df2e56Smrg } 2284f7df2e56Smrg } 2285f7df2e56Smrg return (char *) (wire + XkbPaddedSize(nMods)); 228605b261ecSmrg} 228705b261ecSmrg 228805b261ecSmrgstatic char * 2289f7df2e56SmrgSetKeyExplicit(XkbSrvInfoPtr xkbi, xkbSetMapReq * req, CARD8 *wire, 2290f7df2e56Smrg XkbChangesPtr changes) 229105b261ecSmrg{ 2292f7df2e56Smrg register unsigned i, first, last; 2293f7df2e56Smrg XkbServerMapPtr xkb = xkbi->desc->server; 2294f7df2e56Smrg CARD8 *start; 229505b261ecSmrg 2296f7df2e56Smrg start = wire; 2297f7df2e56Smrg first = req->firstKeyExplicit; 2298f7df2e56Smrg last = req->firstKeyExplicit + req->nKeyExplicit - 1; 22996747b715Smrg memset(&xkb->explicit[first], 0, req->nKeyExplicit); 2300f7df2e56Smrg for (i = 0; i < req->totalKeyExplicit; i++, wire += 2) { 2301f7df2e56Smrg xkb->explicit[wire[0]] = wire[1]; 2302f7df2e56Smrg } 2303f7df2e56Smrg if (first > 0) { 2304f7df2e56Smrg if (changes->map.changed & XkbExplicitComponentsMask) { 2305f7df2e56Smrg int oldLast; 2306f7df2e56Smrg 2307f7df2e56Smrg oldLast = changes->map.first_key_explicit + 2308f7df2e56Smrg changes->map.num_key_explicit - 1; 2309f7df2e56Smrg if (changes->map.first_key_explicit < first) 2310f7df2e56Smrg first = changes->map.first_key_explicit; 2311f7df2e56Smrg if (oldLast > last) 2312f7df2e56Smrg last = oldLast; 2313f7df2e56Smrg } 2314f7df2e56Smrg changes->map.first_key_explicit = first; 2315f7df2e56Smrg changes->map.num_key_explicit = (last - first) + 1; 2316f7df2e56Smrg } 2317f7df2e56Smrg wire += XkbPaddedSize(wire - start) - (wire - start); 2318f7df2e56Smrg return (char *) wire; 231905b261ecSmrg} 232005b261ecSmrg 232105b261ecSmrgstatic char * 2322f7df2e56SmrgSetModifierMap(XkbSrvInfoPtr xkbi, 2323f7df2e56Smrg xkbSetMapReq * req, CARD8 *wire, XkbChangesPtr changes) 232405b261ecSmrg{ 2325f7df2e56Smrg register unsigned i, first, last; 2326f7df2e56Smrg XkbClientMapPtr xkb = xkbi->desc->map; 2327f7df2e56Smrg CARD8 *start; 232805b261ecSmrg 2329f7df2e56Smrg start = wire; 2330f7df2e56Smrg first = req->firstModMapKey; 2331f7df2e56Smrg last = req->firstModMapKey + req->nModMapKeys - 1; 23326747b715Smrg memset(&xkb->modmap[first], 0, req->nModMapKeys); 2333f7df2e56Smrg for (i = 0; i < req->totalModMapKeys; i++, wire += 2) { 2334f7df2e56Smrg xkb->modmap[wire[0]] = wire[1]; 2335f7df2e56Smrg } 2336f7df2e56Smrg if (first > 0) { 2337f7df2e56Smrg if (changes->map.changed & XkbModifierMapMask) { 2338f7df2e56Smrg int oldLast; 2339f7df2e56Smrg 2340f7df2e56Smrg oldLast = changes->map.first_modmap_key + 2341f7df2e56Smrg changes->map.num_modmap_keys - 1; 2342f7df2e56Smrg if (changes->map.first_modmap_key < first) 2343f7df2e56Smrg first = changes->map.first_modmap_key; 2344f7df2e56Smrg if (oldLast > last) 2345f7df2e56Smrg last = oldLast; 2346f7df2e56Smrg } 2347f7df2e56Smrg changes->map.first_modmap_key = first; 2348f7df2e56Smrg changes->map.num_modmap_keys = (last - first) + 1; 2349f7df2e56Smrg } 2350f7df2e56Smrg wire += XkbPaddedSize(wire - start) - (wire - start); 2351f7df2e56Smrg return (char *) wire; 235205b261ecSmrg} 235305b261ecSmrg 235405b261ecSmrgstatic char * 2355f7df2e56SmrgSetVirtualModMap(XkbSrvInfoPtr xkbi, 2356f7df2e56Smrg xkbSetMapReq * req, 2357f7df2e56Smrg xkbVModMapWireDesc * wire, XkbChangesPtr changes) 235805b261ecSmrg{ 2359f7df2e56Smrg register unsigned i, first, last; 2360f7df2e56Smrg XkbServerMapPtr srv = xkbi->desc->server; 2361f7df2e56Smrg 2362f7df2e56Smrg first = req->firstVModMapKey; 2363f7df2e56Smrg last = req->firstVModMapKey + req->nVModMapKeys - 1; 2364f7df2e56Smrg memset(&srv->vmodmap[first], 0, req->nVModMapKeys * sizeof(unsigned short)); 2365f7df2e56Smrg for (i = 0; i < req->totalVModMapKeys; i++, wire++) { 2366f7df2e56Smrg srv->vmodmap[wire->key] = wire->vmods; 2367f7df2e56Smrg } 2368f7df2e56Smrg if (first > 0) { 2369f7df2e56Smrg if (changes->map.changed & XkbVirtualModMapMask) { 2370f7df2e56Smrg int oldLast; 2371f7df2e56Smrg 2372f7df2e56Smrg oldLast = changes->map.first_vmodmap_key + 2373f7df2e56Smrg changes->map.num_vmodmap_keys - 1; 2374f7df2e56Smrg if (changes->map.first_vmodmap_key < first) 2375f7df2e56Smrg first = changes->map.first_vmodmap_key; 2376f7df2e56Smrg if (oldLast > last) 2377f7df2e56Smrg last = oldLast; 2378f7df2e56Smrg } 2379f7df2e56Smrg changes->map.first_vmodmap_key = first; 2380f7df2e56Smrg changes->map.num_vmodmap_keys = (last - first) + 1; 2381f7df2e56Smrg } 2382f7df2e56Smrg return (char *) wire; 238305b261ecSmrg} 238405b261ecSmrg 2385806e81e9Smrg#define _add_check_len(new) \ 2386806e81e9Smrg if (len > UINT32_MAX - (new) || len > req_len - (new)) goto bad; \ 2387806e81e9Smrg else len += new 2388806e81e9Smrg 2389806e81e9Smrg/** 2390806e81e9Smrg * Check the length of the SetMap request 2391806e81e9Smrg */ 2392806e81e9Smrgstatic int 2393806e81e9Smrg_XkbSetMapCheckLength(xkbSetMapReq *req) 2394806e81e9Smrg{ 2395806e81e9Smrg size_t len = sz_xkbSetMapReq, req_len = req->length << 2; 2396806e81e9Smrg xkbKeyTypeWireDesc *keytype; 2397806e81e9Smrg xkbSymMapWireDesc *symmap; 2398806e81e9Smrg BOOL preserve; 2399806e81e9Smrg int i, map_count, nSyms; 2400806e81e9Smrg 2401806e81e9Smrg if (req_len < len) 2402806e81e9Smrg goto bad; 2403806e81e9Smrg /* types */ 2404806e81e9Smrg if (req->present & XkbKeyTypesMask) { 2405806e81e9Smrg keytype = (xkbKeyTypeWireDesc *)(req + 1); 2406806e81e9Smrg for (i = 0; i < req->nTypes; i++) { 2407806e81e9Smrg _add_check_len(XkbPaddedSize(sz_xkbKeyTypeWireDesc)); 24085a112b11Smrg _add_check_len(keytype->nMapEntries 24095a112b11Smrg * sz_xkbKTSetMapEntryWireDesc); 24105a112b11Smrg preserve = keytype->preserve; 24115a112b11Smrg map_count = keytype->nMapEntries; 24125a112b11Smrg if (preserve) { 24135a112b11Smrg _add_check_len(map_count * sz_xkbModsWireDesc); 2414806e81e9Smrg } 24155a112b11Smrg keytype += 1; 24165a112b11Smrg keytype = (xkbKeyTypeWireDesc *) 24175a112b11Smrg ((xkbKTSetMapEntryWireDesc *)keytype + map_count); 24185a112b11Smrg if (preserve) 24195a112b11Smrg keytype = (xkbKeyTypeWireDesc *) 24205a112b11Smrg ((xkbModsWireDesc *)keytype + map_count); 2421806e81e9Smrg } 2422806e81e9Smrg } 2423806e81e9Smrg /* syms */ 2424806e81e9Smrg if (req->present & XkbKeySymsMask) { 2425806e81e9Smrg symmap = (xkbSymMapWireDesc *)((char *)req + len); 2426806e81e9Smrg for (i = 0; i < req->nKeySyms; i++) { 2427806e81e9Smrg _add_check_len(sz_xkbSymMapWireDesc); 2428806e81e9Smrg nSyms = symmap->nSyms; 2429806e81e9Smrg _add_check_len(nSyms*sizeof(CARD32)); 2430806e81e9Smrg symmap += 1; 2431806e81e9Smrg symmap = (xkbSymMapWireDesc *)((CARD32 *)symmap + nSyms); 2432806e81e9Smrg } 2433806e81e9Smrg } 2434806e81e9Smrg /* actions */ 2435806e81e9Smrg if (req->present & XkbKeyActionsMask) { 2436806e81e9Smrg _add_check_len(req->totalActs * sz_xkbActionWireDesc 2437806e81e9Smrg + XkbPaddedSize(req->nKeyActs)); 2438806e81e9Smrg } 2439806e81e9Smrg /* behaviours */ 2440806e81e9Smrg if (req->present & XkbKeyBehaviorsMask) { 2441806e81e9Smrg _add_check_len(req->totalKeyBehaviors * sz_xkbBehaviorWireDesc); 2442806e81e9Smrg } 2443806e81e9Smrg /* vmods */ 2444806e81e9Smrg if (req->present & XkbVirtualModsMask) { 2445806e81e9Smrg _add_check_len(XkbPaddedSize(Ones(req->virtualMods))); 2446806e81e9Smrg } 2447806e81e9Smrg /* explicit */ 2448806e81e9Smrg if (req->present & XkbExplicitComponentsMask) { 2449806e81e9Smrg /* two bytes per non-zero explicit componen */ 2450806e81e9Smrg _add_check_len(XkbPaddedSize(req->totalKeyExplicit * sizeof(CARD16))); 2451806e81e9Smrg } 2452806e81e9Smrg /* modmap */ 2453806e81e9Smrg if (req->present & XkbModifierMapMask) { 2454806e81e9Smrg /* two bytes per non-zero modmap component */ 2455806e81e9Smrg _add_check_len(XkbPaddedSize(req->totalModMapKeys * sizeof(CARD16))); 2456806e81e9Smrg } 2457806e81e9Smrg /* vmodmap */ 2458806e81e9Smrg if (req->present & XkbVirtualModMapMask) { 2459806e81e9Smrg _add_check_len(req->totalVModMapKeys * sz_xkbVModMapWireDesc); 2460806e81e9Smrg } 2461806e81e9Smrg if (len == req_len) 2462806e81e9Smrg return Success; 2463806e81e9Smrgbad: 2464806e81e9Smrg ErrorF("[xkb] BOGUS LENGTH in SetMap: expected %ld got %ld\n", 2465806e81e9Smrg len, req_len); 2466806e81e9Smrg return BadLength; 2467806e81e9Smrg} 2468806e81e9Smrg 2469806e81e9Smrg 24704642e01fSmrg/** 24714642e01fSmrg * Check if the given request can be applied to the given device but don't 24725a112b11Smrg * actually do anything, except swap values when client->swapped and doswap are both true. 24734642e01fSmrg */ 24744642e01fSmrgstatic int 2475f7df2e56Smrg_XkbSetMapChecks(ClientPtr client, DeviceIntPtr dev, xkbSetMapReq * req, 24765a112b11Smrg char *values, Bool doswap) 247705b261ecSmrg{ 2478f7df2e56Smrg XkbSrvInfoPtr xkbi; 2479f7df2e56Smrg XkbDescPtr xkb; 2480f7df2e56Smrg int error; 2481f7df2e56Smrg int nTypes = 0, nActions; 2482f7df2e56Smrg CARD8 mapWidths[XkbMaxLegalKeyCode + 1] = { 0 }; 2483f7df2e56Smrg CARD16 symsPerKey[XkbMaxLegalKeyCode + 1] = { 0 }; 2484f7df2e56Smrg XkbSymMapPtr map; 2485f7df2e56Smrg int i; 2486f7df2e56Smrg 24874e185dc0Smrg if (!dev->key) 24884e185dc0Smrg return 0; 24894e185dc0Smrg 2490f7df2e56Smrg xkbi = dev->key->xkbInfo; 249105b261ecSmrg xkb = xkbi->desc; 249205b261ecSmrg 2493f7df2e56Smrg if ((xkb->min_key_code != req->minKeyCode) || 24944642e01fSmrg (xkb->max_key_code != req->maxKeyCode)) { 24957e31ba66Smrg if (client->xkbClientFlags & _XkbClientIsAncient) { 24967e31ba66Smrg /* pre 1.0 versions of Xlib have a bug */ 2497f7df2e56Smrg req->minKeyCode = xkb->min_key_code; 2498f7df2e56Smrg req->maxKeyCode = xkb->max_key_code; 2499f7df2e56Smrg } 2500f7df2e56Smrg else { 2501f7df2e56Smrg if (!XkbIsLegalKeycode(req->minKeyCode)) { 2502f7df2e56Smrg client->errorValue = 2503f7df2e56Smrg _XkbErrCode3(2, req->minKeyCode, req->maxKeyCode); 2504f7df2e56Smrg return BadValue; 2505f7df2e56Smrg } 2506f7df2e56Smrg if (req->minKeyCode > req->maxKeyCode) { 2507f7df2e56Smrg client->errorValue = 2508f7df2e56Smrg _XkbErrCode3(3, req->minKeyCode, req->maxKeyCode); 2509f7df2e56Smrg return BadMatch; 2510f7df2e56Smrg } 2511f7df2e56Smrg } 251205b261ecSmrg } 251305b261ecSmrg 251490bea6a0Smrg /* nTypes/mapWidths/symsPerKey must be filled for further tests below, 251590bea6a0Smrg * regardless of client-side flags */ 251690bea6a0Smrg 251790bea6a0Smrg if (!CheckKeyTypes(client, xkb, req, (xkbKeyTypeWireDesc **) &values, 251890bea6a0Smrg &nTypes, mapWidths, doswap)) { 25195a112b11Smrg client->errorValue = nTypes; 25205a112b11Smrg return BadValue; 252105b261ecSmrg } 25229ace9065Smrg 25239ace9065Smrg map = &xkb->map->key_sym_map[xkb->min_key_code]; 2524f7df2e56Smrg for (i = xkb->min_key_code; i < xkb->max_key_code; i++, map++) { 2525f7df2e56Smrg register int g, ng, w; 2526f7df2e56Smrg 2527f7df2e56Smrg ng = XkbNumGroups(map->group_info); 2528f7df2e56Smrg for (w = g = 0; g < ng; g++) { 2529f7df2e56Smrg if (map->kt_index[g] >= (unsigned) nTypes) { 2530f7df2e56Smrg client->errorValue = _XkbErrCode4(0x13, i, g, map->kt_index[g]); 25315a112b11Smrg return BadValue; 2532f7df2e56Smrg } 2533f7df2e56Smrg if (mapWidths[map->kt_index[g]] > w) 2534f7df2e56Smrg w = mapWidths[map->kt_index[g]]; 2535f7df2e56Smrg } 2536f7df2e56Smrg symsPerKey[i] = w * ng; 25379ace9065Smrg } 25389ace9065Smrg 25394642e01fSmrg if ((req->present & XkbKeySymsMask) && 2540f7df2e56Smrg (!CheckKeySyms(client, xkb, req, nTypes, mapWidths, symsPerKey, 25415a112b11Smrg (xkbSymMapWireDesc **) &values, &error, doswap))) { 2542f7df2e56Smrg client->errorValue = error; 2543f7df2e56Smrg return BadValue; 254405b261ecSmrg } 254505b261ecSmrg 25464642e01fSmrg if ((req->present & XkbKeyActionsMask) && 2547f7df2e56Smrg (!CheckKeyActions(xkb, req, nTypes, mapWidths, symsPerKey, 2548f7df2e56Smrg (CARD8 **) &values, &nActions))) { 2549f7df2e56Smrg client->errorValue = nActions; 2550f7df2e56Smrg return BadValue; 255105b261ecSmrg } 255205b261ecSmrg 25534642e01fSmrg if ((req->present & XkbKeyBehaviorsMask) && 2554f7df2e56Smrg (!CheckKeyBehaviors 2555f7df2e56Smrg (xkb, req, (xkbBehaviorWireDesc **) &values, &error))) { 2556f7df2e56Smrg client->errorValue = error; 2557f7df2e56Smrg return BadValue; 255805b261ecSmrg } 255905b261ecSmrg 25604642e01fSmrg if ((req->present & XkbVirtualModsMask) && 2561f7df2e56Smrg (!CheckVirtualMods(xkb, req, (CARD8 **) &values, &error))) { 2562f7df2e56Smrg client->errorValue = error; 2563f7df2e56Smrg return BadValue; 256405b261ecSmrg } 2565f7df2e56Smrg if ((req->present & XkbExplicitComponentsMask) && 2566f7df2e56Smrg (!CheckKeyExplicit(xkb, req, (CARD8 **) &values, &error))) { 2567f7df2e56Smrg client->errorValue = error; 2568f7df2e56Smrg return BadValue; 256905b261ecSmrg } 2570f7df2e56Smrg if ((req->present & XkbModifierMapMask) && 2571f7df2e56Smrg (!CheckModifierMap(xkb, req, (CARD8 **) &values, &error))) { 2572f7df2e56Smrg client->errorValue = error; 2573f7df2e56Smrg return BadValue; 257405b261ecSmrg } 2575f7df2e56Smrg if ((req->present & XkbVirtualModMapMask) && 2576f7df2e56Smrg (!CheckVirtualModMap 2577f7df2e56Smrg (xkb, req, (xkbVModMapWireDesc **) &values, &error))) { 2578f7df2e56Smrg client->errorValue = error; 2579f7df2e56Smrg return BadValue; 258005b261ecSmrg } 25814642e01fSmrg 2582f7df2e56Smrg if (((values - ((char *) req)) / 4) != req->length) { 2583f7df2e56Smrg ErrorF("[xkb] Internal error! Bad length in XkbSetMap (after check)\n"); 2584f7df2e56Smrg client->errorValue = values - ((char *) &req[1]); 2585f7df2e56Smrg return BadLength; 258605b261ecSmrg } 25874642e01fSmrg 25884642e01fSmrg return Success; 25894642e01fSmrg} 25904642e01fSmrg 25914642e01fSmrg/** 25924642e01fSmrg * Apply the given request on the given device. 25934642e01fSmrg */ 25944642e01fSmrgstatic int 2595f7df2e56Smrg_XkbSetMap(ClientPtr client, DeviceIntPtr dev, xkbSetMapReq * req, char *values) 25964642e01fSmrg{ 2597f7df2e56Smrg XkbEventCauseRec cause; 2598f7df2e56Smrg XkbChangesRec change; 2599f7df2e56Smrg Bool sentNKN; 2600f7df2e56Smrg XkbSrvInfoPtr xkbi; 2601f7df2e56Smrg XkbDescPtr xkb; 26024642e01fSmrg 26034e185dc0Smrg if (!dev->key) 26044e185dc0Smrg return Success; 26054e185dc0Smrg 2606f7df2e56Smrg xkbi = dev->key->xkbInfo; 26074642e01fSmrg xkb = xkbi->desc; 26084642e01fSmrg 2609f7df2e56Smrg XkbSetCauseXkbReq(&cause, X_kbSetMap, client); 26106747b715Smrg memset(&change, 0, sizeof(change)); 26116747b715Smrg sentNKN = FALSE; 2612f7df2e56Smrg if ((xkb->min_key_code != req->minKeyCode) || 2613f7df2e56Smrg (xkb->max_key_code != req->maxKeyCode)) { 2614f7df2e56Smrg Status status; 2615f7df2e56Smrg xkbNewKeyboardNotify nkn; 2616f7df2e56Smrg 2617f7df2e56Smrg nkn.deviceID = nkn.oldDeviceID = dev->id; 2618f7df2e56Smrg nkn.oldMinKeyCode = xkb->min_key_code; 2619f7df2e56Smrg nkn.oldMaxKeyCode = xkb->max_key_code; 2620f7df2e56Smrg status = XkbChangeKeycodeRange(xkb, req->minKeyCode, 2621f7df2e56Smrg req->maxKeyCode, &change); 2622f7df2e56Smrg if (status != Success) 2623f7df2e56Smrg return status; /* oh-oh. what about the other keyboards? */ 2624f7df2e56Smrg nkn.minKeyCode = xkb->min_key_code; 2625f7df2e56Smrg nkn.maxKeyCode = xkb->max_key_code; 2626f7df2e56Smrg nkn.requestMajor = XkbReqCode; 2627f7df2e56Smrg nkn.requestMinor = X_kbSetMap; 2628f7df2e56Smrg nkn.changed = XkbNKN_KeycodesMask; 2629f7df2e56Smrg XkbSendNewKeyboardNotify(dev, &nkn); 2630f7df2e56Smrg sentNKN = TRUE; 2631f7df2e56Smrg } 2632f7df2e56Smrg 2633f7df2e56Smrg if (req->present & XkbKeyTypesMask) { 2634f7df2e56Smrg values = SetKeyTypes(xkb, req, (xkbKeyTypeWireDesc *) values, &change); 2635f7df2e56Smrg if (!values) 2636f7df2e56Smrg goto allocFailure; 2637f7df2e56Smrg } 2638f7df2e56Smrg if (req->present & XkbKeySymsMask) { 2639f7df2e56Smrg values = 2640f7df2e56Smrg SetKeySyms(client, xkb, req, (xkbSymMapWireDesc *) values, &change, 2641f7df2e56Smrg dev); 2642f7df2e56Smrg if (!values) 2643f7df2e56Smrg goto allocFailure; 2644f7df2e56Smrg } 2645f7df2e56Smrg if (req->present & XkbKeyActionsMask) { 2646f7df2e56Smrg values = SetKeyActions(xkb, req, (CARD8 *) values, &change); 2647f7df2e56Smrg if (!values) 2648f7df2e56Smrg goto allocFailure; 2649f7df2e56Smrg } 2650f7df2e56Smrg if (req->present & XkbKeyBehaviorsMask) { 2651f7df2e56Smrg values = 2652f7df2e56Smrg SetKeyBehaviors(xkbi, req, (xkbBehaviorWireDesc *) values, &change); 2653f7df2e56Smrg if (!values) 2654f7df2e56Smrg goto allocFailure; 2655f7df2e56Smrg } 2656f7df2e56Smrg if (req->present & XkbVirtualModsMask) 2657f7df2e56Smrg values = SetVirtualMods(xkbi, req, (CARD8 *) values, &change); 2658f7df2e56Smrg if (req->present & XkbExplicitComponentsMask) 2659f7df2e56Smrg values = SetKeyExplicit(xkbi, req, (CARD8 *) values, &change); 2660f7df2e56Smrg if (req->present & XkbModifierMapMask) 2661f7df2e56Smrg values = SetModifierMap(xkbi, req, (CARD8 *) values, &change); 2662f7df2e56Smrg if (req->present & XkbVirtualModMapMask) 2663f7df2e56Smrg values = 2664f7df2e56Smrg SetVirtualModMap(xkbi, req, (xkbVModMapWireDesc *) values, &change); 2665f7df2e56Smrg if (((values - ((char *) req)) / 4) != req->length) { 2666f7df2e56Smrg ErrorF("[xkb] Internal error! Bad length in XkbSetMap (after set)\n"); 2667f7df2e56Smrg client->errorValue = values - ((char *) &req[1]); 2668f7df2e56Smrg return BadLength; 2669f7df2e56Smrg } 2670f7df2e56Smrg if (req->flags & XkbSetMapRecomputeActions) { 2671f7df2e56Smrg KeyCode first, last, firstMM, lastMM; 2672f7df2e56Smrg 2673f7df2e56Smrg if (change.map.num_key_syms > 0) { 2674f7df2e56Smrg first = change.map.first_key_sym; 2675f7df2e56Smrg last = first + change.map.num_key_syms - 1; 2676f7df2e56Smrg } 2677f7df2e56Smrg else 2678f7df2e56Smrg first = last = 0; 2679f7df2e56Smrg if (change.map.num_modmap_keys > 0) { 2680f7df2e56Smrg firstMM = change.map.first_modmap_key; 26817e31ba66Smrg lastMM = firstMM + change.map.num_modmap_keys - 1; 2682f7df2e56Smrg } 2683f7df2e56Smrg else 2684f7df2e56Smrg firstMM = lastMM = 0; 2685f7df2e56Smrg if ((last > 0) && (lastMM > 0)) { 2686f7df2e56Smrg if (firstMM < first) 2687f7df2e56Smrg first = firstMM; 2688f7df2e56Smrg if (lastMM > last) 2689f7df2e56Smrg last = lastMM; 2690f7df2e56Smrg } 2691f7df2e56Smrg else if (lastMM > 0) { 2692f7df2e56Smrg first = firstMM; 2693f7df2e56Smrg last = lastMM; 2694f7df2e56Smrg } 2695f7df2e56Smrg if (last > 0) { 2696f7df2e56Smrg unsigned check = 0; 2697f7df2e56Smrg 2698f7df2e56Smrg XkbUpdateActions(dev, first, (last - first + 1), &change, &check, 2699f7df2e56Smrg &cause); 2700f7df2e56Smrg if (check) 2701f7df2e56Smrg XkbCheckSecondaryEffects(xkbi, check, &change, &cause); 2702f7df2e56Smrg } 270305b261ecSmrg } 270405b261ecSmrg if (!sentNKN) 2705f7df2e56Smrg XkbSendNotification(dev, &change, &cause); 270605b261ecSmrg 27074642e01fSmrg return Success; 2708f7df2e56Smrg allocFailure: 270905b261ecSmrg return BadAlloc; 271005b261ecSmrg} 271105b261ecSmrg 27124642e01fSmrgint 27134642e01fSmrgProcXkbSetMap(ClientPtr client) 27144642e01fSmrg{ 27155a112b11Smrg DeviceIntPtr dev, master; 2716f7df2e56Smrg char *tmp; 2717f7df2e56Smrg int rc; 27184642e01fSmrg 27194642e01fSmrg REQUEST(xkbSetMapReq); 27204642e01fSmrg REQUEST_AT_LEAST_SIZE(xkbSetMapReq); 27214642e01fSmrg 2722f7df2e56Smrg if (!(client->xkbClientFlags & _XkbClientInitialized)) 2723f7df2e56Smrg return BadAccess; 27244642e01fSmrg 27254642e01fSmrg CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess); 2726f7df2e56Smrg CHK_MASK_LEGAL(0x01, stuff->present, XkbAllMapComponentsMask); 27274642e01fSmrg 2728806e81e9Smrg /* first verify the request length carefully */ 2729806e81e9Smrg rc = _XkbSetMapCheckLength(stuff); 2730806e81e9Smrg if (rc != Success) 2731806e81e9Smrg return rc; 2732806e81e9Smrg 2733f7df2e56Smrg tmp = (char *) &stuff[1]; 27344642e01fSmrg 27354642e01fSmrg /* Check if we can to the SetMap on the requested device. If this 27364642e01fSmrg succeeds, do the same thing for all extension devices (if needed). 27374642e01fSmrg If any of them fails, fail. */ 27385a112b11Smrg rc = _XkbSetMapChecks(client, dev, stuff, tmp, TRUE); 27394642e01fSmrg 27404642e01fSmrg if (rc != Success) 27414642e01fSmrg return rc; 27424642e01fSmrg 27435a112b11Smrg master = GetMaster(dev, MASTER_KEYBOARD); 27447e31ba66Smrg 2745f7df2e56Smrg if (stuff->deviceSpec == XkbUseCoreKbd) { 27464642e01fSmrg DeviceIntPtr other; 2747f7df2e56Smrg 2748f7df2e56Smrg for (other = inputInfo.devices; other; other = other->next) { 2749f7df2e56Smrg if ((other != dev) && other->key && !IsMaster(other) && 2750f7df2e56Smrg GetMaster(other, MASTER_KEYBOARD) == dev) { 2751f7df2e56Smrg rc = XaceHook(XACE_DEVICE_ACCESS, client, other, 2752f7df2e56Smrg DixManageAccess); 2753f7df2e56Smrg if (rc == Success) { 27545a112b11Smrg rc = _XkbSetMapChecks(client, other, stuff, tmp, FALSE); 27554642e01fSmrg if (rc != Success) 27564642e01fSmrg return rc; 27574642e01fSmrg } 27584642e01fSmrg } 27594642e01fSmrg } 27607e31ba66Smrg } else { 27617e31ba66Smrg DeviceIntPtr other; 27627e31ba66Smrg 27637e31ba66Smrg for (other = inputInfo.devices; other; other = other->next) { 27647e31ba66Smrg if (other != dev && GetMaster(other, MASTER_KEYBOARD) != dev && 27657e31ba66Smrg (other != master || dev != master->lastSlave)) 27667e31ba66Smrg continue; 27677e31ba66Smrg 27685a112b11Smrg rc = _XkbSetMapChecks(client, other, stuff, tmp, FALSE); 27697e31ba66Smrg if (rc != Success) 27707e31ba66Smrg return rc; 27717e31ba66Smrg } 27724642e01fSmrg } 27734642e01fSmrg 27747e31ba66Smrg /* We know now that we will succeed with the SetMap. In theory anyway. */ 27754642e01fSmrg rc = _XkbSetMap(client, dev, stuff, tmp); 27764642e01fSmrg if (rc != Success) 27774642e01fSmrg return rc; 27784642e01fSmrg 2779f7df2e56Smrg if (stuff->deviceSpec == XkbUseCoreKbd) { 27804642e01fSmrg DeviceIntPtr other; 2781f7df2e56Smrg 2782f7df2e56Smrg for (other = inputInfo.devices; other; other = other->next) { 2783f7df2e56Smrg if ((other != dev) && other->key && !IsMaster(other) && 2784f7df2e56Smrg GetMaster(other, MASTER_KEYBOARD) == dev) { 2785f7df2e56Smrg rc = XaceHook(XACE_DEVICE_ACCESS, client, other, 2786f7df2e56Smrg DixManageAccess); 27874642e01fSmrg if (rc == Success) 27884642e01fSmrg _XkbSetMap(client, other, stuff, tmp); 27894642e01fSmrg /* ignore rc. if the SetMap failed although the check above 27904642e01fSmrg reported true there isn't much we can do. we still need to 27914642e01fSmrg set all other devices, hoping that at least they stay in 27924642e01fSmrg sync. */ 27934642e01fSmrg } 27944642e01fSmrg } 27957e31ba66Smrg } else { 27967e31ba66Smrg DeviceIntPtr other; 27977e31ba66Smrg 27987e31ba66Smrg for (other = inputInfo.devices; other; other = other->next) { 27997e31ba66Smrg if (other != dev && GetMaster(other, MASTER_KEYBOARD) != dev && 28007e31ba66Smrg (other != master || dev != master->lastSlave)) 28017e31ba66Smrg continue; 28027e31ba66Smrg 28037e31ba66Smrg _XkbSetMap(client, other, stuff, tmp); //ignore rc 28047e31ba66Smrg } 28054642e01fSmrg } 28064642e01fSmrg 28076747b715Smrg return Success; 28084642e01fSmrg} 28094642e01fSmrg 281005b261ecSmrg/***====================================================================***/ 281105b261ecSmrg 281205b261ecSmrgstatic Status 2813f7df2e56SmrgXkbComputeGetCompatMapReplySize(XkbCompatMapPtr compat, 2814f7df2e56Smrg xkbGetCompatMapReply * rep) 281505b261ecSmrg{ 2816f7df2e56Smrg unsigned size, nGroups; 2817f7df2e56Smrg 2818f7df2e56Smrg nGroups = 0; 2819f7df2e56Smrg if (rep->groups != 0) { 2820f7df2e56Smrg register int i, bit; 2821f7df2e56Smrg 2822f7df2e56Smrg for (i = 0, bit = 1; i < XkbNumKbdGroups; i++, bit <<= 1) { 2823f7df2e56Smrg if (rep->groups & bit) 2824f7df2e56Smrg nGroups++; 2825f7df2e56Smrg } 2826f7df2e56Smrg } 2827f7df2e56Smrg size = nGroups * SIZEOF(xkbModsWireDesc); 2828f7df2e56Smrg size += (rep->nSI * SIZEOF(xkbSymInterpretWireDesc)); 2829f7df2e56Smrg rep->length = size / 4; 283005b261ecSmrg return Success; 283105b261ecSmrg} 283205b261ecSmrg 283305b261ecSmrgstatic int 2834f7df2e56SmrgXkbSendCompatMap(ClientPtr client, 2835f7df2e56Smrg XkbCompatMapPtr compat, xkbGetCompatMapReply * rep) 283605b261ecSmrg{ 2837f7df2e56Smrg char *data; 2838f7df2e56Smrg int size; 2839f7df2e56Smrg 2840f7df2e56Smrg if (rep->length > 0) { 2841f7df2e56Smrg data = xallocarray(rep->length, 4); 2842f7df2e56Smrg if (data) { 2843f7df2e56Smrg register unsigned i, bit; 2844f7df2e56Smrg xkbModsWireDesc *grp; 2845f7df2e56Smrg XkbSymInterpretPtr sym = &compat->sym_interpret[rep->firstSI]; 2846f7df2e56Smrg xkbSymInterpretWireDesc *wire = (xkbSymInterpretWireDesc *) data; 2847f7df2e56Smrg 2848f7df2e56Smrg size = rep->length * 4; 2849f7df2e56Smrg 2850f7df2e56Smrg for (i = 0; i < rep->nSI; i++, sym++, wire++) { 2851f7df2e56Smrg wire->sym = sym->sym; 2852f7df2e56Smrg wire->mods = sym->mods; 2853f7df2e56Smrg wire->match = sym->match; 2854f7df2e56Smrg wire->virtualMod = sym->virtual_mod; 2855f7df2e56Smrg wire->flags = sym->flags; 2856f7df2e56Smrg memcpy((char *) &wire->act, (char *) &sym->act, 2857f7df2e56Smrg sz_xkbActionWireDesc); 2858f7df2e56Smrg if (client->swapped) { 2859f7df2e56Smrg swapl(&wire->sym); 2860f7df2e56Smrg } 2861f7df2e56Smrg } 2862f7df2e56Smrg if (rep->groups) { 2863f7df2e56Smrg grp = (xkbModsWireDesc *) wire; 2864f7df2e56Smrg for (i = 0, bit = 1; i < XkbNumKbdGroups; i++, bit <<= 1) { 2865f7df2e56Smrg if (rep->groups & bit) { 2866f7df2e56Smrg grp->mask = compat->groups[i].mask; 2867f7df2e56Smrg grp->realMods = compat->groups[i].real_mods; 2868f7df2e56Smrg grp->virtualMods = compat->groups[i].vmods; 2869f7df2e56Smrg if (client->swapped) { 2870f7df2e56Smrg swaps(&grp->virtualMods); 2871f7df2e56Smrg } 2872f7df2e56Smrg grp++; 2873f7df2e56Smrg } 2874f7df2e56Smrg } 2875f7df2e56Smrg wire = (xkbSymInterpretWireDesc *) grp; 2876f7df2e56Smrg } 2877f7df2e56Smrg } 2878f7df2e56Smrg else 2879f7df2e56Smrg return BadAlloc; 2880f7df2e56Smrg } 2881f7df2e56Smrg else 2882f7df2e56Smrg data = NULL; 288305b261ecSmrg 288405b261ecSmrg if (client->swapped) { 2885f7df2e56Smrg swaps(&rep->sequenceNumber); 2886f7df2e56Smrg swapl(&rep->length); 2887f7df2e56Smrg swaps(&rep->firstSI); 2888f7df2e56Smrg swaps(&rep->nSI); 2889f7df2e56Smrg swaps(&rep->nTotalSI); 289005b261ecSmrg } 289105b261ecSmrg 2892f7df2e56Smrg WriteToClient(client, SIZEOF(xkbGetCompatMapReply), rep); 289305b261ecSmrg if (data) { 2894f7df2e56Smrg WriteToClient(client, size, data); 2895f7df2e56Smrg free((char *) data); 289605b261ecSmrg } 28976747b715Smrg return Success; 289805b261ecSmrg} 289905b261ecSmrg 290005b261ecSmrgint 290105b261ecSmrgProcXkbGetCompatMap(ClientPtr client) 290205b261ecSmrg{ 2903f7df2e56Smrg xkbGetCompatMapReply rep; 2904f7df2e56Smrg DeviceIntPtr dev; 2905f7df2e56Smrg XkbDescPtr xkb; 2906f7df2e56Smrg XkbCompatMapPtr compat; 290705b261ecSmrg 290805b261ecSmrg REQUEST(xkbGetCompatMapReq); 290905b261ecSmrg REQUEST_SIZE_MATCH(xkbGetCompatMapReq); 291005b261ecSmrg 2911f7df2e56Smrg if (!(client->xkbClientFlags & _XkbClientInitialized)) 2912f7df2e56Smrg return BadAccess; 291305b261ecSmrg 29144642e01fSmrg CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess); 291505b261ecSmrg 291605b261ecSmrg xkb = dev->key->xkbInfo->desc; 2917f7df2e56Smrg compat = xkb->compat; 291805b261ecSmrg 2919f7df2e56Smrg rep = (xkbGetCompatMapReply) { 2920f7df2e56Smrg .type = X_Reply, 2921f7df2e56Smrg .sequenceNumber = client->sequence, 2922f7df2e56Smrg .length = 0, 2923f7df2e56Smrg .deviceID = dev->id, 2924f7df2e56Smrg .firstSI = stuff->firstSI, 2925f7df2e56Smrg .nSI = stuff->nSI 2926f7df2e56Smrg }; 292705b261ecSmrg if (stuff->getAllSI) { 2928f7df2e56Smrg rep.firstSI = 0; 2929f7df2e56Smrg rep.nSI = compat->num_si; 293005b261ecSmrg } 2931f7df2e56Smrg else if ((((unsigned) stuff->nSI) > 0) && 2932f7df2e56Smrg ((unsigned) (stuff->firstSI + stuff->nSI - 1) >= compat->num_si)) { 2933f7df2e56Smrg client->errorValue = _XkbErrCode2(0x05, compat->num_si); 2934f7df2e56Smrg return BadValue; 293505b261ecSmrg } 293605b261ecSmrg rep.nTotalSI = compat->num_si; 2937f7df2e56Smrg rep.groups = stuff->groups; 2938f7df2e56Smrg XkbComputeGetCompatMapReplySize(compat, &rep); 2939f7df2e56Smrg return XkbSendCompatMap(client, compat, &rep); 294005b261ecSmrg} 294105b261ecSmrg 29424642e01fSmrg/** 29434642e01fSmrg * Apply the given request on the given device. 29446747b715Smrg * If dryRun is TRUE, then value checks are performed, but the device isn't 29454642e01fSmrg * modified. 29464642e01fSmrg */ 29474642e01fSmrgstatic int 29484642e01fSmrg_XkbSetCompatMap(ClientPtr client, DeviceIntPtr dev, 2949f7df2e56Smrg xkbSetCompatMapReq * req, char *data, BOOL dryRun) 295005b261ecSmrg{ 2951f7df2e56Smrg XkbSrvInfoPtr xkbi; 2952f7df2e56Smrg XkbDescPtr xkb; 2953f7df2e56Smrg XkbCompatMapPtr compat; 2954f7df2e56Smrg int nGroups; 2955f7df2e56Smrg unsigned i, bit; 295605b261ecSmrg 295705b261ecSmrg xkbi = dev->key->xkbInfo; 29584642e01fSmrg xkb = xkbi->desc; 29594642e01fSmrg compat = xkb->compat; 29604642e01fSmrg 2961f7df2e56Smrg if ((req->nSI > 0) || (req->truncateSI)) { 2962f7df2e56Smrg xkbSymInterpretWireDesc *wire; 2963f7df2e56Smrg 2964f7df2e56Smrg if (req->firstSI > compat->num_si) { 2965f7df2e56Smrg client->errorValue = _XkbErrCode2(0x02, compat->num_si); 2966f7df2e56Smrg return BadValue; 2967f7df2e56Smrg } 2968f7df2e56Smrg wire = (xkbSymInterpretWireDesc *) data; 2969f7df2e56Smrg wire += req->nSI; 2970f7df2e56Smrg data = (char *) wire; 297105b261ecSmrg } 29724642e01fSmrg 2973f7df2e56Smrg nGroups = 0; 2974f7df2e56Smrg if (req->groups != 0) { 2975f7df2e56Smrg for (i = 0, bit = 1; i < XkbNumKbdGroups; i++, bit <<= 1) { 2976f7df2e56Smrg if (req->groups & bit) 2977f7df2e56Smrg nGroups++; 2978f7df2e56Smrg } 297905b261ecSmrg } 2980f7df2e56Smrg data += nGroups * SIZEOF(xkbModsWireDesc); 2981f7df2e56Smrg if (((data - ((char *) req)) / 4) != req->length) { 2982f7df2e56Smrg return BadLength; 298305b261ecSmrg } 29844642e01fSmrg 29854642e01fSmrg /* Done all the checks we can do */ 29864642e01fSmrg if (dryRun) 29874642e01fSmrg return Success; 29884642e01fSmrg 2989f7df2e56Smrg data = (char *) &req[1]; 2990f7df2e56Smrg if (req->nSI > 0) { 2991f7df2e56Smrg xkbSymInterpretWireDesc *wire = (xkbSymInterpretWireDesc *) data; 2992f7df2e56Smrg XkbSymInterpretPtr sym; 2993f7df2e56Smrg unsigned int skipped = 0; 2994f7df2e56Smrg 299559ca590cSmrg if ((unsigned) (req->firstSI + req->nSI) > compat->size_si) { 299659ca590cSmrg compat->num_si = compat->size_si = req->firstSI + req->nSI; 2997f7df2e56Smrg compat->sym_interpret = reallocarray(compat->sym_interpret, 299859ca590cSmrg compat->size_si, 2999f7df2e56Smrg sizeof(XkbSymInterpretRec)); 3000f7df2e56Smrg if (!compat->sym_interpret) { 300159ca590cSmrg compat->num_si = compat->size_si = 0; 3002f7df2e56Smrg return BadAlloc; 3003f7df2e56Smrg } 3004f7df2e56Smrg } 3005f7df2e56Smrg else if (req->truncateSI) { 3006f7df2e56Smrg compat->num_si = req->firstSI + req->nSI; 3007f7df2e56Smrg } 3008f7df2e56Smrg sym = &compat->sym_interpret[req->firstSI]; 3009f7df2e56Smrg for (i = 0; i < req->nSI; i++, wire++) { 3010f7df2e56Smrg if (client->swapped) { 3011f7df2e56Smrg swapl(&wire->sym); 3012f7df2e56Smrg } 3013f7df2e56Smrg if (wire->sym == NoSymbol && wire->match == XkbSI_AnyOfOrNone && 3014f7df2e56Smrg (wire->mods & 0xff) == 0xff && 3015f7df2e56Smrg wire->act.type == XkbSA_XFree86Private) { 3016f7df2e56Smrg ErrorF("XKB: Skipping broken Any+AnyOfOrNone(All) -> Private " 3017f7df2e56Smrg "action from client\n"); 3018f7df2e56Smrg skipped++; 3019f7df2e56Smrg continue; 3020f7df2e56Smrg } 3021f7df2e56Smrg sym->sym = wire->sym; 3022f7df2e56Smrg sym->mods = wire->mods; 3023f7df2e56Smrg sym->match = wire->match; 3024f7df2e56Smrg sym->flags = wire->flags; 3025f7df2e56Smrg sym->virtual_mod = wire->virtualMod; 3026f7df2e56Smrg memcpy((char *) &sym->act, (char *) &wire->act, 3027f7df2e56Smrg SIZEOF(xkbActionWireDesc)); 3028f7df2e56Smrg sym++; 3029f7df2e56Smrg } 3030f7df2e56Smrg if (skipped) { 3031f7df2e56Smrg if (req->firstSI + req->nSI < compat->num_si) 3032f7df2e56Smrg memmove(sym, sym + skipped, 3033f7df2e56Smrg (compat->num_si - req->firstSI - req->nSI) * 3034f7df2e56Smrg sizeof(*sym)); 3035f7df2e56Smrg compat->num_si -= skipped; 3036f7df2e56Smrg } 3037f7df2e56Smrg data = (char *) wire; 303805b261ecSmrg } 30394642e01fSmrg else if (req->truncateSI) { 3040f7df2e56Smrg compat->num_si = req->firstSI; 3041f7df2e56Smrg } 3042f7df2e56Smrg 3043f7df2e56Smrg if (req->groups != 0) { 3044f7df2e56Smrg xkbModsWireDesc *wire = (xkbModsWireDesc *) data; 3045f7df2e56Smrg 3046f7df2e56Smrg for (i = 0, bit = 1; i < XkbNumKbdGroups; i++, bit <<= 1) { 3047f7df2e56Smrg if (req->groups & bit) { 3048f7df2e56Smrg if (client->swapped) { 3049f7df2e56Smrg swaps(&wire->virtualMods); 3050f7df2e56Smrg } 3051f7df2e56Smrg compat->groups[i].mask = wire->realMods; 3052f7df2e56Smrg compat->groups[i].real_mods = wire->realMods; 3053f7df2e56Smrg compat->groups[i].vmods = wire->virtualMods; 3054f7df2e56Smrg if (wire->virtualMods != 0) { 3055f7df2e56Smrg unsigned tmp; 3056f7df2e56Smrg 3057f7df2e56Smrg tmp = XkbMaskForVMask(xkb, wire->virtualMods); 3058f7df2e56Smrg compat->groups[i].mask |= tmp; 3059f7df2e56Smrg } 3060f7df2e56Smrg data += SIZEOF(xkbModsWireDesc); 3061f7df2e56Smrg wire = (xkbModsWireDesc *) data; 3062f7df2e56Smrg } 3063f7df2e56Smrg } 3064f7df2e56Smrg } 3065f7df2e56Smrg i = XkbPaddedSize((data - ((char *) req))); 3066f7df2e56Smrg if ((i / 4) != req->length) { 3067f7df2e56Smrg ErrorF("[xkb] Internal length error on read in _XkbSetCompatMap\n"); 3068f7df2e56Smrg return BadLength; 306905b261ecSmrg } 30704642e01fSmrg 307105b261ecSmrg if (dev->xkb_interest) { 3072f7df2e56Smrg xkbCompatMapNotify ev; 3073f7df2e56Smrg 3074f7df2e56Smrg ev.deviceID = dev->id; 3075f7df2e56Smrg ev.changedGroups = req->groups; 3076f7df2e56Smrg ev.firstSI = req->firstSI; 3077f7df2e56Smrg ev.nSI = req->nSI; 3078f7df2e56Smrg ev.nTotalSI = compat->num_si; 3079f7df2e56Smrg XkbSendCompatMapNotify(dev, &ev); 308005b261ecSmrg } 308105b261ecSmrg 30824642e01fSmrg if (req->recomputeActions) { 3083f7df2e56Smrg XkbChangesRec change; 3084f7df2e56Smrg unsigned check; 3085f7df2e56Smrg XkbEventCauseRec cause; 3086f7df2e56Smrg 3087f7df2e56Smrg XkbSetCauseXkbReq(&cause, X_kbSetCompatMap, client); 3088f7df2e56Smrg memset(&change, 0, sizeof(XkbChangesRec)); 3089f7df2e56Smrg XkbUpdateActions(dev, xkb->min_key_code, XkbNumKeys(xkb), &change, 3090f7df2e56Smrg &check, &cause); 3091f7df2e56Smrg if (check) 3092f7df2e56Smrg XkbCheckSecondaryEffects(xkbi, check, &change, &cause); 3093f7df2e56Smrg XkbSendNotification(dev, &change, &cause); 309405b261ecSmrg } 30954642e01fSmrg return Success; 30964642e01fSmrg} 30974642e01fSmrg 30984642e01fSmrgint 30994642e01fSmrgProcXkbSetCompatMap(ClientPtr client) 31004642e01fSmrg{ 3101f7df2e56Smrg DeviceIntPtr dev; 3102f7df2e56Smrg char *data; 3103f7df2e56Smrg int rc; 31044642e01fSmrg 31054642e01fSmrg REQUEST(xkbSetCompatMapReq); 31064642e01fSmrg REQUEST_AT_LEAST_SIZE(xkbSetCompatMapReq); 31074642e01fSmrg 3108f7df2e56Smrg if (!(client->xkbClientFlags & _XkbClientInitialized)) 3109f7df2e56Smrg return BadAccess; 31104642e01fSmrg 31114642e01fSmrg CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess); 31124642e01fSmrg 3113f7df2e56Smrg data = (char *) &stuff[1]; 31144642e01fSmrg 31154642e01fSmrg /* check first using a dry-run */ 31164642e01fSmrg rc = _XkbSetCompatMap(client, dev, stuff, data, TRUE); 31174642e01fSmrg if (rc != Success) 31184642e01fSmrg return rc; 3119f7df2e56Smrg if (stuff->deviceSpec == XkbUseCoreKbd) { 31204642e01fSmrg DeviceIntPtr other; 3121f7df2e56Smrg 3122f7df2e56Smrg for (other = inputInfo.devices; other; other = other->next) { 3123f7df2e56Smrg if ((other != dev) && other->key && !IsMaster(other) && 3124f7df2e56Smrg GetMaster(other, MASTER_KEYBOARD) == dev) { 3125f7df2e56Smrg rc = XaceHook(XACE_DEVICE_ACCESS, client, other, 3126f7df2e56Smrg DixManageAccess); 3127f7df2e56Smrg if (rc == Success) { 31284642e01fSmrg /* dry-run */ 31294642e01fSmrg rc = _XkbSetCompatMap(client, other, stuff, data, TRUE); 31304642e01fSmrg if (rc != Success) 31314642e01fSmrg return rc; 31324642e01fSmrg } 31334642e01fSmrg } 31344642e01fSmrg } 31354642e01fSmrg } 31364642e01fSmrg 31374642e01fSmrg /* Yay, the dry-runs succeed. Let's apply */ 31384642e01fSmrg rc = _XkbSetCompatMap(client, dev, stuff, data, FALSE); 31394642e01fSmrg if (rc != Success) 31404642e01fSmrg return rc; 3141f7df2e56Smrg if (stuff->deviceSpec == XkbUseCoreKbd) { 31424642e01fSmrg DeviceIntPtr other; 3143f7df2e56Smrg 3144f7df2e56Smrg for (other = inputInfo.devices; other; other = other->next) { 3145f7df2e56Smrg if ((other != dev) && other->key && !IsMaster(other) && 3146f7df2e56Smrg GetMaster(other, MASTER_KEYBOARD) == dev) { 3147f7df2e56Smrg rc = XaceHook(XACE_DEVICE_ACCESS, client, other, 3148f7df2e56Smrg DixManageAccess); 3149f7df2e56Smrg if (rc == Success) { 31504642e01fSmrg rc = _XkbSetCompatMap(client, other, stuff, data, FALSE); 31514642e01fSmrg if (rc != Success) 31524642e01fSmrg return rc; 31534642e01fSmrg } 31544642e01fSmrg } 31554642e01fSmrg } 31564642e01fSmrg } 31574642e01fSmrg 31586747b715Smrg return Success; 315905b261ecSmrg} 316005b261ecSmrg 316105b261ecSmrg/***====================================================================***/ 316205b261ecSmrg 316305b261ecSmrgint 316405b261ecSmrgProcXkbGetIndicatorState(ClientPtr client) 316505b261ecSmrg{ 3166f7df2e56Smrg xkbGetIndicatorStateReply rep; 3167f7df2e56Smrg XkbSrvLedInfoPtr sli; 3168f7df2e56Smrg DeviceIntPtr dev; 316905b261ecSmrg 317005b261ecSmrg REQUEST(xkbGetIndicatorStateReq); 317105b261ecSmrg REQUEST_SIZE_MATCH(xkbGetIndicatorStateReq); 317205b261ecSmrg 3173f7df2e56Smrg if (!(client->xkbClientFlags & _XkbClientInitialized)) 3174f7df2e56Smrg return BadAccess; 317505b261ecSmrg 31764642e01fSmrg CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixReadAccess); 317705b261ecSmrg 3178f7df2e56Smrg sli = XkbFindSrvLedInfo(dev, XkbDfltXIClass, XkbDfltXIId, 3179f7df2e56Smrg XkbXI_IndicatorStateMask); 318005b261ecSmrg if (!sli) 3181f7df2e56Smrg return BadAlloc; 318205b261ecSmrg 3183f7df2e56Smrg rep = (xkbGetIndicatorStateReply) { 3184f7df2e56Smrg .type = X_Reply, 3185f7df2e56Smrg .deviceID = dev->id, 3186f7df2e56Smrg .sequenceNumber = client->sequence, 3187f7df2e56Smrg .length = 0, 3188f7df2e56Smrg .state = sli->effectiveState 3189f7df2e56Smrg }; 319005b261ecSmrg 319105b261ecSmrg if (client->swapped) { 3192f7df2e56Smrg swaps(&rep.sequenceNumber); 3193f7df2e56Smrg swapl(&rep.state); 319405b261ecSmrg } 3195f7df2e56Smrg WriteToClient(client, SIZEOF(xkbGetIndicatorStateReply), &rep); 31966747b715Smrg return Success; 319705b261ecSmrg} 319805b261ecSmrg 319905b261ecSmrg/***====================================================================***/ 320005b261ecSmrg 320105b261ecSmrgstatic Status 3202f7df2e56SmrgXkbComputeGetIndicatorMapReplySize(XkbIndicatorPtr indicators, 3203f7df2e56Smrg xkbGetIndicatorMapReply * rep) 320405b261ecSmrg{ 3205f7df2e56Smrg register int i, bit; 3206f7df2e56Smrg int nIndicators; 320705b261ecSmrg 320805b261ecSmrg rep->realIndicators = indicators->phys_indicators; 3209f7df2e56Smrg for (i = nIndicators = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) { 3210f7df2e56Smrg if (rep->which & bit) 3211f7df2e56Smrg nIndicators++; 321205b261ecSmrg } 3213f7df2e56Smrg rep->length = (nIndicators * SIZEOF(xkbIndicatorMapWireDesc)) / 4; 3214f7df2e56Smrg rep->nIndicators = nIndicators; 321505b261ecSmrg return Success; 321605b261ecSmrg} 321705b261ecSmrg 321805b261ecSmrgstatic int 3219f7df2e56SmrgXkbSendIndicatorMap(ClientPtr client, 3220f7df2e56Smrg XkbIndicatorPtr indicators, xkbGetIndicatorMapReply * rep) 322105b261ecSmrg{ 3222f7df2e56Smrg int length; 3223f7df2e56Smrg CARD8 *map; 3224f7df2e56Smrg register int i; 3225f7df2e56Smrg register unsigned bit; 3226f7df2e56Smrg 3227f7df2e56Smrg if (rep->length > 0) { 3228f7df2e56Smrg CARD8 *to; 3229f7df2e56Smrg 3230f7df2e56Smrg to = map = xallocarray(rep->length, 4); 3231f7df2e56Smrg if (map) { 3232f7df2e56Smrg xkbIndicatorMapWireDesc *wire = (xkbIndicatorMapWireDesc *) to; 3233f7df2e56Smrg 3234f7df2e56Smrg length = rep->length * 4; 3235f7df2e56Smrg 3236f7df2e56Smrg for (i = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) { 3237f7df2e56Smrg if (rep->which & bit) { 3238f7df2e56Smrg wire->flags = indicators->maps[i].flags; 3239f7df2e56Smrg wire->whichGroups = indicators->maps[i].which_groups; 3240f7df2e56Smrg wire->groups = indicators->maps[i].groups; 3241f7df2e56Smrg wire->whichMods = indicators->maps[i].which_mods; 3242f7df2e56Smrg wire->mods = indicators->maps[i].mods.mask; 3243f7df2e56Smrg wire->realMods = indicators->maps[i].mods.real_mods; 3244f7df2e56Smrg wire->virtualMods = indicators->maps[i].mods.vmods; 3245f7df2e56Smrg wire->ctrls = indicators->maps[i].ctrls; 3246f7df2e56Smrg if (client->swapped) { 3247f7df2e56Smrg swaps(&wire->virtualMods); 3248f7df2e56Smrg swapl(&wire->ctrls); 3249f7df2e56Smrg } 3250f7df2e56Smrg wire++; 3251f7df2e56Smrg } 3252f7df2e56Smrg } 3253f7df2e56Smrg to = (CARD8 *) wire; 3254f7df2e56Smrg if ((to - map) != length) { 3255f7df2e56Smrg client->errorValue = _XkbErrCode2(0xff, length); 3256f7df2e56Smrg free(map); 3257f7df2e56Smrg return BadLength; 3258f7df2e56Smrg } 3259f7df2e56Smrg } 3260f7df2e56Smrg else 3261f7df2e56Smrg return BadAlloc; 3262f7df2e56Smrg } 3263f7df2e56Smrg else 3264f7df2e56Smrg map = NULL; 326505b261ecSmrg if (client->swapped) { 3266f7df2e56Smrg swaps(&rep->sequenceNumber); 3267f7df2e56Smrg swapl(&rep->length); 3268f7df2e56Smrg swapl(&rep->which); 3269f7df2e56Smrg swapl(&rep->realIndicators); 327005b261ecSmrg } 3271f7df2e56Smrg WriteToClient(client, SIZEOF(xkbGetIndicatorMapReply), rep); 327205b261ecSmrg if (map) { 3273f7df2e56Smrg WriteToClient(client, length, map); 3274f7df2e56Smrg free((char *) map); 327505b261ecSmrg } 32766747b715Smrg return Success; 327705b261ecSmrg} 327805b261ecSmrg 327905b261ecSmrgint 328005b261ecSmrgProcXkbGetIndicatorMap(ClientPtr client) 328105b261ecSmrg{ 3282f7df2e56Smrg xkbGetIndicatorMapReply rep; 3283f7df2e56Smrg DeviceIntPtr dev; 3284f7df2e56Smrg XkbDescPtr xkb; 3285f7df2e56Smrg XkbIndicatorPtr leds; 328605b261ecSmrg 328705b261ecSmrg REQUEST(xkbGetIndicatorMapReq); 328805b261ecSmrg REQUEST_SIZE_MATCH(xkbGetIndicatorMapReq); 328905b261ecSmrg 3290f7df2e56Smrg if (!(client->xkbClientFlags & _XkbClientInitialized)) 3291f7df2e56Smrg return BadAccess; 329205b261ecSmrg 32934642e01fSmrg CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess); 329405b261ecSmrg 3295f7df2e56Smrg xkb = dev->key->xkbInfo->desc; 3296f7df2e56Smrg leds = xkb->indicators; 3297f7df2e56Smrg 3298f7df2e56Smrg rep = (xkbGetIndicatorMapReply) { 3299f7df2e56Smrg .type = X_Reply, 3300f7df2e56Smrg .deviceID = dev->id, 3301f7df2e56Smrg .sequenceNumber = client->sequence, 3302f7df2e56Smrg .length = 0, 3303f7df2e56Smrg .which = stuff->which 3304f7df2e56Smrg }; 3305f7df2e56Smrg XkbComputeGetIndicatorMapReplySize(leds, &rep); 3306f7df2e56Smrg return XkbSendIndicatorMap(client, leds, &rep); 330705b261ecSmrg} 330805b261ecSmrg 33094642e01fSmrg/** 33104642e01fSmrg * Apply the given map to the given device. Which specifies which components 33114642e01fSmrg * to apply. 33124642e01fSmrg */ 33134642e01fSmrgstatic int 33144642e01fSmrg_XkbSetIndicatorMap(ClientPtr client, DeviceIntPtr dev, 3315f7df2e56Smrg int which, xkbIndicatorMapWireDesc * desc) 33164642e01fSmrg{ 3317f7df2e56Smrg XkbSrvInfoPtr xkbi; 3318f7df2e56Smrg XkbSrvLedInfoPtr sli; 3319f7df2e56Smrg XkbEventCauseRec cause; 3320f7df2e56Smrg int i, bit; 33214642e01fSmrg 33224642e01fSmrg xkbi = dev->key->xkbInfo; 33234642e01fSmrg 3324f7df2e56Smrg sli = XkbFindSrvLedInfo(dev, XkbDfltXIClass, XkbDfltXIId, 3325f7df2e56Smrg XkbXI_IndicatorMapsMask); 33264642e01fSmrg if (!sli) 3327f7df2e56Smrg return BadAlloc; 33284642e01fSmrg 33294642e01fSmrg for (i = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) { 3330f7df2e56Smrg if (which & bit) { 3331f7df2e56Smrg sli->maps[i].flags = desc->flags; 3332f7df2e56Smrg sli->maps[i].which_groups = desc->whichGroups; 3333f7df2e56Smrg sli->maps[i].groups = desc->groups; 3334f7df2e56Smrg sli->maps[i].which_mods = desc->whichMods; 3335f7df2e56Smrg sli->maps[i].mods.mask = desc->mods; 3336f7df2e56Smrg sli->maps[i].mods.real_mods = desc->mods; 3337f7df2e56Smrg sli->maps[i].mods.vmods = desc->virtualMods; 3338f7df2e56Smrg sli->maps[i].ctrls = desc->ctrls; 3339f7df2e56Smrg if (desc->virtualMods != 0) { 3340f7df2e56Smrg unsigned tmp; 3341f7df2e56Smrg 3342f7df2e56Smrg tmp = XkbMaskForVMask(xkbi->desc, desc->virtualMods); 3343f7df2e56Smrg sli->maps[i].mods.mask = desc->mods | tmp; 3344f7df2e56Smrg } 3345f7df2e56Smrg desc++; 3346f7df2e56Smrg } 3347f7df2e56Smrg } 3348f7df2e56Smrg 3349f7df2e56Smrg XkbSetCauseXkbReq(&cause, X_kbSetIndicatorMap, client); 3350f7df2e56Smrg XkbApplyLedMapChanges(dev, sli, which, NULL, NULL, &cause); 33514642e01fSmrg 33524642e01fSmrg return Success; 33534642e01fSmrg} 33544642e01fSmrg 335505b261ecSmrgint 335605b261ecSmrgProcXkbSetIndicatorMap(ClientPtr client) 335705b261ecSmrg{ 3358f7df2e56Smrg int i, bit; 3359f7df2e56Smrg int nIndicators; 3360f7df2e56Smrg DeviceIntPtr dev; 3361f7df2e56Smrg xkbIndicatorMapWireDesc *from; 3362f7df2e56Smrg int rc; 336305b261ecSmrg 336405b261ecSmrg REQUEST(xkbSetIndicatorMapReq); 336505b261ecSmrg REQUEST_AT_LEAST_SIZE(xkbSetIndicatorMapReq); 336605b261ecSmrg 3367f7df2e56Smrg if (!(client->xkbClientFlags & _XkbClientInitialized)) 3368f7df2e56Smrg return BadAccess; 336905b261ecSmrg 33704642e01fSmrg CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixSetAttrAccess); 337105b261ecSmrg 3372f7df2e56Smrg if (stuff->which == 0) 3373f7df2e56Smrg return Success; 337405b261ecSmrg 3375f7df2e56Smrg for (nIndicators = i = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) { 3376f7df2e56Smrg if (stuff->which & bit) 3377f7df2e56Smrg nIndicators++; 337805b261ecSmrg } 3379f7df2e56Smrg if (stuff->length != ((SIZEOF(xkbSetIndicatorMapReq) + 3380f7df2e56Smrg (nIndicators * SIZEOF(xkbIndicatorMapWireDesc))) / 3381f7df2e56Smrg 4)) { 3382f7df2e56Smrg return BadLength; 338305b261ecSmrg } 338405b261ecSmrg 3385f7df2e56Smrg from = (xkbIndicatorMapWireDesc *) &stuff[1]; 3386f7df2e56Smrg for (i = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) { 3387f7df2e56Smrg if (stuff->which & bit) { 3388f7df2e56Smrg if (client->swapped) { 3389f7df2e56Smrg swaps(&from->virtualMods); 3390f7df2e56Smrg swapl(&from->ctrls); 3391f7df2e56Smrg } 3392f7df2e56Smrg CHK_MASK_LEGAL(i, from->whichGroups, XkbIM_UseAnyGroup); 3393f7df2e56Smrg CHK_MASK_LEGAL(i, from->whichMods, XkbIM_UseAnyMods); 3394f7df2e56Smrg from++; 3395f7df2e56Smrg } 339605b261ecSmrg } 339705b261ecSmrg 3398f7df2e56Smrg from = (xkbIndicatorMapWireDesc *) &stuff[1]; 33994642e01fSmrg rc = _XkbSetIndicatorMap(client, dev, stuff->which, from); 34004642e01fSmrg if (rc != Success) 34014642e01fSmrg return rc; 34024642e01fSmrg 3403f7df2e56Smrg if (stuff->deviceSpec == XkbUseCoreKbd) { 34044642e01fSmrg DeviceIntPtr other; 3405f7df2e56Smrg 3406f7df2e56Smrg for (other = inputInfo.devices; other; other = other->next) { 3407f7df2e56Smrg if ((other != dev) && other->key && !IsMaster(other) && 3408f7df2e56Smrg GetMaster(other, MASTER_KEYBOARD) == dev) { 3409f7df2e56Smrg rc = XaceHook(XACE_DEVICE_ACCESS, client, other, 3410f7df2e56Smrg DixSetAttrAccess); 34114642e01fSmrg if (rc == Success) 34124642e01fSmrg _XkbSetIndicatorMap(client, other, stuff->which, from); 34134642e01fSmrg } 34144642e01fSmrg } 341505b261ecSmrg } 341605b261ecSmrg 34174642e01fSmrg return Success; 341805b261ecSmrg} 341905b261ecSmrg 342005b261ecSmrg/***====================================================================***/ 342105b261ecSmrg 342205b261ecSmrgint 342305b261ecSmrgProcXkbGetNamedIndicator(ClientPtr client) 342405b261ecSmrg{ 3425f7df2e56Smrg DeviceIntPtr dev; 3426f7df2e56Smrg xkbGetNamedIndicatorReply rep; 3427f7df2e56Smrg register int i = 0; 3428f7df2e56Smrg XkbSrvLedInfoPtr sli; 3429f7df2e56Smrg XkbIndicatorMapPtr map = NULL; 343005b261ecSmrg 343105b261ecSmrg REQUEST(xkbGetNamedIndicatorReq); 343205b261ecSmrg REQUEST_SIZE_MATCH(xkbGetNamedIndicatorReq); 343305b261ecSmrg 3434f7df2e56Smrg if (!(client->xkbClientFlags & _XkbClientInitialized)) 3435f7df2e56Smrg return BadAccess; 343605b261ecSmrg 34374642e01fSmrg CHK_LED_DEVICE(dev, stuff->deviceSpec, client, DixReadAccess); 343805b261ecSmrg CHK_ATOM_ONLY(stuff->indicator); 343905b261ecSmrg 3440f7df2e56Smrg sli = XkbFindSrvLedInfo(dev, stuff->ledClass, stuff->ledID, 0); 344105b261ecSmrg if (!sli) 3442f7df2e56Smrg return BadAlloc; 3443f7df2e56Smrg 3444f7df2e56Smrg i = 0; 3445f7df2e56Smrg map = NULL; 3446f7df2e56Smrg if ((sli->names) && (sli->maps)) { 3447f7df2e56Smrg for (i = 0; i < XkbNumIndicators; i++) { 3448f7df2e56Smrg if (stuff->indicator == sli->names[i]) { 3449f7df2e56Smrg map = &sli->maps[i]; 345005b261ecSmrg break; 345105b261ecSmrg } 345205b261ecSmrg } 345305b261ecSmrg } 345405b261ecSmrg 3455f7df2e56Smrg rep = (xkbGetNamedIndicatorReply) { 3456f7df2e56Smrg .type = X_Reply, 3457f7df2e56Smrg .sequenceNumber = client->sequence, 3458f7df2e56Smrg .length = 0, 3459f7df2e56Smrg .deviceID = dev->id, 3460f7df2e56Smrg .indicator = stuff->indicator 3461f7df2e56Smrg }; 3462f7df2e56Smrg if (map != NULL) { 3463f7df2e56Smrg rep.found = TRUE; 3464f7df2e56Smrg rep.on = ((sli->effectiveState & (1 << i)) != 0); 3465f7df2e56Smrg rep.realIndicator = ((sli->physIndicators & (1 << i)) != 0); 3466f7df2e56Smrg rep.ndx = i; 3467f7df2e56Smrg rep.flags = map->flags; 3468f7df2e56Smrg rep.whichGroups = map->which_groups; 3469f7df2e56Smrg rep.groups = map->groups; 3470f7df2e56Smrg rep.whichMods = map->which_mods; 3471f7df2e56Smrg rep.mods = map->mods.mask; 3472f7df2e56Smrg rep.realMods = map->mods.real_mods; 3473f7df2e56Smrg rep.virtualMods = map->mods.vmods; 3474f7df2e56Smrg rep.ctrls = map->ctrls; 3475f7df2e56Smrg rep.supported = TRUE; 3476f7df2e56Smrg } 3477f7df2e56Smrg else { 3478f7df2e56Smrg rep.found = FALSE; 3479f7df2e56Smrg rep.on = FALSE; 3480f7df2e56Smrg rep.realIndicator = FALSE; 3481f7df2e56Smrg rep.ndx = XkbNoIndicator; 3482f7df2e56Smrg rep.flags = 0; 3483f7df2e56Smrg rep.whichGroups = 0; 3484f7df2e56Smrg rep.groups = 0; 3485f7df2e56Smrg rep.whichMods = 0; 3486f7df2e56Smrg rep.mods = 0; 3487f7df2e56Smrg rep.realMods = 0; 3488f7df2e56Smrg rep.virtualMods = 0; 3489f7df2e56Smrg rep.ctrls = 0; 3490f7df2e56Smrg rep.supported = TRUE; 3491f7df2e56Smrg } 3492f7df2e56Smrg if (client->swapped) { 3493f7df2e56Smrg swapl(&rep.length); 3494f7df2e56Smrg swaps(&rep.sequenceNumber); 3495f7df2e56Smrg swapl(&rep.indicator); 3496f7df2e56Smrg swaps(&rep.virtualMods); 3497f7df2e56Smrg swapl(&rep.ctrls); 3498f7df2e56Smrg } 3499f7df2e56Smrg 3500f7df2e56Smrg WriteToClient(client, SIZEOF(xkbGetNamedIndicatorReply), &rep); 35016747b715Smrg return Success; 350205b261ecSmrg} 350305b261ecSmrg 35044642e01fSmrg/** 35054642e01fSmrg * Find the IM on the device. 35064642e01fSmrg * Returns the map, or NULL if the map doesn't exist. 35074642e01fSmrg * If the return value is NULL, led_return is undefined. Otherwise, led_return 35084642e01fSmrg * is set to the led index of the map. 35094642e01fSmrg */ 35104642e01fSmrgstatic XkbIndicatorMapPtr 3511f7df2e56Smrg_XkbFindNamedIndicatorMap(XkbSrvLedInfoPtr sli, Atom indicator, int *led_return) 35124642e01fSmrg{ 3513f7df2e56Smrg XkbIndicatorMapPtr map; 351405b261ecSmrg 35154642e01fSmrg /* search for the right indicator */ 35164642e01fSmrg map = NULL; 351705b261ecSmrg if (sli->names && sli->maps) { 3518f7df2e56Smrg int led; 35196747b715Smrg 3520f7df2e56Smrg for (led = 0; (led < XkbNumIndicators) && (map == NULL); led++) { 3521f7df2e56Smrg if (sli->names[led] == indicator) { 3522f7df2e56Smrg map = &sli->maps[led]; 3523f7df2e56Smrg *led_return = led; 3524f7df2e56Smrg break; 3525f7df2e56Smrg } 3526f7df2e56Smrg } 352705b261ecSmrg } 352805b261ecSmrg 35294642e01fSmrg return map; 35304642e01fSmrg} 35314642e01fSmrg 35324642e01fSmrg/** 35336747b715Smrg * Creates an indicator map on the device. If dryRun is TRUE, it only checks 35344642e01fSmrg * if creation is possible, but doesn't actually create it. 35354642e01fSmrg */ 35364642e01fSmrgstatic int 35374642e01fSmrg_XkbCreateIndicatorMap(DeviceIntPtr dev, Atom indicator, 35384642e01fSmrg int ledClass, int ledID, 3539f7df2e56Smrg XkbIndicatorMapPtr * map_return, int *led_return, 35404642e01fSmrg Bool dryRun) 35414642e01fSmrg{ 3542f7df2e56Smrg XkbSrvLedInfoPtr sli; 3543f7df2e56Smrg XkbIndicatorMapPtr map; 3544f7df2e56Smrg int led; 35454642e01fSmrg 35464642e01fSmrg sli = XkbFindSrvLedInfo(dev, ledClass, ledID, XkbXI_IndicatorsMask); 35474642e01fSmrg if (!sli) 35484642e01fSmrg return BadAlloc; 35494642e01fSmrg 35504642e01fSmrg map = _XkbFindNamedIndicatorMap(sli, indicator, &led); 35514642e01fSmrg 3552f7df2e56Smrg if (!map) { 35534642e01fSmrg /* find first unused indicator maps and assign the name to it */ 3554f7df2e56Smrg for (led = 0, map = NULL; (led < XkbNumIndicators) && (map == NULL); 3555f7df2e56Smrg led++) { 35564642e01fSmrg if ((sli->names) && (sli->maps) && (sli->names[led] == None) && 3557f7df2e56Smrg (!XkbIM_InUse(&sli->maps[led]))) { 35584642e01fSmrg map = &sli->maps[led]; 35594642e01fSmrg if (!dryRun) 35604642e01fSmrg sli->names[led] = indicator; 35614642e01fSmrg break; 35624642e01fSmrg } 35634642e01fSmrg } 35644642e01fSmrg } 35654642e01fSmrg 35664642e01fSmrg if (!map) 35674642e01fSmrg return BadAlloc; 35684642e01fSmrg 35694642e01fSmrg *led_return = led; 35704642e01fSmrg *map_return = map; 35714642e01fSmrg return Success; 35724642e01fSmrg} 35734642e01fSmrg 35744642e01fSmrgstatic int 35754642e01fSmrg_XkbSetNamedIndicator(ClientPtr client, DeviceIntPtr dev, 3576f7df2e56Smrg xkbSetNamedIndicatorReq * stuff) 35774642e01fSmrg{ 3578f7df2e56Smrg unsigned int extDevReason; 3579f7df2e56Smrg unsigned int statec, namec, mapc; 3580f7df2e56Smrg XkbSrvLedInfoPtr sli; 3581f7df2e56Smrg int led = 0; 3582f7df2e56Smrg XkbIndicatorMapPtr map; 3583f7df2e56Smrg DeviceIntPtr kbd; 3584f7df2e56Smrg XkbEventCauseRec cause; 3585f7df2e56Smrg xkbExtensionDeviceNotify ed; 3586f7df2e56Smrg XkbChangesRec changes; 3587f7df2e56Smrg int rc; 35884642e01fSmrg 35894642e01fSmrg rc = _XkbCreateIndicatorMap(dev, stuff->indicator, stuff->ledClass, 35904642e01fSmrg stuff->ledID, &map, &led, FALSE); 3591f7df2e56Smrg if (rc != Success || !map) /* oh-oh */ 35924642e01fSmrg return rc; 35934642e01fSmrg 35944642e01fSmrg sli = XkbFindSrvLedInfo(dev, stuff->ledClass, stuff->ledID, 35954642e01fSmrg XkbXI_IndicatorsMask); 35964642e01fSmrg if (!sli) 35974642e01fSmrg return BadAlloc; 35984642e01fSmrg 35994642e01fSmrg namec = mapc = statec = 0; 36004642e01fSmrg extDevReason = 0; 36014642e01fSmrg 3602f7df2e56Smrg namec |= (1 << led); 36034642e01fSmrg sli->namesPresent |= ((stuff->indicator != None) ? (1 << led) : 0); 36044642e01fSmrg extDevReason |= XkbXI_IndicatorNamesMask; 36054642e01fSmrg 36064642e01fSmrg if (stuff->setMap) { 36074642e01fSmrg map->flags = stuff->flags; 36084642e01fSmrg map->which_groups = stuff->whichGroups; 36094642e01fSmrg map->groups = stuff->groups; 36104642e01fSmrg map->which_mods = stuff->whichMods; 36114642e01fSmrg map->mods.mask = stuff->realMods; 36124642e01fSmrg map->mods.real_mods = stuff->realMods; 3613f7df2e56Smrg map->mods.vmods = stuff->virtualMods; 36144642e01fSmrg map->ctrls = stuff->ctrls; 3615f7df2e56Smrg mapc |= (1 << led); 36164642e01fSmrg } 36174642e01fSmrg 3618f7df2e56Smrg if ((stuff->setState) && ((map->flags & XkbIM_NoExplicit) == 0)) { 3619f7df2e56Smrg if (stuff->on) 3620f7df2e56Smrg sli->explicitState |= (1 << led); 3621f7df2e56Smrg else 3622f7df2e56Smrg sli->explicitState &= ~(1 << led); 36234642e01fSmrg statec |= ((sli->effectiveState ^ sli->explicitState) & (1 << led)); 362405b261ecSmrg } 36254642e01fSmrg 3626f7df2e56Smrg memset((char *) &ed, 0, sizeof(xkbExtensionDeviceNotify)); 3627f7df2e56Smrg memset((char *) &changes, 0, sizeof(XkbChangesRec)); 3628f7df2e56Smrg XkbSetCauseXkbReq(&cause, X_kbSetNamedIndicator, client); 362905b261ecSmrg if (namec) 3630f7df2e56Smrg XkbApplyLedNameChanges(dev, sli, namec, &ed, &changes, &cause); 363105b261ecSmrg if (mapc) 3632f7df2e56Smrg XkbApplyLedMapChanges(dev, sli, mapc, &ed, &changes, &cause); 363305b261ecSmrg if (statec) 3634f7df2e56Smrg XkbApplyLedStateChanges(dev, sli, statec, &ed, &changes, &cause); 363505b261ecSmrg 36364642e01fSmrg kbd = dev; 3637f7df2e56Smrg if ((sli->flags & XkbSLI_HasOwnState) == 0) 36384642e01fSmrg kbd = inputInfo.keyboard; 36394642e01fSmrg XkbFlushLedEvents(dev, kbd, sli, &ed, &changes, &cause); 36404642e01fSmrg 36414642e01fSmrg return Success; 36424642e01fSmrg} 36434642e01fSmrg 36444642e01fSmrgint 36454642e01fSmrgProcXkbSetNamedIndicator(ClientPtr client) 36464642e01fSmrg{ 3647f7df2e56Smrg int rc; 3648f7df2e56Smrg DeviceIntPtr dev; 3649f7df2e56Smrg int led = 0; 3650f7df2e56Smrg XkbIndicatorMapPtr map; 36514642e01fSmrg 36524642e01fSmrg REQUEST(xkbSetNamedIndicatorReq); 36534642e01fSmrg REQUEST_SIZE_MATCH(xkbSetNamedIndicatorReq); 36544642e01fSmrg 3655f7df2e56Smrg if (!(client->xkbClientFlags & _XkbClientInitialized)) 3656f7df2e56Smrg return BadAccess; 36574642e01fSmrg 36584642e01fSmrg CHK_LED_DEVICE(dev, stuff->deviceSpec, client, DixSetAttrAccess); 36594642e01fSmrg CHK_ATOM_ONLY(stuff->indicator); 3660f7df2e56Smrg CHK_MASK_LEGAL(0x10, stuff->whichGroups, XkbIM_UseAnyGroup); 3661f7df2e56Smrg CHK_MASK_LEGAL(0x11, stuff->whichMods, XkbIM_UseAnyMods); 36624642e01fSmrg 36634642e01fSmrg /* Dry-run for checks */ 36644642e01fSmrg rc = _XkbCreateIndicatorMap(dev, stuff->indicator, 36654642e01fSmrg stuff->ledClass, stuff->ledID, 36664642e01fSmrg &map, &led, TRUE); 3667f7df2e56Smrg if (rc != Success || !map) /* couldn't be created or didn't exist */ 36684642e01fSmrg return rc; 36694642e01fSmrg 36704642e01fSmrg if (stuff->deviceSpec == XkbUseCoreKbd || 3671f7df2e56Smrg stuff->deviceSpec == XkbUseCorePtr) { 36724642e01fSmrg DeviceIntPtr other; 3673f7df2e56Smrg 3674f7df2e56Smrg for (other = inputInfo.devices; other; other = other->next) { 3675f7df2e56Smrg if ((other != dev) && !IsMaster(other) && 3676f7df2e56Smrg GetMaster(other, MASTER_KEYBOARD) == dev && (other->kbdfeed || 3677f7df2e56Smrg other->leds) && 3678f7df2e56Smrg (XaceHook(XACE_DEVICE_ACCESS, client, other, DixSetAttrAccess) 3679f7df2e56Smrg == Success)) { 36804642e01fSmrg rc = _XkbCreateIndicatorMap(other, stuff->indicator, 3681f7df2e56Smrg stuff->ledClass, stuff->ledID, &map, 3682f7df2e56Smrg &led, TRUE); 36834642e01fSmrg if (rc != Success || !map) 36844642e01fSmrg return rc; 36854642e01fSmrg } 36864642e01fSmrg } 36874642e01fSmrg } 36884642e01fSmrg 36894642e01fSmrg /* All checks passed, let's do it */ 36904642e01fSmrg rc = _XkbSetNamedIndicator(client, dev, stuff); 36914642e01fSmrg if (rc != Success) 36924642e01fSmrg return rc; 36934642e01fSmrg 36944642e01fSmrg if (stuff->deviceSpec == XkbUseCoreKbd || 3695f7df2e56Smrg stuff->deviceSpec == XkbUseCorePtr) { 36964642e01fSmrg DeviceIntPtr other; 3697f7df2e56Smrg 3698f7df2e56Smrg for (other = inputInfo.devices; other; other = other->next) { 3699f7df2e56Smrg if ((other != dev) && !IsMaster(other) && 3700f7df2e56Smrg GetMaster(other, MASTER_KEYBOARD) == dev && (other->kbdfeed || 3701f7df2e56Smrg other->leds) && 3702f7df2e56Smrg (XaceHook(XACE_DEVICE_ACCESS, client, other, DixSetAttrAccess) 3703f7df2e56Smrg == Success)) { 37044642e01fSmrg _XkbSetNamedIndicator(client, other, stuff); 37054642e01fSmrg } 37064642e01fSmrg } 37074642e01fSmrg } 37084642e01fSmrg 37096747b715Smrg return Success; 371005b261ecSmrg} 371105b261ecSmrg 371205b261ecSmrg/***====================================================================***/ 371305b261ecSmrg 371405b261ecSmrgstatic CARD32 3715f7df2e56Smrg_XkbCountAtoms(Atom *atoms, int maxAtoms, int *count) 371605b261ecSmrg{ 3717f7df2e56Smrg register unsigned int i, bit, nAtoms; 3718f7df2e56Smrg register CARD32 atomsPresent; 371905b261ecSmrg 3720f7df2e56Smrg for (i = nAtoms = atomsPresent = 0, bit = 1; i < maxAtoms; i++, bit <<= 1) { 3721f7df2e56Smrg if (atoms[i] != None) { 3722f7df2e56Smrg atomsPresent |= bit; 3723f7df2e56Smrg nAtoms++; 3724f7df2e56Smrg } 372505b261ecSmrg } 372605b261ecSmrg if (count) 3727f7df2e56Smrg *count = nAtoms; 372805b261ecSmrg return atomsPresent; 372905b261ecSmrg} 373005b261ecSmrg 373105b261ecSmrgstatic char * 3732f7df2e56Smrg_XkbWriteAtoms(char *wire, Atom *atoms, int maxAtoms, int swap) 373305b261ecSmrg{ 3734f7df2e56Smrg register unsigned int i; 3735f7df2e56Smrg Atom *atm; 3736f7df2e56Smrg 3737f7df2e56Smrg atm = (Atom *) wire; 3738f7df2e56Smrg for (i = 0; i < maxAtoms; i++) { 3739f7df2e56Smrg if (atoms[i] != None) { 3740f7df2e56Smrg *atm = atoms[i]; 3741f7df2e56Smrg if (swap) { 3742f7df2e56Smrg swapl(atm); 3743f7df2e56Smrg } 3744f7df2e56Smrg atm++; 3745f7df2e56Smrg } 3746f7df2e56Smrg } 3747f7df2e56Smrg return (char *) atm; 374805b261ecSmrg} 374905b261ecSmrg 375005b261ecSmrgstatic Status 3751f7df2e56SmrgXkbComputeGetNamesReplySize(XkbDescPtr xkb, xkbGetNamesReply * rep) 375205b261ecSmrg{ 3753f7df2e56Smrg register unsigned which, length; 3754f7df2e56Smrg register int i; 3755f7df2e56Smrg 3756f7df2e56Smrg rep->minKeyCode = xkb->min_key_code; 3757f7df2e56Smrg rep->maxKeyCode = xkb->max_key_code; 3758f7df2e56Smrg which = rep->which; 3759f7df2e56Smrg length = 0; 3760f7df2e56Smrg if (xkb->names != NULL) { 3761f7df2e56Smrg if (which & XkbKeycodesNameMask) 3762f7df2e56Smrg length++; 3763f7df2e56Smrg if (which & XkbGeometryNameMask) 3764f7df2e56Smrg length++; 3765f7df2e56Smrg if (which & XkbSymbolsNameMask) 3766f7df2e56Smrg length++; 3767f7df2e56Smrg if (which & XkbPhysSymbolsNameMask) 3768f7df2e56Smrg length++; 3769f7df2e56Smrg if (which & XkbTypesNameMask) 3770f7df2e56Smrg length++; 3771f7df2e56Smrg if (which & XkbCompatNameMask) 3772f7df2e56Smrg length++; 3773f7df2e56Smrg } 3774f7df2e56Smrg else 3775f7df2e56Smrg which &= ~XkbComponentNamesMask; 3776f7df2e56Smrg 3777f7df2e56Smrg if (xkb->map != NULL) { 3778f7df2e56Smrg if (which & XkbKeyTypeNamesMask) 3779f7df2e56Smrg length += xkb->map->num_types; 3780f7df2e56Smrg rep->nTypes = xkb->map->num_types; 3781f7df2e56Smrg if (which & XkbKTLevelNamesMask) { 3782f7df2e56Smrg XkbKeyTypePtr pType = xkb->map->types; 3783f7df2e56Smrg int nKTLevels = 0; 3784f7df2e56Smrg 3785f7df2e56Smrg length += XkbPaddedSize(xkb->map->num_types) / 4; 3786f7df2e56Smrg for (i = 0; i < xkb->map->num_types; i++, pType++) { 3787f7df2e56Smrg if (pType->level_names != NULL) 3788f7df2e56Smrg nKTLevels += pType->num_levels; 3789f7df2e56Smrg } 3790f7df2e56Smrg rep->nKTLevels = nKTLevels; 3791f7df2e56Smrg length += nKTLevels; 3792f7df2e56Smrg } 379305b261ecSmrg } 379405b261ecSmrg else { 3795f7df2e56Smrg rep->nTypes = 0; 3796f7df2e56Smrg rep->nKTLevels = 0; 3797f7df2e56Smrg which &= ~(XkbKeyTypeNamesMask | XkbKTLevelNamesMask); 3798f7df2e56Smrg } 3799f7df2e56Smrg 3800f7df2e56Smrg rep->minKeyCode = xkb->min_key_code; 3801f7df2e56Smrg rep->maxKeyCode = xkb->max_key_code; 3802f7df2e56Smrg rep->indicators = 0; 3803f7df2e56Smrg rep->virtualMods = 0; 3804f7df2e56Smrg rep->groupNames = 0; 3805f7df2e56Smrg if (xkb->names != NULL) { 3806f7df2e56Smrg if (which & XkbIndicatorNamesMask) { 3807f7df2e56Smrg int nLeds; 3808f7df2e56Smrg 3809f7df2e56Smrg rep->indicators = 3810f7df2e56Smrg _XkbCountAtoms(xkb->names->indicators, XkbNumIndicators, 3811f7df2e56Smrg &nLeds); 3812f7df2e56Smrg length += nLeds; 3813f7df2e56Smrg if (nLeds == 0) 3814f7df2e56Smrg which &= ~XkbIndicatorNamesMask; 3815f7df2e56Smrg } 3816f7df2e56Smrg 3817f7df2e56Smrg if (which & XkbVirtualModNamesMask) { 3818f7df2e56Smrg int nVMods; 3819f7df2e56Smrg 3820f7df2e56Smrg rep->virtualMods = 3821f7df2e56Smrg _XkbCountAtoms(xkb->names->vmods, XkbNumVirtualMods, &nVMods); 3822f7df2e56Smrg length += nVMods; 3823f7df2e56Smrg if (nVMods == 0) 3824f7df2e56Smrg which &= ~XkbVirtualModNamesMask; 3825f7df2e56Smrg } 3826f7df2e56Smrg 3827f7df2e56Smrg if (which & XkbGroupNamesMask) { 3828f7df2e56Smrg int nGroups; 3829f7df2e56Smrg 3830f7df2e56Smrg rep->groupNames = 3831f7df2e56Smrg _XkbCountAtoms(xkb->names->groups, XkbNumKbdGroups, &nGroups); 3832f7df2e56Smrg length += nGroups; 3833f7df2e56Smrg if (nGroups == 0) 3834f7df2e56Smrg which &= ~XkbGroupNamesMask; 3835f7df2e56Smrg } 3836f7df2e56Smrg 3837f7df2e56Smrg if ((which & XkbKeyNamesMask) && (xkb->names->keys)) 3838f7df2e56Smrg length += rep->nKeys; 3839f7df2e56Smrg else 3840f7df2e56Smrg which &= ~XkbKeyNamesMask; 3841f7df2e56Smrg 3842f7df2e56Smrg if ((which & XkbKeyAliasesMask) && 3843f7df2e56Smrg (xkb->names->key_aliases) && (xkb->names->num_key_aliases > 0)) { 3844f7df2e56Smrg rep->nKeyAliases = xkb->names->num_key_aliases; 3845f7df2e56Smrg length += rep->nKeyAliases * 2; 3846f7df2e56Smrg } 3847f7df2e56Smrg else { 3848f7df2e56Smrg which &= ~XkbKeyAliasesMask; 3849f7df2e56Smrg rep->nKeyAliases = 0; 3850f7df2e56Smrg } 3851f7df2e56Smrg 3852f7df2e56Smrg if ((which & XkbRGNamesMask) && (xkb->names->num_rg > 0)) 3853f7df2e56Smrg length += xkb->names->num_rg; 3854f7df2e56Smrg else 3855f7df2e56Smrg which &= ~XkbRGNamesMask; 385605b261ecSmrg } 385705b261ecSmrg else { 3858f7df2e56Smrg which &= ~(XkbIndicatorNamesMask | XkbVirtualModNamesMask); 3859f7df2e56Smrg which &= ~(XkbGroupNamesMask | XkbKeyNamesMask | XkbKeyAliasesMask); 3860f7df2e56Smrg which &= ~XkbRGNamesMask; 386105b261ecSmrg } 386205b261ecSmrg 3863f7df2e56Smrg rep->length = length; 3864f7df2e56Smrg rep->which = which; 386505b261ecSmrg return Success; 386605b261ecSmrg} 386705b261ecSmrg 386805b261ecSmrgstatic int 3869f7df2e56SmrgXkbSendNames(ClientPtr client, XkbDescPtr xkb, xkbGetNamesReply * rep) 387005b261ecSmrg{ 3871f7df2e56Smrg register unsigned i, length, which; 3872f7df2e56Smrg char *start; 3873f7df2e56Smrg char *desc; 387405b261ecSmrg 3875f7df2e56Smrg length = rep->length * 4; 3876f7df2e56Smrg which = rep->which; 387705b261ecSmrg if (client->swapped) { 3878f7df2e56Smrg swaps(&rep->sequenceNumber); 3879f7df2e56Smrg swapl(&rep->length); 3880f7df2e56Smrg swapl(&rep->which); 3881f7df2e56Smrg swaps(&rep->virtualMods); 3882f7df2e56Smrg swapl(&rep->indicators); 388305b261ecSmrg } 388405b261ecSmrg 38859ace9065Smrg start = desc = calloc(1, length); 3886f7df2e56Smrg if (!start) 3887f7df2e56Smrg return BadAlloc; 388805b261ecSmrg if (xkb->names) { 3889f7df2e56Smrg if (which & XkbKeycodesNameMask) { 3890f7df2e56Smrg *((CARD32 *) desc) = xkb->names->keycodes; 389105b261ecSmrg if (client->swapped) { 3892f7df2e56Smrg swapl((int *) desc); 389305b261ecSmrg } 3894f7df2e56Smrg desc += 4; 389505b261ecSmrg } 3896f7df2e56Smrg if (which & XkbGeometryNameMask) { 3897f7df2e56Smrg *((CARD32 *) desc) = xkb->names->geometry; 389805b261ecSmrg if (client->swapped) { 3899f7df2e56Smrg swapl((int *) desc); 390005b261ecSmrg } 3901f7df2e56Smrg desc += 4; 390205b261ecSmrg } 3903f7df2e56Smrg if (which & XkbSymbolsNameMask) { 3904f7df2e56Smrg *((CARD32 *) desc) = xkb->names->symbols; 390505b261ecSmrg if (client->swapped) { 3906f7df2e56Smrg swapl((int *) desc); 390705b261ecSmrg } 3908f7df2e56Smrg desc += 4; 390905b261ecSmrg } 3910f7df2e56Smrg if (which & XkbPhysSymbolsNameMask) { 3911f7df2e56Smrg register CARD32 *atm = (CARD32 *) desc; 3912f7df2e56Smrg 3913f7df2e56Smrg atm[0] = (CARD32) xkb->names->phys_symbols; 391405b261ecSmrg if (client->swapped) { 3915f7df2e56Smrg swapl(&atm[0]); 391605b261ecSmrg } 3917f7df2e56Smrg desc += 4; 391805b261ecSmrg } 3919f7df2e56Smrg if (which & XkbTypesNameMask) { 3920f7df2e56Smrg *((CARD32 *) desc) = (CARD32) xkb->names->types; 392105b261ecSmrg if (client->swapped) { 3922f7df2e56Smrg swapl((int *) desc); 392305b261ecSmrg } 3924f7df2e56Smrg desc += 4; 392505b261ecSmrg } 3926f7df2e56Smrg if (which & XkbCompatNameMask) { 3927f7df2e56Smrg *((CARD32 *) desc) = (CARD32) xkb->names->compat; 392805b261ecSmrg if (client->swapped) { 3929f7df2e56Smrg swapl((int *) desc); 393005b261ecSmrg } 3931f7df2e56Smrg desc += 4; 393205b261ecSmrg } 3933f7df2e56Smrg if (which & XkbKeyTypeNamesMask) { 3934f7df2e56Smrg register CARD32 *atm = (CARD32 *) desc; 3935f7df2e56Smrg register XkbKeyTypePtr type = xkb->map->types; 393605b261ecSmrg 3937f7df2e56Smrg for (i = 0; i < xkb->map->num_types; i++, atm++, type++) { 3938f7df2e56Smrg *atm = (CARD32) type->name; 393905b261ecSmrg if (client->swapped) { 3940f7df2e56Smrg swapl(atm); 394105b261ecSmrg } 394205b261ecSmrg } 3943f7df2e56Smrg desc = (char *) atm; 394405b261ecSmrg } 3945f7df2e56Smrg if (which & XkbKTLevelNamesMask && xkb->map) { 394605b261ecSmrg XkbKeyTypePtr type = xkb->map->types; 394705b261ecSmrg register CARD32 *atm; 3948f7df2e56Smrg 3949f7df2e56Smrg for (i = 0; i < rep->nTypes; i++, type++) { 395005b261ecSmrg *desc++ = type->num_levels; 395105b261ecSmrg } 3952f7df2e56Smrg desc += XkbPaddedSize(rep->nTypes) - rep->nTypes; 395305b261ecSmrg 3954f7df2e56Smrg atm = (CARD32 *) desc; 395505b261ecSmrg type = xkb->map->types; 3956f7df2e56Smrg for (i = 0; i < xkb->map->num_types; i++, type++) { 395705b261ecSmrg register unsigned l; 3958f7df2e56Smrg 395905b261ecSmrg if (type->level_names) { 3960f7df2e56Smrg for (l = 0; l < type->num_levels; l++, atm++) { 3961f7df2e56Smrg *atm = type->level_names[l]; 396205b261ecSmrg if (client->swapped) { 3963f7df2e56Smrg swapl(atm); 396405b261ecSmrg } 396505b261ecSmrg } 3966f7df2e56Smrg desc += type->num_levels * 4; 396705b261ecSmrg } 396805b261ecSmrg } 396905b261ecSmrg } 3970f7df2e56Smrg if (which & XkbIndicatorNamesMask) { 3971f7df2e56Smrg desc = 3972f7df2e56Smrg _XkbWriteAtoms(desc, xkb->names->indicators, XkbNumIndicators, 3973f7df2e56Smrg client->swapped); 397405b261ecSmrg } 3975f7df2e56Smrg if (which & XkbVirtualModNamesMask) { 3976f7df2e56Smrg desc = _XkbWriteAtoms(desc, xkb->names->vmods, XkbNumVirtualMods, 3977f7df2e56Smrg client->swapped); 397805b261ecSmrg } 3979f7df2e56Smrg if (which & XkbGroupNamesMask) { 3980f7df2e56Smrg desc = _XkbWriteAtoms(desc, xkb->names->groups, XkbNumKbdGroups, 3981f7df2e56Smrg client->swapped); 398205b261ecSmrg } 3983f7df2e56Smrg if (which & XkbKeyNamesMask) { 3984f7df2e56Smrg for (i = 0; i < rep->nKeys; i++, desc += sizeof(XkbKeyNameRec)) { 3985f7df2e56Smrg *((XkbKeyNamePtr) desc) = xkb->names->keys[i + rep->firstKey]; 398605b261ecSmrg } 398705b261ecSmrg } 3988f7df2e56Smrg if (which & XkbKeyAliasesMask) { 3989f7df2e56Smrg XkbKeyAliasPtr pAl; 3990f7df2e56Smrg 3991f7df2e56Smrg pAl = xkb->names->key_aliases; 3992f7df2e56Smrg for (i = 0; i < rep->nKeyAliases; 3993f7df2e56Smrg i++, pAl++, desc += 2 * XkbKeyNameLength) { 3994f7df2e56Smrg *((XkbKeyAliasPtr) desc) = *pAl; 399505b261ecSmrg } 399605b261ecSmrg } 3997f7df2e56Smrg if ((which & XkbRGNamesMask) && (rep->nRadioGroups > 0)) { 3998f7df2e56Smrg register CARD32 *atm = (CARD32 *) desc; 3999f7df2e56Smrg 4000f7df2e56Smrg for (i = 0; i < rep->nRadioGroups; i++, atm++) { 4001f7df2e56Smrg *atm = (CARD32) xkb->names->radio_groups[i]; 400205b261ecSmrg if (client->swapped) { 4003f7df2e56Smrg swapl(atm); 400405b261ecSmrg } 400505b261ecSmrg } 4006f7df2e56Smrg desc += rep->nRadioGroups * 4; 400705b261ecSmrg } 400805b261ecSmrg } 400905b261ecSmrg 4010f7df2e56Smrg if ((desc - start) != (length)) { 4011f7df2e56Smrg ErrorF("[xkb] BOGUS LENGTH in write names, expected %d, got %ld\n", 4012f7df2e56Smrg length, (unsigned long) (desc - start)); 401305b261ecSmrg } 4014f7df2e56Smrg WriteToClient(client, SIZEOF(xkbGetNamesReply), rep); 401505b261ecSmrg WriteToClient(client, length, start); 4016f7df2e56Smrg free((char *) start); 40176747b715Smrg return Success; 401805b261ecSmrg} 401905b261ecSmrg 402005b261ecSmrgint 402105b261ecSmrgProcXkbGetNames(ClientPtr client) 402205b261ecSmrg{ 4023f7df2e56Smrg DeviceIntPtr dev; 4024f7df2e56Smrg XkbDescPtr xkb; 4025f7df2e56Smrg xkbGetNamesReply rep; 402605b261ecSmrg 402705b261ecSmrg REQUEST(xkbGetNamesReq); 402805b261ecSmrg REQUEST_SIZE_MATCH(xkbGetNamesReq); 402905b261ecSmrg 4030f7df2e56Smrg if (!(client->xkbClientFlags & _XkbClientInitialized)) 4031f7df2e56Smrg return BadAccess; 403205b261ecSmrg 40334642e01fSmrg CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess); 4034f7df2e56Smrg CHK_MASK_LEGAL(0x01, stuff->which, XkbAllNamesMask); 403505b261ecSmrg 403605b261ecSmrg xkb = dev->key->xkbInfo->desc; 4037f7df2e56Smrg rep = (xkbGetNamesReply) { 4038f7df2e56Smrg .type = X_Reply, 4039f7df2e56Smrg .deviceID = dev->id, 4040f7df2e56Smrg .sequenceNumber = client->sequence, 4041f7df2e56Smrg .length = 0, 4042f7df2e56Smrg .which = stuff->which, 4043f7df2e56Smrg .nTypes = xkb->map->num_types, 4044f7df2e56Smrg .firstKey = xkb->min_key_code, 4045f7df2e56Smrg .nKeys = XkbNumKeys(xkb), 4046f7df2e56Smrg .nKeyAliases = xkb->names ? xkb->names->num_key_aliases : 0, 4047f7df2e56Smrg .nRadioGroups = xkb->names ? xkb->names->num_rg : 0 4048f7df2e56Smrg }; 4049f7df2e56Smrg XkbComputeGetNamesReplySize(xkb, &rep); 4050f7df2e56Smrg return XkbSendNames(client, xkb, &rep); 405105b261ecSmrg} 405205b261ecSmrg 405305b261ecSmrg/***====================================================================***/ 405405b261ecSmrg 405505b261ecSmrgstatic CARD32 * 4056f7df2e56Smrg_XkbCheckAtoms(CARD32 *wire, int nAtoms, int swapped, Atom *pError) 405705b261ecSmrg{ 4058f7df2e56Smrg register int i; 4059f7df2e56Smrg 4060f7df2e56Smrg for (i = 0; i < nAtoms; i++, wire++) { 4061f7df2e56Smrg if (swapped) { 4062f7df2e56Smrg swapl(wire); 4063f7df2e56Smrg } 4064f7df2e56Smrg if ((((Atom) *wire) != None) && (!ValidAtom((Atom) *wire))) { 4065f7df2e56Smrg *pError = ((Atom) *wire); 4066f7df2e56Smrg return NULL; 4067f7df2e56Smrg } 406805b261ecSmrg } 406905b261ecSmrg return wire; 407005b261ecSmrg} 407105b261ecSmrg 407205b261ecSmrgstatic CARD32 * 4073f7df2e56Smrg_XkbCheckMaskedAtoms(CARD32 *wire, int nAtoms, CARD32 present, int swapped, 4074f7df2e56Smrg Atom *pError) 407505b261ecSmrg{ 4076f7df2e56Smrg register unsigned i, bit; 4077f7df2e56Smrg 4078f7df2e56Smrg for (i = 0, bit = 1; (i < nAtoms) && (present); i++, bit <<= 1) { 4079f7df2e56Smrg if ((present & bit) == 0) 4080f7df2e56Smrg continue; 4081f7df2e56Smrg if (swapped) { 4082f7df2e56Smrg swapl(wire); 4083f7df2e56Smrg } 4084f7df2e56Smrg if ((((Atom) *wire) != None) && (!ValidAtom(((Atom) *wire)))) { 4085f7df2e56Smrg *pError = (Atom) *wire; 4086f7df2e56Smrg return NULL; 4087f7df2e56Smrg } 4088f7df2e56Smrg wire++; 408905b261ecSmrg } 409005b261ecSmrg return wire; 409105b261ecSmrg} 409205b261ecSmrg 409305b261ecSmrgstatic Atom * 4094f7df2e56Smrg_XkbCopyMaskedAtoms(Atom *wire, Atom *dest, int nAtoms, CARD32 present) 409505b261ecSmrg{ 4096f7df2e56Smrg register int i, bit; 409705b261ecSmrg 4098f7df2e56Smrg for (i = 0, bit = 1; (i < nAtoms) && (present); i++, bit <<= 1) { 4099f7df2e56Smrg if ((present & bit) == 0) 4100f7df2e56Smrg continue; 4101f7df2e56Smrg dest[i] = *wire++; 410205b261ecSmrg } 410305b261ecSmrg return wire; 410405b261ecSmrg} 410505b261ecSmrg 410605b261ecSmrgstatic Bool 4107f7df2e56Smrg_XkbCheckTypeName(Atom name, int typeNdx) 410805b261ecSmrg{ 4109f7df2e56Smrg const char *str; 411005b261ecSmrg 4111f7df2e56Smrg str = NameForAtom(name); 4112f7df2e56Smrg if ((strcmp(str, "ONE_LEVEL") == 0) || (strcmp(str, "TWO_LEVEL") == 0) || 4113f7df2e56Smrg (strcmp(str, "ALPHABETIC") == 0) || (strcmp(str, "KEYPAD") == 0)) 4114f7df2e56Smrg return FALSE; 41156747b715Smrg return TRUE; 411605b261ecSmrg} 411705b261ecSmrg 41184642e01fSmrg/** 41194642e01fSmrg * Check the device-dependent data in the request against the device. Returns 41204642e01fSmrg * Success, or the appropriate error code. 41214642e01fSmrg */ 41224642e01fSmrgstatic int 41234642e01fSmrg_XkbSetNamesCheck(ClientPtr client, DeviceIntPtr dev, 4124f7df2e56Smrg xkbSetNamesReq * stuff, CARD32 *data) 412505b261ecSmrg{ 4126f7df2e56Smrg XkbDescRec *xkb; 4127f7df2e56Smrg CARD32 *tmp; 4128f7df2e56Smrg Atom bad = None; 412905b261ecSmrg 41304642e01fSmrg tmp = data; 41314642e01fSmrg xkb = dev->key->xkbInfo->desc; 41324642e01fSmrg 41334642e01fSmrg if (stuff->which & XkbKeyTypeNamesMask) { 41344642e01fSmrg int i; 4135f7df2e56Smrg CARD32 *old; 4136f7df2e56Smrg 4137f7df2e56Smrg if (stuff->nTypes < 1) { 4138f7df2e56Smrg client->errorValue = _XkbErrCode2(0x02, stuff->nTypes); 41394642e01fSmrg return BadValue; 41404642e01fSmrg } 4141f7df2e56Smrg if ((unsigned) (stuff->firstType + stuff->nTypes - 1) >= 4142f7df2e56Smrg xkb->map->num_types) { 4143f7df2e56Smrg client->errorValue = 4144f7df2e56Smrg _XkbErrCode4(0x03, stuff->firstType, stuff->nTypes, 4145f7df2e56Smrg xkb->map->num_types); 41464642e01fSmrg return BadValue; 41474642e01fSmrg } 4148f7df2e56Smrg if (((unsigned) stuff->firstType) <= XkbLastRequiredType) { 4149f7df2e56Smrg client->errorValue = _XkbErrCode2(0x04, stuff->firstType); 41504642e01fSmrg return BadAccess; 41514642e01fSmrg } 4152806e81e9Smrg if (!_XkbCheckRequestBounds(client, stuff, tmp, tmp + stuff->nTypes)) 4153806e81e9Smrg return BadLength; 4154f7df2e56Smrg old = tmp; 4155f7df2e56Smrg tmp = _XkbCheckAtoms(tmp, stuff->nTypes, client->swapped, &bad); 41564642e01fSmrg if (!tmp) { 4157f7df2e56Smrg client->errorValue = bad; 41584642e01fSmrg return BadAtom; 41594642e01fSmrg } 4160f7df2e56Smrg for (i = 0; i < stuff->nTypes; i++, old++) { 4161f7df2e56Smrg if (!_XkbCheckTypeName((Atom) *old, stuff->firstType + i)) 4162f7df2e56Smrg client->errorValue = _XkbErrCode2(0x05, i); 41634642e01fSmrg } 41644642e01fSmrg } 4165f7df2e56Smrg if (stuff->which & XkbKTLevelNamesMask) { 41664642e01fSmrg unsigned i; 4167f7df2e56Smrg XkbKeyTypePtr type; 4168f7df2e56Smrg CARD8 *width; 4169f7df2e56Smrg 4170f7df2e56Smrg if (stuff->nKTLevels < 1) { 4171f7df2e56Smrg client->errorValue = _XkbErrCode2(0x05, stuff->nKTLevels); 41724642e01fSmrg return BadValue; 41734642e01fSmrg } 4174f7df2e56Smrg if ((unsigned) (stuff->firstKTLevel + stuff->nKTLevels - 1) >= 4175f7df2e56Smrg xkb->map->num_types) { 4176f7df2e56Smrg client->errorValue = _XkbErrCode4(0x06, stuff->firstKTLevel, 4177f7df2e56Smrg stuff->nKTLevels, 4178f7df2e56Smrg xkb->map->num_types); 41794642e01fSmrg return BadValue; 41804642e01fSmrg } 4181f7df2e56Smrg width = (CARD8 *) tmp; 4182f7df2e56Smrg tmp = (CARD32 *) (((char *) tmp) + XkbPaddedSize(stuff->nKTLevels)); 4183806e81e9Smrg if (!_XkbCheckRequestBounds(client, stuff, width, tmp)) 4184806e81e9Smrg return BadLength; 41854642e01fSmrg type = &xkb->map->types[stuff->firstKTLevel]; 4186f7df2e56Smrg for (i = 0; i < stuff->nKTLevels; i++, type++) { 4187f7df2e56Smrg if (width[i] == 0) 41884642e01fSmrg continue; 4189f7df2e56Smrg else if (width[i] != type->num_levels) { 4190f7df2e56Smrg client->errorValue = _XkbErrCode4(0x07, i + stuff->firstKTLevel, 4191f7df2e56Smrg type->num_levels, width[i]); 41924642e01fSmrg return BadMatch; 41934642e01fSmrg } 4194806e81e9Smrg if (!_XkbCheckRequestBounds(client, stuff, tmp, tmp + width[i])) 4195806e81e9Smrg return BadLength; 4196f7df2e56Smrg tmp = _XkbCheckAtoms(tmp, width[i], client->swapped, &bad); 41974642e01fSmrg if (!tmp) { 4198f7df2e56Smrg client->errorValue = bad; 41994642e01fSmrg return BadAtom; 42004642e01fSmrg } 42014642e01fSmrg } 42024642e01fSmrg } 4203f7df2e56Smrg if (stuff->which & XkbIndicatorNamesMask) { 4204f7df2e56Smrg if (stuff->indicators == 0) { 4205f7df2e56Smrg client->errorValue = 0x08; 42064642e01fSmrg return BadMatch; 42074642e01fSmrg } 4208806e81e9Smrg if (!_XkbCheckRequestBounds(client, stuff, tmp, 4209806e81e9Smrg tmp + Ones(stuff->indicators))) 4210806e81e9Smrg return BadLength; 4211f7df2e56Smrg tmp = _XkbCheckMaskedAtoms(tmp, XkbNumIndicators, stuff->indicators, 4212f7df2e56Smrg client->swapped, &bad); 42134642e01fSmrg if (!tmp) { 4214f7df2e56Smrg client->errorValue = bad; 42154642e01fSmrg return BadAtom; 42164642e01fSmrg } 42174642e01fSmrg } 4218f7df2e56Smrg if (stuff->which & XkbVirtualModNamesMask) { 4219f7df2e56Smrg if (stuff->virtualMods == 0) { 4220f7df2e56Smrg client->errorValue = 0x09; 42214642e01fSmrg return BadMatch; 42224642e01fSmrg } 4223806e81e9Smrg if (!_XkbCheckRequestBounds(client, stuff, tmp, 4224806e81e9Smrg tmp + Ones(stuff->virtualMods))) 4225806e81e9Smrg return BadLength; 4226f7df2e56Smrg tmp = _XkbCheckMaskedAtoms(tmp, XkbNumVirtualMods, 4227f7df2e56Smrg (CARD32) stuff->virtualMods, 4228f7df2e56Smrg client->swapped, &bad); 42294642e01fSmrg if (!tmp) { 42304642e01fSmrg client->errorValue = bad; 42314642e01fSmrg return BadAtom; 42324642e01fSmrg } 42334642e01fSmrg } 4234f7df2e56Smrg if (stuff->which & XkbGroupNamesMask) { 4235f7df2e56Smrg if (stuff->groupNames == 0) { 4236f7df2e56Smrg client->errorValue = 0x0a; 42374642e01fSmrg return BadMatch; 42384642e01fSmrg } 4239806e81e9Smrg if (!_XkbCheckRequestBounds(client, stuff, tmp, 4240806e81e9Smrg tmp + Ones(stuff->groupNames))) 4241806e81e9Smrg return BadLength; 4242f7df2e56Smrg tmp = _XkbCheckMaskedAtoms(tmp, XkbNumKbdGroups, 4243f7df2e56Smrg (CARD32) stuff->groupNames, 4244f7df2e56Smrg client->swapped, &bad); 42454642e01fSmrg if (!tmp) { 42464642e01fSmrg client->errorValue = bad; 42474642e01fSmrg return BadAtom; 42484642e01fSmrg } 42494642e01fSmrg } 4250f7df2e56Smrg if (stuff->which & XkbKeyNamesMask) { 4251f7df2e56Smrg if (stuff->firstKey < (unsigned) xkb->min_key_code) { 4252f7df2e56Smrg client->errorValue = _XkbErrCode3(0x0b, xkb->min_key_code, 4253f7df2e56Smrg stuff->firstKey); 42544642e01fSmrg return BadValue; 42554642e01fSmrg } 4256f7df2e56Smrg if (((unsigned) (stuff->firstKey + stuff->nKeys - 1) > 4257f7df2e56Smrg xkb->max_key_code) || (stuff->nKeys < 1)) { 4258f7df2e56Smrg client->errorValue = 4259f7df2e56Smrg _XkbErrCode4(0x0c, xkb->max_key_code, stuff->firstKey, 4260f7df2e56Smrg stuff->nKeys); 42614642e01fSmrg return BadValue; 42624642e01fSmrg } 4263806e81e9Smrg if (!_XkbCheckRequestBounds(client, stuff, tmp, tmp + stuff->nKeys)) 4264806e81e9Smrg return BadLength; 4265f7df2e56Smrg tmp += stuff->nKeys; 42664642e01fSmrg } 4267f7df2e56Smrg if ((stuff->which & XkbKeyAliasesMask) && (stuff->nKeyAliases > 0)) { 4268806e81e9Smrg if (!_XkbCheckRequestBounds(client, stuff, tmp, 4269806e81e9Smrg tmp + (stuff->nKeyAliases * 2))) 4270806e81e9Smrg return BadLength; 4271f7df2e56Smrg tmp += stuff->nKeyAliases * 2; 42724642e01fSmrg } 4273f7df2e56Smrg if (stuff->which & XkbRGNamesMask) { 4274f7df2e56Smrg if (stuff->nRadioGroups < 1) { 4275f7df2e56Smrg client->errorValue = _XkbErrCode2(0x0d, stuff->nRadioGroups); 42764642e01fSmrg return BadValue; 42774642e01fSmrg } 4278806e81e9Smrg if (!_XkbCheckRequestBounds(client, stuff, tmp, 4279806e81e9Smrg tmp + stuff->nRadioGroups)) 4280806e81e9Smrg return BadLength; 4281f7df2e56Smrg tmp = _XkbCheckAtoms(tmp, stuff->nRadioGroups, client->swapped, &bad); 42824642e01fSmrg if (!tmp) { 4283f7df2e56Smrg client->errorValue = bad; 42844642e01fSmrg return BadAtom; 42854642e01fSmrg } 42864642e01fSmrg } 4287f7df2e56Smrg if ((tmp - ((CARD32 *) stuff)) != stuff->length) { 42884642e01fSmrg client->errorValue = stuff->length; 42894642e01fSmrg return BadLength; 42904642e01fSmrg } 42914642e01fSmrg 42924642e01fSmrg return Success; 42934642e01fSmrg} 42944642e01fSmrg 42954642e01fSmrgstatic int 4296f7df2e56Smrg_XkbSetNames(ClientPtr client, DeviceIntPtr dev, xkbSetNamesReq * stuff) 42974642e01fSmrg{ 4298f7df2e56Smrg XkbDescRec *xkb; 4299f7df2e56Smrg XkbNamesRec *names; 4300f7df2e56Smrg CARD32 *tmp; 4301f7df2e56Smrg xkbNamesNotify nn; 43024642e01fSmrg 4303f7df2e56Smrg tmp = (CARD32 *) &stuff[1]; 43044642e01fSmrg xkb = dev->key->xkbInfo->desc; 43054642e01fSmrg names = xkb->names; 43064642e01fSmrg 4307f7df2e56Smrg if (XkbAllocNames(xkb, stuff->which, stuff->nRadioGroups, 4308f7df2e56Smrg stuff->nKeyAliases) != Success) { 43094642e01fSmrg return BadAlloc; 43104642e01fSmrg } 43114642e01fSmrg 43126747b715Smrg memset(&nn, 0, sizeof(xkbNamesNotify)); 4313f7df2e56Smrg nn.changed = stuff->which; 4314f7df2e56Smrg tmp = (CARD32 *) &stuff[1]; 4315f7df2e56Smrg if (stuff->which & XkbKeycodesNameMask) 4316f7df2e56Smrg names->keycodes = *tmp++; 4317f7df2e56Smrg if (stuff->which & XkbGeometryNameMask) 4318f7df2e56Smrg names->geometry = *tmp++; 4319f7df2e56Smrg if (stuff->which & XkbSymbolsNameMask) 4320f7df2e56Smrg names->symbols = *tmp++; 4321f7df2e56Smrg if (stuff->which & XkbPhysSymbolsNameMask) 4322f7df2e56Smrg names->phys_symbols = *tmp++; 4323f7df2e56Smrg if (stuff->which & XkbTypesNameMask) 4324f7df2e56Smrg names->types = *tmp++; 4325f7df2e56Smrg if (stuff->which & XkbCompatNameMask) 4326f7df2e56Smrg names->compat = *tmp++; 4327f7df2e56Smrg if ((stuff->which & XkbKeyTypeNamesMask) && (stuff->nTypes > 0)) { 43284642e01fSmrg register unsigned i; 43294642e01fSmrg register XkbKeyTypePtr type; 43304642e01fSmrg 4331f7df2e56Smrg type = &xkb->map->types[stuff->firstType]; 4332f7df2e56Smrg for (i = 0; i < stuff->nTypes; i++, type++) { 4333f7df2e56Smrg type->name = *tmp++; 43344642e01fSmrg } 4335f7df2e56Smrg nn.firstType = stuff->firstType; 4336f7df2e56Smrg nn.nTypes = stuff->nTypes; 43374642e01fSmrg } 4338f7df2e56Smrg if (stuff->which & XkbKTLevelNamesMask) { 4339f7df2e56Smrg register XkbKeyTypePtr type; 43404642e01fSmrg register unsigned i; 43414642e01fSmrg CARD8 *width; 43424642e01fSmrg 4343f7df2e56Smrg width = (CARD8 *) tmp; 4344f7df2e56Smrg tmp = (CARD32 *) (((char *) tmp) + XkbPaddedSize(stuff->nKTLevels)); 4345f7df2e56Smrg type = &xkb->map->types[stuff->firstKTLevel]; 4346f7df2e56Smrg for (i = 0; i < stuff->nKTLevels; i++, type++) { 4347f7df2e56Smrg if (width[i] > 0) { 43484642e01fSmrg if (type->level_names) { 43494642e01fSmrg register unsigned n; 4350f7df2e56Smrg 4351f7df2e56Smrg for (n = 0; n < width[i]; n++) { 4352f7df2e56Smrg type->level_names[n] = tmp[n]; 43534642e01fSmrg } 43544642e01fSmrg } 4355f7df2e56Smrg tmp += width[i]; 43564642e01fSmrg } 43574642e01fSmrg } 4358f7df2e56Smrg nn.firstLevelName = 0; 4359f7df2e56Smrg nn.nLevelNames = stuff->nTypes; 4360f7df2e56Smrg } 4361f7df2e56Smrg if (stuff->which & XkbIndicatorNamesMask) { 4362f7df2e56Smrg tmp = _XkbCopyMaskedAtoms(tmp, names->indicators, XkbNumIndicators, 4363f7df2e56Smrg stuff->indicators); 4364f7df2e56Smrg nn.changedIndicators = stuff->indicators; 4365f7df2e56Smrg } 4366f7df2e56Smrg if (stuff->which & XkbVirtualModNamesMask) { 4367f7df2e56Smrg tmp = _XkbCopyMaskedAtoms(tmp, names->vmods, XkbNumVirtualMods, 4368f7df2e56Smrg stuff->virtualMods); 4369f7df2e56Smrg nn.changedVirtualMods = stuff->virtualMods; 4370f7df2e56Smrg } 4371f7df2e56Smrg if (stuff->which & XkbGroupNamesMask) { 4372f7df2e56Smrg tmp = _XkbCopyMaskedAtoms(tmp, names->groups, XkbNumKbdGroups, 4373f7df2e56Smrg stuff->groupNames); 4374f7df2e56Smrg nn.changedVirtualMods = stuff->groupNames; 4375f7df2e56Smrg } 4376f7df2e56Smrg if (stuff->which & XkbKeyNamesMask) { 4377f7df2e56Smrg memcpy((char *) &names->keys[stuff->firstKey], (char *) tmp, 4378f7df2e56Smrg stuff->nKeys * XkbKeyNameLength); 4379f7df2e56Smrg tmp += stuff->nKeys; 4380f7df2e56Smrg nn.firstKey = stuff->firstKey; 4381f7df2e56Smrg nn.nKeys = stuff->nKeys; 4382f7df2e56Smrg } 4383f7df2e56Smrg if (stuff->which & XkbKeyAliasesMask) { 4384f7df2e56Smrg if (stuff->nKeyAliases > 0) { 4385f7df2e56Smrg register int na = stuff->nKeyAliases; 4386f7df2e56Smrg 4387f7df2e56Smrg if (XkbAllocNames(xkb, XkbKeyAliasesMask, 0, na) != Success) 43884642e01fSmrg return BadAlloc; 4389f7df2e56Smrg memcpy((char *) names->key_aliases, (char *) tmp, 4390f7df2e56Smrg stuff->nKeyAliases * sizeof(XkbKeyAliasRec)); 4391f7df2e56Smrg tmp += stuff->nKeyAliases * 2; 43924642e01fSmrg } 4393f7df2e56Smrg else if (names->key_aliases != NULL) { 43946747b715Smrg free(names->key_aliases); 4395f7df2e56Smrg names->key_aliases = NULL; 4396f7df2e56Smrg names->num_key_aliases = 0; 43974642e01fSmrg } 4398f7df2e56Smrg nn.nAliases = names->num_key_aliases; 43994642e01fSmrg } 4400f7df2e56Smrg if (stuff->which & XkbRGNamesMask) { 4401f7df2e56Smrg if (stuff->nRadioGroups > 0) { 4402f7df2e56Smrg register unsigned i, nrg; 4403f7df2e56Smrg 4404f7df2e56Smrg nrg = stuff->nRadioGroups; 4405f7df2e56Smrg if (XkbAllocNames(xkb, XkbRGNamesMask, nrg, 0) != Success) 44064642e01fSmrg return BadAlloc; 44074642e01fSmrg 4408f7df2e56Smrg for (i = 0; i < stuff->nRadioGroups; i++) { 4409f7df2e56Smrg names->radio_groups[i] = tmp[i]; 44104642e01fSmrg } 4411f7df2e56Smrg tmp += stuff->nRadioGroups; 44124642e01fSmrg } 44134642e01fSmrg else if (names->radio_groups) { 44146747b715Smrg free(names->radio_groups); 4415f7df2e56Smrg names->radio_groups = NULL; 4416f7df2e56Smrg names->num_rg = 0; 44174642e01fSmrg } 4418f7df2e56Smrg nn.nRadioGroups = names->num_rg; 44194642e01fSmrg } 44204642e01fSmrg if (nn.changed) { 44214642e01fSmrg Bool needExtEvent; 4422f7df2e56Smrg 4423f7df2e56Smrg needExtEvent = (nn.changed & XkbIndicatorNamesMask) != 0; 4424f7df2e56Smrg XkbSendNamesNotify(dev, &nn); 44254642e01fSmrg if (needExtEvent) { 4426f7df2e56Smrg XkbSrvLedInfoPtr sli; 4427f7df2e56Smrg xkbExtensionDeviceNotify edev; 4428f7df2e56Smrg register int i; 4429f7df2e56Smrg register unsigned bit; 4430f7df2e56Smrg 4431f7df2e56Smrg sli = XkbFindSrvLedInfo(dev, XkbDfltXIClass, XkbDfltXIId, 4432f7df2e56Smrg XkbXI_IndicatorsMask); 4433f7df2e56Smrg sli->namesPresent = 0; 4434f7df2e56Smrg for (i = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) { 4435f7df2e56Smrg if (names->indicators[i] != None) 4436f7df2e56Smrg sli->namesPresent |= bit; 44374642e01fSmrg } 44386747b715Smrg memset(&edev, 0, sizeof(xkbExtensionDeviceNotify)); 4439f7df2e56Smrg edev.reason = XkbXI_IndicatorNamesMask; 4440f7df2e56Smrg edev.ledClass = KbdFeedbackClass; 4441f7df2e56Smrg edev.ledID = dev->kbdfeed->ctrl.id; 4442f7df2e56Smrg edev.ledsDefined = sli->namesPresent | sli->mapsPresent; 4443f7df2e56Smrg edev.ledState = sli->effectiveState; 4444f7df2e56Smrg edev.firstBtn = 0; 4445f7df2e56Smrg edev.nBtns = 0; 4446f7df2e56Smrg edev.supported = XkbXI_AllFeaturesMask; 4447f7df2e56Smrg edev.unsupported = 0; 4448f7df2e56Smrg XkbSendExtensionDeviceNotify(dev, client, &edev); 44494642e01fSmrg } 44504642e01fSmrg } 44514642e01fSmrg return Success; 44524642e01fSmrg} 44534642e01fSmrg 44544642e01fSmrgint 44554642e01fSmrgProcXkbSetNames(ClientPtr client) 44564642e01fSmrg{ 4457f7df2e56Smrg DeviceIntPtr dev; 4458f7df2e56Smrg CARD32 *tmp; 4459f7df2e56Smrg Atom bad; 4460f7df2e56Smrg int rc; 44614642e01fSmrg 446205b261ecSmrg REQUEST(xkbSetNamesReq); 446305b261ecSmrg REQUEST_AT_LEAST_SIZE(xkbSetNamesReq); 446405b261ecSmrg 4465f7df2e56Smrg if (!(client->xkbClientFlags & _XkbClientInitialized)) 4466f7df2e56Smrg return BadAccess; 446705b261ecSmrg 44684642e01fSmrg CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess); 4469f7df2e56Smrg CHK_MASK_LEGAL(0x01, stuff->which, XkbAllNamesMask); 447005b261ecSmrg 44714642e01fSmrg /* check device-independent stuff */ 4472f7df2e56Smrg tmp = (CARD32 *) &stuff[1]; 4473f7df2e56Smrg 4474806e81e9Smrg if (!_XkbCheckRequestBounds(client, stuff, tmp, tmp + 1)) 4475806e81e9Smrg return BadLength; 4476f7df2e56Smrg if (stuff->which & XkbKeycodesNameMask) { 4477f7df2e56Smrg tmp = _XkbCheckAtoms(tmp, 1, client->swapped, &bad); 4478f7df2e56Smrg if (!tmp) { 4479f7df2e56Smrg client->errorValue = bad; 4480f7df2e56Smrg return BadAtom; 4481f7df2e56Smrg } 4482f7df2e56Smrg } 4483806e81e9Smrg if (!_XkbCheckRequestBounds(client, stuff, tmp, tmp + 1)) 4484806e81e9Smrg return BadLength; 4485f7df2e56Smrg if (stuff->which & XkbGeometryNameMask) { 4486f7df2e56Smrg tmp = _XkbCheckAtoms(tmp, 1, client->swapped, &bad); 4487f7df2e56Smrg if (!tmp) { 4488f7df2e56Smrg client->errorValue = bad; 4489f7df2e56Smrg return BadAtom; 4490f7df2e56Smrg } 4491f7df2e56Smrg } 4492806e81e9Smrg if (!_XkbCheckRequestBounds(client, stuff, tmp, tmp + 1)) 4493806e81e9Smrg return BadLength; 4494f7df2e56Smrg if (stuff->which & XkbSymbolsNameMask) { 4495f7df2e56Smrg tmp = _XkbCheckAtoms(tmp, 1, client->swapped, &bad); 4496f7df2e56Smrg if (!tmp) { 4497f7df2e56Smrg client->errorValue = bad; 4498f7df2e56Smrg return BadAtom; 4499f7df2e56Smrg } 4500f7df2e56Smrg } 4501806e81e9Smrg if (!_XkbCheckRequestBounds(client, stuff, tmp, tmp + 1)) 4502806e81e9Smrg return BadLength; 4503f7df2e56Smrg if (stuff->which & XkbPhysSymbolsNameMask) { 4504f7df2e56Smrg tmp = _XkbCheckAtoms(tmp, 1, client->swapped, &bad); 4505f7df2e56Smrg if (!tmp) { 4506f7df2e56Smrg client->errorValue = bad; 4507f7df2e56Smrg return BadAtom; 4508f7df2e56Smrg } 4509f7df2e56Smrg } 4510806e81e9Smrg if (!_XkbCheckRequestBounds(client, stuff, tmp, tmp + 1)) 4511806e81e9Smrg return BadLength; 4512f7df2e56Smrg if (stuff->which & XkbTypesNameMask) { 4513f7df2e56Smrg tmp = _XkbCheckAtoms(tmp, 1, client->swapped, &bad); 4514f7df2e56Smrg if (!tmp) { 4515f7df2e56Smrg client->errorValue = bad; 4516f7df2e56Smrg return BadAtom; 4517f7df2e56Smrg } 4518f7df2e56Smrg } 4519806e81e9Smrg if (!_XkbCheckRequestBounds(client, stuff, tmp, tmp + 1)) 4520806e81e9Smrg return BadLength; 4521f7df2e56Smrg if (stuff->which & XkbCompatNameMask) { 4522f7df2e56Smrg tmp = _XkbCheckAtoms(tmp, 1, client->swapped, &bad); 4523f7df2e56Smrg if (!tmp) { 4524f7df2e56Smrg client->errorValue = bad; 4525f7df2e56Smrg return BadAtom; 4526f7df2e56Smrg } 452705b261ecSmrg } 45284642e01fSmrg 45294642e01fSmrg /* start of device-dependent tests */ 45304642e01fSmrg rc = _XkbSetNamesCheck(client, dev, stuff, tmp); 45314642e01fSmrg if (rc != Success) 45324642e01fSmrg return rc; 45334642e01fSmrg 4534f7df2e56Smrg if (stuff->deviceSpec == XkbUseCoreKbd) { 45354642e01fSmrg DeviceIntPtr other; 45364642e01fSmrg 4537f7df2e56Smrg for (other = inputInfo.devices; other; other = other->next) { 4538f7df2e56Smrg if ((other != dev) && other->key && !IsMaster(other) && 4539f7df2e56Smrg GetMaster(other, MASTER_KEYBOARD) == dev) { 4540f7df2e56Smrg 4541f7df2e56Smrg rc = XaceHook(XACE_DEVICE_ACCESS, client, other, 4542f7df2e56Smrg DixManageAccess); 4543f7df2e56Smrg if (rc == Success) { 45444642e01fSmrg rc = _XkbSetNamesCheck(client, other, stuff, tmp); 45454642e01fSmrg if (rc != Success) 45464642e01fSmrg return rc; 45474642e01fSmrg } 45484642e01fSmrg } 45494642e01fSmrg } 455005b261ecSmrg } 455105b261ecSmrg 455205b261ecSmrg /* everything is okay -- update names */ 455305b261ecSmrg 45544642e01fSmrg rc = _XkbSetNames(client, dev, stuff); 45554642e01fSmrg if (rc != Success) 45564642e01fSmrg return rc; 455705b261ecSmrg 4558f7df2e56Smrg if (stuff->deviceSpec == XkbUseCoreKbd) { 45594642e01fSmrg DeviceIntPtr other; 45604642e01fSmrg 4561f7df2e56Smrg for (other = inputInfo.devices; other; other = other->next) { 4562f7df2e56Smrg if ((other != dev) && other->key && !IsMaster(other) && 4563f7df2e56Smrg GetMaster(other, MASTER_KEYBOARD) == dev) { 4564f7df2e56Smrg 4565f7df2e56Smrg rc = XaceHook(XACE_DEVICE_ACCESS, client, other, 4566f7df2e56Smrg DixManageAccess); 45674642e01fSmrg if (rc == Success) 45684642e01fSmrg _XkbSetNames(client, other, stuff); 45694642e01fSmrg } 45704642e01fSmrg } 457105b261ecSmrg } 45724642e01fSmrg 45734642e01fSmrg /* everything is okay -- update names */ 45744642e01fSmrg 45756747b715Smrg return Success; 457605b261ecSmrg} 457705b261ecSmrg 457805b261ecSmrg/***====================================================================***/ 457905b261ecSmrg 45804642e01fSmrg#include "xkbgeom.h" 458105b261ecSmrg 458205b261ecSmrg#define XkbSizeCountedString(s) ((s)?((((2+strlen(s))+3)/4)*4):4) 458305b261ecSmrg 4584f7df2e56Smrg/** 4585f7df2e56Smrg * Write the zero-terminated string str into wire as a pascal string with a 4586f7df2e56Smrg * 16-bit length field prefixed before the actual string. 4587f7df2e56Smrg * 4588f7df2e56Smrg * @param wire The destination array, usually the wire struct 4589f7df2e56Smrg * @param str The source string as zero-terminated C string 4590f7df2e56Smrg * @param swap If TRUE, the length field is swapped. 4591f7df2e56Smrg * 4592f7df2e56Smrg * @return The input string in the format <string length><string> with a 4593f7df2e56Smrg * (swapped) 16 bit string length, non-zero terminated. 4594f7df2e56Smrg */ 459505b261ecSmrgstatic char * 4596f7df2e56SmrgXkbWriteCountedString(char *wire, const char *str, Bool swap) 459705b261ecSmrg{ 4598f7df2e56Smrg CARD16 len, *pLen, paddedLen; 459905b261ecSmrg 46006747b715Smrg if (!str) 46016747b715Smrg return wire; 46026747b715Smrg 4603f7df2e56Smrg len = strlen(str); 4604f7df2e56Smrg pLen = (CARD16 *) wire; 4605f7df2e56Smrg *pLen = len; 460605b261ecSmrg if (swap) { 4607f7df2e56Smrg swaps(pLen); 460805b261ecSmrg } 4609f7df2e56Smrg paddedLen = pad_to_int32(sizeof(len) + len) - sizeof(len); 4610f7df2e56Smrg strncpy(&wire[sizeof(len)], str, paddedLen); 4611f7df2e56Smrg wire += sizeof(len) + paddedLen; 461205b261ecSmrg return wire; 461305b261ecSmrg} 461405b261ecSmrg 461505b261ecSmrgstatic int 461605b261ecSmrgXkbSizeGeomProperties(XkbGeometryPtr geom) 461705b261ecSmrg{ 4618f7df2e56Smrg register int i, size; 4619f7df2e56Smrg XkbPropertyPtr prop; 4620f7df2e56Smrg 4621f7df2e56Smrg for (size = i = 0, prop = geom->properties; i < geom->num_properties; 4622f7df2e56Smrg i++, prop++) { 4623f7df2e56Smrg size += XkbSizeCountedString(prop->name); 4624f7df2e56Smrg size += XkbSizeCountedString(prop->value); 462505b261ecSmrg } 462605b261ecSmrg return size; 462705b261ecSmrg} 462805b261ecSmrg 462905b261ecSmrgstatic char * 4630f7df2e56SmrgXkbWriteGeomProperties(char *wire, XkbGeometryPtr geom, Bool swap) 463105b261ecSmrg{ 4632f7df2e56Smrg register int i; 4633f7df2e56Smrg register XkbPropertyPtr prop; 4634f7df2e56Smrg 4635f7df2e56Smrg for (i = 0, prop = geom->properties; i < geom->num_properties; i++, prop++) { 4636f7df2e56Smrg wire = XkbWriteCountedString(wire, prop->name, swap); 4637f7df2e56Smrg wire = XkbWriteCountedString(wire, prop->value, swap); 463805b261ecSmrg } 463905b261ecSmrg return wire; 464005b261ecSmrg} 464105b261ecSmrg 464205b261ecSmrgstatic int 464305b261ecSmrgXkbSizeGeomKeyAliases(XkbGeometryPtr geom) 464405b261ecSmrg{ 4645f7df2e56Smrg return geom->num_key_aliases * (2 * XkbKeyNameLength); 464605b261ecSmrg} 464705b261ecSmrg 464805b261ecSmrgstatic char * 4649f7df2e56SmrgXkbWriteGeomKeyAliases(char *wire, XkbGeometryPtr geom, Bool swap) 465005b261ecSmrg{ 4651f7df2e56Smrg register int sz; 4652f7df2e56Smrg 4653f7df2e56Smrg sz = geom->num_key_aliases * (XkbKeyNameLength * 2); 4654f7df2e56Smrg if (sz > 0) { 4655f7df2e56Smrg memcpy(wire, (char *) geom->key_aliases, sz); 4656f7df2e56Smrg wire += sz; 465705b261ecSmrg } 465805b261ecSmrg return wire; 465905b261ecSmrg} 466005b261ecSmrg 466105b261ecSmrgstatic int 466205b261ecSmrgXkbSizeGeomColors(XkbGeometryPtr geom) 466305b261ecSmrg{ 4664f7df2e56Smrg register int i, size; 4665f7df2e56Smrg register XkbColorPtr color; 466605b261ecSmrg 4667f7df2e56Smrg for (i = size = 0, color = geom->colors; i < geom->num_colors; i++, color++) { 4668f7df2e56Smrg size += XkbSizeCountedString(color->spec); 466905b261ecSmrg } 467005b261ecSmrg return size; 467105b261ecSmrg} 467205b261ecSmrg 467305b261ecSmrgstatic char * 4674f7df2e56SmrgXkbWriteGeomColors(char *wire, XkbGeometryPtr geom, Bool swap) 467505b261ecSmrg{ 4676f7df2e56Smrg register int i; 4677f7df2e56Smrg register XkbColorPtr color; 467805b261ecSmrg 4679f7df2e56Smrg for (i = 0, color = geom->colors; i < geom->num_colors; i++, color++) { 4680f7df2e56Smrg wire = XkbWriteCountedString(wire, color->spec, swap); 468105b261ecSmrg } 468205b261ecSmrg return wire; 468305b261ecSmrg} 468405b261ecSmrg 468505b261ecSmrgstatic int 468605b261ecSmrgXkbSizeGeomShapes(XkbGeometryPtr geom) 468705b261ecSmrg{ 4688f7df2e56Smrg register int i, size; 4689f7df2e56Smrg register XkbShapePtr shape; 4690f7df2e56Smrg 4691f7df2e56Smrg for (i = size = 0, shape = geom->shapes; i < geom->num_shapes; i++, shape++) { 4692f7df2e56Smrg register int n; 4693f7df2e56Smrg register XkbOutlinePtr ol; 4694f7df2e56Smrg 4695f7df2e56Smrg size += SIZEOF(xkbShapeWireDesc); 4696f7df2e56Smrg for (n = 0, ol = shape->outlines; n < shape->num_outlines; n++, ol++) { 4697f7df2e56Smrg size += SIZEOF(xkbOutlineWireDesc); 4698f7df2e56Smrg size += ol->num_points * SIZEOF(xkbPointWireDesc); 4699f7df2e56Smrg } 470005b261ecSmrg } 470105b261ecSmrg return size; 470205b261ecSmrg} 470305b261ecSmrg 470405b261ecSmrgstatic char * 4705f7df2e56SmrgXkbWriteGeomShapes(char *wire, XkbGeometryPtr geom, Bool swap) 470605b261ecSmrg{ 4707f7df2e56Smrg int i; 4708f7df2e56Smrg XkbShapePtr shape; 4709f7df2e56Smrg xkbShapeWireDesc *shapeWire; 4710f7df2e56Smrg 4711f7df2e56Smrg for (i = 0, shape = geom->shapes; i < geom->num_shapes; i++, shape++) { 4712f7df2e56Smrg register int o; 4713f7df2e56Smrg XkbOutlinePtr ol; 4714f7df2e56Smrg xkbOutlineWireDesc *olWire; 4715f7df2e56Smrg 4716f7df2e56Smrg shapeWire = (xkbShapeWireDesc *) wire; 4717f7df2e56Smrg shapeWire->name = shape->name; 4718f7df2e56Smrg shapeWire->nOutlines = shape->num_outlines; 4719f7df2e56Smrg if (shape->primary != NULL) 4720f7df2e56Smrg shapeWire->primaryNdx = XkbOutlineIndex(shape, shape->primary); 4721f7df2e56Smrg else 4722f7df2e56Smrg shapeWire->primaryNdx = XkbNoShape; 4723f7df2e56Smrg if (shape->approx != NULL) 4724f7df2e56Smrg shapeWire->approxNdx = XkbOutlineIndex(shape, shape->approx); 4725f7df2e56Smrg else 4726f7df2e56Smrg shapeWire->approxNdx = XkbNoShape; 4727f7df2e56Smrg shapeWire->pad = 0; 4728f7df2e56Smrg if (swap) { 4729f7df2e56Smrg swapl(&shapeWire->name); 4730f7df2e56Smrg } 4731f7df2e56Smrg wire = (char *) &shapeWire[1]; 4732f7df2e56Smrg for (o = 0, ol = shape->outlines; o < shape->num_outlines; o++, ol++) { 4733f7df2e56Smrg register int p; 4734f7df2e56Smrg XkbPointPtr pt; 4735f7df2e56Smrg xkbPointWireDesc *ptWire; 4736f7df2e56Smrg 4737f7df2e56Smrg olWire = (xkbOutlineWireDesc *) wire; 4738f7df2e56Smrg olWire->nPoints = ol->num_points; 4739f7df2e56Smrg olWire->cornerRadius = ol->corner_radius; 4740f7df2e56Smrg olWire->pad = 0; 4741f7df2e56Smrg wire = (char *) &olWire[1]; 4742f7df2e56Smrg ptWire = (xkbPointWireDesc *) wire; 4743f7df2e56Smrg for (p = 0, pt = ol->points; p < ol->num_points; p++, pt++) { 4744f7df2e56Smrg ptWire[p].x = pt->x; 4745f7df2e56Smrg ptWire[p].y = pt->y; 4746f7df2e56Smrg if (swap) { 4747f7df2e56Smrg swaps(&ptWire[p].x); 4748f7df2e56Smrg swaps(&ptWire[p].y); 4749f7df2e56Smrg } 4750f7df2e56Smrg } 4751f7df2e56Smrg wire = (char *) &ptWire[ol->num_points]; 4752f7df2e56Smrg } 475305b261ecSmrg } 475405b261ecSmrg return wire; 475505b261ecSmrg} 475605b261ecSmrg 475705b261ecSmrgstatic int 4758f7df2e56SmrgXkbSizeGeomDoodads(int num_doodads, XkbDoodadPtr doodad) 475905b261ecSmrg{ 4760f7df2e56Smrg register int i, size; 4761f7df2e56Smrg 4762f7df2e56Smrg for (i = size = 0; i < num_doodads; i++, doodad++) { 4763f7df2e56Smrg size += SIZEOF(xkbAnyDoodadWireDesc); 4764f7df2e56Smrg if (doodad->any.type == XkbTextDoodad) { 4765f7df2e56Smrg size += XkbSizeCountedString(doodad->text.text); 4766f7df2e56Smrg size += XkbSizeCountedString(doodad->text.font); 4767f7df2e56Smrg } 4768f7df2e56Smrg else if (doodad->any.type == XkbLogoDoodad) { 4769f7df2e56Smrg size += XkbSizeCountedString(doodad->logo.logo_name); 4770f7df2e56Smrg } 477105b261ecSmrg } 477205b261ecSmrg return size; 477305b261ecSmrg} 477405b261ecSmrg 477505b261ecSmrgstatic char * 4776f7df2e56SmrgXkbWriteGeomDoodads(char *wire, int num_doodads, XkbDoodadPtr doodad, Bool swap) 477705b261ecSmrg{ 4778f7df2e56Smrg register int i; 4779f7df2e56Smrg xkbDoodadWireDesc *doodadWire; 4780f7df2e56Smrg 4781f7df2e56Smrg for (i = 0; i < num_doodads; i++, doodad++) { 4782f7df2e56Smrg doodadWire = (xkbDoodadWireDesc *) wire; 4783f7df2e56Smrg wire = (char *) &doodadWire[1]; 4784f7df2e56Smrg memset(doodadWire, 0, SIZEOF(xkbDoodadWireDesc)); 4785f7df2e56Smrg doodadWire->any.name = doodad->any.name; 4786f7df2e56Smrg doodadWire->any.type = doodad->any.type; 4787f7df2e56Smrg doodadWire->any.priority = doodad->any.priority; 4788f7df2e56Smrg doodadWire->any.top = doodad->any.top; 4789f7df2e56Smrg doodadWire->any.left = doodad->any.left; 4790f7df2e56Smrg if (swap) { 4791f7df2e56Smrg swapl(&doodadWire->any.name); 4792f7df2e56Smrg swaps(&doodadWire->any.top); 4793f7df2e56Smrg swaps(&doodadWire->any.left); 4794f7df2e56Smrg } 4795f7df2e56Smrg switch (doodad->any.type) { 4796f7df2e56Smrg case XkbOutlineDoodad: 4797f7df2e56Smrg case XkbSolidDoodad: 4798f7df2e56Smrg doodadWire->shape.angle = doodad->shape.angle; 4799f7df2e56Smrg doodadWire->shape.colorNdx = doodad->shape.color_ndx; 4800f7df2e56Smrg doodadWire->shape.shapeNdx = doodad->shape.shape_ndx; 4801f7df2e56Smrg if (swap) { 4802f7df2e56Smrg swaps(&doodadWire->shape.angle); 4803f7df2e56Smrg } 4804f7df2e56Smrg break; 4805f7df2e56Smrg case XkbTextDoodad: 4806f7df2e56Smrg doodadWire->text.angle = doodad->text.angle; 4807f7df2e56Smrg doodadWire->text.width = doodad->text.width; 4808f7df2e56Smrg doodadWire->text.height = doodad->text.height; 4809f7df2e56Smrg doodadWire->text.colorNdx = doodad->text.color_ndx; 4810f7df2e56Smrg if (swap) { 4811f7df2e56Smrg swaps(&doodadWire->text.angle); 4812f7df2e56Smrg swaps(&doodadWire->text.width); 4813f7df2e56Smrg swaps(&doodadWire->text.height); 4814f7df2e56Smrg } 4815f7df2e56Smrg wire = XkbWriteCountedString(wire, doodad->text.text, swap); 4816f7df2e56Smrg wire = XkbWriteCountedString(wire, doodad->text.font, swap); 4817f7df2e56Smrg break; 4818f7df2e56Smrg case XkbIndicatorDoodad: 4819f7df2e56Smrg doodadWire->indicator.shapeNdx = doodad->indicator.shape_ndx; 4820f7df2e56Smrg doodadWire->indicator.onColorNdx = doodad->indicator.on_color_ndx; 4821f7df2e56Smrg doodadWire->indicator.offColorNdx = doodad->indicator.off_color_ndx; 4822f7df2e56Smrg break; 4823f7df2e56Smrg case XkbLogoDoodad: 4824f7df2e56Smrg doodadWire->logo.angle = doodad->logo.angle; 4825f7df2e56Smrg doodadWire->logo.colorNdx = doodad->logo.color_ndx; 4826f7df2e56Smrg doodadWire->logo.shapeNdx = doodad->logo.shape_ndx; 4827f7df2e56Smrg wire = XkbWriteCountedString(wire, doodad->logo.logo_name, swap); 4828f7df2e56Smrg break; 4829f7df2e56Smrg default: 4830f7df2e56Smrg ErrorF("[xkb] Unknown doodad type %d in XkbWriteGeomDoodads\n", 4831f7df2e56Smrg doodad->any.type); 4832f7df2e56Smrg ErrorF("[xkb] Ignored\n"); 4833f7df2e56Smrg break; 4834f7df2e56Smrg } 483505b261ecSmrg } 483605b261ecSmrg return wire; 483705b261ecSmrg} 483805b261ecSmrg 483905b261ecSmrgstatic char * 4840f7df2e56SmrgXkbWriteGeomOverlay(char *wire, XkbOverlayPtr ol, Bool swap) 484105b261ecSmrg{ 4842f7df2e56Smrg register int r; 4843f7df2e56Smrg XkbOverlayRowPtr row; 4844f7df2e56Smrg xkbOverlayWireDesc *olWire; 4845f7df2e56Smrg 4846f7df2e56Smrg olWire = (xkbOverlayWireDesc *) wire; 4847f7df2e56Smrg olWire->name = ol->name; 4848f7df2e56Smrg olWire->nRows = ol->num_rows; 4849f7df2e56Smrg olWire->pad1 = 0; 4850f7df2e56Smrg olWire->pad2 = 0; 4851f7df2e56Smrg if (swap) { 4852f7df2e56Smrg swapl(&olWire->name); 4853f7df2e56Smrg } 4854f7df2e56Smrg wire = (char *) &olWire[1]; 4855f7df2e56Smrg for (r = 0, row = ol->rows; r < ol->num_rows; r++, row++) { 4856f7df2e56Smrg unsigned int k; 4857f7df2e56Smrg XkbOverlayKeyPtr key; 4858f7df2e56Smrg xkbOverlayRowWireDesc *rowWire; 4859f7df2e56Smrg 4860f7df2e56Smrg rowWire = (xkbOverlayRowWireDesc *) wire; 4861f7df2e56Smrg rowWire->rowUnder = row->row_under; 4862f7df2e56Smrg rowWire->nKeys = row->num_keys; 4863f7df2e56Smrg rowWire->pad1 = 0; 4864f7df2e56Smrg wire = (char *) &rowWire[1]; 4865f7df2e56Smrg for (k = 0, key = row->keys; k < row->num_keys; k++, key++) { 4866f7df2e56Smrg xkbOverlayKeyWireDesc *keyWire; 4867f7df2e56Smrg 4868f7df2e56Smrg keyWire = (xkbOverlayKeyWireDesc *) wire; 4869f7df2e56Smrg memcpy(keyWire->over, key->over.name, XkbKeyNameLength); 4870f7df2e56Smrg memcpy(keyWire->under, key->under.name, XkbKeyNameLength); 4871f7df2e56Smrg wire = (char *) &keyWire[1]; 4872f7df2e56Smrg } 4873f7df2e56Smrg } 4874f7df2e56Smrg return wire; 487505b261ecSmrg} 487605b261ecSmrg 487705b261ecSmrgstatic int 487805b261ecSmrgXkbSizeGeomSections(XkbGeometryPtr geom) 487905b261ecSmrg{ 4880f7df2e56Smrg register int i, size; 4881f7df2e56Smrg XkbSectionPtr section; 4882f7df2e56Smrg 4883f7df2e56Smrg for (i = size = 0, section = geom->sections; i < geom->num_sections; 4884f7df2e56Smrg i++, section++) { 4885f7df2e56Smrg size += SIZEOF(xkbSectionWireDesc); 4886f7df2e56Smrg if (section->rows) { 4887f7df2e56Smrg int r; 4888f7df2e56Smrg XkbRowPtr row; 4889f7df2e56Smrg 4890f7df2e56Smrg for (r = 0, row = section->rows; r < section->num_rows; row++, r++) { 4891f7df2e56Smrg size += SIZEOF(xkbRowWireDesc); 4892f7df2e56Smrg size += row->num_keys * SIZEOF(xkbKeyWireDesc); 4893f7df2e56Smrg } 4894f7df2e56Smrg } 4895f7df2e56Smrg if (section->doodads) 4896f7df2e56Smrg size += XkbSizeGeomDoodads(section->num_doodads, section->doodads); 4897f7df2e56Smrg if (section->overlays) { 4898f7df2e56Smrg int o; 4899f7df2e56Smrg XkbOverlayPtr ol; 4900f7df2e56Smrg 4901f7df2e56Smrg for (o = 0, ol = section->overlays; o < section->num_overlays; 4902f7df2e56Smrg o++, ol++) { 4903f7df2e56Smrg int r; 4904f7df2e56Smrg XkbOverlayRowPtr row; 4905f7df2e56Smrg 4906f7df2e56Smrg size += SIZEOF(xkbOverlayWireDesc); 4907f7df2e56Smrg for (r = 0, row = ol->rows; r < ol->num_rows; r++, row++) { 4908f7df2e56Smrg size += SIZEOF(xkbOverlayRowWireDesc); 4909f7df2e56Smrg size += row->num_keys * SIZEOF(xkbOverlayKeyWireDesc); 4910f7df2e56Smrg } 4911f7df2e56Smrg } 4912f7df2e56Smrg } 491305b261ecSmrg } 491405b261ecSmrg return size; 491505b261ecSmrg} 491605b261ecSmrg 491705b261ecSmrgstatic char * 4918f7df2e56SmrgXkbWriteGeomSections(char *wire, XkbGeometryPtr geom, Bool swap) 491905b261ecSmrg{ 4920f7df2e56Smrg register int i; 4921f7df2e56Smrg XkbSectionPtr section; 4922f7df2e56Smrg xkbSectionWireDesc *sectionWire; 4923f7df2e56Smrg 4924f7df2e56Smrg for (i = 0, section = geom->sections; i < geom->num_sections; 4925f7df2e56Smrg i++, section++) { 4926f7df2e56Smrg sectionWire = (xkbSectionWireDesc *) wire; 4927f7df2e56Smrg sectionWire->name = section->name; 4928f7df2e56Smrg sectionWire->top = section->top; 4929f7df2e56Smrg sectionWire->left = section->left; 4930f7df2e56Smrg sectionWire->width = section->width; 4931f7df2e56Smrg sectionWire->height = section->height; 4932f7df2e56Smrg sectionWire->angle = section->angle; 4933f7df2e56Smrg sectionWire->priority = section->priority; 4934f7df2e56Smrg sectionWire->nRows = section->num_rows; 4935f7df2e56Smrg sectionWire->nDoodads = section->num_doodads; 4936f7df2e56Smrg sectionWire->nOverlays = section->num_overlays; 4937f7df2e56Smrg sectionWire->pad = 0; 4938f7df2e56Smrg if (swap) { 4939f7df2e56Smrg swapl(§ionWire->name); 4940f7df2e56Smrg swaps(§ionWire->top); 4941f7df2e56Smrg swaps(§ionWire->left); 4942f7df2e56Smrg swaps(§ionWire->width); 4943f7df2e56Smrg swaps(§ionWire->height); 4944f7df2e56Smrg swaps(§ionWire->angle); 4945f7df2e56Smrg } 4946f7df2e56Smrg wire = (char *) §ionWire[1]; 4947f7df2e56Smrg if (section->rows) { 4948f7df2e56Smrg int r; 4949f7df2e56Smrg XkbRowPtr row; 4950f7df2e56Smrg xkbRowWireDesc *rowWire; 4951f7df2e56Smrg 4952f7df2e56Smrg for (r = 0, row = section->rows; r < section->num_rows; r++, row++) { 4953f7df2e56Smrg rowWire = (xkbRowWireDesc *) wire; 4954f7df2e56Smrg rowWire->top = row->top; 4955f7df2e56Smrg rowWire->left = row->left; 4956f7df2e56Smrg rowWire->nKeys = row->num_keys; 4957f7df2e56Smrg rowWire->vertical = row->vertical; 4958f7df2e56Smrg rowWire->pad = 0; 4959f7df2e56Smrg if (swap) { 4960f7df2e56Smrg swaps(&rowWire->top); 4961f7df2e56Smrg swaps(&rowWire->left); 4962f7df2e56Smrg } 4963f7df2e56Smrg wire = (char *) &rowWire[1]; 4964f7df2e56Smrg if (row->keys) { 4965f7df2e56Smrg int k; 4966f7df2e56Smrg XkbKeyPtr key; 4967f7df2e56Smrg xkbKeyWireDesc *keyWire; 4968f7df2e56Smrg 4969f7df2e56Smrg keyWire = (xkbKeyWireDesc *) wire; 4970f7df2e56Smrg for (k = 0, key = row->keys; k < row->num_keys; k++, key++) { 4971f7df2e56Smrg memcpy(keyWire[k].name, key->name.name, 4972f7df2e56Smrg XkbKeyNameLength); 4973f7df2e56Smrg keyWire[k].gap = key->gap; 4974f7df2e56Smrg keyWire[k].shapeNdx = key->shape_ndx; 4975f7df2e56Smrg keyWire[k].colorNdx = key->color_ndx; 4976f7df2e56Smrg if (swap) { 4977f7df2e56Smrg swaps(&keyWire[k].gap); 4978f7df2e56Smrg } 4979f7df2e56Smrg } 4980f7df2e56Smrg wire = (char *) &keyWire[row->num_keys]; 4981f7df2e56Smrg } 4982f7df2e56Smrg } 4983f7df2e56Smrg } 4984f7df2e56Smrg if (section->doodads) { 4985f7df2e56Smrg wire = XkbWriteGeomDoodads(wire, 4986f7df2e56Smrg section->num_doodads, section->doodads, 4987f7df2e56Smrg swap); 4988f7df2e56Smrg } 4989f7df2e56Smrg if (section->overlays) { 4990f7df2e56Smrg register int o; 4991f7df2e56Smrg 4992f7df2e56Smrg for (o = 0; o < section->num_overlays; o++) { 4993f7df2e56Smrg wire = XkbWriteGeomOverlay(wire, §ion->overlays[o], swap); 4994f7df2e56Smrg } 4995f7df2e56Smrg } 499605b261ecSmrg } 499705b261ecSmrg return wire; 499805b261ecSmrg} 499905b261ecSmrg 500005b261ecSmrgstatic Status 5001f7df2e56SmrgXkbComputeGetGeometryReplySize(XkbGeometryPtr geom, 5002f7df2e56Smrg xkbGetGeometryReply * rep, Atom name) 500305b261ecSmrg{ 5004f7df2e56Smrg int len; 5005f7df2e56Smrg 5006f7df2e56Smrg if (geom != NULL) { 5007f7df2e56Smrg len = XkbSizeCountedString(geom->label_font); 5008f7df2e56Smrg len += XkbSizeGeomProperties(geom); 5009f7df2e56Smrg len += XkbSizeGeomColors(geom); 5010f7df2e56Smrg len += XkbSizeGeomShapes(geom); 5011f7df2e56Smrg len += XkbSizeGeomSections(geom); 5012f7df2e56Smrg len += XkbSizeGeomDoodads(geom->num_doodads, geom->doodads); 5013f7df2e56Smrg len += XkbSizeGeomKeyAliases(geom); 5014f7df2e56Smrg rep->length = len / 4; 5015f7df2e56Smrg rep->found = TRUE; 5016f7df2e56Smrg rep->name = geom->name; 5017f7df2e56Smrg rep->widthMM = geom->width_mm; 5018f7df2e56Smrg rep->heightMM = geom->height_mm; 5019f7df2e56Smrg rep->nProperties = geom->num_properties; 5020f7df2e56Smrg rep->nColors = geom->num_colors; 5021f7df2e56Smrg rep->nShapes = geom->num_shapes; 5022f7df2e56Smrg rep->nSections = geom->num_sections; 5023f7df2e56Smrg rep->nDoodads = geom->num_doodads; 5024f7df2e56Smrg rep->nKeyAliases = geom->num_key_aliases; 5025f7df2e56Smrg rep->baseColorNdx = XkbGeomColorIndex(geom, geom->base_color); 5026f7df2e56Smrg rep->labelColorNdx = XkbGeomColorIndex(geom, geom->label_color); 502705b261ecSmrg } 502805b261ecSmrg else { 5029f7df2e56Smrg rep->length = 0; 5030f7df2e56Smrg rep->found = FALSE; 5031f7df2e56Smrg rep->name = name; 5032f7df2e56Smrg rep->widthMM = rep->heightMM = 0; 5033f7df2e56Smrg rep->nProperties = rep->nColors = rep->nShapes = 0; 5034f7df2e56Smrg rep->nSections = rep->nDoodads = 0; 5035f7df2e56Smrg rep->nKeyAliases = 0; 5036f7df2e56Smrg rep->labelColorNdx = rep->baseColorNdx = 0; 503705b261ecSmrg } 503805b261ecSmrg return Success; 503905b261ecSmrg} 504005b261ecSmrgstatic int 5041f7df2e56SmrgXkbSendGeometry(ClientPtr client, 5042f7df2e56Smrg XkbGeometryPtr geom, xkbGetGeometryReply * rep, Bool freeGeom) 504305b261ecSmrg{ 5044f7df2e56Smrg char *desc, *start; 5045f7df2e56Smrg int len; 5046f7df2e56Smrg 5047f7df2e56Smrg if (geom != NULL) { 5048f7df2e56Smrg start = desc = xallocarray(rep->length, 4); 5049f7df2e56Smrg if (!start) 5050f7df2e56Smrg return BadAlloc; 5051f7df2e56Smrg len = rep->length * 4; 5052f7df2e56Smrg desc = XkbWriteCountedString(desc, geom->label_font, client->swapped); 5053f7df2e56Smrg if (rep->nProperties > 0) 5054f7df2e56Smrg desc = XkbWriteGeomProperties(desc, geom, client->swapped); 5055f7df2e56Smrg if (rep->nColors > 0) 5056f7df2e56Smrg desc = XkbWriteGeomColors(desc, geom, client->swapped); 5057f7df2e56Smrg if (rep->nShapes > 0) 5058f7df2e56Smrg desc = XkbWriteGeomShapes(desc, geom, client->swapped); 5059f7df2e56Smrg if (rep->nSections > 0) 5060f7df2e56Smrg desc = XkbWriteGeomSections(desc, geom, client->swapped); 5061f7df2e56Smrg if (rep->nDoodads > 0) 5062f7df2e56Smrg desc = XkbWriteGeomDoodads(desc, geom->num_doodads, geom->doodads, 5063f7df2e56Smrg client->swapped); 5064f7df2e56Smrg if (rep->nKeyAliases > 0) 5065f7df2e56Smrg desc = XkbWriteGeomKeyAliases(desc, geom, client->swapped); 5066f7df2e56Smrg if ((desc - start) != (len)) { 5067f7df2e56Smrg ErrorF 5068f7df2e56Smrg ("[xkb] BOGUS LENGTH in XkbSendGeometry, expected %d, got %ld\n", 5069f7df2e56Smrg len, (unsigned long) (desc - start)); 5070f7df2e56Smrg } 507105b261ecSmrg } 507205b261ecSmrg else { 5073f7df2e56Smrg len = 0; 5074f7df2e56Smrg start = NULL; 507505b261ecSmrg } 507605b261ecSmrg if (client->swapped) { 5077f7df2e56Smrg swaps(&rep->sequenceNumber); 5078f7df2e56Smrg swapl(&rep->length); 5079f7df2e56Smrg swapl(&rep->name); 5080f7df2e56Smrg swaps(&rep->widthMM); 5081f7df2e56Smrg swaps(&rep->heightMM); 5082f7df2e56Smrg swaps(&rep->nProperties); 5083f7df2e56Smrg swaps(&rep->nColors); 5084f7df2e56Smrg swaps(&rep->nShapes); 5085f7df2e56Smrg swaps(&rep->nSections); 5086f7df2e56Smrg swaps(&rep->nDoodads); 5087f7df2e56Smrg swaps(&rep->nKeyAliases); 5088f7df2e56Smrg } 5089f7df2e56Smrg WriteToClient(client, SIZEOF(xkbGetGeometryReply), rep); 5090f7df2e56Smrg if (len > 0) 5091f7df2e56Smrg WriteToClient(client, len, start); 5092f7df2e56Smrg if (start != NULL) 5093f7df2e56Smrg free((char *) start); 509405b261ecSmrg if (freeGeom) 5095f7df2e56Smrg XkbFreeGeometry(geom, XkbGeomAllMask, TRUE); 50966747b715Smrg return Success; 509705b261ecSmrg} 509805b261ecSmrg 509905b261ecSmrgint 510005b261ecSmrgProcXkbGetGeometry(ClientPtr client) 510105b261ecSmrg{ 5102f7df2e56Smrg DeviceIntPtr dev; 510305b261ecSmrg xkbGetGeometryReply rep; 5104f7df2e56Smrg XkbGeometryPtr geom; 5105f7df2e56Smrg Bool shouldFree; 5106f7df2e56Smrg Status status; 510705b261ecSmrg 510805b261ecSmrg REQUEST(xkbGetGeometryReq); 510905b261ecSmrg REQUEST_SIZE_MATCH(xkbGetGeometryReq); 511005b261ecSmrg 5111f7df2e56Smrg if (!(client->xkbClientFlags & _XkbClientInitialized)) 5112f7df2e56Smrg return BadAccess; 511305b261ecSmrg 51144642e01fSmrg CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess); 511505b261ecSmrg CHK_ATOM_OR_NONE(stuff->name); 511605b261ecSmrg 5117f7df2e56Smrg geom = XkbLookupNamedGeometry(dev, stuff->name, &shouldFree); 5118f7df2e56Smrg rep = (xkbGetGeometryReply) { 5119f7df2e56Smrg .type = X_Reply, 5120f7df2e56Smrg .deviceID = dev->id, 5121f7df2e56Smrg .sequenceNumber = client->sequence, 5122f7df2e56Smrg .length = 0 5123f7df2e56Smrg }; 5124f7df2e56Smrg status = XkbComputeGetGeometryReplySize(geom, &rep, stuff->name); 5125f7df2e56Smrg if (status != Success) 5126f7df2e56Smrg return status; 5127f7df2e56Smrg else 5128f7df2e56Smrg return XkbSendGeometry(client, geom, &rep, shouldFree); 512905b261ecSmrg} 513005b261ecSmrg 513105b261ecSmrg/***====================================================================***/ 513205b261ecSmrg 51331e26616aSmrgstatic Status 51341e26616aSmrg_GetCountedString(char **wire_inout, ClientPtr client, char **str) 513505b261ecSmrg{ 51361e26616aSmrg char *wire, *next; 51371e26616aSmrg CARD16 len; 513805b261ecSmrg 51391e26616aSmrg wire = *wire_inout; 51402d19872aSmrg 51412d19872aSmrg if (client->req_len < 51422d19872aSmrg bytes_to_int32(wire + 2 - (char *) client->requestBuffer)) 51432d19872aSmrg return BadValue; 51442d19872aSmrg 51451e26616aSmrg len = *(CARD16 *) wire; 51461e26616aSmrg if (client->swapped) { 5147f7df2e56Smrg swaps(&len); 514805b261ecSmrg } 51491e26616aSmrg next = wire + XkbPaddedSize(len + 2); 51501e26616aSmrg /* Check we're still within the size of the request */ 51511e26616aSmrg if (client->req_len < 51521e26616aSmrg bytes_to_int32(next - (char *) client->requestBuffer)) 51531e26616aSmrg return BadValue; 51541e26616aSmrg *str = malloc(len + 1); 51551e26616aSmrg if (!*str) 51561e26616aSmrg return BadAlloc; 51571e26616aSmrg memcpy(*str, &wire[2], len); 51581e26616aSmrg *(*str + len) = '\0'; 51591e26616aSmrg *wire_inout = next; 51601e26616aSmrg return Success; 516105b261ecSmrg} 516205b261ecSmrg 516305b261ecSmrgstatic Status 516490bea6a0Smrg_CheckSetDoodad(char **wire_inout, xkbSetGeometryReq *req, 5165f7df2e56Smrg XkbGeometryPtr geom, XkbSectionPtr section, ClientPtr client) 516605b261ecSmrg{ 5167f7df2e56Smrg char *wire; 5168f7df2e56Smrg xkbDoodadWireDesc *dWire; 5169f7df2e56Smrg xkbAnyDoodadWireDesc any; 5170f7df2e56Smrg xkbTextDoodadWireDesc text; 5171f7df2e56Smrg XkbDoodadPtr doodad; 51721e26616aSmrg Status status; 517305b261ecSmrg 5174f7df2e56Smrg dWire = (xkbDoodadWireDesc *) (*wire_inout); 517590bea6a0Smrg if (!_XkbCheckRequestBounds(client, req, dWire, dWire + 1)) 517690bea6a0Smrg return BadLength; 517790bea6a0Smrg 5178f7df2e56Smrg any = dWire->any; 5179f7df2e56Smrg wire = (char *) &dWire[1]; 518005b261ecSmrg if (client->swapped) { 5181f7df2e56Smrg swapl(&any.name); 5182f7df2e56Smrg swaps(&any.top); 5183f7df2e56Smrg swaps(&any.left); 5184f7df2e56Smrg swaps(&any.angle); 518505b261ecSmrg } 518605b261ecSmrg CHK_ATOM_ONLY(dWire->any.name); 5187f7df2e56Smrg doodad = XkbAddGeomDoodad(geom, section, any.name); 518805b261ecSmrg if (!doodad) 5189f7df2e56Smrg return BadAlloc; 5190f7df2e56Smrg doodad->any.type = dWire->any.type; 5191f7df2e56Smrg doodad->any.priority = dWire->any.priority; 5192f7df2e56Smrg doodad->any.top = any.top; 5193f7df2e56Smrg doodad->any.left = any.left; 5194f7df2e56Smrg doodad->any.angle = any.angle; 519505b261ecSmrg switch (doodad->any.type) { 5196f7df2e56Smrg case XkbOutlineDoodad: 5197f7df2e56Smrg case XkbSolidDoodad: 5198f7df2e56Smrg if (dWire->shape.colorNdx >= geom->num_colors) { 5199f7df2e56Smrg client->errorValue = _XkbErrCode3(0x40, geom->num_colors, 5200f7df2e56Smrg dWire->shape.colorNdx); 5201f7df2e56Smrg return BadMatch; 5202f7df2e56Smrg } 5203f7df2e56Smrg if (dWire->shape.shapeNdx >= geom->num_shapes) { 5204f7df2e56Smrg client->errorValue = _XkbErrCode3(0x41, geom->num_shapes, 5205f7df2e56Smrg dWire->shape.shapeNdx); 5206f7df2e56Smrg return BadMatch; 5207f7df2e56Smrg } 5208f7df2e56Smrg doodad->shape.color_ndx = dWire->shape.colorNdx; 5209f7df2e56Smrg doodad->shape.shape_ndx = dWire->shape.shapeNdx; 5210f7df2e56Smrg break; 5211f7df2e56Smrg case XkbTextDoodad: 5212f7df2e56Smrg if (dWire->text.colorNdx >= geom->num_colors) { 5213f7df2e56Smrg client->errorValue = _XkbErrCode3(0x42, geom->num_colors, 5214f7df2e56Smrg dWire->text.colorNdx); 5215f7df2e56Smrg return BadMatch; 5216f7df2e56Smrg } 5217f7df2e56Smrg text = dWire->text; 5218f7df2e56Smrg if (client->swapped) { 5219f7df2e56Smrg swaps(&text.width); 5220f7df2e56Smrg swaps(&text.height); 5221f7df2e56Smrg } 5222f7df2e56Smrg doodad->text.width = text.width; 5223f7df2e56Smrg doodad->text.height = text.height; 5224f7df2e56Smrg doodad->text.color_ndx = dWire->text.colorNdx; 5225f7df2e56Smrg status = _GetCountedString(&wire, client, &doodad->text.text); 5226f7df2e56Smrg if (status != Success) 5227f7df2e56Smrg return status; 5228f7df2e56Smrg status = _GetCountedString(&wire, client, &doodad->text.font); 5229f7df2e56Smrg if (status != Success) { 5230f7df2e56Smrg free (doodad->text.text); 5231f7df2e56Smrg return status; 5232f7df2e56Smrg } 5233f7df2e56Smrg break; 5234f7df2e56Smrg case XkbIndicatorDoodad: 5235f7df2e56Smrg if (dWire->indicator.onColorNdx >= geom->num_colors) { 5236f7df2e56Smrg client->errorValue = _XkbErrCode3(0x43, geom->num_colors, 5237f7df2e56Smrg dWire->indicator.onColorNdx); 5238f7df2e56Smrg return BadMatch; 5239f7df2e56Smrg } 5240f7df2e56Smrg if (dWire->indicator.offColorNdx >= geom->num_colors) { 5241f7df2e56Smrg client->errorValue = _XkbErrCode3(0x44, geom->num_colors, 5242f7df2e56Smrg dWire->indicator.offColorNdx); 5243f7df2e56Smrg return BadMatch; 5244f7df2e56Smrg } 5245f7df2e56Smrg if (dWire->indicator.shapeNdx >= geom->num_shapes) { 5246f7df2e56Smrg client->errorValue = _XkbErrCode3(0x45, geom->num_shapes, 5247f7df2e56Smrg dWire->indicator.shapeNdx); 5248f7df2e56Smrg return BadMatch; 5249f7df2e56Smrg } 5250f7df2e56Smrg doodad->indicator.shape_ndx = dWire->indicator.shapeNdx; 5251f7df2e56Smrg doodad->indicator.on_color_ndx = dWire->indicator.onColorNdx; 5252f7df2e56Smrg doodad->indicator.off_color_ndx = dWire->indicator.offColorNdx; 5253f7df2e56Smrg break; 5254f7df2e56Smrg case XkbLogoDoodad: 5255f7df2e56Smrg if (dWire->logo.colorNdx >= geom->num_colors) { 5256f7df2e56Smrg client->errorValue = _XkbErrCode3(0x46, geom->num_colors, 5257f7df2e56Smrg dWire->logo.colorNdx); 5258f7df2e56Smrg return BadMatch; 5259f7df2e56Smrg } 5260f7df2e56Smrg if (dWire->logo.shapeNdx >= geom->num_shapes) { 5261f7df2e56Smrg client->errorValue = _XkbErrCode3(0x47, geom->num_shapes, 5262f7df2e56Smrg dWire->logo.shapeNdx); 5263f7df2e56Smrg return BadMatch; 5264f7df2e56Smrg } 5265f7df2e56Smrg doodad->logo.color_ndx = dWire->logo.colorNdx; 5266f7df2e56Smrg doodad->logo.shape_ndx = dWire->logo.shapeNdx; 5267f7df2e56Smrg status = _GetCountedString(&wire, client, &doodad->logo.logo_name); 5268f7df2e56Smrg if (status != Success) 5269f7df2e56Smrg return status; 5270f7df2e56Smrg break; 5271f7df2e56Smrg default: 5272f7df2e56Smrg client->errorValue = _XkbErrCode2(0x4F, dWire->any.type); 5273f7df2e56Smrg return BadValue; 5274f7df2e56Smrg } 5275f7df2e56Smrg *wire_inout = wire; 5276f7df2e56Smrg return Success; 5277f7df2e56Smrg} 5278f7df2e56Smrg 5279f7df2e56Smrgstatic Status 528090bea6a0Smrg_CheckSetOverlay(char **wire_inout, xkbSetGeometryReq *req, 5281f7df2e56Smrg XkbGeometryPtr geom, XkbSectionPtr section, ClientPtr client) 528205b261ecSmrg{ 5283f7df2e56Smrg register int r; 5284f7df2e56Smrg char *wire; 5285f7df2e56Smrg XkbOverlayPtr ol; 5286f7df2e56Smrg xkbOverlayWireDesc *olWire; 5287f7df2e56Smrg xkbOverlayRowWireDesc *rWire; 528805b261ecSmrg 5289f7df2e56Smrg wire = *wire_inout; 5290f7df2e56Smrg olWire = (xkbOverlayWireDesc *) wire; 529190bea6a0Smrg if (!_XkbCheckRequestBounds(client, req, olWire, olWire + 1)) 529290bea6a0Smrg return BadLength; 529390bea6a0Smrg 5294f7df2e56Smrg if (client->swapped) { 5295f7df2e56Smrg swapl(&olWire->name); 5296f7df2e56Smrg } 5297f7df2e56Smrg CHK_ATOM_ONLY(olWire->name); 5298f7df2e56Smrg ol = XkbAddGeomOverlay(section, olWire->name, olWire->nRows); 5299f7df2e56Smrg rWire = (xkbOverlayRowWireDesc *) &olWire[1]; 5300f7df2e56Smrg for (r = 0; r < olWire->nRows; r++) { 5301f7df2e56Smrg register int k; 5302f7df2e56Smrg xkbOverlayKeyWireDesc *kWire; 5303f7df2e56Smrg XkbOverlayRowPtr row; 5304f7df2e56Smrg 530590bea6a0Smrg if (!_XkbCheckRequestBounds(client, req, rWire, rWire + 1)) 530690bea6a0Smrg return BadLength; 530790bea6a0Smrg 5308f7df2e56Smrg if (rWire->rowUnder > section->num_rows) { 5309f7df2e56Smrg client->errorValue = _XkbErrCode4(0x20, r, section->num_rows, 5310f7df2e56Smrg rWire->rowUnder); 5311f7df2e56Smrg return BadMatch; 5312f7df2e56Smrg } 5313f7df2e56Smrg row = XkbAddGeomOverlayRow(ol, rWire->rowUnder, rWire->nKeys); 5314f7df2e56Smrg kWire = (xkbOverlayKeyWireDesc *) &rWire[1]; 5315f7df2e56Smrg for (k = 0; k < rWire->nKeys; k++, kWire++) { 531690bea6a0Smrg if (!_XkbCheckRequestBounds(client, req, kWire, kWire + 1)) 531790bea6a0Smrg return BadLength; 531890bea6a0Smrg 5319f7df2e56Smrg if (XkbAddGeomOverlayKey(ol, row, 5320f7df2e56Smrg (char *) kWire->over, 5321f7df2e56Smrg (char *) kWire->under) == NULL) { 5322f7df2e56Smrg client->errorValue = _XkbErrCode3(0x21, r, k); 5323f7df2e56Smrg return BadMatch; 5324f7df2e56Smrg } 5325f7df2e56Smrg } 5326f7df2e56Smrg rWire = (xkbOverlayRowWireDesc *) kWire; 5327f7df2e56Smrg } 5328f7df2e56Smrg olWire = (xkbOverlayWireDesc *) rWire; 5329f7df2e56Smrg wire = (char *) olWire; 5330f7df2e56Smrg *wire_inout = wire; 5331f7df2e56Smrg return Success; 5332f7df2e56Smrg} 5333f7df2e56Smrg 5334f7df2e56Smrgstatic Status 5335f7df2e56Smrg_CheckSetSections(XkbGeometryPtr geom, 5336f7df2e56Smrg xkbSetGeometryReq * req, char **wire_inout, ClientPtr client) 5337f7df2e56Smrg{ 5338f7df2e56Smrg Status status; 5339f7df2e56Smrg register int s; 5340f7df2e56Smrg char *wire; 5341f7df2e56Smrg xkbSectionWireDesc *sWire; 5342f7df2e56Smrg XkbSectionPtr section; 5343f7df2e56Smrg 5344f7df2e56Smrg wire = *wire_inout; 5345f7df2e56Smrg if (req->nSections < 1) 5346f7df2e56Smrg return Success; 5347f7df2e56Smrg sWire = (xkbSectionWireDesc *) wire; 5348f7df2e56Smrg for (s = 0; s < req->nSections; s++) { 5349f7df2e56Smrg register int r; 5350f7df2e56Smrg xkbRowWireDesc *rWire; 5351f7df2e56Smrg 535290bea6a0Smrg if (!_XkbCheckRequestBounds(client, req, sWire, sWire + 1)) 535390bea6a0Smrg return BadLength; 535490bea6a0Smrg 5355f7df2e56Smrg if (client->swapped) { 5356f7df2e56Smrg swapl(&sWire->name); 5357f7df2e56Smrg swaps(&sWire->top); 5358f7df2e56Smrg swaps(&sWire->left); 5359f7df2e56Smrg swaps(&sWire->width); 5360f7df2e56Smrg swaps(&sWire->height); 5361f7df2e56Smrg swaps(&sWire->angle); 5362f7df2e56Smrg } 5363f7df2e56Smrg CHK_ATOM_ONLY(sWire->name); 5364f7df2e56Smrg section = XkbAddGeomSection(geom, sWire->name, sWire->nRows, 5365f7df2e56Smrg sWire->nDoodads, sWire->nOverlays); 5366f7df2e56Smrg if (!section) 5367f7df2e56Smrg return BadAlloc; 5368f7df2e56Smrg section->priority = sWire->priority; 5369f7df2e56Smrg section->top = sWire->top; 5370f7df2e56Smrg section->left = sWire->left; 5371f7df2e56Smrg section->width = sWire->width; 5372f7df2e56Smrg section->height = sWire->height; 5373f7df2e56Smrg section->angle = sWire->angle; 5374f7df2e56Smrg rWire = (xkbRowWireDesc *) &sWire[1]; 5375f7df2e56Smrg for (r = 0; r < sWire->nRows; r++) { 5376f7df2e56Smrg register int k; 5377f7df2e56Smrg XkbRowPtr row; 5378f7df2e56Smrg xkbKeyWireDesc *kWire; 5379f7df2e56Smrg 538090bea6a0Smrg if (!_XkbCheckRequestBounds(client, req, rWire, rWire + 1)) 538190bea6a0Smrg return BadLength; 538290bea6a0Smrg 5383f7df2e56Smrg if (client->swapped) { 5384f7df2e56Smrg swaps(&rWire->top); 5385f7df2e56Smrg swaps(&rWire->left); 5386f7df2e56Smrg } 5387f7df2e56Smrg row = XkbAddGeomRow(section, rWire->nKeys); 5388f7df2e56Smrg if (!row) 5389f7df2e56Smrg return BadAlloc; 5390f7df2e56Smrg row->top = rWire->top; 5391f7df2e56Smrg row->left = rWire->left; 5392f7df2e56Smrg row->vertical = rWire->vertical; 5393f7df2e56Smrg kWire = (xkbKeyWireDesc *) &rWire[1]; 539490bea6a0Smrg for (k = 0; k < rWire->nKeys; k++, kWire++) { 5395f7df2e56Smrg XkbKeyPtr key; 5396f7df2e56Smrg 539790bea6a0Smrg if (!_XkbCheckRequestBounds(client, req, kWire, kWire + 1)) 539890bea6a0Smrg return BadLength; 539990bea6a0Smrg 5400f7df2e56Smrg key = XkbAddGeomKey(row); 5401f7df2e56Smrg if (!key) 5402f7df2e56Smrg return BadAlloc; 540390bea6a0Smrg memcpy(key->name.name, kWire->name, XkbKeyNameLength); 540490bea6a0Smrg key->gap = kWire->gap; 540590bea6a0Smrg key->shape_ndx = kWire->shapeNdx; 540690bea6a0Smrg key->color_ndx = kWire->colorNdx; 5407f7df2e56Smrg if (key->shape_ndx >= geom->num_shapes) { 5408f7df2e56Smrg client->errorValue = _XkbErrCode3(0x10, key->shape_ndx, 5409f7df2e56Smrg geom->num_shapes); 5410f7df2e56Smrg return BadMatch; 5411f7df2e56Smrg } 5412f7df2e56Smrg if (key->color_ndx >= geom->num_colors) { 5413f7df2e56Smrg client->errorValue = _XkbErrCode3(0x11, key->color_ndx, 5414f7df2e56Smrg geom->num_colors); 5415f7df2e56Smrg return BadMatch; 5416f7df2e56Smrg } 5417f7df2e56Smrg } 541890bea6a0Smrg rWire = (xkbRowWireDesc *)kWire; 5419f7df2e56Smrg } 5420f7df2e56Smrg wire = (char *) rWire; 5421f7df2e56Smrg if (sWire->nDoodads > 0) { 5422f7df2e56Smrg register int d; 5423f7df2e56Smrg 5424f7df2e56Smrg for (d = 0; d < sWire->nDoodads; d++) { 542590bea6a0Smrg status = _CheckSetDoodad(&wire, req, geom, section, client); 5426f7df2e56Smrg if (status != Success) 5427f7df2e56Smrg return status; 5428f7df2e56Smrg } 5429f7df2e56Smrg } 5430f7df2e56Smrg if (sWire->nOverlays > 0) { 5431f7df2e56Smrg register int o; 5432f7df2e56Smrg 5433f7df2e56Smrg for (o = 0; o < sWire->nOverlays; o++) { 543490bea6a0Smrg status = _CheckSetOverlay(&wire, req, geom, section, client); 5435f7df2e56Smrg if (status != Success) 5436f7df2e56Smrg return status; 5437f7df2e56Smrg } 5438f7df2e56Smrg } 5439f7df2e56Smrg sWire = (xkbSectionWireDesc *) wire; 5440f7df2e56Smrg } 5441f7df2e56Smrg wire = (char *) sWire; 5442f7df2e56Smrg *wire_inout = wire; 5443f7df2e56Smrg return Success; 5444f7df2e56Smrg} 5445f7df2e56Smrg 5446f7df2e56Smrgstatic Status 5447f7df2e56Smrg_CheckSetShapes(XkbGeometryPtr geom, 5448f7df2e56Smrg xkbSetGeometryReq * req, char **wire_inout, ClientPtr client) 5449f7df2e56Smrg{ 5450f7df2e56Smrg register int i; 5451f7df2e56Smrg char *wire; 5452f7df2e56Smrg 5453f7df2e56Smrg wire = *wire_inout; 5454f7df2e56Smrg if (req->nShapes < 1) { 5455f7df2e56Smrg client->errorValue = _XkbErrCode2(0x06, req->nShapes); 5456f7df2e56Smrg return BadValue; 545705b261ecSmrg } 545805b261ecSmrg else { 5459f7df2e56Smrg xkbShapeWireDesc *shapeWire; 5460f7df2e56Smrg XkbShapePtr shape; 5461f7df2e56Smrg register int o; 5462f7df2e56Smrg 5463f7df2e56Smrg shapeWire = (xkbShapeWireDesc *) wire; 5464f7df2e56Smrg for (i = 0; i < req->nShapes; i++) { 5465f7df2e56Smrg xkbOutlineWireDesc *olWire; 5466f7df2e56Smrg XkbOutlinePtr ol; 5467f7df2e56Smrg 546890bea6a0Smrg if (!_XkbCheckRequestBounds(client, req, shapeWire, shapeWire + 1)) 546990bea6a0Smrg return BadLength; 547090bea6a0Smrg 5471f7df2e56Smrg shape = 5472f7df2e56Smrg XkbAddGeomShape(geom, shapeWire->name, shapeWire->nOutlines); 5473f7df2e56Smrg if (!shape) 5474f7df2e56Smrg return BadAlloc; 5475f7df2e56Smrg olWire = (xkbOutlineWireDesc *) (&shapeWire[1]); 5476f7df2e56Smrg for (o = 0; o < shapeWire->nOutlines; o++) { 5477f7df2e56Smrg register int p; 5478f7df2e56Smrg XkbPointPtr pt; 5479f7df2e56Smrg xkbPointWireDesc *ptWire; 5480f7df2e56Smrg 548190bea6a0Smrg if (!_XkbCheckRequestBounds(client, req, olWire, olWire + 1)) 548290bea6a0Smrg return BadLength; 548390bea6a0Smrg 5484f7df2e56Smrg ol = XkbAddGeomOutline(shape, olWire->nPoints); 5485f7df2e56Smrg if (!ol) 5486f7df2e56Smrg return BadAlloc; 5487f7df2e56Smrg ol->corner_radius = olWire->cornerRadius; 5488f7df2e56Smrg ptWire = (xkbPointWireDesc *) &olWire[1]; 548990bea6a0Smrg for (p = 0, pt = ol->points; p < olWire->nPoints; p++, pt++, ptWire++) { 549090bea6a0Smrg if (!_XkbCheckRequestBounds(client, req, ptWire, ptWire + 1)) 549190bea6a0Smrg return BadLength; 549290bea6a0Smrg 549390bea6a0Smrg pt->x = ptWire->x; 549490bea6a0Smrg pt->y = ptWire->y; 5495f7df2e56Smrg if (client->swapped) { 5496f7df2e56Smrg swaps(&pt->x); 5497f7df2e56Smrg swaps(&pt->y); 5498f7df2e56Smrg } 5499f7df2e56Smrg } 5500f7df2e56Smrg ol->num_points = olWire->nPoints; 550190bea6a0Smrg olWire = (xkbOutlineWireDesc *)ptWire; 5502f7df2e56Smrg } 5503f7df2e56Smrg if (shapeWire->primaryNdx != XkbNoShape) 5504f7df2e56Smrg shape->primary = &shape->outlines[shapeWire->primaryNdx]; 5505f7df2e56Smrg if (shapeWire->approxNdx != XkbNoShape) 5506f7df2e56Smrg shape->approx = &shape->outlines[shapeWire->approxNdx]; 5507f7df2e56Smrg shapeWire = (xkbShapeWireDesc *) olWire; 5508f7df2e56Smrg } 5509f7df2e56Smrg wire = (char *) shapeWire; 5510f7df2e56Smrg } 5511f7df2e56Smrg if (geom->num_shapes != req->nShapes) { 5512f7df2e56Smrg client->errorValue = _XkbErrCode3(0x07, geom->num_shapes, req->nShapes); 5513f7df2e56Smrg return BadMatch; 5514f7df2e56Smrg } 5515f7df2e56Smrg 5516f7df2e56Smrg *wire_inout = wire; 551705b261ecSmrg return Success; 551805b261ecSmrg} 551905b261ecSmrg 552005b261ecSmrgstatic Status 5521f7df2e56Smrg_CheckSetGeom(XkbGeometryPtr geom, xkbSetGeometryReq * req, ClientPtr client) 552205b261ecSmrg{ 5523f7df2e56Smrg register int i; 5524f7df2e56Smrg Status status; 5525f7df2e56Smrg char *wire; 552605b261ecSmrg 5527f7df2e56Smrg wire = (char *) &req[1]; 55281e26616aSmrg status = _GetCountedString(&wire, client, &geom->label_font); 55291e26616aSmrg if (status != Success) 55301e26616aSmrg return status; 55311e26616aSmrg 55321e26616aSmrg for (i = 0; i < req->nProperties; i++) { 5533f7df2e56Smrg char *name, *val; 55341e26616aSmrg 55351e26616aSmrg status = _GetCountedString(&wire, client, &name); 55361e26616aSmrg if (status != Success) 55371e26616aSmrg return status; 55381e26616aSmrg status = _GetCountedString(&wire, client, &val); 55391e26616aSmrg if (status != Success) { 55406747b715Smrg free(name); 55411e26616aSmrg return status; 554205b261ecSmrg } 5543f7df2e56Smrg if (XkbAddGeomProperty(geom, name, val) == NULL) { 55446747b715Smrg free(name); 55456747b715Smrg free(val); 5546f7df2e56Smrg return BadAlloc; 554705b261ecSmrg } 55486747b715Smrg free(name); 55496747b715Smrg free(val); 555005b261ecSmrg } 555105b261ecSmrg 5552f7df2e56Smrg if (req->nColors < 2) { 5553f7df2e56Smrg client->errorValue = _XkbErrCode3(0x01, 2, req->nColors); 5554f7df2e56Smrg return BadValue; 555505b261ecSmrg } 5556f7df2e56Smrg if (req->baseColorNdx > req->nColors) { 5557f7df2e56Smrg client->errorValue = 5558f7df2e56Smrg _XkbErrCode3(0x03, req->nColors, req->baseColorNdx); 5559f7df2e56Smrg return BadMatch; 556005b261ecSmrg } 5561f7df2e56Smrg if (req->labelColorNdx > req->nColors) { 5562f7df2e56Smrg client->errorValue = 5563f7df2e56Smrg _XkbErrCode3(0x03, req->nColors, req->labelColorNdx); 5564f7df2e56Smrg return BadMatch; 556505b261ecSmrg } 5566f7df2e56Smrg if (req->labelColorNdx == req->baseColorNdx) { 5567f7df2e56Smrg client->errorValue = _XkbErrCode3(0x04, req->baseColorNdx, 5568f7df2e56Smrg req->labelColorNdx); 5569f7df2e56Smrg return BadMatch; 557005b261ecSmrg } 557105b261ecSmrg 55721e26616aSmrg for (i = 0; i < req->nColors; i++) { 5573f7df2e56Smrg char *name; 5574f7df2e56Smrg 55751e26616aSmrg status = _GetCountedString(&wire, client, &name); 55761e26616aSmrg if (status != Success) 55771e26616aSmrg return status; 5578f7df2e56Smrg if (!XkbAddGeomColor(geom, name, geom->num_colors)) { 55796747b715Smrg free(name); 5580f7df2e56Smrg return BadAlloc; 558105b261ecSmrg } 55826747b715Smrg free(name); 558305b261ecSmrg } 5584f7df2e56Smrg if (req->nColors != geom->num_colors) { 5585f7df2e56Smrg client->errorValue = _XkbErrCode3(0x05, req->nColors, geom->num_colors); 5586f7df2e56Smrg return BadMatch; 558705b261ecSmrg } 5588f7df2e56Smrg geom->label_color = &geom->colors[req->labelColorNdx]; 5589f7df2e56Smrg geom->base_color = &geom->colors[req->baseColorNdx]; 559005b261ecSmrg 5591f7df2e56Smrg if ((status = _CheckSetShapes(geom, req, &wire, client)) != Success) 5592f7df2e56Smrg return status; 559305b261ecSmrg 5594f7df2e56Smrg if ((status = _CheckSetSections(geom, req, &wire, client)) != Success) 5595f7df2e56Smrg return status; 559605b261ecSmrg 5597f7df2e56Smrg for (i = 0; i < req->nDoodads; i++) { 559890bea6a0Smrg status = _CheckSetDoodad(&wire, req, geom, NULL, client); 5599f7df2e56Smrg if (status != Success) 5600f7df2e56Smrg return status; 560105b261ecSmrg } 560205b261ecSmrg 5603f7df2e56Smrg for (i = 0; i < req->nKeyAliases; i++) { 560490bea6a0Smrg if (!_XkbCheckRequestBounds(client, req, wire, wire + XkbKeyNameLength)) 560590bea6a0Smrg return BadLength; 560690bea6a0Smrg 5607f7df2e56Smrg if (XkbAddGeomKeyAlias(geom, &wire[XkbKeyNameLength], wire) == NULL) 5608f7df2e56Smrg return BadAlloc; 5609f7df2e56Smrg wire += 2 * XkbKeyNameLength; 561005b261ecSmrg } 561105b261ecSmrg return Success; 561205b261ecSmrg} 561305b261ecSmrg 56144642e01fSmrgstatic int 5615f7df2e56Smrg_XkbSetGeometry(ClientPtr client, DeviceIntPtr dev, xkbSetGeometryReq * stuff) 561605b261ecSmrg{ 5617f7df2e56Smrg XkbDescPtr xkb; 5618f7df2e56Smrg Bool new_name; 5619f7df2e56Smrg xkbNewKeyboardNotify nkn; 5620f7df2e56Smrg XkbGeometryPtr geom, old; 5621f7df2e56Smrg XkbGeometrySizesRec sizes; 5622f7df2e56Smrg Status status; 5623f7df2e56Smrg 5624f7df2e56Smrg xkb = dev->key->xkbInfo->desc; 5625f7df2e56Smrg old = xkb->geom; 5626f7df2e56Smrg xkb->geom = NULL; 5627f7df2e56Smrg 5628f7df2e56Smrg sizes.which = XkbGeomAllMask; 5629f7df2e56Smrg sizes.num_properties = stuff->nProperties; 5630f7df2e56Smrg sizes.num_colors = stuff->nColors; 5631f7df2e56Smrg sizes.num_shapes = stuff->nShapes; 5632f7df2e56Smrg sizes.num_sections = stuff->nSections; 5633f7df2e56Smrg sizes.num_doodads = stuff->nDoodads; 5634f7df2e56Smrg sizes.num_key_aliases = stuff->nKeyAliases; 5635f7df2e56Smrg if ((status = XkbAllocGeometry(xkb, &sizes)) != Success) { 5636f7df2e56Smrg xkb->geom = old; 56374642e01fSmrg return status; 563805b261ecSmrg } 5639f7df2e56Smrg geom = xkb->geom; 5640f7df2e56Smrg geom->name = stuff->name; 5641f7df2e56Smrg geom->width_mm = stuff->widthMM; 5642f7df2e56Smrg geom->height_mm = stuff->heightMM; 5643f7df2e56Smrg if ((status = _CheckSetGeom(geom, stuff, client)) != Success) { 5644f7df2e56Smrg XkbFreeGeometry(geom, XkbGeomAllMask, TRUE); 5645f7df2e56Smrg xkb->geom = old; 56464642e01fSmrg return status; 564705b261ecSmrg } 5648f7df2e56Smrg new_name = (xkb->names->geometry != geom->name); 5649f7df2e56Smrg xkb->names->geometry = geom->name; 565005b261ecSmrg if (old) 5651f7df2e56Smrg XkbFreeGeometry(old, XkbGeomAllMask, TRUE); 565205b261ecSmrg if (new_name) { 5653f7df2e56Smrg xkbNamesNotify nn; 5654f7df2e56Smrg 56556747b715Smrg memset(&nn, 0, sizeof(xkbNamesNotify)); 5656f7df2e56Smrg nn.changed = XkbGeometryNameMask; 5657f7df2e56Smrg XkbSendNamesNotify(dev, &nn); 5658f7df2e56Smrg } 5659f7df2e56Smrg nkn.deviceID = nkn.oldDeviceID = dev->id; 5660f7df2e56Smrg nkn.minKeyCode = nkn.oldMinKeyCode = xkb->min_key_code; 5661f7df2e56Smrg nkn.maxKeyCode = nkn.oldMaxKeyCode = xkb->max_key_code; 5662f7df2e56Smrg nkn.requestMajor = XkbReqCode; 5663f7df2e56Smrg nkn.requestMinor = X_kbSetGeometry; 5664f7df2e56Smrg nkn.changed = XkbNKN_GeometryMask; 5665f7df2e56Smrg XkbSendNewKeyboardNotify(dev, &nkn); 566605b261ecSmrg return Success; 566705b261ecSmrg} 566805b261ecSmrg 56694642e01fSmrgint 56704642e01fSmrgProcXkbSetGeometry(ClientPtr client) 56714642e01fSmrg{ 5672f7df2e56Smrg DeviceIntPtr dev; 5673f7df2e56Smrg int rc; 56744642e01fSmrg 56754642e01fSmrg REQUEST(xkbSetGeometryReq); 56764642e01fSmrg REQUEST_AT_LEAST_SIZE(xkbSetGeometryReq); 56774642e01fSmrg 5678f7df2e56Smrg if (!(client->xkbClientFlags & _XkbClientInitialized)) 5679f7df2e56Smrg return BadAccess; 56804642e01fSmrg 56814642e01fSmrg CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess); 56824642e01fSmrg CHK_ATOM_OR_NONE(stuff->name); 56834642e01fSmrg 56844642e01fSmrg rc = _XkbSetGeometry(client, dev, stuff); 56854642e01fSmrg if (rc != Success) 56864642e01fSmrg return rc; 56874642e01fSmrg 5688f7df2e56Smrg if (stuff->deviceSpec == XkbUseCoreKbd) { 56894642e01fSmrg DeviceIntPtr other; 5690f7df2e56Smrg 5691f7df2e56Smrg for (other = inputInfo.devices; other; other = other->next) { 5692f7df2e56Smrg if ((other != dev) && other->key && !IsMaster(other) && 5693f7df2e56Smrg GetMaster(other, MASTER_KEYBOARD) == dev) { 5694f7df2e56Smrg rc = XaceHook(XACE_DEVICE_ACCESS, client, other, 5695f7df2e56Smrg DixManageAccess); 56964642e01fSmrg if (rc == Success) 56974642e01fSmrg _XkbSetGeometry(client, other, stuff); 56984642e01fSmrg } 56994642e01fSmrg } 57004642e01fSmrg } 57014642e01fSmrg 57024642e01fSmrg return Success; 57034642e01fSmrg} 57044642e01fSmrg 570505b261ecSmrg/***====================================================================***/ 570605b261ecSmrg 570705b261ecSmrgint 570805b261ecSmrgProcXkbPerClientFlags(ClientPtr client) 570905b261ecSmrg{ 5710f7df2e56Smrg DeviceIntPtr dev; 5711f7df2e56Smrg xkbPerClientFlagsReply rep; 5712f7df2e56Smrg XkbInterestPtr interest; 57134642e01fSmrg Mask access_mode = DixGetAttrAccess | DixSetAttrAccess; 571405b261ecSmrg 571505b261ecSmrg REQUEST(xkbPerClientFlagsReq); 571605b261ecSmrg REQUEST_SIZE_MATCH(xkbPerClientFlagsReq); 571705b261ecSmrg 5718f7df2e56Smrg if (!(client->xkbClientFlags & _XkbClientInitialized)) 5719f7df2e56Smrg return BadAccess; 572005b261ecSmrg 57214642e01fSmrg CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, access_mode); 5722f7df2e56Smrg CHK_MASK_LEGAL(0x01, stuff->change, XkbPCF_AllFlagsMask); 5723f7df2e56Smrg CHK_MASK_MATCH(0x02, stuff->change, stuff->value); 572405b261ecSmrg 5725f7df2e56Smrg interest = XkbFindClientResource((DevicePtr) dev, client); 572605b261ecSmrg if (stuff->change) { 5727f7df2e56Smrg client->xkbClientFlags &= ~stuff->change; 5728f7df2e56Smrg client->xkbClientFlags |= stuff->value; 572905b261ecSmrg } 5730f7df2e56Smrg if (stuff->change & XkbPCF_AutoResetControlsMask) { 5731f7df2e56Smrg Bool want; 5732f7df2e56Smrg 5733f7df2e56Smrg want = stuff->value & XkbPCF_AutoResetControlsMask; 5734f7df2e56Smrg if (interest && !want) { 5735f7df2e56Smrg interest->autoCtrls = interest->autoCtrlValues = 0; 5736f7df2e56Smrg } 5737f7df2e56Smrg else if (want && (!interest)) { 5738f7df2e56Smrg XID id = FakeClientID(client->index); 5739f7df2e56Smrg 5740f7df2e56Smrg if (!AddResource(id, RT_XKBCLIENT, dev)) 5741f7df2e56Smrg return BadAlloc; 5742f7df2e56Smrg interest = XkbAddClientResource((DevicePtr) dev, client, id); 5743f7df2e56Smrg if (!interest) 5744f7df2e56Smrg return BadAlloc; 5745f7df2e56Smrg } 5746f7df2e56Smrg if (interest && want) { 5747f7df2e56Smrg register unsigned affect; 5748f7df2e56Smrg 5749f7df2e56Smrg affect = stuff->ctrlsToChange; 5750f7df2e56Smrg 5751f7df2e56Smrg CHK_MASK_LEGAL(0x03, affect, XkbAllBooleanCtrlsMask); 5752f7df2e56Smrg CHK_MASK_MATCH(0x04, affect, stuff->autoCtrls); 5753f7df2e56Smrg CHK_MASK_MATCH(0x05, stuff->autoCtrls, stuff->autoCtrlValues); 5754f7df2e56Smrg 5755f7df2e56Smrg interest->autoCtrls &= ~affect; 5756f7df2e56Smrg interest->autoCtrlValues &= ~affect; 5757f7df2e56Smrg interest->autoCtrls |= stuff->autoCtrls & affect; 5758f7df2e56Smrg interest->autoCtrlValues |= stuff->autoCtrlValues & affect; 5759f7df2e56Smrg } 576005b261ecSmrg } 5761f7df2e56Smrg 5762f7df2e56Smrg rep = (xkbPerClientFlagsReply) { 5763f7df2e56Smrg .type = X_Reply, 5764f7df2e56Smrg .sequenceNumber = client->sequence, 5765f7df2e56Smrg .length = 0, 5766f7df2e56Smrg .supported = XkbPCF_AllFlagsMask, 5767f7df2e56Smrg .value = client->xkbClientFlags & XkbPCF_AllFlagsMask, 5768f7df2e56Smrg .autoCtrls = interest ? interest->autoCtrls : 0, 5769f7df2e56Smrg .autoCtrlValues = interest ? interest->autoCtrlValues : 0, 5770f7df2e56Smrg }; 5771f7df2e56Smrg if (client->swapped) { 5772f7df2e56Smrg swaps(&rep.sequenceNumber); 5773f7df2e56Smrg swapl(&rep.supported); 5774f7df2e56Smrg swapl(&rep.value); 5775f7df2e56Smrg swapl(&rep.autoCtrls); 5776f7df2e56Smrg swapl(&rep.autoCtrlValues); 577705b261ecSmrg } 5778f7df2e56Smrg WriteToClient(client, SIZEOF(xkbPerClientFlagsReply), &rep); 57796747b715Smrg return Success; 578005b261ecSmrg} 578105b261ecSmrg 578205b261ecSmrg/***====================================================================***/ 578305b261ecSmrg 578405b261ecSmrg/* all latin-1 alphanumerics, plus parens, minus, underscore, slash */ 578505b261ecSmrg/* and wildcards */ 578605b261ecSmrgstatic unsigned char componentSpecLegal[] = { 5787f7df2e56Smrg 0x00, 0x00, 0x00, 0x00, 0x00, 0xa7, 0xff, 0x87, 5788f7df2e56Smrg 0xfe, 0xff, 0xff, 0x87, 0xfe, 0xff, 0xff, 0x07, 5789f7df2e56Smrg 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 5790f7df2e56Smrg 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0x7f, 0xff 579105b261ecSmrg}; 579205b261ecSmrg 579305b261ecSmrg/* same as above but accepts percent, plus and bar too */ 579405b261ecSmrgstatic unsigned char componentExprLegal[] = { 5795f7df2e56Smrg 0x00, 0x00, 0x00, 0x00, 0x20, 0xaf, 0xff, 0x87, 5796f7df2e56Smrg 0xfe, 0xff, 0xff, 0x87, 0xfe, 0xff, 0xff, 0x17, 5797f7df2e56Smrg 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 5798f7df2e56Smrg 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0x7f, 0xff 579905b261ecSmrg}; 580005b261ecSmrg 580105b261ecSmrgstatic char * 5802f7df2e56SmrgGetComponentSpec(unsigned char **pWire, Bool allowExpr, int *errRtrn) 580305b261ecSmrg{ 5804f7df2e56Smrg int len; 5805f7df2e56Smrg register int i; 5806f7df2e56Smrg unsigned char *wire, *str, *tmp, *legal; 5807f7df2e56Smrg 5808f7df2e56Smrg if (allowExpr) 5809f7df2e56Smrg legal = &componentExprLegal[0]; 5810f7df2e56Smrg else 5811f7df2e56Smrg legal = &componentSpecLegal[0]; 5812f7df2e56Smrg 5813f7df2e56Smrg wire = *pWire; 5814f7df2e56Smrg len = (*(unsigned char *) wire++); 5815f7df2e56Smrg if (len > 0) { 5816f7df2e56Smrg str = calloc(1, len + 1); 5817f7df2e56Smrg if (str) { 5818f7df2e56Smrg tmp = str; 5819f7df2e56Smrg for (i = 0; i < len; i++) { 5820f7df2e56Smrg if (legal[(*wire) / 8] & (1 << ((*wire) % 8))) 5821f7df2e56Smrg *tmp++ = *wire++; 5822f7df2e56Smrg else 5823f7df2e56Smrg wire++; 5824f7df2e56Smrg } 5825f7df2e56Smrg if (tmp != str) 5826f7df2e56Smrg *tmp++ = '\0'; 5827f7df2e56Smrg else { 5828f7df2e56Smrg free(str); 5829f7df2e56Smrg str = NULL; 5830f7df2e56Smrg } 5831f7df2e56Smrg } 5832f7df2e56Smrg else { 5833f7df2e56Smrg *errRtrn = BadAlloc; 5834f7df2e56Smrg } 583505b261ecSmrg } 583605b261ecSmrg else { 5837f7df2e56Smrg str = NULL; 583805b261ecSmrg } 5839f7df2e56Smrg *pWire = wire; 5840f7df2e56Smrg return (char *) str; 584105b261ecSmrg} 584205b261ecSmrg 584305b261ecSmrg/***====================================================================***/ 584405b261ecSmrg 584505b261ecSmrgint 584605b261ecSmrgProcXkbListComponents(ClientPtr client) 584705b261ecSmrg{ 5848f7df2e56Smrg DeviceIntPtr dev; 5849f7df2e56Smrg xkbListComponentsReply rep; 5850f7df2e56Smrg unsigned len; 5851f7df2e56Smrg unsigned char *str; 5852f7df2e56Smrg uint8_t size; 5853f7df2e56Smrg int i; 585405b261ecSmrg 585505b261ecSmrg REQUEST(xkbListComponentsReq); 585605b261ecSmrg REQUEST_AT_LEAST_SIZE(xkbListComponentsReq); 585705b261ecSmrg 5858f7df2e56Smrg if (!(client->xkbClientFlags & _XkbClientInitialized)) 5859f7df2e56Smrg return BadAccess; 586005b261ecSmrg 58614642e01fSmrg CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess); 586205b261ecSmrg 5863f7df2e56Smrg /* The request is followed by six Pascal strings (i.e. size in characters 5864f7df2e56Smrg * followed by a string pattern) describing what the client wants us to 5865f7df2e56Smrg * list. We don't care, but might as well check they haven't got the 5866f7df2e56Smrg * length wrong. */ 5867f7df2e56Smrg str = (unsigned char *) &stuff[1]; 5868f7df2e56Smrg for (i = 0; i < 6; i++) { 5869f7df2e56Smrg size = *((uint8_t *)str); 5870f7df2e56Smrg len = (str + size + 1) - ((unsigned char *) stuff); 5871f7df2e56Smrg if ((XkbPaddedSize(len) / 4) > stuff->length) 5872f7df2e56Smrg return BadLength; 5873f7df2e56Smrg str += (size + 1); 5874f7df2e56Smrg } 5875f7df2e56Smrg if ((XkbPaddedSize(len) / 4) != stuff->length) 5876f7df2e56Smrg return BadLength; 5877f7df2e56Smrg rep = (xkbListComponentsReply) { 5878f7df2e56Smrg .type = X_Reply, 5879f7df2e56Smrg .deviceID = dev->id, 5880f7df2e56Smrg .sequenceNumber = client->sequence, 5881f7df2e56Smrg .length = 0, 5882f7df2e56Smrg .nKeymaps = 0, 5883f7df2e56Smrg .nKeycodes = 0, 5884f7df2e56Smrg .nTypes = 0, 5885f7df2e56Smrg .nCompatMaps = 0, 5886f7df2e56Smrg .nSymbols = 0, 5887f7df2e56Smrg .nGeometries = 0, 5888f7df2e56Smrg .extra = 0 5889f7df2e56Smrg }; 589005b261ecSmrg if (client->swapped) { 5891f7df2e56Smrg swaps(&rep.sequenceNumber); 5892f7df2e56Smrg swapl(&rep.length); 5893f7df2e56Smrg swaps(&rep.nKeymaps); 5894f7df2e56Smrg swaps(&rep.nKeycodes); 5895f7df2e56Smrg swaps(&rep.nTypes); 5896f7df2e56Smrg swaps(&rep.nCompatMaps); 5897f7df2e56Smrg swaps(&rep.nSymbols); 5898f7df2e56Smrg swaps(&rep.nGeometries); 5899f7df2e56Smrg swaps(&rep.extra); 5900f7df2e56Smrg } 5901f7df2e56Smrg WriteToClient(client, SIZEOF(xkbListComponentsReply), &rep); 59026747b715Smrg return Success; 590305b261ecSmrg} 590405b261ecSmrg 590505b261ecSmrg/***====================================================================***/ 590605b261ecSmrgint 590705b261ecSmrgProcXkbGetKbdByName(ClientPtr client) 590805b261ecSmrg{ 5909f7df2e56Smrg DeviceIntPtr dev; 5910f7df2e56Smrg DeviceIntPtr tmpd; 5911f7df2e56Smrg DeviceIntPtr master; 5912f7df2e56Smrg xkbGetKbdByNameReply rep = { 0 }; 5913f7df2e56Smrg xkbGetMapReply mrep = { 0 }; 5914f7df2e56Smrg xkbGetCompatMapReply crep = { 0 }; 5915f7df2e56Smrg xkbGetIndicatorMapReply irep = { 0 }; 5916f7df2e56Smrg xkbGetNamesReply nrep = { 0 }; 5917f7df2e56Smrg xkbGetGeometryReply grep = { 0 }; 5918f7df2e56Smrg XkbComponentNamesRec names = { 0 }; 5919f7df2e56Smrg XkbDescPtr xkb, new; 5920f7df2e56Smrg XkbEventCauseRec cause; 5921f7df2e56Smrg unsigned char *str; 5922f7df2e56Smrg char mapFile[PATH_MAX]; 5923f7df2e56Smrg unsigned len; 5924f7df2e56Smrg unsigned fwant, fneed, reported; 5925f7df2e56Smrg int status; 5926f7df2e56Smrg Bool geom_changed; 5927f7df2e56Smrg XkbSrvLedInfoPtr old_sli; 5928f7df2e56Smrg XkbSrvLedInfoPtr sli; 59294642e01fSmrg Mask access_mode = DixGetAttrAccess | DixManageAccess; 593005b261ecSmrg 593105b261ecSmrg REQUEST(xkbGetKbdByNameReq); 593205b261ecSmrg REQUEST_AT_LEAST_SIZE(xkbGetKbdByNameReq); 593305b261ecSmrg 5934f7df2e56Smrg if (!(client->xkbClientFlags & _XkbClientInitialized)) 5935f7df2e56Smrg return BadAccess; 593605b261ecSmrg 59374642e01fSmrg CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, access_mode); 5938f7df2e56Smrg master = GetMaster(dev, MASTER_KEYBOARD); 593905b261ecSmrg 594005b261ecSmrg xkb = dev->key->xkbInfo->desc; 5941f7df2e56Smrg status = Success; 5942f7df2e56Smrg str = (unsigned char *) &stuff[1]; 59432d19872aSmrg { 59442d19872aSmrg char *keymap = GetComponentSpec(&str, TRUE, &status); /* keymap, unsupported */ 59452d19872aSmrg if (keymap) { 59462d19872aSmrg free(keymap); 59472d19872aSmrg return BadMatch; 59482d19872aSmrg } 59492d19872aSmrg } 5950f7df2e56Smrg names.keycodes = GetComponentSpec(&str, TRUE, &status); 5951f7df2e56Smrg names.types = GetComponentSpec(&str, TRUE, &status); 5952f7df2e56Smrg names.compat = GetComponentSpec(&str, TRUE, &status); 5953f7df2e56Smrg names.symbols = GetComponentSpec(&str, TRUE, &status); 5954f7df2e56Smrg names.geometry = GetComponentSpec(&str, TRUE, &status); 59552d19872aSmrg if (status == Success) { 59562d19872aSmrg len = str - ((unsigned char *) stuff); 59572d19872aSmrg if ((XkbPaddedSize(len) / 4) != stuff->length) 59582d19872aSmrg status = BadLength; 59592d19872aSmrg } 59602d19872aSmrg 59612d19872aSmrg if (status != Success) { 59622d19872aSmrg free(names.keycodes); 59632d19872aSmrg free(names.types); 59642d19872aSmrg free(names.compat); 59652d19872aSmrg free(names.symbols); 59662d19872aSmrg free(names.geometry); 5967f7df2e56Smrg return status; 59682d19872aSmrg } 5969f7df2e56Smrg 5970f7df2e56Smrg CHK_MASK_LEGAL(0x01, stuff->want, XkbGBN_AllComponentsMask); 5971f7df2e56Smrg CHK_MASK_LEGAL(0x02, stuff->need, XkbGBN_AllComponentsMask); 5972f7df2e56Smrg 597305b261ecSmrg if (stuff->load) 5974f7df2e56Smrg fwant = XkbGBN_AllComponentsMask; 5975f7df2e56Smrg else 5976f7df2e56Smrg fwant = stuff->want | stuff->need; 5977f7df2e56Smrg if ((!names.compat) && 5978f7df2e56Smrg (fwant & (XkbGBN_CompatMapMask | XkbGBN_IndicatorMapMask))) { 5979f7df2e56Smrg names.compat = Xstrdup("%"); 598005b261ecSmrg } 5981f7df2e56Smrg if ((!names.types) && (fwant & (XkbGBN_TypesMask))) { 5982f7df2e56Smrg names.types = Xstrdup("%"); 59834642e01fSmrg } 5984f7df2e56Smrg if ((!names.symbols) && (fwant & XkbGBN_SymbolsMask)) { 5985f7df2e56Smrg names.symbols = Xstrdup("%"); 59864642e01fSmrg } 5987f7df2e56Smrg geom_changed = ((names.geometry != NULL) && 5988f7df2e56Smrg (strcmp(names.geometry, "%") != 0)); 5989f7df2e56Smrg if ((!names.geometry) && (fwant & XkbGBN_GeometryMask)) { 5990f7df2e56Smrg names.geometry = Xstrdup("%"); 5991f7df2e56Smrg geom_changed = FALSE; 599205b261ecSmrg } 599305b261ecSmrg 59946747b715Smrg memset(mapFile, 0, PATH_MAX); 5995f7df2e56Smrg rep.type = X_Reply; 599605b261ecSmrg rep.deviceID = dev->id; 599705b261ecSmrg rep.sequenceNumber = client->sequence; 599805b261ecSmrg rep.length = 0; 599905b261ecSmrg rep.minKeyCode = xkb->min_key_code; 600005b261ecSmrg rep.maxKeyCode = xkb->max_key_code; 6001f7df2e56Smrg rep.loaded = FALSE; 6002f7df2e56Smrg fwant = 6003f7df2e56Smrg XkbConvertGetByNameComponents(TRUE, stuff->want) | XkmVirtualModsMask; 6004f7df2e56Smrg fneed = XkbConvertGetByNameComponents(TRUE, stuff->need); 6005f7df2e56Smrg rep.reported = XkbConvertGetByNameComponents(FALSE, fwant | fneed); 600605b261ecSmrg if (stuff->load) { 6007f7df2e56Smrg fneed |= XkmKeymapRequired; 6008f7df2e56Smrg fwant |= XkmKeymapLegal; 600905b261ecSmrg } 6010f7df2e56Smrg if ((fwant | fneed) & XkmSymbolsMask) { 6011f7df2e56Smrg fneed |= XkmKeyNamesIndex | XkmTypesIndex; 6012f7df2e56Smrg fwant |= XkmIndicatorsIndex; 601305b261ecSmrg } 601405b261ecSmrg 601505b261ecSmrg /* We pass dev in here so we can get the old names out if needed. */ 6016f7df2e56Smrg rep.found = XkbDDXLoadKeymapByNames(dev, &names, fwant, fneed, &new, 6017f7df2e56Smrg mapFile, PATH_MAX); 6018f7df2e56Smrg rep.newKeyboard = FALSE; 6019f7df2e56Smrg rep.pad1 = rep.pad2 = rep.pad3 = rep.pad4 = 0; 6020f7df2e56Smrg 6021f7df2e56Smrg stuff->want |= stuff->need; 6022f7df2e56Smrg if (new == NULL) 6023f7df2e56Smrg rep.reported = 0; 602405b261ecSmrg else { 6025f7df2e56Smrg if (stuff->load) 6026f7df2e56Smrg rep.loaded = TRUE; 6027f7df2e56Smrg if (stuff->load || 6028f7df2e56Smrg ((rep.reported & XkbGBN_SymbolsMask) && (new->compat))) { 6029f7df2e56Smrg XkbChangesRec changes; 6030f7df2e56Smrg 6031f7df2e56Smrg memset(&changes, 0, sizeof(changes)); 6032f7df2e56Smrg XkbUpdateDescActions(new, 6033f7df2e56Smrg new->min_key_code, XkbNumKeys(new), &changes); 6034f7df2e56Smrg } 603505b261ecSmrg 6036f7df2e56Smrg if (new->map == NULL) 6037f7df2e56Smrg rep.reported &= ~(XkbGBN_SymbolsMask | XkbGBN_TypesMask); 6038f7df2e56Smrg else if (rep.reported & (XkbGBN_SymbolsMask | XkbGBN_TypesMask)) { 6039f7df2e56Smrg mrep.type = X_Reply; 6040f7df2e56Smrg mrep.deviceID = dev->id; 6041f7df2e56Smrg mrep.sequenceNumber = client->sequence; 6042f7df2e56Smrg mrep.length = 6043f7df2e56Smrg ((SIZEOF(xkbGetMapReply) - SIZEOF(xGenericReply)) >> 2); 6044f7df2e56Smrg mrep.minKeyCode = new->min_key_code; 6045f7df2e56Smrg mrep.maxKeyCode = new->max_key_code; 6046f7df2e56Smrg mrep.present = 0; 6047f7df2e56Smrg mrep.totalSyms = mrep.totalActs = 6048f7df2e56Smrg mrep.totalKeyBehaviors = mrep.totalKeyExplicit = 6049f7df2e56Smrg mrep.totalModMapKeys = mrep.totalVModMapKeys = 0; 6050f7df2e56Smrg if (rep.reported & (XkbGBN_TypesMask | XkbGBN_ClientSymbolsMask)) { 6051f7df2e56Smrg mrep.present |= XkbKeyTypesMask; 6052f7df2e56Smrg mrep.firstType = 0; 6053f7df2e56Smrg mrep.nTypes = mrep.totalTypes = new->map->num_types; 6054f7df2e56Smrg } 6055f7df2e56Smrg else { 6056f7df2e56Smrg mrep.firstType = mrep.nTypes = 0; 6057f7df2e56Smrg mrep.totalTypes = 0; 6058f7df2e56Smrg } 6059f7df2e56Smrg if (rep.reported & XkbGBN_ClientSymbolsMask) { 6060f7df2e56Smrg mrep.present |= (XkbKeySymsMask | XkbModifierMapMask); 6061f7df2e56Smrg mrep.firstKeySym = mrep.firstModMapKey = new->min_key_code; 6062f7df2e56Smrg mrep.nKeySyms = mrep.nModMapKeys = XkbNumKeys(new); 6063f7df2e56Smrg } 6064f7df2e56Smrg else { 6065f7df2e56Smrg mrep.firstKeySym = mrep.firstModMapKey = 0; 6066f7df2e56Smrg mrep.nKeySyms = mrep.nModMapKeys = 0; 6067f7df2e56Smrg } 6068f7df2e56Smrg if (rep.reported & XkbGBN_ServerSymbolsMask) { 6069f7df2e56Smrg mrep.present |= XkbAllServerInfoMask; 6070f7df2e56Smrg mrep.virtualMods = ~0; 6071f7df2e56Smrg mrep.firstKeyAct = mrep.firstKeyBehavior = 6072f7df2e56Smrg mrep.firstKeyExplicit = new->min_key_code; 6073f7df2e56Smrg mrep.nKeyActs = mrep.nKeyBehaviors = 6074f7df2e56Smrg mrep.nKeyExplicit = XkbNumKeys(new); 6075f7df2e56Smrg mrep.firstVModMapKey = new->min_key_code; 6076f7df2e56Smrg mrep.nVModMapKeys = XkbNumKeys(new); 6077f7df2e56Smrg } 6078f7df2e56Smrg else { 6079f7df2e56Smrg mrep.virtualMods = 0; 6080f7df2e56Smrg mrep.firstKeyAct = mrep.firstKeyBehavior = 6081f7df2e56Smrg mrep.firstKeyExplicit = 0; 6082f7df2e56Smrg mrep.nKeyActs = mrep.nKeyBehaviors = mrep.nKeyExplicit = 0; 6083f7df2e56Smrg } 6084f7df2e56Smrg XkbComputeGetMapReplySize(new, &mrep); 6085f7df2e56Smrg rep.length += SIZEOF(xGenericReply) / 4 + mrep.length; 6086f7df2e56Smrg } 6087f7df2e56Smrg if (new->compat == NULL) 6088f7df2e56Smrg rep.reported &= ~XkbGBN_CompatMapMask; 6089f7df2e56Smrg else if (rep.reported & XkbGBN_CompatMapMask) { 6090f7df2e56Smrg crep.type = X_Reply; 6091f7df2e56Smrg crep.deviceID = dev->id; 6092f7df2e56Smrg crep.sequenceNumber = client->sequence; 6093f7df2e56Smrg crep.length = 0; 6094f7df2e56Smrg crep.groups = XkbAllGroupsMask; 6095f7df2e56Smrg crep.firstSI = 0; 6096f7df2e56Smrg crep.nSI = crep.nTotalSI = new->compat->num_si; 6097f7df2e56Smrg XkbComputeGetCompatMapReplySize(new->compat, &crep); 6098f7df2e56Smrg rep.length += SIZEOF(xGenericReply) / 4 + crep.length; 6099f7df2e56Smrg } 6100f7df2e56Smrg if (new->indicators == NULL) 6101f7df2e56Smrg rep.reported &= ~XkbGBN_IndicatorMapMask; 6102f7df2e56Smrg else if (rep.reported & XkbGBN_IndicatorMapMask) { 6103f7df2e56Smrg irep.type = X_Reply; 6104f7df2e56Smrg irep.deviceID = dev->id; 6105f7df2e56Smrg irep.sequenceNumber = client->sequence; 6106f7df2e56Smrg irep.length = 0; 6107f7df2e56Smrg irep.which = XkbAllIndicatorsMask; 6108f7df2e56Smrg XkbComputeGetIndicatorMapReplySize(new->indicators, &irep); 6109f7df2e56Smrg rep.length += SIZEOF(xGenericReply) / 4 + irep.length; 6110f7df2e56Smrg } 6111f7df2e56Smrg if (new->names == NULL) 6112f7df2e56Smrg rep.reported &= ~(XkbGBN_OtherNamesMask | XkbGBN_KeyNamesMask); 6113f7df2e56Smrg else if (rep.reported & (XkbGBN_OtherNamesMask | XkbGBN_KeyNamesMask)) { 6114f7df2e56Smrg nrep.type = X_Reply; 6115f7df2e56Smrg nrep.deviceID = dev->id; 6116f7df2e56Smrg nrep.sequenceNumber = client->sequence; 6117f7df2e56Smrg nrep.length = 0; 6118f7df2e56Smrg nrep.minKeyCode = new->min_key_code; 6119f7df2e56Smrg nrep.maxKeyCode = new->max_key_code; 6120f7df2e56Smrg if (rep.reported & XkbGBN_OtherNamesMask) { 6121f7df2e56Smrg nrep.which = XkbAllNamesMask; 6122f7df2e56Smrg if (new->map != NULL) 6123f7df2e56Smrg nrep.nTypes = new->map->num_types; 6124f7df2e56Smrg else 6125f7df2e56Smrg nrep.nTypes = 0; 6126f7df2e56Smrg nrep.nKTLevels = 0; 6127f7df2e56Smrg nrep.groupNames = XkbAllGroupsMask; 6128f7df2e56Smrg nrep.virtualMods = XkbAllVirtualModsMask; 6129f7df2e56Smrg nrep.indicators = XkbAllIndicatorsMask; 6130f7df2e56Smrg nrep.nRadioGroups = new->names->num_rg; 6131f7df2e56Smrg } 6132f7df2e56Smrg else { 6133f7df2e56Smrg nrep.which = 0; 6134f7df2e56Smrg nrep.nTypes = 0; 6135f7df2e56Smrg nrep.nKTLevels = 0; 6136f7df2e56Smrg nrep.groupNames = 0; 6137f7df2e56Smrg nrep.virtualMods = 0; 6138f7df2e56Smrg nrep.indicators = 0; 6139f7df2e56Smrg nrep.nRadioGroups = 0; 6140f7df2e56Smrg } 6141f7df2e56Smrg if (rep.reported & XkbGBN_KeyNamesMask) { 6142f7df2e56Smrg nrep.which |= XkbKeyNamesMask; 6143f7df2e56Smrg nrep.firstKey = new->min_key_code; 6144f7df2e56Smrg nrep.nKeys = XkbNumKeys(new); 6145f7df2e56Smrg nrep.nKeyAliases = new->names->num_key_aliases; 6146f7df2e56Smrg if (nrep.nKeyAliases) 6147f7df2e56Smrg nrep.which |= XkbKeyAliasesMask; 6148f7df2e56Smrg } 6149f7df2e56Smrg else { 6150f7df2e56Smrg nrep.which &= ~(XkbKeyNamesMask | XkbKeyAliasesMask); 6151f7df2e56Smrg nrep.firstKey = nrep.nKeys = 0; 6152f7df2e56Smrg nrep.nKeyAliases = 0; 6153f7df2e56Smrg } 6154f7df2e56Smrg XkbComputeGetNamesReplySize(new, &nrep); 6155f7df2e56Smrg rep.length += SIZEOF(xGenericReply) / 4 + nrep.length; 6156f7df2e56Smrg } 6157f7df2e56Smrg if (new->geom == NULL) 6158f7df2e56Smrg rep.reported &= ~XkbGBN_GeometryMask; 6159f7df2e56Smrg else if (rep.reported & XkbGBN_GeometryMask) { 6160f7df2e56Smrg grep.type = X_Reply; 6161f7df2e56Smrg grep.deviceID = dev->id; 6162f7df2e56Smrg grep.sequenceNumber = client->sequence; 6163f7df2e56Smrg grep.length = 0; 6164f7df2e56Smrg grep.found = TRUE; 6165f7df2e56Smrg grep.pad = 0; 6166f7df2e56Smrg grep.widthMM = grep.heightMM = 0; 6167f7df2e56Smrg grep.nProperties = grep.nColors = grep.nShapes = 0; 6168f7df2e56Smrg grep.nSections = grep.nDoodads = 0; 6169f7df2e56Smrg grep.baseColorNdx = grep.labelColorNdx = 0; 6170f7df2e56Smrg XkbComputeGetGeometryReplySize(new->geom, &grep, None); 6171f7df2e56Smrg rep.length += SIZEOF(xGenericReply) / 4 + grep.length; 6172f7df2e56Smrg } 6173f7df2e56Smrg } 6174f7df2e56Smrg 6175f7df2e56Smrg reported = rep.reported; 6176f7df2e56Smrg if (client->swapped) { 6177f7df2e56Smrg swaps(&rep.sequenceNumber); 6178f7df2e56Smrg swapl(&rep.length); 6179f7df2e56Smrg swaps(&rep.found); 6180f7df2e56Smrg swaps(&rep.reported); 6181f7df2e56Smrg } 6182f7df2e56Smrg WriteToClient(client, SIZEOF(xkbGetKbdByNameReply), &rep); 6183f7df2e56Smrg if (reported & (XkbGBN_SymbolsMask | XkbGBN_TypesMask)) 6184f7df2e56Smrg XkbSendMap(client, new, &mrep); 6185f7df2e56Smrg if (reported & XkbGBN_CompatMapMask) 6186f7df2e56Smrg XkbSendCompatMap(client, new->compat, &crep); 6187f7df2e56Smrg if (reported & XkbGBN_IndicatorMapMask) 6188f7df2e56Smrg XkbSendIndicatorMap(client, new->indicators, &irep); 6189f7df2e56Smrg if (reported & (XkbGBN_KeyNamesMask | XkbGBN_OtherNamesMask)) 6190f7df2e56Smrg XkbSendNames(client, new, &nrep); 6191f7df2e56Smrg if (reported & XkbGBN_GeometryMask) 6192f7df2e56Smrg XkbSendGeometry(client, new->geom, &grep, FALSE); 6193f7df2e56Smrg if (rep.loaded) { 6194f7df2e56Smrg XkbDescPtr old_xkb; 6195f7df2e56Smrg xkbNewKeyboardNotify nkn; 6196f7df2e56Smrg 6197f7df2e56Smrg old_xkb = xkb; 6198f7df2e56Smrg xkb = new; 6199f7df2e56Smrg dev->key->xkbInfo->desc = xkb; 6200f7df2e56Smrg new = old_xkb; /* so it'll get freed automatically */ 6201f7df2e56Smrg 6202f7df2e56Smrg XkbCopyControls(xkb, old_xkb); 6203f7df2e56Smrg 6204f7df2e56Smrg nkn.deviceID = nkn.oldDeviceID = dev->id; 6205f7df2e56Smrg nkn.minKeyCode = new->min_key_code; 6206f7df2e56Smrg nkn.maxKeyCode = new->max_key_code; 6207f7df2e56Smrg nkn.oldMinKeyCode = xkb->min_key_code; 6208f7df2e56Smrg nkn.oldMaxKeyCode = xkb->max_key_code; 6209f7df2e56Smrg nkn.requestMajor = XkbReqCode; 6210f7df2e56Smrg nkn.requestMinor = X_kbGetKbdByName; 6211f7df2e56Smrg nkn.changed = XkbNKN_KeycodesMask; 6212f7df2e56Smrg if (geom_changed) 6213f7df2e56Smrg nkn.changed |= XkbNKN_GeometryMask; 6214f7df2e56Smrg XkbSendNewKeyboardNotify(dev, &nkn); 6215f7df2e56Smrg 6216f7df2e56Smrg /* Update the map and LED info on the device itself, as well as 6217f7df2e56Smrg * any slaves if it's an MD, or its MD if it's an SD and was the 6218f7df2e56Smrg * last device used on that MD. */ 621905b261ecSmrg for (tmpd = inputInfo.devices; tmpd; tmpd = tmpd->next) { 6220f7df2e56Smrg if (tmpd != dev && GetMaster(tmpd, MASTER_KEYBOARD) != dev && 6221f7df2e56Smrg (tmpd != master || dev != master->lastSlave)) 6222f7df2e56Smrg continue; 6223f7df2e56Smrg 6224f7df2e56Smrg if (tmpd != dev) 6225f7df2e56Smrg XkbDeviceApplyKeymap(tmpd, xkb); 6226f7df2e56Smrg 6227f7df2e56Smrg if (tmpd->kbdfeed && tmpd->kbdfeed->xkb_sli) { 6228f7df2e56Smrg old_sli = tmpd->kbdfeed->xkb_sli; 6229f7df2e56Smrg tmpd->kbdfeed->xkb_sli = NULL; 6230f7df2e56Smrg sli = XkbAllocSrvLedInfo(tmpd, tmpd->kbdfeed, NULL, 0); 6231f7df2e56Smrg if (sli) { 6232f7df2e56Smrg sli->explicitState = old_sli->explicitState; 6233f7df2e56Smrg sli->effectiveState = old_sli->effectiveState; 623405b261ecSmrg } 6235f7df2e56Smrg tmpd->kbdfeed->xkb_sli = sli; 6236f7df2e56Smrg XkbFreeSrvLedInfo(old_sli); 623705b261ecSmrg } 623805b261ecSmrg } 6239f7df2e56Smrg } 6240f7df2e56Smrg if ((new != NULL) && (new != xkb)) { 6241f7df2e56Smrg XkbFreeKeyboard(new, XkbAllComponentsMask, TRUE); 6242f7df2e56Smrg new = NULL; 624305b261ecSmrg } 62449ace9065Smrg XkbFreeComponentNames(&names, FALSE); 6245f7df2e56Smrg XkbSetCauseXkbReq(&cause, X_kbGetKbdByName, client); 6246f7df2e56Smrg XkbUpdateAllDeviceIndicators(NULL, &cause); 6247f7df2e56Smrg 62486747b715Smrg return Success; 624905b261ecSmrg} 625005b261ecSmrg 625105b261ecSmrg/***====================================================================***/ 625205b261ecSmrg 625305b261ecSmrgstatic int 6254f7df2e56SmrgComputeDeviceLedInfoSize(DeviceIntPtr dev, 6255f7df2e56Smrg unsigned int what, XkbSrvLedInfoPtr sli) 625605b261ecSmrg{ 6257f7df2e56Smrg int nNames, nMaps; 6258f7df2e56Smrg register unsigned n, bit; 6259f7df2e56Smrg 6260f7df2e56Smrg if (sli == NULL) 6261f7df2e56Smrg return 0; 6262f7df2e56Smrg nNames = nMaps = 0; 6263f7df2e56Smrg if ((what & XkbXI_IndicatorNamesMask) == 0) 6264f7df2e56Smrg sli->namesPresent = 0; 6265f7df2e56Smrg if ((what & XkbXI_IndicatorMapsMask) == 0) 6266f7df2e56Smrg sli->mapsPresent = 0; 6267f7df2e56Smrg 6268f7df2e56Smrg for (n = 0, bit = 1; n < XkbNumIndicators; n++, bit <<= 1) { 6269f7df2e56Smrg if (sli->names && sli->names[n] != None) { 6270f7df2e56Smrg sli->namesPresent |= bit; 6271f7df2e56Smrg nNames++; 6272f7df2e56Smrg } 6273f7df2e56Smrg if (sli->maps && XkbIM_InUse(&sli->maps[n])) { 6274f7df2e56Smrg sli->mapsPresent |= bit; 6275f7df2e56Smrg nMaps++; 6276f7df2e56Smrg } 6277f7df2e56Smrg } 6278f7df2e56Smrg return (nNames * 4) + (nMaps * SIZEOF(xkbIndicatorMapWireDesc)); 627905b261ecSmrg} 628005b261ecSmrg 6281f7df2e56Smrgstatic int 6282f7df2e56SmrgCheckDeviceLedFBs(DeviceIntPtr dev, 6283f7df2e56Smrg int class, 6284f7df2e56Smrg int id, xkbGetDeviceInfoReply * rep, ClientPtr client) 628505b261ecSmrg{ 6286f7df2e56Smrg int nFBs = 0; 6287f7df2e56Smrg int length = 0; 6288f7df2e56Smrg Bool classOk; 6289f7df2e56Smrg 6290f7df2e56Smrg if (class == XkbDfltXIClass) { 6291f7df2e56Smrg if (dev->kbdfeed) 6292f7df2e56Smrg class = KbdFeedbackClass; 6293f7df2e56Smrg else if (dev->leds) 6294f7df2e56Smrg class = LedFeedbackClass; 6295f7df2e56Smrg else { 6296f7df2e56Smrg client->errorValue = _XkbErrCode2(XkbErr_BadClass, class); 6297f7df2e56Smrg return XkbKeyboardErrorCode; 6298f7df2e56Smrg } 6299f7df2e56Smrg } 6300f7df2e56Smrg classOk = FALSE; 6301f7df2e56Smrg if ((dev->kbdfeed) && 6302f7df2e56Smrg ((class == KbdFeedbackClass) || (class == XkbAllXIClasses))) { 6303f7df2e56Smrg KbdFeedbackPtr kf; 6304f7df2e56Smrg 6305f7df2e56Smrg classOk = TRUE; 6306f7df2e56Smrg for (kf = dev->kbdfeed; (kf); kf = kf->next) { 6307f7df2e56Smrg if ((id != XkbAllXIIds) && (id != XkbDfltXIId) && 6308f7df2e56Smrg (id != kf->ctrl.id)) 6309f7df2e56Smrg continue; 6310f7df2e56Smrg nFBs++; 6311f7df2e56Smrg length += SIZEOF(xkbDeviceLedsWireDesc); 6312f7df2e56Smrg if (!kf->xkb_sli) 6313f7df2e56Smrg kf->xkb_sli = XkbAllocSrvLedInfo(dev, kf, NULL, 0); 6314f7df2e56Smrg length += ComputeDeviceLedInfoSize(dev, rep->present, kf->xkb_sli); 6315f7df2e56Smrg if (id != XkbAllXIIds) 6316f7df2e56Smrg break; 6317f7df2e56Smrg } 6318f7df2e56Smrg } 6319f7df2e56Smrg if ((dev->leds) && 6320f7df2e56Smrg ((class == LedFeedbackClass) || (class == XkbAllXIClasses))) { 6321f7df2e56Smrg LedFeedbackPtr lf; 6322f7df2e56Smrg 6323f7df2e56Smrg classOk = TRUE; 6324f7df2e56Smrg for (lf = dev->leds; (lf); lf = lf->next) { 6325f7df2e56Smrg if ((id != XkbAllXIIds) && (id != XkbDfltXIId) && 6326f7df2e56Smrg (id != lf->ctrl.id)) 6327f7df2e56Smrg continue; 6328f7df2e56Smrg nFBs++; 6329f7df2e56Smrg length += SIZEOF(xkbDeviceLedsWireDesc); 6330f7df2e56Smrg if (!lf->xkb_sli) 6331f7df2e56Smrg lf->xkb_sli = XkbAllocSrvLedInfo(dev, NULL, lf, 0); 6332f7df2e56Smrg length += ComputeDeviceLedInfoSize(dev, rep->present, lf->xkb_sli); 6333f7df2e56Smrg if (id != XkbAllXIIds) 6334f7df2e56Smrg break; 6335f7df2e56Smrg } 6336f7df2e56Smrg } 6337f7df2e56Smrg if (nFBs > 0) { 6338f7df2e56Smrg rep->nDeviceLedFBs = nFBs; 6339f7df2e56Smrg rep->length += (length / 4); 6340f7df2e56Smrg return Success; 6341f7df2e56Smrg } 6342f7df2e56Smrg if (classOk) 6343f7df2e56Smrg client->errorValue = _XkbErrCode2(XkbErr_BadId, id); 6344f7df2e56Smrg else 6345f7df2e56Smrg client->errorValue = _XkbErrCode2(XkbErr_BadClass, class); 634605b261ecSmrg return XkbKeyboardErrorCode; 634705b261ecSmrg} 634805b261ecSmrg 634905b261ecSmrgstatic int 6350f7df2e56SmrgSendDeviceLedInfo(XkbSrvLedInfoPtr sli, ClientPtr client) 635105b261ecSmrg{ 6352f7df2e56Smrg xkbDeviceLedsWireDesc wire; 6353f7df2e56Smrg int length; 6354f7df2e56Smrg 6355f7df2e56Smrg length = 0; 6356f7df2e56Smrg wire.ledClass = sli->class; 6357f7df2e56Smrg wire.ledID = sli->id; 6358f7df2e56Smrg wire.namesPresent = sli->namesPresent; 6359f7df2e56Smrg wire.mapsPresent = sli->mapsPresent; 6360f7df2e56Smrg wire.physIndicators = sli->physIndicators; 6361f7df2e56Smrg wire.state = sli->effectiveState; 636205b261ecSmrg if (client->swapped) { 6363f7df2e56Smrg swaps(&wire.ledClass); 6364f7df2e56Smrg swaps(&wire.ledID); 6365f7df2e56Smrg swapl(&wire.namesPresent); 6366f7df2e56Smrg swapl(&wire.mapsPresent); 6367f7df2e56Smrg swapl(&wire.physIndicators); 6368f7df2e56Smrg swapl(&wire.state); 6369f7df2e56Smrg } 6370f7df2e56Smrg WriteToClient(client, SIZEOF(xkbDeviceLedsWireDesc), &wire); 6371f7df2e56Smrg length += SIZEOF(xkbDeviceLedsWireDesc); 6372f7df2e56Smrg if (sli->namesPresent | sli->mapsPresent) { 6373f7df2e56Smrg register unsigned i, bit; 6374f7df2e56Smrg 6375f7df2e56Smrg if (sli->namesPresent) { 6376f7df2e56Smrg CARD32 awire; 6377f7df2e56Smrg 6378f7df2e56Smrg for (i = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) { 6379f7df2e56Smrg if (sli->namesPresent & bit) { 6380f7df2e56Smrg awire = (CARD32) sli->names[i]; 6381f7df2e56Smrg if (client->swapped) { 6382f7df2e56Smrg swapl(&awire); 6383f7df2e56Smrg } 6384f7df2e56Smrg WriteToClient(client, 4, &awire); 6385f7df2e56Smrg length += 4; 6386f7df2e56Smrg } 6387f7df2e56Smrg } 6388f7df2e56Smrg } 6389f7df2e56Smrg if (sli->mapsPresent) { 6390f7df2e56Smrg for (i = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) { 6391f7df2e56Smrg xkbIndicatorMapWireDesc iwire; 6392f7df2e56Smrg 6393f7df2e56Smrg if (sli->mapsPresent & bit) { 6394f7df2e56Smrg iwire.flags = sli->maps[i].flags; 6395f7df2e56Smrg iwire.whichGroups = sli->maps[i].which_groups; 6396f7df2e56Smrg iwire.groups = sli->maps[i].groups; 6397f7df2e56Smrg iwire.whichMods = sli->maps[i].which_mods; 6398f7df2e56Smrg iwire.mods = sli->maps[i].mods.mask; 6399f7df2e56Smrg iwire.realMods = sli->maps[i].mods.real_mods; 6400f7df2e56Smrg iwire.virtualMods = sli->maps[i].mods.vmods; 6401f7df2e56Smrg iwire.ctrls = sli->maps[i].ctrls; 6402f7df2e56Smrg if (client->swapped) { 6403f7df2e56Smrg swaps(&iwire.virtualMods); 6404f7df2e56Smrg swapl(&iwire.ctrls); 6405f7df2e56Smrg } 6406f7df2e56Smrg WriteToClient(client, SIZEOF(xkbIndicatorMapWireDesc), 6407f7df2e56Smrg &iwire); 6408f7df2e56Smrg length += SIZEOF(xkbIndicatorMapWireDesc); 6409f7df2e56Smrg } 6410f7df2e56Smrg } 6411f7df2e56Smrg } 641205b261ecSmrg } 641305b261ecSmrg return length; 641405b261ecSmrg} 641505b261ecSmrg 641605b261ecSmrgstatic int 6417f7df2e56SmrgSendDeviceLedFBs(DeviceIntPtr dev, 6418f7df2e56Smrg int class, int id, unsigned wantLength, ClientPtr client) 641905b261ecSmrg{ 6420f7df2e56Smrg int length = 0; 6421f7df2e56Smrg 6422f7df2e56Smrg if (class == XkbDfltXIClass) { 6423f7df2e56Smrg if (dev->kbdfeed) 6424f7df2e56Smrg class = KbdFeedbackClass; 6425f7df2e56Smrg else if (dev->leds) 6426f7df2e56Smrg class = LedFeedbackClass; 6427f7df2e56Smrg } 6428f7df2e56Smrg if ((dev->kbdfeed) && 6429f7df2e56Smrg ((class == KbdFeedbackClass) || (class == XkbAllXIClasses))) { 6430f7df2e56Smrg KbdFeedbackPtr kf; 6431f7df2e56Smrg 6432f7df2e56Smrg for (kf = dev->kbdfeed; (kf); kf = kf->next) { 6433f7df2e56Smrg if ((id == XkbAllXIIds) || (id == XkbDfltXIId) || 6434f7df2e56Smrg (id == kf->ctrl.id)) { 6435f7df2e56Smrg length += SendDeviceLedInfo(kf->xkb_sli, client); 6436f7df2e56Smrg if (id != XkbAllXIIds) 6437f7df2e56Smrg break; 6438f7df2e56Smrg } 6439f7df2e56Smrg } 6440f7df2e56Smrg } 6441f7df2e56Smrg if ((dev->leds) && 6442f7df2e56Smrg ((class == LedFeedbackClass) || (class == XkbAllXIClasses))) { 6443f7df2e56Smrg LedFeedbackPtr lf; 6444f7df2e56Smrg 6445f7df2e56Smrg for (lf = dev->leds; (lf); lf = lf->next) { 6446f7df2e56Smrg if ((id == XkbAllXIIds) || (id == XkbDfltXIId) || 6447f7df2e56Smrg (id == lf->ctrl.id)) { 6448f7df2e56Smrg length += SendDeviceLedInfo(lf->xkb_sli, client); 6449f7df2e56Smrg if (id != XkbAllXIIds) 6450f7df2e56Smrg break; 6451f7df2e56Smrg } 6452f7df2e56Smrg } 6453f7df2e56Smrg } 6454f7df2e56Smrg if (length == wantLength) 6455f7df2e56Smrg return Success; 6456f7df2e56Smrg else 6457f7df2e56Smrg return BadLength; 645805b261ecSmrg} 645905b261ecSmrg 646005b261ecSmrgint 646105b261ecSmrgProcXkbGetDeviceInfo(ClientPtr client) 646205b261ecSmrg{ 6463f7df2e56Smrg DeviceIntPtr dev; 6464f7df2e56Smrg xkbGetDeviceInfoReply rep; 6465f7df2e56Smrg int status, nDeviceLedFBs; 6466f7df2e56Smrg unsigned length, nameLen; 6467f7df2e56Smrg CARD16 ledClass, ledID; 6468f7df2e56Smrg unsigned wanted; 6469f7df2e56Smrg char *str; 647005b261ecSmrg 647105b261ecSmrg REQUEST(xkbGetDeviceInfoReq); 647205b261ecSmrg REQUEST_SIZE_MATCH(xkbGetDeviceInfoReq); 647305b261ecSmrg 6474f7df2e56Smrg if (!(client->xkbClientFlags & _XkbClientInitialized)) 6475f7df2e56Smrg return BadAccess; 647605b261ecSmrg 6477f7df2e56Smrg wanted = stuff->wanted; 647805b261ecSmrg 64794642e01fSmrg CHK_ANY_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess); 6480f7df2e56Smrg CHK_MASK_LEGAL(0x01, wanted, XkbXI_AllDeviceFeaturesMask); 6481f7df2e56Smrg 6482f7df2e56Smrg if ((!dev->button) || ((stuff->nBtns < 1) && (!stuff->allBtns))) 6483f7df2e56Smrg wanted &= ~XkbXI_ButtonActionsMask; 6484f7df2e56Smrg if ((!dev->kbdfeed) && (!dev->leds)) 6485f7df2e56Smrg wanted &= ~XkbXI_IndicatorsMask; 6486f7df2e56Smrg 6487f7df2e56Smrg nameLen = XkbSizeCountedString(dev->name); 6488f7df2e56Smrg rep = (xkbGetDeviceInfoReply) { 6489f7df2e56Smrg .type = X_Reply, 6490f7df2e56Smrg .deviceID = dev->id, 6491f7df2e56Smrg .sequenceNumber = client->sequence, 6492f7df2e56Smrg .length = nameLen / 4, 6493f7df2e56Smrg .present = wanted, 6494f7df2e56Smrg .supported = XkbXI_AllDeviceFeaturesMask, 6495f7df2e56Smrg .unsupported = 0, 6496f7df2e56Smrg .nDeviceLedFBs = 0, 6497f7df2e56Smrg .firstBtnWanted = 0, 6498f7df2e56Smrg .nBtnsWanted = 0, 6499f7df2e56Smrg .firstBtnRtrn = 0, 6500f7df2e56Smrg .nBtnsRtrn = 0, 6501f7df2e56Smrg .totalBtns = dev->button ? dev->button->numButtons : 0, 6502f7df2e56Smrg .hasOwnState = (dev->key && dev->key->xkbInfo), 6503f7df2e56Smrg .dfltKbdFB = dev->kbdfeed ? dev->kbdfeed->ctrl.id : XkbXINone, 6504f7df2e56Smrg .dfltLedFB = dev->leds ? dev->leds->ctrl.id : XkbXINone, 6505f7df2e56Smrg .devType = dev->xinput_type 6506f7df2e56Smrg }; 6507f7df2e56Smrg 6508f7df2e56Smrg ledClass = stuff->ledClass; 6509f7df2e56Smrg ledID = stuff->ledID; 6510f7df2e56Smrg 6511f7df2e56Smrg if (wanted & XkbXI_ButtonActionsMask) { 6512f7df2e56Smrg if (stuff->allBtns) { 6513f7df2e56Smrg stuff->firstBtn = 0; 6514f7df2e56Smrg stuff->nBtns = dev->button->numButtons; 6515f7df2e56Smrg } 651605b261ecSmrg 6517f7df2e56Smrg if ((stuff->firstBtn + stuff->nBtns) > dev->button->numButtons) { 6518f7df2e56Smrg client->errorValue = _XkbErrCode4(0x02, dev->button->numButtons, 6519f7df2e56Smrg stuff->firstBtn, stuff->nBtns); 6520f7df2e56Smrg return BadValue; 6521f7df2e56Smrg } 6522f7df2e56Smrg else { 6523f7df2e56Smrg rep.firstBtnWanted = stuff->firstBtn; 6524f7df2e56Smrg rep.nBtnsWanted = stuff->nBtns; 6525f7df2e56Smrg if (dev->button->xkb_acts != NULL) { 6526f7df2e56Smrg XkbAction *act; 6527f7df2e56Smrg register int i; 6528f7df2e56Smrg 6529f7df2e56Smrg rep.firstBtnRtrn = stuff->firstBtn; 6530f7df2e56Smrg rep.nBtnsRtrn = stuff->nBtns; 6531f7df2e56Smrg act = &dev->button->xkb_acts[rep.firstBtnWanted]; 6532f7df2e56Smrg for (i = 0; i < rep.nBtnsRtrn; i++, act++) { 6533f7df2e56Smrg if (act->type != XkbSA_NoAction) 6534f7df2e56Smrg break; 6535f7df2e56Smrg } 6536f7df2e56Smrg rep.firstBtnRtrn += i; 6537f7df2e56Smrg rep.nBtnsRtrn -= i; 6538f7df2e56Smrg act = 6539f7df2e56Smrg &dev->button->xkb_acts[rep.firstBtnRtrn + rep.nBtnsRtrn - 6540f7df2e56Smrg 1]; 6541f7df2e56Smrg for (i = 0; i < rep.nBtnsRtrn; i++, act--) { 6542f7df2e56Smrg if (act->type != XkbSA_NoAction) 6543f7df2e56Smrg break; 6544f7df2e56Smrg } 6545f7df2e56Smrg rep.nBtnsRtrn -= i; 6546f7df2e56Smrg } 6547f7df2e56Smrg rep.length += (rep.nBtnsRtrn * SIZEOF(xkbActionWireDesc)) / 4; 6548f7df2e56Smrg } 6549f7df2e56Smrg } 655005b261ecSmrg 6551f7df2e56Smrg if (wanted & XkbXI_IndicatorsMask) { 6552f7df2e56Smrg status = CheckDeviceLedFBs(dev, ledClass, ledID, &rep, client); 6553f7df2e56Smrg if (status != Success) 6554f7df2e56Smrg return status; 6555f7df2e56Smrg } 6556f7df2e56Smrg length = rep.length * 4; 655705b261ecSmrg nDeviceLedFBs = rep.nDeviceLedFBs; 655805b261ecSmrg if (client->swapped) { 6559f7df2e56Smrg swaps(&rep.sequenceNumber); 6560f7df2e56Smrg swapl(&rep.length); 6561f7df2e56Smrg swaps(&rep.present); 6562f7df2e56Smrg swaps(&rep.supported); 6563f7df2e56Smrg swaps(&rep.unsupported); 6564f7df2e56Smrg swaps(&rep.nDeviceLedFBs); 6565f7df2e56Smrg swaps(&rep.dfltKbdFB); 6566f7df2e56Smrg swaps(&rep.dfltLedFB); 6567f7df2e56Smrg swapl(&rep.devType); 6568f7df2e56Smrg } 6569f7df2e56Smrg WriteToClient(client, SIZEOF(xkbGetDeviceInfoReply), &rep); 6570f7df2e56Smrg 6571f7df2e56Smrg str = malloc(nameLen); 6572f7df2e56Smrg if (!str) 6573f7df2e56Smrg return BadAlloc; 6574f7df2e56Smrg XkbWriteCountedString(str, dev->name, client->swapped); 6575f7df2e56Smrg WriteToClient(client, nameLen, str); 65766747b715Smrg free(str); 6577f7df2e56Smrg length -= nameLen; 6578f7df2e56Smrg 6579f7df2e56Smrg if (rep.nBtnsRtrn > 0) { 6580f7df2e56Smrg int sz; 6581f7df2e56Smrg xkbActionWireDesc *awire; 6582f7df2e56Smrg 6583f7df2e56Smrg sz = rep.nBtnsRtrn * SIZEOF(xkbActionWireDesc); 6584f7df2e56Smrg awire = (xkbActionWireDesc *) &dev->button->xkb_acts[rep.firstBtnRtrn]; 6585f7df2e56Smrg WriteToClient(client, sz, awire); 6586f7df2e56Smrg length -= sz; 6587f7df2e56Smrg } 6588f7df2e56Smrg if (nDeviceLedFBs > 0) { 6589f7df2e56Smrg status = SendDeviceLedFBs(dev, ledClass, ledID, length, client); 6590f7df2e56Smrg if (status != Success) 6591f7df2e56Smrg return status; 6592f7df2e56Smrg } 6593f7df2e56Smrg else if (length != 0) { 6594f7df2e56Smrg ErrorF("[xkb] Internal Error! BadLength in ProcXkbGetDeviceInfo\n"); 6595f7df2e56Smrg ErrorF("[xkb] Wrote %d fewer bytes than expected\n", 6596f7df2e56Smrg length); 6597f7df2e56Smrg return BadLength; 659805b261ecSmrg } 65996747b715Smrg return Success; 660005b261ecSmrg} 660105b261ecSmrg 660205b261ecSmrgstatic char * 6603f7df2e56SmrgCheckSetDeviceIndicators(char *wire, 6604f7df2e56Smrg DeviceIntPtr dev, 660590bea6a0Smrg int num, int *status_rtrn, ClientPtr client, 660690bea6a0Smrg xkbSetDeviceInfoReq * stuff) 660705b261ecSmrg{ 6608f7df2e56Smrg xkbDeviceLedsWireDesc *ledWire; 6609f7df2e56Smrg int i; 6610f7df2e56Smrg XkbSrvLedInfoPtr sli; 6611f7df2e56Smrg 6612f7df2e56Smrg ledWire = (xkbDeviceLedsWireDesc *) wire; 6613f7df2e56Smrg for (i = 0; i < num; i++) { 661490bea6a0Smrg if (!_XkbCheckRequestBounds(client, stuff, ledWire, ledWire + 1)) { 661590bea6a0Smrg *status_rtrn = BadLength; 661690bea6a0Smrg return (char *) ledWire; 661790bea6a0Smrg } 661890bea6a0Smrg 6619f7df2e56Smrg if (client->swapped) { 6620f7df2e56Smrg swaps(&ledWire->ledClass); 6621f7df2e56Smrg swaps(&ledWire->ledID); 6622f7df2e56Smrg swapl(&ledWire->namesPresent); 6623f7df2e56Smrg swapl(&ledWire->mapsPresent); 6624f7df2e56Smrg swapl(&ledWire->physIndicators); 6625f7df2e56Smrg } 6626f7df2e56Smrg 6627f7df2e56Smrg sli = XkbFindSrvLedInfo(dev, ledWire->ledClass, ledWire->ledID, 6628f7df2e56Smrg XkbXI_IndicatorsMask); 6629f7df2e56Smrg if (sli != NULL) { 6630f7df2e56Smrg register int n; 6631f7df2e56Smrg register unsigned bit; 6632f7df2e56Smrg int nMaps, nNames; 6633f7df2e56Smrg CARD32 *atomWire; 6634f7df2e56Smrg xkbIndicatorMapWireDesc *mapWire; 6635f7df2e56Smrg 6636f7df2e56Smrg nMaps = nNames = 0; 6637f7df2e56Smrg for (n = 0, bit = 1; n < XkbNumIndicators; n++, bit <<= 1) { 6638f7df2e56Smrg if (ledWire->namesPresent & bit) 6639f7df2e56Smrg nNames++; 6640f7df2e56Smrg if (ledWire->mapsPresent & bit) 6641f7df2e56Smrg nMaps++; 6642f7df2e56Smrg } 6643f7df2e56Smrg atomWire = (CARD32 *) &ledWire[1]; 6644f7df2e56Smrg if (nNames > 0) { 6645f7df2e56Smrg for (n = 0; n < nNames; n++) { 664690bea6a0Smrg if (!_XkbCheckRequestBounds(client, stuff, atomWire, atomWire + 1)) { 664790bea6a0Smrg *status_rtrn = BadLength; 664890bea6a0Smrg return (char *) atomWire; 664990bea6a0Smrg } 665090bea6a0Smrg 6651f7df2e56Smrg if (client->swapped) { 6652f7df2e56Smrg swapl(atomWire); 6653f7df2e56Smrg } 6654f7df2e56Smrg CHK_ATOM_OR_NONE3(((Atom) (*atomWire)), client->errorValue, 6655f7df2e56Smrg *status_rtrn, NULL); 6656f7df2e56Smrg atomWire++; 6657f7df2e56Smrg } 6658f7df2e56Smrg } 6659f7df2e56Smrg mapWire = (xkbIndicatorMapWireDesc *) atomWire; 6660f7df2e56Smrg if (nMaps > 0) { 6661f7df2e56Smrg for (n = 0; n < nMaps; n++) { 666290bea6a0Smrg if (!_XkbCheckRequestBounds(client, stuff, mapWire, mapWire + 1)) { 666390bea6a0Smrg *status_rtrn = BadLength; 666490bea6a0Smrg return (char *) mapWire; 666590bea6a0Smrg } 6666f7df2e56Smrg if (client->swapped) { 6667f7df2e56Smrg swaps(&mapWire->virtualMods); 6668f7df2e56Smrg swapl(&mapWire->ctrls); 6669f7df2e56Smrg } 6670f7df2e56Smrg CHK_MASK_LEGAL3(0x21, mapWire->whichGroups, 6671f7df2e56Smrg XkbIM_UseAnyGroup, 6672f7df2e56Smrg client->errorValue, *status_rtrn, NULL); 6673f7df2e56Smrg CHK_MASK_LEGAL3(0x22, mapWire->whichMods, XkbIM_UseAnyMods, 6674f7df2e56Smrg client->errorValue, *status_rtrn, NULL); 6675f7df2e56Smrg mapWire++; 6676f7df2e56Smrg } 6677f7df2e56Smrg } 6678f7df2e56Smrg ledWire = (xkbDeviceLedsWireDesc *) mapWire; 6679f7df2e56Smrg } 6680f7df2e56Smrg else { 6681f7df2e56Smrg /* SHOULD NEVER HAPPEN */ 6682f7df2e56Smrg return (char *) ledWire; 6683f7df2e56Smrg } 6684f7df2e56Smrg } 6685f7df2e56Smrg return (char *) ledWire; 668605b261ecSmrg} 668705b261ecSmrg 668805b261ecSmrgstatic char * 6689f7df2e56SmrgSetDeviceIndicators(char *wire, 6690f7df2e56Smrg DeviceIntPtr dev, 6691f7df2e56Smrg unsigned changed, 6692f7df2e56Smrg int num, 6693f7df2e56Smrg int *status_rtrn, 6694806e81e9Smrg ClientPtr client, 6695806e81e9Smrg xkbExtensionDeviceNotify * ev, 6696806e81e9Smrg xkbSetDeviceInfoReq * stuff) 669705b261ecSmrg{ 6698f7df2e56Smrg xkbDeviceLedsWireDesc *ledWire; 6699f7df2e56Smrg int i; 6700f7df2e56Smrg XkbEventCauseRec cause; 6701f7df2e56Smrg unsigned namec, mapc, statec; 6702f7df2e56Smrg xkbExtensionDeviceNotify ed; 6703f7df2e56Smrg XkbChangesRec changes; 6704f7df2e56Smrg DeviceIntPtr kbd; 6705f7df2e56Smrg 6706f7df2e56Smrg memset((char *) &ed, 0, sizeof(xkbExtensionDeviceNotify)); 6707f7df2e56Smrg memset((char *) &changes, 0, sizeof(XkbChangesRec)); 6708f7df2e56Smrg XkbSetCauseXkbReq(&cause, X_kbSetDeviceInfo, client); 6709f7df2e56Smrg ledWire = (xkbDeviceLedsWireDesc *) wire; 6710f7df2e56Smrg for (i = 0; i < num; i++) { 6711f7df2e56Smrg register int n; 6712f7df2e56Smrg register unsigned bit; 6713f7df2e56Smrg CARD32 *atomWire; 6714f7df2e56Smrg xkbIndicatorMapWireDesc *mapWire; 6715f7df2e56Smrg XkbSrvLedInfoPtr sli; 6716f7df2e56Smrg 6717f7df2e56Smrg namec = mapc = statec = 0; 6718f7df2e56Smrg sli = XkbFindSrvLedInfo(dev, ledWire->ledClass, ledWire->ledID, 6719f7df2e56Smrg XkbXI_IndicatorMapsMask); 6720f7df2e56Smrg if (!sli) { 6721f7df2e56Smrg /* SHOULD NEVER HAPPEN!! */ 6722f7df2e56Smrg return (char *) ledWire; 6723f7df2e56Smrg } 672405b261ecSmrg 6725f7df2e56Smrg atomWire = (CARD32 *) &ledWire[1]; 6726f7df2e56Smrg if (changed & XkbXI_IndicatorNamesMask) { 6727f7df2e56Smrg namec = sli->namesPresent | ledWire->namesPresent; 6728f7df2e56Smrg memset((char *) sli->names, 0, XkbNumIndicators * sizeof(Atom)); 6729f7df2e56Smrg } 6730f7df2e56Smrg if (ledWire->namesPresent) { 6731f7df2e56Smrg sli->namesPresent = ledWire->namesPresent; 6732f7df2e56Smrg memset((char *) sli->names, 0, XkbNumIndicators * sizeof(Atom)); 6733f7df2e56Smrg for (n = 0, bit = 1; n < XkbNumIndicators; n++, bit <<= 1) { 6734f7df2e56Smrg if (ledWire->namesPresent & bit) { 6735f7df2e56Smrg sli->names[n] = (Atom) *atomWire; 6736f7df2e56Smrg if (sli->names[n] == None) 6737f7df2e56Smrg ledWire->namesPresent &= ~bit; 6738f7df2e56Smrg atomWire++; 6739f7df2e56Smrg } 6740f7df2e56Smrg } 6741f7df2e56Smrg } 6742f7df2e56Smrg mapWire = (xkbIndicatorMapWireDesc *) atomWire; 6743f7df2e56Smrg if (changed & XkbXI_IndicatorMapsMask) { 6744f7df2e56Smrg mapc = sli->mapsPresent | ledWire->mapsPresent; 6745f7df2e56Smrg sli->mapsPresent = ledWire->mapsPresent; 6746f7df2e56Smrg memset((char *) sli->maps, 0, 6747f7df2e56Smrg XkbNumIndicators * sizeof(XkbIndicatorMapRec)); 6748f7df2e56Smrg } 6749f7df2e56Smrg if (ledWire->mapsPresent) { 6750f7df2e56Smrg for (n = 0, bit = 1; n < XkbNumIndicators; n++, bit <<= 1) { 6751f7df2e56Smrg if (ledWire->mapsPresent & bit) { 6752f7df2e56Smrg sli->maps[n].flags = mapWire->flags; 6753f7df2e56Smrg sli->maps[n].which_groups = mapWire->whichGroups; 6754f7df2e56Smrg sli->maps[n].groups = mapWire->groups; 6755f7df2e56Smrg sli->maps[n].which_mods = mapWire->whichMods; 6756f7df2e56Smrg sli->maps[n].mods.mask = mapWire->mods; 6757f7df2e56Smrg sli->maps[n].mods.real_mods = mapWire->realMods; 6758f7df2e56Smrg sli->maps[n].mods.vmods = mapWire->virtualMods; 6759f7df2e56Smrg sli->maps[n].ctrls = mapWire->ctrls; 6760f7df2e56Smrg mapWire++; 6761f7df2e56Smrg } 6762f7df2e56Smrg } 6763f7df2e56Smrg } 6764f7df2e56Smrg if (changed & XkbXI_IndicatorStateMask) { 6765f7df2e56Smrg statec = sli->effectiveState ^ ledWire->state; 6766f7df2e56Smrg sli->explicitState &= ~statec; 6767f7df2e56Smrg sli->explicitState |= (ledWire->state & statec); 6768f7df2e56Smrg } 6769f7df2e56Smrg if (namec) 6770f7df2e56Smrg XkbApplyLedNameChanges(dev, sli, namec, &ed, &changes, &cause); 6771f7df2e56Smrg if (mapc) 6772f7df2e56Smrg XkbApplyLedMapChanges(dev, sli, mapc, &ed, &changes, &cause); 6773f7df2e56Smrg if (statec) 6774f7df2e56Smrg XkbApplyLedStateChanges(dev, sli, statec, &ed, &changes, &cause); 6775f7df2e56Smrg 6776f7df2e56Smrg kbd = dev; 6777f7df2e56Smrg if ((sli->flags & XkbSLI_HasOwnState) == 0) 6778f7df2e56Smrg kbd = inputInfo.keyboard; 6779f7df2e56Smrg 6780f7df2e56Smrg XkbFlushLedEvents(dev, kbd, sli, &ed, &changes, &cause); 6781f7df2e56Smrg ledWire = (xkbDeviceLedsWireDesc *) mapWire; 6782f7df2e56Smrg } 6783f7df2e56Smrg return (char *) ledWire; 6784f7df2e56Smrg} 678505b261ecSmrg 67864642e01fSmrgstatic int 678790bea6a0Smrg_XkbSetDeviceInfoCheck(ClientPtr client, DeviceIntPtr dev, 6788f7df2e56Smrg xkbSetDeviceInfoReq * stuff) 67894642e01fSmrg{ 6790f7df2e56Smrg char *wire; 6791f7df2e56Smrg 6792f7df2e56Smrg wire = (char *) &stuff[1]; 6793f7df2e56Smrg if (stuff->change & XkbXI_ButtonActionsMask) { 679490bea6a0Smrg int sz = stuff->nBtns * SIZEOF(xkbActionWireDesc); 679590bea6a0Smrg if (!_XkbCheckRequestBounds(client, stuff, wire, (char *) wire + sz)) 679690bea6a0Smrg return BadLength; 679790bea6a0Smrg 6798f7df2e56Smrg if (!dev->button) { 6799f7df2e56Smrg client->errorValue = _XkbErrCode2(XkbErr_BadClass, ButtonClass); 6800f7df2e56Smrg return XkbKeyboardErrorCode; 6801f7df2e56Smrg } 6802f7df2e56Smrg if ((stuff->firstBtn + stuff->nBtns) > dev->button->numButtons) { 6803f7df2e56Smrg client->errorValue = 6804f7df2e56Smrg _XkbErrCode4(0x02, stuff->firstBtn, stuff->nBtns, 6805f7df2e56Smrg dev->button->numButtons); 6806f7df2e56Smrg return BadMatch; 6807f7df2e56Smrg } 680890bea6a0Smrg wire += sz; 6809f7df2e56Smrg } 6810f7df2e56Smrg if (stuff->change & XkbXI_IndicatorsMask) { 6811f7df2e56Smrg int status = Success; 6812f7df2e56Smrg 6813f7df2e56Smrg wire = CheckSetDeviceIndicators(wire, dev, stuff->nDeviceLedFBs, 681490bea6a0Smrg &status, client, stuff); 6815f7df2e56Smrg if (status != Success) 6816f7df2e56Smrg return status; 6817f7df2e56Smrg } 6818f7df2e56Smrg if (((wire - ((char *) stuff)) / 4) != stuff->length) 6819f7df2e56Smrg return BadLength; 682005b261ecSmrg 68214642e01fSmrg return Success; 68224642e01fSmrg} 68234642e01fSmrg 68244642e01fSmrgstatic int 682590bea6a0Smrg_XkbSetDeviceInfo(ClientPtr client, DeviceIntPtr dev, 682690bea6a0Smrg xkbSetDeviceInfoReq * stuff) 68274642e01fSmrg{ 6828f7df2e56Smrg char *wire; 6829f7df2e56Smrg xkbExtensionDeviceNotify ed; 6830f7df2e56Smrg 6831f7df2e56Smrg memset((char *) &ed, 0, SIZEOF(xkbExtensionDeviceNotify)); 6832f7df2e56Smrg ed.deviceID = dev->id; 6833f7df2e56Smrg wire = (char *) &stuff[1]; 6834f7df2e56Smrg if (stuff->change & XkbXI_ButtonActionsMask) { 6835806e81e9Smrg int nBtns, sz, i; 6836f7df2e56Smrg XkbAction *acts; 6837f7df2e56Smrg DeviceIntPtr kbd; 6838f7df2e56Smrg 6839f7df2e56Smrg nBtns = dev->button->numButtons; 6840f7df2e56Smrg acts = dev->button->xkb_acts; 6841f7df2e56Smrg if (acts == NULL) { 6842f7df2e56Smrg acts = calloc(nBtns, sizeof(XkbAction)); 6843f7df2e56Smrg if (!acts) 6844f7df2e56Smrg return BadAlloc; 6845f7df2e56Smrg dev->button->xkb_acts = acts; 6846f7df2e56Smrg } 6847806e81e9Smrg if (stuff->firstBtn + stuff->nBtns > nBtns) 6848806e81e9Smrg return BadValue; 6849f7df2e56Smrg sz = stuff->nBtns * SIZEOF(xkbActionWireDesc); 6850f7df2e56Smrg memcpy((char *) &acts[stuff->firstBtn], (char *) wire, sz); 6851f7df2e56Smrg wire += sz; 6852f7df2e56Smrg ed.reason |= XkbXI_ButtonActionsMask; 6853f7df2e56Smrg ed.firstBtn = stuff->firstBtn; 6854f7df2e56Smrg ed.nBtns = stuff->nBtns; 6855f7df2e56Smrg 6856f7df2e56Smrg if (dev->key) 6857f7df2e56Smrg kbd = dev; 6858f7df2e56Smrg else 6859f7df2e56Smrg kbd = inputInfo.keyboard; 6860f7df2e56Smrg acts = &dev->button->xkb_acts[stuff->firstBtn]; 6861f7df2e56Smrg for (i = 0; i < stuff->nBtns; i++, acts++) { 6862f7df2e56Smrg if (acts->type != XkbSA_NoAction) 6863f7df2e56Smrg XkbSetActionKeyMods(kbd->key->xkbInfo->desc, acts, 0); 6864f7df2e56Smrg } 6865f7df2e56Smrg } 6866f7df2e56Smrg if (stuff->change & XkbXI_IndicatorsMask) { 6867f7df2e56Smrg int status = Success; 6868f7df2e56Smrg 6869f7df2e56Smrg wire = SetDeviceIndicators(wire, dev, stuff->change, 6870806e81e9Smrg stuff->nDeviceLedFBs, &status, client, &ed, 6871806e81e9Smrg stuff); 6872f7df2e56Smrg if (status != Success) 6873f7df2e56Smrg return status; 6874f7df2e56Smrg } 6875f7df2e56Smrg if ((stuff->change) && (ed.reason)) 6876f7df2e56Smrg XkbSendExtensionDeviceNotify(dev, client, &ed); 68774642e01fSmrg return Success; 68784642e01fSmrg} 68794642e01fSmrg 68804642e01fSmrgint 68814642e01fSmrgProcXkbSetDeviceInfo(ClientPtr client) 68824642e01fSmrg{ 6883f7df2e56Smrg DeviceIntPtr dev; 6884f7df2e56Smrg int rc; 68854642e01fSmrg 68864642e01fSmrg REQUEST(xkbSetDeviceInfoReq); 68874642e01fSmrg REQUEST_AT_LEAST_SIZE(xkbSetDeviceInfoReq); 68884642e01fSmrg 6889f7df2e56Smrg if (!(client->xkbClientFlags & _XkbClientInitialized)) 6890f7df2e56Smrg return BadAccess; 68914642e01fSmrg 68924642e01fSmrg CHK_ANY_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess); 6893f7df2e56Smrg CHK_MASK_LEGAL(0x01, stuff->change, XkbXI_AllFeaturesMask); 68944642e01fSmrg 68954642e01fSmrg rc = _XkbSetDeviceInfoCheck(client, dev, stuff); 68964642e01fSmrg 68974642e01fSmrg if (rc != Success) 68984642e01fSmrg return rc; 68994642e01fSmrg 6900f7df2e56Smrg if (stuff->deviceSpec == XkbUseCoreKbd || 6901f7df2e56Smrg stuff->deviceSpec == XkbUseCorePtr) { 69024642e01fSmrg DeviceIntPtr other; 6903f7df2e56Smrg 6904f7df2e56Smrg for (other = inputInfo.devices; other; other = other->next) { 6905f7df2e56Smrg if (((other != dev) && !IsMaster(other) && 6906f7df2e56Smrg GetMaster(other, MASTER_KEYBOARD) == dev) && 69074642e01fSmrg ((stuff->deviceSpec == XkbUseCoreKbd && other->key) || 6908f7df2e56Smrg (stuff->deviceSpec == XkbUseCorePtr && other->button))) { 6909f7df2e56Smrg rc = XaceHook(XACE_DEVICE_ACCESS, client, other, 6910f7df2e56Smrg DixManageAccess); 6911f7df2e56Smrg if (rc == Success) { 69124642e01fSmrg rc = _XkbSetDeviceInfoCheck(client, other, stuff); 69134642e01fSmrg if (rc != Success) 69144642e01fSmrg return rc; 69154642e01fSmrg } 69164642e01fSmrg } 69174642e01fSmrg } 69184642e01fSmrg } 69194642e01fSmrg 69204642e01fSmrg /* checks done, apply */ 69214642e01fSmrg rc = _XkbSetDeviceInfo(client, dev, stuff); 69224642e01fSmrg if (rc != Success) 69234642e01fSmrg return rc; 69244642e01fSmrg 6925f7df2e56Smrg if (stuff->deviceSpec == XkbUseCoreKbd || 6926f7df2e56Smrg stuff->deviceSpec == XkbUseCorePtr) { 69274642e01fSmrg DeviceIntPtr other; 6928f7df2e56Smrg 6929f7df2e56Smrg for (other = inputInfo.devices; other; other = other->next) { 6930f7df2e56Smrg if (((other != dev) && !IsMaster(other) && 6931f7df2e56Smrg GetMaster(other, MASTER_KEYBOARD) == dev) && 69324642e01fSmrg ((stuff->deviceSpec == XkbUseCoreKbd && other->key) || 6933f7df2e56Smrg (stuff->deviceSpec == XkbUseCorePtr && other->button))) { 6934f7df2e56Smrg rc = XaceHook(XACE_DEVICE_ACCESS, client, other, 6935f7df2e56Smrg DixManageAccess); 6936f7df2e56Smrg if (rc == Success) { 69374642e01fSmrg rc = _XkbSetDeviceInfo(client, other, stuff); 69384642e01fSmrg if (rc != Success) 69394642e01fSmrg return rc; 69404642e01fSmrg } 69414642e01fSmrg } 69424642e01fSmrg } 69434642e01fSmrg } 69444642e01fSmrg 69456747b715Smrg return Success; 694605b261ecSmrg} 694705b261ecSmrg 694805b261ecSmrg/***====================================================================***/ 694905b261ecSmrg 695005b261ecSmrgint 695105b261ecSmrgProcXkbSetDebuggingFlags(ClientPtr client) 695205b261ecSmrg{ 6953f7df2e56Smrg CARD32 newFlags, newCtrls, extraLength; 6954f7df2e56Smrg xkbSetDebuggingFlagsReply rep; 6955f7df2e56Smrg int rc; 695605b261ecSmrg 695705b261ecSmrg REQUEST(xkbSetDebuggingFlagsReq); 695805b261ecSmrg REQUEST_AT_LEAST_SIZE(xkbSetDebuggingFlagsReq); 695905b261ecSmrg 69604642e01fSmrg rc = XaceHook(XACE_SERVER_ACCESS, client, DixDebugAccess); 69614642e01fSmrg if (rc != Success) 6962f7df2e56Smrg return rc; 69634642e01fSmrg 6964f7df2e56Smrg newFlags = xkbDebugFlags & (~stuff->affectFlags); 6965f7df2e56Smrg newFlags |= (stuff->flags & stuff->affectFlags); 6966f7df2e56Smrg newCtrls = xkbDebugCtrls & (~stuff->affectCtrls); 6967f7df2e56Smrg newCtrls |= (stuff->ctrls & stuff->affectCtrls); 696805b261ecSmrg if (xkbDebugFlags || newFlags || stuff->msgLength) { 6969f7df2e56Smrg ErrorF("[xkb] XkbDebug: Setting debug flags to 0x%lx\n", 6970f7df2e56Smrg (long) newFlags); 6971f7df2e56Smrg if (newCtrls != xkbDebugCtrls) 6972f7df2e56Smrg ErrorF("[xkb] XkbDebug: Setting debug controls to 0x%lx\n", 6973f7df2e56Smrg (long) newCtrls); 6974f7df2e56Smrg } 6975f7df2e56Smrg extraLength = (stuff->length << 2) - sz_xkbSetDebuggingFlagsReq; 6976f7df2e56Smrg if (stuff->msgLength > 0) { 6977f7df2e56Smrg char *msg; 6978f7df2e56Smrg 6979f7df2e56Smrg if (extraLength < XkbPaddedSize(stuff->msgLength)) { 6980f7df2e56Smrg ErrorF 6981f7df2e56Smrg ("[xkb] XkbDebug: msgLength= %d, length= %ld (should be %d)\n", 6982f7df2e56Smrg stuff->msgLength, (long) extraLength, 6983f7df2e56Smrg XkbPaddedSize(stuff->msgLength)); 6984f7df2e56Smrg return BadLength; 6985f7df2e56Smrg } 6986f7df2e56Smrg msg = (char *) &stuff[1]; 6987f7df2e56Smrg if (msg[stuff->msgLength - 1] != '\0') { 6988f7df2e56Smrg ErrorF("[xkb] XkbDebug: message not null-terminated\n"); 6989f7df2e56Smrg return BadValue; 6990f7df2e56Smrg } 6991f7df2e56Smrg ErrorF("[xkb] XkbDebug: %s\n", msg); 699205b261ecSmrg } 699305b261ecSmrg xkbDebugFlags = newFlags; 699405b261ecSmrg xkbDebugCtrls = newCtrls; 699505b261ecSmrg 6996f7df2e56Smrg rep = (xkbSetDebuggingFlagsReply) { 6997f7df2e56Smrg .type = X_Reply, 6998f7df2e56Smrg .sequenceNumber = client->sequence, 6999f7df2e56Smrg .length = 0, 7000f7df2e56Smrg .currentFlags = newFlags, 7001f7df2e56Smrg .currentCtrls = newCtrls, 7002f7df2e56Smrg .supportedFlags = ~0, 7003f7df2e56Smrg .supportedCtrls = ~0 7004f7df2e56Smrg }; 7005f7df2e56Smrg if (client->swapped) { 7006f7df2e56Smrg swaps(&rep.sequenceNumber); 7007f7df2e56Smrg swapl(&rep.currentFlags); 7008f7df2e56Smrg swapl(&rep.currentCtrls); 7009f7df2e56Smrg swapl(&rep.supportedFlags); 7010f7df2e56Smrg swapl(&rep.supportedCtrls); 7011f7df2e56Smrg } 7012f7df2e56Smrg WriteToClient(client, SIZEOF(xkbSetDebuggingFlagsReply), &rep); 70136747b715Smrg return Success; 701405b261ecSmrg} 701505b261ecSmrg 701605b261ecSmrg/***====================================================================***/ 701705b261ecSmrg 701805b261ecSmrgstatic int 7019f7df2e56SmrgProcXkbDispatch(ClientPtr client) 702005b261ecSmrg{ 702105b261ecSmrg REQUEST(xReq); 7022f7df2e56Smrg switch (stuff->data) { 702305b261ecSmrg case X_kbUseExtension: 7024f7df2e56Smrg return ProcXkbUseExtension(client); 702505b261ecSmrg case X_kbSelectEvents: 7026f7df2e56Smrg return ProcXkbSelectEvents(client); 702705b261ecSmrg case X_kbBell: 7028f7df2e56Smrg return ProcXkbBell(client); 702905b261ecSmrg case X_kbGetState: 7030f7df2e56Smrg return ProcXkbGetState(client); 703105b261ecSmrg case X_kbLatchLockState: 7032f7df2e56Smrg return ProcXkbLatchLockState(client); 703305b261ecSmrg case X_kbGetControls: 7034f7df2e56Smrg return ProcXkbGetControls(client); 703505b261ecSmrg case X_kbSetControls: 7036f7df2e56Smrg return ProcXkbSetControls(client); 703705b261ecSmrg case X_kbGetMap: 7038f7df2e56Smrg return ProcXkbGetMap(client); 703905b261ecSmrg case X_kbSetMap: 7040f7df2e56Smrg return ProcXkbSetMap(client); 704105b261ecSmrg case X_kbGetCompatMap: 7042f7df2e56Smrg return ProcXkbGetCompatMap(client); 704305b261ecSmrg case X_kbSetCompatMap: 7044f7df2e56Smrg return ProcXkbSetCompatMap(client); 704505b261ecSmrg case X_kbGetIndicatorState: 7046f7df2e56Smrg return ProcXkbGetIndicatorState(client); 704705b261ecSmrg case X_kbGetIndicatorMap: 7048f7df2e56Smrg return ProcXkbGetIndicatorMap(client); 704905b261ecSmrg case X_kbSetIndicatorMap: 7050f7df2e56Smrg return ProcXkbSetIndicatorMap(client); 705105b261ecSmrg case X_kbGetNamedIndicator: 7052f7df2e56Smrg return ProcXkbGetNamedIndicator(client); 705305b261ecSmrg case X_kbSetNamedIndicator: 7054f7df2e56Smrg return ProcXkbSetNamedIndicator(client); 705505b261ecSmrg case X_kbGetNames: 7056f7df2e56Smrg return ProcXkbGetNames(client); 705705b261ecSmrg case X_kbSetNames: 7058f7df2e56Smrg return ProcXkbSetNames(client); 705905b261ecSmrg case X_kbGetGeometry: 7060f7df2e56Smrg return ProcXkbGetGeometry(client); 706105b261ecSmrg case X_kbSetGeometry: 7062f7df2e56Smrg return ProcXkbSetGeometry(client); 706305b261ecSmrg case X_kbPerClientFlags: 7064f7df2e56Smrg return ProcXkbPerClientFlags(client); 706505b261ecSmrg case X_kbListComponents: 7066f7df2e56Smrg return ProcXkbListComponents(client); 706705b261ecSmrg case X_kbGetKbdByName: 7068f7df2e56Smrg return ProcXkbGetKbdByName(client); 706905b261ecSmrg case X_kbGetDeviceInfo: 7070f7df2e56Smrg return ProcXkbGetDeviceInfo(client); 707105b261ecSmrg case X_kbSetDeviceInfo: 7072f7df2e56Smrg return ProcXkbSetDeviceInfo(client); 707305b261ecSmrg case X_kbSetDebuggingFlags: 7074f7df2e56Smrg return ProcXkbSetDebuggingFlags(client); 707505b261ecSmrg default: 7076f7df2e56Smrg return BadRequest; 707705b261ecSmrg } 707805b261ecSmrg} 707905b261ecSmrg 708005b261ecSmrgstatic int 7081f7df2e56SmrgXkbClientGone(void *data, XID id) 708205b261ecSmrg{ 7083f7df2e56Smrg DevicePtr pXDev = (DevicePtr) data; 708405b261ecSmrg 7085f7df2e56Smrg if (!XkbRemoveResourceClient(pXDev, id)) { 7086f7df2e56Smrg ErrorF 7087f7df2e56Smrg ("[xkb] Internal Error! bad RemoveResourceClient in XkbClientGone\n"); 708805b261ecSmrg } 708905b261ecSmrg return 1; 709005b261ecSmrg} 709105b261ecSmrg 709205b261ecSmrgvoid 709305b261ecSmrgXkbExtensionInit(void) 709405b261ecSmrg{ 709505b261ecSmrg ExtensionEntry *extEntry; 709605b261ecSmrg 70976747b715Smrg RT_XKBCLIENT = CreateNewResourceType(XkbClientGone, "XkbClient"); 70986747b715Smrg if (!RT_XKBCLIENT) 7099f7df2e56Smrg return; 71006747b715Smrg 71016747b715Smrg if (!XkbInitPrivates()) 7102f7df2e56Smrg return; 71036747b715Smrg 710405b261ecSmrg if ((extEntry = AddExtension(XkbName, XkbNumberEvents, XkbNumberErrors, 7105f7df2e56Smrg ProcXkbDispatch, SProcXkbDispatch, 7106f7df2e56Smrg NULL, StandardMinorOpcode))) { 7107f7df2e56Smrg XkbReqCode = (unsigned char) extEntry->base; 7108f7df2e56Smrg XkbEventBase = (unsigned char) extEntry->eventBase; 7109f7df2e56Smrg XkbErrorBase = (unsigned char) extEntry->errorBase; 7110f7df2e56Smrg XkbKeyboardErrorCode = XkbErrorBase + XkbKeyboard; 711105b261ecSmrg } 711205b261ecSmrg return; 711305b261ecSmrg} 7114