backend-x11: Ensure the Xkb group index remains properly set

Ubuntu ships a patch in the X server that makes the group switch
keybindings only work on key release, i.e. the X server internal group
locking happens on key release which means that mutter gets the
XKB_KEY_ISO_Next_Group key press event, does its XLockGroup() call
with a new index and then, on key release, the X server moves the
index further again.

We can work around this without affecting our behavior in unpatched X
servers by doing a XLockGroup() every time we're notified of the
locked group changing if it doesn't match what we requested.

https://bugzilla.gnome.org/show_bug.cgi?id=756543
This commit is contained in:
Alberts Muktupāvels 2015-10-14 03:14:14 +03:00 committed by Rui Matos
parent 69a7d5ff02
commit 2857fdbdb8

View File

@ -82,6 +82,7 @@ struct _MetaBackendX11Private
gchar *keymap_layouts; gchar *keymap_layouts;
gchar *keymap_variants; gchar *keymap_variants;
gchar *keymap_options; gchar *keymap_options;
int locked_group;
}; };
typedef struct _MetaBackendX11Private MetaBackendX11Private; typedef struct _MetaBackendX11Private MetaBackendX11Private;
@ -297,15 +298,23 @@ handle_host_xevent (MetaBackend *backend,
if (event->type == priv->xkb_event_base) if (event->type == priv->xkb_event_base)
{ {
XkbAnyEvent *xkb_ev = (XkbAnyEvent *) event; XkbEvent *xkb_ev = (XkbEvent *) event;
if (xkb_ev->device == META_VIRTUAL_CORE_KEYBOARD_ID) if (xkb_ev->any.device == META_VIRTUAL_CORE_KEYBOARD_ID)
{ {
switch (xkb_ev->xkb_type) switch (xkb_ev->any.xkb_type)
{ {
case XkbNewKeyboardNotify: case XkbNewKeyboardNotify:
case XkbMapNotify: case XkbMapNotify:
keymap_changed (backend); keymap_changed (backend);
break;
case XkbStateNotify:
if (xkb_ev->state.changed & XkbGroupLockMask)
{
if (priv->locked_group != xkb_ev->state.locked_group)
XkbLockGroup (priv->xdisplay, XkbUseCoreKbd, priv->locked_group);
}
break;
default: default:
break; break;
} }
@ -776,6 +785,7 @@ meta_backend_x11_lock_layout_group (MetaBackend *backend,
MetaBackendX11 *x11 = META_BACKEND_X11 (backend); MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11); MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
priv->locked_group = idx;
XkbLockGroup (priv->xdisplay, XkbUseCoreKbd, idx); XkbLockGroup (priv->xdisplay, XkbUseCoreKbd, idx);
} }