[mutter/wip/media-keys: 1/4] Keybindings: add a mechanism to grab a specific key combination



commit f505c59a9f4232a9faa0d71e5abf21df4a8bf406
Author: Giovanni Campagna <gcampagna src gnome org>
Date:   Fri Jun 22 23:38:43 2012 +0200

    Keybindings: add a mechanism to grab a specific key combination
    
    Instead of requiring a GSettings object, allow to hardcode a specific
    combination for a keybinding. This will be used by the Shell to
    replace the media keys plugin in gnome-settings-daemon.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=613543

 src/core/keybindings-private.h |    1 +
 src/core/keybindings.c         |   56 ++++++++++++++++++++++++++--
 src/core/prefs.c               |   79 ++++++++++++++++++++++++++++------------
 src/meta/display.h             |    9 +++++
 src/meta/prefs.h               |    8 ++++-
 5 files changed, 125 insertions(+), 28 deletions(-)
---
diff --git a/src/core/keybindings-private.h b/src/core/keybindings-private.h
index 7be9c24..b891d11 100644
--- a/src/core/keybindings-private.h
+++ b/src/core/keybindings-private.h
@@ -75,6 +75,7 @@ void     meta_display_process_mapping_event (MetaDisplay *display,
 
 gboolean meta_prefs_add_keybinding          (const char           *name,
                                              GSettings            *settings,
+                                             const char           *hardcoded_key,
                                              MetaKeyBindingAction  action,
                                              MetaKeyBindingFlags   flags);
 
diff --git a/src/core/keybindings.c b/src/core/keybindings.c
index 4892942..94f57ac 100644
--- a/src/core/keybindings.c
+++ b/src/core/keybindings.c
@@ -539,6 +539,7 @@ static gboolean
 add_keybinding_internal (MetaDisplay          *display,
                          const char           *name,
                          GSettings            *settings,
+                         const char           *hardcoded_key,
                          MetaKeyBindingFlags   flags,
                          MetaKeyBindingAction  action,
                          MetaKeyHandlerFunc    func,
@@ -548,7 +549,7 @@ add_keybinding_internal (MetaDisplay          *display,
 {
   MetaKeyHandler *handler;
 
-  if (!meta_prefs_add_keybinding (name, settings, action, flags))
+  if (!meta_prefs_add_keybinding (name, settings, hardcoded_key, action, flags))
     return FALSE;
 
   handler = g_new0 (MetaKeyHandler, 1);
@@ -574,7 +575,7 @@ add_builtin_keybinding (MetaDisplay          *display,
                         MetaKeyHandlerFunc    handler,
                         int                   handler_arg)
 {
-  return add_keybinding_internal (display, name, settings,
+  return add_keybinding_internal (display, name, settings, NULL,
                                   flags | META_KEY_BINDING_BUILTIN,
                                   action, handler, handler_arg, NULL, NULL);
 }
@@ -615,12 +616,59 @@ meta_display_add_keybinding (MetaDisplay         *display,
                              gpointer             user_data,
                              GDestroyNotify       free_data)
 {
-  return add_keybinding_internal (display, name, settings, flags,
-                                  META_KEYBINDING_ACTION_NONE,
+  return add_keybinding_internal (display, name, settings, NULL,
+                                  flags, META_KEYBINDING_ACTION_NONE,
                                   handler, 0, user_data, free_data);
 }
 
 /**
+ * meta_display_add_grabbed_key:
+ * @display: a #MetaDisplay
+ * @name: the binding's name
+ * @keyval: the key combination that should trigger this keybinding
+ * @flags: flags to specify binding details
+ * @handler: function to run when the keybinding is invoked
+ * @user_data: the data to pass to @handler
+ * @free_data: function to free @user_data
+ *
+ * This function is similar to meta_display_add_keybinding(), except
+ * that the keybinding is hardcoded to @keyval, which should be a GTK
+ * key string combination.
+ */
+gboolean
+meta_display_add_grabbed_key (MetaDisplay         *display,
+                              const char          *name,
+                              const char          *keyval,
+                              MetaKeyBindingFlags  flags,
+                              MetaKeyHandlerFunc   handler,
+                              gpointer             user_data,
+                              GDestroyNotify       free_data)
+{
+  return add_keybinding_internal (display, name, NULL, keyval,
+                                  flags, META_KEYBINDING_ACTION_NONE,
+                                  handler, 0, user_data, free_data);
+}
+
+/**
+ * meta_display_remove_grabbed_key:
+ * @display: the #MetaDisplay
+ * @name: the name that was passed to meta_display_add_grabbed_key()
+ *
+ * Undoes the effect of meta_display_add_grabbed_key()
+ */
+gboolean
+meta_display_remove_grabbed_key (MetaDisplay *display,
+                                 const char  *name)
+{
+  if (!meta_prefs_remove_keybinding (name))
+    return FALSE;
+
+  g_hash_table_remove (key_handlers, name);
+
+  return TRUE;
+}
+
+/**
  * meta_display_remove_keybinding:
  * @display: the #MetaDisplay
  * @name: name of the keybinding to remove
diff --git a/src/core/prefs.c b/src/core/prefs.c
index 802d620..c860407 100644
--- a/src/core/prefs.c
+++ b/src/core/prefs.c
@@ -110,13 +110,12 @@ static gboolean workspaces_only_on_primary = FALSE;
 
 static gboolean no_tab_popup = FALSE;
 
+static GHashTable *key_bindings;
 
 static void handle_preference_update_enum (GSettings *settings,
                                            gchar     *key);
 static gboolean update_binding         (MetaKeyPref *binding,
                                         gchar      **strokes);
-static gboolean update_key_binding     (const char  *key,
-                                        gchar      **strokes);
 static gboolean update_workspace_names (void);
 
 static void settings_changed (GSettings      *settings,
@@ -1052,13 +1051,30 @@ bindings_changed (GSettings *settings,
                   gchar *key,
                   gpointer data)
 {
+  gchar  *static_strokes[2];
   gchar **strokes;
-  strokes = g_settings_get_strv (settings, key);
+  MetaKeyPref *pref;
 
-  if (update_key_binding (key, strokes))
-    queue_changed (META_PREF_KEYBINDINGS);
+  pref = g_hash_table_lookup (key_bindings, key);
+  if (!pref)
+    return;
+
+  if (pref->is_single)
+    {
+      static_strokes[0] = g_settings_get_string (settings, key);
+      static_strokes[1] = NULL;
+      strokes = static_strokes;
+    }
+  else
+    strokes = g_settings_get_strv (settings, key);
 
-  g_strfreev (strokes);
+  update_binding (pref, strokes);
+  queue_changed (META_PREF_KEYBINDINGS);
+
+  if (strokes != static_strokes)
+    g_strfreev(strokes);
+  else
+    g_free(static_strokes[0]);
 }
 
 /**
@@ -1693,7 +1709,9 @@ meta_key_pref_free (MetaKeyPref *pref)
   update_binding (pref, NULL);
 
   g_free (pref->name);
-  g_object_unref (pref->settings);
+  if (pref->settings)
+    g_object_unref (pref->settings);
+  g_free (pref->hardcoded_key);
 
   g_free (pref);
 }
@@ -1786,18 +1804,6 @@ update_binding (MetaKeyPref *binding,
 }
 
 static gboolean
-update_key_binding (const char *key,
-                    gchar     **strokes)
-{
-  MetaKeyPref *pref = g_hash_table_lookup (key_bindings, key);
-
-  if (pref)
-    return update_binding (pref, strokes);
-  else
-    return FALSE;
-}
-
-static gboolean
 update_workspace_names (void)
 {
   int i;
@@ -1929,11 +1935,13 @@ meta_prefs_get_visual_bell_type (void)
 gboolean
 meta_prefs_add_keybinding (const char           *name,
                            GSettings            *settings,
+                           const char           *hardcoded_key,
                            MetaKeyBindingAction  action,
                            MetaKeyBindingFlags   flags)
 {
   MetaKeyPref  *pref;
   char        **strokes;
+  char         *static_strokes[2];
   guint         id;
 
   if (g_hash_table_lookup (key_bindings, name))
@@ -1944,19 +1952,44 @@ meta_prefs_add_keybinding (const char           *name,
 
   pref = g_new0 (MetaKeyPref, 1);
   pref->name = g_strdup (name);
-  pref->settings = g_object_ref (settings);
+  pref->settings = settings ? g_object_ref (settings) : NULL;
+  pref->hardcoded_key = g_strdup (hardcoded_key);
   pref->action = action;
   pref->bindings = NULL;
   pref->add_shift = (flags & META_KEY_BINDING_REVERSES) != 0;
   pref->per_window = (flags & META_KEY_BINDING_PER_WINDOW) != 0;
   pref->builtin = (flags & META_KEY_BINDING_BUILTIN) != 0;
+  pref->is_single = (flags & META_KEY_BINDING_IS_SINGLE) != 0;
 
-  strokes = g_settings_get_strv (settings, name);
-  update_binding (pref, strokes);
-  g_strfreev (strokes);
+  if (settings)
+    {
+      if (pref->is_single)
+        {
+          static_strokes[0] = g_settings_get_string (settings, name);
+          static_strokes[1] = NULL;
+          strokes = static_strokes;
+        }
+      else
+        strokes = g_settings_get_strv (settings, name);
+    }
+  else
+    {
+      static_strokes[0] = (char*)hardcoded_key;
+      static_strokes[1] = NULL;
+      strokes = static_strokes;
+    }
 
+  update_binding (pref, strokes);
   g_hash_table_insert (key_bindings, g_strdup (name), pref);
 
+  if (strokes != static_strokes)
+    g_strfreev (strokes);
+  else if (static_strokes[0] != hardcoded_key)
+    g_free (static_strokes[0]);
+
+  if (!settings)
+    return TRUE;
+
   if (pref->builtin)
     {
       if (g_object_get_data (G_OBJECT (settings), "changed-signal") == NULL)
diff --git a/src/meta/display.h b/src/meta/display.h
index 04d545c..7af830b 100644
--- a/src/meta/display.h
+++ b/src/meta/display.h
@@ -134,6 +134,15 @@ gboolean meta_display_add_keybinding    (MetaDisplay         *display,
                                          MetaKeyHandlerFunc   handler,
                                          gpointer             user_data,
                                          GDestroyNotify       free_data);
+gboolean meta_display_add_grabbed_key   (MetaDisplay         *display,
+                                         const char          *name,
+                                         const char          *keyval,
+                                         MetaKeyBindingFlags  flags,
+                                         MetaKeyHandlerFunc   handler,
+                                         gpointer             user_data,
+                                         GDestroyNotify       free_data);
+gboolean meta_display_remove_grabbed_key(MetaDisplay         *display,
+                                         const char          *name);
 gboolean meta_display_remove_keybinding (MetaDisplay         *display,
                                          const char          *name);
 
diff --git a/src/meta/prefs.h b/src/meta/prefs.h
index ff6984c..c63ab68 100644
--- a/src/meta/prefs.h
+++ b/src/meta/prefs.h
@@ -234,7 +234,8 @@ typedef enum
   META_KEY_BINDING_PER_WINDOW  = 1 << 0,
   META_KEY_BINDING_BUILTIN     = 1 << 1,
   META_KEY_BINDING_REVERSES    = 1 << 2,
-  META_KEY_BINDING_IS_REVERSED = 1 << 3
+  META_KEY_BINDING_IS_REVERSED = 1 << 3,
+  META_KEY_BINDING_IS_SINGLE   = 1 << 4,
 } MetaKeyBindingFlags;
 
 typedef struct
@@ -262,6 +263,7 @@ typedef struct
 {
   char *name;
   GSettings *settings;
+  char *hardcoded_key;
 
   MetaKeyBindingAction action;
 
@@ -280,6 +282,10 @@ typedef struct
 
   /** for keybindings not added with meta_display_add_keybinding() */
   gboolean      builtin:1;
+
+  /** for keybindings that are stored as a single value, not
+      as a list */
+  gboolean      is_single:1;
 } MetaKeyPref;
 
 GType meta_key_binding_get_type    (void);



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