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
This commit is contained in:
Giovanni Campagna 2012-06-22 23:38:43 +02:00
parent e46cf80fdd
commit f505c59a9f
5 changed files with 125 additions and 28 deletions

View File

@ -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);

View File

@ -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,11 +616,58 @@ 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

View File

@ -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;
g_strfreev (strokes);
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);
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);
}
@ -1785,18 +1803,6 @@ update_binding (MetaKeyPref *binding,
return changed;
}
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)
{
@ -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;
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;
}
strokes = g_settings_get_strv (settings, name);
update_binding (pref, strokes);
g_strfreev (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)

View File

@ -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);

View File

@ -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);