1 /************************************************************ 2 Copyright (c) 1993 by Silicon Graphics Computer Systems, Inc. 3 4 Permission to use, copy, modify, and distribute this 5 software and its documentation for any purpose and without 6 fee is hereby granted, provided that the above copyright 7 notice appear in all copies and that both that copyright 8 notice and this permission notice appear in supporting 9 documentation, and that the name of Silicon Graphics not be 10 used in advertising or publicity pertaining to distribution 11 of the software without specific prior written permission. 12 Silicon Graphics makes no representation about the suitability 13 of this software for any purpose. It is provided "as is" 14 without any express or implied warranty. 15 16 SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS 17 SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 18 AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON 19 GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL 20 DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 21 DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 22 OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH 23 THE 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 36 static Bool _XkbIgnoreExtension = False; 37 38 void 39 XkbNoteMapChanges(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 180 void 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 209 static Bool 210 wire_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 if (xkbi->desc && xkbi->desc->device_spec == mn->deviceID) { 294 XkbNoteMapChanges(&xkbi->changes, mev, XKB_XLIB_MAP_MASK); 295 if (xkbi->changes.changed) 296 xkbi->flags |= XkbMapPending; 297 } 298 return True; 299 } 300 else if (mn->nKeySyms > 0) { 301 register XMappingEvent *ev = (XMappingEvent *) re; 302 303 ev->type = MappingNotify; 304 ev->serial = _XSetLastRequestRead(dpy, (xGenericReply *) event); 305 ev->send_event = ((event->u.u.type & 0x80) != 0); 306 ev->display = dpy; 307 ev->window = 0; 308 ev->first_keycode = mn->firstKeySym; 309 ev->request = MappingKeyboard; 310 ev->count = mn->nKeySyms; 311 if (xkbi->desc && xkbi->desc->device_spec == mn->deviceID) { 312 _XkbNoteCoreMapChanges(&xkbi->changes, ev, XKB_XLIB_MAP_MASK); 313 if (xkbi->changes.changed) 314 xkbi->flags |= XkbMapPending; 315 } 316 return True; 317 } 318 } 319 break; 320 case XkbControlsNotify: 321 { 322 if (xkbi->selected_events & XkbControlsNotifyMask) { 323 xkbControlsNotify *cn = (xkbControlsNotify *) event; 324 XkbControlsNotifyEvent *cev = (XkbControlsNotifyEvent *) re; 325 326 cev->type = XkbEventCode + xkbi->codes->first_event; 327 cev->xkb_type = XkbControlsNotify; 328 cev->serial = _XSetLastRequestRead(dpy, (xGenericReply *) event); 329 cev->send_event = ((event->u.u.type & 0x80) != 0); 330 cev->display = dpy; 331 cev->time = cn->time; 332 cev->device = cn->deviceID; 333 cev->changed_ctrls = cn->changedControls; 334 cev->enabled_ctrls = cn->enabledControls; 335 cev->enabled_ctrl_changes = cn->enabledControlChanges; 336 cev->keycode = cn->keycode; 337 cev->num_groups = cn->numGroups; 338 cev->event_type = cn->eventType; 339 cev->req_major = cn->requestMajor; 340 cev->req_minor = cn->requestMinor; 341 return True; 342 } 343 } 344 break; 345 case XkbIndicatorMapNotify: 346 { 347 if (xkbi->selected_events & XkbIndicatorMapNotifyMask) { 348 xkbIndicatorNotify *in = (xkbIndicatorNotify *) event; 349 XkbIndicatorNotifyEvent *iev = (XkbIndicatorNotifyEvent *) re; 350 351 iev->type = XkbEventCode + xkbi->codes->first_event; 352 iev->xkb_type = XkbIndicatorMapNotify; 353 iev->serial = _XSetLastRequestRead(dpy, (xGenericReply *) event); 354 iev->send_event = ((event->u.u.type & 0x80) != 0); 355 iev->display = dpy; 356 iev->time = in->time; 357 iev->device = in->deviceID; 358 iev->changed = in->changed; 359 iev->state = in->state; 360 return True; 361 } 362 } 363 break; 364 case XkbIndicatorStateNotify: 365 { 366 if (xkbi->selected_events & XkbIndicatorStateNotifyMask) { 367 xkbIndicatorNotify *in = (xkbIndicatorNotify *) event; 368 XkbIndicatorNotifyEvent *iev = (XkbIndicatorNotifyEvent *) re; 369 370 iev->type = XkbEventCode + xkbi->codes->first_event; 371 iev->xkb_type = XkbIndicatorStateNotify; 372 iev->serial = _XSetLastRequestRead(dpy, (xGenericReply *) event); 373 iev->send_event = ((event->u.u.type & 0x80) != 0); 374 iev->display = dpy; 375 iev->time = in->time; 376 iev->device = in->deviceID; 377 iev->changed = in->changed; 378 iev->state = in->state; 379 return True; 380 } 381 } 382 break; 383 case XkbBellNotify: 384 { 385 if (xkbi->selected_events & XkbBellNotifyMask) { 386 xkbBellNotify *bn = (xkbBellNotify *) event; 387 XkbBellNotifyEvent *bev = (XkbBellNotifyEvent *) re; 388 389 bev->type = XkbEventCode + xkbi->codes->first_event; 390 bev->xkb_type = XkbBellNotify; 391 bev->serial = _XSetLastRequestRead(dpy, (xGenericReply *) event); 392 bev->send_event = ((event->u.u.type & 0x80) != 0); 393 bev->display = dpy; 394 bev->time = bn->time; 395 bev->device = bn->deviceID; 396 bev->percent = bn->percent; 397 bev->pitch = bn->pitch; 398 bev->duration = bn->duration; 399 bev->bell_class = bn->bellClass; 400 bev->bell_id = bn->bellID; 401 bev->name = bn->name; 402 bev->window = bn->window; 403 bev->event_only = bn->eventOnly; 404 return True; 405 } 406 } 407 break; 408 case XkbAccessXNotify: 409 { 410 if (xkbi->selected_events & XkbAccessXNotifyMask) { 411 xkbAccessXNotify *axn = (xkbAccessXNotify *) event; 412 XkbAccessXNotifyEvent *axev = (XkbAccessXNotifyEvent *) re; 413 414 axev->type = XkbEventCode + xkbi->codes->first_event; 415 axev->xkb_type = XkbAccessXNotify; 416 axev->serial = _XSetLastRequestRead(dpy, (xGenericReply *) event); 417 axev->send_event = ((event->u.u.type & 0x80) != 0); 418 axev->display = dpy; 419 axev->time = axn->time; 420 axev->device = axn->deviceID; 421 axev->detail = axn->detail; 422 axev->keycode = axn->keycode; 423 axev->sk_delay = axn->slowKeysDelay; 424 axev->debounce_delay = axn->debounceDelay; 425 return True; 426 } 427 } 428 break; 429 case XkbNamesNotify: 430 { 431 if (xkbi->selected_events & XkbNamesNotifyMask) { 432 xkbNamesNotify *nn = (xkbNamesNotify *) event; 433 XkbNamesNotifyEvent *nev = (XkbNamesNotifyEvent *) re; 434 435 nev->type = XkbEventCode + xkbi->codes->first_event; 436 nev->xkb_type = XkbNamesNotify; 437 nev->serial = _XSetLastRequestRead(dpy, (xGenericReply *) event); 438 nev->send_event = ((event->u.u.type & 0x80) != 0); 439 nev->display = dpy; 440 nev->time = nn->time; 441 nev->device = nn->deviceID; 442 nev->changed = nn->changed; 443 nev->first_type = nn->firstType; 444 nev->num_types = nn->nTypes; 445 nev->first_lvl = nn->firstLevelName; 446 nev->num_lvls = nn->nLevelNames; 447 nev->num_aliases = nn->nAliases; 448 nev->num_radio_groups = nn->nRadioGroups; 449 nev->changed_vmods = nn->changedVirtualMods; 450 nev->changed_groups = nn->changedGroupNames; 451 nev->changed_indicators = nn->changedIndicators; 452 nev->first_key = nn->firstKey; 453 nev->num_keys = nn->nKeys; 454 return True; 455 } 456 } 457 break; 458 case XkbCompatMapNotify: 459 { 460 if (xkbi->selected_events & XkbCompatMapNotifyMask) { 461 xkbCompatMapNotify *cmn = (xkbCompatMapNotify *) event; 462 XkbCompatMapNotifyEvent *cmev = (XkbCompatMapNotifyEvent *) re; 463 464 cmev->type = XkbEventCode + xkbi->codes->first_event; 465 cmev->xkb_type = XkbCompatMapNotify; 466 cmev->serial = _XSetLastRequestRead(dpy, (xGenericReply *) event); 467 cmev->send_event = ((event->u.u.type & 0x80) != 0); 468 cmev->display = dpy; 469 cmev->time = cmn->time; 470 cmev->device = cmn->deviceID; 471 cmev->changed_groups = cmn->changedGroups; 472 cmev->first_si = cmn->firstSI; 473 cmev->num_si = cmn->nSI; 474 cmev->num_total_si = cmn->nTotalSI; 475 return True; 476 } 477 } 478 break; 479 case XkbActionMessage: 480 { 481 if (xkbi->selected_events & XkbActionMessageMask) { 482 xkbActionMessage *am = (xkbActionMessage *) event; 483 XkbActionMessageEvent *amev = (XkbActionMessageEvent *) re; 484 485 amev->type = XkbEventCode + xkbi->codes->first_event; 486 amev->xkb_type = XkbActionMessage; 487 amev->serial = _XSetLastRequestRead(dpy, (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 = (xkbExtensionDeviceNotify *) event; 507 XkbExtensionDeviceNotifyEvent *edev 508 = (XkbExtensionDeviceNotifyEvent *) re; 509 510 edev->type = XkbEventCode + xkbi->codes->first_event; 511 edev->xkb_type = XkbExtensionDeviceNotify; 512 edev->serial = _XSetLastRequestRead(dpy, (xGenericReply *) event); 513 edev->send_event = ((event->u.u.type & 0x80) != 0); 514 edev->display = dpy; 515 edev->time = ed->time; 516 edev->device = ed->deviceID; 517 edev->led_class = ed->ledClass; 518 edev->led_id = ed->ledID; 519 edev->reason = ed->reason; 520 edev->supported = ed->supported; 521 edev->leds_defined = ed->ledsDefined; 522 edev->led_state = ed->ledState; 523 edev->first_btn = ed->firstBtn; 524 edev->num_btns = ed->nBtns; 525 edev->unsupported = ed->unsupported; 526 return True; 527 } 528 } 529 break; 530 case XkbNewKeyboardNotify: 531 { 532 xkbNewKeyboardNotify *nkn = (xkbNewKeyboardNotify *) event; 533 534 if ((xkbi->selected_events & XkbNewKeyboardNotifyMask) && 535 (xkbi->selected_nkn_details & nkn->changed)) { 536 XkbNewKeyboardNotifyEvent *nkev = (XkbNewKeyboardNotifyEvent *) re; 537 538 nkev->type = XkbEventCode + xkbi->codes->first_event; 539 nkev->xkb_type = XkbNewKeyboardNotify; 540 nkev->serial = _XSetLastRequestRead(dpy, (xGenericReply *) event); 541 nkev->send_event = ((event->u.u.type & 0x80) != 0); 542 nkev->display = dpy; 543 nkev->time = nkn->time; 544 nkev->device = nkn->deviceID; 545 nkev->old_device = nkn->oldDeviceID; 546 nkev->min_key_code = nkn->minKeyCode; 547 nkev->max_key_code = nkn->maxKeyCode; 548 nkev->old_min_key_code = nkn->oldMinKeyCode; 549 nkev->old_max_key_code = nkn->oldMaxKeyCode; 550 nkev->req_major = nkn->requestMajor; 551 nkev->req_minor = nkn->requestMinor; 552 nkev->changed = nkn->changed; 553 if ((xkbi->desc) && (nkev->send_event == 0) && 554 ((xkbi->desc->device_spec == nkev->old_device) || 555 (nkev->device != nkev->old_device))) { 556 xkbi->flags = XkbMapPending | XkbXlibNewKeyboard; 557 } 558 return True; 559 } 560 else if (nkn->changed & (XkbNKN_KeycodesMask | XkbNKN_DeviceIDMask)) { 561 register XMappingEvent *ev = (XMappingEvent *) re; 562 563 ev->type = MappingNotify; 564 ev->serial = _XSetLastRequestRead(dpy, (xGenericReply *) event); 565 ev->send_event = ((event->u.u.type & 0x80) != 0); 566 ev->display = dpy; 567 ev->window = 0; 568 ev->first_keycode = dpy->min_keycode; 569 ev->request = MappingKeyboard; 570 ev->count = (dpy->max_keycode - dpy->min_keycode) + 1; 571 if ((xkbi->desc) && (ev->send_event == 0) && 572 ((xkbi->desc->device_spec == nkn->oldDeviceID) || 573 (nkn->deviceID != nkn->oldDeviceID))) { 574 xkbi->flags |= XkbMapPending | XkbXlibNewKeyboard; 575 } 576 return True; 577 } 578 } 579 break; 580 default: 581 #ifdef DEBUG 582 fprintf(stderr, "Got unknown XKEYBOARD event (%d, base=%d)\n", 583 re->type, xkbi->codes->first_event); 584 #endif 585 break; 586 } 587 return False; 588 } 589 590 Bool 591 XkbIgnoreExtension(Bool ignore) 592 { 593 if (getenv("XKB_FORCE") != NULL) { 594 #ifdef DEBUG 595 fprintf(stderr, 596 "Forcing use of XKEYBOARD (overriding an IgnoreExtensions)\n"); 597 #endif 598 return False; 599 } 600 #ifdef DEBUG 601 else if (getenv("XKB_DEBUG") != NULL) { 602 fprintf(stderr, "Explicitly %signoring XKEYBOARD\n", 603 ignore ? "" : "not "); 604 } 605 #endif 606 _XkbIgnoreExtension = ignore; 607 return True; 608 } 609 610 static void 611 _XkbFreeInfo(Display *dpy) 612 { 613 XkbInfoPtr xkbi = dpy->xkb_info; 614 615 if (xkbi) { 616 if (xkbi->desc) 617 XkbFreeKeyboard(xkbi->desc, XkbAllComponentsMask, True); 618 Xfree(xkbi); 619 dpy->xkb_info = NULL; 620 } 621 } 622 623 Bool 624 XkbUseExtension(Display *dpy, int *major_rtrn, int *minor_rtrn) 625 { 626 xkbUseExtensionReply rep; 627 register xkbUseExtensionReq *req; 628 XExtCodes *codes; 629 int ev_base, forceIgnore; 630 XkbInfoPtr xkbi; 631 char *str; 632 static int debugMsg; 633 static int been_here = 0; 634 635 if (dpy->xkb_info && !(dpy->flags & XlibDisplayNoXkb)) { 636 if (major_rtrn) 637 *major_rtrn = dpy->xkb_info->srv_major; 638 if (minor_rtrn) 639 *minor_rtrn = dpy->xkb_info->srv_minor; 640 return True; 641 } 642 if (!been_here) { 643 debugMsg = (getenv("XKB_DEBUG") != NULL); 644 been_here = 1; 645 } 646 647 if (major_rtrn) 648 *major_rtrn = 0; 649 if (minor_rtrn) 650 *minor_rtrn = 0; 651 652 if (!dpy->xkb_info) { 653 xkbi = _XkbTypedCalloc(1, XkbInfoRec); 654 if (!xkbi) 655 return False; 656 dpy->xkb_info = xkbi; 657 dpy->free_funcs->xkb = _XkbFreeInfo; 658 659 xkbi->xlib_ctrls |= (XkbLC_ControlFallback | XkbLC_ConsumeLookupMods); 660 if ((str = getenv("_XKB_OPTIONS_ENABLE")) != NULL) { 661 if ((str = getenv("_XKB_LATIN1_LOOKUP")) != NULL) { 662 if ((strcmp(str, "off") == 0) || (strcmp(str, "0") == 0)) 663 xkbi->xlib_ctrls &= ~XkbLC_ForceLatin1Lookup; 664 else 665 xkbi->xlib_ctrls |= XkbLC_ForceLatin1Lookup; 666 } 667 if ((str = getenv("_XKB_CONSUME_LOOKUP_MODS")) != NULL) { 668 if ((strcmp(str, "off") == 0) || (strcmp(str, "0") == 0)) 669 xkbi->xlib_ctrls &= ~XkbLC_ConsumeLookupMods; 670 else 671 xkbi->xlib_ctrls |= XkbLC_ConsumeLookupMods; 672 } 673 if ((str = getenv("_XKB_CONSUME_SHIFT_AND_LOCK")) != NULL) { 674 if ((strcmp(str, "off") == 0) || (strcmp(str, "0") == 0)) 675 xkbi->xlib_ctrls &= ~XkbLC_AlwaysConsumeShiftAndLock; 676 else 677 xkbi->xlib_ctrls |= XkbLC_AlwaysConsumeShiftAndLock; 678 } 679 if ((str = getenv("_XKB_IGNORE_NEW_KEYBOARDS")) != NULL) { 680 if ((strcmp(str, "off") == 0) || (strcmp(str, "0") == 0)) 681 xkbi->xlib_ctrls &= ~XkbLC_IgnoreNewKeyboards; 682 else 683 xkbi->xlib_ctrls |= XkbLC_IgnoreNewKeyboards; 684 } 685 if ((str = getenv("_XKB_CONTROL_FALLBACK")) != NULL) { 686 if ((strcmp(str, "off") == 0) || (strcmp(str, "0") == 0)) 687 xkbi->xlib_ctrls &= ~XkbLC_ControlFallback; 688 else 689 xkbi->xlib_ctrls |= XkbLC_ControlFallback; 690 } 691 if ((str = getenv("_XKB_COMP_LED")) != NULL) { 692 if ((strcmp(str, "off") == 0) || (strcmp(str, "0") == 0)) 693 xkbi->xlib_ctrls &= ~XkbLC_ComposeLED; 694 else { 695 xkbi->xlib_ctrls |= XkbLC_ComposeLED; 696 if (strlen(str) > 0) 697 xkbi->composeLED = XInternAtom(dpy, str, False); 698 } 699 } 700 if ((str = getenv("_XKB_COMP_FAIL_BEEP")) != NULL) { 701 if ((strcmp(str, "off") == 0) || (strcmp(str, "0") == 0)) 702 xkbi->xlib_ctrls &= ~XkbLC_BeepOnComposeFail; 703 else 704 xkbi->xlib_ctrls |= XkbLC_BeepOnComposeFail; 705 } 706 } 707 if ((xkbi->composeLED == None) && 708 ((xkbi->xlib_ctrls & XkbLC_ComposeLED) != 0)) 709 xkbi->composeLED = XInternAtom(dpy, "Compose", False); 710 #ifdef DEBUG 711 if (debugMsg) { 712 register unsigned c = xkbi->xlib_ctrls; 713 714 fprintf(stderr, 715 "XKEYBOARD compose: beep on failure is %s, LED is %s\n", 716 ((c & XkbLC_BeepOnComposeFail) ? "on" : "off"), 717 ((c & XkbLC_ComposeLED) ? "on" : "off")); 718 fprintf(stderr, 719 "XKEYBOARD XLookupString: %slatin-1, %s lookup modifiers\n", 720 ((c & XkbLC_ForceLatin1Lookup) ? "allow non-" : "force "), 721 ((c & XkbLC_ConsumeLookupMods) ? "consume" : "re-use")); 722 fprintf(stderr, 723 "XKEYBOARD XLookupString: %sconsume shift and lock, %scontrol fallback\n", 724 ((c & XkbLC_AlwaysConsumeShiftAndLock) ? "always " : 725 "don't "), ((c & XkbLC_ControlFallback) ? "" : "no ")); 726 727 } 728 #endif 729 } 730 else 731 xkbi = dpy->xkb_info; 732 733 forceIgnore = (dpy->flags & XlibDisplayNoXkb) || dpy->keysyms; 734 forceIgnore = forceIgnore && (major_rtrn == NULL) && (minor_rtrn == NULL); 735 if (forceIgnore || _XkbIgnoreExtension || getenv("XKB_DISABLE")) { 736 LockDisplay(dpy); 737 dpy->flags |= XlibDisplayNoXkb; 738 UnlockDisplay(dpy); 739 if (debugMsg) 740 fprintf(stderr, "XKEYBOARD extension disabled or missing\n"); 741 return False; 742 } 743 744 if ((codes = XInitExtension(dpy, XkbName)) == NULL) { 745 LockDisplay(dpy); 746 dpy->flags |= XlibDisplayNoXkb; 747 UnlockDisplay(dpy); 748 if (debugMsg) 749 fprintf(stderr, "XKEYBOARD extension not present\n"); 750 return False; 751 } 752 xkbi->codes = codes; 753 LockDisplay(dpy); 754 755 GetReq(kbUseExtension, req); 756 req->reqType = xkbi->codes->major_opcode; 757 req->xkbReqType = X_kbUseExtension; 758 req->wantedMajor = XkbMajorVersion; 759 req->wantedMinor = XkbMinorVersion; 760 if (!_XReply(dpy, (xReply *) &rep, 0, xFalse) || !rep.supported) { 761 Bool fail = True; 762 763 if (debugMsg) 764 fprintf(stderr, 765 "XKEYBOARD version mismatch (want %d.%02d, got %d.%02d)\n", 766 XkbMajorVersion, XkbMinorVersion, 767 rep.serverMajor, rep.serverMinor); 768 769 /* pre-release 0.65 is very close to 1.00 */ 770 if ((rep.serverMajor == 0) && (rep.serverMinor == 65)) { 771 if (debugMsg) 772 fprintf(stderr, "Trying to fall back to version 0.65..."); 773 GetReq(kbUseExtension, req); 774 req->reqType = xkbi->codes->major_opcode; 775 req->xkbReqType = X_kbUseExtension; 776 req->wantedMajor = 0; 777 req->wantedMinor = 65; 778 if (_XReply(dpy, (xReply *) &rep, 0, xFalse) && rep.supported) { 779 if (debugMsg) 780 fprintf(stderr, "succeeded\n"); 781 fail = False; 782 } 783 else if (debugMsg) 784 fprintf(stderr, "failed\n"); 785 } 786 if (fail) { 787 dpy->flags |= XlibDisplayNoXkb; 788 UnlockDisplay(dpy); 789 SyncHandle(); 790 if (major_rtrn) 791 *major_rtrn = rep.serverMajor; 792 if (minor_rtrn) 793 *minor_rtrn = rep.serverMinor; 794 return False; 795 } 796 } 797 #ifdef DEBUG 798 else if (forceIgnore) { 799 fprintf(stderr, 800 "Internal Error! XkbUseExtension succeeded with forceIgnore set\n"); 801 } 802 #endif 803 UnlockDisplay(dpy); 804 xkbi->srv_major = rep.serverMajor; 805 xkbi->srv_minor = rep.serverMinor; 806 if (major_rtrn) 807 *major_rtrn = rep.serverMajor; 808 if (minor_rtrn) 809 *minor_rtrn = rep.serverMinor; 810 if (debugMsg) 811 fprintf(stderr, "XKEYBOARD (version %d.%02d/%d.%02d) OK!\n", 812 XkbMajorVersion, XkbMinorVersion, 813 rep.serverMajor, rep.serverMinor); 814 815 ev_base = codes->first_event; 816 XESetWireToEvent(dpy, ev_base + XkbEventCode, wire_to_event); 817 SyncHandle(); 818 return True; 819 } 820