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
This commit is contained in:
parent
1fce26d7e2
commit
a01e8daa6d
3 changed files with 79 additions and 15 deletions
|
@ -15,10 +15,10 @@ typedef struct _WMCallbackData
|
||||||
/* Our WM Window */
|
/* Our WM Window */
|
||||||
static Window wm_window = None;
|
static Window wm_window = None;
|
||||||
|
|
||||||
char*
|
static char *
|
||||||
wm_common_get_current_window_manager (void)
|
wm_common_get_window_manager_property (Atom atom)
|
||||||
{
|
{
|
||||||
Atom utf8_string, atom, type;
|
Atom utf8_string, type;
|
||||||
int result;
|
int result;
|
||||||
char *retval;
|
char *retval;
|
||||||
int format;
|
int format;
|
||||||
|
@ -30,7 +30,6 @@ wm_common_get_current_window_manager (void)
|
||||||
return g_strdup (WM_COMMON_UNKNOWN);
|
return g_strdup (WM_COMMON_UNKNOWN);
|
||||||
|
|
||||||
utf8_string = XInternAtom (GDK_DISPLAY (), "UTF8_STRING", False);
|
utf8_string = XInternAtom (GDK_DISPLAY (), "UTF8_STRING", False);
|
||||||
atom = XInternAtom (GDK_DISPLAY (), "_NET_WM_NAME", False);
|
|
||||||
|
|
||||||
gdk_error_trap_push ();
|
gdk_error_trap_push ();
|
||||||
|
|
||||||
|
@ -60,6 +59,49 @@ wm_common_get_current_window_manager (void)
|
||||||
return retval;
|
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
|
static void
|
||||||
update_wm_window (void)
|
update_wm_window (void)
|
||||||
{
|
{
|
||||||
|
|
|
@ -6,6 +6,10 @@
|
||||||
#define WM_COMMON_UNKNOWN "Unknown"
|
#define WM_COMMON_UNKNOWN "Unknown"
|
||||||
|
|
||||||
gchar *wm_common_get_current_window_manager (void);
|
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,
|
void wm_common_register_window_manager_change (GFunc func,
|
||||||
gpointer data);
|
gpointer data);
|
||||||
|
|
||||||
|
|
|
@ -816,10 +816,22 @@ parse_start_tag (GMarkupParseContext *ctx,
|
||||||
g_array_append_val (keylist->entries, key);
|
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
|
static void
|
||||||
append_keys_to_tree_from_file (GtkBuilder *builder,
|
append_keys_to_tree_from_file (GtkBuilder *builder,
|
||||||
const char *filename,
|
const char *filename,
|
||||||
const char *wm_name)
|
char **wm_keybindings)
|
||||||
{
|
{
|
||||||
GMarkupParseContext *ctx;
|
GMarkupParseContext *ctx;
|
||||||
GMarkupParser parser = { parse_start_tag, NULL, NULL, NULL, NULL };
|
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
|
/* If there's no keys to add, or the settings apply to a window manager
|
||||||
* that's not the one we're running */
|
* that's not the one we're running */
|
||||||
if (keylist->entries->len == 0
|
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)
|
|| keylist->name == NULL)
|
||||||
{
|
{
|
||||||
g_free (keylist->name);
|
g_free (keylist->name);
|
||||||
|
@ -951,12 +963,15 @@ append_keys_to_tree_from_gconf (GtkBuilder *builder, const gchar *gconf_path)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
reload_key_entries (gpointer wm_name, GtkBuilder *builder)
|
reload_key_entries (GtkBuilder *builder)
|
||||||
{
|
{
|
||||||
|
gchar **wm_keybindings;
|
||||||
GDir *dir;
|
GDir *dir;
|
||||||
const char *name;
|
const char *name;
|
||||||
GList *list, *l;
|
GList *list, *l;
|
||||||
|
|
||||||
|
wm_keybindings = wm_common_get_current_keybindings();
|
||||||
|
|
||||||
clear_old_model (builder);
|
clear_old_model (builder);
|
||||||
|
|
||||||
dir = g_dir_open (GNOMECC_KEYBINDINGS_DIR, 0, NULL);
|
dir = g_dir_open (GNOMECC_KEYBINDINGS_DIR, 0, NULL);
|
||||||
|
@ -979,7 +994,7 @@ reload_key_entries (gpointer wm_name, GtkBuilder *builder)
|
||||||
gchar *path;
|
gchar *path;
|
||||||
|
|
||||||
path = g_build_filename (GNOMECC_KEYBINDINGS_DIR, l->data, NULL);
|
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 (l->data);
|
||||||
g_free (path);
|
g_free (path);
|
||||||
}
|
}
|
||||||
|
@ -991,6 +1006,8 @@ reload_key_entries (gpointer wm_name, GtkBuilder *builder)
|
||||||
* such keys not show up in the custom section.
|
* such keys not show up in the custom section.
|
||||||
*/
|
*/
|
||||||
append_keys_to_tree_from_gconf (builder, GCONF_BINDING_DIR);
|
append_keys_to_tree_from_gconf (builder, GCONF_BINDING_DIR);
|
||||||
|
|
||||||
|
g_strfreev (wm_keybindings);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -999,9 +1016,7 @@ key_entry_controlling_key_changed (GConfClient *client,
|
||||||
GConfEntry *entry,
|
GConfEntry *entry,
|
||||||
gpointer user_data)
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
gchar *wm_name = wm_common_get_current_window_manager();
|
reload_key_entries (user_data);
|
||||||
reload_key_entries (wm_name, user_data);
|
|
||||||
g_free (wm_name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
|
@ -1795,7 +1810,6 @@ setup_dialog (GtkBuilder *builder)
|
||||||
GtkTreeViewColumn *column;
|
GtkTreeViewColumn *column;
|
||||||
GtkWidget *widget;
|
GtkWidget *widget;
|
||||||
GtkTreeView *treeview;
|
GtkTreeView *treeview;
|
||||||
gchar *wm_name;
|
|
||||||
GtkTreeSelection *selection;
|
GtkTreeSelection *selection;
|
||||||
GSList *allowed_keys;
|
GSList *allowed_keys;
|
||||||
|
|
||||||
|
@ -1852,9 +1866,7 @@ setup_dialog (GtkBuilder *builder)
|
||||||
builder, NULL, NULL);
|
builder, NULL, NULL);
|
||||||
|
|
||||||
/* set up the dialog */
|
/* set up the dialog */
|
||||||
wm_name = wm_common_get_current_window_manager();
|
|
||||||
reload_key_entries (wm_name, builder);
|
reload_key_entries (wm_name, builder);
|
||||||
g_free (wm_name);
|
|
||||||
|
|
||||||
widget = _gtk_builder_get_widget (builder, "gnome-keybinding-dialog");
|
widget = _gtk_builder_get_widget (builder, "gnome-keybinding-dialog");
|
||||||
capplet_set_icon (widget, "preferences-desktop-keyboard-shortcuts");
|
capplet_set_icon (widget, "preferences-desktop-keyboard-shortcuts");
|
||||||
|
@ -1895,6 +1907,12 @@ setup_dialog (GtkBuilder *builder)
|
||||||
GTK_WINDOW (widget));
|
GTK_WINDOW (widget));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_window_manager_change (const char *wm_name, GtkBuilder *builder)
|
||||||
|
{
|
||||||
|
reload_key_entries (builder);
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
main (int argc, char *argv[])
|
main (int argc, char *argv[])
|
||||||
{
|
{
|
||||||
|
@ -1916,7 +1934,7 @@ main (int argc, char *argv[])
|
||||||
if (!builder) /* Warning was already printed to console */
|
if (!builder) /* Warning was already printed to console */
|
||||||
exit (EXIT_FAILURE);
|
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);
|
setup_dialog (builder);
|
||||||
|
|
||||||
gtk_main ();
|
gtk_main ();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue