Imported Upstream version 1.15.1
[deb_xorg-server.git] / xkb / xkb.c
CommitLineData
a09e091a
JB
1/************************************************************
2Copyright (c) 1993 by Silicon Graphics Computer Systems, Inc.
3
4Permission to use, copy, modify, and distribute this
5software and its documentation for any purpose and without
6fee is hereby granted, provided that the above copyright
7notice appear in all copies and that both that copyright
8notice and this permission notice appear in supporting
9documentation, and that the name of Silicon Graphics not be
10used in advertising or publicity pertaining to distribution
11of the software without specific prior written permission.
12Silicon Graphics makes no representation about the suitability
13of this software for any purpose. It is provided "as is"
14without any express or implied warranty.
15
16SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
17SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
18AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
19GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
20DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
21DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
22OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH
23THE USE OR PERFORMANCE OF THIS SOFTWARE.
24
25********************************************************/
26
27#ifdef HAVE_DIX_CONFIG_H
28#include <dix-config.h>
29#endif
30
31#include <stdio.h>
32#include <X11/X.h>
33#include <X11/Xproto.h>
34#include "misc.h"
35#include "inputstr.h"
36#define XKBSRV_NEED_FILE_FUNCS
37#include <xkbsrv.h>
38#include "extnsionst.h"
39#include "extinit.h"
40#include "xace.h"
41#include "xkb.h"
42#include "protocol-versions.h"
43
44#include <X11/extensions/XI.h>
45#include <X11/extensions/XKMformat.h>
46
47int XkbEventBase;
48static int XkbErrorBase;
49int XkbReqCode;
50int XkbKeyboardErrorCode;
51CARD32 xkbDebugFlags = 0;
52static CARD32 xkbDebugCtrls = 0;
53
54static RESTYPE RT_XKBCLIENT;
55
56/***====================================================================***/
57
58#define CHK_DEVICE(dev, id, client, access_mode, lf) {\
59 int why;\
60 int tmprc = lf(&(dev), id, client, access_mode, &why);\
61 if (tmprc != Success) {\
62 client->errorValue = _XkbErrCode2(why, id);\
63 return tmprc;\
64 }\
65}
66
67#define CHK_KBD_DEVICE(dev, id, client, mode) \
68 CHK_DEVICE(dev, id, client, mode, _XkbLookupKeyboard)
69#define CHK_LED_DEVICE(dev, id, client, mode) \
70 CHK_DEVICE(dev, id, client, mode, _XkbLookupLedDevice)
71#define CHK_BELL_DEVICE(dev, id, client, mode) \
72 CHK_DEVICE(dev, id, client, mode, _XkbLookupBellDevice)
73#define CHK_ANY_DEVICE(dev, id, client, mode) \
74 CHK_DEVICE(dev, id, client, mode, _XkbLookupAnyDevice)
75
76#define CHK_ATOM_ONLY2(a,ev,er) {\
77 if (((a)==None)||(!ValidAtom((a)))) {\
78 (ev)= (XID)(a);\
79 return er;\
80 }\
81}
82#define CHK_ATOM_ONLY(a) \
83 CHK_ATOM_ONLY2(a,client->errorValue,BadAtom)
84
85#define CHK_ATOM_OR_NONE3(a,ev,er,ret) {\
86 if (((a)!=None)&&(!ValidAtom((a)))) {\
87 (ev)= (XID)(a);\
88 (er)= BadAtom;\
89 return ret;\
90 }\
91}
92#define CHK_ATOM_OR_NONE2(a,ev,er) {\
93 if (((a)!=None)&&(!ValidAtom((a)))) {\
94 (ev)= (XID)(a);\
95 return er;\
96 }\
97}
98#define CHK_ATOM_OR_NONE(a) \
99 CHK_ATOM_OR_NONE2(a,client->errorValue,BadAtom)
100
101#define CHK_MASK_LEGAL3(err,mask,legal,ev,er,ret) {\
102 if ((mask)&(~(legal))) { \
103 (ev)= _XkbErrCode2((err),((mask)&(~(legal))));\
104 (er)= BadValue;\
105 return ret;\
106 }\
107}
108#define CHK_MASK_LEGAL2(err,mask,legal,ev,er) {\
109 if ((mask)&(~(legal))) { \
110 (ev)= _XkbErrCode2((err),((mask)&(~(legal))));\
111 return er;\
112 }\
113}
114#define CHK_MASK_LEGAL(err,mask,legal) \
115 CHK_MASK_LEGAL2(err,mask,legal,client->errorValue,BadValue)
116
117#define CHK_MASK_MATCH(err,affect,value) {\
118 if ((value)&(~(affect))) { \
119 client->errorValue= _XkbErrCode2((err),((value)&(~(affect))));\
120 return BadMatch;\
121 }\
122}
123#define CHK_MASK_OVERLAP(err,m1,m2) {\
124 if ((m1)&(m2)) { \
125 client->errorValue= _XkbErrCode2((err),((m1)&(m2)));\
126 return BadMatch;\
127 }\
128}
129#define CHK_KEY_RANGE2(err,first,num,x,ev,er) {\
130 if (((unsigned)(first)+(num)-1)>(x)->max_key_code) {\
131 (ev)=_XkbErrCode4(err,(first),(num),(x)->max_key_code);\
132 return er;\
133 }\
134 else if ( (first)<(x)->min_key_code ) {\
135 (ev)=_XkbErrCode3(err+1,(first),xkb->min_key_code);\
136 return er;\
137 }\
138}
139#define CHK_KEY_RANGE(err,first,num,x) \
140 CHK_KEY_RANGE2(err,first,num,x,client->errorValue,BadValue)
141
142#define CHK_REQ_KEY_RANGE2(err,first,num,r,ev,er) {\
143 if (((unsigned)(first)+(num)-1)>(r)->maxKeyCode) {\
144 (ev)=_XkbErrCode4(err,(first),(num),(r)->maxKeyCode);\
145 return er;\
146 }\
147 else if ( (first)<(r)->minKeyCode ) {\
148 (ev)=_XkbErrCode3(err+1,(first),(r)->minKeyCode);\
149 return er;\
150 }\
151}
152#define CHK_REQ_KEY_RANGE(err,first,num,r) \
153 CHK_REQ_KEY_RANGE2(err,first,num,r,client->errorValue,BadValue)
154
155/***====================================================================***/
156
157int
158ProcXkbUseExtension(ClientPtr client)
159{
160 REQUEST(xkbUseExtensionReq);
161 xkbUseExtensionReply rep;
162 int supported;
163
164 REQUEST_SIZE_MATCH(xkbUseExtensionReq);
165 if (stuff->wantedMajor != SERVER_XKB_MAJOR_VERSION) {
166 /* pre-release version 0.65 is compatible with 1.00 */
167 supported = ((SERVER_XKB_MAJOR_VERSION == 1) &&
168 (stuff->wantedMajor == 0) && (stuff->wantedMinor == 65));
169 }
170 else
171 supported = 1;
172
173 if ((supported) && (!(client->xkbClientFlags & _XkbClientInitialized))) {
174 client->xkbClientFlags = _XkbClientInitialized;
175 client->vMajor = stuff->wantedMajor;
176 client->vMinor = stuff->wantedMinor;
177 }
178 else if (xkbDebugFlags & 0x1) {
179 ErrorF
180 ("[xkb] Rejecting client %d (0x%lx) (wants %d.%02d, have %d.%02d)\n",
181 client->index, (long) client->clientAsMask, stuff->wantedMajor,
182 stuff->wantedMinor, SERVER_XKB_MAJOR_VERSION,
183 SERVER_XKB_MINOR_VERSION);
184 }
185 rep = (xkbUseExtensionReply) {
186 .type = X_Reply,
187 .supported = supported,
188 .sequenceNumber = client->sequence,
189 .length = 0,
190 .serverMajor = SERVER_XKB_MAJOR_VERSION,
191 .serverMinor = SERVER_XKB_MINOR_VERSION
192 };
193 if (client->swapped) {
194 swaps(&rep.sequenceNumber);
195 swaps(&rep.serverMajor);
196 swaps(&rep.serverMinor);
197 }
198 WriteToClient(client, SIZEOF(xkbUseExtensionReply), &rep);
199 return Success;
200}
201
202/***====================================================================***/
203
204int
205ProcXkbSelectEvents(ClientPtr client)
206{
207 unsigned legal;
208 DeviceIntPtr dev;
209 XkbInterestPtr masks;
210
211 REQUEST(xkbSelectEventsReq);
212
213 REQUEST_AT_LEAST_SIZE(xkbSelectEventsReq);
214
215 if (!(client->xkbClientFlags & _XkbClientInitialized))
216 return BadAccess;
217
218 CHK_ANY_DEVICE(dev, stuff->deviceSpec, client, DixUseAccess);
219
220 if (((stuff->affectWhich & XkbMapNotifyMask) != 0) && (stuff->affectMap)) {
221 client->mapNotifyMask &= ~stuff->affectMap;
222 client->mapNotifyMask |= (stuff->affectMap & stuff->map);
223 }
224 if ((stuff->affectWhich & (~XkbMapNotifyMask)) == 0)
225 return Success;
226
227 masks = XkbFindClientResource((DevicePtr) dev, client);
228 if (!masks) {
229 XID id = FakeClientID(client->index);
230
231 if (!AddResource(id, RT_XKBCLIENT, dev))
232 return BadAlloc;
233 masks = XkbAddClientResource((DevicePtr) dev, client, id);
234 }
235 if (masks) {
236 union {
237 CARD8 *c8;
238 CARD16 *c16;
239 CARD32 *c32;
240 } from, to;
241 register unsigned bit, ndx, maskLeft, dataLeft, size;
242
243 from.c8 = (CARD8 *) &stuff[1];
244 dataLeft = (stuff->length * 4) - SIZEOF(xkbSelectEventsReq);
245 maskLeft = (stuff->affectWhich & (~XkbMapNotifyMask));
246 for (ndx = 0, bit = 1; (maskLeft != 0); ndx++, bit <<= 1) {
247 if ((bit & maskLeft) == 0)
248 continue;
249 maskLeft &= ~bit;
250 switch (ndx) {
251 case XkbNewKeyboardNotify:
252 to.c16 = &client->newKeyboardNotifyMask;
253 legal = XkbAllNewKeyboardEventsMask;
254 size = 2;
255 break;
256 case XkbStateNotify:
257 to.c16 = &masks->stateNotifyMask;
258 legal = XkbAllStateEventsMask;
259 size = 2;
260 break;
261 case XkbControlsNotify:
262 to.c32 = &masks->ctrlsNotifyMask;
263 legal = XkbAllControlEventsMask;
264 size = 4;
265 break;
266 case XkbIndicatorStateNotify:
267 to.c32 = &masks->iStateNotifyMask;
268 legal = XkbAllIndicatorEventsMask;
269 size = 4;
270 break;
271 case XkbIndicatorMapNotify:
272 to.c32 = &masks->iMapNotifyMask;
273 legal = XkbAllIndicatorEventsMask;
274 size = 4;
275 break;
276 case XkbNamesNotify:
277 to.c16 = &masks->namesNotifyMask;
278 legal = XkbAllNameEventsMask;
279 size = 2;
280 break;
281 case XkbCompatMapNotify:
282 to.c8 = &masks->compatNotifyMask;
283 legal = XkbAllCompatMapEventsMask;
284 size = 1;
285 break;
286 case XkbBellNotify:
287 to.c8 = &masks->bellNotifyMask;
288 legal = XkbAllBellEventsMask;
289 size = 1;
290 break;
291 case XkbActionMessage:
292 to.c8 = &masks->actionMessageMask;
293 legal = XkbAllActionMessagesMask;
294 size = 1;
295 break;
296 case XkbAccessXNotify:
297 to.c16 = &masks->accessXNotifyMask;
298 legal = XkbAllAccessXEventsMask;
299 size = 2;
300 break;
301 case XkbExtensionDeviceNotify:
302 to.c16 = &masks->extDevNotifyMask;
303 legal = XkbAllExtensionDeviceEventsMask;
304 size = 2;
305 break;
306 default:
307 client->errorValue = _XkbErrCode2(33, bit);
308 return BadValue;
309 }
310
311 if (stuff->clear & bit) {
312 if (size == 2)
313 to.c16[0] = 0;
314 else if (size == 4)
315 to.c32[0] = 0;
316 else
317 to.c8[0] = 0;
318 }
319 else if (stuff->selectAll & bit) {
320 if (size == 2)
321 to.c16[0] = ~0;
322 else if (size == 4)
323 to.c32[0] = ~0;
324 else
325 to.c8[0] = ~0;
326 }
327 else {
328 if (dataLeft < (size * 2))
329 return BadLength;
330 if (size == 2) {
331 CHK_MASK_MATCH(ndx, from.c16[0], from.c16[1]);
332 CHK_MASK_LEGAL(ndx, from.c16[0], legal);
333 to.c16[0] &= ~from.c16[0];
334 to.c16[0] |= (from.c16[0] & from.c16[1]);
335 }
336 else if (size == 4) {
337 CHK_MASK_MATCH(ndx, from.c32[0], from.c32[1]);
338 CHK_MASK_LEGAL(ndx, from.c32[0], legal);
339 to.c32[0] &= ~from.c32[0];
340 to.c32[0] |= (from.c32[0] & from.c32[1]);
341 }
342 else {
343 CHK_MASK_MATCH(ndx, from.c8[0], from.c8[1]);
344 CHK_MASK_LEGAL(ndx, from.c8[0], legal);
345 to.c8[0] &= ~from.c8[0];
346 to.c8[0] |= (from.c8[0] & from.c8[1]);
347 size = 2;
348 }
349 from.c8 += (size * 2);
350 dataLeft -= (size * 2);
351 }
352 }
353 if (dataLeft > 2) {
354 ErrorF("[xkb] Extra data (%d bytes) after SelectEvents\n",
355 dataLeft);
356 return BadLength;
357 }
358 return Success;
359 }
360 return BadAlloc;
361}
362
363/***====================================================================***/
364/**
365 * Ring a bell on the given device for the given client.
366 */
367static int
368_XkbBell(ClientPtr client, DeviceIntPtr dev, WindowPtr pWin,
369 int bellClass, int bellID, int pitch, int duration,
370 int percent, int forceSound, int eventOnly, Atom name)
371{
372 int base;
373 pointer ctrl;
374 int oldPitch, oldDuration;
375 int newPercent;
376
377 if (bellClass == KbdFeedbackClass) {
378 KbdFeedbackPtr k;
379
380 if (bellID == XkbDfltXIId)
381 k = dev->kbdfeed;
382 else {
383 for (k = dev->kbdfeed; k; k = k->next) {
384 if (k->ctrl.id == bellID)
385 break;
386 }
387 }
388 if (!k) {
389 client->errorValue = _XkbErrCode2(0x5, bellID);
390 return BadValue;
391 }
392 base = k->ctrl.bell;
393 ctrl = (pointer) &(k->ctrl);
394 oldPitch = k->ctrl.bell_pitch;
395 oldDuration = k->ctrl.bell_duration;
396 if (pitch != 0) {
397 if (pitch == -1)
398 k->ctrl.bell_pitch = defaultKeyboardControl.bell_pitch;
399 else
400 k->ctrl.bell_pitch = pitch;
401 }
402 if (duration != 0) {
403 if (duration == -1)
404 k->ctrl.bell_duration = defaultKeyboardControl.bell_duration;
405 else
406 k->ctrl.bell_duration = duration;
407 }
408 }
409 else if (bellClass == BellFeedbackClass) {
410 BellFeedbackPtr b;
411
412 if (bellID == XkbDfltXIId)
413 b = dev->bell;
414 else {
415 for (b = dev->bell; b; b = b->next) {
416 if (b->ctrl.id == bellID)
417 break;
418 }
419 }
420 if (!b) {
421 client->errorValue = _XkbErrCode2(0x6, bellID);
422 return BadValue;
423 }
424 base = b->ctrl.percent;
425 ctrl = (pointer) &(b->ctrl);
426 oldPitch = b->ctrl.pitch;
427 oldDuration = b->ctrl.duration;
428 if (pitch != 0) {
429 if (pitch == -1)
430 b->ctrl.pitch = defaultKeyboardControl.bell_pitch;
431 else
432 b->ctrl.pitch = pitch;
433 }
434 if (duration != 0) {
435 if (duration == -1)
436 b->ctrl.duration = defaultKeyboardControl.bell_duration;
437 else
438 b->ctrl.duration = duration;
439 }
440 }
441 else {
442 client->errorValue = _XkbErrCode2(0x7, bellClass);
443 return BadValue;
444 }
445
446 newPercent = (base * percent) / 100;
447 if (percent < 0)
448 newPercent = base + newPercent;
449 else
450 newPercent = base - newPercent + percent;
451
452 XkbHandleBell(forceSound, eventOnly,
453 dev, newPercent, ctrl, bellClass, name, pWin, client);
454 if ((pitch != 0) || (duration != 0)) {
455 if (bellClass == KbdFeedbackClass) {
456 KbdFeedbackPtr k;
457
458 k = (KbdFeedbackPtr) ctrl;
459 if (pitch != 0)
460 k->ctrl.bell_pitch = oldPitch;
461 if (duration != 0)
462 k->ctrl.bell_duration = oldDuration;
463 }
464 else {
465 BellFeedbackPtr b;
466
467 b = (BellFeedbackPtr) ctrl;
468 if (pitch != 0)
469 b->ctrl.pitch = oldPitch;
470 if (duration != 0)
471 b->ctrl.duration = oldDuration;
472 }
473 }
474
475 return Success;
476}
477
478int
479ProcXkbBell(ClientPtr client)
480{
481 REQUEST(xkbBellReq);
482 DeviceIntPtr dev;
483 WindowPtr pWin;
484 int rc;
485
486 REQUEST_SIZE_MATCH(xkbBellReq);
487
488 if (!(client->xkbClientFlags & _XkbClientInitialized))
489 return BadAccess;
490
491 CHK_BELL_DEVICE(dev, stuff->deviceSpec, client, DixBellAccess);
492 CHK_ATOM_OR_NONE(stuff->name);
493
494 /* device-independent checks request for sane values */
495 if ((stuff->forceSound) && (stuff->eventOnly)) {
496 client->errorValue =
497 _XkbErrCode3(0x1, stuff->forceSound, stuff->eventOnly);
498 return BadMatch;
499 }
500 if (stuff->percent < -100 || stuff->percent > 100) {
501 client->errorValue = _XkbErrCode2(0x2, stuff->percent);
502 return BadValue;
503 }
504 if (stuff->duration < -1) {
505 client->errorValue = _XkbErrCode2(0x3, stuff->duration);
506 return BadValue;
507 }
508 if (stuff->pitch < -1) {
509 client->errorValue = _XkbErrCode2(0x4, stuff->pitch);
510 return BadValue;
511 }
512
513 if (stuff->bellClass == XkbDfltXIClass) {
514 if (dev->kbdfeed != NULL)
515 stuff->bellClass = KbdFeedbackClass;
516 else
517 stuff->bellClass = BellFeedbackClass;
518 }
519
520 if (stuff->window != None) {
521 rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
522 if (rc != Success) {
523 client->errorValue = stuff->window;
524 return rc;
525 }
526 }
527 else
528 pWin = NULL;
529
530 /* Client wants to ring a bell on the core keyboard?
531 Ring the bell on the core keyboard (which does nothing, but if that
532 fails the client is screwed anyway), and then on all extension devices.
533 Fail if the core keyboard fails but not the extension devices. this
534 may cause some keyboards to ding and others to stay silent. Fix
535 your client to use explicit keyboards to avoid this.
536
537 dev is the device the client requested.
538 */
539 rc = _XkbBell(client, dev, pWin, stuff->bellClass, stuff->bellID,
540 stuff->pitch, stuff->duration, stuff->percent,
541 stuff->forceSound, stuff->eventOnly, stuff->name);
542
543 if ((rc == Success) && ((stuff->deviceSpec == XkbUseCoreKbd) ||
544 (stuff->deviceSpec == XkbUseCorePtr))) {
545 DeviceIntPtr other;
546
547 for (other = inputInfo.devices; other; other = other->next) {
548 if ((other != dev) && other->key && !IsMaster(other) &&
549 GetMaster(other, MASTER_KEYBOARD) == dev) {
550 rc = XaceHook(XACE_DEVICE_ACCESS, client, other, DixBellAccess);
551 if (rc == Success)
552 _XkbBell(client, other, pWin, stuff->bellClass,
553 stuff->bellID, stuff->pitch, stuff->duration,
554 stuff->percent, stuff->forceSound,
555 stuff->eventOnly, stuff->name);
556 }
557 }
558 rc = Success; /* reset to success, that's what we got for the VCK */
559 }
560
561 return rc;
562}
563
564/***====================================================================***/
565
566int
567ProcXkbGetState(ClientPtr client)
568{
569 REQUEST(xkbGetStateReq);
570 DeviceIntPtr dev;
571 xkbGetStateReply rep;
572 XkbStateRec *xkb;
573
574 REQUEST_SIZE_MATCH(xkbGetStateReq);
575
576 if (!(client->xkbClientFlags & _XkbClientInitialized))
577 return BadAccess;
578
579 CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess);
580
581 xkb = &dev->key->xkbInfo->state;
582 rep = (xkbGetStateReply) {
583 .type = X_Reply,
584 .deviceID = dev->id,
585 .sequenceNumber = client->sequence,
586 .length = 0,
587 .mods = XkbStateFieldFromRec(xkb) & 0xff,
588 .baseMods = xkb->base_mods,
589 .latchedMods = xkb->latched_mods,
590 .lockedMods = xkb->locked_mods,
591 .group = xkb->group,
592 .lockedGroup = xkb->locked_group,
593 .baseGroup = xkb->base_group,
594 .latchedGroup = xkb->latched_group,
595 .compatState = xkb->compat_state,
596 .ptrBtnState = xkb->ptr_buttons
597 };
598 if (client->swapped) {
599 swaps(&rep.sequenceNumber);
600 swaps(&rep.ptrBtnState);
601 }
602 WriteToClient(client, SIZEOF(xkbGetStateReply), &rep);
603 return Success;
604}
605
606/***====================================================================***/
607
608int
609ProcXkbLatchLockState(ClientPtr client)
610{
611 int status;
612 DeviceIntPtr dev, tmpd;
613 XkbStateRec oldState, *newState;
614 CARD16 changed;
615 xkbStateNotify sn;
616 XkbEventCauseRec cause;
617
618 REQUEST(xkbLatchLockStateReq);
619 REQUEST_SIZE_MATCH(xkbLatchLockStateReq);
620
621 if (!(client->xkbClientFlags & _XkbClientInitialized))
622 return BadAccess;
623
624 CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixSetAttrAccess);
625 CHK_MASK_MATCH(0x01, stuff->affectModLocks, stuff->modLocks);
626 CHK_MASK_MATCH(0x01, stuff->affectModLatches, stuff->modLatches);
627
628 status = Success;
629
630 for (tmpd = inputInfo.devices; tmpd; tmpd = tmpd->next) {
631 if ((tmpd == dev) ||
632 (!IsMaster(tmpd) && GetMaster(tmpd, MASTER_KEYBOARD) == dev)) {
633 if (!tmpd->key || !tmpd->key->xkbInfo)
634 continue;
635
636 oldState = tmpd->key->xkbInfo->state;
637 newState = &tmpd->key->xkbInfo->state;
638 if (stuff->affectModLocks) {
639 newState->locked_mods &= ~stuff->affectModLocks;
640 newState->locked_mods |=
641 (stuff->affectModLocks & stuff->modLocks);
642 }
643 if (status == Success && stuff->lockGroup)
644 newState->locked_group = stuff->groupLock;
645 if (status == Success && stuff->affectModLatches)
646 status = XkbLatchModifiers(tmpd, stuff->affectModLatches,
647 stuff->modLatches);
648 if (status == Success && stuff->latchGroup)
649 status = XkbLatchGroup(tmpd, stuff->groupLatch);
650
651 if (status != Success)
652 return status;
653
654 XkbComputeDerivedState(tmpd->key->xkbInfo);
655
656 changed = XkbStateChangedFlags(&oldState, newState);
657 if (changed) {
658 sn.keycode = 0;
659 sn.eventType = 0;
660 sn.requestMajor = XkbReqCode;
661 sn.requestMinor = X_kbLatchLockState;
662 sn.changed = changed;
663 XkbSendStateNotify(tmpd, &sn);
664 changed = XkbIndicatorsToUpdate(tmpd, changed, FALSE);
665 if (changed) {
666 XkbSetCauseXkbReq(&cause, X_kbLatchLockState, client);
667 XkbUpdateIndicators(tmpd, changed, TRUE, NULL, &cause);
668 }
669 }
670 }
671 }
672
673 return Success;
674}
675
676/***====================================================================***/
677
678int
679ProcXkbGetControls(ClientPtr client)
680{
681 xkbGetControlsReply rep;
682 XkbControlsPtr xkb;
683 DeviceIntPtr dev;
684
685 REQUEST(xkbGetControlsReq);
686 REQUEST_SIZE_MATCH(xkbGetControlsReq);
687
688 if (!(client->xkbClientFlags & _XkbClientInitialized))
689 return BadAccess;
690
691 CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess);
692
693 xkb = dev->key->xkbInfo->desc->ctrls;
694 rep = (xkbGetControlsReply) {
695 .type = X_Reply,
696 .deviceID = ((DeviceIntPtr) dev)->id,
697 .sequenceNumber = client->sequence,
698 .length = bytes_to_int32(SIZEOF(xkbGetControlsReply) -
699 SIZEOF(xGenericReply)),
700 .mkDfltBtn = xkb->mk_dflt_btn,
701 .numGroups = xkb->num_groups,
702 .groupsWrap = xkb->groups_wrap,
703 .internalMods = xkb->internal.mask,
704 .ignoreLockMods = xkb->ignore_lock.mask,
705 .internalRealMods = xkb->internal.real_mods,
706 .ignoreLockRealMods = xkb->ignore_lock.real_mods,
707 .internalVMods = xkb->internal.vmods,
708 .ignoreLockVMods = xkb->ignore_lock.vmods,
709 .repeatDelay = xkb->repeat_delay,
710 .repeatInterval = xkb->repeat_interval,
711 .slowKeysDelay = xkb->slow_keys_delay,
712 .debounceDelay = xkb->debounce_delay,
713 .mkDelay = xkb->mk_delay,
714 .mkInterval = xkb->mk_interval,
715 .mkTimeToMax = xkb->mk_time_to_max,
716 .mkMaxSpeed = xkb->mk_max_speed,
717 .mkCurve = xkb->mk_curve,
718 .axOptions = xkb->ax_options,
719 .axTimeout = xkb->ax_timeout,
720 .axtOptsMask = xkb->axt_opts_mask,
721 .axtOptsValues = xkb->axt_opts_values,
722 .axtCtrlsMask = xkb->axt_ctrls_mask,
723 .axtCtrlsValues = xkb->axt_ctrls_values,
724 .enabledCtrls = xkb->enabled_ctrls,
725 };
726 memcpy(rep.perKeyRepeat, xkb->per_key_repeat, XkbPerKeyBitArraySize);
727 if (client->swapped) {
728 swaps(&rep.sequenceNumber);
729 swapl(&rep.length);
730 swaps(&rep.internalVMods);
731 swaps(&rep.ignoreLockVMods);
732 swapl(&rep.enabledCtrls);
733 swaps(&rep.repeatDelay);
734 swaps(&rep.repeatInterval);
735 swaps(&rep.slowKeysDelay);
736 swaps(&rep.debounceDelay);
737 swaps(&rep.mkDelay);
738 swaps(&rep.mkInterval);
739 swaps(&rep.mkTimeToMax);
740 swaps(&rep.mkMaxSpeed);
741 swaps(&rep.mkCurve);
742 swaps(&rep.axTimeout);
743 swapl(&rep.axtCtrlsMask);
744 swapl(&rep.axtCtrlsValues);
745 swaps(&rep.axtOptsMask);
746 swaps(&rep.axtOptsValues);
747 swaps(&rep.axOptions);
748 }
749 WriteToClient(client, SIZEOF(xkbGetControlsReply), &rep);
750 return Success;
751}
752
753int
754ProcXkbSetControls(ClientPtr client)
755{
756 DeviceIntPtr dev, tmpd;
757 XkbSrvInfoPtr xkbi;
758 XkbControlsPtr ctrl;
759 XkbControlsRec new, old;
760 xkbControlsNotify cn;
761 XkbEventCauseRec cause;
762 XkbSrvLedInfoPtr sli;
763
764 REQUEST(xkbSetControlsReq);
765 REQUEST_SIZE_MATCH(xkbSetControlsReq);
766
767 if (!(client->xkbClientFlags & _XkbClientInitialized))
768 return BadAccess;
769
770 CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess);
771 CHK_MASK_LEGAL(0x01, stuff->changeCtrls, XkbAllControlsMask);
772
773 for (tmpd = inputInfo.devices; tmpd; tmpd = tmpd->next) {
774 if (!tmpd->key || !tmpd->key->xkbInfo)
775 continue;
776 if ((tmpd == dev) ||
777 (!IsMaster(tmpd) && GetMaster(tmpd, MASTER_KEYBOARD) == dev)) {
778 xkbi = tmpd->key->xkbInfo;
779 ctrl = xkbi->desc->ctrls;
780 new = *ctrl;
781 XkbSetCauseXkbReq(&cause, X_kbSetControls, client);
782
783 if (stuff->changeCtrls & XkbInternalModsMask) {
784 CHK_MASK_MATCH(0x02, stuff->affectInternalMods,
785 stuff->internalMods);
786 CHK_MASK_MATCH(0x03, stuff->affectInternalVMods,
787 stuff->internalVMods);
788
789 new.internal.real_mods &= ~(stuff->affectInternalMods);
790 new.internal.real_mods |= (stuff->affectInternalMods &
791 stuff->internalMods);
792 new.internal.vmods &= ~(stuff->affectInternalVMods);
793 new.internal.vmods |= (stuff->affectInternalVMods &
794 stuff->internalVMods);
795 new.internal.mask = new.internal.real_mods |
796 XkbMaskForVMask(xkbi->desc, new.internal.vmods);
797 }
798
799 if (stuff->changeCtrls & XkbIgnoreLockModsMask) {
800 CHK_MASK_MATCH(0x4, stuff->affectIgnoreLockMods,
801 stuff->ignoreLockMods);
802 CHK_MASK_MATCH(0x5, stuff->affectIgnoreLockVMods,
803 stuff->ignoreLockVMods);
804
805 new.ignore_lock.real_mods &= ~(stuff->affectIgnoreLockMods);
806 new.ignore_lock.real_mods |= (stuff->affectIgnoreLockMods &
807 stuff->ignoreLockMods);
808 new.ignore_lock.vmods &= ~(stuff->affectIgnoreLockVMods);
809 new.ignore_lock.vmods |= (stuff->affectIgnoreLockVMods &
810 stuff->ignoreLockVMods);
811 new.ignore_lock.mask = new.ignore_lock.real_mods |
812 XkbMaskForVMask(xkbi->desc, new.ignore_lock.vmods);
813 }
814
815 CHK_MASK_MATCH(0x06, stuff->affectEnabledCtrls,
816 stuff->enabledCtrls);
817 if (stuff->affectEnabledCtrls) {
818 CHK_MASK_LEGAL(0x07, stuff->affectEnabledCtrls,
819 XkbAllBooleanCtrlsMask);
820
821 new.enabled_ctrls &= ~(stuff->affectEnabledCtrls);
822 new.enabled_ctrls |= (stuff->affectEnabledCtrls &
823 stuff->enabledCtrls);
824 }
825
826 if (stuff->changeCtrls & XkbRepeatKeysMask) {
827 if (stuff->repeatDelay < 1 || stuff->repeatInterval < 1) {
828 client->errorValue = _XkbErrCode3(0x08, stuff->repeatDelay,
829 stuff->repeatInterval);
830 return BadValue;
831 }
832
833 new.repeat_delay = stuff->repeatDelay;
834 new.repeat_interval = stuff->repeatInterval;
835 }
836
837 if (stuff->changeCtrls & XkbSlowKeysMask) {
838 if (stuff->slowKeysDelay < 1) {
839 client->errorValue = _XkbErrCode2(0x09,
840 stuff->slowKeysDelay);
841 return BadValue;
842 }
843
844 new.slow_keys_delay = stuff->slowKeysDelay;
845 }
846
847 if (stuff->changeCtrls & XkbBounceKeysMask) {
848 if (stuff->debounceDelay < 1) {
849 client->errorValue = _XkbErrCode2(0x0A,
850 stuff->debounceDelay);
851 return BadValue;
852 }
853
854 new.debounce_delay = stuff->debounceDelay;
855 }
856
857 if (stuff->changeCtrls & XkbMouseKeysMask) {
858 if (stuff->mkDfltBtn > XkbMaxMouseKeysBtn) {
859 client->errorValue = _XkbErrCode2(0x0B, stuff->mkDfltBtn);
860 return BadValue;
861 }
862
863 new.mk_dflt_btn = stuff->mkDfltBtn;
864 }
865
866 if (stuff->changeCtrls & XkbMouseKeysAccelMask) {
867 if (stuff->mkDelay < 1 || stuff->mkInterval < 1 ||
868 stuff->mkTimeToMax < 1 || stuff->mkMaxSpeed < 1 ||
869 stuff->mkCurve < -1000) {
870 client->errorValue = _XkbErrCode2(0x0C, 0);
871 return BadValue;
872 }
873
874 new.mk_delay = stuff->mkDelay;
875 new.mk_interval = stuff->mkInterval;
876 new.mk_time_to_max = stuff->mkTimeToMax;
877 new.mk_max_speed = stuff->mkMaxSpeed;
878 new.mk_curve = stuff->mkCurve;
879 AccessXComputeCurveFactor(xkbi, &new);
880 }
881
882 if (stuff->changeCtrls & XkbGroupsWrapMask) {
883 unsigned act, num;
884
885 act = XkbOutOfRangeGroupAction(stuff->groupsWrap);
886 switch (act) {
887 case XkbRedirectIntoRange:
888 num = XkbOutOfRangeGroupNumber(stuff->groupsWrap);
889 if (num >= new.num_groups) {
890 client->errorValue = _XkbErrCode3(0x0D, new.num_groups,
891 num);
892 return BadValue;
893 }
894 case XkbWrapIntoRange:
895 case XkbClampIntoRange:
896 break;
897 default:
898 client->errorValue = _XkbErrCode2(0x0E, act);
899 return BadValue;
900 }
901
902 new.groups_wrap = stuff->groupsWrap;
903 }
904
905 CHK_MASK_LEGAL(0x0F, stuff->axOptions, XkbAX_AllOptionsMask);
906 if (stuff->changeCtrls & XkbAccessXKeysMask) {
907 new.ax_options = stuff->axOptions & XkbAX_AllOptionsMask;
908 }
909 else {
910 if (stuff->changeCtrls & XkbStickyKeysMask) {
911 new.ax_options &= ~(XkbAX_SKOptionsMask);
912 new.ax_options |= (stuff->axOptions & XkbAX_SKOptionsMask);
913 }
914
915 if (stuff->changeCtrls & XkbAccessXFeedbackMask) {
916 new.ax_options &= ~(XkbAX_FBOptionsMask);
917 new.ax_options |= (stuff->axOptions & XkbAX_FBOptionsMask);
918 }
919 }
920
921 if (stuff->changeCtrls & XkbAccessXTimeoutMask) {
922 if (stuff->axTimeout < 1) {
923 client->errorValue = _XkbErrCode2(0x10, stuff->axTimeout);
924 return BadValue;
925 }
926 CHK_MASK_MATCH(0x11, stuff->axtCtrlsMask,
927 stuff->axtCtrlsValues);
928 CHK_MASK_LEGAL(0x12, stuff->axtCtrlsMask,
929 XkbAllBooleanCtrlsMask);
930 CHK_MASK_MATCH(0x13, stuff->axtOptsMask, stuff->axtOptsValues);
931 CHK_MASK_LEGAL(0x14, stuff->axtOptsMask, XkbAX_AllOptionsMask);
932 new.ax_timeout = stuff->axTimeout;
933 new.axt_ctrls_mask = stuff->axtCtrlsMask;
934 new.axt_ctrls_values = (stuff->axtCtrlsValues &
935 stuff->axtCtrlsMask);
936 new.axt_opts_mask = stuff->axtOptsMask;
937 new.axt_opts_values = (stuff->axtOptsValues &
938 stuff->axtOptsMask);
939 }
940
941 if (stuff->changeCtrls & XkbPerKeyRepeatMask) {
942 memcpy(new.per_key_repeat, stuff->perKeyRepeat,
943 XkbPerKeyBitArraySize);
944 if (xkbi->repeatKey &&
945 !BitIsOn(new.per_key_repeat, xkbi->repeatKey)) {
946 AccessXCancelRepeatKey(xkbi, xkbi->repeatKey);
947 }
948 }
949
950 old = *ctrl;
951 *ctrl = new;
952 XkbDDXChangeControls(tmpd, &old, ctrl);
953
954 if (XkbComputeControlsNotify(tmpd, &old, ctrl, &cn, FALSE)) {
955 cn.keycode = 0;
956 cn.eventType = 0;
957 cn.requestMajor = XkbReqCode;
958 cn.requestMinor = X_kbSetControls;
959 XkbSendControlsNotify(tmpd, &cn);
960 }
961
962 sli = XkbFindSrvLedInfo(tmpd, XkbDfltXIClass, XkbDfltXIId, 0);
963 if (sli)
964 XkbUpdateIndicators(tmpd, sli->usesControls, TRUE, NULL,
965 &cause);
966
967 /* If sticky keys were disabled, clear all locks and latches */
968 if ((old.enabled_ctrls & XkbStickyKeysMask) &&
969 !(ctrl->enabled_ctrls & XkbStickyKeysMask))
970 XkbClearAllLatchesAndLocks(tmpd, xkbi, TRUE, &cause);
971 }
972 }
973
974 return Success;
975}
976
977/***====================================================================***/
978
979static int
980XkbSizeKeyTypes(XkbDescPtr xkb, xkbGetMapReply * rep)
981{
982 XkbKeyTypeRec *type;
983 unsigned i, len;
984
985 len = 0;
986 if (((rep->present & XkbKeyTypesMask) == 0) || (rep->nTypes < 1) ||
987 (!xkb) || (!xkb->map) || (!xkb->map->types)) {
988 rep->present &= ~XkbKeyTypesMask;
989 rep->firstType = rep->nTypes = 0;
990 return 0;
991 }
992 type = &xkb->map->types[rep->firstType];
993 for (i = 0; i < rep->nTypes; i++, type++) {
994 len += SIZEOF(xkbKeyTypeWireDesc);
995 if (type->map_count > 0) {
996 len += (type->map_count * SIZEOF(xkbKTMapEntryWireDesc));
997 if (type->preserve)
998 len += (type->map_count * SIZEOF(xkbModsWireDesc));
999 }
1000 }
1001 return len;
1002}
1003
1004static char *
1005XkbWriteKeyTypes(XkbDescPtr xkb,
1006 xkbGetMapReply * rep, char *buf, ClientPtr client)
1007{
1008 XkbKeyTypePtr type;
1009 unsigned i;
1010 xkbKeyTypeWireDesc *wire;
1011
1012 type = &xkb->map->types[rep->firstType];
1013 for (i = 0; i < rep->nTypes; i++, type++) {
1014 register unsigned n;
1015
1016 wire = (xkbKeyTypeWireDesc *) buf;
1017 wire->mask = type->mods.mask;
1018 wire->realMods = type->mods.real_mods;
1019 wire->virtualMods = type->mods.vmods;
1020 wire->numLevels = type->num_levels;
1021 wire->nMapEntries = type->map_count;
1022 wire->preserve = (type->preserve != NULL);
1023 if (client->swapped) {
1024 swaps(&wire->virtualMods);
1025 }
1026
1027 buf = (char *) &wire[1];
1028 if (wire->nMapEntries > 0) {
1029 xkbKTMapEntryWireDesc *ewire;
1030 XkbKTMapEntryPtr entry;
1031
1032 ewire = (xkbKTMapEntryWireDesc *) buf;
1033 entry = type->map;
1034 for (n = 0; n < type->map_count; n++, ewire++, entry++) {
1035 ewire->active = entry->active;
1036 ewire->mask = entry->mods.mask;
1037 ewire->level = entry->level;
1038 ewire->realMods = entry->mods.real_mods;
1039 ewire->virtualMods = entry->mods.vmods;
1040 if (client->swapped) {
1041 swaps(&ewire->virtualMods);
1042 }
1043 }
1044 buf = (char *) ewire;
1045 if (type->preserve != NULL) {
1046 xkbModsWireDesc *pwire;
1047 XkbModsPtr preserve;
1048
1049 pwire = (xkbModsWireDesc *) buf;
1050 preserve = type->preserve;
1051 for (n = 0; n < type->map_count; n++, pwire++, preserve++) {
1052 pwire->mask = preserve->mask;
1053 pwire->realMods = preserve->real_mods;
1054 pwire->virtualMods = preserve->vmods;
1055 if (client->swapped) {
1056 swaps(&pwire->virtualMods);
1057 }
1058 }
1059 buf = (char *) pwire;
1060 }
1061 }
1062 }
1063 return buf;
1064}
1065
1066static int
1067XkbSizeKeySyms(XkbDescPtr xkb, xkbGetMapReply * rep)
1068{
1069 XkbSymMapPtr symMap;
1070 unsigned i, len;
1071 unsigned nSyms, nSymsThisKey;
1072
1073 if (((rep->present & XkbKeySymsMask) == 0) || (rep->nKeySyms < 1) ||
1074 (!xkb) || (!xkb->map) || (!xkb->map->key_sym_map)) {
1075 rep->present &= ~XkbKeySymsMask;
1076 rep->firstKeySym = rep->nKeySyms = 0;
1077 rep->totalSyms = 0;
1078 return 0;
1079 }
1080 len = rep->nKeySyms * SIZEOF(xkbSymMapWireDesc);
1081 symMap = &xkb->map->key_sym_map[rep->firstKeySym];
1082 for (i = nSyms = 0; i < rep->nKeySyms; i++, symMap++) {
1083 if (symMap->offset != 0) {
1084 nSymsThisKey = XkbNumGroups(symMap->group_info) * symMap->width;
1085 nSyms += nSymsThisKey;
1086 }
1087 }
1088 len += nSyms * 4;
1089 rep->totalSyms = nSyms;
1090 return len;
1091}
1092
1093static int
1094XkbSizeVirtualMods(XkbDescPtr xkb, xkbGetMapReply * rep)
1095{
1096 register unsigned i, nMods, bit;
1097
1098 if (((rep->present & XkbVirtualModsMask) == 0) || (rep->virtualMods == 0) ||
1099 (!xkb) || (!xkb->server)) {
1100 rep->present &= ~XkbVirtualModsMask;
1101 rep->virtualMods = 0;
1102 return 0;
1103 }
1104 for (i = nMods = 0, bit = 1; i < XkbNumVirtualMods; i++, bit <<= 1) {
1105 if (rep->virtualMods & bit)
1106 nMods++;
1107 }
1108 return XkbPaddedSize(nMods);
1109}
1110
1111static char *
1112XkbWriteKeySyms(XkbDescPtr xkb, xkbGetMapReply * rep, char *buf,
1113 ClientPtr client)
1114{
1115 register KeySym *pSym;
1116 XkbSymMapPtr symMap;
1117 xkbSymMapWireDesc *outMap;
1118 register unsigned i;
1119
1120 symMap = &xkb->map->key_sym_map[rep->firstKeySym];
1121 for (i = 0; i < rep->nKeySyms; i++, symMap++) {
1122 outMap = (xkbSymMapWireDesc *) buf;
1123 outMap->ktIndex[0] = symMap->kt_index[0];
1124 outMap->ktIndex[1] = symMap->kt_index[1];
1125 outMap->ktIndex[2] = symMap->kt_index[2];
1126 outMap->ktIndex[3] = symMap->kt_index[3];
1127 outMap->groupInfo = symMap->group_info;
1128 outMap->width = symMap->width;
1129 outMap->nSyms = symMap->width * XkbNumGroups(symMap->group_info);
1130 buf = (char *) &outMap[1];
1131 if (outMap->nSyms == 0)
1132 continue;
1133
1134 pSym = &xkb->map->syms[symMap->offset];
1135 memcpy((char *) buf, (char *) pSym, outMap->nSyms * 4);
1136 if (client->swapped) {
1137 register int nSyms = outMap->nSyms;
1138
1139 swaps(&outMap->nSyms);
1140 while (nSyms-- > 0) {
1141 swapl((int *) buf);
1142 buf += 4;
1143 }
1144 }
1145 else
1146 buf += outMap->nSyms * 4;
1147 }
1148 return buf;
1149}
1150
1151static int
1152XkbSizeKeyActions(XkbDescPtr xkb, xkbGetMapReply * rep)
1153{
1154 unsigned i, len, nActs;
1155 register KeyCode firstKey;
1156
1157 if (((rep->present & XkbKeyActionsMask) == 0) || (rep->nKeyActs < 1) ||
1158 (!xkb) || (!xkb->server) || (!xkb->server->key_acts)) {
1159 rep->present &= ~XkbKeyActionsMask;
1160 rep->firstKeyAct = rep->nKeyActs = 0;
1161 rep->totalActs = 0;
1162 return 0;
1163 }
1164 firstKey = rep->firstKeyAct;
1165 for (nActs = i = 0; i < rep->nKeyActs; i++) {
1166 if (xkb->server->key_acts[i + firstKey] != 0)
1167 nActs += XkbKeyNumActions(xkb, i + firstKey);
1168 }
1169 len = XkbPaddedSize(rep->nKeyActs) + (nActs * SIZEOF(xkbActionWireDesc));
1170 rep->totalActs = nActs;
1171 return len;
1172}
1173
1174static char *
1175XkbWriteKeyActions(XkbDescPtr xkb, xkbGetMapReply * rep, char *buf,
1176 ClientPtr client)
1177{
1178 unsigned i;
1179 CARD8 *numDesc;
1180 XkbAnyAction *actDesc;
1181
1182 numDesc = (CARD8 *) buf;
1183 for (i = 0; i < rep->nKeyActs; i++) {
1184 if (xkb->server->key_acts[i + rep->firstKeyAct] == 0)
1185 numDesc[i] = 0;
1186 else
1187 numDesc[i] = XkbKeyNumActions(xkb, (i + rep->firstKeyAct));
1188 }
1189 buf += XkbPaddedSize(rep->nKeyActs);
1190
1191 actDesc = (XkbAnyAction *) buf;
1192 for (i = 0; i < rep->nKeyActs; i++) {
1193 if (xkb->server->key_acts[i + rep->firstKeyAct] != 0) {
1194 unsigned int num;
1195
1196 num = XkbKeyNumActions(xkb, (i + rep->firstKeyAct));
1197 memcpy((char *) actDesc,
1198 (char *) XkbKeyActionsPtr(xkb, (i + rep->firstKeyAct)),
1199 num * SIZEOF(xkbActionWireDesc));
1200 actDesc += num;
1201 }
1202 }
1203 buf = (char *) actDesc;
1204 return buf;
1205}
1206
1207static int
1208XkbSizeKeyBehaviors(XkbDescPtr xkb, xkbGetMapReply * rep)
1209{
1210 unsigned i, len, nBhvr;
1211 XkbBehavior *bhv;
1212
1213 if (((rep->present & XkbKeyBehaviorsMask) == 0) || (rep->nKeyBehaviors < 1)
1214 || (!xkb) || (!xkb->server) || (!xkb->server->behaviors)) {
1215 rep->present &= ~XkbKeyBehaviorsMask;
1216 rep->firstKeyBehavior = rep->nKeyBehaviors = 0;
1217 rep->totalKeyBehaviors = 0;
1218 return 0;
1219 }
1220 bhv = &xkb->server->behaviors[rep->firstKeyBehavior];
1221 for (nBhvr = i = 0; i < rep->nKeyBehaviors; i++, bhv++) {
1222 if (bhv->type != XkbKB_Default)
1223 nBhvr++;
1224 }
1225 len = nBhvr * SIZEOF(xkbBehaviorWireDesc);
1226 rep->totalKeyBehaviors = nBhvr;
1227 return len;
1228}
1229
1230static char *
1231XkbWriteKeyBehaviors(XkbDescPtr xkb, xkbGetMapReply * rep, char *buf,
1232 ClientPtr client)
1233{
1234 unsigned i;
1235 xkbBehaviorWireDesc *wire;
1236 XkbBehavior *pBhvr;
1237
1238 wire = (xkbBehaviorWireDesc *) buf;
1239 pBhvr = &xkb->server->behaviors[rep->firstKeyBehavior];
1240 for (i = 0; i < rep->nKeyBehaviors; i++, pBhvr++) {
1241 if (pBhvr->type != XkbKB_Default) {
1242 wire->key = i + rep->firstKeyBehavior;
1243 wire->type = pBhvr->type;
1244 wire->data = pBhvr->data;
1245 wire++;
1246 }
1247 }
1248 buf = (char *) wire;
1249 return buf;
1250}
1251
1252static int
1253XkbSizeExplicit(XkbDescPtr xkb, xkbGetMapReply * rep)
1254{
1255 unsigned i, len, nRtrn;
1256
1257 if (((rep->present & XkbExplicitComponentsMask) == 0) ||
1258 (rep->nKeyExplicit < 1) || (!xkb) || (!xkb->server) ||
1259 (!xkb->server->explicit)) {
1260 rep->present &= ~XkbExplicitComponentsMask;
1261 rep->firstKeyExplicit = rep->nKeyExplicit = 0;
1262 rep->totalKeyExplicit = 0;
1263 return 0;
1264 }
1265 for (nRtrn = i = 0; i < rep->nKeyExplicit; i++) {
1266 if (xkb->server->explicit[i + rep->firstKeyExplicit] != 0)
1267 nRtrn++;
1268 }
1269 rep->totalKeyExplicit = nRtrn;
1270 len = XkbPaddedSize(nRtrn * 2); /* two bytes per non-zero explicit component */
1271 return len;
1272}
1273
1274static char *
1275XkbWriteExplicit(XkbDescPtr xkb, xkbGetMapReply * rep, char *buf,
1276 ClientPtr client)
1277{
1278 unsigned i;
1279 char *start;
1280 unsigned char *pExp;
1281
1282 start = buf;
1283 pExp = &xkb->server->explicit[rep->firstKeyExplicit];
1284 for (i = 0; i < rep->nKeyExplicit; i++, pExp++) {
1285 if (*pExp != 0) {
1286 *buf++ = i + rep->firstKeyExplicit;
1287 *buf++ = *pExp;
1288 }
1289 }
1290 i = XkbPaddedSize(buf - start) - (buf - start); /* pad to word boundary */
1291 return buf + i;
1292}
1293
1294static int
1295XkbSizeModifierMap(XkbDescPtr xkb, xkbGetMapReply * rep)
1296{
1297 unsigned i, len, nRtrn;
1298
1299 if (((rep->present & XkbModifierMapMask) == 0) || (rep->nModMapKeys < 1) ||
1300 (!xkb) || (!xkb->map) || (!xkb->map->modmap)) {
1301 rep->present &= ~XkbModifierMapMask;
1302 rep->firstModMapKey = rep->nModMapKeys = 0;
1303 rep->totalModMapKeys = 0;
1304 return 0;
1305 }
1306 for (nRtrn = i = 0; i < rep->nModMapKeys; i++) {
1307 if (xkb->map->modmap[i + rep->firstModMapKey] != 0)
1308 nRtrn++;
1309 }
1310 rep->totalModMapKeys = nRtrn;
1311 len = XkbPaddedSize(nRtrn * 2); /* two bytes per non-zero modmap component */
1312 return len;
1313}
1314
1315static char *
1316XkbWriteModifierMap(XkbDescPtr xkb, xkbGetMapReply * rep, char *buf,
1317 ClientPtr client)
1318{
1319 unsigned i;
1320 char *start;
1321 unsigned char *pMap;
1322
1323 start = buf;
1324 pMap = &xkb->map->modmap[rep->firstModMapKey];
1325 for (i = 0; i < rep->nModMapKeys; i++, pMap++) {
1326 if (*pMap != 0) {
1327 *buf++ = i + rep->firstModMapKey;
1328 *buf++ = *pMap;
1329 }
1330 }
1331 i = XkbPaddedSize(buf - start) - (buf - start); /* pad to word boundary */
1332 return buf + i;
1333}
1334
1335static int
1336XkbSizeVirtualModMap(XkbDescPtr xkb, xkbGetMapReply * rep)
1337{
1338 unsigned i, len, nRtrn;
1339
1340 if (((rep->present & XkbVirtualModMapMask) == 0) || (rep->nVModMapKeys < 1)
1341 || (!xkb) || (!xkb->server) || (!xkb->server->vmodmap)) {
1342 rep->present &= ~XkbVirtualModMapMask;
1343 rep->firstVModMapKey = rep->nVModMapKeys = 0;
1344 rep->totalVModMapKeys = 0;
1345 return 0;
1346 }
1347 for (nRtrn = i = 0; i < rep->nVModMapKeys; i++) {
1348 if (xkb->server->vmodmap[i + rep->firstVModMapKey] != 0)
1349 nRtrn++;
1350 }
1351 rep->totalVModMapKeys = nRtrn;
1352 len = nRtrn * SIZEOF(xkbVModMapWireDesc);
1353 return len;
1354}
1355
1356static char *
1357XkbWriteVirtualModMap(XkbDescPtr xkb, xkbGetMapReply * rep, char *buf,
1358 ClientPtr client)
1359{
1360 unsigned i;
1361 xkbVModMapWireDesc *wire;
1362 unsigned short *pMap;
1363
1364 wire = (xkbVModMapWireDesc *) buf;
1365 pMap = &xkb->server->vmodmap[rep->firstVModMapKey];
1366 for (i = 0; i < rep->nVModMapKeys; i++, pMap++) {
1367 if (*pMap != 0) {
1368 wire->key = i + rep->firstVModMapKey;
1369 wire->vmods = *pMap;
1370 wire++;
1371 }
1372 }
1373 return (char *) wire;
1374}
1375
1376static Status
1377XkbComputeGetMapReplySize(XkbDescPtr xkb, xkbGetMapReply * rep)
1378{
1379 int len;
1380
1381 rep->minKeyCode = xkb->min_key_code;
1382 rep->maxKeyCode = xkb->max_key_code;
1383 len = XkbSizeKeyTypes(xkb, rep);
1384 len += XkbSizeKeySyms(xkb, rep);
1385 len += XkbSizeKeyActions(xkb, rep);
1386 len += XkbSizeKeyBehaviors(xkb, rep);
1387 len += XkbSizeVirtualMods(xkb, rep);
1388 len += XkbSizeExplicit(xkb, rep);
1389 len += XkbSizeModifierMap(xkb, rep);
1390 len += XkbSizeVirtualModMap(xkb, rep);
1391 rep->length += (len / 4);
1392 return Success;
1393}
1394
1395static int
1396XkbSendMap(ClientPtr client, XkbDescPtr xkb, xkbGetMapReply * rep)
1397{
1398 unsigned i, len;
1399 char *desc, *start;
1400
1401 len = (rep->length * 4) - (SIZEOF(xkbGetMapReply) - SIZEOF(xGenericReply));
1402 start = desc = calloc(1, len);
1403 if (!start)
1404 return BadAlloc;
1405 if (rep->nTypes > 0)
1406 desc = XkbWriteKeyTypes(xkb, rep, desc, client);
1407 if (rep->nKeySyms > 0)
1408 desc = XkbWriteKeySyms(xkb, rep, desc, client);
1409 if (rep->nKeyActs > 0)
1410 desc = XkbWriteKeyActions(xkb, rep, desc, client);
1411 if (rep->totalKeyBehaviors > 0)
1412 desc = XkbWriteKeyBehaviors(xkb, rep, desc, client);
1413 if (rep->virtualMods) {
1414 register int sz, bit;
1415
1416 for (i = sz = 0, bit = 1; i < XkbNumVirtualMods; i++, bit <<= 1) {
1417 if (rep->virtualMods & bit) {
1418 desc[sz++] = xkb->server->vmods[i];
1419 }
1420 }
1421 desc += XkbPaddedSize(sz);
1422 }
1423 if (rep->totalKeyExplicit > 0)
1424 desc = XkbWriteExplicit(xkb, rep, desc, client);
1425 if (rep->totalModMapKeys > 0)
1426 desc = XkbWriteModifierMap(xkb, rep, desc, client);
1427 if (rep->totalVModMapKeys > 0)
1428 desc = XkbWriteVirtualModMap(xkb, rep, desc, client);
1429 if ((desc - start) != (len)) {
1430 ErrorF
1431 ("[xkb] BOGUS LENGTH in write keyboard desc, expected %d, got %ld\n",
1432 len, (unsigned long) (desc - start));
1433 }
1434 if (client->swapped) {
1435 swaps(&rep->sequenceNumber);
1436 swapl(&rep->length);
1437 swaps(&rep->present);
1438 swaps(&rep->totalSyms);
1439 swaps(&rep->totalActs);
1440 }
1441 WriteToClient(client, (i = SIZEOF(xkbGetMapReply)), rep);
1442 WriteToClient(client, len, start);
1443 free((char *) start);
1444 return Success;
1445}
1446
1447int
1448ProcXkbGetMap(ClientPtr client)
1449{
1450 DeviceIntPtr dev;
1451 xkbGetMapReply rep;
1452 XkbDescRec *xkb;
1453 int n, status;
1454
1455 REQUEST(xkbGetMapReq);
1456 REQUEST_SIZE_MATCH(xkbGetMapReq);
1457
1458 if (!(client->xkbClientFlags & _XkbClientInitialized))
1459 return BadAccess;
1460
1461 CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess);
1462 CHK_MASK_OVERLAP(0x01, stuff->full, stuff->partial);
1463 CHK_MASK_LEGAL(0x02, stuff->full, XkbAllMapComponentsMask);
1464 CHK_MASK_LEGAL(0x03, stuff->partial, XkbAllMapComponentsMask);
1465
1466 xkb = dev->key->xkbInfo->desc;
1467 rep = (xkbGetMapReply) {
1468 .type = X_Reply,
1469 .deviceID = dev->id,
1470 .sequenceNumber = client->sequence,
1471 .length = (SIZEOF(xkbGetMapReply) - SIZEOF(xGenericReply)) >> 2,
1472 .present = stuff->partial | stuff->full,
1473 .minKeyCode = xkb->min_key_code,
1474 .maxKeyCode = xkb->max_key_code
1475 };
1476
1477 if (stuff->full & XkbKeyTypesMask) {
1478 rep.firstType = 0;
1479 rep.nTypes = xkb->map->num_types;
1480 }
1481 else if (stuff->partial & XkbKeyTypesMask) {
1482 if (((unsigned) stuff->firstType + stuff->nTypes) > xkb->map->num_types) {
1483 client->errorValue = _XkbErrCode4(0x04, xkb->map->num_types,
1484 stuff->firstType, stuff->nTypes);
1485 return BadValue;
1486 }
1487 rep.firstType = stuff->firstType;
1488 rep.nTypes = stuff->nTypes;
1489 }
1490 else
1491 rep.nTypes = 0;
1492 rep.totalTypes = xkb->map->num_types;
1493
1494 n = XkbNumKeys(xkb);
1495 if (stuff->full & XkbKeySymsMask) {
1496 rep.firstKeySym = xkb->min_key_code;
1497 rep.nKeySyms = n;
1498 }
1499 else if (stuff->partial & XkbKeySymsMask) {
1500 CHK_KEY_RANGE(0x05, stuff->firstKeySym, stuff->nKeySyms, xkb);
1501 rep.firstKeySym = stuff->firstKeySym;
1502 rep.nKeySyms = stuff->nKeySyms;
1503 }
1504 else
1505 rep.nKeySyms = 0;
1506 rep.totalSyms = 0;
1507
1508 if (stuff->full & XkbKeyActionsMask) {
1509 rep.firstKeyAct = xkb->min_key_code;
1510 rep.nKeyActs = n;
1511 }
1512 else if (stuff->partial & XkbKeyActionsMask) {
1513 CHK_KEY_RANGE(0x07, stuff->firstKeyAct, stuff->nKeyActs, xkb);
1514 rep.firstKeyAct = stuff->firstKeyAct;
1515 rep.nKeyActs = stuff->nKeyActs;
1516 }
1517 else
1518 rep.nKeyActs = 0;
1519 rep.totalActs = 0;
1520
1521 if (stuff->full & XkbKeyBehaviorsMask) {
1522 rep.firstKeyBehavior = xkb->min_key_code;
1523 rep.nKeyBehaviors = n;
1524 }
1525 else if (stuff->partial & XkbKeyBehaviorsMask) {
1526 CHK_KEY_RANGE(0x09, stuff->firstKeyBehavior, stuff->nKeyBehaviors, xkb);
1527 rep.firstKeyBehavior = stuff->firstKeyBehavior;
1528 rep.nKeyBehaviors = stuff->nKeyBehaviors;
1529 }
1530 else
1531 rep.nKeyBehaviors = 0;
1532 rep.totalKeyBehaviors = 0;
1533
1534 if (stuff->full & XkbVirtualModsMask)
1535 rep.virtualMods = ~0;
1536 else if (stuff->partial & XkbVirtualModsMask)
1537 rep.virtualMods = stuff->virtualMods;
1538
1539 if (stuff->full & XkbExplicitComponentsMask) {
1540 rep.firstKeyExplicit = xkb->min_key_code;
1541 rep.nKeyExplicit = n;
1542 }
1543 else if (stuff->partial & XkbExplicitComponentsMask) {
1544 CHK_KEY_RANGE(0x0B, stuff->firstKeyExplicit, stuff->nKeyExplicit, xkb);
1545 rep.firstKeyExplicit = stuff->firstKeyExplicit;
1546 rep.nKeyExplicit = stuff->nKeyExplicit;
1547 }
1548 else
1549 rep.nKeyExplicit = 0;
1550 rep.totalKeyExplicit = 0;
1551
1552 if (stuff->full & XkbModifierMapMask) {
1553 rep.firstModMapKey = xkb->min_key_code;
1554 rep.nModMapKeys = n;
1555 }
1556 else if (stuff->partial & XkbModifierMapMask) {
1557 CHK_KEY_RANGE(0x0D, stuff->firstModMapKey, stuff->nModMapKeys, xkb);
1558 rep.firstModMapKey = stuff->firstModMapKey;
1559 rep.nModMapKeys = stuff->nModMapKeys;
1560 }
1561 else
1562 rep.nModMapKeys = 0;
1563 rep.totalModMapKeys = 0;
1564
1565 if (stuff->full & XkbVirtualModMapMask) {
1566 rep.firstVModMapKey = xkb->min_key_code;
1567 rep.nVModMapKeys = n;
1568 }
1569 else if (stuff->partial & XkbVirtualModMapMask) {
1570 CHK_KEY_RANGE(0x0F, stuff->firstVModMapKey, stuff->nVModMapKeys, xkb);
1571 rep.firstVModMapKey = stuff->firstVModMapKey;
1572 rep.nVModMapKeys = stuff->nVModMapKeys;
1573 }
1574 else
1575 rep.nVModMapKeys = 0;
1576 rep.totalVModMapKeys = 0;
1577
1578 if ((status = XkbComputeGetMapReplySize(xkb, &rep)) != Success)
1579 return status;
1580 return XkbSendMap(client, xkb, &rep);
1581}
1582
1583/***====================================================================***/
1584
1585static int
1586CheckKeyTypes(ClientPtr client,
1587 XkbDescPtr xkb,
1588 xkbSetMapReq * req,
1589 xkbKeyTypeWireDesc ** wireRtrn,
1590 int *nMapsRtrn, CARD8 *mapWidthRtrn)
1591{
1592 unsigned nMaps;
1593 register unsigned i, n;
1594 register CARD8 *map;
1595 register xkbKeyTypeWireDesc *wire = *wireRtrn;
1596
1597 if (req->firstType > ((unsigned) xkb->map->num_types)) {
1598 *nMapsRtrn = _XkbErrCode3(0x01, req->firstType, xkb->map->num_types);
1599 return 0;
1600 }
1601 if (req->flags & XkbSetMapResizeTypes) {
1602 nMaps = req->firstType + req->nTypes;
1603 if (nMaps < XkbNumRequiredTypes) { /* canonical types must be there */
1604 *nMapsRtrn = _XkbErrCode4(0x02, req->firstType, req->nTypes, 4);
1605 return 0;
1606 }
1607 }
1608 else if (req->present & XkbKeyTypesMask) {
1609 nMaps = xkb->map->num_types;
1610 if ((req->firstType + req->nTypes) > nMaps) {
1611 *nMapsRtrn = req->firstType + req->nTypes;
1612 return 0;
1613 }
1614 }
1615 else {
1616 *nMapsRtrn = xkb->map->num_types;
1617 for (i = 0; i < xkb->map->num_types; i++) {
1618 mapWidthRtrn[i] = xkb->map->types[i].num_levels;
1619 }
1620 return 1;
1621 }
1622
1623 for (i = 0; i < req->firstType; i++) {
1624 mapWidthRtrn[i] = xkb->map->types[i].num_levels;
1625 }
1626 for (i = 0; i < req->nTypes; i++) {
1627 unsigned width;
1628
1629 if (client->swapped) {
1630 swaps(&wire->virtualMods);
1631 }
1632 n = i + req->firstType;
1633 width = wire->numLevels;
1634 if (width < 1) {
1635 *nMapsRtrn = _XkbErrCode3(0x04, n, width);
1636 return 0;
1637 }
1638 else if ((n == XkbOneLevelIndex) && (width != 1)) { /* must be width 1 */
1639 *nMapsRtrn = _XkbErrCode3(0x05, n, width);
1640 return 0;
1641 }
1642 else if ((width != 2) &&
1643 ((n == XkbTwoLevelIndex) || (n == XkbKeypadIndex) ||
1644 (n == XkbAlphabeticIndex))) {
1645 /* TWO_LEVEL, ALPHABETIC and KEYPAD must be width 2 */
1646 *nMapsRtrn = _XkbErrCode3(0x05, n, width);
1647 return 0;
1648 }
1649 if (wire->nMapEntries > 0) {
1650 xkbKTSetMapEntryWireDesc *mapWire;
1651 xkbModsWireDesc *preWire;
1652
1653 mapWire = (xkbKTSetMapEntryWireDesc *) &wire[1];
1654 preWire = (xkbModsWireDesc *) &mapWire[wire->nMapEntries];
1655 for (n = 0; n < wire->nMapEntries; n++) {
1656 if (client->swapped) {
1657 swaps(&mapWire[n].virtualMods);
1658 }
1659 if (mapWire[n].realMods & (~wire->realMods)) {
1660 *nMapsRtrn = _XkbErrCode4(0x06, n, mapWire[n].realMods,
1661 wire->realMods);
1662 return 0;
1663 }
1664 if (mapWire[n].virtualMods & (~wire->virtualMods)) {
1665 *nMapsRtrn = _XkbErrCode3(0x07, n, mapWire[n].virtualMods);
1666 return 0;
1667 }
1668 if (mapWire[n].level >= wire->numLevels) {
1669 *nMapsRtrn = _XkbErrCode4(0x08, n, wire->numLevels,
1670 mapWire[n].level);
1671 return 0;
1672 }
1673 if (wire->preserve) {
1674 if (client->swapped) {
1675 swaps(&preWire[n].virtualMods);
1676 }
1677 if (preWire[n].realMods & (~mapWire[n].realMods)) {
1678 *nMapsRtrn = _XkbErrCode4(0x09, n, preWire[n].realMods,
1679 mapWire[n].realMods);
1680 return 0;
1681 }
1682 if (preWire[n].virtualMods & (~mapWire[n].virtualMods)) {
1683 *nMapsRtrn =
1684 _XkbErrCode3(0x0a, n, preWire[n].virtualMods);
1685 return 0;
1686 }
1687 }
1688 }
1689 if (wire->preserve)
1690 map = (CARD8 *) &preWire[wire->nMapEntries];
1691 else
1692 map = (CARD8 *) &mapWire[wire->nMapEntries];
1693 }
1694 else
1695 map = (CARD8 *) &wire[1];
1696 mapWidthRtrn[i + req->firstType] = wire->numLevels;
1697 wire = (xkbKeyTypeWireDesc *) map;
1698 }
1699 for (i = req->firstType + req->nTypes; i < nMaps; i++) {
1700 mapWidthRtrn[i] = xkb->map->types[i].num_levels;
1701 }
1702 *nMapsRtrn = nMaps;
1703 *wireRtrn = wire;
1704 return 1;
1705}
1706
1707static int
1708CheckKeySyms(ClientPtr client,
1709 XkbDescPtr xkb,
1710 xkbSetMapReq * req,
1711 int nTypes,
1712 CARD8 *mapWidths,
1713 CARD16 *symsPerKey, xkbSymMapWireDesc ** wireRtrn, int *errorRtrn)
1714{
1715 register unsigned i;
1716 XkbSymMapPtr map;
1717 xkbSymMapWireDesc *wire = *wireRtrn;
1718
1719 if (!(XkbKeySymsMask & req->present))
1720 return 1;
1721 CHK_REQ_KEY_RANGE2(0x11, req->firstKeySym, req->nKeySyms, req, (*errorRtrn),
1722 0);
1723 for (i = 0; i < req->nKeySyms; i++) {
1724 KeySym *pSyms;
1725 register unsigned nG;
1726
1727 if (client->swapped) {
1728 swaps(&wire->nSyms);
1729 }
1730 nG = XkbNumGroups(wire->groupInfo);
1731 if (nG > XkbNumKbdGroups) {
1732 *errorRtrn = _XkbErrCode3(0x14, i + req->firstKeySym, nG);
1733 return 0;
1734 }
1735 if (nG > 0) {
1736 register int g, w;
1737
1738 for (g = w = 0; g < nG; g++) {
1739 if (wire->ktIndex[g] >= (unsigned) nTypes) {
1740 *errorRtrn = _XkbErrCode4(0x15, i + req->firstKeySym, g,
1741 wire->ktIndex[g]);
1742 return 0;
1743 }
1744 if (mapWidths[wire->ktIndex[g]] > w)
1745 w = mapWidths[wire->ktIndex[g]];
1746 }
1747 if (wire->width != w) {
1748 *errorRtrn =
1749 _XkbErrCode3(0x16, i + req->firstKeySym, wire->width);
1750 return 0;
1751 }
1752 w *= nG;
1753 symsPerKey[i + req->firstKeySym] = w;
1754 if (w != wire->nSyms) {
1755 *errorRtrn =
1756 _XkbErrCode4(0x16, i + req->firstKeySym, wire->nSyms, w);
1757 return 0;
1758 }
1759 }
1760 else if (wire->nSyms != 0) {
1761 *errorRtrn = _XkbErrCode3(0x17, i + req->firstKeySym, wire->nSyms);
1762 return 0;
1763 }
1764 pSyms = (KeySym *) &wire[1];
1765 wire = (xkbSymMapWireDesc *) &pSyms[wire->nSyms];
1766 }
1767
1768 map = &xkb->map->key_sym_map[i];
1769 for (; i <= (unsigned) xkb->max_key_code; i++, map++) {
1770 register int g, nG, w;
1771
1772 nG = XkbKeyNumGroups(xkb, i);
1773 for (w = g = 0; g < nG; g++) {
1774 if (map->kt_index[g] >= (unsigned) nTypes) {
1775 *errorRtrn = _XkbErrCode4(0x18, i, g, map->kt_index[g]);
1776 return 0;
1777 }
1778 if (mapWidths[map->kt_index[g]] > w)
1779 w = mapWidths[map->kt_index[g]];
1780 }
1781 symsPerKey[i] = w * nG;
1782 }
1783 *wireRtrn = wire;
1784 return 1;
1785}
1786
1787static int
1788CheckKeyActions(XkbDescPtr xkb,
1789 xkbSetMapReq * req,
1790 int nTypes,
1791 CARD8 *mapWidths,
1792 CARD16 *symsPerKey, CARD8 **wireRtrn, int *nActsRtrn)
1793{
1794 int nActs;
1795 CARD8 *wire = *wireRtrn;
1796 register unsigned i;
1797
1798 if (!(XkbKeyActionsMask & req->present))
1799 return 1;
1800 CHK_REQ_KEY_RANGE2(0x21, req->firstKeyAct, req->nKeyActs, req, (*nActsRtrn),
1801 0);
1802 for (nActs = i = 0; i < req->nKeyActs; i++) {
1803 if (wire[0] != 0) {
1804 if (wire[0] == symsPerKey[i + req->firstKeyAct])
1805 nActs += wire[0];
1806 else {
1807 *nActsRtrn = _XkbErrCode3(0x23, i + req->firstKeyAct, wire[0]);
1808 return 0;
1809 }
1810 }
1811 wire++;
1812 }
1813 if (req->nKeyActs % 4)
1814 wire += 4 - (req->nKeyActs % 4);
1815 *wireRtrn = (CARD8 *) (((XkbAnyAction *) wire) + nActs);
1816 *nActsRtrn = nActs;
1817 return 1;
1818}
1819
1820static int
1821CheckKeyBehaviors(XkbDescPtr xkb,
1822 xkbSetMapReq * req,
1823 xkbBehaviorWireDesc ** wireRtrn, int *errorRtrn)
1824{
1825 register xkbBehaviorWireDesc *wire = *wireRtrn;
1826 register XkbServerMapPtr server = xkb->server;
1827 register unsigned i;
1828 unsigned first, last;
1829
1830 if (((req->present & XkbKeyBehaviorsMask) == 0) || (req->nKeyBehaviors < 1)) {
1831 req->present &= ~XkbKeyBehaviorsMask;
1832 req->nKeyBehaviors = 0;
1833 return 1;
1834 }
1835 first = req->firstKeyBehavior;
1836 last = req->firstKeyBehavior + req->nKeyBehaviors - 1;
1837 if (first < req->minKeyCode) {
1838 *errorRtrn = _XkbErrCode3(0x31, first, req->minKeyCode);
1839 return 0;
1840 }
1841 if (last > req->maxKeyCode) {
1842 *errorRtrn = _XkbErrCode3(0x32, last, req->maxKeyCode);
1843 return 0;
1844 }
1845
1846 for (i = 0; i < req->totalKeyBehaviors; i++, wire++) {
1847 if ((wire->key < first) || (wire->key > last)) {
1848 *errorRtrn = _XkbErrCode4(0x33, first, last, wire->key);
1849 return 0;
1850 }
1851 if ((wire->type & XkbKB_Permanent) &&
1852 ((server->behaviors[wire->key].type != wire->type) ||
1853 (server->behaviors[wire->key].data != wire->data))) {
1854 *errorRtrn = _XkbErrCode3(0x33, wire->key, wire->type);
1855 return 0;
1856 }
1857 if ((wire->type == XkbKB_RadioGroup) &&
1858 ((wire->data & (~XkbKB_RGAllowNone)) > XkbMaxRadioGroups)) {
1859 *errorRtrn = _XkbErrCode4(0x34, wire->key, wire->data,
1860 XkbMaxRadioGroups);
1861 return 0;
1862 }
1863 if ((wire->type == XkbKB_Overlay1) || (wire->type == XkbKB_Overlay2)) {
1864 CHK_KEY_RANGE2(0x35, wire->key, 1, xkb, *errorRtrn, 0);
1865 }
1866 }
1867 *wireRtrn = wire;
1868 return 1;
1869}
1870
1871static int
1872CheckVirtualMods(XkbDescRec * xkb,
1873 xkbSetMapReq * req, CARD8 **wireRtrn, int *errorRtrn)
1874{
1875 register CARD8 *wire = *wireRtrn;
1876 register unsigned i, nMods, bit;
1877
1878 if (((req->present & XkbVirtualModsMask) == 0) || (req->virtualMods == 0))
1879 return 1;
1880 for (i = nMods = 0, bit = 1; i < XkbNumVirtualMods; i++, bit <<= 1) {
1881 if (req->virtualMods & bit)
1882 nMods++;
1883 }
1884 *wireRtrn = (wire + XkbPaddedSize(nMods));
1885 return 1;
1886}
1887
1888static int
1889CheckKeyExplicit(XkbDescPtr xkb,
1890 xkbSetMapReq * req, CARD8 **wireRtrn, int *errorRtrn)
1891{
1892 register CARD8 *wire = *wireRtrn;
1893 CARD8 *start;
1894 register unsigned i;
1895 int first, last;
1896
1897 if (((req->present & XkbExplicitComponentsMask) == 0) ||
1898 (req->nKeyExplicit < 1)) {
1899 req->present &= ~XkbExplicitComponentsMask;
1900 req->nKeyExplicit = 0;
1901 return 1;
1902 }
1903 first = req->firstKeyExplicit;
1904 last = first + req->nKeyExplicit - 1;
1905 if (first < req->minKeyCode) {
1906 *errorRtrn = _XkbErrCode3(0x51, first, req->minKeyCode);
1907 return 0;
1908 }
1909 if (last > req->maxKeyCode) {
1910 *errorRtrn = _XkbErrCode3(0x52, last, req->maxKeyCode);
1911 return 0;
1912 }
1913 start = wire;
1914 for (i = 0; i < req->totalKeyExplicit; i++, wire += 2) {
1915 if ((wire[0] < first) || (wire[0] > last)) {
1916 *errorRtrn = _XkbErrCode4(0x53, first, last, wire[0]);
1917 return 0;
1918 }
1919 if (wire[1] & (~XkbAllExplicitMask)) {
1920 *errorRtrn = _XkbErrCode3(0x52, ~XkbAllExplicitMask, wire[1]);
1921 return 0;
1922 }
1923 }
1924 wire += XkbPaddedSize(wire - start) - (wire - start);
1925 *wireRtrn = wire;
1926 return 1;
1927}
1928
1929static int
1930CheckModifierMap(XkbDescPtr xkb, xkbSetMapReq * req, CARD8 **wireRtrn,
1931 int *errRtrn)
1932{
1933 register CARD8 *wire = *wireRtrn;
1934 CARD8 *start;
1935 register unsigned i;
1936 int first, last;
1937
1938 if (((req->present & XkbModifierMapMask) == 0) || (req->nModMapKeys < 1)) {
1939 req->present &= ~XkbModifierMapMask;
1940 req->nModMapKeys = 0;
1941 return 1;
1942 }
1943 first = req->firstModMapKey;
1944 last = first + req->nModMapKeys - 1;
1945 if (first < req->minKeyCode) {
1946 *errRtrn = _XkbErrCode3(0x61, first, req->minKeyCode);
1947 return 0;
1948 }
1949 if (last > req->maxKeyCode) {
1950 *errRtrn = _XkbErrCode3(0x62, last, req->maxKeyCode);
1951 return 0;
1952 }
1953 start = wire;
1954 for (i = 0; i < req->totalModMapKeys; i++, wire += 2) {
1955 if ((wire[0] < first) || (wire[0] > last)) {
1956 *errRtrn = _XkbErrCode4(0x63, first, last, wire[0]);
1957 return 0;
1958 }
1959 }
1960 wire += XkbPaddedSize(wire - start) - (wire - start);
1961 *wireRtrn = wire;
1962 return 1;
1963}
1964
1965static int
1966CheckVirtualModMap(XkbDescPtr xkb,
1967 xkbSetMapReq * req,
1968 xkbVModMapWireDesc ** wireRtrn, int *errRtrn)
1969{
1970 register xkbVModMapWireDesc *wire = *wireRtrn;
1971 register unsigned i;
1972 int first, last;
1973
1974 if (((req->present & XkbVirtualModMapMask) == 0) || (req->nVModMapKeys < 1)) {
1975 req->present &= ~XkbVirtualModMapMask;
1976 req->nVModMapKeys = 0;
1977 return 1;
1978 }
1979 first = req->firstVModMapKey;
1980 last = first + req->nVModMapKeys - 1;
1981 if (first < req->minKeyCode) {
1982 *errRtrn = _XkbErrCode3(0x71, first, req->minKeyCode);
1983 return 0;
1984 }
1985 if (last > req->maxKeyCode) {
1986 *errRtrn = _XkbErrCode3(0x72, last, req->maxKeyCode);
1987 return 0;
1988 }
1989 for (i = 0; i < req->totalVModMapKeys; i++, wire++) {
1990 if ((wire->key < first) || (wire->key > last)) {
1991 *errRtrn = _XkbErrCode4(0x73, first, last, wire->key);
1992 return 0;
1993 }
1994 }
1995 *wireRtrn = wire;
1996 return 1;
1997}
1998
1999static char *
2000SetKeyTypes(XkbDescPtr xkb,
2001 xkbSetMapReq * req,
2002 xkbKeyTypeWireDesc * wire, XkbChangesPtr changes)
2003{
2004 register unsigned i;
2005 unsigned first, last;
2006 CARD8 *map;
2007
2008 if ((unsigned) (req->firstType + req->nTypes) > xkb->map->size_types) {
2009 i = req->firstType + req->nTypes;
2010 if (XkbAllocClientMap(xkb, XkbKeyTypesMask, i) != Success) {
2011 return NULL;
2012 }
2013 }
2014 if ((unsigned) (req->firstType + req->nTypes) > xkb->map->num_types)
2015 xkb->map->num_types = req->firstType + req->nTypes;
2016
2017 for (i = 0; i < req->nTypes; i++) {
2018 XkbKeyTypePtr pOld;
2019 register unsigned n;
2020
2021 if (XkbResizeKeyType(xkb, i + req->firstType, wire->nMapEntries,
2022 wire->preserve, wire->numLevels) != Success) {
2023 return NULL;
2024 }
2025 pOld = &xkb->map->types[i + req->firstType];
2026 map = (CARD8 *) &wire[1];
2027
2028 pOld->mods.real_mods = wire->realMods;
2029 pOld->mods.vmods = wire->virtualMods;
2030 pOld->num_levels = wire->numLevels;
2031 pOld->map_count = wire->nMapEntries;
2032
2033 pOld->mods.mask = pOld->mods.real_mods |
2034 XkbMaskForVMask(xkb, pOld->mods.vmods);
2035
2036 if (wire->nMapEntries) {
2037 xkbKTSetMapEntryWireDesc *mapWire;
2038 xkbModsWireDesc *preWire;
2039 unsigned tmp;
2040
2041 mapWire = (xkbKTSetMapEntryWireDesc *) map;
2042 preWire = (xkbModsWireDesc *) &mapWire[wire->nMapEntries];
2043 for (n = 0; n < wire->nMapEntries; n++) {
2044 pOld->map[n].active = 1;
2045 pOld->map[n].mods.mask = mapWire[n].realMods;
2046 pOld->map[n].mods.real_mods = mapWire[n].realMods;
2047 pOld->map[n].mods.vmods = mapWire[n].virtualMods;
2048 pOld->map[n].level = mapWire[n].level;
2049 if (mapWire[n].virtualMods != 0) {
2050 tmp = XkbMaskForVMask(xkb, mapWire[n].virtualMods);
2051 pOld->map[n].active = (tmp != 0);
2052 pOld->map[n].mods.mask |= tmp;
2053 }
2054 if (wire->preserve) {
2055 pOld->preserve[n].real_mods = preWire[n].realMods;
2056 pOld->preserve[n].vmods = preWire[n].virtualMods;
2057 tmp = XkbMaskForVMask(xkb, preWire[n].virtualMods);
2058 pOld->preserve[n].mask = preWire[n].realMods | tmp;
2059 }
2060 }
2061 if (wire->preserve)
2062 map = (CARD8 *) &preWire[wire->nMapEntries];
2063 else
2064 map = (CARD8 *) &mapWire[wire->nMapEntries];
2065 }
2066 else
2067 map = (CARD8 *) &wire[1];
2068 wire = (xkbKeyTypeWireDesc *) map;
2069 }
2070 first = req->firstType;
2071 last = first + req->nTypes - 1; /* last changed type */
2072 if (changes->map.changed & XkbKeyTypesMask) {
2073 int oldLast;
2074
2075 oldLast = changes->map.first_type + changes->map.num_types - 1;
2076 if (changes->map.first_type < first)
2077 first = changes->map.first_type;
2078 if (oldLast > last)
2079 last = oldLast;
2080 }
2081 changes->map.changed |= XkbKeyTypesMask;
2082 changes->map.first_type = first;
2083 changes->map.num_types = (last - first) + 1;
2084 return (char *) wire;
2085}
2086
2087static char *
2088SetKeySyms(ClientPtr client,
2089 XkbDescPtr xkb,
2090 xkbSetMapReq * req,
2091 xkbSymMapWireDesc * wire, XkbChangesPtr changes, DeviceIntPtr dev)
2092{
2093 register unsigned i, s;
2094 XkbSymMapPtr oldMap;
2095 KeySym *newSyms;
2096 KeySym *pSyms;
2097 unsigned first, last;
2098
2099 oldMap = &xkb->map->key_sym_map[req->firstKeySym];
2100 for (i = 0; i < req->nKeySyms; i++, oldMap++) {
2101 pSyms = (KeySym *) &wire[1];
2102 if (wire->nSyms > 0) {
2103 newSyms = XkbResizeKeySyms(xkb, i + req->firstKeySym, wire->nSyms);
2104 for (s = 0; s < wire->nSyms; s++) {
2105 newSyms[s] = pSyms[s];
2106 }
2107 if (client->swapped) {
2108 for (s = 0; s < wire->nSyms; s++) {
2109 swapl(&newSyms[s]);
2110 }
2111 }
2112 }
2113 oldMap->kt_index[0] = wire->ktIndex[0];
2114 oldMap->kt_index[1] = wire->ktIndex[1];
2115 oldMap->kt_index[2] = wire->ktIndex[2];
2116 oldMap->kt_index[3] = wire->ktIndex[3];
2117 oldMap->group_info = wire->groupInfo;
2118 oldMap->width = wire->width;
2119 wire = (xkbSymMapWireDesc *) &pSyms[wire->nSyms];
2120 }
2121 first = req->firstKeySym;
2122 last = first + req->nKeySyms - 1;
2123 if (changes->map.changed & XkbKeySymsMask) {
2124 int oldLast =
2125 (changes->map.first_key_sym + changes->map.num_key_syms - 1);
2126 if (changes->map.first_key_sym < first)
2127 first = changes->map.first_key_sym;
2128 if (oldLast > last)
2129 last = oldLast;
2130 }
2131 changes->map.changed |= XkbKeySymsMask;
2132 changes->map.first_key_sym = first;
2133 changes->map.num_key_syms = (last - first + 1);
2134
2135 s = 0;
2136 for (i = xkb->min_key_code; i <= xkb->max_key_code; i++) {
2137 if (XkbKeyNumGroups(xkb, i) > s)
2138 s = XkbKeyNumGroups(xkb, i);
2139 }
2140 if (s != xkb->ctrls->num_groups) {
2141 xkbControlsNotify cn;
2142 XkbControlsRec old;
2143
2144 cn.keycode = 0;
2145 cn.eventType = 0;
2146 cn.requestMajor = XkbReqCode;
2147 cn.requestMinor = X_kbSetMap;
2148 old = *xkb->ctrls;
2149 xkb->ctrls->num_groups = s;
2150 if (XkbComputeControlsNotify(dev, &old, xkb->ctrls, &cn, FALSE))
2151 XkbSendControlsNotify(dev, &cn);
2152 }
2153 return (char *) wire;
2154}
2155
2156static char *
2157SetKeyActions(XkbDescPtr xkb,
2158 xkbSetMapReq * req, CARD8 *wire, XkbChangesPtr changes)
2159{
2160 register unsigned i, first, last;
2161 CARD8 *nActs = wire;
2162 XkbAction *newActs;
2163
2164 wire += XkbPaddedSize(req->nKeyActs);
2165 for (i = 0; i < req->nKeyActs; i++) {
2166 if (nActs[i] == 0)
2167 xkb->server->key_acts[i + req->firstKeyAct] = 0;
2168 else {
2169 newActs = XkbResizeKeyActions(xkb, i + req->firstKeyAct, nActs[i]);
2170 memcpy((char *) newActs, (char *) wire,
2171 nActs[i] * SIZEOF(xkbActionWireDesc));
2172 wire += nActs[i] * SIZEOF(xkbActionWireDesc);
2173 }
2174 }
2175 first = req->firstKeyAct;
2176 last = (first + req->nKeyActs - 1);
2177 if (changes->map.changed & XkbKeyActionsMask) {
2178 int oldLast;
2179
2180 oldLast = changes->map.first_key_act + changes->map.num_key_acts - 1;
2181 if (changes->map.first_key_act < first)
2182 first = changes->map.first_key_act;
2183 if (oldLast > last)
2184 last = oldLast;
2185 }
2186 changes->map.changed |= XkbKeyActionsMask;
2187 changes->map.first_key_act = first;
2188 changes->map.num_key_acts = (last - first + 1);
2189 return (char *) wire;
2190}
2191
2192static char *
2193SetKeyBehaviors(XkbSrvInfoPtr xkbi,
2194 xkbSetMapReq * req,
2195 xkbBehaviorWireDesc * wire, XkbChangesPtr changes)
2196{
2197 register unsigned i;
2198 int maxRG = -1;
2199 XkbDescPtr xkb = xkbi->desc;
2200 XkbServerMapPtr server = xkb->server;
2201 unsigned first, last;
2202
2203 first = req->firstKeyBehavior;
2204 last = req->firstKeyBehavior + req->nKeyBehaviors - 1;
2205 memset(&server->behaviors[first], 0,
2206 req->nKeyBehaviors * sizeof(XkbBehavior));
2207 for (i = 0; i < req->totalKeyBehaviors; i++) {
2208 if ((server->behaviors[wire->key].type & XkbKB_Permanent) == 0) {
2209 server->behaviors[wire->key].type = wire->type;
2210 server->behaviors[wire->key].data = wire->data;
2211 if ((wire->type == XkbKB_RadioGroup) &&
2212 (((int) wire->data) > maxRG))
2213 maxRG = wire->data + 1;
2214 }
2215 wire++;
2216 }
2217
2218 if (maxRG > (int) xkbi->nRadioGroups) {
2219 int sz = maxRG * sizeof(XkbRadioGroupRec);
2220
2221 if (xkbi->radioGroups)
2222 xkbi->radioGroups = realloc(xkbi->radioGroups, sz);
2223 else
2224 xkbi->radioGroups = calloc(1, sz);
2225 if (xkbi->radioGroups) {
2226 if (xkbi->nRadioGroups)
2227 memset(&xkbi->radioGroups[xkbi->nRadioGroups], 0,
2228 (maxRG - xkbi->nRadioGroups) * sizeof(XkbRadioGroupRec));
2229 xkbi->nRadioGroups = maxRG;
2230 }
2231 else
2232 xkbi->nRadioGroups = 0;
2233 /* should compute members here */
2234 }
2235 if (changes->map.changed & XkbKeyBehaviorsMask) {
2236 unsigned oldLast;
2237
2238 oldLast = changes->map.first_key_behavior +
2239 changes->map.num_key_behaviors - 1;
2240 if (changes->map.first_key_behavior < req->firstKeyBehavior)
2241 first = changes->map.first_key_behavior;
2242 if (oldLast > last)
2243 last = oldLast;
2244 }
2245 changes->map.changed |= XkbKeyBehaviorsMask;
2246 changes->map.first_key_behavior = first;
2247 changes->map.num_key_behaviors = (last - first + 1);
2248 return (char *) wire;
2249}
2250
2251static char *
2252SetVirtualMods(XkbSrvInfoPtr xkbi, xkbSetMapReq * req, CARD8 *wire,
2253 XkbChangesPtr changes)
2254{
2255 register int i, bit, nMods;
2256 XkbServerMapPtr srv = xkbi->desc->server;
2257
2258 if (((req->present & XkbVirtualModsMask) == 0) || (req->virtualMods == 0))
2259 return (char *) wire;
2260 for (i = nMods = 0, bit = 1; i < XkbNumVirtualMods; i++, bit <<= 1) {
2261 if (req->virtualMods & bit) {
2262 if (srv->vmods[i] != wire[nMods]) {
2263 changes->map.changed |= XkbVirtualModsMask;
2264 changes->map.vmods |= bit;
2265 srv->vmods[i] = wire[nMods];
2266 }
2267 nMods++;
2268 }
2269 }
2270 return (char *) (wire + XkbPaddedSize(nMods));
2271}
2272
2273static char *
2274SetKeyExplicit(XkbSrvInfoPtr xkbi, xkbSetMapReq * req, CARD8 *wire,
2275 XkbChangesPtr changes)
2276{
2277 register unsigned i, first, last;
2278 XkbServerMapPtr xkb = xkbi->desc->server;
2279 CARD8 *start;
2280
2281 start = wire;
2282 first = req->firstKeyExplicit;
2283 last = req->firstKeyExplicit + req->nKeyExplicit - 1;
2284 memset(&xkb->explicit[first], 0, req->nKeyExplicit);
2285 for (i = 0; i < req->totalKeyExplicit; i++, wire += 2) {
2286 xkb->explicit[wire[0]] = wire[1];
2287 }
2288 if (first > 0) {
2289 if (changes->map.changed & XkbExplicitComponentsMask) {
2290 int oldLast;
2291
2292 oldLast = changes->map.first_key_explicit +
2293 changes->map.num_key_explicit - 1;
2294 if (changes->map.first_key_explicit < first)
2295 first = changes->map.first_key_explicit;
2296 if (oldLast > last)
2297 last = oldLast;
2298 }
2299 changes->map.first_key_explicit = first;
2300 changes->map.num_key_explicit = (last - first) + 1;
2301 }
2302 wire += XkbPaddedSize(wire - start) - (wire - start);
2303 return (char *) wire;
2304}
2305
2306static char *
2307SetModifierMap(XkbSrvInfoPtr xkbi,
2308 xkbSetMapReq * req, CARD8 *wire, XkbChangesPtr changes)
2309{
2310 register unsigned i, first, last;
2311 XkbClientMapPtr xkb = xkbi->desc->map;
2312 CARD8 *start;
2313
2314 start = wire;
2315 first = req->firstModMapKey;
2316 last = req->firstModMapKey + req->nModMapKeys - 1;
2317 memset(&xkb->modmap[first], 0, req->nModMapKeys);
2318 for (i = 0; i < req->totalModMapKeys; i++, wire += 2) {
2319 xkb->modmap[wire[0]] = wire[1];
2320 }
2321 if (first > 0) {
2322 if (changes->map.changed & XkbModifierMapMask) {
2323 int oldLast;
2324
2325 oldLast = changes->map.first_modmap_key +
2326 changes->map.num_modmap_keys - 1;
2327 if (changes->map.first_modmap_key < first)
2328 first = changes->map.first_modmap_key;
2329 if (oldLast > last)
2330 last = oldLast;
2331 }
2332 changes->map.first_modmap_key = first;
2333 changes->map.num_modmap_keys = (last - first) + 1;
2334 }
2335 wire += XkbPaddedSize(wire - start) - (wire - start);
2336 return (char *) wire;
2337}
2338
2339static char *
2340SetVirtualModMap(XkbSrvInfoPtr xkbi,
2341 xkbSetMapReq * req,
2342 xkbVModMapWireDesc * wire, XkbChangesPtr changes)
2343{
2344 register unsigned i, first, last;
2345 XkbServerMapPtr srv = xkbi->desc->server;
2346
2347 first = req->firstVModMapKey;
2348 last = req->firstVModMapKey + req->nVModMapKeys - 1;
2349 memset(&srv->vmodmap[first], 0, req->nVModMapKeys * sizeof(unsigned short));
2350 for (i = 0; i < req->totalVModMapKeys; i++, wire++) {
2351 srv->vmodmap[wire->key] = wire->vmods;
2352 }
2353 if (first > 0) {
2354 if (changes->map.changed & XkbVirtualModMapMask) {
2355 int oldLast;
2356
2357 oldLast = changes->map.first_vmodmap_key +
2358 changes->map.num_vmodmap_keys - 1;
2359 if (changes->map.first_vmodmap_key < first)
2360 first = changes->map.first_vmodmap_key;
2361 if (oldLast > last)
2362 last = oldLast;
2363 }
2364 changes->map.first_vmodmap_key = first;
2365 changes->map.num_vmodmap_keys = (last - first) + 1;
2366 }
2367 return (char *) wire;
2368}
2369
2370/**
2371 * Check if the given request can be applied to the given device but don't
2372 * actually do anything..
2373 */
2374static int
2375_XkbSetMapChecks(ClientPtr client, DeviceIntPtr dev, xkbSetMapReq * req,
2376 char *values)
2377{
2378 XkbSrvInfoPtr xkbi;
2379 XkbDescPtr xkb;
2380 int error;
2381 int nTypes = 0, nActions;
2382 CARD8 mapWidths[XkbMaxLegalKeyCode + 1] = { 0 };
2383 CARD16 symsPerKey[XkbMaxLegalKeyCode + 1] = { 0 };
2384 XkbSymMapPtr map;
2385 int i;
2386
2387 xkbi = dev->key->xkbInfo;
2388 xkb = xkbi->desc;
2389
2390 if ((xkb->min_key_code != req->minKeyCode) ||
2391 (xkb->max_key_code != req->maxKeyCode)) {
2392 if (client->vMajor != 1) { /* pre 1.0 versions of Xlib have a bug */
2393 req->minKeyCode = xkb->min_key_code;
2394 req->maxKeyCode = xkb->max_key_code;
2395 }
2396 else {
2397 if (!XkbIsLegalKeycode(req->minKeyCode)) {
2398 client->errorValue =
2399 _XkbErrCode3(2, req->minKeyCode, req->maxKeyCode);
2400 return BadValue;
2401 }
2402 if (req->minKeyCode > req->maxKeyCode) {
2403 client->errorValue =
2404 _XkbErrCode3(3, req->minKeyCode, req->maxKeyCode);
2405 return BadMatch;
2406 }
2407 }
2408 }
2409
2410 if ((req->present & XkbKeyTypesMask) &&
2411 (!CheckKeyTypes(client, xkb, req, (xkbKeyTypeWireDesc **) &values,
2412 &nTypes, mapWidths))) {
2413 client->errorValue = nTypes;
2414 return BadValue;
2415 }
2416
2417 /* symsPerKey/mapWidths must be filled regardless of client-side flags */
2418 map = &xkb->map->key_sym_map[xkb->min_key_code];
2419 for (i = xkb->min_key_code; i < xkb->max_key_code; i++, map++) {
2420 register int g, ng, w;
2421
2422 ng = XkbNumGroups(map->group_info);
2423 for (w = g = 0; g < ng; g++) {
2424 if (map->kt_index[g] >= (unsigned) nTypes) {
2425 client->errorValue = _XkbErrCode4(0x13, i, g, map->kt_index[g]);
2426 return 0;
2427 }
2428 if (mapWidths[map->kt_index[g]] > w)
2429 w = mapWidths[map->kt_index[g]];
2430 }
2431 symsPerKey[i] = w * ng;
2432 }
2433
2434 if ((req->present & XkbKeySymsMask) &&
2435 (!CheckKeySyms(client, xkb, req, nTypes, mapWidths, symsPerKey,
2436 (xkbSymMapWireDesc **) &values, &error))) {
2437 client->errorValue = error;
2438 return BadValue;
2439 }
2440
2441 if ((req->present & XkbKeyActionsMask) &&
2442 (!CheckKeyActions(xkb, req, nTypes, mapWidths, symsPerKey,
2443 (CARD8 **) &values, &nActions))) {
2444 client->errorValue = nActions;
2445 return BadValue;
2446 }
2447
2448 if ((req->present & XkbKeyBehaviorsMask) &&
2449 (!CheckKeyBehaviors
2450 (xkb, req, (xkbBehaviorWireDesc **) &values, &error))) {
2451 client->errorValue = error;
2452 return BadValue;
2453 }
2454
2455 if ((req->present & XkbVirtualModsMask) &&
2456 (!CheckVirtualMods(xkb, req, (CARD8 **) &values, &error))) {
2457 client->errorValue = error;
2458 return BadValue;
2459 }
2460 if ((req->present & XkbExplicitComponentsMask) &&
2461 (!CheckKeyExplicit(xkb, req, (CARD8 **) &values, &error))) {
2462 client->errorValue = error;
2463 return BadValue;
2464 }
2465 if ((req->present & XkbModifierMapMask) &&
2466 (!CheckModifierMap(xkb, req, (CARD8 **) &values, &error))) {
2467 client->errorValue = error;
2468 return BadValue;
2469 }
2470 if ((req->present & XkbVirtualModMapMask) &&
2471 (!CheckVirtualModMap
2472 (xkb, req, (xkbVModMapWireDesc **) &values, &error))) {
2473 client->errorValue = error;
2474 return BadValue;
2475 }
2476
2477 if (((values - ((char *) req)) / 4) != req->length) {
2478 ErrorF("[xkb] Internal error! Bad length in XkbSetMap (after check)\n");
2479 client->errorValue = values - ((char *) &req[1]);
2480 return BadLength;
2481 }
2482
2483 return Success;
2484}
2485
2486/**
2487 * Apply the given request on the given device.
2488 */
2489static int
2490_XkbSetMap(ClientPtr client, DeviceIntPtr dev, xkbSetMapReq * req, char *values)
2491{
2492 XkbEventCauseRec cause;
2493 XkbChangesRec change;
2494 Bool sentNKN;
2495 XkbSrvInfoPtr xkbi;
2496 XkbDescPtr xkb;
2497
2498 xkbi = dev->key->xkbInfo;
2499 xkb = xkbi->desc;
2500
2501 XkbSetCauseXkbReq(&cause, X_kbSetMap, client);
2502 memset(&change, 0, sizeof(change));
2503 sentNKN = FALSE;
2504 if ((xkb->min_key_code != req->minKeyCode) ||
2505 (xkb->max_key_code != req->maxKeyCode)) {
2506 Status status;
2507 xkbNewKeyboardNotify nkn;
2508
2509 nkn.deviceID = nkn.oldDeviceID = dev->id;
2510 nkn.oldMinKeyCode = xkb->min_key_code;
2511 nkn.oldMaxKeyCode = xkb->max_key_code;
2512 status = XkbChangeKeycodeRange(xkb, req->minKeyCode,
2513 req->maxKeyCode, &change);
2514 if (status != Success)
2515 return status; /* oh-oh. what about the other keyboards? */
2516 nkn.minKeyCode = xkb->min_key_code;
2517 nkn.maxKeyCode = xkb->max_key_code;
2518 nkn.requestMajor = XkbReqCode;
2519 nkn.requestMinor = X_kbSetMap;
2520 nkn.changed = XkbNKN_KeycodesMask;
2521 XkbSendNewKeyboardNotify(dev, &nkn);
2522 sentNKN = TRUE;
2523 }
2524
2525 if (req->present & XkbKeyTypesMask) {
2526 values = SetKeyTypes(xkb, req, (xkbKeyTypeWireDesc *) values, &change);
2527 if (!values)
2528 goto allocFailure;
2529 }
2530 if (req->present & XkbKeySymsMask) {
2531 values =
2532 SetKeySyms(client, xkb, req, (xkbSymMapWireDesc *) values, &change,
2533 dev);
2534 if (!values)
2535 goto allocFailure;
2536 }
2537 if (req->present & XkbKeyActionsMask) {
2538 values = SetKeyActions(xkb, req, (CARD8 *) values, &change);
2539 if (!values)
2540 goto allocFailure;
2541 }
2542 if (req->present & XkbKeyBehaviorsMask) {
2543 values =
2544 SetKeyBehaviors(xkbi, req, (xkbBehaviorWireDesc *) values, &change);
2545 if (!values)
2546 goto allocFailure;
2547 }
2548 if (req->present & XkbVirtualModsMask)
2549 values = SetVirtualMods(xkbi, req, (CARD8 *) values, &change);
2550 if (req->present & XkbExplicitComponentsMask)
2551 values = SetKeyExplicit(xkbi, req, (CARD8 *) values, &change);
2552 if (req->present & XkbModifierMapMask)
2553 values = SetModifierMap(xkbi, req, (CARD8 *) values, &change);
2554 if (req->present & XkbVirtualModMapMask)
2555 values =
2556 SetVirtualModMap(xkbi, req, (xkbVModMapWireDesc *) values, &change);
2557 if (((values - ((char *) req)) / 4) != req->length) {
2558 ErrorF("[xkb] Internal error! Bad length in XkbSetMap (after set)\n");
2559 client->errorValue = values - ((char *) &req[1]);
2560 return BadLength;
2561 }
2562 if (req->flags & XkbSetMapRecomputeActions) {
2563 KeyCode first, last, firstMM, lastMM;
2564
2565 if (change.map.num_key_syms > 0) {
2566 first = change.map.first_key_sym;
2567 last = first + change.map.num_key_syms - 1;
2568 }
2569 else
2570 first = last = 0;
2571 if (change.map.num_modmap_keys > 0) {
2572 firstMM = change.map.first_modmap_key;
2573 lastMM = first + change.map.num_modmap_keys - 1;
2574 }
2575 else
2576 firstMM = lastMM = 0;
2577 if ((last > 0) && (lastMM > 0)) {
2578 if (firstMM < first)
2579 first = firstMM;
2580 if (lastMM > last)
2581 last = lastMM;
2582 }
2583 else if (lastMM > 0) {
2584 first = firstMM;
2585 last = lastMM;
2586 }
2587 if (last > 0) {
2588 unsigned check = 0;
2589
2590 XkbUpdateActions(dev, first, (last - first + 1), &change, &check,
2591 &cause);
2592 if (check)
2593 XkbCheckSecondaryEffects(xkbi, check, &change, &cause);
2594 }
2595 }
2596 if (!sentNKN)
2597 XkbSendNotification(dev, &change, &cause);
2598
2599 return Success;
2600 allocFailure:
2601 return BadAlloc;
2602}
2603
2604int
2605ProcXkbSetMap(ClientPtr client)
2606{
2607 DeviceIntPtr dev;
2608 char *tmp;
2609 int rc;
2610
2611 REQUEST(xkbSetMapReq);
2612 REQUEST_AT_LEAST_SIZE(xkbSetMapReq);
2613
2614 if (!(client->xkbClientFlags & _XkbClientInitialized))
2615 return BadAccess;
2616
2617 CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess);
2618 CHK_MASK_LEGAL(0x01, stuff->present, XkbAllMapComponentsMask);
2619
2620 tmp = (char *) &stuff[1];
2621
2622 /* Check if we can to the SetMap on the requested device. If this
2623 succeeds, do the same thing for all extension devices (if needed).
2624 If any of them fails, fail. */
2625 rc = _XkbSetMapChecks(client, dev, stuff, tmp);
2626
2627 if (rc != Success)
2628 return rc;
2629
2630 if (stuff->deviceSpec == XkbUseCoreKbd) {
2631 DeviceIntPtr other;
2632
2633 for (other = inputInfo.devices; other; other = other->next) {
2634 if ((other != dev) && other->key && !IsMaster(other) &&
2635 GetMaster(other, MASTER_KEYBOARD) == dev) {
2636 rc = XaceHook(XACE_DEVICE_ACCESS, client, other,
2637 DixManageAccess);
2638 if (rc == Success) {
2639 rc = _XkbSetMapChecks(client, other, stuff, tmp);
2640 if (rc != Success)
2641 return rc;
2642 }
2643 }
2644 }
2645 }
2646
2647 /* We know now that we will succed with the SetMap. In theory anyway. */
2648 rc = _XkbSetMap(client, dev, stuff, tmp);
2649 if (rc != Success)
2650 return rc;
2651
2652 if (stuff->deviceSpec == XkbUseCoreKbd) {
2653 DeviceIntPtr other;
2654
2655 for (other = inputInfo.devices; other; other = other->next) {
2656 if ((other != dev) && other->key && !IsMaster(other) &&
2657 GetMaster(other, MASTER_KEYBOARD) == dev) {
2658 rc = XaceHook(XACE_DEVICE_ACCESS, client, other,
2659 DixManageAccess);
2660 if (rc == Success)
2661 _XkbSetMap(client, other, stuff, tmp);
2662 /* ignore rc. if the SetMap failed although the check above
2663 reported true there isn't much we can do. we still need to
2664 set all other devices, hoping that at least they stay in
2665 sync. */
2666 }
2667 }
2668 }
2669
2670 return Success;
2671}
2672
2673/***====================================================================***/
2674
2675static Status
2676XkbComputeGetCompatMapReplySize(XkbCompatMapPtr compat,
2677 xkbGetCompatMapReply * rep)
2678{
2679 unsigned size, nGroups;
2680
2681 nGroups = 0;
2682 if (rep->groups != 0) {
2683 register int i, bit;
2684
2685 for (i = 0, bit = 1; i < XkbNumKbdGroups; i++, bit <<= 1) {
2686 if (rep->groups & bit)
2687 nGroups++;
2688 }
2689 }
2690 size = nGroups * SIZEOF(xkbModsWireDesc);
2691 size += (rep->nSI * SIZEOF(xkbSymInterpretWireDesc));
2692 rep->length = size / 4;
2693 return Success;
2694}
2695
2696static int
2697XkbSendCompatMap(ClientPtr client,
2698 XkbCompatMapPtr compat, xkbGetCompatMapReply * rep)
2699{
2700 char *data;
2701 int size;
2702
2703 size = rep->length * 4;
2704 if (size > 0) {
2705 data = malloc(size);
2706 if (data) {
2707 register unsigned i, bit;
2708 xkbModsWireDesc *grp;
2709 XkbSymInterpretPtr sym = &compat->sym_interpret[rep->firstSI];
2710 xkbSymInterpretWireDesc *wire = (xkbSymInterpretWireDesc *) data;
2711
2712 for (i = 0; i < rep->nSI; i++, sym++, wire++) {
2713 wire->sym = sym->sym;
2714 wire->mods = sym->mods;
2715 wire->match = sym->match;
2716 wire->virtualMod = sym->virtual_mod;
2717 wire->flags = sym->flags;
2718 memcpy((char *) &wire->act, (char *) &sym->act,
2719 sz_xkbActionWireDesc);
2720 if (client->swapped) {
2721 swapl(&wire->sym);
2722 }
2723 }
2724 if (rep->groups) {
2725 grp = (xkbModsWireDesc *) wire;
2726 for (i = 0, bit = 1; i < XkbNumKbdGroups; i++, bit <<= 1) {
2727 if (rep->groups & bit) {
2728 grp->mask = compat->groups[i].mask;
2729 grp->realMods = compat->groups[i].real_mods;
2730 grp->virtualMods = compat->groups[i].vmods;
2731 if (client->swapped) {
2732 swaps(&grp->virtualMods);
2733 }
2734 grp++;
2735 }
2736 }
2737 wire = (xkbSymInterpretWireDesc *) grp;
2738 }
2739 }
2740 else
2741 return BadAlloc;
2742 }
2743 else
2744 data = NULL;
2745
2746 if (client->swapped) {
2747 swaps(&rep->sequenceNumber);
2748 swapl(&rep->length);
2749 swaps(&rep->firstSI);
2750 swaps(&rep->nSI);
2751 swaps(&rep->nTotalSI);
2752 }
2753
2754 WriteToClient(client, SIZEOF(xkbGetCompatMapReply), rep);
2755 if (data) {
2756 WriteToClient(client, size, data);
2757 free((char *) data);
2758 }
2759 return Success;
2760}
2761
2762int
2763ProcXkbGetCompatMap(ClientPtr client)
2764{
2765 xkbGetCompatMapReply rep;
2766 DeviceIntPtr dev;
2767 XkbDescPtr xkb;
2768 XkbCompatMapPtr compat;
2769
2770 REQUEST(xkbGetCompatMapReq);
2771 REQUEST_SIZE_MATCH(xkbGetCompatMapReq);
2772
2773 if (!(client->xkbClientFlags & _XkbClientInitialized))
2774 return BadAccess;
2775
2776 CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess);
2777
2778 xkb = dev->key->xkbInfo->desc;
2779 compat = xkb->compat;
2780
2781 rep = (xkbGetCompatMapReply) {
2782 .type = X_Reply,
2783 .sequenceNumber = client->sequence,
2784 .length = 0,
2785 .deviceID = dev->id,
2786 .firstSI = stuff->firstSI,
2787 .nSI = stuff->nSI
2788 };
2789 if (stuff->getAllSI) {
2790 rep.firstSI = 0;
2791 rep.nSI = compat->num_si;
2792 }
2793 else if ((((unsigned) stuff->nSI) > 0) &&
2794 ((unsigned) (stuff->firstSI + stuff->nSI - 1) >= compat->num_si)) {
2795 client->errorValue = _XkbErrCode2(0x05, compat->num_si);
2796 return BadValue;
2797 }
2798 rep.nTotalSI = compat->num_si;
2799 rep.groups = stuff->groups;
2800 XkbComputeGetCompatMapReplySize(compat, &rep);
2801 return XkbSendCompatMap(client, compat, &rep);
2802}
2803
2804/**
2805 * Apply the given request on the given device.
2806 * If dryRun is TRUE, then value checks are performed, but the device isn't
2807 * modified.
2808 */
2809static int
2810_XkbSetCompatMap(ClientPtr client, DeviceIntPtr dev,
2811 xkbSetCompatMapReq * req, char *data, BOOL dryRun)
2812{
2813 XkbSrvInfoPtr xkbi;
2814 XkbDescPtr xkb;
2815 XkbCompatMapPtr compat;
2816 int nGroups;
2817 unsigned i, bit;
2818
2819 xkbi = dev->key->xkbInfo;
2820 xkb = xkbi->desc;
2821 compat = xkb->compat;
2822
2823 if ((req->nSI > 0) || (req->truncateSI)) {
2824 xkbSymInterpretWireDesc *wire;
2825
2826 if (req->firstSI > compat->num_si) {
2827 client->errorValue = _XkbErrCode2(0x02, compat->num_si);
2828 return BadValue;
2829 }
2830 wire = (xkbSymInterpretWireDesc *) data;
2831 wire += req->nSI;
2832 data = (char *) wire;
2833 }
2834
2835 nGroups = 0;
2836 if (req->groups != 0) {
2837 for (i = 0, bit = 1; i < XkbNumKbdGroups; i++, bit <<= 1) {
2838 if (req->groups & bit)
2839 nGroups++;
2840 }
2841 }
2842 data += nGroups * SIZEOF(xkbModsWireDesc);
2843 if (((data - ((char *) req)) / 4) != req->length) {
2844 return BadLength;
2845 }
2846
2847 /* Done all the checks we can do */
2848 if (dryRun)
2849 return Success;
2850
2851 data = (char *) &req[1];
2852 if (req->nSI > 0) {
2853 xkbSymInterpretWireDesc *wire = (xkbSymInterpretWireDesc *) data;
2854 XkbSymInterpretPtr sym;
2855 unsigned int skipped = 0;
2856
2857 if ((unsigned) (req->firstSI + req->nSI) > compat->num_si) {
2858 compat->num_si = req->firstSI + req->nSI;
2859 compat->sym_interpret = realloc(compat->sym_interpret,
2860 compat->num_si *
2861 sizeof(XkbSymInterpretRec));
2862 if (!compat->sym_interpret) {
2863 compat->num_si = 0;
2864 return BadAlloc;
2865 }
2866 }
2867 else if (req->truncateSI) {
2868 compat->num_si = req->firstSI + req->nSI;
2869 }
2870 sym = &compat->sym_interpret[req->firstSI];
2871 for (i = 0; i < req->nSI; i++, wire++) {
2872 if (client->swapped) {
2873 swapl(&wire->sym);
2874 }
2875 if (wire->sym == NoSymbol && wire->match == XkbSI_AnyOfOrNone &&
2876 (wire->mods & 0xff) == 0xff &&
2877 wire->act.type == XkbSA_XFree86Private) {
2878 ErrorF("XKB: Skipping broken Any+AnyOfOrNone(All) -> Private "
2879 "action from client\n");
2880 skipped++;
2881 continue;
2882 }
2883 sym->sym = wire->sym;
2884 sym->mods = wire->mods;
2885 sym->match = wire->match;
2886 sym->flags = wire->flags;
2887 sym->virtual_mod = wire->virtualMod;
2888 memcpy((char *) &sym->act, (char *) &wire->act,
2889 SIZEOF(xkbActionWireDesc));
2890 sym++;
2891 }
2892 if (skipped) {
2893 if (req->firstSI + req->nSI < compat->num_si)
2894 memmove(sym, sym + skipped,
2895 (compat->num_si - req->firstSI - req->nSI) *
2896 sizeof(*sym));
2897 compat->num_si -= skipped;
2898 }
2899 data = (char *) wire;
2900 }
2901 else if (req->truncateSI) {
2902 compat->num_si = req->firstSI;
2903 }
2904
2905 if (req->groups != 0) {
2906 xkbModsWireDesc *wire = (xkbModsWireDesc *) data;
2907
2908 for (i = 0, bit = 1; i < XkbNumKbdGroups; i++, bit <<= 1) {
2909 if (req->groups & bit) {
2910 if (client->swapped) {
2911 swaps(&wire->virtualMods);
2912 }
2913 compat->groups[i].mask = wire->realMods;
2914 compat->groups[i].real_mods = wire->realMods;
2915 compat->groups[i].vmods = wire->virtualMods;
2916 if (wire->virtualMods != 0) {
2917 unsigned tmp;
2918
2919 tmp = XkbMaskForVMask(xkb, wire->virtualMods);
2920 compat->groups[i].mask |= tmp;
2921 }
2922 data += SIZEOF(xkbModsWireDesc);
2923 wire = (xkbModsWireDesc *) data;
2924 }
2925 }
2926 }
2927 i = XkbPaddedSize((data - ((char *) req)));
2928 if ((i / 4) != req->length) {
2929 ErrorF("[xkb] Internal length error on read in _XkbSetCompatMap\n");
2930 return BadLength;
2931 }
2932
2933 if (dev->xkb_interest) {
2934 xkbCompatMapNotify ev;
2935
2936 ev.deviceID = dev->id;
2937 ev.changedGroups = req->groups;
2938 ev.firstSI = req->firstSI;
2939 ev.nSI = req->nSI;
2940 ev.nTotalSI = compat->num_si;
2941 XkbSendCompatMapNotify(dev, &ev);
2942 }
2943
2944 if (req->recomputeActions) {
2945 XkbChangesRec change;
2946 unsigned check;
2947 XkbEventCauseRec cause;
2948
2949 XkbSetCauseXkbReq(&cause, X_kbSetCompatMap, client);
2950 memset(&change, 0, sizeof(XkbChangesRec));
2951 XkbUpdateActions(dev, xkb->min_key_code, XkbNumKeys(xkb), &change,
2952 &check, &cause);
2953 if (check)
2954 XkbCheckSecondaryEffects(xkbi, check, &change, &cause);
2955 XkbSendNotification(dev, &change, &cause);
2956 }
2957 return Success;
2958}
2959
2960int
2961ProcXkbSetCompatMap(ClientPtr client)
2962{
2963 DeviceIntPtr dev;
2964 char *data;
2965 int rc;
2966
2967 REQUEST(xkbSetCompatMapReq);
2968 REQUEST_AT_LEAST_SIZE(xkbSetCompatMapReq);
2969
2970 if (!(client->xkbClientFlags & _XkbClientInitialized))
2971 return BadAccess;
2972
2973 CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess);
2974
2975 data = (char *) &stuff[1];
2976
2977 /* check first using a dry-run */
2978 rc = _XkbSetCompatMap(client, dev, stuff, data, TRUE);
2979 if (rc != Success)
2980 return rc;
2981 if (stuff->deviceSpec == XkbUseCoreKbd) {
2982 DeviceIntPtr other;
2983
2984 for (other = inputInfo.devices; other; other = other->next) {
2985 if ((other != dev) && other->key && !IsMaster(other) &&
2986 GetMaster(other, MASTER_KEYBOARD) == dev) {
2987 rc = XaceHook(XACE_DEVICE_ACCESS, client, other,
2988 DixManageAccess);
2989 if (rc == Success) {
2990 /* dry-run */
2991 rc = _XkbSetCompatMap(client, other, stuff, data, TRUE);
2992 if (rc != Success)
2993 return rc;
2994 }
2995 }
2996 }
2997 }
2998
2999 /* Yay, the dry-runs succeed. Let's apply */
3000 rc = _XkbSetCompatMap(client, dev, stuff, data, FALSE);
3001 if (rc != Success)
3002 return rc;
3003 if (stuff->deviceSpec == XkbUseCoreKbd) {
3004 DeviceIntPtr other;
3005
3006 for (other = inputInfo.devices; other; other = other->next) {
3007 if ((other != dev) && other->key && !IsMaster(other) &&
3008 GetMaster(other, MASTER_KEYBOARD) == dev) {
3009 rc = XaceHook(XACE_DEVICE_ACCESS, client, other,
3010 DixManageAccess);
3011 if (rc == Success) {
3012 rc = _XkbSetCompatMap(client, other, stuff, data, FALSE);
3013 if (rc != Success)
3014 return rc;
3015 }
3016 }
3017 }
3018 }
3019
3020 return Success;
3021}
3022
3023/***====================================================================***/
3024
3025int
3026ProcXkbGetIndicatorState(ClientPtr client)
3027{
3028 xkbGetIndicatorStateReply rep;
3029 XkbSrvLedInfoPtr sli;
3030 DeviceIntPtr dev;
3031
3032 REQUEST(xkbGetIndicatorStateReq);
3033 REQUEST_SIZE_MATCH(xkbGetIndicatorStateReq);
3034
3035 if (!(client->xkbClientFlags & _XkbClientInitialized))
3036 return BadAccess;
3037
3038 CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixReadAccess);
3039
3040 sli = XkbFindSrvLedInfo(dev, XkbDfltXIClass, XkbDfltXIId,
3041 XkbXI_IndicatorStateMask);
3042 if (!sli)
3043 return BadAlloc;
3044
3045 rep = (xkbGetIndicatorStateReply) {
3046 .type = X_Reply,
3047 .deviceID = dev->id,
3048 .sequenceNumber = client->sequence,
3049 .length = 0,
3050 .state = sli->effectiveState
3051 };
3052
3053 if (client->swapped) {
3054 swaps(&rep.sequenceNumber);
3055 swapl(&rep.state);
3056 }
3057 WriteToClient(client, SIZEOF(xkbGetIndicatorStateReply), &rep);
3058 return Success;
3059}
3060
3061/***====================================================================***/
3062
3063static Status
3064XkbComputeGetIndicatorMapReplySize(XkbIndicatorPtr indicators,
3065 xkbGetIndicatorMapReply * rep)
3066{
3067 register int i, bit;
3068 int nIndicators;
3069
3070 rep->realIndicators = indicators->phys_indicators;
3071 for (i = nIndicators = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) {
3072 if (rep->which & bit)
3073 nIndicators++;
3074 }
3075 rep->length = (nIndicators * SIZEOF(xkbIndicatorMapWireDesc)) / 4;
3076 rep->nIndicators = nIndicators;
3077 return Success;
3078}
3079
3080static int
3081XkbSendIndicatorMap(ClientPtr client,
3082 XkbIndicatorPtr indicators, xkbGetIndicatorMapReply * rep)
3083{
3084 int length;
3085 CARD8 *map;
3086 register int i;
3087 register unsigned bit;
3088
3089 length = rep->length * 4;
3090 if (length > 0) {
3091 CARD8 *to;
3092
3093 to = map = malloc(length);
3094 if (map) {
3095 xkbIndicatorMapWireDesc *wire = (xkbIndicatorMapWireDesc *) to;
3096
3097 for (i = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) {
3098 if (rep->which & bit) {
3099 wire->flags = indicators->maps[i].flags;
3100 wire->whichGroups = indicators->maps[i].which_groups;
3101 wire->groups = indicators->maps[i].groups;
3102 wire->whichMods = indicators->maps[i].which_mods;
3103 wire->mods = indicators->maps[i].mods.mask;
3104 wire->realMods = indicators->maps[i].mods.real_mods;
3105 wire->virtualMods = indicators->maps[i].mods.vmods;
3106 wire->ctrls = indicators->maps[i].ctrls;
3107 if (client->swapped) {
3108 swaps(&wire->virtualMods);
3109 swapl(&wire->ctrls);
3110 }
3111 wire++;
3112 }
3113 }
3114 to = (CARD8 *) wire;
3115 if ((to - map) != length) {
3116 client->errorValue = _XkbErrCode2(0xff, length);
3117 free(map);
3118 return BadLength;
3119 }
3120 }
3121 else
3122 return BadAlloc;
3123 }
3124 else
3125 map = NULL;
3126 if (client->swapped) {
3127 swaps(&rep->sequenceNumber);
3128 swapl(&rep->length);
3129 swapl(&rep->which);
3130 swapl(&rep->realIndicators);
3131 }
3132 WriteToClient(client, SIZEOF(xkbGetIndicatorMapReply), rep);
3133 if (map) {
3134 WriteToClient(client, length, map);
3135 free((char *) map);
3136 }
3137 return Success;
3138}
3139
3140int
3141ProcXkbGetIndicatorMap(ClientPtr client)
3142{
3143 xkbGetIndicatorMapReply rep;
3144 DeviceIntPtr dev;
3145 XkbDescPtr xkb;
3146 XkbIndicatorPtr leds;
3147
3148 REQUEST(xkbGetIndicatorMapReq);
3149 REQUEST_SIZE_MATCH(xkbGetIndicatorMapReq);
3150
3151 if (!(client->xkbClientFlags & _XkbClientInitialized))
3152 return BadAccess;
3153
3154 CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess);
3155
3156 xkb = dev->key->xkbInfo->desc;
3157 leds = xkb->indicators;
3158
3159 rep = (xkbGetIndicatorMapReply) {
3160 .type = X_Reply,
3161 .deviceID = dev->id,
3162 .sequenceNumber = client->sequence,
3163 .length = 0,
3164 .which = stuff->which
3165 };
3166 XkbComputeGetIndicatorMapReplySize(leds, &rep);
3167 return XkbSendIndicatorMap(client, leds, &rep);
3168}
3169
3170/**
3171 * Apply the given map to the given device. Which specifies which components
3172 * to apply.
3173 */
3174static int
3175_XkbSetIndicatorMap(ClientPtr client, DeviceIntPtr dev,
3176 int which, xkbIndicatorMapWireDesc * desc)
3177{
3178 XkbSrvInfoPtr xkbi;
3179 XkbSrvLedInfoPtr sli;
3180 XkbEventCauseRec cause;
3181 int i, bit;
3182
3183 xkbi = dev->key->xkbInfo;
3184
3185 sli = XkbFindSrvLedInfo(dev, XkbDfltXIClass, XkbDfltXIId,
3186 XkbXI_IndicatorMapsMask);
3187 if (!sli)
3188 return BadAlloc;
3189
3190 for (i = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) {
3191 if (which & bit) {
3192 sli->maps[i].flags = desc->flags;
3193 sli->maps[i].which_groups = desc->whichGroups;
3194 sli->maps[i].groups = desc->groups;
3195 sli->maps[i].which_mods = desc->whichMods;
3196 sli->maps[i].mods.mask = desc->mods;
3197 sli->maps[i].mods.real_mods = desc->mods;
3198 sli->maps[i].mods.vmods = desc->virtualMods;
3199 sli->maps[i].ctrls = desc->ctrls;
3200 if (desc->virtualMods != 0) {
3201 unsigned tmp;
3202
3203 tmp = XkbMaskForVMask(xkbi->desc, desc->virtualMods);
3204 sli->maps[i].mods.mask = desc->mods | tmp;
3205 }
3206 desc++;
3207 }
3208 }
3209
3210 XkbSetCauseXkbReq(&cause, X_kbSetIndicatorMap, client);
3211 XkbApplyLedMapChanges(dev, sli, which, NULL, NULL, &cause);
3212
3213 return Success;
3214}
3215
3216int
3217ProcXkbSetIndicatorMap(ClientPtr client)
3218{
3219 int i, bit;
3220 int nIndicators;
3221 DeviceIntPtr dev;
3222 xkbIndicatorMapWireDesc *from;
3223 int rc;
3224
3225 REQUEST(xkbSetIndicatorMapReq);
3226 REQUEST_AT_LEAST_SIZE(xkbSetIndicatorMapReq);
3227
3228 if (!(client->xkbClientFlags & _XkbClientInitialized))
3229 return BadAccess;
3230
3231 CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixSetAttrAccess);
3232
3233 if (stuff->which == 0)
3234 return Success;
3235
3236 for (nIndicators = i = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) {
3237 if (stuff->which & bit)
3238 nIndicators++;
3239 }
3240 if (stuff->length != ((SIZEOF(xkbSetIndicatorMapReq) +
3241 (nIndicators * SIZEOF(xkbIndicatorMapWireDesc))) /
3242 4)) {
3243 return BadLength;
3244 }
3245
3246 from = (xkbIndicatorMapWireDesc *) &stuff[1];
3247 for (i = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) {
3248 if (stuff->which & bit) {
3249 if (client->swapped) {
3250 swaps(&from->virtualMods);
3251 swapl(&from->ctrls);
3252 }
3253 CHK_MASK_LEGAL(i, from->whichGroups, XkbIM_UseAnyGroup);
3254 CHK_MASK_LEGAL(i, from->whichMods, XkbIM_UseAnyMods);
3255 from++;
3256 }
3257 }
3258
3259 from = (xkbIndicatorMapWireDesc *) &stuff[1];
3260 rc = _XkbSetIndicatorMap(client, dev, stuff->which, from);
3261 if (rc != Success)
3262 return rc;
3263
3264 if (stuff->deviceSpec == XkbUseCoreKbd) {
3265 DeviceIntPtr other;
3266
3267 for (other = inputInfo.devices; other; other = other->next) {
3268 if ((other != dev) && other->key && !IsMaster(other) &&
3269 GetMaster(other, MASTER_KEYBOARD) == dev) {
3270 rc = XaceHook(XACE_DEVICE_ACCESS, client, other,
3271 DixSetAttrAccess);
3272 if (rc == Success)
3273 _XkbSetIndicatorMap(client, other, stuff->which, from);
3274 }
3275 }
3276 }
3277
3278 return Success;
3279}
3280
3281/***====================================================================***/
3282
3283int
3284ProcXkbGetNamedIndicator(ClientPtr client)
3285{
3286 DeviceIntPtr dev;
3287 xkbGetNamedIndicatorReply rep;
3288 register int i = 0;
3289 XkbSrvLedInfoPtr sli;
3290 XkbIndicatorMapPtr map = NULL;
3291
3292 REQUEST(xkbGetNamedIndicatorReq);
3293 REQUEST_SIZE_MATCH(xkbGetNamedIndicatorReq);
3294
3295 if (!(client->xkbClientFlags & _XkbClientInitialized))
3296 return BadAccess;
3297
3298 CHK_LED_DEVICE(dev, stuff->deviceSpec, client, DixReadAccess);
3299 CHK_ATOM_ONLY(stuff->indicator);
3300
3301 sli = XkbFindSrvLedInfo(dev, stuff->ledClass, stuff->ledID, 0);
3302 if (!sli)
3303 return BadAlloc;
3304
3305 i = 0;
3306 map = NULL;
3307 if ((sli->names) && (sli->maps)) {
3308 for (i = 0; i < XkbNumIndicators; i++) {
3309 if (stuff->indicator == sli->names[i]) {
3310 map = &sli->maps[i];
3311 break;
3312 }
3313 }
3314 }
3315
3316 rep = (xkbGetNamedIndicatorReply) {
3317 .type = X_Reply,
3318 .sequenceNumber = client->sequence,
3319 .length = 0,
3320 .deviceID = dev->id,
3321 .indicator = stuff->indicator
3322 };
3323 if (map != NULL) {
3324 rep.found = TRUE;
3325 rep.on = ((sli->effectiveState & (1 << i)) != 0);
3326 rep.realIndicator = ((sli->physIndicators & (1 << i)) != 0);
3327 rep.ndx = i;
3328 rep.flags = map->flags;
3329 rep.whichGroups = map->which_groups;
3330 rep.groups = map->groups;
3331 rep.whichMods = map->which_mods;
3332 rep.mods = map->mods.mask;
3333 rep.realMods = map->mods.real_mods;
3334 rep.virtualMods = map->mods.vmods;
3335 rep.ctrls = map->ctrls;
3336 rep.supported = TRUE;
3337 }
3338 else {
3339 rep.found = FALSE;
3340 rep.on = FALSE;
3341 rep.realIndicator = FALSE;
3342 rep.ndx = XkbNoIndicator;
3343 rep.flags = 0;
3344 rep.whichGroups = 0;
3345 rep.groups = 0;
3346 rep.whichMods = 0;
3347 rep.mods = 0;
3348 rep.realMods = 0;
3349 rep.virtualMods = 0;
3350 rep.ctrls = 0;
3351 rep.supported = TRUE;
3352 }
3353 if (client->swapped) {
3354 swapl(&rep.length);
3355 swaps(&rep.sequenceNumber);
3356 swapl(&rep.indicator);
3357 swaps(&rep.virtualMods);
3358 swapl(&rep.ctrls);
3359 }
3360
3361 WriteToClient(client, SIZEOF(xkbGetNamedIndicatorReply), &rep);
3362 return Success;
3363}
3364
3365/**
3366 * Find the IM on the device.
3367 * Returns the map, or NULL if the map doesn't exist.
3368 * If the return value is NULL, led_return is undefined. Otherwise, led_return
3369 * is set to the led index of the map.
3370 */
3371static XkbIndicatorMapPtr
3372_XkbFindNamedIndicatorMap(XkbSrvLedInfoPtr sli, Atom indicator, int *led_return)
3373{
3374 XkbIndicatorMapPtr map;
3375
3376 /* search for the right indicator */
3377 map = NULL;
3378 if (sli->names && sli->maps) {
3379 int led;
3380
3381 for (led = 0; (led < XkbNumIndicators) && (map == NULL); led++) {
3382 if (sli->names[led] == indicator) {
3383 map = &sli->maps[led];
3384 *led_return = led;
3385 break;
3386 }
3387 }
3388 }
3389
3390 return map;
3391}
3392
3393/**
3394 * Creates an indicator map on the device. If dryRun is TRUE, it only checks
3395 * if creation is possible, but doesn't actually create it.
3396 */
3397static int
3398_XkbCreateIndicatorMap(DeviceIntPtr dev, Atom indicator,
3399 int ledClass, int ledID,
3400 XkbIndicatorMapPtr * map_return, int *led_return,
3401 Bool dryRun)
3402{
3403 XkbSrvLedInfoPtr sli;
3404 XkbIndicatorMapPtr map;
3405 int led;
3406
3407 sli = XkbFindSrvLedInfo(dev, ledClass, ledID, XkbXI_IndicatorsMask);
3408 if (!sli)
3409 return BadAlloc;
3410
3411 map = _XkbFindNamedIndicatorMap(sli, indicator, &led);
3412
3413 if (!map) {
3414 /* find first unused indicator maps and assign the name to it */
3415 for (led = 0, map = NULL; (led < XkbNumIndicators) && (map == NULL);
3416 led++) {
3417 if ((sli->names) && (sli->maps) && (sli->names[led] == None) &&
3418 (!XkbIM_InUse(&sli->maps[led]))) {
3419 map = &sli->maps[led];
3420 if (!dryRun)
3421 sli->names[led] = indicator;
3422 break;
3423 }
3424 }
3425 }
3426
3427 if (!map)
3428 return BadAlloc;
3429
3430 *led_return = led;
3431 *map_return = map;
3432 return Success;
3433}
3434
3435static int
3436_XkbSetNamedIndicator(ClientPtr client, DeviceIntPtr dev,
3437 xkbSetNamedIndicatorReq * stuff)
3438{
3439 unsigned int extDevReason;
3440 unsigned int statec, namec, mapc;
3441 XkbSrvLedInfoPtr sli;
3442 int led = 0;
3443 XkbIndicatorMapPtr map;
3444 DeviceIntPtr kbd;
3445 XkbEventCauseRec cause;
3446 xkbExtensionDeviceNotify ed;
3447 XkbChangesRec changes;
3448 int rc;
3449
3450 rc = _XkbCreateIndicatorMap(dev, stuff->indicator, stuff->ledClass,
3451 stuff->ledID, &map, &led, FALSE);
3452 if (rc != Success || !map) /* oh-oh */
3453 return rc;
3454
3455 sli = XkbFindSrvLedInfo(dev, stuff->ledClass, stuff->ledID,
3456 XkbXI_IndicatorsMask);
3457 if (!sli)
3458 return BadAlloc;
3459
3460 namec = mapc = statec = 0;
3461 extDevReason = 0;
3462
3463 namec |= (1 << led);
3464 sli->namesPresent |= ((stuff->indicator != None) ? (1 << led) : 0);
3465 extDevReason |= XkbXI_IndicatorNamesMask;
3466
3467 if (stuff->setMap) {
3468 map->flags = stuff->flags;
3469 map->which_groups = stuff->whichGroups;
3470 map->groups = stuff->groups;
3471 map->which_mods = stuff->whichMods;
3472 map->mods.mask = stuff->realMods;
3473 map->mods.real_mods = stuff->realMods;
3474 map->mods.vmods = stuff->virtualMods;
3475 map->ctrls = stuff->ctrls;
3476 mapc |= (1 << led);
3477 }
3478
3479 if ((stuff->setState) && ((map->flags & XkbIM_NoExplicit) == 0)) {
3480 if (stuff->on)
3481 sli->explicitState |= (1 << led);
3482 else
3483 sli->explicitState &= ~(1 << led);
3484 statec |= ((sli->effectiveState ^ sli->explicitState) & (1 << led));
3485 }
3486
3487 memset((char *) &ed, 0, sizeof(xkbExtensionDeviceNotify));
3488 memset((char *) &changes, 0, sizeof(XkbChangesRec));
3489 XkbSetCauseXkbReq(&cause, X_kbSetNamedIndicator, client);
3490 if (namec)
3491 XkbApplyLedNameChanges(dev, sli, namec, &ed, &changes, &cause);
3492 if (mapc)
3493 XkbApplyLedMapChanges(dev, sli, mapc, &ed, &changes, &cause);
3494 if (statec)
3495 XkbApplyLedStateChanges(dev, sli, statec, &ed, &changes, &cause);
3496
3497 kbd = dev;
3498 if ((sli->flags & XkbSLI_HasOwnState) == 0)
3499 kbd = inputInfo.keyboard;
3500 XkbFlushLedEvents(dev, kbd, sli, &ed, &changes, &cause);
3501
3502 return Success;
3503}
3504
3505int
3506ProcXkbSetNamedIndicator(ClientPtr client)
3507{
3508 int rc;
3509 DeviceIntPtr dev;
3510 int led = 0;
3511 XkbIndicatorMapPtr map;
3512
3513 REQUEST(xkbSetNamedIndicatorReq);
3514 REQUEST_SIZE_MATCH(xkbSetNamedIndicatorReq);
3515
3516 if (!(client->xkbClientFlags & _XkbClientInitialized))
3517 return BadAccess;
3518
3519 CHK_LED_DEVICE(dev, stuff->deviceSpec, client, DixSetAttrAccess);
3520 CHK_ATOM_ONLY(stuff->indicator);
3521 CHK_MASK_LEGAL(0x10, stuff->whichGroups, XkbIM_UseAnyGroup);
3522 CHK_MASK_LEGAL(0x11, stuff->whichMods, XkbIM_UseAnyMods);
3523
3524 /* Dry-run for checks */
3525 rc = _XkbCreateIndicatorMap(dev, stuff->indicator,
3526 stuff->ledClass, stuff->ledID,
3527 &map, &led, TRUE);
3528 if (rc != Success || !map) /* couldn't be created or didn't exist */
3529 return rc;
3530
3531 if (stuff->deviceSpec == XkbUseCoreKbd ||
3532 stuff->deviceSpec == XkbUseCorePtr) {
3533 DeviceIntPtr other;
3534
3535 for (other = inputInfo.devices; other; other = other->next) {
3536 if ((other != dev) && !IsMaster(other) &&
3537 GetMaster(other, MASTER_KEYBOARD) == dev && (other->kbdfeed ||
3538 other->leds) &&
3539 (XaceHook(XACE_DEVICE_ACCESS, client, other, DixSetAttrAccess)
3540 == Success)) {
3541 rc = _XkbCreateIndicatorMap(other, stuff->indicator,
3542 stuff->ledClass, stuff->ledID, &map,
3543 &led, TRUE);
3544 if (rc != Success || !map)
3545 return rc;
3546 }
3547 }
3548 }
3549
3550 /* All checks passed, let's do it */
3551 rc = _XkbSetNamedIndicator(client, dev, stuff);
3552 if (rc != Success)
3553 return rc;
3554
3555 if (stuff->deviceSpec == XkbUseCoreKbd ||
3556 stuff->deviceSpec == XkbUseCorePtr) {
3557 DeviceIntPtr other;
3558
3559 for (other = inputInfo.devices; other; other = other->next) {
3560 if ((other != dev) && !IsMaster(other) &&
3561 GetMaster(other, MASTER_KEYBOARD) == dev && (other->kbdfeed ||
3562 other->leds) &&
3563 (XaceHook(XACE_DEVICE_ACCESS, client, other, DixSetAttrAccess)
3564 == Success)) {
3565 _XkbSetNamedIndicator(client, other, stuff);
3566 }
3567 }
3568 }
3569
3570 return Success;
3571}
3572
3573/***====================================================================***/
3574
3575static CARD32
3576_XkbCountAtoms(Atom *atoms, int maxAtoms, int *count)
3577{
3578 register unsigned int i, bit, nAtoms;
3579 register CARD32 atomsPresent;
3580
3581 for (i = nAtoms = atomsPresent = 0, bit = 1; i < maxAtoms; i++, bit <<= 1) {
3582 if (atoms[i] != None) {
3583 atomsPresent |= bit;
3584 nAtoms++;
3585 }
3586 }
3587 if (count)
3588 *count = nAtoms;
3589 return atomsPresent;
3590}
3591
3592static char *
3593_XkbWriteAtoms(char *wire, Atom *atoms, int maxAtoms, int swap)
3594{
3595 register unsigned int i;
3596 Atom *atm;
3597
3598 atm = (Atom *) wire;
3599 for (i = 0; i < maxAtoms; i++) {
3600 if (atoms[i] != None) {
3601 *atm = atoms[i];
3602 if (swap) {
3603 swapl(atm);
3604 }
3605 atm++;
3606 }
3607 }
3608 return (char *) atm;
3609}
3610
3611static Status
3612XkbComputeGetNamesReplySize(XkbDescPtr xkb, xkbGetNamesReply * rep)
3613{
3614 register unsigned which, length;
3615 register int i;
3616
3617 rep->minKeyCode = xkb->min_key_code;
3618 rep->maxKeyCode = xkb->max_key_code;
3619 which = rep->which;
3620 length = 0;
3621 if (xkb->names != NULL) {
3622 if (which & XkbKeycodesNameMask)
3623 length++;
3624 if (which & XkbGeometryNameMask)
3625 length++;
3626 if (which & XkbSymbolsNameMask)
3627 length++;
3628 if (which & XkbPhysSymbolsNameMask)
3629 length++;
3630 if (which & XkbTypesNameMask)
3631 length++;
3632 if (which & XkbCompatNameMask)
3633 length++;
3634 }
3635 else
3636 which &= ~XkbComponentNamesMask;
3637
3638 if (xkb->map != NULL) {
3639 if (which & XkbKeyTypeNamesMask)
3640 length += xkb->map->num_types;
3641 rep->nTypes = xkb->map->num_types;
3642 if (which & XkbKTLevelNamesMask) {
3643 XkbKeyTypePtr pType = xkb->map->types;
3644 int nKTLevels = 0;
3645
3646 length += XkbPaddedSize(xkb->map->num_types) / 4;
3647 for (i = 0; i < xkb->map->num_types; i++, pType++) {
3648 if (pType->level_names != NULL)
3649 nKTLevels += pType->num_levels;
3650 }
3651 rep->nKTLevels = nKTLevels;
3652 length += nKTLevels;
3653 }
3654 }
3655 else {
3656 rep->nTypes = 0;
3657 rep->nKTLevels = 0;
3658 which &= ~(XkbKeyTypeNamesMask | XkbKTLevelNamesMask);
3659 }
3660
3661 rep->minKeyCode = xkb->min_key_code;
3662 rep->maxKeyCode = xkb->max_key_code;
3663 rep->indicators = 0;
3664 rep->virtualMods = 0;
3665 rep->groupNames = 0;
3666 if (xkb->names != NULL) {
3667 if (which & XkbIndicatorNamesMask) {
3668 int nLeds;
3669
3670 rep->indicators =
3671 _XkbCountAtoms(xkb->names->indicators, XkbNumIndicators,
3672 &nLeds);
3673 length += nLeds;
3674 if (nLeds == 0)
3675 which &= ~XkbIndicatorNamesMask;
3676 }
3677
3678 if (which & XkbVirtualModNamesMask) {
3679 int nVMods;
3680
3681 rep->virtualMods =
3682 _XkbCountAtoms(xkb->names->vmods, XkbNumVirtualMods, &nVMods);
3683 length += nVMods;
3684 if (nVMods == 0)
3685 which &= ~XkbVirtualModNamesMask;
3686 }
3687
3688 if (which & XkbGroupNamesMask) {
3689 int nGroups;
3690
3691 rep->groupNames =
3692 _XkbCountAtoms(xkb->names->groups, XkbNumKbdGroups, &nGroups);
3693 length += nGroups;
3694 if (nGroups == 0)
3695 which &= ~XkbGroupNamesMask;
3696 }
3697
3698 if ((which & XkbKeyNamesMask) && (xkb->names->keys))
3699 length += rep->nKeys;
3700 else
3701 which &= ~XkbKeyNamesMask;
3702
3703 if ((which & XkbKeyAliasesMask) &&
3704 (xkb->names->key_aliases) && (xkb->names->num_key_aliases > 0)) {
3705 rep->nKeyAliases = xkb->names->num_key_aliases;
3706 length += rep->nKeyAliases * 2;
3707 }
3708 else {
3709 which &= ~XkbKeyAliasesMask;
3710 rep->nKeyAliases = 0;
3711 }
3712
3713 if ((which & XkbRGNamesMask) && (xkb->names->num_rg > 0))
3714 length += xkb->names->num_rg;
3715 else
3716 which &= ~XkbRGNamesMask;
3717 }
3718 else {
3719 which &= ~(XkbIndicatorNamesMask | XkbVirtualModNamesMask);
3720 which &= ~(XkbGroupNamesMask | XkbKeyNamesMask | XkbKeyAliasesMask);
3721 which &= ~XkbRGNamesMask;
3722 }
3723
3724 rep->length = length;
3725 rep->which = which;
3726 return Success;
3727}
3728
3729static int
3730XkbSendNames(ClientPtr client, XkbDescPtr xkb, xkbGetNamesReply * rep)
3731{
3732 register unsigned i, length, which;
3733 char *start;
3734 char *desc;
3735
3736 length = rep->length * 4;
3737 which = rep->which;
3738 if (client->swapped) {
3739 swaps(&rep->sequenceNumber);
3740 swapl(&rep->length);
3741 swapl(&rep->which);
3742 swaps(&rep->virtualMods);
3743 swapl(&rep->indicators);
3744 }
3745
3746 start = desc = calloc(1, length);
3747 if (!start)
3748 return BadAlloc;
3749 if (xkb->names) {
3750 if (which & XkbKeycodesNameMask) {
3751 *((CARD32 *) desc) = xkb->names->keycodes;
3752 if (client->swapped) {
3753 swapl((int *) desc);
3754 }
3755 desc += 4;
3756 }
3757 if (which & XkbGeometryNameMask) {
3758 *((CARD32 *) desc) = xkb->names->geometry;
3759 if (client->swapped) {
3760 swapl((int *) desc);
3761 }
3762 desc += 4;
3763 }
3764 if (which & XkbSymbolsNameMask) {
3765 *((CARD32 *) desc) = xkb->names->symbols;
3766 if (client->swapped) {
3767 swapl((int *) desc);
3768 }
3769 desc += 4;
3770 }
3771 if (which & XkbPhysSymbolsNameMask) {
3772 register CARD32 *atm = (CARD32 *) desc;
3773
3774 atm[0] = (CARD32) xkb->names->phys_symbols;
3775 if (client->swapped) {
3776 swapl(&atm[0]);
3777 }
3778 desc += 4;
3779 }
3780 if (which & XkbTypesNameMask) {
3781 *((CARD32 *) desc) = (CARD32) xkb->names->types;
3782 if (client->swapped) {
3783 swapl((int *) desc);
3784 }
3785 desc += 4;
3786 }
3787 if (which & XkbCompatNameMask) {
3788 *((CARD32 *) desc) = (CARD32) xkb->names->compat;
3789 if (client->swapped) {
3790 swapl((int *) desc);
3791 }
3792 desc += 4;
3793 }
3794 if (which & XkbKeyTypeNamesMask) {
3795 register CARD32 *atm = (CARD32 *) desc;
3796 register XkbKeyTypePtr type = xkb->map->types;
3797
3798 for (i = 0; i < xkb->map->num_types; i++, atm++, type++) {
3799 *atm = (CARD32) type->name;
3800 if (client->swapped) {
3801 swapl(atm);
3802 }
3803 }
3804 desc = (char *) atm;
3805 }
3806 if (which & XkbKTLevelNamesMask && xkb->map) {
3807 XkbKeyTypePtr type = xkb->map->types;
3808 register CARD32 *atm;
3809
3810 for (i = 0; i < rep->nTypes; i++, type++) {
3811 *desc++ = type->num_levels;
3812 }
3813 desc += XkbPaddedSize(rep->nTypes) - rep->nTypes;
3814
3815 atm = (CARD32 *) desc;
3816 type = xkb->map->types;
3817 for (i = 0; i < xkb->map->num_types; i++, type++) {
3818 register unsigned l;
3819
3820 if (type->level_names) {
3821 for (l = 0; l < type->num_levels; l++, atm++) {
3822 *atm = type->level_names[l];
3823 if (client->swapped) {
3824 swapl(atm);
3825 }
3826 }
3827 desc += type->num_levels * 4;
3828 }
3829 }
3830 }
3831 if (which & XkbIndicatorNamesMask) {
3832 desc =
3833 _XkbWriteAtoms(desc, xkb->names->indicators, XkbNumIndicators,
3834 client->swapped);
3835 }
3836 if (which & XkbVirtualModNamesMask) {
3837 desc = _XkbWriteAtoms(desc, xkb->names->vmods, XkbNumVirtualMods,
3838 client->swapped);
3839 }
3840 if (which & XkbGroupNamesMask) {
3841 desc = _XkbWriteAtoms(desc, xkb->names->groups, XkbNumKbdGroups,
3842 client->swapped);
3843 }
3844 if (which & XkbKeyNamesMask) {
3845 for (i = 0; i < rep->nKeys; i++, desc += sizeof(XkbKeyNameRec)) {
3846 *((XkbKeyNamePtr) desc) = xkb->names->keys[i + rep->firstKey];
3847 }
3848 }
3849 if (which & XkbKeyAliasesMask) {
3850 XkbKeyAliasPtr pAl;
3851
3852 pAl = xkb->names->key_aliases;
3853 for (i = 0; i < rep->nKeyAliases;
3854 i++, pAl++, desc += 2 * XkbKeyNameLength) {
3855 *((XkbKeyAliasPtr) desc) = *pAl;
3856 }
3857 }
3858 if ((which & XkbRGNamesMask) && (rep->nRadioGroups > 0)) {
3859 register CARD32 *atm = (CARD32 *) desc;
3860
3861 for (i = 0; i < rep->nRadioGroups; i++, atm++) {
3862 *atm = (CARD32) xkb->names->radio_groups[i];
3863 if (client->swapped) {
3864 swapl(atm);
3865 }
3866 }
3867 desc += rep->nRadioGroups * 4;
3868 }
3869 }
3870
3871 if ((desc - start) != (length)) {
3872 ErrorF("[xkb] BOGUS LENGTH in write names, expected %d, got %ld\n",
3873 length, (unsigned long) (desc - start));
3874 }
3875 WriteToClient(client, SIZEOF(xkbGetNamesReply), rep);
3876 WriteToClient(client, length, start);
3877 free((char *) start);
3878 return Success;
3879}
3880
3881int
3882ProcXkbGetNames(ClientPtr client)
3883{
3884 DeviceIntPtr dev;
3885 XkbDescPtr xkb;
3886 xkbGetNamesReply rep;
3887
3888 REQUEST(xkbGetNamesReq);
3889 REQUEST_SIZE_MATCH(xkbGetNamesReq);
3890
3891 if (!(client->xkbClientFlags & _XkbClientInitialized))
3892 return BadAccess;
3893
3894 CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess);
3895 CHK_MASK_LEGAL(0x01, stuff->which, XkbAllNamesMask);
3896
3897 xkb = dev->key->xkbInfo->desc;
3898 rep = (xkbGetNamesReply) {
3899 .type = X_Reply,
3900 .deviceID = dev->id,
3901 .sequenceNumber = client->sequence,
3902 .length = 0,
3903 .which = stuff->which,
3904 .nTypes = xkb->map->num_types,
3905 .firstKey = xkb->min_key_code,
3906 .nKeys = XkbNumKeys(xkb),
3907 .nKeyAliases = xkb->names ? xkb->names->num_key_aliases : 0,
3908 .nRadioGroups = xkb->names ? xkb->names->num_rg : 0
3909 };
3910 XkbComputeGetNamesReplySize(xkb, &rep);
3911 return XkbSendNames(client, xkb, &rep);
3912}
3913
3914/***====================================================================***/
3915
3916static CARD32 *
3917_XkbCheckAtoms(CARD32 *wire, int nAtoms, int swapped, Atom *pError)
3918{
3919 register int i;
3920
3921 for (i = 0; i < nAtoms; i++, wire++) {
3922 if (swapped) {
3923 swapl(wire);
3924 }
3925 if ((((Atom) *wire) != None) && (!ValidAtom((Atom) *wire))) {
3926 *pError = ((Atom) *wire);
3927 return NULL;
3928 }
3929 }
3930 return wire;
3931}
3932
3933static CARD32 *
3934_XkbCheckMaskedAtoms(CARD32 *wire, int nAtoms, CARD32 present, int swapped,
3935 Atom *pError)
3936{
3937 register unsigned i, bit;
3938
3939 for (i = 0, bit = 1; (i < nAtoms) && (present); i++, bit <<= 1) {
3940 if ((present & bit) == 0)
3941 continue;
3942 if (swapped) {
3943 swapl(wire);
3944 }
3945 if ((((Atom) *wire) != None) && (!ValidAtom(((Atom) *wire)))) {
3946 *pError = (Atom) *wire;
3947 return NULL;
3948 }
3949 wire++;
3950 }
3951 return wire;
3952}
3953
3954static Atom *
3955_XkbCopyMaskedAtoms(Atom *wire, Atom *dest, int nAtoms, CARD32 present)
3956{
3957 register int i, bit;
3958
3959 for (i = 0, bit = 1; (i < nAtoms) && (present); i++, bit <<= 1) {
3960 if ((present & bit) == 0)
3961 continue;
3962 dest[i] = *wire++;
3963 }
3964 return wire;
3965}
3966
3967static Bool
3968_XkbCheckTypeName(Atom name, int typeNdx)
3969{
3970 const char *str;
3971
3972 str = NameForAtom(name);
3973 if ((strcmp(str, "ONE_LEVEL") == 0) || (strcmp(str, "TWO_LEVEL") == 0) ||
3974 (strcmp(str, "ALPHABETIC") == 0) || (strcmp(str, "KEYPAD") == 0))
3975 return FALSE;
3976 return TRUE;
3977}
3978
3979/**
3980 * Check the device-dependent data in the request against the device. Returns
3981 * Success, or the appropriate error code.
3982 */
3983static int
3984_XkbSetNamesCheck(ClientPtr client, DeviceIntPtr dev,
3985 xkbSetNamesReq * stuff, CARD32 *data)
3986{
3987 XkbDescRec *xkb;
3988 CARD32 *tmp;
3989 Atom bad;
3990
3991 tmp = data;
3992 xkb = dev->key->xkbInfo->desc;
3993
3994 if (stuff->which & XkbKeyTypeNamesMask) {
3995 int i;
3996 CARD32 *old;
3997
3998 if (stuff->nTypes < 1) {
3999 client->errorValue = _XkbErrCode2(0x02, stuff->nTypes);
4000 return BadValue;
4001 }
4002 if ((unsigned) (stuff->firstType + stuff->nTypes - 1) >=
4003 xkb->map->num_types) {
4004 client->errorValue =
4005 _XkbErrCode4(0x03, stuff->firstType, stuff->nTypes,
4006 xkb->map->num_types);
4007 return BadValue;
4008 }
4009 if (((unsigned) stuff->firstType) <= XkbLastRequiredType) {
4010 client->errorValue = _XkbErrCode2(0x04, stuff->firstType);
4011 return BadAccess;
4012 }
4013 old = tmp;
4014 tmp = _XkbCheckAtoms(tmp, stuff->nTypes, client->swapped, &bad);
4015 if (!tmp) {
4016 client->errorValue = bad;
4017 return BadAtom;
4018 }
4019 for (i = 0; i < stuff->nTypes; i++, old++) {
4020 if (!_XkbCheckTypeName((Atom) *old, stuff->firstType + i))
4021 client->errorValue = _XkbErrCode2(0x05, i);
4022 }
4023 }
4024 if (stuff->which & XkbKTLevelNamesMask) {
4025 unsigned i;
4026 XkbKeyTypePtr type;
4027 CARD8 *width;
4028
4029 if (stuff->nKTLevels < 1) {
4030 client->errorValue = _XkbErrCode2(0x05, stuff->nKTLevels);
4031 return BadValue;
4032 }
4033 if ((unsigned) (stuff->firstKTLevel + stuff->nKTLevels - 1) >=
4034 xkb->map->num_types) {
4035 client->errorValue = _XkbErrCode4(0x06, stuff->firstKTLevel,
4036 stuff->nKTLevels,
4037 xkb->map->num_types);
4038 return BadValue;
4039 }
4040 width = (CARD8 *) tmp;
4041 tmp = (CARD32 *) (((char *) tmp) + XkbPaddedSize(stuff->nKTLevels));
4042 type = &xkb->map->types[stuff->firstKTLevel];
4043 for (i = 0; i < stuff->nKTLevels; i++, type++) {
4044 if (width[i] == 0)
4045 continue;
4046 else if (width[i] != type->num_levels) {
4047 client->errorValue = _XkbErrCode4(0x07, i + stuff->firstKTLevel,
4048 type->num_levels, width[i]);
4049 return BadMatch;
4050 }
4051 tmp = _XkbCheckAtoms(tmp, width[i], client->swapped, &bad);
4052 if (!tmp) {
4053 client->errorValue = bad;
4054 return BadAtom;
4055 }
4056 }
4057 }
4058 if (stuff->which & XkbIndicatorNamesMask) {
4059 if (stuff->indicators == 0) {
4060 client->errorValue = 0x08;
4061 return BadMatch;
4062 }
4063 tmp = _XkbCheckMaskedAtoms(tmp, XkbNumIndicators, stuff->indicators,
4064 client->swapped, &bad);
4065 if (!tmp) {
4066 client->errorValue = bad;
4067 return BadAtom;
4068 }
4069 }
4070 if (stuff->which & XkbVirtualModNamesMask) {
4071 if (stuff->virtualMods == 0) {
4072 client->errorValue = 0x09;
4073 return BadMatch;
4074 }
4075 tmp = _XkbCheckMaskedAtoms(tmp, XkbNumVirtualMods,
4076 (CARD32) stuff->virtualMods,
4077 client->swapped, &bad);
4078 if (!tmp) {
4079 client->errorValue = bad;
4080 return BadAtom;
4081 }
4082 }
4083 if (stuff->which & XkbGroupNamesMask) {
4084 if (stuff->groupNames == 0) {
4085 client->errorValue = 0x0a;
4086 return BadMatch;
4087 }
4088 tmp = _XkbCheckMaskedAtoms(tmp, XkbNumKbdGroups,
4089 (CARD32) stuff->groupNames,
4090 client->swapped, &bad);
4091 if (!tmp) {
4092 client->errorValue = bad;
4093 return BadAtom;
4094 }
4095 }
4096 if (stuff->which & XkbKeyNamesMask) {
4097 if (stuff->firstKey < (unsigned) xkb->min_key_code) {
4098 client->errorValue = _XkbErrCode3(0x0b, xkb->min_key_code,
4099 stuff->firstKey);
4100 return BadValue;
4101 }
4102 if (((unsigned) (stuff->firstKey + stuff->nKeys - 1) >
4103 xkb->max_key_code) || (stuff->nKeys < 1)) {
4104 client->errorValue =
4105 _XkbErrCode4(0x0c, xkb->max_key_code, stuff->firstKey,
4106 stuff->nKeys);
4107 return BadValue;
4108 }
4109 tmp += stuff->nKeys;
4110 }
4111 if ((stuff->which & XkbKeyAliasesMask) && (stuff->nKeyAliases > 0)) {
4112 tmp += stuff->nKeyAliases * 2;
4113 }
4114 if (stuff->which & XkbRGNamesMask) {
4115 if (stuff->nRadioGroups < 1) {
4116 client->errorValue = _XkbErrCode2(0x0d, stuff->nRadioGroups);
4117 return BadValue;
4118 }
4119 tmp = _XkbCheckAtoms(tmp, stuff->nRadioGroups, client->swapped, &bad);
4120 if (!tmp) {
4121 client->errorValue = bad;
4122 return BadAtom;
4123 }
4124 }
4125 if ((tmp - ((CARD32 *) stuff)) != stuff->length) {
4126 client->errorValue = stuff->length;
4127 return BadLength;
4128 }
4129
4130 return Success;
4131}
4132
4133static int
4134_XkbSetNames(ClientPtr client, DeviceIntPtr dev, xkbSetNamesReq * stuff)
4135{
4136 XkbDescRec *xkb;
4137 XkbNamesRec *names;
4138 CARD32 *tmp;
4139 xkbNamesNotify nn;
4140
4141 tmp = (CARD32 *) &stuff[1];
4142 xkb = dev->key->xkbInfo->desc;
4143 names = xkb->names;
4144
4145 if (XkbAllocNames(xkb, stuff->which, stuff->nRadioGroups,
4146 stuff->nKeyAliases) != Success) {
4147 return BadAlloc;
4148 }
4149
4150 memset(&nn, 0, sizeof(xkbNamesNotify));
4151 nn.changed = stuff->which;
4152 tmp = (CARD32 *) &stuff[1];
4153 if (stuff->which & XkbKeycodesNameMask)
4154 names->keycodes = *tmp++;
4155 if (stuff->which & XkbGeometryNameMask)
4156 names->geometry = *tmp++;
4157 if (stuff->which & XkbSymbolsNameMask)
4158 names->symbols = *tmp++;
4159 if (stuff->which & XkbPhysSymbolsNameMask)
4160 names->phys_symbols = *tmp++;
4161 if (stuff->which & XkbTypesNameMask)
4162 names->types = *tmp++;
4163 if (stuff->which & XkbCompatNameMask)
4164 names->compat = *tmp++;
4165 if ((stuff->which & XkbKeyTypeNamesMask) && (stuff->nTypes > 0)) {
4166 register unsigned i;
4167 register XkbKeyTypePtr type;
4168
4169 type = &xkb->map->types[stuff->firstType];
4170 for (i = 0; i < stuff->nTypes; i++, type++) {
4171 type->name = *tmp++;
4172 }
4173 nn.firstType = stuff->firstType;
4174 nn.nTypes = stuff->nTypes;
4175 }
4176 if (stuff->which & XkbKTLevelNamesMask) {
4177 register XkbKeyTypePtr type;
4178 register unsigned i;
4179 CARD8 *width;
4180
4181 width = (CARD8 *) tmp;
4182 tmp = (CARD32 *) (((char *) tmp) + XkbPaddedSize(stuff->nKTLevels));
4183 type = &xkb->map->types[stuff->firstKTLevel];
4184 for (i = 0; i < stuff->nKTLevels; i++, type++) {
4185 if (width[i] > 0) {
4186 if (type->level_names) {
4187 register unsigned n;
4188
4189 for (n = 0; n < width[i]; n++) {
4190 type->level_names[n] = tmp[n];
4191 }
4192 }
4193 tmp += width[i];
4194 }
4195 }
4196 nn.firstLevelName = 0;
4197 nn.nLevelNames = stuff->nTypes;
4198 }
4199 if (stuff->which & XkbIndicatorNamesMask) {
4200 tmp = _XkbCopyMaskedAtoms(tmp, names->indicators, XkbNumIndicators,
4201 stuff->indicators);
4202 nn.changedIndicators = stuff->indicators;
4203 }
4204 if (stuff->which & XkbVirtualModNamesMask) {
4205 tmp = _XkbCopyMaskedAtoms(tmp, names->vmods, XkbNumVirtualMods,
4206 stuff->virtualMods);
4207 nn.changedVirtualMods = stuff->virtualMods;
4208 }
4209 if (stuff->which & XkbGroupNamesMask) {
4210 tmp = _XkbCopyMaskedAtoms(tmp, names->groups, XkbNumKbdGroups,
4211 stuff->groupNames);
4212 nn.changedVirtualMods = stuff->groupNames;
4213 }
4214 if (stuff->which & XkbKeyNamesMask) {
4215 memcpy((char *) &names->keys[stuff->firstKey], (char *) tmp,
4216 stuff->nKeys * XkbKeyNameLength);
4217 tmp += stuff->nKeys;
4218 nn.firstKey = stuff->firstKey;
4219 nn.nKeys = stuff->nKeys;
4220 }
4221 if (stuff->which & XkbKeyAliasesMask) {
4222 if (stuff->nKeyAliases > 0) {
4223 register int na = stuff->nKeyAliases;
4224
4225 if (XkbAllocNames(xkb, XkbKeyAliasesMask, 0, na) != Success)
4226 return BadAlloc;
4227 memcpy((char *) names->key_aliases, (char *) tmp,
4228 stuff->nKeyAliases * sizeof(XkbKeyAliasRec));
4229 tmp += stuff->nKeyAliases * 2;
4230 }
4231 else if (names->key_aliases != NULL) {
4232 free(names->key_aliases);
4233 names->key_aliases = NULL;
4234 names->num_key_aliases = 0;
4235 }
4236 nn.nAliases = names->num_key_aliases;
4237 }
4238 if (stuff->which & XkbRGNamesMask) {
4239 if (stuff->nRadioGroups > 0) {
4240 register unsigned i, nrg;
4241
4242 nrg = stuff->nRadioGroups;
4243 if (XkbAllocNames(xkb, XkbRGNamesMask, nrg, 0) != Success)
4244 return BadAlloc;
4245
4246 for (i = 0; i < stuff->nRadioGroups; i++) {
4247 names->radio_groups[i] = tmp[i];
4248 }
4249 tmp += stuff->nRadioGroups;
4250 }
4251 else if (names->radio_groups) {
4252 free(names->radio_groups);
4253 names->radio_groups = NULL;
4254 names->num_rg = 0;
4255 }
4256 nn.nRadioGroups = names->num_rg;
4257 }
4258 if (nn.changed) {
4259 Bool needExtEvent;
4260
4261 needExtEvent = (nn.changed & XkbIndicatorNamesMask) != 0;
4262 XkbSendNamesNotify(dev, &nn);
4263 if (needExtEvent) {
4264 XkbSrvLedInfoPtr sli;
4265 xkbExtensionDeviceNotify edev;
4266 register int i;
4267 register unsigned bit;
4268
4269 sli = XkbFindSrvLedInfo(dev, XkbDfltXIClass, XkbDfltXIId,
4270 XkbXI_IndicatorsMask);
4271 sli->namesPresent = 0;
4272 for (i = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) {
4273 if (names->indicators[i] != None)
4274 sli->namesPresent |= bit;
4275 }
4276 memset(&edev, 0, sizeof(xkbExtensionDeviceNotify));
4277 edev.reason = XkbXI_IndicatorNamesMask;
4278 edev.ledClass = KbdFeedbackClass;
4279 edev.ledID = dev->kbdfeed->ctrl.id;
4280 edev.ledsDefined = sli->namesPresent | sli->mapsPresent;
4281 edev.ledState = sli->effectiveState;
4282 edev.firstBtn = 0;
4283 edev.nBtns = 0;
4284 edev.supported = XkbXI_AllFeaturesMask;
4285 edev.unsupported = 0;
4286 XkbSendExtensionDeviceNotify(dev, client, &edev);
4287 }
4288 }
4289 return Success;
4290}
4291
4292int
4293ProcXkbSetNames(ClientPtr client)
4294{
4295 DeviceIntPtr dev;
4296 CARD32 *tmp;
4297 Atom bad;
4298 int rc;
4299
4300 REQUEST(xkbSetNamesReq);
4301 REQUEST_AT_LEAST_SIZE(xkbSetNamesReq);
4302
4303 if (!(client->xkbClientFlags & _XkbClientInitialized))
4304 return BadAccess;
4305
4306 CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess);
4307 CHK_MASK_LEGAL(0x01, stuff->which, XkbAllNamesMask);
4308
4309 /* check device-independent stuff */
4310 tmp = (CARD32 *) &stuff[1];
4311
4312 if (stuff->which & XkbKeycodesNameMask) {
4313 tmp = _XkbCheckAtoms(tmp, 1, client->swapped, &bad);
4314 if (!tmp) {
4315 client->errorValue = bad;
4316 return BadAtom;
4317 }
4318 }
4319 if (stuff->which & XkbGeometryNameMask) {
4320 tmp = _XkbCheckAtoms(tmp, 1, client->swapped, &bad);
4321 if (!tmp) {
4322 client->errorValue = bad;
4323 return BadAtom;
4324 }
4325 }
4326 if (stuff->which & XkbSymbolsNameMask) {
4327 tmp = _XkbCheckAtoms(tmp, 1, client->swapped, &bad);
4328 if (!tmp) {
4329 client->errorValue = bad;
4330 return BadAtom;
4331 }
4332 }
4333 if (stuff->which & XkbPhysSymbolsNameMask) {
4334 tmp = _XkbCheckAtoms(tmp, 1, client->swapped, &bad);
4335 if (!tmp) {
4336 client->errorValue = bad;
4337 return BadAtom;
4338 }
4339 }
4340 if (stuff->which & XkbTypesNameMask) {
4341 tmp = _XkbCheckAtoms(tmp, 1, client->swapped, &bad);
4342 if (!tmp) {
4343 client->errorValue = bad;
4344 return BadAtom;
4345 }
4346 }
4347 if (stuff->which & XkbCompatNameMask) {
4348 tmp = _XkbCheckAtoms(tmp, 1, client->swapped, &bad);
4349 if (!tmp) {
4350 client->errorValue = bad;
4351 return BadAtom;
4352 }
4353 }
4354
4355 /* start of device-dependent tests */
4356 rc = _XkbSetNamesCheck(client, dev, stuff, tmp);
4357 if (rc != Success)
4358 return rc;
4359
4360 if (stuff->deviceSpec == XkbUseCoreKbd) {
4361 DeviceIntPtr other;
4362
4363 for (other = inputInfo.devices; other; other = other->next) {
4364 if ((other != dev) && other->key && !IsMaster(other) &&
4365 GetMaster(other, MASTER_KEYBOARD) == dev) {
4366
4367 rc = XaceHook(XACE_DEVICE_ACCESS, client, other,
4368 DixManageAccess);
4369 if (rc == Success) {
4370 rc = _XkbSetNamesCheck(client, other, stuff, tmp);
4371 if (rc != Success)
4372 return rc;
4373 }
4374 }
4375 }
4376 }
4377
4378 /* everything is okay -- update names */
4379
4380 rc = _XkbSetNames(client, dev, stuff);
4381 if (rc != Success)
4382 return rc;
4383
4384 if (stuff->deviceSpec == XkbUseCoreKbd) {
4385 DeviceIntPtr other;
4386
4387 for (other = inputInfo.devices; other; other = other->next) {
4388 if ((other != dev) && other->key && !IsMaster(other) &&
4389 GetMaster(other, MASTER_KEYBOARD) == dev) {
4390
4391 rc = XaceHook(XACE_DEVICE_ACCESS, client, other,
4392 DixManageAccess);
4393 if (rc == Success)
4394 _XkbSetNames(client, other, stuff);
4395 }
4396 }
4397 }
4398
4399 /* everything is okay -- update names */
4400
4401 return Success;
4402}
4403
4404/***====================================================================***/
4405
4406#include "xkbgeom.h"
4407
4408#define XkbSizeCountedString(s) ((s)?((((2+strlen(s))+3)/4)*4):4)
4409
4410/**
4411 * Write the zero-terminated string str into wire as a pascal string with a
4412 * 16-bit length field prefixed before the actual string.
4413 *
4414 * @param wire The destination array, usually the wire struct
4415 * @param str The source string as zero-terminated C string
4416 * @param swap If TRUE, the length field is swapped.
4417 *
4418 * @return The input string in the format <string length><string> with a
4419 * (swapped) 16 bit string length, non-zero terminated.
4420 */
4421static char *
4422XkbWriteCountedString(char *wire, char *str, Bool swap)
4423{
4424 CARD16 len, *pLen, paddedLen;
4425
4426 if (!str)
4427 return wire;
4428
4429 len = strlen(str);
4430 pLen = (CARD16 *) wire;
4431 *pLen = len;
4432 if (swap) {
4433 swaps(pLen);
4434 }
4435 paddedLen = pad_to_int32(sizeof(len) + len) - sizeof(len);
4436 strncpy(&wire[sizeof(len)], str, paddedLen);
4437 wire += sizeof(len) + paddedLen;
4438 return wire;
4439}
4440
4441static int
4442XkbSizeGeomProperties(XkbGeometryPtr geom)
4443{
4444 register int i, size;
4445 XkbPropertyPtr prop;
4446
4447 for (size = i = 0, prop = geom->properties; i < geom->num_properties;
4448 i++, prop++) {
4449 size += XkbSizeCountedString(prop->name);
4450 size += XkbSizeCountedString(prop->value);
4451 }
4452 return size;
4453}
4454
4455static char *
4456XkbWriteGeomProperties(char *wire, XkbGeometryPtr geom, Bool swap)
4457{
4458 register int i;
4459 register XkbPropertyPtr prop;
4460
4461 for (i = 0, prop = geom->properties; i < geom->num_properties; i++, prop++) {
4462 wire = XkbWriteCountedString(wire, prop->name, swap);
4463 wire = XkbWriteCountedString(wire, prop->value, swap);
4464 }
4465 return wire;
4466}
4467
4468static int
4469XkbSizeGeomKeyAliases(XkbGeometryPtr geom)
4470{
4471 return geom->num_key_aliases * (2 * XkbKeyNameLength);
4472}
4473
4474static char *
4475XkbWriteGeomKeyAliases(char *wire, XkbGeometryPtr geom, Bool swap)
4476{
4477 register int sz;
4478
4479 sz = geom->num_key_aliases * (XkbKeyNameLength * 2);
4480 if (sz > 0) {
4481 memcpy(wire, (char *) geom->key_aliases, sz);
4482 wire += sz;
4483 }
4484 return wire;
4485}
4486
4487static int
4488XkbSizeGeomColors(XkbGeometryPtr geom)
4489{
4490 register int i, size;
4491 register XkbColorPtr color;
4492
4493 for (i = size = 0, color = geom->colors; i < geom->num_colors; i++, color++) {
4494 size += XkbSizeCountedString(color->spec);
4495 }
4496 return size;
4497}
4498
4499static char *
4500XkbWriteGeomColors(char *wire, XkbGeometryPtr geom, Bool swap)
4501{
4502 register int i;
4503 register XkbColorPtr color;
4504
4505 for (i = 0, color = geom->colors; i < geom->num_colors; i++, color++) {
4506 wire = XkbWriteCountedString(wire, color->spec, swap);
4507 }
4508 return wire;
4509}
4510
4511static int
4512XkbSizeGeomShapes(XkbGeometryPtr geom)
4513{
4514 register int i, size;
4515 register XkbShapePtr shape;
4516
4517 for (i = size = 0, shape = geom->shapes; i < geom->num_shapes; i++, shape++) {
4518 register int n;
4519 register XkbOutlinePtr ol;
4520
4521 size += SIZEOF(xkbShapeWireDesc);
4522 for (n = 0, ol = shape->outlines; n < shape->num_outlines; n++, ol++) {
4523 size += SIZEOF(xkbOutlineWireDesc);
4524 size += ol->num_points * SIZEOF(xkbPointWireDesc);
4525 }
4526 }
4527 return size;
4528}
4529
4530static char *
4531XkbWriteGeomShapes(char *wire, XkbGeometryPtr geom, Bool swap)
4532{
4533 int i;
4534 XkbShapePtr shape;
4535 xkbShapeWireDesc *shapeWire;
4536
4537 for (i = 0, shape = geom->shapes; i < geom->num_shapes; i++, shape++) {
4538 register int o;
4539 XkbOutlinePtr ol;
4540 xkbOutlineWireDesc *olWire;
4541
4542 shapeWire = (xkbShapeWireDesc *) wire;
4543 shapeWire->name = shape->name;
4544 shapeWire->nOutlines = shape->num_outlines;
4545 if (shape->primary != NULL)
4546 shapeWire->primaryNdx = XkbOutlineIndex(shape, shape->primary);
4547 else
4548 shapeWire->primaryNdx = XkbNoShape;
4549 if (shape->approx != NULL)
4550 shapeWire->approxNdx = XkbOutlineIndex(shape, shape->approx);
4551 else
4552 shapeWire->approxNdx = XkbNoShape;
4553 shapeWire->pad = 0;
4554 if (swap) {
4555 swapl(&shapeWire->name);
4556 }
4557 wire = (char *) &shapeWire[1];
4558 for (o = 0, ol = shape->outlines; o < shape->num_outlines; o++, ol++) {
4559 register int p;
4560 XkbPointPtr pt;
4561 xkbPointWireDesc *ptWire;
4562
4563 olWire = (xkbOutlineWireDesc *) wire;
4564 olWire->nPoints = ol->num_points;
4565 olWire->cornerRadius = ol->corner_radius;
4566 olWire->pad = 0;
4567 wire = (char *) &olWire[1];
4568 ptWire = (xkbPointWireDesc *) wire;
4569 for (p = 0, pt = ol->points; p < ol->num_points; p++, pt++) {
4570 ptWire[p].x = pt->x;
4571 ptWire[p].y = pt->y;
4572 if (swap) {
4573 swaps(&ptWire[p].x);
4574 swaps(&ptWire[p].y);
4575 }
4576 }
4577 wire = (char *) &ptWire[ol->num_points];
4578 }
4579 }
4580 return wire;
4581}
4582
4583static int
4584XkbSizeGeomDoodads(int num_doodads, XkbDoodadPtr doodad)
4585{
4586 register int i, size;
4587
4588 for (i = size = 0; i < num_doodads; i++, doodad++) {
4589 size += SIZEOF(xkbAnyDoodadWireDesc);
4590 if (doodad->any.type == XkbTextDoodad) {
4591 size += XkbSizeCountedString(doodad->text.text);
4592 size += XkbSizeCountedString(doodad->text.font);
4593 }
4594 else if (doodad->any.type == XkbLogoDoodad) {
4595 size += XkbSizeCountedString(doodad->logo.logo_name);
4596 }
4597 }
4598 return size;
4599}
4600
4601static char *
4602XkbWriteGeomDoodads(char *wire, int num_doodads, XkbDoodadPtr doodad, Bool swap)
4603{
4604 register int i;
4605 xkbDoodadWireDesc *doodadWire;
4606
4607 for (i = 0; i < num_doodads; i++, doodad++) {
4608 doodadWire = (xkbDoodadWireDesc *) wire;
4609 wire = (char *) &doodadWire[1];
4610 memset(doodadWire, 0, SIZEOF(xkbDoodadWireDesc));
4611 doodadWire->any.name = doodad->any.name;
4612 doodadWire->any.type = doodad->any.type;
4613 doodadWire->any.priority = doodad->any.priority;
4614 doodadWire->any.top = doodad->any.top;
4615 doodadWire->any.left = doodad->any.left;
4616 if (swap) {
4617 swapl(&doodadWire->any.name);
4618 swaps(&doodadWire->any.top);
4619 swaps(&doodadWire->any.left);
4620 }
4621 switch (doodad->any.type) {
4622 case XkbOutlineDoodad:
4623 case XkbSolidDoodad:
4624 doodadWire->shape.angle = doodad->shape.angle;
4625 doodadWire->shape.colorNdx = doodad->shape.color_ndx;
4626 doodadWire->shape.shapeNdx = doodad->shape.shape_ndx;
4627 if (swap) {
4628 swaps(&doodadWire->shape.angle);
4629 }
4630 break;
4631 case XkbTextDoodad:
4632 doodadWire->text.angle = doodad->text.angle;
4633 doodadWire->text.width = doodad->text.width;
4634 doodadWire->text.height = doodad->text.height;
4635 doodadWire->text.colorNdx = doodad->text.color_ndx;
4636 if (swap) {
4637 swaps(&doodadWire->text.angle);
4638 swaps(&doodadWire->text.width);
4639 swaps(&doodadWire->text.height);
4640 }
4641 wire = XkbWriteCountedString(wire, doodad->text.text, swap);
4642 wire = XkbWriteCountedString(wire, doodad->text.font, swap);
4643 break;
4644 case XkbIndicatorDoodad:
4645 doodadWire->indicator.shapeNdx = doodad->indicator.shape_ndx;
4646 doodadWire->indicator.onColorNdx = doodad->indicator.on_color_ndx;
4647 doodadWire->indicator.offColorNdx = doodad->indicator.off_color_ndx;
4648 break;
4649 case XkbLogoDoodad:
4650 doodadWire->logo.angle = doodad->logo.angle;
4651 doodadWire->logo.colorNdx = doodad->logo.color_ndx;
4652 doodadWire->logo.shapeNdx = doodad->logo.shape_ndx;
4653 wire = XkbWriteCountedString(wire, doodad->logo.logo_name, swap);
4654 break;
4655 default:
4656 ErrorF("[xkb] Unknown doodad type %d in XkbWriteGeomDoodads\n",
4657 doodad->any.type);
4658 ErrorF("[xkb] Ignored\n");
4659 break;
4660 }
4661 }
4662 return wire;
4663}
4664
4665static char *
4666XkbWriteGeomOverlay(char *wire, XkbOverlayPtr ol, Bool swap)
4667{
4668 register int r;
4669 XkbOverlayRowPtr row;
4670 xkbOverlayWireDesc *olWire;
4671
4672 olWire = (xkbOverlayWireDesc *) wire;
4673 olWire->name = ol->name;
4674 olWire->nRows = ol->num_rows;
4675 olWire->pad1 = 0;
4676 olWire->pad2 = 0;
4677 if (swap) {
4678 swapl(&olWire->name);
4679 }
4680 wire = (char *) &olWire[1];
4681 for (r = 0, row = ol->rows; r < ol->num_rows; r++, row++) {
4682 unsigned int k;
4683 XkbOverlayKeyPtr key;
4684 xkbOverlayRowWireDesc *rowWire;
4685
4686 rowWire = (xkbOverlayRowWireDesc *) wire;
4687 rowWire->rowUnder = row->row_under;
4688 rowWire->nKeys = row->num_keys;
4689 rowWire->pad1 = 0;
4690 wire = (char *) &rowWire[1];
4691 for (k = 0, key = row->keys; k < row->num_keys; k++, key++) {
4692 xkbOverlayKeyWireDesc *keyWire;
4693
4694 keyWire = (xkbOverlayKeyWireDesc *) wire;
4695 memcpy(keyWire->over, key->over.name, XkbKeyNameLength);
4696 memcpy(keyWire->under, key->under.name, XkbKeyNameLength);
4697 wire = (char *) &keyWire[1];
4698 }
4699 }
4700 return wire;
4701}
4702
4703static int
4704XkbSizeGeomSections(XkbGeometryPtr geom)
4705{
4706 register int i, size;
4707 XkbSectionPtr section;
4708
4709 for (i = size = 0, section = geom->sections; i < geom->num_sections;
4710 i++, section++) {
4711 size += SIZEOF(xkbSectionWireDesc);
4712 if (section->rows) {
4713 int r;
4714 XkbRowPtr row;
4715
4716 for (r = 0, row = section->rows; r < section->num_rows; row++, r++) {
4717 size += SIZEOF(xkbRowWireDesc);
4718 size += row->num_keys * SIZEOF(xkbKeyWireDesc);
4719 }
4720 }
4721 if (section->doodads)
4722 size += XkbSizeGeomDoodads(section->num_doodads, section->doodads);
4723 if (section->overlays) {
4724 int o;
4725 XkbOverlayPtr ol;
4726
4727 for (o = 0, ol = section->overlays; o < section->num_overlays;
4728 o++, ol++) {
4729 int r;
4730 XkbOverlayRowPtr row;
4731
4732 size += SIZEOF(xkbOverlayWireDesc);
4733 for (r = 0, row = ol->rows; r < ol->num_rows; r++, row++) {
4734 size += SIZEOF(xkbOverlayRowWireDesc);
4735 size += row->num_keys * SIZEOF(xkbOverlayKeyWireDesc);
4736 }
4737 }
4738 }
4739 }
4740 return size;
4741}
4742
4743static char *
4744XkbWriteGeomSections(char *wire, XkbGeometryPtr geom, Bool swap)
4745{
4746 register int i;
4747 XkbSectionPtr section;
4748 xkbSectionWireDesc *sectionWire;
4749
4750 for (i = 0, section = geom->sections; i < geom->num_sections;
4751 i++, section++) {
4752 sectionWire = (xkbSectionWireDesc *) wire;
4753 sectionWire->name = section->name;
4754 sectionWire->top = section->top;
4755 sectionWire->left = section->left;
4756 sectionWire->width = section->width;
4757 sectionWire->height = section->height;
4758 sectionWire->angle = section->angle;
4759 sectionWire->priority = section->priority;
4760 sectionWire->nRows = section->num_rows;
4761 sectionWire->nDoodads = section->num_doodads;
4762 sectionWire->nOverlays = section->num_overlays;
4763 sectionWire->pad = 0;
4764 if (swap) {
4765 swapl(&sectionWire->name);
4766 swaps(&sectionWire->top);
4767 swaps(&sectionWire->left);
4768 swaps(&sectionWire->width);
4769 swaps(&sectionWire->height);
4770 swaps(&sectionWire->angle);
4771 }
4772 wire = (char *) &sectionWire[1];
4773 if (section->rows) {
4774 int r;
4775 XkbRowPtr row;
4776 xkbRowWireDesc *rowWire;
4777
4778 for (r = 0, row = section->rows; r < section->num_rows; r++, row++) {
4779 rowWire = (xkbRowWireDesc *) wire;
4780 rowWire->top = row->top;
4781 rowWire->left = row->left;
4782 rowWire->nKeys = row->num_keys;
4783 rowWire->vertical = row->vertical;
4784 rowWire->pad = 0;
4785 if (swap) {
4786 swaps(&rowWire->top);
4787 swaps(&rowWire->left);
4788 }
4789 wire = (char *) &rowWire[1];
4790 if (row->keys) {
4791 int k;
4792 XkbKeyPtr key;
4793 xkbKeyWireDesc *keyWire;
4794
4795 keyWire = (xkbKeyWireDesc *) wire;
4796 for (k = 0, key = row->keys; k < row->num_keys; k++, key++) {
4797 memcpy(keyWire[k].name, key->name.name,
4798 XkbKeyNameLength);
4799 keyWire[k].gap = key->gap;
4800 keyWire[k].shapeNdx = key->shape_ndx;
4801 keyWire[k].colorNdx = key->color_ndx;
4802 if (swap) {
4803 swaps(&keyWire[k].gap);
4804 }
4805 }
4806 wire = (char *) &keyWire[row->num_keys];
4807 }
4808 }
4809 }
4810 if (section->doodads) {
4811 wire = XkbWriteGeomDoodads(wire,
4812 section->num_doodads, section->doodads,
4813 swap);
4814 }
4815 if (section->overlays) {
4816 register int o;
4817
4818 for (o = 0; o < section->num_overlays; o++) {
4819 wire = XkbWriteGeomOverlay(wire, &section->overlays[o], swap);
4820 }
4821 }
4822 }
4823 return wire;
4824}
4825
4826static Status
4827XkbComputeGetGeometryReplySize(XkbGeometryPtr geom,
4828 xkbGetGeometryReply * rep, Atom name)
4829{
4830 int len;
4831
4832 if (geom != NULL) {
4833 len = XkbSizeCountedString(geom->label_font);
4834 len += XkbSizeGeomProperties(geom);
4835 len += XkbSizeGeomColors(geom);
4836 len += XkbSizeGeomShapes(geom);
4837 len += XkbSizeGeomSections(geom);
4838 len += XkbSizeGeomDoodads(geom->num_doodads, geom->doodads);
4839 len += XkbSizeGeomKeyAliases(geom);
4840 rep->length = len / 4;
4841 rep->found = TRUE;
4842 rep->name = geom->name;
4843 rep->widthMM = geom->width_mm;
4844 rep->heightMM = geom->height_mm;
4845 rep->nProperties = geom->num_properties;
4846 rep->nColors = geom->num_colors;
4847 rep->nShapes = geom->num_shapes;
4848 rep->nSections = geom->num_sections;
4849 rep->nDoodads = geom->num_doodads;
4850 rep->nKeyAliases = geom->num_key_aliases;
4851 rep->baseColorNdx = XkbGeomColorIndex(geom, geom->base_color);
4852 rep->labelColorNdx = XkbGeomColorIndex(geom, geom->label_color);
4853 }
4854 else {
4855 rep->length = 0;
4856 rep->found = FALSE;
4857 rep->name = name;
4858 rep->widthMM = rep->heightMM = 0;
4859 rep->nProperties = rep->nColors = rep->nShapes = 0;
4860 rep->nSections = rep->nDoodads = 0;
4861 rep->nKeyAliases = 0;
4862 rep->labelColorNdx = rep->baseColorNdx = 0;
4863 }
4864 return Success;
4865}
4866
4867static int
4868XkbSendGeometry(ClientPtr client,
4869 XkbGeometryPtr geom, xkbGetGeometryReply * rep, Bool freeGeom)
4870{
4871 char *desc, *start;
4872 int len;
4873
4874 if (geom != NULL) {
4875 len = rep->length * 4;
4876 start = desc = malloc(len);
4877 if (!start)
4878 return BadAlloc;
4879 desc = XkbWriteCountedString(desc, geom->label_font, client->swapped);
4880 if (rep->nProperties > 0)
4881 desc = XkbWriteGeomProperties(desc, geom, client->swapped);
4882 if (rep->nColors > 0)
4883 desc = XkbWriteGeomColors(desc, geom, client->swapped);
4884 if (rep->nShapes > 0)
4885 desc = XkbWriteGeomShapes(desc, geom, client->swapped);
4886 if (rep->nSections > 0)
4887 desc = XkbWriteGeomSections(desc, geom, client->swapped);
4888 if (rep->nDoodads > 0)
4889 desc = XkbWriteGeomDoodads(desc, geom->num_doodads, geom->doodads,
4890 client->swapped);
4891 if (rep->nKeyAliases > 0)
4892 desc = XkbWriteGeomKeyAliases(desc, geom, client->swapped);
4893 if ((desc - start) != (len)) {
4894 ErrorF
4895 ("[xkb] BOGUS LENGTH in XkbSendGeometry, expected %d, got %ld\n",
4896 len, (unsigned long) (desc - start));
4897 }
4898 }
4899 else {
4900 len = 0;
4901 start = NULL;
4902 }
4903 if (client->swapped) {
4904 swaps(&rep->sequenceNumber);
4905 swapl(&rep->length);
4906 swapl(&rep->name);
4907 swaps(&rep->widthMM);
4908 swaps(&rep->heightMM);
4909 swaps(&rep->nProperties);
4910 swaps(&rep->nColors);
4911 swaps(&rep->nShapes);
4912 swaps(&rep->nSections);
4913 swaps(&rep->nDoodads);
4914 swaps(&rep->nKeyAliases);
4915 }
4916 WriteToClient(client, SIZEOF(xkbGetGeometryReply), rep);
4917 if (len > 0)
4918 WriteToClient(client, len, start);
4919 if (start != NULL)
4920 free((char *) start);
4921 if (freeGeom)
4922 XkbFreeGeometry(geom, XkbGeomAllMask, TRUE);
4923 return Success;
4924}
4925
4926int
4927ProcXkbGetGeometry(ClientPtr client)
4928{
4929 DeviceIntPtr dev;
4930 xkbGetGeometryReply rep;
4931 XkbGeometryPtr geom;
4932 Bool shouldFree;
4933 Status status;
4934
4935 REQUEST(xkbGetGeometryReq);
4936 REQUEST_SIZE_MATCH(xkbGetGeometryReq);
4937
4938 if (!(client->xkbClientFlags & _XkbClientInitialized))
4939 return BadAccess;
4940
4941 CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess);
4942 CHK_ATOM_OR_NONE(stuff->name);
4943
4944 geom = XkbLookupNamedGeometry(dev, stuff->name, &shouldFree);
4945 rep = (xkbGetGeometryReply) {
4946 .type = X_Reply,
4947 .deviceID = dev->id,
4948 .sequenceNumber = client->sequence,
4949 .length = 0
4950 };
4951 status = XkbComputeGetGeometryReplySize(geom, &rep, stuff->name);
4952 if (status != Success)
4953 return status;
4954 else
4955 return XkbSendGeometry(client, geom, &rep, shouldFree);
4956}
4957
4958/***====================================================================***/
4959
4960static char *
4961_GetCountedString(char **wire_inout, Bool swap)
4962{
4963 char *wire, *str;
4964 CARD16 len, *plen;
4965
4966 wire = *wire_inout;
4967 plen = (CARD16 *) wire;
4968 if (swap) {
4969 swaps(plen);
4970 }
4971 len = *plen;
4972 str = malloc(len + 1);
4973 if (str) {
4974 memcpy(str, &wire[2], len);
4975 str[len] = '\0';
4976 }
4977 wire += XkbPaddedSize(len + 2);
4978 *wire_inout = wire;
4979 return str;
4980}
4981
4982static Status
4983_CheckSetDoodad(char **wire_inout,
4984 XkbGeometryPtr geom, XkbSectionPtr section, ClientPtr client)
4985{
4986 char *wire;
4987 xkbDoodadWireDesc *dWire;
4988 XkbDoodadPtr doodad;
4989
4990 dWire = (xkbDoodadWireDesc *) (*wire_inout);
4991 wire = (char *) &dWire[1];
4992 if (client->swapped) {
4993 swapl(&dWire->any.name);
4994 swaps(&dWire->any.top);
4995 swaps(&dWire->any.left);
4996 swaps(&dWire->any.angle);
4997 }
4998 CHK_ATOM_ONLY(dWire->any.name);
4999 doodad = XkbAddGeomDoodad(geom, section, dWire->any.name);
5000 if (!doodad)
5001 return BadAlloc;
5002 doodad->any.type = dWire->any.type;
5003 doodad->any.priority = dWire->any.priority;
5004 doodad->any.top = dWire->any.top;
5005 doodad->any.left = dWire->any.left;
5006 doodad->any.angle = dWire->any.angle;
5007 switch (doodad->any.type) {
5008 case XkbOutlineDoodad:
5009 case XkbSolidDoodad:
5010 if (dWire->shape.colorNdx >= geom->num_colors) {
5011 client->errorValue = _XkbErrCode3(0x40, geom->num_colors,
5012 dWire->shape.colorNdx);
5013 return BadMatch;
5014 }
5015 if (dWire->shape.shapeNdx >= geom->num_shapes) {
5016 client->errorValue = _XkbErrCode3(0x41, geom->num_shapes,
5017 dWire->shape.shapeNdx);
5018 return BadMatch;
5019 }
5020 doodad->shape.color_ndx = dWire->shape.colorNdx;
5021 doodad->shape.shape_ndx = dWire->shape.shapeNdx;
5022 break;
5023 case XkbTextDoodad:
5024 if (dWire->text.colorNdx >= geom->num_colors) {
5025 client->errorValue = _XkbErrCode3(0x42, geom->num_colors,
5026 dWire->text.colorNdx);
5027 return BadMatch;
5028 }
5029 if (client->swapped) {
5030 swaps(&dWire->text.width);
5031 swaps(&dWire->text.height);
5032 }
5033 doodad->text.width = dWire->text.width;
5034 doodad->text.height = dWire->text.height;
5035 doodad->text.color_ndx = dWire->text.colorNdx;
5036 doodad->text.text = _GetCountedString(&wire, client->swapped);
5037 doodad->text.font = _GetCountedString(&wire, client->swapped);
5038 break;
5039 case XkbIndicatorDoodad:
5040 if (dWire->indicator.onColorNdx >= geom->num_colors) {
5041 client->errorValue = _XkbErrCode3(0x43, geom->num_colors,
5042 dWire->indicator.onColorNdx);
5043 return BadMatch;
5044 }
5045 if (dWire->indicator.offColorNdx >= geom->num_colors) {
5046 client->errorValue = _XkbErrCode3(0x44, geom->num_colors,
5047 dWire->indicator.offColorNdx);
5048 return BadMatch;
5049 }
5050 if (dWire->indicator.shapeNdx >= geom->num_shapes) {
5051 client->errorValue = _XkbErrCode3(0x45, geom->num_shapes,
5052 dWire->indicator.shapeNdx);
5053 return BadMatch;
5054 }
5055 doodad->indicator.shape_ndx = dWire->indicator.shapeNdx;
5056 doodad->indicator.on_color_ndx = dWire->indicator.onColorNdx;
5057 doodad->indicator.off_color_ndx = dWire->indicator.offColorNdx;
5058 break;
5059 case XkbLogoDoodad:
5060 if (dWire->logo.colorNdx >= geom->num_colors) {
5061 client->errorValue = _XkbErrCode3(0x46, geom->num_colors,
5062 dWire->logo.colorNdx);
5063 return BadMatch;
5064 }
5065 if (dWire->logo.shapeNdx >= geom->num_shapes) {
5066 client->errorValue = _XkbErrCode3(0x47, geom->num_shapes,
5067 dWire->logo.shapeNdx);
5068 return BadMatch;
5069 }
5070 doodad->logo.color_ndx = dWire->logo.colorNdx;
5071 doodad->logo.shape_ndx = dWire->logo.shapeNdx;
5072 doodad->logo.logo_name = _GetCountedString(&wire, client->swapped);
5073 break;
5074 default:
5075 client->errorValue = _XkbErrCode2(0x4F, dWire->any.type);
5076 return BadValue;
5077 }
5078 *wire_inout = wire;
5079 return Success;
5080}
5081
5082static Status
5083_CheckSetOverlay(char **wire_inout,
5084 XkbGeometryPtr geom, XkbSectionPtr section, ClientPtr client)
5085{
5086 register int r;
5087 char *wire;
5088 XkbOverlayPtr ol;
5089 xkbOverlayWireDesc *olWire;
5090 xkbOverlayRowWireDesc *rWire;
5091
5092 wire = *wire_inout;
5093 olWire = (xkbOverlayWireDesc *) wire;
5094 if (client->swapped) {
5095 swapl(&olWire->name);
5096 }
5097 CHK_ATOM_ONLY(olWire->name);
5098 ol = XkbAddGeomOverlay(section, olWire->name, olWire->nRows);
5099 rWire = (xkbOverlayRowWireDesc *) &olWire[1];
5100 for (r = 0; r < olWire->nRows; r++) {
5101 register int k;
5102 xkbOverlayKeyWireDesc *kWire;
5103 XkbOverlayRowPtr row;
5104
5105 if (rWire->rowUnder > section->num_rows) {
5106 client->errorValue = _XkbErrCode4(0x20, r, section->num_rows,
5107 rWire->rowUnder);
5108 return BadMatch;
5109 }
5110 row = XkbAddGeomOverlayRow(ol, rWire->rowUnder, rWire->nKeys);
5111 kWire = (xkbOverlayKeyWireDesc *) &rWire[1];
5112 for (k = 0; k < rWire->nKeys; k++, kWire++) {
5113 if (XkbAddGeomOverlayKey(ol, row,
5114 (char *) kWire->over,
5115 (char *) kWire->under) == NULL) {
5116 client->errorValue = _XkbErrCode3(0x21, r, k);
5117 return BadMatch;
5118 }
5119 }
5120 rWire = (xkbOverlayRowWireDesc *) kWire;
5121 }
5122 olWire = (xkbOverlayWireDesc *) rWire;
5123 wire = (char *) olWire;
5124 *wire_inout = wire;
5125 return Success;
5126}
5127
5128static Status
5129_CheckSetSections(XkbGeometryPtr geom,
5130 xkbSetGeometryReq * req, char **wire_inout, ClientPtr client)
5131{
5132 Status status;
5133 register int s;
5134 char *wire;
5135 xkbSectionWireDesc *sWire;
5136 XkbSectionPtr section;
5137
5138 wire = *wire_inout;
5139 if (req->nSections < 1)
5140 return Success;
5141 sWire = (xkbSectionWireDesc *) wire;
5142 for (s = 0; s < req->nSections; s++) {
5143 register int r;
5144 xkbRowWireDesc *rWire;
5145
5146 if (client->swapped) {
5147 swapl(&sWire->name);
5148 swaps(&sWire->top);
5149 swaps(&sWire->left);
5150 swaps(&sWire->width);
5151 swaps(&sWire->height);
5152 swaps(&sWire->angle);
5153 }
5154 CHK_ATOM_ONLY(sWire->name);
5155 section = XkbAddGeomSection(geom, sWire->name, sWire->nRows,
5156 sWire->nDoodads, sWire->nOverlays);
5157 if (!section)
5158 return BadAlloc;
5159 section->priority = sWire->priority;
5160 section->top = sWire->top;
5161 section->left = sWire->left;
5162 section->width = sWire->width;
5163 section->height = sWire->height;
5164 section->angle = sWire->angle;
5165 rWire = (xkbRowWireDesc *) &sWire[1];
5166 for (r = 0; r < sWire->nRows; r++) {
5167 register int k;
5168 XkbRowPtr row;
5169 xkbKeyWireDesc *kWire;
5170
5171 if (client->swapped) {
5172 swaps(&rWire->top);
5173 swaps(&rWire->left);
5174 }
5175 row = XkbAddGeomRow(section, rWire->nKeys);
5176 if (!row)
5177 return BadAlloc;
5178 row->top = rWire->top;
5179 row->left = rWire->left;
5180 row->vertical = rWire->vertical;
5181 kWire = (xkbKeyWireDesc *) &rWire[1];
5182 for (k = 0; k < rWire->nKeys; k++) {
5183 XkbKeyPtr key;
5184
5185 key = XkbAddGeomKey(row);
5186 if (!key)
5187 return BadAlloc;
5188 memcpy(key->name.name, kWire[k].name, XkbKeyNameLength);
5189 key->gap = kWire[k].gap;
5190 key->shape_ndx = kWire[k].shapeNdx;
5191 key->color_ndx = kWire[k].colorNdx;
5192 if (key->shape_ndx >= geom->num_shapes) {
5193 client->errorValue = _XkbErrCode3(0x10, key->shape_ndx,
5194 geom->num_shapes);
5195 return BadMatch;
5196 }
5197 if (key->color_ndx >= geom->num_colors) {
5198 client->errorValue = _XkbErrCode3(0x11, key->color_ndx,
5199 geom->num_colors);
5200 return BadMatch;
5201 }
5202 }
5203 rWire = (xkbRowWireDesc *) &kWire[rWire->nKeys];
5204 }
5205 wire = (char *) rWire;
5206 if (sWire->nDoodads > 0) {
5207 register int d;
5208
5209 for (d = 0; d < sWire->nDoodads; d++) {
5210 status = _CheckSetDoodad(&wire, geom, section, client);
5211 if (status != Success)
5212 return status;
5213 }
5214 }
5215 if (sWire->nOverlays > 0) {
5216 register int o;
5217
5218 for (o = 0; o < sWire->nOverlays; o++) {
5219 status = _CheckSetOverlay(&wire, geom, section, client);
5220 if (status != Success)
5221 return status;
5222 }
5223 }
5224 sWire = (xkbSectionWireDesc *) wire;
5225 }
5226 wire = (char *) sWire;
5227 *wire_inout = wire;
5228 return Success;
5229}
5230
5231static Status
5232_CheckSetShapes(XkbGeometryPtr geom,
5233 xkbSetGeometryReq * req, char **wire_inout, ClientPtr client)
5234{
5235 register int i;
5236 char *wire;
5237
5238 wire = *wire_inout;
5239 if (req->nShapes < 1) {
5240 client->errorValue = _XkbErrCode2(0x06, req->nShapes);
5241 return BadValue;
5242 }
5243 else {
5244 xkbShapeWireDesc *shapeWire;
5245 XkbShapePtr shape;
5246 register int o;
5247
5248 shapeWire = (xkbShapeWireDesc *) wire;
5249 for (i = 0; i < req->nShapes; i++) {
5250 xkbOutlineWireDesc *olWire;
5251 XkbOutlinePtr ol;
5252
5253 shape =
5254 XkbAddGeomShape(geom, shapeWire->name, shapeWire->nOutlines);
5255 if (!shape)
5256 return BadAlloc;
5257 olWire = (xkbOutlineWireDesc *) (&shapeWire[1]);
5258 for (o = 0; o < shapeWire->nOutlines; o++) {
5259 register int p;
5260 XkbPointPtr pt;
5261 xkbPointWireDesc *ptWire;
5262
5263 ol = XkbAddGeomOutline(shape, olWire->nPoints);
5264 if (!ol)
5265 return BadAlloc;
5266 ol->corner_radius = olWire->cornerRadius;
5267 ptWire = (xkbPointWireDesc *) &olWire[1];
5268 for (p = 0, pt = ol->points; p < olWire->nPoints; p++, pt++) {
5269 pt->x = ptWire[p].x;
5270 pt->y = ptWire[p].y;
5271 if (client->swapped) {
5272 swaps(&pt->x);
5273 swaps(&pt->y);
5274 }
5275 }
5276 ol->num_points = olWire->nPoints;
5277 olWire = (xkbOutlineWireDesc *) (&ptWire[olWire->nPoints]);
5278 }
5279 if (shapeWire->primaryNdx != XkbNoShape)
5280 shape->primary = &shape->outlines[shapeWire->primaryNdx];
5281 if (shapeWire->approxNdx != XkbNoShape)
5282 shape->approx = &shape->outlines[shapeWire->approxNdx];
5283 shapeWire = (xkbShapeWireDesc *) olWire;
5284 }
5285 wire = (char *) shapeWire;
5286 }
5287 if (geom->num_shapes != req->nShapes) {
5288 client->errorValue = _XkbErrCode3(0x07, geom->num_shapes, req->nShapes);
5289 return BadMatch;
5290 }
5291
5292 *wire_inout = wire;
5293 return Success;
5294}
5295
5296static Status
5297_CheckSetGeom(XkbGeometryPtr geom, xkbSetGeometryReq * req, ClientPtr client)
5298{
5299 register int i;
5300 Status status;
5301 char *wire;
5302
5303 wire = (char *) &req[1];
5304 geom->label_font = _GetCountedString(&wire, client->swapped);
5305
5306 for (i = 0; i < req->nProperties; i++) {
5307 char *name, *val;
5308
5309 name = _GetCountedString(&wire, client->swapped);
5310 if (!name)
5311 return BadAlloc;
5312 val = _GetCountedString(&wire, client->swapped);
5313 if (!val) {
5314 free(name);
5315 return BadAlloc;
5316 }
5317 if (XkbAddGeomProperty(geom, name, val) == NULL) {
5318 free(name);
5319 free(val);
5320 return BadAlloc;
5321 }
5322 free(name);
5323 free(val);
5324 }
5325
5326 if (req->nColors < 2) {
5327 client->errorValue = _XkbErrCode3(0x01, 2, req->nColors);
5328 return BadValue;
5329 }
5330 if (req->baseColorNdx > req->nColors) {
5331 client->errorValue =
5332 _XkbErrCode3(0x03, req->nColors, req->baseColorNdx);
5333 return BadMatch;
5334 }
5335 if (req->labelColorNdx > req->nColors) {
5336 client->errorValue =
5337 _XkbErrCode3(0x03, req->nColors, req->labelColorNdx);
5338 return BadMatch;
5339 }
5340 if (req->labelColorNdx == req->baseColorNdx) {
5341 client->errorValue = _XkbErrCode3(0x04, req->baseColorNdx,
5342 req->labelColorNdx);
5343 return BadMatch;
5344 }
5345
5346 for (i = 0; i < req->nColors; i++) {
5347 char *name;
5348
5349 name = _GetCountedString(&wire, client->swapped);
5350 if (!name)
5351 return BadAlloc;
5352 if (!XkbAddGeomColor(geom, name, geom->num_colors)) {
5353 free(name);
5354 return BadAlloc;
5355 }
5356 free(name);
5357 }
5358 if (req->nColors != geom->num_colors) {
5359 client->errorValue = _XkbErrCode3(0x05, req->nColors, geom->num_colors);
5360 return BadMatch;
5361 }
5362 geom->label_color = &geom->colors[req->labelColorNdx];
5363 geom->base_color = &geom->colors[req->baseColorNdx];
5364
5365 if ((status = _CheckSetShapes(geom, req, &wire, client)) != Success)
5366 return status;
5367
5368 if ((status = _CheckSetSections(geom, req, &wire, client)) != Success)
5369 return status;
5370
5371 for (i = 0; i < req->nDoodads; i++) {
5372 status = _CheckSetDoodad(&wire, geom, NULL, client);
5373 if (status != Success)
5374 return status;
5375 }
5376
5377 for (i = 0; i < req->nKeyAliases; i++) {
5378 if (XkbAddGeomKeyAlias(geom, &wire[XkbKeyNameLength], wire) == NULL)
5379 return BadAlloc;
5380 wire += 2 * XkbKeyNameLength;
5381 }
5382 return Success;
5383}
5384
5385static int
5386_XkbSetGeometry(ClientPtr client, DeviceIntPtr dev, xkbSetGeometryReq * stuff)
5387{
5388 XkbDescPtr xkb;
5389 Bool new_name;
5390 xkbNewKeyboardNotify nkn;
5391 XkbGeometryPtr geom, old;
5392 XkbGeometrySizesRec sizes;
5393 Status status;
5394
5395 xkb = dev->key->xkbInfo->desc;
5396 old = xkb->geom;
5397 xkb->geom = NULL;
5398
5399 sizes.which = XkbGeomAllMask;
5400 sizes.num_properties = stuff->nProperties;
5401 sizes.num_colors = stuff->nColors;
5402 sizes.num_shapes = stuff->nShapes;
5403 sizes.num_sections = stuff->nSections;
5404 sizes.num_doodads = stuff->nDoodads;
5405 sizes.num_key_aliases = stuff->nKeyAliases;
5406 if ((status = XkbAllocGeometry(xkb, &sizes)) != Success) {
5407 xkb->geom = old;
5408 return status;
5409 }
5410 geom = xkb->geom;
5411 geom->name = stuff->name;
5412 geom->width_mm = stuff->widthMM;
5413 geom->height_mm = stuff->heightMM;
5414 if ((status = _CheckSetGeom(geom, stuff, client)) != Success) {
5415 XkbFreeGeometry(geom, XkbGeomAllMask, TRUE);
5416 xkb->geom = old;
5417 return status;
5418 }
5419 new_name = (xkb->names->geometry != geom->name);
5420 xkb->names->geometry = geom->name;
5421 if (old)
5422 XkbFreeGeometry(old, XkbGeomAllMask, TRUE);
5423 if (new_name) {
5424 xkbNamesNotify nn;
5425
5426 memset(&nn, 0, sizeof(xkbNamesNotify));
5427 nn.changed = XkbGeometryNameMask;
5428 XkbSendNamesNotify(dev, &nn);
5429 }
5430 nkn.deviceID = nkn.oldDeviceID = dev->id;
5431 nkn.minKeyCode = nkn.oldMinKeyCode = xkb->min_key_code;
5432 nkn.maxKeyCode = nkn.oldMaxKeyCode = xkb->max_key_code;
5433 nkn.requestMajor = XkbReqCode;
5434 nkn.requestMinor = X_kbSetGeometry;
5435 nkn.changed = XkbNKN_GeometryMask;
5436 XkbSendNewKeyboardNotify(dev, &nkn);
5437 return Success;
5438}
5439
5440int
5441ProcXkbSetGeometry(ClientPtr client)
5442{
5443 DeviceIntPtr dev;
5444 int rc;
5445
5446 REQUEST(xkbSetGeometryReq);
5447 REQUEST_AT_LEAST_SIZE(xkbSetGeometryReq);
5448
5449 if (!(client->xkbClientFlags & _XkbClientInitialized))
5450 return BadAccess;
5451
5452 CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess);
5453 CHK_ATOM_OR_NONE(stuff->name);
5454
5455 rc = _XkbSetGeometry(client, dev, stuff);
5456 if (rc != Success)
5457 return rc;
5458
5459 if (stuff->deviceSpec == XkbUseCoreKbd) {
5460 DeviceIntPtr other;
5461
5462 for (other = inputInfo.devices; other; other = other->next) {
5463 if ((other != dev) && other->key && !IsMaster(other) &&
5464 GetMaster(other, MASTER_KEYBOARD) == dev) {
5465 rc = XaceHook(XACE_DEVICE_ACCESS, client, other,
5466 DixManageAccess);
5467 if (rc == Success)
5468 _XkbSetGeometry(client, other, stuff);
5469 }
5470 }
5471 }
5472
5473 return Success;
5474}
5475
5476/***====================================================================***/
5477
5478int
5479ProcXkbPerClientFlags(ClientPtr client)
5480{
5481 DeviceIntPtr dev;
5482 xkbPerClientFlagsReply rep;
5483 XkbInterestPtr interest;
5484 Mask access_mode = DixGetAttrAccess | DixSetAttrAccess;
5485
5486 REQUEST(xkbPerClientFlagsReq);
5487 REQUEST_SIZE_MATCH(xkbPerClientFlagsReq);
5488
5489 if (!(client->xkbClientFlags & _XkbClientInitialized))
5490 return BadAccess;
5491
5492 CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, access_mode);
5493 CHK_MASK_LEGAL(0x01, stuff->change, XkbPCF_AllFlagsMask);
5494 CHK_MASK_MATCH(0x02, stuff->change, stuff->value);
5495
5496 interest = XkbFindClientResource((DevicePtr) dev, client);
5497 if (stuff->change) {
5498 client->xkbClientFlags &= ~stuff->change;
5499 client->xkbClientFlags |= stuff->value;
5500 }
5501 if (stuff->change & XkbPCF_AutoResetControlsMask) {
5502 Bool want;
5503
5504 want = stuff->value & XkbPCF_AutoResetControlsMask;
5505 if (interest && !want) {
5506 interest->autoCtrls = interest->autoCtrlValues = 0;
5507 }
5508 else if (want && (!interest)) {
5509 XID id = FakeClientID(client->index);
5510
5511 if (!AddResource(id, RT_XKBCLIENT, dev))
5512 return BadAlloc;
5513 interest = XkbAddClientResource((DevicePtr) dev, client, id);
5514 if (!interest)
5515 return BadAlloc;
5516 }
5517 if (interest && want) {
5518 register unsigned affect;
5519
5520 affect = stuff->ctrlsToChange;
5521
5522 CHK_MASK_LEGAL(0x03, affect, XkbAllBooleanCtrlsMask);
5523 CHK_MASK_MATCH(0x04, affect, stuff->autoCtrls);
5524 CHK_MASK_MATCH(0x05, stuff->autoCtrls, stuff->autoCtrlValues);
5525
5526 interest->autoCtrls &= ~affect;
5527 interest->autoCtrlValues &= ~affect;
5528 interest->autoCtrls |= stuff->autoCtrls & affect;
5529 interest->autoCtrlValues |= stuff->autoCtrlValues & affect;
5530 }
5531 }
5532
5533 rep = (xkbPerClientFlagsReply) {
5534 .type = X_Reply,
5535 .sequenceNumber = client->sequence,
5536 .length = 0,
5537 .supported = XkbPCF_AllFlagsMask,
5538 .value = client->xkbClientFlags & XkbPCF_AllFlagsMask,
5539 .autoCtrls = interest ? interest->autoCtrls : 0,
5540 .autoCtrlValues = interest ? interest->autoCtrlValues : 0,
5541 };
5542 if (client->swapped) {
5543 swaps(&rep.sequenceNumber);
5544 swapl(&rep.supported);
5545 swapl(&rep.value);
5546 swapl(&rep.autoCtrls);
5547 swapl(&rep.autoCtrlValues);
5548 }
5549 WriteToClient(client, SIZEOF(xkbPerClientFlagsReply), &rep);
5550 return Success;
5551}
5552
5553/***====================================================================***/
5554
5555/* all latin-1 alphanumerics, plus parens, minus, underscore, slash */
5556/* and wildcards */
5557static unsigned char componentSpecLegal[] = {
5558 0x00, 0x00, 0x00, 0x00, 0x00, 0xa7, 0xff, 0x87,
5559 0xfe, 0xff, 0xff, 0x87, 0xfe, 0xff, 0xff, 0x07,
5560 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5561 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0x7f, 0xff
5562};
5563
5564/* same as above but accepts percent, plus and bar too */
5565static unsigned char componentExprLegal[] = {
5566 0x00, 0x00, 0x00, 0x00, 0x20, 0xaf, 0xff, 0x87,
5567 0xfe, 0xff, 0xff, 0x87, 0xfe, 0xff, 0xff, 0x17,
5568 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5569 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0x7f, 0xff
5570};
5571
5572static char *
5573GetComponentSpec(unsigned char **pWire, Bool allowExpr, int *errRtrn)
5574{
5575 int len;
5576 register int i;
5577 unsigned char *wire, *str, *tmp, *legal;
5578
5579 if (allowExpr)
5580 legal = &componentExprLegal[0];
5581 else
5582 legal = &componentSpecLegal[0];
5583
5584 wire = *pWire;
5585 len = (*(unsigned char *) wire++);
5586 if (len > 0) {
5587 str = calloc(1, len + 1);
5588 if (str) {
5589 tmp = str;
5590 for (i = 0; i < len; i++) {
5591 if (legal[(*wire) / 8] & (1 << ((*wire) % 8)))
5592 *tmp++ = *wire++;
5593 else
5594 wire++;
5595 }
5596 if (tmp != str)
5597 *tmp++ = '\0';
5598 else {
5599 free(str);
5600 str = NULL;
5601 }
5602 }
5603 else {
5604 *errRtrn = BadAlloc;
5605 }
5606 }
5607 else {
5608 str = NULL;
5609 }
5610 *pWire = wire;
5611 return (char *) str;
5612}
5613
5614/***====================================================================***/
5615
5616int
5617ProcXkbListComponents(ClientPtr client)
5618{
5619 DeviceIntPtr dev;
5620 xkbListComponentsReply rep;
5621 unsigned len;
5622 unsigned char *str;
5623 uint8_t size;
5624 int i;
5625
5626 REQUEST(xkbListComponentsReq);
5627 REQUEST_AT_LEAST_SIZE(xkbListComponentsReq);
5628
5629 if (!(client->xkbClientFlags & _XkbClientInitialized))
5630 return BadAccess;
5631
5632 CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess);
5633
5634 /* The request is followed by six Pascal strings (i.e. size in characters
5635 * followed by a string pattern) describing what the client wants us to
5636 * list. We don't care, but might as well check they haven't got the
5637 * length wrong. */
5638 str = (unsigned char *) &stuff[1];
5639 for (i = 0; i < 6; i++) {
5640 size = *((uint8_t *)str);
5641 len = (str + size + 1) - ((unsigned char *) stuff);
5642 if ((XkbPaddedSize(len) / 4) > stuff->length)
5643 return BadLength;
5644 str += (size + 1);
5645 }
5646 if ((XkbPaddedSize(len) / 4) != stuff->length)
5647 return BadLength;
5648 rep = (xkbListComponentsReply) {
5649 .type = X_Reply,
5650 .deviceID = dev->id,
5651 .sequenceNumber = client->sequence,
5652 .length = 0,
5653 .nKeymaps = 0,
5654 .nKeycodes = 0,
5655 .nTypes = 0,
5656 .nCompatMaps = 0,
5657 .nSymbols = 0,
5658 .nGeometries = 0,
5659 .extra = 0
5660 };
5661 if (client->swapped) {
5662 swaps(&rep.sequenceNumber);
5663 swapl(&rep.length);
5664 swaps(&rep.nKeymaps);
5665 swaps(&rep.nKeycodes);
5666 swaps(&rep.nTypes);
5667 swaps(&rep.nCompatMaps);
5668 swaps(&rep.nSymbols);
5669 swaps(&rep.nGeometries);
5670 swaps(&rep.extra);
5671 }
5672 WriteToClient(client, SIZEOF(xkbListComponentsReply), &rep);
5673 return Success;
5674}
5675
5676/***====================================================================***/
5677
5678int
5679ProcXkbGetKbdByName(ClientPtr client)
5680{
5681 DeviceIntPtr dev;
5682 DeviceIntPtr tmpd;
5683 DeviceIntPtr master;
5684 xkbGetKbdByNameReply rep = { 0 };
5685 xkbGetMapReply mrep = { 0 };
5686 xkbGetCompatMapReply crep = { 0 };
5687 xkbGetIndicatorMapReply irep = { 0 };
5688 xkbGetNamesReply nrep = { 0 };
5689 xkbGetGeometryReply grep = { 0 };
5690 XkbComponentNamesRec names = { 0 };
5691 XkbDescPtr xkb, new;
5692 unsigned char *str;
5693 char mapFile[PATH_MAX];
5694 unsigned len;
5695 unsigned fwant, fneed, reported;
5696 int status;
5697 Bool geom_changed;
5698 XkbSrvLedInfoPtr old_sli;
5699 XkbSrvLedInfoPtr sli;
5700 Mask access_mode = DixGetAttrAccess | DixManageAccess;
5701
5702 REQUEST(xkbGetKbdByNameReq);
5703 REQUEST_AT_LEAST_SIZE(xkbGetKbdByNameReq);
5704
5705 if (!(client->xkbClientFlags & _XkbClientInitialized))
5706 return BadAccess;
5707
5708 CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, access_mode);
5709 master = GetMaster(dev, MASTER_KEYBOARD);
5710
5711 xkb = dev->key->xkbInfo->desc;
5712 status = Success;
5713 str = (unsigned char *) &stuff[1];
5714 if (GetComponentSpec(&str, TRUE, &status)) /* keymap, unsupported */
5715 return BadMatch;
5716 names.keycodes = GetComponentSpec(&str, TRUE, &status);
5717 names.types = GetComponentSpec(&str, TRUE, &status);
5718 names.compat = GetComponentSpec(&str, TRUE, &status);
5719 names.symbols = GetComponentSpec(&str, TRUE, &status);
5720 names.geometry = GetComponentSpec(&str, TRUE, &status);
5721 if (status != Success)
5722 return status;
5723 len = str - ((unsigned char *) stuff);
5724 if ((XkbPaddedSize(len) / 4) != stuff->length)
5725 return BadLength;
5726
5727 CHK_MASK_LEGAL(0x01, stuff->want, XkbGBN_AllComponentsMask);
5728 CHK_MASK_LEGAL(0x02, stuff->need, XkbGBN_AllComponentsMask);
5729
5730 if (stuff->load)
5731 fwant = XkbGBN_AllComponentsMask;
5732 else
5733 fwant = stuff->want | stuff->need;
5734 if ((!names.compat) &&
5735 (fwant & (XkbGBN_CompatMapMask | XkbGBN_IndicatorMapMask))) {
5736 names.compat = Xstrdup("%");
5737 }
5738 if ((!names.types) && (fwant & (XkbGBN_TypesMask))) {
5739 names.types = Xstrdup("%");
5740 }
5741 if ((!names.symbols) && (fwant & XkbGBN_SymbolsMask)) {
5742 names.symbols = Xstrdup("%");
5743 }
5744 geom_changed = ((names.geometry != NULL) &&
5745 (strcmp(names.geometry, "%") != 0));
5746 if ((!names.geometry) && (fwant & XkbGBN_GeometryMask)) {
5747 names.geometry = Xstrdup("%");
5748 geom_changed = FALSE;
5749 }
5750
5751 memset(mapFile, 0, PATH_MAX);
5752 rep.type = X_Reply;
5753 rep.deviceID = dev->id;
5754 rep.sequenceNumber = client->sequence;
5755 rep.length = 0;
5756 rep.minKeyCode = xkb->min_key_code;
5757 rep.maxKeyCode = xkb->max_key_code;
5758 rep.loaded = FALSE;
5759 fwant =
5760 XkbConvertGetByNameComponents(TRUE, stuff->want) | XkmVirtualModsMask;
5761 fneed = XkbConvertGetByNameComponents(TRUE, stuff->need);
5762 rep.reported = XkbConvertGetByNameComponents(FALSE, fwant | fneed);
5763 if (stuff->load) {
5764 fneed |= XkmKeymapRequired;
5765 fwant |= XkmKeymapLegal;
5766 }
5767 if ((fwant | fneed) & XkmSymbolsMask) {
5768 fneed |= XkmKeyNamesIndex | XkmTypesIndex;
5769 fwant |= XkmIndicatorsIndex;
5770 }
5771
5772 /* We pass dev in here so we can get the old names out if needed. */
5773 rep.found = XkbDDXLoadKeymapByNames(dev, &names, fwant, fneed, &new,
5774 mapFile, PATH_MAX);
5775 rep.newKeyboard = FALSE;
5776 rep.pad1 = rep.pad2 = rep.pad3 = rep.pad4 = 0;
5777
5778 stuff->want |= stuff->need;
5779 if (new == NULL)
5780 rep.reported = 0;
5781 else {
5782 if (stuff->load)
5783 rep.loaded = TRUE;
5784 if (stuff->load ||
5785 ((rep.reported & XkbGBN_SymbolsMask) && (new->compat))) {
5786 XkbChangesRec changes;
5787
5788 memset(&changes, 0, sizeof(changes));
5789 XkbUpdateDescActions(new,
5790 new->min_key_code, XkbNumKeys(new), &changes);
5791 }
5792
5793 if (new->map == NULL)
5794 rep.reported &= ~(XkbGBN_SymbolsMask | XkbGBN_TypesMask);
5795 else if (rep.reported & (XkbGBN_SymbolsMask | XkbGBN_TypesMask)) {
5796 mrep.type = X_Reply;
5797 mrep.deviceID = dev->id;
5798 mrep.sequenceNumber = client->sequence;
5799 mrep.length =
5800 ((SIZEOF(xkbGetMapReply) - SIZEOF(xGenericReply)) >> 2);
5801 mrep.minKeyCode = new->min_key_code;
5802 mrep.maxKeyCode = new->max_key_code;
5803 mrep.present = 0;
5804 mrep.totalSyms = mrep.totalActs =
5805 mrep.totalKeyBehaviors = mrep.totalKeyExplicit =
5806 mrep.totalModMapKeys = mrep.totalVModMapKeys = 0;
5807 if (rep.reported & (XkbGBN_TypesMask | XkbGBN_ClientSymbolsMask)) {
5808 mrep.present |= XkbKeyTypesMask;
5809 mrep.firstType = 0;
5810 mrep.nTypes = mrep.totalTypes = new->map->num_types;
5811 }
5812 else {
5813 mrep.firstType = mrep.nTypes = 0;
5814 mrep.totalTypes = 0;
5815 }
5816 if (rep.reported & XkbGBN_ClientSymbolsMask) {
5817 mrep.present |= (XkbKeySymsMask | XkbModifierMapMask);
5818 mrep.firstKeySym = mrep.firstModMapKey = new->min_key_code;
5819 mrep.nKeySyms = mrep.nModMapKeys = XkbNumKeys(new);
5820 }
5821 else {
5822 mrep.firstKeySym = mrep.firstModMapKey = 0;
5823 mrep.nKeySyms = mrep.nModMapKeys = 0;
5824 }
5825 if (rep.reported & XkbGBN_ServerSymbolsMask) {
5826 mrep.present |= XkbAllServerInfoMask;
5827 mrep.virtualMods = ~0;
5828 mrep.firstKeyAct = mrep.firstKeyBehavior =
5829 mrep.firstKeyExplicit = new->min_key_code;
5830 mrep.nKeyActs = mrep.nKeyBehaviors =
5831 mrep.nKeyExplicit = XkbNumKeys(new);
5832 mrep.firstVModMapKey = new->min_key_code;
5833 mrep.nVModMapKeys = XkbNumKeys(new);
5834 }
5835 else {
5836 mrep.virtualMods = 0;
5837 mrep.firstKeyAct = mrep.firstKeyBehavior =
5838 mrep.firstKeyExplicit = 0;
5839 mrep.nKeyActs = mrep.nKeyBehaviors = mrep.nKeyExplicit = 0;
5840 }
5841 XkbComputeGetMapReplySize(new, &mrep);
5842 rep.length += SIZEOF(xGenericReply) / 4 + mrep.length;
5843 }
5844 if (new->compat == NULL)
5845 rep.reported &= ~XkbGBN_CompatMapMask;
5846 else if (rep.reported & XkbGBN_CompatMapMask) {
5847 crep.type = X_Reply;
5848 crep.deviceID = dev->id;
5849 crep.sequenceNumber = client->sequence;
5850 crep.length = 0;
5851 crep.groups = XkbAllGroupsMask;
5852 crep.firstSI = 0;
5853 crep.nSI = crep.nTotalSI = new->compat->num_si;
5854 XkbComputeGetCompatMapReplySize(new->compat, &crep);
5855 rep.length += SIZEOF(xGenericReply) / 4 + crep.length;
5856 }
5857 if (new->indicators == NULL)
5858 rep.reported &= ~XkbGBN_IndicatorMapMask;
5859 else if (rep.reported & XkbGBN_IndicatorMapMask) {
5860 irep.type = X_Reply;
5861 irep.deviceID = dev->id;
5862 irep.sequenceNumber = client->sequence;
5863 irep.length = 0;
5864 irep.which = XkbAllIndicatorsMask;
5865 XkbComputeGetIndicatorMapReplySize(new->indicators, &irep);
5866 rep.length += SIZEOF(xGenericReply) / 4 + irep.length;
5867 }
5868 if (new->names == NULL)
5869 rep.reported &= ~(XkbGBN_OtherNamesMask | XkbGBN_KeyNamesMask);
5870 else if (rep.reported & (XkbGBN_OtherNamesMask | XkbGBN_KeyNamesMask)) {
5871 nrep.type = X_Reply;
5872 nrep.deviceID = dev->id;
5873 nrep.sequenceNumber = client->sequence;
5874 nrep.length = 0;
5875 nrep.minKeyCode = new->min_key_code;
5876 nrep.maxKeyCode = new->max_key_code;
5877 if (rep.reported & XkbGBN_OtherNamesMask) {
5878 nrep.which = XkbAllNamesMask;
5879 if (new->map != NULL)
5880 nrep.nTypes = new->map->num_types;
5881 else
5882 nrep.nTypes = 0;
5883 nrep.nKTLevels = 0;
5884 nrep.groupNames = XkbAllGroupsMask;
5885 nrep.virtualMods = XkbAllVirtualModsMask;
5886 nrep.indicators = XkbAllIndicatorsMask;
5887 nrep.nRadioGroups = new->names->num_rg;
5888 }
5889 else {
5890 nrep.which = 0;
5891 nrep.nTypes = 0;
5892 nrep.nKTLevels = 0;
5893 nrep.groupNames = 0;
5894 nrep.virtualMods = 0;
5895 nrep.indicators = 0;
5896 nrep.nRadioGroups = 0;
5897 }
5898 if (rep.reported & XkbGBN_KeyNamesMask) {
5899 nrep.which |= XkbKeyNamesMask;
5900 nrep.firstKey = new->min_key_code;
5901 nrep.nKeys = XkbNumKeys(new);
5902 nrep.nKeyAliases = new->names->num_key_aliases;
5903 if (nrep.nKeyAliases)
5904 nrep.which |= XkbKeyAliasesMask;
5905 }
5906 else {
5907 nrep.which &= ~(XkbKeyNamesMask | XkbKeyAliasesMask);
5908 nrep.firstKey = nrep.nKeys = 0;
5909 nrep.nKeyAliases = 0;
5910 }
5911 XkbComputeGetNamesReplySize(new, &nrep);
5912 rep.length += SIZEOF(xGenericReply) / 4 + nrep.length;
5913 }
5914 if (new->geom == NULL)
5915 rep.reported &= ~XkbGBN_GeometryMask;
5916 else if (rep.reported & XkbGBN_GeometryMask) {
5917 grep.type = X_Reply;
5918 grep.deviceID = dev->id;
5919 grep.sequenceNumber = client->sequence;
5920 grep.length = 0;
5921 grep.found = TRUE;
5922 grep.pad = 0;
5923 grep.widthMM = grep.heightMM = 0;
5924 grep.nProperties = grep.nColors = grep.nShapes = 0;
5925 grep.nSections = grep.nDoodads = 0;
5926 grep.baseColorNdx = grep.labelColorNdx = 0;
5927 XkbComputeGetGeometryReplySize(new->geom, &grep, None);
5928 rep.length += SIZEOF(xGenericReply) / 4 + grep.length;
5929 }
5930 }
5931
5932 reported = rep.reported;
5933 if (client->swapped) {
5934 swaps(&rep.sequenceNumber);
5935 swapl(&rep.length);
5936 swaps(&rep.found);
5937 swaps(&rep.reported);
5938 }
5939 WriteToClient(client, SIZEOF(xkbGetKbdByNameReply), &rep);
5940 if (reported & (XkbGBN_SymbolsMask | XkbGBN_TypesMask))
5941 XkbSendMap(client, new, &mrep);
5942 if (reported & XkbGBN_CompatMapMask)
5943 XkbSendCompatMap(client, new->compat, &crep);
5944 if (reported & XkbGBN_IndicatorMapMask)
5945 XkbSendIndicatorMap(client, new->indicators, &irep);
5946 if (reported & (XkbGBN_KeyNamesMask | XkbGBN_OtherNamesMask))
5947 XkbSendNames(client, new, &nrep);
5948 if (reported & XkbGBN_GeometryMask)
5949 XkbSendGeometry(client, new->geom, &grep, FALSE);
5950 if (rep.loaded) {
5951 XkbDescPtr old_xkb;
5952 xkbNewKeyboardNotify nkn;
5953 int i, nG, nTG;
5954
5955 old_xkb = xkb;
5956 xkb = new;
5957 dev->key->xkbInfo->desc = xkb;
5958 new = old_xkb; /* so it'll get freed automatically */
5959
5960 *xkb->ctrls = *old_xkb->ctrls;
5961 for (nG = nTG = 0, i = xkb->min_key_code; i <= xkb->max_key_code; i++) {
5962 nG = XkbKeyNumGroups(xkb, i);
5963 if (nG >= XkbNumKbdGroups) {
5964 nTG = XkbNumKbdGroups;
5965 break;
5966 }
5967 if (nG > nTG) {
5968 nTG = nG;
5969 }
5970 }
5971 xkb->ctrls->num_groups = nTG;
5972
5973 nkn.deviceID = nkn.oldDeviceID = dev->id;
5974 nkn.minKeyCode = new->min_key_code;
5975 nkn.maxKeyCode = new->max_key_code;
5976 nkn.oldMinKeyCode = xkb->min_key_code;
5977 nkn.oldMaxKeyCode = xkb->max_key_code;
5978 nkn.requestMajor = XkbReqCode;
5979 nkn.requestMinor = X_kbGetKbdByName;
5980 nkn.changed = XkbNKN_KeycodesMask;
5981 if (geom_changed)
5982 nkn.changed |= XkbNKN_GeometryMask;
5983 XkbSendNewKeyboardNotify(dev, &nkn);
5984
5985 /* Update the map and LED info on the device itself, as well as
5986 * any slaves if it's an MD, or its MD if it's an SD and was the
5987 * last device used on that MD. */
5988 for (tmpd = inputInfo.devices; tmpd; tmpd = tmpd->next) {
5989 if (tmpd != dev && GetMaster(tmpd, MASTER_KEYBOARD) != dev &&
5990 (tmpd != master || dev != master->lastSlave))
5991 continue;
5992
5993 if (tmpd != dev)
5994 XkbCopyDeviceKeymap(tmpd, dev);
5995
5996 if (tmpd->kbdfeed && tmpd->kbdfeed->xkb_sli) {
5997 old_sli = tmpd->kbdfeed->xkb_sli;
5998 tmpd->kbdfeed->xkb_sli = NULL;
5999 sli = XkbAllocSrvLedInfo(tmpd, tmpd->kbdfeed, NULL, 0);
6000 if (sli) {
6001 sli->explicitState = old_sli->explicitState;
6002 sli->effectiveState = old_sli->effectiveState;
6003 }
6004 tmpd->kbdfeed->xkb_sli = sli;
6005 XkbFreeSrvLedInfo(old_sli);
6006 }
6007 }
6008 }
6009 if ((new != NULL) && (new != xkb)) {
6010 XkbFreeKeyboard(new, XkbAllComponentsMask, TRUE);
6011 new = NULL;
6012 }
6013 XkbFreeComponentNames(&names, FALSE);
6014 return Success;
6015}
6016
6017/***====================================================================***/
6018
6019static int
6020ComputeDeviceLedInfoSize(DeviceIntPtr dev,
6021 unsigned int what, XkbSrvLedInfoPtr sli)
6022{
6023 int nNames, nMaps;
6024 register unsigned n, bit;
6025
6026 if (sli == NULL)
6027 return 0;
6028 nNames = nMaps = 0;
6029 if ((what & XkbXI_IndicatorNamesMask) == 0)
6030 sli->namesPresent = 0;
6031 if ((what & XkbXI_IndicatorMapsMask) == 0)
6032 sli->mapsPresent = 0;
6033
6034 for (n = 0, bit = 1; n < XkbNumIndicators; n++, bit <<= 1) {
6035 if (sli->names && sli->names[n] != None) {
6036 sli->namesPresent |= bit;
6037 nNames++;
6038 }
6039 if (sli->maps && XkbIM_InUse(&sli->maps[n])) {
6040 sli->mapsPresent |= bit;
6041 nMaps++;
6042 }
6043 }
6044 return (nNames * 4) + (nMaps * SIZEOF(xkbIndicatorMapWireDesc));
6045}
6046
6047static int
6048CheckDeviceLedFBs(DeviceIntPtr dev,
6049 int class,
6050 int id, xkbGetDeviceInfoReply * rep, ClientPtr client)
6051{
6052 int nFBs = 0;
6053 int length = 0;
6054 Bool classOk;
6055
6056 if (class == XkbDfltXIClass) {
6057 if (dev->kbdfeed)
6058 class = KbdFeedbackClass;
6059 else if (dev->leds)
6060 class = LedFeedbackClass;
6061 else {
6062 client->errorValue = _XkbErrCode2(XkbErr_BadClass, class);
6063 return XkbKeyboardErrorCode;
6064 }
6065 }
6066 classOk = FALSE;
6067 if ((dev->kbdfeed) &&
6068 ((class == KbdFeedbackClass) || (class == XkbAllXIClasses))) {
6069 KbdFeedbackPtr kf;
6070
6071 classOk = TRUE;
6072 for (kf = dev->kbdfeed; (kf); kf = kf->next) {
6073 if ((id != XkbAllXIIds) && (id != XkbDfltXIId) &&
6074 (id != kf->ctrl.id))
6075 continue;
6076 nFBs++;
6077 length += SIZEOF(xkbDeviceLedsWireDesc);
6078 if (!kf->xkb_sli)
6079 kf->xkb_sli = XkbAllocSrvLedInfo(dev, kf, NULL, 0);
6080 length += ComputeDeviceLedInfoSize(dev, rep->present, kf->xkb_sli);
6081 if (id != XkbAllXIIds)
6082 break;
6083 }
6084 }
6085 if ((dev->leds) &&
6086 ((class == LedFeedbackClass) || (class == XkbAllXIClasses))) {
6087 LedFeedbackPtr lf;
6088
6089 classOk = TRUE;
6090 for (lf = dev->leds; (lf); lf = lf->next) {
6091 if ((id != XkbAllXIIds) && (id != XkbDfltXIId) &&
6092 (id != lf->ctrl.id))
6093 continue;
6094 nFBs++;
6095 length += SIZEOF(xkbDeviceLedsWireDesc);
6096 if (!lf->xkb_sli)
6097 lf->xkb_sli = XkbAllocSrvLedInfo(dev, NULL, lf, 0);
6098 length += ComputeDeviceLedInfoSize(dev, rep->present, lf->xkb_sli);
6099 if (id != XkbAllXIIds)
6100 break;
6101 }
6102 }
6103 if (nFBs > 0) {
6104 rep->nDeviceLedFBs = nFBs;
6105 rep->length += (length / 4);
6106 return Success;
6107 }
6108 if (classOk)
6109 client->errorValue = _XkbErrCode2(XkbErr_BadId, id);
6110 else
6111 client->errorValue = _XkbErrCode2(XkbErr_BadClass, class);
6112 return XkbKeyboardErrorCode;
6113}
6114
6115static int
6116SendDeviceLedInfo(XkbSrvLedInfoPtr sli, ClientPtr client)
6117{
6118 xkbDeviceLedsWireDesc wire;
6119 int length;
6120
6121 length = 0;
6122 wire.ledClass = sli->class;
6123 wire.ledID = sli->id;
6124 wire.namesPresent = sli->namesPresent;
6125 wire.mapsPresent = sli->mapsPresent;
6126 wire.physIndicators = sli->physIndicators;
6127 wire.state = sli->effectiveState;
6128 if (client->swapped) {
6129 swaps(&wire.ledClass);
6130 swaps(&wire.ledID);
6131 swapl(&wire.namesPresent);
6132 swapl(&wire.mapsPresent);
6133 swapl(&wire.physIndicators);
6134 swapl(&wire.state);
6135 }
6136 WriteToClient(client, SIZEOF(xkbDeviceLedsWireDesc), &wire);
6137 length += SIZEOF(xkbDeviceLedsWireDesc);
6138 if (sli->namesPresent | sli->mapsPresent) {
6139 register unsigned i, bit;
6140
6141 if (sli->namesPresent) {
6142 CARD32 awire;
6143
6144 for (i = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) {
6145 if (sli->namesPresent & bit) {
6146 awire = (CARD32) sli->names[i];
6147 if (client->swapped) {
6148 swapl(&awire);
6149 }
6150 WriteToClient(client, 4, &awire);
6151 length += 4;
6152 }
6153 }
6154 }
6155 if (sli->mapsPresent) {
6156 for (i = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) {
6157 xkbIndicatorMapWireDesc iwire;
6158
6159 if (sli->mapsPresent & bit) {
6160 iwire.flags = sli->maps[i].flags;
6161 iwire.whichGroups = sli->maps[i].which_groups;
6162 iwire.groups = sli->maps[i].groups;
6163 iwire.whichMods = sli->maps[i].which_mods;
6164 iwire.mods = sli->maps[i].mods.mask;
6165 iwire.realMods = sli->maps[i].mods.real_mods;
6166 iwire.virtualMods = sli->maps[i].mods.vmods;
6167 iwire.ctrls = sli->maps[i].ctrls;
6168 if (client->swapped) {
6169 swaps(&iwire.virtualMods);
6170 swapl(&iwire.ctrls);
6171 }
6172 WriteToClient(client, SIZEOF(xkbIndicatorMapWireDesc),
6173 &iwire);
6174 length += SIZEOF(xkbIndicatorMapWireDesc);
6175 }
6176 }
6177 }
6178 }
6179 return length;
6180}
6181
6182static int
6183SendDeviceLedFBs(DeviceIntPtr dev,
6184 int class, int id, unsigned wantLength, ClientPtr client)
6185{
6186 int length = 0;
6187
6188 if (class == XkbDfltXIClass) {
6189 if (dev->kbdfeed)
6190 class = KbdFeedbackClass;
6191 else if (dev->leds)
6192 class = LedFeedbackClass;
6193 }
6194 if ((dev->kbdfeed) &&
6195 ((class == KbdFeedbackClass) || (class == XkbAllXIClasses))) {
6196 KbdFeedbackPtr kf;
6197
6198 for (kf = dev->kbdfeed; (kf); kf = kf->next) {
6199 if ((id == XkbAllXIIds) || (id == XkbDfltXIId) ||
6200 (id == kf->ctrl.id)) {
6201 length += SendDeviceLedInfo(kf->xkb_sli, client);
6202 if (id != XkbAllXIIds)
6203 break;
6204 }
6205 }
6206 }
6207 if ((dev->leds) &&
6208 ((class == LedFeedbackClass) || (class == XkbAllXIClasses))) {
6209 LedFeedbackPtr lf;
6210
6211 for (lf = dev->leds; (lf); lf = lf->next) {
6212 if ((id == XkbAllXIIds) || (id == XkbDfltXIId) ||
6213 (id == lf->ctrl.id)) {
6214 length += SendDeviceLedInfo(lf->xkb_sli, client);
6215 if (id != XkbAllXIIds)
6216 break;
6217 }
6218 }
6219 }
6220 if (length == wantLength)
6221 return Success;
6222 else
6223 return BadLength;
6224}
6225
6226int
6227ProcXkbGetDeviceInfo(ClientPtr client)
6228{
6229 DeviceIntPtr dev;
6230 xkbGetDeviceInfoReply rep;
6231 int status, nDeviceLedFBs;
6232 unsigned length, nameLen;
6233 CARD16 ledClass, ledID;
6234 unsigned wanted;
6235 char *str;
6236
6237 REQUEST(xkbGetDeviceInfoReq);
6238 REQUEST_SIZE_MATCH(xkbGetDeviceInfoReq);
6239
6240 if (!(client->xkbClientFlags & _XkbClientInitialized))
6241 return BadAccess;
6242
6243 wanted = stuff->wanted;
6244
6245 CHK_ANY_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess);
6246 CHK_MASK_LEGAL(0x01, wanted, XkbXI_AllDeviceFeaturesMask);
6247
6248 if ((!dev->button) || ((stuff->nBtns < 1) && (!stuff->allBtns)))
6249 wanted &= ~XkbXI_ButtonActionsMask;
6250 if ((!dev->kbdfeed) && (!dev->leds))
6251 wanted &= ~XkbXI_IndicatorsMask;
6252
6253 nameLen = XkbSizeCountedString(dev->name);
6254 rep = (xkbGetDeviceInfoReply) {
6255 .type = X_Reply,
6256 .deviceID = dev->id,
6257 .sequenceNumber = client->sequence,
6258 .length = nameLen / 4,
6259 .present = wanted,
6260 .supported = XkbXI_AllDeviceFeaturesMask,
6261 .unsupported = 0,
6262 .nDeviceLedFBs = 0,
6263 .firstBtnWanted = 0,
6264 .nBtnsWanted = 0,
6265 .firstBtnRtrn = 0,
6266 .nBtnsRtrn = 0,
6267 .totalBtns = dev->button ? dev->button->numButtons : 0,
6268 .hasOwnState = (dev->key && dev->key->xkbInfo),
6269 .dfltKbdFB = dev->kbdfeed ? dev->kbdfeed->ctrl.id : XkbXINone,
6270 .dfltLedFB = dev->leds ? dev->leds->ctrl.id : XkbXINone,
6271 .devType = dev->xinput_type
6272 };
6273
6274 ledClass = stuff->ledClass;
6275 ledID = stuff->ledID;
6276
6277 if (wanted & XkbXI_ButtonActionsMask) {
6278 if (stuff->allBtns) {
6279 stuff->firstBtn = 0;
6280 stuff->nBtns = dev->button->numButtons;
6281 }
6282
6283 if ((stuff->firstBtn + stuff->nBtns) > dev->button->numButtons) {
6284 client->errorValue = _XkbErrCode4(0x02, dev->button->numButtons,
6285 stuff->firstBtn, stuff->nBtns);
6286 return BadValue;
6287 }
6288 else {
6289 rep.firstBtnWanted = stuff->firstBtn;
6290 rep.nBtnsWanted = stuff->nBtns;
6291 if (dev->button->xkb_acts != NULL) {
6292 XkbAction *act;
6293 register int i;
6294
6295 rep.firstBtnRtrn = stuff->firstBtn;
6296 rep.nBtnsRtrn = stuff->nBtns;
6297 act = &dev->button->xkb_acts[rep.firstBtnWanted];
6298 for (i = 0; i < rep.nBtnsRtrn; i++, act++) {
6299 if (act->type != XkbSA_NoAction)
6300 break;
6301 }
6302 rep.firstBtnRtrn += i;
6303 rep.nBtnsRtrn -= i;
6304 act =
6305 &dev->button->xkb_acts[rep.firstBtnRtrn + rep.nBtnsRtrn -
6306 1];
6307 for (i = 0; i < rep.nBtnsRtrn; i++, act--) {
6308 if (act->type != XkbSA_NoAction)
6309 break;
6310 }
6311 rep.nBtnsRtrn -= i;
6312 }
6313 rep.length += (rep.nBtnsRtrn * SIZEOF(xkbActionWireDesc)) / 4;
6314 }
6315 }
6316
6317 if (wanted & XkbXI_IndicatorsMask) {
6318 status = CheckDeviceLedFBs(dev, ledClass, ledID, &rep, client);
6319 if (status != Success)
6320 return status;
6321 }
6322 length = rep.length * 4;
6323 nDeviceLedFBs = rep.nDeviceLedFBs;
6324 if (client->swapped) {
6325 swaps(&rep.sequenceNumber);
6326 swapl(&rep.length);
6327 swaps(&rep.present);
6328 swaps(&rep.supported);
6329 swaps(&rep.unsupported);
6330 swaps(&rep.nDeviceLedFBs);
6331 swaps(&rep.dfltKbdFB);
6332 swaps(&rep.dfltLedFB);
6333 swapl(&rep.devType);
6334 }
6335 WriteToClient(client, SIZEOF(xkbGetDeviceInfoReply), &rep);
6336
6337 str = malloc(nameLen);
6338 if (!str)
6339 return BadAlloc;
6340 XkbWriteCountedString(str, dev->name, client->swapped);
6341 WriteToClient(client, nameLen, str);
6342 free(str);
6343 length -= nameLen;
6344
6345 if (rep.nBtnsRtrn > 0) {
6346 int sz;
6347 xkbActionWireDesc *awire;
6348
6349 sz = rep.nBtnsRtrn * SIZEOF(xkbActionWireDesc);
6350 awire = (xkbActionWireDesc *) &dev->button->xkb_acts[rep.firstBtnRtrn];
6351 WriteToClient(client, sz, awire);
6352 length -= sz;
6353 }
6354 if (nDeviceLedFBs > 0) {
6355 status = SendDeviceLedFBs(dev, ledClass, ledID, length, client);
6356 if (status != Success)
6357 return status;
6358 }
6359 else if (length != 0) {
6360 ErrorF("[xkb] Internal Error! BadLength in ProcXkbGetDeviceInfo\n");
6361 ErrorF("[xkb] Wrote %d fewer bytes than expected\n",
6362 length);
6363 return BadLength;
6364 }
6365 return Success;
6366}
6367
6368static char *
6369CheckSetDeviceIndicators(char *wire,
6370 DeviceIntPtr dev,
6371 int num, int *status_rtrn, ClientPtr client)
6372{
6373 xkbDeviceLedsWireDesc *ledWire;
6374 int i;
6375 XkbSrvLedInfoPtr sli;
6376
6377 ledWire = (xkbDeviceLedsWireDesc *) wire;
6378 for (i = 0; i < num; i++) {
6379 if (client->swapped) {
6380 swaps(&ledWire->ledClass);
6381 swaps(&ledWire->ledID);
6382 swapl(&ledWire->namesPresent);
6383 swapl(&ledWire->mapsPresent);
6384 swapl(&ledWire->physIndicators);
6385 }
6386
6387 sli = XkbFindSrvLedInfo(dev, ledWire->ledClass, ledWire->ledID,
6388 XkbXI_IndicatorsMask);
6389 if (sli != NULL) {
6390 register int n;
6391 register unsigned bit;
6392 int nMaps, nNames;
6393 CARD32 *atomWire;
6394 xkbIndicatorMapWireDesc *mapWire;
6395
6396 nMaps = nNames = 0;
6397 for (n = 0, bit = 1; n < XkbNumIndicators; n++, bit <<= 1) {
6398 if (ledWire->namesPresent & bit)
6399 nNames++;
6400 if (ledWire->mapsPresent & bit)
6401 nMaps++;
6402 }
6403 atomWire = (CARD32 *) &ledWire[1];
6404 if (nNames > 0) {
6405 for (n = 0; n < nNames; n++) {
6406 if (client->swapped) {
6407 swapl(atomWire);
6408 }
6409 CHK_ATOM_OR_NONE3(((Atom) (*atomWire)), client->errorValue,
6410 *status_rtrn, NULL);
6411 atomWire++;
6412 }
6413 }
6414 mapWire = (xkbIndicatorMapWireDesc *) atomWire;
6415 if (nMaps > 0) {
6416 for (n = 0; n < nMaps; n++) {
6417 if (client->swapped) {
6418 swaps(&mapWire->virtualMods);
6419 swapl(&mapWire->ctrls);
6420 }
6421 CHK_MASK_LEGAL3(0x21, mapWire->whichGroups,
6422 XkbIM_UseAnyGroup,
6423 client->errorValue, *status_rtrn, NULL);
6424 CHK_MASK_LEGAL3(0x22, mapWire->whichMods, XkbIM_UseAnyMods,
6425 client->errorValue, *status_rtrn, NULL);
6426 mapWire++;
6427 }
6428 }
6429 ledWire = (xkbDeviceLedsWireDesc *) mapWire;
6430 }
6431 else {
6432 /* SHOULD NEVER HAPPEN */
6433 return (char *) ledWire;
6434 }
6435 }
6436 return (char *) ledWire;
6437}
6438
6439static char *
6440SetDeviceIndicators(char *wire,
6441 DeviceIntPtr dev,
6442 unsigned changed,
6443 int num,
6444 int *status_rtrn,
6445 ClientPtr client, xkbExtensionDeviceNotify * ev)
6446{
6447 xkbDeviceLedsWireDesc *ledWire;
6448 int i;
6449 XkbEventCauseRec cause;
6450 unsigned namec, mapc, statec;
6451 xkbExtensionDeviceNotify ed;
6452 XkbChangesRec changes;
6453 DeviceIntPtr kbd;
6454
6455 memset((char *) &ed, 0, sizeof(xkbExtensionDeviceNotify));
6456 memset((char *) &changes, 0, sizeof(XkbChangesRec));
6457 XkbSetCauseXkbReq(&cause, X_kbSetDeviceInfo, client);
6458 ledWire = (xkbDeviceLedsWireDesc *) wire;
6459 for (i = 0; i < num; i++) {
6460 register int n;
6461 register unsigned bit;
6462 CARD32 *atomWire;
6463 xkbIndicatorMapWireDesc *mapWire;
6464 XkbSrvLedInfoPtr sli;
6465
6466 namec = mapc = statec = 0;
6467 sli = XkbFindSrvLedInfo(dev, ledWire->ledClass, ledWire->ledID,
6468 XkbXI_IndicatorMapsMask);
6469 if (!sli) {
6470 /* SHOULD NEVER HAPPEN!! */
6471 return (char *) ledWire;
6472 }
6473
6474 atomWire = (CARD32 *) &ledWire[1];
6475 if (changed & XkbXI_IndicatorNamesMask) {
6476 namec = sli->namesPresent | ledWire->namesPresent;
6477 memset((char *) sli->names, 0, XkbNumIndicators * sizeof(Atom));
6478 }
6479 if (ledWire->namesPresent) {
6480 sli->namesPresent = ledWire->namesPresent;
6481 memset((char *) sli->names, 0, XkbNumIndicators * sizeof(Atom));
6482 for (n = 0, bit = 1; n < XkbNumIndicators; n++, bit <<= 1) {
6483 if (ledWire->namesPresent & bit) {
6484 sli->names[n] = (Atom) *atomWire;
6485 if (sli->names[n] == None)
6486 ledWire->namesPresent &= ~bit;
6487 atomWire++;
6488 }
6489 }
6490 }
6491 mapWire = (xkbIndicatorMapWireDesc *) atomWire;
6492 if (changed & XkbXI_IndicatorMapsMask) {
6493 mapc = sli->mapsPresent | ledWire->mapsPresent;
6494 sli->mapsPresent = ledWire->mapsPresent;
6495 memset((char *) sli->maps, 0,
6496 XkbNumIndicators * sizeof(XkbIndicatorMapRec));
6497 }
6498 if (ledWire->mapsPresent) {
6499 for (n = 0, bit = 1; n < XkbNumIndicators; n++, bit <<= 1) {
6500 if (ledWire->mapsPresent & bit) {
6501 sli->maps[n].flags = mapWire->flags;
6502 sli->maps[n].which_groups = mapWire->whichGroups;
6503 sli->maps[n].groups = mapWire->groups;
6504 sli->maps[n].which_mods = mapWire->whichMods;
6505 sli->maps[n].mods.mask = mapWire->mods;
6506 sli->maps[n].mods.real_mods = mapWire->realMods;
6507 sli->maps[n].mods.vmods = mapWire->virtualMods;
6508 sli->maps[n].ctrls = mapWire->ctrls;
6509 mapWire++;
6510 }
6511 }
6512 }
6513 if (changed & XkbXI_IndicatorStateMask) {
6514 statec = sli->effectiveState ^ ledWire->state;
6515 sli->explicitState &= ~statec;
6516 sli->explicitState |= (ledWire->state & statec);
6517 }
6518 if (namec)
6519 XkbApplyLedNameChanges(dev, sli, namec, &ed, &changes, &cause);
6520 if (mapc)
6521 XkbApplyLedMapChanges(dev, sli, mapc, &ed, &changes, &cause);
6522 if (statec)
6523 XkbApplyLedStateChanges(dev, sli, statec, &ed, &changes, &cause);
6524
6525 kbd = dev;
6526 if ((sli->flags & XkbSLI_HasOwnState) == 0)
6527 kbd = inputInfo.keyboard;
6528
6529 XkbFlushLedEvents(dev, kbd, sli, &ed, &changes, &cause);
6530 ledWire = (xkbDeviceLedsWireDesc *) mapWire;
6531 }
6532 return (char *) ledWire;
6533}
6534
6535static int
6536_XkbSetDeviceInfo(ClientPtr client, DeviceIntPtr dev,
6537 xkbSetDeviceInfoReq * stuff)
6538{
6539 char *wire;
6540
6541 wire = (char *) &stuff[1];
6542 if (stuff->change & XkbXI_ButtonActionsMask) {
6543 if (!dev->button) {
6544 client->errorValue = _XkbErrCode2(XkbErr_BadClass, ButtonClass);
6545 return XkbKeyboardErrorCode;
6546 }
6547 if ((stuff->firstBtn + stuff->nBtns) > dev->button->numButtons) {
6548 client->errorValue =
6549 _XkbErrCode4(0x02, stuff->firstBtn, stuff->nBtns,
6550 dev->button->numButtons);
6551 return BadMatch;
6552 }
6553 wire += (stuff->nBtns * SIZEOF(xkbActionWireDesc));
6554 }
6555 if (stuff->change & XkbXI_IndicatorsMask) {
6556 int status = Success;
6557
6558 wire = CheckSetDeviceIndicators(wire, dev, stuff->nDeviceLedFBs,
6559 &status, client);
6560 if (status != Success)
6561 return status;
6562 }
6563 if (((wire - ((char *) stuff)) / 4) != stuff->length)
6564 return BadLength;
6565
6566 return Success;
6567}
6568
6569static int
6570_XkbSetDeviceInfoCheck(ClientPtr client, DeviceIntPtr dev,
6571 xkbSetDeviceInfoReq * stuff)
6572{
6573 char *wire;
6574 xkbExtensionDeviceNotify ed;
6575
6576 memset((char *) &ed, 0, SIZEOF(xkbExtensionDeviceNotify));
6577 ed.deviceID = dev->id;
6578 wire = (char *) &stuff[1];
6579 if (stuff->change & XkbXI_ButtonActionsMask) {
6580 int nBtns, sz, i;
6581 XkbAction *acts;
6582 DeviceIntPtr kbd;
6583
6584 nBtns = dev->button->numButtons;
6585 acts = dev->button->xkb_acts;
6586 if (acts == NULL) {
6587 acts = calloc(nBtns, sizeof(XkbAction));
6588 if (!acts)
6589 return BadAlloc;
6590 dev->button->xkb_acts = acts;
6591 }
6592 sz = stuff->nBtns * SIZEOF(xkbActionWireDesc);
6593 memcpy((char *) &acts[stuff->firstBtn], (char *) wire, sz);
6594 wire += sz;
6595 ed.reason |= XkbXI_ButtonActionsMask;
6596 ed.firstBtn = stuff->firstBtn;
6597 ed.nBtns = stuff->nBtns;
6598
6599 if (dev->key)
6600 kbd = dev;
6601 else
6602 kbd = inputInfo.keyboard;
6603 acts = &dev->button->xkb_acts[stuff->firstBtn];
6604 for (i = 0; i < stuff->nBtns; i++, acts++) {
6605 if (acts->type != XkbSA_NoAction)
6606 XkbSetActionKeyMods(kbd->key->xkbInfo->desc, acts, 0);
6607 }
6608 }
6609 if (stuff->change & XkbXI_IndicatorsMask) {
6610 int status = Success;
6611
6612 wire = SetDeviceIndicators(wire, dev, stuff->change,
6613 stuff->nDeviceLedFBs, &status, client, &ed);
6614 if (status != Success)
6615 return status;
6616 }
6617 if ((stuff->change) && (ed.reason))
6618 XkbSendExtensionDeviceNotify(dev, client, &ed);
6619 return Success;
6620}
6621
6622int
6623ProcXkbSetDeviceInfo(ClientPtr client)
6624{
6625 DeviceIntPtr dev;
6626 int rc;
6627
6628 REQUEST(xkbSetDeviceInfoReq);
6629 REQUEST_AT_LEAST_SIZE(xkbSetDeviceInfoReq);
6630
6631 if (!(client->xkbClientFlags & _XkbClientInitialized))
6632 return BadAccess;
6633
6634 CHK_ANY_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess);
6635 CHK_MASK_LEGAL(0x01, stuff->change, XkbXI_AllFeaturesMask);
6636
6637 rc = _XkbSetDeviceInfoCheck(client, dev, stuff);
6638
6639 if (rc != Success)
6640 return rc;
6641
6642 if (stuff->deviceSpec == XkbUseCoreKbd ||
6643 stuff->deviceSpec == XkbUseCorePtr) {
6644 DeviceIntPtr other;
6645
6646 for (other = inputInfo.devices; other; other = other->next) {
6647 if (((other != dev) && !IsMaster(other) &&
6648 GetMaster(other, MASTER_KEYBOARD) == dev) &&
6649 ((stuff->deviceSpec == XkbUseCoreKbd && other->key) ||
6650 (stuff->deviceSpec == XkbUseCorePtr && other->button))) {
6651 rc = XaceHook(XACE_DEVICE_ACCESS, client, other,
6652 DixManageAccess);
6653 if (rc == Success) {
6654 rc = _XkbSetDeviceInfoCheck(client, other, stuff);
6655 if (rc != Success)
6656 return rc;
6657 }
6658 }
6659 }
6660 }
6661
6662 /* checks done, apply */
6663 rc = _XkbSetDeviceInfo(client, dev, stuff);
6664 if (rc != Success)
6665 return rc;
6666
6667 if (stuff->deviceSpec == XkbUseCoreKbd ||
6668 stuff->deviceSpec == XkbUseCorePtr) {
6669 DeviceIntPtr other;
6670
6671 for (other = inputInfo.devices; other; other = other->next) {
6672 if (((other != dev) && !IsMaster(other) &&
6673 GetMaster(other, MASTER_KEYBOARD) == dev) &&
6674 ((stuff->deviceSpec == XkbUseCoreKbd && other->key) ||
6675 (stuff->deviceSpec == XkbUseCorePtr && other->button))) {
6676 rc = XaceHook(XACE_DEVICE_ACCESS, client, other,
6677 DixManageAccess);
6678 if (rc == Success) {
6679 rc = _XkbSetDeviceInfo(client, other, stuff);
6680 if (rc != Success)
6681 return rc;
6682 }
6683 }
6684 }
6685 }
6686
6687 return Success;
6688}
6689
6690/***====================================================================***/
6691
6692int
6693ProcXkbSetDebuggingFlags(ClientPtr client)
6694{
6695 CARD32 newFlags, newCtrls, extraLength;
6696 xkbSetDebuggingFlagsReply rep;
6697 int rc;
6698
6699 REQUEST(xkbSetDebuggingFlagsReq);
6700 REQUEST_AT_LEAST_SIZE(xkbSetDebuggingFlagsReq);
6701
6702 rc = XaceHook(XACE_SERVER_ACCESS, client, DixDebugAccess);
6703 if (rc != Success)
6704 return rc;
6705
6706 newFlags = xkbDebugFlags & (~stuff->affectFlags);
6707 newFlags |= (stuff->flags & stuff->affectFlags);
6708 newCtrls = xkbDebugCtrls & (~stuff->affectCtrls);
6709 newCtrls |= (stuff->ctrls & stuff->affectCtrls);
6710 if (xkbDebugFlags || newFlags || stuff->msgLength) {
6711 ErrorF("[xkb] XkbDebug: Setting debug flags to 0x%lx\n",
6712 (long) newFlags);
6713 if (newCtrls != xkbDebugCtrls)
6714 ErrorF("[xkb] XkbDebug: Setting debug controls to 0x%lx\n",
6715 (long) newCtrls);
6716 }
6717 extraLength = (stuff->length << 2) - sz_xkbSetDebuggingFlagsReq;
6718 if (stuff->msgLength > 0) {
6719 char *msg;
6720
6721 if (extraLength < XkbPaddedSize(stuff->msgLength)) {
6722 ErrorF
6723 ("[xkb] XkbDebug: msgLength= %d, length= %ld (should be %d)\n",
6724 stuff->msgLength, (long) extraLength,
6725 XkbPaddedSize(stuff->msgLength));
6726 return BadLength;
6727 }
6728 msg = (char *) &stuff[1];
6729 if (msg[stuff->msgLength - 1] != '\0') {
6730 ErrorF("[xkb] XkbDebug: message not null-terminated\n");
6731 return BadValue;
6732 }
6733 ErrorF("[xkb] XkbDebug: %s\n", msg);
6734 }
6735 xkbDebugFlags = newFlags;
6736 xkbDebugCtrls = newCtrls;
6737
6738 rep = (xkbSetDebuggingFlagsReply) {
6739 .type = X_Reply,
6740 .sequenceNumber = client->sequence,
6741 .length = 0,
6742 .currentFlags = newFlags,
6743 .currentCtrls = newCtrls,
6744 .supportedFlags = ~0,
6745 .supportedCtrls = ~0
6746 };
6747 if (client->swapped) {
6748 swaps(&rep.sequenceNumber);
6749 swapl(&rep.currentFlags);
6750 swapl(&rep.currentCtrls);
6751 swapl(&rep.supportedFlags);
6752 swapl(&rep.supportedCtrls);
6753 }
6754 WriteToClient(client, SIZEOF(xkbSetDebuggingFlagsReply), &rep);
6755 return Success;
6756}
6757
6758/***====================================================================***/
6759
6760static int
6761ProcXkbDispatch(ClientPtr client)
6762{
6763 REQUEST(xReq);
6764 switch (stuff->data) {
6765 case X_kbUseExtension:
6766 return ProcXkbUseExtension(client);
6767 case X_kbSelectEvents:
6768 return ProcXkbSelectEvents(client);
6769 case X_kbBell:
6770 return ProcXkbBell(client);
6771 case X_kbGetState:
6772 return ProcXkbGetState(client);
6773 case X_kbLatchLockState:
6774 return ProcXkbLatchLockState(client);
6775 case X_kbGetControls:
6776 return ProcXkbGetControls(client);
6777 case X_kbSetControls:
6778 return ProcXkbSetControls(client);
6779 case X_kbGetMap:
6780 return ProcXkbGetMap(client);
6781 case X_kbSetMap:
6782 return ProcXkbSetMap(client);
6783 case X_kbGetCompatMap:
6784 return ProcXkbGetCompatMap(client);
6785 case X_kbSetCompatMap:
6786 return ProcXkbSetCompatMap(client);
6787 case X_kbGetIndicatorState:
6788 return ProcXkbGetIndicatorState(client);
6789 case X_kbGetIndicatorMap:
6790 return ProcXkbGetIndicatorMap(client);
6791 case X_kbSetIndicatorMap:
6792 return ProcXkbSetIndicatorMap(client);
6793 case X_kbGetNamedIndicator:
6794 return ProcXkbGetNamedIndicator(client);
6795 case X_kbSetNamedIndicator:
6796 return ProcXkbSetNamedIndicator(client);
6797 case X_kbGetNames:
6798 return ProcXkbGetNames(client);
6799 case X_kbSetNames:
6800 return ProcXkbSetNames(client);
6801 case X_kbGetGeometry:
6802 return ProcXkbGetGeometry(client);
6803 case X_kbSetGeometry:
6804 return ProcXkbSetGeometry(client);
6805 case X_kbPerClientFlags:
6806 return ProcXkbPerClientFlags(client);
6807 case X_kbListComponents:
6808 return ProcXkbListComponents(client);
6809 case X_kbGetKbdByName:
6810 return ProcXkbGetKbdByName(client);
6811 case X_kbGetDeviceInfo:
6812 return ProcXkbGetDeviceInfo(client);
6813 case X_kbSetDeviceInfo:
6814 return ProcXkbSetDeviceInfo(client);
6815 case X_kbSetDebuggingFlags:
6816 return ProcXkbSetDebuggingFlags(client);
6817 default:
6818 return BadRequest;
6819 }
6820}
6821
6822static int
6823XkbClientGone(pointer data, XID id)
6824{
6825 DevicePtr pXDev = (DevicePtr) data;
6826
6827 if (!XkbRemoveResourceClient(pXDev, id)) {
6828 ErrorF
6829 ("[xkb] Internal Error! bad RemoveResourceClient in XkbClientGone\n");
6830 }
6831 return 1;
6832}
6833
6834void
6835XkbExtensionInit(void)
6836{
6837 ExtensionEntry *extEntry;
6838
6839 RT_XKBCLIENT = CreateNewResourceType(XkbClientGone, "XkbClient");
6840 if (!RT_XKBCLIENT)
6841 return;
6842
6843 if (!XkbInitPrivates())
6844 return;
6845
6846 if ((extEntry = AddExtension(XkbName, XkbNumberEvents, XkbNumberErrors,
6847 ProcXkbDispatch, SProcXkbDispatch,
6848 NULL, StandardMinorOpcode))) {
6849 XkbReqCode = (unsigned char) extEntry->base;
6850 XkbEventBase = (unsigned char) extEntry->eventBase;
6851 XkbErrorBase = (unsigned char) extEntry->errorBase;
6852 XkbKeyboardErrorCode = XkbErrorBase + XkbKeyboard;
6853 }
6854 return;
6855}