CasildaCompositor: foward keyboard layout changes to clients.

Fix issue #5 "Track keymap layout changes"
This commit is contained in:
Juan Pablo Ugarte 2026-04-03 15:49:45 -04:00
parent 75e43ed930
commit 023b44d1c5
No known key found for this signature in database
2 changed files with 41 additions and 50 deletions

View file

@ -9,20 +9,20 @@ development releases.
## Unreleased
2026-03-31 - 1.2.2 Bugfix release
- Add basic fractional scale support
- Add viewporter support
- Add support for cursor shape
- Forward keyboard layout changes to clients.
### Issues
- Fix issue #13 "Wrong cursor size on client windows"
- Fix issue #5 "Track keymap layout changes"
### Packaging
- Casilda now depends on wlroots 0.20 instead of 0.19
- Use wlroots headers instead of using wayland_scanner for protocol headers
- Use installed headers instead of using wayland_scanner to generate them
## 1.2.1

View file

@ -1763,30 +1763,14 @@ casilda_pointer_mode_init (CasildaCompositorPrivate *priv)
g_object_ref (priv->click_gesture);
}
static void
casilda_compositor_keyboard_init (CasildaCompositorPrivate *priv)
static struct xkb_keymap *
_gdk_device_get_xkb_keymap (GdkDevice *gkeyboard)
{
struct xkb_keymap *keymap = NULL;
struct xkb_state *state = NULL;
GdkDevice *gkeyboard;
GdkDisplay *gdisplay;
GdkSeat *gseat;
wlr_keyboard_init (&priv->keyboard, NULL, "Casilda-keyboard");
gdisplay = gtk_widget_get_display (priv->self);
gseat = gdk_display_get_default_seat (gdisplay);
gkeyboard = gdk_seat_get_keyboard (gseat);
#ifdef GDK_WINDOWING_WAYLAND
if (GDK_IS_WAYLAND_DEVICE (gkeyboard))
{
keymap = gdk_wayland_device_get_xkb_keymap (gkeyboard);
/* TODO: add a way to get keymap state from gtk wayland backend
* Or even better add a way to get the layout directly
*/
xkb_keymap_ref (keymap);
}
#endif
@ -1796,15 +1780,12 @@ casilda_compositor_keyboard_init (CasildaCompositorPrivate *priv)
{
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
struct xkb_context *context = xkb_context_new (XKB_CONTEXT_NO_FLAGS);
Display *dpy = gdk_x11_display_get_xdisplay (GDK_X11_DISPLAY (gdisplay));
Display *dpy = gdk_x11_display_get_xdisplay (GDK_X11_DISPLAY (gdk_device_get_display (gkeyboard)));
keymap = xkb_x11_keymap_new_from_device (context,
XGetXCBConnection (dpy),
gdk_x11_device_get_id (gkeyboard),
XKB_KEYMAP_COMPILE_NO_FLAGS);
state = xkb_x11_state_new_from_device (keymap,
XGetXCBConnection (dpy),
gdk_x11_device_get_id (gkeyboard));
xkb_context_unref (context);
G_GNUC_END_IGNORE_DEPRECATIONS
}
@ -1818,36 +1799,46 @@ G_GNUC_END_IGNORE_DEPRECATIONS
xkb_context_unref (context);
}
/* Set keymap */
wlr_keyboard_set_keymap (&priv->keyboard, keymap);
return keymap;
}
/* Update layout if present */
if (state)
static void
on_gdk_keyboard_notify (GObject *object, GParamSpec *pspec, CasildaCompositor *compositor)
{
CasildaCompositorPrivate *priv = GET_PRIVATE(compositor);
GdkDevice *gkeyboard = GDK_DEVICE (object);
if (g_strcmp0 (pspec->name, "layout-names") == 0)
{
gint active_layout = -1;
struct xkb_keymap *keymap = _gdk_device_get_xkb_keymap (gkeyboard);
for (guint i = 0; i < xkb_keymap_num_layouts (keymap); i++)
{
if (xkb_state_layout_index_is_active (state,
i,
XKB_STATE_LAYOUT_EFFECTIVE))
active_layout = i;
g_debug ("\t %i %s", i, xkb_keymap_layout_get_name (keymap, i));
}
if (active_layout >= 0)
{
wlr_keyboard_notify_modifiers (&priv->keyboard,
priv->keyboard.modifiers.depressed,
priv->keyboard.modifiers.latched,
priv->keyboard.modifiers.locked,
active_layout);
}
xkb_state_unref (state);
/* Set keymap */
wlr_keyboard_set_keymap (&priv->keyboard, keymap);
xkb_keymap_unref (keymap);
}
else if (g_strcmp0 (pspec->name, "active-layout-index") == 0)
{
/* Update layout/group index*/
priv->keyboard.modifiers.group = gdk_device_get_active_layout_index (gkeyboard);
wlr_seat_keyboard_notify_modifiers (priv->seat, &priv->keyboard.modifiers);
}
}
xkb_keymap_unref (keymap);
static void
casilda_compositor_keyboard_init (CasildaCompositorPrivate *priv)
{
GdkDevice *gkeyboard;
GdkDisplay *gdisplay;
GdkSeat *gseat;
wlr_keyboard_init (&priv->keyboard, NULL, "Casilda-keyboard");
gdisplay = gtk_widget_get_display (priv->self);
gseat = gdk_display_get_default_seat (gdisplay);
gkeyboard = gdk_seat_get_keyboard (gseat);
/* layout-names and active-layout-index notification */
g_signal_connect_object (gkeyboard, "notify", G_CALLBACK (on_gdk_keyboard_notify), priv->self, G_CONNECT_DEFAULT);
wlr_seat_set_keyboard (priv->seat, &priv->keyboard);