Home | History | Annotate | Line # | Download | only in xkb
      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