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