#ifdef HAVE_XKB
XkbDescPtr xkb_desc; /* We cache the directions */
Atom current_group_atom;
guint current_cache_serial; /* A cache of size four should be more than enough, people usually *havetwogroupsaround,andthexkblimitisfour.Itstill *workscorrectformorethanfourgroups.It'sjustthe *cache.
*/
DirectionCacheEntry group_direction_cache[4];
/* Whether we were able to turn on detectable-autorepeat using *XkbSetDetectableAutorepeat.IfFALSE,we’llfallback *tocheckingthenexteventwithXPending().
*/
/* Find the index of the group/level pair within the keysyms for a key. *Weroundupthenumberofkeysymsperkeycodetothenextevennumber, *otherwiseweloseawholegroupofkeys
*/ #define KEYSYM_INDEX(keymap_impl, group, level) \
(2 * ((group) % (int)((keymap_impl->keysyms_per_keycode + 1) / 2)) + (level)) #define KEYSYM_IS_KEYPAD(s) (((s) >= 0xff80 && (s) <= 0xffbd) || \
((s) >= 0x11000000 && (s) <= 0x1100ffff))
staticint
get_symbol (const KeySym *syms,
GdkX11Keymap *keymap_x11, int group, int level)
{ int index;
index = KEYSYM_INDEX(keymap_x11, group, level); if (index >= keymap_x11->keysyms_per_keycode) return NoSymbol;
return syms[index];
}
staticvoid
set_symbol (KeySym *syms,
GdkX11Keymap *keymap_x11, int group, int level,
KeySym sym)
{ int index;
index = KEYSYM_INDEX(keymap_x11, group, level); if (index >= keymap_x11->keysyms_per_keycode) return;
for (i = 0; i < 8; i++)
keymap_x11->modmap[i] = 1 << i;
/* There are 8 sets of modifiers, with each set containing *max_keypermodkeycodes.
*/
map_size = 8 * keymap_x11->mod_keymap->max_keypermod; for (i = 0; i < map_size; i++)
{ /* Get the key code at this point in the map. */ int code = keymap_x11->mod_keymap->modifiermap[i]; int j;
KeySym *syms;
guint mask;
/* The fourth modifier, GDK_ALT_MASK is 1 << 3. *Eachgroupofmax_keypermodentriesreferstothesamemodifier.
*/
mask = 1 << (i / keymap_x11->mod_keymap->max_keypermod);
switch (mask)
{ case GDK_LOCK_MASK: /* Get the Lock keysym. If any keysym bound to the Lock modifier *isCaps_Lock,wewillinterpretthemodifierasCaps_Lock; *otherwise,ifanyisboundtoShift_Lock,wewillinterpret *themodifierasShift_Lock.Otherwise,thelockmodifier *hasnoeffect.
*/ for (j = 0; j < keymap_x11->keysyms_per_keycode; j++)
{ if (syms[j] == GDK_KEY_Caps_Lock)
keymap_x11->lock_keysym = GDK_KEY_Caps_Lock; elseif (syms[j] == GDK_KEY_Shift_Lock &&
keymap_x11->lock_keysym == GDK_KEY_VoidSymbol)
keymap_x11->lock_keysym = GDK_KEY_Shift_Lock;
} break;
case GDK_CONTROL_MASK: case GDK_SHIFT_MASK: case GDK_ALT_MASK: /* Some keyboard maps are known to map Mode_Switch as an *extraMod1key.Incircumstanceslikethat,itwon'tbe *usedtoswitchgroups.
*/ break;
default: /* Find the Mode_Switch, Num_Lock and Scroll_Lock modifiers. */ for (j = 0; j < keymap_x11->keysyms_per_keycode; j++)
{ if (syms[j] == GDK_KEY_Mode_switch)
{ /* This modifier swaps groups */
keymap_x11->group_switch_mask |= mask;
} elseif (syms[j] == GDK_KEY_Num_Lock)
{ /* This modifier is used for Num_Lock */
keymap_x11->num_lock_mask |= mask;
} elseif (syms[j] == GDK_KEY_Scroll_Lock)
{ /* This modifier is used for Scroll_Lock */
keymap_x11->scroll_lock_mask |= mask;
}
} break;
}
}
}
}
#ifdef HAVE_XKB static PangoDirection
get_direction (XkbDescRec *xkb, int group)
{ int code;
int rtl_minus_ltr = 0; /* total number of RTL keysyms minus LTR ones */
for (code = xkb->min_key_code; code <= xkb->max_key_code; code++)
{ int level = 0;
KeySym sym = XkbKeySymEntry (xkb, code, level, group);
PangoDirection dir = gdk_unichar_direction (gdk_keyval_to_unicode (sym));
switch (dir)
{ case PANGO_DIRECTION_RTL:
rtl_minus_ltr++; break; case PANGO_DIRECTION_LTR:
rtl_minus_ltr--; break; case PANGO_DIRECTION_TTB_LTR: case PANGO_DIRECTION_TTB_RTL: case PANGO_DIRECTION_WEAK_LTR: case PANGO_DIRECTION_WEAK_RTL: case PANGO_DIRECTION_NEUTRAL: default: break;
}
}
if (rtl_minus_ltr > 0) return PANGO_DIRECTION_RTL; else return PANGO_DIRECTION_LTR;
}
static PangoDirection
get_direction_from_cache (GdkX11Keymap *keymap_x11,
XkbDescPtr xkb, int group)
{
Atom group_atom = xkb->names->groups[group];
PangoDirection direction = PANGO_DIRECTION_NEUTRAL; int i;
if (keymap_x11->have_direction)
{ /* lookup in cache */ for (i = 0; i < G_N_ELEMENTS (keymap_x11->group_direction_cache); i++)
{ if (cache[i].group_atom == group_atom)
{
cache_hit = TRUE;
cache[i].serial = keymap_x11->current_cache_serial++; /* freshen */
direction = cache[i].direction;
group_atom = cache[i].group_atom; break;
}
}
} else
{ /* initialize cache */ for (i = 0; i < G_N_ELEMENTS (keymap_x11->group_direction_cache); i++)
{
cache[i].group_atom = 0;
cache[i].serial = keymap_x11->current_cache_serial;
}
keymap_x11->current_cache_serial++;
}
/* insert in cache */ if (!cache_hit)
{ int oldest = 0;
direction = get_direction (xkb, group);
/* remove the oldest entry */ for (i = 0; i < G_N_ELEMENTS (keymap_x11->group_direction_cache); i++)
{ if (cache[i].serial < cache[oldest].serial)
oldest = i;
}
#ifdef HAVE_XKB if (KEYMAP_USE_XKB (keymap))
{ /* See sec 15.3.4 in XKB docs */
XkbDescRec *xkb = get_xkb (keymap_x11); int keycode;
keycode = keymap_x11->min_keycode;
while (keycode <= keymap_x11->max_keycode)
{ int max_shift_levels = XkbKeyGroupsWidth (xkb, keycode); /* "key width" */ int group = 0; int level = 0; int total_syms = XkbKeyNumSyms (xkb, keycode); int i = 0;
KeySym *entry;
/* entry is an array with all syms for group 0, all *symsforgroup1,etc.andforeachgroupthe *shiftlevelsymsareinorder
*/
entry = XkbKeySymsPtr (xkb, keycode);
while (i < total_syms)
{ /* check out our cool loop invariant */
g_assert (i == (group * max_shift_levels + level));
if (entry[i] == keyval)
{ /* Found a match */
GdkKeymapKey key;
/* entry is an array with all syms for group 0, all *symsforgroup1,etc.andforeachgroupthe *shiftlevelsymsareinorder
*/
entry = XkbKeySymsPtr (xkb, hardware_keycode);
while (i < total_syms)
{ /* check out our cool loop invariant */
g_assert (i == (group * max_shift_levels + level));
#ifdef HAVE_XKB /* This is copied straight from XFree86 Xlib, to: *-addthegroupandlevelreturn. *-changetheinterpretationofmods_rtrnasdescribed *inthedocsforgdk_keymap_translate_keyboard_state() *It’sunchangedforeaseofdiffagainsttheXlibsources;don't *reformatit.
*/ staticBool
MyEnhancedXkbTranslateKeyCode(register XkbDescPtr xkb,
KeyCode key, registerunsignedint mods, unsignedint * mods_rtrn,
KeySym * keysym_rtrn, int * group_rtrn, int * level_rtrn)
{
XkbKeyTypeRec *type; int col,nKeyGroups; unsigned preserve,effectiveGroup;
KeySym *syms; int found_col = 0;
if (mods_rtrn!=NULL)
*mods_rtrn = 0;
nKeyGroups= XkbKeyNumGroups(xkb,key); if ((!XkbKeycodeInRange(xkb,key))||(nKeyGroups==0)) { if (keysym_rtrn!=NULL)
*keysym_rtrn = NoSymbol; returnFalse;
}
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;
}
}
found_col = col= effectiveGroup*XkbKeyGroupsWidth(xkb,key);
type = XkbKeyKeyType(xkb,key,effectiveGroup);
preserve= 0; if (type->map) { /* find the column (shift level) within the group */ registerint i; register XkbKTMapEntryPtr entry; /* ---- Begin section modified for GDK ---- */ int found = 0;
for (i=0,entry=type->map;i<type->map_count;i++,entry++) { if (!entry->active || syms[col+entry->level] == syms[col]) continue; if (mods_rtrn) { int bits = 0; unsignedlong tmp = entry->mods.mask; while (tmp) { if ((tmp & 1) == 1)
bits++;
tmp >>= 1;
} /* We always add one-modifiers levels to mods_rtrn since *theycan'twipeoutbitsinthestateunlessthe *levelwouldbetriggered.Butnotiftheydon'tchange *thesymbol(otherwisewecan'tdiscriminateShift-F10 *andF10anymore).Anddon'taddmodifiersthatare *explicitlymarkedaspreserved,either.
*/ if (bits == 1 ||
(mods&type->mods.mask) == entry->mods.mask)
{ if (type->preserve)
*mods_rtrn |= (entry->mods.mask & ~type->preserve[i].mask); else
*mods_rtrn |= entry->mods.mask;
}
}
if (!found && ((mods&type->mods.mask) == entry->mods.mask)) {
found_col= col + entry->level; if (type->preserve)
preserve= type->preserve[i].mask;
if (level_rtrn)
*level_rtrn = entry->level;
found = 1;
}
} /* ---- End section modified for GDK ---- */
}
if (keysym_rtrn!=NULL)
*keysym_rtrn= syms[found_col]; if (mods_rtrn) { /* ---- Begin section modified for GDK ---- */
*mods_rtrn &= ~preserve; /* ---- End section modified for GDK ---- */
/* ---- Begin stuff GDK comments out of the original Xlib version ---- */ /* This is commented out because xkb_info is a private struct */
#if0 /* The Motif VTS doesn't get the help callback called if help *isboundtoShift+<whatever>,anditappearsasthoughit *isXkbTranslateKeyCodethatiscausingtheproblem.The *coreXversionofXTranslateKeyalwaysOR'sinShiftMask *andLockMaskformods_rtrn,sothis"fix"keepsthisbehavior *andsolvestheVTSproblem.
*/ if ((xkb->dpy)&&(xkb->dpy->xkb_info)&&
(xkb->dpy->xkb_info->xlib_ctrls&XkbLC_AlwaysConsumeShiftAndLock)) { *mods_rtrn|= (ShiftMask|LockMask);
} #endif
/* ---- End stuff GDK comments out of the original Xlib version ---- */
}
/* ---- Begin stuff GDK adds to the original Xlib version ---- */
if (group_rtrn)
*group_rtrn = effectiveGroup;
/* ---- End stuff GDK adds to the original Xlib version ---- */
/* Translates from keycode/state to keysymbol using the traditional interpretation *ofthekeyboardmap.Seesection12.7oftheXlibreferencemanual
*/ static guint
translate_keysym (GdkX11Keymap *keymap_x11,
guint hardware_keycode, int group,
GdkModifierType state, int *effective_group, int *effective_level)
{ const KeySym *map = get_keymap (keymap_x11); const KeySym *syms = map + (hardware_keycode - keymap_x11->min_keycode) * keymap_x11->keysyms_per_keycode;
#define SYM(k,g,l) get_symbol (syms, k,g,l)
GdkModifierType shift_modifiers; int shift_level;
guint tmp_keyval;
shift_modifiers = GDK_SHIFT_MASK; if (keymap_x11->lock_keysym == GDK_KEY_Shift_Lock)
shift_modifiers |= GDK_LOCK_MASK;
/* Fall back to the first group if the passed in group is empty
*/ if (!(SYM (keymap_x11, group, 0) || SYM (keymap_x11, group, 1)) &&
(SYM (keymap_x11, 0, 0) || SYM (keymap_x11, 0, 1)))
group = 0;
tmp_keyval = SYM (keymap_x11, group, shift_level);
} else
{ /* Fall back to the first level if no symbol for the level *wewerepassed.
*/
shift_level = (state & shift_modifiers) ? 1 : 0; if (!SYM (keymap_x11, group, shift_level) && SYM (keymap_x11, group, 0))
shift_level = 0;
if (state & ~tmp_modifiers & LockMask)
tmp_keyval = gdk_keyval_to_upper (tmp_keyval);
/* We need to augment the consumed modifiers with LockMask, since *wehandlethatourselves,andalsowiththegroupbits
*/
tmp_modifiers |= LockMask | 1 << 13 | 1 << 14;
} else #endif
{
GdkModifierType bit;
tmp_modifiers = 0;
/* We see what modifiers matter by trying the translation with *andwithouteachpossiblemodifier
*/ for (bit = GDK_SHIFT_MASK; bit < GDK_BUTTON1_MASK; bit <<= 1)
{ /* Handling of the group here is a bit funky; a traditional *Xkeyboardmapcanhavemorethantwogroups,butnoway *ofaccessingtheextragroupsisdefined.Weallowa *callertopassinanygrouptothisfunction,butwe *onlycanrepresentswitchingbetweengroup0and1in *consumedmodifiers.
*/ if (translate_keysym (keymap_x11, hardware_keycode,
(bit == keymap_x11->group_switch_mask) ? 0 : group,
state & ~bit,
NULL, NULL) !=
translate_keysym (keymap_x11, hardware_keycode,
(bit == keymap_x11->group_switch_mask) ? 1 : group,
state | bit,
NULL, NULL))
tmp_modifiers |= bit;
}
/* This loop used to start at 3, which included MOD1 in the *virtualmapping.However,allofGTK+treatsMOD1asa *synonymforAlt,anddoesnotexpectittobemappedaround, *thereforeit'smoresanetosimplytreatMOD1likeSHIFTand *CONTROL,whicharenotmappableeither.
*/ for (i = 4; i < 8; i++)
{ if ((1 << i) & *modifiers)
{ if (keymap_x11->modmap[i] & GDK_SUPER_MASK)
*modifiers |= GDK_SUPER_MASK; elseif (keymap_x11->modmap[i] & GDK_HYPER_MASK)
*modifiers |= GDK_HYPER_MASK; elseif (keymap_x11->modmap[i] & GDK_META_MASK)
*modifiers |= GDK_META_MASK;
}
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.