xkbInit.c revision 4642e01f
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#ifdef HAVE_XKB_CONFIG_H 32#include <xkb-config.h> 33#endif 34 35#include <stdio.h> 36#include <stdlib.h> 37#include <ctype.h> 38#include <unistd.h> 39#include <math.h> 40#define NEED_EVENTS 1 41#include <X11/X.h> 42#include <X11/Xproto.h> 43#include <X11/keysym.h> 44#include <X11/Xatom.h> 45#include "misc.h" 46#include "inputstr.h" 47#include "opaque.h" 48#include "property.h" 49#define XKBSRV_NEED_FILE_FUNCS 50#include <xkbsrv.h> 51#include "xkbgeom.h" 52#include <X11/extensions/XKMformat.h> 53#include "xkbfile.h" 54#include "xkb.h" 55 56#define CREATE_ATOM(s) MakeAtom(s,sizeof(s)-1,1) 57 58#if defined(__alpha) || defined(__alpha__) 59#define LED_COMPOSE 2 60#define LED_CAPS 3 61#define LED_SCROLL 4 62#define LED_NUM 5 63#define PHYS_LEDS 0x1f 64#else 65#ifdef sun 66#define LED_NUM 1 67#define LED_SCROLL 2 68#define LED_COMPOSE 3 69#define LED_CAPS 4 70#define PHYS_LEDS 0x0f 71#else 72#define LED_CAPS 1 73#define LED_NUM 2 74#define LED_SCROLL 3 75#define PHYS_LEDS 0x07 76#endif 77#endif 78 79#define MAX_TOC 16 80typedef struct _SrvXkmInfo { 81 DeviceIntPtr dev; 82 FILE * file; 83 XkbDescPtr xkb; 84} SrvXkmInfo; 85 86 87/***====================================================================***/ 88 89#ifndef XKB_BASE_DIRECTORY 90#define XKB_BASE_DIRECTORY "/usr/lib/X11/xkb" 91#endif 92#ifndef XKB_BIN_DIRECTORY 93#define XKB_BIN_DIRECTORY XKB_BASE_DIRECTORY 94#endif 95#ifndef XKB_DFLT_RULES_FILE 96#define XKB_DFLT_RULES_FILE "base" 97#endif 98#ifndef XKB_DFLT_KB_LAYOUT 99#define XKB_DFLT_KB_LAYOUT "us" 100#endif 101#ifndef XKB_DFLT_KB_MODEL 102#define XKB_DFLT_KB_MODEL "dflt" 103#endif 104#ifndef XKB_DFLT_KB_VARIANT 105#define XKB_DFLT_KB_VARIANT NULL 106#endif 107#ifndef XKB_DFLT_KB_OPTIONS 108#define XKB_DFLT_KB_OPTIONS NULL 109#endif 110#ifndef XKB_DFLT_DISABLED 111#define XKB_DFLT_DISABLED True 112#endif 113#ifndef XKB_DFLT_RULES_PROP 114#define XKB_DFLT_RULES_PROP True 115#endif 116 117char * XkbBaseDirectory= XKB_BASE_DIRECTORY; 118char * XkbBinDirectory= XKB_BIN_DIRECTORY; 119static int XkbWantAccessX= 0; 120 121static Bool rulesDefined= False; 122static char * XkbRulesFile= NULL; 123static char * XkbModelDflt= NULL; 124static char * XkbLayoutDflt= NULL; 125static char * XkbVariantDflt= NULL; 126static char * XkbOptionsDflt= NULL; 127 128static char * XkbModelUsed= NULL; 129static char * XkbLayoutUsed= NULL; 130static char * XkbVariantUsed= NULL; 131static char * XkbOptionsUsed= NULL; 132 133static XkbDescPtr xkb_cached_map = NULL; 134 135_X_EXPORT Bool noXkbExtension= XKB_DFLT_DISABLED; 136static Bool XkbWantRulesProp= XKB_DFLT_RULES_PROP; 137 138/***====================================================================***/ 139 140static char * 141XkbGetRulesDflts(XkbRF_VarDefsPtr defs) 142{ 143 if (XkbModelDflt) defs->model= XkbModelDflt; 144 else defs->model= XKB_DFLT_KB_MODEL; 145 if (XkbLayoutDflt) defs->layout= XkbLayoutDflt; 146 else defs->layout= XKB_DFLT_KB_LAYOUT; 147 if (XkbVariantDflt) defs->variant= XkbVariantDflt; 148 else defs->variant= XKB_DFLT_KB_VARIANT; 149 if (XkbOptionsDflt) defs->options= XkbOptionsDflt; 150 else defs->options= XKB_DFLT_KB_OPTIONS; 151 return (rulesDefined?XkbRulesFile:XKB_DFLT_RULES_FILE); 152} 153 154static Bool 155XkbWriteRulesProp(ClientPtr client, pointer closure) 156{ 157int len,out; 158Atom name; 159char * pval; 160 161 if (rulesDefined && (!XkbRulesFile)) 162 return False; 163 len= (XkbRulesFile?strlen(XkbRulesFile):strlen(XKB_DFLT_RULES_FILE)); 164 len+= (XkbModelUsed?strlen(XkbModelUsed):0); 165 len+= (XkbLayoutUsed?strlen(XkbLayoutUsed):0); 166 len+= (XkbVariantUsed?strlen(XkbVariantUsed):0); 167 len+= (XkbOptionsUsed?strlen(XkbOptionsUsed):0); 168 if (len<1) 169 return True; 170 171 len+= 5; /* trailing NULs */ 172 173 name= MakeAtom(_XKB_RF_NAMES_PROP_ATOM,strlen(_XKB_RF_NAMES_PROP_ATOM),1); 174 if (name==None) { 175 ErrorF("[xkb] Atom error: %s not created\n",_XKB_RF_NAMES_PROP_ATOM); 176 return True; 177 } 178 pval= (char*) xalloc(len); 179 if (!pval) { 180 ErrorF("[xkb] Allocation error: %s proprerty not created\n", 181 _XKB_RF_NAMES_PROP_ATOM); 182 return True; 183 } 184 out= 0; 185 if (XkbRulesFile) { 186 strcpy(&pval[out],XkbRulesFile); 187 out+= strlen(XkbRulesFile); 188 } else { 189 strcpy(&pval[out],XKB_DFLT_RULES_FILE); 190 out+= strlen(XKB_DFLT_RULES_FILE); 191 } 192 pval[out++]= '\0'; 193 if (XkbModelUsed) { 194 strcpy(&pval[out],XkbModelUsed); 195 out+= strlen(XkbModelUsed); 196 } 197 pval[out++]= '\0'; 198 if (XkbLayoutUsed) { 199 strcpy(&pval[out],XkbLayoutUsed); 200 out+= strlen(XkbLayoutUsed); 201 } 202 pval[out++]= '\0'; 203 if (XkbVariantUsed) { 204 strcpy(&pval[out],XkbVariantUsed); 205 out+= strlen(XkbVariantUsed); 206 } 207 pval[out++]= '\0'; 208 if (XkbOptionsUsed) { 209 strcpy(&pval[out],XkbOptionsUsed); 210 out+= strlen(XkbOptionsUsed); 211 } 212 pval[out++]= '\0'; 213 if (out!=len) { 214 ErrorF("[xkb] Internal Error! bad size (%d!=%d) for _XKB_RULES_NAMES\n", 215 out,len); 216 } 217 dixChangeWindowProperty(serverClient, WindowTable[0], name, XA_STRING, 8, 218 PropModeReplace, len, pval, True); 219 xfree(pval); 220 return True; 221} 222 223static void 224XkbSetRulesUsed(XkbRF_VarDefsPtr defs) 225{ 226 if (XkbModelUsed) 227 _XkbFree(XkbModelUsed); 228 XkbModelUsed= (defs->model?_XkbDupString(defs->model):NULL); 229 if (XkbLayoutUsed) 230 _XkbFree(XkbLayoutUsed); 231 XkbLayoutUsed= (defs->layout?_XkbDupString(defs->layout):NULL); 232 if (XkbVariantUsed) 233 _XkbFree(XkbVariantUsed); 234 XkbVariantUsed= (defs->variant?_XkbDupString(defs->variant):NULL); 235 if (XkbOptionsUsed) 236 _XkbFree(XkbOptionsUsed); 237 XkbOptionsUsed= (defs->options?_XkbDupString(defs->options):NULL); 238 if (XkbWantRulesProp) 239 QueueWorkProc(XkbWriteRulesProp,NULL,NULL); 240 return; 241} 242 243/** 244 * Set the default RMLVO for the next device to be initialised. 245 * If a parameter is NULL, the previous setting will be used. Use empty 246 * strings if you want to delete a previous setting. 247 * 248 * If @rulesFile is NULL and no previous @rulesFile has been set, the 249 * built-in default is chosen as default. 250 */ 251_X_EXPORT void 252XkbSetRulesDflts(char *rulesFile,char *model,char *layout, 253 char *variant,char *options) 254{ 255 if (!rulesFile && !XkbRulesFile) 256 { 257 LogMessage(X_WARNING, "[xkb] No rule given, and no previous rule " 258 "defined. Defaulting to '%s'.\n", 259 XKB_DFLT_RULES_FILE); 260 rulesFile = XKB_DFLT_RULES_FILE; 261 } 262 263 if (rulesFile) { 264 if (XkbRulesFile) 265 _XkbFree(XkbRulesFile); 266 XkbRulesFile= _XkbDupString(rulesFile); 267 rulesDefined= True; 268 } 269 270 if (model) { 271 if (XkbModelDflt) 272 _XkbFree(XkbModelDflt); 273 XkbModelDflt= _XkbDupString(model); 274 } 275 if (layout) { 276 if (XkbLayoutDflt) 277 _XkbFree(XkbLayoutDflt); 278 XkbLayoutDflt= _XkbDupString(layout); 279 } 280 if (variant) { 281 if (XkbVariantDflt) 282 _XkbFree(XkbVariantDflt); 283 XkbVariantDflt= _XkbDupString(variant); 284 } 285 if (options) { 286 if (XkbOptionsDflt) 287 _XkbFree(XkbOptionsDflt); 288 XkbOptionsDflt= _XkbDupString(options); 289 } 290 return; 291} 292 293void 294XkbDeleteRulesDflts() 295{ 296 _XkbFree(XkbRulesFile); 297 XkbRulesFile = NULL; 298 _XkbFree(XkbModelDflt); 299 XkbModelDflt = NULL; 300 _XkbFree(XkbLayoutDflt); 301 XkbLayoutDflt = NULL; 302 _XkbFree(XkbVariantDflt); 303 XkbVariantDflt = NULL; 304 _XkbFree(XkbOptionsDflt); 305 XkbOptionsDflt = NULL; 306 307 XkbFreeKeyboard(xkb_cached_map, XkbAllComponentsMask, True); 308 xkb_cached_map = NULL; 309} 310 311/***====================================================================***/ 312 313#include "xkbDflts.h" 314 315static Bool 316XkbInitKeyTypes(XkbDescPtr xkb) 317{ 318 if (xkb->defined & XkmTypesMask) 319 return True; 320 321 initTypeNames(NULL); 322 if (XkbAllocClientMap(xkb,XkbKeyTypesMask,num_dflt_types)!=Success) 323 return False; 324 if (XkbCopyKeyTypes(dflt_types,xkb->map->types,num_dflt_types)!= 325 Success) { 326 return False; 327 } 328 xkb->map->size_types= xkb->map->num_types= num_dflt_types; 329 return True; 330} 331 332static void 333XkbInitRadioGroups(XkbSrvInfoPtr xkbi) 334{ 335 xkbi->nRadioGroups = 0; 336 xkbi->radioGroups = NULL; 337 return; 338} 339 340 341static Status 342XkbInitCompatStructs(XkbDescPtr xkb) 343{ 344register int i; 345XkbCompatMapPtr compat; 346 347 if (xkb->defined & XkmCompatMapMask) 348 return True; 349 350 if (XkbAllocCompatMap(xkb,XkbAllCompatMask,num_dfltSI)!=Success) 351 return BadAlloc; 352 compat = xkb->compat; 353 if (compat->sym_interpret) { 354 compat->num_si = num_dfltSI; 355 memcpy((char *)compat->sym_interpret,(char *)dfltSI,sizeof(dfltSI)); 356 } 357 for (i=0;i<XkbNumKbdGroups;i++) { 358 compat->groups[i]= compatMap.groups[i]; 359 if (compat->groups[i].vmods!=0) { 360 unsigned mask; 361 mask= XkbMaskForVMask(xkb,compat->groups[i].vmods); 362 compat->groups[i].mask= compat->groups[i].real_mods|mask; 363 } 364 else compat->groups[i].mask= compat->groups[i].real_mods; 365 } 366 return Success; 367} 368 369static void 370XkbInitSemantics(XkbDescPtr xkb) 371{ 372 XkbInitKeyTypes(xkb); 373 XkbInitCompatStructs(xkb); 374 return; 375} 376 377/***====================================================================***/ 378 379static Status 380XkbInitNames(XkbSrvInfoPtr xkbi) 381{ 382XkbDescPtr xkb; 383XkbNamesPtr names; 384Status rtrn; 385Atom unknown; 386 387 xkb= xkbi->desc; 388 if ((rtrn=XkbAllocNames(xkb,XkbAllNamesMask,0,0))!=Success) 389 return rtrn; 390 unknown= CREATE_ATOM("unknown"); 391 names = xkb->names; 392 if (names->keycodes==None) names->keycodes= unknown; 393 if (names->geometry==None) names->geometry= unknown; 394 if (names->phys_symbols==None) names->phys_symbols= unknown; 395 if (names->symbols==None) names->symbols= unknown; 396 if (names->types==None) names->types= unknown; 397 if (names->compat==None) names->compat= unknown; 398 if (!(xkb->defined & XkmVirtualModsMask)) { 399 if (names->vmods[vmod_NumLock]==None) 400 names->vmods[vmod_NumLock]= CREATE_ATOM("NumLock"); 401 if (names->vmods[vmod_Alt]==None) 402 names->vmods[vmod_Alt]= CREATE_ATOM("Alt"); 403 if (names->vmods[vmod_AltGr]==None) 404 names->vmods[vmod_AltGr]= CREATE_ATOM("ModeSwitch"); 405 } 406 407 if (!(xkb->defined & XkmIndicatorsMask) || 408 !(xkb->defined & XkmGeometryMask)) { 409 initIndicatorNames(NULL,xkb); 410 if (names->indicators[LED_CAPS-1]==None) 411 names->indicators[LED_CAPS-1] = CREATE_ATOM("Caps Lock"); 412 if (names->indicators[LED_NUM-1]==None) 413 names->indicators[LED_NUM-1] = CREATE_ATOM("Num Lock"); 414 if (names->indicators[LED_SCROLL-1]==None) 415 names->indicators[LED_SCROLL-1] = CREATE_ATOM("Scroll Lock"); 416#ifdef LED_COMPOSE 417 if (names->indicators[LED_COMPOSE-1]==None) 418 names->indicators[LED_COMPOSE-1] = CREATE_ATOM("Compose"); 419#endif 420 } 421 422 if (xkb->geom!=NULL) 423 names->geometry= xkb->geom->name; 424 else names->geometry= unknown; 425 426 return Success; 427} 428 429static Status 430XkbInitIndicatorMap(XkbSrvInfoPtr xkbi) 431{ 432XkbDescPtr xkb; 433XkbIndicatorPtr map; 434XkbSrvLedInfoPtr sli; 435 436 xkb= xkbi->desc; 437 if (XkbAllocIndicatorMaps(xkb)!=Success) 438 return BadAlloc; 439 440 if (!(xkb->defined & XkmIndicatorsMask)) { 441 map= xkb->indicators; 442 map->phys_indicators = PHYS_LEDS; 443 map->maps[LED_CAPS-1].flags= XkbIM_NoExplicit; 444 map->maps[LED_CAPS-1].which_mods= XkbIM_UseLocked; 445 map->maps[LED_CAPS-1].mods.mask= LockMask; 446 map->maps[LED_CAPS-1].mods.real_mods= LockMask; 447 448 map->maps[LED_NUM-1].flags= XkbIM_NoExplicit; 449 map->maps[LED_NUM-1].which_mods= XkbIM_UseLocked; 450 map->maps[LED_NUM-1].mods.mask= 0; 451 map->maps[LED_NUM-1].mods.real_mods= 0; 452 map->maps[LED_NUM-1].mods.vmods= vmod_NumLockMask; 453 454 map->maps[LED_SCROLL-1].flags= XkbIM_NoExplicit; 455 map->maps[LED_SCROLL-1].which_mods= XkbIM_UseLocked; 456 map->maps[LED_SCROLL-1].mods.mask= Mod3Mask; 457 map->maps[LED_SCROLL-1].mods.real_mods= Mod3Mask; 458 } 459 460 sli= XkbFindSrvLedInfo(xkbi->device,XkbDfltXIClass,XkbDfltXIId,0); 461 if (sli) 462 XkbCheckIndicatorMaps(xkbi->device,sli,XkbAllIndicatorsMask); 463 464 return Success; 465} 466 467static Status 468XkbInitControls(DeviceIntPtr pXDev,XkbSrvInfoPtr xkbi) 469{ 470XkbDescPtr xkb; 471XkbControlsPtr ctrls; 472 473 xkb= xkbi->desc; 474 /* 12/31/94 (ef) -- XXX! Should check if controls loaded from file */ 475 if (XkbAllocControls(xkb,XkbAllControlsMask)!=Success) 476 FatalError("Couldn't allocate keyboard controls\n"); 477 ctrls= xkb->ctrls; 478 if (!(xkb->defined & XkmSymbolsMask)) 479 ctrls->num_groups = 1; 480 ctrls->groups_wrap = XkbSetGroupInfo(1,XkbWrapIntoRange,0); 481 ctrls->internal.mask = 0; 482 ctrls->internal.real_mods = 0; 483 ctrls->internal.vmods = 0; 484 ctrls->ignore_lock.mask = 0; 485 ctrls->ignore_lock.real_mods = 0; 486 ctrls->ignore_lock.vmods = 0; 487 ctrls->enabled_ctrls = XkbAccessXTimeoutMask|XkbRepeatKeysMask| 488 XkbMouseKeysAccelMask|XkbAudibleBellMask| 489 XkbIgnoreGroupLockMask; 490 if (XkbWantAccessX) 491 ctrls->enabled_ctrls|= XkbAccessXKeysMask; 492 AccessXInit(pXDev); 493 return Success; 494} 495 496void 497XkbInitDevice(DeviceIntPtr pXDev) 498{ 499int i; 500XkbSrvInfoPtr xkbi; 501XkbChangesRec changes; 502unsigned check; 503XkbEventCauseRec cause; 504 505 bzero(&changes,sizeof(XkbChangesRec)); 506 pXDev->key->xkbInfo= xkbi= _XkbTypedCalloc(1,XkbSrvInfoRec); 507 if ( xkbi ) { 508 XkbDescPtr xkb; 509 510 if (xkb_cached_map) { 511 xkbi->desc = xkb_cached_map; 512 xkb_cached_map = NULL; 513 } 514 else { 515 xkbi->desc= XkbAllocKeyboard(); 516 if (!xkbi->desc) 517 FatalError("Couldn't allocate keyboard description\n"); 518 xkbi->desc->min_key_code = pXDev->key->curKeySyms.minKeyCode; 519 xkbi->desc->max_key_code = pXDev->key->curKeySyms.maxKeyCode; 520 } 521 xkb= xkbi->desc; 522 if (xkb->min_key_code == 0) 523 xkb->min_key_code = pXDev->key->curKeySyms.minKeyCode; 524 if (xkb->max_key_code == 0) 525 xkb->max_key_code = pXDev->key->curKeySyms.maxKeyCode; 526 if ((pXDev->key->curKeySyms.minKeyCode!=xkbi->desc->min_key_code)|| 527 (pXDev->key->curKeySyms.maxKeyCode!=xkbi->desc->max_key_code)) { 528 /* 12/9/95 (ef) -- XXX! Maybe we should try to fix up one or */ 529 /* the other here, but for now just complain */ 530 /* can't just update the core range without */ 531 /* reallocating the KeySymsRec (pain) */ 532 ErrorF("[xkb] Internal Error!! XKB and core keymap have different range\n"); 533 } 534 if (XkbAllocClientMap(xkb,XkbAllClientInfoMask,0)!=Success) 535 FatalError("Couldn't allocate client map in XkbInitDevice\n"); 536 i= XkbNumKeys(xkb)/3+1; 537 if (XkbAllocServerMap(xkb,XkbAllServerInfoMask,i)!=Success) 538 FatalError("Couldn't allocate server map in XkbInitDevice\n"); 539 540 xkbi->dfltPtrDelta=1; 541 xkbi->device = pXDev; 542 543 XkbInitSemantics(xkb); 544 XkbInitNames(xkbi); 545 XkbInitRadioGroups(xkbi); 546 547 /* 12/31/94 (ef) -- XXX! Should check if state loaded from file */ 548 bzero(&xkbi->state,sizeof(XkbStateRec)); 549 550 XkbInitControls(pXDev,xkbi); 551 552 if (xkb->defined & XkmSymbolsMask) 553 memcpy(pXDev->key->modifierMap, xkb->map->modmap, 554 xkb->max_key_code + 1); 555 else 556 memcpy(xkb->map->modmap, pXDev->key->modifierMap, 557 xkb->max_key_code + 1); 558 559 XkbInitIndicatorMap(xkbi); 560 561 XkbDDXInitDevice(pXDev); 562 563 if (xkb->defined & XkmSymbolsMask) 564 XkbUpdateCoreDescription(pXDev, True); 565 else 566 XkbUpdateKeyTypesFromCore(pXDev, xkb->min_key_code, 567 XkbNumKeys(xkb), &changes); 568 569 XkbSetCauseUnknown(&cause); 570 XkbUpdateActions(pXDev,xkb->min_key_code, XkbNumKeys(xkb),&changes, 571 &check,&cause); 572 /* For sanity. The first time the connection 573 * is opened, the client side min and max are set 574 * using QueryMinMaxKeyCodes() which grabs them 575 * from pXDev. 576 */ 577 pXDev->key->curKeySyms.minKeyCode = xkb->min_key_code; 578 pXDev->key->curKeySyms.maxKeyCode = xkb->max_key_code; 579 } 580 return; 581} 582 583#if MAP_LENGTH > XkbMaxKeyCount 584#undef XkbMaxKeyCount 585#define XkbMaxKeyCount MAP_LENGTH 586#endif 587 588_X_EXPORT Bool 589XkbInitKeyboardDeviceStruct( 590 DeviceIntPtr dev, 591 XkbComponentNamesPtr names, 592 KeySymsPtr pSymsIn, 593 CARD8 pModsIn[], 594 void (*bellProc)( 595 int /*percent*/, 596 DeviceIntPtr /*device*/, 597 pointer /*ctrl*/, 598 int), 599 void (*ctrlProc)( 600 DeviceIntPtr /*device*/, 601 KeybdCtrl * /*ctrl*/)) 602{ 603KeySymsRec tmpSyms,*pSyms; 604CARD8 tmpMods[XkbMaxLegalKeyCode+1],*pMods; 605char name[PATH_MAX],*rules; 606Bool ok=False; 607XkbRF_VarDefsRec defs; 608XkbDescPtr xkb; 609 610 if ((dev->key!=NULL)||(dev->kbdfeed!=NULL)) 611 return False; 612 pSyms= pSymsIn; 613 pMods= pModsIn; 614 bzero(&defs,sizeof(XkbRF_VarDefsRec)); 615 rules= XkbGetRulesDflts(&defs); 616 617 /* 618 * The strings are duplicated because it is not guaranteed that 619 * they are allocated, or that they are allocated for every server 620 * generation. Eventually they will be freed at the end of this 621 * function. 622 */ 623 names->keymap = NULL; 624 if (names->keycodes) names->keycodes = _XkbDupString(names->keycodes); 625 if (names->types) names->types = _XkbDupString(names->types); 626 if (names->compat) names->compat = _XkbDupString(names->compat); 627 if (names->geometry) names->geometry = _XkbDupString(names->geometry); 628 if (names->symbols) names->symbols = _XkbDupString(names->symbols); 629 630 if (defs.model && defs.layout && rules) { 631 XkbComponentNamesRec rNames; 632 bzero(&rNames,sizeof(XkbComponentNamesRec)); 633 if (XkbDDXNamesFromRules(dev,rules,&defs,&rNames)) { 634 if (rNames.keycodes) { 635 if (!names->keycodes) 636 names->keycodes = rNames.keycodes; 637 else 638 _XkbFree(rNames.keycodes); 639 } 640 if (rNames.types) { 641 if (!names->types) 642 names->types = rNames.types; 643 else _XkbFree(rNames.types); 644 } 645 if (rNames.compat) { 646 if (!names->compat) 647 names->compat = rNames.compat; 648 else _XkbFree(rNames.compat); 649 } 650 if (rNames.symbols) { 651 if (!names->symbols) 652 names->symbols = rNames.symbols; 653 else _XkbFree(rNames.symbols); 654 } 655 if (rNames.geometry) { 656 if (!names->geometry) 657 names->geometry = rNames.geometry; 658 else _XkbFree(rNames.geometry); 659 } 660 XkbSetRulesUsed(&defs); 661 } 662 } 663 664 ok = (Bool) XkbDDXLoadKeymapByNames(dev,names,XkmAllIndicesMask,0, 665 &xkb,name,PATH_MAX); 666 667 if (ok && (xkb!=NULL)) { 668 KeyCode minKC,maxKC; 669 670 minKC= xkb->min_key_code; 671 maxKC= xkb->max_key_code; 672 if (XkbIsLegalKeycode(minKC)&&XkbIsLegalKeycode(maxKC)&&(minKC<=maxKC)&& 673 ((minKC!=pSyms->minKeyCode)||(maxKC!=pSyms->maxKeyCode))) { 674 if (xkb->map!=NULL) { 675 KeySym *inSym,*outSym; 676 int width= pSymsIn->mapWidth; 677 678 tmpSyms.minKeyCode= minKC; 679 tmpSyms.maxKeyCode= maxKC; 680 681 if (minKC<pSymsIn->minKeyCode) 682 minKC= pSymsIn->minKeyCode; 683 if (maxKC>pSymsIn->maxKeyCode) 684 maxKC= pSymsIn->maxKeyCode; 685 686 tmpSyms.mapWidth= width; 687 tmpSyms.map= _XkbTypedCalloc(width*XkbNumKeys(xkb),KeySym); 688 inSym= &pSymsIn->map[(minKC-pSymsIn->minKeyCode)*width]; 689 outSym= &tmpSyms.map[(minKC-tmpSyms.minKeyCode)*width]; 690 memcpy(outSym,inSym,((maxKC-minKC+1)*width)*sizeof(KeySym)); 691 pSyms= &tmpSyms; 692 } 693 if ((xkb->map!=NULL)&&(xkb->map->modmap!=NULL)) { 694 bzero(tmpMods,XkbMaxKeyCount); 695 memcpy(tmpMods,xkb->map->modmap,maxKC+1); 696 pMods= tmpMods; 697 } 698 } 699 /* Store the map here so we can pick it back up in XkbInitDevice. 700 * Sigh. */ 701 xkb_cached_map = xkb; 702 } 703 else { 704 LogMessage(X_WARNING, "Couldn't load XKB keymap, falling back to pre-XKB keymap\n"); 705 } 706 ok= InitKeyboardDeviceStruct((DevicePtr)dev,pSyms,pMods,bellProc,ctrlProc); 707 xkb_cached_map = NULL; 708 if ((pSyms==&tmpSyms)&&(pSyms->map!=NULL)) { 709 _XkbFree(pSyms->map); 710 pSyms->map= NULL; 711 } 712 713 if (names->keycodes) _XkbFree(names->keycodes); 714 names->keycodes = NULL; 715 if (names->types) _XkbFree(names->types); 716 names->types = NULL; 717 if (names->compat) _XkbFree(names->compat); 718 names->compat = NULL; 719 if (names->geometry) _XkbFree(names->geometry); 720 names->geometry = NULL; 721 if (names->symbols) _XkbFree(names->symbols); 722 names->symbols = NULL; 723 724 return ok; 725} 726 727/***====================================================================***/ 728 729 /* 730 * InitKeyClassDeviceStruct initializes the key class before it 731 * initializes the keyboard feedback class for a device. 732 * UpdateActions can't set up the correct autorepeat for keyboard 733 * initialization because the keyboard feedback isn't created yet. 734 * Instead, UpdateActions notes the "correct" autorepeat in the 735 * SrvInfo structure and InitKbdFeedbackClass calls UpdateAutoRepeat 736 * to apply the computed autorepeat once the feedback class exists. 737 * 738 * DIX will apply the changed autorepeat, so there's no need to 739 * do so here. This function returns True if both RepeatKeys and 740 * the core protocol autorepeat ctrls are set (i.e. should use 741 * software autorepeat), false otherwise. 742 * 743 * This function also computes the autorepeat accelerators for the 744 * default indicator feedback. 745 */ 746int 747XkbFinishDeviceInit(DeviceIntPtr pXDev) 748{ 749XkbSrvInfoPtr xkbi; 750XkbDescPtr xkb; 751int softRepeat; 752XkbSrvLedInfoPtr sli; 753 754 xkbi = NULL; 755 if (pXDev && pXDev->key && pXDev->key->xkbInfo && pXDev->kbdfeed) { 756 xkbi= pXDev->key->xkbInfo; 757 xkb= xkbi->desc; 758 /* If we come from DeepCopyDeviceClasses, the CtrlProc was already set 759 * to XkbDDXKeybdCtrlProc, overwriting it leads to happy recursion. 760 */ 761 if (pXDev->kbdfeed && pXDev->kbdfeed->CtrlProc != XkbDDXKeybdCtrlProc) { 762 xkbi->kbdProc= pXDev->kbdfeed->CtrlProc; 763 pXDev->kbdfeed->CtrlProc= XkbDDXKeybdCtrlProc; 764 } 765 if (pXDev->kbdfeed->ctrl.autoRepeat) 766 xkb->ctrls->enabled_ctrls|= XkbRepeatKeysMask; 767 softRepeat= (xkb->ctrls->enabled_ctrls&XkbRepeatKeysMask)!=0; 768 if (pXDev->kbdfeed) { 769 memcpy(pXDev->kbdfeed->ctrl.autoRepeats, 770 xkb->ctrls->per_key_repeat,XkbPerKeyBitArraySize); 771 softRepeat= softRepeat&&pXDev->kbdfeed->ctrl.autoRepeat; 772 } 773 } 774 else softRepeat= 0; 775 sli= XkbFindSrvLedInfo(pXDev,XkbDfltXIClass,XkbDfltXIId,0); 776 if (sli && xkbi) 777 XkbCheckIndicatorMaps(xkbi->device,sli,XkbAllIndicatorsMask); 778 else DebugF("[xkb] No indicator feedback in XkbFinishInit (shouldn't happen)!\n"); 779 return softRepeat; 780} 781 782 /* 783 * Be very careful about what does and doesn't get freed by this 784 * function. To reduce fragmentation, XkbInitDevice allocates a 785 * single huge block per device and divides it up into most of the 786 * fixed-size structures for the device. Don't free anything that 787 * is part of this larger block. 788 */ 789void 790XkbFreeInfo(XkbSrvInfoPtr xkbi) 791{ 792 if (xkbi->radioGroups) { 793 _XkbFree(xkbi->radioGroups); 794 xkbi->radioGroups= NULL; 795 } 796 if (xkbi->mouseKeyTimer) { 797 TimerFree(xkbi->mouseKeyTimer); 798 xkbi->mouseKeyTimer= NULL; 799 } 800 if (xkbi->slowKeysTimer) { 801 TimerFree(xkbi->slowKeysTimer); 802 xkbi->slowKeysTimer= NULL; 803 } 804 if (xkbi->bounceKeysTimer) { 805 TimerFree(xkbi->bounceKeysTimer); 806 xkbi->bounceKeysTimer= NULL; 807 } 808 if (xkbi->repeatKeyTimer) { 809 TimerFree(xkbi->repeatKeyTimer); 810 xkbi->repeatKeyTimer= NULL; 811 } 812 if (xkbi->krgTimer) { 813 TimerFree(xkbi->krgTimer); 814 xkbi->krgTimer= NULL; 815 } 816 xkbi->beepType= _BEEP_NONE; 817 if (xkbi->beepTimer) { 818 TimerFree(xkbi->beepTimer); 819 xkbi->beepTimer= NULL; 820 } 821 if (xkbi->desc) { 822 XkbFreeKeyboard(xkbi->desc,XkbAllComponentsMask,True); 823 xkbi->desc= NULL; 824 } 825 _XkbFree(xkbi); 826 return; 827} 828 829/***====================================================================***/ 830 831extern int XkbDfltRepeatDelay; 832extern int XkbDfltRepeatInterval; 833 834extern unsigned short XkbDfltAccessXTimeout; 835extern unsigned int XkbDfltAccessXTimeoutMask; 836extern unsigned int XkbDfltAccessXFeedback; 837extern unsigned char XkbDfltAccessXOptions; 838 839int 840XkbProcessArguments(int argc,char *argv[],int i) 841{ 842 if (strcmp(argv[i],"-kb")==0) { 843 noXkbExtension= True; 844 return 1; 845 } 846 else if (strcmp(argv[i],"+kb")==0) { 847 noXkbExtension= False; 848 return 1; 849 } 850 else if (strncmp(argv[i], "-xkbdir", 7) == 0) { 851 if(++i < argc) { 852#if !defined(WIN32) && !defined(__CYGWIN__) 853 if (getuid() != geteuid()) { 854 LogMessage(X_WARNING, "-xkbdir is not available for setuid X servers\n"); 855 return -1; 856 } else 857#endif 858 { 859 if (strlen(argv[i]) < PATH_MAX) { 860 XkbBaseDirectory= argv[i]; 861 return 2; 862 } else { 863 LogMessage(X_ERROR, "-xkbdir pathname too long\n"); 864 return -1; 865 } 866 } 867 } 868 else { 869 return -1; 870 } 871 } 872 else if ((strncmp(argv[i],"-accessx",8)==0)|| 873 (strncmp(argv[i],"+accessx",8)==0)) { 874 int j=1; 875 if (argv[i][0]=='-') 876 XkbWantAccessX= 0; 877 else { 878 XkbWantAccessX= 1; 879 880 if ( ((i+1)<argc) && (isdigit(argv[i+1][0])) ) { 881 XkbDfltAccessXTimeout = atoi(argv[++i]); 882 j++; 883 884 if ( ((i+1)<argc) && (isdigit(argv[i+1][0])) ) { 885 /* 886 * presumption that the reasonably useful range of 887 * values fits in 0..MAXINT since SunOS 4 doesn't 888 * have strtoul. 889 */ 890 XkbDfltAccessXTimeoutMask=(unsigned int) 891 strtol(argv[++i],NULL,16); 892 j++; 893 } 894 if ( ((i+1)<argc) && (isdigit(argv[i+1][0])) ) { 895 if (argv[++i][0] == '1' ) 896 XkbDfltAccessXFeedback=XkbAccessXFeedbackMask; 897 else 898 XkbDfltAccessXFeedback=0; 899 j++; 900 } 901 if ( ((i+1)<argc) && (isdigit(argv[i+1][0])) ) { 902 XkbDfltAccessXOptions=(unsigned char) 903 strtol(argv[++i],NULL,16); 904 j++; 905 } 906 } 907 } 908 return j; 909 } 910 if ((strcmp(argv[i], "-ardelay") == 0) || 911 (strcmp (argv[i], "-ar1") == 0)) { /* -ardelay int */ 912 if (++i >= argc) UseMsg (); 913 XkbDfltRepeatDelay = (long)atoi(argv[i]); 914 return 2; 915 } 916 if ((strcmp(argv[i], "-arinterval") == 0) || 917 (strcmp (argv[i], "-ar2") == 0)) { /* -arinterval int */ 918 if (++i >= argc) UseMsg (); 919 XkbDfltRepeatInterval = (long)atoi(argv[i]); 920 return 2; 921 } 922 return 0; 923} 924 925void 926XkbUseMsg(void) 927{ 928 ErrorF("-kb disable the X Keyboard Extension\n"); 929 ErrorF("+kb enable the X Keyboard Extension\n"); 930 ErrorF("[+-]accessx [ timeout [ timeout_mask [ feedback [ options_mask] ] ] ]\n"); 931 ErrorF(" enable/disable accessx key sequences\n"); 932 ErrorF("-ardelay set XKB autorepeat delay\n"); 933 ErrorF("-arinterval set XKB autorepeat interval\n"); 934} 935