Commit 15195bf6 authored by Mike Auty's avatar Mike Auty
Browse files

virtual-input-device/native: Try lower level keycodes first

Issue 405 relates to mismapped keys injected by gnome-remote-desktop.  It
seems to be because a keyval (keysym) may be in the keymap more than once.
We currently run through each keycode, trying from lowest level to highest
level and stop as soon as we find a hit, which means that if the key
symbol is in a lower level of a later keycode, we mis-pick the earlier one
with the higher level (hence the far less common greek_OMEGA rather than
common AT symbol).

This patch swaps the order of the loops (so we loop through the levels
from lowest to highest, and at each level run through the keycodes. We
make sure we only go as high as the highest level for all keys (by
figuring out the maximum on the first level's run through). This resolves
the issues being experienced and ensures it is possible to type characters
like @. It is slightly less efficient in the worst case, in that we keep
figuring out the maximum for each key multiplied by the maximum number of
levels (rather than 1), but in the common case is probably more efficient
(because there's a whole bunch of higher levels we never have to try if we
hit the right keycode first).

Fixes #405.

GNOME/mutter#405
parent 3c0067dc
Pipeline #110871 failed with stages
in 8 minutes and 26 seconds
......@@ -287,6 +287,7 @@ pick_keycode_for_keyval_in_current_group (ClutterVirtualInputDevice *virtual_dev
struct xkb_state *state;
guint keycode, layout;
xkb_keycode_t min_keycode, max_keycode;
int max_num_levels, level;
keymap = clutter_backend_get_keymap (clutter_get_default_backend ());
xkb_keymap = meta_keymap_native_get_keyboard_map (META_KEYMAP_NATIVE (keymap));
......@@ -295,23 +296,41 @@ pick_keycode_for_keyval_in_current_group (ClutterVirtualInputDevice *virtual_dev
layout = xkb_state_serialize_layout (state, XKB_STATE_LAYOUT_EFFECTIVE);
min_keycode = xkb_keymap_min_keycode (xkb_keymap);
max_keycode = xkb_keymap_max_keycode (xkb_keymap);
for (keycode = min_keycode; keycode < max_keycode; keycode++)
max_num_levels = 1;
/*
* Iterate over the lower levels of the keymap first, in an attempt to try to
* pick lower level keycodes before higher level ones that may come later.
*
* The max_num_levels is determined dynamically by the highest encountered
* level count for any key we iterate over in the keymap.
*/
for (level = 0; level < max_num_levels; level++)
{
gint num_levels, level;
num_levels = xkb_keymap_num_levels_for_key (xkb_keymap, keycode, layout);
for (level = 0; level < num_levels; level++)
for (keycode = min_keycode; keycode < max_keycode; keycode++)
{
const xkb_keysym_t *syms;
gint num_syms, sym;
num_syms = xkb_keymap_key_get_syms_by_level (xkb_keymap, keycode, layout, level, &syms);
for (sym = 0; sym < num_syms; sym++)
{
if (syms[sym] == keyval)
int num_levels;
num_levels = xkb_keymap_num_levels_for_key (xkb_keymap, keycode, layout);
max_num_levels = MAX (max_num_levels, num_levels);
if (level < num_levels)
{
const xkb_keysym_t *syms;
int num_syms, sym;
num_syms = xkb_keymap_key_get_syms_by_level (xkb_keymap,
keycode,
layout,
level,
&syms);
for (sym = 0; sym < num_syms; sym++)
{
*keycode_out = keycode;
if (level_out)
*level_out = level;
return TRUE;
if (syms[sym] == keyval)
{
*keycode_out = keycode;
if (level_out)
*level_out = level;
return TRUE;
}
}
}
}
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment