XKBUse.c revision e9fcaa8a
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_CONFIG_H 28#include <config.h> 29#endif 30#include <stdio.h> 31#include <ctype.h> 32#include "Xlibint.h" 33#include <X11/extensions/XKBproto.h> 34#include "XKBlibint.h" 35 36static Bool _XkbIgnoreExtension = False; 37 38void 39XkbNoteMapChanges(XkbMapChangesPtr old,XkbMapNotifyEvent *new,unsigned wanted) 40{ 41 int first,oldLast,newLast; 42 wanted&= new->changed; 43 44 if (wanted&XkbKeyTypesMask) { 45 if (old->changed&XkbKeyTypesMask) { 46 first = old->first_type; 47 oldLast = old->first_type+old->num_types-1; 48 newLast = new->first_type+new->num_types-1; 49 50 if (new->first_type<first) 51 first = new->first_type; 52 if (oldLast>newLast) 53 newLast= oldLast; 54 old->first_type = first; 55 old->num_types = newLast-first+1; 56 } 57 else { 58 old->first_type= new->first_type; 59 old->num_types = new->num_types; 60 } 61 } 62 if (wanted&XkbKeySymsMask) { 63 if (old->changed&XkbKeySymsMask) { 64 first = old->first_key_sym; 65 oldLast = old->first_key_sym+old->num_key_syms-1; 66 newLast = new->first_key_sym+new->num_key_syms-1; 67 68 if (new->first_key_sym<first) 69 first = new->first_key_sym; 70 if (oldLast>newLast) 71 newLast= oldLast; 72 old->first_key_sym = first; 73 old->num_key_syms = newLast-first+1; 74 } 75 else { 76 old->first_key_sym = new->first_key_sym; 77 old->num_key_syms = new->num_key_syms; 78 } 79 } 80 if (wanted&XkbKeyActionsMask) { 81 if (old->changed&XkbKeyActionsMask) { 82 first = old->first_key_act; 83 oldLast = old->first_key_act+old->num_key_acts-1; 84 newLast = new->first_key_act+new->num_key_acts-1; 85 86 if (new->first_key_act<first) 87 first = new->first_key_act; 88 if (oldLast>newLast) 89 newLast= oldLast; 90 old->first_key_act = first; 91 old->num_key_acts = newLast-first+1; 92 } 93 else { 94 old->first_key_act = new->first_key_act; 95 old->num_key_acts = new->num_key_acts; 96 } 97 } 98 if (wanted&XkbKeyBehaviorsMask) { 99 if (old->changed&XkbKeyBehaviorsMask) { 100 first = old->first_key_behavior; 101 oldLast = old->first_key_behavior+old->num_key_behaviors-1; 102 newLast = new->first_key_behavior+new->num_key_behaviors-1; 103 104 if (new->first_key_behavior<first) 105 first = new->first_key_behavior; 106 if (oldLast>newLast) 107 newLast= oldLast; 108 old->first_key_behavior = first; 109 old->num_key_behaviors = newLast-first+1; 110 } 111 else { 112 old->first_key_behavior = new->first_key_behavior; 113 old->num_key_behaviors = new->num_key_behaviors; 114 } 115 } 116 if (wanted&XkbVirtualModsMask) { 117 old->vmods|= new->vmods; 118 } 119 if (wanted&XkbExplicitComponentsMask) { 120 if (old->changed&XkbExplicitComponentsMask) { 121 first = old->first_key_explicit; 122 oldLast = old->first_key_explicit+old->num_key_explicit-1; 123 newLast = new->first_key_explicit+new->num_key_explicit-1; 124 125 if (new->first_key_explicit<first) 126 first = new->first_key_explicit; 127 if (oldLast>newLast) 128 newLast= oldLast; 129 old->first_key_explicit = first; 130 old->num_key_explicit = newLast-first+1; 131 } 132 else { 133 old->first_key_explicit = new->first_key_explicit; 134 old->num_key_explicit = new->num_key_explicit; 135 } 136 } 137 if (wanted&XkbModifierMapMask) { 138 if (old->changed&XkbModifierMapMask) { 139 first = old->first_modmap_key; 140 oldLast = old->first_modmap_key+old->num_modmap_keys-1; 141 newLast = new->first_modmap_key+new->num_modmap_keys-1; 142 143 if (new->first_modmap_key<first) 144 first = new->first_modmap_key; 145 if (oldLast>newLast) 146 newLast= oldLast; 147 old->first_modmap_key = first; 148 old->num_modmap_keys = newLast-first+1; 149 } 150 else { 151 old->first_modmap_key = new->first_modmap_key; 152 old->num_modmap_keys = new->num_modmap_keys; 153 } 154 } 155 if (wanted&XkbVirtualModMapMask) { 156 if (old->changed&XkbVirtualModMapMask) { 157 first = old->first_vmodmap_key; 158 oldLast = old->first_vmodmap_key+old->num_vmodmap_keys-1; 159 newLast = new->first_vmodmap_key+new->num_vmodmap_keys-1; 160 161 if (new->first_vmodmap_key<first) 162 first = new->first_vmodmap_key; 163 if (oldLast>newLast) 164 newLast= oldLast; 165 old->first_vmodmap_key = first; 166 old->num_vmodmap_keys = newLast-first+1; 167 } 168 else { 169 old->first_vmodmap_key = new->first_vmodmap_key; 170 old->num_vmodmap_keys = new->num_vmodmap_keys; 171 } 172 } 173 old->changed|= wanted; 174 return; 175} 176 177void 178_XkbNoteCoreMapChanges( XkbMapChangesPtr old, 179 XMappingEvent * new, 180 unsigned int wanted) 181{ 182 int first,oldLast,newLast; 183 184 if ((new->request==MappingKeyboard)&&(wanted&XkbKeySymsMask)) { 185 if (old->changed&XkbKeySymsMask) { 186 first = old->first_key_sym; 187 oldLast = old->first_key_sym+old->num_key_syms-1; 188 newLast = new->first_keycode+new->count-1; 189 190 if (new->first_keycode<first) 191 first = new->first_keycode; 192 if (oldLast>newLast) 193 newLast= oldLast; 194 old->first_key_sym = first; 195 old->num_key_syms = newLast-first+1; 196 } 197 else { 198 old->changed|= XkbKeySymsMask; 199 old->first_key_sym = new->first_keycode; 200 old->num_key_syms = new->count; 201 } 202 } 203 return; 204} 205 206static Bool 207wire_to_event(Display *dpy,XEvent *re,xEvent *event) 208{ 209 xkbEvent *xkbevent= (xkbEvent *)event; 210 XkbInfoPtr xkbi; 211 212 if ((dpy->flags & XlibDisplayNoXkb) || 213 (!dpy->xkb_info && !XkbUseExtension(dpy,NULL,NULL))) 214 return False; 215 xkbi = dpy->xkb_info; 216 if (((event->u.u.type&0x7f)-xkbi->codes->first_event)!=XkbEventCode) 217 return False; 218 219 switch (xkbevent->u.any.xkbType) { 220 case XkbStateNotify: 221 { 222 xkbStateNotify *sn = (xkbStateNotify *)event; 223 if ( xkbi->selected_events&XkbStateNotifyMask ) { 224 XkbStateNotifyEvent *sev=(XkbStateNotifyEvent *)re; 225 sev->type = XkbEventCode+xkbi->codes->first_event; 226 sev->xkb_type = XkbStateNotify; 227 sev->serial = _XSetLastRequestRead(dpy, 228 (xGenericReply *)event); 229 sev->send_event = ((event->u.u.type & 0x80) != 0); 230 sev->display = dpy; 231 sev->time = sn->time; 232 sev->device = sn->deviceID; 233 sev->keycode = sn->keycode; 234 sev->event_type = sn->eventType; 235 sev->req_major = sn->requestMajor; 236 sev->req_minor = sn->requestMinor; 237 sev->changed = sn->changed; 238 sev->group = sn->group; 239 sev->base_group = sn->baseGroup; 240 sev->latched_group = sn->latchedGroup; 241 sev->locked_group = sn->lockedGroup; 242 sev->mods = sn->mods; 243 sev->base_mods = sn->baseMods; 244 sev->latched_mods = sn->latchedMods; 245 sev->locked_mods = sn->lockedMods; 246 sev->compat_state = sn->compatState; 247 sev->grab_mods = sn->grabMods; 248 sev->compat_grab_mods = sn->compatGrabMods; 249 sev->lookup_mods = sn->lookupMods; 250 sev->compat_lookup_mods = sn->compatLookupMods; 251 sev->ptr_buttons = sn->ptrBtnState; 252 return True; 253 } 254 } 255 break; 256 case XkbMapNotify: 257 { 258 xkbMapNotify *mn = (xkbMapNotify *)event; 259 if ((xkbi->selected_events&XkbMapNotifyMask)&& 260 (xkbi->selected_map_details&mn->changed)) { 261 XkbMapNotifyEvent *mev; 262 mev =(XkbMapNotifyEvent *)re; 263 mev->type = XkbEventCode+xkbi->codes->first_event; 264 mev->xkb_type = XkbMapNotify; 265 mev->serial = _XSetLastRequestRead(dpy, 266 (xGenericReply *)event); 267 mev->send_event = ((event->u.u.type&0x80)!=0); 268 mev->display = dpy; 269 mev->time = mn->time; 270 mev->device = mn->deviceID; 271 mev->changed = mn->changed; 272 mev->min_key_code = mn->minKeyCode; 273 mev->max_key_code = mn->maxKeyCode; 274 mev->first_type = mn->firstType; 275 mev->num_types = mn->nTypes; 276 mev->first_key_sym = mn->firstKeySym; 277 mev->num_key_syms = mn->nKeySyms; 278 mev->first_key_act = mn->firstKeyAct; 279 mev->num_key_acts = mn->nKeyActs; 280 mev->first_key_behavior = mn->firstKeyBehavior; 281 mev->num_key_behaviors = mn->nKeyBehaviors; 282 mev->vmods = mn->virtualMods; 283 mev->first_key_explicit = mn->firstKeyExplicit; 284 mev->num_key_explicit = mn->nKeyExplicit; 285 mev->first_modmap_key = mn->firstModMapKey; 286 mev->num_modmap_keys = mn->nModMapKeys; 287 mev->first_vmodmap_key = mn->firstVModMapKey; 288 mev->num_vmodmap_keys = mn->nVModMapKeys; 289 XkbNoteMapChanges(&xkbi->changes,mev,XKB_XLIB_MAP_MASK); 290 if (xkbi->changes.changed) 291 xkbi->flags|= XkbMapPending; 292 return True; 293 } 294 else if (mn->nKeySyms>0) { 295 register XMappingEvent *ev = (XMappingEvent *)re; 296 ev->type = MappingNotify; 297 ev->serial = _XSetLastRequestRead(dpy, 298 (xGenericReply *)event); 299 ev->send_event = ((event->u.u.type&0x80)!=0); 300 ev->display = dpy; 301 ev->window = 0; 302 ev->first_keycode = mn->firstKeySym; 303 ev->request = MappingKeyboard; 304 ev->count = mn->nKeySyms; 305 _XkbNoteCoreMapChanges(&xkbi->changes,ev,XKB_XLIB_MAP_MASK); 306 if (xkbi->changes.changed) 307 xkbi->flags|= XkbMapPending; 308 return True; 309 } 310 } 311 break; 312 case XkbControlsNotify: 313 { 314 if (xkbi->selected_events&XkbControlsNotifyMask) { 315 xkbControlsNotify *cn =(xkbControlsNotify *)event; 316 XkbControlsNotifyEvent *cev; 317 cev =(XkbControlsNotifyEvent *)re; 318 cev->type = XkbEventCode+xkbi->codes->first_event; 319 cev->xkb_type = XkbControlsNotify; 320 cev->serial = _XSetLastRequestRead(dpy, 321 (xGenericReply *)event); 322 cev->send_event = ((event->u.u.type&0x80)!=0); 323 cev->display = dpy; 324 cev->time = cn->time; 325 cev->device = cn->deviceID; 326 cev->changed_ctrls = cn->changedControls; 327 cev->enabled_ctrls = cn->enabledControls; 328 cev->enabled_ctrl_changes = cn->enabledControlChanges; 329 cev->keycode = cn->keycode; 330 cev->num_groups = cn->numGroups; 331 cev->event_type = cn->eventType; 332 cev->req_major = cn->requestMajor; 333 cev->req_minor = cn->requestMinor; 334 return True; 335 } 336 } 337 break; 338 case XkbIndicatorMapNotify: 339 { 340 if (xkbi->selected_events&XkbIndicatorMapNotifyMask) { 341 xkbIndicatorNotify *in =(xkbIndicatorNotify *)event; 342 XkbIndicatorNotifyEvent *iev; 343 iev =(XkbIndicatorNotifyEvent *)re; 344 iev->type = XkbEventCode+xkbi->codes->first_event; 345 iev->xkb_type = XkbIndicatorMapNotify; 346 iev->serial = _XSetLastRequestRead(dpy, 347 (xGenericReply *)event); 348 iev->send_event = ((event->u.u.type&0x80)!=0); 349 iev->display = dpy; 350 iev->time = in->time; 351 iev->device = in->deviceID; 352 iev->changed = in->changed; 353 iev->state= in->state; 354 return True; 355 } 356 } 357 break; 358 case XkbIndicatorStateNotify: 359 { 360 if (xkbi->selected_events&XkbIndicatorStateNotifyMask) { 361 xkbIndicatorNotify *in =(xkbIndicatorNotify *)event; 362 XkbIndicatorNotifyEvent *iev; 363 iev =(XkbIndicatorNotifyEvent *)re; 364 iev->type = XkbEventCode+xkbi->codes->first_event; 365 iev->xkb_type = XkbIndicatorStateNotify; 366 iev->serial = _XSetLastRequestRead(dpy, 367 (xGenericReply *)event); 368 iev->send_event = ((event->u.u.type&0x80)!=0); 369 iev->display = dpy; 370 iev->time = in->time; 371 iev->device = in->deviceID; 372 iev->changed = in->changed; 373 iev->state= in->state; 374 return True; 375 } 376 } 377 break; 378 case XkbBellNotify: 379 { 380 if (xkbi->selected_events&XkbBellNotifyMask) { 381 xkbBellNotify *bn =(xkbBellNotify *)event; 382 XkbBellNotifyEvent *bev; 383 bev =(XkbBellNotifyEvent *)re; 384 bev->type = XkbEventCode+xkbi->codes->first_event; 385 bev->xkb_type = XkbBellNotify; 386 bev->serial = _XSetLastRequestRead(dpy, 387 (xGenericReply *)event); 388 bev->send_event = ((event->u.u.type&0x80)!=0); 389 bev->display = dpy; 390 bev->time = bn->time; 391 bev->device = bn->deviceID; 392 bev->percent = bn->percent; 393 bev->pitch = bn->pitch; 394 bev->duration = bn->duration; 395 bev->bell_class = bn->bellClass; 396 bev->bell_id = bn->bellID; 397 bev->name = bn->name; 398 bev->window = bn->window; 399 bev->event_only = bn->eventOnly; 400 return True; 401 } 402 } 403 break; 404 case XkbAccessXNotify: 405 { 406 if (xkbi->selected_events&XkbAccessXNotifyMask) { 407 xkbAccessXNotify *axn =(xkbAccessXNotify *)event; 408 XkbAccessXNotifyEvent *axev; 409 axev =(XkbAccessXNotifyEvent *)re; 410 axev->type = XkbEventCode+xkbi->codes->first_event; 411 axev->xkb_type = XkbAccessXNotify; 412 axev->serial = _XSetLastRequestRead(dpy, 413 (xGenericReply *)event); 414 axev->send_event = ((event->u.u.type&0x80)!=0); 415 axev->display = dpy; 416 axev->time = axn->time; 417 axev->device = axn->deviceID; 418 axev->detail = axn->detail; 419 axev->keycode = axn->keycode; 420 axev->sk_delay = axn->slowKeysDelay; 421 axev->debounce_delay = axn->debounceDelay; 422 return True; 423 } 424 } 425 break; 426 case XkbNamesNotify: 427 { 428 if (xkbi->selected_events&XkbNamesNotifyMask) { 429 xkbNamesNotify *nn =(xkbNamesNotify *)event; 430 XkbNamesNotifyEvent *nev; 431 nev =(XkbNamesNotifyEvent *)re; 432 nev->type = XkbEventCode+xkbi->codes->first_event; 433 nev->xkb_type = XkbNamesNotify; 434 nev->serial = _XSetLastRequestRead(dpy, 435 (xGenericReply *)event); 436 nev->send_event = ((event->u.u.type&0x80)!=0); 437 nev->display = dpy; 438 nev->time = nn->time; 439 nev->device = nn->deviceID; 440 nev->changed = nn->changed; 441 nev->first_type = nn->firstType; 442 nev->num_types = nn->nTypes; 443 nev->first_lvl = nn->firstLevelName; 444 nev->num_lvls = nn->nLevelNames; 445 nev->num_aliases = nn->nAliases; 446 nev->num_radio_groups = nn->nRadioGroups; 447 nev->changed_vmods = nn->changedVirtualMods; 448 nev->changed_groups = nn->changedGroupNames; 449 nev->changed_indicators = nn->changedIndicators; 450 nev->first_key = nn->firstKey; 451 nev->num_keys = nn->nKeys; 452 return True; 453 } 454 } 455 break; 456 case XkbCompatMapNotify: 457 { 458 if (xkbi->selected_events&XkbCompatMapNotifyMask) { 459 xkbCompatMapNotify *cmn =(xkbCompatMapNotify *)event; 460 XkbCompatMapNotifyEvent *cmev; 461 cmev =(XkbCompatMapNotifyEvent *)re; 462 cmev->type = XkbEventCode+xkbi->codes->first_event; 463 cmev->xkb_type = XkbCompatMapNotify; 464 cmev->serial = _XSetLastRequestRead(dpy, 465 (xGenericReply *)event); 466 cmev->send_event = ((event->u.u.type&0x80)!=0); 467 cmev->display = dpy; 468 cmev->time = cmn->time; 469 cmev->device = cmn->deviceID; 470 cmev->changed_groups = cmn->changedGroups; 471 cmev->first_si = cmn->firstSI; 472 cmev->num_si = cmn->nSI; 473 cmev->num_total_si = cmn->nTotalSI; 474 return True; 475 } 476 } 477 break; 478 case XkbActionMessage: 479 { 480 if (xkbi->selected_events&XkbActionMessageMask) { 481 xkbActionMessage *am= (xkbActionMessage *)event; 482 XkbActionMessageEvent *amev; 483 amev= (XkbActionMessageEvent *)re; 484 amev->type = XkbEventCode+xkbi->codes->first_event; 485 amev->xkb_type = XkbActionMessage; 486 amev->serial = _XSetLastRequestRead(dpy, 487 (xGenericReply *)event); 488 amev->send_event = ((event->u.u.type&0x80)!=0); 489 amev->display = dpy; 490 amev->time = am->time; 491 amev->device = am->deviceID; 492 amev->keycode = am->keycode; 493 amev->press = am->press; 494 amev->key_event_follows = am->keyEventFollows; 495 amev->group = am->group; 496 amev->mods = am->mods; 497 memcpy(amev->message,am->message,XkbActionMessageLength); 498 amev->message[XkbActionMessageLength]= '\0'; 499 return True; 500 } 501 } 502 break; 503 case XkbExtensionDeviceNotify: 504 { 505 if (xkbi->selected_events&XkbExtensionDeviceNotifyMask) { 506 xkbExtensionDeviceNotify *ed= 507 (xkbExtensionDeviceNotify *)event; 508 XkbExtensionDeviceNotifyEvent *edev; 509 edev= (XkbExtensionDeviceNotifyEvent *)re; 510 edev->type= XkbEventCode+xkbi->codes->first_event; 511 edev->xkb_type= XkbExtensionDeviceNotify; 512 edev->serial= _XSetLastRequestRead(dpy, 513 (xGenericReply *)event); 514 edev->send_event= ((event->u.u.type&0x80)!=0); 515 edev->display= dpy; 516 edev->time= ed->time; 517 edev->device= ed->deviceID; 518 edev->led_class= ed->ledClass; 519 edev->led_id= ed->ledID; 520 edev->reason= ed->reason; 521 edev->supported= ed->supported; 522 edev->leds_defined= ed->ledsDefined; 523 edev->led_state= ed->ledState; 524 edev->first_btn= ed->firstBtn; 525 edev->num_btns= ed->nBtns; 526 edev->unsupported= ed->unsupported; 527 return True; 528 } 529 } 530 break; 531 case XkbNewKeyboardNotify: 532 { 533 xkbNewKeyboardNotify *nkn = (xkbNewKeyboardNotify *)event; 534 if ((xkbi->selected_events&XkbNewKeyboardNotifyMask)&& 535 (xkbi->selected_nkn_details&nkn->changed)) { 536 XkbNewKeyboardNotifyEvent *nkev; 537 nkev =(XkbNewKeyboardNotifyEvent *)re; 538 nkev->type = XkbEventCode+xkbi->codes->first_event; 539 nkev->xkb_type = XkbNewKeyboardNotify; 540 nkev->serial = _XSetLastRequestRead(dpy, 541 (xGenericReply *)event); 542 nkev->send_event = ((event->u.u.type&0x80)!=0); 543 nkev->display = dpy; 544 nkev->time = nkn->time; 545 nkev->device = nkn->deviceID; 546 nkev->old_device = nkn->oldDeviceID; 547 nkev->min_key_code = nkn->minKeyCode; 548 nkev->max_key_code = nkn->maxKeyCode; 549 nkev->old_min_key_code = nkn->oldMinKeyCode; 550 nkev->old_max_key_code = nkn->oldMaxKeyCode; 551 nkev->req_major = nkn->requestMajor; 552 nkev->req_minor = nkn->requestMinor; 553 nkev->changed = nkn->changed; 554 if ((xkbi->desc)&&(nkev->send_event==0)&& 555 ((xkbi->desc->device_spec==nkev->old_device)|| 556 (nkev->device!=nkev->old_device))) { 557 xkbi->flags= XkbMapPending|XkbXlibNewKeyboard; 558 } 559 return True; 560 } 561 else if(nkn->changed&(XkbNKN_KeycodesMask|XkbNKN_DeviceIDMask)){ 562 register XMappingEvent *ev = (XMappingEvent *)re; 563 ev->type = MappingNotify; 564 ev->serial = _XSetLastRequestRead(dpy, 565 (xGenericReply *)event); 566 ev->send_event = ((event->u.u.type&0x80)!=0); 567 ev->display = dpy; 568 ev->window = 0; 569 ev->first_keycode = dpy->min_keycode; 570 ev->request = MappingKeyboard; 571 ev->count = (dpy->max_keycode-dpy->min_keycode)+1; 572 if ((xkbi->desc)&&(ev->send_event==0)&& 573 ((xkbi->desc->device_spec==nkn->oldDeviceID)|| 574 (nkn->deviceID!=nkn->oldDeviceID))) { 575 xkbi->flags|= XkbMapPending|XkbXlibNewKeyboard; 576 } 577 return True; 578 } 579 } 580 break; 581 default: 582#ifdef DEBUG 583 fprintf(stderr,"Got unknown XKEYBOARD event (%d, base=%d)\n", 584 re->type, 585 xkbi->codes->first_event); 586#endif 587 break; 588 } 589 return False; 590} 591 592Bool 593XkbIgnoreExtension(Bool ignore) 594{ 595 if (getenv("XKB_FORCE")!=NULL) { 596#ifdef DEBUG 597 fprintf(stderr,"Forcing use of XKEYBOARD (overriding an IgnoreExtensions)\n"); 598#endif 599 return False; 600 } 601#ifdef DEBUG 602 else if (getenv("XKB_DEBUG")!=NULL) { 603 fprintf(stderr,"Explicitly %signoring XKEYBOARD\n",ignore?"":"not "); 604 } 605#endif 606 _XkbIgnoreExtension = ignore; 607 return True; 608} 609 610static void 611_XkbFreeInfo(Display *dpy) 612{ 613 XkbInfoPtr xkbi = dpy->xkb_info; 614 if (xkbi) { 615 if (xkbi->desc) 616 XkbFreeKeyboard(xkbi->desc,XkbAllComponentsMask,True); 617 Xfree(xkbi); 618 } 619} 620 621Bool 622XkbUseExtension(Display *dpy,int *major_rtrn,int *minor_rtrn) 623{ 624 xkbUseExtensionReply rep; 625 register xkbUseExtensionReq *req; 626 XExtCodes *codes; 627 int ev_base,forceIgnore; 628 XkbInfoPtr xkbi; 629 char * str; 630 static int debugMsg; 631 static int been_here= 0; 632 633 if ( dpy->xkb_info && !(dpy->flags & XlibDisplayNoXkb)) { 634 if (major_rtrn) *major_rtrn= dpy->xkb_info->srv_major; 635 if (minor_rtrn) *minor_rtrn= dpy->xkb_info->srv_minor; 636 return True; 637 } 638 if (!been_here) { 639 debugMsg= (getenv("XKB_DEBUG")!=NULL); 640 been_here= 1; 641 } 642 643 if (major_rtrn) *major_rtrn= 0; 644 if (minor_rtrn) *minor_rtrn= 0; 645 646 if (!dpy->xkb_info) { 647 xkbi = _XkbTypedCalloc(1, XkbInfoRec); 648 if ( !xkbi ) 649 return False; 650 dpy->xkb_info = xkbi; 651 dpy->free_funcs->xkb = _XkbFreeInfo; 652 653 xkbi->xlib_ctrls|= (XkbLC_ControlFallback|XkbLC_ConsumeLookupMods); 654 if ((str=getenv("_XKB_OPTIONS_ENABLE"))!=NULL) { 655 if ((str=getenv("_XKB_LATIN1_LOOKUP"))!=NULL) { 656 if ((strcmp(str,"off")==0)||(strcmp(str,"0")==0)) 657 xkbi->xlib_ctrls&= ~XkbLC_ForceLatin1Lookup; 658 else xkbi->xlib_ctrls|= XkbLC_ForceLatin1Lookup; 659 } 660 if ((str=getenv("_XKB_CONSUME_LOOKUP_MODS"))!=NULL) { 661 if ((strcmp(str,"off")==0)||(strcmp(str,"0")==0)) 662 xkbi->xlib_ctrls&= ~XkbLC_ConsumeLookupMods; 663 else xkbi->xlib_ctrls|= XkbLC_ConsumeLookupMods; 664 } 665 if ((str=getenv("_XKB_CONSUME_SHIFT_AND_LOCK"))!=NULL) { 666 if ((strcmp(str,"off")==0)||(strcmp(str,"0")==0)) 667 xkbi->xlib_ctrls&= ~XkbLC_AlwaysConsumeShiftAndLock; 668 else xkbi->xlib_ctrls|= XkbLC_AlwaysConsumeShiftAndLock; 669 } 670 if ((str=getenv("_XKB_IGNORE_NEW_KEYBOARDS"))!=NULL) { 671 if ((strcmp(str,"off")==0)||(strcmp(str,"0")==0)) 672 xkbi->xlib_ctrls&= ~XkbLC_IgnoreNewKeyboards; 673 else xkbi->xlib_ctrls|= XkbLC_IgnoreNewKeyboards; 674 } 675 if ((str=getenv("_XKB_CONTROL_FALLBACK"))!=NULL) { 676 if ((strcmp(str,"off")==0)||(strcmp(str,"0")==0)) 677 xkbi->xlib_ctrls&= ~XkbLC_ControlFallback; 678 else xkbi->xlib_ctrls|= XkbLC_ControlFallback; 679 } 680 if ((str=getenv("_XKB_COMP_LED"))!=NULL) { 681 if ((strcmp(str,"off")==0)||(strcmp(str,"0")==0)) 682 xkbi->xlib_ctrls&= ~XkbLC_ComposeLED; 683 else { 684 xkbi->xlib_ctrls|= XkbLC_ComposeLED; 685 if (strlen(str)>0) 686 xkbi->composeLED= XInternAtom(dpy,str,False); 687 } 688 } 689 if ((str=getenv("_XKB_COMP_FAIL_BEEP"))!=NULL) { 690 if ((strcmp(str,"off")==0)||(strcmp(str,"0")==0)) 691 xkbi->xlib_ctrls&= ~XkbLC_BeepOnComposeFail; 692 else xkbi->xlib_ctrls|= XkbLC_BeepOnComposeFail; 693 } 694 } 695 if ((xkbi->composeLED==None)&&((xkbi->xlib_ctrls&XkbLC_ComposeLED)!=0)) 696 xkbi->composeLED= XInternAtom(dpy,"Compose",False); 697#ifdef DEBUG 698 if (debugMsg) { 699 register unsigned c= xkbi->xlib_ctrls; 700 fprintf(stderr,"XKEYBOARD compose: beep on failure is %s, LED is %s\n", 701 ((c&XkbLC_BeepOnComposeFail)?"on":"off"), 702 ((c&XkbLC_ComposeLED)?"on":"off")); 703 fprintf(stderr,"XKEYBOARD XLookupString: %slatin-1, %s lookup modifiers\n", 704 ((c&XkbLC_ForceLatin1Lookup)?"allow non-":"force "), 705 ((c&XkbLC_ConsumeLookupMods)?"consume":"re-use")); 706 fprintf(stderr, 707 "XKEYBOARD XLookupString: %sconsume shift and lock, %scontrol fallback\n", 708 ((c&XkbLC_AlwaysConsumeShiftAndLock)?"always ":"don't "), 709 ((c&XkbLC_ControlFallback)?"":"no ")); 710 711 } 712#endif 713 } else 714 xkbi = dpy->xkb_info; 715 716 forceIgnore= (dpy->flags&XlibDisplayNoXkb)||dpy->keysyms; 717 forceIgnore= forceIgnore&&(major_rtrn==NULL)&&(minor_rtrn==NULL); 718 if ( forceIgnore || _XkbIgnoreExtension || getenv("XKB_DISABLE")) { 719 LockDisplay(dpy); 720 dpy->flags |= XlibDisplayNoXkb; 721 UnlockDisplay(dpy); 722 if (debugMsg) 723 fprintf(stderr,"XKEYBOARD extension disabled or missing\n"); 724 return False; 725 } 726 727 if ( (codes=XInitExtension(dpy,XkbName))==NULL ) { 728 LockDisplay(dpy); 729 dpy->flags |= XlibDisplayNoXkb; 730 UnlockDisplay(dpy); 731 if (debugMsg) 732 fprintf(stderr,"XKEYBOARD extension not present\n"); 733 return False; 734 } 735 xkbi->codes = codes; 736 LockDisplay(dpy); 737 738 GetReq(kbUseExtension, req); 739 req->reqType = xkbi->codes->major_opcode; 740 req->xkbReqType = X_kbUseExtension; 741 req->wantedMajor = XkbMajorVersion; 742 req->wantedMinor = XkbMinorVersion; 743 if (!_XReply(dpy, (xReply *)&rep, 0, xFalse) || !rep.supported ) { 744 Bool fail; 745 fail= True; 746 if (debugMsg) 747 fprintf(stderr, 748 "XKEYBOARD version mismatch (want %d.%02d, got %d.%02d)\n", 749 XkbMajorVersion,XkbMinorVersion, 750 rep.serverMajor, rep.serverMinor); 751 752 /* pre-release 0.65 is very close to 1.00 */ 753 if ((rep.serverMajor==0)&&(rep.serverMinor==65)) { 754 if (debugMsg) 755 fprintf(stderr,"Trying to fall back to version 0.65..."); 756 GetReq(kbUseExtension, req); 757 req->reqType = xkbi->codes->major_opcode; 758 req->xkbReqType = X_kbUseExtension; 759 req->wantedMajor = 0; 760 req->wantedMinor = 65; 761 if ( _XReply(dpy, (xReply *)&rep, 0, xFalse) && rep.supported ) { 762 if (debugMsg) 763 fprintf(stderr,"succeeded\n"); 764 fail= False; 765 } 766 else if (debugMsg) fprintf(stderr,"failed\n"); 767 } 768 if (fail) { 769 dpy->flags |= XlibDisplayNoXkb; 770 UnlockDisplay(dpy); 771 SyncHandle(); 772 if (major_rtrn) *major_rtrn= rep.serverMajor; 773 if (minor_rtrn) *minor_rtrn= rep.serverMinor; 774 return False; 775 } 776 } 777#ifdef DEBUG 778 else if ( forceIgnore ) { 779 fprintf(stderr,"Internal Error! XkbUseExtension succeeded with forceIgnore set\n"); 780 } 781#endif 782 UnlockDisplay(dpy); 783 xkbi->srv_major= rep.serverMajor; 784 xkbi->srv_minor= rep.serverMinor; 785 if (major_rtrn) *major_rtrn= rep.serverMajor; 786 if (minor_rtrn) *minor_rtrn= rep.serverMinor; 787 if (debugMsg) 788 fprintf(stderr,"XKEYBOARD (version %d.%02d/%d.%02d) OK!\n", 789 XkbMajorVersion,XkbMinorVersion, 790 rep.serverMajor,rep.serverMinor); 791 792 ev_base = codes->first_event; 793 XESetWireToEvent(dpy,ev_base+XkbEventCode,wire_to_event); 794 SyncHandle(); 795 return True; 796} 797 798