[gnome-terminal] accels: Port accelerators to use GtkApplication



commit a319aeb66f36e728af1b4929ddd69574df838702
Author: Christian Persch <chpe gnome org>
Date:   Sun May 12 22:26:03 2013 +0200

    accels: Port accelerators to use GtkApplication
    
    Add GActions for the window actions, and use these as targets for the
    accelerators.
    
    Conflicts:
        src/terminal-accels.c
        src/terminal-window.c

 src/terminal-accels.c |  574 ++++++-----------------
 src/terminal-accels.h |    3 +-
 src/terminal-app.c    |    2 +-
 src/terminal-window.c | 1241 +++++++++++++++++++++++++++++++------------------
 4 files changed, 935 insertions(+), 885 deletions(-)
---
diff --git a/src/terminal-accels.c b/src/terminal-accels.c
index 0c61ee0..0701dc8 100644
--- a/src/terminal-accels.c
+++ b/src/terminal-accels.c
@@ -48,31 +48,6 @@
  * actually apply the change to the accel map.
  */
 
-#define ACCEL_PATH_ROOT "<Actions>/Main/"
-#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"
@@ -111,22 +86,15 @@
 #endif
 #endif
 
-typedef struct {
-  GdkModifierType mods;
-  guint key;
-} Keybinding;
-
 typedef struct
 {
   const char *user_visible_name;
   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;
+  const char *action_name;
+  const GVariantType *action_parameter_type;
+  const char *action_parameter;
+  GVariant *parameter;
+  gboolean installed;
 } KeyEntry;
 
 typedef struct
@@ -136,124 +104,72 @@ typedef struct
   const char *user_visible_name;
 } KeyEntryList;
 
-static KeyEntry file_entries[] =
-{
-  { 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 },
+#define ENTRY(name, key, action, type, parameter)       \
+  { name, key, "win." action, (const GVariantType *) type, parameter, NULL, FALSE }
+
+static KeyEntry file_entries[] = {
+  ENTRY (N_("New Tab"),       KEY_NEW_TAB,       "new-terminal",  "s",  "'tab'"   ),
+  ENTRY (N_("New Window"),    KEY_NEW_WINDOW,    "new-terminal",  "s",  "'window'"),
+  ENTRY (N_("New Profile"),   KEY_NEW_PROFILE,   "new-profile",   NULL, NULL      ),
 #ifdef ENABLE_SAVE
-  { N_("Save Contents"),
-    KEY_SAVE_CONTENTS, ACCEL_PATH_SAVE_CONTENTS, { 0, 0 }, NULL, FALSE, TRUE },
+  ENTRY (N_("Save Contents"), KEY_SAVE_CONTENTS, "save-contents", NULL, NULL      ),
 #endif
-  { 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 },
+  ENTRY (N_("Close Tab"),     KEY_CLOSE_TAB,     "close",         "s",  "'tab'"   ),
+  ENTRY (N_("Close Window"),  KEY_CLOSE_WINDOW,  "close",         "s",  "'window'"),
 };
 
-static KeyEntry edit_entries[] =
-{
-  { 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 edit_entries[] = {
+  ENTRY (N_("Copy"),  KEY_COPY,  "copy",  NULL, NULL      ),
+  ENTRY (N_("Paste"), KEY_PASTE, "paste", "s",  "'normal'"),
 };
 
-static KeyEntry view_entries[] =
-{
-  { 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 view_entries[] = {
+  ENTRY (N_("Hide and Show toolbar"), KEY_TOGGLE_MENUBAR, "show-menubar", NULL, NULL),
+  ENTRY (N_("Full Screen"),           KEY_FULL_SCREEN,    "fullscreen",   NULL, NULL),
+  ENTRY (N_("Zoom In"),               KEY_ZOOM_IN,        "zoom",         "i",  "1" ),
+  ENTRY (N_("Zoom Out"),              KEY_ZOOM_OUT,       "zoom",         "i",  "-1"),
+  ENTRY (N_("Normal Size"),           KEY_ZOOM_NORMAL,    "zoom",         "i",  "0" )
 };
 
-static KeyEntry terminal_entries[] =
-{
-  { 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 terminal_entries[] = {
+  ENTRY (N_("Set Title"),       KEY_SET_TERMINAL_TITLE, "set-title", NULL, NULL   ),
+  ENTRY (N_("Reset"),           KEY_RESET,              "reset",     "b",  "false"),
+  ENTRY (N_("Reset and Clear"), KEY_RESET_AND_CLEAR,    "reset",     "b",  "true" ),
 };
 
-static KeyEntry tabs_entries[] =
-{
-  { 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 },
-
-#define SWITCH_TAB_ACCEL(num, modifier, key)    \
-  { NULL, \
-    KEY_SWITCH_TAB_PREFIX # num, \
-    ACCEL_PATH_SWITCH_TAB_PREFIX # num, \
-    { modifier, key }, \
-    NULL, \
-    FALSE, \
-    TRUE \
-  }
-#define SWITCH_TAB_ACCEL_NO_DEFAULT(num) SWITCH_TAB_ACCEL (num, 0, 0)
-
-  SWITCH_TAB_ACCEL (1,  GDK_MOD1_MASK, GDK_KEY_1),
-  SWITCH_TAB_ACCEL (2,  GDK_MOD1_MASK, GDK_KEY_2),
-  SWITCH_TAB_ACCEL (3,  GDK_MOD1_MASK, GDK_KEY_3),
-  SWITCH_TAB_ACCEL (4,  GDK_MOD1_MASK, GDK_KEY_4),
-  SWITCH_TAB_ACCEL (5,  GDK_MOD1_MASK, GDK_KEY_5),
-  SWITCH_TAB_ACCEL (6,  GDK_MOD1_MASK, GDK_KEY_6),
-  SWITCH_TAB_ACCEL (7,  GDK_MOD1_MASK, GDK_KEY_7),
-  SWITCH_TAB_ACCEL (8,  GDK_MOD1_MASK, GDK_KEY_8),
-  SWITCH_TAB_ACCEL (9,  GDK_MOD1_MASK, GDK_KEY_9),
-  SWITCH_TAB_ACCEL (10, GDK_MOD1_MASK, GDK_KEY_0),
-  SWITCH_TAB_ACCEL_NO_DEFAULT (11),
-  SWITCH_TAB_ACCEL_NO_DEFAULT (12),
-  SWITCH_TAB_ACCEL_NO_DEFAULT (13),
-  SWITCH_TAB_ACCEL_NO_DEFAULT (14),
-  SWITCH_TAB_ACCEL_NO_DEFAULT (15),
-  SWITCH_TAB_ACCEL_NO_DEFAULT (16),
-  SWITCH_TAB_ACCEL_NO_DEFAULT (17),
-  SWITCH_TAB_ACCEL_NO_DEFAULT (18),
-  SWITCH_TAB_ACCEL_NO_DEFAULT (19),
-  SWITCH_TAB_ACCEL_NO_DEFAULT (20),
-  SWITCH_TAB_ACCEL_NO_DEFAULT (21),
-  SWITCH_TAB_ACCEL_NO_DEFAULT (22),
-  SWITCH_TAB_ACCEL_NO_DEFAULT (23),
-  SWITCH_TAB_ACCEL_NO_DEFAULT (24),
-  SWITCH_TAB_ACCEL_NO_DEFAULT (25),
-  SWITCH_TAB_ACCEL_NO_DEFAULT (26),
-  SWITCH_TAB_ACCEL_NO_DEFAULT (27),
-  SWITCH_TAB_ACCEL_NO_DEFAULT (28),
-  SWITCH_TAB_ACCEL_NO_DEFAULT (29),
-  SWITCH_TAB_ACCEL_NO_DEFAULT (30),
-  SWITCH_TAB_ACCEL_NO_DEFAULT (31),
-  SWITCH_TAB_ACCEL_NO_DEFAULT (32),
-  SWITCH_TAB_ACCEL_NO_DEFAULT (33),
-  SWITCH_TAB_ACCEL_NO_DEFAULT (34),
-  SWITCH_TAB_ACCEL_NO_DEFAULT (35)
+static KeyEntry tabs_entries[] = {
+  ENTRY (N_("Switch to Previous Tab"), KEY_PREV_TAB,       "switch-tab", "i",  "-2"),
+  ENTRY (N_("Switch to Next Tab"),     KEY_NEXT_TAB,       "switch-tab", "i",  "-1"),
+  ENTRY (N_("Move Tab to the Left"),   KEY_MOVE_TAB_LEFT,  "move-tab",   "i",  "-1"),
+  ENTRY (N_("Move Tab to the Right"),  KEY_MOVE_TAB_RIGHT, "move-tab",   "i",  "1" ),
+  ENTRY (N_("Detach Tab"),             KEY_DETACH_TAB,     "detach-tab", NULL, NULL),
+
+#define SWITCH_TAB_ENTRY(num) \
+  ENTRY (NULL, \
+         KEY_SWITCH_TAB_PREFIX # num, \
+         "switch-tab", \
+         "i", \
+         # num)
+
+  SWITCH_TAB_ENTRY (1),  SWITCH_TAB_ENTRY (2),  SWITCH_TAB_ENTRY (3),  SWITCH_TAB_ENTRY (4),
+  SWITCH_TAB_ENTRY (5),  SWITCH_TAB_ENTRY (6),  SWITCH_TAB_ENTRY (7),  SWITCH_TAB_ENTRY (8),
+  SWITCH_TAB_ENTRY (9),  SWITCH_TAB_ENTRY (10), SWITCH_TAB_ENTRY (11), SWITCH_TAB_ENTRY (12),
+  SWITCH_TAB_ENTRY (13), SWITCH_TAB_ENTRY (14), SWITCH_TAB_ENTRY (15), SWITCH_TAB_ENTRY (16),
+  SWITCH_TAB_ENTRY (17), SWITCH_TAB_ENTRY (18), SWITCH_TAB_ENTRY (19), SWITCH_TAB_ENTRY (20),
+  SWITCH_TAB_ENTRY (21), SWITCH_TAB_ENTRY (22), SWITCH_TAB_ENTRY (23), SWITCH_TAB_ENTRY (24),
+  SWITCH_TAB_ENTRY (25), SWITCH_TAB_ENTRY (26), SWITCH_TAB_ENTRY (27), SWITCH_TAB_ENTRY (28),
+  SWITCH_TAB_ENTRY (29), SWITCH_TAB_ENTRY (30), SWITCH_TAB_ENTRY (31), SWITCH_TAB_ENTRY (32),
+  SWITCH_TAB_ENTRY (33), SWITCH_TAB_ENTRY (34), SWITCH_TAB_ENTRY (35)
+
+#undef SWITCH_TAB_ENTRY
 };
 
-#undef SWITCH_TAB_ACCEL
-#undef SWITCH_TAB_ACCEL_NO_DEFAULT
-
 static KeyEntry help_entries[] = {
-  { N_("Contents"), KEY_HELP, ACCEL_PATH_HELP, { 0, GDK_KEY_F1 }, NULL, FALSE, TRUE }
+  ENTRY (N_("Contents"), KEY_HELP, "help", NULL, NULL)
 };
 
+#undef ENTRY
+
 static KeyEntryList all_entries[] =
 {
   { file_entries, G_N_ELEMENTS (file_entries), N_("File") },
@@ -271,23 +187,6 @@ enum
   N_COLUMNS
 };
 
-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 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 GtkTreeStore *edit_keys_store = NULL;
 static GHashTable *settings_key_to_entry;
 static GSettings *keybinding_settings = NULL;
 
@@ -301,42 +200,55 @@ binding_name (guint            keyval,
   return g_strdup ("disabled");
 }
 
-static gboolean
-map_keybinding (GVariant *variant,
-                gpointer *result,
+static void
+key_changed_cb (GSettings *settings,
+                const char *settings_key,
                 gpointer user_data)
 {
-  Keybinding *keybinding = user_data;
+  GtkApplication *application = user_data;
+  KeyEntry *key_entry;
   const char *value;
 
-  value = g_variant_get_string (variant, NULL);
+  _terminal_debug_print (TERMINAL_DEBUG_ACCELS,
+                         "key %s changed\n",
+                         settings_key);
 
-  if (value == NULL || g_str_equal (value, "disabled"))
+  key_entry = g_hash_table_lookup (settings_key_to_entry, settings_key);
+  if (!key_entry)
     {
-      keybinding->mods = 0;
-      keybinding->key = 0;
-      return TRUE;
+      /* 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;
     }
 
-  gtk_accelerator_parse (value, &keybinding->key, &keybinding->mods);
-  if (keybinding->key == 0 && keybinding->mods == 0)
-    return FALSE;
-
-  return TRUE;
+  g_settings_get (settings, settings_key, "&s", &value);
+
+  if (g_str_equal (value, "disabled")) {
+    if (key_entry->installed)
+      gtk_application_remove_accelerator (application,
+                                          key_entry->action_name,
+                                          key_entry->parameter);
+    key_entry->installed = FALSE;
+  } else {
+    gtk_application_add_accelerator (application,
+                                     value,
+                                     key_entry->action_name,
+                                     key_entry->parameter);
+    key_entry->installed = TRUE;
+  }
 }
 
 void
-terminal_accels_init (GSettings *settings)
+terminal_accels_init (GApplication *application,
+                      GSettings *settings)
 {
   guint i, j;
 
   keybinding_settings = g_object_ref (settings);
-  g_signal_connect (keybinding_settings, "changed", G_CALLBACK (keys_change_notify), NULL);
 
   settings_key_to_entry = g_hash_table_new (g_str_hash, g_str_equal);
 
-  notification_group = gtk_accel_group_new ();
-
   /* Initialise names of tab_switch_entries */
   j = 1;
   for (i = 0; i < G_N_ELEMENTS (tabs_entries); i++)
@@ -358,204 +270,80 @@ terminal_accels_init (GSettings *settings)
          KeyEntry *key_entry;
 
          key_entry = &(all_entries[i].key_entry[j]);
+          if (key_entry->action_parameter) {
+            GError *err = NULL;
+            key_entry->parameter = g_variant_parse (key_entry->action_parameter_type,
+                                                    key_entry->action_parameter,
+                                                    NULL, NULL, &err);
+            g_assert_no_error (err);
+
+            g_assert (key_entry->parameter != NULL);
+          }
 
           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_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);
-
-          keys_change_notify (keybinding_settings, key_entry->settings_key, NULL);
+          key_changed_cb (keybinding_settings, key_entry->settings_key, application);
        }
     }
 
-  g_signal_connect (notification_group, "accel-changed",
-                    G_CALLBACK (accel_changed_callback), NULL);
+  g_signal_connect (keybinding_settings, "changed", G_CALLBACK (key_changed_cb), application);
 }
 
 void
 terminal_accels_shutdown (void)
 {
-  g_signal_handlers_disconnect_by_func (keybinding_settings, G_CALLBACK (keys_change_notify), NULL);
+  guint i, j;
 
-  if (sync_idle_id != 0)
-    {
-      g_source_remove (sync_idle_id);
-      sync_idle_id = 0;
+  for (i = 0; i < G_N_ELEMENTS (all_entries); ++i) {
+    for (j = 0; j < all_entries[i].n_elements; ++j) {
+      KeyEntry *key_entry;
 
-      sync_idle_cb (NULL);
+      key_entry = &(all_entries[i].key_entry[j]);
+      if (key_entry->parameter)
+        g_variant_unref (key_entry->parameter);
     }
+  }
+
+  g_signal_handlers_disconnect_by_func (keybinding_settings,
+                                        G_CALLBACK (key_changed_cb),
+                                        g_application_get_default ());
 
   g_clear_pointer (&settings_key_to_entry, (GDestroyNotify) g_hash_table_unref);
-  g_clear_object (&notification_group);
   g_clear_object (&keybinding_settings);
 }
 
 static gboolean
-update_model_foreach (GtkTreeModel *model,
-                     GtkTreePath  *path,
-                     GtkTreeIter  *iter,
-                     gpointer      data)
+foreach_row_cb (GtkTreeModel *model,
+                GtkTreePath  *path,
+                GtkTreeIter  *iter,
+                gpointer      data)
 {
-  KeyEntry *key_entry = NULL;
+  const char *key = data;
+  KeyEntry *key_entry;
 
   gtk_tree_model_get (model, iter,
                      KEYVAL_COLUMN, &key_entry,
                      -1);
 
-  if (key_entry == (KeyEntry *) data)
-    {
-      gtk_tree_model_row_changed (model, path, iter);
-      return TRUE;
-    }
-  return FALSE;
-}
-
-static void
-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);
+  if (key_entry == NULL ||
+      !g_str_equal (key_entry->settings_key, key))
+    return FALSE;
 
-  /* 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);
+  gtk_tree_model_row_changed (model, path, iter);
+  return TRUE;
 }
 
 static void
-accel_changed_callback (GtkAccelGroup  *accel_group,
-                        guint           keyval,
-                        GdkModifierType modifier,
-                        GClosure       *accel_closure,
-                        gpointer        data)
+treeview_key_changed_cb (GSettings *settings,
+                         const char *key,
+                         GtkTreeView *tree_view)
 {
-  /* 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);
+  gtk_tree_model_foreach (gtk_tree_view_get_model (tree_view), foreach_row_cb, (gpointer) key);
 }
 
 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,
-                         "settings sync handler\n");
-  sync_idle_id = 0;
-
-  g_hash_table_foreach (settings_key_to_entry, (GHFunc) sync_key_entry, keybinding_settings);
-
-  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,
                 GtkTreeModel      *model,
@@ -563,34 +351,35 @@ accel_set_func (GtkTreeViewColumn *tree_column,
                 gpointer           data)
 {
   KeyEntry *ke;
-  
+
   gtk_tree_model_get (model, iter,
                       KEYVAL_COLUMN, &ke,
                       -1);
 
-  if (ke == NULL)
+  if (ke == NULL) {
     /* This is a title row */
     g_object_set (cell,
                   "visible", FALSE,
                  NULL);
-  else
+  } else {
+    const char *value;
+    guint key;
+    GdkModifierType mods;
+    gboolean writable;
+
+    g_settings_get (keybinding_settings, ke->settings_key, "&s", &value);
+    gtk_accelerator_parse (value, &key, &mods);
+
+    writable = g_settings_is_writable (keybinding_settings, ke->settings_key);
+
     g_object_set (cell,
                   "visible", TRUE,
-                  "sensitive", ke->accel_path_unlocked,
-                  "editable", ke->accel_path_unlocked,
-                  "accel-key", ke->settings_keybinding.key,
-                  "accel-mods", ke->settings_keybinding.mods,
+                  "sensitive", writable,
+                  "editable", writable,
+                  "accel-key", key,
+                  "accel-mods", mods,
                  NULL);
-}
-
-static void
-treeview_accel_changed_cb (GtkAccelGroup  *accel_group,
-                           guint keyval,
-                           GdkModifierType modifier,
-                           GClosure *accel_closure,
-                           GtkTreeModel *model)
-{
-  gtk_tree_model_foreach (model, update_model_foreach, accel_closure->data);
+  }
 }
 
 static void
@@ -605,8 +394,6 @@ accel_edited_callback (GtkCellRendererAccel *cell,
   GtkTreePath *path;
   GtkTreeIter iter;
   KeyEntry *ke;
-  GtkAccelGroupEntry *entries;
-  guint n_entries;
   char *str;
 
   model = gtk_tree_view_get_model (view);
@@ -627,61 +414,7 @@ accel_edited_callback (GtkCellRendererAccel *cell,
   if (ke == NULL)
     return;
 
-  /* 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);
 }
@@ -715,16 +448,7 @@ accel_cleared_callback (GtkCellRendererAccel *cell,
   if (ke == NULL)
     return;
 
-  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);
 }
@@ -733,8 +457,9 @@ static void
 treeview_destroy_cb (GtkWidget *tree_view,
                      gpointer user_data)
 {
-  g_signal_handlers_disconnect_by_func (notification_group, G_CALLBACK (treeview_accel_changed_cb), 
user_data);
-  edit_keys_store = NULL;
+  g_signal_handlers_disconnect_by_func (keybinding_settings,
+                                        G_CALLBACK (treeview_key_changed_cb),
+                                        tree_view);
 }
 
 #ifdef GNOME_ENABLE_DEBUG
@@ -784,7 +509,7 @@ terminal_accels_fill_treeview (GtkWidget *tree_view)
 
   /* Add the data */
 
-  tree = edit_keys_store = gtk_tree_store_new (N_COLUMNS, G_TYPE_STRING, G_TYPE_POINTER);
+  tree = gtk_tree_store_new (N_COLUMNS, G_TYPE_STRING, G_TYPE_POINTER);
 
 #ifdef GNOME_ENABLE_DEBUG
   _TERMINAL_DEBUG_IF (TERMINAL_DEBUG_ACCELS)
@@ -818,9 +543,8 @@ terminal_accels_fill_treeview (GtkWidget *tree_view)
 
   gtk_tree_view_expand_all (GTK_TREE_VIEW (tree_view));
 
-  g_signal_connect (notification_group, "accel-changed",
-                    G_CALLBACK (treeview_accel_changed_cb), tree);
-
+  g_signal_connect (keybinding_settings, "changed",
+                    G_CALLBACK (treeview_key_changed_cb), tree_view);
   g_signal_connect (tree_view, "destroy",
                     G_CALLBACK (treeview_destroy_cb), tree);
 }
diff --git a/src/terminal-accels.h b/src/terminal-accels.h
index 86e5be6..bd28d71 100644
--- a/src/terminal-accels.h
+++ b/src/terminal-accels.h
@@ -23,7 +23,8 @@
 
 G_BEGIN_DECLS
 
-void terminal_accels_init (GSettings *settings);
+void terminal_accels_init (GApplication *application,
+                           GSettings *settings);
  
 void terminal_accels_shutdown (void);
 
diff --git a/src/terminal-app.c b/src/terminal-app.c
index 2075562..3bdc03f 100644
--- a/src/terminal-app.c
+++ b/src/terminal-app.c
@@ -377,7 +377,7 @@ terminal_app_init (TerminalApp *app)
                     app);
 
   settings = g_settings_get_child (app->global_settings, "keybindings");
-  terminal_accels_init (settings);
+  terminal_accels_init (G_APPLICATION (app), settings);
   g_object_unref (settings);
 }
 
diff --git a/src/terminal-window.c b/src/terminal-window.c
index 9cce9cc..e91067a 100644
--- a/src/terminal-window.c
+++ b/src/terminal-window.c
@@ -211,6 +211,7 @@ static gboolean find_larger_zoom_factor  (double  current,
                                           double *found);
 static gboolean find_smaller_zoom_factor (double  current,
                                           double *found);
+static void terminal_window_update_zoom_sensitivity (TerminalWindow *window);
 
 static void terminal_window_show (GtkWidget *widget);
 
@@ -230,6 +231,760 @@ static void terminal_window_update_size (TerminalWindow *window);
 
 G_DEFINE_TYPE (TerminalWindow, terminal_window, GTK_TYPE_APPLICATION_WINDOW)
 
+/* Clipboard helpers */
+
+typedef struct {
+  TerminalScreen *screen;
+  gboolean uris_as_paths;
+} PasteData;
+
+static void
+clipboard_uris_received_cb (GtkClipboard *clipboard,
+                            /* const */ char **uris,
+                            PasteData *data)
+{
+  char *text;
+  gsize len;
+
+  if (!uris) {
+    g_object_unref (data->screen);
+    g_slice_free (PasteData, data);
+    return;
+  }
+
+  /* This potentially modifies the strings in |uris| but that's ok */
+  if (data->uris_as_paths)
+    terminal_util_transform_uris_to_quoted_fuse_paths (uris);
+
+  text = terminal_util_concat_uris (uris, &len);
+  vte_terminal_feed_child (VTE_TERMINAL (data->screen), text, len);
+  g_free (text);
+
+  g_object_unref (data->screen);
+  g_slice_free (PasteData, data);
+}
+
+static void
+clipboard_targets_received_cb (GtkClipboard *clipboard,
+                               GdkAtom *targets,
+                               int n_targets,
+                               PasteData *data)
+{
+  if (!targets) {
+    g_object_unref (data->screen);
+    g_slice_free (PasteData, data);
+    return;
+  }
+
+  if (gtk_targets_include_uri (targets, n_targets)) {
+    gtk_clipboard_request_uris (clipboard,
+                                (GtkClipboardURIReceivedFunc) clipboard_uris_received_cb,
+                                data);
+    return;
+  } else /* if (gtk_targets_include_text (targets, n_targets)) */ {
+    vte_terminal_paste_clipboard (VTE_TERMINAL (data->screen));
+  }
+
+  g_object_unref (data->screen);
+  g_slice_free (PasteData, data);
+}
+
+/* Zoom helpers */
+
+static const double zoom_factors[] = {
+  TERMINAL_SCALE_MINIMUM,
+  TERMINAL_SCALE_XXXXX_SMALL,
+  TERMINAL_SCALE_XXXX_SMALL,
+  TERMINAL_SCALE_XXX_SMALL,
+  PANGO_SCALE_XX_SMALL,
+  PANGO_SCALE_X_SMALL,
+  PANGO_SCALE_SMALL,
+  PANGO_SCALE_MEDIUM,
+  PANGO_SCALE_LARGE,
+  PANGO_SCALE_X_LARGE,
+  PANGO_SCALE_XX_LARGE,
+  TERMINAL_SCALE_XXX_LARGE,
+  TERMINAL_SCALE_XXXX_LARGE,
+  TERMINAL_SCALE_XXXXX_LARGE,
+  TERMINAL_SCALE_MAXIMUM
+};
+
+static gboolean
+find_larger_zoom_factor (double  current,
+                         double *found)
+{
+  guint i;
+
+  for (i = 0; i < G_N_ELEMENTS (zoom_factors); ++i)
+    {
+      /* Find a font that's larger than this one */
+      if ((zoom_factors[i] - current) > 1e-6)
+        {
+          *found = zoom_factors[i];
+          return TRUE;
+        }
+    }
+  
+  return FALSE;
+}
+
+static gboolean
+find_smaller_zoom_factor (double  current,
+                          double *found)
+{
+  int i;
+  
+  i = (int) G_N_ELEMENTS (zoom_factors) - 1;
+  while (i >= 0)
+    {
+      /* Find a font that's smaller than this one */
+      if ((current - zoom_factors[i]) > 1e-6)
+        {
+          *found = zoom_factors[i];
+          return TRUE;
+        }
+      
+      --i;
+    }
+
+  return FALSE;
+}
+
+/* GAction callbacks */
+
+// FIXMEchpe: profile as parameter too
+static void
+action_new_terminal_cb (GSimpleAction *action,
+                        GVariant *parameter,
+                        gpointer user_data)
+{
+  TerminalWindow *window = user_data;
+  TerminalWindowPrivate *priv = window->priv;
+  TerminalApp *app;
+  GSettings *profile;
+  char *new_working_directory;
+  const char *mode_str;
+  TerminalNewTerminalMode mode;
+  GdkModifierType modifiers;
+
+  g_assert (TERMINAL_IS_WINDOW (window));
+
+  app = terminal_app_get ();
+  profile = g_object_get_data (G_OBJECT (action), PROFILE_DATA_KEY);
+  if (!profile)
+    profile = terminal_screen_get_profile (priv->active_screen);
+  if (!profile)
+    return;
+
+  g_variant_get (parameter, "&s", &mode_str);
+  if (g_str_equal (mode_str, "tab"))
+    mode = TERMINAL_NEW_TERMINAL_MODE_TAB;
+  else if (g_str_equal (mode_str, "window"))
+    mode = TERMINAL_NEW_TERMINAL_MODE_WINDOW;
+  else {
+    mode = g_settings_get_enum (terminal_app_get_global_settings (app),
+                                TERMINAL_SETTING_NEW_TERMINAL_MODE_KEY);
+    if (gtk_get_current_event_state (&modifiers) &&
+        (modifiers & gtk_accelerator_get_default_mod_mask () & GDK_CONTROL_MASK)) {
+      /* Invert */
+      if (mode == TERMINAL_NEW_TERMINAL_MODE_WINDOW)
+        mode = TERMINAL_NEW_TERMINAL_MODE_TAB;
+      else
+        mode = TERMINAL_NEW_TERMINAL_MODE_WINDOW;
+    }
+  }
+
+  if (mode == TERMINAL_NEW_TERMINAL_MODE_WINDOW)
+    window = terminal_app_new_window (app, gtk_widget_get_screen (GTK_WIDGET (window)));
+
+  new_working_directory = terminal_screen_get_current_dir (priv->active_screen);
+  terminal_app_new_terminal (app, window, profile,
+                             NULL, NULL,
+                             new_working_directory,
+                             terminal_screen_get_initial_environment (priv->active_screen),
+                             1.0);
+  g_free (new_working_directory);
+
+  if (mode == TERMINAL_NEW_TERMINAL_MODE_WINDOW)
+    gtk_window_present (GTK_WINDOW (window));
+}
+
+static void
+file_new_terminal_callback (GtkAction *action,
+                            TerminalWindow *window)
+{
+  const char *name;
+  GVariant *param;
+
+  name = gtk_action_get_name (action);
+  if (g_str_has_prefix (name, "FileNewTab"))
+    param = g_variant_new_string ("tab");
+  else if (g_str_has_prefix (name, "FileNewWindow"))
+    param = g_variant_new_string ("window");
+  else
+    param = g_variant_new_string ("default");
+
+  g_action_activate (g_action_map_lookup_action (G_ACTION_MAP (window), "new-terminal"),
+                     param);
+}
+
+static void
+action_new_profile_cb (GSimpleAction *action,
+                       GVariant *parameter,
+                       gpointer user_data)
+{
+  TerminalWindow *window = user_data;
+  TerminalWindowPrivate *priv = window->priv;
+  
+  terminal_app_new_profile (terminal_app_get (),
+                            terminal_screen_get_profile (priv->active_screen),
+                            GTK_WINDOW (window));
+}
+
+
+#ifdef ENABLE_SAVE
+static void
+save_contents_dialog_on_response (GtkDialog *dialog, gint response_id, gpointer terminal)
+{
+  GtkWindow *parent;
+  gchar *filename_uri = NULL;
+  GFile *file;
+  GOutputStream *stream;
+  GError *error = NULL;
+
+  if (response_id != GTK_RESPONSE_ACCEPT)
+    {
+      gtk_widget_destroy (GTK_WIDGET (dialog));
+      return;
+    }
+
+  parent = (GtkWindow*) gtk_widget_get_ancestor (GTK_WIDGET (terminal), GTK_TYPE_WINDOW);
+  filename_uri = gtk_file_chooser_get_uri (GTK_FILE_CHOOSER (dialog));
+
+  gtk_widget_destroy (GTK_WIDGET (dialog));
+
+  if (filename_uri == NULL)
+    return;
+
+  file = g_file_new_for_uri (filename_uri);
+  stream = G_OUTPUT_STREAM (g_file_replace (file, NULL, FALSE, G_FILE_CREATE_NONE, NULL, &error));
+
+  if (stream)
+    {
+      /* XXX
+       * FIXME
+       * This is a sync operation.
+       * Should be replaced with the async version when vte implements that.
+       */
+      vte_terminal_write_contents (terminal, stream,
+                                  VTE_TERMINAL_WRITE_DEFAULT,
+                                  NULL, &error);
+      g_object_unref (stream);
+    }
+
+  if (error)
+    {
+      terminal_util_show_error_dialog (parent, NULL, error,
+                                      "%s", _("Could not save contents"));
+      g_error_free (error);
+    }
+
+  g_object_unref(file);
+  g_free(filename_uri);
+}
+#endif /* ENABLE_SAVE */
+
+static void
+action_save_contents_cb (GSimpleAction *action,
+                         GVariant *parameter,
+                         gpointer user_data)
+{
+#ifdef ENABLE_SAVE
+  TerminalWindow *window = user_data;
+  GtkWidget *dialog = NULL;
+  TerminalWindowPrivate *priv = window->priv;
+  VteTerminal *terminal;
+
+  if (!priv->active_screen)
+    return;
+
+  terminal = VTE_TERMINAL (priv->active_screen);
+  g_return_if_fail (VTE_IS_TERMINAL (terminal));
+
+  dialog = gtk_file_chooser_dialog_new (_("Save as…"),
+                                        GTK_WINDOW(window),
+                                        GTK_FILE_CHOOSER_ACTION_SAVE,
+                                        GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+                                        GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
+                                        NULL);
+
+  gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (dialog), TRUE);
+  /* XXX where should we save to? */
+  gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), g_get_user_special_dir 
(G_USER_DIRECTORY_DESKTOP));
+
+  gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW(window));
+  gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
+  gtk_window_set_destroy_with_parent (GTK_WINDOW (dialog), TRUE);
+
+  g_signal_connect (dialog, "response", G_CALLBACK (save_contents_dialog_on_response), terminal);
+  g_signal_connect (dialog, "delete_event", G_CALLBACK (terminal_util_dialog_response_on_delete), NULL);
+
+  gtk_window_present (GTK_WINDOW (dialog));
+#endif /* ENABLE_SAVE */
+}
+
+static void
+file_save_contents_callback (GtkAction *action,
+                             TerminalWindow *window)
+{
+  g_action_activate (g_action_map_lookup_action (G_ACTION_MAP (window), "save-contents"),
+                     NULL);
+}
+
+static void
+action_close_cb (GSimpleAction *action,
+                 GVariant *parameter,
+                 gpointer user_data)
+{
+  TerminalWindow *window = user_data;
+  TerminalWindowPrivate *priv = window->priv;
+  TerminalScreen *screen;
+  const char *mode_str;
+
+  g_assert (parameter != NULL);
+  g_variant_get (parameter, "&s", &mode_str);
+
+  if (g_str_equal (mode_str, "tab"))
+    screen = priv->active_screen;
+  else if (g_str_equal (mode_str, "window"))
+    screen = NULL;
+  else
+    g_assert_not_reached ();
+
+  if (confirm_close_window_or_tab (window, screen))
+    return;
+
+  if (screen)
+    terminal_window_remove_screen (window, screen);
+  else
+    gtk_widget_destroy (GTK_WIDGET (window));
+}
+
+static void
+action_copy_cb (GSimpleAction *action,
+                GVariant *parameter,
+                gpointer user_data)
+{
+  TerminalWindow *window = user_data;
+  TerminalWindowPrivate *priv = window->priv;
+
+  if (!priv->active_screen)
+    return;
+      
+  vte_terminal_copy_clipboard (VTE_TERMINAL (priv->active_screen));
+}
+
+static void
+edit_copy_callback (GtkAction *action,
+                    TerminalWindow *window)
+{
+  g_action_activate (g_action_map_lookup_action (G_ACTION_MAP (window), "copy"),
+                     NULL);
+}
+
+static void
+action_paste_cb (GSimpleAction *action,
+                 GVariant *parameter,
+                 gpointer user_data)
+{
+  TerminalWindow *window = user_data;
+  TerminalWindowPrivate *priv = window->priv;
+  GtkClipboard *clipboard;
+  PasteData *data;
+  const char *mode;
+
+  g_assert (parameter != NULL);
+
+  if (!priv->active_screen)
+    return;
+
+  g_variant_get (parameter, "&s", &mode);
+
+  data = g_slice_new (PasteData);
+  data->screen = g_object_ref (priv->active_screen);
+  data->uris_as_paths = g_str_equal (mode, "uri");
+
+  clipboard = gtk_widget_get_clipboard (GTK_WIDGET (window), GDK_SELECTION_CLIPBOARD);
+  gtk_clipboard_request_targets (clipboard,
+                                 (GtkClipboardTargetsReceivedFunc) clipboard_targets_received_cb,
+                                 data);
+}
+
+static void
+edit_paste_callback (GtkAction *action,
+                     TerminalWindow *window)
+{
+  const char *name;
+  GVariant *parameter;
+
+  name = gtk_action_get_name (action);
+  if ((name == I_("EditPasteURIPaths") || name == I_("PopupPasteURIPaths")))
+    parameter = g_variant_new_string ("uri");
+  else
+    parameter = g_variant_new_string ("normal");
+
+  g_action_activate (g_action_map_lookup_action (G_ACTION_MAP (window), "paste"),
+                     parameter);
+}
+
+static void
+action_select_all_cb (GSimpleAction *action,
+                      GVariant *parameter,
+                      gpointer user_data)
+{
+  TerminalWindow *window = user_data;
+  TerminalWindowPrivate *priv = window->priv;
+
+  if (!priv->active_screen)
+    return;
+
+  vte_terminal_select_all (VTE_TERMINAL (priv->active_screen));
+}
+
+static void
+edit_select_all_callback (GtkAction *action,
+                          TerminalWindow *window)
+{
+  g_action_activate (g_action_map_lookup_action (G_ACTION_MAP (window), "select-all"),
+                     NULL);
+}
+
+static void
+action_reset_cb (GSimpleAction *action,
+                 GVariant *parameter,
+                 gpointer user_data)
+{
+  TerminalWindow *window = user_data;
+  TerminalWindowPrivate *priv = window->priv;
+
+  g_assert (parameter != NULL);
+
+  if (priv->active_screen == NULL)
+    return;
+
+  vte_terminal_reset (VTE_TERMINAL (priv->active_screen),
+                      TRUE,
+                      g_variant_get_boolean (parameter));
+}
+
+static void
+action_switch_tab_cb (GSimpleAction *action,
+                      GVariant *parameter,
+                      gpointer user_data)
+{
+  TerminalWindow *window = user_data;
+  TerminalWindowPrivate *priv = window->priv;
+  int value;
+
+  g_assert (parameter != NULL);
+
+  value = g_variant_get_int32 (parameter);
+
+  if (value > 0)
+    terminal_mdi_container_set_active_screen_num (priv->mdi_container, value - 1);
+  else
+    terminal_mdi_container_change_screen (priv->mdi_container, value == -2 ? -1 : 1);
+}
+
+static void
+action_move_tab_cb (GSimpleAction *action,
+                    GVariant *parameter,
+                    gpointer user_data)
+{
+  TerminalWindow *window = user_data;
+  TerminalWindowPrivate *priv = window->priv;
+  int value;
+  
+  g_assert (parameter != NULL);
+
+  value = g_variant_get_int32 (parameter);
+  terminal_mdi_container_reorder_screen (priv->mdi_container,
+                                         terminal_mdi_container_get_active_screen (priv->mdi_container),
+                                         value);
+}
+
+static void
+terminal_set_title_dialog_response_cb (GtkWidget *dialog,
+                                       int response,
+                                       TerminalScreen *screen)
+{
+  if (response == GTK_RESPONSE_OK)
+    {
+      GtkEntry *entry;
+      const char *text;
+
+      entry = GTK_ENTRY (g_object_get_data (G_OBJECT (dialog), "title-entry"));
+      text = gtk_entry_get_text (entry);
+      terminal_screen_set_user_title (screen, text);
+    }
+
+  gtk_widget_destroy (dialog);
+}
+
+static const char *
+terminal_screen_get_user_title (TerminalScreen *screen)
+{
+  return terminal_screen_get_raw_title (screen);
+}
+
+static void
+action_set_title_cb (GSimpleAction *action,
+                     GVariant *parameter,
+                     gpointer user_data)
+{
+  TerminalWindow *window = user_data;
+  TerminalWindowPrivate *priv = window->priv;
+  GtkWidget *dialog, *message_area, *hbox, *label, *entry;
+
+  if (priv->active_screen == NULL)
+    return;
+
+  /* FIXME: hook the screen up so this dialogue closes if the terminal screen closes */
+
+  dialog = gtk_message_dialog_new (GTK_WINDOW (window),
+                                   GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
+                                   GTK_MESSAGE_OTHER,
+                                   GTK_BUTTONS_OK_CANCEL,
+                                   "%s", "");
+
+  gtk_window_set_title (GTK_WINDOW (dialog), _("Set Title"));
+  gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);
+  gtk_window_set_role (GTK_WINDOW (dialog), "gnome-terminal-change-title");
+  gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
+  /* Alternative button order was set automatically by GtkMessageDialog */
+
+  g_signal_connect (dialog, "response",
+                    G_CALLBACK (terminal_set_title_dialog_response_cb), priv->active_screen);
+  g_signal_connect (dialog, "delete-event",
+                    G_CALLBACK (terminal_util_dialog_response_on_delete), NULL);
+
+  message_area = gtk_message_dialog_get_message_area (GTK_MESSAGE_DIALOG (dialog));
+  gtk_container_foreach (GTK_CONTAINER (message_area), (GtkCallback) gtk_widget_hide, NULL);
+
+  hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12);
+  gtk_box_pack_start (GTK_BOX (message_area), hbox, FALSE, FALSE, 0);
+
+  label = gtk_label_new_with_mnemonic (_("_Title:"));
+  gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+  gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
+
+  entry = gtk_entry_new ();
+  gtk_entry_set_width_chars (GTK_ENTRY (entry), 32);
+  gtk_entry_set_activates_default (GTK_ENTRY (entry), TRUE);
+  gtk_label_set_mnemonic_widget (GTK_LABEL (label), entry);
+  gtk_box_pack_start (GTK_BOX (hbox), entry, TRUE, TRUE, 0);
+  gtk_widget_show_all (hbox);
+
+  gtk_widget_grab_focus (entry);
+  gtk_entry_set_text (GTK_ENTRY (entry), terminal_screen_get_user_title (priv->active_screen));
+  gtk_editable_select_region (GTK_EDITABLE (entry), 0, -1);
+  g_object_set_data (G_OBJECT (dialog), "title-entry", entry);
+
+  gtk_window_present (GTK_WINDOW (dialog));
+}
+
+static void
+terminal_set_title_callback (GtkAction *action,
+                             TerminalWindow *window)
+{
+  g_action_activate (g_action_map_lookup_action (G_ACTION_MAP (window), "set-title"),
+                     NULL);
+}
+
+static void
+action_zoom_cb (GSimpleAction *action,
+                GVariant *parameter,
+                gpointer user_data)
+{
+  TerminalWindow *window = user_data;
+  TerminalWindowPrivate *priv = window->priv;
+  int value;
+  double zoom;
+  
+  if (priv->active_screen == NULL)
+    return;
+
+  g_assert (parameter != NULL);
+
+  value = g_variant_get_int32 (parameter);
+
+  if (value == 0) {
+    zoom = PANGO_SCALE_MEDIUM;
+  } else if (value == 1) {
+    zoom = terminal_screen_get_font_scale (priv->active_screen);
+    if (!find_larger_zoom_factor (zoom, &zoom))
+      return;
+  } else if (value == -1) {
+    zoom = terminal_screen_get_font_scale (priv->active_screen);
+    if (!find_smaller_zoom_factor (zoom, &zoom))
+      return;
+  } else
+    g_assert_not_reached ();
+
+  terminal_screen_set_font_scale (priv->active_screen, zoom);
+  terminal_window_update_zoom_sensitivity (window);
+}
+
+static void
+view_zoom_in_callback (GtkAction *action,
+                       TerminalWindow *window)
+{
+  g_action_activate (g_action_map_lookup_action (G_ACTION_MAP (window), "zoom"),
+                     g_variant_new_int32 (1));
+}
+
+static void
+view_zoom_out_callback (GtkAction *action,
+                        TerminalWindow *window)
+{
+  g_action_activate (g_action_map_lookup_action (G_ACTION_MAP (window), "zoom"),
+                     g_variant_new_int32 (-1));
+}
+
+static void
+view_zoom_normal_callback (GtkAction *action,
+                           TerminalWindow *window)
+{
+  g_action_activate (g_action_map_lookup_action (G_ACTION_MAP (window), "zoom"),
+                     g_variant_new_int32 (0));
+}
+
+static void
+action_detach_tab_cb (GSimpleAction *action,
+                      GVariant *parameter,
+                      gpointer user_data)
+{
+  TerminalWindow *window = user_data;
+  TerminalWindowPrivate *priv = window->priv;
+  TerminalApp *app;
+  TerminalWindow *new_window;
+  TerminalScreen *screen;
+  char *geometry;
+  int width, height;
+
+  app = terminal_app_get ();
+
+  screen = priv->active_screen;
+
+  /* FIXME: this seems wrong if tabs are shown in the window */
+  terminal_screen_get_size (screen, &width, &height);
+  geometry = g_strdup_printf ("%dx%d", width, height);
+
+  new_window = terminal_app_new_window (app, gtk_widget_get_screen (GTK_WIDGET (window)));
+
+  terminal_window_move_screen (window, new_window, screen, -1);
+
+  terminal_window_parse_geometry (new_window, geometry);
+  g_free (geometry);
+
+  gtk_window_present_with_time (GTK_WINDOW (new_window), gtk_get_current_event_time ());
+}
+
+static void
+tabs_detach_tab_callback (GtkAction *action,
+                          TerminalWindow *window)
+{
+  g_action_activate (g_action_map_lookup_action (G_ACTION_MAP (window), "detach-tab"),
+                     NULL);
+}
+
+static void
+action_help_cb (GSimpleAction *action,
+                GVariant *parameter,
+                gpointer user_data)
+{
+  TerminalWindow *window = user_data;
+
+  terminal_util_show_help (NULL, GTK_WINDOW (window));
+}
+
+static void
+action_about_cb (GSimpleAction *action,
+                 GVariant *parameter,
+                 gpointer user_data)
+{
+  TerminalWindow *window = user_data;
+
+  terminal_util_show_about (GTK_WINDOW (window));
+}
+
+static void
+action_preferences_cb (GSimpleAction *action,
+                       GVariant *parameter,
+                       gpointer user_data)
+{
+  TerminalWindow *window = user_data;
+
+  terminal_app_edit_preferences (terminal_app_get (), GTK_WINDOW (window));
+}
+
+static void
+action_edit_profile_cb (GSimpleAction *action,
+                        GVariant *parameter,
+                        gpointer user_data)
+{
+  TerminalWindow *window = user_data;
+  TerminalWindowPrivate *priv = window->priv;
+
+  terminal_app_edit_profile (terminal_app_get (),
+                             terminal_screen_get_profile (priv->active_screen),
+                             GTK_WINDOW (window),
+                             NULL);
+}
+
+static void
+action_toggle_state_cb (GSimpleAction *saction,
+                        GVariant *parameter,
+                        gpointer user_data)
+{
+  GAction *action = G_ACTION (saction);
+  GVariant *state;
+
+  state = g_action_get_state (action);
+  g_action_change_state (action, g_variant_new_boolean (!g_variant_get_boolean (state)));
+  g_variant_unref (state);
+}
+
+static void
+action_show_menubar_state_cb (GSimpleAction *action,
+                              GVariant *state,
+                              gpointer user_data)
+{
+  TerminalWindow *window = user_data;
+
+  g_simple_action_set_state (action, state);
+
+  terminal_window_set_menubar_visible (window, g_variant_get_boolean (state));
+}
+
+static void
+action_fullscreen_state_cb (GSimpleAction *action,
+                            GVariant *state,
+                            gpointer user_data)
+{
+  TerminalWindow *window = user_data;
+
+  g_simple_action_set_state (action, state);
+
+  if (!gtk_widget_get_realized (GTK_WIDGET (window)))
+    return;
+
+  if (g_variant_get_boolean (state))
+    gtk_window_fullscreen (GTK_WINDOW (window));
+  else
+    gtk_window_unfullscreen (GTK_WINDOW (window));
+}
+
 /* Menubar mnemonics & accel settings handling */
 
 static void
@@ -1551,6 +2306,28 @@ terminal_window_encoding_list_changed_cb (TerminalApp *app,
 static void
 terminal_window_init (TerminalWindow *window)
 {
+  const GActionEntry gaction_entries[] = {
+    { "new-terminal",        action_new_terminal_cb,   "s",  NULL, NULL },
+    { "new-profile",         action_new_profile_cb,    NULL, NULL, NULL },
+    { "save-contents",       action_save_contents_cb,  NULL, NULL, NULL },
+    { "close",               action_close_cb,          "s",  NULL, NULL },
+    { "copy",                action_copy_cb,           NULL, NULL, NULL },
+    { "paste",               action_paste_cb,          "s",  NULL, NULL },
+    { "select-all",          action_select_all_cb,     NULL, NULL, NULL },
+    { "reset",               action_reset_cb,          "b",  NULL, NULL },
+    { "switch-tab",          action_switch_tab_cb,     "i",  NULL, NULL },
+    { "move-tab",            action_move_tab_cb,       "i",  NULL, NULL },
+    { "set-title",           action_set_title_cb,      NULL, NULL, NULL },
+    { "zoom",                action_zoom_cb,           "i",  NULL, NULL },
+    { "detach-tab",          action_detach_tab_cb,     NULL, NULL, NULL },
+    { "help",                action_help_cb,           NULL, NULL, NULL },
+    { "about",               action_about_cb,          NULL, NULL, NULL },
+    { "preferences",         action_preferences_cb,    NULL, NULL, NULL },
+    { "edit-profile",        action_edit_profile_cb,   "s",  NULL, NULL },
+    { "show-menubar",        action_toggle_state_cb,   NULL, "true",  action_show_menubar_state_cb },
+    { "fullscreen",          action_toggle_state_cb,   NULL, "false", action_fullscreen_state_cb   },
+  };
+
   const GtkActionEntry menu_entries[] =
     {
       /* Toplevel */
@@ -1806,7 +2583,12 @@ terminal_window_init (TerminalWindow *window)
   priv->old_char_width = -1;
   priv->old_char_height = -1;
   priv->old_geometry_widget = NULL;
-  
+
+  /* GAction setup */
+  g_action_map_add_action_entries (G_ACTION_MAP (window),
+                                   gaction_entries, G_N_ELEMENTS (gaction_entries),
+                                   window);
+
   /* Create the UI manager */
   manager = priv->ui_manager = gtk_ui_manager_new ();
 
@@ -2692,60 +3474,6 @@ terminal_window_update_geometry (TerminalWindow *window)
 }
 
 static void
-file_new_terminal_callback (GtkAction *action,
-                            TerminalWindow *window)
-{
-  TerminalWindowPrivate *priv = window->priv;
-  TerminalApp *app;
-  GSettings *profile;
-  char *new_working_directory;
-  const char *name;
-  TerminalNewTerminalMode mode;
-  GdkModifierType modifiers;
-
-  g_assert (TERMINAL_IS_WINDOW (window));
-
-  app = terminal_app_get ();
-  profile = g_object_get_data (G_OBJECT (action), PROFILE_DATA_KEY);
-  if (!profile)
-    profile = terminal_screen_get_profile (priv->active_screen);
-  if (!profile)
-    return;
-
-  name = gtk_action_get_name (action);
-  if (g_str_has_prefix (name, "FileNewTab"))
-    mode = TERMINAL_NEW_TERMINAL_MODE_TAB;
-  else if (g_str_has_prefix (name, "FileNewWindow"))
-    mode = TERMINAL_NEW_TERMINAL_MODE_WINDOW;
-  else {
-    mode = g_settings_get_enum (terminal_app_get_global_settings (app),
-                                TERMINAL_SETTING_NEW_TERMINAL_MODE_KEY);
-    if (gtk_get_current_event_state (&modifiers) &&
-        (modifiers & gtk_accelerator_get_default_mod_mask () & GDK_CONTROL_MASK)) {
-      /* Invert */
-      if (mode == TERMINAL_NEW_TERMINAL_MODE_WINDOW)
-        mode = TERMINAL_NEW_TERMINAL_MODE_TAB;
-      else
-        mode = TERMINAL_NEW_TERMINAL_MODE_WINDOW;
-    }
-  }
-
-  if (mode == TERMINAL_NEW_TERMINAL_MODE_WINDOW)
-    window = terminal_app_new_window (app, gtk_widget_get_screen (GTK_WIDGET (window)));
-
-  new_working_directory = terminal_screen_get_current_dir (priv->active_screen);
-  terminal_app_new_terminal (app, window, profile,
-                             NULL, NULL,
-                             new_working_directory,
-                             terminal_screen_get_initial_environment (priv->active_screen),
-                             1.0);
-  g_free (new_working_directory);
-
-  if (mode == TERMINAL_NEW_TERMINAL_MODE_WINDOW)
-    gtk_window_present (GTK_WINDOW (window));
-}
-
-static void
 confirm_close_response_cb (GtkWidget *dialog,
                            int response,
                            TerminalWindow *window)
@@ -2865,95 +3593,6 @@ file_close_window_callback (GtkAction *action,
   terminal_window_request_close (window);
 }
 
-#ifdef ENABLE_SAVE
-static void
-save_contents_dialog_on_response (GtkDialog *dialog, gint response_id, gpointer terminal)
-{
-  GtkWindow *parent;
-  gchar *filename_uri = NULL;
-  GFile *file;
-  GOutputStream *stream;
-  GError *error = NULL;
-
-  if (response_id != GTK_RESPONSE_ACCEPT)
-    {
-      gtk_widget_destroy (GTK_WIDGET (dialog));
-      return;
-    }
-
-  parent = (GtkWindow*) gtk_widget_get_ancestor (GTK_WIDGET (terminal), GTK_TYPE_WINDOW);
-  filename_uri = gtk_file_chooser_get_uri (GTK_FILE_CHOOSER (dialog));
-
-  gtk_widget_destroy (GTK_WIDGET (dialog));
-
-  if (filename_uri == NULL)
-    return;
-
-  file = g_file_new_for_uri (filename_uri);
-  stream = G_OUTPUT_STREAM (g_file_replace (file, NULL, FALSE, G_FILE_CREATE_NONE, NULL, &error));
-
-  if (stream)
-    {
-      /* XXX
-       * FIXME
-       * This is a sync operation.
-       * Should be replaced with the async version when vte implements that.
-       */
-      vte_terminal_write_contents (terminal, stream,
-                                  VTE_TERMINAL_WRITE_DEFAULT,
-                                  NULL, &error);
-      g_object_unref (stream);
-    }
-
-  if (error)
-    {
-      terminal_util_show_error_dialog (parent, NULL, error,
-                                      "%s", _("Could not save contents"));
-      g_error_free (error);
-    }
-
-  g_object_unref(file);
-  g_free(filename_uri);
-}
-#endif /* ENABLE_SAVE */
-
-static void
-file_save_contents_callback (GtkAction *action,
-                             TerminalWindow *window)
-{
-#ifdef ENABLE_SAVE
-  GtkWidget *dialog = NULL;
-  TerminalWindowPrivate *priv = window->priv;
-  VteTerminal *terminal;
-
-  if (!priv->active_screen)
-    return;
-
-  terminal = VTE_TERMINAL (priv->active_screen);
-  g_return_if_fail (VTE_IS_TERMINAL (terminal));
-
-  dialog = gtk_file_chooser_dialog_new (_("Save as…"),
-                                        GTK_WINDOW(window),
-                                        GTK_FILE_CHOOSER_ACTION_SAVE,
-                                        GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
-                                        GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
-                                        NULL);
-
-  gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (dialog), TRUE);
-  /* XXX where should we save to? */
-  gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), g_get_user_special_dir 
(G_USER_DIRECTORY_DESKTOP));
-
-  gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW(window));
-  gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
-  gtk_window_set_destroy_with_parent (GTK_WINDOW (dialog), TRUE);
-
-  g_signal_connect (dialog, "response", G_CALLBACK (save_contents_dialog_on_response), terminal);
-  g_signal_connect (dialog, "delete_event", G_CALLBACK (terminal_util_dialog_response_on_delete), NULL);
-
-  gtk_window_present (GTK_WINDOW (dialog));
-#endif /* ENABLE_SAVE */
-}
-
 static void
 file_close_tab_callback (GtkAction *action,
                          TerminalWindow *window)
@@ -2971,110 +3610,6 @@ file_close_tab_callback (GtkAction *action,
 }
 
 static void
-edit_copy_callback (GtkAction *action,
-                    TerminalWindow *window)
-{
-  TerminalWindowPrivate *priv = window->priv;
-
-  if (!priv->active_screen)
-    return;
-      
-  vte_terminal_copy_clipboard (VTE_TERMINAL (priv->active_screen));
-}
-
-typedef struct {
-  TerminalScreen *screen;
-  gboolean uris_as_paths;
-} PasteData;
-
-static void
-clipboard_uris_received_cb (GtkClipboard *clipboard,
-                            /* const */ char **uris,
-                            PasteData *data)
-{
-  char *text;
-  gsize len;
-
-  if (!uris) {
-    g_object_unref (data->screen);
-    g_slice_free (PasteData, data);
-    return;
-  }
-
-  /* This potentially modifies the strings in |uris| but that's ok */
-  if (data->uris_as_paths)
-    terminal_util_transform_uris_to_quoted_fuse_paths (uris);
-
-  text = terminal_util_concat_uris (uris, &len);
-  vte_terminal_feed_child (VTE_TERMINAL (data->screen), text, len);
-  g_free (text);
-
-  g_object_unref (data->screen);
-  g_slice_free (PasteData, data);
-}
-
-static void
-clipboard_targets_received_cb (GtkClipboard *clipboard,
-                               GdkAtom *targets,
-                               int n_targets,
-                               PasteData *data)
-{
-  if (!targets) {
-    g_object_unref (data->screen);
-    g_slice_free (PasteData, data);
-    return;
-  }
-
-  if (gtk_targets_include_uri (targets, n_targets)) {
-    gtk_clipboard_request_uris (clipboard,
-                                (GtkClipboardURIReceivedFunc) clipboard_uris_received_cb,
-                                data);
-    return;
-  } else /* if (gtk_targets_include_text (targets, n_targets)) */ {
-    vte_terminal_paste_clipboard (VTE_TERMINAL (data->screen));
-  }
-
-  g_object_unref (data->screen);
-  g_slice_free (PasteData, data);
-}
-
-static void
-edit_paste_callback (GtkAction *action,
-                     TerminalWindow *window)
-{
-  TerminalWindowPrivate *priv = window->priv;
-  GtkClipboard *clipboard;
-  PasteData *data;
-  const char *name;
-
-  if (!priv->active_screen)
-    return;
-      
-  clipboard = gtk_widget_get_clipboard (GTK_WIDGET (window), GDK_SELECTION_CLIPBOARD);
-  name = gtk_action_get_name (action);
-
-  data = g_slice_new (PasteData);
-  data->screen = g_object_ref (priv->active_screen);
-  data->uris_as_paths = (name == I_("EditPasteURIPaths") || name == I_("PopupPasteURIPaths"));
-
-  gtk_clipboard_request_targets (clipboard,
-                                 (GtkClipboardTargetsReceivedFunc) clipboard_targets_received_cb,
-                                 data);
-}
-
-static void
-edit_select_all_callback (GtkAction *action,
-                          TerminalWindow *window)
-{
-  TerminalWindowPrivate *priv = window->priv;
-
-  if (!priv->active_screen)
-    return;
-
-  vte_terminal_select_all (VTE_TERMINAL (priv->active_screen));
-}
-      
-static void
 edit_preferences_callback (GtkAction *action,
                            TerminalWindow *window)
 {
@@ -3123,115 +3658,6 @@ view_fullscreen_toggled_callback (GtkToggleAction *action,
     gtk_window_unfullscreen (GTK_WINDOW (window));
 }
 
-static const double zoom_factors[] = {
-  TERMINAL_SCALE_MINIMUM,
-  TERMINAL_SCALE_XXXXX_SMALL,
-  TERMINAL_SCALE_XXXX_SMALL,
-  TERMINAL_SCALE_XXX_SMALL,
-  PANGO_SCALE_XX_SMALL,
-  PANGO_SCALE_X_SMALL,
-  PANGO_SCALE_SMALL,
-  PANGO_SCALE_MEDIUM,
-  PANGO_SCALE_LARGE,
-  PANGO_SCALE_X_LARGE,
-  PANGO_SCALE_XX_LARGE,
-  TERMINAL_SCALE_XXX_LARGE,
-  TERMINAL_SCALE_XXXX_LARGE,
-  TERMINAL_SCALE_XXXXX_LARGE,
-  TERMINAL_SCALE_MAXIMUM
-};
-
-static gboolean
-find_larger_zoom_factor (double  current,
-                         double *found)
-{
-  guint i;
-
-  for (i = 0; i < G_N_ELEMENTS (zoom_factors); ++i)
-    {
-      /* Find a font that's larger than this one */
-      if ((zoom_factors[i] - current) > 1e-6)
-        {
-          *found = zoom_factors[i];
-          return TRUE;
-        }
-    }
-  
-  return FALSE;
-}
-
-static gboolean
-find_smaller_zoom_factor (double  current,
-                          double *found)
-{
-  int i;
-  
-  i = (int) G_N_ELEMENTS (zoom_factors) - 1;
-  while (i >= 0)
-    {
-      /* Find a font that's smaller than this one */
-      if ((current - zoom_factors[i]) > 1e-6)
-        {
-          *found = zoom_factors[i];
-          return TRUE;
-        }
-      
-      --i;
-    }
-
-  return FALSE;
-}
-
-static void
-view_zoom_in_callback (GtkAction *action,
-                       TerminalWindow *window)
-{
-  TerminalWindowPrivate *priv = window->priv;
-  double current;
-  
-  if (priv->active_screen == NULL)
-    return;
-  
-  current = terminal_screen_get_font_scale (priv->active_screen);
-  if (!find_larger_zoom_factor (current, &current))
-    return;
-      
-  terminal_screen_set_font_scale (priv->active_screen, current);
-  terminal_window_update_zoom_sensitivity (window);
-}
-
-static void
-view_zoom_out_callback (GtkAction *action,
-                        TerminalWindow *window)
-{
-  TerminalWindowPrivate *priv = window->priv;
-  double current;
-
-  if (priv->active_screen == NULL)
-    return;
-  
-  current = terminal_screen_get_font_scale (priv->active_screen);
-  if (!find_smaller_zoom_factor (current, &current))
-    return;
-      
-  terminal_screen_set_font_scale (priv->active_screen, current);
-  terminal_window_update_zoom_sensitivity (window);
-}
-
-static void
-view_zoom_normal_callback (GtkAction *action,
-                           TerminalWindow *window)
-{
-  TerminalWindowPrivate *priv = window->priv;
-  
-  if (priv->active_screen == NULL)
-    return;
-
-  terminal_screen_set_font_scale (priv->active_screen, PANGO_SCALE_MEDIUM);
-  terminal_window_update_zoom_sensitivity (window);
-}
-
-
 static void
 search_find_response_callback (GtkWidget *dialog,
                               int        response,
@@ -3327,78 +3753,6 @@ search_clear_highlight_callback (GtkAction *action,
 }
 
 static void
-terminal_set_title_dialog_response_cb (GtkWidget *dialog,
-                                       int response,
-                                       TerminalScreen *screen)
-{
-  if (response == GTK_RESPONSE_OK)
-    {
-      GtkEntry *entry;
-      const char *text;
-
-      entry = GTK_ENTRY (g_object_get_data (G_OBJECT (dialog), "title-entry"));
-      text = gtk_entry_get_text (entry);
-      terminal_screen_set_user_title (screen, text);
-    }
-
-  gtk_widget_destroy (dialog);
-}
-
-static void
-terminal_set_title_callback (GtkAction *action,
-                             TerminalWindow *window)
-{
-  TerminalWindowPrivate *priv = window->priv;
-  GtkWidget *dialog, *message_area, *hbox, *label, *entry;
-
-  if (priv->active_screen == NULL)
-    return;
-
-  /* FIXME: hook the screen up so this dialogue closes if the terminal screen closes */
-
-  dialog = gtk_message_dialog_new (GTK_WINDOW (window),
-                                   GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
-                                   GTK_MESSAGE_OTHER,
-                                   GTK_BUTTONS_OK_CANCEL,
-                                   "%s", "");
-
-  gtk_window_set_title (GTK_WINDOW (dialog), _("Set Title"));
-  gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);
-  gtk_window_set_role (GTK_WINDOW (dialog), "gnome-terminal-change-title");
-  gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
-  /* Alternative button order was set automatically by GtkMessageDialog */
-
-  g_signal_connect (dialog, "response",
-                    G_CALLBACK (terminal_set_title_dialog_response_cb), priv->active_screen);
-  g_signal_connect (dialog, "delete-event",
-                    G_CALLBACK (terminal_util_dialog_response_on_delete), NULL);
-
-  message_area = gtk_message_dialog_get_message_area (GTK_MESSAGE_DIALOG (dialog));
-  gtk_container_foreach (GTK_CONTAINER (message_area), (GtkCallback) gtk_widget_hide, NULL);
-
-  hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12);
-  gtk_box_pack_start (GTK_BOX (message_area), hbox, FALSE, FALSE, 0);
-
-  label = gtk_label_new_with_mnemonic (_("_Title:"));
-  gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
-  gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
-
-  entry = gtk_entry_new ();
-  gtk_entry_set_width_chars (GTK_ENTRY (entry), 32);
-  gtk_entry_set_activates_default (GTK_ENTRY (entry), TRUE);
-  gtk_label_set_mnemonic_widget (GTK_LABEL (label), entry);
-  gtk_box_pack_start (GTK_BOX (hbox), entry, TRUE, TRUE, 0);
-  gtk_widget_show_all (hbox);
-
-  gtk_widget_grab_focus (entry);
-  gtk_entry_set_text (GTK_ENTRY (entry), terminal_screen_get_raw_title (priv->active_screen));
-  gtk_editable_select_region (GTK_EDITABLE (entry), 0, -1);
-  g_object_set_data (G_OBJECT (dialog), "title-entry", entry);
-
-  gtk_window_present (GTK_WINDOW (dialog));
-}
-
-static void
 terminal_add_encoding_callback (GtkAction *action,
                                 TerminalWindow *window)
 {
@@ -3474,35 +3828,6 @@ tabs_move_right_callback (GtkAction *action,
 }
 
 static void
-tabs_detach_tab_callback (GtkAction *action,
-                          TerminalWindow *window)
-{
-  TerminalWindowPrivate *priv = window->priv;
-  TerminalApp *app;
-  TerminalWindow *new_window;
-  TerminalScreen *screen;
-  char *geometry;
-  int width, height;
-
-  app = terminal_app_get ();
-
-  screen = priv->active_screen;
-
-  /* FIXME: this seems wrong if tabs are shown in the window */
-  terminal_screen_get_size (screen, &width, &height);
-  geometry = g_strdup_printf ("%dx%d", width, height);
-
-  new_window = terminal_app_new_window (app, gtk_widget_get_screen (GTK_WIDGET (window)));
-
-  terminal_window_move_screen (window, new_window, screen, -1);
-
-  terminal_window_parse_geometry (new_window, geometry);
-  g_free (geometry);
-
-  gtk_window_present_with_time (GTK_WINDOW (new_window), gtk_get_current_event_time ());
-}
-
-static void
 help_contents_callback (GtkAction *action,
                         TerminalWindow *window)
 {


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