XKBUse.c revision b4ee4795
11.171Speter/************************************************************
21.161SlukemCopyright (c) 1993 by Silicon Graphics Computer Systems, Inc.
31.161Slukem
41.161SlukemPermission to use, copy, modify, and distribute this
51.161Slukemsoftware and its documentation for any purpose and without
61.161Slukemfee is hereby granted, provided that the above copyright
71.161Slukemnotice appear in all copies and that both that copyright
81.161Slukemnotice and this permission notice appear in supporting
91.161Slukemdocumentation, and that the name of Silicon Graphics not be
101.161Slukemused in advertising or publicity pertaining to distribution
111.135Slukemof the software without specific prior written permission.
121.135SlukemSilicon Graphics makes no representation about the suitability
131.135Slukemof this software for any purpose. It is provided "as is"
141.135Slukemwithout any express or implied warranty.
151.135Slukem
161.135SlukemSILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
171.135SlukemSOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
181.135SlukemAND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
191.135SlukemGRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
201.169SgdamoreDAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
211.169SgdamoreDATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
221.169SgdamoreOR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
231.169SgdamoreTHE USE OR PERFORMANCE OF THIS SOFTWARE.
241.135Slukem
251.135Slukem********************************************************/
261.135Slukem
271.135Slukem#ifdef HAVE_CONFIG_H
281.135Slukem#include <config.h>
291.135Slukem#endif
301.135Slukem#include <stdio.h>
311.135Slukem#include <ctype.h>
321.135Slukem#define NEED_REPLIES
331.135Slukem#define NEED_EVENTS
341.163Sjwise#include "Xlibint.h"
351.135Slukem#include <X11/extensions/XKBproto.h>
361.135Slukem#include "XKBlibint.h"
371.135Slukem
381.135Slukemstatic Bool	_XkbIgnoreExtension = False;
391.135Slukem
401.135Slukemvoid
411.135SlukemXkbNoteMapChanges(XkbMapChangesPtr old,XkbMapNotifyEvent *new,unsigned wanted)
421.135Slukem{
431.135Slukem    int first,oldLast,newLast;
441.135Slukem    wanted&= new->changed;
451.135Slukem
461.135Slukem    if (wanted&XkbKeyTypesMask) {
471.135Slukem	if (old->changed&XkbKeyTypesMask) {
481.135Slukem	    first = old->first_type;
491.135Slukem	    oldLast = old->first_type+old->num_types-1;
501.135Slukem	    newLast = new->first_type+new->num_types-1;
511.135Slukem
521.135Slukem	    if (new->first_type<first)
531.135Slukem		first = new->first_type;
541.135Slukem	    if (oldLast>newLast)
551.135Slukem		newLast= oldLast;
561.135Slukem	    old->first_type = first;
571.135Slukem	    old->num_types = newLast-first+1;
581.135Slukem	}
591.135Slukem	else {
601.135Slukem	    old->first_type= new->first_type;
611.135Slukem	    old->num_types = new->num_types;
621.135Slukem	}
631.170Smrg    }
641.170Smrg    if (wanted&XkbKeySymsMask) {
651.135Slukem	if (old->changed&XkbKeySymsMask) {
661.135Slukem	    first = old->first_key_sym;
671.140Sitohy	    oldLast = old->first_key_sym+old->num_key_syms-1;
681.135Slukem	    newLast = new->first_key_sym+new->num_key_syms-1;
691.167Stron
701.135Slukem	    if (new->first_key_sym<first)
711.135Slukem		first = new->first_key_sym;
721.135Slukem	    if (oldLast>newLast)
731.135Slukem		newLast= oldLast;
741.135Slukem	    old->first_key_sym = first;
751.135Slukem	    old->num_key_syms = newLast-first+1;
761.135Slukem	}
771.135Slukem	else {
781.135Slukem	    old->first_key_sym = new->first_key_sym;
791.138Slukem	    old->num_key_syms = new->num_key_syms;
801.135Slukem	}
811.159Stron    }
821.135Slukem    if (wanted&XkbKeyActionsMask) {
831.135Slukem	if (old->changed&XkbKeyActionsMask) {
841.135Slukem	    first = old->first_key_act;
851.135Slukem	    oldLast = old->first_key_act+old->num_key_acts-1;
861.135Slukem	    newLast = new->first_key_act+new->num_key_acts-1;
871.135Slukem
881.135Slukem	    if (new->first_key_act<first)
891.135Slukem		first = new->first_key_act;
901.135Slukem	    if (oldLast>newLast)
911.135Slukem		newLast= oldLast;
921.135Slukem	    old->first_key_act = first;
931.135Slukem	    old->num_key_acts = newLast-first+1;
941.135Slukem	}
951.135Slukem	else {
961.135Slukem	    old->first_key_act = new->first_key_act;
971.135Slukem	    old->num_key_acts = new->num_key_acts;
981.147Slukem	}
991.150Sthorpej    }
1001.147Slukem    if (wanted&XkbKeyBehaviorsMask) {
1011.147Slukem	if (old->changed&XkbKeyBehaviorsMask) {
1021.147Slukem	    first = old->first_key_behavior;
1031.147Slukem	    oldLast = old->first_key_behavior+old->num_key_behaviors-1;
1041.147Slukem	    newLast = new->first_key_behavior+new->num_key_behaviors-1;
1051.147Slukem
1061.147Slukem	    if (new->first_key_behavior<first)
1071.147Slukem		first = new->first_key_behavior;
1081.151Schristos	    if (oldLast>newLast)
1091.147Slukem		newLast= oldLast;
1101.147Slukem	    old->first_key_behavior = first;
1111.147Slukem	    old->num_key_behaviors = newLast-first+1;
1121.147Slukem	}
1131.147Slukem	else {
1141.147Slukem	    old->first_key_behavior = new->first_key_behavior;
1151.147Slukem	    old->num_key_behaviors = new->num_key_behaviors;
1161.152Schristos	}
1171.135Slukem    }
1181.135Slukem    if (wanted&XkbVirtualModsMask) {
1191.163Sjwise	old->vmods|= new->vmods;
1201.163Sjwise    }
1211.135Slukem    if (wanted&XkbExplicitComponentsMask) {
1221.145Smatt	if (old->changed&XkbExplicitComponentsMask) {
1231.145Smatt	    first = old->first_key_explicit;
1241.145Smatt	    oldLast = old->first_key_explicit+old->num_key_explicit-1;
1251.145Smatt	    newLast = new->first_key_explicit+new->num_key_explicit-1;
1261.145Smatt
1271.145Smatt	    if (new->first_key_explicit<first)
1281.155Swiz		first = new->first_key_explicit;
1291.135Slukem	    if (oldLast>newLast)
1301.135Slukem		newLast= oldLast;
1311.135Slukem	    old->first_key_explicit = first;
1321.135Slukem	    old->num_key_explicit = newLast-first+1;
1331.135Slukem	}
1341.135Slukem	else {
1351.135Slukem	    old->first_key_explicit = new->first_key_explicit;
1361.135Slukem	    old->num_key_explicit = new->num_key_explicit;
1371.135Slukem	}
1381.135Slukem    }
1391.135Slukem    if (wanted&XkbModifierMapMask) {
1401.135Slukem	if (old->changed&XkbModifierMapMask) {
1411.135Slukem	    first = old->first_modmap_key;
1421.135Slukem	    oldLast = old->first_modmap_key+old->num_modmap_keys-1;
1431.135Slukem	    newLast = new->first_modmap_key+new->num_modmap_keys-1;
1441.135Slukem
1451.135Slukem	    if (new->first_modmap_key<first)
1461.135Slukem		first = new->first_modmap_key;
1471.135Slukem	    if (oldLast>newLast)
1481.135Slukem		newLast= oldLast;
1491.135Slukem	    old->first_modmap_key = first;
1501.169Sgdamore	    old->num_modmap_keys = newLast-first+1;
1511.169Sgdamore	}
1521.135Slukem	else {
1531.135Slukem	    old->first_modmap_key = new->first_modmap_key;
1541.135Slukem	    old->num_modmap_keys = new->num_modmap_keys;
1551.135Slukem	}
1561.135Slukem    }
1571.135Slukem    if (wanted&XkbVirtualModMapMask) {
1581.135Slukem	if (old->changed&XkbVirtualModMapMask) {
1591.135Slukem	    first = old->first_vmodmap_key;
1601.135Slukem	    oldLast = old->first_vmodmap_key+old->num_vmodmap_keys-1;
1611.141Sdbj	    newLast = new->first_vmodmap_key+new->num_vmodmap_keys-1;
1621.135Slukem
1631.135Slukem	    if (new->first_vmodmap_key<first)
1641.157Speter		first = new->first_vmodmap_key;
1651.164Srpaulo	    if (oldLast>newLast)
1661.135Slukem		newLast= oldLast;
1671.142Sitojun	    old->first_vmodmap_key = first;
1681.135Slukem	    old->num_vmodmap_keys = newLast-first+1;
1691.135Slukem	}
1701.171Speter	else {
1711.171Speter	    old->first_vmodmap_key = new->first_vmodmap_key;
1721.171Speter	    old->num_vmodmap_keys = new->num_vmodmap_keys;
1731.171Speter	}
1741.135Slukem    }
1751.165Srpaulo    old->changed|= wanted;
1761.162Sagc    return;
1771.135Slukem}
1781.135Slukem
1791.135Slukemvoid
1801.135Slukem_XkbNoteCoreMapChanges(	XkbMapChangesPtr	 old,
1811.135Slukem			XMappingEvent * 	new,
1821.135Slukem			unsigned int 		wanted)
1831.135Slukem{
1841.135Slukem    int first,oldLast,newLast;
1851.135Slukem
1861.135Slukem    if ((new->request==MappingKeyboard)&&(wanted&XkbKeySymsMask)) {
1871.135Slukem	if (old->changed&XkbKeySymsMask) {
1881.135Slukem	    first = old->first_key_sym;
1891.135Slukem	    oldLast = old->first_key_sym+old->num_key_syms-1;
1901.135Slukem	    newLast = new->first_keycode+new->count-1;
1911.135Slukem
1921.135Slukem	    if (new->first_keycode<first)
1931.135Slukem		first = new->first_keycode;
1941.135Slukem	    if (oldLast>newLast)
1951.135Slukem		newLast= oldLast;
1961.135Slukem	    old->first_key_sym = first;
1971.135Slukem	    old->num_key_syms = newLast-first+1;
1981.135Slukem	}
1991.135Slukem	else {
2001.135Slukem	    old->changed|= XkbKeySymsMask;
2011.135Slukem	    old->first_key_sym = new->first_keycode;
2021.135Slukem	    old->num_key_syms = new->count;
2031.143Sitojun	}
2041.158Speter    }
2051.143Sitojun    return;
2061.135Slukem}
2071.135Slukem
2081.135Slukemstatic Bool
2091.135Slukemwire_to_event(Display *dpy,XEvent *re,xEvent *event)
2101.135Slukem{
2111.135Slukem    xkbEvent *xkbevent= (xkbEvent *)event;
2121.135Slukem    XkbInfoPtr xkbi;
2131.135Slukem
2141.135Slukem    if ((dpy->flags & XlibDisplayNoXkb) ||
2151.135Slukem	(!dpy->xkb_info && !XkbUseExtension(dpy,NULL,NULL)))
2161.135Slukem	return False;
2171.135Slukem    xkbi = dpy->xkb_info;
2181.135Slukem    if (((event->u.u.type&0x7f)-xkbi->codes->first_event)!=XkbEventCode)
2191.135Slukem	return False;
2201.135Slukem
2211.135Slukem    switch (xkbevent->u.any.xkbType) {
2221.135Slukem	case XkbStateNotify:
2231.135Slukem	    {
2241.135Slukem		xkbStateNotify *sn = (xkbStateNotify *)event;
2251.135Slukem		if ( xkbi->selected_events&XkbStateNotifyMask ) {
2261.135Slukem		    XkbStateNotifyEvent *sev=(XkbStateNotifyEvent *)re;
2271.169Sgdamore		    sev->type = XkbEventCode+xkbi->codes->first_event;
2281.135Slukem		    sev->xkb_type = XkbStateNotify;
2291.135Slukem		    sev->serial = _XSetLastRequestRead(dpy,
2301.135Slukem					(xGenericReply *)event);
2311.135Slukem		    sev->send_event = ((event->u.u.type & 0x80) != 0);
2321.135Slukem		    sev->display = dpy;
2331.135Slukem		    sev->time = sn->time;
2341.135Slukem		    sev->device = sn->deviceID;
2351.135Slukem		    sev->keycode = sn->keycode;
2361.135Slukem		    sev->event_type = sn->eventType;
2371.135Slukem		    sev->req_major = sn->requestMajor;
2381.135Slukem		    sev->req_minor = sn->requestMinor;
2391.135Slukem		    sev->changed = sn->changed;
2401.137Sblymn		    sev->group = sn->group;
2411.135Slukem		    sev->base_group = sn->baseGroup;
2421.135Slukem		    sev->latched_group = sn->latchedGroup;
2431.135Slukem		    sev->locked_group = sn->lockedGroup;
2441.135Slukem		    sev->mods = sn->mods;
2451.135Slukem		    sev->base_mods = sn->baseMods;
2461.135Slukem		    sev->latched_mods = sn->latchedMods;
2471.135Slukem		    sev->locked_mods = sn->lockedMods;
2481.135Slukem		    sev->compat_state = sn->compatState;
2491.135Slukem		    sev->grab_mods = sn->grabMods;
2501.135Slukem		    sev->compat_grab_mods = sn->compatGrabMods;
2511.135Slukem		    sev->lookup_mods = sn->lookupMods;
2521.135Slukem		    sev->compat_lookup_mods = sn->compatLookupMods;
2531.135Slukem		    sev->ptr_buttons = sn->ptrBtnState;
2541.135Slukem		    return True;
2551.135Slukem		}
2561.135Slukem	    }
2571.144Swiz	    break;
2581.135Slukem	case XkbMapNotify:
2591.135Slukem	    {
2601.135Slukem		xkbMapNotify *mn = (xkbMapNotify *)event;
2611.135Slukem		if ((xkbi->selected_events&XkbMapNotifyMask)&&
2621.135Slukem				(xkbi->selected_map_details&mn->changed)) {
2631.135Slukem		    XkbMapNotifyEvent *mev;
2641.135Slukem		    mev =(XkbMapNotifyEvent *)re;
2651.135Slukem		    mev->type = XkbEventCode+xkbi->codes->first_event;
2661.135Slukem		    mev->xkb_type = XkbMapNotify;
2671.135Slukem		    mev->serial = _XSetLastRequestRead(dpy,
2681.135Slukem						(xGenericReply *)event);
2691.135Slukem		    mev->send_event = ((event->u.u.type&0x80)!=0);
2701.156Speter		    mev->display = dpy;
2711.135Slukem		    mev->time = mn->time;
2721.135Slukem		    mev->device = mn->deviceID;
2731.142Sitojun		    mev->changed =  mn->changed;
2741.135Slukem		    mev->min_key_code = mn->minKeyCode;
2751.135Slukem		    mev->max_key_code = mn->maxKeyCode;
2761.135Slukem		    mev->first_type = mn->firstType;
2771.135Slukem		    mev->num_types = mn->nTypes;
2781.135Slukem		    mev->first_key_sym = mn->firstKeySym;
2791.135Slukem		    mev->num_key_syms = mn->nKeySyms;
2801.135Slukem		    mev->first_key_act = mn->firstKeyAct;
2811.135Slukem		    mev->num_key_acts = mn->nKeyActs;
2821.135Slukem		    mev->first_key_behavior = mn->firstKeyBehavior;
2831.135Slukem		    mev->num_key_behaviors = mn->nKeyBehaviors;
2841.135Slukem		    mev->vmods = mn->virtualMods;
2851.135Slukem		    mev->first_key_explicit = mn->firstKeyExplicit;
2861.135Slukem		    mev->num_key_explicit = mn->nKeyExplicit;
2871.135Slukem		    mev->first_modmap_key = mn->firstModMapKey;
2881.135Slukem		    mev->num_modmap_keys = mn->nModMapKeys;
2891.135Slukem		    mev->first_vmodmap_key = mn->firstVModMapKey;
2901.135Slukem		    mev->num_vmodmap_keys = mn->nVModMapKeys;
2911.135Slukem		    XkbNoteMapChanges(&xkbi->changes,mev,XKB_XLIB_MAP_MASK);
2921.135Slukem		    if (xkbi->changes.changed)
2931.135Slukem			xkbi->flags|= XkbMapPending;
2941.135Slukem		    return True;
2951.135Slukem		}
2961.135Slukem		else if (mn->nKeySyms>0) {
2971.135Slukem		    register XMappingEvent *ev = (XMappingEvent *)re;
2981.135Slukem		    ev->type = MappingNotify;
2991.135Slukem		    ev->serial = _XSetLastRequestRead(dpy,
3001.135Slukem						(xGenericReply *)event);
3011.135Slukem		    ev->send_event = ((event->u.u.type&0x80)!=0);
3021.135Slukem		    ev->display = dpy;
3031.135Slukem		    ev->window = 0;
3041.135Slukem		    ev->first_keycode = mn->firstKeySym;
3051.135Slukem		    ev->request = MappingKeyboard;
3061.135Slukem		    ev->count = mn->nKeySyms;
3071.135Slukem		    _XkbNoteCoreMapChanges(&xkbi->changes,ev,XKB_XLIB_MAP_MASK);
3081.135Slukem		    if (xkbi->changes.changed)
3091.135Slukem			xkbi->flags|= XkbMapPending;
3101.153Skleink		    return True;
3111.135Slukem		}
3121.135Slukem	    }
3131.135Slukem	    break;
3141.135Slukem	case XkbControlsNotify:
3151.166Schristos	    {
3161.135Slukem		if (xkbi->selected_events&XkbControlsNotifyMask) {
3171.135Slukem		    xkbControlsNotify *cn =(xkbControlsNotify *)event;
3181.135Slukem		    XkbControlsNotifyEvent *cev;
3191.135Slukem		    cev =(XkbControlsNotifyEvent *)re;
3201.135Slukem		    cev->type = XkbEventCode+xkbi->codes->first_event;
3211.135Slukem		    cev->xkb_type = XkbControlsNotify;
3221.135Slukem		    cev->serial = _XSetLastRequestRead(dpy,
3231.135Slukem						(xGenericReply *)event);
324		    cev->send_event = ((event->u.u.type&0x80)!=0);
325		    cev->display = dpy;
326		    cev->time = cn->time;
327		    cev->device = cn->deviceID;
328		    cev->changed_ctrls =  cn->changedControls;
329		    cev->enabled_ctrls =  cn->enabledControls;
330		    cev->enabled_ctrl_changes = cn->enabledControlChanges;
331		    cev->keycode = cn->keycode;
332		    cev->num_groups = cn->numGroups;
333		    cev->event_type = cn->eventType;
334		    cev->req_major = cn->requestMajor;
335		    cev->req_minor = cn->requestMinor;
336		    return True;
337		}
338	    }
339	    break;
340	case XkbIndicatorMapNotify:
341	    {
342		if (xkbi->selected_events&XkbIndicatorMapNotifyMask) {
343		    xkbIndicatorNotify *in =(xkbIndicatorNotify *)event;
344		    XkbIndicatorNotifyEvent *iev;
345		    iev =(XkbIndicatorNotifyEvent *)re;
346		    iev->type = XkbEventCode+xkbi->codes->first_event;
347		    iev->xkb_type = XkbIndicatorMapNotify;
348		    iev->serial = _XSetLastRequestRead(dpy,
349						(xGenericReply *)event);
350		    iev->send_event = ((event->u.u.type&0x80)!=0);
351		    iev->display = dpy;
352		    iev->time = in->time;
353		    iev->device = in->deviceID;
354		    iev->changed =  in->changed;
355		    iev->state=  in->state;
356		    return True;
357		}
358	    }
359	    break;
360	case XkbIndicatorStateNotify:
361	    {
362		if (xkbi->selected_events&XkbIndicatorStateNotifyMask) {
363		    xkbIndicatorNotify *in =(xkbIndicatorNotify *)event;
364		    XkbIndicatorNotifyEvent *iev;
365		    iev =(XkbIndicatorNotifyEvent *)re;
366		    iev->type = XkbEventCode+xkbi->codes->first_event;
367		    iev->xkb_type = XkbIndicatorStateNotify;
368		    iev->serial = _XSetLastRequestRead(dpy,
369						(xGenericReply *)event);
370		    iev->send_event = ((event->u.u.type&0x80)!=0);
371		    iev->display = dpy;
372		    iev->time = in->time;
373		    iev->device = in->deviceID;
374		    iev->changed =  in->changed;
375		    iev->state=  in->state;
376		    return True;
377		}
378	    }
379	    break;
380	case XkbBellNotify:
381	    {
382		if (xkbi->selected_events&XkbBellNotifyMask) {
383		    xkbBellNotify *bn =(xkbBellNotify *)event;
384		    XkbBellNotifyEvent *bev;
385		    bev =(XkbBellNotifyEvent *)re;
386		    bev->type = XkbEventCode+xkbi->codes->first_event;
387		    bev->xkb_type = XkbBellNotify;
388		    bev->serial = _XSetLastRequestRead(dpy,
389						(xGenericReply *)event);
390		    bev->send_event = ((event->u.u.type&0x80)!=0);
391		    bev->display = dpy;
392		    bev->time = bn->time;
393		    bev->device = bn->deviceID;
394		    bev->percent = bn->percent;
395		    bev->pitch = bn->pitch;
396		    bev->duration = bn->duration;
397		    bev->bell_class = bn->bellClass;
398		    bev->bell_id = bn->bellID;
399		    bev->name = bn->name;
400		    bev->window = bn->window;
401		    bev->event_only = bn->eventOnly;
402		    return True;
403		}
404	    }
405	    break;
406	case XkbAccessXNotify:
407	    {
408		if (xkbi->selected_events&XkbAccessXNotifyMask) {
409		    xkbAccessXNotify *axn =(xkbAccessXNotify *)event;
410		    XkbAccessXNotifyEvent *axev;
411		    axev =(XkbAccessXNotifyEvent *)re;
412		    axev->type = XkbEventCode+xkbi->codes->first_event;
413		    axev->xkb_type = XkbAccessXNotify;
414		    axev->serial = _XSetLastRequestRead(dpy,
415						(xGenericReply *)event);
416		    axev->send_event = ((event->u.u.type&0x80)!=0);
417		    axev->display = dpy;
418		    axev->time = axn->time;
419		    axev->device = axn->deviceID;
420		    axev->detail = axn->detail;
421		    axev->keycode = axn->keycode;
422		    axev->sk_delay = axn->slowKeysDelay;
423		    axev->debounce_delay = axn->debounceDelay;
424		    return True;
425		}
426	    }
427	    break;
428	case XkbNamesNotify:
429	    {
430		if (xkbi->selected_events&XkbNamesNotifyMask) {
431		    xkbNamesNotify *nn =(xkbNamesNotify *)event;
432		    XkbNamesNotifyEvent *nev;
433		    nev =(XkbNamesNotifyEvent *)re;
434		    nev->type = XkbEventCode+xkbi->codes->first_event;
435		    nev->xkb_type = XkbNamesNotify;
436		    nev->serial = _XSetLastRequestRead(dpy,
437						(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;
463		    cmev =(XkbCompatMapNotifyEvent *)re;
464		    cmev->type = XkbEventCode+xkbi->codes->first_event;
465		    cmev->xkb_type = XkbCompatMapNotify;
466		    cmev->serial = _XSetLastRequestRead(dpy,
467						(xGenericReply *)event);
468		    cmev->send_event = ((event->u.u.type&0x80)!=0);
469		    cmev->display = dpy;
470		    cmev->time = cmn->time;
471		    cmev->device = cmn->deviceID;
472		    cmev->changed_groups = cmn->changedGroups;
473		    cmev->first_si = cmn->firstSI;
474		    cmev->num_si = cmn->nSI;
475		    cmev->num_total_si = cmn->nTotalSI;
476		    return True;
477		}
478	    }
479	    break;
480	case XkbActionMessage:
481	    {
482		if (xkbi->selected_events&XkbActionMessageMask) {
483		    xkbActionMessage *am= (xkbActionMessage *)event;
484		    XkbActionMessageEvent *amev;
485		    amev= (XkbActionMessageEvent *)re;
486		    amev->type = XkbEventCode+xkbi->codes->first_event;
487		    amev->xkb_type = XkbActionMessage;
488		    amev->serial = _XSetLastRequestRead(dpy,
489						(xGenericReply *)event);
490		    amev->send_event = ((event->u.u.type&0x80)!=0);
491		    amev->display = dpy;
492		    amev->time = am->time;
493		    amev->device = am->deviceID;
494		    amev->keycode = am->keycode;
495		    amev->press = am->press;
496		    amev->key_event_follows = am->keyEventFollows;
497		    amev->group = am->group;
498		    amev->mods = am->mods;
499		    memcpy(amev->message,am->message,XkbActionMessageLength);
500		    amev->message[XkbActionMessageLength]= '\0';
501		    return True;
502		}
503	    }
504	    break;
505	case XkbExtensionDeviceNotify:
506	    {
507		if (xkbi->selected_events&XkbExtensionDeviceNotifyMask) {
508		    xkbExtensionDeviceNotify *ed=
509					(xkbExtensionDeviceNotify *)event;
510		    XkbExtensionDeviceNotifyEvent *edev;
511		    edev= (XkbExtensionDeviceNotifyEvent *)re;
512		    edev->type= XkbEventCode+xkbi->codes->first_event;
513		    edev->xkb_type= XkbExtensionDeviceNotify;
514		    edev->serial= _XSetLastRequestRead(dpy,
515						(xGenericReply *)event);
516		    edev->send_event= ((event->u.u.type&0x80)!=0);
517		    edev->display= dpy;
518		    edev->time= ed->time;
519		    edev->device= ed->deviceID;
520		    edev->led_class= ed->ledClass;
521		    edev->led_id= ed->ledID;
522		    edev->reason= ed->reason;
523		    edev->supported= ed->supported;
524		    edev->leds_defined= ed->ledsDefined;
525		    edev->led_state= ed->ledState;
526		    edev->first_btn= ed->firstBtn;
527		    edev->num_btns= ed->nBtns;
528		    edev->unsupported= ed->unsupported;
529		    return True;
530		}
531	    }
532	    break;
533	case XkbNewKeyboardNotify:
534	    {
535		xkbNewKeyboardNotify *nkn = (xkbNewKeyboardNotify *)event;
536		if ((xkbi->selected_events&XkbNewKeyboardNotifyMask)&&
537				    (xkbi->selected_nkn_details&nkn->changed)) {
538		    XkbNewKeyboardNotifyEvent *nkev;
539		    nkev =(XkbNewKeyboardNotifyEvent *)re;
540		    nkev->type = XkbEventCode+xkbi->codes->first_event;
541		    nkev->xkb_type = XkbNewKeyboardNotify;
542		    nkev->serial = _XSetLastRequestRead(dpy,
543						(xGenericReply *)event);
544		    nkev->send_event = ((event->u.u.type&0x80)!=0);
545		    nkev->display = dpy;
546		    nkev->time = nkn->time;
547		    nkev->device = nkn->deviceID;
548		    nkev->old_device = nkn->oldDeviceID;
549		    nkev->min_key_code = nkn->minKeyCode;
550		    nkev->max_key_code = nkn->maxKeyCode;
551		    nkev->old_min_key_code = nkn->oldMinKeyCode;
552		    nkev->old_max_key_code = nkn->oldMaxKeyCode;
553		    nkev->req_major = nkn->requestMajor;
554		    nkev->req_minor = nkn->requestMinor;
555		    nkev->changed = nkn->changed;
556		    if ((xkbi->desc)&&(nkev->send_event==0)&&
557			((xkbi->desc->device_spec==nkev->old_device)||
558			 (nkev->device!=nkev->old_device))) {
559			xkbi->flags= XkbMapPending|XkbXlibNewKeyboard;
560		    }
561		    return True;
562		}
563		else if(nkn->changed&(XkbNKN_KeycodesMask|XkbNKN_DeviceIDMask)){
564		    register XMappingEvent *ev = (XMappingEvent *)re;
565		    ev->type = MappingNotify;
566		    ev->serial = _XSetLastRequestRead(dpy,
567						(xGenericReply *)event);
568		    ev->send_event = ((event->u.u.type&0x80)!=0);
569		    ev->display = dpy;
570		    ev->window = 0;
571		    ev->first_keycode = dpy->min_keycode;
572		    ev->request = MappingKeyboard;
573		    ev->count = (dpy->max_keycode-dpy->min_keycode)+1;
574		    if ((xkbi->desc)&&(ev->send_event==0)&&
575			((xkbi->desc->device_spec==nkn->oldDeviceID)||
576			 (nkn->deviceID!=nkn->oldDeviceID))) {
577			xkbi->flags|= XkbMapPending|XkbXlibNewKeyboard;
578		    }
579		    return True;
580		}
581	    }
582	    break;
583	default:
584#ifdef DEBUG
585	    fprintf(stderr,"Got unknown XKEYBOARD event (%d, base=%d)\n",
586						re->type,
587						xkbi->codes->first_event);
588#endif
589	    break;
590    }
591    return False;
592}
593
594Bool
595XkbIgnoreExtension(Bool ignore)
596{
597    if (getenv("XKB_FORCE")!=NULL) {
598#ifdef DEBUG
599	fprintf(stderr,"Forcing use of XKEYBOARD (overriding an IgnoreExtensions)\n");
600#endif
601	return False;
602    }
603#ifdef DEBUG
604    else if (getenv("XKB_DEBUG")!=NULL) {
605	fprintf(stderr,"Explicitly %signoring XKEYBOARD\n",ignore?"":"not ");
606    }
607#endif
608    _XkbIgnoreExtension = ignore;
609    return True;
610}
611
612static void
613_XkbFreeInfo(Display *dpy)
614{
615    XkbInfoPtr xkbi = dpy->xkb_info;
616    if (xkbi) {
617	if (xkbi->desc)
618	    XkbFreeKeyboard(xkbi->desc,XkbAllComponentsMask,True);
619	Xfree(xkbi);
620      }
621}
622
623Bool
624XkbUseExtension(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)	*major_rtrn= dpy->xkb_info->srv_major;
637	if (minor_rtrn)	*minor_rtrn= dpy->xkb_info->srv_minor;
638	return True;
639    }
640    if (!been_here) {
641	debugMsg= (getenv("XKB_DEBUG")!=NULL);
642	been_here= 1;
643    }
644
645    if (major_rtrn)	*major_rtrn= 0;
646    if (minor_rtrn)	*minor_rtrn= 0;
647
648    if (!dpy->xkb_info) {
649        xkbi = _XkbTypedCalloc(1, XkbInfoRec);
650        if ( !xkbi )
651	    return False;
652        dpy->xkb_info = xkbi;
653        dpy->free_funcs->xkb = _XkbFreeInfo;
654
655        xkbi->xlib_ctrls|= (XkbLC_ControlFallback|XkbLC_ConsumeLookupMods);
656        if ((str=getenv("_XKB_OPTIONS_ENABLE"))!=NULL) {
657	    if ((str=getenv("_XKB_LATIN1_LOOKUP"))!=NULL) {
658	        if ((strcmp(str,"off")==0)||(strcmp(str,"0")==0))
659		     xkbi->xlib_ctrls&= ~XkbLC_ForceLatin1Lookup;
660	        else xkbi->xlib_ctrls|= XkbLC_ForceLatin1Lookup;
661	    }
662	    if ((str=getenv("_XKB_CONSUME_LOOKUP_MODS"))!=NULL) {
663	        if ((strcmp(str,"off")==0)||(strcmp(str,"0")==0))
664		     xkbi->xlib_ctrls&= ~XkbLC_ConsumeLookupMods;
665	        else xkbi->xlib_ctrls|= XkbLC_ConsumeLookupMods;
666	    }
667	    if ((str=getenv("_XKB_CONSUME_SHIFT_AND_LOCK"))!=NULL) {
668	        if ((strcmp(str,"off")==0)||(strcmp(str,"0")==0))
669		     xkbi->xlib_ctrls&= ~XkbLC_AlwaysConsumeShiftAndLock;
670	        else xkbi->xlib_ctrls|= XkbLC_AlwaysConsumeShiftAndLock;
671	    }
672	    if ((str=getenv("_XKB_IGNORE_NEW_KEYBOARDS"))!=NULL) {
673	        if ((strcmp(str,"off")==0)||(strcmp(str,"0")==0))
674		     xkbi->xlib_ctrls&= ~XkbLC_IgnoreNewKeyboards;
675	        else xkbi->xlib_ctrls|= XkbLC_IgnoreNewKeyboards;
676	    }
677	    if ((str=getenv("_XKB_CONTROL_FALLBACK"))!=NULL) {
678	        if ((strcmp(str,"off")==0)||(strcmp(str,"0")==0))
679		     xkbi->xlib_ctrls&= ~XkbLC_ControlFallback;
680	        else xkbi->xlib_ctrls|= XkbLC_ControlFallback;
681	    }
682	    if ((str=getenv("_XKB_COMP_LED"))!=NULL) {
683	        if ((strcmp(str,"off")==0)||(strcmp(str,"0")==0))
684		    xkbi->xlib_ctrls&= ~XkbLC_ComposeLED;
685	        else {
686		    xkbi->xlib_ctrls|= XkbLC_ComposeLED;
687		    if (strlen(str)>0)
688		        xkbi->composeLED= XInternAtom(dpy,str,False);
689	        }
690	    }
691	    if ((str=getenv("_XKB_COMP_FAIL_BEEP"))!=NULL) {
692	        if ((strcmp(str,"off")==0)||(strcmp(str,"0")==0))
693		     xkbi->xlib_ctrls&= ~XkbLC_BeepOnComposeFail;
694	        else xkbi->xlib_ctrls|= XkbLC_BeepOnComposeFail;
695	    }
696        }
697        if ((xkbi->composeLED==None)&&((xkbi->xlib_ctrls&XkbLC_ComposeLED)!=0))
698	    xkbi->composeLED= XInternAtom(dpy,"Compose",False);
699#ifdef DEBUG
700        if (debugMsg) {
701	    register unsigned c= xkbi->xlib_ctrls;
702	    fprintf(stderr,"XKEYBOARD compose: beep on failure is %s, LED is %s\n",
703		((c&XkbLC_BeepOnComposeFail)?"on":"off"),
704		((c&XkbLC_ComposeLED)?"on":"off"));
705	    fprintf(stderr,"XKEYBOARD XLookupString: %slatin-1, %s lookup modifiers\n",
706		((c&XkbLC_ForceLatin1Lookup)?"allow non-":"force "),
707		((c&XkbLC_ConsumeLookupMods)?"consume":"re-use"));
708	    fprintf(stderr,
709	        "XKEYBOARD XLookupString: %sconsume shift and lock, %scontrol fallback\n",
710	        ((c&XkbLC_AlwaysConsumeShiftAndLock)?"always ":"don't "),
711	        ((c&XkbLC_ControlFallback)?"":"no "));
712
713        }
714#endif
715    } else
716        xkbi = dpy->xkb_info;
717
718    forceIgnore= (dpy->flags&XlibDisplayNoXkb)||dpy->keysyms;
719    forceIgnore= forceIgnore&&(major_rtrn==NULL)&&(minor_rtrn==NULL);
720    if ( forceIgnore || _XkbIgnoreExtension || getenv("XKB_DISABLE")) {
721	LockDisplay(dpy);
722	dpy->flags |= XlibDisplayNoXkb;
723	UnlockDisplay(dpy);
724	if (debugMsg)
725	    fprintf(stderr,"XKEYBOARD extension disabled or missing\n");
726	return False;
727    }
728
729    if ( (codes=XInitExtension(dpy,XkbName))==NULL ) {
730	LockDisplay(dpy);
731	dpy->flags |= XlibDisplayNoXkb;
732	UnlockDisplay(dpy);
733	if (debugMsg)
734	    fprintf(stderr,"XKEYBOARD extension not present\n");
735	return False;
736    }
737    xkbi->codes = codes;
738    LockDisplay(dpy);
739
740    GetReq(kbUseExtension, req);
741    req->reqType = xkbi->codes->major_opcode;
742    req->xkbReqType = X_kbUseExtension;
743    req->wantedMajor = XkbMajorVersion;
744    req->wantedMinor = XkbMinorVersion;
745    if (!_XReply(dpy, (xReply *)&rep, 0, xFalse) || !rep.supported ) {
746	Bool	fail;
747	fail= True;
748	if (debugMsg)
749	    fprintf(stderr,
750		"XKEYBOARD version mismatch (want %d.%02d, got %d.%02d)\n",
751		XkbMajorVersion,XkbMinorVersion,
752		rep.serverMajor, rep.serverMinor);
753
754	/* pre-release 0.65 is very close to 1.00 */
755	if ((rep.serverMajor==0)&&(rep.serverMinor==65)) {
756	    if (debugMsg)
757		fprintf(stderr,"Trying to fall back to version 0.65...");
758	    GetReq(kbUseExtension, req);
759	    req->reqType = xkbi->codes->major_opcode;
760	    req->xkbReqType = X_kbUseExtension;
761	    req->wantedMajor = 0;
762	    req->wantedMinor = 65;
763	    if ( _XReply(dpy, (xReply *)&rep, 0, xFalse) && rep.supported ) {
764		if (debugMsg)
765		    fprintf(stderr,"succeeded\n");
766		fail= False;
767	    }
768	    else if (debugMsg) fprintf(stderr,"failed\n");
769	}
770	if (fail) {
771	    dpy->flags |= XlibDisplayNoXkb;
772	    UnlockDisplay(dpy);
773	    SyncHandle();
774	    if (major_rtrn) *major_rtrn= rep.serverMajor;
775	    if (minor_rtrn) *minor_rtrn= rep.serverMinor;
776	    return False;
777	}
778    }
779#ifdef DEBUG
780    else if ( forceIgnore ) {
781	fprintf(stderr,"Internal Error!  XkbUseExtension succeeded with forceIgnore set\n");
782    }
783#endif
784    UnlockDisplay(dpy);
785    xkbi->srv_major= rep.serverMajor;
786    xkbi->srv_minor= rep.serverMinor;
787    if (major_rtrn)	*major_rtrn= rep.serverMajor;
788    if (minor_rtrn)	*minor_rtrn= rep.serverMinor;
789    if (debugMsg)
790	fprintf(stderr,"XKEYBOARD (version %d.%02d/%d.%02d) OK!\n",
791				XkbMajorVersion,XkbMinorVersion,
792				rep.serverMajor,rep.serverMinor);
793
794    ev_base = codes->first_event;
795    XESetWireToEvent(dpy,ev_base+XkbEventCode,wire_to_event);
796    SyncHandle();
797    return True;
798}
799
800