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 dpy->xkb_info = NULL; 616 } 617} 618 619Bool 620XkbUseExtension(Display *dpy, int *major_rtrn, int *minor_rtrn) 621{ 622 xkbUseExtensionReply rep; 623 register xkbUseExtensionReq *req; 624 XExtCodes *codes; 625 int ev_base, forceIgnore; 626 XkbInfoPtr xkbi; 627 char *str; 628 static int debugMsg; 629 static int been_here = 0; 630 631 if (dpy->xkb_info && !(dpy->flags & XlibDisplayNoXkb)) { 632 if (major_rtrn) 633 *major_rtrn = dpy->xkb_info->srv_major; 634 if (minor_rtrn) 635 *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) 644 *major_rtrn = 0; 645 if (minor_rtrn) 646 *minor_rtrn = 0; 647 648 if (!dpy->xkb_info) { 649 xkbi = _XkbTypedCalloc(1, XkbInfoRec); 650 if (!xkbi) 651 return False; 652 dpy->xkb_info = xkbi; 653 dpy->free_funcs->xkb = _XkbFreeInfo; 654 655 xkbi->xlib_ctrls |= (XkbLC_ControlFallback | XkbLC_ConsumeLookupMods); 656 if ((str = getenv("_XKB_OPTIONS_ENABLE")) != NULL) { 657 if ((str = getenv("_XKB_LATIN1_LOOKUP")) != NULL) { 658 if ((strcmp(str, "off") == 0) || (strcmp(str, "0") == 0)) 659 xkbi->xlib_ctrls &= ~XkbLC_ForceLatin1Lookup; 660 else 661 xkbi->xlib_ctrls |= XkbLC_ForceLatin1Lookup; 662 } 663 if ((str = getenv("_XKB_CONSUME_LOOKUP_MODS")) != NULL) { 664 if ((strcmp(str, "off") == 0) || (strcmp(str, "0") == 0)) 665 xkbi->xlib_ctrls &= ~XkbLC_ConsumeLookupMods; 666 else 667 xkbi->xlib_ctrls |= XkbLC_ConsumeLookupMods; 668 } 669 if ((str = getenv("_XKB_CONSUME_SHIFT_AND_LOCK")) != NULL) { 670 if ((strcmp(str, "off") == 0) || (strcmp(str, "0") == 0)) 671 xkbi->xlib_ctrls &= ~XkbLC_AlwaysConsumeShiftAndLock; 672 else 673 xkbi->xlib_ctrls |= XkbLC_AlwaysConsumeShiftAndLock; 674 } 675 if ((str = getenv("_XKB_IGNORE_NEW_KEYBOARDS")) != NULL) { 676 if ((strcmp(str, "off") == 0) || (strcmp(str, "0") == 0)) 677 xkbi->xlib_ctrls &= ~XkbLC_IgnoreNewKeyboards; 678 else 679 xkbi->xlib_ctrls |= XkbLC_IgnoreNewKeyboards; 680 } 681 if ((str = getenv("_XKB_CONTROL_FALLBACK")) != NULL) { 682 if ((strcmp(str, "off") == 0) || (strcmp(str, "0") == 0)) 683 xkbi->xlib_ctrls &= ~XkbLC_ControlFallback; 684 else 685 xkbi->xlib_ctrls |= XkbLC_ControlFallback; 686 } 687 if ((str = getenv("_XKB_COMP_LED")) != NULL) { 688 if ((strcmp(str, "off") == 0) || (strcmp(str, "0") == 0)) 689 xkbi->xlib_ctrls &= ~XkbLC_ComposeLED; 690 else { 691 xkbi->xlib_ctrls |= XkbLC_ComposeLED; 692 if (strlen(str) > 0) 693 xkbi->composeLED = XInternAtom(dpy, str, False); 694 } 695 } 696 if ((str = getenv("_XKB_COMP_FAIL_BEEP")) != NULL) { 697 if ((strcmp(str, "off") == 0) || (strcmp(str, "0") == 0)) 698 xkbi->xlib_ctrls &= ~XkbLC_BeepOnComposeFail; 699 else 700 xkbi->xlib_ctrls |= XkbLC_BeepOnComposeFail; 701 } 702 } 703 if ((xkbi->composeLED == None) && 704 ((xkbi->xlib_ctrls & XkbLC_ComposeLED) != 0)) 705 xkbi->composeLED = XInternAtom(dpy, "Compose", False); 706#ifdef DEBUG 707 if (debugMsg) { 708 register unsigned c = xkbi->xlib_ctrls; 709 710 fprintf(stderr, 711 "XKEYBOARD compose: beep on failure is %s, LED is %s\n", 712 ((c & XkbLC_BeepOnComposeFail) ? "on" : "off"), 713 ((c & XkbLC_ComposeLED) ? "on" : "off")); 714 fprintf(stderr, 715 "XKEYBOARD XLookupString: %slatin-1, %s lookup modifiers\n", 716 ((c & XkbLC_ForceLatin1Lookup) ? "allow non-" : "force "), 717 ((c & XkbLC_ConsumeLookupMods) ? "consume" : "re-use")); 718 fprintf(stderr, 719 "XKEYBOARD XLookupString: %sconsume shift and lock, %scontrol fallback\n", 720 ((c & XkbLC_AlwaysConsumeShiftAndLock) ? "always " : 721 "don't "), ((c & XkbLC_ControlFallback) ? "" : "no ")); 722 723 } 724#endif 725 } 726 else 727 xkbi = dpy->xkb_info; 728 729 forceIgnore = (dpy->flags & XlibDisplayNoXkb) || dpy->keysyms; 730 forceIgnore = forceIgnore && (major_rtrn == NULL) && (minor_rtrn == NULL); 731 if (forceIgnore || _XkbIgnoreExtension || getenv("XKB_DISABLE")) { 732 LockDisplay(dpy); 733 dpy->flags |= XlibDisplayNoXkb; 734 UnlockDisplay(dpy); 735 if (debugMsg) 736 fprintf(stderr, "XKEYBOARD extension disabled or missing\n"); 737 return False; 738 } 739 740 if ((codes = XInitExtension(dpy, XkbName)) == NULL) { 741 LockDisplay(dpy); 742 dpy->flags |= XlibDisplayNoXkb; 743 UnlockDisplay(dpy); 744 if (debugMsg) 745 fprintf(stderr, "XKEYBOARD extension not present\n"); 746 return False; 747 } 748 xkbi->codes = codes; 749 LockDisplay(dpy); 750 751 GetReq(kbUseExtension, req); 752 req->reqType = xkbi->codes->major_opcode; 753 req->xkbReqType = X_kbUseExtension; 754 req->wantedMajor = XkbMajorVersion; 755 req->wantedMinor = XkbMinorVersion; 756 if (!_XReply(dpy, (xReply *) &rep, 0, xFalse) || !rep.supported) { 757 Bool fail = True; 758 759 if (debugMsg) 760 fprintf(stderr, 761 "XKEYBOARD version mismatch (want %d.%02d, got %d.%02d)\n", 762 XkbMajorVersion, XkbMinorVersion, 763 rep.serverMajor, rep.serverMinor); 764 765 /* pre-release 0.65 is very close to 1.00 */ 766 if ((rep.serverMajor == 0) && (rep.serverMinor == 65)) { 767 if (debugMsg) 768 fprintf(stderr, "Trying to fall back to version 0.65..."); 769 GetReq(kbUseExtension, req); 770 req->reqType = xkbi->codes->major_opcode; 771 req->xkbReqType = X_kbUseExtension; 772 req->wantedMajor = 0; 773 req->wantedMinor = 65; 774 if (_XReply(dpy, (xReply *) &rep, 0, xFalse) && rep.supported) { 775 if (debugMsg) 776 fprintf(stderr, "succeeded\n"); 777 fail = False; 778 } 779 else if (debugMsg) 780 fprintf(stderr, "failed\n"); 781 } 782 if (fail) { 783 dpy->flags |= XlibDisplayNoXkb; 784 UnlockDisplay(dpy); 785 SyncHandle(); 786 if (major_rtrn) 787 *major_rtrn = rep.serverMajor; 788 if (minor_rtrn) 789 *minor_rtrn = rep.serverMinor; 790 return False; 791 } 792 } 793#ifdef DEBUG 794 else if (forceIgnore) { 795 fprintf(stderr, 796 "Internal Error! XkbUseExtension succeeded with forceIgnore set\n"); 797 } 798#endif 799 UnlockDisplay(dpy); 800 xkbi->srv_major = rep.serverMajor; 801 xkbi->srv_minor = rep.serverMinor; 802 if (major_rtrn) 803 *major_rtrn = rep.serverMajor; 804 if (minor_rtrn) 805 *minor_rtrn = rep.serverMinor; 806 if (debugMsg) 807 fprintf(stderr, "XKEYBOARD (version %d.%02d/%d.%02d) OK!\n", 808 XkbMajorVersion, XkbMinorVersion, 809 rep.serverMajor, rep.serverMinor); 810 811 ev_base = codes->first_event; 812 XESetWireToEvent(dpy, ev_base + XkbEventCode, wire_to_event); 813 SyncHandle(); 814 return True; 815} 816