From a01e8daa6dbefca3948d2a7be6358b41b58cb3f3 Mon Sep 17 00:00:00 2001 From: "Owen W. Taylor" Date: Thu, 3 Sep 2009 14:36:12 -0400 Subject: [PATCH] Allow a window manager to inherit keybindings from another window manager Mutter shares most (currently all) its keybindings with Metacity, and uses the same /apps/metacity GConf keys. For 2.28, the schemas stay in Metacity; the eventual plan is to have a gnome-wm-data package. This patch allows a window manager to put a _GNOME_WM_KEYBINDINGS property on its _NET_SUPPORTING_WM_CHECK window to provide a comma separated list of window manager names to use for keybinding lookup instead of _NET_WM_NAME. http://bugzilla.gnome.org/show_bug.cgi?id=594066 --- capplets/common/wm-common.c | 50 +++++++++++++++++-- capplets/common/wm-common.h | 4 ++ .../keybindings/gnome-keybinding-properties.c | 40 +++++++++++---- 3 files changed, 79 insertions(+), 15 deletions(-) diff --git a/capplets/common/wm-common.c b/capplets/common/wm-common.c index 61b1a4d1c..ef38489e9 100644 --- a/capplets/common/wm-common.c +++ b/capplets/common/wm-common.c @@ -15,10 +15,10 @@ typedef struct _WMCallbackData /* Our WM Window */ static Window wm_window = None; -char* -wm_common_get_current_window_manager (void) +static char * +wm_common_get_window_manager_property (Atom atom) { - Atom utf8_string, atom, type; + Atom utf8_string, type; int result; char *retval; int format; @@ -30,7 +30,6 @@ wm_common_get_current_window_manager (void) return g_strdup (WM_COMMON_UNKNOWN); utf8_string = XInternAtom (GDK_DISPLAY (), "UTF8_STRING", False); - atom = XInternAtom (GDK_DISPLAY (), "_NET_WM_NAME", False); gdk_error_trap_push (); @@ -60,6 +59,49 @@ wm_common_get_current_window_manager (void) return retval; } +char* +wm_common_get_current_window_manager (void) +{ + Atom atom = XInternAtom (GDK_DISPLAY (), "_NET_WM_NAME", False); + char *result; + + result = wm_common_get_window_manager_property (atom); + if (result) + return result; + else + return g_strdup (WM_COMMON_UNKNOWN); +} + +char** +wm_common_get_current_keybindings (void) +{ + Atom keybindings_atom = XInternAtom (GDK_DISPLAY (), "_GNOME_WM_KEYBINDINGS", False); + char *keybindings = wm_common_get_window_manager_property (keybindings_atom); + char **results; + + if (keybindings) + { + char **p; + results = g_strsplit(keybindings, ",", -1); + for (p = results; *p; p++) + g_strstrip (*p); + g_free (keybindings); + } + else + { + Atom wm_atom = XInternAtom (GDK_DISPLAY (), "_NET_WM_NAME", False); + char *wm_name = wm_common_get_window_manager_property (wm_atom); + char *to_copy[] = { NULL, NULL }; + + to_copy[0] = wm_name; + + results = g_strdupv (to_copy); + g_free (wm_name); + } + + return results; +} + static void update_wm_window (void) { diff --git a/capplets/common/wm-common.h b/capplets/common/wm-common.h index 08c7145d0..4da0d2821 100644 --- a/capplets/common/wm-common.h +++ b/capplets/common/wm-common.h @@ -6,6 +6,10 @@ #define WM_COMMON_UNKNOWN "Unknown" gchar *wm_common_get_current_window_manager (void); +/* Returns a strv of keybinding names for the window manager; + * using _GNOME_WM_KEYBINDINGS if available, _NET_WM_NAME otherwise. */ +char **wm_common_get_current_keybindings (void); + void wm_common_register_window_manager_change (GFunc func, gpointer data); diff --git a/capplets/keybindings/gnome-keybinding-properties.c b/capplets/keybindings/gnome-keybinding-properties.c index 53832980d..814bee267 100644 --- a/capplets/keybindings/gnome-keybinding-properties.c +++ b/capplets/keybindings/gnome-keybinding-properties.c @@ -816,10 +816,22 @@ parse_start_tag (GMarkupParseContext *ctx, g_array_append_val (keylist->entries, key); } +static gboolean +strv_contains (char **strv, + char *str) +{ + char **p = strv; + for (p = strv; *p; p++) + if (strcmp (*p, str) == 0) + return TRUE; + + return FALSE; +} + static void append_keys_to_tree_from_file (GtkBuilder *builder, const char *filename, - const char *wm_name) + char **wm_keybindings) { GMarkupParseContext *ctx; GMarkupParser parser = { parse_start_tag, NULL, NULL, NULL, NULL }; @@ -860,7 +872,7 @@ append_keys_to_tree_from_file (GtkBuilder *builder, /* If there's no keys to add, or the settings apply to a window manager * that's not the one we're running */ if (keylist->entries->len == 0 - || (keylist->wm_name != NULL && !g_str_equal (wm_name, keylist->wm_name)) + || (keylist->wm_name != NULL && strv_contains (wm_keybindings, keylist->wm_name)) || keylist->name == NULL) { g_free (keylist->name); @@ -951,12 +963,15 @@ append_keys_to_tree_from_gconf (GtkBuilder *builder, const gchar *gconf_path) } static void -reload_key_entries (gpointer wm_name, GtkBuilder *builder) +reload_key_entries (GtkBuilder *builder) { + gchar **wm_keybindings; GDir *dir; const char *name; GList *list, *l; + wm_keybindings = wm_common_get_current_keybindings(); + clear_old_model (builder); dir = g_dir_open (GNOMECC_KEYBINDINGS_DIR, 0, NULL); @@ -979,7 +994,7 @@ reload_key_entries (gpointer wm_name, GtkBuilder *builder) gchar *path; path = g_build_filename (GNOMECC_KEYBINDINGS_DIR, l->data, NULL); - append_keys_to_tree_from_file (builder, path, wm_name); + append_keys_to_tree_from_file (builder, path, wm_keybindings); g_free (l->data); g_free (path); } @@ -991,6 +1006,8 @@ reload_key_entries (gpointer wm_name, GtkBuilder *builder) * such keys not show up in the custom section. */ append_keys_to_tree_from_gconf (builder, GCONF_BINDING_DIR); + + g_strfreev (wm_keybindings); } static void @@ -999,9 +1016,7 @@ key_entry_controlling_key_changed (GConfClient *client, GConfEntry *entry, gpointer user_data) { - gchar *wm_name = wm_common_get_current_window_manager(); - reload_key_entries (wm_name, user_data); - g_free (wm_name); + reload_key_entries (user_data); } static gboolean @@ -1795,7 +1810,6 @@ setup_dialog (GtkBuilder *builder) GtkTreeViewColumn *column; GtkWidget *widget; GtkTreeView *treeview; - gchar *wm_name; GtkTreeSelection *selection; GSList *allowed_keys; @@ -1852,9 +1866,7 @@ setup_dialog (GtkBuilder *builder) builder, NULL, NULL); /* set up the dialog */ - wm_name = wm_common_get_current_window_manager(); reload_key_entries (wm_name, builder); - g_free (wm_name); widget = _gtk_builder_get_widget (builder, "gnome-keybinding-dialog"); capplet_set_icon (widget, "preferences-desktop-keyboard-shortcuts"); @@ -1895,6 +1907,12 @@ setup_dialog (GtkBuilder *builder) GTK_WINDOW (widget)); } +static void +on_window_manager_change (const char *wm_name, GtkBuilder *builder) +{ + reload_key_entries (builder); +} + int main (int argc, char *argv[]) { @@ -1916,7 +1934,7 @@ main (int argc, char *argv[]) if (!builder) /* Warning was already printed to console */ exit (EXIT_FAILURE); - wm_common_register_window_manager_change ((GFunc) reload_key_entries, builder); + wm_common_register_window_manager_change ((GFunc) on_window_manager_change, dialog); setup_dialog (builder); gtk_main ();