KeySym X11_KeyCodeToSym(_THIS, KeyCode keycode, unsigned char group) { SDL_VideoData *data = (SDL_VideoData *) _this->driverdata; KeySym keysym; #if SDL_VIDEO_DRIVER_X11_HAS_XKBKEYCODETOKEYSYM if (data->xkb) { int num_groups = XkbKeyNumGroups(data->xkb, keycode); unsigned char info = XkbKeyGroupInfo(data->xkb, keycode); if (num_groups && group >= num_groups) { int action = XkbOutOfRangeGroupAction(info); if (action == XkbRedirectIntoRange) { if ((group = XkbOutOfRangeGroupNumber(info)) >= num_groups) { group = 0; } } else if (action == XkbClampIntoRange) { group = num_groups - 1; } else { group %= num_groups; } } keysym = X11_XkbKeycodeToKeysym(data->display, keycode, group, 0); } else { keysym = X11_XKeycodeToKeysym(data->display, keycode, 0); } #else keysym = X11_XKeycodeToKeysym(data->display, keycode, 0); #endif return keysym; }
KeySym XkbKeycodeToKeysym(Display *dpy, #if NeedWidePrototypes unsigned int kc, #else KeyCode kc, #endif int group, int level) { XkbDescRec *xkb; if (_XkbUnavailable(dpy)) return NoSymbol; _XkbCheckPendingRefresh(dpy,dpy->xkb_info); xkb = dpy->xkb_info->desc; if ((kc<xkb->min_key_code)||(kc>xkb->max_key_code)) return NoSymbol; if ((group<0)||(level<0)||(group>=XkbKeyNumGroups(xkb,kc))) return NoSymbol; if (level>=XkbKeyGroupWidth(xkb,kc,group)) { /* for compatibility with the core protocol, _always_ allow */ /* two symbols in the first two groups. If either of the */ /* two is of type ONE_LEVEL, just replicate the first symbol */ if ((group>XkbGroup2Index)||(XkbKeyGroupWidth(xkb,kc,group)!=1)|| (level!=1)) { return NoSymbol; } level= 0; } return XkbKeySymEntry(xkb,kc,level,group); }
static unsigned XkbKeyEffectiveGroup(XkbDescPtr xkb, KeyCode key, unsigned int mods) { int nKeyGroups; unsigned effectiveGroup; nKeyGroups= XkbKeyNumGroups(xkb,key); if ((!XkbKeycodeInRange(xkb,key))||(nKeyGroups==0)) return 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; } } return effectiveGroup; }
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]; }
KeySym XKeycodeToKeysym(Display *dpy, #if NeedWidePrototypes unsigned int kc, #else KeyCode kc, #endif int col) { XkbDescRec *xkb; if (_XkbUnavailable(dpy)) return _XKeycodeToKeysym(dpy, kc, col); _XkbCheckPendingRefresh(dpy,dpy->xkb_info); xkb = dpy->xkb_info->desc; if ((kc<xkb->min_key_code)||(kc>xkb->max_key_code)) return NoSymbol; if (col>3) { int lastSym,tmp,nGrp; lastSym= 3; nGrp= XkbKeyNumGroups(xkb,kc); if ((nGrp>0)&&((tmp=XkbKeyGroupWidth(xkb,kc,XkbGroup1Index))>2)) { if (col<=(lastSym+tmp-2)) return XkbKeycodeToKeysym(dpy,kc,XkbGroup1Index,col-lastSym+2); lastSym+= tmp-2; } if ((nGrp>1)&&((tmp=XkbKeyGroupWidth(xkb,kc,XkbGroup2Index))>2)) { if (col<=(lastSym+tmp-2)) return XkbKeycodeToKeysym(dpy,kc,XkbGroup2Index,col-lastSym+2); lastSym+= tmp-2; } if (nGrp>2) { tmp= XkbKeyGroupWidth(xkb,kc,XkbGroup3Index); if (col<=lastSym+tmp) return XkbKeycodeToKeysym(dpy,kc,XkbGroup3Index,col-lastSym); lastSym+= tmp; } if (nGrp>3) { tmp= XkbKeyGroupWidth(xkb,kc,XkbGroup4Index); if (col<=lastSym+tmp) return XkbKeycodeToKeysym(dpy,kc,XkbGroup4Index,col-lastSym); } return NoSymbol; } return XkbKeycodeToKeysym(dpy,kc,(col>>1),(col&1)); }
/* 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; }
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); }
KeyCode vncAddKeysym(KeySym keysym, unsigned state) { DeviceIntPtr master; XkbDescPtr xkb; unsigned int key; XkbEventCauseRec cause; XkbChangesRec changes; int types[1]; KeySym *syms; KeySym upper, lower; master = GetMaster(vncKeyboardDev, KEYBOARD_OR_FLOAT); xkb = master->key->xkbInfo->desc; for (key = xkb->max_key_code; key >= xkb->min_key_code; key--) { if (XkbKeyNumGroups(xkb, key) == 0) break; } if (key < xkb->min_key_code) return 0; memset(&changes, 0, sizeof(changes)); memset(&cause, 0, sizeof(cause)); XkbSetCauseUnknown(&cause); /* * Tools like xkbcomp get confused if there isn't a name * assigned to the keycode we're trying to use. */ if (xkb->names && xkb->names->keys && (xkb->names->keys[key].name[0] == '\0')) { xkb->names->keys[key].name[0] = 'I'; xkb->names->keys[key].name[1] = '0' + (key / 100) % 10; xkb->names->keys[key].name[2] = '0' + (key / 10) % 10; xkb->names->keys[key].name[3] = '0' + (key / 1) % 10; changes.names.changed |= XkbKeyNamesMask; changes.names.first_key = key; changes.names.num_keys = 1; } /* FIXME: Verify that ONE_LEVEL/ALPHABETIC isn't screwed up */ /* * For keysyms that are affected by Lock, we are better off * using ALPHABETIC rather than ONE_LEVEL as the latter * generally cannot produce lower case when Lock is active. */ XkbConvertCase(keysym, &lower, &upper); if (upper == lower) types[XkbGroup1Index] = XkbOneLevelIndex; else types[XkbGroup1Index] = XkbAlphabeticIndex; XkbChangeTypesOfKey(xkb, key, 1, XkbGroup1Mask, types, &changes.map); syms = XkbKeySymsPtr(xkb,key); if (upper == lower) syms[0] = keysym; else { syms[0] = lower; syms[1] = upper; } changes.map.changed |= XkbKeySymsMask; changes.map.first_key_sym = key; changes.map.num_key_syms = 1; XkbSendNotification(master, &changes, &cause); return key; }
int XLookupString ( register XKeyEvent * event, char * buffer, int nbytes, KeySym * keysym, XComposeStatus * status) { KeySym dummy; int rtrnLen; unsigned int new_mods; Display *dpy = event->display; if (keysym==NULL) keysym= &dummy; if (!XkbLookupKeySym(dpy,event->keycode,event->state, &new_mods,keysym)) return 0; new_mods= (event->state&(~new_mods)); /* find the group where a symbol can be converted to control one */ if (new_mods&ControlMask && *keysym > 0x7F && (dpy->xkb_info->xlib_ctrls & XkbLC_ControlFallback)) { XKeyEvent tmp_ev = *event; KeySym tmp_keysym; unsigned int tmp_new_mods; if (_XkbUnavailable(dpy)) { tmp_ev.state= event->state ^ dpy->mode_switch; if (XkbLookupKeySym(dpy, tmp_ev.keycode, tmp_ev.state, &tmp_new_mods, &tmp_keysym) && tmp_keysym != NoSymbol && tmp_keysym < 0x80 ) { *keysym = tmp_keysym; } } else { int n = XkbKeyNumGroups(dpy->xkb_info->desc, tmp_ev.keycode); int i; for (i = 0; i < n; i++) { if (XkbGroupForCoreState(event->state) == i) continue; tmp_ev.state= XkbBuildCoreState(tmp_ev.state, i); if (XkbLookupKeySym(dpy, tmp_ev.keycode, tmp_ev.state, &tmp_new_mods, &tmp_keysym) && tmp_keysym != NoSymbol && tmp_keysym < 0x80 ) { *keysym = tmp_keysym; new_mods= (event->state&(~tmp_new_mods)); break; } } } } #ifdef USE_OWN_COMPOSE if ( status ) { static int been_here= 0; if ( !been_here ) { XimCompInitTables(); been_here = 1; } if ( !XimCompLegalStatus(status) ) { status->compose_ptr = NULL; status->chars_matched = 0; } if ( ((status->chars_matched>0)&&(status->compose_ptr!=NULL)) || XimCompIsComposeKey(*keysym,event->keycode,status) ) { XimCompRtrn rtrn; switch (XimCompProcessSym(status,*keysym,&rtrn)) { case XIM_COMP_IGNORE: break; case XIM_COMP_IN_PROGRESS: if ( keysym!=NULL ) *keysym = NoSymbol; #ifndef NO_COMPOSE_LED if ( dpy->xkb_info->xlib_ctrls&XkbLC_ComposeLED ) { XkbSetNamedIndicator(dpy,dpy->xkb_info->composeLED, True,True,False,NULL); } #endif return 0; case XIM_COMP_FAIL: { static Atom _ComposeFail= None; int n = 0, len= 0; #ifndef NO_COMPOSE_LED if ( dpy->xkb_info->xlib_ctrls&XkbLC_ComposeLED ) { XkbSetNamedIndicator(dpy,dpy->xkb_info->composeLED, True,False,False,NULL); } #endif #ifndef NO_BELL_ON_COMPOSE_FAIL if (dpy->xkb_info->xlib_ctrls&XkbLC_BeepOnComposeFail) { if (_ComposeFail==None) _ComposeFail= XInternAtom(dpy,"ComposeFail",0); XkbBell(dpy,event->window,0,_ComposeFail); } #endif for (n=len=0;rtrn.sym[n]!=XK_VoidSymbol;n++) { if ( nbytes-len > 0 ) { len+= XkbTranslateKeySym(dpy,&rtrn.sym[n],new_mods, buffer+len,nbytes-len, NULL); } } if ( keysym!=NULL ) { if ( n==1 ) *keysym = rtrn.sym[0]; else *keysym = NoSymbol; } return len; } case XIM_COMP_SUCCEED: { int len,n = 0; #ifndef NO_COMPOSE_LED if ( dpy->xkb_info->xlib_ctrls&XkbLC_ComposeLED ) { XkbSetNamedIndicator(dpy,dpy->xkb_info->composeLED, True,False,False,NULL); } #endif *keysym = rtrn.matchSym; if ( rtrn.str[0]!='\0' ) { strncpy(buffer,rtrn.str,nbytes-1); buffer[nbytes-1]= '\0'; len = (int)strlen(buffer); } else { len = XkbTranslateKeySym(dpy,keysym,new_mods, buffer,nbytes, NULL); } for (n=0;rtrn.sym[n]!=XK_VoidSymbol;n++) { if ( nbytes-len > 0 ) { len+= XkbTranslateKeySym(dpy,&rtrn.sym[n], event->state, buffer+len,nbytes-len, NULL); } } return len; } } } } #endif /* We *should* use the new_mods (which does not contain any modifiers */ /* that were used to compute the symbol here, but pre-XKB XLookupString */ /* did not and we have to remain compatible. Sigh. */ if (_XkbUnavailable(dpy) || (dpy->xkb_info->xlib_ctrls&XkbLC_ConsumeLookupMods)==0) new_mods= event->state; rtrnLen= XkbLookupKeyBinding(dpy,*keysym,new_mods,buffer,nbytes,NULL); if (rtrnLen>0) return rtrnLen; return XkbTranslateKeySym(dpy,keysym,new_mods,buffer,nbytes,NULL); }
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); }