Commit | Line | Data |
---|---|---|
a09e091a JB |
1 | /************************************************************ |
2 | Copyright (c) 1993 by Silicon Graphics Computer Systems, Inc. | |
3 | ||
4 | Permission to use, copy, modify, and distribute this | |
5 | software and its documentation for any purpose and without | |
6 | fee is hereby granted, provided that the above copyright | |
7 | notice appear in all copies and that both that copyright | |
8 | notice and this permission notice appear in supporting | |
9 | documentation, and that the name of Silicon Graphics not be | |
10 | used in advertising or publicity pertaining to distribution | |
11 | of the software without specific prior written permission. | |
12 | Silicon Graphics makes no representation about the suitability | |
13 | of this software for any purpose. It is provided "as is" | |
14 | without any express or implied warranty. | |
15 | ||
16 | SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS | |
17 | SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY | |
18 | AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON | |
19 | GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL | |
20 | DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, | |
21 | DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE | |
22 | OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH | |
23 | THE 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 | ||
47 | int XkbEventBase; | |
48 | static int XkbErrorBase; | |
49 | int XkbReqCode; | |
50 | int XkbKeyboardErrorCode; | |
51 | CARD32 xkbDebugFlags = 0; | |
52 | static CARD32 xkbDebugCtrls = 0; | |
53 | ||
54 | static 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 | ||
157 | int | |
158 | ProcXkbUseExtension(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 | ||
204 | int | |
205 | ProcXkbSelectEvents(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 | */ | |
367 | static 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 | ||
478 | int | |
479 | ProcXkbBell(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 | ||
566 | int | |
567 | ProcXkbGetState(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 | ||
608 | int | |
609 | ProcXkbLatchLockState(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 | ||
678 | int | |
679 | ProcXkbGetControls(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 | ||
753 | int | |
754 | ProcXkbSetControls(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 | ||
979 | static int | |
980 | XkbSizeKeyTypes(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 | ||
1004 | static char * | |
1005 | XkbWriteKeyTypes(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 | ||
1066 | static int | |
1067 | XkbSizeKeySyms(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 | ||
1093 | static int | |
1094 | XkbSizeVirtualMods(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 | ||
1111 | static char * | |
1112 | XkbWriteKeySyms(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 | ||
1151 | static int | |
1152 | XkbSizeKeyActions(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 | ||
1174 | static char * | |
1175 | XkbWriteKeyActions(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 | ||
1207 | static int | |
1208 | XkbSizeKeyBehaviors(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 | ||
1230 | static char * | |
1231 | XkbWriteKeyBehaviors(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 | ||
1252 | static int | |
1253 | XkbSizeExplicit(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 | ||
1274 | static char * | |
1275 | XkbWriteExplicit(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 | ||
1294 | static int | |
1295 | XkbSizeModifierMap(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 | ||
1315 | static char * | |
1316 | XkbWriteModifierMap(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 | ||
1335 | static int | |
1336 | XkbSizeVirtualModMap(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 | ||
1356 | static char * | |
1357 | XkbWriteVirtualModMap(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 | ||
1376 | static Status | |
1377 | XkbComputeGetMapReplySize(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 | ||
1395 | static int | |
1396 | XkbSendMap(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 | ||
1447 | int | |
1448 | ProcXkbGetMap(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 | ||
1585 | static int | |
1586 | CheckKeyTypes(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 | ||
1707 | static int | |
1708 | CheckKeySyms(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 | ||
1787 | static int | |
1788 | CheckKeyActions(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 | ||
1820 | static int | |
1821 | CheckKeyBehaviors(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 | ||
1871 | static int | |
1872 | CheckVirtualMods(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 | ||
1888 | static int | |
1889 | CheckKeyExplicit(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 | ||
1929 | static int | |
1930 | CheckModifierMap(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 | ||
1965 | static int | |
1966 | CheckVirtualModMap(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 | ||
1999 | static char * | |
2000 | SetKeyTypes(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 | ||
2087 | static char * | |
2088 | SetKeySyms(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 | ||
2156 | static char * | |
2157 | SetKeyActions(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 | ||
2192 | static char * | |
2193 | SetKeyBehaviors(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 | ||
2251 | static char * | |
2252 | SetVirtualMods(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 | ||
2273 | static char * | |
2274 | SetKeyExplicit(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 | ||
2306 | static char * | |
2307 | SetModifierMap(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 | ||
2339 | static char * | |
2340 | SetVirtualModMap(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 | */ | |
2374 | static 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 | */ | |
2489 | static 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 | ||
2604 | int | |
2605 | ProcXkbSetMap(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 | ||
2675 | static Status | |
2676 | XkbComputeGetCompatMapReplySize(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 | ||
2696 | static int | |
2697 | XkbSendCompatMap(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 | ||
2762 | int | |
2763 | ProcXkbGetCompatMap(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 | */ | |
2809 | static 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 | ||
2960 | int | |
2961 | ProcXkbSetCompatMap(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 | ||
3025 | int | |
3026 | ProcXkbGetIndicatorState(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 | ||
3063 | static Status | |
3064 | XkbComputeGetIndicatorMapReplySize(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 | ||
3080 | static int | |
3081 | XkbSendIndicatorMap(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 | ||
3140 | int | |
3141 | ProcXkbGetIndicatorMap(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 | */ | |
3174 | static 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 | ||
3216 | int | |
3217 | ProcXkbSetIndicatorMap(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 | ||
3283 | int | |
3284 | ProcXkbGetNamedIndicator(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 | */ | |
3371 | static 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 | */ | |
3397 | static 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 | ||
3435 | static 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 | ||
3505 | int | |
3506 | ProcXkbSetNamedIndicator(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 | ||
3575 | static 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 | ||
3592 | static 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 | ||
3611 | static Status | |
3612 | XkbComputeGetNamesReplySize(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 | ||
3729 | static int | |
3730 | XkbSendNames(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 | ||
3881 | int | |
3882 | ProcXkbGetNames(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 | ||
3916 | static 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 | ||
3933 | static 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 | ||
3954 | static 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 | ||
3967 | static 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 | */ | |
3983 | static 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 | ||
4133 | static 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 | ||
4292 | int | |
4293 | ProcXkbSetNames(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 | */ | |
4421 | static char * | |
4422 | XkbWriteCountedString(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 | ||
4441 | static int | |
4442 | XkbSizeGeomProperties(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 | ||
4455 | static char * | |
4456 | XkbWriteGeomProperties(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 | ||
4468 | static int | |
4469 | XkbSizeGeomKeyAliases(XkbGeometryPtr geom) | |
4470 | { | |
4471 | return geom->num_key_aliases * (2 * XkbKeyNameLength); | |
4472 | } | |
4473 | ||
4474 | static char * | |
4475 | XkbWriteGeomKeyAliases(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 | ||
4487 | static int | |
4488 | XkbSizeGeomColors(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 | ||
4499 | static char * | |
4500 | XkbWriteGeomColors(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 | ||
4511 | static int | |
4512 | XkbSizeGeomShapes(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 | ||
4530 | static char * | |
4531 | XkbWriteGeomShapes(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 | ||
4583 | static int | |
4584 | XkbSizeGeomDoodads(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 | ||
4601 | static char * | |
4602 | XkbWriteGeomDoodads(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 | ||
4665 | static char * | |
4666 | XkbWriteGeomOverlay(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 | ||
4703 | static int | |
4704 | XkbSizeGeomSections(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 | ||
4743 | static char * | |
4744 | XkbWriteGeomSections(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(§ionWire->name); | |
4766 | swaps(§ionWire->top); | |
4767 | swaps(§ionWire->left); | |
4768 | swaps(§ionWire->width); | |
4769 | swaps(§ionWire->height); | |
4770 | swaps(§ionWire->angle); | |
4771 | } | |
4772 | wire = (char *) §ionWire[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, §ion->overlays[o], swap); | |
4820 | } | |
4821 | } | |
4822 | } | |
4823 | return wire; | |
4824 | } | |
4825 | ||
4826 | static Status | |
4827 | XkbComputeGetGeometryReplySize(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 | ||
4867 | static int | |
4868 | XkbSendGeometry(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 | ||
4926 | int | |
4927 | ProcXkbGetGeometry(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 | ||
4960 | static 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 | ||
4982 | static 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 | ||
5082 | static 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 | ||
5128 | static 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 | ||
5231 | static 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 | ||
5296 | static 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 | ||
5385 | static 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 | ||
5440 | int | |
5441 | ProcXkbSetGeometry(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 | ||
5478 | int | |
5479 | ProcXkbPerClientFlags(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 */ | |
5557 | static 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 */ | |
5565 | static 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 | ||
5572 | static char * | |
5573 | GetComponentSpec(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 | ||
5616 | int | |
5617 | ProcXkbListComponents(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 | ||
5678 | int | |
5679 | ProcXkbGetKbdByName(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 | ||
6019 | static int | |
6020 | ComputeDeviceLedInfoSize(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 | ||
6047 | static int | |
6048 | CheckDeviceLedFBs(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 | ||
6115 | static int | |
6116 | SendDeviceLedInfo(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 | ||
6182 | static int | |
6183 | SendDeviceLedFBs(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 | ||
6226 | int | |
6227 | ProcXkbGetDeviceInfo(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 | ||
6368 | static char * | |
6369 | CheckSetDeviceIndicators(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 | ||
6439 | static char * | |
6440 | SetDeviceIndicators(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 | ||
6535 | static 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 | ||
6569 | static 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 | ||
6622 | int | |
6623 | ProcXkbSetDeviceInfo(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 | ||
6692 | int | |
6693 | ProcXkbSetDebuggingFlags(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 | ||
6760 | static int | |
6761 | ProcXkbDispatch(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 | ||
6822 | static int | |
6823 | XkbClientGone(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 | ||
6834 | void | |
6835 | XkbExtensionInit(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 | } |