xkbInit.c revision 1b5d61b8
1/************************************************************ 2Copyright (c) 1993 by Silicon Graphics Computer Systems, Inc. 3 4Permission to use, copy, modify, and distribute this 5software and its documentation for any purpose and without 6fee is hereby granted, provided that the above copyright 7notice appear in all copies and that both that copyright 8notice and this permission notice appear in supporting 9documentation, and that the name of Silicon Graphics not be 10used in advertising or publicity pertaining to distribution 11of the software without specific prior written permission. 12Silicon Graphics makes no representation about the suitability 13of this software for any purpose. It is provided "as is" 14without any express or implied warranty. 15 16SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS 17SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 18AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON 19GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL 20DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 21DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 22OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH 23THE USE OR PERFORMANCE OF THIS SOFTWARE. 24 25********************************************************/ 26 27#ifdef HAVE_DIX_CONFIG_H 28#include <dix-config.h> 29#endif 30 31#include <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 78typedef 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 90const char *XkbBaseDirectory = XKB_BASE_DIRECTORY; 91const char *XkbBinDirectory = XKB_BIN_DIRECTORY; 92static int XkbWantAccessX = 0; 93 94static char *XkbRulesDflt = NULL; 95static char *XkbModelDflt = NULL; 96static char *XkbLayoutDflt = NULL; 97static char *XkbVariantDflt = NULL; 98static char *XkbOptionsDflt = NULL; 99 100static char *XkbRulesUsed = NULL; 101static char *XkbModelUsed = NULL; 102static char *XkbLayoutUsed = NULL; 103static char *XkbVariantUsed = NULL; 104static char *XkbOptionsUsed = NULL; 105 106static XkbDescPtr xkb_cached_map = NULL; 107 108static 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 */ 116void 117XkbGetRulesDflts(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 126void 127XkbFreeRMLVOSet(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 144static Bool 145XkbWriteRulesProp(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 209void 210XkbInitRules(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 224static void 225XkbSetRulesUsed(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 242void 243XkbSetRulesDflts(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 268void 269XkbDeleteRulesUsed(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 283void 284XkbDeleteRulesDflts(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 303static Bool 304XkbCompareUsedRMLVO(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 321static Bool 322XkbInitKeyTypes(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 337static void 338XkbInitRadioGroups(XkbSrvInfoPtr xkbi) 339{ 340 xkbi->nRadioGroups = 0; 341 xkbi->radioGroups = NULL; 342 return; 343} 344 345static Status 346XkbInitCompatStructs(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 375static void 376XkbInitSemantics(XkbDescPtr xkb) 377{ 378 XkbInitKeyTypes(xkb); 379 XkbInitCompatStructs(xkb); 380 return; 381} 382 383/***====================================================================***/ 384 385static Status 386XkbInitNames(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 442static Status 443XkbInitIndicatorMap(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 480static Status 481XkbInitControls(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 508static Status 509XkbInitOverlayState(XkbSrvInfoPtr xkbi) 510{ 511 memset(xkbi->overlay_perkey_state, 0, sizeof(xkbi->overlay_perkey_state)); 512 return Success; 513} 514 515static Bool 516InitKeyboardDeviceStructInternal(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 668InitKeyboardDeviceStruct(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 676InitKeyboardDeviceStructFromString(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 */ 694void 695XkbFreeInfo(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 734extern int XkbDfltRepeatDelay; 735extern int XkbDfltRepeatInterval; 736 737extern unsigned short XkbDfltAccessXTimeout; 738extern unsigned int XkbDfltAccessXTimeoutMask; 739extern unsigned int XkbDfltAccessXFeedback; 740extern unsigned short XkbDfltAccessXOptions; 741 742int 743XkbProcessArguments(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 826void 827XkbUseMsg(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