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]; }
/* Return the modifier mask that needs to be pressed to produce key in the * given group (keyboard layout) and level ("shift level"). */ static GdkModifierType FinallyGetModifiersForKeycode (XkbDescPtr xkb, KeyCode key, uint group, uint level) { int nKeyGroups; int effectiveGroup; XkbKeyTypeRec *type; int k; nKeyGroups = XkbKeyNumGroups(xkb, key); if ((!XkbKeycodeInRange(xkb, key)) || (nKeyGroups == 0)) { return MODIFIERS_ERROR; } /* Taken from GDK's MyEnhancedXkbTranslateKeyCode */ /* find the offset of the effective group */ effectiveGroup = group; 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; } } type = XkbKeyKeyType(xkb, key, effectiveGroup); for (k = 0; k < type->map_count; k++) { if (type->map[k].active && type->map[k].level == level) { if (type->preserve) { return (type->map[k].mods.mask & ~type->preserve[k].mask); } else { return type->map[k].mods.mask; } } } return MODIFIERS_NONE; }
int vncIsAffectedByNumLock(KeyCode keycode) { unsigned state; KeyCode numlock_keycode; unsigned numlock_mask; XkbDescPtr xkb; XkbAction *act; unsigned group; XkbKeyTypeRec *type; /* Group state is still important */ state = vncGetKeyboardState(); state &= ~0xff; /* * Not sure if hunting for a virtual modifier called "NumLock", * or following the keysym Num_Lock is the best approach. We * try the latter. */ numlock_keycode = vncKeysymToKeycode(XK_Num_Lock, state, NULL); if (numlock_keycode == 0) return 0; xkb = GetMaster(vncKeyboardDev, KEYBOARD_OR_FLOAT)->key->xkbInfo->desc; act = XkbKeyActionPtr(xkb, numlock_keycode, state); if (act == NULL) return 0; if (act->type != XkbSA_LockMods) return 0; if (act->mods.flags & XkbSA_UseModMapMods) numlock_mask = xkb->map->modmap[keycode]; else numlock_mask = act->mods.mask; group = XkbKeyEffectiveGroup(xkb, keycode, state); type = XkbKeyKeyType(xkb, keycode, group); if ((type->mods.mask & numlock_mask) == 0) return 0; return 1; }
void KeyboardLayoutWidget::drawKeyLabel(QPainter* painter, uint keycode, int angle, int xkb_origin_x, int xkb_origin_y, int xkb_width, int xkb_height, bool is_pressed) { int x, y, width, height; int padding; int g, l, glp; if (!xkb) return; padding = 23 * ratio; /* 2.3mm */ x = xkbToPixmapCoord (xkb_origin_x); y = xkbToPixmapCoord (xkb_origin_y); width = xkbToPixmapCoord (xkb_origin_x + xkb_width) - x; height = xkbToPixmapCoord (xkb_origin_y + xkb_height) - y; for (glp = KEYBOARD_DRAWING_POS_TOPLEFT; glp < KEYBOARD_DRAWING_POS_TOTAL; glp++) { if (groupLevels[glp] == NULL) continue; g = groupLevels[glp]->group; l = groupLevels[glp]->level; if (g < 0 || g >= XkbKeyNumGroups (xkb, keycode)) continue; if (l < 0 || l >= XkbKeyGroupWidth (xkb, keycode, g)) continue; /* Skip "exotic" levels like the "Ctrl" level in PC_SYSREQ */ if (l > 0) { uint mods = XkbKeyKeyType (xkb, keycode, g)->mods.mask; if ((mods & (ShiftMask | l3mod)) == 0) continue; } if (trackModifiers) { uint mods_rtrn; KeySym keysym; if (XkbTranslateKeyCode (xkb, keycode, XkbBuildCoreState(mods, g), &mods_rtrn, &keysym)) { drawKeyLabelHelper (painter, keysym, angle, glp, x, y, width, height, padding, is_pressed); /* reverse y order */ } } else { KeySym keysym; keysym = XkbKeySymEntry (xkb, keycode, l, g); drawKeyLabelHelper (painter, keysym, angle, glp, x, y, width, height, padding, is_pressed); /* reverse y order */ } } }
Bool XkbLookupGroupAndLevel( XkbDescPtr xkb, int key, int * mods_inout, int * grp_inout, int * lvl_rtrn) { int nG,eG; if ((!xkb)||(!XkbKeycodeInRange(xkb,key))||(!grp_inout)) return False; nG= XkbKeyNumGroups(xkb,key); eG= *grp_inout; if ( nG==0 ) { *grp_inout= 0; if (lvl_rtrn!=NULL) *lvl_rtrn= 0; return False; } else if ( nG==1 ) { eG= 0; } else if ( eG>=nG ) { unsigned gI= XkbKeyGroupInfo(xkb,key); switch (XkbOutOfRangeGroupAction(gI)) { default: eG %= nG; break; case XkbClampIntoRange: eG = nG-1; break; case XkbRedirectIntoRange: eG = XkbOutOfRangeGroupNumber(gI); if (eG>=nG) eG= 0; break; } } *grp_inout= eG; if (mods_inout!=NULL) { XkbKeyTypePtr type; int preserve; type = XkbKeyKeyType(xkb,key,eG); if (lvl_rtrn!=NULL) *lvl_rtrn= 0; preserve= 0; if (type->map) { /* find the shift level */ register int i; register XkbKTMapEntryPtr entry; for (i=0,entry=type->map; i<type->map_count; i++,entry++) { if ((entry->active)&& (((*mods_inout)&type->mods.mask)==entry->mods.mask)) { if (lvl_rtrn!=NULL) *lvl_rtrn= entry->level; if (type->preserve) preserve= type->preserve[i].mask; break; } } } (*mods_inout)&= ~(type->mods.mask&(~preserve)); } return True; }
/* 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); }