int main(int, char **) { Display *display = 0; int opcode = -1; int xkbEventBase = -1; int xkbErrorBase = -1; int xkblibMajor = XkbMajorVersion; int xkblibMinor = XkbMinorVersion; XkbQueryExtension(display, &opcode, &xkbEventBase, &xkbErrorBase, &xkblibMajor, &xkblibMinor); int keycode = 0; unsigned int state = 0; KeySym keySym; unsigned int consumedModifiers; XkbLookupKeySym(display, keycode, state, &consumedModifiers, &keySym); XkbDescPtr xkbDesc = XkbGetMap(display, XkbAllClientInfoMask, XkbUseCoreKbd); int w = XkbKeyGroupsWidth(xkbDesc, keycode); keySym = XkbKeySym(xkbDesc, keycode, w-1); XkbFreeClientMap(xkbDesc, XkbAllClientInfoMask, true); state = XkbPCF_GrabsUseXKBStateMask; (void) XkbSetPerClientControls(display, state, &state); return 0; }
static XkbAction *XkbKeyActionPtr(XkbDescPtr xkb, KeyCode key, unsigned int mods) { XkbKeyTypeRec *type; int col,nKeyGroups; unsigned effectiveGroup; XkbAction *acts; if (!XkbKeyHasActions(xkb, key)) return NULL; nKeyGroups= XkbKeyNumGroups(xkb,key); if ((!XkbKeycodeInRange(xkb,key))||(nKeyGroups==0)) return NULL; acts = XkbKeyActionsPtr(xkb,key); /* find the offset of the effective group */ col = 0; effectiveGroup= XkbGroupForCoreState(mods); if ( effectiveGroup>=nKeyGroups ) { unsigned groupInfo= XkbKeyGroupInfo(xkb,key); switch (XkbOutOfRangeGroupAction(groupInfo)) { default: effectiveGroup %= nKeyGroups; break; case XkbClampIntoRange: effectiveGroup = nKeyGroups-1; break; case XkbRedirectIntoRange: effectiveGroup = XkbOutOfRangeGroupNumber(groupInfo); if (effectiveGroup>=nKeyGroups) effectiveGroup= 0; break; } } col= effectiveGroup*XkbKeyGroupsWidth(xkb,key); type = XkbKeyKeyType(xkb,key,effectiveGroup); if (type->map) { /* find the column (shift level) within the group */ register int i; register XkbKTMapEntryPtr entry; for (i=0,entry=type->map;i<type->map_count;i++,entry++) { if ((entry->active)&&((mods&type->mods.mask)==entry->mods.mask)) { col+= entry->level; break; } } } return &acts[col]; }
/* Stolen from libX11 */ static Bool XkbTranslateKeyCode(register XkbDescPtr xkb, KeyCode key, register unsigned int mods, unsigned int *mods_rtrn, KeySym *keysym_rtrn) { XkbKeyTypeRec *type; int col,nKeyGroups; unsigned preserve,effectiveGroup; KeySym *syms; if (mods_rtrn!=NULL) *mods_rtrn = 0; nKeyGroups= XkbKeyNumGroups(xkb,key); if ((!XkbKeycodeInRange(xkb,key))||(nKeyGroups==0)) { if (keysym_rtrn!=NULL) *keysym_rtrn = NoSymbol; return False; } syms = XkbKeySymsPtr(xkb,key); /* find the offset of the effective group */ col = 0; effectiveGroup= XkbGroupForCoreState(mods); if ( effectiveGroup>=nKeyGroups ) { unsigned groupInfo= XkbKeyGroupInfo(xkb,key); switch (XkbOutOfRangeGroupAction(groupInfo)) { default: effectiveGroup %= nKeyGroups; break; case XkbClampIntoRange: effectiveGroup = nKeyGroups-1; break; case XkbRedirectIntoRange: effectiveGroup = XkbOutOfRangeGroupNumber(groupInfo); if (effectiveGroup>=nKeyGroups) effectiveGroup= 0; break; } } col= effectiveGroup*XkbKeyGroupsWidth(xkb,key); type = XkbKeyKeyType(xkb,key,effectiveGroup); preserve= 0; if (type->map) { /* find the column (shift level) within the group */ register int i; register XkbKTMapEntryPtr entry; for (i=0,entry=type->map;i<type->map_count;i++,entry++) { if ((entry->active)&&((mods&type->mods.mask)==entry->mods.mask)) { col+= entry->level; if (type->preserve) preserve= type->preserve[i].mask; break; } } } if (keysym_rtrn!=NULL) *keysym_rtrn= syms[col]; if (mods_rtrn) *mods_rtrn= type->mods.mask&(~preserve); return (syms[col]!=NoSymbol); }
Bool XkbTranslateKeyCode( register XkbDescPtr xkb, KeyCode key, register unsigned int mods, unsigned int * mods_rtrn, KeySym * keysym_rtrn) { XkbKeyTypeRec *type; int col,nKeyGroups; unsigned preserve,effectiveGroup; KeySym *syms; if (mods_rtrn!=NULL) *mods_rtrn = 0; nKeyGroups= XkbKeyNumGroups(xkb,key); if ((!XkbKeycodeInRange(xkb,key))||(nKeyGroups==0)) { if (keysym_rtrn!=NULL) *keysym_rtrn = NoSymbol; return False; } syms = XkbKeySymsPtr(xkb,key); /* find the offset of the effective group */ col = 0; effectiveGroup= XkbGroupForCoreState(mods); if ( effectiveGroup>=nKeyGroups ) { unsigned groupInfo= XkbKeyGroupInfo(xkb,key); switch (XkbOutOfRangeGroupAction(groupInfo)) { default: effectiveGroup %= nKeyGroups; break; case XkbClampIntoRange: effectiveGroup = nKeyGroups-1; break; case XkbRedirectIntoRange: effectiveGroup = XkbOutOfRangeGroupNumber(groupInfo); if (effectiveGroup>=nKeyGroups) effectiveGroup= 0; break; } } col= effectiveGroup*XkbKeyGroupsWidth(xkb,key); type = XkbKeyKeyType(xkb,key,effectiveGroup); preserve= 0; if (type->map) { /* find the column (shift level) within the group */ register int i; register XkbKTMapEntryPtr entry; for (i=0,entry=type->map;i<type->map_count;i++,entry++) { if ((entry->active)&&((mods&type->mods.mask)==entry->mods.mask)) { col+= entry->level; if (type->preserve) preserve= type->preserve[i].mask; break; } } } if (keysym_rtrn!=NULL) *keysym_rtrn= syms[col]; if (mods_rtrn) { *mods_rtrn= type->mods.mask&(~preserve); /* The Motif VTS doesn't get the help callback called if help * is bound to Shift+<whatever>, and it appears as though it * is XkbTranslateKeyCode that is causing the problem. The * core X version of XTranslateKey always OR's in ShiftMask * and LockMask for mods_rtrn, so this "fix" keeps this behavior * and solves the VTS problem. */ if ((xkb->dpy)&&(xkb->dpy->xkb_info)&& (xkb->dpy->xkb_info->xlib_ctrls&XkbLC_AlwaysConsumeShiftAndLock)) { *mods_rtrn|= (ShiftMask|LockMask); } } return (syms[col]!=NoSymbol); }