[mutter] keybindings: Add external grab API
- From: Florian Müllner <fmuellner src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [mutter] keybindings: Add external grab API
- Date: Fri, 1 Mar 2013 15:50:24 +0000 (UTC)
commit a39cabfadb1d160b284ca3a17fdbf4f9e7c6d42c
Author: Florian Müllner <fmuellner gnome org>
Date: Tue Aug 28 15:28:11 2012 +0200
keybindings: Add external grab API
During compositor grabs, all global keybindings that don't go
through mutter's keybinding system are blocked. To allow other
processes to make use of it, gnome-shell will expose a simple
grab API on DBus; for this, add API to grab key combos directly
instead of parsing accelerators stored in GSettings.
https://bugzilla.gnome.org/show_bug.cgi?id=643111
src/core/display-private.h | 3 +
src/core/display.c | 18 ++++
src/core/keybindings.c | 196 ++++++++++++++++++++++++++++++++++++++++++--
src/core/util.c | 6 ++
src/meta/display.h | 5 +
src/meta/util.h | 2 +
6 files changed, 223 insertions(+), 7 deletions(-)
---
diff --git a/src/core/display-private.h b/src/core/display-private.h
index c4abbfa..c30d312 100644
--- a/src/core/display-private.h
+++ b/src/core/display-private.h
@@ -460,6 +460,9 @@ void meta_display_queue_autoraise_callback (MetaDisplay *display,
void meta_display_remove_autoraise_callback (MetaDisplay *display);
void meta_display_overlay_key_activate (MetaDisplay *display);
+void meta_display_accelerator_activate (MetaDisplay *display,
+ guint action,
+ guint deviceid);
/* In above-tab-keycode.c */
guint meta_display_get_above_tab_keycode (MetaDisplay *display);
diff --git a/src/core/display.c b/src/core/display.c
index b1e6543..e3bf5f6 100644
--- a/src/core/display.c
+++ b/src/core/display.c
@@ -138,6 +138,7 @@ G_DEFINE_TYPE(MetaDisplay, meta_display, G_TYPE_OBJECT);
enum
{
OVERLAY_KEY,
+ ACCELERATOR_ACTIVATED,
FOCUS_WINDOW,
WINDOW_CREATED,
WINDOW_DEMANDS_ATTENTION,
@@ -246,6 +247,14 @@ meta_display_class_init (MetaDisplayClass *klass)
NULL, NULL, NULL,
G_TYPE_NONE, 0);
+ display_signals[ACCELERATOR_ACTIVATED] =
+ g_signal_new ("accelerator-activated",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ 0,
+ NULL, NULL, NULL,
+ G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_UINT);
+
display_signals[WINDOW_CREATED] =
g_signal_new ("window-created",
G_TYPE_FROM_CLASS (klass),
@@ -5663,6 +5672,15 @@ meta_display_overlay_key_activate (MetaDisplay *display)
}
void
+meta_display_accelerator_activate (MetaDisplay *display,
+ guint action,
+ guint deviceid)
+{
+ g_signal_emit (display, display_signals[ACCELERATOR_ACTIVATED],
+ 0, action, deviceid);
+}
+
+void
meta_display_get_compositor_version (MetaDisplay *display,
int *major,
int *minor)
diff --git a/src/core/keybindings.c b/src/core/keybindings.c
index 7f6be7e..b3bb1ce 100644
--- a/src/core/keybindings.c
+++ b/src/core/keybindings.c
@@ -145,6 +145,7 @@ static void regrab_key_bindings (MetaDisplay *display);
static GHashTable *key_handlers;
+static GHashTable *external_grabs;
#define HANDLER(name) g_hash_table_lookup (key_handlers, (name))
@@ -157,6 +158,22 @@ key_handler_free (MetaKeyHandler *handler)
g_free (handler);
}
+typedef struct _MetaKeyGrab MetaKeyGrab;
+struct _MetaKeyGrab {
+ char *name;
+ guint action;
+ MetaKeyCombo *combo;
+};
+
+static void
+meta_key_grab_free (MetaKeyGrab *grab)
+{
+ g_free (grab->name);
+ g_free (grab->combo);
+ g_free (grab);
+}
+
+
static void
reload_keymap (MetaDisplay *display)
{
@@ -390,13 +407,14 @@ static void
rebuild_binding_table (MetaDisplay *display,
MetaKeyBinding **bindings_p,
int *n_bindings_p,
- GList *prefs)
+ GList *prefs,
+ GList *grabs)
{
- GList *p;
+ GList *p, *g;
int n_bindings;
int i;
- n_bindings = count_bindings (prefs);
+ n_bindings = count_bindings (prefs) + g_list_length (grabs);
g_free (*bindings_p);
*bindings_p = g_new0 (MetaKeyBinding, n_bindings);
@@ -449,6 +467,27 @@ rebuild_binding_table (MetaDisplay *display,
p = p->next;
}
+ g = grabs;
+ while (g)
+ {
+ MetaKeyGrab *grab = (MetaKeyGrab*)g->data;
+ if (grab->combo && (grab->combo->keysym != None || grab->combo->keycode != 0))
+ {
+ MetaKeyHandler *handler = HANDLER ("external-grab");
+
+ (*bindings_p)[i].name = grab->name;
+ (*bindings_p)[i].handler = handler;
+ (*bindings_p)[i].keysym = grab->combo->keysym;
+ (*bindings_p)[i].keycode = grab->combo->keycode;
+ (*bindings_p)[i].modifiers = grab->combo->modifiers;
+ (*bindings_p)[i].mask = 0;
+
+ ++i;
+ }
+
+ g = g->next;
+ }
+
g_assert (i == n_bindings);
*n_bindings_p = i;
@@ -461,17 +500,19 @@ rebuild_binding_table (MetaDisplay *display,
static void
rebuild_key_binding_table (MetaDisplay *display)
{
- GList *prefs;
+ GList *prefs, *grabs;
meta_topic (META_DEBUG_KEYBINDINGS,
"Rebuilding key binding table from preferences\n");
prefs = meta_prefs_get_keybindings ();
+ grabs = g_hash_table_get_values (external_grabs);
rebuild_binding_table (display,
&display->key_bindings,
&display->n_key_bindings,
- prefs);
+ prefs, grabs);
g_list_free (prefs);
+ g_list_free (grabs);
}
static void
@@ -699,9 +740,17 @@ meta_display_get_keybinding_action (MetaDisplay *display,
binding = display_get_keybinding (display, META_KEY_ABOVE_TAB, keycode, mask);
if (binding)
- return (guint) meta_prefs_get_keybinding_action (binding->name);
+ {
+ MetaKeyGrab *grab = g_hash_table_lookup (external_grabs, binding->name);
+ if (grab)
+ return grab->action;
+ else
+ return (guint) meta_prefs_get_keybinding_action (binding->name);
+ }
else
- return META_KEYBINDING_ACTION_NONE;
+ {
+ return META_KEYBINDING_ACTION_NONE;
+ }
}
void
@@ -1046,6 +1095,128 @@ meta_window_ungrab_keys (MetaWindow *window)
}
}
+static void
+handle_external_grab (MetaDisplay *display,
+ MetaScreen *screen,
+ MetaWindow *window,
+ XIDeviceEvent *event,
+ MetaKeyBinding *binding,
+ gpointer user_data)
+{
+ guint action = meta_display_get_keybinding_action (display,
+ binding->keycode,
+ binding->mask);
+ meta_display_accelerator_activate (display, action, event->deviceid);
+}
+
+
+guint
+meta_display_grab_accelerator (MetaDisplay *display,
+ const char *accelerator)
+{
+ MetaKeyGrab *grab;
+ guint keysym = 0;
+ guint keycode = 0;
+ guint mask = 0;
+ MetaVirtualModifier modifiers = 0;
+ GSList *l;
+ int i;
+
+ if (!meta_ui_parse_accelerator (accelerator, &keysym, &keycode, &modifiers))
+ {
+ meta_topic (META_DEBUG_KEYBINDINGS,
+ "Failed to parse accelerator\n");
+ meta_warning (_("\"%s\" is not a valid accelerator\n"), accelerator);
+
+ return META_KEYBINDING_ACTION_NONE;
+ }
+
+ meta_display_devirtualize_modifiers (display, modifiers, &mask);
+ keycode = keysym_to_keycode (display, keysym);
+
+ if (keycode == 0)
+ return META_KEYBINDING_ACTION_NONE;
+
+ for (i = 0; i < display->n_key_bindings; i++)
+ if (display->key_bindings[i].keycode == keycode &&
+ display->key_bindings[i].mask == mask)
+ return META_KEYBINDING_ACTION_NONE;
+
+ for (l = display->screens; l; l = l->next)
+ {
+ MetaScreen *screen = l->data;
+ meta_grab_key (display, screen->xroot, keysym, keycode, mask);
+ }
+
+ grab = g_new0 (MetaKeyGrab, 1);
+ grab->action = next_dynamic_keybinding_action ();
+ grab->name = meta_external_binding_name_for_action (grab->action);
+ grab->combo = g_malloc0 (sizeof (MetaKeyCombo));
+ grab->combo->keysym = keysym;
+ grab->combo->keycode = keycode;
+ grab->combo->modifiers = modifiers;
+
+ g_hash_table_insert (external_grabs, grab->name, grab);
+
+ display->n_key_bindings++;
+ display->key_bindings = g_renew (MetaKeyBinding,
+ display->key_bindings,
+ display->n_key_bindings);
+
+ MetaKeyBinding *binding = &display->key_bindings[display->n_key_bindings - 1];
+ binding->name = grab->name;
+ binding->handler = HANDLER ("external-grab");
+ binding->keysym = grab->combo->keysym;
+ binding->keycode = grab->combo->keycode;
+ binding->modifiers = grab->combo->modifiers;
+ binding->mask = mask;
+
+ return grab->action;
+}
+
+gboolean
+meta_display_ungrab_accelerator (MetaDisplay *display,
+ guint action)
+{
+ MetaKeyGrab *grab;
+ char *key;
+ int i;
+
+ g_return_val_if_fail (action != META_KEYBINDING_ACTION_NONE, FALSE);
+
+ key = meta_external_binding_name_for_action (action);
+ grab = g_hash_table_lookup (external_grabs, key);
+ if (!grab)
+ return FALSE;
+
+ for (i = 0; i < display->n_key_bindings; i++)
+ if (display->key_bindings[i].keysym == grab->combo->keysym &&
+ display->key_bindings[i].keycode == grab->combo->keycode &&
+ display->key_bindings[i].modifiers == grab->combo->modifiers)
+ {
+ GSList *l;
+ for (l = display->screens; l; l = l->next)
+ {
+ MetaScreen *screen = l->data;
+ meta_change_keygrab (display, screen->xroot, FALSE,
+ display->key_bindings[i].keysym,
+ display->key_bindings[i].keycode,
+ display->key_bindings[i].mask);
+ }
+
+ display->key_bindings[i].keysym = 0;
+ display->key_bindings[i].keycode = 0;
+ display->key_bindings[i].modifiers = 0;
+ display->key_bindings[i].mask = 0;
+ break;
+ }
+
+ g_hash_table_remove (external_grabs, key);
+ g_free (key);
+
+ return TRUE;
+}
+
#ifdef WITH_VERBOSE_MODE
static const char*
grab_status_to_string (int status)
@@ -4335,6 +4506,17 @@ meta_display_init_keys (MetaDisplay *display)
g_hash_table_insert (key_handlers, g_strdup ("overlay-key"), handler);
+ handler = g_new0 (MetaKeyHandler, 1);
+ handler->name = g_strdup ("external-grab");
+ handler->func = handle_external_grab;
+ handler->default_func = handle_external_grab;
+
+ g_hash_table_insert (key_handlers, g_strdup ("external-grab"), handler);
+
+ external_grabs = g_hash_table_new_full (g_str_hash, g_str_equal,
+ NULL,
+ (GDestroyNotify)meta_key_grab_free);
+
init_builtin_key_bindings (display);
rebuild_key_binding_table (display);
diff --git a/src/core/util.c b/src/core/util.c
index 0ab87bb..a8da0d2 100644
--- a/src/core/util.c
+++ b/src/core/util.c
@@ -555,6 +555,12 @@ meta_gravity_to_string (int gravity)
}
}
+char*
+meta_external_binding_name_for_action (guint keybinding_action)
+{
+ return g_strdup_printf ("external-grab-%u", keybinding_action);
+}
+
static gboolean
zenity_supports_option (const char *section, const char *option)
{
diff --git a/src/meta/display.h b/src/meta/display.h
index b922b48..9ac8d20 100644
--- a/src/meta/display.h
+++ b/src/meta/display.h
@@ -139,6 +139,11 @@ guint meta_display_add_keybinding (MetaDisplay *display,
gboolean meta_display_remove_keybinding (MetaDisplay *display,
const char *name);
+guint meta_display_grab_accelerator (MetaDisplay *display,
+ const char *accelerator);
+gboolean meta_display_ungrab_accelerator (MetaDisplay *display,
+ guint action_id);
+
guint meta_display_get_keybinding_action (MetaDisplay *display,
unsigned int keycode,
unsigned long mask);
diff --git a/src/meta/util.h b/src/meta/util.h
index 04bb7bf..b34d935 100644
--- a/src/meta/util.h
+++ b/src/meta/util.h
@@ -93,6 +93,8 @@ guint meta_unsigned_long_hash (gconstpointer v);
const char* meta_frame_type_to_string (MetaFrameType type);
const char* meta_gravity_to_string (int gravity);
+char* meta_external_binding_name_for_action (guint keybinding_action);
+
#include <libintl.h>
#define _(x) dgettext (GETTEXT_PACKAGE, x)
#define N_(x) x
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]