[gnome-terminal] keybindings: Port to gsettings



commit b8171022016d40618a3ff291258053608c850257
Author: Christian Persch <chpe gnome org>
Date:   Mon Jan 14 17:47:32 2013 +0100

    keybindings: Port to gsettings
    
    Redo the gconf->gsettings port of the keybindings part. Use gsettings
    for the keybindings instead of the simple accel map file.

 src/migration.c                       |  111 +++---
 src/org.gnome.Terminal.gschema.xml.in |  143 +++++++-
 src/terminal-accels.c                 |  670 ++++++++++++++++++++++++---------
 src/terminal-schemas.h                |    1 +
 4 files changed, 683 insertions(+), 242 deletions(-)
---
diff --git a/src/migration.c b/src/migration.c
index 6760688..bb02039 100644
--- a/src/migration.c
+++ b/src/migration.c
@@ -1,5 +1,5 @@
 /*
- * Copyright  2011 Christian Persch
+ * Copyright  2011, 2012, 2013 Christian Persch
  *
  * Gnome-terminal is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -508,80 +508,65 @@ migrate_profiles (GSettings *global_settings,
 static gboolean
 migrate_accels (GError **error)
 {
-  static const struct { const char *key; const char *path; } data[] = {
-    { "new_tab", "FileNewTab" },
-    { "new_window", "FileNewWindow" },
-    { "new_profile", "FileNewProfile" },
-    { "close_tab", "FileCloseTab" },
-    { "close_window", "FileCloseWindow"},
-    { "copy", "EditCopy" },
-    { "paste", "EditPaste" },
-    { "toggle_menubar", "ViewMenubar" },
-    { "full_screen", "ViewFullscreen" },
-    { "zoom_in", "ViewZoomIn" },
-    { "zoom_out", "ViewZoomOut" },
-    { "zoom_normal", "ViewZoom100" },
-    { "set_window_title", "TerminalSetTitle" },
-    { "reset", "TerminalReset" },
-    { "reset_and_clear", "TerminalResetClear" },
-    { "prev_tab", "TabsPrevious" },
-    { "next_tab", "TabsNext" },
-    { "move_tab_left", "TabsMoveLeft" },
-    { "move_tab_right", "TabsMoveRight" },
-    { "detach_tab", "TabsDetach" },
-    { "switch_to_tab_1", "TabsSwitch1" },
-    { "switch_to_tab_2", "TabsSwitch2" },
-    { "switch_to_tab_3", "TabsSwitch3" },
-    { "switch_to_tab_4", "TabsSwitch4" },
-    { "switch_to_tab_5", "TabsSwitch5" },
-    { "switch_to_tab_6", "TabsSwitch6" },
-    { "switch_to_tab_7", "TabsSwitch7" },
-    { "switch_to_tab_8", "TabsSwitch8" },
-    { "switch_to_tab_9", "TabsSwitch9" },
-    { "switch_to_tab_10", "TabsSwitch10" },
-    { "switch_to_tab_11", "TabsSwitch11" },
-    { "switch_to_tab_12", "TabsSwitch12" },
-    { "help", "HelpContents" }
+  static const const struct { const char *gconf_key; const char *settings_key; } const data[] = {
+    { "new_tab",          "new-tab"            },
+    { "new_window",       "new-window"         },
+    { "new_profile",      "new-profile"        },
+    { "close_tab",        "close-tab"          },
+    { "close_window",     "close-window"       },
+    { "copy",             "copy"               },
+    { "paste",            "paste"              },
+    { "toggle_menubar",   "toggle-menubar"     },
+    { "full_screen",      "full-screen"        },
+    { "zoom_in",          "zoom-in"            },
+    { "zoom_out",         "zoom-out"           },
+    { "zoom_normal",      "zoom-normal"        },
+    { "set_window_title", "set-terminal-title" },
+    { "reset",            "reset"              },
+    { "reset_and_clear",  "reset-and-clear"    },
+    { "prev_tab",         "prev-tab"           },
+    { "next_tab",         "next-tab"           },
+    { "move_tab_left",    "move-tab-left"      },
+    { "move_tab_right",   "move-tab-right"     },
+    { "detach_tab",       "detach-tab"         },
+    { "switch_to_tab_1",  "switch-to-tab-1"    },
+    { "switch_to_tab_2",  "switch-to-tab-2"    },
+    { "switch_to_tab_3",  "switch-to-tab-3"    },
+    { "switch_to_tab_4",  "switch-to-tab-4"    },
+    { "switch_to_tab_5",  "switch-to-tab-5"    },
+    { "switch_to_tab_6",  "switch-to-tab-6"    },
+    { "switch_to_tab_7",  "switch-to-tab-7"    },
+    { "switch_to_tab_8",  "switch-to-tab-8"    },
+    { "switch_to_tab_9",  "switch-to-tab-9"    },
+    { "switch_to_tab_10", "switch-to-tab-10"   },
+    { "switch_to_tab_11", "switch-to-tab-11"   },
+    { "switch_to_tab_12", "switch-to-tab-12"   },
+    { "help",             "help"               }
   };
   GConfClient *client;
+  GSettings *settings;
   guint i;
-  char *key, *path;
+  char *gconf_path;
   GConfValue *value;
-  GString *str;
 
   client = gconf_client_get_default ();
-  str = g_string_sized_new (1024);
+  settings = g_settings_new (TERMINAL_KEYBINDINGS_SCHEMA);
 
   for (i = 0; i < G_N_ELEMENTS (data); ++i) {
-    key = g_strdup_printf ("/apps/gnome-terminal/keybindings/%s", data[i].key);
-    path = g_strdup_printf ("<Actions>/Main/%s", data[i].path);
-
-    if ((value = gconf_client_get_without_default (client, key, NULL)) != NULL &&
-        value->type == GCONF_VALUE_STRING)
-      g_string_append_printf (str,
-                              "(gtk_accel_path \"%s\" \"%s\")\n",
-                              path, gconf_value_get_string (value));
+    gconf_path = g_strdup_printf ("/apps/gnome-terminal/keybindings/%s", data[i].gconf_key);
 
-    g_free (key);
-    g_free (path);
-    if (value)
-      gconf_value_free (value);
-  }
+    value = gconf_client_get_without_default (client, gconf_path, NULL);
+    g_free (gconf_path);
+    if (value == NULL)
+      continue;
 
-  path = g_build_filename (g_get_user_config_dir (),
-                           "gnome-terminal",
-                           NULL);
-  g_mkdir_with_parents (path, 0700);
-  g_free (path);
+    if (value->type == GCONF_VALUE_STRING)
+      g_settings_set_string (settings, data[i].settings_key, gconf_value_get_string (value));
 
-  path = g_build_filename (g_get_user_config_dir (),
-                           "gnome-terminal",
-                           "accels",
-                           NULL);
-  g_file_set_contents (path, str->str, str->len, NULL);
-  g_free (path);
+    gconf_value_free (value);
+  }
 
-  g_string_free (str, TRUE);
+  g_object_unref (settings);
   g_object_unref (client);
 
   return TRUE;
diff --git a/src/org.gnome.Terminal.gschema.xml.in b/src/org.gnome.Terminal.gschema.xml.in
index abbe5d9..b62b14d 100644
--- a/src/org.gnome.Terminal.gschema.xml.in
+++ b/src/org.gnome.Terminal.gschema.xml.in
@@ -312,11 +312,146 @@
     </key>
   </schema>
 
-  <!-- Profiles list -->
+  <!-- Keybinding settings -->
 
-  <!--
-  <schema id="org.gnome.Terminal.Profiles" list-of="org.gnome.Terminal.Profile" />
-  -->
+  <schema id="org.gnome.Terminal.Legacy.Keybindings" path="/org/gnome/terminal/legacy/keybindings/">
+    <key name="new-tab" type="s">
+      <default>'&lt;Ctrl&gt;&lt;Shift&gt;t'</default>
+      <_summary>Keyboard shortcut to open a new tab</_summary>
+    </key>
+    <key name="new-window" type="s">
+      <default>'&lt;Ctrl&gt;&lt;Shift&gt;n'</default>
+      <_summary>Keyboard shortcut to open a new window</_summary>
+    </key>
+    <key name="new-profile" type="s">
+      <default>'disabled'</default>
+      <_summary>Keyboard shortcut to create a new profile</_summary>
+    </key>
+    <key name="save-contents" type="s">
+      <default>'disabled'</default>
+      <_summary>Keyboard shortcut to save the current tab contents to file</_summary>
+    </key>
+    <key name="close-tab" type="s">
+      <default>'&lt;Ctrl&gt;&lt;Shift&gt;w'</default>
+      <_summary>Keyboard shortcut to close a tab</_summary>
+    </key>
+    <key name="close-window" type="s">
+      <default>'&lt;Ctrl&gt;&lt;Shift&gt;q'</default>
+      <_summary>Keyboard shortcut to close a window</_summary>
+    </key>
+    <key name="copy" type="s">
+      <default>'&lt;Ctrl&gt;&lt;Shift&gt;c'</default>
+      <_summary>Keyboard shortcut to copy text</_summary>
+    </key>
+    <key name="paste" type="s">
+      <default>'&lt;Ctrl&gt;&lt;Shift&gt;v'</default>
+      <_summary>Keyboard shortcut to paste text</_summary>
+    </key>
+    <key name="full-screen" type="s">
+      <default>'F11'</default>
+      <_summary>Keyboard shortcut to toggle full screen mode</_summary>
+    </key>
+    <key name="toggle-menubar" type="s">
+      <default>'disabled'</default>
+      <_summary>Keyboard shortcut to toggle the visibility of the menubar</_summary>
+    </key>
+    <key name="set-terminal-title" type="s">
+      <default>'disabled'</default>
+      <_summary>Keyboard shortcut to set the terminal title</_summary>
+    </key>
+    <key name="reset" type="s">
+      <default>'disabled'</default>
+      <_summary>Keyboard shortcut to reset the terminal</_summary>
+    </key>
+    <key name="reset-and-clear" type="s">
+      <default>'disabled'</default>
+      <_summary>Keyboard shortcut to reset and clear the terminal</_summary>
+    </key>
+    <key name="prev-tab" type="s">
+      <default>'&lt;Control&gt;Page_Up'</default>
+      <_summary>Keyboard shortcut to switch to the previous tab</_summary>
+    </key>
+    <key name="next-tab" type="s">
+      <default>'&lt;Control&gt;Page_Down'</default>
+      <_summary>Keyboard shortcut to switch to the next tab</_summary>
+    </key>
+    <key name="move-tab-left" type="s">
+      <default>'&lt;Ctrl&gt;&lt;Shift&gt;Page_Up'</default>
+      <_summary>Keyboard shortcut to move the current tab to the left</_summary>
+    </key>
+    <key name="move-tab-right" type="s">
+      <default>'&lt;Ctrl&gt;&lt;Shift&gt;Page_Down'</default>
+      <_summary>Keyboard shortbut to move the current tab to the right</_summary>
+    </key>
+    <key name="detach-tab" type="s">
+      <default>'disabled'</default>
+      <_summary>Keyboard shortbut to detach current tab</_summary>
+    </key>
+    <key name="switch-to-tab-1" type="s">
+      <default>'&lt;Alt&gt;1'</default>
+      <_summary>Keyboard shortcut to switch to tab 1</_summary>
+    </key>
+    <key name="switch-to-tab-2" type="s">
+      <default>'&lt;Alt&gt;2'</default>
+      <_summary>Keyboard shortcut to switch to tab 2</_summary>
+    </key>
+    <key name="switch-to-tab-3" type="s">
+      <default>'&lt;Alt&gt;3'</default>
+      <_summary>Keyboard shortcut to switch to tab 3</_summary>
+    </key>
+    <key name="switch-to-tab-4" type="s">
+      <default>'&lt;Alt&gt;4'</default>
+      <_summary>Keyboard shortcut to switch to tab 4</_summary>
+    </key>
+    <key name="switch-to-tab-5" type="s">
+      <default>'&lt;Alt&gt;5'</default>
+      <_summary>Keyboard shortcut to switch to tab 5</_summary>
+    </key>
+    <key name="switch-to-tab-6" type="s">
+      <default>'&lt;Alt&gt;6'</default>
+      <_summary>Keyboard shortcut to switch to tab 6</_summary>
+    </key>
+    <key name="switch-to-tab-7" type="s">
+      <default>'&lt;Alt&gt;7'</default>
+      <_summary>Keyboard shortcut to switch to tab 7</_summary>
+    </key>
+    <key name="switch-to-tab-8" type="s">
+      <default>'&lt;Alt&gt;8'</default>
+      <_summary>Keyboard shortcut to switch to tab 8</_summary>
+    </key>
+    <key name="switch-to-tab-9" type="s">
+      <default>'&lt;Alt&gt;9'</default>
+      <_summary>Keyboard shortcut to switch to tab 9</_summary>
+    </key>
+    <key name="switch-to-tab-10" type="s">
+      <default>'&lt;Alt&gt;0'</default>
+      <_summary>Keyboard shortcut to switch to tab 10</_summary>
+    </key>
+    <key name="switch-to-tab-11" type="s">
+      <default>'disabled'</default>
+      <_summary>Keyboard shortcut to switch to tab 11</_summary>
+    </key>
+    <key name="switch-to-tab-12" type="s">
+      <default>'disabled'</default>
+      <_summary>Keyboard shortcut to switch to tab 12</_summary>
+    </key>
+    <key name="help" type="s">
+      <default>'F1'</default>
+      <_summary>Keyboard shortcut to launch help</_summary>
+    </key>
+    <key name="zoom-in" type="s">
+      <default>'&lt;Ctrl&gt;plus'</default>
+      <_summary>Keyboard shortcut to make font larger</_summary>
+    </key>
+    <key name="zoom-out" type="s">
+      <default>'&lt;Ctrl&gt;minus'</default>
+      <_summary>Keyboard shortcut to make font smaller</_summary>
+    </key>
+    <key name="zoom-normal" type="s">
+      <default>'&lt;Ctrl&gt;0'</default>
+      <_summary>Keyboard shortcut to make font normal-size</_summary>
+    </key>
+  </schema>
 
   <!-- Global settings -->
 
diff --git a/src/terminal-accels.c b/src/terminal-accels.c
index 0d36d2a..29d554e 100644
--- a/src/terminal-accels.c
+++ b/src/terminal-accels.c
@@ -1,6 +1,6 @@
 /*
  * Copyright  2001, 2002 Havoc Pennington, Red Hat Inc.
- * Copyright  2008, 2011 Christian Persch
+ * Copyright  2008, 2011, 2012, 2013 Christian Persch
  *
  * Gnome-terminal is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -29,30 +29,71 @@
 #include "terminal-schemas.h"
 #include "terminal-util.h"
 
+/* NOTES
+ *
+ * There are two sources of keybindings changes, from GSettings and from
+ * the accel map (happens with in-place menu editing).
+ *
+ * When a keybinding gconf key changes, we propagate that into the
+ * accel map.
+ * When the accel map changes, we queue a sync to GSettings.
+ *
+ * To avoid infinite loops, we short-circuit in both directions
+ * if the value is unchanged from last known.
+ *
+ * In the keybinding editor, when editing or clearing an accel, we write
+ * the change directly to GSettings and rely on the callback to
+ * actually apply the change to the accel map.
+ */
+
 #define ACCEL_PATH_ROOT "<Actions>/Main/"
-#define ACCEL_NEW_TAB              "FileNewTab"
-#define ACCEL_NEW_WINDOW           "FileNewWindow"
-#define ACCEL_NEW_PROFILE          "FileNewProfile"
-#define ACCEL_SAVE_CONTENTS        "FileSaveContents"
-#define ACCEL_CLOSE_TAB            "FileCloseTab"
-#define ACCEL_CLOSE_WINDOW         "FileCloseWindow"
-#define ACCEL_COPY                 "EditCopy"
-#define ACCEL_PASTE                "EditPaste"
-#define ACCEL_TOGGLE_MENUBAR       "ViewMenubar"
-#define ACCEL_FULL_SCREEN          "ViewFullscreen"
-#define ACCEL_RESET                "TerminalReset"
-#define ACCEL_RESET_AND_CLEAR      "TerminalResetClear"
-#define ACCEL_PREV_TAB             "TabsPrevious"
-#define ACCEL_NEXT_TAB             "TabsNext"
-#define ACCEL_SET_TERMINAL_TITLE   "TerminalSetTitle"
-#define ACCEL_HELP                 "HelpContents"
-#define ACCEL_ZOOM_IN              "ViewZoomIn"
-#define ACCEL_ZOOM_OUT             "ViewZoomOut"
-#define ACCEL_ZOOM_NORMAL          "ViewZoom100"
-#define ACCEL_MOVE_TAB_LEFT        "TabsMoveLeft"
-#define ACCEL_MOVE_TAB_RIGHT       "TabsMoveRight"
-#define ACCEL_DETACH_TAB           "TabsDetach"
-#define ACCEL_SWITCH_TAB_PREFIX    "TabsSwitch"
+#define ACCEL_PATH_NEW_TAB              ACCEL_PATH_ROOT "FileNewTab"
+#define ACCEL_PATH_NEW_WINDOW           ACCEL_PATH_ROOT "FileNewWindow"
+#define ACCEL_PATH_NEW_PROFILE          ACCEL_PATH_ROOT "FileNewProfile"
+#define ACCEL_PATH_SAVE_CONTENTS        ACCEL_PATH_ROOT "FileSaveContents"
+#define ACCEL_PATH_CLOSE_TAB            ACCEL_PATH_ROOT "FileCloseTab"
+#define ACCEL_PATH_CLOSE_WINDOW         ACCEL_PATH_ROOT "FileCloseWindow"
+#define ACCEL_PATH_COPY                 ACCEL_PATH_ROOT "EditCopy"
+#define ACCEL_PATH_PASTE                ACCEL_PATH_ROOT "EditPaste"
+#define ACCEL_PATH_TOGGLE_MENUBAR       ACCEL_PATH_ROOT "ViewMenubar"
+#define ACCEL_PATH_FULL_SCREEN          ACCEL_PATH_ROOT "ViewFullscreen"
+#define ACCEL_PATH_RESET                ACCEL_PATH_ROOT "TerminalReset"
+#define ACCEL_PATH_RESET_AND_CLEAR      ACCEL_PATH_ROOT "TerminalResetClear"
+#define ACCEL_PATH_PREV_TAB             ACCEL_PATH_ROOT "TabsPrevious"
+#define ACCEL_PATH_NEXT_TAB             ACCEL_PATH_ROOT "TabsNext"
+#define ACCEL_PATH_SET_TERMINAL_TITLE   ACCEL_PATH_ROOT "TerminalSetTitle"
+#define ACCEL_PATH_HELP                 ACCEL_PATH_ROOT "HelpContents"
+#define ACCEL_PATH_ZOOM_IN              ACCEL_PATH_ROOT "ViewZoomIn"
+#define ACCEL_PATH_ZOOM_OUT             ACCEL_PATH_ROOT "ViewZoomOut"
+#define ACCEL_PATH_ZOOM_NORMAL          ACCEL_PATH_ROOT "ViewZoom100"
+#define ACCEL_PATH_MOVE_TAB_LEFT        ACCEL_PATH_ROOT "TabsMoveLeft"
+#define ACCEL_PATH_MOVE_TAB_RIGHT       ACCEL_PATH_ROOT "TabsMoveRight"
+#define ACCEL_PATH_DETACH_TAB           ACCEL_PATH_ROOT "TabsDetach"
+#define ACCEL_PATH_SWITCH_TAB_PREFIX    ACCEL_PATH_ROOT "TabsSwitch"
+
+#define KEY_CLOSE_TAB           "close-tab"
+#define KEY_CLOSE_WINDOW        "close-window"
+#define KEY_COPY                "copy"
+#define KEY_DETACH_TAB          "detach-tab"
+#define KEY_FULL_SCREEN         "full-screen"
+#define KEY_HELP                "help"
+#define KEY_MOVE_TAB_LEFT       "move-tab-left"
+#define KEY_MOVE_TAB_RIGHT      "move-tab-right"
+#define KEY_NEW_PROFILE         "new-profile"
+#define KEY_NEW_TAB             "new-tab"
+#define KEY_NEW_WINDOW          "new-window"
+#define KEY_NEXT_TAB            "next-tab"
+#define KEY_PASTE               "paste"
+#define KEY_PREV_TAB            "prev-tab"
+#define KEY_RESET_AND_CLEAR     "reset-and-clear"
+#define KEY_RESET               "reset"
+#define KEY_SAVE_CONTENTS       "save-contents"
+#define KEY_SET_TERMINAL_TITLE  "set-terminal-title"
+#define KEY_TOGGLE_MENUBAR      "toggle-menubar"
+#define KEY_ZOOM_IN             "zoom-in"
+#define KEY_ZOOM_NORMAL         "zoom-normal"
+#define KEY_ZOOM_OUT            "zoom-out"
+#define KEY_SWITCH_TAB_PREFIX   "switch-to-tab-"
 
 #if 1
 /*
@@ -68,10 +109,22 @@
 #endif
 #endif
 
+typedef struct {
+  GdkModifierType mods;
+  guint key;
+} Keybinding;
+
 typedef struct
 {
   const char *user_visible_name;
-  const char *accel_path_suffix;
+  const char *settings_key;
+  const char *accel_path;
+  /* last values received from settings */
+  Keybinding settings_keybinding;
+  GClosure *closure;
+  /* have gotten a notification from gtk */
+  gboolean needs_settings_sync;
+  gboolean accel_path_unlocked;
 } KeyEntry;
 
 typedef struct
@@ -83,61 +136,106 @@ typedef struct
 
 static KeyEntry file_entries[] =
 {
-  { N_("New Tab"), ACCEL_NEW_TAB },
-  { N_("New Window"), ACCEL_NEW_WINDOW },
-  { N_("New Profile"), ACCEL_NEW_PROFILE },
+  { N_("New Tab"),
+    KEY_NEW_TAB, ACCEL_PATH_NEW_TAB, { GDK_SHIFT_MASK | GDK_CONTROL_MASK, GDK_KEY_t }, NULL, FALSE, TRUE },
+  { N_("New Window"),
+    KEY_NEW_WINDOW, ACCEL_PATH_NEW_WINDOW, { GDK_SHIFT_MASK | GDK_CONTROL_MASK, GDK_KEY_n }, NULL, FALSE, TRUE },
+  { N_("New Profile"),
+    KEY_NEW_PROFILE, ACCEL_PATH_NEW_PROFILE, { 0, 0 } , NULL, FALSE, TRUE },
 #ifdef ENABLE_SAVE
-  { N_("Save Contents"), ACCEL_SAVE_CONTENTS },
+  { N_("Save Contents"),
+    KEY_SAVE_CONTENTS, ACCEL_PATH_SAVE_CONTENTS, { 0, 0 }, NULL, FALSE, TRUE },
 #endif
-  { N_("Close Tab"), ACCEL_CLOSE_TAB },
-  { N_("Close Window"), ACCEL_CLOSE_WINDOW }
+  { N_("Close Tab"),
+    KEY_CLOSE_TAB, ACCEL_PATH_CLOSE_TAB, { GDK_SHIFT_MASK | GDK_CONTROL_MASK, GDK_KEY_w }, NULL, FALSE, TRUE },
+  { N_("Close Window"),
+    KEY_CLOSE_WINDOW, ACCEL_PATH_CLOSE_WINDOW, { GDK_SHIFT_MASK | GDK_CONTROL_MASK, GDK_KEY_q }, NULL, FALSE, TRUE },
 };
 
 static KeyEntry edit_entries[] =
 {
-  { N_("Copy"), ACCEL_COPY },
-  { N_("Paste"), ACCEL_PASTE }
+  { N_("Copy"),
+    KEY_COPY, ACCEL_PATH_COPY, { GDK_SHIFT_MASK | GDK_CONTROL_MASK, GDK_KEY_c }, NULL, FALSE, TRUE },
+  { N_("Paste"),
+    KEY_PASTE, ACCEL_PATH_PASTE, { GDK_SHIFT_MASK | GDK_CONTROL_MASK, GDK_KEY_v }, NULL, FALSE, TRUE },
 };
 
 static KeyEntry view_entries[] =
 {
-  { N_("Hide and Show menubar"), ACCEL_TOGGLE_MENUBAR },
-  { N_("Full Screen"), ACCEL_FULL_SCREEN },
-  { N_("Zoom In"), ACCEL_ZOOM_IN },
-  { N_("Zoom Out"), ACCEL_ZOOM_OUT },
-  { N_("Normal Size"), ACCEL_ZOOM_NORMAL },
+  { N_("Hide and Show menubar"),
+    KEY_TOGGLE_MENUBAR, ACCEL_PATH_TOGGLE_MENUBAR, { 0, 0 }, NULL, FALSE, TRUE },
+  { N_("Full Screen"),
+    KEY_FULL_SCREEN, ACCEL_PATH_FULL_SCREEN, { 0, GDK_KEY_F11 }, NULL, FALSE, TRUE },
+  { N_("Zoom In"),
+    KEY_ZOOM_IN, ACCEL_PATH_ZOOM_IN, { GDK_CONTROL_MASK, GDK_KEY_plus }, NULL, FALSE, TRUE },
+  { N_("Zoom Out"),
+    KEY_ZOOM_OUT, ACCEL_PATH_ZOOM_OUT, { GDK_CONTROL_MASK, GDK_KEY_minus }, NULL, FALSE, TRUE },
+  { N_("Normal Size"),
+    KEY_ZOOM_NORMAL, ACCEL_PATH_ZOOM_NORMAL, { GDK_CONTROL_MASK, GDK_KEY_0 }, NULL, FALSE, TRUE }
 };
 
 static KeyEntry terminal_entries[] =
 {
-  { N_("Set Title"), ACCEL_SET_TERMINAL_TITLE },
-  { N_("Reset"), ACCEL_RESET },
-  { N_("Reset and Clear"), ACCEL_RESET_AND_CLEAR }
+  { N_("Set Title"),
+    KEY_SET_TERMINAL_TITLE, ACCEL_PATH_SET_TERMINAL_TITLE, { 0, 0 }, NULL, FALSE, TRUE },
+  { N_("Reset"),
+    KEY_RESET, ACCEL_PATH_RESET, { 0, 0 }, NULL, FALSE, TRUE },
+  { N_("Reset and Clear"),
+    KEY_RESET_AND_CLEAR, ACCEL_PATH_RESET_AND_CLEAR, { 0, 0 }, NULL, FALSE, TRUE },
 };
 
 static KeyEntry tabs_entries[] =
 {
-  { N_("Switch to Previous Tab"), ACCEL_PREV_TAB },
-  { N_("Switch to Next Tab"), ACCEL_NEXT_TAB },
-  { N_("Move Tab to the Left"), ACCEL_MOVE_TAB_LEFT },
-  { N_("Move Tab to the Right"), ACCEL_MOVE_TAB_RIGHT },
-  { N_("Detach Tab"), ACCEL_DETACH_TAB },
-  { N_("Switch to Tab 1"), ACCEL_SWITCH_TAB_PREFIX "1" },
-  { N_("Switch to Tab 2"), ACCEL_SWITCH_TAB_PREFIX "2" },
-  { N_("Switch to Tab 3"), ACCEL_SWITCH_TAB_PREFIX "3" },
-  { N_("Switch to Tab 4"), ACCEL_SWITCH_TAB_PREFIX "4" },
-  { N_("Switch to Tab 5"), ACCEL_SWITCH_TAB_PREFIX "5" },
-  { N_("Switch to Tab 6"), ACCEL_SWITCH_TAB_PREFIX "6" },
-  { N_("Switch to Tab 7"), ACCEL_SWITCH_TAB_PREFIX "7" },
-  { N_("Switch to Tab 8"), ACCEL_SWITCH_TAB_PREFIX "8" },
-  { N_("Switch to Tab 9"), ACCEL_SWITCH_TAB_PREFIX "9" },
-  { N_("Switch to Tab 10"), ACCEL_SWITCH_TAB_PREFIX "10" },
-  { N_("Switch to Tab 11"), ACCEL_SWITCH_TAB_PREFIX "11" },
-  { N_("Switch to Tab 12"), ACCEL_SWITCH_TAB_PREFIX "12" }
+  { N_("Switch to Previous Tab"),
+    KEY_PREV_TAB, ACCEL_PATH_PREV_TAB, { GDK_CONTROL_MASK, GDK_KEY_Page_Up }, NULL, FALSE, TRUE },
+  { N_("Switch to Next Tab"),
+    KEY_NEXT_TAB, ACCEL_PATH_NEXT_TAB, { GDK_CONTROL_MASK, GDK_KEY_Page_Down }, NULL, FALSE, TRUE },
+  { N_("Move Tab to the Left"),
+    KEY_MOVE_TAB_LEFT, ACCEL_PATH_MOVE_TAB_LEFT, { GDK_SHIFT_MASK | GDK_CONTROL_MASK, GDK_KEY_Page_Up }, NULL, FALSE, TRUE },
+  { N_("Move Tab to the Right"),
+    KEY_MOVE_TAB_RIGHT, ACCEL_PATH_MOVE_TAB_RIGHT, { GDK_SHIFT_MASK | GDK_CONTROL_MASK, GDK_KEY_Page_Down }, NULL, FALSE, TRUE },
+  { N_("Detach Tab"),
+    KEY_DETACH_TAB, ACCEL_PATH_DETACH_TAB, { 0, 0 }, NULL, FALSE, TRUE },
+  { N_("Switch to Tab 1"),
+    KEY_SWITCH_TAB_PREFIX "1",
+    ACCEL_PATH_SWITCH_TAB_PREFIX "1", { GDK_MOD1_MASK, GDK_KEY_1 }, NULL, FALSE, TRUE },
+  { N_("Switch to Tab 2"),
+    KEY_SWITCH_TAB_PREFIX "2",
+    ACCEL_PATH_SWITCH_TAB_PREFIX "2", { GDK_MOD1_MASK, GDK_KEY_2 }, NULL, FALSE, TRUE },
+  { N_("Switch to Tab 3"),
+    KEY_SWITCH_TAB_PREFIX "3",
+    ACCEL_PATH_SWITCH_TAB_PREFIX "3", { GDK_MOD1_MASK, GDK_KEY_3 }, NULL, FALSE, TRUE },
+  { N_("Switch to Tab 4"),
+    KEY_SWITCH_TAB_PREFIX "4",
+    ACCEL_PATH_SWITCH_TAB_PREFIX "4", { GDK_MOD1_MASK, GDK_KEY_4 }, NULL, FALSE, TRUE },
+  { N_("Switch to Tab 5"),
+    KEY_SWITCH_TAB_PREFIX "5",
+    ACCEL_PATH_SWITCH_TAB_PREFIX "5", { GDK_MOD1_MASK, GDK_KEY_5 }, NULL, FALSE, TRUE },
+  { N_("Switch to Tab 6"),
+    KEY_SWITCH_TAB_PREFIX "6",
+    ACCEL_PATH_SWITCH_TAB_PREFIX "6", { GDK_MOD1_MASK, GDK_KEY_6 }, NULL, FALSE, TRUE },
+  { N_("Switch to Tab 7"),
+    KEY_SWITCH_TAB_PREFIX "7",
+    ACCEL_PATH_SWITCH_TAB_PREFIX "7", { GDK_MOD1_MASK, GDK_KEY_7 }, NULL, FALSE, TRUE },
+  { N_("Switch to Tab 8"),
+    KEY_SWITCH_TAB_PREFIX "8",
+    ACCEL_PATH_SWITCH_TAB_PREFIX "8", { GDK_MOD1_MASK, GDK_KEY_8 }, NULL, FALSE, TRUE },
+  { N_("Switch to Tab 9"),
+    KEY_SWITCH_TAB_PREFIX "9",
+    ACCEL_PATH_SWITCH_TAB_PREFIX "9", { GDK_MOD1_MASK, GDK_KEY_9 }, NULL, FALSE, TRUE },
+  { N_("Switch to Tab 10"),
+    KEY_SWITCH_TAB_PREFIX "10",
+    ACCEL_PATH_SWITCH_TAB_PREFIX "10", { GDK_MOD1_MASK, GDK_KEY_0}, NULL, FALSE, TRUE },
+  { N_("Switch to Tab 11"),
+    KEY_SWITCH_TAB_PREFIX "11",
+    ACCEL_PATH_SWITCH_TAB_PREFIX "11", { 0, 0 }, NULL, FALSE, TRUE },
+  { N_("Switch to Tab 12"),
+    KEY_SWITCH_TAB_PREFIX "12",
+    ACCEL_PATH_SWITCH_TAB_PREFIX "12", { 0, 0 }, NULL, FALSE, TRUE }
 };
 
 static KeyEntry help_entries[] = {
-  { N_("Contents"), ACCEL_HELP }
+  { N_("Contents"), KEY_HELP, ACCEL_PATH_HELP, { 0, GDK_KEY_F1 }, NULL, FALSE, TRUE }
 };
 
 static KeyEntryList all_entries[] =
@@ -153,22 +251,32 @@ static KeyEntryList all_entries[] =
 enum
 {
   ACTION_COLUMN,
-  ACCEL_PATH_COLUMN,
+  KEYVAL_COLUMN,
   N_COLUMNS
 };
 
-static void accel_map_changed_callback (GtkAccelMap    *accel_map,
-                                        const char     *accel_path,
-                                        guint           keyval,
-                                        GdkModifierType modifier,
-                                        gpointer        data);
+static void keys_change_notify (GSettings *settings,
+                                const char *key,
+                                gpointer     user_data);
+
+static void accel_changed_callback (GtkAccelGroup  *accel_group,
+                                    guint           keyval,
+                                    GdkModifierType modifier,
+                                    GClosure       *accel_closure,
+                                    gpointer        data);
 
-static guint save_id = 0;
+static gboolean sync_idle_cb (gpointer data);
+
+static guint sync_idle_id = 0;
+static GtkAccelGroup *notification_group = NULL;
+/* never set settings keys in response to receiving a settings notify. */
+static int inside_settings_notify = 0;
 static GtkWidget *edit_keys_dialog = NULL;
 static GtkTreeStore *edit_keys_store = NULL;
-static gboolean dirty = FALSE;
+static GHashTable *settings_key_to_entry;
+static GSettings *keybinding_settings = NULL;
 
-static char *
+static char*
 binding_name (guint            keyval,
               GdkModifierType  mask)
 {
@@ -178,71 +286,87 @@ binding_name (guint            keyval,
   return g_strdup ("disabled");
 }
 
-static char *
-get_accel_map_filename (void)
-{
-  return g_build_filename (g_get_user_config_dir (),
-                           "gnome-terminal",
-                           "accels",
-                           NULL);
-}
-
 static gboolean
-save_cb (gpointer data)
+map_keybinding (GVariant *variant,
+                gpointer *result,
+                gpointer user_data)
 {
-  char *path;
+  Keybinding *keybinding = user_data;
+  const char *value;
 
-  _terminal_debug_print (TERMINAL_DEBUG_ACCELS,
-                         "saving accel map\n");
+  value = g_variant_get_string (variant, NULL);
 
-  save_id = 0;
+  if (value == NULL || g_str_equal (value, "disabled"))
+    {
+      keybinding->mods = 0;
+      keybinding->key = 0;
+      return TRUE;
+    }
 
-  if (!dirty)
+  gtk_accelerator_parse (value, &keybinding->key, &keybinding->mods);
+  if (keybinding->key == 0 && keybinding->mods == 0)
     return FALSE;
 
-  dirty = FALSE;
-
-  path = get_accel_map_filename ();
-  gtk_accel_map_save (path);
-  g_free (path);
-
-  return FALSE; /* don't run again */
+  return TRUE;
 }
 
-static void
-schedule_save (void)
+void
+terminal_accels_init (void)
 {
-  if (save_id != 0)
-    return;
+  guint i, j;
 
-  dirty = TRUE;
+  keybinding_settings = g_settings_new (TERMINAL_KEYBINDINGS_SCHEMA);
+  g_signal_connect (keybinding_settings, "changed", G_CALLBACK (keys_change_notify), NULL);
 
-  save_id = g_timeout_add_seconds (5, save_cb, NULL);
-}
+  settings_key_to_entry = g_hash_table_new (g_str_hash, g_str_equal);
 
-void
-terminal_accels_init (void)
-{
-  char *path;
+  notification_group = gtk_accel_group_new ();
+
+  for (i = 0; i < G_N_ELEMENTS (all_entries); ++i)
+    {
+      for (j = 0; j < all_entries[i].n_elements; ++j)
+	{
+	  KeyEntry *key_entry;
+
+	  key_entry = &(all_entries[i].key_entry[j]);
+
+          g_hash_table_insert (settings_key_to_entry,
+                               (gpointer) key_entry->settings_key,
+                               key_entry);
+
+	  key_entry->closure = g_closure_new_simple (sizeof (GClosure), key_entry);
 
-  g_signal_connect (gtk_accel_map_get (), "changed",
-                    G_CALLBACK (accel_map_changed_callback), NULL);
+	  g_closure_ref (key_entry->closure);
+	  g_closure_sink (key_entry->closure);
+  
+	  gtk_accel_group_connect_by_path (notification_group,
+					   I_(key_entry->accel_path),
+					   key_entry->closure);
 
-  path = get_accel_map_filename ();
-  gtk_accel_map_load (path);
-  g_free (path);
+          keys_change_notify (keybinding_settings, key_entry->settings_key, NULL);
+	}
+    }
+
+  g_signal_connect (notification_group, "accel-changed",
+                    G_CALLBACK (accel_changed_callback), NULL);
 }
 
 void
 terminal_accels_shutdown (void)
 {
-  if (save_id != 0)
+  g_signal_handlers_disconnect_by_func (keybinding_settings, G_CALLBACK (keys_change_notify), NULL);
+
+  if (sync_idle_id != 0)
     {
-      g_source_remove (save_id);
-      save_id = 0;
+      g_source_remove (sync_idle_id);
+      sync_idle_id = 0;
 
-      save_cb (NULL);
+      sync_idle_cb (NULL);
     }
+
+  g_clear_pointer (&settings_key_to_entry, (GDestroyNotify) g_hash_table_unref);
+  g_clear_object (&notification_group);
+  g_clear_object (&keybinding_settings);
 }
 
 static gboolean
@@ -251,10 +375,13 @@ update_model_foreach (GtkTreeModel *model,
 		      GtkTreeIter  *iter,
 		      gpointer      data)
 {
-  guint accel_path_quark;
+  KeyEntry *key_entry = NULL;
+
+  gtk_tree_model_get (model, iter,
+		      KEYVAL_COLUMN, &key_entry,
+		      -1);
 
-  gtk_tree_model_get (model, iter, ACCEL_PATH_COLUMN, &accel_path_quark, -1);
-  if (accel_path_quark == GPOINTER_TO_UINT (data))
+  if (key_entry == (KeyEntry *) data)
     {
       gtk_tree_model_row_changed (model, path, iter);
       return TRUE;
@@ -263,20 +390,142 @@ update_model_foreach (GtkTreeModel *model,
 }
 
 static void
-accel_map_changed_callback (GtkAccelMap    *accel_map,
-                            const char     *accel_path,
-                            guint           keyval,
-                            GdkModifierType modifier,
-                            gpointer        data)
+keys_change_notify (GSettings *settings,
+                    const char *settings_key,
+                    gpointer user_data)
+{
+  Keybinding keybinding;
+  KeyEntry *key_entry;
+
+  _terminal_debug_print (TERMINAL_DEBUG_ACCELS,
+                         "key %s changed\n",
+                         settings_key);
+
+  key_entry = g_hash_table_lookup (settings_key_to_entry, settings_key);
+  if (!key_entry)
+    {
+      /* shouldn't really happen, but let's be safe */
+      _terminal_debug_print (TERMINAL_DEBUG_ACCELS,
+                             "  WARNING: KeyEntry for changed key not found, bailing out\n");
+      return;
+    }
+
+  g_settings_get_mapped (settings, settings_key,
+                         (GSettingsGetMapping) map_keybinding, &keybinding);
+
+  key_entry->settings_keybinding = keybinding;
+
+  /* Unlock the path, so we can change its accel */
+  if (!key_entry->accel_path_unlocked)
+    gtk_accel_map_unlock_path (key_entry->accel_path);
+
+  /* sync over to GTK */
+  _terminal_debug_print (TERMINAL_DEBUG_ACCELS,
+                         "changing path %s to %s\n",
+                         key_entry->accel_path,
+                         binding_name (keybinding.key, keybinding.mods)); /* memleak */
+  inside_settings_notify += 1;
+  /* Note that this may return FALSE, e.g. when the entry was already set correctly. */
+  gtk_accel_map_change_entry (key_entry->accel_path,
+                              keybinding.key, keybinding.mods,
+                              TRUE);
+  inside_settings_notify -= 1;
+
+  /* Lock the path if the settings key isn't writable */
+  key_entry->accel_path_unlocked = g_settings_is_writable (settings, settings_key);
+  if (!key_entry->accel_path_unlocked)
+    gtk_accel_map_lock_path (key_entry->accel_path);
+
+  /* This seems necessary to update the tree model, since sometimes the
+   * notification on the notification_group seems not to be emitted correctly.
+   * Without this change, when trying to set an accel to e.g. Alt-T (while the main
+   * menu in the terminal windows is _Terminal with Alt-T mnemonic) only displays
+   * the accel change after a re-expose of the row.
+   * FIXME: Find out *why* the accel-changed signal is wrong here!
+   */
+  if (edit_keys_store)
+    gtk_tree_model_foreach (GTK_TREE_MODEL (edit_keys_store), update_model_foreach, key_entry);
+}
+
+static void
+accel_changed_callback (GtkAccelGroup  *accel_group,
+                        guint           keyval,
+                        GdkModifierType modifier,
+                        GClosure       *accel_closure,
+                        gpointer        data)
+{
+  /* FIXME because GTK accel API is so nonsensical, we get
+   * a notify for each closure, on both the added and the removed
+   * accelerator. We just use the accel closure to find our
+   * accel entry, then update the value of that entry.
+   * We use an idle function to avoid setting the entry
+   * in settings when the accelerator gets removed and then
+   * setting it again when it gets added.
+   */
+  KeyEntry *key_entry;
+  
+  _terminal_debug_print (TERMINAL_DEBUG_ACCELS,
+                         "Changed accel %s closure %p\n",
+                         binding_name (keyval, modifier), /* memleak */
+                         accel_closure);
+
+  if (inside_settings_notify)
+    {
+      _terminal_debug_print (TERMINAL_DEBUG_ACCELS,
+                             "Ignoring change from gtk because we're inside a settings notify\n");
+      return;
+    }
+
+  key_entry = accel_closure->data;
+  g_assert (key_entry);
+
+  key_entry->needs_settings_sync = TRUE;
+
+  if (sync_idle_id == 0)
+    sync_idle_id = g_idle_add (sync_idle_cb, NULL);
+}
+
+static void
+sync_key_entry (gpointer key,
+                KeyEntry *key_entry,
+                GSettings *settings)
+{
+  GtkAccelKey gtk_key;
+
+  if (!key_entry->needs_settings_sync)
+    return;
+
+  key_entry->needs_settings_sync = FALSE;
+
+  if (gtk_accel_map_lookup_entry (key_entry->accel_path, &gtk_key) &&
+      (gtk_key.accel_key != key_entry->settings_keybinding.key ||
+       gtk_key.accel_mods != key_entry->settings_keybinding.mods))
+    {
+      char *accel_name;
+
+      accel_name = binding_name (gtk_key.accel_key, gtk_key.accel_mods);
+      g_settings_set_string (settings, key_entry->settings_key, accel_name);
+      g_free (accel_name);
+    }
+}
+
+static gboolean
+sync_idle_cb (gpointer data)
 {
   _terminal_debug_print (TERMINAL_DEBUG_ACCELS,
-                         "Changed accel path %s to %s\n",
-                         accel_path,
-                         binding_name (keyval, modifier) /* memleak */);
+                         "settings sync handler\n");
+  sync_idle_id = 0;
+
+  g_hash_table_foreach (settings_key_to_entry, (GHFunc) sync_key_entry, keybinding_settings);
 
-  schedule_save ();
+  return FALSE;
 }
 
+/* We have the same KeyEntry* in both columns;
+ * we only have two columns because we want to be able
+ * to sort by either one of them.
+ */
+
 static void
 accel_set_func (GtkTreeViewColumn *tree_column,
                 GtkCellRenderer   *cell,
@@ -284,46 +533,35 @@ accel_set_func (GtkTreeViewColumn *tree_column,
                 GtkTreeIter       *iter,
                 gpointer           data)
 {
-  guint accel_path_quark;
-  GtkAccelKey key;
+  KeyEntry *ke;
+  
+  gtk_tree_model_get (model, iter,
+                      KEYVAL_COLUMN, &ke,
+                      -1);
 
-  gtk_tree_model_get (model, iter, ACCEL_PATH_COLUMN, &accel_path_quark, -1);
-  if (accel_path_quark == 0) {
+  if (ke == NULL)
     /* This is a title row */
     g_object_set (cell,
                   "visible", FALSE,
 		  NULL);
-    return;
-  }
-
-  if (gtk_accel_map_lookup_entry (g_quark_to_string (accel_path_quark), &key))
-    g_object_set (cell,
-                  "visible", TRUE,
-                  "sensitive", (key.accel_flags & GTK_ACCEL_LOCKED) == 0,
-                  "editable", (key.accel_flags & GTK_ACCEL_LOCKED) == 0,
-                  "accel-key", key.accel_key,
-                  "accel-mods", (guint) key.accel_mods,
-                  NULL);
   else
     g_object_set (cell,
                   "visible", TRUE,
-                  "sensitive", TRUE,
-                  "editable", TRUE,
-                  "accel-key", (guint) 0,
-                  "accel-mods", (guint) 0,
-                  NULL);
+                  "sensitive", ke->accel_path_unlocked,
+                  "editable", ke->accel_path_unlocked,
+                  "accel-key", ke->settings_keybinding.key,
+                  "accel-mods", ke->settings_keybinding.mods,
+		  NULL);
 }
 
 static void
-treeview_accel_map_changed_cb (GtkAccelMap *accel_map,
-                               const char *accel_path,
-                               guint keyval,
-                               GdkModifierType modifier,
-                               GtkTreeModel *model)
+treeview_accel_changed_cb (GtkAccelGroup  *accel_group,
+                           guint keyval,
+                           GdkModifierType modifier,
+                           GClosure *accel_closure,
+                           GtkTreeModel *model)
 {
-  gtk_tree_model_foreach (model,
-                          update_model_foreach,
-                          GUINT_TO_POINTER (g_quark_from_string (accel_path)));
+  gtk_tree_model_foreach (model, update_model_foreach, accel_closure->data);
 }
 
 static void
@@ -337,7 +575,10 @@ accel_edited_callback (GtkCellRendererAccel *cell,
   GtkTreeModel *model;
   GtkTreePath *path;
   GtkTreeIter iter;
-  guint accel_path_quark;
+  KeyEntry *ke;
+  GtkAccelGroupEntry *entries;
+  guint n_entries;
+  char *str;
 
   model = gtk_tree_view_get_model (view);
 
@@ -351,12 +592,69 @@ accel_edited_callback (GtkCellRendererAccel *cell,
   }
   gtk_tree_path_free (path);
 
-  gtk_tree_model_get (model, &iter, ACCEL_PATH_COLUMN, &accel_path_quark, -1);
+  gtk_tree_model_get (model, &iter, KEYVAL_COLUMN, &ke, -1);
+
   /* sanity check */
-  if (accel_path_quark == 0)
+  if (ke == NULL)
     return;
 
-  gtk_accel_map_change_entry (g_quark_to_string (accel_path_quark), keyval, mask, TRUE);
+  /* Check if we already have an entry using this accel */
+  entries = gtk_accel_group_query (notification_group, keyval, mask, &n_entries);
+  if (n_entries > 0)
+    {
+      if (entries[0].accel_path_quark != g_quark_from_string (ke->accel_path))
+        {
+          GtkWidget *dialog;
+          char *name;
+          KeyEntry *other_key;
+
+          name = gtk_accelerator_get_label (keyval, mask);
+          other_key = entries[0].closure->data;
+          g_assert (other_key);
+
+          dialog =
+            gtk_message_dialog_new (GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (view))),
+                                    GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_MODAL,
+                                    GTK_MESSAGE_WARNING,
+                                    GTK_BUTTONS_OK,
+                                    _("The shortcut key â%sâ is already bound to the â%sâ action"),
+                                    name,
+                                    other_key->user_visible_name ? _(other_key->user_visible_name) : other_key->settings_key);
+          g_free (name);
+
+          g_signal_connect (dialog, "response", G_CALLBACK (gtk_widget_destroy), NULL);
+          gtk_window_present (GTK_WINDOW (dialog));
+        }
+
+      return;
+    }
+
+  str = binding_name (keyval, mask);
+
+  _terminal_debug_print (TERMINAL_DEBUG_ACCELS,
+                         "Edited path %s keyval %s, setting settings to %s\n",
+                         ke->accel_path,
+                         gdk_keyval_name (keyval) ? gdk_keyval_name (keyval) : "null",
+                         str);
+#ifdef GNOME_ENABLE_DEBUG
+  _TERMINAL_DEBUG_IF (TERMINAL_DEBUG_ACCELS)
+    {
+      GtkAccelKey old_key;
+
+      if (gtk_accel_map_lookup_entry (ke->accel_path, &old_key)) {
+        _terminal_debug_print (TERMINAL_DEBUG_ACCELS,
+                               "  Old entry of path %s is keyval %s mask %x\n",
+                               ke->accel_path, gdk_keyval_name (old_key.accel_key), old_key.accel_mods);
+      } else {
+        _terminal_debug_print (TERMINAL_DEBUG_ACCELS,
+                               "  Failed to look up the old entry of path %s\n",
+                               ke->accel_path);
+      }
+    }
+#endif
+
+  g_settings_set_string (keybinding_settings, ke->settings_key, str);
+  g_free (str);
 }
 
 static void
@@ -367,7 +665,8 @@ accel_cleared_callback (GtkCellRendererAccel *cell,
   GtkTreeModel *model;
   GtkTreePath *path;
   GtkTreeIter iter;
-  guint accel_path_quark;
+  KeyEntry *ke;
+  char *str;
 
   model = gtk_tree_view_get_model (view);
 
@@ -381,21 +680,31 @@ accel_cleared_callback (GtkCellRendererAccel *cell,
   }
   gtk_tree_path_free (path);
 
-  gtk_tree_model_get (model, &iter, ACCEL_PATH_COLUMN, &accel_path_quark, -1);
+  gtk_tree_model_get (model, &iter, KEYVAL_COLUMN, &ke, -1);
+
   /* sanity check */
-  if (accel_path_quark == 0)
+  if (ke == NULL)
     return;
 
-  gtk_accel_map_change_entry (g_quark_to_string (accel_path_quark), 0, 0, TRUE);
+  ke->settings_keybinding.key = 0;
+  ke->settings_keybinding.mods = 0;
+  ke->needs_settings_sync = TRUE;
+
+  str = binding_name (0, 0);
+
+  _terminal_debug_print (TERMINAL_DEBUG_ACCELS,
+                         "Cleared keybinding for settings %s",
+                         ke->settings_key);
+
+  g_settings_set_string (keybinding_settings, ke->settings_key, str);
+  g_free (str);
 }
 
 static void
 edit_keys_dialog_destroy_cb (GtkWidget *widget,
                              gpointer user_data)
 {
-  g_signal_handlers_disconnect_by_func (gtk_accel_map_get (),
-                                        G_CALLBACK (treeview_accel_map_changed_cb),
-                                        user_data);
+  g_signal_handlers_disconnect_by_func (notification_group, G_CALLBACK (treeview_accel_changed_cb), user_data);
   edit_keys_dialog = NULL;
   edit_keys_store = NULL;
 }
@@ -404,16 +713,28 @@ static void
 edit_keys_dialog_response_cb (GtkWidget *editor,
                               int response,
                               gpointer use_data)
-{
+{  
   if (response == GTK_RESPONSE_HELP)
     {
       terminal_util_show_help ("gnome-terminal-shortcuts", GTK_WINDOW (editor));
       return;
     }
-
+    
   gtk_widget_destroy (editor);
 }
 
+#ifdef GNOME_ENABLE_DEBUG
+static void
+row_changed (GtkTreeModel *tree_model,
+             GtkTreePath  *path,
+             GtkTreeIter  *iter,
+             gpointer      user_data)
+{
+  _terminal_debug_print (TERMINAL_DEBUG_ACCELS,
+                         "ROW-CHANGED [%s]\n", gtk_tree_path_to_string (path) /* leak */);
+}
+#endif
+
 void
 terminal_edit_keys_dialog_show (GtkWindow *transient_parent)
 {
@@ -421,8 +742,8 @@ terminal_edit_keys_dialog_show (GtkWindow *transient_parent)
   GtkTreeViewColumn *column;
   GtkCellRenderer *cell_renderer;
   GtkTreeStore *tree;
-  GSettings *settings;
   guint i;
+  GSettings *settings;
 
   if (edit_keys_dialog != NULL)
     goto done;
@@ -475,7 +796,12 @@ terminal_edit_keys_dialog_show (GtkWindow *transient_parent)
 
   /* Add the data */
 
-  tree = edit_keys_store = gtk_tree_store_new (N_COLUMNS, G_TYPE_STRING, G_TYPE_UINT);
+  tree = edit_keys_store = gtk_tree_store_new (N_COLUMNS, G_TYPE_STRING, G_TYPE_POINTER);
+
+#ifdef GNOME_ENABLE_DEBUG
+  _TERMINAL_DEBUG_IF (TERMINAL_DEBUG_ACCELS)
+    g_signal_connect (tree, "row-changed", G_CALLBACK (row_changed), NULL);
+#endif
 
   for (i = 0; i < G_N_ELEMENTS (all_entries); ++i)
     {
@@ -484,34 +810,28 @@ terminal_edit_keys_dialog_show (GtkWindow *transient_parent)
 
       gtk_tree_store_insert_with_values (tree, &parent_iter, NULL, -1,
                                          ACTION_COLUMN, _(all_entries[i].user_visible_name),
-                                         ACCEL_PATH_COLUMN, 0,
+                                         KEYVAL_COLUMN, NULL,
                                          -1);
 
       for (j = 0; j < all_entries[i].n_elements; ++j)
 	{
 	  KeyEntry *key_entry = &(all_entries[i].key_entry[j]);
 	  GtkTreeIter iter;
-          char *accel_path;
 
-          accel_path = g_strconcat (ACCEL_PATH_ROOT, key_entry->accel_path_suffix, NULL);
           gtk_tree_store_insert_with_values (tree, &iter, &parent_iter, -1,
                                              ACTION_COLUMN, _(key_entry->user_visible_name),
-                                             ACCEL_PATH_COLUMN, g_quark_from_string (accel_path),
+                                             KEYVAL_COLUMN, key_entry,
                                              -1);
-          g_free (accel_path);
 	}
     }
 
-  gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (tree), ACTION_COLUMN,
-                                        GTK_SORT_ASCENDING);
-
   gtk_tree_view_set_model (GTK_TREE_VIEW (tree_view), GTK_TREE_MODEL (tree));
   g_object_unref (tree);
 
   gtk_tree_view_expand_all (GTK_TREE_VIEW (tree_view));
 
-  g_signal_connect (gtk_accel_map_get (), "changed",
-                    G_CALLBACK (treeview_accel_map_changed_cb), tree);
+  g_signal_connect (notification_group, "accel-changed",
+                    G_CALLBACK (treeview_accel_changed_cb), tree);
 
   edit_keys_dialog = dialog;
   g_signal_connect (dialog, "destroy",
diff --git a/src/terminal-schemas.h b/src/terminal-schemas.h
index 0d335c2..cd2acbc 100644
--- a/src/terminal-schemas.h
+++ b/src/terminal-schemas.h
@@ -26,6 +26,7 @@ G_BEGIN_DECLS
 
 #define TERMINAL_SCHEMA_VERSION         (1u)
 
+#define TERMINAL_KEYBINDINGS_SCHEMA     "org.gnome.Terminal.Legacy.Keybindings"
 #define TERMINAL_PROFILE_SCHEMA         "org.gnome.Terminal.Legacy.Profile"
 #define TERMINAL_SETTING_SCHEMA         "org.gnome.Terminal.Settings"
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]