[mutter] backends/x11: Only apply keymap when not running nested



commit bd2ca79a481fcde67e8e1b352b124937226d6236
Author: Jonas Ådahl <jadahl gmail com>
Date:   Tue Jan 31 22:09:02 2017 +0800

    backends/x11: Only apply keymap when not running nested
    
    https://bugzilla.gnome.org/show_bug.cgi?id=777800

 src/backends/x11/cm/meta-backend-x11-cm.c         |  217 +++++++++++++++++++++
 src/backends/x11/meta-backend-x11.c               |  198 +------------------
 src/backends/x11/meta-backend-x11.h               |    3 +
 src/backends/x11/nested/meta-backend-x11-nested.c |   16 ++
 4 files changed, 244 insertions(+), 190 deletions(-)
---
diff --git a/src/backends/x11/cm/meta-backend-x11-cm.c b/src/backends/x11/cm/meta-backend-x11-cm.c
index ac9fc25..814ca61 100644
--- a/src/backends/x11/cm/meta-backend-x11-cm.c
+++ b/src/backends/x11/cm/meta-backend-x11-cm.c
@@ -21,6 +21,11 @@
 
 #include "backends/x11/cm/meta-backend-x11-cm.h"
 
+#include <stdlib.h>
+#include <X11/XKBlib.h>
+#include <X11/extensions/XKBrules.h>
+#include <xkbcommon/xkbcommon-x11.h>
+
 #include "backends/meta-backend-private.h"
 #include "backends/x11/meta-cursor-renderer-x11.h"
 #include "backends/x11/meta-monitor-manager-xrandr.h"
@@ -28,11 +33,19 @@
 struct _MetaBackendX11Cm
 {
   MetaBackendX11 parent;
+
+  char *keymap_layouts;
+  char *keymap_variants;
+  char *keymap_options;
+  int locked_group;
 };
 
 G_DEFINE_TYPE (MetaBackendX11Cm, meta_backend_x11_cm, META_TYPE_BACKEND_X11)
 
 static void
+apply_keymap (MetaBackendX11 *x11);
+
+static void
 take_touch_grab (MetaBackend *backend)
 {
   MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
@@ -51,6 +64,17 @@ take_touch_grab (MetaBackend *backend)
 }
 
 static void
+on_device_added (ClutterDeviceManager *device_manager,
+                 ClutterInputDevice   *device,
+                 gpointer              user_data)
+{
+  MetaBackendX11 *x11 = META_BACKEND_X11 (user_data);
+
+  if (clutter_input_device_get_device_type (device) == CLUTTER_KEYBOARD_DEVICE)
+    apply_keymap (x11);
+}
+
+static void
 meta_backend_x11_cm_post_init (MetaBackend *backend)
 {
   MetaBackendClass *parent_backend_class =
@@ -58,6 +82,10 @@ meta_backend_x11_cm_post_init (MetaBackend *backend)
 
   parent_backend_class->post_init (backend);
 
+  g_signal_connect_object (clutter_device_manager_get_default (),
+                           "device-added",
+                           G_CALLBACK (on_device_added), backend, 0);
+
   take_touch_grab (backend);
 }
 
@@ -107,15 +135,202 @@ meta_backend_x11_cm_select_stage_events (MetaBackend *backend)
   XISelectEvents (xdisplay, xwin, &mask, 1);
 }
 
+static void
+get_xkbrf_var_defs (Display           *xdisplay,
+                    const char        *layouts,
+                    const char        *variants,
+                    const char        *options,
+                    char             **rules_p,
+                    XkbRF_VarDefsRec  *var_defs)
+{
+  char *rules = NULL;
+
+  /* Get it from the X property or fallback on defaults */
+  if (!XkbRF_GetNamesProp (xdisplay, &rules, var_defs) || !rules)
+    {
+      rules = strdup (DEFAULT_XKB_RULES_FILE);
+      var_defs->model = strdup (DEFAULT_XKB_MODEL);
+      var_defs->layout = NULL;
+      var_defs->variant = NULL;
+      var_defs->options = NULL;
+    }
+
+  /* Swap in our new options... */
+  free (var_defs->layout);
+  var_defs->layout = strdup (layouts);
+  free (var_defs->variant);
+  var_defs->variant = strdup (variants);
+  free (var_defs->options);
+  var_defs->options = strdup (options);
+
+  /* Sometimes, the property is a file path, and sometimes it's
+     not. Normalize it so it's always a file path. */
+  if (rules[0] == '/')
+    *rules_p = g_strdup (rules);
+  else
+    *rules_p = g_build_filename (XKB_BASE, "rules", rules, NULL);
+
+  free (rules);
+}
+
+static void
+free_xkbrf_var_defs (XkbRF_VarDefsRec *var_defs)
+{
+  free (var_defs->model);
+  free (var_defs->layout);
+  free (var_defs->variant);
+  free (var_defs->options);
+}
+
+static void
+free_xkb_component_names (XkbComponentNamesRec *p)
+{
+  free (p->keymap);
+  free (p->keycodes);
+  free (p->types);
+  free (p->compat);
+  free (p->symbols);
+  free (p->geometry);
+}
+
+static void
+upload_xkb_description (Display              *xdisplay,
+                        const gchar          *rules_file_path,
+                        XkbRF_VarDefsRec     *var_defs,
+                        XkbComponentNamesRec *comp_names)
+{
+  XkbDescRec *xkb_desc;
+  gchar *rules_file;
+
+  /* Upload it to the X server using the same method as setxkbmap */
+  xkb_desc = XkbGetKeyboardByName (xdisplay,
+                                   XkbUseCoreKbd,
+                                   comp_names,
+                                   XkbGBN_AllComponentsMask,
+                                   XkbGBN_AllComponentsMask &
+                                   (~XkbGBN_GeometryMask), True);
+  if (!xkb_desc)
+    {
+      g_warning ("Couldn't upload new XKB keyboard description");
+      return;
+    }
+
+  XkbFreeKeyboard (xkb_desc, 0, True);
+
+  rules_file = g_path_get_basename (rules_file_path);
+
+  if (!XkbRF_SetNamesProp (xdisplay, rules_file, var_defs))
+    g_warning ("Couldn't update the XKB root window property");
+
+  g_free (rules_file);
+}
+
+static void
+apply_keymap (MetaBackendX11 *x11)
+{
+  MetaBackendX11Cm *x11_cm = META_BACKEND_X11_CM (x11);
+  Display *xdisplay = meta_backend_x11_get_xdisplay (x11);
+  XkbRF_RulesRec *xkb_rules;
+  XkbRF_VarDefsRec xkb_var_defs = { 0 };
+  char *rules_file_path;
+
+  if (!x11_cm->keymap_layouts ||
+      !x11_cm->keymap_variants ||
+      !x11_cm->keymap_options)
+    return;
+
+  get_xkbrf_var_defs (xdisplay,
+                      x11_cm->keymap_layouts,
+                      x11_cm->keymap_variants,
+                      x11_cm->keymap_options,
+                      &rules_file_path,
+                      &xkb_var_defs);
+
+  xkb_rules = XkbRF_Load (rules_file_path, NULL, True, True);
+  if (xkb_rules)
+    {
+      XkbComponentNamesRec xkb_comp_names = { 0 };
+
+      XkbRF_GetComponents (xkb_rules, &xkb_var_defs, &xkb_comp_names);
+      upload_xkb_description (xdisplay, rules_file_path, &xkb_var_defs, &xkb_comp_names);
+
+      free_xkb_component_names (&xkb_comp_names);
+      XkbRF_Free (xkb_rules, True);
+    }
+  else
+    {
+      g_warning ("Couldn't load XKB rules");
+    }
+
+  free_xkbrf_var_defs (&xkb_var_defs);
+  g_free (rules_file_path);
+}
+
+static void
+meta_backend_x11_cm_set_keymap (MetaBackend *backend,
+                                const char  *layouts,
+                                const char  *variants,
+                                const char  *options)
+{
+  MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
+  MetaBackendX11Cm *x11_cm = META_BACKEND_X11_CM (x11);
+
+  g_free (x11_cm->keymap_layouts);
+  x11_cm->keymap_layouts = g_strdup (layouts);
+  g_free (x11_cm->keymap_variants);
+  x11_cm->keymap_variants = g_strdup (variants);
+  g_free (x11_cm->keymap_options);
+  x11_cm->keymap_options = g_strdup (options);
+
+  apply_keymap (x11);
+}
+
+static void
+meta_backend_x11_cm_lock_layout_group (MetaBackend *backend,
+                                       guint        idx)
+{
+  MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
+  MetaBackendX11Cm *x11_cm = META_BACKEND_X11_CM (x11);
+  Display *xdisplay = meta_backend_x11_get_xdisplay (x11);
+
+  x11_cm->locked_group = idx;
+  XkbLockGroup (xdisplay, XkbUseCoreKbd, idx);
+}
+
 static gboolean
 meta_backend_x11_cm_handle_host_xevent (MetaBackendX11 *backend_x11,
                                         XEvent         *event)
 {
   MetaBackend *backend = META_BACKEND (backend_x11);
+  MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
+  MetaBackendX11Cm *x11_cm = META_BACKEND_X11_CM (x11);
   MetaMonitorManager *monitor_manager =
     meta_backend_get_monitor_manager (backend);
   MetaMonitorManagerXrandr *monitor_manager_xrandr =
     META_MONITOR_MANAGER_XRANDR (monitor_manager);
+  Display *xdisplay = meta_backend_x11_get_xdisplay (x11);
+
+  if (event->type == meta_backend_x11_get_xkb_event_base (x11))
+    {
+      XkbEvent *xkb_ev = (XkbEvent *) event;
+
+      if (xkb_ev->any.device == META_VIRTUAL_CORE_KEYBOARD_ID)
+        {
+          switch (xkb_ev->any.xkb_type)
+            {
+            case XkbStateNotify:
+              if (xkb_ev->state.changed & XkbGroupLockMask)
+                {
+                  if (x11_cm->locked_group != xkb_ev->state.locked_group)
+                    XkbLockGroup (xdisplay, XkbUseCoreKbd,
+                                  x11_cm->locked_group);
+                }
+              break;
+            default:
+              break;
+            }
+        }
+    }
 
   return meta_monitor_manager_xrandr_handle_xevent (monitor_manager_xrandr,
                                                     event);
@@ -169,6 +384,8 @@ meta_backend_x11_cm_class_init (MetaBackendX11CmClass *klass)
   backend_class->create_cursor_renderer = meta_backend_x11_cm_create_cursor_renderer;
   backend_class->update_screen_size = meta_backend_x11_cm_update_screen_size;
   backend_class->select_stage_events = meta_backend_x11_cm_select_stage_events;
+  backend_class->lock_layout_group = meta_backend_x11_cm_lock_layout_group;
+  backend_class->set_keymap = meta_backend_x11_cm_set_keymap;
 
   backend_x11_class->handle_host_xevent = meta_backend_x11_cm_handle_host_xevent;
   backend_x11_class->translate_device_event = meta_backend_x11_cm_translate_device_event;
diff --git a/src/backends/x11/meta-backend-x11.c b/src/backends/x11/meta-backend-x11.c
index 92a13dc..0fd7e77 100644
--- a/src/backends/x11/meta-backend-x11.c
+++ b/src/backends/x11/meta-backend-x11.c
@@ -34,7 +34,6 @@
 
 #include <X11/extensions/sync.h>
 #include <X11/XKBlib.h>
-#include <X11/extensions/XKBrules.h>
 #include <X11/Xlib-xcb.h>
 #include <xkbcommon/xkbcommon-x11.h>
 
@@ -67,17 +66,11 @@ struct _MetaBackendX11Private
   uint8_t xkb_error_base;
 
   struct xkb_keymap *keymap;
-  gchar *keymap_layouts;
-  gchar *keymap_variants;
-  gchar *keymap_options;
-  int locked_group;
 
   MetaLogicalMonitor *cached_current_logical_monitor;
 };
 typedef struct _MetaBackendX11Private MetaBackendX11Private;
 
-static void apply_keymap (MetaBackendX11 *x11);
-
 G_DEFINE_TYPE_WITH_PRIVATE (MetaBackendX11, meta_backend_x11, META_TYPE_BACKEND);
 
 static void
@@ -283,13 +276,6 @@ handle_host_xevent (MetaBackend *backend,
             case XkbMapNotify:
               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:
               break;
             }
@@ -384,17 +370,6 @@ x_event_source_new (MetaBackend *backend)
 }
 
 static void
-on_device_added (ClutterDeviceManager *device_manager,
-                 ClutterInputDevice   *device,
-                 gpointer              user_data)
-{
-  MetaBackendX11 *x11 = META_BACKEND_X11 (user_data);
-
-  if (clutter_input_device_get_device_type (device) == CLUTTER_KEYBOARD_DEVICE)
-    apply_keymap (x11);
-}
-
-static void
 on_monitors_changed (MetaMonitorManager *manager,
                      MetaBackend        *backend)
 {
@@ -450,9 +425,6 @@ meta_backend_x11_post_init (MetaBackend *backend)
     meta_fatal ("X server doesn't have the XKB extension, version %d.%d or newer\n",
                 XKB_X11_MIN_MAJOR_XKB_VERSION, XKB_X11_MIN_MINOR_XKB_VERSION);
 
-  g_signal_connect_object (clutter_device_manager_get_default (), "device-added",
-                           G_CALLBACK (on_device_added), backend, 0);
-
   META_BACKEND_CLASS (meta_backend_x11_parent_class)->post_init (backend);
 
   monitor_manager = meta_backend_get_monitor_manager (backend);
@@ -567,155 +539,6 @@ meta_backend_x11_get_current_logical_monitor (MetaBackend *backend)
   return priv->cached_current_logical_monitor;
 }
 
-static void
-get_xkbrf_var_defs (Display           *xdisplay,
-                    const char        *layouts,
-                    const char        *variants,
-                    const char        *options,
-                    char             **rules_p,
-                    XkbRF_VarDefsRec  *var_defs)
-{
-  char *rules = NULL;
-
-  /* Get it from the X property or fallback on defaults */
-  if (!XkbRF_GetNamesProp (xdisplay, &rules, var_defs) || !rules)
-    {
-      rules = strdup (DEFAULT_XKB_RULES_FILE);
-      var_defs->model = strdup (DEFAULT_XKB_MODEL);
-      var_defs->layout = NULL;
-      var_defs->variant = NULL;
-      var_defs->options = NULL;
-    }
-
-  /* Swap in our new options... */
-  free (var_defs->layout);
-  var_defs->layout = strdup (layouts);
-  free (var_defs->variant);
-  var_defs->variant = strdup (variants);
-  free (var_defs->options);
-  var_defs->options = strdup (options);
-
-  /* Sometimes, the property is a file path, and sometimes it's
-     not. Normalize it so it's always a file path. */
-  if (rules[0] == '/')
-    *rules_p = g_strdup (rules);
-  else
-    *rules_p = g_build_filename (XKB_BASE, "rules", rules, NULL);
-
-  free (rules);
-}
-
-static void
-free_xkbrf_var_defs (XkbRF_VarDefsRec *var_defs)
-{
-  free (var_defs->model);
-  free (var_defs->layout);
-  free (var_defs->variant);
-  free (var_defs->options);
-}
-
-static void
-free_xkb_component_names (XkbComponentNamesRec *p)
-{
-  free (p->keymap);
-  free (p->keycodes);
-  free (p->types);
-  free (p->compat);
-  free (p->symbols);
-  free (p->geometry);
-}
-
-static void
-upload_xkb_description (Display              *xdisplay,
-                        const gchar          *rules_file_path,
-                        XkbRF_VarDefsRec     *var_defs,
-                        XkbComponentNamesRec *comp_names)
-{
-  XkbDescRec *xkb_desc;
-  gchar *rules_file;
-
-  /* Upload it to the X server using the same method as setxkbmap */
-  xkb_desc = XkbGetKeyboardByName (xdisplay,
-                                   XkbUseCoreKbd,
-                                   comp_names,
-                                   XkbGBN_AllComponentsMask,
-                                   XkbGBN_AllComponentsMask &
-                                   (~XkbGBN_GeometryMask), True);
-  if (!xkb_desc)
-    {
-      g_warning ("Couldn't upload new XKB keyboard description");
-      return;
-    }
-
-  XkbFreeKeyboard (xkb_desc, 0, True);
-
-  rules_file = g_path_get_basename (rules_file_path);
-
-  if (!XkbRF_SetNamesProp (xdisplay, rules_file, var_defs))
-    g_warning ("Couldn't update the XKB root window property");
-
-  g_free (rules_file);
-}
-
-static void
-apply_keymap (MetaBackendX11 *x11)
-{
-  MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
-  XkbRF_RulesRec *xkb_rules;
-  XkbRF_VarDefsRec xkb_var_defs = { 0 };
-  gchar *rules_file_path;
-
-  if (!priv->keymap_layouts ||
-      !priv->keymap_variants ||
-      !priv->keymap_options)
-    return;
-
-  get_xkbrf_var_defs (priv->xdisplay,
-                      priv->keymap_layouts,
-                      priv->keymap_variants,
-                      priv->keymap_options,
-                      &rules_file_path,
-                      &xkb_var_defs);
-
-  xkb_rules = XkbRF_Load (rules_file_path, NULL, True, True);
-  if (xkb_rules)
-    {
-      XkbComponentNamesRec xkb_comp_names = { 0 };
-
-      XkbRF_GetComponents (xkb_rules, &xkb_var_defs, &xkb_comp_names);
-      upload_xkb_description (priv->xdisplay, rules_file_path, &xkb_var_defs, &xkb_comp_names);
-
-      free_xkb_component_names (&xkb_comp_names);
-      XkbRF_Free (xkb_rules, True);
-    }
-  else
-    {
-      g_warning ("Couldn't load XKB rules");
-    }
-
-  free_xkbrf_var_defs (&xkb_var_defs);
-  g_free (rules_file_path);
-}
-
-static void
-meta_backend_x11_set_keymap (MetaBackend *backend,
-                             const char  *layouts,
-                             const char  *variants,
-                             const char  *options)
-{
-  MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
-  MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
-
-  g_free (priv->keymap_layouts);
-  priv->keymap_layouts = g_strdup (layouts);
-  g_free (priv->keymap_variants);
-  priv->keymap_variants = g_strdup (variants);
-  g_free (priv->keymap_options);
-  priv->keymap_options = g_strdup (options);
-
-  apply_keymap (x11);
-}
-
 static struct xkb_keymap *
 meta_backend_x11_get_keymap (MetaBackend *backend)
 {
@@ -739,17 +562,6 @@ meta_backend_x11_get_keymap (MetaBackend *backend)
 }
 
 static void
-meta_backend_x11_lock_layout_group (MetaBackend *backend,
-                                    guint        idx)
-{
-  MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
-  MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
-
-  priv->locked_group = idx;
-  XkbLockGroup (priv->xdisplay, XkbUseCoreKbd, idx);
-}
-
-static void
 meta_backend_x11_set_numlock (MetaBackend *backend,
                               gboolean     numlock_state)
 {
@@ -765,6 +577,14 @@ meta_backend_x11_handle_event (MetaBackendX11 *x11,
   priv->cached_current_logical_monitor = NULL;
 }
 
+uint8_t
+meta_backend_x11_get_xkb_event_base (MetaBackendX11 *x11)
+{
+  MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
+
+  return priv->xkb_event_base;
+}
+
 static void
 meta_backend_x11_class_init (MetaBackendX11Class *klass)
 {
@@ -778,9 +598,7 @@ meta_backend_x11_class_init (MetaBackendX11Class *klass)
   backend_class->ungrab_device = meta_backend_x11_ungrab_device;
   backend_class->warp_pointer = meta_backend_x11_warp_pointer;
   backend_class->get_current_logical_monitor = meta_backend_x11_get_current_logical_monitor;
-  backend_class->set_keymap = meta_backend_x11_set_keymap;
   backend_class->get_keymap = meta_backend_x11_get_keymap;
-  backend_class->lock_layout_group = meta_backend_x11_lock_layout_group;
   backend_class->set_numlock = meta_backend_x11_set_numlock;
 }
 
diff --git a/src/backends/x11/meta-backend-x11.h b/src/backends/x11/meta-backend-x11.h
index 9c163eb..cfd5bd7 100644
--- a/src/backends/x11/meta-backend-x11.h
+++ b/src/backends/x11/meta-backend-x11.h
@@ -27,6 +27,7 @@
 
 #include "backends/meta-backend-private.h"
 
+#include <stdint.h>
 #include <X11/Xlib.h>
 
 #include "backends/x11/meta-clutter-backend-x11.h"
@@ -54,4 +55,6 @@ Window meta_backend_x11_get_xwindow (MetaBackendX11 *backend);
 void meta_backend_x11_handle_event (MetaBackendX11 *x11,
                                     XEvent         *xevent);
 
+uint8_t meta_backend_x11_get_xkb_event_base (MetaBackendX11 *x11);
+
 #endif /* META_BACKEND_X11_H */
diff --git a/src/backends/x11/nested/meta-backend-x11-nested.c 
b/src/backends/x11/nested/meta-backend-x11-nested.c
index cf9cea7..0225994 100644
--- a/src/backends/x11/nested/meta-backend-x11-nested.c
+++ b/src/backends/x11/nested/meta-backend-x11-nested.c
@@ -105,6 +105,20 @@ meta_backend_x11_nested_select_stage_events (MetaBackend *backend)
                xwa.your_event_mask | FocusChangeMask | KeymapStateMask);
 }
 
+static void
+meta_backend_x11_nested_lock_layout_group (MetaBackend *backend,
+                                           guint        idx)
+{
+}
+
+static void
+meta_backend_x11_nested_set_keymap (MetaBackend *backend,
+                                    const char  *layouts,
+                                    const char  *variants,
+                                    const char  *options)
+{
+}
+
 static gboolean
 meta_backend_x11_nested_handle_host_xevent (MetaBackendX11 *x11,
                                             XEvent         *event)
@@ -162,6 +176,8 @@ meta_backend_x11_nested_class_init (MetaBackendX11NestedClass *klass)
   backend_class->create_cursor_renderer = meta_backend_x11_nested_create_cursor_renderer;
   backend_class->update_screen_size = meta_backend_x11_nested_update_screen_size;
   backend_class->select_stage_events = meta_backend_x11_nested_select_stage_events;
+  backend_class->lock_layout_group = meta_backend_x11_nested_lock_layout_group;
+  backend_class->set_keymap = meta_backend_x11_nested_set_keymap;
 
   backend_x11_class->handle_host_xevent = meta_backend_x11_nested_handle_host_xevent;
   backend_x11_class->translate_device_event = meta_backend_x11_nested_translate_device_event;


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]