11ab64890Smrg/************************************************************ 21ab64890SmrgCopyright (c) 1993 by Silicon Graphics Computer Systems, Inc. 31ab64890Smrg 41ab64890SmrgPermission to use, copy, modify, and distribute this 51ab64890Smrgsoftware and its documentation for any purpose and without 61ab64890Smrgfee is hereby granted, provided that the above copyright 71ab64890Smrgnotice appear in all copies and that both that copyright 81ab64890Smrgnotice and this permission notice appear in supporting 961b2299dSmrgdocumentation, and that the name of Silicon Graphics not be 1061b2299dSmrgused in advertising or publicity pertaining to distribution 111ab64890Smrgof the software without specific prior written permission. 1261b2299dSmrgSilicon Graphics makes no representation about the suitability 131ab64890Smrgof this software for any purpose. It is provided "as is" 141ab64890Smrgwithout any express or implied warranty. 151ab64890Smrg 1661b2299dSmrgSILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS 1761b2299dSmrgSOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 181ab64890SmrgAND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON 1961b2299dSmrgGRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL 2061b2299dSmrgDAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 2161b2299dSmrgDATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 221ab64890SmrgOR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH 231ab64890SmrgTHE USE OR PERFORMANCE OF THIS SOFTWARE. 241ab64890Smrg 251ab64890Smrg********************************************************/ 261ab64890Smrg 271ab64890Smrg#ifdef HAVE_CONFIG_H 281ab64890Smrg#include <config.h> 291ab64890Smrg#endif 301ab64890Smrg#include <stdio.h> 311ab64890Smrg#include <ctype.h> 321ab64890Smrg#include "Xlibint.h" 331ab64890Smrg#include <X11/extensions/XKBproto.h> 341ab64890Smrg#include "XKBlibint.h" 351ab64890Smrg 36818534a1Smrgstatic Bool _XkbIgnoreExtension = False; 371ab64890Smrg 381ab64890Smrgvoid 39818534a1SmrgXkbNoteMapChanges(XkbMapChangesPtr old, 40818534a1Smrg XkbMapNotifyEvent *new, 41818534a1Smrg unsigned wanted) 421ab64890Smrg{ 43818534a1Smrg int first, oldLast, newLast; 44818534a1Smrg 45818534a1Smrg wanted &= new->changed; 46818534a1Smrg 47818534a1Smrg if (wanted & XkbKeyTypesMask) { 48818534a1Smrg if (old->changed & XkbKeyTypesMask) { 49818534a1Smrg first = old->first_type; 50818534a1Smrg oldLast = old->first_type + old->num_types - 1; 51818534a1Smrg newLast = new->first_type + new->num_types - 1; 52818534a1Smrg 53818534a1Smrg if (new->first_type < first) 54818534a1Smrg first = new->first_type; 55818534a1Smrg if (oldLast > newLast) 56818534a1Smrg newLast = oldLast; 57818534a1Smrg old->first_type = first; 58818534a1Smrg old->num_types = newLast - first + 1; 59818534a1Smrg } 60818534a1Smrg else { 61818534a1Smrg old->first_type = new->first_type; 62818534a1Smrg old->num_types = new->num_types; 63818534a1Smrg } 64818534a1Smrg } 65818534a1Smrg if (wanted & XkbKeySymsMask) { 66818534a1Smrg if (old->changed & XkbKeySymsMask) { 67818534a1Smrg first = old->first_key_sym; 68818534a1Smrg oldLast = old->first_key_sym + old->num_key_syms - 1; 69818534a1Smrg newLast = new->first_key_sym + new->num_key_syms - 1; 70818534a1Smrg 71818534a1Smrg if (new->first_key_sym < first) 72818534a1Smrg first = new->first_key_sym; 73818534a1Smrg if (oldLast > newLast) 74818534a1Smrg newLast = oldLast; 75818534a1Smrg old->first_key_sym = first; 76818534a1Smrg old->num_key_syms = newLast - first + 1; 77818534a1Smrg } 78818534a1Smrg else { 79818534a1Smrg old->first_key_sym = new->first_key_sym; 80818534a1Smrg old->num_key_syms = new->num_key_syms; 81818534a1Smrg } 82818534a1Smrg } 83818534a1Smrg if (wanted & XkbKeyActionsMask) { 84818534a1Smrg if (old->changed & XkbKeyActionsMask) { 85818534a1Smrg first = old->first_key_act; 86818534a1Smrg oldLast = old->first_key_act + old->num_key_acts - 1; 87818534a1Smrg newLast = new->first_key_act + new->num_key_acts - 1; 88818534a1Smrg 89818534a1Smrg if (new->first_key_act < first) 90818534a1Smrg first = new->first_key_act; 91818534a1Smrg if (oldLast > newLast) 92818534a1Smrg newLast = oldLast; 93818534a1Smrg old->first_key_act = first; 94818534a1Smrg old->num_key_acts = newLast - first + 1; 95818534a1Smrg } 96818534a1Smrg else { 97818534a1Smrg old->first_key_act = new->first_key_act; 98818534a1Smrg old->num_key_acts = new->num_key_acts; 99818534a1Smrg } 100818534a1Smrg } 101818534a1Smrg if (wanted & XkbKeyBehaviorsMask) { 102818534a1Smrg if (old->changed & XkbKeyBehaviorsMask) { 103818534a1Smrg first = old->first_key_behavior; 104818534a1Smrg oldLast = old->first_key_behavior + old->num_key_behaviors - 1; 105818534a1Smrg newLast = new->first_key_behavior + new->num_key_behaviors - 1; 106818534a1Smrg 107818534a1Smrg if (new->first_key_behavior < first) 108818534a1Smrg first = new->first_key_behavior; 109818534a1Smrg if (oldLast > newLast) 110818534a1Smrg newLast = oldLast; 111818534a1Smrg old->first_key_behavior = first; 112818534a1Smrg old->num_key_behaviors = newLast - first + 1; 113818534a1Smrg } 114818534a1Smrg else { 115818534a1Smrg old->first_key_behavior = new->first_key_behavior; 116818534a1Smrg old->num_key_behaviors = new->num_key_behaviors; 117818534a1Smrg } 118818534a1Smrg } 119818534a1Smrg if (wanted & XkbVirtualModsMask) { 120818534a1Smrg old->vmods |= new->vmods; 121818534a1Smrg } 122818534a1Smrg if (wanted & XkbExplicitComponentsMask) { 123818534a1Smrg if (old->changed & XkbExplicitComponentsMask) { 124818534a1Smrg first = old->first_key_explicit; 125818534a1Smrg oldLast = old->first_key_explicit + old->num_key_explicit - 1; 126818534a1Smrg newLast = new->first_key_explicit + new->num_key_explicit - 1; 127818534a1Smrg 128818534a1Smrg if (new->first_key_explicit < first) 129818534a1Smrg first = new->first_key_explicit; 130818534a1Smrg if (oldLast > newLast) 131818534a1Smrg newLast = oldLast; 132818534a1Smrg old->first_key_explicit = first; 133818534a1Smrg old->num_key_explicit = newLast - first + 1; 134818534a1Smrg } 135818534a1Smrg else { 136818534a1Smrg old->first_key_explicit = new->first_key_explicit; 137818534a1Smrg old->num_key_explicit = new->num_key_explicit; 138818534a1Smrg } 139818534a1Smrg } 140818534a1Smrg if (wanted & XkbModifierMapMask) { 141818534a1Smrg if (old->changed & XkbModifierMapMask) { 142818534a1Smrg first = old->first_modmap_key; 143818534a1Smrg oldLast = old->first_modmap_key + old->num_modmap_keys - 1; 144818534a1Smrg newLast = new->first_modmap_key + new->num_modmap_keys - 1; 145818534a1Smrg 146818534a1Smrg if (new->first_modmap_key < first) 147818534a1Smrg first = new->first_modmap_key; 148818534a1Smrg if (oldLast > newLast) 149818534a1Smrg newLast = oldLast; 150818534a1Smrg old->first_modmap_key = first; 151818534a1Smrg old->num_modmap_keys = newLast - first + 1; 152818534a1Smrg } 153818534a1Smrg else { 154818534a1Smrg old->first_modmap_key = new->first_modmap_key; 155818534a1Smrg old->num_modmap_keys = new->num_modmap_keys; 156818534a1Smrg } 157818534a1Smrg } 158818534a1Smrg if (wanted & XkbVirtualModMapMask) { 159818534a1Smrg if (old->changed & XkbVirtualModMapMask) { 160818534a1Smrg first = old->first_vmodmap_key; 161818534a1Smrg oldLast = old->first_vmodmap_key + old->num_vmodmap_keys - 1; 162818534a1Smrg newLast = new->first_vmodmap_key + new->num_vmodmap_keys - 1; 163818534a1Smrg 164818534a1Smrg if (new->first_vmodmap_key < first) 165818534a1Smrg first = new->first_vmodmap_key; 166818534a1Smrg if (oldLast > newLast) 167818534a1Smrg newLast = oldLast; 168818534a1Smrg old->first_vmodmap_key = first; 169818534a1Smrg old->num_vmodmap_keys = newLast - first + 1; 170818534a1Smrg } 171818534a1Smrg else { 172818534a1Smrg old->first_vmodmap_key = new->first_vmodmap_key; 173818534a1Smrg old->num_vmodmap_keys = new->num_vmodmap_keys; 174818534a1Smrg } 175818534a1Smrg } 176818534a1Smrg old->changed |= wanted; 1771ab64890Smrg return; 1781ab64890Smrg} 1791ab64890Smrg 1801ab64890Smrgvoid 181818534a1Smrg_XkbNoteCoreMapChanges(XkbMapChangesPtr old, 182818534a1Smrg XMappingEvent *new, 183818534a1Smrg unsigned int wanted) 1841ab64890Smrg{ 185818534a1Smrg int first, oldLast, newLast; 186818534a1Smrg 187818534a1Smrg if ((new->request == MappingKeyboard) && (wanted & XkbKeySymsMask)) { 188818534a1Smrg if (old->changed & XkbKeySymsMask) { 189818534a1Smrg first = old->first_key_sym; 190818534a1Smrg oldLast = old->first_key_sym + old->num_key_syms - 1; 191818534a1Smrg newLast = new->first_keycode + new->count - 1; 192818534a1Smrg 193818534a1Smrg if (new->first_keycode < first) 194818534a1Smrg first = new->first_keycode; 195818534a1Smrg if (oldLast > newLast) 196818534a1Smrg newLast = oldLast; 197818534a1Smrg old->first_key_sym = first; 198818534a1Smrg old->num_key_syms = newLast - first + 1; 199818534a1Smrg } 200818534a1Smrg else { 201818534a1Smrg old->changed |= XkbKeySymsMask; 202818534a1Smrg old->first_key_sym = new->first_keycode; 203818534a1Smrg old->num_key_syms = new->count; 204818534a1Smrg } 2051ab64890Smrg } 2061ab64890Smrg return; 2071ab64890Smrg} 2081ab64890Smrg 2091ab64890Smrgstatic Bool 210818534a1Smrgwire_to_event(Display *dpy, XEvent *re, xEvent *event) 2111ab64890Smrg{ 212818534a1Smrg xkbEvent *xkbevent = (xkbEvent *) event; 2131ab64890Smrg XkbInfoPtr xkbi; 2141ab64890Smrg 2151ab64890Smrg if ((dpy->flags & XlibDisplayNoXkb) || 216818534a1Smrg (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL))) 217818534a1Smrg return False; 2181ab64890Smrg xkbi = dpy->xkb_info; 219818534a1Smrg if (((event->u.u.type & 0x7f) - xkbi->codes->first_event) != XkbEventCode) 220818534a1Smrg return False; 2211ab64890Smrg 2221ab64890Smrg switch (xkbevent->u.any.xkbType) { 223818534a1Smrg case XkbStateNotify: 224818534a1Smrg { 225818534a1Smrg xkbStateNotify *sn = (xkbStateNotify *) event; 226818534a1Smrg 227818534a1Smrg if (xkbi->selected_events & XkbStateNotifyMask) { 228818534a1Smrg XkbStateNotifyEvent *sev = (XkbStateNotifyEvent *) re; 229818534a1Smrg 230818534a1Smrg sev->type = XkbEventCode + xkbi->codes->first_event; 231818534a1Smrg sev->xkb_type = XkbStateNotify; 232818534a1Smrg sev->serial = _XSetLastRequestRead(dpy, (xGenericReply *) event); 233818534a1Smrg sev->send_event = ((event->u.u.type & 0x80) != 0); 234818534a1Smrg sev->display = dpy; 235818534a1Smrg sev->time = sn->time; 236818534a1Smrg sev->device = sn->deviceID; 237818534a1Smrg sev->keycode = sn->keycode; 238818534a1Smrg sev->event_type = sn->eventType; 239818534a1Smrg sev->req_major = sn->requestMajor; 240818534a1Smrg sev->req_minor = sn->requestMinor; 241818534a1Smrg sev->changed = sn->changed; 242818534a1Smrg sev->group = sn->group; 243818534a1Smrg sev->base_group = sn->baseGroup; 244818534a1Smrg sev->latched_group = sn->latchedGroup; 245818534a1Smrg sev->locked_group = sn->lockedGroup; 246818534a1Smrg sev->mods = sn->mods; 247818534a1Smrg sev->base_mods = sn->baseMods; 248818534a1Smrg sev->latched_mods = sn->latchedMods; 249818534a1Smrg sev->locked_mods = sn->lockedMods; 250818534a1Smrg sev->compat_state = sn->compatState; 251818534a1Smrg sev->grab_mods = sn->grabMods; 252818534a1Smrg sev->compat_grab_mods = sn->compatGrabMods; 253818534a1Smrg sev->lookup_mods = sn->lookupMods; 254818534a1Smrg sev->compat_lookup_mods = sn->compatLookupMods; 255818534a1Smrg sev->ptr_buttons = sn->ptrBtnState; 256818534a1Smrg return True; 257818534a1Smrg } 258818534a1Smrg } 259818534a1Smrg break; 260818534a1Smrg case XkbMapNotify: 261818534a1Smrg { 262818534a1Smrg xkbMapNotify *mn = (xkbMapNotify *) event; 263818534a1Smrg 264818534a1Smrg if ((xkbi->selected_events & XkbMapNotifyMask) && 265818534a1Smrg (xkbi->selected_map_details & mn->changed)) { 266818534a1Smrg XkbMapNotifyEvent *mev = (XkbMapNotifyEvent *) re; 267818534a1Smrg 268818534a1Smrg mev->type = XkbEventCode + xkbi->codes->first_event; 269818534a1Smrg mev->xkb_type = XkbMapNotify; 270818534a1Smrg mev->serial = _XSetLastRequestRead(dpy, (xGenericReply *) event); 271818534a1Smrg mev->send_event = ((event->u.u.type & 0x80) != 0); 272818534a1Smrg mev->display = dpy; 273818534a1Smrg mev->time = mn->time; 274818534a1Smrg mev->device = mn->deviceID; 275818534a1Smrg mev->changed = mn->changed; 276818534a1Smrg mev->min_key_code = mn->minKeyCode; 277818534a1Smrg mev->max_key_code = mn->maxKeyCode; 278818534a1Smrg mev->first_type = mn->firstType; 279818534a1Smrg mev->num_types = mn->nTypes; 280818534a1Smrg mev->first_key_sym = mn->firstKeySym; 281818534a1Smrg mev->num_key_syms = mn->nKeySyms; 282818534a1Smrg mev->first_key_act = mn->firstKeyAct; 283818534a1Smrg mev->num_key_acts = mn->nKeyActs; 284818534a1Smrg mev->first_key_behavior = mn->firstKeyBehavior; 285818534a1Smrg mev->num_key_behaviors = mn->nKeyBehaviors; 286818534a1Smrg mev->vmods = mn->virtualMods; 287818534a1Smrg mev->first_key_explicit = mn->firstKeyExplicit; 288818534a1Smrg mev->num_key_explicit = mn->nKeyExplicit; 289818534a1Smrg mev->first_modmap_key = mn->firstModMapKey; 290818534a1Smrg mev->num_modmap_keys = mn->nModMapKeys; 291818534a1Smrg mev->first_vmodmap_key = mn->firstVModMapKey; 292818534a1Smrg mev->num_vmodmap_keys = mn->nVModMapKeys; 293818534a1Smrg XkbNoteMapChanges(&xkbi->changes, mev, XKB_XLIB_MAP_MASK); 294818534a1Smrg if (xkbi->changes.changed) 295818534a1Smrg xkbi->flags |= XkbMapPending; 296818534a1Smrg return True; 297818534a1Smrg } 298818534a1Smrg else if (mn->nKeySyms > 0) { 299818534a1Smrg register XMappingEvent *ev = (XMappingEvent *) re; 300818534a1Smrg 301818534a1Smrg ev->type = MappingNotify; 302818534a1Smrg ev->serial = _XSetLastRequestRead(dpy, (xGenericReply *) event); 303818534a1Smrg ev->send_event = ((event->u.u.type & 0x80) != 0); 304818534a1Smrg ev->display = dpy; 305818534a1Smrg ev->window = 0; 306818534a1Smrg ev->first_keycode = mn->firstKeySym; 307818534a1Smrg ev->request = MappingKeyboard; 308818534a1Smrg ev->count = mn->nKeySyms; 309818534a1Smrg _XkbNoteCoreMapChanges(&xkbi->changes, ev, XKB_XLIB_MAP_MASK); 310818534a1Smrg if (xkbi->changes.changed) 311818534a1Smrg xkbi->flags |= XkbMapPending; 312818534a1Smrg return True; 313818534a1Smrg } 314818534a1Smrg } 315818534a1Smrg break; 316818534a1Smrg case XkbControlsNotify: 317818534a1Smrg { 318818534a1Smrg if (xkbi->selected_events & XkbControlsNotifyMask) { 319818534a1Smrg xkbControlsNotify *cn = (xkbControlsNotify *) event; 320818534a1Smrg XkbControlsNotifyEvent *cev = (XkbControlsNotifyEvent *) re; 321818534a1Smrg 322818534a1Smrg cev->type = XkbEventCode + xkbi->codes->first_event; 323818534a1Smrg cev->xkb_type = XkbControlsNotify; 324818534a1Smrg cev->serial = _XSetLastRequestRead(dpy, (xGenericReply *) event); 325818534a1Smrg cev->send_event = ((event->u.u.type & 0x80) != 0); 326818534a1Smrg cev->display = dpy; 327818534a1Smrg cev->time = cn->time; 328818534a1Smrg cev->device = cn->deviceID; 329818534a1Smrg cev->changed_ctrls = cn->changedControls; 330818534a1Smrg cev->enabled_ctrls = cn->enabledControls; 331818534a1Smrg cev->enabled_ctrl_changes = cn->enabledControlChanges; 332818534a1Smrg cev->keycode = cn->keycode; 333818534a1Smrg cev->num_groups = cn->numGroups; 334818534a1Smrg cev->event_type = cn->eventType; 335818534a1Smrg cev->req_major = cn->requestMajor; 336818534a1Smrg cev->req_minor = cn->requestMinor; 337818534a1Smrg return True; 338818534a1Smrg } 339818534a1Smrg } 340818534a1Smrg break; 341818534a1Smrg case XkbIndicatorMapNotify: 342818534a1Smrg { 343818534a1Smrg if (xkbi->selected_events & XkbIndicatorMapNotifyMask) { 344818534a1Smrg xkbIndicatorNotify *in = (xkbIndicatorNotify *) event; 345818534a1Smrg XkbIndicatorNotifyEvent *iev = (XkbIndicatorNotifyEvent *) re; 346818534a1Smrg 347818534a1Smrg iev->type = XkbEventCode + xkbi->codes->first_event; 348818534a1Smrg iev->xkb_type = XkbIndicatorMapNotify; 349818534a1Smrg iev->serial = _XSetLastRequestRead(dpy, (xGenericReply *) event); 350818534a1Smrg iev->send_event = ((event->u.u.type & 0x80) != 0); 351818534a1Smrg iev->display = dpy; 352818534a1Smrg iev->time = in->time; 353818534a1Smrg iev->device = in->deviceID; 354818534a1Smrg iev->changed = in->changed; 355818534a1Smrg iev->state = in->state; 356818534a1Smrg return True; 357818534a1Smrg } 358818534a1Smrg } 359818534a1Smrg break; 360818534a1Smrg case XkbIndicatorStateNotify: 361818534a1Smrg { 362818534a1Smrg if (xkbi->selected_events & XkbIndicatorStateNotifyMask) { 363818534a1Smrg xkbIndicatorNotify *in = (xkbIndicatorNotify *) event; 364818534a1Smrg XkbIndicatorNotifyEvent *iev = (XkbIndicatorNotifyEvent *) re; 365818534a1Smrg 366818534a1Smrg iev->type = XkbEventCode + xkbi->codes->first_event; 367818534a1Smrg iev->xkb_type = XkbIndicatorStateNotify; 368818534a1Smrg iev->serial = _XSetLastRequestRead(dpy, (xGenericReply *) event); 369818534a1Smrg iev->send_event = ((event->u.u.type & 0x80) != 0); 370818534a1Smrg iev->display = dpy; 371818534a1Smrg iev->time = in->time; 372818534a1Smrg iev->device = in->deviceID; 373818534a1Smrg iev->changed = in->changed; 374818534a1Smrg iev->state = in->state; 375818534a1Smrg return True; 376818534a1Smrg } 377818534a1Smrg } 378818534a1Smrg break; 379818534a1Smrg case XkbBellNotify: 380818534a1Smrg { 381818534a1Smrg if (xkbi->selected_events & XkbBellNotifyMask) { 382818534a1Smrg xkbBellNotify *bn = (xkbBellNotify *) event; 383818534a1Smrg XkbBellNotifyEvent *bev = (XkbBellNotifyEvent *) re; 384818534a1Smrg 385818534a1Smrg bev->type = XkbEventCode + xkbi->codes->first_event; 386818534a1Smrg bev->xkb_type = XkbBellNotify; 387818534a1Smrg bev->serial = _XSetLastRequestRead(dpy, (xGenericReply *) event); 388818534a1Smrg bev->send_event = ((event->u.u.type & 0x80) != 0); 389818534a1Smrg bev->display = dpy; 390818534a1Smrg bev->time = bn->time; 391818534a1Smrg bev->device = bn->deviceID; 392818534a1Smrg bev->percent = bn->percent; 393818534a1Smrg bev->pitch = bn->pitch; 394818534a1Smrg bev->duration = bn->duration; 395818534a1Smrg bev->bell_class = bn->bellClass; 396818534a1Smrg bev->bell_id = bn->bellID; 397818534a1Smrg bev->name = bn->name; 398818534a1Smrg bev->window = bn->window; 399818534a1Smrg bev->event_only = bn->eventOnly; 400818534a1Smrg return True; 401818534a1Smrg } 402818534a1Smrg } 403818534a1Smrg break; 404818534a1Smrg case XkbAccessXNotify: 405818534a1Smrg { 406818534a1Smrg if (xkbi->selected_events & XkbAccessXNotifyMask) { 407818534a1Smrg xkbAccessXNotify *axn = (xkbAccessXNotify *) event; 408818534a1Smrg XkbAccessXNotifyEvent *axev = (XkbAccessXNotifyEvent *) re; 409818534a1Smrg 410818534a1Smrg axev->type = XkbEventCode + xkbi->codes->first_event; 411818534a1Smrg axev->xkb_type = XkbAccessXNotify; 412818534a1Smrg axev->serial = _XSetLastRequestRead(dpy, (xGenericReply *) event); 413818534a1Smrg axev->send_event = ((event->u.u.type & 0x80) != 0); 414818534a1Smrg axev->display = dpy; 415818534a1Smrg axev->time = axn->time; 416818534a1Smrg axev->device = axn->deviceID; 417818534a1Smrg axev->detail = axn->detail; 418818534a1Smrg axev->keycode = axn->keycode; 419818534a1Smrg axev->sk_delay = axn->slowKeysDelay; 420818534a1Smrg axev->debounce_delay = axn->debounceDelay; 421818534a1Smrg return True; 422818534a1Smrg } 423818534a1Smrg } 424818534a1Smrg break; 425818534a1Smrg case XkbNamesNotify: 426818534a1Smrg { 427818534a1Smrg if (xkbi->selected_events & XkbNamesNotifyMask) { 428818534a1Smrg xkbNamesNotify *nn = (xkbNamesNotify *) event; 429818534a1Smrg XkbNamesNotifyEvent *nev = (XkbNamesNotifyEvent *) re; 430818534a1Smrg 431818534a1Smrg nev->type = XkbEventCode + xkbi->codes->first_event; 432818534a1Smrg nev->xkb_type = XkbNamesNotify; 433818534a1Smrg nev->serial = _XSetLastRequestRead(dpy, (xGenericReply *) event); 434818534a1Smrg nev->send_event = ((event->u.u.type & 0x80) != 0); 435818534a1Smrg nev->display = dpy; 436818534a1Smrg nev->time = nn->time; 437818534a1Smrg nev->device = nn->deviceID; 438818534a1Smrg nev->changed = nn->changed; 439818534a1Smrg nev->first_type = nn->firstType; 440818534a1Smrg nev->num_types = nn->nTypes; 441818534a1Smrg nev->first_lvl = nn->firstLevelName; 442818534a1Smrg nev->num_lvls = nn->nLevelNames; 443818534a1Smrg nev->num_aliases = nn->nAliases; 444818534a1Smrg nev->num_radio_groups = nn->nRadioGroups; 445818534a1Smrg nev->changed_vmods = nn->changedVirtualMods; 446818534a1Smrg nev->changed_groups = nn->changedGroupNames; 447818534a1Smrg nev->changed_indicators = nn->changedIndicators; 448818534a1Smrg nev->first_key = nn->firstKey; 449818534a1Smrg nev->num_keys = nn->nKeys; 450818534a1Smrg return True; 451818534a1Smrg } 452818534a1Smrg } 453818534a1Smrg break; 454818534a1Smrg case XkbCompatMapNotify: 455818534a1Smrg { 456818534a1Smrg if (xkbi->selected_events & XkbCompatMapNotifyMask) { 457818534a1Smrg xkbCompatMapNotify *cmn = (xkbCompatMapNotify *) event; 458818534a1Smrg XkbCompatMapNotifyEvent *cmev = (XkbCompatMapNotifyEvent *) re; 459818534a1Smrg 460818534a1Smrg cmev->type = XkbEventCode + xkbi->codes->first_event; 461818534a1Smrg cmev->xkb_type = XkbCompatMapNotify; 462818534a1Smrg cmev->serial = _XSetLastRequestRead(dpy, (xGenericReply *) event); 463818534a1Smrg cmev->send_event = ((event->u.u.type & 0x80) != 0); 464818534a1Smrg cmev->display = dpy; 465818534a1Smrg cmev->time = cmn->time; 466818534a1Smrg cmev->device = cmn->deviceID; 467818534a1Smrg cmev->changed_groups = cmn->changedGroups; 468818534a1Smrg cmev->first_si = cmn->firstSI; 469818534a1Smrg cmev->num_si = cmn->nSI; 470818534a1Smrg cmev->num_total_si = cmn->nTotalSI; 471818534a1Smrg return True; 472818534a1Smrg } 473818534a1Smrg } 474818534a1Smrg break; 475818534a1Smrg case XkbActionMessage: 476818534a1Smrg { 477818534a1Smrg if (xkbi->selected_events & XkbActionMessageMask) { 478818534a1Smrg xkbActionMessage *am = (xkbActionMessage *) event; 479818534a1Smrg XkbActionMessageEvent *amev = (XkbActionMessageEvent *) re; 480818534a1Smrg 481818534a1Smrg amev->type = XkbEventCode + xkbi->codes->first_event; 482818534a1Smrg amev->xkb_type = XkbActionMessage; 483818534a1Smrg amev->serial = _XSetLastRequestRead(dpy, (xGenericReply *) event); 484818534a1Smrg amev->send_event = ((event->u.u.type & 0x80) != 0); 485818534a1Smrg amev->display = dpy; 486818534a1Smrg amev->time = am->time; 487818534a1Smrg amev->device = am->deviceID; 488818534a1Smrg amev->keycode = am->keycode; 489818534a1Smrg amev->press = am->press; 490818534a1Smrg amev->key_event_follows = am->keyEventFollows; 491818534a1Smrg amev->group = am->group; 492818534a1Smrg amev->mods = am->mods; 493818534a1Smrg memcpy(amev->message, am->message, XkbActionMessageLength); 494818534a1Smrg amev->message[XkbActionMessageLength] = '\0'; 495818534a1Smrg return True; 496818534a1Smrg } 497818534a1Smrg } 498818534a1Smrg break; 499818534a1Smrg case XkbExtensionDeviceNotify: 500818534a1Smrg { 501818534a1Smrg if (xkbi->selected_events & XkbExtensionDeviceNotifyMask) { 502818534a1Smrg xkbExtensionDeviceNotify *ed = (xkbExtensionDeviceNotify *) event; 503818534a1Smrg XkbExtensionDeviceNotifyEvent *edev 504818534a1Smrg = (XkbExtensionDeviceNotifyEvent *) re; 505818534a1Smrg 506818534a1Smrg edev->type = XkbEventCode + xkbi->codes->first_event; 507818534a1Smrg edev->xkb_type = XkbExtensionDeviceNotify; 508818534a1Smrg edev->serial = _XSetLastRequestRead(dpy, (xGenericReply *) event); 509818534a1Smrg edev->send_event = ((event->u.u.type & 0x80) != 0); 510818534a1Smrg edev->display = dpy; 511818534a1Smrg edev->time = ed->time; 512818534a1Smrg edev->device = ed->deviceID; 513818534a1Smrg edev->led_class = ed->ledClass; 514818534a1Smrg edev->led_id = ed->ledID; 515818534a1Smrg edev->reason = ed->reason; 516818534a1Smrg edev->supported = ed->supported; 517818534a1Smrg edev->leds_defined = ed->ledsDefined; 518818534a1Smrg edev->led_state = ed->ledState; 519818534a1Smrg edev->first_btn = ed->firstBtn; 520818534a1Smrg edev->num_btns = ed->nBtns; 521818534a1Smrg edev->unsupported = ed->unsupported; 522818534a1Smrg return True; 523818534a1Smrg } 524818534a1Smrg } 525818534a1Smrg break; 526818534a1Smrg case XkbNewKeyboardNotify: 527818534a1Smrg { 528818534a1Smrg xkbNewKeyboardNotify *nkn = (xkbNewKeyboardNotify *) event; 529818534a1Smrg 530818534a1Smrg if ((xkbi->selected_events & XkbNewKeyboardNotifyMask) && 531818534a1Smrg (xkbi->selected_nkn_details & nkn->changed)) { 532818534a1Smrg XkbNewKeyboardNotifyEvent *nkev = (XkbNewKeyboardNotifyEvent *) re; 533818534a1Smrg 534818534a1Smrg nkev->type = XkbEventCode + xkbi->codes->first_event; 535818534a1Smrg nkev->xkb_type = XkbNewKeyboardNotify; 536818534a1Smrg nkev->serial = _XSetLastRequestRead(dpy, (xGenericReply *) event); 537818534a1Smrg nkev->send_event = ((event->u.u.type & 0x80) != 0); 538818534a1Smrg nkev->display = dpy; 539818534a1Smrg nkev->time = nkn->time; 540818534a1Smrg nkev->device = nkn->deviceID; 541818534a1Smrg nkev->old_device = nkn->oldDeviceID; 542818534a1Smrg nkev->min_key_code = nkn->minKeyCode; 543818534a1Smrg nkev->max_key_code = nkn->maxKeyCode; 544818534a1Smrg nkev->old_min_key_code = nkn->oldMinKeyCode; 545818534a1Smrg nkev->old_max_key_code = nkn->oldMaxKeyCode; 546818534a1Smrg nkev->req_major = nkn->requestMajor; 547818534a1Smrg nkev->req_minor = nkn->requestMinor; 548818534a1Smrg nkev->changed = nkn->changed; 549818534a1Smrg if ((xkbi->desc) && (nkev->send_event == 0) && 550818534a1Smrg ((xkbi->desc->device_spec == nkev->old_device) || 551818534a1Smrg (nkev->device != nkev->old_device))) { 552818534a1Smrg xkbi->flags = XkbMapPending | XkbXlibNewKeyboard; 553818534a1Smrg } 554818534a1Smrg return True; 555818534a1Smrg } 556818534a1Smrg else if (nkn->changed & (XkbNKN_KeycodesMask | XkbNKN_DeviceIDMask)) { 557818534a1Smrg register XMappingEvent *ev = (XMappingEvent *) re; 558818534a1Smrg 559818534a1Smrg ev->type = MappingNotify; 560818534a1Smrg ev->serial = _XSetLastRequestRead(dpy, (xGenericReply *) event); 561818534a1Smrg ev->send_event = ((event->u.u.type & 0x80) != 0); 562818534a1Smrg ev->display = dpy; 563818534a1Smrg ev->window = 0; 564818534a1Smrg ev->first_keycode = dpy->min_keycode; 565818534a1Smrg ev->request = MappingKeyboard; 566818534a1Smrg ev->count = (dpy->max_keycode - dpy->min_keycode) + 1; 567818534a1Smrg if ((xkbi->desc) && (ev->send_event == 0) && 568818534a1Smrg ((xkbi->desc->device_spec == nkn->oldDeviceID) || 569818534a1Smrg (nkn->deviceID != nkn->oldDeviceID))) { 570818534a1Smrg xkbi->flags |= XkbMapPending | XkbXlibNewKeyboard; 571818534a1Smrg } 572818534a1Smrg return True; 573818534a1Smrg } 574818534a1Smrg } 575818534a1Smrg break; 576818534a1Smrg default: 5771ab64890Smrg#ifdef DEBUG 578818534a1Smrg fprintf(stderr, "Got unknown XKEYBOARD event (%d, base=%d)\n", 579818534a1Smrg re->type, xkbi->codes->first_event); 5801ab64890Smrg#endif 581818534a1Smrg break; 5821ab64890Smrg } 5831ab64890Smrg return False; 5841ab64890Smrg} 5851ab64890Smrg 5861ab64890SmrgBool 5871ab64890SmrgXkbIgnoreExtension(Bool ignore) 5881ab64890Smrg{ 589818534a1Smrg if (getenv("XKB_FORCE") != NULL) { 5901ab64890Smrg#ifdef DEBUG 591818534a1Smrg fprintf(stderr, 592818534a1Smrg "Forcing use of XKEYBOARD (overriding an IgnoreExtensions)\n"); 5931ab64890Smrg#endif 594818534a1Smrg return False; 5951ab64890Smrg } 5961ab64890Smrg#ifdef DEBUG 597818534a1Smrg else if (getenv("XKB_DEBUG") != NULL) { 598818534a1Smrg fprintf(stderr, "Explicitly %signoring XKEYBOARD\n", 599818534a1Smrg ignore ? "" : "not "); 6001ab64890Smrg } 6011ab64890Smrg#endif 6021ab64890Smrg _XkbIgnoreExtension = ignore; 6031ab64890Smrg return True; 6041ab64890Smrg} 6051ab64890Smrg 6061ab64890Smrgstatic void 6071ab64890Smrg_XkbFreeInfo(Display *dpy) 6081ab64890Smrg{ 6091ab64890Smrg XkbInfoPtr xkbi = dpy->xkb_info; 610818534a1Smrg 6111ab64890Smrg if (xkbi) { 612818534a1Smrg if (xkbi->desc) 613818534a1Smrg XkbFreeKeyboard(xkbi->desc, XkbAllComponentsMask, True); 614818534a1Smrg Xfree(xkbi); 615d4a3aaf4Smrg dpy->xkb_info = NULL; 616818534a1Smrg } 6171ab64890Smrg} 6181ab64890Smrg 6191ab64890SmrgBool 620818534a1SmrgXkbUseExtension(Display *dpy, int *major_rtrn, int *minor_rtrn) 6211ab64890Smrg{ 6221ab64890Smrg xkbUseExtensionReply rep; 6231ab64890Smrg register xkbUseExtensionReq *req; 624818534a1Smrg XExtCodes *codes; 625818534a1Smrg int ev_base, forceIgnore; 6261ab64890Smrg XkbInfoPtr xkbi; 627818534a1Smrg char *str; 6281ab64890Smrg static int debugMsg; 629818534a1Smrg static int been_here = 0; 630818534a1Smrg 631818534a1Smrg if (dpy->xkb_info && !(dpy->flags & XlibDisplayNoXkb)) { 632818534a1Smrg if (major_rtrn) 633818534a1Smrg *major_rtrn = dpy->xkb_info->srv_major; 634818534a1Smrg if (minor_rtrn) 635818534a1Smrg *minor_rtrn = dpy->xkb_info->srv_minor; 636818534a1Smrg return True; 6371ab64890Smrg } 6381ab64890Smrg if (!been_here) { 639818534a1Smrg debugMsg = (getenv("XKB_DEBUG") != NULL); 640818534a1Smrg been_here = 1; 6411ab64890Smrg } 6421ab64890Smrg 643818534a1Smrg if (major_rtrn) 644818534a1Smrg *major_rtrn = 0; 645818534a1Smrg if (minor_rtrn) 646818534a1Smrg *minor_rtrn = 0; 6471ab64890Smrg 6481ab64890Smrg if (!dpy->xkb_info) { 6491ab64890Smrg xkbi = _XkbTypedCalloc(1, XkbInfoRec); 650818534a1Smrg if (!xkbi) 651818534a1Smrg return False; 6521ab64890Smrg dpy->xkb_info = xkbi; 6531ab64890Smrg dpy->free_funcs->xkb = _XkbFreeInfo; 6541ab64890Smrg 655818534a1Smrg xkbi->xlib_ctrls |= (XkbLC_ControlFallback | XkbLC_ConsumeLookupMods); 656818534a1Smrg if ((str = getenv("_XKB_OPTIONS_ENABLE")) != NULL) { 657818534a1Smrg if ((str = getenv("_XKB_LATIN1_LOOKUP")) != NULL) { 658818534a1Smrg if ((strcmp(str, "off") == 0) || (strcmp(str, "0") == 0)) 659818534a1Smrg xkbi->xlib_ctrls &= ~XkbLC_ForceLatin1Lookup; 660818534a1Smrg else 661818534a1Smrg xkbi->xlib_ctrls |= XkbLC_ForceLatin1Lookup; 662818534a1Smrg } 663818534a1Smrg if ((str = getenv("_XKB_CONSUME_LOOKUP_MODS")) != NULL) { 664818534a1Smrg if ((strcmp(str, "off") == 0) || (strcmp(str, "0") == 0)) 665818534a1Smrg xkbi->xlib_ctrls &= ~XkbLC_ConsumeLookupMods; 666818534a1Smrg else 667818534a1Smrg xkbi->xlib_ctrls |= XkbLC_ConsumeLookupMods; 668818534a1Smrg } 669818534a1Smrg if ((str = getenv("_XKB_CONSUME_SHIFT_AND_LOCK")) != NULL) { 670818534a1Smrg if ((strcmp(str, "off") == 0) || (strcmp(str, "0") == 0)) 671818534a1Smrg xkbi->xlib_ctrls &= ~XkbLC_AlwaysConsumeShiftAndLock; 672818534a1Smrg else 673818534a1Smrg xkbi->xlib_ctrls |= XkbLC_AlwaysConsumeShiftAndLock; 674818534a1Smrg } 675818534a1Smrg if ((str = getenv("_XKB_IGNORE_NEW_KEYBOARDS")) != NULL) { 676818534a1Smrg if ((strcmp(str, "off") == 0) || (strcmp(str, "0") == 0)) 677818534a1Smrg xkbi->xlib_ctrls &= ~XkbLC_IgnoreNewKeyboards; 678818534a1Smrg else 679818534a1Smrg xkbi->xlib_ctrls |= XkbLC_IgnoreNewKeyboards; 680818534a1Smrg } 681818534a1Smrg if ((str = getenv("_XKB_CONTROL_FALLBACK")) != NULL) { 682818534a1Smrg if ((strcmp(str, "off") == 0) || (strcmp(str, "0") == 0)) 683818534a1Smrg xkbi->xlib_ctrls &= ~XkbLC_ControlFallback; 684818534a1Smrg else 685818534a1Smrg xkbi->xlib_ctrls |= XkbLC_ControlFallback; 686818534a1Smrg } 687818534a1Smrg if ((str = getenv("_XKB_COMP_LED")) != NULL) { 688818534a1Smrg if ((strcmp(str, "off") == 0) || (strcmp(str, "0") == 0)) 689818534a1Smrg xkbi->xlib_ctrls &= ~XkbLC_ComposeLED; 690818534a1Smrg else { 691818534a1Smrg xkbi->xlib_ctrls |= XkbLC_ComposeLED; 692818534a1Smrg if (strlen(str) > 0) 693818534a1Smrg xkbi->composeLED = XInternAtom(dpy, str, False); 694818534a1Smrg } 695818534a1Smrg } 696818534a1Smrg if ((str = getenv("_XKB_COMP_FAIL_BEEP")) != NULL) { 697818534a1Smrg if ((strcmp(str, "off") == 0) || (strcmp(str, "0") == 0)) 698818534a1Smrg xkbi->xlib_ctrls &= ~XkbLC_BeepOnComposeFail; 699818534a1Smrg else 700818534a1Smrg xkbi->xlib_ctrls |= XkbLC_BeepOnComposeFail; 701818534a1Smrg } 702818534a1Smrg } 703818534a1Smrg if ((xkbi->composeLED == None) && 704818534a1Smrg ((xkbi->xlib_ctrls & XkbLC_ComposeLED) != 0)) 705818534a1Smrg xkbi->composeLED = XInternAtom(dpy, "Compose", False); 7061ab64890Smrg#ifdef DEBUG 7071ab64890Smrg if (debugMsg) { 708818534a1Smrg register unsigned c = xkbi->xlib_ctrls; 709818534a1Smrg 710818534a1Smrg fprintf(stderr, 711818534a1Smrg "XKEYBOARD compose: beep on failure is %s, LED is %s\n", 712818534a1Smrg ((c & XkbLC_BeepOnComposeFail) ? "on" : "off"), 713818534a1Smrg ((c & XkbLC_ComposeLED) ? "on" : "off")); 714818534a1Smrg fprintf(stderr, 715818534a1Smrg "XKEYBOARD XLookupString: %slatin-1, %s lookup modifiers\n", 716818534a1Smrg ((c & XkbLC_ForceLatin1Lookup) ? "allow non-" : "force "), 717818534a1Smrg ((c & XkbLC_ConsumeLookupMods) ? "consume" : "re-use")); 718818534a1Smrg fprintf(stderr, 719818534a1Smrg "XKEYBOARD XLookupString: %sconsume shift and lock, %scontrol fallback\n", 720818534a1Smrg ((c & XkbLC_AlwaysConsumeShiftAndLock) ? "always " : 721818534a1Smrg "don't "), ((c & XkbLC_ControlFallback) ? "" : "no ")); 7221ab64890Smrg 7231ab64890Smrg } 7241ab64890Smrg#endif 725818534a1Smrg } 726818534a1Smrg else 7271ab64890Smrg xkbi = dpy->xkb_info; 7281ab64890Smrg 729818534a1Smrg forceIgnore = (dpy->flags & XlibDisplayNoXkb) || dpy->keysyms; 730818534a1Smrg forceIgnore = forceIgnore && (major_rtrn == NULL) && (minor_rtrn == NULL); 731818534a1Smrg if (forceIgnore || _XkbIgnoreExtension || getenv("XKB_DISABLE")) { 732818534a1Smrg LockDisplay(dpy); 733818534a1Smrg dpy->flags |= XlibDisplayNoXkb; 734818534a1Smrg UnlockDisplay(dpy); 735818534a1Smrg if (debugMsg) 736818534a1Smrg fprintf(stderr, "XKEYBOARD extension disabled or missing\n"); 737818534a1Smrg return False; 738818534a1Smrg } 739818534a1Smrg 740818534a1Smrg if ((codes = XInitExtension(dpy, XkbName)) == NULL) { 741818534a1Smrg LockDisplay(dpy); 742818534a1Smrg dpy->flags |= XlibDisplayNoXkb; 743818534a1Smrg UnlockDisplay(dpy); 744818534a1Smrg if (debugMsg) 745818534a1Smrg fprintf(stderr, "XKEYBOARD extension not present\n"); 746818534a1Smrg return False; 7471ab64890Smrg } 7481ab64890Smrg xkbi->codes = codes; 7491ab64890Smrg LockDisplay(dpy); 7501ab64890Smrg 7511ab64890Smrg GetReq(kbUseExtension, req); 7521ab64890Smrg req->reqType = xkbi->codes->major_opcode; 7531ab64890Smrg req->xkbReqType = X_kbUseExtension; 7541ab64890Smrg req->wantedMajor = XkbMajorVersion; 7551ab64890Smrg req->wantedMinor = XkbMinorVersion; 756818534a1Smrg if (!_XReply(dpy, (xReply *) &rep, 0, xFalse) || !rep.supported) { 757818534a1Smrg Bool fail = True; 758818534a1Smrg 759818534a1Smrg if (debugMsg) 760818534a1Smrg fprintf(stderr, 761818534a1Smrg "XKEYBOARD version mismatch (want %d.%02d, got %d.%02d)\n", 762818534a1Smrg XkbMajorVersion, XkbMinorVersion, 763818534a1Smrg rep.serverMajor, rep.serverMinor); 764818534a1Smrg 765818534a1Smrg /* pre-release 0.65 is very close to 1.00 */ 766818534a1Smrg if ((rep.serverMajor == 0) && (rep.serverMinor == 65)) { 767818534a1Smrg if (debugMsg) 768818534a1Smrg fprintf(stderr, "Trying to fall back to version 0.65..."); 769818534a1Smrg GetReq(kbUseExtension, req); 770818534a1Smrg req->reqType = xkbi->codes->major_opcode; 771818534a1Smrg req->xkbReqType = X_kbUseExtension; 772818534a1Smrg req->wantedMajor = 0; 773818534a1Smrg req->wantedMinor = 65; 774818534a1Smrg if (_XReply(dpy, (xReply *) &rep, 0, xFalse) && rep.supported) { 775818534a1Smrg if (debugMsg) 776818534a1Smrg fprintf(stderr, "succeeded\n"); 777818534a1Smrg fail = False; 778818534a1Smrg } 779818534a1Smrg else if (debugMsg) 780818534a1Smrg fprintf(stderr, "failed\n"); 781818534a1Smrg } 782818534a1Smrg if (fail) { 783818534a1Smrg dpy->flags |= XlibDisplayNoXkb; 784818534a1Smrg UnlockDisplay(dpy); 785818534a1Smrg SyncHandle(); 786818534a1Smrg if (major_rtrn) 787818534a1Smrg *major_rtrn = rep.serverMajor; 788818534a1Smrg if (minor_rtrn) 789818534a1Smrg *minor_rtrn = rep.serverMinor; 790818534a1Smrg return False; 791818534a1Smrg } 7921ab64890Smrg } 7931ab64890Smrg#ifdef DEBUG 794818534a1Smrg else if (forceIgnore) { 795818534a1Smrg fprintf(stderr, 796818534a1Smrg "Internal Error! XkbUseExtension succeeded with forceIgnore set\n"); 7971ab64890Smrg } 7981ab64890Smrg#endif 7991ab64890Smrg UnlockDisplay(dpy); 800818534a1Smrg xkbi->srv_major = rep.serverMajor; 801818534a1Smrg xkbi->srv_minor = rep.serverMinor; 802818534a1Smrg if (major_rtrn) 803818534a1Smrg *major_rtrn = rep.serverMajor; 804818534a1Smrg if (minor_rtrn) 805818534a1Smrg *minor_rtrn = rep.serverMinor; 8061ab64890Smrg if (debugMsg) 807818534a1Smrg fprintf(stderr, "XKEYBOARD (version %d.%02d/%d.%02d) OK!\n", 808818534a1Smrg XkbMajorVersion, XkbMinorVersion, 809818534a1Smrg rep.serverMajor, rep.serverMinor); 8101ab64890Smrg 8111ab64890Smrg ev_base = codes->first_event; 812818534a1Smrg XESetWireToEvent(dpy, ev_base + XkbEventCode, wire_to_event); 8131ab64890Smrg SyncHandle(); 8141ab64890Smrg return True; 8151ab64890Smrg} 816