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 <xkb-config.h>
32
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <ctype.h>
36 #include <unistd.h>
37 #include <math.h>
38 #include <X11/X.h>
39 #include <X11/Xproto.h>
40 #include <X11/keysym.h>
41 #include <X11/Xatom.h>
42 #include "misc.h"
43 #include "inputstr.h"
44 #include "opaque.h"
45 #include "property.h"
46 #include "scrnintstr.h"
47 #define XKBSRV_NEED_FILE_FUNCS
48 #include <xkbsrv.h>
49 #include "xkbgeom.h"
50 #include <X11/extensions/XKMformat.h>
51 #include "xkbfile.h"
52 #include "xkb.h"
53
54 #define CREATE_ATOM(s) MakeAtom(s,sizeof(s)-1,1)
55
56 #if defined(__alpha) || defined(__alpha__)
57 #define LED_COMPOSE 2
58 #define LED_CAPS 3
59 #define LED_SCROLL 4
60 #define LED_NUM 5
61 #define PHYS_LEDS 0x1f
62 #else
63 #ifdef __sun
64 #define LED_NUM 1
65 #define LED_SCROLL 2
66 #define LED_COMPOSE 3
67 #define LED_CAPS 4
68 #define PHYS_LEDS 0x0f
69 #else
70 #define LED_CAPS 1
71 #define LED_NUM 2
72 #define LED_SCROLL 3
73 #define PHYS_LEDS 0x07
74 #endif
75 #endif
76
77 #define MAX_TOC 16
78 typedef struct _SrvXkmInfo {
79 DeviceIntPtr dev;
80 FILE *file;
81 XkbDescPtr xkb;
82 } SrvXkmInfo;
83
84 /***====================================================================***/
85
86 #ifndef XKB_DFLT_RULES_PROP
87 #define XKB_DFLT_RULES_PROP TRUE
88 #endif
89
90 const char *XkbBaseDirectory = XKB_BASE_DIRECTORY;
91 const char *XkbBinDirectory = XKB_BIN_DIRECTORY;
92 static int XkbWantAccessX = 0;
93
94 static char *XkbRulesDflt = NULL;
95 static char *XkbModelDflt = NULL;
96 static char *XkbLayoutDflt = NULL;
97 static char *XkbVariantDflt = NULL;
98 static char *XkbOptionsDflt = NULL;
99
100 static char *XkbRulesUsed = NULL;
101 static char *XkbModelUsed = NULL;
102 static char *XkbLayoutUsed = NULL;
103 static char *XkbVariantUsed = NULL;
104 static char *XkbOptionsUsed = NULL;
105
106 static XkbDescPtr xkb_cached_map = NULL;
107
108 static Bool XkbWantRulesProp = XKB_DFLT_RULES_PROP;
109
110 /***====================================================================***/
111
112 /**
113 * Get the current default XKB rules.
114 * Caller must free the data in rmlvo.
115 */
116 void
XkbGetRulesDflts(XkbRMLVOSet * rmlvo)117 XkbGetRulesDflts(XkbRMLVOSet * rmlvo)
118 {
119 rmlvo->rules = strdup(XkbRulesDflt ? XkbRulesDflt : XKB_DFLT_RULES);
120 rmlvo->model = strdup(XkbModelDflt ? XkbModelDflt : XKB_DFLT_MODEL);
121 rmlvo->layout = strdup(XkbLayoutDflt ? XkbLayoutDflt : XKB_DFLT_LAYOUT);
122 rmlvo->variant = strdup(XkbVariantDflt ? XkbVariantDflt : XKB_DFLT_VARIANT);
123 rmlvo->options = strdup(XkbOptionsDflt ? XkbOptionsDflt : XKB_DFLT_OPTIONS);
124 }
125
126 void
XkbFreeRMLVOSet(XkbRMLVOSet * rmlvo,Bool freeRMLVO)127 XkbFreeRMLVOSet(XkbRMLVOSet * rmlvo, Bool freeRMLVO)
128 {
129 if (!rmlvo)
130 return;
131
132 free(rmlvo->rules);
133 free(rmlvo->model);
134 free(rmlvo->layout);
135 free(rmlvo->variant);
136 free(rmlvo->options);
137
138 if (freeRMLVO)
139 free(rmlvo);
140 else
141 memset(rmlvo, 0, sizeof(XkbRMLVOSet));
142 }
143
144 static Bool
XkbWriteRulesProp(ClientPtr client,void * closure)145 XkbWriteRulesProp(ClientPtr client, void *closure)
146 {
147 int len, out;
148 Atom name;
149 char *pval;
150
151 len = (XkbRulesUsed ? strlen(XkbRulesUsed) : 0);
152 len += (XkbModelUsed ? strlen(XkbModelUsed) : 0);
153 len += (XkbLayoutUsed ? strlen(XkbLayoutUsed) : 0);
154 len += (XkbVariantUsed ? strlen(XkbVariantUsed) : 0);
155 len += (XkbOptionsUsed ? strlen(XkbOptionsUsed) : 0);
156 if (len < 1)
157 return TRUE;
158
159 len += 5; /* trailing NULs */
160
161 name =
162 MakeAtom(_XKB_RF_NAMES_PROP_ATOM, strlen(_XKB_RF_NAMES_PROP_ATOM), 1);
163 if (name == None) {
164 ErrorF("[xkb] Atom error: %s not created\n", _XKB_RF_NAMES_PROP_ATOM);
165 return TRUE;
166 }
167 pval = (char *) malloc(len);
168 if (!pval) {
169 ErrorF("[xkb] Allocation error: %s proprerty not created\n",
170 _XKB_RF_NAMES_PROP_ATOM);
171 return TRUE;
172 }
173 out = 0;
174 if (XkbRulesUsed) {
175 strcpy(&pval[out], XkbRulesUsed);
176 out += strlen(XkbRulesUsed);
177 }
178 pval[out++] = '\0';
179 if (XkbModelUsed) {
180 strcpy(&pval[out], XkbModelUsed);
181 out += strlen(XkbModelUsed);
182 }
183 pval[out++] = '\0';
184 if (XkbLayoutUsed) {
185 strcpy(&pval[out], XkbLayoutUsed);
186 out += strlen(XkbLayoutUsed);
187 }
188 pval[out++] = '\0';
189 if (XkbVariantUsed) {
190 strcpy(&pval[out], XkbVariantUsed);
191 out += strlen(XkbVariantUsed);
192 }
193 pval[out++] = '\0';
194 if (XkbOptionsUsed) {
195 strcpy(&pval[out], XkbOptionsUsed);
196 out += strlen(XkbOptionsUsed);
197 }
198 pval[out++] = '\0';
199 if (out != len) {
200 ErrorF("[xkb] Internal Error! bad size (%d!=%d) for _XKB_RULES_NAMES\n",
201 out, len);
202 }
203 dixChangeWindowProperty(serverClient, screenInfo.screens[0]->root, name,
204 XA_STRING, 8, PropModeReplace, len, pval, TRUE);
205 free(pval);
206 return TRUE;
207 }
208
209 void
XkbInitRules(XkbRMLVOSet * rmlvo,const char * rules,const char * model,const char * layout,const char * variant,const char * options)210 XkbInitRules(XkbRMLVOSet *rmlvo,
211 const char *rules,
212 const char *model,
213 const char *layout,
214 const char *variant,
215 const char *options)
216 {
217 rmlvo->rules = rules ? xnfstrdup(rules) : NULL;
218 rmlvo->model = model ? xnfstrdup(model) : NULL;
219 rmlvo->layout = layout ? xnfstrdup(layout) : NULL;
220 rmlvo->variant = variant ? xnfstrdup(variant) : NULL;
221 rmlvo->options = options ? xnfstrdup(options) : NULL;
222 }
223
224 static void
XkbSetRulesUsed(XkbRMLVOSet * rmlvo)225 XkbSetRulesUsed(XkbRMLVOSet * rmlvo)
226 {
227 free(XkbRulesUsed);
228 XkbRulesUsed = (rmlvo->rules ? Xstrdup(rmlvo->rules) : NULL);
229 free(XkbModelUsed);
230 XkbModelUsed = (rmlvo->model ? Xstrdup(rmlvo->model) : NULL);
231 free(XkbLayoutUsed);
232 XkbLayoutUsed = (rmlvo->layout ? Xstrdup(rmlvo->layout) : NULL);
233 free(XkbVariantUsed);
234 XkbVariantUsed = (rmlvo->variant ? Xstrdup(rmlvo->variant) : NULL);
235 free(XkbOptionsUsed);
236 XkbOptionsUsed = (rmlvo->options ? Xstrdup(rmlvo->options) : NULL);
237 if (XkbWantRulesProp)
238 QueueWorkProc(XkbWriteRulesProp, NULL, NULL);
239 return;
240 }
241
242 void
XkbSetRulesDflts(XkbRMLVOSet * rmlvo)243 XkbSetRulesDflts(XkbRMLVOSet * rmlvo)
244 {
245 if (rmlvo->rules) {
246 free(XkbRulesDflt);
247 XkbRulesDflt = Xstrdup(rmlvo->rules);
248 }
249 if (rmlvo->model) {
250 free(XkbModelDflt);
251 XkbModelDflt = Xstrdup(rmlvo->model);
252 }
253 if (rmlvo->layout) {
254 free(XkbLayoutDflt);
255 XkbLayoutDflt = Xstrdup(rmlvo->layout);
256 }
257 if (rmlvo->variant) {
258 free(XkbVariantDflt);
259 XkbVariantDflt = Xstrdup(rmlvo->variant);
260 }
261 if (rmlvo->options) {
262 free(XkbOptionsDflt);
263 XkbOptionsDflt = Xstrdup(rmlvo->options);
264 }
265 return;
266 }
267
268 void
XkbDeleteRulesUsed(void)269 XkbDeleteRulesUsed(void)
270 {
271 free(XkbRulesUsed);
272 XkbRulesUsed = NULL;
273 free(XkbModelUsed);
274 XkbModelUsed = NULL;
275 free(XkbLayoutUsed);
276 XkbLayoutUsed = NULL;
277 free(XkbVariantUsed);
278 XkbVariantUsed = NULL;
279 free(XkbOptionsUsed);
280 XkbOptionsUsed = NULL;
281 }
282
283 void
XkbDeleteRulesDflts(void)284 XkbDeleteRulesDflts(void)
285 {
286 free(XkbRulesDflt);
287 XkbRulesDflt = NULL;
288 free(XkbModelDflt);
289 XkbModelDflt = NULL;
290 free(XkbLayoutDflt);
291 XkbLayoutDflt = NULL;
292 free(XkbVariantDflt);
293 XkbVariantDflt = NULL;
294 free(XkbOptionsDflt);
295 XkbOptionsDflt = NULL;
296
297 XkbFreeKeyboard(xkb_cached_map, XkbAllComponentsMask, TRUE);
298 xkb_cached_map = NULL;
299 }
300
301 #define DIFFERS(a, b) (strcmp((a) ? (a) : "", (b) ? (b) : "") != 0)
302
303 static Bool
XkbCompareUsedRMLVO(XkbRMLVOSet * rmlvo)304 XkbCompareUsedRMLVO(XkbRMLVOSet * rmlvo)
305 {
306 if (DIFFERS(rmlvo->rules, XkbRulesUsed) ||
307 DIFFERS(rmlvo->model, XkbModelUsed) ||
308 DIFFERS(rmlvo->layout, XkbLayoutUsed) ||
309 DIFFERS(rmlvo->variant, XkbVariantUsed) ||
310 DIFFERS(rmlvo->options, XkbOptionsUsed))
311 return FALSE;
312 return TRUE;
313 }
314
315 #undef DIFFERS
316
317 /***====================================================================***/
318
319 #include "xkbDflts.h"
320
321 static Bool
XkbInitKeyTypes(XkbDescPtr xkb)322 XkbInitKeyTypes(XkbDescPtr xkb)
323 {
324 if (xkb->defined & XkmTypesMask)
325 return TRUE;
326
327 initTypeNames(NULL);
328 if (XkbAllocClientMap(xkb, XkbKeyTypesMask, num_dflt_types) != Success)
329 return FALSE;
330 if (XkbCopyKeyTypes(dflt_types, xkb->map->types, num_dflt_types) != Success) {
331 return FALSE;
332 }
333 xkb->map->size_types = xkb->map->num_types = num_dflt_types;
334 return TRUE;
335 }
336
337 static void
XkbInitRadioGroups(XkbSrvInfoPtr xkbi)338 XkbInitRadioGroups(XkbSrvInfoPtr xkbi)
339 {
340 xkbi->nRadioGroups = 0;
341 xkbi->radioGroups = NULL;
342 return;
343 }
344
345 static Status
XkbInitCompatStructs(XkbDescPtr xkb)346 XkbInitCompatStructs(XkbDescPtr xkb)
347 {
348 register int i;
349 XkbCompatMapPtr compat;
350
351 if (xkb->defined & XkmCompatMapMask)
352 return TRUE;
353
354 if (XkbAllocCompatMap(xkb, XkbAllCompatMask, num_dfltSI) != Success)
355 return BadAlloc;
356 compat = xkb->compat;
357 if (compat->sym_interpret) {
358 compat->num_si = num_dfltSI;
359 memcpy((char *) compat->sym_interpret, (char *) dfltSI, sizeof(dfltSI));
360 }
361 for (i = 0; i < XkbNumKbdGroups; i++) {
362 compat->groups[i] = compatMap.groups[i];
363 if (compat->groups[i].vmods != 0) {
364 unsigned mask;
365
366 mask = XkbMaskForVMask(xkb, compat->groups[i].vmods);
367 compat->groups[i].mask = compat->groups[i].real_mods | mask;
368 }
369 else
370 compat->groups[i].mask = compat->groups[i].real_mods;
371 }
372 return Success;
373 }
374
375 static void
XkbInitSemantics(XkbDescPtr xkb)376 XkbInitSemantics(XkbDescPtr xkb)
377 {
378 XkbInitKeyTypes(xkb);
379 XkbInitCompatStructs(xkb);
380 return;
381 }
382
383 /***====================================================================***/
384
385 static Status
XkbInitNames(XkbSrvInfoPtr xkbi)386 XkbInitNames(XkbSrvInfoPtr xkbi)
387 {
388 XkbDescPtr xkb;
389 XkbNamesPtr names;
390 Status rtrn;
391 Atom unknown;
392
393 xkb = xkbi->desc;
394 if ((rtrn = XkbAllocNames(xkb, XkbAllNamesMask, 0, 0)) != Success)
395 return rtrn;
396 unknown = CREATE_ATOM("unknown");
397 names = xkb->names;
398 if (names->keycodes == None)
399 names->keycodes = unknown;
400 if (names->geometry == None)
401 names->geometry = unknown;
402 if (names->phys_symbols == None)
403 names->phys_symbols = unknown;
404 if (names->symbols == None)
405 names->symbols = unknown;
406 if (names->types == None)
407 names->types = unknown;
408 if (names->compat == None)
409 names->compat = unknown;
410 if (!(xkb->defined & XkmVirtualModsMask)) {
411 if (names->vmods[vmod_NumLock] == None)
412 names->vmods[vmod_NumLock] = CREATE_ATOM("NumLock");
413 if (names->vmods[vmod_Alt] == None)
414 names->vmods[vmod_Alt] = CREATE_ATOM("Alt");
415 if (names->vmods[vmod_AltGr] == None)
416 names->vmods[vmod_AltGr] = CREATE_ATOM("ModeSwitch");
417 }
418
419 if (!(xkb->defined & XkmIndicatorsMask) ||
420 !(xkb->defined & XkmGeometryMask)) {
421 initIndicatorNames(NULL, xkb);
422 if (names->indicators[LED_CAPS - 1] == None)
423 names->indicators[LED_CAPS - 1] = CREATE_ATOM("Caps Lock");
424 if (names->indicators[LED_NUM - 1] == None)
425 names->indicators[LED_NUM - 1] = CREATE_ATOM("Num Lock");
426 if (names->indicators[LED_SCROLL - 1] == None)
427 names->indicators[LED_SCROLL - 1] = CREATE_ATOM("Scroll Lock");
428 #ifdef LED_COMPOSE
429 if (names->indicators[LED_COMPOSE - 1] == None)
430 names->indicators[LED_COMPOSE - 1] = CREATE_ATOM("Compose");
431 #endif
432 }
433
434 if (xkb->geom != NULL)
435 names->geometry = xkb->geom->name;
436 else
437 names->geometry = unknown;
438
439 return Success;
440 }
441
442 static Status
XkbInitIndicatorMap(XkbSrvInfoPtr xkbi)443 XkbInitIndicatorMap(XkbSrvInfoPtr xkbi)
444 {
445 XkbDescPtr xkb;
446 XkbIndicatorPtr map;
447 XkbSrvLedInfoPtr sli;
448
449 xkb = xkbi->desc;
450 if (XkbAllocIndicatorMaps(xkb) != Success)
451 return BadAlloc;
452
453 if (!(xkb->defined & XkmIndicatorsMask)) {
454 map = xkb->indicators;
455 map->phys_indicators = PHYS_LEDS;
456 map->maps[LED_CAPS - 1].flags = XkbIM_NoExplicit;
457 map->maps[LED_CAPS - 1].which_mods = XkbIM_UseLocked;
458 map->maps[LED_CAPS - 1].mods.mask = LockMask;
459 map->maps[LED_CAPS - 1].mods.real_mods = LockMask;
460
461 map->maps[LED_NUM - 1].flags = XkbIM_NoExplicit;
462 map->maps[LED_NUM - 1].which_mods = XkbIM_UseLocked;
463 map->maps[LED_NUM - 1].mods.mask = 0;
464 map->maps[LED_NUM - 1].mods.real_mods = 0;
465 map->maps[LED_NUM - 1].mods.vmods = vmod_NumLockMask;
466
467 map->maps[LED_SCROLL - 1].flags = XkbIM_NoExplicit;
468 map->maps[LED_SCROLL - 1].which_mods = XkbIM_UseLocked;
469 map->maps[LED_SCROLL - 1].mods.mask = Mod3Mask;
470 map->maps[LED_SCROLL - 1].mods.real_mods = Mod3Mask;
471 }
472
473 sli = XkbFindSrvLedInfo(xkbi->device, XkbDfltXIClass, XkbDfltXIId, 0);
474 if (sli)
475 XkbCheckIndicatorMaps(xkbi->device, sli, XkbAllIndicatorsMask);
476
477 return Success;
478 }
479
480 static Status
XkbInitControls(DeviceIntPtr pXDev,XkbSrvInfoPtr xkbi)481 XkbInitControls(DeviceIntPtr pXDev, XkbSrvInfoPtr xkbi)
482 {
483 XkbDescPtr xkb;
484 XkbControlsPtr ctrls;
485
486 xkb = xkbi->desc;
487 /* 12/31/94 (ef) -- XXX! Should check if controls loaded from file */
488 if (XkbAllocControls(xkb, XkbAllControlsMask) != Success)
489 FatalError("Couldn't allocate keyboard controls\n");
490 ctrls = xkb->ctrls;
491 if (!(xkb->defined & XkmSymbolsMask))
492 ctrls->num_groups = 1;
493 ctrls->groups_wrap = XkbSetGroupInfo(1, XkbWrapIntoRange, 0);
494 ctrls->internal.mask = 0;
495 ctrls->internal.real_mods = 0;
496 ctrls->internal.vmods = 0;
497 ctrls->ignore_lock.mask = 0;
498 ctrls->ignore_lock.real_mods = 0;
499 ctrls->ignore_lock.vmods = 0;
500 ctrls->enabled_ctrls = XkbAccessXTimeoutMask | XkbRepeatKeysMask |
501 XkbMouseKeysAccelMask | XkbAudibleBellMask | XkbIgnoreGroupLockMask;
502 if (XkbWantAccessX)
503 ctrls->enabled_ctrls |= XkbAccessXKeysMask;
504 AccessXInit(pXDev);
505 return Success;
506 }
507
508 static Status
XkbInitOverlayState(XkbSrvInfoPtr xkbi)509 XkbInitOverlayState(XkbSrvInfoPtr xkbi)
510 {
511 memset(xkbi->overlay_perkey_state, 0, sizeof(xkbi->overlay_perkey_state));
512 return Success;
513 }
514
515 static Bool
InitKeyboardDeviceStructInternal(DeviceIntPtr dev,XkbRMLVOSet * rmlvo,const char * keymap,int keymap_length,BellProcPtr bell_func,KbdCtrlProcPtr ctrl_func)516 InitKeyboardDeviceStructInternal(DeviceIntPtr dev, XkbRMLVOSet * rmlvo,
517 const char *keymap, int keymap_length,
518 BellProcPtr bell_func, KbdCtrlProcPtr ctrl_func)
519 {
520 int i;
521 unsigned int check;
522 XkbSrvInfoPtr xkbi;
523 XkbDescPtr xkb;
524 XkbSrvLedInfoPtr sli;
525 XkbChangesRec changes;
526 XkbEventCauseRec cause;
527 XkbRMLVOSet rmlvo_dflts = { NULL };
528
529 BUG_RETURN_VAL(dev == NULL, FALSE);
530 BUG_RETURN_VAL(dev->key != NULL, FALSE);
531 BUG_RETURN_VAL(dev->kbdfeed != NULL, FALSE);
532 BUG_RETURN_VAL(rmlvo && keymap, FALSE);
533
534 if (!rmlvo && !keymap) {
535 rmlvo = &rmlvo_dflts;
536 XkbGetRulesDflts(rmlvo);
537 }
538
539 memset(&changes, 0, sizeof(changes));
540 XkbSetCauseUnknown(&cause);
541
542 dev->key = calloc(1, sizeof(*dev->key));
543 if (!dev->key) {
544 ErrorF("XKB: Failed to allocate key class\n");
545 return FALSE;
546 }
547 dev->key->sourceid = dev->id;
548
549 dev->kbdfeed = calloc(1, sizeof(*dev->kbdfeed));
550 if (!dev->kbdfeed) {
551 ErrorF("XKB: Failed to allocate key feedback class\n");
552 goto unwind_key;
553 }
554
555 xkbi = calloc(1, sizeof(*xkbi));
556 if (!xkbi) {
557 ErrorF("XKB: Failed to allocate XKB info\n");
558 goto unwind_kbdfeed;
559 }
560 dev->key->xkbInfo = xkbi;
561
562 if (xkb_cached_map && (keymap || (rmlvo && !XkbCompareUsedRMLVO(rmlvo)))) {
563 XkbFreeKeyboard(xkb_cached_map, XkbAllComponentsMask, TRUE);
564 xkb_cached_map = NULL;
565 }
566
567 if (xkb_cached_map)
568 LogMessageVerb(X_INFO, 4, "XKB: Reusing cached keymap\n");
569 else {
570 if (rmlvo)
571 xkb_cached_map = XkbCompileKeymap(dev, rmlvo);
572 else
573 xkb_cached_map = XkbCompileKeymapFromString(dev, keymap, keymap_length);
574
575 if (!xkb_cached_map) {
576 ErrorF("XKB: Failed to compile keymap\n");
577 goto unwind_info;
578 }
579 }
580
581 xkb = XkbAllocKeyboard();
582 if (!xkb) {
583 ErrorF("XKB: Failed to allocate keyboard description\n");
584 goto unwind_info;
585 }
586
587 if (!XkbCopyKeymap(xkb, xkb_cached_map)) {
588 ErrorF("XKB: Failed to copy keymap\n");
589 goto unwind_desc;
590 }
591 xkb->defined = xkb_cached_map->defined;
592 xkb->flags = xkb_cached_map->flags;
593 xkb->device_spec = xkb_cached_map->device_spec;
594 xkbi->desc = xkb;
595
596 if (xkb->min_key_code == 0)
597 xkb->min_key_code = 8;
598 if (xkb->max_key_code == 0)
599 xkb->max_key_code = 255;
600
601 i = XkbNumKeys(xkb) / 3 + 1;
602 if (XkbAllocClientMap(xkb, XkbAllClientInfoMask, 0) != Success)
603 goto unwind_desc;
604 if (XkbAllocServerMap(xkb, XkbAllServerInfoMask, i) != Success)
605 goto unwind_desc;
606
607 xkbi->dfltPtrDelta = 1;
608 xkbi->device = dev;
609
610 XkbInitSemantics(xkb);
611 XkbInitNames(xkbi);
612 XkbInitRadioGroups(xkbi);
613
614 XkbInitControls(dev, xkbi);
615
616 XkbInitIndicatorMap(xkbi);
617
618 XkbInitOverlayState(xkbi);
619
620 XkbUpdateActions(dev, xkb->min_key_code, XkbNumKeys(xkb), &changes,
621 &check, &cause);
622
623 if (!dev->focus)
624 InitFocusClassDeviceStruct(dev);
625
626 xkbi->kbdProc = ctrl_func;
627 dev->kbdfeed->BellProc = bell_func;
628 dev->kbdfeed->CtrlProc = XkbDDXKeybdCtrlProc;
629
630 dev->kbdfeed->ctrl = defaultKeyboardControl;
631 if (dev->kbdfeed->ctrl.autoRepeat)
632 xkb->ctrls->enabled_ctrls |= XkbRepeatKeysMask;
633
634 memcpy(dev->kbdfeed->ctrl.autoRepeats, xkb->ctrls->per_key_repeat,
635 XkbPerKeyBitArraySize);
636
637 sli = XkbFindSrvLedInfo(dev, XkbDfltXIClass, XkbDfltXIId, 0);
638 if (sli)
639 XkbCheckIndicatorMaps(dev, sli, XkbAllIndicatorsMask);
640 else
641 DebugF("XKB: No indicator feedback in XkbFinishInit!\n");
642
643 dev->kbdfeed->CtrlProc(dev, &dev->kbdfeed->ctrl);
644
645 if (rmlvo) {
646 XkbSetRulesDflts(rmlvo);
647 XkbSetRulesUsed(rmlvo);
648 }
649 XkbFreeRMLVOSet(&rmlvo_dflts, FALSE);
650
651 return TRUE;
652
653 unwind_desc:
654 XkbFreeKeyboard(xkb, 0, TRUE);
655 unwind_info:
656 free(xkbi);
657 dev->key->xkbInfo = NULL;
658 unwind_kbdfeed:
659 free(dev->kbdfeed);
660 dev->kbdfeed = NULL;
661 unwind_key:
662 free(dev->key);
663 dev->key = NULL;
664 return FALSE;
665 }
666
667 _X_EXPORT Bool
InitKeyboardDeviceStruct(DeviceIntPtr dev,XkbRMLVOSet * rmlvo,BellProcPtr bell_func,KbdCtrlProcPtr ctrl_func)668 InitKeyboardDeviceStruct(DeviceIntPtr dev, XkbRMLVOSet * rmlvo,
669 BellProcPtr bell_func, KbdCtrlProcPtr ctrl_func)
670 {
671 return InitKeyboardDeviceStructInternal(dev, rmlvo,
672 NULL, 0, bell_func, ctrl_func);
673 }
674
675 _X_EXPORT Bool
InitKeyboardDeviceStructFromString(DeviceIntPtr dev,const char * keymap,int keymap_length,BellProcPtr bell_func,KbdCtrlProcPtr ctrl_func)676 InitKeyboardDeviceStructFromString(DeviceIntPtr dev,
677 const char *keymap, int keymap_length,
678 BellProcPtr bell_func, KbdCtrlProcPtr ctrl_func)
679 {
680 return InitKeyboardDeviceStructInternal(dev, NULL,
681 keymap, keymap_length,
682 bell_func, ctrl_func);
683 }
684
685 /***====================================================================***/
686
687 /*
688 * Be very careful about what does and doesn't get freed by this
689 * function. To reduce fragmentation, XkbInitDevice allocates a
690 * single huge block per device and divides it up into most of the
691 * fixed-size structures for the device. Don't free anything that
692 * is part of this larger block.
693 */
694 void
XkbFreeInfo(XkbSrvInfoPtr xkbi)695 XkbFreeInfo(XkbSrvInfoPtr xkbi)
696 {
697 free(xkbi->radioGroups);
698 xkbi->radioGroups = NULL;
699 if (xkbi->mouseKeyTimer) {
700 TimerFree(xkbi->mouseKeyTimer);
701 xkbi->mouseKeyTimer = NULL;
702 }
703 if (xkbi->slowKeysTimer) {
704 TimerFree(xkbi->slowKeysTimer);
705 xkbi->slowKeysTimer = NULL;
706 }
707 if (xkbi->bounceKeysTimer) {
708 TimerFree(xkbi->bounceKeysTimer);
709 xkbi->bounceKeysTimer = NULL;
710 }
711 if (xkbi->repeatKeyTimer) {
712 TimerFree(xkbi->repeatKeyTimer);
713 xkbi->repeatKeyTimer = NULL;
714 }
715 if (xkbi->krgTimer) {
716 TimerFree(xkbi->krgTimer);
717 xkbi->krgTimer = NULL;
718 }
719 xkbi->beepType = _BEEP_NONE;
720 if (xkbi->beepTimer) {
721 TimerFree(xkbi->beepTimer);
722 xkbi->beepTimer = NULL;
723 }
724 if (xkbi->desc) {
725 XkbFreeKeyboard(xkbi->desc, XkbAllComponentsMask, TRUE);
726 xkbi->desc = NULL;
727 }
728 free(xkbi);
729 return;
730 }
731
732 /***====================================================================***/
733
734 extern int XkbDfltRepeatDelay;
735 extern int XkbDfltRepeatInterval;
736
737 extern unsigned short XkbDfltAccessXTimeout;
738 extern unsigned int XkbDfltAccessXTimeoutMask;
739 extern unsigned int XkbDfltAccessXFeedback;
740 extern unsigned short XkbDfltAccessXOptions;
741
742 int
XkbProcessArguments(int argc,char * argv[],int i)743 XkbProcessArguments(int argc, char *argv[], int i)
744 {
745 if (strncmp(argv[i], "-xkbdir", 7) == 0) {
746 if (++i < argc) {
747 #if !defined(WIN32) && !defined(__CYGWIN__)
748 if (getuid() != geteuid()) {
749 LogMessage(X_WARNING,
750 "-xkbdir is not available for setuid X servers\n");
751 return -1;
752 }
753 else
754 #endif
755 {
756 if (strlen(argv[i]) < PATH_MAX) {
757 XkbBaseDirectory = argv[i];
758 return 2;
759 }
760 else {
761 LogMessage(X_ERROR, "-xkbdir pathname too long\n");
762 return -1;
763 }
764 }
765 }
766 else {
767 return -1;
768 }
769 }
770 else if ((strncmp(argv[i], "-accessx", 8) == 0) ||
771 (strncmp(argv[i], "+accessx", 8) == 0)) {
772 int j = 1;
773
774 if (argv[i][0] == '-')
775 XkbWantAccessX = 0;
776 else {
777 XkbWantAccessX = 1;
778
779 if (((i + 1) < argc) && (isdigit(argv[i + 1][0]))) {
780 XkbDfltAccessXTimeout = atoi(argv[++i]);
781 j++;
782
783 if (((i + 1) < argc) && (isdigit(argv[i + 1][0]))) {
784 /*
785 * presumption that the reasonably useful range of
786 * values fits in 0..MAXINT since SunOS 4 doesn't
787 * have strtoul.
788 */
789 XkbDfltAccessXTimeoutMask = (unsigned int)
790 strtol(argv[++i], NULL, 16);
791 j++;
792 }
793 if (((i + 1) < argc) && (isdigit(argv[i + 1][0]))) {
794 if (argv[++i][0] == '1')
795 XkbDfltAccessXFeedback = XkbAccessXFeedbackMask;
796 else
797 XkbDfltAccessXFeedback = 0;
798 j++;
799 }
800 if (((i + 1) < argc) && (isdigit(argv[i + 1][0]))) {
801 XkbDfltAccessXOptions = (unsigned short)
802 strtol(argv[++i], NULL, 16);
803 j++;
804 }
805 }
806 }
807 return j;
808 }
809 if ((strcmp(argv[i], "-ardelay") == 0) || (strcmp(argv[i], "-ar1") == 0)) { /* -ardelay int */
810 if (++i >= argc)
811 UseMsg();
812 else
813 XkbDfltRepeatDelay = (long) atoi(argv[i]);
814 return 2;
815 }
816 if ((strcmp(argv[i], "-arinterval") == 0) || (strcmp(argv[i], "-ar2") == 0)) { /* -arinterval int */
817 if (++i >= argc)
818 UseMsg();
819 else
820 XkbDfltRepeatInterval = (long) atoi(argv[i]);
821 return 2;
822 }
823 return 0;
824 }
825
826 void
XkbUseMsg(void)827 XkbUseMsg(void)
828 {
829 ErrorF
830 ("[+-]accessx [ timeout [ timeout_mask [ feedback [ options_mask] ] ] ]\n");
831 ErrorF(" enable/disable accessx key sequences\n");
832 ErrorF("-ardelay set XKB autorepeat delay\n");
833 ErrorF("-arinterval set XKB autorepeat interval\n");
834 }
835