Merge branch 'fix-wayland-layout-changes' into 'master'

Fix wayland layout changes

See merge request GNOME/gtk!3303
This commit is contained in:
Matthias Clasen 2021-03-15 22:31:08 +00:00
commit 08b27848e1
2 changed files with 76 additions and 20 deletions

View File

@ -1686,6 +1686,24 @@ gdk_key_event_is_modifier (GdkEvent *event)
return self->key_is_modifier;
}
static gboolean
keyval_in_group (GdkKeymap *keymap,
guint keyval,
int group)
{
GdkKeymapKey *keys;
guint n_keys;
gdk_keymap_get_cached_entries_for_keyval (keymap, keyval, &keys, &n_keys);
for (int i = 0; i < n_keys; i++)
{
if (keys[i].group == group)
return TRUE;
}
return FALSE;
}
/**
* gdk_key_event_matches:
* @event: (type GdkKeyEvent): a key `GdkEvent`
@ -1781,10 +1799,9 @@ gdk_key_event_matches (GdkEvent *event,
if (keys[i].keycode == keycode &&
keys[i].level == level &&
/* Only match for group if it's an accel mod */
(!group_mod_is_accel_mod || keys[i].group == layout))
{
return GDK_KEY_MATCH_PARTIAL;
}
(keys[i].group == layout ||
(!group_mod_is_accel_mod && !keyval_in_group (keymap, keyval, layout))))
return GDK_KEY_MATCH_PARTIAL;
}
}

View File

@ -1846,6 +1846,36 @@ pointer_handle_axis_discrete (void *data,
get_axis_name (axis), value, seat));
}
static int
get_active_layout (GdkKeymap *keymap)
{
struct xkb_keymap *xkb_keymap;
struct xkb_state *xkb_state;
xkb_keymap = _gdk_wayland_keymap_get_xkb_keymap (keymap);
xkb_state = _gdk_wayland_keymap_get_xkb_state (keymap);
for (int i = 0; i < xkb_keymap_num_layouts (xkb_keymap); i++)
{
if (xkb_state_layout_index_is_active (xkb_state, i, XKB_STATE_LAYOUT_EFFECTIVE))
return i;
}
return -1;
}
#ifdef G_ENABLE_DEBUG
static const char *
get_active_layout_name (GdkKeymap *keymap)
{
struct xkb_keymap *xkb_keymap;
xkb_keymap = _gdk_wayland_keymap_get_xkb_keymap (keymap);
return xkb_keymap_layout_get_name (xkb_keymap, get_active_layout (keymap));
}
#endif
static void
keyboard_handle_keymap (void *data,
struct wl_keyboard *keyboard,
@ -1870,6 +1900,8 @@ keyboard_handle_keymap (void *data,
_gdk_wayland_keymap_update_from_fd (seat->keymap, format, fd, size);
GDK_DISPLAY_NOTE(seat->keymap->display, INPUT, g_print ("active layout now: %s\n", get_active_layout_name (seat->keymap)));
g_signal_emit_by_name (seat->keymap, "keys-changed");
g_signal_emit_by_name (seat->keymap, "state-changed");
if (direction != gdk_keymap_get_direction (seat->keymap))
@ -2215,17 +2247,18 @@ keyboard_handle_modifiers (void *data,
gboolean num_lock;
gboolean scroll_lock;
GdkModifierType modifiers;
int layout;
keymap = seat->keymap;
xkb_state = _gdk_wayland_keymap_get_xkb_state (keymap);
direction = gdk_keymap_get_direction (seat->keymap);
bidi = gdk_keymap_have_bidi_layouts (seat->keymap);
caps_lock = gdk_keymap_get_caps_lock_state (seat->keymap);
num_lock = gdk_keymap_get_num_lock_state (seat->keymap);
scroll_lock = gdk_keymap_get_scroll_lock_state (seat->keymap);
modifiers = gdk_keymap_get_modifier_state (seat->keymap);
direction = gdk_keymap_get_direction (keymap);
bidi = gdk_keymap_have_bidi_layouts (keymap);
caps_lock = gdk_keymap_get_caps_lock_state (keymap);
num_lock = gdk_keymap_get_num_lock_state (keymap);
scroll_lock = gdk_keymap_get_scroll_lock_state (keymap);
modifiers = gdk_keymap_get_modifier_state (keymap);
layout = get_active_layout (keymap);
/* Note: the docs for xkb_state_update mask state that all parameters
* must be passed, or we may end up with an 'incoherent' state. But the
@ -2247,20 +2280,26 @@ keyboard_handle_modifiers (void *data,
seat->key_modifiers = gdk_keymap_get_modifier_state (keymap);
g_signal_emit_by_name (keymap, "state-changed");
if (direction != gdk_keymap_get_direction (keymap))
g_signal_emit_by_name (keymap, "direction-changed");
if (layout != get_active_layout (keymap))
{
GDK_DISPLAY_NOTE(keymap->display, INPUT, g_print ("active layout now: %s\n", get_active_layout_name (keymap)));
if (direction != gdk_keymap_get_direction (seat->keymap))
g_object_notify (G_OBJECT (seat->logical_keyboard), "direction");
if (bidi != gdk_keymap_have_bidi_layouts (seat->keymap))
g_signal_emit_by_name (keymap, "keys-changed");
}
if (direction != gdk_keymap_get_direction (keymap))
{
g_signal_emit_by_name (keymap, "direction-changed");
g_object_notify (G_OBJECT (seat->logical_keyboard), "direction");
}
if (bidi != gdk_keymap_have_bidi_layouts (keymap))
g_object_notify (G_OBJECT (seat->logical_keyboard), "has-bidi-layouts");
if (caps_lock != gdk_keymap_get_caps_lock_state (seat->keymap))
if (caps_lock != gdk_keymap_get_caps_lock_state (keymap))
g_object_notify (G_OBJECT (seat->logical_keyboard), "caps-lock-state");
if (num_lock != gdk_keymap_get_num_lock_state (seat->keymap))
if (num_lock != gdk_keymap_get_num_lock_state (keymap))
g_object_notify (G_OBJECT (seat->logical_keyboard), "num-lock-state");
if (scroll_lock != gdk_keymap_get_scroll_lock_state (seat->keymap))
if (scroll_lock != gdk_keymap_get_scroll_lock_state (keymap))
g_object_notify (G_OBJECT (seat->logical_keyboard), "scroll-lock-state");
if (modifiers != gdk_keymap_get_modifier_state (seat->keymap))
if (modifiers != gdk_keymap_get_modifier_state (keymap))
g_object_notify (G_OBJECT (seat->logical_keyboard), "modifier-state");
}