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; }
gint _clutter_keymap_x11_get_key_group (ClutterKeymapX11 *keymap, ClutterModifierType state) { #ifdef HAVE_XKB return XkbGroupForCoreState (state); #else return 0; #endif /* HAVE_XKB */ }
gboolean match_xi2_key (Key *key, XIDeviceEvent *event) { guint keyval; GdkModifierType consumed; gint group; guint keycode, state; if (key == NULL) return FALSE; setup_modifiers (); state = device_xi2_translate_state (&event->mods, &event->group); if (have_xkb (event->display)) group = XkbGroupForCoreState (state); else group = (state & GDK_KEY_Mode_switch) ? 1 : 0; keycode = event->detail; /* Check if we find a keysym that matches our current state */ if (gdk_keymap_translate_keyboard_state (gdk_keymap_get_default (), keycode, state, group, &keyval, NULL, NULL, &consumed)) { guint lower, upper; guint mask; /* The Key structure contains virtual modifiers, whereas * the XEvent will be using the real modifier, so translate those */ mask = key->state; gdk_keymap_map_virtual_modifiers (gdk_keymap_get_default (), &mask); gdk_keyval_convert_case (keyval, &lower, &upper); /* If we are checking against the lower version of the * keysym, we might need the Shift state for matching, * so remove it from the consumed modifiers */ if (lower == key->keysym) consumed &= ~GDK_SHIFT_MASK; return ((lower == key->keysym || upper == key->keysym) && (state & ~consumed & gsd_used_mods) == mask); } /* The key we passed doesn't have a keysym, so try with just the keycode */ return (key != NULL && key->state == (state & gsd_used_mods) && key_uses_keycode (key, keycode)); }
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]; }
static GdkEventKey * key_event_to_gdk (ClutterKeyEvent *event_clutter) { GdkDisplay *display = gdk_display_get_default (); GdkKeymap *keymap = gdk_keymap_get_for_display (display); GdkEventKey *event_gdk; event_gdk = (GdkEventKey *)gdk_event_new ((event_clutter->type == CLUTTER_KEY_PRESS) ? GDK_KEY_PRESS : GDK_KEY_RELEASE); event_gdk->window = window_for_actor ((ClutterActor *)event_clutter->stage); event_gdk->send_event = FALSE; event_gdk->time = event_clutter->time; /* This depends on ClutterModifierType and GdkModifierType being * identical, which they are currently. (They both match the X * modifier state in the low 16-bits and have the same extensions.) */ event_gdk->state = event_clutter->modifier_state; event_gdk->keyval = event_clutter->keyval; event_gdk->hardware_keycode = event_clutter->hardware_keycode; /* For non-proper non-XKB support, we'd need a huge cut-and-paste * from gdkkeys-x11.c; this is a macro that just shifts a few bits * out of state, so won't make the situation worse if the server * doesn't support XKB; we'll just end up with group == 0 */ event_gdk->group = XkbGroupForCoreState (event_gdk->state); gdk_keymap_translate_keyboard_state (keymap, event_gdk->hardware_keycode, event_gdk->state, event_gdk->group, &event_gdk->keyval, NULL, NULL, NULL); if (event_clutter->unicode_value) { /* This is not particularly close to what GDK does - event_gdk->string * is supposed to be in the locale encoding, and have control keys * as control characters, etc. See gdkevents-x11.c:translate_key_event(). * Hopefully no input method is using event.string. */ char buf[6]; event_gdk->length = g_unichar_to_utf8 (event_clutter->unicode_value, buf); event_gdk->string = g_strndup (buf, event_gdk->length); } event_gdk->is_modifier = key_is_modifier (event_gdk->keyval); return event_gdk; }
gboolean match_key (Key *key, XEvent *event) { guint keyval; GdkModifierType consumed; gint group; if (key == NULL) return FALSE; setup_modifiers (); #ifdef HAVE_X11_EXTENSIONS_XKB_H if (have_xkb (event->xkey.display)) group = XkbGroupForCoreState (event->xkey.state); else #endif group = (event->xkey.state & GDK_KEY_Mode_switch) ? 1 : 0; /* Check if we find a keysym that matches our current state */ if (gdk_keymap_translate_keyboard_state (NULL, event->xkey.keycode, event->xkey.state, group, &keyval, NULL, NULL, &consumed)) { guint lower, upper; gdk_keyval_convert_case (keyval, &lower, &upper); /* If we are checking against the lower version of the * keysym, we might need the Shift state for matching, * so remove it from the consumed modifiers */ if (lower == key->keysym) consumed &= ~GDK_SHIFT_MASK; return ((lower == key->keysym || upper == key->keysym) && (event->xkey.state & ~consumed & msd_used_mods) == key->state); } /* The key we passed doesn't have a keysym, so try with just the keycode */ return (key != NULL && key->state == (event->xkey.state & msd_used_mods) && key_uses_keycode (key, event->xkey.keycode)); }
static NimfEvent * translate_xkey_event (XEvent *xevent) { g_debug (G_STRLOC ": %s", G_STRFUNC); GdkKeymap *keymap = gdk_keymap_get_default (); GdkModifierType consumed, state; NimfEvent *nimf_event = nimf_event_new (NIMF_EVENT_NOTHING); if (xevent->type == KeyPress) nimf_event->key.type = NIMF_EVENT_KEY_PRESS; else nimf_event->key.type = NIMF_EVENT_KEY_RELEASE; nimf_event->key.state = (NimfModifierType) xevent->xkey.state; #if GTK_CHECK_VERSION (3, 6, 0) gint group = gdk_x11_keymap_get_group_for_state (keymap, xevent->xkey.state); #else gint group = XkbGroupForCoreState (xevent->xkey.state); #endif nimf_event->key.hardware_keycode = xevent->xkey.keycode; nimf_event->key.keyval = NIMF_KEY_VoidSymbol; gdk_keymap_translate_keyboard_state (keymap, nimf_event->key.hardware_keycode, nimf_event->key.state, group, &nimf_event->key.keyval, NULL, NULL, &consumed); state = nimf_event->key.state & ~consumed; gdk_keymap_add_virtual_modifiers (keymap, &state); nimf_event->key.state |= (NimfModifierType) state; return nimf_event; }
void translate_key_event (GdkDisplay *display, GdkEvent *event, XEvent *xevent) { GdkKeymap *keymap = gdk_keymap_get_for_display (display); event->key.type = xevent->xany.type == KeyPress ? GDK_KEY_PRESS : GDK_KEY_RELEASE; event->key.time = xevent->xkey.time; event->key.state = (GdkModifierType) xevent->xkey.state; #ifdef HAVE_XKB event->key.group = XkbGroupForCoreState (xevent->xkey.state); #else event->key.group = 0; #endif event->key.hardware_keycode = xevent->xkey.keycode; event->key.keyval = GDK_VoidSymbol; gdk_keymap_translate_keyboard_state (keymap, event->key.hardware_keycode, event->key.state, event->key.group, &event->key.keyval, NULL, NULL, NULL); event->key.is_modifier = 0; /* Fill in event->string crudely, since various programs * depend on it. */ event->key.string = NULL; event->key.length = 0; return; }
/* 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); }
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); }