keybindings: Add support for resolving from multiple layouts
Add the infrastructure to resolve keybinding symbols from multiple layouts. It is still unused, but will be, when the primary layout does not have the required latin keysyms in it. https://bugzilla.gnome.org/show_bug.cgi?id=787016
This commit is contained in:
parent
27d6c063ad
commit
8b060342bd
@ -89,6 +89,13 @@ typedef struct
|
|||||||
gboolean builtin:1;
|
gboolean builtin:1;
|
||||||
} MetaKeyPref;
|
} MetaKeyPref;
|
||||||
|
|
||||||
|
typedef struct _MetaKeyBindingKeyboardLayout
|
||||||
|
{
|
||||||
|
struct xkb_keymap *keymap;
|
||||||
|
xkb_layout_index_t index;
|
||||||
|
xkb_level_index_t n_levels;
|
||||||
|
} MetaKeyBindingKeyboardLayout;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
MetaBackend *backend;
|
MetaBackend *backend;
|
||||||
@ -108,7 +115,11 @@ typedef struct
|
|||||||
MetaResolvedKeyCombo iso_next_group_combo[2];
|
MetaResolvedKeyCombo iso_next_group_combo[2];
|
||||||
int n_iso_next_group_combos;
|
int n_iso_next_group_combos;
|
||||||
|
|
||||||
xkb_level_index_t keymap_num_levels;
|
/*
|
||||||
|
* A primary layout, and an optional secondary layout that is
|
||||||
|
* not yet used.
|
||||||
|
*/
|
||||||
|
MetaKeyBindingKeyboardLayout active_layouts[2];
|
||||||
|
|
||||||
/* Alt+click button grabs */
|
/* Alt+click button grabs */
|
||||||
ClutterModifierType window_grab_modifiers;
|
ClutterModifierType window_grab_modifiers;
|
||||||
|
@ -57,6 +57,9 @@
|
|||||||
#define SCHEMA_MUTTER_KEYBINDINGS "org.gnome.mutter.keybindings"
|
#define SCHEMA_MUTTER_KEYBINDINGS "org.gnome.mutter.keybindings"
|
||||||
#define SCHEMA_MUTTER_WAYLAND_KEYBINDINGS "org.gnome.mutter.wayland.keybindings"
|
#define SCHEMA_MUTTER_WAYLAND_KEYBINDINGS "org.gnome.mutter.wayland.keybindings"
|
||||||
|
|
||||||
|
#define META_KEY_BINDING_PRIMARY_LAYOUT 0
|
||||||
|
#define META_KEY_BINDING_SECONDARY_LAYOUT 1
|
||||||
|
|
||||||
static gboolean add_builtin_keybinding (MetaDisplay *display,
|
static gboolean add_builtin_keybinding (MetaDisplay *display,
|
||||||
const char *name,
|
const char *name,
|
||||||
GSettings *settings,
|
GSettings *settings,
|
||||||
@ -339,6 +342,27 @@ get_keycodes_for_keysym_iter (struct xkb_keymap *keymap,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
add_keysym_keycodes_from_layout (int keysym,
|
||||||
|
MetaKeyBindingKeyboardLayout *layout,
|
||||||
|
GArray *keycodes)
|
||||||
|
{
|
||||||
|
xkb_level_index_t layout_level;
|
||||||
|
|
||||||
|
for (layout_level = 0; layout_level < layout->n_levels; layout_level++)
|
||||||
|
{
|
||||||
|
FindKeysymData search_data = (FindKeysymData) {
|
||||||
|
.keycodes = keycodes,
|
||||||
|
.keysym = keysym,
|
||||||
|
.layout = layout->index,
|
||||||
|
.level = layout_level
|
||||||
|
};
|
||||||
|
xkb_keymap_key_for_each (layout->keymap,
|
||||||
|
get_keycodes_for_keysym_iter,
|
||||||
|
&search_data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Original code from gdk_x11_keymap_get_entries_for_keyval() in
|
/* Original code from gdk_x11_keymap_get_entries_for_keyval() in
|
||||||
* gdkkeys-x11.c */
|
* gdkkeys-x11.c */
|
||||||
static void
|
static void
|
||||||
@ -346,9 +370,7 @@ get_keycodes_for_keysym (MetaKeyBindingManager *keys,
|
|||||||
int keysym,
|
int keysym,
|
||||||
MetaResolvedKeyCombo *resolved_combo)
|
MetaResolvedKeyCombo *resolved_combo)
|
||||||
{
|
{
|
||||||
struct xkb_keymap *keymap;
|
unsigned int i;
|
||||||
xkb_layout_index_t layout_index;
|
|
||||||
xkb_level_index_t layout_level;
|
|
||||||
GArray *keycodes;
|
GArray *keycodes;
|
||||||
int keycode;
|
int keycode;
|
||||||
|
|
||||||
@ -362,19 +384,14 @@ get_keycodes_for_keysym (MetaKeyBindingManager *keys,
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
keymap = meta_backend_get_keymap (keys->backend);
|
for (i = 0; i < G_N_ELEMENTS (keys->active_layouts); i++)
|
||||||
layout_index = meta_backend_get_keymap_layout_group (keys->backend);
|
|
||||||
|
|
||||||
for (layout_level = 0; layout_level < keys->keymap_num_levels; layout_level++)
|
|
||||||
{
|
{
|
||||||
FindKeysymData search_data = (FindKeysymData) {
|
MetaKeyBindingKeyboardLayout *layout = &keys->active_layouts[i];
|
||||||
.keycodes = keycodes,
|
|
||||||
.keysym = keysym,
|
if (!layout->keymap)
|
||||||
.layout = layout_index,
|
continue;
|
||||||
.level = layout_level
|
|
||||||
};
|
add_keysym_keycodes_from_layout (keysym, layout, keycodes);
|
||||||
xkb_keymap_key_for_each (keymap, get_keycodes_for_keysym_iter,
|
|
||||||
&search_data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
@ -384,29 +401,44 @@ get_keycodes_for_keysym (MetaKeyBindingManager *keys,
|
|||||||
keycodes->len == 0 ? TRUE : FALSE);
|
keycodes->len == 0 ? TRUE : FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef struct _CalculateLayoutLevelsState
|
||||||
|
{
|
||||||
|
struct xkb_keymap *keymap;
|
||||||
|
xkb_layout_index_t layout_index;
|
||||||
|
|
||||||
|
xkb_level_index_t out_n_levels;
|
||||||
|
} CalculateLayoutLevelState;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
determine_keymap_num_levels_iter (struct xkb_keymap *keymap,
|
calculate_n_layout_levels_iter (struct xkb_keymap *keymap,
|
||||||
xkb_keycode_t keycode,
|
xkb_keycode_t keycode,
|
||||||
void *data)
|
void *data)
|
||||||
{
|
{
|
||||||
xkb_level_index_t *num_levels = data;
|
CalculateLayoutLevelState *state = data;
|
||||||
xkb_layout_index_t i;
|
xkb_level_index_t n_levels;
|
||||||
|
|
||||||
for (i = 0; i < xkb_keymap_num_layouts_for_key (keymap, keycode); i++)
|
n_levels = xkb_keymap_num_levels_for_key (keymap,
|
||||||
{
|
keycode,
|
||||||
xkb_level_index_t level = xkb_keymap_num_levels_for_key (keymap, keycode, i);
|
state->layout_index);
|
||||||
if (level > *num_levels)
|
|
||||||
*num_levels = level;
|
state->out_n_levels = MAX (n_levels, state->out_n_levels);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static xkb_level_index_t
|
||||||
determine_keymap_num_levels (MetaKeyBindingManager *keys)
|
calculate_n_layout_levels (struct xkb_keymap *keymap,
|
||||||
{
|
xkb_layout_index_t layout_index)
|
||||||
struct xkb_keymap *keymap = meta_backend_get_keymap (keys->backend);
|
|
||||||
|
|
||||||
keys->keymap_num_levels = 0;
|
{
|
||||||
xkb_keymap_key_for_each (keymap, determine_keymap_num_levels_iter, &keys->keymap_num_levels);
|
CalculateLayoutLevelState state = {
|
||||||
|
.keymap = keymap,
|
||||||
|
.layout_index = layout_index,
|
||||||
|
|
||||||
|
.out_n_levels = 0
|
||||||
|
};
|
||||||
|
|
||||||
|
xkb_keymap_key_for_each (keymap, calculate_n_layout_levels_iter, &state);
|
||||||
|
|
||||||
|
return state.out_n_levels;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -590,12 +622,44 @@ binding_reload_combos_foreach (gpointer key,
|
|||||||
index_binding (keys, binding);
|
index_binding (keys, binding);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
clear_active_keyboard_layouts (MetaKeyBindingManager *keys)
|
||||||
|
{
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
for (i = 0; i < G_N_ELEMENTS (keys->active_layouts); i++)
|
||||||
|
{
|
||||||
|
MetaKeyBindingKeyboardLayout *layout = &keys->active_layouts[i];
|
||||||
|
|
||||||
|
g_clear_pointer (&layout->keymap, xkb_keymap_unref);
|
||||||
|
*layout = (MetaKeyBindingKeyboardLayout) { 0 };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
reload_active_keyboard_layouts (MetaKeyBindingManager *keys)
|
||||||
|
{
|
||||||
|
struct xkb_keymap *keymap;
|
||||||
|
xkb_layout_index_t layout_index;
|
||||||
|
|
||||||
|
clear_active_keyboard_layouts (keys);
|
||||||
|
|
||||||
|
keymap = meta_backend_get_keymap (keys->backend);
|
||||||
|
layout_index = meta_backend_get_keymap_layout_group (keys->backend);
|
||||||
|
|
||||||
|
keys->active_layouts[META_KEY_BINDING_PRIMARY_LAYOUT] = (MetaKeyBindingKeyboardLayout) {
|
||||||
|
.keymap = xkb_keymap_ref (keymap),
|
||||||
|
.index = layout_index,
|
||||||
|
.n_levels = calculate_n_layout_levels (keymap, layout_index),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
reload_combos (MetaKeyBindingManager *keys)
|
reload_combos (MetaKeyBindingManager *keys)
|
||||||
{
|
{
|
||||||
g_hash_table_remove_all (keys->key_bindings_index);
|
g_hash_table_remove_all (keys->key_bindings_index);
|
||||||
|
|
||||||
determine_keymap_num_levels (keys);
|
reload_active_keyboard_layouts (keys);
|
||||||
|
|
||||||
resolve_key_combo (keys,
|
resolve_key_combo (keys,
|
||||||
&keys->overlay_key_combo,
|
&keys->overlay_key_combo,
|
||||||
@ -1196,6 +1260,8 @@ meta_display_shutdown_keys (MetaDisplay *display)
|
|||||||
|
|
||||||
g_hash_table_destroy (keys->key_bindings_index);
|
g_hash_table_destroy (keys->key_bindings_index);
|
||||||
g_hash_table_destroy (keys->key_bindings);
|
g_hash_table_destroy (keys->key_bindings);
|
||||||
|
|
||||||
|
clear_active_keyboard_layouts (keys);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Grab/ungrab, ignoring all annoying modifiers like NumLock etc. */
|
/* Grab/ungrab, ignoring all annoying modifiers like NumLock etc. */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user