summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Thurman <thomas@thurman.org.uk>2006-04-17 17:23:09 +0000
committerThomas James Alexander Thurman <tthurman@src.gnome.org>2006-04-17 17:23:09 +0000
commitfee1fb094a3448f0c65a90c86f60786da7eac9c2 (patch)
tree4f201e9570d75fc93a3bc189f966d1df118019d6
parent83d21b97c48927ed25a935932f1fd075cc0249a5 (diff)
downloadmetacity-fee1fb094a3448f0c65a90c86f60786da7eac9c2.tar.gz
Allow any keybinding pref to be specified either with <foo>, a string, or
2004-04-17 Thomas Thurman <thomas@thurman.org.uk> * keybindings.c (count_bindings, rebuild_binding_table): * prefs.c (change_notify, screen_bindings, window_bindings, init_bindings, update_binding, find_and_update_list_binding, update_list_binding, meta_prefs_get_window_binding): Allow any keybinding pref to be specified either with <foo>, a string, or <foo>_list, a list of strings, or both. Fixes #164831.
-rw-r--r--ChangeLog10
-rw-r--r--src/keybindings.c64
-rw-r--r--src/prefs.c540
-rw-r--r--src/prefs.h16
4 files changed, 476 insertions, 154 deletions
diff --git a/ChangeLog b/ChangeLog
index b13b1673..1a483ad6 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+2004-04-17 Thomas Thurman <thomas@thurman.org.uk>
+
+ * keybindings.c (count_bindings, rebuild_binding_table):
+ * prefs.c (change_notify, screen_bindings,
+ window_bindings, init_bindings, update_binding,
+ find_and_update_list_binding, update_list_binding,
+ meta_prefs_get_window_binding): Allow any keybinding pref
+ to be specified either with <foo>, a string, or <foo>_list,
+ a list of strings, or both. Fixes #164831.
+
2006-04-16 Elijah Newren <newren gmail com>
Patch from Dan Sanders to fix #334899.
diff --git a/src/keybindings.c b/src/keybindings.c
index 201293a8..77dc78a9 100644
--- a/src/keybindings.c
+++ b/src/keybindings.c
@@ -639,13 +639,22 @@ count_bindings (const MetaKeyPref *prefs,
i = 0;
while (i < n_prefs)
{
- if (prefs[i].keysym != None)
+ GSList *tmp = prefs[i].bindings;
+
+ while (tmp)
{
- count += 1;
+ MetaKeyCombo *combo = tmp->data;
+
+ if (combo && combo->keysym != None)
+ {
+ count += 1;
+
+ if (prefs[i].add_shift &&
+ (combo->modifiers & META_VIRTUAL_SHIFT_MASK) == 0)
+ count += 1;
+ }
- if (prefs[i].add_shift &&
- (prefs[i].modifiers & META_VIRTUAL_SHIFT_MASK) == 0)
- count += 1;
+ tmp = tmp->next;
}
++i;
@@ -672,32 +681,41 @@ rebuild_binding_table (MetaDisplay *display,
dest = 0;
while (src < n_prefs)
{
- if (prefs[src].keysym != None)
+ GSList *tmp = prefs[src].bindings;
+
+ while (tmp)
{
- (*bindings_p)[dest].name = prefs[src].name;
- (*bindings_p)[dest].keysym = prefs[src].keysym;
- (*bindings_p)[dest].modifiers = prefs[src].modifiers;
- (*bindings_p)[dest].mask = 0;
- (*bindings_p)[dest].keycode = 0;
-
- ++dest;
+ MetaKeyCombo *combo = tmp->data;
- if (prefs[src].add_shift &&
- (prefs[src].modifiers & META_VIRTUAL_SHIFT_MASK) == 0)
+ if (combo && combo->keysym != None)
{
- meta_topic (META_DEBUG_KEYBINDINGS,
- "Binding %s also needs Shift grabbed\n",
- prefs[src].name);
-
(*bindings_p)[dest].name = prefs[src].name;
- (*bindings_p)[dest].keysym = prefs[src].keysym;
- (*bindings_p)[dest].modifiers = prefs[src].modifiers |
- META_VIRTUAL_SHIFT_MASK;
+ (*bindings_p)[dest].keysym = combo->keysym;
+ (*bindings_p)[dest].modifiers = combo->modifiers;
(*bindings_p)[dest].mask = 0;
(*bindings_p)[dest].keycode = 0;
-
+
++dest;
+
+ if (prefs[src].add_shift &&
+ (combo->modifiers & META_VIRTUAL_SHIFT_MASK) == 0)
+ {
+ meta_topic (META_DEBUG_KEYBINDINGS,
+ "Binding %s also needs Shift grabbed\n",
+ prefs[src].name);
+
+ (*bindings_p)[dest].name = prefs[src].name;
+ (*bindings_p)[dest].keysym = combo->keysym;
+ (*bindings_p)[dest].modifiers = combo->modifiers |
+ META_VIRTUAL_SHIFT_MASK;
+ (*bindings_p)[dest].mask = 0;
+ (*bindings_p)[dest].keycode = 0;
+
+ ++dest;
+ }
}
+
+ tmp = tmp->next;
}
++src;
diff --git a/src/prefs.c b/src/prefs.c
index 217f883f..6f5263cd 100644
--- a/src/prefs.c
+++ b/src/prefs.c
@@ -63,6 +63,7 @@
#define KEY_SCREEN_BINDINGS_PREFIX "/apps/metacity/global_keybindings"
#define KEY_WINDOW_BINDINGS_PREFIX "/apps/metacity/window_keybindings"
+#define KEY_LIST_BINDINGS_SUFFIX "_list"
#define KEY_WORKSPACE_NAME_PREFIX "/apps/metacity/workspace_names/name_"
@@ -146,6 +147,13 @@ static gboolean update_window_binding (const char *name,
const char *value);
static gboolean update_screen_binding (const char *name,
const char *value);
+static gboolean find_and_update_list_binding (MetaKeyPref *bindings,
+ const char *name,
+ GSList *value);
+static gboolean update_window_list_binding (const char *name,
+ GSList *value);
+static gboolean update_screen_list_binding (const char *name,
+ GSList *value);
static gboolean update_command (const char *name,
const char *value);
static gboolean update_terminal_command (const char *value);
@@ -169,6 +177,16 @@ static void queue_changed (MetaPreference pref);
static gboolean update_binding (MetaKeyPref *binding,
const char *value);
+typedef enum
+ {
+ META_LIST_OF_STRINGS,
+ META_LIST_OF_GCONFVALUE_STRINGS
+ } MetaStringListType;
+
+static gboolean update_list_binding (MetaKeyPref *binding,
+ GSList *value,
+ MetaStringListType type_of_value);
+
static void init_bindings (void);
static void init_commands (void);
static void init_workspace_names (void);
@@ -713,35 +731,73 @@ change_notify (GConfClient *client,
}
else if (g_str_has_prefix (key, KEY_WINDOW_BINDINGS_PREFIX))
{
- const char *str;
-
- if (value && value->type != GCONF_VALUE_STRING)
+ if (g_str_has_suffix (key, KEY_LIST_BINDINGS_SUFFIX))
{
- meta_warning (_("GConf key \"%s\" is set to an invalid type\n"),
- key);
- goto out;
+ GSList *list;
+
+ if (value && value->type != GCONF_VALUE_LIST)
+ {
+ meta_warning (_("GConf key \"%s\" is set to an invalid type\n"),
+ key);
+ goto out;
+ }
+
+ list = value ? gconf_value_get_list (value) : NULL;
+
+ if (update_window_list_binding (key, list))
+ queue_changed (META_PREF_WINDOW_KEYBINDINGS);
}
+ else
+ {
+ const char *str;
- str = value ? gconf_value_get_string (value) : NULL;
+ if (value && value->type != GCONF_VALUE_STRING)
+ {
+ meta_warning (_("GConf key \"%s\" is set to an invalid type\n"),
+ key);
+ goto out;
+ }
- if (update_window_binding (key, str))
- queue_changed (META_PREF_WINDOW_KEYBINDINGS);
+ str = value ? gconf_value_get_string (value) : NULL;
+
+ if (update_window_binding (key, str))
+ queue_changed (META_PREF_WINDOW_KEYBINDINGS);
+ }
}
else if (g_str_has_prefix (key, KEY_SCREEN_BINDINGS_PREFIX))
{
- const char *str;
+ if (g_str_has_suffix (key, KEY_LIST_BINDINGS_SUFFIX))
+ {
+ GSList *list;
- if (value && value->type != GCONF_VALUE_STRING)
+ if (value && value->type != GCONF_VALUE_LIST)
+ {
+ meta_warning (_("GConf key \"%s\" is set to an invalid type\n"),
+ key);
+ goto out;
+ }
+
+ list = value ? gconf_value_get_list (value) : NULL;
+
+ if (update_screen_list_binding (key, list))
+ queue_changed (META_PREF_SCREEN_KEYBINDINGS);
+ }
+ else
{
- meta_warning (_("GConf key \"%s\" is set to an invalid type\n"),
- key);
- goto out;
- }
+ const char *str;
- str = value ? gconf_value_get_string (value) : NULL;
+ if (value && value->type != GCONF_VALUE_STRING)
+ {
+ meta_warning (_("GConf key \"%s\" is set to an invalid type\n"),
+ key);
+ goto out;
+ }
+
+ str = value ? gconf_value_get_string (value) : NULL;
- if (update_screen_binding (key, str))
- queue_changed (META_PREF_SCREEN_KEYBINDINGS);
+ if (update_screen_binding (key, str))
+ queue_changed (META_PREF_SCREEN_KEYBINDINGS);
+ }
}
else if (strcmp (key, KEY_ACTION_DOUBLE_CLICK_TITLEBAR) == 0)
{
@@ -1737,110 +1793,110 @@ meta_prefs_set_num_workspaces (int n_workspaces)
/* Indexes must correspond to MetaKeybindingAction */
static MetaKeyPref screen_bindings[] = {
- { META_KEYBINDING_WORKSPACE_1, 0, 0, FALSE },
- { META_KEYBINDING_WORKSPACE_2, 0, 0, FALSE },
- { META_KEYBINDING_WORKSPACE_3, 0, 0, FALSE },
- { META_KEYBINDING_WORKSPACE_4, 0, 0, FALSE },
- { META_KEYBINDING_WORKSPACE_5, 0, 0, FALSE },
- { META_KEYBINDING_WORKSPACE_6, 0, 0, FALSE },
- { META_KEYBINDING_WORKSPACE_7, 0, 0, FALSE },
- { META_KEYBINDING_WORKSPACE_8, 0, 0, FALSE },
- { META_KEYBINDING_WORKSPACE_9, 0, 0, FALSE },
- { META_KEYBINDING_WORKSPACE_10, 0, 0, FALSE },
- { META_KEYBINDING_WORKSPACE_11, 0, 0, FALSE },
- { META_KEYBINDING_WORKSPACE_12, 0, 0, FALSE },
- { META_KEYBINDING_WORKSPACE_LEFT, 0, 0, FALSE },
- { META_KEYBINDING_WORKSPACE_RIGHT, 0, 0, FALSE },
- { META_KEYBINDING_WORKSPACE_UP, 0, 0, FALSE },
- { META_KEYBINDING_WORKSPACE_DOWN, 0, 0, FALSE },
- { META_KEYBINDING_SWITCH_GROUP, 0, 0, TRUE },
- { META_KEYBINDING_SWITCH_GROUP_BACKWARD, 0, 0, TRUE },
- { META_KEYBINDING_SWITCH_WINDOWS, 0, 0, TRUE },
- { META_KEYBINDING_SWITCH_WINDOWS_BACKWARD, 0, 0, TRUE },
- { META_KEYBINDING_SWITCH_PANELS, 0, 0, TRUE },
- { META_KEYBINDING_SWITCH_PANELS_BACKWARD, 0, 0, TRUE },
- { META_KEYBINDING_CYCLE_GROUP, 0, 0, TRUE },
- { META_KEYBINDING_CYCLE_GROUP_BACKWARD, 0, 0, TRUE },
- { META_KEYBINDING_CYCLE_WINDOWS, 0, 0, TRUE },
- { META_KEYBINDING_CYCLE_WINDOWS_BACKWARD, 0, 0, TRUE },
- { META_KEYBINDING_CYCLE_PANELS, 0, 0, TRUE },
- { META_KEYBINDING_CYCLE_PANELS_BACKWARD, 0, 0, TRUE },
- { META_KEYBINDING_SHOW_DESKTOP, 0, 0, FALSE },
- { META_KEYBINDING_PANEL_MAIN_MENU, 0, 0, FALSE },
- { META_KEYBINDING_PANEL_RUN_DIALOG, 0, 0, FALSE },
- { META_KEYBINDING_COMMAND_1, 0, 0, FALSE },
- { META_KEYBINDING_COMMAND_2, 0, 0, FALSE },
- { META_KEYBINDING_COMMAND_3, 0, 0, FALSE },
- { META_KEYBINDING_COMMAND_4, 0, 0, FALSE },
- { META_KEYBINDING_COMMAND_5, 0, 0, FALSE },
- { META_KEYBINDING_COMMAND_6, 0, 0, FALSE },
- { META_KEYBINDING_COMMAND_7, 0, 0, FALSE },
- { META_KEYBINDING_COMMAND_8, 0, 0, FALSE },
- { META_KEYBINDING_COMMAND_9, 0, 0, FALSE },
- { META_KEYBINDING_COMMAND_10, 0, 0, FALSE },
- { META_KEYBINDING_COMMAND_11, 0, 0, FALSE },
- { META_KEYBINDING_COMMAND_12, 0, 0, FALSE },
- { META_KEYBINDING_COMMAND_13, 0, 0, FALSE },
- { META_KEYBINDING_COMMAND_14, 0, 0, FALSE },
- { META_KEYBINDING_COMMAND_15, 0, 0, FALSE },
- { META_KEYBINDING_COMMAND_16, 0, 0, FALSE },
- { META_KEYBINDING_COMMAND_17, 0, 0, FALSE },
- { META_KEYBINDING_COMMAND_18, 0, 0, FALSE },
- { META_KEYBINDING_COMMAND_19, 0, 0, FALSE },
- { META_KEYBINDING_COMMAND_20, 0, 0, FALSE },
- { META_KEYBINDING_COMMAND_21, 0, 0, FALSE },
- { META_KEYBINDING_COMMAND_22, 0, 0, FALSE },
- { META_KEYBINDING_COMMAND_23, 0, 0, FALSE },
- { META_KEYBINDING_COMMAND_24, 0, 0, FALSE },
- { META_KEYBINDING_COMMAND_25, 0, 0, FALSE },
- { META_KEYBINDING_COMMAND_26, 0, 0, FALSE },
- { META_KEYBINDING_COMMAND_27, 0, 0, FALSE },
- { META_KEYBINDING_COMMAND_28, 0, 0, FALSE },
- { META_KEYBINDING_COMMAND_29, 0, 0, FALSE },
- { META_KEYBINDING_COMMAND_30, 0, 0, FALSE },
- { META_KEYBINDING_COMMAND_31, 0, 0, FALSE },
- { META_KEYBINDING_COMMAND_32, 0, 0, FALSE },
- { META_KEYBINDING_COMMAND_SCREENSHOT, 0, 0, FALSE },
- { META_KEYBINDING_COMMAND_WIN_SCREENSHOT, 0, 0, FALSE },
- { META_KEYBINDING_RUN_COMMAND_TERMINAL, 0, 0, FALSE },
- { NULL, 0, 0, FALSE}
+ { META_KEYBINDING_WORKSPACE_1, NULL, FALSE },
+ { META_KEYBINDING_WORKSPACE_2, NULL, FALSE },
+ { META_KEYBINDING_WORKSPACE_3, NULL, FALSE },
+ { META_KEYBINDING_WORKSPACE_4, NULL, FALSE },
+ { META_KEYBINDING_WORKSPACE_5, NULL, FALSE },
+ { META_KEYBINDING_WORKSPACE_6, NULL, FALSE },
+ { META_KEYBINDING_WORKSPACE_7, NULL, FALSE },
+ { META_KEYBINDING_WORKSPACE_8, NULL, FALSE },
+ { META_KEYBINDING_WORKSPACE_9, NULL, FALSE },
+ { META_KEYBINDING_WORKSPACE_10, NULL, FALSE },
+ { META_KEYBINDING_WORKSPACE_11, NULL, FALSE },
+ { META_KEYBINDING_WORKSPACE_12, NULL, FALSE },
+ { META_KEYBINDING_WORKSPACE_LEFT, NULL, FALSE },
+ { META_KEYBINDING_WORKSPACE_RIGHT, NULL, FALSE },
+ { META_KEYBINDING_WORKSPACE_UP, NULL, FALSE },
+ { META_KEYBINDING_WORKSPACE_DOWN, NULL, FALSE },
+ { META_KEYBINDING_SWITCH_GROUP, NULL, TRUE },
+ { META_KEYBINDING_SWITCH_GROUP_BACKWARD, NULL, TRUE },
+ { META_KEYBINDING_SWITCH_WINDOWS, NULL, TRUE },
+ { META_KEYBINDING_SWITCH_WINDOWS_BACKWARD, NULL, TRUE },
+ { META_KEYBINDING_SWITCH_PANELS, NULL, TRUE },
+ { META_KEYBINDING_SWITCH_PANELS_BACKWARD, NULL, TRUE },
+ { META_KEYBINDING_CYCLE_GROUP, NULL, TRUE },
+ { META_KEYBINDING_CYCLE_GROUP_BACKWARD, NULL, TRUE },
+ { META_KEYBINDING_CYCLE_WINDOWS, NULL, TRUE },
+ { META_KEYBINDING_CYCLE_WINDOWS_BACKWARD, NULL, TRUE },
+ { META_KEYBINDING_CYCLE_PANELS, NULL, TRUE },
+ { META_KEYBINDING_CYCLE_PANELS_BACKWARD, NULL, TRUE },
+ { META_KEYBINDING_SHOW_DESKTOP, NULL, FALSE },
+ { META_KEYBINDING_PANEL_MAIN_MENU, NULL, FALSE },
+ { META_KEYBINDING_PANEL_RUN_DIALOG, NULL, FALSE },
+ { META_KEYBINDING_COMMAND_1, NULL, FALSE },
+ { META_KEYBINDING_COMMAND_2, NULL, FALSE },
+ { META_KEYBINDING_COMMAND_3, NULL, FALSE },
+ { META_KEYBINDING_COMMAND_4, NULL, FALSE },
+ { META_KEYBINDING_COMMAND_5, NULL, FALSE },
+ { META_KEYBINDING_COMMAND_6, NULL, FALSE },
+ { META_KEYBINDING_COMMAND_7, NULL, FALSE },
+ { META_KEYBINDING_COMMAND_8, NULL, FALSE },
+ { META_KEYBINDING_COMMAND_9, NULL, FALSE },
+ { META_KEYBINDING_COMMAND_10, NULL, FALSE },
+ { META_KEYBINDING_COMMAND_11, NULL, FALSE },
+ { META_KEYBINDING_COMMAND_12, NULL, FALSE },
+ { META_KEYBINDING_COMMAND_13, NULL, FALSE },
+ { META_KEYBINDING_COMMAND_14, NULL, FALSE },
+ { META_KEYBINDING_COMMAND_15, NULL, FALSE },
+ { META_KEYBINDING_COMMAND_16, NULL, FALSE },
+ { META_KEYBINDING_COMMAND_17, NULL, FALSE },
+ { META_KEYBINDING_COMMAND_18, NULL, FALSE },
+ { META_KEYBINDING_COMMAND_19, NULL, FALSE },
+ { META_KEYBINDING_COMMAND_20, NULL, FALSE },
+ { META_KEYBINDING_COMMAND_21, NULL, FALSE },
+ { META_KEYBINDING_COMMAND_22, NULL, FALSE },
+ { META_KEYBINDING_COMMAND_23, NULL, FALSE },
+ { META_KEYBINDING_COMMAND_24, NULL, FALSE },
+ { META_KEYBINDING_COMMAND_25, NULL, FALSE },
+ { META_KEYBINDING_COMMAND_26, NULL, FALSE },
+ { META_KEYBINDING_COMMAND_27, NULL, FALSE },
+ { META_KEYBINDING_COMMAND_28, NULL, FALSE },
+ { META_KEYBINDING_COMMAND_29, NULL, FALSE },
+ { META_KEYBINDING_COMMAND_30, NULL, FALSE },
+ { META_KEYBINDING_COMMAND_31, NULL, FALSE },
+ { META_KEYBINDING_COMMAND_32, NULL, FALSE },
+ { META_KEYBINDING_COMMAND_SCREENSHOT, NULL, FALSE },
+ { META_KEYBINDING_COMMAND_WIN_SCREENSHOT, NULL, FALSE },
+ { META_KEYBINDING_RUN_COMMAND_TERMINAL, NULL, FALSE },
+ { NULL, NULL, FALSE}
};
static MetaKeyPref window_bindings[] = {
- { META_KEYBINDING_WINDOW_MENU, 0, 0, FALSE },
- { META_KEYBINDING_TOGGLE_FULLSCREEN, 0, 0, FALSE },
- { META_KEYBINDING_TOGGLE_MAXIMIZE, 0, 0, FALSE },
- { META_KEYBINDING_TOGGLE_ABOVE, 0, 0, FALSE },
- { META_KEYBINDING_MAXIMIZE, 0, 0, FALSE },
- { META_KEYBINDING_UNMAXIMIZE, 0, 0, FALSE },
- { META_KEYBINDING_TOGGLE_SHADE, 0, 0, FALSE },
- { META_KEYBINDING_MINIMIZE, 0, 0, FALSE },
- { META_KEYBINDING_CLOSE, 0, 0, FALSE },
- { META_KEYBINDING_BEGIN_MOVE, 0, 0, FALSE },
- { META_KEYBINDING_BEGIN_RESIZE, 0, 0, FALSE },
- { META_KEYBINDING_TOGGLE_STICKY, 0, 0, FALSE },
- { META_KEYBINDING_MOVE_WORKSPACE_1, 0, 0, FALSE },
- { META_KEYBINDING_MOVE_WORKSPACE_2, 0, 0, FALSE },
- { META_KEYBINDING_MOVE_WORKSPACE_3, 0, 0, FALSE },
- { META_KEYBINDING_MOVE_WORKSPACE_4, 0, 0, FALSE },
- { META_KEYBINDING_MOVE_WORKSPACE_5, 0, 0, FALSE },
- { META_KEYBINDING_MOVE_WORKSPACE_6, 0, 0, FALSE },
- { META_KEYBINDING_MOVE_WORKSPACE_7, 0, 0, FALSE },
- { META_KEYBINDING_MOVE_WORKSPACE_8, 0, 0, FALSE },
- { META_KEYBINDING_MOVE_WORKSPACE_9, 0, 0, FALSE },
- { META_KEYBINDING_MOVE_WORKSPACE_10, 0, 0, FALSE },
- { META_KEYBINDING_MOVE_WORKSPACE_11, 0, 0, FALSE },
- { META_KEYBINDING_MOVE_WORKSPACE_12, 0, 0, FALSE },
- { META_KEYBINDING_MOVE_WORKSPACE_LEFT, 0, 0, FALSE },
- { META_KEYBINDING_MOVE_WORKSPACE_RIGHT, 0, 0, FALSE },
- { META_KEYBINDING_MOVE_WORKSPACE_UP, 0, 0, FALSE },
- { META_KEYBINDING_MOVE_WORKSPACE_DOWN, 0, 0, FALSE },
- { META_KEYBINDING_RAISE_OR_LOWER, 0, 0, FALSE },
- { META_KEYBINDING_RAISE, 0, 0, FALSE },
- { META_KEYBINDING_LOWER, 0, 0, FALSE },
- { META_KEYBINDING_MAXIMIZE_VERTICALLY, 0, 0, FALSE },
- { META_KEYBINDING_MAXIMIZE_HORIZONTALLY, 0, 0, FALSE },
- { NULL, 0, 0, FALSE }
+ { META_KEYBINDING_WINDOW_MENU, NULL, FALSE },
+ { META_KEYBINDING_TOGGLE_FULLSCREEN, NULL, FALSE },
+ { META_KEYBINDING_TOGGLE_MAXIMIZE, NULL, FALSE },
+ { META_KEYBINDING_TOGGLE_ABOVE, NULL, FALSE },
+ { META_KEYBINDING_MAXIMIZE, NULL, FALSE },
+ { META_KEYBINDING_UNMAXIMIZE, NULL, FALSE },
+ { META_KEYBINDING_TOGGLE_SHADE, NULL, FALSE },
+ { META_KEYBINDING_MINIMIZE, NULL, FALSE },
+ { META_KEYBINDING_CLOSE, NULL, FALSE },
+ { META_KEYBINDING_BEGIN_MOVE, NULL, FALSE },
+ { META_KEYBINDING_BEGIN_RESIZE, NULL, FALSE },
+ { META_KEYBINDING_TOGGLE_STICKY, NULL, FALSE },
+ { META_KEYBINDING_MOVE_WORKSPACE_1, NULL, FALSE },
+ { META_KEYBINDING_MOVE_WORKSPACE_2, NULL, FALSE },
+ { META_KEYBINDING_MOVE_WORKSPACE_3, NULL, FALSE },
+ { META_KEYBINDING_MOVE_WORKSPACE_4, NULL, FALSE },
+ { META_KEYBINDING_MOVE_WORKSPACE_5, NULL, FALSE },
+ { META_KEYBINDING_MOVE_WORKSPACE_6, NULL, FALSE },
+ { META_KEYBINDING_MOVE_WORKSPACE_7, NULL, FALSE },
+ { META_KEYBINDING_MOVE_WORKSPACE_8, NULL, FALSE },
+ { META_KEYBINDING_MOVE_WORKSPACE_9, NULL, FALSE },
+ { META_KEYBINDING_MOVE_WORKSPACE_10, NULL, FALSE },
+ { META_KEYBINDING_MOVE_WORKSPACE_11, NULL, FALSE },
+ { META_KEYBINDING_MOVE_WORKSPACE_12, NULL, FALSE },
+ { META_KEYBINDING_MOVE_WORKSPACE_LEFT, NULL, FALSE },
+ { META_KEYBINDING_MOVE_WORKSPACE_RIGHT, NULL, FALSE },
+ { META_KEYBINDING_MOVE_WORKSPACE_UP, NULL, FALSE },
+ { META_KEYBINDING_MOVE_WORKSPACE_DOWN, NULL, FALSE },
+ { META_KEYBINDING_RAISE_OR_LOWER, NULL, FALSE },
+ { META_KEYBINDING_RAISE, NULL, FALSE },
+ { META_KEYBINDING_LOWER, NULL, FALSE },
+ { META_KEYBINDING_MAXIMIZE_VERTICALLY, NULL, FALSE },
+ { META_KEYBINDING_MAXIMIZE_HORIZONTALLY, NULL, FALSE },
+ { NULL, NULL, FALSE }
};
#ifndef HAVE_GCONF
@@ -1900,6 +1956,7 @@ init_bindings (void)
i = 0;
while (window_bindings[i].name)
{
+ GSList *list_val, *tmp;
char *str_val;
char *key;
@@ -1915,12 +1972,33 @@ init_bindings (void)
g_free (str_val);
g_free (key);
+ key = g_strconcat (KEY_WINDOW_BINDINGS_PREFIX, "/",
+ window_bindings[i].name,
+ KEY_LIST_BINDINGS_SUFFIX, NULL);
+
+ err = NULL;
+
+ list_val = gconf_client_get_list (default_client, key, GCONF_VALUE_STRING, &err);
+ cleanup_error (&err);
+
+ update_list_binding (&window_bindings[i], list_val, META_LIST_OF_STRINGS);
+
+ tmp = list_val;
+ while (tmp)
+ {
+ g_free (tmp->data);
+ tmp = tmp->next;
+ }
+ g_slist_free (list_val);
+ g_free (key);
+
++i;
}
i = 0;
while (screen_bindings[i].name)
{
+ GSList *list_val, *tmp;
char *str_val;
char *key;
@@ -1936,6 +2014,26 @@ init_bindings (void)
g_free (str_val);
g_free (key);
+ key = g_strconcat (KEY_SCREEN_BINDINGS_PREFIX, "/",
+ screen_bindings[i].name,
+ KEY_LIST_BINDINGS_SUFFIX, NULL);
+
+ err = NULL;
+
+ list_val = gconf_client_get_list (default_client, key, GCONF_VALUE_STRING, &err);
+ cleanup_error (&err);
+
+ update_list_binding (&screen_bindings[i], list_val, META_LIST_OF_STRINGS);
+
+ tmp = list_val;
+ while (tmp)
+ {
+ g_free (tmp->data);
+ tmp = tmp->next;
+ }
+ g_slist_free (list_val);
+ g_free (key);
+
++i;
}
#else /* HAVE_GCONF */
@@ -2054,6 +2152,7 @@ update_binding (MetaKeyPref *binding,
{
unsigned int keysym;
MetaVirtualModifier mods;
+ MetaKeyCombo *combo;
gboolean changed;
meta_topic (META_DEBUG_KEYBINDINGS,
@@ -2075,7 +2174,17 @@ update_binding (MetaKeyPref *binding,
}
}
- /* Bug 329676: Bindings which can be shifted must not have no modifiers,
+ /* If there isn't already a first element, make one. */
+ if (!binding->bindings)
+ {
+ MetaKeyCombo *blank = g_malloc0 (sizeof (MetaKeyCombo));
+ binding->bindings = g_slist_alloc();
+ binding->bindings->data = blank;
+ }
+
+ combo = binding->bindings->data;
+
+ /* Bug 329676: Bindings which can be shifted must not have no modifiers,
* nor only SHIFT as a modifier.
*/
@@ -2093,8 +2202,8 @@ update_binding (MetaKeyPref *binding,
value);
old_setting = meta_ui_accelerator_name(
- binding->keysym,
- binding->modifiers);
+ combo->keysym,
+ combo->modifiers);
if (!strcmp(old_setting, value))
{
@@ -2136,17 +2245,17 @@ update_binding (MetaKeyPref *binding,
}
changed = FALSE;
- if (keysym != binding->keysym ||
- mods != binding->modifiers)
+ if (keysym != combo->keysym ||
+ mods != combo->modifiers)
{
changed = TRUE;
- binding->keysym = keysym;
- binding->modifiers = mods;
+ combo->keysym = keysym;
+ combo->modifiers = mods;
meta_topic (META_DEBUG_KEYBINDINGS,
"New keybinding for \"%s\" is keysym = 0x%x mods = 0x%x\n",
- binding->name, binding->keysym, binding->modifiers);
+ binding->name, combo->keysym, combo->modifiers);
}
else
{
@@ -2157,6 +2266,115 @@ update_binding (MetaKeyPref *binding,
return changed;
}
+static gboolean
+update_list_binding (MetaKeyPref *binding,
+ GSList *value,
+ MetaStringListType type_of_value)
+{
+ unsigned int keysym;
+ MetaVirtualModifier mods;
+ gboolean changed = FALSE;
+ const gchar *pref_string;
+ GSList *pref_iterator = value, *tmp;
+ MetaKeyCombo *combo;
+
+ meta_topic (META_DEBUG_KEYBINDINGS,
+ "Binding \"%s\" has new gconf value\n",
+ binding->name);
+
+ if (binding->bindings == NULL)
+ {
+ /* We need to insert a dummy element into the list, because the first
+ * element is the one governed by update_binding. We only handle the
+ * subsequent elements.
+ */
+ MetaKeyCombo *blank = g_malloc0 (sizeof (MetaKeyCombo));
+ binding->bindings = g_slist_alloc();
+ binding->bindings->data = blank;
+ }
+
+ /* Okay, so, we're about to provide a new list of key combos for this
+ * action. Delete any pre-existing list.
+ */
+ tmp = binding->bindings->next;
+ while (tmp)
+ {
+ g_free (tmp->data);
+ tmp = tmp->next;
+ }
+ g_slist_free (binding->bindings->next);
+ binding->bindings->next = NULL;
+
+ while (pref_iterator)
+ {
+ keysym = 0;
+ mods = 0;
+
+ if (!pref_iterator->data)
+ {
+ pref_iterator = pref_iterator->next;
+ continue;
+ }
+
+ switch (type_of_value)
+ {
+ case META_LIST_OF_STRINGS:
+ pref_string = pref_iterator->data;
+ break;
+ case META_LIST_OF_GCONFVALUE_STRINGS:
+ pref_string = gconf_value_get_string (pref_iterator->data);
+ break;
+ default:
+ g_assert_not_reached ();
+ }
+
+ if (!meta_ui_parse_accelerator (pref_string, &keysym, &mods))
+ {
+ meta_topic (META_DEBUG_KEYBINDINGS,
+ "Failed to parse new gconf value\n");
+ meta_warning (_("\"%s\" found in configuration database is not a valid value for keybinding \"%s\"\n"),
+ pref_string, binding->name);
+
+ /* Should we remove this value from the list in gconf? */
+ pref_iterator = pref_iterator->next;
+ continue;
+ }
+
+ /* Bug 329676: Bindings which can be shifted must not have no modifiers,
+ * nor only SHIFT as a modifier.
+ */
+
+ if (binding->add_shift &&
+ 0 != keysym &&
+ (META_VIRTUAL_SHIFT_MASK == mods || 0 == mods))
+ {
+ meta_warning ("Cannot bind \"%s\" to %s: it needs a modifier "
+ "such as Ctrl or Alt.\n",
+ binding->name,
+ pref_string);
+
+ /* Should we remove this value from the list in gconf? */
+
+ pref_iterator = pref_iterator->next;
+ continue;
+ }
+
+ changed = TRUE;
+
+ combo = g_malloc0 (sizeof (MetaKeyCombo));
+ combo->keysym = keysym;
+ combo->modifiers = mods;
+ binding->bindings->next = g_slist_prepend (binding->bindings->next, combo);
+
+ meta_topic (META_DEBUG_KEYBINDINGS,
+ "New keybinding for \"%s\" is keysym = 0x%x mods = 0x%x\n",
+ binding->name, keysym, mods);
+
+ pref_iterator = pref_iterator->next;
+ }
+ return changed;
+}
+
#ifdef HAVE_GCONF
static const gchar*
relative_key (const gchar* key)
@@ -2212,6 +2430,50 @@ update_screen_binding (const char *name,
}
static gboolean
+find_and_update_list_binding (MetaKeyPref *bindings,
+ const char *name,
+ GSList *value)
+{
+ const char *key;
+ int i;
+ gchar *name_without_suffix = g_strdup(name);
+
+ name_without_suffix[strlen(name_without_suffix) - strlen(KEY_LIST_BINDINGS_SUFFIX)] = 0;
+
+ /* FIXME factor out dupld code */
+ if (*name_without_suffix == '/')
+ key = relative_key (name_without_suffix);
+ else
+ key = name_without_suffix;
+
+ i = 0;
+ while (bindings[i].name &&
+ strcmp (key, bindings[i].name) != 0)
+ ++i;
+
+ g_free (name_without_suffix);
+
+ if (bindings[i].name)
+ return update_list_binding (&bindings[i], value, META_LIST_OF_GCONFVALUE_STRINGS);
+ else
+ return FALSE;
+}
+
+static gboolean
+update_window_list_binding (const char *name,
+ GSList *value)
+{
+ return find_and_update_list_binding (window_bindings, name, value);
+}
+
+static gboolean
+update_screen_list_binding (const char *name,
+ GSList *value)
+{
+ return find_and_update_list_binding (screen_bindings, name, value);
+}
+
+static gboolean
update_command (const char *name,
const char *value)
{
@@ -2598,6 +2860,10 @@ meta_prefs_get_keybinding_action (const char *name)
return META_KEYBINDING_ACTION_NONE;
}
+/* This is used by the menu system to decide what key binding
+ * to display next to an option. We return the first non-disabled
+ * binding, if any.
+ */
void
meta_prefs_get_window_binding (const char *name,
unsigned int *keysym,
@@ -2610,8 +2876,24 @@ meta_prefs_get_window_binding (const char *name,
{
if (strcmp (window_bindings[i].name, name) == 0)
{
- *keysym = window_bindings[i].keysym;
- *modifiers = window_bindings[i].modifiers;
+ GSList *s = window_bindings[i].bindings;
+
+ while (s)
+ {
+ MetaKeyCombo *c = s->data;
+
+ if (c->keysym!=0 || c->modifiers!=0)
+ {
+ *keysym = c->keysym;
+ *modifiers = c->modifiers;
+ return;
+ }
+
+ s = s->next;
+ }
+
+ /* Not found; return the disabled value */
+ *keysym = *modifiers = 0;
return;
}
diff --git a/src/prefs.h b/src/prefs.h
index 8ae3e7ed..7f53a782 100644
--- a/src/prefs.h
+++ b/src/prefs.h
@@ -256,9 +256,21 @@ typedef enum _MetaKeyBindingAction
typedef struct
{
- const char *name;
- unsigned int keysym;
+ unsigned int keysym;
MetaVirtualModifier modifiers;
+} MetaKeyCombo;
+
+typedef struct
+{
+ const char *name;
+ /* a list of MetaKeyCombos. Each of them is bound to
+ * this keypref. If one has keysym==modifiers==0, it is
+ * ignored. For historical reasons, the first entry is
+ * governed by the pref FOO and the remainder are
+ * governed by the pref FOO_list.
+ */
+ GSList *bindings;
+
/* for keybindings that can have shift or not like Alt+Tab */
gboolean add_shift;
} MetaKeyPref;