[gnome-terminal] all: Port to GMenu
- From: Christian Persch <chpe src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-terminal] all: Port to GMenu
- Date: Sun, 22 Oct 2017 16:48:33 +0000 (UTC)
commit 0820b3853a3b7c629a93fa820d5372eac1760686
Author: Christian Persch <chpe gnome org>
Date: Sun Oct 22 18:48:15 2017 +0200
all: Port to GMenu
Port from GtkAction and GtkMenuManager to GAction and GMenu.
(Initial patch by Lars Uebernickel <lars uebernickel canonical com>)
https://bugzilla.gnome.org/show_bug.cgi?id=745329
configure.ac | 5 +-
src/Makefile.am | 6 +-
src/migration.c | 4 +-
src/org.gnome.Terminal.gschema.xml | 31 +-
src/preferences.ui | 71 +-
src/profile-editor.c | 44 +-
src/profile-editor.h | 1 -
src/server.c | 44 +-
src/terminal-accels.c | 201 +-
src/terminal-app.c | 651 +++--
src/terminal-app.h | 26 +-
src/{terminal-menus.ui => terminal-appmenu.ui} | 8 +-
src/terminal-debug.c | 3 +-
src/terminal-debug.h | 16 +-
src/terminal-encoding.c | 379 ++--
src/terminal-encoding.h | 34 +-
src/terminal-libgsystem.h | 27 +
src/terminal-menu-button.c | 107 +
src/terminal-menu-button.h | 57 +
src/terminal-menubar.ui | 252 ++
...terminal-menus.ui => terminal-notebook-menu.ui} | 28 +-
src/terminal-notebook.c | 24 +
src/terminal-prefs.c | 217 +--
src/terminal-prefs.h | 3 +-
src/terminal-schemas.h | 1 -
src/terminal-screen.c | 66 +-
src/terminal-screen.h | 6 +-
src/terminal-settings-list.c | 45 +-
src/terminal-settings-list.h | 11 +
src/terminal-tabs-menu.c | 468 ---
src/terminal-tabs-menu.h | 55 -
src/terminal-util.c | 228 ++-
src/terminal-util.h | 18 +-
src/terminal-window.c | 2983 +++++++-------------
src/terminal-window.h | 3 -
src/terminal.c | 1 -
src/terminal.gresource.xml | 11 +-
src/terminal.xml | 121 -
38 files changed, 2753 insertions(+), 3503 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index b45627b..00d5f60 100644
--- a/configure.ac
+++ b/configure.ac
@@ -13,6 +13,8 @@ AC_CONFIG_MACRO_DIR([m4])
AM_INIT_AUTOMAKE([1.9 foreign no-dist-gzip dist-bzip2])
+AC_USE_SYSTEM_EXTENSIONS
+
m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])])
GETTEXT_PACKAGE=gnome-terminal
@@ -26,7 +28,7 @@ AM_MAINTAINER_MODE([enable])
PKG_PROG_PKG_CONFIG
AC_PROG_MKDIR_P
-AC_PROG_CC
+AC_PROG_CC_C99
AC_ISC_POSIX
AC_HEADER_STDC
AM_PROG_LIBTOOL
@@ -294,7 +296,6 @@ CC_CHECK_FLAGS_APPEND([WARN_CFLAGS],[CFLAGS],[ \
-Wall \
-Wcast-align \
-Wendif-labels \
- -Werror=declaration-after-statement \
"-Werror=format=2 -Werror=format-nonliteral -Werror=format-security" \
-Werror=implicit-function-declaration \
-Werror=init-self \
diff --git a/src/Makefile.am b/src/Makefile.am
index aa63b7b..5c9f720 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -61,6 +61,8 @@ gnome_terminal_server_SOURCES = \
terminal-libgsystem.h \
terminal-mdi-container.c \
terminal-mdi-container.h \
+ terminal-menu-button.h \
+ terminal-menu-button.c \
terminal-notebook.c \
terminal-notebook.h \
terminal-pcre2.h \
@@ -80,8 +82,6 @@ gnome_terminal_server_SOURCES = \
terminal-search-popover.h \
terminal-tab-label.c \
terminal-tab-label.h \
- terminal-tabs-menu.c \
- terminal-tabs-menu.h \
terminal-util.c \
terminal-util.h \
terminal-version.h \
@@ -94,7 +94,6 @@ nodist_gnome_terminal_server_SOURCES = $(gnome_terminal_server_built)
gnome_terminal_server_CPPFLAGS = \
-DTERMINAL_COMPILATION \
-DTERM_LOCALEDIR="\"$(datadir)/locale\"" \
- -DTERM_HELPDIR="\"$(HELP_DIR)\"" \
-DTERM_LIBEXECDIR="\"$(libexecdir)\"" \
$(AM_CPPFLAGS)
@@ -416,7 +415,6 @@ CLEANFILES = \
EXTRA_DIST = \
terminal.about \
- terminal.xml \
terminal-menus.ui \
terminal-window.ui \
terminal.gresource.xml \
diff --git a/src/migration.c b/src/migration.c
index 34401c7..68acd41 100644
--- a/src/migration.c
+++ b/src/migration.c
@@ -205,6 +205,7 @@ migrate_string (GConfClient *client,
gconf_value_free (value);
}
+#if 0
static void
migrate_string_list (GConfClient *client,
const char *gconf_path,
@@ -235,6 +236,7 @@ migrate_string_list (GConfClient *client,
if (value)
gconf_value_free (value);
}
+#endif
static void
migrate_enum (GConfClient *client,
@@ -328,8 +330,6 @@ migrate_global_prefs (GSettings *settings,
migrate_bool (client, GCONF_GLOBAL_PREFIX, "use_menu_accelerator",
settings, TERMINAL_SETTING_ENABLE_MENU_BAR_ACCEL_KEY,
FALSE);
- migrate_string_list (client, GCONF_GLOBAL_PREFIX, "active_encodings",
- settings, TERMINAL_SETTING_ENCODINGS_KEY);
g_object_unref (client);
diff --git a/src/org.gnome.Terminal.gschema.xml b/src/org.gnome.Terminal.gschema.xml
index ebb450b..16fd832 100644
--- a/src/org.gnome.Terminal.gschema.xml
+++ b/src/org.gnome.Terminal.gschema.xml
@@ -310,7 +310,11 @@
<choice value="ISO-8859-14" />
<choice value="ISO-8859-15" />
<choice value="ISO-8859-16" />
+ <!-- <choice value="UTF-7" /> -->
<choice value="UTF-8" />
+ <!-- <choice value="UTF-16" /> -->
+ <!-- <choice value="UTF-32" /> -->
+ <!-- <choice value="UCS-4" /> -->
<choice value="ARMSCII-8" />
<choice value="BIG5" />
<choice value="BIG5-HKSCS" />
@@ -331,6 +335,7 @@
<choice value="ISO-2022-JP" />
<choice value="ISO-2022-KR" />
<choice value="ISO-IR-111" />
+ <!-- <choice value="JOHAB" /> -->
<choice value="KOI8-R" />
<choice value="KOI8-U" />
<choice value="MAC_ARABIC" />
@@ -391,6 +396,14 @@
<default>'disabled'</default>
<summary>Keyboard shortcut to save the current tab contents to file</summary>
</key>
+ <key name="export" type="s">
+ <default>'disabled'</default>
+ <summary>Keyboard shortcut to export the current tab contents to file in various formats</summary>
+ </key>
+ <key name="print" type="s">
+ <default>'disabled'</default>
+ <summary>Keyboard shortcut to print the current tab contents to printer or file</summary>
+ </key>
<key name="close-tab" type="s">
<default>'<Ctrl><Shift>w'</default>
<summary>Keyboard shortcut to close a tab</summary>
@@ -619,6 +632,10 @@
<default>'disabled'</default>
<summary>Keyboard shortcut to switch to the numbered tab</summary>
</key>
+ <key name="switch-to-tab-last" type="s">
+ <default>'disabled'</default>
+ <summary>Keyboard shortcut to switch to the last tab</summary>
+ </key>
<key name="help" type="s">
<default>'F1'</default>
<summary>Keyboard shortcut to launch help</summary>
@@ -677,21 +694,9 @@
<summary>Whether the shell integration is enabled</summary>
</key>
+ <!-- This one is deprecated and unused -->
<key name="encodings" type="as">
- <!-- Translators: Please note that this has to be a list of
- valid encodings (which are to be taken from the list in src/encoding.c).
- It has to include UTF-8 the list entries themselves are not to be
- translated. This is provided for customization of the default encoding
- menu; see bug 144810 for an use case. In most cases, this should be
- left alone.
- -->
<default>["UTF-8"]</default>
- <summary>List of available encodings</summary>
- <description>
- A subset of possible encodings are presented in
- the Encoding submenu. This is a list of encodings
- to appear there.
- </description>
</key>
<key name="confirm-close" type="b">
diff --git a/src/preferences.ui b/src/preferences.ui
index 6acab38..cdccdc2 100644
--- a/src/preferences.ui
+++ b/src/preferences.ui
@@ -143,7 +143,7 @@
</packing>
</child>
<child>
- <object class="GtkLabel" id="label480">
+ <object class="GtkLabel" id="new-terminal-mode-label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">start</property>
@@ -429,75 +429,6 @@
<property name="tab_fill">False</property>
</packing>
</child>
- <child>
- <object class="GtkBox" id="encodings">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="border_width">12</property>
- <property name="orientation">vertical</property>
- <property name="spacing">6</property>
- <child>
- <object class="GtkLabel" id="encodings-label">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="label" translatable="yes">E_ncodings shown in menu:</property>
- <property name="use_underline">True</property>
- <property name="mnemonic_widget">encodings-treeview</property>
- <property name="xalign">0</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">1</property>
- </packing>
- </child>
- <child>
- <object class="GtkScrolledWindow" id="scrolledwindow2">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="hscrollbar_policy">never</property>
- <property name="shadow_type">in</property>
- <child>
- <object class="GtkTreeView" id="encodings-treeview">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="hscroll_policy">natural</property>
- <property name="vscroll_policy">natural</property>
- <property name="headers_visible">False</property>
- <property name="headers_clickable">False</property>
- <property name="rules_hint">True</property>
- <property name="enable_search">False</property>
- <child internal-child="selection">
- <object class="GtkTreeSelection" id="treeview-selection1"/>
- </child>
- <accessibility>
- <relation type="labelled-by" target="encodings-label"/>
- </accessibility>
- </object>
- </child>
- </object>
- <packing>
- <property name="expand">True</property>
- <property name="fill">True</property>
- <property name="position">2</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="position">3</property>
- </packing>
- </child>
- <child type="tab">
- <object class="GtkLabel" id="label4">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="label" translatable="yes">Encodings</property>
- </object>
- <packing>
- <property name="position">3</property>
- <property name="tab_fill">False</property>
- </packing>
- </child>
</object>
<packing>
<property name="expand">True</property>
diff --git a/src/profile-editor.c b/src/profile-editor.c
index 002561d..c23386b 100644
--- a/src/profile-editor.c
+++ b/src/profile-editor.c
@@ -2,7 +2,7 @@
/*
* Copyright © 2002 Havoc Pennington
* Copyright © 2002 Mathias Hasselmann
- * Copyright © 2008, 2011 Christian Persch
+ * Copyright © 2008, 2011, 2017 Christian Persch
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -28,6 +28,7 @@
#include <gio/gio.h>
#include "terminal-app.h"
+#include "terminal-encoding.h"
#include "terminal-enums.h"
#include "profile-editor.h"
#include "terminal-schemas.h"
@@ -486,55 +487,36 @@ init_color_scheme_menu (GtkWidget *widget)
}
enum {
- ENCODINGS_COLUMN_ID,
- ENCODINGS_COLUMN_MARKUP
+ ENCODINGS_COLUMN_ID = 0,
+ ENCODINGS_COLUMN_TEXT = 1
};
static void
init_encodings_combo (GtkWidget *widget)
{
- GtkCellRenderer *renderer;
- GHashTableIter ht_iter;
- gpointer key, value;
- gs_unref_object GtkListStore *store;
-
- store = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_STRING);
-
- g_hash_table_iter_init (&ht_iter, terminal_app_get_encodings (terminal_app_get ()));
- while (g_hash_table_iter_next (&ht_iter, &key, &value)) {
- TerminalEncoding *encoding = value;
- GtkTreeIter iter;
- gs_free char *name;
-
- name = g_markup_printf_escaped ("%s <span size=\"small\">%s</span>",
- terminal_encoding_get_charset (encoding),
- encoding->name);
- gtk_list_store_insert_with_values (store, &iter, -1,
- ENCODINGS_COLUMN_MARKUP, name,
- ENCODINGS_COLUMN_ID, terminal_encoding_get_charset (encoding),
- -1);
- }
+ gs_unref_object GtkListStore *store = terminal_encodings_list_store_new (ENCODINGS_COLUMN_ID,
+ ENCODINGS_COLUMN_TEXT);
/* Now turn on sorting */
gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (store),
- ENCODINGS_COLUMN_MARKUP,
+ ENCODINGS_COLUMN_TEXT,
GTK_SORT_ASCENDING);
gtk_combo_box_set_id_column (GTK_COMBO_BOX (widget), ENCODINGS_COLUMN_ID);
gtk_combo_box_set_model (GTK_COMBO_BOX (widget), GTK_TREE_MODEL (store));
/* Cell renderer */
- renderer = gtk_cell_renderer_text_new ();
+ GtkCellRenderer *renderer = gtk_cell_renderer_text_new ();
gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (widget), renderer, TRUE);
gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (widget), renderer,
- "markup", ENCODINGS_COLUMN_MARKUP, NULL);
+ "text", ENCODINGS_COLUMN_TEXT, NULL);
}
static void
editor_help_button_clicked_cb (GtkWidget *button,
GtkWidget *editor)
{
- terminal_util_show_help ("profile", GTK_WINDOW (editor));
+ terminal_util_show_help ("profile");
}
static void
@@ -799,7 +781,6 @@ fixup_color_chooser_button (void)
/**
* terminal_profile_edit:
* @profile: a #GSettings
- * @transient_parent: a #GtkWindow, or %NULL
* @widget_name: a widget name in the profile editor's UI, or %NULL
*
* Shows the profile editor with @profile, anchored to @transient_parent.
@@ -808,7 +789,6 @@ fixup_color_chooser_button (void)
*/
void
terminal_profile_edit (GSettings *profile,
- GtkWindow *transient_parent,
const char *widget_name)
{
TerminalSettingsList *profiles_list;
@@ -823,8 +803,6 @@ terminal_profile_edit (GSettings *profile,
{
terminal_util_dialog_focus_widget (editor, widget_name);
- gtk_window_set_transient_for (GTK_WINDOW (editor),
- GTK_WINDOW (transient_parent));
gtk_window_present (GTK_WINDOW (editor));
return;
}
@@ -1220,7 +1198,5 @@ terminal_profile_edit (GSettings *profile,
terminal_util_dialog_focus_widget (editor, widget_name);
- gtk_window_set_transient_for (GTK_WINDOW (editor),
- GTK_WINDOW (transient_parent));
gtk_window_present (GTK_WINDOW (editor));
}
diff --git a/src/profile-editor.h b/src/profile-editor.h
index b538b74..bddb95c 100644
--- a/src/profile-editor.h
+++ b/src/profile-editor.h
@@ -24,7 +24,6 @@
G_BEGIN_DECLS
void terminal_profile_edit (GSettings *profile,
- GtkWindow *transient_parent,
const char *widget_name);
G_END_DECLS
diff --git a/src/server.c b/src/server.c
index d516cbb..ac89ca7 100644
--- a/src/server.c
+++ b/src/server.c
@@ -100,13 +100,11 @@ increase_rlimit_nofile (void)
return TRUE;
}
-int
-main (int argc, char **argv)
+static int
+init_server (int argc,
+ char *argv[],
+ GApplication **application)
{
- gs_unref_object GApplication *app = NULL;
- const char *home_dir, *charset;
- GError *error = NULL;
-
if (G_UNLIKELY ((getuid () != geteuid () ||
getgid () != getegid ()) &&
geteuid () == 0 &&
@@ -121,7 +119,7 @@ main (int argc, char **argv)
}
terminal_i18n_init (TRUE);
-
+ const char *charset;
if (!g_get_charset (&charset)) {
g_printerr ("Non UTF-8 locale (%s) is not supported!\n", charset);
return _EXIT_FAILURE_NO_UTF8;
@@ -134,36 +132,38 @@ main (int argc, char **argv)
if (g_getenv ("G_ENABLE_DIAGNOSTIC") == NULL)
g_setenv ("G_ENABLE_DIAGNOSTIC", "0", TRUE);
-#ifndef ENABLE_DISTRO_PACKAGING
#ifdef HAVE_UBUNTU
+#ifndef ENABLE_DISTRO_PACKAGING
/* Set some env vars to disable the ubuntu modules. Their package will be
* built using --enable-distro-packaging, but anyone running from git will
* get the right behaviour.
*/
g_setenv ("LIBOVERLAY_SCROLLBAR", "0", TRUE);
+#endif
g_setenv ("UBUNTU_MENUPROXY", "0", TRUE);
g_setenv ("NO_UNITY_GTK_MODULE", "1", TRUE);
#endif
-#endif
_terminal_debug_init ();
- // FIXMEchpe: just use / here but make sure #565328 doesn't regress
/* Change directory to $HOME so we don't prevent unmounting, e.g. if the
* factory is started by nautilus-open-terminal. See bug #565328.
* On failure back to /.
*/
- home_dir = g_get_home_dir ();
+ const char *home_dir = g_get_home_dir ();
if (home_dir == NULL || chdir (home_dir) < 0)
(void) chdir ("/");
g_set_prgname ("gnome-terminal-server");
g_set_application_name (_("Terminal"));
+ GError *error = NULL;
if (!gtk_init_with_args (&argc, &argv, NULL, options, NULL, &error)) {
- g_printerr ("Failed to parse arguments: %s\n", error->message);
- g_error_free (error);
- exit (_EXIT_FAILURE_GTK_INIT);
+ if (error != NULL) {
+ g_printerr ("Failed to parse arguments: %s\n", error->message);
+ g_error_free (error);
+ }
+ return _EXIT_FAILURE_GTK_INIT;
}
if (!increase_rlimit_nofile ()) {
@@ -171,11 +171,25 @@ main (int argc, char **argv)
}
/* Now we can create the app */
- app = terminal_app_new (app_id);
+ GApplication *app = terminal_app_new (app_id);
g_free (app_id);
+ app_id = NULL;
/* We stay around a bit after the last window closed */
g_application_set_inactivity_timeout (app, INACTIVITY_TIMEOUT);
+ *application = app;
+ return 0;
+}
+
+int
+main (int argc,
+ char *argv[])
+{
+ gs_unref_object GApplication *app = NULL;
+ int r = init_server (argc, argv, &app);
+ if (r != 0)
+ return r;
+
return g_application_run (app, 0, NULL);
}
diff --git a/src/terminal-accels.c b/src/terminal-accels.c
index 3adbfc7..1ea02ce 100644
--- a/src/terminal-accels.c
+++ b/src/terminal-accels.c
@@ -54,6 +54,7 @@
#define KEY_COPY "copy"
#define KEY_COPY_HTML "copy-html"
#define KEY_DETACH_TAB "detach-tab"
+#define KEY_EXPORT "export"
#define KEY_FIND "find"
#define KEY_FIND_CLEAR "find-clear"
#define KEY_FIND_PREV "find-previous"
@@ -69,6 +70,7 @@
#define KEY_PASTE "paste"
#define KEY_PREFERENCES "preferences"
#define KEY_PREV_TAB "prev-tab"
+#define KEY_PRINT "print"
#define KEY_PROFILE_PREFERENCES "profile-preferences"
#define KEY_READ_ONLY "read-only"
#define KEY_RESET_AND_CLEAR "reset-and-clear"
@@ -81,40 +83,6 @@
#define KEY_ZOOM_OUT "zoom-out"
#define KEY_SWITCH_TAB_PREFIX "switch-to-tab-"
-/* Accel paths for the gtkuimanager based menus */
-#define ACCEL_PATH_ROOT "<Actions>/Main/"
-#define ACCEL_PATH_KEY_CLOSE_TAB ACCEL_PATH_ROOT "FileCloseTab"
-#define ACCEL_PATH_KEY_CLOSE_WINDOW ACCEL_PATH_ROOT "FileCloseWindow"
-#define ACCEL_PATH_KEY_COPY ACCEL_PATH_ROOT "EditCopy"
-#define ACCEL_PATH_KEY_COPY_HTML ACCEL_PATH_ROOT "EditCopyHtml"
-#define ACCEL_PATH_KEY_DETACH_TAB ACCEL_PATH_ROOT "TabsDetach"
-#define ACCEL_PATH_KEY_FIND ACCEL_PATH_ROOT "SearchFind"
-#define ACCEL_PATH_KEY_FIND_CLEAR ACCEL_PATH_ROOT "SearchClearHighlight"
-#define ACCEL_PATH_KEY_FIND_PREV ACCEL_PATH_ROOT "SearchFindPrevious"
-#define ACCEL_PATH_KEY_FIND_NEXT ACCEL_PATH_ROOT "SearchFindNext"
-#define ACCEL_PATH_KEY_FULL_SCREEN ACCEL_PATH_ROOT "ViewFullscreen"
-#define ACCEL_PATH_KEY_HELP ACCEL_PATH_ROOT "HelpContents"
-#define ACCEL_PATH_KEY_MOVE_TAB_LEFT ACCEL_PATH_ROOT "TabsMoveLeft"
-#define ACCEL_PATH_KEY_MOVE_TAB_RIGHT ACCEL_PATH_ROOT "TabsMoveRight"
-#define ACCEL_PATH_KEY_NEW_PROFILE ACCEL_PATH_ROOT "FileNewProfile"
-#define ACCEL_PATH_KEY_NEW_TAB ACCEL_PATH_ROOT "FileNewTab"
-#define ACCEL_PATH_KEY_NEW_WINDOW ACCEL_PATH_ROOT "FileNewWindow"
-#define ACCEL_PATH_KEY_NEXT_TAB ACCEL_PATH_ROOT "TabsNext"
-#define ACCEL_PATH_KEY_PASTE ACCEL_PATH_ROOT "EditPaste"
-#define ACCEL_PATH_KEY_PREFERENCES ACCEL_PATH_ROOT "EditPreferences"
-#define ACCEL_PATH_KEY_PREV_TAB ACCEL_PATH_ROOT "TabsPrevious"
-#define ACCEL_PATH_KEY_PROFILE_PREFERENCES ACCEL_PATH_ROOT "EditCurrentProfile"
-#define ACCEL_PATH_KEY_READ_ONLY ACCEL_PATH_ROOT "TerminalReadOnly"
-#define ACCEL_PATH_KEY_RESET ACCEL_PATH_ROOT "TerminalReset"
-#define ACCEL_PATH_KEY_RESET_AND_CLEAR ACCEL_PATH_ROOT "TerminalResetClear"
-#define ACCEL_PATH_KEY_SAVE_CONTENTS ACCEL_PATH_ROOT "FileSaveContents"
-#define ACCEL_PATH_KEY_SELECT_ALL ACCEL_PATH_ROOT "EditSelectAll"
-#define ACCEL_PATH_KEY_TOGGLE_MENUBAR ACCEL_PATH_ROOT "ViewMenubar"
-#define ACCEL_PATH_KEY_ZOOM_IN ACCEL_PATH_ROOT "ViewZoomIn"
-#define ACCEL_PATH_KEY_ZOOM_NORMAL ACCEL_PATH_ROOT "ViewZoom100"
-#define ACCEL_PATH_KEY_ZOOM_OUT ACCEL_PATH_ROOT "ViewZoomOut"
-#define ACCEL_PATH_KEY_SWITCH_TAB_PREFIX ACCEL_PATH_ROOT "TabsSwitch"
-
#if 1
/*
* We don't want to enable content saving until vte supports it async.
@@ -137,11 +105,7 @@ typedef struct
const GVariantType *action_parameter_type;
const char *action_parameter;
GVariant *parameter;
- gboolean installed;
-#if 1
- /* Legacy gtkuimanager menu accelerator */
- const char *legacy_accel_path;
-#endif
+ const char *shadow_action_name;
} KeyEntry;
typedef struct
@@ -151,42 +115,52 @@ typedef struct
const char *user_visible_name;
} KeyEntryList;
+#define ENTRY_FULL(name, key, action, type, parameter, shadow_name) \
+ { name, key, "win." action, (const GVariantType *) type, parameter, NULL, shadow_name }
#define ENTRY(name, key, action, type, parameter) \
- { name, key, "win." action, (const GVariantType *) type, parameter, NULL, FALSE, ACCEL_PATH_##key }
+ ENTRY_FULL (name, key, action, type, parameter, "win.shadow")
+#define ENTRY_MDI(name, key, action, type, parameter) \
+ ENTRY_FULL (name, key, action, type, parameter, "win.shadow-mdi")
static KeyEntry file_entries[] = {
- ENTRY (N_("New Terminal in New Tab"), KEY_NEW_TAB, "new-terminal", "(ss)", "('tab','current')"
),
- ENTRY (N_("New Terminal in New Window"), KEY_NEW_WINDOW, "new-terminal", "(ss)",
"('window','current')"),
- ENTRY (N_("New Profile"), KEY_NEW_PROFILE, "new-profile", NULL, NULL
),
+ ENTRY (N_("New Tab"), KEY_NEW_TAB, "new-terminal", "(ss)", "('tab','current')" ),
+ ENTRY (N_("New Window"), KEY_NEW_WINDOW, "new-terminal", "(ss)", "('window','current')"),
+ ENTRY (N_("New Profile"), KEY_NEW_PROFILE, "new-profile", NULL, NULL ),
#ifdef ENABLE_SAVE
- ENTRY (N_("Save Contents"), KEY_SAVE_CONTENTS, "save-contents", NULL, NULL
),
+ ENTRY (N_("Save Contents"), KEY_SAVE_CONTENTS, "save-contents", NULL, NULL ),
+#endif
+#ifdef ENABLE_EXPORT
+ ENTRY (N_("Export"), KEY_EXPORT, "export", NULL, NULL ),
#endif
- ENTRY (N_("Close Terminal"), KEY_CLOSE_TAB, "close", "s", "'tab'"
),
- ENTRY (N_("Close All Terminals"), KEY_CLOSE_WINDOW, "close", "s", "'window'"
),
+#ifdef ENABLE_PRINT
+ ENTRY (N_("Print"), KEY_PRINT, "print", NULL, NULL ),
+#endif
+ ENTRY (N_("Close Tab"), KEY_CLOSE_TAB, "close", "s", "'tab'" ),
+ ENTRY (N_("Close Window"), KEY_CLOSE_WINDOW, "close", "s", "'window'" ),
};
static KeyEntry edit_entries[] = {
ENTRY (N_("Copy"), KEY_COPY, "copy", "s", "'text'" ),
ENTRY (N_("Copy as HTML"), KEY_COPY_HTML, "copy", "s", "'html'" ),
- ENTRY (N_("Paste"), KEY_PASTE, "paste", "s", "'normal'"),
+ ENTRY (N_("Paste"), KEY_PASTE, "paste-text", NULL, NULL ),
ENTRY (N_("Select All"), KEY_SELECT_ALL, "select-all", NULL, NULL ),
- ENTRY (N_("Preferences"), KEY_PREFERENCES, "preferences", NULL, NULL ),
+ ENTRY (N_("Preferences"), KEY_PREFERENCES, "edit-preferences", NULL, NULL ),
ENTRY (N_("Profile Preferences"), KEY_PROFILE_PREFERENCES, "edit-profile", NULL, NULL ),
};
static KeyEntry find_entries[] = {
- ENTRY (N_("Find"), KEY_FIND, "find", "s", "'find'" ),
- ENTRY (N_("Find Next"), KEY_FIND_NEXT, "find", "s", "'next'" ),
- ENTRY (N_("Find Previous"), KEY_FIND_PREV, "find", "s", "'previous'"),
- ENTRY (N_("Clear Find Highlight"), KEY_FIND_CLEAR, "find", "s", "'clear'" )
+ ENTRY (N_("Find"), KEY_FIND, "find", NULL, NULL),
+ ENTRY (N_("Find Next"), KEY_FIND_NEXT, "find-forward", NULL, NULL),
+ ENTRY (N_("Find Previous"), KEY_FIND_PREV, "find-backward", NULL, NULL),
+ ENTRY (N_("Clear Highlight"), KEY_FIND_CLEAR, "find-clear", NULL, NULL)
};
static KeyEntry view_entries[] = {
- ENTRY (N_("Hide and Show toolbar"), KEY_TOGGLE_MENUBAR, "show-menubar", NULL, NULL),
+ ENTRY (N_("Hide and Show Menubar"), 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" )
+ ENTRY (N_("Zoom In"), KEY_ZOOM_IN, "zoom-in", NULL, NULL),
+ ENTRY (N_("Zoom Out"), KEY_ZOOM_OUT, "zoom-out", NULL, NULL),
+ ENTRY (N_("Normal Size"), KEY_ZOOM_NORMAL, "zoom-normal", NULL, NULL)
};
static KeyEntry terminal_entries[] = {
@@ -196,37 +170,56 @@ static KeyEntry terminal_entries[] = {
};
static KeyEntry tabs_entries[] = {
- ENTRY (N_("Switch to Previous Terminal"), KEY_PREV_TAB, "switch-tab", "i", "-2"),
- ENTRY (N_("Switch to Next Terminal"), KEY_NEXT_TAB, "switch-tab", "i", "-1"),
- ENTRY (N_("Move Terminal to the Left"), KEY_MOVE_TAB_LEFT, "move-tab", "i", "-1"),
- ENTRY (N_("Move Terminal to the Right"), KEY_MOVE_TAB_RIGHT, "move-tab", "i", "1" ),
- ENTRY (N_("Detach Terminal"), 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
+ ENTRY_MDI (N_("Switch to Previous Tab"), KEY_PREV_TAB, "tab-switch-left", NULL, NULL),
+ ENTRY_MDI (N_("Switch to Next Tab"), KEY_NEXT_TAB, "tab-switch-right", NULL, NULL),
+ ENTRY_MDI (N_("Move Tab to the Left"), KEY_MOVE_TAB_LEFT, "tab-move-left", NULL, NULL),
+ ENTRY_MDI (N_("Move Tab to the Right"), KEY_MOVE_TAB_RIGHT, "tab-move-right", NULL, NULL),
+ ENTRY_MDI (N_("Detach Tab"), KEY_DETACH_TAB, "tab-detach", NULL, NULL),
+ ENTRY_MDI (NULL, KEY_SWITCH_TAB_PREFIX "1", "active-tab", "i", "0"),
+ ENTRY_MDI (NULL, KEY_SWITCH_TAB_PREFIX "2", "active-tab", "i", "1"),
+ ENTRY_MDI (NULL, KEY_SWITCH_TAB_PREFIX "3", "active-tab", "i", "2"),
+ ENTRY_MDI (NULL, KEY_SWITCH_TAB_PREFIX "4", "active-tab", "i", "3"),
+ ENTRY_MDI (NULL, KEY_SWITCH_TAB_PREFIX "5", "active-tab", "i", "4"),
+ ENTRY_MDI (NULL, KEY_SWITCH_TAB_PREFIX "6", "active-tab", "i", "5"),
+ ENTRY_MDI (NULL, KEY_SWITCH_TAB_PREFIX "7", "active-tab", "i", "6"),
+ ENTRY_MDI (NULL, KEY_SWITCH_TAB_PREFIX "8", "active-tab", "i", "7"),
+ ENTRY_MDI (NULL, KEY_SWITCH_TAB_PREFIX "9", "active-tab", "i", "8"),
+ ENTRY_MDI (NULL, KEY_SWITCH_TAB_PREFIX "10", "active-tab", "i", "9"),
+ ENTRY_MDI (NULL, KEY_SWITCH_TAB_PREFIX "11", "active-tab", "i", "10"),
+ ENTRY_MDI (NULL, KEY_SWITCH_TAB_PREFIX "12", "active-tab", "i", "11"),
+ ENTRY_MDI (NULL, KEY_SWITCH_TAB_PREFIX "13", "active-tab", "i", "12"),
+ ENTRY_MDI (NULL, KEY_SWITCH_TAB_PREFIX "14", "active-tab", "i", "13"),
+ ENTRY_MDI (NULL, KEY_SWITCH_TAB_PREFIX "15", "active-tab", "i", "14"),
+ ENTRY_MDI (NULL, KEY_SWITCH_TAB_PREFIX "16", "active-tab", "i", "15"),
+ ENTRY_MDI (NULL, KEY_SWITCH_TAB_PREFIX "17", "active-tab", "i", "16"),
+ ENTRY_MDI (NULL, KEY_SWITCH_TAB_PREFIX "18", "active-tab", "i", "17"),
+ ENTRY_MDI (NULL, KEY_SWITCH_TAB_PREFIX "19", "active-tab", "i", "18"),
+ ENTRY_MDI (NULL, KEY_SWITCH_TAB_PREFIX "20", "active-tab", "i", "19"),
+ ENTRY_MDI (NULL, KEY_SWITCH_TAB_PREFIX "21", "active-tab", "i", "20"),
+ ENTRY_MDI (NULL, KEY_SWITCH_TAB_PREFIX "22", "active-tab", "i", "21"),
+ ENTRY_MDI (NULL, KEY_SWITCH_TAB_PREFIX "23", "active-tab", "i", "22"),
+ ENTRY_MDI (NULL, KEY_SWITCH_TAB_PREFIX "24", "active-tab", "i", "23"),
+ ENTRY_MDI (NULL, KEY_SWITCH_TAB_PREFIX "25", "active-tab", "i", "24"),
+ ENTRY_MDI (NULL, KEY_SWITCH_TAB_PREFIX "26", "active-tab", "i", "25"),
+ ENTRY_MDI (NULL, KEY_SWITCH_TAB_PREFIX "27", "active-tab", "i", "26"),
+ ENTRY_MDI (NULL, KEY_SWITCH_TAB_PREFIX "28", "active-tab", "i", "27"),
+ ENTRY_MDI (NULL, KEY_SWITCH_TAB_PREFIX "29", "active-tab", "i", "28"),
+ ENTRY_MDI (NULL, KEY_SWITCH_TAB_PREFIX "30", "active-tab", "i", "29"),
+ ENTRY_MDI (NULL, KEY_SWITCH_TAB_PREFIX "31", "active-tab", "i", "30"),
+ ENTRY_MDI (NULL, KEY_SWITCH_TAB_PREFIX "32", "active-tab", "i", "31"),
+ ENTRY_MDI (NULL, KEY_SWITCH_TAB_PREFIX "33", "active-tab", "i", "32"),
+ ENTRY_MDI (NULL, KEY_SWITCH_TAB_PREFIX "34", "active-tab", "i", "33"),
+ ENTRY_MDI (NULL, KEY_SWITCH_TAB_PREFIX "35", "active-tab", "i", "34"),
+ ENTRY_MDI (N_("Switch to Last Tab"), KEY_SWITCH_TAB_PREFIX "last", "active-tab", "i", "-1"),
};
static KeyEntry help_entries[] = {
ENTRY (N_("Contents"), KEY_HELP, "help", NULL, NULL)
};
+#undef ENTRY_FULL
#undef ENTRY
+#undef ENTRY_MDI
static KeyEntryList all_entries[] =
{
@@ -268,14 +261,12 @@ key_changed_cb (GSettings *settings,
gpointer user_data)
{
GtkApplication *application = user_data;
- KeyEntry *key_entry;
- gs_free char *value = NULL;
_terminal_debug_print (TERMINAL_DEBUG_ACCELS,
"key %s changed\n",
settings_key);
- key_entry = g_hash_table_lookup (settings_key_to_entry, settings_key);
+ KeyEntry *key_entry = g_hash_table_lookup (settings_key_to_entry, settings_key);
if (!key_entry)
{
/* shouldn't really happen, but let's be safe */
@@ -284,34 +275,38 @@ key_changed_cb (GSettings *settings,
return;
}
- value = g_settings_get_string (settings, settings_key);
+ gs_free char *value = g_settings_get_string (settings, settings_key);
+
+ gs_free char *detailed = g_action_print_detailed_name (key_entry->action_name,
+ key_entry->parameter);
+ gs_unref_variant GVariant *shadow_parameter = g_variant_new_string (detailed);
+
+ /* We want to always consume the action's accelerators, even if the corresponding
+ * action is insensitive, so the corresponding shortcut key escape code isn't sent
+ * to the terminal. See bug #453193, bug #138609, and bug #559728.
+ * Since GtkApplication's accelerators don't use GtkAccelGroup, we have no way
+ * to intercept/chain on its activation. The only way to do this that I found
+ * was to install an extra action with the same accelerator that shadows
+ * the real action and gets activated when the shadowed action is disabled.
+ */
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;
+ gtk_application_remove_accelerator (application,
+ key_entry->action_name,
+ key_entry->parameter);
+ gtk_application_remove_accelerator (application,
+ key_entry->shadow_action_name,
+ shadow_parameter);
} else {
gtk_application_add_accelerator (application,
value,
key_entry->action_name,
key_entry->parameter);
- key_entry->installed = TRUE;
- }
-
-#if 1
- /* Legacy gtkuimanager menu accelerator */
- {
- GdkModifierType mods = 0;
- guint key = 0;
-
- if (!g_str_equal (value, "disabled"))
- gtk_accelerator_parse (value, &key, &mods);
-
- gtk_accel_map_change_entry (key_entry->legacy_accel_path, key, mods, TRUE);
+ gtk_application_add_accelerator (application,
+ value,
+ key_entry->shadow_action_name,
+ shadow_parameter);
}
-#endif
}
void
diff --git a/src/terminal-app.c b/src/terminal-app.c
index 6c783bc..e611a70 100644
--- a/src/terminal-app.c
+++ b/src/terminal-app.c
@@ -3,7 +3,7 @@
* Copyright © 2002 Red Hat, Inc.
* Copyright © 2002 Sun Microsystems
* Copyright © 2003 Mariano Suarez-Alvarez
- * Copyright © 2008, 2010, 2011, 2015 Christian Persch
+ * Copyright © 2008, 2010, 2011, 2015, 2017 Christian Persch
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -19,12 +19,15 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include <config.h>
+#include "config.h"
#include <glib.h>
#include <glib/gi18n.h>
#include <gio/gio.h>
+#define G_SETTINGS_ENABLE_BACKEND
+#include <gio/gsettingsbackend.h>
+
#include "terminal-intl.h"
#include "terminal-debug.h"
#include "terminal-app.h"
@@ -74,7 +77,8 @@
struct _TerminalAppClass {
GtkApplicationClass parent_class;
- void (* encoding_list_changed) (TerminalApp *app);
+ void (* clipboard_targets_changed) (TerminalApp *app,
+ GtkClipboard *clipboard);
};
struct _TerminalApp
@@ -85,9 +89,6 @@ struct _TerminalApp
TerminalSettingsList *profiles_list;
- GHashTable *encodings;
- gboolean encodings_locked;
-
GHashTable *screen_map;
GSettings *global_settings;
@@ -98,16 +99,104 @@ struct _TerminalApp
#ifdef ENABLE_SEARCH_PROVIDER
TerminalSearchProvider *search_provider;
#endif /* ENABLE_SEARCH_PROVIDER */
+
+ GMenuModel *menubar;
+ GMenu *menubar_new_terminal_section;
+ GMenu *menubar_set_profile_section;
+ GMenu *menubar_set_encoding_submenu;
+ GMenu *set_profile_menu;
+
+ GtkClipboard *clipboard;
+ GdkAtom *clipboard_targets;
+ int n_clipboard_targets;
};
enum
{
- ENCODING_LIST_CHANGED,
+ CLIPBOARD_TARGETS_CHANGED,
LAST_SIGNAL
};
static guint signals[LAST_SIGNAL];
+/* Debugging helper */
+
+static void
+terminal_app_init_debug (void)
+{
+#ifdef ENABLE_DEBUG
+ const char *env = g_getenv ("GTK_TEXT_DIR");
+ if (env != NULL) {
+ if (g_str_equal (env, "help")) {
+ g_printerr ("Usage: GTK_TEXT_DIR=ltr|rtl\n");
+ } else {
+ GtkTextDirection dir;
+ if (g_str_equal (env, "rtl"))
+ dir = GTK_TEXT_DIR_RTL;
+ else
+ dir = GTK_TEXT_DIR_LTR;
+
+ gtk_widget_set_default_direction (dir);
+ }
+ }
+
+ env = g_getenv ("GTK_SETTINGS");
+ if (env == NULL)
+ return;
+
+ GObject *settings = G_OBJECT (gtk_settings_get_default ());
+ GObjectClass *settings_class = G_OBJECT_GET_CLASS (settings);
+
+ if (g_str_equal (env, "help")) {
+ g_printerr ("Usage: GTK_SETTINGS=setting[,setting…] where 'setting' is one of these:\n");
+
+ guint n_props;
+ GParamSpec **props = g_object_class_list_properties (settings_class, &n_props);
+ for (guint i = 0; i < n_props; i++) {
+ if (G_PARAM_SPEC_VALUE_TYPE (props[i]) != G_TYPE_BOOLEAN)
+ continue;
+
+ GValue value = { 0, };
+ g_value_init (&value, G_TYPE_BOOLEAN);
+ g_object_get_property (settings, props[i]->name, &value);
+ g_printerr (" %s (%s)\n", props[i]->name, g_value_get_boolean (&value) ? "true" : "false");
+ g_value_unset (&value);
+ }
+ g_printerr (" Use 'setting' to set to true, "
+ "'~setting' to set to false, "
+ "and '!setting' to invert.\n");
+ } else {
+ gs_strfreev char **tokens = g_strsplit (env, ",", -1);
+ for (guint i = 0; tokens[i] != NULL; i++) {
+ const char *prop = tokens[i];
+ char c = prop[0];
+ if (c == '~' || c == '!')
+ prop++;
+
+ GParamSpec *pspec = g_object_class_find_property (settings_class, prop);
+ if (pspec == NULL) {
+ g_printerr ("Setting \"%s\" does not exist.\n", prop);
+ } else if (G_PARAM_SPEC_VALUE_TYPE (pspec) != G_TYPE_BOOLEAN) {
+ g_printerr ("Setting \"%s\" is not boolean.\n", prop);
+ } else {
+ GValue value = { 0, };
+ g_value_init (&value, G_TYPE_BOOLEAN);
+ if (c == '!') {
+ g_object_get_property (settings, pspec->name, &value);
+ g_value_set_boolean (&value, !g_value_get_boolean (&value));
+ } else if (c == '~') {
+ g_value_set_boolean (&value, FALSE);
+ } else {
+ g_value_set_boolean (&value, TRUE);
+ }
+ g_object_set_property (settings, pspec->name, &value);
+ g_value_unset (&value);
+ }
+ }
+ }
+#endif
+}
+
/* Helper functions */
static void
@@ -134,6 +223,14 @@ maybe_migrate_settings (TerminalApp *app)
}
#ifdef ENABLE_MIGRATION
+ /* Only do migration if the settings backend is dconf */
+ GType type = G_OBJECT_TYPE (g_settings_backend_get_default ());
+ if (!g_type_is_a (type, g_type_from_name ("DConfSettingsBackend"))) {
+ _terminal_debug_print (TERMINAL_DEBUG_SERVER | TERMINAL_DEBUG_PROFILE,
+ "Not migration settings to %s\n", g_type_name (type));
+ goto done;
+ }
+
if (!g_spawn_sync (NULL /* our home directory */,
(char **) argv,
NULL /* envv */,
@@ -152,11 +249,11 @@ maybe_migrate_settings (TerminalApp *app)
} else {
g_printerr ("Profile migrator exited abnormally.\n");
}
-#else
+done:
+#endif /* ENABLE_MIGRATION */
g_settings_set_uint (terminal_app_get_global_settings (app),
TERMINAL_SETTING_SCHEMA_VERSION,
TERMINAL_SCHEMA_VERSION);
-#endif /* ENABLE_MIGRATION */
}
static gboolean
@@ -215,8 +312,7 @@ app_load_css (GApplication *application)
void
terminal_app_new_profile (TerminalApp *app,
- GSettings *base_profile,
- GtkWindow *transient_parent)
+ GSettings *base_profile)
{
gs_unref_object GSettings *profile = NULL;
gs_free char *uuid;
@@ -237,99 +333,288 @@ terminal_app_new_profile (TerminalApp *app,
if (profile == NULL)
return;
- terminal_profile_edit (profile, NULL, "profile-name-entry");
+ terminal_profile_edit (profile, "profile-name-entry");
}
void
terminal_app_remove_profile (TerminalApp *app,
GSettings *profile)
{
- gs_free char *uuid;
+ g_return_if_fail (TERMINAL_IS_APP (app));
+ g_return_if_fail (G_IS_SETTINGS (profile));
+
+ gs_unref_object GSettings *default_profile = terminal_settings_list_ref_default_child (app->profiles_list);
+ if (default_profile == profile)
+ return;
+
+ /* First, we need to switch any screen using this profile to the default profile */
+ gs_free_list GList *screens = g_hash_table_get_values (app->screen_map);
+ for (GList *l = screens; l != NULL; l = l->next) {
+ TerminalScreen *screen = TERMINAL_SCREEN (l->data);
+ if (terminal_screen_get_profile (screen) != profile)
+ continue;
+
+ terminal_screen_set_profile (screen, default_profile);
+ }
- uuid = terminal_settings_list_dup_uuid_from_child (app->profiles_list, profile);
+ /* Now we can safely remove the profile */
+ gs_free char *uuid = terminal_settings_list_dup_uuid_from_child (app->profiles_list, profile);
terminal_settings_list_remove_child (app->profiles_list, uuid);
}
-gboolean
-terminal_app_can_remove_profile (TerminalApp *app,
- GSettings *profile)
+#if GTK_CHECK_VERSION (3, 19, 0)
+static void
+terminal_app_theme_variant_changed_cb (GSettings *settings,
+ const char *key,
+ GtkSettings *gtk_settings)
{
- return TRUE;
+ TerminalThemeVariant theme;
+
+ theme = g_settings_get_enum (settings, key);
+ if (theme == TERMINAL_THEME_VARIANT_SYSTEM)
+ gtk_settings_reset_property (gtk_settings, GTK_SETTING_PREFER_DARK_THEME);
+ else
+ g_object_set (gtk_settings,
+ GTK_SETTING_PREFER_DARK_THEME,
+ theme == TERMINAL_THEME_VARIANT_DARK,
+ NULL);
+}
+#endif /* GTK+ 3.19 */
+
+/* Submenus for New Terminal per profile, and to change profiles */
+
+static void terminal_app_update_profile_menus (TerminalApp *app);
+
+typedef struct {
+ char *uuid;
+ char *label;
+} ProfileData;
+
+static void
+profile_data_clear (ProfileData *data)
+{
+ g_free (data->uuid);
+ g_free (data->label);
+}
+
+typedef struct {
+ GArray *array;
+ TerminalApp *app;
+} ProfilesForeachData;
+
+static void
+foreach_profile_cb (TerminalSettingsList *list,
+ const char *uuid,
+ GSettings *profile,
+ ProfilesForeachData *user_data)
+{
+ ProfileData data;
+ data.uuid = g_strdup (uuid);
+ data.label = g_settings_get_string (profile, TERMINAL_PROFILE_VISIBLE_NAME_KEY);
+
+ g_array_append_val (user_data->array, data);
+
+ /* only connect if we haven't seen this profile before */
+ if (g_signal_handler_find (profile, G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA,
+ 0, 0, NULL, terminal_app_update_profile_menus, user_data->app) == 0)
+ g_signal_connect_swapped (profile, "changed::" TERMINAL_PROFILE_VISIBLE_NAME_KEY,
+ G_CALLBACK (terminal_app_update_profile_menus), user_data->app);
}
static int
-compare_encodings (TerminalEncoding *a,
- TerminalEncoding *b)
+compare_profile_label_cb (gconstpointer ap,
+ gconstpointer bp)
{
- return g_utf8_collate (a->name, b->name);
+ const ProfileData *a = ap;
+ const ProfileData *b = bp;
+
+ return g_utf8_collate (a->label, b->label);
}
static void
-encoding_mark_active (gpointer key,
- gpointer value,
- gpointer data)
+menu_append_numbered (GMenu *menu,
+ const char *label,
+ int num,
+ const char *action_name,
+ GVariant *target)
{
- TerminalEncoding *encoding = (TerminalEncoding *) value;
- guint active = GPOINTER_TO_UINT (data);
+ gs_free_gstring GString *str;
+ gs_unref_object GMenuItem *item;
+ const char *p;
+
+ /* Who'd use more that 4 underscores in a profile name... */
+ str = g_string_sized_new (strlen (label) + 4 + 1 + 8);
+
+ if (num < 10)
+ g_string_append_printf (str, "%Id. ", num);
+ else if (num < 36)
+ g_string_append_printf (str, "%c. ", (char)('A' + num - 10));
+
+ /* Append the label with underscores elided */
+ for (p = label; *p; p++) {
+ if (*p == '_')
+ g_string_append (str, "__");
+ else
+ g_string_append_c (str, *p);
+ }
- encoding->is_active = active;
+ item = g_menu_item_new (str->str, NULL);
+ g_menu_item_set_action_and_target_value (item, action_name, target);
+ g_menu_append_item (menu, item);
}
static void
-terminal_app_encoding_list_notify_cb (GSettings *settings,
- const char *key,
- TerminalApp *app)
-{
- gs_strfreev char **encodings = NULL;
- int i;
- TerminalEncoding *encoding;
-
- app->encodings_locked = !g_settings_is_writable (settings, key);
-
- /* Mark all as non-active, then re-enable the active ones */
- g_hash_table_foreach (app->encodings, (GHFunc) encoding_mark_active, GUINT_TO_POINTER (FALSE));
-
- /* Also always make UTF-8 available */
- encoding = g_hash_table_lookup (app->encodings, "UTF-8");
- g_assert (encoding);
- g_assert (terminal_encoding_is_valid (encoding));
- encoding->is_active = TRUE;
-
- g_settings_get (settings, key, "^as", &encodings);
- for (i = 0; encodings[i] != NULL; ++i)
- {
- /* Pre-3.13, not supported anymore */
- if (g_str_equal (encodings[i], "current"))
- continue;
+append_new_terminal_item (GMenu *section,
+ const char *label,
+ const char *target,
+ ProfileData *data,
+ guint n_profiles)
+{
+ gs_unref_object GMenuItem *item = g_menu_item_new (label, NULL);
- encoding = terminal_app_ensure_encoding (app, encodings[i]);
- if (!terminal_encoding_is_valid (encoding))
- continue;
+ if (n_profiles > 1) {
+ gs_unref_object GMenu *submenu = g_menu_new ();
- encoding->is_active = TRUE;
+ for (guint i = 0; i < n_profiles; i++) {
+ menu_append_numbered (submenu, data[i].label, i + 1,
+ "win.new-terminal",
+ g_variant_new ("(ss)", target, data[i].uuid));
}
- g_signal_emit (app, signals[ENCODING_LIST_CHANGED], 0);
+ g_menu_item_set_link (item, G_MENU_LINK_SUBMENU, G_MENU_MODEL (submenu));
+ } else {
+ g_menu_item_set_action_and_target (item, "win.new-terminal",
+ "(ss)", target, "default");
+ }
+ g_menu_append_item (section, item);
}
-#if GTK_CHECK_VERSION (3, 19, 0)
static void
-terminal_app_theme_variant_changed_cb (GSettings *settings,
- const char *key,
- GtkSettings *gtk_settings)
+fill_new_terminal_section (GMenu *section,
+ ProfileData *profiles,
+ guint n_profiles)
{
- TerminalThemeVariant theme;
+#ifndef DISUNIFY_NEW_TERMINAL_SECTION
+ append_new_terminal_item (section, _("New _Terminal"), "default", profiles, n_profiles);
+#else
+ append_new_terminal_item (section, _("New _Tab"), "tab", profiles, n_profiles);
+ append_new_terminal_item (section, _("New _Window"), "window", profiles, n_profiles);
+#endif
+}
- theme = g_settings_get_enum (settings, key);
- if (theme == TERMINAL_THEME_VARIANT_SYSTEM)
- gtk_settings_reset_property (gtk_settings, GTK_SETTING_PREFER_DARK_THEME);
- else
- g_object_set (gtk_settings,
- GTK_SETTING_PREFER_DARK_THEME,
- theme == TERMINAL_THEME_VARIANT_DARK,
- NULL);
+static GMenu *
+set_profile_submenu_new (ProfileData *data,
+ guint n_profiles)
+{
+ GMenu *menu = g_menu_new ();
+
+ /* No submenu if there's only one profile */
+ if (n_profiles <= 1)
+ return NULL;
+
+ for (guint i = 0; i < n_profiles; i++) {
+ menu_append_numbered (menu, data[i].label, i + 1,
+ "win.profile",
+ g_variant_new_string (data[i].uuid));
+ }
+
+ return menu;
+}
+
+static void
+terminal_app_update_profile_menus (TerminalApp *app)
+{
+ g_menu_remove_all (G_MENU (app->menubar_new_terminal_section));
+ g_menu_remove_all (G_MENU (app->menubar_set_profile_section));
+ g_clear_object (&app->set_profile_menu);
+
+ /* Get profiles list and sort by label */
+ gs_unref_array GArray *array = g_array_sized_new (FALSE, TRUE, sizeof (ProfileData),
+ terminal_settings_list_get_n_children
(app->profiles_list));
+ g_array_set_clear_func (array, (GDestroyNotify) profile_data_clear);
+
+ ProfilesForeachData data = { array, app };
+ terminal_settings_list_foreach_child (app->profiles_list,
+ (TerminalSettingsListForeachFunc) foreach_profile_cb,
+ &data);
+ g_array_sort (array, compare_profile_label_cb);
+
+ ProfileData *profiles = (ProfileData*) array->data;
+ guint n_profiles = array->len;
+
+ fill_new_terminal_section (app->menubar_new_terminal_section, profiles, n_profiles);
+
+ app->set_profile_menu = set_profile_submenu_new (profiles, n_profiles);
+
+ if (app->set_profile_menu != NULL) {
+ g_menu_append_submenu (app->menubar_set_profile_section, _("Change _Profile"),
+ G_MENU_MODEL (app->set_profile_menu));
+ }
+}
+
+/* Clipboard */
+
+static void
+free_clipboard_targets (TerminalApp *app)
+{
+ g_free (app->clipboard_targets);
+ app->clipboard_targets = NULL;
+ app->n_clipboard_targets = 0;
+}
+
+static void
+update_clipboard_targets (TerminalApp *app,
+ GdkAtom *targets,
+ int n_targets)
+{
+ free_clipboard_targets (app);
+
+ /* Sometimes we receive targets == NULL but n_targets == -1 */
+ if (targets != NULL) {
+ app->clipboard_targets = g_memdup (targets, sizeof (targets[0]) * n_targets);
+ app->n_clipboard_targets = n_targets;
+ }
+}
+
+static void
+clipboard_targets_received_cb (GtkClipboard *clipboard,
+ GdkAtom *targets,
+ int n_targets,
+ TerminalApp *app)
+{
+ update_clipboard_targets (app, targets, n_targets);
+
+ _TERMINAL_DEBUG_IF (TERMINAL_DEBUG_CLIPBOARD) {
+ g_printerr ("Clipboard has %d targets:", app->n_clipboard_targets);
+
+ int i;
+ for (i = 0; i < app->n_clipboard_targets; i++) {
+ gs_free char *atom_name = gdk_atom_name (app->clipboard_targets[i]);
+ g_printerr (" %s", atom_name);
+ }
+ g_printerr ("\n");
+ }
+
+ g_signal_emit (app, signals[CLIPBOARD_TARGETS_CHANGED], 0, clipboard);
+}
+
+static void
+clipboard_owner_change_cb (GtkClipboard *clipboard,
+ GdkEvent *event G_GNUC_UNUSED,
+ TerminalApp *app)
+{
+ _terminal_debug_print (TERMINAL_DEBUG_CLIPBOARD,
+ "Clipboard owner changed\n");
+
+ clipboard_targets_received_cb (clipboard, NULL, 0, app); /* clear */
+
+ /* We can do this without holding a reference to @app since
+ * the app lives as long as the process.
+ */
+ gtk_clipboard_request_targets (clipboard,
+ (GtkClipboardTargetsReceivedFunc) clipboard_targets_received_cb,
+ app);
}
-#endif /* GTK+ 3.19 */
/* App menu callbacks */
@@ -340,7 +625,7 @@ app_menu_preferences_cb (GSimpleAction *action,
{
TerminalApp *app = user_data;
- terminal_app_edit_preferences (app, NULL);
+ terminal_app_edit_preferences (app);
}
static void
@@ -348,7 +633,7 @@ app_menu_help_cb (GSimpleAction *action,
GVariant *parameter,
gpointer user_data)
{
- terminal_util_show_help (NULL, NULL);
+ terminal_util_show_help (NULL);
}
static void
@@ -356,7 +641,7 @@ app_menu_about_cb (GSimpleAction *action,
GVariant *parameter,
gpointer user_data)
{
- terminal_util_show_about (NULL);
+ terminal_util_show_about ();
}
static void
@@ -389,7 +674,9 @@ terminal_app_activate (GApplication *application)
static void
terminal_app_startup (GApplication *application)
{
- const GActionEntry app_menu_actions[] = {
+ TerminalApp *app = TERMINAL_APP (application);
+ GtkApplication *gtk_application = GTK_APPLICATION (application);
+ const GActionEntry action_entries[] = {
{ "preferences", app_menu_preferences_cb, NULL, NULL, NULL },
{ "help", app_menu_help_cb, NULL, NULL, NULL },
{ "about", app_menu_about_cb, NULL, NULL, NULL },
@@ -404,12 +691,43 @@ terminal_app_startup (GApplication *application)
gdk_set_program_class("Gnome-terminal");
g_action_map_add_action_entries (G_ACTION_MAP (application),
- app_menu_actions, G_N_ELEMENTS (app_menu_actions),
+ action_entries, G_N_ELEMENTS (action_entries),
application);
-
app_load_css (application);
+ /* App menu */
+ GMenu *appmenu_new_terminal_section = gtk_application_get_menu_by_id (gtk_application,
+ "new-terminal-section");
+ fill_new_terminal_section (appmenu_new_terminal_section, NULL, 0); /* no submenu */
+
+ /* Menubar */
+ terminal_util_load_objects_resource ("/org/gnome/terminal/ui/menubar.ui",
+ "menubar", &app->menubar,
+ "new-terminal-section", &app->menubar_new_terminal_section,
+ "set-profile-section", &app->menubar_set_profile_section,
+ "set-encoding-submenu", &app->menubar_set_encoding_submenu,
+ NULL);
+
+ /* Create dynamic menus and keep them updated */
+ terminal_app_update_profile_menus (app);
+ g_signal_connect_swapped (app->profiles_list, "children-changed",
+ G_CALLBACK (terminal_app_update_profile_menus), app);
+
+ /* Install the encodings submenu */
+ terminal_encodings_append_menu (app->menubar_set_encoding_submenu);
+
+ /* If the shell wants to show the appmenu/menubar, make it available */
+ gboolean shell_shows_appmenu, shell_shows_menubar;
+ g_object_get (gtk_settings_get_default (),
+ "gtk-shell-shows-app-menu", &shell_shows_appmenu,
+ "gtk-shell-shows-menubar", &shell_shows_menubar,
+ NULL);
+ if (!shell_shows_appmenu)
+ gtk_application_set_app_menu (GTK_APPLICATION (app), NULL);
+ if (shell_shows_menubar)
+ gtk_application_set_menubar (GTK_APPLICATION (app), app->menubar);
+
_terminal_debug_print (TERMINAL_DEBUG_SERVER, "Startup complete\n");
}
@@ -418,7 +736,7 @@ terminal_app_startup (GApplication *application)
static void
terminal_app_init (TerminalApp *app)
{
- gs_unref_object GSettings *settings;
+ terminal_app_init_debug ();
gtk_window_set_default_icon_name (GNOME_TERMINAL_ICON_NAME);
@@ -437,36 +755,34 @@ terminal_app_init (TerminalApp *app)
GTK_DEBUG_ENABLE_INSPECTOR_TYPE);
#if GTK_CHECK_VERSION (3, 19, 0)
- {
- GtkSettings *gtk_settings;
-
- gtk_settings = gtk_settings_get_default ();
+ GtkSettings *gtk_settings = gtk_settings_get_default ();
terminal_app_theme_variant_changed_cb (app->global_settings,
TERMINAL_SETTING_THEME_VARIANT_KEY, gtk_settings);
g_signal_connect (app->global_settings,
"changed::" TERMINAL_SETTING_THEME_VARIANT_KEY,
G_CALLBACK (terminal_app_theme_variant_changed_cb),
gtk_settings);
- }
#endif /* GTK+ 3.19 */
+ /* Clipboard targets */
+ GdkDisplay *display = gdk_display_get_default ();
+ app->clipboard = gtk_clipboard_get_for_display (display, GDK_SELECTION_CLIPBOARD);
+ clipboard_owner_change_cb (app->clipboard, NULL, app);
+ g_signal_connect (app->clipboard, "owner-change",
+ G_CALLBACK (clipboard_owner_change_cb), app);
+
+ if (!gdk_display_supports_selection_notification (display))
+ g_printerr ("Display does not support owner-change; copy/paste will be broken!\n");
+
/* Check if we need to migrate from gconf to dconf */
maybe_migrate_settings (app);
/* Get the profiles */
app->profiles_list = terminal_profiles_list_new ();
- /* Get the encodings */
- app->encodings = terminal_encodings_get_builtins ();
- terminal_app_encoding_list_notify_cb (app->global_settings, "encodings", app);
- g_signal_connect (app->global_settings,
- "changed::encodings",
- G_CALLBACK (terminal_app_encoding_list_notify_cb),
- app);
-
app->screen_map = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
- settings = g_settings_get_child (app->global_settings, "keybindings");
+ gs_unref_object GSettings *settings = g_settings_get_child (app->global_settings, "keybindings");
terminal_accels_init (G_APPLICATION (app), settings);
}
@@ -475,10 +791,14 @@ terminal_app_finalize (GObject *object)
{
TerminalApp *app = TERMINAL_APP (object);
- g_signal_handlers_disconnect_by_func (app->global_settings,
- G_CALLBACK (terminal_app_encoding_list_notify_cb),
+ g_signal_handlers_disconnect_by_func (app->clipboard,
+ G_CALLBACK (clipboard_owner_change_cb),
+ app);
+ free_clipboard_targets (app);
+
+ g_signal_handlers_disconnect_by_func (app->profiles_list,
+ G_CALLBACK (terminal_app_update_profile_menus),
app);
- g_hash_table_destroy (app->encodings);
g_hash_table_destroy (app->screen_map);
g_object_unref (app->global_settings);
@@ -486,6 +806,12 @@ terminal_app_finalize (GObject *object)
g_object_unref (app->system_proxy_settings);
g_clear_object (&app->gtk_debug_settings);
+ g_clear_object (&app->menubar);
+ g_clear_object (&app->menubar_new_terminal_section);
+ g_clear_object (&app->menubar_set_profile_section);
+ g_clear_object (&app->menubar_set_encoding_submenu);
+ g_clear_object (&app->set_profile_menu);
+
terminal_accels_shutdown ();
G_OBJECT_CLASS (terminal_app_parent_class)->finalize (object);
@@ -574,14 +900,14 @@ terminal_app_class_init (TerminalAppClass *klass)
g_application_class->dbus_register = terminal_app_dbus_register;
g_application_class->dbus_unregister = terminal_app_dbus_unregister;
- signals[ENCODING_LIST_CHANGED] =
- g_signal_new (I_("encoding-list-changed"),
+ signals[CLIPBOARD_TARGETS_CHANGED] =
+ g_signal_new (I_("clipboard-targets-changed"),
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (TerminalAppClass, encoding_list_changed),
+ G_STRUCT_OFFSET (TerminalAppClass, clipboard_targets_changed),
NULL, NULL,
- g_cclosure_marshal_VOID__VOID,
- G_TYPE_NONE, 0);
+ g_cclosure_marshal_VOID__OBJECT,
+ G_TYPE_NONE, 1, G_TYPE_OBJECT);
}
/* Public API */
@@ -615,7 +941,7 @@ TerminalScreen *
terminal_app_new_terminal (TerminalApp *app,
TerminalWindow *window,
GSettings *profile,
- const char *encoding,
+ const char *charset,
char **override_command,
const char *title,
const char *working_dir,
@@ -626,8 +952,9 @@ terminal_app_new_terminal (TerminalApp *app,
g_return_val_if_fail (TERMINAL_IS_APP (app), NULL);
g_return_val_if_fail (TERMINAL_IS_WINDOW (window), NULL);
+ g_return_val_if_fail (charset == NULL || terminal_encodings_is_known_charset (charset), NULL);
- screen = terminal_screen_new (profile, encoding, override_command, title,
+ screen = terminal_screen_new (profile, charset, override_command, title,
working_dir, child_env, zoom);
terminal_window_add_screen (window, screen, -1);
@@ -669,27 +996,35 @@ terminal_app_unregister_screen (TerminalApp *app,
g_assert (found == TRUE);
}
-void
-terminal_app_edit_profile (TerminalApp *app,
- GSettings *profile,
- GtkWindow *transient_parent,
- const char *widget_name)
+GdkAtom *
+terminal_app_get_clipboard_targets (TerminalApp *app,
+ GtkClipboard *clipboard,
+ int *n_targets)
{
- terminal_profile_edit (profile, NULL, widget_name);
+ g_return_val_if_fail (TERMINAL_IS_APP (app), NULL);
+ g_return_val_if_fail (n_targets != NULL, NULL);
+
+ if (clipboard != app->clipboard) {
+ *n_targets = 0;
+ return NULL;
+ }
+
+ *n_targets = app->n_clipboard_targets;
+ return app->clipboard_targets;
}
void
-terminal_app_edit_preferences (TerminalApp *app,
- GtkWindow *transient_parent)
+terminal_app_edit_profile (TerminalApp *app,
+ GSettings *profile,
+ const char *widget_name)
{
- terminal_prefs_show_preferences (NULL, "general");
+ terminal_profile_edit (profile, widget_name);
}
void
-terminal_app_edit_encodings (TerminalApp *app,
- GtkWindow *transient_parent)
+terminal_app_edit_preferences (TerminalApp *app)
{
- terminal_prefs_show_preferences (NULL, "encodings");
+ terminal_prefs_show_preferences ("general");
}
/**
@@ -703,88 +1038,28 @@ terminal_app_get_profiles_list (TerminalApp *app)
return app->profiles_list;
}
-GHashTable *
-terminal_app_get_encodings (TerminalApp *app)
-{
- return app->encodings;
-}
-
-static const char *
-charset_validated (const char *charset)
-{
- gsize i;
-
- if (charset == NULL)
- goto out;
-
- for (i = 0; charset[i] != '\0'; i++) {
- char c = charset[i];
- if (!(g_ascii_isalnum(c) || c == '_' || c == '-'))
- goto out;
- }
-
- return charset;
- out:
- return "UTF-8";
-}
-
/**
- * terminal_app_ensure_encoding:
- * @app:
- * @charset: (allow-none): a charset, or %NULL
- *
- * Ensures there's a #TerminalEncoding for @charset available. If @charset
- * is %NULL, returns the #TerminalEncoding for the locale's charset. If
- * @charset is not a known charset, returns a #TerminalEncoding for a
- * custom charset.
+ * terminal_app_get_menubar:
+ * @app: a #TerminalApp
*
- * Returns: (transfer none): a #TerminalEncoding, or %NULL
+ * Returns: (tranfer none): the main window menu bar as a #GMenuModel
*/
-TerminalEncoding *
-terminal_app_ensure_encoding (TerminalApp *app,
- const char *charset)
-{
- TerminalEncoding *encoding;
-
- encoding = g_hash_table_lookup (app->encodings, charset_validated (charset));
- if (encoding == NULL)
- {
- encoding = terminal_encoding_new (charset,
- _("User Defined"),
- TRUE,
- TRUE /* scary! */);
- g_hash_table_insert (app->encodings,
- (gpointer) terminal_encoding_get_charset (encoding),
- encoding);
- }
-
- return encoding;
+GMenuModel *
+terminal_app_get_menubar (TerminalApp *app)
+{
+ return app->menubar;
}
/**
- * terminal_app_get_active_encodings:
+ * terminal_app_get_profile_section:
+ * @app: a #TerminalApp
*
- * Returns: a newly allocated list of newly referenced #TerminalEncoding objects.
+ * Returns: (tranfer none): the main window's menubar's profiles section as a #GMenuModel
*/
-GSList*
-terminal_app_get_active_encodings (TerminalApp *app)
+GMenuModel *
+terminal_app_get_profile_section (TerminalApp *app)
{
- GSList *list = NULL;
- GHashTableIter iter;
- gpointer key, value;
-
- g_hash_table_iter_init (&iter, app->encodings);
- while (g_hash_table_iter_next (&iter, &key, &value))
- {
- TerminalEncoding *encoding = (TerminalEncoding *) value;
-
- if (!encoding->is_active)
- continue;
-
- list = g_slist_prepend (list, terminal_encoding_ref (encoding));
- }
-
- return g_slist_sort (list, (GCompareFunc) compare_encodings);
+ return G_MENU_MODEL (app->set_profile_menu);
}
/**
@@ -834,7 +1109,7 @@ terminal_app_get_gtk_debug_settings (TerminalApp *app)
* @app:
*
* Creates a #PangoFontDescription for the system monospace font.
- *
+ *
* Returns: (transfer full): a new #PangoFontDescription
*/
PangoFontDescription *
diff --git a/src/terminal-app.h b/src/terminal-app.h
index 39d6768..22436f1 100644
--- a/src/terminal-app.h
+++ b/src/terminal-app.h
@@ -21,7 +21,6 @@
#include <gtk/gtk.h>
-#include "terminal-encoding.h"
#include "terminal-screen.h"
#include "terminal-profiles-list.h"
@@ -53,17 +52,16 @@ GApplication *terminal_app_new (const char *app_id);
GDBusObjectManagerServer *terminal_app_get_object_manager (TerminalApp *app);
+GdkAtom *terminal_app_get_clipboard_targets (TerminalApp *app,
+ GtkClipboard *clipboard,
+ int *n_targets);
+
void terminal_app_edit_profile (TerminalApp *app,
GSettings *profile,
- GtkWindow *transient_parent,
const char *widget_name);
void terminal_app_new_profile (TerminalApp *app,
- GSettings *default_base_profile,
- GtkWindow *transient_parent);
-
-gboolean terminal_app_can_remove_profile (TerminalApp *app,
- GSettings *profile);
+ GSettings *default_base_profile);
void terminal_app_remove_profile (TerminalApp *app,
GSettings *profile);
@@ -74,7 +72,7 @@ TerminalWindow * terminal_app_new_window (TerminalApp *app,
TerminalScreen *terminal_app_new_terminal (TerminalApp *app,
TerminalWindow *window,
GSettings *profile,
- const char *encoding,
+ const char *charset,
char **override_command,
const char *title,
const char *working_dir,
@@ -90,19 +88,15 @@ void terminal_app_register_screen (TerminalApp *app,
void terminal_app_unregister_screen (TerminalApp *app,
TerminalScreen *screen);
-void terminal_app_edit_preferences (TerminalApp *app,
- GtkWindow *transient_parent);
-void terminal_app_edit_encodings (TerminalApp *app,
- GtkWindow *transient_parent);
+void terminal_app_edit_preferences (TerminalApp *app);
TerminalSettingsList *terminal_app_get_profiles_list (TerminalApp *app);
-TerminalEncoding *terminal_app_ensure_encoding (TerminalApp *app,
- const char *charset);
+/* Menus */
-GHashTable *terminal_app_get_encodings (TerminalApp *app);
+GMenuModel *terminal_app_get_menubar (TerminalApp *app);
-GSList* terminal_app_get_active_encodings (TerminalApp *app);
+GMenuModel *terminal_app_get_profile_section (TerminalApp *app);
/* GSettings */
diff --git a/src/terminal-menus.ui b/src/terminal-appmenu.ui
similarity index 84%
copy from src/terminal-menus.ui
copy to src/terminal-appmenu.ui
index e248590..8ea3159 100644
--- a/src/terminal-menus.ui
+++ b/src/terminal-appmenu.ui
@@ -17,13 +17,7 @@
-->
<interface>
<menu id="app-menu">
- <section>
- <item>
- <attribute name="label" translatable="yes">_New Terminal</attribute>
- <attribute name="action">win.new-terminal</attribute>
- <attribute name="target" type="(ss)">('default','default')</attribute>
- </item>
- </section>
+ <section id="new-terminal-section" />
<section>
<item>
<attribute name="label" translatable="yes">_Preferences</attribute>
diff --git a/src/terminal-debug.c b/src/terminal-debug.c
index 0ff321f..d08829e 100644
--- a/src/terminal-debug.c
+++ b/src/terminal-debug.c
@@ -29,6 +29,7 @@ _terminal_debug_init(void)
#ifdef ENABLE_DEBUG
const GDebugKey keys[] = {
{ "accels", TERMINAL_DEBUG_ACCELS },
+ { "clipboard", TERMINAL_DEBUG_CLIPBOARD },
{ "encodings", TERMINAL_DEBUG_ENCODINGS },
{ "server", TERMINAL_DEBUG_SERVER },
{ "geometry", TERMINAL_DEBUG_GEOMETRY },
@@ -36,12 +37,12 @@ _terminal_debug_init(void)
{ "processes", TERMINAL_DEBUG_PROCESSES },
{ "profile", TERMINAL_DEBUG_PROFILE },
{ "settings-list", TERMINAL_DEBUG_SETTINGS_LIST },
- { "appmenu", TERMINAL_DEBUG_APPMENU },
{ "search", TERMINAL_DEBUG_SEARCH },
};
_terminal_debug_flags = g_parse_debug_string (g_getenv ("GNOME_TERMINAL_DEBUG"),
keys, G_N_ELEMENTS (keys));
+
#endif /* ENABLE_DEBUG */
}
diff --git a/src/terminal-debug.h b/src/terminal-debug.h
index 5dc3ca4..0fafcc3 100644
--- a/src/terminal-debug.h
+++ b/src/terminal-debug.h
@@ -26,14 +26,14 @@ G_BEGIN_DECLS
typedef enum {
TERMINAL_DEBUG_ACCELS = 1 << 0,
- TERMINAL_DEBUG_ENCODINGS = 1 << 1,
- TERMINAL_DEBUG_SERVER = 1 << 2,
- TERMINAL_DEBUG_GEOMETRY = 1 << 3,
- TERMINAL_DEBUG_MDI = 1 << 4,
- TERMINAL_DEBUG_PROCESSES = 1 << 5,
- TERMINAL_DEBUG_PROFILE = 1 << 6,
- TERMINAL_DEBUG_SETTINGS_LIST = 1 << 7,
- TERMINAL_DEBUG_APPMENU = 1 << 8,
+ TERMINAL_DEBUG_CLIPBOARD = 1 << 1,
+ TERMINAL_DEBUG_ENCODINGS = 1 << 2,
+ TERMINAL_DEBUG_SERVER = 1 << 3,
+ TERMINAL_DEBUG_GEOMETRY = 1 << 4,
+ TERMINAL_DEBUG_MDI = 1 << 5,
+ TERMINAL_DEBUG_PROCESSES = 1 << 6,
+ TERMINAL_DEBUG_PROFILE = 1 << 7,
+ TERMINAL_DEBUG_SETTINGS_LIST = 1 << 8,
TERMINAL_DEBUG_SEARCH = 1 << 9
} TerminalDebugFlags;
diff --git a/src/terminal-encoding.c b/src/terminal-encoding.c
index 2aeb4d4..019624b 100644
--- a/src/terminal-encoding.c
+++ b/src/terminal-encoding.c
@@ -1,6 +1,6 @@
/*
* Copyright © 2002 Red Hat, Inc.
- * Copyright © 2008 Christian Persch
+ * Copyright © 2008, 2017 Christian Persch
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -19,6 +19,8 @@
#include "config.h"
#include <string.h>
+#include <search.h>
+#include <stdlib.h>
#include <glib.h>
#include <glib/gi18n.h>
@@ -29,6 +31,7 @@
#include "terminal-encoding.h"
#include "terminal-schemas.h"
#include "terminal-util.h"
+#include "terminal-libgsystem.h"
/* Overview
*
@@ -45,221 +48,215 @@
* labeled "user defined" but still appears in the menu.
*/
-static const struct {
+typedef enum {
+ GROUP_UNICODE,
+ GROUP_ASIAN,
+ GROUP_EUROPEAN,
+ LAST_GROUP
+} EncodingGroup;
+
+typedef struct {
const char *charset;
const char *name;
-} encodings[] = {
- { "ISO-8859-1", N_("Western") },
- { "ISO-8859-2", N_("Central European") },
- { "ISO-8859-3", N_("South European") },
- { "ISO-8859-4", N_("Baltic") },
- { "ISO-8859-5", N_("Cyrillic") },
- { "ISO-8859-6", N_("Arabic") },
- { "ISO-8859-7", N_("Greek") },
- { "ISO-8859-8", N_("Hebrew Visual") },
- { "ISO-8859-8-I", N_("Hebrew") },
- { "ISO-8859-9", N_("Turkish") },
- { "ISO-8859-10", N_("Nordic") },
- { "ISO-8859-13", N_("Baltic") },
- { "ISO-8859-14", N_("Celtic") },
- { "ISO-8859-15", N_("Western") },
- { "ISO-8859-16", N_("Romanian") },
- { "UTF-8", N_("Unicode") },
- { "ARMSCII-8", N_("Armenian") },
- { "BIG5", N_("Chinese Traditional") },
- { "BIG5-HKSCS", N_("Chinese Traditional") },
- { "CP866", N_("Cyrillic/Russian") },
- { "EUC-JP", N_("Japanese") },
- { "EUC-KR", N_("Korean") },
- { "EUC-TW", N_("Chinese Traditional") },
- { "GB18030", N_("Chinese Simplified") },
- { "GB2312", N_("Chinese Simplified") },
- { "GBK", N_("Chinese Simplified") },
- { "GEORGIAN-PS", N_("Georgian") },
- { "IBM850", N_("Western") },
- { "IBM852", N_("Central European") },
- { "IBM855", N_("Cyrillic") },
- { "IBM857", N_("Turkish") },
- { "IBM862", N_("Hebrew") },
- { "IBM864", N_("Arabic") },
- { "ISO-2022-JP", N_("Japanese") },
- { "ISO-2022-KR", N_("Korean") },
- { "ISO-IR-111", N_("Cyrillic") },
- { "KOI8-R", N_("Cyrillic") },
- { "KOI8-U", N_("Cyrillic/Ukrainian") },
- { "MAC_ARABIC", N_("Arabic") },
- { "MAC_CE", N_("Central European") },
- { "MAC_CROATIAN", N_("Croatian") },
- { "MAC-CYRILLIC", N_("Cyrillic") },
- { "MAC_DEVANAGARI", N_("Hindi") },
- { "MAC_FARSI", N_("Persian") },
- { "MAC_GREEK", N_("Greek") },
- { "MAC_GUJARATI", N_("Gujarati") },
- { "MAC_GURMUKHI", N_("Gurmukhi") },
- { "MAC_HEBREW", N_("Hebrew") },
- { "MAC_ICELANDIC", N_("Icelandic") },
- { "MAC_ROMAN", N_("Western") },
- { "MAC_ROMANIAN", N_("Romanian") },
- { "MAC_TURKISH", N_("Turkish") },
- { "MAC_UKRAINIAN", N_("Cyrillic/Ukrainian") },
- { "SHIFT_JIS", N_("Japanese") },
- { "TCVN", N_("Vietnamese") },
- { "TIS-620", N_("Thai") },
- { "UHC", N_("Korean") },
- { "VISCII", N_("Vietnamese") },
- { "WINDOWS-1250", N_("Central European") },
- { "WINDOWS-1251", N_("Cyrillic") },
- { "WINDOWS-1252", N_("Western") },
- { "WINDOWS-1253", N_("Greek") },
- { "WINDOWS-1254", N_("Turkish") },
- { "WINDOWS-1255", N_("Hebrew") },
- { "WINDOWS-1256", N_("Arabic") },
- { "WINDOWS-1257", N_("Baltic") },
- { "WINDOWS-1258", N_("Vietnamese") },
-#if 0
- /* These encodings do NOT pass-through ASCII, so are always rejected.
- * FIXME: why are they in this table; or rather why do we need
- * the ASCII pass-through requirement?
- */
- { "UTF-7", N_("Unicode") },
- { "UTF-16", N_("Unicode") },
- { "UCS-2", N_("Unicode") },
- { "UCS-4", N_("Unicode") },
- { "JOHAB", N_("Korean") },
-#endif
-};
+ EncodingGroup group;
+} EncodingEntry;
-TerminalEncoding *
-terminal_encoding_new (const char *charset,
- const char *display_name,
- gboolean is_custom,
- gboolean force_valid)
-{
- TerminalEncoding *encoding;
+/* These MUST be sorted by charset so that bsearch can work! */
+static const EncodingEntry const encodings[] = {
+ { "ARMSCII-8", N_("Armenian"), GROUP_ASIAN },
+ { "BIG5", N_("Chinese Traditional"), GROUP_ASIAN },
+ { "BIG5-HKSCS", N_("Chinese Traditional"), GROUP_ASIAN },
+ { "CP866", N_("Cyrillic/Russian"), GROUP_EUROPEAN },
+ { "EUC-JP", N_("Japanese"), GROUP_ASIAN },
+ { "EUC-KR", N_("Korean"), GROUP_ASIAN },
+ { "EUC-TW", N_("Chinese Traditional"), GROUP_ASIAN },
+ { "GB18030", N_("Chinese Simplified"), GROUP_ASIAN },
+ { "GB2312", N_("Chinese Simplified"), GROUP_ASIAN },
+ { "GBK", N_("Chinese Simplified"), GROUP_ASIAN },
+ { "GEORGIAN-PS", N_("Georgian"), GROUP_ASIAN },
+ { "IBM850", N_("Western"), GROUP_EUROPEAN },
+ { "IBM852", N_("Central European"), GROUP_EUROPEAN },
+ { "IBM855", N_("Cyrillic"), GROUP_EUROPEAN },
+ { "IBM857", N_("Turkish"), GROUP_ASIAN },
+ { "IBM862", N_("Hebrew"), GROUP_ASIAN },
+ { "IBM864", N_("Arabic"), GROUP_ASIAN },
+ { "ISO-2022-JP", N_("Japanese"), GROUP_ASIAN },
+ { "ISO-2022-KR", N_("Korean"), GROUP_ASIAN },
+ { "ISO-8859-1", N_("Western"), GROUP_EUROPEAN },
+ { "ISO-8859-10", N_("Nordic"), GROUP_EUROPEAN },
+ { "ISO-8859-13", N_("Baltic"), GROUP_EUROPEAN },
+ { "ISO-8859-14", N_("Celtic"), GROUP_EUROPEAN },
+ { "ISO-8859-15", N_("Western"), GROUP_EUROPEAN },
+ { "ISO-8859-16", N_("Romanian"), GROUP_EUROPEAN },
+ { "ISO-8859-2", N_("Central European"), GROUP_EUROPEAN },
+ { "ISO-8859-3", N_("South European"), GROUP_EUROPEAN },
+ { "ISO-8859-4", N_("Baltic"), GROUP_EUROPEAN },
+ { "ISO-8859-5", N_("Cyrillic"), GROUP_EUROPEAN },
+ { "ISO-8859-6", N_("Arabic"), GROUP_ASIAN },
+ { "ISO-8859-7", N_("Greek"), GROUP_EUROPEAN },
+ { "ISO-8859-8", N_("Hebrew Visual"), GROUP_ASIAN },
+ { "ISO-8859-8-I", N_("Hebrew"), GROUP_ASIAN },
+ { "ISO-8859-9", N_("Turkish"), GROUP_ASIAN },
+ { "ISO-IR-111", N_("Cyrillic"), GROUP_EUROPEAN },
+ /* { "JOHAB", N_("Korean"), GROUP_ASIAN }, */
+ { "KOI8-R", N_("Cyrillic"), GROUP_EUROPEAN },
+ { "KOI8-U", N_("Cyrillic/Ukrainian"), GROUP_EUROPEAN },
+ { "MAC-CYRILLIC", N_("Cyrillic"), GROUP_EUROPEAN },
+ { "MAC_ARABIC", N_("Arabic"), GROUP_ASIAN },
+ { "MAC_CE", N_("Central European"), GROUP_EUROPEAN },
+ { "MAC_CROATIAN", N_("Croatian"), GROUP_EUROPEAN },
+ { "MAC_DEVANAGARI", N_("Hindi"), GROUP_ASIAN },
+ { "MAC_FARSI", N_("Persian"), GROUP_ASIAN },
+ { "MAC_GREEK", N_("Greek"), GROUP_EUROPEAN },
+ { "MAC_GUJARATI", N_("Gujarati"), GROUP_ASIAN },
+ { "MAC_GURMUKHI", N_("Gurmukhi"), GROUP_ASIAN },
+ { "MAC_HEBREW", N_("Hebrew"), GROUP_ASIAN },
+ { "MAC_ICELANDIC", N_("Icelandic"), GROUP_EUROPEAN },
+ { "MAC_ROMAN", N_("Western"), GROUP_EUROPEAN },
+ { "MAC_ROMANIAN", N_("Romanian"), GROUP_EUROPEAN },
+ { "MAC_TURKISH", N_("Turkish"), GROUP_ASIAN },
+ { "MAC_UKRAINIAN", N_("Cyrillic/Ukrainian"), GROUP_EUROPEAN },
+ { "SHIFT_JIS", N_("Japanese"), GROUP_ASIAN },
+ { "TCVN", N_("Vietnamese"), GROUP_ASIAN },
+ { "TIS-620", N_("Thai"), GROUP_ASIAN },
+ /* { "UCS-4", N_("Unicode"), GROUP_UNICODE }, */
+ { "UHC", N_("Korean"), GROUP_ASIAN },
+ /* { "UTF-16", N_("Unicode"), GROUP_UNICODE }, */
+ /* { "UTF-32", N_("Unicode"), GROUP_UNICODE }, */
+ /* { "UTF-7", N_("Unicode"), GROUP_UNICODE }, */
+ { "UTF-8", N_("Unicode"), GROUP_UNICODE },
+ { "VISCII", N_("Vietnamese"), GROUP_ASIAN },
+ { "WINDOWS-1250", N_("Central European"), GROUP_EUROPEAN },
+ { "WINDOWS-1251", N_("Cyrillic"), GROUP_EUROPEAN },
+ { "WINDOWS-1252", N_("Western"), GROUP_EUROPEAN },
+ { "WINDOWS-1253", N_("Greek"), GROUP_EUROPEAN },
+ { "WINDOWS-1254", N_("Turkish"), GROUP_ASIAN },
+ { "WINDOWS-1255", N_("Hebrew"), GROUP_ASIAN },
+ { "WINDOWS-1256", N_("Arabic"), GROUP_ASIAN },
+ { "WINDOWS-1257", N_("Baltic"), GROUP_EUROPEAN },
+ { "WINDOWS-1258", N_("Vietnamese"), GROUP_ASIAN },
+};
- encoding = g_slice_new (TerminalEncoding);
- encoding->refcount = 1;
- encoding->charset = g_intern_string (charset);
- encoding->name = g_strdup (display_name);
- encoding->valid = encoding->validity_checked = force_valid || g_str_equal (charset, "UTF-8");
- encoding->is_custom = is_custom;
- encoding->is_active = FALSE;
+static const struct {
+ EncodingGroup group;
+ const char *name;
+} group_names[] = {
+ { GROUP_UNICODE, N_("Unicode") },
+ { GROUP_ASIAN, N_("Legacy Asian Encodings") },
+ { GROUP_EUROPEAN, N_("Legacy European Encodings") },
+};
- return encoding;
-}
+#define EM_DASH "—"
-TerminalEncoding*
-terminal_encoding_ref (TerminalEncoding *encoding)
+static int
+compare_encoding_entry_cb (const void *ap,
+ const void *bp)
{
- g_return_val_if_fail (encoding != NULL, NULL);
+ const EncodingEntry *a = ap;
+ const EncodingEntry *b = bp;
- encoding->refcount++;
- return encoding;
-}
+ int r = a->group - b->group;
+ if (r != 0)
+ return r;
-void
-terminal_encoding_unref (TerminalEncoding *encoding)
-{
- if (--encoding->refcount > 0)
- return;
+ r = g_utf8_collate (a->name, b->name);
+ if (r != 0)
+ return r;
- g_free (encoding->name);
- g_slice_free (TerminalEncoding, encoding);
+ return strcmp (a->charset, b->charset);
}
-const char *
-terminal_encoding_get_charset (TerminalEncoding *encoding)
+/**
+ * terminal_encodings_append_menu:
+ *
+ * Appends to known encodings to a #GMenu, sorted in groups and
+ * alphabetically by name inside the groups. The action name
+ * used when activating the menu items is "win.encoding".
+ */
+void
+terminal_encodings_append_menu (GMenu *menu)
{
- g_return_val_if_fail (encoding != NULL, NULL);
+ /* First, sort the encodings */
+ gs_free EncodingEntry *array = g_memdup (encodings, sizeof encodings);
+ for (guint i = 0; i < G_N_ELEMENTS (encodings); i++)
+ array[i].name = _(array[i].name); /* translate */
- return encoding->charset;
-}
+ qsort (array, G_N_ELEMENTS (encodings), sizeof array[0],
+ compare_encoding_entry_cb);
-gboolean
-terminal_encoding_is_valid (TerminalEncoding *encoding)
-{
- /* All of the printing ASCII characters from space (32) to the tilde (126) */
- static const char ascii_sample[] =
- " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~";
- char *converted;
- gsize bytes_read = 0, bytes_written = 0;
- GError *error = NULL;
+ for (guint group = 0 ; group < LAST_GROUP; group++) {
+ gs_unref_object GMenu *section = g_menu_new ();
- if (encoding->validity_checked)
- return encoding->valid;
+ for (guint i = 0; i < G_N_ELEMENTS (encodings); i++) {
+ if (array[i].group != group)
+ continue;
- /* Test that the encoding is a proper superset of ASCII (which naive
- * apps are going to use anyway) by attempting to validate the text
- * using the current encoding. This also flushes out any encodings
- * which the underlying GIConv implementation can't support.
- */
- converted = g_convert (ascii_sample, sizeof (ascii_sample) - 1,
- terminal_encoding_get_charset (encoding), "UTF-8",
- &bytes_read, &bytes_written, &error);
+ gs_free_gstring GString *str = g_string_sized_new (128);
+ g_string_append (str, array[i].name);
+ g_string_append (str, " " EM_DASH " ");
+ for (const char *p = array[i].charset; *p; p++) {
+ if (*p == '_')
+ g_string_append (str, "__");
+ else
+ g_string_append_c (str, *p);
+ }
- /* The encoding is only valid if ASCII passes through cleanly. */
- encoding->valid = (bytes_read == (sizeof (ascii_sample) - 1)) &&
- (converted != NULL) &&
- (strcmp (converted, ascii_sample) == 0);
+ gs_unref_object GMenuItem *item = g_menu_item_new (str->str, NULL);
+ g_menu_item_set_action_and_target (item, "win.encoding", "s", array[i].charset);
-#ifdef ENABLE_DEBUG
- _TERMINAL_DEBUG_IF (TERMINAL_DEBUG_ENCODINGS)
- {
- if (!encoding->valid)
- {
- _terminal_debug_print (TERMINAL_DEBUG_ENCODINGS,
- "Rejecting encoding %s as invalid:\n",
- terminal_encoding_get_charset (encoding));
- _terminal_debug_print (TERMINAL_DEBUG_ENCODINGS,
- " input \"%s\"\n",
- ascii_sample);
- _terminal_debug_print (TERMINAL_DEBUG_ENCODINGS,
- " output \"%s\" bytes read %" G_GSIZE_FORMAT " written %" G_GSIZE_FORMAT "\n",
- converted ? converted : "(null)", bytes_read, bytes_written);
- if (error)
- _terminal_debug_print (TERMINAL_DEBUG_ENCODINGS,
- " Error: %s\n",
- error->message);
- }
- else
- _terminal_debug_print (TERMINAL_DEBUG_ENCODINGS,
- "Encoding %s is valid\n\n",
- terminal_encoding_get_charset (encoding));
+ g_menu_append_item (section, item);
+ }
+
+ g_menu_append_section (menu, _(group_names[group].name), G_MENU_MODEL (section));
}
-#endif
+}
+
+/**
+ * terminal_encodings_list_store_new:
+ *
+ * Creates a #GtkListStore containing the known encodings.
+ * The model containing 2 columns, the 0th one with the
+ * charset name, and the 1st one with the label.
+ * The model is unsorted.
+ *
+ * Returns: (transfer full): a new #GtkTreeModel
+ */
+GtkListStore *
+terminal_encodings_list_store_new (int column_id,
+ int column_text)
+{
+ GtkListStore *store = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_STRING);
- g_clear_error (&error);
- g_free (converted);
+ for (guint i = 0; i < G_N_ELEMENTS (encodings); i++) {
+ gs_free char *name = g_strdup_printf ("%s " EM_DASH " %s",
+ encodings[i].name, encodings[i].charset);
- encoding->validity_checked = TRUE;
- return encoding->valid;
-}
+ GtkTreeIter iter;
+ gtk_list_store_insert_with_values (store, &iter, -1,
+ column_id, encodings[i].charset,
+ column_text, name,
+ -1);
+ }
-G_DEFINE_BOXED_TYPE (TerminalEncoding, terminal_encoding,
- terminal_encoding_ref,
- terminal_encoding_unref);
+ return store;
+}
-GHashTable *
-terminal_encodings_get_builtins (void)
+static int
+compare_charset_cb (const void *ap,
+ const void *bp)
{
- GHashTable *encodings_hashtable;
- guint i;
- TerminalEncoding *encoding;
-
- encodings_hashtable = g_hash_table_new_full (g_str_hash, g_str_equal,
- NULL,
- (GDestroyNotify) terminal_encoding_unref);
+ const EncodingEntry *a = ap;
+ const EncodingEntry *b = bp;
- for (i = 0; i < G_N_ELEMENTS (encodings); ++i)
- {
- encoding = terminal_encoding_new (encodings[i].charset,
- _(encodings[i].name),
- FALSE,
- FALSE);
- g_hash_table_insert (encodings_hashtable,
- (gpointer) terminal_encoding_get_charset (encoding),
- encoding);
- }
+ return strcmp (a->charset, b->charset);
+}
- return encodings_hashtable;
+gboolean
+terminal_encodings_is_known_charset (const char *charset)
+{
+ EncodingEntry key = { charset, NULL, 0 };
+ return bsearch (&key,
+ encodings, G_N_ELEMENTS (encodings),
+ sizeof (encodings[0]),
+ compare_charset_cb) != NULL;
}
diff --git a/src/terminal-encoding.h b/src/terminal-encoding.h
index 63c27ba..c3336df 100644
--- a/src/terminal-encoding.h
+++ b/src/terminal-encoding.h
@@ -1,7 +1,6 @@
-/* Encoding stuff */
-
/*
* Copyright © 2002 Red Hat, Inc.
+ * Copyright © 2017 Christian Persch
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -22,34 +21,11 @@
#include <gtk/gtk.h>
-#define TERMINAL_TYPE_ENCODING (terminal_encoding_get_type ())
-
-typedef struct
-{
- int refcount;
- const char *charset; /* interned */
- char *name;
- guint valid : 1;
- guint validity_checked : 1;
- guint is_custom : 1;
- guint is_active : 1;
-} TerminalEncoding;
-
-GType terminal_encoding_get_type (void);
-
-TerminalEncoding *terminal_encoding_new (const char *charset,
- const char *display_name,
- gboolean is_custom,
- gboolean force_valid);
-
-TerminalEncoding *terminal_encoding_ref (TerminalEncoding *encoding);
-
-void terminal_encoding_unref (TerminalEncoding *encoding);
-
-gboolean terminal_encoding_is_valid (TerminalEncoding *encoding);
+gboolean terminal_encodings_is_known_charset (const char *charset);
-const char *terminal_encoding_get_charset (TerminalEncoding *encoding);
+void terminal_encodings_append_menu (GMenu *menu);
-GHashTable *terminal_encodings_get_builtins (void);
+GtkListStore *terminal_encodings_list_store_new (int column_id,
+ int column_text);
#endif /* TERMINAL_ENCODING_H */
diff --git a/src/terminal-libgsystem.h b/src/terminal-libgsystem.h
index 90d61b9..e2e5080 100644
--- a/src/terminal-libgsystem.h
+++ b/src/terminal-libgsystem.h
@@ -53,6 +53,7 @@ GS_DEFINE_CLEANUP_FUNCTION0(GBytes*, gs_local_bytes_unref, g_bytes_unref)
GS_DEFINE_CLEANUP_FUNCTION0(GChecksum*, gs_local_checksum_free, g_checksum_free)
GS_DEFINE_CLEANUP_FUNCTION0(GError*, gs_local_free_error, g_error_free)
GS_DEFINE_CLEANUP_FUNCTION0(GHashTable*, gs_local_hashtable_unref, g_hash_table_unref)
+GS_DEFINE_CLEANUP_FUNCTION0(GKeyFile*, gs_local_key_file_unref, g_key_file_unref)
GS_DEFINE_CLEANUP_FUNCTION0(GList*, gs_local_list_free, g_list_free)
GS_DEFINE_CLEANUP_FUNCTION0(GMatchInfo*, gs_local_match_info_free, g_match_info_free)
GS_DEFINE_CLEANUP_FUNCTION0(GObject*, gs_local_obj_unref, g_object_unref)
@@ -67,6 +68,14 @@ GS_DEFINE_CLEANUP_FUNCTION0(GVariantIter*, gs_local_variant_iter_free, g_variant
GS_DEFINE_CLEANUP_FUNCTION(char**, gs_local_strfreev, g_strfreev)
GS_DEFINE_CLEANUP_FUNCTION(void*, gs_local_free, g_free)
+/* special */
+
+static inline void gs_local_gstring_free (void *v) \
+{ \
+ if (*(GString**)v) \
+ g_string_free (*(GString**)v, TRUE); \
+}
+
/**
* gs_free:
*
@@ -138,6 +147,15 @@ GS_DEFINE_CLEANUP_FUNCTION(void*, gs_local_free, g_free)
#define gs_unref_hashtable __attribute__ ((cleanup(gs_local_hashtable_unref)))
/**
+ * gs_unref_key_file:
+ *
+ * Call g_key_file_unref() on a variable location when it goes out
+ * of scope. Note that unlike g_key_file_unref(), the variable may
+ * be %NULL.
+ */
+#define gs_unref_key_file __attribute__ ((cleanup(gs_local_key_file_unref)))
+
+/**
* gs_free_checksum:
*
* Call g_checksum_free() on a variable location when it goes out
@@ -216,6 +234,15 @@ GS_DEFINE_CLEANUP_FUNCTION(void*, gs_local_free, g_free)
*/
#define gs_unref_settings_schema_key __attribute__ ((cleanup(gs_local_settings_schema_key_unref)))
+/**
+ * gs_free_gstring:
+ *
+ * Call g_string_free(TRUE) on a variable location when it goes out
+ * of scope. Note that unlike g_string_free(), the variable may
+ * be %NULL.
+ */
+#define gs_free_gstring __attribute__ ((cleanup(gs_local_gstring_free)))
+
G_END_DECLS
#endif
diff --git a/src/terminal-menu-button.c b/src/terminal-menu-button.c
new file mode 100644
index 0000000..fdaaffa
--- /dev/null
+++ b/src/terminal-menu-button.c
@@ -0,0 +1,107 @@
+/*
+ * Copyright © 2017 Christian Persch
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANMENUILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include "terminal-menu-button.h"
+#include "terminal-intl.h"
+#include "terminal-libgsystem.h"
+
+/* All this just because GtkToggleButton:toggled is RUN_FIRST (and the
+ * notify::active comes after the toggled signal). :-(
+ */
+
+enum
+{
+ UPDATE_MENU,
+ LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL];
+
+/* The menu button sets itself insensitive when it has no menu.
+ * Work around this by using an empty menu.
+ */
+static void
+set_empty_menu (GtkMenuButton *button)
+{
+ gs_unref_object GMenu *menu = g_menu_new ();
+ gtk_menu_button_set_menu_model (button, G_MENU_MODEL (menu));
+}
+
+/* Class implementation */
+
+G_DEFINE_TYPE (TerminalMenuButton, terminal_menu_button, GTK_TYPE_MENU_BUTTON);
+
+static void
+terminal_menu_button_init (TerminalMenuButton *button_)
+{
+ GtkButton *button = GTK_BUTTON (button_);
+ GtkMenuButton *menu_button = GTK_MENU_BUTTON (button_);
+
+ gtk_button_set_relief (button, GTK_RELIEF_NONE);
+ gtk_button_set_focus_on_click (button, FALSE);
+ gtk_menu_button_set_use_popover (menu_button, FALSE);
+ set_empty_menu (menu_button);
+}
+
+static void
+terminal_menu_button_toggled (GtkToggleButton *button)
+{
+ gboolean active = gtk_toggle_button_get_active (button); /* this is already the new state */
+
+ /* On activate, update the menu */
+ if (active)
+ g_signal_emit (button, signals[UPDATE_MENU], 0);
+
+ GTK_TOGGLE_BUTTON_CLASS (terminal_menu_button_parent_class)->toggled (button);
+
+ /* On deactivate, clear the menu */
+ if (!active)
+ set_empty_menu (GTK_MENU_BUTTON (button));
+}
+
+static void
+terminal_menu_button_class_init (TerminalMenuButtonClass *klass)
+{
+ GtkToggleButtonClass *toggle_button_class = GTK_TOGGLE_BUTTON_CLASS (klass);
+
+ toggle_button_class->toggled = terminal_menu_button_toggled;
+
+ signals[UPDATE_MENU] =
+ g_signal_new (I_("update-menu"),
+ G_OBJECT_CLASS_TYPE (klass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (TerminalMenuButtonClass, update_menu),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE,
+ 0);
+}
+
+/* public API */
+
+/**
+ * terminal_menu_button_new:
+ *
+ * Returns: a new #TerminalMenuButton
+ */
+GtkWidget *
+terminal_menu_button_new (void)
+{
+ return g_object_new (TERMINAL_TYPE_MENU_BUTTON, NULL);
+}
diff --git a/src/terminal-menu-button.h b/src/terminal-menu-button.h
new file mode 100644
index 0000000..c9362d0
--- /dev/null
+++ b/src/terminal-menu-button.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright © 2008, 2017 Christian Persch
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANMENUILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef TERMINAL_MENU_BUTTON_H
+#define TERMINAL_MENU_BUTTON_H
+
+#include <gtk/gtk.h>
+
+#include "terminal-screen.h"
+
+G_BEGIN_DECLS
+
+#define TERMINAL_TYPE_MENU_BUTTON (terminal_menu_button_get_type ())
+#define TERMINAL_MENU_BUTTON(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), TERMINAL_TYPE_MENU_BUTTON,
TerminalMenuButton))
+#define TERMINAL_MENU_BUTTON_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), TERMINAL_TYPE_MENU_BUTTON,
TerminalMenuButtonClass))
+#define TERMINAL_IS_MENU_BUTTON(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), TERMINAL_TYPE_MENU_BUTTON))
+#define TERMINAL_IS_MENU_BUTTON_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), TERMINAL_TYPE_MENU_BUTTON))
+#define TERMINAL_MENU_BUTTON_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), TERMINAL_TYPE_MENU_BUTTON,
TerminalMenuButtonClass))
+
+typedef struct _TerminalMenuButton TerminalMenuButton;
+typedef struct _TerminalMenuButtonClass TerminalMenuButtonClass;
+typedef struct _TerminalMenuButtonPrivate TerminalMenuButtonPrivate;
+
+struct _TerminalMenuButton
+{
+ GtkMenuButton parent_instance;
+};
+
+struct _TerminalMenuButtonClass
+{
+ GtkMenuButtonClass parent_class;
+
+ /* Signals */
+ void (* update_menu) (TerminalMenuButton *menu_button);
+};
+
+GType terminal_menu_button_get_type (void);
+
+GtkWidget *terminal_menu_button_new (void);
+
+G_END_DECLS
+
+#endif /* !TERMINAL_MENU_BUTTON_H */
diff --git a/src/terminal-menubar.ui b/src/terminal-menubar.ui
new file mode 100644
index 0000000..664942c
--- /dev/null
+++ b/src/terminal-menubar.ui
@@ -0,0 +1,252 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright © 2012, 2017 Christian Persch
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+-->
+<interface>
+ <menu id="menubar">
+ <submenu>
+ <attribute name="label" translatable="yes">_File</attribute>
+ <section id="new-terminal-section" />
+ <section>
+ <item>
+ <attribute name="label" translatable="yes">New _Profile…</attribute>
+ <attribute name="action">win.new-profile</attribute>
+ </item>
+ <item>
+ <attribute name="label" translatable="yes">_Save Contents…</attribute>
+ <attribute name="action">win.save-contents</attribute>
+ <attribute name="hidden-when">action-missing</attribute>
+ </item>
+ <item>
+ <attribute name="label" translatable="yes">_Export…</attribute>
+ <attribute name="action">win.export</attribute>
+ <attribute name="hidden-when">action-missing</attribute>
+ </item>
+ <item>
+ <attribute name="label" translatable="yes">_Print…</attribute>
+ <attribute name="action">win.print</attribute>
+ <attribute name="hidden-when">action-missing</attribute>
+ </item>
+ </section>
+ <section>
+ <item>
+ <attribute name="label" translatable="yes">C_lose Tab</attribute>
+ <attribute name="action">win.close</attribute>
+ <attribute name="target">tab</attribute>
+ </item>
+ <item>
+ <attribute name="label" translatable="yes">_Close Window</attribute>
+ <attribute name="action">win.close</attribute>
+ <attribute name="target">window</attribute>
+ </item>
+ </section>
+ </submenu>
+ <submenu>
+ <attribute name="label" translatable="yes">_Edit</attribute>
+ <section>
+ <item>
+ <attribute name="label" translatable="yes">_Copy</attribute>
+ <attribute name="action">win.copy</attribute>
+ <attribute name="target">text</attribute>
+ </item>
+ <item>
+ <attribute name="label" translatable="yes">Copy as _HTML</attribute>
+ <attribute name="action">win.copy</attribute>
+ <attribute name="target">html</attribute>
+ </item>
+ <item>
+ <attribute name="label" translatable="yes">_Paste</attribute>
+ <attribute name="action">win.paste-text</attribute>
+ </item>
+ <item>
+ <attribute name="label" translatable="yes">Paste as _Filenames</attribute>
+ <attribute name="action">win.paste-uris</attribute>
+ <attribute name="hidden-when">action-disabled</attribute>
+ </item>
+ </section>
+ <section>
+ <item>
+ <attribute name="label" translatable="yes">Select _All</attribute>
+ <attribute name="action">win.select-all</attribute>
+ </item>
+ </section>
+ <section>
+ <item>
+ <attribute name="label" translatable="yes">P_references…</attribute>
+ <attribute name="action">win.edit-preferences</attribute>
+ </item>
+ <item>
+ <attribute name="label" translatable="yes">Pr_ofile Preferences…</attribute>
+ <attribute name="action">win.edit-profile</attribute>
+ </item>
+ </section>
+ </submenu>
+ <submenu>
+ <attribute name="label" translatable="yes">_View</attribute>
+ <section>
+ <item>
+ <attribute name="label" translatable="yes">Show _Menubar</attribute>
+ <attribute name="action">win.menubar-visible</attribute>
+ <attribute name="hidden-when">action-disabled</attribute>
+ </item>
+ <item>
+ <attribute name="label" translatable="yes">_Full Screen</attribute>
+ <attribute name="action">win.fullscreen</attribute>
+ </item>
+ </section>
+ <section>
+ <item>
+ <attribute name="label" translatable="yes">Zoom _In</attribute>
+ <attribute name="action">win.zoom-in</attribute>
+ </item>
+ <item>
+ <attribute name="label" translatable="yes">_Normal Size</attribute>
+ <attribute name="action">win.zoom-normal</attribute>
+ </item>
+ <item>
+ <attribute name="label" translatable="yes">Zoom _Out</attribute>
+ <attribute name="action">win.zoom-out</attribute>
+ </item>
+ </section>
+ </submenu>
+ <submenu>
+ <attribute name="label" translatable="yes">_Find</attribute>
+ <section>
+ <item>
+ <attribute name="label" translatable="yes">_Find…</attribute>
+ <attribute name="action">win.find</attribute>
+ </item>
+ <item>
+ <attribute name="label" translatable="yes">Find _Next</attribute>
+ <attribute name="action">win.find-forward</attribute>
+ </item>
+ <item>
+ <attribute name="label" translatable="yes">Find _Previous</attribute>
+ <attribute name="action">win.find-backward</attribute>
+ </item>
+ <item>
+ <attribute name="label" translatable="yes">_Clear Highlight</attribute>
+ <attribute name="action">win.find-clear</attribute>
+ </item>
+ </section>
+ </submenu>
+ <submenu>
+ <attribute name="label" translatable="yes">_Terminal</attribute>
+ <section>
+ <section id="set-profile-section" />
+ <item>
+ <attribute name="label" translatable="yes">Set _Title…</attribute>
+ <attribute name="action">win.set-title</attribute>
+ <attribute name="hidden-when">action-missing</attribute>
+ </item>
+ <submenu id="set-encoding-submenu">
+ <attribute name="label" translatable="yes">Set _Character Encoding</attribute>
+ </submenu>
+ </section>
+ <section>
+ <item>
+ <attribute name="label" translatable="yes">Read-_Only</attribute>
+ <attribute name="action">win.read-only</attribute>
+ </item>
+ </section>
+ <section>
+ <item>
+ <attribute name="label" translatable="yes">_Reset</attribute>
+ <attribute name="action">win.reset</attribute>
+ <attribute name="target" type="b">false</attribute>
+ </item>
+ <item>
+ <attribute name="label" translatable="yes">Reset and C_lear</attribute>
+ <attribute name="action">win.reset</attribute>
+ <attribute name="target" type="b">true</attribute>
+ </item>
+ </section>
+ <section>
+ <item>
+ <attribute name="label" translatable="yes">_1. 80×24</attribute>
+ <attribute name="action">win.size-to</attribute>
+ <attribute name="target" type="(uu)">(80, 24)</attribute>
+ </item>
+ <item>
+ <attribute name="label" translatable="yes">_1. 80×43</attribute>
+ <attribute name="action">win.size-to</attribute>
+ <attribute name="target" type="(uu)">(80, 43)</attribute>
+ </item>
+ <item>
+ <attribute name="label" translatable="yes">_1. 132×24</attribute>
+ <attribute name="action">win.size-to</attribute>
+ <attribute name="target" type="(uu)">(132, 24)</attribute>
+ </item>
+ <item>
+ <attribute name="label" translatable="yes">_1. 132×42</attribute>
+ <attribute name="action">win.size-to</attribute>
+ <attribute name="target" type="(uu)">(132, 43)</attribute>
+ </item>
+ </section>
+ </submenu>
+ <submenu>
+ <attribute name="label" translatable="yes">Ta_bs</attribute>
+ <attribute name="action">win.tabs-menu</attribute>
+ <attribute name="hidden-when">action-disabled</attribute>
+ <section>
+ <item>
+ <attribute name="label" translatable="yes">_Previous Tab</attribute>
+ <attribute name="action">win.tab-switch-left</attribute>
+ </item>
+ <item>
+ <attribute name="label" translatable="yes">_Next Tab</attribute>
+ <attribute name="action">win.tab-switch-right</attribute>
+ </item>
+ </section>
+ <section>
+ <item>
+ <attribute name="label" translatable="yes">Move Tab _Left</attribute>
+ <attribute name="action">win.tab-move-left</attribute>
+ </item>
+ <item>
+ <attribute name="label" translatable="yes">Move Tab _Right</attribute>
+ <attribute name="action">win.tab-move-right</attribute>
+ </item>
+ </section>
+ <section>
+ <item>
+ <attribute name="label" translatable="yes">_Detach Tab</attribute>
+ <attribute name="action">win.tab-detach</attribute>
+ </item>
+ </section>
+ </submenu>
+ <submenu>
+ <attribute name="label" translatable="yes">_Help</attribute>
+ <section>
+ <item>
+ <attribute name="label" translatable="yes">_Contents</attribute>
+ <attribute name="action">win.help</attribute>
+ </item>
+ <item>
+ <attribute name="label" translatable="yes">_About</attribute>
+ <attribute name="action">win.about</attribute>
+ </item>
+ </section>
+ <section>
+ <item>
+ <attribute name="label" translatable="yes">_Inspector</attribute>
+ <attribute name="action">win.inspector</attribute>
+ <attribute name="hidden-when">action-disabled</attribute>
+ </item>
+ </section>
+ </submenu>
+ </menu>
+</interface>
diff --git a/src/terminal-menus.ui b/src/terminal-notebook-menu.ui
similarity index 54%
rename from src/terminal-menus.ui
rename to src/terminal-notebook-menu.ui
index e248590..8854a7b 100644
--- a/src/terminal-menus.ui
+++ b/src/terminal-notebook-menu.ui
@@ -16,32 +16,28 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
-->
<interface>
- <menu id="app-menu">
+ <menu id="notebook-popup">
<section>
<item>
- <attribute name="label" translatable="yes">_New Terminal</attribute>
- <attribute name="action">win.new-terminal</attribute>
- <attribute name="target" type="(ss)">('default','default')</attribute>
+ <attribute name="label" translatable="yes">Move Terminal _Left</attribute>
+ <attribute name="action">win.tab-move-left</attribute>
</item>
- </section>
- <section>
<item>
- <attribute name="label" translatable="yes">_Preferences</attribute>
- <attribute name="action">app.preferences</attribute>
+ <attribute name="label" translatable="yes">Move Terminal _Right</attribute>
+ <attribute name="action">win.tab-move-right</attribute>
</item>
</section>
<section>
<item>
- <attribute name="label" translatable="yes">_Help</attribute>
- <attribute name="action">app.help</attribute>
- </item>
- <item>
- <attribute name="label" translatable="yes">_About</attribute>
- <attribute name="action">app.about</attribute>
+ <attribute name="label" translatable="yes">_Detach Terminal</attribute>
+ <attribute name="action">win.tab-detach</attribute>
</item>
+ </section>
+ <section>
<item>
- <attribute name="label" translatable="yes">_Quit</attribute>
- <attribute name="action">app.quit</attribute>
+ <attribute name="label" translatable="yes">C_lose Terminal</attribute>
+ <attribute name="action">win.close</attribute>
+ <attribute name="target">tab</attribute>
</item>
</section>
</menu>
diff --git a/src/terminal-notebook.c b/src/terminal-notebook.c
index 392c978..19d938e 100644
--- a/src/terminal-notebook.c
+++ b/src/terminal-notebook.c
@@ -105,6 +105,15 @@ close_button_clicked_cb (TerminalTabLabel *tab_label,
}
+static void
+remove_reorder_bindings (GtkBindingSet *binding_set,
+ guint keysym)
+{
+ guint keypad_keysym = keysym - GDK_KEY_Left + GDK_KEY_KP_Left;
+ gtk_binding_entry_skip (binding_set, keysym, GDK_MOD1_MASK);
+ gtk_binding_entry_skip (binding_set, keypad_keysym, GDK_MOD1_MASK);
+}
+
/* TerminalMdiContainer impl */
static void
@@ -560,6 +569,21 @@ terminal_notebook_class_init (TerminalNotebookClass *klass)
GTK_TYPE_POLICY_TYPE,
GTK_POLICY_AUTOMATIC,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+ /* Remove unwanted and interfering keybindings */
+ GtkBindingSet *binding_set = gtk_binding_set_by_class (terminal_notebook_parent_class);
+ gtk_binding_entry_skip (binding_set, GDK_KEY_Page_Up, GDK_CONTROL_MASK);
+ gtk_binding_entry_skip (binding_set, GDK_KEY_Page_Up, GDK_CONTROL_MASK | GDK_MOD1_MASK);
+ gtk_binding_entry_skip (binding_set, GDK_KEY_Page_Down, GDK_CONTROL_MASK);
+ gtk_binding_entry_skip (binding_set, GDK_KEY_Page_Down, GDK_CONTROL_MASK | GDK_MOD1_MASK);
+ remove_reorder_bindings (binding_set, GDK_KEY_Up);
+ remove_reorder_bindings (binding_set, GDK_KEY_Down);
+ remove_reorder_bindings (binding_set, GDK_KEY_Left);
+ remove_reorder_bindings (binding_set, GDK_KEY_Right);
+ remove_reorder_bindings (binding_set, GDK_KEY_Home);
+ remove_reorder_bindings (binding_set, GDK_KEY_Home);
+ remove_reorder_bindings (binding_set, GDK_KEY_End);
+ remove_reorder_bindings (binding_set, GDK_KEY_End);
}
/* public API */
diff --git a/src/terminal-prefs.c b/src/terminal-prefs.c
index cd7b0d9..8e59ca1 100644
--- a/src/terminal-prefs.c
+++ b/src/terminal-prefs.c
@@ -34,7 +34,6 @@
#include "terminal-schemas.h"
#include "terminal-util.h"
#include "terminal-profiles-list.h"
-#include "terminal-encoding.h"
#include "terminal-libgsystem.h"
typedef struct {
@@ -48,10 +47,6 @@ typedef struct {
GtkWidget *manage_profiles_clone_button;
GtkWidget *manage_profiles_delete_button;
GtkWidget *profiles_default_combo;
-
- GtkListStore *encoding_base_store;
- GtkTreeModel *encodings_model;
- GtkTreeView *encodings_tree_view;
} PrefData;
static GtkWidget *prefs_dialog = NULL;
@@ -60,7 +55,7 @@ static void
prefs_dialog_help_button_clicked_cb (GtkWidget *button,
PrefData *data)
{
- terminal_util_show_help ("pref", GTK_WINDOW (data->dialog));
+ terminal_util_show_help ("pref");
}
static void
@@ -300,7 +295,7 @@ profile_list_row_activated_cb (GtkTreeView *tree_view,
if (selected_profile == NULL)
return;
- terminal_app_edit_profile (terminal_app_get (), selected_profile, NULL, NULL);
+ terminal_app_edit_profile (terminal_app_get (), selected_profile, NULL);
}
static GtkTreeView *
@@ -399,7 +394,7 @@ static void
profile_list_new_button_clicked_cb (GtkWidget *button,
PrefData *data)
{
- terminal_app_new_profile (terminal_app_get (), NULL, GTK_WINDOW (data->parent));
+ terminal_app_new_profile (terminal_app_get (), NULL);
}
static void
@@ -412,7 +407,7 @@ profile_list_clone_button_clicked_cb (GtkWidget *button,
if (selected_profile == NULL)
return;
- terminal_app_new_profile (terminal_app_get (), selected_profile, GTK_WINDOW (data->parent));
+ terminal_app_new_profile (terminal_app_get (), selected_profile);
}
static void
@@ -425,134 +420,40 @@ profile_list_edit_button_clicked_cb (GtkWidget *button,
if (selected_profile == NULL)
return;
- terminal_app_edit_profile (terminal_app_get (), selected_profile, NULL, NULL);
+ terminal_app_edit_profile (terminal_app_get (), selected_profile, NULL);
}
static void
profile_list_selection_changed_cb (GtkTreeSelection *selection,
PrefData *data)
{
- gboolean selected;
- gs_unref_object GSettings *selected_profile;
-
- selected = gtk_tree_selection_get_selected (selection, NULL, NULL);
- selected_profile = profile_list_ref_selected (data);
+ gboolean selected = gtk_tree_selection_get_selected (selection, NULL, NULL);
gtk_widget_set_sensitive (data->manage_profiles_edit_button, selected);
gtk_widget_set_sensitive (data->manage_profiles_clone_button, selected);
- gtk_widget_set_sensitive (data->manage_profiles_delete_button,
- selected &&
- terminal_app_can_remove_profile (terminal_app_get (), selected_profile));
+ gtk_widget_set_sensitive (data->manage_profiles_delete_button, selected);
}
/* Keybindings tab */
/* Encodings tab */
-static void
-update_active_encodings_setting (void)
-{
- TerminalApp *app;
- GSList *list, *l;
- GVariantBuilder builder;
- GSettings *settings;
-
- app = terminal_app_get ();
-
- g_variant_builder_init (&builder, G_VARIANT_TYPE ("as"));
-
- list = terminal_app_get_active_encodings (app);
- for (l = list; l != NULL; l = l->next)
- {
- TerminalEncoding *encoding = (TerminalEncoding *) l->data;
-
- g_variant_builder_add (&builder, "s", terminal_encoding_get_charset (encoding));
- }
- g_slist_foreach (list, (GFunc) terminal_encoding_unref, NULL);
- g_slist_free (list);
-
- settings = terminal_app_get_global_settings (app);
- g_settings_set (settings, TERMINAL_SETTING_ENCODINGS_KEY, "as", &builder);
-}
-
-enum
-{
- COLUMN_NAME,
- COLUMN_CHARSET,
- COLUMN_DATA,
- N_ENCODING_COLUMNS
-};
-
-static void
-encoding_active_toggled_cb (GtkCellRendererToggle *cell,
- gchar *path_as_string,
- PrefData *data)
-{
- GtkTreePath *path;
- GtkTreeIter iter;
- TerminalEncoding *encoding;
-
- path = gtk_tree_path_new_from_string (path_as_string);
- if (!gtk_tree_model_get_iter (data->encodings_model, &iter, path))
- goto out;
-
- gtk_tree_model_get (data->encodings_model, &iter, COLUMN_DATA, &encoding, -1);
- g_assert (encoding != NULL);
-
- encoding->is_active = !encoding->is_active;
- terminal_encoding_unref (encoding);
-
- gtk_tree_model_row_changed (GTK_TREE_MODEL (data->encodings_model), path, &iter);
-
- /* Persist the change */
- update_active_encodings_setting ();
-
- out:
- gtk_tree_path_free (path);
-}
-
-static void
-encoding_active_cell_data_func (GtkTreeViewColumn *tree_column,
- GtkCellRenderer *cell,
- GtkTreeModel *tree_model,
- GtkTreeIter *iter,
- PrefData *data)
-{
- TerminalEncoding *encoding;
-
- gtk_tree_model_get (tree_model, iter, (int) COLUMN_DATA, &encoding, -1);
- g_object_set (G_OBJECT (cell), "active", encoding->is_active, NULL);
- terminal_encoding_unref (encoding);
-}
-
-static void
-encodings_list_changed_cb (PrefData *data)
-{
- /* We just queue a redraw here which will take care of everything */
- gtk_widget_queue_draw (GTK_WIDGET (data->encodings_tree_view));
-}
-
/* misc */
static void
prefs_dialog_destroy_cb (GtkWidget *widget,
PrefData *data)
{
- TerminalApp *app = terminal_app_get ();
-
g_signal_handlers_disconnect_by_func (data->profiles_list, G_CALLBACK (profile_combo_box_refill), data);
g_signal_handlers_disconnect_by_func (data->profiles_list, G_CALLBACK (profile_list_treeview_refill),
data);
- g_signal_handlers_disconnect_by_func (app, G_CALLBACK (encodings_list_changed_cb), data);
-
/* Don't run this handler again */
g_signal_handlers_disconnect_by_func (widget, G_CALLBACK (prefs_dialog_destroy_cb), data);
g_free (data);
}
void
-terminal_prefs_show_preferences (GtkWindow *transient_parent,
- const char *page)
+terminal_prefs_show_preferences (const char *page)
{
TerminalApp *app = terminal_app_get ();
PrefData *data;
@@ -560,25 +461,20 @@ terminal_prefs_show_preferences (GtkWindow *transient_parent,
GtkWidget *show_menubar_button, *disable_mnemonics_button, *disable_menu_accel_button;
GtkWidget *disable_shortcuts_button;
GtkWidget *tree_view_container, *new_button, *edit_button, *clone_button, *remove_button;
- GtkWidget *theme_variant_label, *theme_variant_combo, *new_terminal_mode_combo;
+ GtkWidget *theme_variant_label, *theme_variant_combo;
+ GtkWidget *new_terminal_mode_label, *new_terminal_mode_combo;
GtkWidget *default_hbox, *default_label;
GtkWidget *close_button, *help_button;
GtkTreeSelection *selection;
GSettings *settings;
- GtkCellRenderer *cell_renderer;
- GtkTreeViewColumn *column;
- GtkListStore *list_store;
- GHashTableIter ht_iter;
- gpointer key, value;
if (prefs_dialog != NULL)
goto done;
data = g_new0 (PrefData, 1);
- data->parent = transient_parent;
data->profiles_list = terminal_app_get_profiles_list (app);
- terminal_util_load_builder_resource ("/org/gnome/terminal/ui/preferences.ui",
+ terminal_util_load_widgets_resource ("/org/gnome/terminal/ui/preferences.ui",
"preferences-dialog",
"preferences-dialog", &dialog,
"close-button", &close_button,
@@ -586,6 +482,7 @@ terminal_prefs_show_preferences (GtkWindow *transient_parent,
"default-show-menubar-checkbutton", &show_menubar_button,
"theme-variant-label", &theme_variant_label,
"theme-variant-combobox", &theme_variant_combo,
+ "new-terminal-mode-label", &new_terminal_mode_label,
"new-terminal-mode-combobox", &new_terminal_mode_combo,
"disable-mnemonics-checkbutton", &disable_mnemonics_button,
"disable-shortcuts-checkbutton", &disable_shortcuts_button,
@@ -598,7 +495,6 @@ terminal_prefs_show_preferences (GtkWindow *transient_parent,
"delete-profile-button", &remove_button,
"default-profile-hbox", &default_hbox,
"default-profile-label", &default_label,
- "encodings-treeview", &data->encodings_tree_view,
NULL);
data->dialog = dialog;
@@ -611,11 +507,19 @@ terminal_prefs_show_preferences (GtkWindow *transient_parent,
/* General tab */
- g_settings_bind (settings,
- TERMINAL_SETTING_DEFAULT_SHOW_MENUBAR_KEY,
- show_menubar_button,
- "active",
- G_SETTINGS_BIND_GET | G_SETTINGS_BIND_SET);
+ gboolean shell_shows_menubar;
+ g_object_get (gtk_settings_get_default (),
+ "gtk-shell-shows-menubar", &shell_shows_menubar,
+ NULL);
+ if (shell_shows_menubar) {
+ gtk_widget_set_visible (show_menubar_button, FALSE);
+ } else {
+ g_settings_bind (settings,
+ TERMINAL_SETTING_DEFAULT_SHOW_MENUBAR_KEY,
+ show_menubar_button,
+ "active",
+ G_SETTINGS_BIND_GET | G_SETTINGS_BIND_SET);
+ }
#if GTK_CHECK_VERSION (3, 19, 0)
g_settings_bind (settings,
@@ -628,11 +532,16 @@ terminal_prefs_show_preferences (GtkWindow *transient_parent,
gtk_widget_set_visible (theme_variant_combo, FALSE);
#endif /* GTK+ 3.19 */
+#ifndef DISUNIFY_NEW_TERMINAL_SECTION
g_settings_bind (settings,
TERMINAL_SETTING_NEW_TERMINAL_MODE_KEY,
new_terminal_mode_combo,
"active-id",
G_SETTINGS_BIND_GET | G_SETTINGS_BIND_SET);
+#else
+ gtk_widget_set_visible (new_terminal_mode_label, FALSE);
+ gtk_widget_set_visible (new_terminal_mode_combo, FALSE);
+#endif
/* Keybindings tab */
@@ -697,70 +606,6 @@ terminal_prefs_show_preferences (GtkWindow *transient_parent,
// FIXMEchpe
gtk_label_set_mnemonic_widget (GTK_LABEL (default_label), data->profiles_default_combo);
- /* Encodings tab */
-
- selection = gtk_tree_view_get_selection (data->encodings_tree_view);
- gtk_tree_selection_set_mode (selection, GTK_SELECTION_BROWSE);
-
- /* Column 1 */
- cell_renderer = gtk_cell_renderer_toggle_new ();
- g_object_set (cell_renderer, "xalign", 0.0, NULL);
- g_signal_connect (cell_renderer, "toggled",
- G_CALLBACK (encoding_active_toggled_cb), data);
- column = gtk_tree_view_column_new ();
- gtk_tree_view_column_set_title (column, _("Show"));
- gtk_tree_view_column_pack_start (column, cell_renderer, FALSE);
- gtk_cell_layout_set_cell_data_func (GTK_CELL_LAYOUT (column),
- cell_renderer,
- (GtkCellLayoutDataFunc) encoding_active_cell_data_func,
- data, NULL);
-
- gtk_tree_view_append_column (data->encodings_tree_view, column);
-
- /* Column 2 */
- cell_renderer = gtk_cell_renderer_text_new ();
- column = gtk_tree_view_column_new_with_attributes (_("_Encoding"),
- cell_renderer,
- "markup", COLUMN_NAME,
- NULL);
- gtk_tree_view_append_column (data->encodings_tree_view, column);
- gtk_tree_view_column_set_sort_column_id (column, COLUMN_CHARSET);
-
- /* Add the data */
-
- list_store = gtk_list_store_new (N_ENCODING_COLUMNS,
- G_TYPE_STRING,
- G_TYPE_STRING,
- TERMINAL_TYPE_ENCODING);
- data->encodings_model = GTK_TREE_MODEL (list_store);
-
- g_hash_table_iter_init (&ht_iter, terminal_app_get_encodings (app));
- while (g_hash_table_iter_next (&ht_iter, &key, &value)) {
- TerminalEncoding *encoding = value;
- GtkTreeIter iter;
- gs_free char *name;
-
- name = g_markup_printf_escaped ("%s <span size=\"small\">%s</span>",
- terminal_encoding_get_charset (encoding),
- encoding->name);
- gtk_list_store_insert_with_values (list_store, &iter, -1,
- COLUMN_NAME, name,
- COLUMN_CHARSET, terminal_encoding_get_charset (encoding),
- COLUMN_DATA, encoding,
- -1);
- }
-
- /* Now turn on sorting */
- gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (data->encodings_model),
- COLUMN_CHARSET,
- GTK_SORT_ASCENDING);
-
- gtk_tree_view_set_model (data->encodings_tree_view, data->encodings_model);
- g_object_unref (data->encodings_model);
-
- g_signal_connect_swapped (app, "encoding-list-changed",
- G_CALLBACK (encodings_list_changed_cb), data);
-
/* misc */
g_signal_connect (close_button, "clicked", G_CALLBACK (prefs_dialog_close_button_clicked_cb), data);
@@ -772,8 +617,6 @@ terminal_prefs_show_preferences (GtkWindow *transient_parent,
g_object_add_weak_pointer (G_OBJECT (dialog), (gpointer *) &prefs_dialog);
done:
- gtk_window_set_transient_for (GTK_WINDOW (prefs_dialog), transient_parent);
-
terminal_util_dialog_focus_widget (prefs_dialog, page);
gtk_window_present (GTK_WINDOW (prefs_dialog));
diff --git a/src/terminal-prefs.h b/src/terminal-prefs.h
index 82d423b..1a4bc2d 100644
--- a/src/terminal-prefs.h
+++ b/src/terminal-prefs.h
@@ -22,8 +22,7 @@
G_BEGIN_DECLS
-void terminal_prefs_show_preferences (GtkWindow *transient_parent,
- const char *page);
+void terminal_prefs_show_preferences (const char *page);
G_END_DECLS
diff --git a/src/terminal-schemas.h b/src/terminal-schemas.h
index 4b734a3..35ab577 100644
--- a/src/terminal-schemas.h
+++ b/src/terminal-schemas.h
@@ -74,7 +74,6 @@ G_BEGIN_DECLS
#define TERMINAL_SETTING_ENABLE_MENU_BAR_ACCEL_KEY "menu-accelerator-enabled"
#define TERMINAL_SETTING_ENABLE_MNEMONICS_KEY "mnemonics-enabled"
#define TERMINAL_SETTING_ENABLE_SHORTCUTS_KEY "shortcuts-enabled"
-#define TERMINAL_SETTING_ENCODINGS_KEY "encodings"
#define TERMINAL_SETTING_NEW_TERMINAL_MODE_KEY "new-terminal-mode"
#define TERMINAL_SETTING_SCHEMA_VERSION "schema-version"
#define TERMINAL_SETTING_SHELL_INTEGRATION_KEY "shell-integration-enabled"
diff --git a/src/terminal-screen.c b/src/terminal-screen.c
index f6cc4a5..b18de53 100644
--- a/src/terminal-screen.c
+++ b/src/terminal-screen.c
@@ -17,7 +17,6 @@
*/
#include "config.h"
-#define _GNU_SOURCE /* for dup3 */
#include "terminal-pcre2.h"
#include "terminal-regex.h"
@@ -49,6 +48,7 @@
#include "terminal-accels.h"
#include "terminal-app.h"
#include "terminal-debug.h"
+#include "terminal-encoding.h"
#include "terminal-enums.h"
#include "terminal-intl.h"
#include "terminal-marshal.h"
@@ -644,7 +644,7 @@ terminal_screen_finalize (GObject *object)
TerminalScreen *
terminal_screen_new (GSettings *profile,
- const char *encoding,
+ const char *charset,
char **override_command,
const char *title,
const char *working_dir,
@@ -665,12 +665,11 @@ terminal_screen_new (GSettings *profile,
* override the profile encoding; otherwise use the profile
* encoding.
*/
- if (encoding != NULL && override_command != NULL) {
- TerminalEncoding *enc;
-
- enc = terminal_app_ensure_encoding (terminal_app_get (), encoding);
+ if (charset != NULL &&
+ terminal_encodings_is_known_charset (charset) &&
+ override_command != NULL) {
vte_terminal_set_encoding (VTE_TERMINAL (screen),
- terminal_encoding_get_charset (enc),
+ charset,
NULL);
}
@@ -797,14 +796,9 @@ terminal_screen_profile_changed_cb (GSettings *profile,
if (!prop_name || prop_name == I_(TERMINAL_PROFILE_ENCODING_KEY))
{
- TerminalEncoding *encoding;
- gs_free char *str;
-
- str = g_settings_get_string (profile, TERMINAL_PROFILE_ENCODING_KEY);
- encoding = terminal_app_ensure_encoding (terminal_app_get (), str);
- vte_terminal_set_encoding (vte_terminal,
- terminal_encoding_get_charset (encoding),
- NULL);
+ gs_free char *charset = g_settings_get_string (profile, TERMINAL_PROFILE_ENCODING_KEY);
+ g_warn_if_fail (terminal_encodings_is_known_charset (charset));
+ vte_terminal_set_encoding (vte_terminal, charset, NULL);
}
if (!prop_name || prop_name == I_(TERMINAL_PROFILE_CJK_UTF8_AMBIGUOUS_WIDTH_KEY))
@@ -1204,17 +1198,17 @@ get_child_environment (TerminalScreen *screen,
g_hash_table_remove (env_table, "COLUMNS");
g_hash_table_remove (env_table, "LINES");
g_hash_table_remove (env_table, "GNOME_DESKTOP_ICON");
-
-#ifdef GDK_WINDOWING_X11
- if (GDK_IS_X11_SCREEN (gtk_widget_get_screen (window)))
- {
- /* FIXME: moving the tab between windows, or the window between displays will make the next two
invalid... */
- g_hash_table_replace (env_table, g_strdup ("WINDOWID"),
- g_strdup_printf ("%lu",
- GDK_WINDOW_XID (gtk_widget_get_window (window))));
- g_hash_table_replace (env_table, g_strdup ("DISPLAY"), g_strdup (gdk_display_get_name
(gtk_widget_get_display (window))));
- }
-#endif
+
+ /* WINDOWID does not work correctly ever since we don't use a native
+ * GdkWindow anymore, and it also becomes incorrect if the screen is
+ * moved to a different window, or the window unrealized and re-realized.
+ * Additionally, it cannot ever work on non-X11 displays like wayland.
+ * And on X11, the only use for this is broken foreign drawing on the
+ * window (w3m etc), and trying to find the focused screen (brltty),
+ * which can now be done correctly using DECSET 1004.
+ * Therefore we do not set WINDOWID, and remove an existing variable.
+ */
+ g_hash_table_remove (env_table, "WINDOWID");
/* We need to put the working directory also in PWD, so that
* e.g. bash starts in the right directory if @cwd is a symlink.
@@ -1260,7 +1254,6 @@ info_bar_response_cb (GtkWidget *info_bar,
case RESPONSE_EDIT_PROFILE:
terminal_app_edit_profile (terminal_app_get (),
terminal_screen_get_profile (screen),
- GTK_WINDOW (terminal_screen_get_window (screen)),
"custom-command-entry");
break;
default:
@@ -1487,9 +1480,6 @@ terminal_screen_popup_info_new (TerminalScreen *screen)
info = g_slice_new0 (TerminalScreenPopupInfo);
info->ref_count = 1;
- info->screen = g_object_ref (screen);
-
- g_weak_ref_init (&info->window_weak_ref, terminal_screen_get_window (screen));
return info;
}
@@ -1511,28 +1501,12 @@ terminal_screen_popup_info_unref (TerminalScreenPopupInfo *info)
if (--info->ref_count > 0)
return;
- g_object_unref (info->screen);
- g_weak_ref_clear (&info->window_weak_ref);
g_free (info->hyperlink);
g_free (info->url);
g_free (info->number_info);
g_slice_free (TerminalScreenPopupInfo, info);
}
-/**
- * terminal_screen_popup_info_ref_window:
- * @info: a #TerminalScreenPopupInfo
- *
- * Returns: the window, or %NULL
- */
-TerminalWindow *
-terminal_screen_popup_info_ref_window (TerminalScreenPopupInfo *info)
-{
- g_return_val_if_fail (info != NULL, NULL);
-
- return g_weak_ref_get (&info->window_weak_ref);
-}
-
static gboolean
terminal_screen_popup_menu (GtkWidget *widget)
{
diff --git a/src/terminal-screen.h b/src/terminal-screen.h
index 2e8f6dc..743071d 100644
--- a/src/terminal-screen.h
+++ b/src/terminal-screen.h
@@ -76,7 +76,7 @@ GType terminal_screen_get_type (void) G_GNUC_CONST;
const char *terminal_screen_get_uuid (TerminalScreen *screen);
TerminalScreen *terminal_screen_new (GSettings *profile,
- const char *encoding,
+ const char *charset,
char **override_command,
const char *title,
const char *working_dir,
@@ -138,8 +138,6 @@ gboolean terminal_screen_has_foreground_process (TerminalScreen *screen,
struct _TerminalScreenPopupInfo {
int ref_count;
- GWeakRef window_weak_ref;
- TerminalScreen *screen;
char *url;
TerminalURLFlavor url_flavor;
char *hyperlink;
@@ -153,8 +151,6 @@ TerminalScreenPopupInfo *terminal_screen_popup_info_ref (TerminalScreenPopupInfo
void terminal_screen_popup_info_unref (TerminalScreenPopupInfo *info);
-TerminalWindow *terminal_screen_popup_info_ref_window (TerminalScreenPopupInfo *info);
-
G_END_DECLS
#endif /* TERMINAL_SCREEN_H */
diff --git a/src/terminal-settings-list.c b/src/terminal-settings-list.c
index e9ed2b8..cdc80b6 100644
--- a/src/terminal-settings-list.c
+++ b/src/terminal-settings-list.c
@@ -817,7 +817,7 @@ terminal_settings_list_remove_child (TerminalSettingsList *list,
* @list: a #TerminalSettingsList
* @child: a #GSettings of a child in the list
*
- * Returns the UUID of @child in the list, or %NULL if @child is in the list.
+ * Returns the UUID of @child in the list, or %NULL if @child is not in the list.
*
* Returns: (transfer full): the UUID of the child in the settings list, or %NULL
*/
@@ -837,6 +837,7 @@ terminal_settings_list_dup_uuid_from_child (TerminalSettingsList *list,
g_return_val_if_fail (p[0] == ':', NULL);
p++;
g_return_val_if_fail (strlen (p) == 37, NULL);
+ g_return_val_if_fail (p[36] == '/', NULL);
p[36] = '\0';
g_assert (terminal_settings_list_valid_uuid (p));
@@ -850,7 +851,7 @@ terminal_settings_list_dup_uuid_from_child (TerminalSettingsList *list,
*
* Sets @uuid as the default child.
*/
-void
+void
terminal_settings_list_set_default_child (TerminalSettingsList *list,
const char *uuid)
{
@@ -862,3 +863,43 @@ terminal_settings_list_set_default_child (TerminalSettingsList *list,
g_settings_set_string (&list->parent, TERMINAL_SETTINGS_LIST_DEFAULT_KEY, uuid);
}
+
+/**
+ * terminal_settings_list_foreach_child:
+ * @list: a #TerminalSettingsList
+ * @callback: a #TerminalSettingsListForeachFunc
+ * @user_data: user data for @callback
+ *
+ * Calls @callback for each child of @list.
+ *
+ * NOTE: No changes to @list must be made from @callback.
+ */
+void
+terminal_settings_list_foreach_child (TerminalSettingsList *list,
+ TerminalSettingsListForeachFunc callback,
+ gpointer user_data)
+{
+ g_return_if_fail (TERMINAL_IS_SETTINGS_LIST (list));
+ g_return_if_fail (callback);
+
+ for (char **p = list->uuids; *p; p++) {
+ const char *uuid = *p;
+ gs_unref_object GSettings *child = terminal_settings_list_ref_child_internal (list, uuid);
+ if (child != NULL)
+ callback (list, uuid, child, user_data);
+ }
+}
+
+/**
+ * terminal_settings_list_foreach_child:
+ * @list: a #TerminalSettingsList
+ *
+ * Returns: the number of children of @list.
+ */
+guint
+terminal_settings_list_get_n_children (TerminalSettingsList *list)
+{
+ g_return_val_if_fail (TERMINAL_IS_SETTINGS_LIST (list), 0);
+
+ return g_hash_table_size (list->children);
+}
diff --git a/src/terminal-settings-list.h b/src/terminal-settings-list.h
index ed37611..c68c499 100644
--- a/src/terminal-settings-list.h
+++ b/src/terminal-settings-list.h
@@ -69,6 +69,17 @@ char *terminal_settings_list_dup_default_child (TerminalSettingsList *list);
void terminal_settings_list_set_default_child (TerminalSettingsList *list,
const char *uuid);
+typedef void (* TerminalSettingsListForeachFunc) (TerminalSettingsList *list,
+ const char *uuid,
+ GSettings *child,
+ gpointer user_data);
+
+void terminal_settings_list_foreach_child (TerminalSettingsList *list,
+ TerminalSettingsListForeachFunc callback,
+ gpointer user_data);
+
+guint terminal_settings_list_get_n_children (TerminalSettingsList *list);
+
gboolean terminal_settings_list_valid_uuid (const char *str);
G_END_DECLS
diff --git a/src/terminal-util.c b/src/terminal-util.c
index b0c73e0..598d6c2 100644
--- a/src/terminal-util.c
+++ b/src/terminal-util.c
@@ -20,7 +20,6 @@
*/
#include "config.h"
-#define _GNU_SOURCE /* for strchrnul */
#include <string.h>
#include <stdlib.h>
@@ -41,9 +40,7 @@
#include "terminal-accels.h"
#include "terminal-app.h"
#include "terminal-intl.h"
-#include "terminal-screen.h"
#include "terminal-util.h"
-#include "terminal-window.h"
#include "terminal-libgsystem.h"
/**
@@ -136,8 +133,7 @@ open_url (GtkWindow *parent,
}
void
-terminal_util_show_help (const char *topic,
- GtkWindow *parent)
+terminal_util_show_help (const char *topic)
{
gs_free_error GError *error = NULL;
gs_free char *uri;
@@ -148,9 +144,9 @@ terminal_util_show_help (const char *topic,
uri = g_strdup ("help:gnome-terminal");
}
- if (!open_url (GTK_WINDOW (parent), uri, gtk_get_current_event_time (), &error))
+ if (!open_url (NULL, uri, gtk_get_current_event_time (), &error))
{
- terminal_util_show_error_dialog (GTK_WINDOW (parent), NULL, error,
+ terminal_util_show_error_dialog (NULL, NULL, error,
_("There was an error displaying help"));
}
}
@@ -160,13 +156,13 @@ terminal_util_show_help (const char *topic,
#define EMAILIFY(string) (g_strdelimit ((string), "%", '@'))
void
-terminal_util_show_about (GtkWindow *transient_parent G_GNUC_UNUSED)
+terminal_util_show_about (void)
{
static const char copyright[] =
"Copyright © 2002–2004 Havoc Pennington\n"
"Copyright © 2003–2004, 2007 Mariano Suárez-Alvarez\n"
"Copyright © 2006 Guilherme de S. Pastore\n"
- "Copyright © 2007–2016 Christian Persch";
+ "Copyright © 2007–2017 Christian Persch";
char *licence_text;
GKeyFile *key_file;
GBytes *bytes;
@@ -277,11 +273,10 @@ terminal_util_set_atk_name_description (GtkWidget *widget,
return;
}
-
if (!GTK_IS_ACCESSIBLE (obj))
return; /* This means GAIL is not loaded so we have the NoOp accessible */
-
- g_return_if_fail (GTK_IS_ACCESSIBLE (obj));
+
+ g_return_if_fail (GTK_IS_ACCESSIBLE (obj));
if (desc)
atk_object_set_description (obj, desc);
if (name)
@@ -413,7 +408,7 @@ main_object_destroy_cb (GtkWidget *widget)
}
void
-terminal_util_load_builder_resource (const char *path,
+terminal_util_load_widgets_resource (const char *path,
const char *main_object_name,
const char *object_name,
...)
@@ -460,6 +455,37 @@ terminal_util_load_builder_resource (const char *path,
}
}
+void
+terminal_util_load_objects_resource (const char *path,
+ const char *object_name,
+ ...)
+{
+ gs_unref_object GtkBuilder *builder;
+ GError *error = NULL;
+ va_list args;
+
+ builder = gtk_builder_new ();
+ gtk_builder_add_from_resource (builder, path, &error);
+ g_assert_no_error (error);
+
+ va_start (args, object_name);
+
+ while (object_name) {
+ GObject **objectptr;
+
+ objectptr = va_arg (args, GObject**);
+ *objectptr = gtk_builder_get_object (builder, object_name);
+ if (*objectptr)
+ g_object_ref (*objectptr);
+ else
+ g_error ("Failed to fetch object \"%s\" from resource \"%s\"\n", object_name, path);
+
+ object_name = va_arg (args, const char*);
+ }
+
+ va_end (args);
+}
+
gboolean
terminal_util_dialog_response_on_delete (GtkWindow *widget)
{
@@ -1285,3 +1311,179 @@ terminal_util_utf8_make_valid (const gchar *str,
return g_string_free (string, FALSE);
}
+
+#define TERMINAL_CACHE_DIR "gnome-terminal"
+#define TERMINAL_PRINT_SETTINGS_FILENAME "print-settings.ini"
+#define TERMINAL_PRINT_SETTINGS_GROUP_NAME "Print Settings"
+#define TERMINAL_PAGE_SETUP_GROUP_NAME "Page Setup"
+
+#define KEYFILE_FLAGS_FOR_LOAD (G_KEY_FILE_NONE)
+#define KEYFILE_FLAGS_FOR_SAVE (G_KEY_FILE_KEEP_COMMENTS | G_KEY_FILE_KEEP_TRANSLATIONS)
+
+static char *
+get_cache_dir (void)
+{
+ return g_build_filename (g_get_user_cache_dir (), TERMINAL_CACHE_DIR, NULL);
+}
+
+static gboolean
+ensure_cache_dir (void)
+{
+ gs_free char *cache_dir;
+ int r;
+
+ cache_dir = get_cache_dir ();
+ errno = 0;
+ r = g_mkdir_with_parents (cache_dir, 0700);
+ if (r == -1 && errno != EEXIST)
+ g_printerr ("Failed to create cache dir: %m\n");
+ return r == 0;
+}
+
+static char *
+get_cache_filename (const char *filename)
+{
+ gs_free char *cache_dir = get_cache_dir ();
+ return g_build_filename (cache_dir, filename, NULL);
+}
+
+static GKeyFile *
+load_cache_keyfile (const char *filename,
+ GKeyFileFlags flags,
+ gboolean ignore_error)
+{
+ gs_free char *path;
+ GKeyFile *keyfile;
+
+ path = get_cache_filename (filename);
+ keyfile = g_key_file_new ();
+ if (g_key_file_load_from_file (keyfile, path, flags, NULL) || ignore_error)
+ return keyfile;
+
+ g_key_file_unref (keyfile);
+ return NULL;
+}
+
+static void
+save_cache_keyfile (GKeyFile *keyfile,
+ const char *filename)
+{
+ gs_free char *path = NULL;
+ gs_free char *data = NULL;
+ gsize len = 0;
+
+ if (!ensure_cache_dir ())
+ return;
+
+ data = g_key_file_to_data (keyfile, &len, NULL);
+ if (data == NULL || len == 0)
+ return;
+
+ path = get_cache_filename (filename);
+
+ /* Ignore errors */
+ GError *err = NULL;
+ if (!g_file_set_contents (path, data, len, &err)) {
+ g_printerr ("Error saving print settings: %s\n", err->message);
+ g_error_free (err);
+ }
+}
+
+static void
+keyfile_remove_keys (GKeyFile *keyfile,
+ const char *group_name,
+ ...)
+{
+ va_list args;
+ const char *key;
+
+ va_start (args, group_name);
+ while ((key = va_arg (args, const char *)) != NULL) {
+ g_key_file_remove_key (keyfile, group_name, key, NULL);
+ }
+ va_end (args);
+}
+
+/**
+ * terminal_util_load_print_settings:
+ *
+ * Loads the saved print settings, if any.
+ */
+void
+terminal_util_load_print_settings (GtkPrintSettings **settings,
+ GtkPageSetup **page_setup)
+{
+ gs_unref_key_file GKeyFile *keyfile = load_cache_keyfile (TERMINAL_PRINT_SETTINGS_FILENAME,
+ KEYFILE_FLAGS_FOR_LOAD,
+ FALSE);
+ if (keyfile == NULL) {
+ *settings = NULL;
+ *page_setup = NULL;
+ return;
+ }
+
+ /* Ignore errors */
+ *settings = gtk_print_settings_new_from_key_file (keyfile,
+ TERMINAL_PRINT_SETTINGS_GROUP_NAME,
+ NULL);
+ *page_setup = gtk_page_setup_new_from_key_file (keyfile,
+ TERMINAL_PAGE_SETUP_GROUP_NAME,
+ NULL);
+}
+
+/**
+ * terminal_util_save_print_settings:
+ * @settings: (allow-none): a #GtkPrintSettings
+ * @page_setup: (allow-none): a #GtkPageSetup
+ *
+ * Saves the print settings.
+ */
+void
+terminal_util_save_print_settings (GtkPrintSettings *settings,
+ GtkPageSetup *page_setup)
+{
+ gs_unref_key_file GKeyFile *keyfile = NULL;
+
+ keyfile = load_cache_keyfile (TERMINAL_PRINT_SETTINGS_FILENAME,
+ KEYFILE_FLAGS_FOR_SAVE,
+ TRUE);
+ g_assert (keyfile != NULL);
+
+ if (settings != NULL)
+ gtk_print_settings_to_key_file (settings, keyfile,
+ TERMINAL_PRINT_SETTINGS_GROUP_NAME);
+
+ /* Some keys are not desirable to persist; remove these.
+ * This list comes from evince.
+ */
+ keyfile_remove_keys (keyfile,
+ TERMINAL_PRINT_SETTINGS_GROUP_NAME,
+ GTK_PRINT_SETTINGS_COLLATE,
+ GTK_PRINT_SETTINGS_NUMBER_UP,
+ GTK_PRINT_SETTINGS_N_COPIES,
+ GTK_PRINT_SETTINGS_OUTPUT_URI,
+ GTK_PRINT_SETTINGS_PAGE_RANGES,
+ GTK_PRINT_SETTINGS_PAGE_SET,
+ GTK_PRINT_SETTINGS_PRINT_PAGES,
+ GTK_PRINT_SETTINGS_REVERSE,
+ GTK_PRINT_SETTINGS_SCALE,
+ NULL);
+
+ if (page_setup != NULL)
+ gtk_page_setup_to_key_file (page_setup, keyfile,
+ TERMINAL_PAGE_SETUP_GROUP_NAME);
+
+ /* Some keys are not desirable to persist; remove these.
+ * This list comes from evince.
+ */
+ keyfile_remove_keys (keyfile,
+ TERMINAL_PAGE_SETUP_GROUP_NAME,
+ "page-setup-orientation",
+ "page-setup-margin-bottom",
+ "page-setup-margin-left",
+ "page-setup-margin-right",
+ "page-setup-margin-top",
+ NULL);
+
+ save_cache_keyfile (keyfile, TERMINAL_PRINT_SETTINGS_FILENAME);
+}
diff --git a/src/terminal-util.h b/src/terminal-util.h
index 040f487..d3b13f2 100644
--- a/src/terminal-util.h
+++ b/src/terminal-util.h
@@ -22,8 +22,6 @@
#include <gio/gio.h>
#include <gtk/gtk.h>
-#include "terminal-screen.h"
-
G_BEGIN_DECLS
void terminal_util_show_error_dialog (GtkWindow *transient_parent,
@@ -31,9 +29,9 @@ void terminal_util_show_error_dialog (GtkWindow *transient_parent,
GError *error,
const char *message_format, ...) G_GNUC_PRINTF(4, 5);
-void terminal_util_show_help (const char *topic, GtkWindow *transient_parent);
+void terminal_util_show_help (const char *topic);
-void terminal_util_show_about (GtkWindow *transient_parent);
+void terminal_util_show_about (void);
void terminal_util_set_labelled_by (GtkWidget *widget,
GtkLabel *label);
@@ -53,11 +51,15 @@ char *terminal_util_concat_uris (char **uris,
char *terminal_util_get_licence_text (void);
-void terminal_util_load_builder_resource (const char *path,
+void terminal_util_load_widgets_resource (const char *path,
const char *main_object_name,
const char *object_name,
...);
+void terminal_util_load_objects_resource (const char *path,
+ const char *object_name,
+ ...);
+
void terminal_util_dialog_focus_widget (GtkWidget *dialog,
const char *widget_name);
@@ -103,6 +105,12 @@ char *terminal_util_hyperlink_uri_label (const char *str);
gchar *terminal_util_utf8_make_valid (const gchar *str,
gssize len) G_GNUC_MALLOC;
+void terminal_util_load_print_settings (GtkPrintSettings **settings,
+ GtkPageSetup **page_setup);
+
+void terminal_util_save_print_settings (GtkPrintSettings *settings,
+ GtkPageSetup *page_setup);
+
G_END_DECLS
#endif /* TERMINAL_UTIL_H */
diff --git a/src/terminal-window.c b/src/terminal-window.c
index 2719708..cd5d4a3 100644
--- a/src/terminal-window.c
+++ b/src/terminal-window.c
@@ -1,8 +1,7 @@
-
/*
* Copyright © 2001 Havoc Pennington
* Copyright © 2002 Red Hat, Inc.
- * Copyright © 2007, 2008, 2009, 2011 Christian Persch
+ * Copyright © 2007, 2008, 2009, 2011, 2017 Christian Persch
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -36,12 +35,12 @@
#include "terminal-icon-button.h"
#include "terminal-intl.h"
#include "terminal-mdi-container.h"
+#include "terminal-menu-button.h"
#include "terminal-notebook.h"
#include "terminal-schemas.h"
#include "terminal-screen-container.h"
#include "terminal-search-popover.h"
#include "terminal-tab-label.h"
-#include "terminal-tabs-menu.h"
#include "terminal-util.h"
#include "terminal-window.h"
#include "terminal-libgsystem.h"
@@ -52,24 +51,9 @@ struct _TerminalWindowPrivate
GtkClipboard *clipboard;
- GtkActionGroup *action_group;
- GtkUIManager *ui_manager;
- guint ui_id;
-
- GtkActionGroup *profiles_action_group;
- guint profiles_ui_id;
-
- GtkActionGroup *encodings_action_group;
- guint encodings_ui_id;
-
- TerminalTabsMenu *tabs_menu;
-
TerminalScreenPopupInfo *popup_info;
guint remove_popup_info_idle;
- GtkActionGroup *new_terminal_action_group;
- guint new_terminal_ui_id;
-
GtkWidget *menubar;
TerminalMdiContainer *mdi_container;
GtkWidget *main_vbox;
@@ -101,7 +85,6 @@ struct _TerminalWindowPrivate
GtkWidget *confirm_close_dialog;
TerminalSearchPopover *search_popover;
- guint menubar_visible : 1;
guint use_default_menubar_visibility : 1;
guint disposed : 1;
@@ -115,22 +98,8 @@ struct _TerminalWindowPrivate
#define TERMINAL_WINDOW_CSS_NAME "terminal-window"
-#define PROFILE_DATA_KEY "GT::Profile"
-
-#define FILE_NEW_TERMINAL_UI_PATH "/menubar/File/FileNewTerminalProfiles"
-#define SET_ENCODING_UI_PATH "/menubar/Terminal/TerminalSetEncoding/EncodingsPH"
-#define SET_ENCODING_ACTION_NAME_PREFIX "TerminalSetEncoding"
-
-#define PROFILES_UI_PATH "/menubar/Terminal/TerminalProfiles"
-#define PROFILES_POPUP_UI_PATH "/Popup/PopupTerminalProfiles/ProfilesPH"
-
-#define SIZE_TO_UI_PATH "/menubar/Terminal/TerminalSizeToPH"
-#define SIZE_TO_ACTION_NAME_PREFIX "TerminalSizeTo"
-
-#define STOCK_NEW_WINDOW "window-new"
-#define STOCK_NEW_TAB "tab-new"
-
-#define ENCODING_DATA_KEY "encoding"
+#define MIN_WIDTH_CHARS 4
+#define MIN_HEIGHT_CHARS 1
#if 1
/*
@@ -170,70 +139,15 @@ static void mdi_screen_added_cb (TerminalMdiContainer *container,
static void mdi_screen_removed_cb (TerminalMdiContainer *container,
TerminalScreen *screen,
TerminalWindow *window);
+static void mdi_screens_reordered_cb (TerminalMdiContainer *container,
+ TerminalWindow *window);
static void screen_close_request_cb (TerminalMdiContainer *container,
TerminalScreen *screen,
TerminalWindow *window);
/* Menu action callbacks */
-static void file_new_terminal_callback (GtkAction *action,
- TerminalWindow *window);
-static void file_new_profile_callback (GtkAction *action,
- TerminalWindow *window);
-static void file_close_window_callback (GtkAction *action,
- TerminalWindow *window);
-static void file_save_contents_callback (GtkAction *action,
- TerminalWindow *window);
-static void file_close_tab_callback (GtkAction *action,
- TerminalWindow *window);
-static void edit_copy_callback (GtkAction *action,
- TerminalWindow *window);
-static void edit_copy_html_callback (GtkAction *action,
- TerminalWindow *window);
-static void edit_paste_callback (GtkAction *action,
- TerminalWindow *window);
-static void edit_select_all_callback (GtkAction *action,
- TerminalWindow *window);
-static void edit_preferences_callback (GtkAction *action,
- TerminalWindow *window);
-static void edit_current_profile_callback (GtkAction *action,
- TerminalWindow *window);
-static void view_menubar_toggled_callback (GtkToggleAction *action,
- TerminalWindow *window);
-static void view_fullscreen_toggled_callback (GtkToggleAction *action,
- TerminalWindow *window);
-static void view_zoom_in_callback (GtkAction *action,
- TerminalWindow *window);
-static void view_zoom_out_callback (GtkAction *action,
- TerminalWindow *window);
-static void view_zoom_normal_callback (GtkAction *action,
- TerminalWindow *window);
-static void terminal_add_encoding_callback (GtkAction *action,
- TerminalWindow *window);
-static void terminal_reset_callback (GtkAction *action,
- TerminalWindow *window);
-static void terminal_reset_clear_callback (GtkAction *action,
- TerminalWindow *window);
-static void terminal_readonly_toggled_callback(GtkToggleAction *action,
- TerminalWindow *window);
-static void tabs_next_or_previous_tab_cb (GtkAction *action,
- TerminalWindow *window);
-static void tabs_move_left_callback (GtkAction *action,
- TerminalWindow *window);
-static void tabs_move_right_callback (GtkAction *action,
- TerminalWindow *window);
-static void tabs_detach_tab_callback (GtkAction *action,
- TerminalWindow *window);
-static void help_contents_callback (GtkAction *action,
- TerminalWindow *window);
-static void help_about_callback (GtkAction *action,
- TerminalWindow *window);
-static void help_inspector_callback (GtkAction *action,
- TerminalWindow *window);
-
-static gboolean find_larger_zoom_factor (double current,
- double *found);
-static gboolean find_smaller_zoom_factor (double current,
- double *found);
+static gboolean find_larger_zoom_factor (double *zoom);
+static gboolean find_smaller_zoom_factor (double *zoom);
static void terminal_window_update_zoom_sensitivity (TerminalWindow *window);
static void terminal_window_update_search_sensitivity (TerminalScreen *screen,
TerminalWindow *window);
@@ -244,73 +158,12 @@ static gboolean confirm_close_window_or_tab (TerminalWindow *window,
TerminalScreen *screen);
static void
-profile_set_callback (TerminalScreen *screen,
- GSettings *old_profile,
- TerminalWindow *window);
-static void
sync_screen_icon_title (TerminalScreen *screen,
GParamSpec *psepc,
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)
-{
- gs_free char *text = NULL;
- 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_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[] = {
@@ -332,9 +185,9 @@ static const double zoom_factors[] = {
};
static gboolean
-find_larger_zoom_factor (double current,
- double *found)
+find_larger_zoom_factor (double *zoom)
{
+ double current = *zoom;
guint i;
for (i = 0; i < G_N_ELEMENTS (zoom_factors); ++i)
@@ -342,36 +195,125 @@ find_larger_zoom_factor (double current,
/* Find a font that's larger than this one */
if ((zoom_factors[i] - current) > 1e-6)
{
- *found = zoom_factors[i];
+ *zoom = zoom_factors[i];
return TRUE;
}
}
-
+
return FALSE;
}
static gboolean
-find_smaller_zoom_factor (double current,
- double *found)
+find_smaller_zoom_factor (double *zoom)
{
+ double current = *zoom;
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];
+ *zoom = zoom_factors[i];
return TRUE;
}
-
+
--i;
}
return FALSE;
}
+static inline GSimpleAction *
+lookup_action (TerminalWindow *window,
+ const char *name)
+{
+ GAction *action;
+
+ action = g_action_map_lookup_action (G_ACTION_MAP (window), name);
+ g_return_val_if_fail (action != NULL, NULL);
+
+ return G_SIMPLE_ACTION (action);
+}
+
+/* Context menu helpers */
+
+/* We don't want context menus to show accelerators.
+ * Setting the menu's accel group and/or accel path to NULL
+ * unfortunately doesn't hide accelerators; we need to walk
+ * the menu items and remove the accelerators on each,
+ * manually.
+ */
+static void
+popup_menu_remove_accelerators (GtkWidget *menu)
+{
+ gs_free_list GList *menu_items;
+ GList *l;
+
+ menu_items = gtk_container_get_children (GTK_CONTAINER (menu));
+ for (l = menu_items; l != NULL; l = l ->next) {
+ GtkWidget *label;
+
+ if (GTK_IS_BIN (l->data) &&
+ GTK_IS_ACCEL_LABEL ((label = gtk_bin_get_child (GTK_BIN (l->data)))))
+ gtk_accel_label_set_accel (GTK_ACCEL_LABEL (label), 0, 0);
+ }
+}
+
+/* Because we're using gtk_menu_attach_to_widget(), the attach
+ * widget holds a strong reference to the menu, causing it not to
+ * be automatically destroyed once popped down. So we need to
+ * detach the menu from the attach widget manually, which will
+ * cause the menu to be destroyed. We cannot do so in the
+ * "deactivate" handler however, since that causes the menu
+ * item activation to be lost. The "selection-done" signal
+ * appears to be the right place.
+ */
+
+static void
+popup_menu_destroy_cb (GtkWidget *menu,
+ gpointer user_data)
+{
+ /* g_printerr ("Menu %p destroyed!\n", menu); */
+}
+
+static void
+popup_menu_selection_done_cb (GtkMenu *menu,
+ gpointer user_data)
+{
+ g_signal_handlers_disconnect_by_func
+ (menu, G_CALLBACK (popup_menu_selection_done_cb), user_data);
+
+ /* g_printerr ("selection-done %p\n", menu); */
+
+ /* This will remove the ref from the attach widget widget, and destroy the menu */
+ gtk_menu_detach (menu);
+}
+
+static GtkWidget *
+context_menu_new (GMenuModel *menu,
+ GtkWidget *widget)
+{
+ GtkWidget *popup_menu;
+
+ popup_menu = gtk_menu_new_from_model (menu);
+ gtk_style_context_add_class (gtk_widget_get_style_context (popup_menu),
+ GTK_STYLE_CLASS_CONTEXT_MENU);
+ gtk_menu_set_screen (GTK_MENU (popup_menu), gtk_widget_get_screen (widget));
+ gtk_menu_attach_to_widget (GTK_MENU (popup_menu), widget, NULL);
+
+ popup_menu_remove_accelerators (popup_menu);
+
+ /* Staggered destruction */
+ g_signal_connect (popup_menu, "selection-done",
+ G_CALLBACK (popup_menu_selection_done_cb), widget);
+ g_signal_connect (popup_menu, "destroy",
+ G_CALLBACK (popup_menu_destroy_cb), widget);
+
+ return popup_menu;
+}
+
/* GAction callbacks */
static void
@@ -385,16 +327,15 @@ action_new_terminal_cb (GSimpleAction *action,
TerminalSettingsList *profiles_list;
gs_unref_object GSettings *profile = NULL;
gs_free char *new_working_directory = NULL;
- const char *mode_str, *uuid_str;
- TerminalNewTerminalMode mode;
- GdkModifierType modifiers;
g_assert (TERMINAL_IS_WINDOW (window));
app = terminal_app_get ();
+ const char *mode_str, *uuid_str;
g_variant_get (parameter, "(&s&s)", &mode_str, &uuid_str);
+ TerminalNewTerminalMode mode;
if (g_str_equal (mode_str, "tab"))
mode = TERMINAL_NEW_TERMINAL_MODE_TAB;
else if (g_str_equal (mode_str, "window"))
@@ -402,13 +343,22 @@ action_new_terminal_cb (GSimpleAction *action,
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;
+
+ GdkEvent *event = gtk_get_current_event ();
+ if (event != NULL) {
+ GdkModifierType modifiers;
+ guint button;
+
+ if ((gdk_event_get_state (event, &modifiers) &&
+ (modifiers & gtk_accelerator_get_default_mod_mask () & GDK_CONTROL_MASK)) ||
+ (gdk_event_get_button (event, &button) && (button == GDK_BUTTON_SECONDARY))) {
+ /* Invert */
+ if (mode == TERMINAL_NEW_TERMINAL_MODE_WINDOW)
+ mode = TERMINAL_NEW_TERMINAL_MODE_TAB;
+ else
+ mode = TERMINAL_NEW_TERMINAL_MODE_WINDOW;
+ }
+ gdk_event_free (event);
}
}
@@ -438,47 +388,19 @@ action_new_terminal_cb (GSimpleAction *action,
}
static void
-file_new_terminal_callback (GtkAction *action,
- TerminalWindow *window)
-{
- GSettings *profile;
- gs_free char *uuid;
- const char *name;
- GVariant *param;
-
- profile = g_object_get_data (G_OBJECT (action), PROFILE_DATA_KEY);
- if (profile)
- uuid = terminal_settings_list_dup_uuid_from_child (terminal_app_get_profiles_list (terminal_app_get ()),
profile);
- else
- uuid = g_strdup ("current");
-
- name = gtk_action_get_name (action);
- if (g_str_has_prefix (name, "FileNewTab"))
- param = g_variant_new ("(ss)", "tab", uuid);
- else if (g_str_has_prefix (name, "FileNewWindow"))
- param = g_variant_new ("(ss)", "window", uuid);
- else
- param = g_variant_new ("(ss)", "default", uuid);
-
- 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));
+ terminal_screen_get_profile (priv->active_screen));
}
-
#ifdef ENABLE_SAVE
+
static void
save_contents_dialog_on_response (GtkDialog *dialog, gint response_id, gpointer terminal)
{
@@ -524,20 +446,18 @@ save_contents_dialog_on_response (GtkDialog *dialog, gint response_id, gpointer
"%s", _("Could not save contents"));
}
}
-#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)
+ if (priv->active_screen == NULL)
return;
terminal = VTE_TERMINAL (priv->active_screen);
@@ -554,7 +474,7 @@ action_save_contents_cb (GSimpleAction *action,
/* 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_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);
@@ -562,18 +482,114 @@ action_save_contents_cb (GSimpleAction *action,
g_signal_connect (dialog, "delete_event", G_CALLBACK (terminal_util_dialog_response_on_delete), NULL);
gtk_window_present (GTK_WINDOW (dialog));
+}
+
#endif /* ENABLE_SAVE */
+
+#ifdef ENABLE_PRINT
+
+static void
+print_begin_cb (GtkPrintOperation *op,
+ GtkPrintContext *context,
+ TerminalApp *app)
+{
+ GtkPrintSettings *settings;
+ GtkPageSetup *page_setup;
+
+ /* Don't save if the print dialogue was cancelled */
+ if (gtk_print_operation_get_status(op) == GTK_PRINT_STATUS_FINISHED_ABORTED)
+ return;
+
+ settings = gtk_print_operation_get_print_settings (op);
+ page_setup = gtk_print_operation_get_default_page_setup (op);
+ terminal_util_save_print_settings (settings, page_setup);
}
static void
-file_save_contents_callback (GtkAction *action,
- TerminalWindow *window)
+print_done_cb (GtkPrintOperation *op,
+ GtkPrintOperationResult result,
+ TerminalWindow *window)
{
- g_action_activate (g_action_map_lookup_action (G_ACTION_MAP (window), "save-contents"),
- NULL);
+ if (result != GTK_PRINT_OPERATION_RESULT_ERROR)
+ return;
+
+ /* FIXME: show error */
}
static void
+action_print_cb (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
+{
+ TerminalWindow *window = user_data;
+ TerminalWindowPrivate *priv = window->priv;
+ gs_unref_object GtkPrintSettings *settings = NULL;
+ gs_unref_object GtkPageSetup *page_setup = NULL;
+ gs_unref_object GtkPrintOperation *op = NULL;
+ gs_free_error GError *error = NULL;
+ GtkPrintOperationResult result;
+
+ if (priv->active_screen == NULL)
+ return;
+
+ op = vte_print_operation_new (VTE_TERMINAL (priv->active_screen),
+ VTE_PRINT_OPERATION_DEFAULT /* flags */);
+ if (op == NULL)
+ return;
+
+ terminal_util_load_print_settings (&settings, &page_setup);
+ if (settings != NULL)
+ gtk_print_operation_set_print_settings (op, settings);
+ if (page_setup != NULL)
+ gtk_print_operation_set_default_page_setup (op, page_setup);
+
+ g_signal_connect (op, "begin-print", G_CALLBACK (print_begin_cb), window);
+ g_signal_connect (op, "done", G_CALLBACK (print_done_cb), window);
+
+ /* FIXME: show progress better */
+
+ result = gtk_print_operation_run (op,
+ /* this is the only supported one: */
+ GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG,
+ GTK_WINDOW (window),
+ &error);
+ /* VtePrintOperation always runs async */
+ g_assert_cmpint (result, ==, GTK_PRINT_OPERATION_RESULT_IN_PROGRESS);
+}
+
+#endif /* ENABLE_PRINT */
+
+#ifdef ENABLE_EXPORT
+
+static void
+action_export_cb (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
+{
+ TerminalWindow *window = user_data;
+ TerminalWindowPrivate *priv = window->priv;
+ gs_unref_object VteExportOperation *op = NULL;
+ gs_free_error GError *error = NULL;
+
+ if (priv->active_screen == NULL)
+ return;
+
+ op = vte_export_operation_new (VTE_TERMINAL (priv->active_screen),
+ TRUE /* interactive */,
+ VTE_EXPORT_FORMAT_ASK /* allow user to choose export format */,
+ NULL, NULL /* GSettings & key to load/store default directory from, FIXME
*/,
+ NULL, NULL /* progress callback & user data, FIXME */);
+ if (op == NULL)
+ return;
+
+ /* FIXME: show progress better */
+
+ vte_export_operation_run_async (op, GTK_WINDOW (window), NULL /* cancellable */);
+}
+
+#endif /* ENABLE_EXPORT */
+
+static void
action_close_cb (GSimpleAction *action,
GVariant *parameter,
gpointer user_data)
@@ -583,7 +599,7 @@ action_close_cb (GSimpleAction *action,
TerminalScreen *screen;
const char *mode_str;
- g_assert (parameter != NULL);
+ g_assert_nonnull (parameter);
g_variant_get (parameter, "&s", &mode_str);
if (g_str_equal (mode_str, "tab"))
@@ -591,7 +607,7 @@ action_close_cb (GSimpleAction *action,
else if (g_str_equal (mode_str, "window"))
screen = NULL;
else
- g_assert_not_reached ();
+ return;
if (confirm_close_window_or_tab (window, screen))
return;
@@ -612,10 +628,10 @@ action_copy_cb (GSimpleAction *action,
const char *format_str;
VteFormat format;
- if (!priv->active_screen)
+ if (priv->active_screen == NULL)
return;
- g_assert (parameter != NULL);
+ g_assert_nonnull (parameter);
g_variant_get (parameter, "&s", &format_str);
if (g_str_equal (format_str, "text"))
@@ -628,64 +644,83 @@ action_copy_cb (GSimpleAction *action,
vte_terminal_copy_clipboard_format (VTE_TERMINAL (priv->active_screen), format);
}
+/* Clipboard helpers */
+
+typedef struct {
+ GWeakRef screen_weak_ref;
+} PasteData;
+
static void
-edit_copy_callback (GtkAction *action,
- TerminalWindow *window)
+clipboard_uris_received_cb (GtkClipboard *clipboard,
+ /* const */ char **uris,
+ PasteData *data)
{
- g_action_activate (g_action_map_lookup_action (G_ACTION_MAP (window), "copy"),
- g_variant_new_string ("text"));
-}
+ gs_unref_object TerminalScreen *screen = NULL;
-static void edit_copy_html_callback (GtkAction *action,
- TerminalWindow *window)
-{
- g_action_activate (g_action_map_lookup_action (G_ACTION_MAP (window), "copy"),
- g_variant_new_string ("html"));
+ if (uris != NULL && uris[0] != NULL &&
+ (screen = g_weak_ref_get (&data->screen_weak_ref))) {
+ gs_free char *text;
+ gsize len;
+
+ /* This potentially modifies the strings in |uris| but that's ok */
+ terminal_util_transform_uris_to_quoted_fuse_paths (uris);
+ text = terminal_util_concat_uris (uris, &len);
+
+ vte_terminal_feed_child (VTE_TERMINAL (screen), text, len);
+ }
+
+ g_weak_ref_clear (&data->screen_weak_ref);
+ g_slice_free (PasteData, data);
}
static void
-action_paste_cb (GSimpleAction *action,
- GVariant *parameter,
- gpointer user_data)
+request_clipboard_contents_for_paste (TerminalWindow *window,
+ gboolean paste_as_uris)
{
- TerminalWindow *window = user_data;
TerminalWindowPrivate *priv = window->priv;
- GtkClipboard *clipboard;
- PasteData *data;
- const char *mode;
-
- g_assert (parameter != NULL);
+ GdkAtom *targets;
+ int n_targets;
- if (!priv->active_screen)
+ if (priv->active_screen == NULL)
return;
- g_variant_get (parameter, "&s", &mode);
+ targets = terminal_app_get_clipboard_targets (terminal_app_get (),
+ priv->clipboard,
+ &n_targets);
+ if (targets == NULL)
+ return;
- data = g_slice_new (PasteData);
- data->screen = g_object_ref (priv->active_screen);
- data->uris_as_paths = g_str_equal (mode, "uri");
+ if (paste_as_uris && gtk_targets_include_uri (targets, n_targets)) {
+ PasteData *data = g_slice_new (PasteData);
+ g_weak_ref_init (&data->screen_weak_ref, priv->active_screen);
- clipboard = gtk_widget_get_clipboard (GTK_WIDGET (window), GDK_SELECTION_CLIPBOARD);
- gtk_clipboard_request_targets (clipboard,
- (GtkClipboardTargetsReceivedFunc) clipboard_targets_received_cb,
- data);
+ gtk_clipboard_request_uris (priv->clipboard,
+ (GtkClipboardURIReceivedFunc) clipboard_uris_received_cb,
+ data);
+ return;
+ } else if (gtk_targets_include_text (targets, n_targets)) {
+ vte_terminal_paste_clipboard (VTE_TERMINAL (priv->active_screen));
+ }
}
static void
-edit_paste_callback (GtkAction *action,
- TerminalWindow *window)
+action_paste_text_cb (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
{
- const char *name;
- GVariant *parameter;
+ TerminalWindow *window = user_data;
- 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");
+ request_clipboard_contents_for_paste (window, FALSE);
+}
- g_action_activate (g_action_map_lookup_action (G_ACTION_MAP (window), "paste"),
- parameter);
+static void
+action_paste_uris_cb (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
+{
+ TerminalWindow *window = user_data;
+
+ request_clipboard_contents_for_paste (window, TRUE);
}
static void
@@ -696,21 +731,13 @@ action_select_all_cb (GSimpleAction *action,
TerminalWindow *window = user_data;
TerminalWindowPrivate *priv = window->priv;
- if (!priv->active_screen)
+ if (priv->active_screen == NULL)
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)
@@ -718,7 +745,7 @@ action_reset_cb (GSimpleAction *action,
TerminalWindow *window = user_data;
TerminalWindowPrivate *priv = window->priv;
- g_assert (parameter != NULL);
+ g_assert_nonnull (parameter);
if (priv->active_screen == NULL)
return;
@@ -729,101 +756,146 @@ action_reset_cb (GSimpleAction *action,
}
static void
-action_switch_tab_cb (GSimpleAction *action,
- GVariant *parameter,
- gpointer user_data)
+tab_switch_relative (TerminalWindow *window,
+ int change)
{
- TerminalWindow *window = user_data;
TerminalWindowPrivate *priv = window->priv;
- int value;
+ int n_screens, value;
- g_assert (parameter != NULL);
+ n_screens = terminal_mdi_container_get_n_screens (priv->mdi_container);
+ value = terminal_mdi_container_get_active_screen_num (priv->mdi_container) + change;
- value = g_variant_get_int32 (parameter);
+ gboolean keynav_wrap_around;
+ g_object_get (gtk_widget_get_settings (GTK_WIDGET (window)),
+ "gtk-keynav-wrap-around", &keynav_wrap_around,
+ NULL);
+ if (keynav_wrap_around) {
+ if (value < 0)
+ value += n_screens;
+ else if (value >= n_screens)
+ value -= n_screens;
+ }
- 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);
+ if (value < 0 || value >= n_screens)
+ return;
+
+ g_action_change_state (G_ACTION (lookup_action (window, "active-tab")),
+ g_variant_new_int32 (value));
}
static void
-action_move_tab_cb (GSimpleAction *action,
- GVariant *parameter,
- gpointer user_data)
+action_tab_switch_left_cb (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
+{
+ TerminalWindow *window = user_data;
+
+ tab_switch_relative (window, -1);
+}
+
+static void
+action_tab_switch_right_cb (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
+{
+ TerminalWindow *window = user_data;
+
+ tab_switch_relative (window, 1);
+}
+
+static void
+action_tab_move_left_cb (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
{
TerminalWindow *window = user_data;
TerminalWindowPrivate *priv = window->priv;
- int value;
-
- g_assert (parameter != NULL);
+ int change;
- value = g_variant_get_int32 (parameter);
+ if (priv->active_screen == NULL)
+ return;
+
+ change = gtk_widget_get_direction (GTK_WIDGET (window)) == GTK_TEXT_DIR_RTL ? 1 : -1;
terminal_mdi_container_reorder_screen (priv->mdi_container,
terminal_mdi_container_get_active_screen (priv->mdi_container),
- value);
+ change);
}
static void
-action_zoom_cb (GSimpleAction *action,
- GVariant *parameter,
- gpointer user_data)
+action_tab_move_right_cb (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
{
TerminalWindow *window = user_data;
TerminalWindowPrivate *priv = window->priv;
- int value;
- double zoom;
-
+ int change;
+
if (priv->active_screen == NULL)
return;
- g_assert (parameter != NULL);
+ change = gtk_widget_get_direction (GTK_WIDGET (window)) == GTK_TEXT_DIR_RTL ? -1 : 1;
+ terminal_mdi_container_reorder_screen (priv->mdi_container,
+ terminal_mdi_container_get_active_screen (priv->mdi_container),
+ change);
+}
- value = g_variant_get_int32 (parameter);
+static void
+action_zoom_in_cb (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
+{
+ TerminalWindow *window = user_data;
+ TerminalWindowPrivate *priv = window->priv;
+ double zoom;
- if (value == 0) {
- zoom = PANGO_SCALE_MEDIUM;
- } else if (value == 1) {
- zoom = vte_terminal_get_font_scale (VTE_TERMINAL (priv->active_screen));
- if (!find_larger_zoom_factor (zoom, &zoom))
- return;
- } else if (value == -1) {
- zoom = vte_terminal_get_font_scale (VTE_TERMINAL (priv->active_screen));
- if (!find_smaller_zoom_factor (zoom, &zoom))
- return;
- } else
- g_assert_not_reached ();
+ if (priv->active_screen == NULL)
+ return;
+
+ zoom = vte_terminal_get_font_scale (VTE_TERMINAL (priv->active_screen));
+ if (!find_larger_zoom_factor (&zoom))
+ return;
vte_terminal_set_font_scale (VTE_TERMINAL (priv->active_screen), zoom);
terminal_window_update_zoom_sensitivity (window);
}
static void
-view_zoom_in_callback (GtkAction *action,
- TerminalWindow *window)
+action_zoom_out_cb (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
{
- g_action_activate (g_action_map_lookup_action (G_ACTION_MAP (window), "zoom"),
- g_variant_new_int32 (1));
-}
+ TerminalWindow *window = user_data;
+ TerminalWindowPrivate *priv = window->priv;
+ double zoom;
-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));
+ if (priv->active_screen == NULL)
+ return;
+
+ zoom = vte_terminal_get_font_scale (VTE_TERMINAL (priv->active_screen));
+ if (!find_smaller_zoom_factor (&zoom))
+ return;
+
+ vte_terminal_set_font_scale (VTE_TERMINAL (priv->active_screen), zoom);
+ terminal_window_update_zoom_sensitivity (window);
}
static void
-view_zoom_normal_callback (GtkAction *action,
- TerminalWindow *window)
+action_zoom_normal_cb (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
{
- g_action_activate (g_action_map_lookup_action (G_ACTION_MAP (window), "zoom"),
- g_variant_new_int32 (0));
+ TerminalWindow *window = user_data;
+ TerminalWindowPrivate *priv = window->priv;
+
+ if (priv->active_screen == NULL)
+ return;
+
+ vte_terminal_set_font_scale (VTE_TERMINAL (priv->active_screen), PANGO_SCALE_MEDIUM);
+ terminal_window_update_zoom_sensitivity (window);
}
static void
-action_detach_tab_cb (GSimpleAction *action,
+action_tab_detach_cb (GSimpleAction *action,
GVariant *parameter,
gpointer user_data)
{
@@ -839,7 +911,6 @@ action_detach_tab_cb (GSimpleAction *action,
screen = priv->active_screen;
- /* FIXME: this seems wrong if tabs are shown in the window */
terminal_screen_get_size (screen, &width, &height);
g_snprintf (geometry, sizeof (geometry), "%dx%d", width, height);
@@ -853,21 +924,11 @@ action_detach_tab_cb (GSimpleAction *action,
}
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));
+ terminal_util_show_help (NULL);
}
static void
@@ -875,19 +936,15 @@ action_about_cb (GSimpleAction *action,
GVariant *parameter,
gpointer user_data)
{
- TerminalWindow *window = user_data;
-
- terminal_util_show_about (GTK_WINDOW (window));
+ terminal_util_show_about ();
}
static void
-action_preferences_cb (GSimpleAction *action,
- GVariant *parameter,
- gpointer user_data)
+action_edit_preferences_cb (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
{
- TerminalWindow *window = user_data;
-
- terminal_app_edit_preferences (terminal_app_get (), GTK_WINDOW (window));
+ terminal_app_edit_preferences (terminal_app_get ());
}
static void
@@ -900,11 +957,122 @@ action_edit_profile_cb (GSimpleAction *action,
terminal_app_edit_profile (terminal_app_get (),
terminal_screen_get_profile (priv->active_screen),
- GTK_WINDOW (window),
NULL);
}
static void
+action_size_to_cb (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
+{
+ TerminalWindow *window = user_data;
+ TerminalWindowPrivate *priv = window->priv;
+ guint width, height;
+
+ g_assert_nonnull (parameter);
+
+ if (priv->active_screen == NULL)
+ return;
+
+ g_variant_get (parameter, "(uu)", &width, &height);
+ if (width < MIN_WIDTH_CHARS || height < MIN_HEIGHT_CHARS ||
+ width > 256 || height > 256)
+ return;
+
+ vte_terminal_set_size (VTE_TERMINAL (priv->active_screen), width, height);
+ terminal_window_update_size (window);
+}
+
+static void
+action_open_match_cb (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
+{
+ TerminalWindow *window = user_data;
+ TerminalWindowPrivate *priv = window->priv;
+ TerminalScreenPopupInfo *info = priv->popup_info;
+
+ if (info == NULL)
+ return;
+ if (info->url == NULL)
+ return;
+
+ terminal_util_open_url (GTK_WIDGET (window), info->url, info->url_flavor,
+ gtk_get_current_event_time ());
+}
+
+static void
+action_copy_match_cb (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
+{
+ TerminalWindow *window = user_data;
+ TerminalWindowPrivate *priv = window->priv;
+ TerminalScreenPopupInfo *info = priv->popup_info;
+
+ if (info == NULL)
+ return;
+ if (info->url == NULL)
+ return;
+
+ gtk_clipboard_set_text (priv->clipboard, info->url, -1);
+}
+
+static void
+action_open_hyperlink_cb (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
+{
+ TerminalWindow *window = user_data;
+ TerminalWindowPrivate *priv = window->priv;
+ TerminalScreenPopupInfo *info = priv->popup_info;
+
+ if (info == NULL)
+ return;
+ if (info->hyperlink == NULL)
+ return;
+
+ terminal_util_open_url (GTK_WIDGET (window), info->hyperlink, FLAVOR_AS_IS,
+ gtk_get_current_event_time ());
+}
+
+static void
+action_copy_hyperlink_cb (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
+{
+ TerminalWindow *window = user_data;
+ TerminalWindowPrivate *priv = window->priv;
+ TerminalScreenPopupInfo *info = priv->popup_info;
+
+ if (info == NULL)
+ return;
+ if (info->hyperlink == NULL)
+ return;
+
+ gtk_clipboard_set_text (priv->clipboard, info->hyperlink, -1);
+}
+
+static void
+action_leave_fullscreen_cb (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
+{
+ TerminalWindow *window = user_data;
+
+ g_action_group_change_action_state (G_ACTION_GROUP (window), "fullscreen",
+ g_variant_new_boolean (FALSE));
+}
+
+static void
+action_inspector_cb (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
+{
+ gtk_window_set_interactive_debugging (TRUE);
+}
+
+static void
search_popover_search_cb (TerminalSearchPopover *popover,
gboolean backward,
TerminalWindow *window)
@@ -953,8 +1121,11 @@ search_popover_notify_wrap_around_cb (TerminalSearchPopover *popover,
}
static void
-terminal_window_ensure_search_popover (TerminalWindow *window)
+action_find_cb (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
{
+ TerminalWindow *window = user_data;
TerminalWindowPrivate *priv = window->priv;
if (G_UNLIKELY(priv->active_screen == NULL))
@@ -971,7 +1142,7 @@ terminal_window_ensure_search_popover (TerminalWindow *window)
if (priv->active_screen == NULL)
return;
- priv->search_popover = terminal_search_popover_new (GTK_WIDGET (priv->menubar));
+ priv->search_popover = terminal_search_popover_new (GTK_WIDGET (window));
g_signal_connect (priv->search_popover, "search", G_CALLBACK (search_popover_search_cb), window);
@@ -987,103 +1158,196 @@ terminal_window_ensure_search_popover (TerminalWindow *window)
}
static void
-action_find_cb (GSimpleAction *action,
- GVariant *parameter,
- gpointer user_data)
+action_find_forward_cb (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
{
TerminalWindow *window = user_data;
TerminalWindowPrivate *priv = window->priv;
- const char *mode;
- if (G_UNLIKELY (!priv->active_screen))
+ if (priv->active_screen == NULL)
return;
- g_variant_get (parameter, "&s", &mode);
+ vte_terminal_search_find_next (VTE_TERMINAL (priv->active_screen));
+}
- if (g_str_equal (mode, "find")) {
- terminal_window_ensure_search_popover (window);
- } else if (g_str_equal (mode, "next")) {
- vte_terminal_search_find_next (VTE_TERMINAL (priv->active_screen));
- } else if (g_str_equal (mode, "previous")) {
- vte_terminal_search_find_previous (VTE_TERMINAL (priv->active_screen));
- } else if (g_str_equal (mode, "clear")) {
- vte_terminal_search_set_regex (VTE_TERMINAL (priv->active_screen), NULL, 0);
- } else
+static void
+action_find_backward_cb (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
+{
+ TerminalWindow *window = user_data;
+ TerminalWindowPrivate *priv = window->priv;
+
+ if (priv->active_screen == NULL)
return;
+
+ vte_terminal_search_find_previous (VTE_TERMINAL (priv->active_screen));
}
static void
-search_find_callback (GtkAction *action,
- TerminalWindow *window)
+action_find_clear_cb (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
{
- g_action_activate (g_action_map_lookup_action (G_ACTION_MAP (window), "find"),
- g_variant_new ("s", "find"));
+ TerminalWindow *window = user_data;
+ TerminalWindowPrivate *priv = window->priv;
+
+ if (priv->active_screen == NULL)
+ return;
+
+ vte_terminal_search_set_regex (VTE_TERMINAL (priv->active_screen), NULL, 0);
}
static void
-search_find_next_callback (GtkAction *action,
- TerminalWindow *window)
+action_shadow_activate_cb (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
{
- g_action_activate (g_action_map_lookup_action (G_ACTION_MAP (window), "find"),
- g_variant_new ("s", "next"));
+ TerminalWindow *window = user_data;
+ gs_free char *param = g_variant_print(parameter, TRUE);
+
+ _terminal_debug_print (TERMINAL_DEBUG_ACCELS,
+ "Window %p shadow action activated for %s\n",
+ window, param);
+
+ /* We make sure in terminal-accels to always install the keybinding
+ * for the real action first, so that it's first in line for activation.
+ * That means we can make this here a NOP, instead of forwarding the
+ * activation to the shadowed action.
+ */
}
static void
-search_find_prev_callback (GtkAction *action,
- TerminalWindow *window)
+action_menubar_visible_state_cb (GSimpleAction *action,
+ GVariant *state,
+ gpointer user_data)
{
- g_action_activate (g_action_map_lookup_action (G_ACTION_MAP (window), "find"),
- g_variant_new ("s", "previous"));
+ TerminalWindow *window = user_data;
+ gboolean active;
+
+ active = g_variant_get_boolean (state);
+ terminal_window_set_menubar_visible (window, active); /* this also sets the action state */
}
static void
-search_clear_highlight_callback (GtkAction *action,
- TerminalWindow *window)
+action_fullscreen_state_cb (GSimpleAction *action,
+ GVariant *state,
+ gpointer user_data)
{
- g_action_activate (g_action_map_lookup_action (G_ACTION_MAP (window), "find"),
- g_variant_new ("s", "clear"));
+ TerminalWindow *window = user_data;
+
+ 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));
+
+ /* The window-state-changed callback will update the action's actual state */
}
static void
-action_toggle_state_cb (GSimpleAction *saction,
- GVariant *parameter,
- gpointer user_data)
+action_read_only_state_cb (GSimpleAction *action,
+ GVariant *state,
+ gpointer user_data)
{
- GAction *action = G_ACTION (saction);
- gs_unref_variant GVariant *state;
+ TerminalWindow *window = user_data;
+ TerminalWindowPrivate *priv = window->priv;
- state = g_action_get_state (action);
- g_action_change_state (action, g_variant_new_boolean (!g_variant_get_boolean (state)));
+ g_assert_nonnull (state);
+
+ g_simple_action_set_state (action, state);
+
+ if (priv->active_screen == NULL)
+ return;
+
+ vte_terminal_set_input_enabled (VTE_TERMINAL (priv->active_screen),
+ !g_variant_get_boolean (state));
}
static void
-action_show_menubar_state_cb (GSimpleAction *action,
- GVariant *state,
- gpointer user_data)
+action_profile_state_cb (GSimpleAction *action,
+ GVariant *state,
+ gpointer user_data)
{
TerminalWindow *window = user_data;
+ TerminalWindowPrivate *priv = window->priv;
+ TerminalSettingsList *profiles_list;
+ const gchar *uuid;
+ gs_unref_object GSettings *profile;
+
+ g_assert_nonnull (state);
+
+ uuid = g_variant_get_string (state, NULL);
+ profiles_list = terminal_app_get_profiles_list (terminal_app_get ());
+ profile = terminal_settings_list_ref_child (profiles_list, uuid);
+ if (profile == NULL)
+ return;
g_simple_action_set_state (action, state);
- terminal_window_set_menubar_visible (window, g_variant_get_boolean (state));
+ terminal_screen_set_profile (priv->active_screen, profile);
}
static void
-action_fullscreen_state_cb (GSimpleAction *action,
+action_encoding_state_cb (GSimpleAction *action,
+ GVariant *state,
+ gpointer user_data)
+{
+ TerminalWindow *window = user_data;
+ TerminalWindowPrivate *priv = window->priv;
+
+ g_assert_nonnull (state);
+
+ if (priv->active_screen == NULL)
+ return;
+
+ const char *charset = g_variant_get_string (state, NULL);
+ g_warn_if_fail (terminal_encodings_is_known_charset (charset));
+
+ /* Only change the state if changing encoding worked */
+ if (vte_terminal_set_encoding (VTE_TERMINAL (priv->active_screen), charset, NULL)) {
+ g_simple_action_set_state (action, state);
+ }
+}
+
+static void
+action_active_tab_set_cb (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
+{
+ TerminalWindow *window = user_data;
+ TerminalWindowPrivate *priv = window->priv;
+ int value, n_screens;
+
+ g_assert_nonnull (parameter);
+
+ n_screens = terminal_mdi_container_get_n_screens (priv->mdi_container);
+
+ value = g_variant_get_int32 (parameter);
+ if (value < 0)
+ value += n_screens;
+ if (value < 0 || value >= n_screens)
+ return;
+
+ g_action_change_state (G_ACTION (action), g_variant_new_int32 (value));
+}
+
+static void
+action_active_tab_state_cb (GSimpleAction *action,
GVariant *state,
gpointer user_data)
{
TerminalWindow *window = user_data;
+ TerminalWindowPrivate *priv = window->priv;
- g_simple_action_set_state (action, state);
+ g_assert_nonnull (state);
- if (!gtk_widget_get_realized (GTK_WIDGET (window)))
- return;
+ g_simple_action_set_state (action, state);
- if (g_variant_get_boolean (state))
- gtk_window_fullscreen (GTK_WINDOW (window));
- else
- gtk_window_unfullscreen (GTK_WINDOW (window));
+ terminal_mdi_container_set_active_screen_num (priv->mdi_container, g_variant_get_int32 (state));
}
/* Menubar mnemonics & accel settings handling */
@@ -1093,9 +1357,14 @@ enable_menubar_accel_changed_cb (GSettings *settings,
const char *key,
GtkSettings *gtk_settings)
{
- /* const */ char *saved_menubar_accel;
+#if GTK_CHECK_VERSION (3, 20, 0)
+ if (g_settings_get_boolean (settings, key))
+ gtk_settings_reset_property (gtk_settings, "gtk-menu-bar-accel");
+ else
+ g_object_set (gtk_settings, "gtk-menu-bar-accel", NULL, NULL);
+#else
+ const char *saved_menubar_accel;
- /* FIXME: Once gtk+ bug 507398 is fixed, use that to reset the property instead */
/* Now this is a bad hack on so many levels. */
saved_menubar_accel = g_object_get_data (G_OBJECT (gtk_settings), "GT::gtk-menu-bar-accel");
@@ -1103,6 +1372,7 @@ enable_menubar_accel_changed_cb (GSettings *settings,
g_object_set (gtk_settings, "gtk-menu-bar-accel", saved_menubar_accel, NULL);
else
g_object_set (gtk_settings, "gtk-menu-bar-accel", NULL, NULL);
+#endif
}
static void
@@ -1115,28 +1385,6 @@ app_setting_notify_destroy_cb (GtkSettings *gtk_settings)
/* utility functions */
-static char *
-escape_underscores (const char *name)
-{
- GString *escaped_name;
-
- g_assert (name != NULL);
-
- /* Who'd use more that 4 underscores in a profile name... */
- escaped_name = g_string_sized_new (strlen (name) + 4 + 1);
-
- while (*name)
- {
- if (*name == '_')
- g_string_append (escaped_name, "__");
- else
- g_string_append_c (escaped_name, *name);
- name++;
- }
-
- return g_string_free (escaped_name, FALSE);
-}
-
static int
find_tab_num_at_pos (GtkNotebook *notebook,
int screen_x,
@@ -1210,7 +1458,7 @@ position_menu_under_widget (GtkMenu *menu,
screen = gtk_widget_get_screen (GTK_WIDGET (menu));
monitor_num = gdk_screen_get_monitor_at_window (screen, widget_window);
if (monitor_num < 0)
- monitor_num = 0;
+ monitor_num = 0;
gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
gdk_window_get_origin (widget_window, x, y);
@@ -1219,9 +1467,9 @@ position_menu_under_widget (GtkMenu *menu,
*x += widget_allocation.x;
*y += widget_allocation.y;
}
- if (gtk_widget_get_direction (container) == GTK_TEXT_DIR_LTR)
+ if (gtk_widget_get_direction (container) == GTK_TEXT_DIR_LTR)
*x += widget_allocation.width - req.width;
- else
+ else
*x += req.width - menu_req.width;
if ((*y + widget_allocation.height + menu_req.height) <= monitor.y + monitor.height)
@@ -1237,533 +1485,49 @@ position_menu_under_widget (GtkMenu *menu,
}
static void
-terminal_set_profile_toggled_callback (GtkToggleAction *action,
- TerminalWindow *window)
-{
- TerminalWindowPrivate *priv = window->priv;
- GSettings *profile;
-
- if (!gtk_toggle_action_get_active (action))
- return;
-
- if (priv->active_screen == NULL)
- return;
-
- profile = g_object_get_data (G_OBJECT (action), PROFILE_DATA_KEY);
- g_assert (profile);
-
- g_signal_handlers_block_by_func (priv->active_screen, G_CALLBACK (profile_set_callback), window);
- terminal_screen_set_profile (priv->active_screen, profile);
- g_signal_handlers_unblock_by_func (priv->active_screen, G_CALLBACK (profile_set_callback), window);
-}
-
-static void
-profile_visible_name_notify_cb (GSettings *profile,
- const char *key,
- GtkAction *action)
-{
- gs_free char *visible_name;
- char *dot;
- gs_free char *display_name;
- guint num;
-
- visible_name = g_settings_get_string (profile, TERMINAL_PROFILE_VISIBLE_NAME_KEY);
- display_name = escape_underscores (visible_name);
-
- dot = strchr (gtk_action_get_name (action), '.');
- if (dot != NULL)
- {
- gs_free char *free_me;
-
- num = g_ascii_strtoll (dot + 1, NULL, 10);
-
- free_me = display_name;
- if (num < 10)
- /* Translators: This is the label of a menu item to choose a profile.
- * _%u is used as the accelerator (with u between 1 and 9), and
- * the %s is the name of the terminal profile.
- */
- display_name = g_strdup_printf (_("_%u. %s"), num, display_name);
- else if (num < 36)
- /* Translators: This is the label of a menu item to choose a profile.
- * _%c is used as the accelerator (it will be a character between A and Z),
- * and the %s is the name of the terminal profile.
- */
- display_name = g_strdup_printf (_("_%c. %s"), (guchar)('A' + num - 10), display_name);
- else
- free_me = NULL;
- }
-
- g_object_set (action, "label", display_name, NULL);
-}
-
-static void
-disconnect_profiles_from_actions_in_group (GtkActionGroup *action_group)
-{
- GList *actions, *l;
-
- actions = gtk_action_group_list_actions (action_group);
- for (l = actions; l != NULL; l = l->next)
- {
- GObject *action = G_OBJECT (l->data);
- GSettings *profile;
-
- profile = g_object_get_data (action, PROFILE_DATA_KEY);
- if (!profile)
- continue;
-
- g_signal_handlers_disconnect_by_func (profile, G_CALLBACK (profile_visible_name_notify_cb), action);
- }
- g_list_free (actions);
-}
-
-static void
terminal_window_update_set_profile_menu_active_profile (TerminalWindow *window)
{
TerminalWindowPrivate *priv = window->priv;
GSettings *new_active_profile;
- GList *actions, *l;
-
- if (!priv->profiles_action_group)
- return;
-
- if (!priv->active_screen)
- return;
-
- new_active_profile = terminal_screen_get_profile (priv->active_screen);
-
- actions = gtk_action_group_list_actions (priv->profiles_action_group);
- for (l = actions; l != NULL; l = l->next)
- {
- GObject *action = G_OBJECT (l->data);
- GSettings *profile;
-
- profile = g_object_get_data (action, PROFILE_DATA_KEY);
- if (profile != new_active_profile)
- continue;
-
- g_signal_handlers_block_by_func (action, G_CALLBACK (terminal_set_profile_toggled_callback), window);
- gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
- g_signal_handlers_unblock_by_func (action, G_CALLBACK (terminal_set_profile_toggled_callback), window);
-
- break;
- }
- g_list_free (actions);
-}
-
-static void
-terminal_window_update_set_profile_menu (TerminalWindow *window)
-{
- TerminalWindowPrivate *priv = window->priv;
- GSettings *active_profile;
- GtkActionGroup *action_group;
- GtkAction *action;
- TerminalSettingsList *profiles_list;
- GList *profiles, *p;
- GSList *group;
- guint n;
- gboolean single_profile;
-
- /* Remove the old UI */
- if (priv->profiles_ui_id != 0)
- {
- gtk_ui_manager_remove_ui (priv->ui_manager, priv->profiles_ui_id);
- priv->profiles_ui_id = 0;
- }
-
- if (priv->profiles_action_group != NULL)
- {
- disconnect_profiles_from_actions_in_group (priv->profiles_action_group);
- gtk_ui_manager_remove_action_group (priv->ui_manager,
- priv->profiles_action_group);
- priv->profiles_action_group = NULL;
- }
-
- profiles_list = terminal_app_get_profiles_list (terminal_app_get ());
- profiles = terminal_profiles_list_ref_children_sorted (profiles_list);
-
- action = gtk_action_group_get_action (priv->action_group, "TerminalProfiles");
- single_profile = !profiles || profiles->next == NULL; /* list length <= 1 */
- gtk_action_set_sensitive (action, !single_profile);
-
- if (profiles == NULL)
- return;
-
- if (priv->active_screen)
- active_profile = terminal_screen_get_profile (priv->active_screen);
- else
- active_profile = NULL;
-
- action_group = priv->profiles_action_group = gtk_action_group_new ("Profiles");
- gtk_ui_manager_insert_action_group (priv->ui_manager, action_group, -1);
- g_object_unref (action_group);
-
- priv->profiles_ui_id = gtk_ui_manager_new_merge_id (priv->ui_manager);
-
- group = NULL;
- n = 0;
- for (p = profiles; p != NULL; p = p->next)
- {
- GSettings *profile = (GSettings *) p->data;
- gs_unref_object GtkRadioAction *profile_action;
- char name[32];
-
- g_snprintf (name, sizeof (name), "TerminalSetProfile%u", n++);
-
- profile_action = gtk_radio_action_new (name,
- NULL,
- NULL,
- NULL,
- n);
-
- gtk_radio_action_set_group (profile_action, group);
- group = gtk_radio_action_get_group (profile_action);
-
- if (profile == active_profile)
- gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (profile_action), TRUE);
-
- g_object_set_data_full (G_OBJECT (profile_action),
- PROFILE_DATA_KEY,
- g_object_ref (profile),
- (GDestroyNotify) g_object_unref);
- profile_visible_name_notify_cb (profile, TERMINAL_PROFILE_VISIBLE_NAME_KEY, GTK_ACTION
(profile_action));
- g_signal_connect (profile, "changed::" TERMINAL_PROFILE_VISIBLE_NAME_KEY,
- G_CALLBACK (profile_visible_name_notify_cb), profile_action);
- g_signal_connect (profile_action, "toggled",
- G_CALLBACK (terminal_set_profile_toggled_callback), window);
-
- gtk_action_group_add_action (action_group, GTK_ACTION (profile_action));
-
- gtk_ui_manager_add_ui (priv->ui_manager, priv->profiles_ui_id,
- PROFILES_UI_PATH,
- name, name,
- GTK_UI_MANAGER_MENUITEM, FALSE);
- gtk_ui_manager_add_ui (priv->ui_manager, priv->profiles_ui_id,
- PROFILES_POPUP_UI_PATH,
- name, name,
- GTK_UI_MANAGER_MENUITEM, FALSE);
- }
-
- g_list_free_full (profiles, (GDestroyNotify) g_object_unref);
-}
-
-static void
-terminal_window_create_new_terminal_action (TerminalWindow *window,
- GSettings *profile,
- const char *name,
- guint num,
- GCallback callback)
-{
- TerminalWindowPrivate *priv = window->priv;
- gs_unref_object GtkAction *action;
-
- action = gtk_action_new (name, NULL, NULL, NULL);
-
- g_object_set_data_full (G_OBJECT (action),
- PROFILE_DATA_KEY,
- g_object_ref (profile),
- (GDestroyNotify) g_object_unref);
- profile_visible_name_notify_cb (profile, TERMINAL_PROFILE_VISIBLE_NAME_KEY, action);
- g_signal_connect (profile, "changed::" TERMINAL_PROFILE_VISIBLE_NAME_KEY,
- G_CALLBACK (profile_visible_name_notify_cb), action);
- g_signal_connect (action, "activate", callback, window);
-
- gtk_action_group_add_action (priv->new_terminal_action_group, action);
-}
-
-static void
-terminal_window_update_new_terminal_menus (TerminalWindow *window)
-{
- TerminalWindowPrivate *priv = window->priv;
- GtkActionGroup *action_group;
- GtkAction *action;
TerminalSettingsList *profiles_list;
- GList *profiles, *p;
- guint n;
- gboolean have_single_profile;
-
- /* Remove the old UI */
- if (priv->new_terminal_ui_id != 0)
- {
- gtk_ui_manager_remove_ui (priv->ui_manager, priv->new_terminal_ui_id);
- priv->new_terminal_ui_id = 0;
- }
-
- if (priv->new_terminal_action_group != NULL)
- {
- disconnect_profiles_from_actions_in_group (priv->new_terminal_action_group);
- gtk_ui_manager_remove_action_group (priv->ui_manager,
- priv->new_terminal_action_group);
- priv->new_terminal_action_group = NULL;
- }
-
- profiles_list = terminal_app_get_profiles_list (terminal_app_get ());
- profiles = terminal_profiles_list_ref_children_sorted (profiles_list);
-
- have_single_profile = !profiles || !profiles->next;
-
- action = gtk_action_group_get_action (priv->action_group, "FileNewTab");
- gtk_action_set_visible (action, have_single_profile);
- action = gtk_action_group_get_action (priv->action_group, "FileNewWindow");
- gtk_action_set_visible (action, have_single_profile);
- action = gtk_action_group_get_action (priv->action_group, "FileNewTerminal");
- gtk_action_set_visible (action, have_single_profile);
-
- if (have_single_profile)
- {
- g_list_free_full (profiles, (GDestroyNotify) g_object_unref);
- return;
- }
-
- /* Now build the submenus */
-
- action_group = priv->new_terminal_action_group = gtk_action_group_new ("NewTerminal");
- gtk_ui_manager_insert_action_group (priv->ui_manager, action_group, -1);
- g_object_unref (action_group);
-
- priv->new_terminal_ui_id = gtk_ui_manager_new_merge_id (priv->ui_manager);
-
- n = 0;
- for (p = profiles; p != NULL; p = p->next)
- {
- GSettings *profile = (GSettings *) p->data;
- char name[32];
-
- g_snprintf (name, sizeof (name), "FileNewTerminal.%u", n);
- terminal_window_create_new_terminal_action (window,
- profile,
- name,
- n,
- G_CALLBACK (file_new_terminal_callback));
-
- gtk_ui_manager_add_ui (priv->ui_manager, priv->new_terminal_ui_id,
- FILE_NEW_TERMINAL_UI_PATH,
- name, name,
- GTK_UI_MANAGER_MENUITEM, FALSE);
-
- ++n;
- }
-
- g_list_free_full (profiles, (GDestroyNotify) g_object_unref);
-}
-
-static void
-terminal_set_encoding_callback (GtkToggleAction *action,
- TerminalWindow *window)
-{
- TerminalWindowPrivate *priv = window->priv;
- TerminalEncoding *encoding;
-
- if (!gtk_toggle_action_get_active (action))
- return;
+ char *uuid;
if (priv->active_screen == NULL)
return;
- encoding = g_object_get_data (G_OBJECT (action), ENCODING_DATA_KEY);
- g_assert (encoding);
-
- vte_terminal_set_encoding (VTE_TERMINAL (priv->active_screen),
- terminal_encoding_get_charset (encoding),
- NULL);
-}
-
-static void
-terminal_window_update_encoding_menu (TerminalWindow *window)
-{
- TerminalWindowPrivate *priv = window->priv;
- TerminalApp *app;
- GtkActionGroup *action_group;
- GSList *group;
- guint n;
- GSList *encodings, *l;
- const char *charset;
- TerminalEncoding *active_encoding;
-
- /* Remove the old UI */
- if (priv->encodings_ui_id != 0)
- {
- gtk_ui_manager_remove_ui (priv->ui_manager, priv->encodings_ui_id);
- priv->encodings_ui_id = 0;
- }
-
- if (priv->encodings_action_group != NULL)
- {
- gtk_ui_manager_remove_action_group (priv->ui_manager,
- priv->encodings_action_group);
- priv->encodings_action_group = NULL;
- }
-
- action_group = priv->encodings_action_group = gtk_action_group_new ("Encodings");
- gtk_ui_manager_insert_action_group (priv->ui_manager, action_group, -1);
- g_object_unref (action_group);
-
- priv->encodings_ui_id = gtk_ui_manager_new_merge_id (priv->ui_manager);
-
- if (priv->active_screen)
- charset = vte_terminal_get_encoding (VTE_TERMINAL (priv->active_screen));
- else
- charset = "UTF-8";
-
- app = terminal_app_get ();
- active_encoding = terminal_app_ensure_encoding (app, charset);
-
- encodings = terminal_app_get_active_encodings (app);
-
- if (g_slist_find (encodings, active_encoding) == NULL)
- encodings = g_slist_append (encodings, terminal_encoding_ref (active_encoding));
-
- group = NULL;
- n = 0;
- for (l = encodings; l != NULL; l = l->next)
- {
- TerminalEncoding *e = (TerminalEncoding *) l->data;
- gs_unref_object GtkRadioAction *encoding_action;
- char name[128];
- gs_free char *display_name;
-
- g_snprintf (name, sizeof (name), SET_ENCODING_ACTION_NAME_PREFIX "%s", terminal_encoding_get_charset
(e));
- display_name = g_strdup_printf ("%s (%s)", e->name, terminal_encoding_get_charset (e));
-
- encoding_action = gtk_radio_action_new (name,
- display_name,
- NULL,
- NULL,
- n);
-
- gtk_radio_action_set_group (encoding_action, group);
- group = gtk_radio_action_get_group (encoding_action);
-
- if (charset && strcmp (terminal_encoding_get_charset (e), charset) == 0)
- gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (encoding_action), TRUE);
-
- g_signal_connect (encoding_action, "toggled",
- G_CALLBACK (terminal_set_encoding_callback), window);
-
- g_object_set_data_full (G_OBJECT (encoding_action), ENCODING_DATA_KEY,
- terminal_encoding_ref (e),
- (GDestroyNotify) terminal_encoding_unref);
-
- gtk_action_group_add_action (action_group, GTK_ACTION (encoding_action));
+ new_active_profile = terminal_screen_get_profile (priv->active_screen);
- gtk_ui_manager_add_ui (priv->ui_manager, priv->encodings_ui_id,
- SET_ENCODING_UI_PATH,
- name, name,
- GTK_UI_MANAGER_MENUITEM, FALSE);
- }
+ profiles_list = terminal_app_get_profiles_list (terminal_app_get ());
+ uuid = terminal_settings_list_dup_uuid_from_child (profiles_list, new_active_profile);
- g_slist_foreach (encodings, (GFunc) terminal_encoding_unref, NULL);
- g_slist_free (encodings);
+ g_simple_action_set_state (lookup_action (window, "profile"),
+ g_variant_new_take_string (uuid));
}
static void
terminal_window_update_encoding_menu_active_encoding (TerminalWindow *window)
{
TerminalWindowPrivate *priv = window->priv;
- GtkAction *action;
- char name[128];
-
- if (!priv->active_screen)
- return;
- if (!priv->encodings_action_group)
- return;
- g_snprintf (name, sizeof (name), SET_ENCODING_ACTION_NAME_PREFIX "%s",
- vte_terminal_get_encoding (VTE_TERMINAL (priv->active_screen)));
- action = gtk_action_group_get_action (priv->encodings_action_group, name);
- if (!action)
+ if (priv->active_screen == NULL)
return;
- g_signal_handlers_block_by_func (action, G_CALLBACK (terminal_set_encoding_callback), window);
- gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
- g_signal_handlers_unblock_by_func (action, G_CALLBACK (terminal_set_encoding_callback), window);
+ const char *charset = vte_terminal_get_encoding (VTE_TERMINAL (priv->active_screen));
+ g_simple_action_set_state (lookup_action (window, "encoding"),
+ g_variant_new_string (charset));
}
static void
terminal_window_update_terminal_menu (TerminalWindow *window)
{
TerminalWindowPrivate *priv = window->priv;
- GtkAction *action;
-
- if (!priv->active_screen)
- return;
-
- action = gtk_action_group_get_action(priv->action_group, "TerminalReadOnly");
- g_signal_handlers_block_by_func (action, G_CALLBACK (terminal_readonly_toggled_callback), window);
- gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
- !vte_terminal_get_input_enabled (VTE_TERMINAL (priv->active_screen)));
- g_signal_handlers_unblock_by_func (action, G_CALLBACK (terminal_readonly_toggled_callback), window);
-}
-
-static void
-terminal_size_to_cb (GtkAction *action,
- TerminalWindow *window)
-{
- TerminalWindowPrivate *priv = window->priv;
- const char *name;
- char *end = NULL;
- guint width, height;
if (priv->active_screen == NULL)
return;
- name = gtk_action_get_name (action) + strlen (SIZE_TO_ACTION_NAME_PREFIX);
- width = g_ascii_strtoull (name, &end, 10);
- g_assert (end && *end == 'x');
- height = g_ascii_strtoull (end + 1, &end, 10);
- g_assert (end && *end == '\0');
-
- vte_terminal_set_size (VTE_TERMINAL (priv->active_screen), width, height);
-
- terminal_window_update_size (window);
-}
-
-static void
-terminal_window_update_size_to_menu (TerminalWindow *window)
-{
- static const struct {
- guint grid_width;
- guint grid_height;
- } predefined_sizes[] = {
- { 80, 24 },
- { 80, 43 },
- { 132, 24 },
- { 132, 43 }
- };
- TerminalWindowPrivate *priv = window->priv;
- guint i;
-
- /* We only install this once, so there's no need for a separate action group
- * and any cleanup + build-new-one action here.
- */
-
- for (i = 0; i < G_N_ELEMENTS (predefined_sizes); ++i)
- {
- guint grid_width = predefined_sizes[i].grid_width;
- guint grid_height = predefined_sizes[i].grid_height;
- gs_unref_object GtkAction *action;
- char name[40];
- gs_free char *display_name;
-
- g_snprintf (name, sizeof (name), SIZE_TO_ACTION_NAME_PREFIX "%ux%u",
- grid_width, grid_height);
-
- /* If there are ever more than 9 of these, extend this to use A..Z as mnemonics,
- * like we do for the profiles menu.
- */
- display_name = g_strdup_printf ("_%u. %u×%u", i + 1, grid_width, grid_height);
-
- action = gtk_action_new (name, display_name, NULL, NULL);
- g_signal_connect (action, "activate",
- G_CALLBACK (terminal_size_to_cb), window);
-
- gtk_action_group_add_action (priv->action_group, action);
-
- gtk_ui_manager_add_ui (priv->ui_manager, priv->ui_id,
- SIZE_TO_UI_PATH,
- name, name,
- GTK_UI_MANAGER_MENUITEM, FALSE);
- }
+ gboolean read_only = !vte_terminal_get_input_enabled (VTE_TERMINAL (priv->active_screen));
+ g_simple_action_set_state (lookup_action (window, "read-only"),
+ g_variant_new_boolean (read_only));
}
/* Actions stuff */
@@ -1773,19 +1537,13 @@ terminal_window_update_copy_sensitivity (TerminalScreen *screen,
TerminalWindow *window)
{
TerminalWindowPrivate *priv = window->priv;
- GtkAction *action;
gboolean can_copy;
if (screen != priv->active_screen)
return;
can_copy = vte_terminal_get_has_selection (VTE_TERMINAL (screen));
-
- action = gtk_action_group_get_action (priv->action_group, "EditCopy");
- gtk_action_set_sensitive (action, can_copy);
-
- action = gtk_action_group_get_action (priv->action_group, "EditCopyHTML");
- gtk_action_set_sensitive (action, can_copy);
+ g_simple_action_set_enabled (lookup_action (window, "copy"), can_copy);
}
static void
@@ -1793,19 +1551,17 @@ terminal_window_update_zoom_sensitivity (TerminalWindow *window)
{
TerminalWindowPrivate *priv = window->priv;
TerminalScreen *screen;
- GtkAction *action;
- double current, zoom;
-
+
screen = priv->active_screen;
if (screen == NULL)
return;
- current = vte_terminal_get_font_scale (VTE_TERMINAL (screen));
+ double zoom = vte_terminal_get_font_scale (VTE_TERMINAL (screen));
- action = gtk_action_group_get_action (priv->action_group, "ViewZoomOut");
- gtk_action_set_sensitive (action, find_smaller_zoom_factor (current, &zoom));
- action = gtk_action_group_get_action (priv->action_group, "ViewZoomIn");
- gtk_action_set_sensitive (action, find_larger_zoom_factor (current, &zoom));
+ g_simple_action_set_enabled (lookup_action (window, "zoom-in"),
+ find_larger_zoom_factor (&zoom));
+ g_simple_action_set_enabled (lookup_action (window, "zoom-out"),
+ find_smaller_zoom_factor (&zoom));
}
static void
@@ -1813,67 +1569,36 @@ terminal_window_update_search_sensitivity (TerminalScreen *screen,
TerminalWindow *window)
{
TerminalWindowPrivate *priv = window->priv;
- GtkAction *action;
- gboolean can_search;
if (screen != priv->active_screen)
return;
- can_search = vte_terminal_search_get_regex (VTE_TERMINAL (screen)) != NULL;
+ gboolean can_search = vte_terminal_search_get_regex (VTE_TERMINAL (screen)) != NULL;
- action = gtk_action_group_get_action (priv->action_group, "SearchFindNext");
- gtk_action_set_sensitive (action, can_search);
- action = gtk_action_group_get_action (priv->action_group, "SearchFindPrevious");
- gtk_action_set_sensitive (action, can_search);
- action = gtk_action_group_get_action (priv->action_group, "SearchClearHighlight");
- gtk_action_set_sensitive (action, can_search);
+ g_simple_action_set_enabled (lookup_action (window, "find-forward"), can_search);
+ g_simple_action_set_enabled (lookup_action (window, "find-backward"), can_search);
+ g_simple_action_set_enabled (lookup_action (window, "find-clear"), can_search);
}
static void
-update_edit_menu_cb (GtkClipboard *clipboard,
- GdkAtom *targets,
- int n_targets,
- GWeakRef *ref)
+clipboard_targets_changed_cb (TerminalApp *app,
+ GtkClipboard *clipboard,
+ TerminalWindow *window)
{
- TerminalWindow *window;
- TerminalWindowPrivate *priv;
- GtkAction *action;
- gboolean can_paste, can_paste_uris;
-
- window = g_weak_ref_get (ref);
- if (window == NULL)
- goto out;
-
- /* Now we know the window is still alive */
- priv = window->priv;
-
- can_paste = targets != NULL && gtk_targets_include_text (targets, n_targets);
- can_paste_uris = targets != NULL && gtk_targets_include_uri (targets, n_targets);
+ TerminalWindowPrivate *priv = window->priv;
- action = gtk_action_group_get_action (priv->action_group, "EditPaste");
- gtk_action_set_sensitive (action, can_paste);
- action = gtk_action_group_get_action (priv->action_group, "EditPasteURIPaths");
- gtk_action_set_visible (action, can_paste_uris);
- gtk_action_set_sensitive (action, can_paste_uris);
+ if (clipboard != priv->clipboard)
+ return;
- g_object_unref (window);
- out:
- g_weak_ref_clear (ref);
- g_slice_free (GWeakRef, ref);
-}
+ GdkAtom *targets;
+ int n_targets;
+ targets = terminal_app_get_clipboard_targets (app, clipboard, &n_targets);
-static void
-update_edit_menu (GtkClipboard *clipboard,
- GdkEvent *event G_GNUC_UNUSED,
- TerminalWindow *window)
-{
- GWeakRef *ref;
+ gboolean can_paste = gtk_targets_include_text (targets, n_targets);
+ gboolean can_paste_uris = gtk_targets_include_uri (targets, n_targets);
- ref = g_slice_new0 (GWeakRef);
- g_weak_ref_init (ref, window);
- gtk_clipboard_request_targets (clipboard,
- (GtkClipboardTargetsReceivedFunc) update_edit_menu_cb,
- ref);
+ g_simple_action_set_enabled (lookup_action (window, "paste-text"), can_paste);
+ g_simple_action_set_enabled (lookup_action (window, "paste-uris"), can_paste_uris);
}
static void
@@ -1886,7 +1611,9 @@ screen_resize_window_cb (TerminalScreen *screen,
GtkWidget *widget = GTK_WIDGET (screen);
if (gtk_widget_get_realized (widget) &&
- (gdk_window_get_state (gtk_widget_get_window (widget)) & (GDK_WINDOW_STATE_MAXIMIZED |
GDK_WINDOW_STATE_FULLSCREEN)) != 0)
+ (gdk_window_get_state (gtk_widget_get_window (widget)) & (GDK_WINDOW_STATE_MAXIMIZED |
+ GDK_WINDOW_STATE_FULLSCREEN |
+ GDK_WINDOW_STATE_TILED)) != 0)
return;
vte_terminal_set_size (VTE_TERMINAL (priv->active_screen), columns, rows);
@@ -1896,55 +1623,54 @@ screen_resize_window_cb (TerminalScreen *screen,
}
static void
-terminal_window_update_tabs_menu_sensitivity (TerminalWindow *window)
+terminal_window_update_tabs_actions_sensitivity (TerminalWindow *window)
{
TerminalWindowPrivate *priv = window->priv;
- GAction *gaction;
- GtkActionGroup *action_group = priv->action_group;
- GtkAction *action;
- int num_pages, page_num;
- gboolean not_first, not_last;
if (priv->disposed)
return;
- num_pages = terminal_mdi_container_get_n_screens (priv->mdi_container);
- page_num = terminal_mdi_container_get_active_screen_num (priv->mdi_container);
- not_first = page_num > 0;
- not_last = page_num + 1 < num_pages;
+ int num_pages = terminal_mdi_container_get_n_screens (priv->mdi_container);
+ int page_num = terminal_mdi_container_get_active_screen_num (priv->mdi_container);
+
+ gboolean not_only = num_pages > 1;
+ gboolean not_first = page_num > 0;
+ gboolean not_last = page_num + 1 < num_pages;
+
+ gboolean not_first_lr, not_last_lr;
+ if (gtk_widget_get_direction (GTK_WIDGET (window)) == GTK_TEXT_DIR_RTL) {
+ not_first_lr = not_last;
+ not_last_lr = not_first;
+ } else {
+ not_first_lr = not_first;
+ not_last_lr = not_last;
+ }
/* Hide the tabs menu in single-tab windows */
- action = gtk_action_group_get_action (action_group, "Tabs");
- gtk_action_set_visible (action, num_pages > 1);
-
-#if 1
- /* NOTE: We always make next/prev actions sensitive except in
- * single-tab windows, so the corresponding shortcut key escape code
- * isn't sent to the terminal. See bug #453193 and bug #138609.
- * This also makes tab cycling work, bug #92139.
- * FIXME: Find a better way to do this.
- */
- action = gtk_action_group_get_action (action_group, "TabsPrevious");
- gtk_action_set_sensitive (action, num_pages > 1);
- action = gtk_action_group_get_action (action_group, "TabsNext");
- gtk_action_set_sensitive (action, num_pages > 1);
-#else
- /* This would be correct, but see the comment above. */
- action = gtk_action_group_get_action (action_group, "TabsPrevious");
- gtk_action_set_sensitive (action, not_first);
- action = gtk_action_group_get_action (action_group, "TabsNext");
- gtk_action_set_sensitive (action, not_last);
-#endif
+ g_simple_action_set_enabled (lookup_action (window, "tabs-menu"), not_only);
+
+ /* Disable shadowing of MDI actions in SDI windows */
+ g_simple_action_set_enabled (lookup_action (window, "shadow-mdi"), not_only);
- gaction = g_action_map_lookup_action (G_ACTION_MAP (window), "switch-tab");
- g_simple_action_set_enabled (G_SIMPLE_ACTION (gaction), num_pages > 1);
+ /* Disable tab switching (and all its shortcuts) in SDI windows */
+ g_simple_action_set_enabled (lookup_action (window, "active-tab"), not_only);
- action = gtk_action_group_get_action (action_group, "TabsMoveLeft");
- gtk_action_set_sensitive (action, not_first);
- action = gtk_action_group_get_action (action_group, "TabsMoveRight");
- gtk_action_set_sensitive (action, not_last);
- action = gtk_action_group_get_action (action_group, "TabsDetach");
- gtk_action_set_sensitive (action, num_pages > 1);
+ /* Set the active tab */
+ g_simple_action_set_state (lookup_action (window, "active-tab"),
+ g_variant_new_int32 (page_num));
+
+ /* Keynav wraps around? See bug #92139 */
+ gboolean keynav_wrap_around;
+ g_object_get (gtk_widget_get_settings (GTK_WIDGET (window)),
+ "gtk-keynav-wrap-around", &keynav_wrap_around,
+ NULL);
+
+ gboolean wrap = keynav_wrap_around && not_only;
+ g_simple_action_set_enabled (lookup_action (window, "tab-switch-left"), not_first || wrap);
+ g_simple_action_set_enabled (lookup_action (window, "tab-switch-right"), not_last || wrap);
+ g_simple_action_set_enabled (lookup_action (window, "tab-move-left"), not_first_lr || wrap);
+ g_simple_action_set_enabled (lookup_action (window, "tab-move-right"), not_last_lr || wrap);
+ g_simple_action_set_enabled (lookup_action (window, "tab-detach"), not_only);
}
static GtkNotebook *
@@ -1966,86 +1692,12 @@ handle_tab_droped_on_desktop (GtkNotebook *source_notebook,
new_priv = new_window->priv;
new_priv->present_on_insert = TRUE;
-// update_tab_visibility (source_window, -1);
-// update_tab_visibility (new_window, +1);
-
return GTK_NOTEBOOK (new_priv->mdi_container);
}
/* Terminal screen popup menu handling */
static void
-popup_open_hyperlink_callback (GtkAction *action,
- TerminalWindow *window)
-{
- TerminalWindowPrivate *priv = window->priv;
- TerminalScreenPopupInfo *info = priv->popup_info;
-
- if (info == NULL)
- return;
-
- terminal_util_open_url (GTK_WIDGET (window), info->hyperlink, FLAVOR_AS_IS,
- gtk_get_current_event_time ());
-}
-
-static void
-popup_copy_hyperlink_callback (GtkAction *action,
- TerminalWindow *window)
-{
- TerminalWindowPrivate *priv = window->priv;
- TerminalScreenPopupInfo *info = priv->popup_info;
- GtkClipboard *clipboard;
-
- if (info == NULL)
- return;
-
- if (info->hyperlink == NULL)
- return;
-
- clipboard = gtk_widget_get_clipboard (GTK_WIDGET (window), GDK_SELECTION_CLIPBOARD);
- gtk_clipboard_set_text (clipboard, info->hyperlink, -1);
-}
-
-static void
-popup_open_url_callback (GtkAction *action,
- TerminalWindow *window)
-{
- TerminalWindowPrivate *priv = window->priv;
- TerminalScreenPopupInfo *info = priv->popup_info;
-
- if (info == NULL)
- return;
-
- terminal_util_open_url (GTK_WIDGET (window), info->url, info->url_flavor,
- gtk_get_current_event_time ());
-}
-
-static void
-popup_copy_url_callback (GtkAction *action,
- TerminalWindow *window)
-{
- TerminalWindowPrivate *priv = window->priv;
- TerminalScreenPopupInfo *info = priv->popup_info;
- GtkClipboard *clipboard;
-
- if (info == NULL)
- return;
-
- if (info->url == NULL)
- return;
-
- clipboard = gtk_widget_get_clipboard (GTK_WIDGET (window), GDK_SELECTION_CLIPBOARD);
- gtk_clipboard_set_text (clipboard, info->url, -1);
-}
-
-static void
-popup_leave_fullscreen_callback (GtkAction *action,
- TerminalWindow *window)
-{
- gtk_window_unfullscreen (GTK_WINDOW (window));
-}
-
-static void
remove_popup_info (TerminalWindow *window)
{
TerminalWindowPrivate *priv = window->priv;
@@ -2090,118 +1742,154 @@ unset_popup_info (TerminalWindow *window)
}
static void
-popup_menu_deactivate_callback (GtkWidget *popup,
- TerminalWindow *window)
+screen_popup_menu_deactivate_cb (GtkWidget *popup,
+ TerminalWindow *window)
{
g_signal_handlers_disconnect_by_func
- (popup, G_CALLBACK (popup_menu_deactivate_callback), window);
+ (popup, G_CALLBACK (screen_popup_menu_deactivate_cb), window);
unset_popup_info (window);
}
static void
-popup_clipboard_targets_received_cb (GtkClipboard *clipboard,
- GdkAtom *targets,
- int n_targets,
- TerminalScreenPopupInfo *info)
+screen_show_popup_menu_cb (TerminalScreen *screen,
+ TerminalScreenPopupInfo *info,
+ TerminalWindow *window)
{
- TerminalWindow *window;
- TerminalWindowPrivate *priv;
- TerminalScreen *screen = info->screen;
- GtkWidget *popup_menu;
- GtkAction *action;
- gboolean has_selection;
- gboolean can_paste, can_paste_uris, show_hyperlink, show_link, show_email_link, show_call_link,
show_number_info;
+ TerminalWindowPrivate *priv = window->priv;
+ TerminalApp *app = terminal_app_get ();
- window = terminal_screen_popup_info_ref_window (info);
- if (window == NULL ||
- !gtk_widget_get_realized (GTK_WIDGET (screen)))
- {
- terminal_screen_popup_info_unref (info);
- return;
+ if (screen != priv->active_screen)
+ return;
+
+ remove_popup_info (window);
+ priv->popup_info = terminal_screen_popup_info_ref (info);
+
+ gs_unref_object GMenu *menu = g_menu_new ();
+
+ /* Hyperlink section */
+ if (info->hyperlink != NULL) {
+ gs_unref_object GMenu *section1 = g_menu_new ();
+
+ g_menu_append (section1, _("Open _Hyperlink"), "win.open-hyperlink");
+ g_menu_append (section1, _("Copy Hyperlink _Address"), "win.copy-hyperlink");
+ g_menu_append_section (menu, NULL, G_MENU_MODEL (section1));
+ }
+ /* Matched link section */
+ else if (info->url != NULL) {
+ gs_unref_object GMenu *section2 = g_menu_new ();
+
+ const char *open_label = NULL, *copy_label = NULL;
+ switch (info->url_flavor) {
+ case FLAVOR_EMAIL:
+ open_label = _("Call _To…");
+ copy_label = _("Copy Call _Address ");
+ break;
+ case FLAVOR_VOIP_CALL:
+ open_label = _("Send Mail _To…");
+ copy_label = _("Copy Mail _Address");
+ break;
+ case FLAVOR_AS_IS:
+ case FLAVOR_DEFAULT_TO_HTTP:
+ default:
+ open_label = _("_Open Link");
+ copy_label = _("Copy _Link");
+ break;
}
- /* Now we know that the window is still alive */
- priv = window->priv;
+ g_menu_append (section2, open_label, "win.open-match");
+ g_menu_append (section2, copy_label, "win.copy-match");
+ g_menu_append_section (menu, NULL, G_MENU_MODEL (section2));
+ }
- remove_popup_info (window);
- priv->popup_info = info; /* adopt the ref added when requesting the clipboard */
-
- has_selection = vte_terminal_get_has_selection (VTE_TERMINAL (screen));
- can_paste = targets != NULL && gtk_targets_include_text (targets, n_targets);
- can_paste_uris = targets != NULL && gtk_targets_include_uri (targets, n_targets);
- show_hyperlink = info->hyperlink != NULL;
- show_link = !show_hyperlink && info->url != NULL && (info->url_flavor == FLAVOR_AS_IS || info->url_flavor
== FLAVOR_DEFAULT_TO_HTTP);
- show_email_link = !show_hyperlink && info->url != NULL && info->url_flavor == FLAVOR_EMAIL;
- show_call_link = !show_hyperlink && info->url != NULL && info->url_flavor == FLAVOR_VOIP_CALL;
- show_number_info = info->number_info != NULL;
-
- action = gtk_action_group_get_action (priv->action_group, "PopupOpenHyperlink");
- gtk_action_set_visible (action, show_hyperlink);
- action = gtk_action_group_get_action (priv->action_group, "PopupCopyHyperlinkAddress");
- gtk_action_set_visible (action, show_hyperlink);
-
- action = gtk_action_group_get_action (priv->action_group, "PopupSendEmail");
- gtk_action_set_visible (action, show_email_link);
- action = gtk_action_group_get_action (priv->action_group, "PopupCopyEmailAddress");
- gtk_action_set_visible (action, show_email_link);
- action = gtk_action_group_get_action (priv->action_group, "PopupCall");
- gtk_action_set_visible (action, show_call_link);
- action = gtk_action_group_get_action (priv->action_group, "PopupCopyCallAddress");
- gtk_action_set_visible (action, show_call_link);
- action = gtk_action_group_get_action (priv->action_group, "PopupOpenLink");
- gtk_action_set_visible (action, show_link);
- action = gtk_action_group_get_action (priv->action_group, "PopupCopyLinkAddress");
- gtk_action_set_visible (action, show_link);
-
- action = gtk_action_group_get_action (priv->action_group, "PopupNumberInfo");
- gtk_action_set_label (action, info->number_info);
- gtk_action_set_sensitive (action, FALSE);
- gtk_action_set_visible (action, show_number_info);
-
- action = gtk_action_group_get_action (priv->action_group, "PopupCopy");
- gtk_action_set_sensitive (action, has_selection);
- action = gtk_action_group_get_action (priv->action_group, "PopupCopyHTML");
- gtk_action_set_sensitive (action, has_selection);
- action = gtk_action_group_get_action (priv->action_group, "PopupPaste");
- gtk_action_set_sensitive (action, can_paste);
- action = gtk_action_group_get_action (priv->action_group, "PopupPasteURIPaths");
- gtk_action_set_visible (action, can_paste_uris);
-
- popup_menu = gtk_ui_manager_get_widget (priv->ui_manager, "/Popup");
- g_signal_connect (popup_menu, "deactivate",
- G_CALLBACK (popup_menu_deactivate_callback), window);
+ /* Info section */
+ if (info->number_info != NULL) {
+ gs_unref_object GMenu *section3 = g_menu_new ();
+ /* Non-existent action will make this item insensitive */
+ gs_unref_object GMenuItem *item3 = g_menu_item_new (info->number_info, "win.notexist");
+ g_menu_append_item (section3, item3);
+ g_menu_append_section (menu, NULL, G_MENU_MODEL (section3));
+ }
- /* Pseudo activation of the popup menu's action */
- action = gtk_action_group_get_action (priv->action_group, "Popup");
- gtk_action_activate (action);
+ /* Clipboard section */
+ gs_unref_object GMenu *section4 = g_menu_new ();
+
+ g_menu_append (section4, _("_Copy"), "win.copy::text");
+ g_menu_append (section4, _("Copy as _HTML"), "win.copy::html");
+ g_menu_append (section4, _("_Paste"), "win.paste-text");
+ if (g_action_get_enabled (G_ACTION (lookup_action (window, "paste-uris"))))
+ g_menu_append (section4, _("Paste as _Filenames"), "win.paste-uris");
+
+ g_menu_append_section (menu, NULL, G_MENU_MODEL (section4));
+
+ /* Profile and property section */
+ gs_unref_object GMenu *section5 = g_menu_new ();
+ g_menu_append (section5, _("Read-_Only"), "win.read-only");
+
+ GMenuModel *profiles_menu = terminal_app_get_profile_section (app);
+ if (profiles_menu != NULL && g_menu_model_get_n_items (profiles_menu) > 1) {
+ gs_unref_object GMenu *submenu5 = g_menu_new ();
+ g_menu_append_section (submenu5, NULL, profiles_menu);
+
+ gs_unref_object GMenu *section51 = g_menu_new ();
+ g_menu_append (section51, _("_Profile Preferences…"), "win.edit-profile");
+ g_menu_append_section (submenu5, NULL, G_MENU_MODEL (section51));
+
+ gs_unref_object GMenuItem *item5 = g_menu_item_new (_("P_rofiles"), NULL);
+ g_menu_item_set_submenu (item5, G_MENU_MODEL (submenu5));
+ g_menu_append_item (section5, item5);
+ } else {
+ /* If there's only a single profile, put the Profile Preferences item in the
+ * context menu itself.
+ */
+ g_menu_append (section5, _("_Profile Preferences…"), "win.edit-profile");
+ }
- if (info->button == 0)
- gtk_menu_shell_select_first (GTK_MENU_SHELL (popup_menu), FALSE);
+ g_menu_append_section (menu, NULL, G_MENU_MODEL (section5));
+
+ /* New Terminal section */
+ gs_unref_object GMenu *section6 = g_menu_new ();
+#ifndef DISUNIFY_NEW_TERMINAL_SECTION
+ gs_unref_object GMenuItem *item6 = g_menu_item_new (_("New _Terminal"), NULL);
+ g_menu_item_set_action_and_target (item6, "win.new-terminal",
+ "(ss)", "default", "current");
+ g_menu_append_item (section6, item6);
+#else
+ gs_unref_object GMenuItem *item61 = g_menu_item_new (_("New _Window"), NULL);
+ g_menu_item_set_action_and_target (item61, "win.new-terminal",
+ "(ss)", "window", "current");
+ g_menu_append_item (section6, item61);
+ gs_unref_object GMenuItem *item62 = g_menu_item_new (_("New _Tab"), NULL);
+ g_menu_item_set_action_and_target (item62, "win.new-terminal",
+ "(ss)", "tab", "current");
+ g_menu_append_item (section6, item62);
+#endif
+ g_menu_append_section (menu, NULL, G_MENU_MODEL (section6));
+
+ /* Window section */
+ gs_unref_object GMenu *section7 = g_menu_new ();
- if (gtk_menu_get_attach_widget (GTK_MENU (popup_menu)))
- gtk_menu_detach (GTK_MENU (popup_menu));
- gtk_menu_attach_to_widget (GTK_MENU (popup_menu), GTK_WIDGET (screen), NULL);
- gtk_menu_popup (GTK_MENU (popup_menu),
+ /* Only show this if the WM doesn't show the menubar */
+ if (g_action_get_enabled (G_ACTION (lookup_action (window, "menubar-visible"))))
+ g_menu_append (section7, _("Show _Menubar"), "win.menubar-visible");
+ if (g_action_get_enabled (G_ACTION (lookup_action (window, "leave-fullscreen"))))
+ g_menu_append (section7, _("L_eave Full Screen"), "win.leave-fullscreen");
+
+ g_menu_append_section (menu, NULL, G_MENU_MODEL (section7));
+
+ /* Now create the popup menu and show it */
+ GtkWidget *popup_menu = context_menu_new (G_MENU_MODEL (menu), GTK_WIDGET (window));
+
+ g_signal_connect (popup_menu, "deactivate",
+ G_CALLBACK (screen_popup_menu_deactivate_cb), window);
+
+ gtk_menu_popup (GTK_MENU (popup_menu), NULL, NULL,
NULL, NULL,
- NULL, NULL,
info->button,
info->timestamp);
- g_object_unref (window);
-}
-
-static void
-screen_show_popup_menu_callback (TerminalScreen *screen,
- TerminalScreenPopupInfo *info,
- TerminalWindow *window)
-{
- GtkClipboard *clipboard;
-
- clipboard = gtk_widget_get_clipboard (GTK_WIDGET (window), GDK_SELECTION_CLIPBOARD);
- gtk_clipboard_request_targets (clipboard,
- (GtkClipboardTargetsReceivedFunc) popup_clipboard_targets_received_cb,
- terminal_screen_popup_info_ref (info));
+ if (info->button == 0)
+ gtk_menu_shell_select_first (GTK_MENU_SHELL (popup_menu), FALSE);
}
static gboolean
@@ -2230,83 +1918,59 @@ screen_close_cb (TerminalScreen *screen,
terminal_window_remove_screen (window, screen);
}
-static gboolean
-terminal_window_accel_activate_cb (GtkAccelGroup *accel_group,
- GObject *acceleratable,
- guint keyval,
- GdkModifierType modifier,
- TerminalWindow *window)
+static void
+notebook_update_tabs_menu_cb (GtkMenuButton *button,
+ TerminalWindow *window)
{
- GtkAccelGroupEntry *entries;
- guint n_entries;
- gboolean retval = FALSE;
+ gs_unref_object GMenu *menu;
+ gs_free_list GList *tabs;
+ GList *t;
+ int i;
- entries = gtk_accel_group_query (accel_group, keyval, modifier, &n_entries);
- if (n_entries > 0)
- {
- const char *accel_path;
+ menu = g_menu_new ();
+ tabs = terminal_window_list_screen_containers (window);
- accel_path = g_quark_to_string (entries[0].accel_path_quark);
+ for (t = tabs, i = 0; t != NULL; t = t->next, i++) {
+ TerminalScreenContainer *container = t->data;
+ TerminalScreen *screen = terminal_screen_container_get_screen (container);
+ gs_unref_object GMenuItem *item;
+ const char *title;
- if (g_str_has_prefix (accel_path, "<Actions>/Main/"))
- {
- const char *action_name;
+ title = terminal_screen_get_title (screen);
- /* We want to always consume these accelerators, even if the corresponding
- * action is insensitive, so the corresponding shortcut key escape code
- * isn't sent to the terminal. See bug #453193, bug #138609 and bug #559728.
- * This also makes tab cycling work, bug #92139. (NOT!)
- */
+ item = g_menu_item_new (title && title[0] ? title : _("Terminal"), NULL);
+ g_menu_item_set_action_and_target (item, "win.active-tab", "i", i);
+ g_menu_append_item (menu, item);
+ }
- action_name = I_(accel_path + strlen ("<Actions>/Main/"));
+ gtk_menu_button_set_menu_model (button, G_MENU_MODEL (menu));
-#if 0
- if (gtk_notebook_get_n_pages (GTK_NOTEBOOK (priv->notebook)) > 1 &&
- (action_name == I_("TabsPrevious") || action_name == I_("TabsNext")))
- retval = TRUE;
- else
-#endif
- if (action_name == I_("EditCopy") ||
- action_name == I_("PopupCopy") ||
- action_name == I_("EditPaste") ||
- action_name == I_("PopupPaste"))
- retval = TRUE;
- }
- }
-
- return retval;
+ /* Need this so the menu is positioned correctly */
+ gtk_widget_set_halign (GTK_WIDGET (gtk_menu_button_get_popup (button)), GTK_ALIGN_END);
}
static void
terminal_window_fill_notebook_action_box (TerminalWindow *window)
{
TerminalWindowPrivate *priv = window->priv;
- GtkWidget *box, *button;
- GtkAction *action;
- GtkWidget *menu;
+ GtkWidget *box, *new_tab_button, *tabs_menu_button;
box = terminal_notebook_get_action_box (TERMINAL_NOTEBOOK (priv->mdi_container), GTK_PACK_END);
/* Create the NewTerminal button */
- action = gtk_action_group_get_action (priv->action_group, "FileNewTab");
-
- button = terminal_icon_button_new ("tab-new-symbolic");
- gtk_activatable_set_related_action (GTK_ACTIVATABLE (button), action);
- gtk_box_pack_start (GTK_BOX (box), button, FALSE, FALSE, 0);
- gtk_widget_show (button);
+ new_tab_button = terminal_icon_button_new ("tab-new-symbolic");
+ gtk_actionable_set_action_name (GTK_ACTIONABLE (new_tab_button), "win.new-terminal");
+ gtk_actionable_set_action_target (GTK_ACTIONABLE (new_tab_button), "(ss)", "tab", "current");
+ gtk_box_pack_start (GTK_BOX (box), new_tab_button, FALSE, FALSE, 0);
+ gtk_widget_show (new_tab_button);
/* Create Tabs menu button */
- menu = gtk_ui_manager_get_widget (priv->ui_manager, "/TabsPopup");
- gtk_widget_set_halign (menu, GTK_ALIGN_END);
-
- button = gtk_menu_button_new ();
- gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE);
- gtk_button_set_focus_on_click (GTK_BUTTON (button), FALSE);
- gtk_menu_button_set_popup (GTK_MENU_BUTTON (button), menu);
-
- gtk_box_pack_start (GTK_BOX (box), button, FALSE, FALSE, 0);
- gtk_menu_button_set_align_widget (GTK_MENU_BUTTON (button), box);
- gtk_widget_show (button);
+ tabs_menu_button = terminal_menu_button_new ();
+ g_signal_connect (tabs_menu_button, "update-menu",
+ G_CALLBACK (notebook_update_tabs_menu_cb), window);
+ gtk_box_pack_start (GTK_BOX (box), tabs_menu_button, FALSE, FALSE, 0);
+ gtk_menu_button_set_align_widget (GTK_MENU_BUTTON (tabs_menu_button), box);
+ gtk_widget_show (tabs_menu_button);
}
/*****************************************/
@@ -2366,24 +2030,21 @@ terminal_window_state_event (GtkWidget *widget,
GdkEventWindowState *event)
{
gboolean (* window_state_event) (GtkWidget *, GdkEventWindowState *event) =
- GTK_WIDGET_CLASS (terminal_window_parent_class)->window_state_event;
+ GTK_WIDGET_CLASS (terminal_window_parent_class)->window_state_event;
if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN)
{
TerminalWindow *window = TERMINAL_WINDOW (widget);
- TerminalWindowPrivate *priv = window->priv;
- GtkAction *action;
gboolean is_fullscreen;
is_fullscreen = (event->new_window_state & GDK_WINDOW_STATE_FULLSCREEN) != 0;
- action = gtk_action_group_get_action (priv->action_group, "ViewFullscreen");
- gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), is_fullscreen);
-
- action = gtk_action_group_get_action (priv->action_group, "PopupLeaveFullscreen");
- gtk_action_set_visible (action, is_fullscreen);
+ g_simple_action_set_state (lookup_action (window, "fullscreen"),
+ g_variant_new_boolean (is_fullscreen));
+ g_simple_action_set_enabled (lookup_action (window, "leave-fullscreen"),
+ is_fullscreen);
}
-
+
if (window_state_event)
return window_state_event (widget, event);
@@ -2421,9 +2082,11 @@ terminal_window_screen_update (TerminalWindow *window,
G_SETTINGS_BIND_GET);
g_object_get (gtk_settings, "gtk-menu-bar-accel", &value, NULL);
+#if !GTK_CHECK_VERSION (3, 20, 0)
g_object_set_data_full (G_OBJECT (gtk_settings), "GT::gtk-menu-bar-accel",
value, (GDestroyNotify) g_free);
- enable_menubar_accel_changed_cb (settings,
+#endif
+ enable_menubar_accel_changed_cb (settings,
TERMINAL_SETTING_ENABLE_MENU_BAR_ACCEL_KEY,
gtk_settings);
g_signal_connect (settings, "changed::" TERMINAL_SETTING_ENABLE_MENU_BAR_ACCEL_KEY,
@@ -2454,261 +2117,73 @@ terminal_window_screen_changed (GtkWidget *widget,
}
static void
-terminal_window_profile_list_changed_cb (TerminalSettingsList *profiles_list,
- TerminalWindow *window)
-{
- terminal_window_update_set_profile_menu (window);
- terminal_window_update_new_terminal_menus (window);
-}
-
-static void
-terminal_window_encoding_list_changed_cb (TerminalApp *app,
- TerminalWindow *window)
-{
- terminal_window_update_encoding_menu (window);
-}
-
-static void
terminal_window_init (TerminalWindow *window)
{
- const GActionEntry gaction_entries[] = {
- { "new-terminal", action_new_terminal_cb, "(ss)", 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, "s", 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 },
- { "zoom", action_zoom_cb, "i", NULL, NULL },
- { "detach-tab", action_detach_tab_cb, NULL, NULL, NULL },
- { "find", action_find_cb, "s", 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 */
- { "File", NULL, N_("_File") },
- { "FileNewTerminalProfiles", STOCK_NEW_WINDOW, N_("Open _Terminal")},
- { "Edit", NULL, N_("_Edit") },
- { "View", NULL, N_("_View") },
- { "Search", NULL, N_("_Search") },
- { "Terminal", NULL, N_("_Terminal") },
- { "Tabs", NULL, N_("Ta_bs") },
- { "Help", NULL, N_("_Help") },
- { "Popup", NULL, NULL },
- { "NotebookPopup", NULL, "" },
- { "TabsPopup", NULL, "" },
-
- /* File menu */
- { "FileNewWindow", STOCK_NEW_WINDOW, N_("Open _Terminal"), "<shift><control>N",
- NULL,
- G_CALLBACK (file_new_terminal_callback) },
- { "FileNewTab", STOCK_NEW_TAB, N_("Open Ta_b"), "<shift><control>T",
- NULL,
- G_CALLBACK (file_new_terminal_callback) },
- { "FileNewTerminal", STOCK_NEW_TAB, N_("Open _Terminal"), NULL,
- NULL,
- G_CALLBACK (file_new_terminal_callback) },
- { "FileNewProfile", "document-open", N_("New _Profile"), "",
- NULL,
- G_CALLBACK (file_new_profile_callback) },
- { "FileSaveContents", "document-save", N_("_Save Contents"), "",
- NULL,
- G_CALLBACK (file_save_contents_callback) },
- { "FileCloseTab", "window-close", N_("C_lose Terminal"), "<shift><control>W",
- NULL,
- G_CALLBACK (file_close_tab_callback) },
- { "FileCloseWindow", "window-close", N_("_Close All Terminals"), "<shift><control>Q",
- NULL,
- G_CALLBACK (file_close_window_callback) },
-
- /* Edit menu */
- { "EditCopy", "edit-copy", N_("_Copy"), "<shift><control>C",
- NULL,
- G_CALLBACK (edit_copy_callback) },
- { "EditCopyHTML", "edit-copy", N_("Copy as _HTML"), NULL,
- NULL,
- G_CALLBACK (edit_copy_html_callback) },
- { "EditPaste", "edit-paste", N_("_Paste"), "<shift><control>V",
- NULL,
- G_CALLBACK (edit_paste_callback) },
- { "EditPasteURIPaths", "edit-paste", N_("Paste _Filenames"), "",
- NULL,
- G_CALLBACK (edit_paste_callback) },
- { "EditSelectAll", "edit-select-all", N_("Select All"), NULL,
- NULL,
- G_CALLBACK (edit_select_all_callback) },
- { "EditPreferences", NULL, N_("Pre_ferences"), NULL,
- NULL,
- G_CALLBACK (edit_preferences_callback) },
- { "EditCurrentProfile", "preferences-system", N_("_Profile Preferences"), NULL,
- NULL,
- G_CALLBACK (edit_current_profile_callback) },
-
- /* View menu */
- { "ViewZoomIn", "zoom-in", N_("Zoom In"), "<control>plus",
- NULL,
- G_CALLBACK (view_zoom_in_callback) },
- { "ViewZoomOut", "zoom-out", N_("Zoom Out"), "<control>minus",
- NULL,
- G_CALLBACK (view_zoom_out_callback) },
- { "ViewZoom100", "zoom-original", N_("Normal Size"), "<control>0",
- NULL,
- G_CALLBACK (view_zoom_normal_callback) },
-
- /* Search menu */
- { "SearchFind", "edit-find", N_("_Find…"), "<shift><control>F",
- NULL,
- G_CALLBACK (search_find_callback) },
- { "SearchFindNext", NULL, N_("Find Ne_xt"), "<shift><control>G",
- NULL,
- G_CALLBACK (search_find_next_callback) },
- { "SearchFindPrevious", NULL, N_("Find Pre_vious"), "<shift><control>H",
- NULL,
- G_CALLBACK (search_find_prev_callback) },
- { "SearchClearHighlight", NULL, N_("_Clear Highlight"), "<shift><control>J",
- NULL,
- G_CALLBACK (search_clear_highlight_callback) },
-#if 0
- { "SearchGoToLine", "go-jump", N_("Go to _Line…"), "<shift><control>I",
- NULL,
- G_CALLBACK (search_goto_line_callback) },
- { "SearchIncrementalSearch", "edit-find", N_("_Incremental Search…"), "<shift><control>K",
- NULL,
- G_CALLBACK (search_incremental_search_callback) },
+ const GActionEntry action_entries[] = {
+ /* Actions without state */
+ { "about", action_about_cb, NULL, NULL, NULL },
+ { "close", action_close_cb, "s", NULL, NULL },
+ { "copy", action_copy_cb, "s", NULL, NULL },
+ { "copy-hyperlink", action_copy_hyperlink_cb, NULL, NULL, NULL },
+ { "copy-match", action_copy_match_cb, NULL, NULL, NULL },
+ { "edit-profile", action_edit_profile_cb, NULL, NULL, NULL },
+ { "edit-preferences", action_edit_preferences_cb, NULL, NULL, NULL },
+ { "find", action_find_cb, NULL, NULL, NULL },
+ { "find-backward", action_find_backward_cb, NULL, NULL, NULL },
+ { "find-clear", action_find_clear_cb, NULL, NULL, NULL },
+ { "find-forward", action_find_forward_cb, NULL, NULL, NULL },
+ { "help", action_help_cb, NULL, NULL, NULL },
+ { "inspector", action_inspector_cb, NULL, NULL, NULL },
+ { "leave-fullscreen", action_leave_fullscreen_cb, NULL, NULL, NULL },
+ { "new-profile", action_new_profile_cb, NULL, NULL, NULL },
+ { "new-terminal", action_new_terminal_cb, "(ss)", NULL, NULL },
+ { "open-match", action_open_match_cb, NULL, NULL, NULL },
+ { "open-hyperlink", action_open_hyperlink_cb, NULL, NULL, NULL },
+ { "paste-text", action_paste_text_cb, NULL, NULL, NULL },
+ { "paste-uris", action_paste_uris_cb, NULL, NULL, NULL },
+ { "reset", action_reset_cb, "b", NULL, NULL },
+ { "select-all", action_select_all_cb, NULL, NULL, NULL },
+ { "size-to", action_size_to_cb, "(uu)", NULL, NULL },
+ { "tab-detach", action_tab_detach_cb, NULL, NULL, NULL },
+ { "tab-move-left", action_tab_move_left_cb, NULL, NULL, NULL },
+ { "tab-move-right", action_tab_move_right_cb, NULL, NULL, NULL },
+ { "tab-switch-left", action_tab_switch_left_cb, NULL, NULL, NULL },
+ { "tab-switch-right", action_tab_switch_right_cb, NULL, NULL, NULL },
+ { "tabs-menu", NULL, NULL, NULL, NULL },
+ { "zoom-in", action_zoom_in_cb, NULL, NULL, NULL },
+ { "zoom-normal", action_zoom_normal_cb, NULL, NULL, NULL },
+ { "zoom-out", action_zoom_out_cb, NULL, NULL, NULL },
+#ifdef ENABLE_EXPORT
+ { "export", action_export_cb, NULL, NULL, NULL },
+#endif
+#ifdef ENABLE_PRINT
+ { "print", action_print_cb, NULL, NULL, NULL },
+#endif
+#ifdef ENABLE_SAVE
+ { "save-contents", action_save_contents_cb, NULL, NULL, NULL },
#endif
- /* Terminal menu */
- { "TerminalProfiles", NULL, N_("Change _Profile") },
- { "TerminalSetEncoding", NULL, N_("Set _Character Encoding") },
- { "TerminalReset", NULL, N_("_Reset"), NULL,
- NULL,
- G_CALLBACK (terminal_reset_callback) },
- { "TerminalResetClear", NULL, N_("Reset and C_lear"), NULL,
- NULL,
- G_CALLBACK (terminal_reset_clear_callback) },
-
- /* Terminal/Encodings menu */
- { "TerminalAddEncoding", NULL, N_("_Add or Remove…"), NULL,
- NULL,
- G_CALLBACK (terminal_add_encoding_callback) },
-
- /* Tabs menu */
- { "TabsPrevious", NULL, N_("_Previous Terminal"), "<control>Page_Up",
- NULL,
- G_CALLBACK (tabs_next_or_previous_tab_cb) },
- { "TabsNext", NULL, N_("_Next Terminal"), "<control>Page_Down",
- NULL,
- G_CALLBACK (tabs_next_or_previous_tab_cb) },
- { "TabsMoveLeft", NULL, N_("Move Terminal _Left"), "<shift><control>Page_Up",
- NULL,
- G_CALLBACK (tabs_move_left_callback) },
- { "TabsMoveRight", NULL, N_("Move Terminal _Right"), "<shift><control>Page_Down",
- NULL,
- G_CALLBACK (tabs_move_right_callback) },
- { "TabsDetach", NULL, N_("_Detach Terminal"), NULL,
- NULL,
- G_CALLBACK (tabs_detach_tab_callback) },
-
- /* Help menu */
- { "HelpContents", "help-browser", N_("_Contents"), "F1",
- NULL,
- G_CALLBACK (help_contents_callback) },
- { "HelpAbout", "help-about", N_("_About"), NULL,
- NULL,
- G_CALLBACK (help_about_callback) },
- { "HelpInspector", NULL, N_("_Inspector"), NULL,
- NULL,
- G_CALLBACK (help_inspector_callback) },
-
- /* Popup menu */
- { "PopupOpenHyperlink", NULL, N_("_Open Hyperlink"), NULL,
- NULL,
- G_CALLBACK (popup_open_hyperlink_callback) },
- { "PopupCopyHyperlinkAddress", NULL, N_("_Copy Hyperlink Address"), NULL,
- NULL,
- G_CALLBACK (popup_copy_hyperlink_callback) },
- { "PopupSendEmail", NULL, N_("_Send Mail To…"), NULL,
- NULL,
- G_CALLBACK (popup_open_url_callback) },
- { "PopupCopyEmailAddress", NULL, N_("_Copy E-mail Address"), NULL,
- NULL,
- G_CALLBACK (popup_copy_url_callback) },
- { "PopupCall", NULL, N_("C_all To…"), NULL,
- NULL,
- G_CALLBACK (popup_open_url_callback) },
- { "PopupCopyCallAddress", NULL, N_("_Copy Call Address"), NULL,
- NULL,
- G_CALLBACK (popup_copy_url_callback) },
- { "PopupOpenLink", NULL, N_("_Open Link"), NULL,
- NULL,
- G_CALLBACK (popup_open_url_callback) },
- { "PopupCopyLinkAddress", NULL, N_("_Copy Link Address"), NULL,
- NULL,
- G_CALLBACK (popup_copy_url_callback) },
- { "PopupNumberInfo", NULL, "", NULL,
- NULL,
- NULL },
- { "PopupTerminalProfiles", NULL, N_("P_rofiles") },
- { "PopupCopy", "edit-copy", N_("_Copy"), "",
- NULL,
- G_CALLBACK (edit_copy_callback) },
- { "PopupCopyHTML", "edit-copy", N_("Copy as _HTML"), "",
- NULL,
- G_CALLBACK (edit_copy_html_callback) },
- { "PopupPaste", "edit-paste", N_("_Paste"), "",
- NULL,
- G_CALLBACK (edit_paste_callback) },
- { "PopupPasteURIPaths", "edit-paste", N_("Paste _Filenames"), "",
- NULL,
- G_CALLBACK (edit_paste_callback) },
- { "PopupNewTerminal", NULL, N_("Open _Terminal"), NULL,
- NULL,
- G_CALLBACK (file_new_terminal_callback) },
- { "PopupLeaveFullscreen", NULL, N_("L_eave Full Screen"), NULL,
- NULL,
- G_CALLBACK (popup_leave_fullscreen_callback) },
- };
-
- const GtkToggleActionEntry toggle_menu_entries[] =
- {
- /* View Menu */
- { "ViewMenubar", NULL, N_("Show _Menubar"), NULL,
- NULL,
- G_CALLBACK (view_menubar_toggled_callback),
- FALSE },
- { "ViewFullscreen", NULL, N_("_Full Screen"), NULL,
- NULL,
- G_CALLBACK (view_fullscreen_toggled_callback),
- FALSE },
- /* Terminal menu */
- { "TerminalReadOnly", NULL, N_("Read-_Only"), NULL,
- NULL,
- G_CALLBACK (terminal_readonly_toggled_callback),
- FALSE }
- };
+ /* Shadow actions for keybinding comsumption, see comment in terminal-accels.c */
+ { "shadow", action_shadow_activate_cb, "s", NULL, NULL },
+ { "shadow-mdi", action_shadow_activate_cb, "s", NULL, NULL },
+
+ /* Actions with state */
+ { "active-tab", action_active_tab_set_cb, "i", "@i 0", action_active_tab_state_cb },
+ { "encoding", NULL /* changes state */, "s", "'UTF-8'", action_encoding_state_cb },
+ { "fullscreen", NULL /* toggles state */, NULL, "false", action_fullscreen_state_cb },
+ { "menubar-visible", NULL /* toggles state */, NULL, "true", action_menubar_visible_state_cb },
+ { "profile", NULL /* changes state */, "s", "''", action_profile_state_cb },
+ { "read-only", NULL /* toggles state */, NULL, "false", action_read_only_state_cb },
+ };
TerminalWindowPrivate *priv;
TerminalApp *app;
- TerminalSettingsList *profiles_list;
GSettings *gtk_debug_settings;
- GtkActionGroup *action_group;
- GtkAction *action;
- GtkUIManager *manager;
- GError *error;
GtkWindowGroup *window_group;
- GtkAccelGroup *accel_group;
+ // GtkAccelGroup *accel_group;
uuid_t u;
char uuidstr[37], role[64];
+ gboolean shell_shows_menubar;
+ GSimpleAction *action;
app = terminal_app_get ();
@@ -2748,9 +2223,8 @@ terminal_window_init (TerminalWindow *window)
G_CALLBACK (mdi_screen_added_cb), window);
g_signal_connect_after (priv->mdi_container, "screen-removed",
G_CALLBACK (mdi_screen_removed_cb), window);
- g_signal_connect_data (priv->mdi_container, "screens-reordered",
- G_CALLBACK (terminal_window_update_tabs_menu_sensitivity),
- window, NULL, G_CONNECT_SWAPPED | G_CONNECT_AFTER);
+ g_signal_connect_after (priv->mdi_container, "screens-reordered",
+ G_CALLBACK (mdi_screens_reordered_cb), window);
g_signal_connect_swapped (priv->mdi_container, "notify::tab-pos",
G_CALLBACK (terminal_window_update_geometry), window);
@@ -2759,16 +2233,13 @@ terminal_window_init (TerminalWindow *window)
/* FIXME hack hack! */
if (GTK_IS_NOTEBOOK (priv->mdi_container)) {
- g_signal_connect (priv->mdi_container, "button-press-event",
- G_CALLBACK (notebook_button_press_cb), window);
- g_signal_connect (priv->mdi_container, "popup-menu",
- G_CALLBACK (notebook_popup_menu_cb), window);
- }
-
- /* FIXME hack */
- if (GTK_IS_NOTEBOOK (priv->mdi_container))
+ g_signal_connect (priv->mdi_container, "button-press-event",
+ G_CALLBACK (notebook_button_press_cb), window);
+ g_signal_connect (priv->mdi_container, "popup-menu",
+ G_CALLBACK (notebook_popup_menu_cb), window);
g_signal_connect (priv->mdi_container, "create-window",
G_CALLBACK (handle_tab_droped_on_desktop), window);
+ }
gtk_box_pack_end (GTK_BOX (priv->main_vbox), GTK_WIDGET (priv->mdi_container), TRUE, TRUE, 0);
gtk_widget_show (GTK_WIDGET (priv->mdi_container));
@@ -2787,86 +2258,43 @@ terminal_window_init (TerminalWindow *window)
/* GAction setup */
g_action_map_add_action_entries (G_ACTION_MAP (window),
- gaction_entries, G_N_ELEMENTS (gaction_entries),
+ action_entries, G_N_ELEMENTS (action_entries),
window);
- /* Create the UI manager */
- manager = priv->ui_manager = gtk_ui_manager_new ();
-
- accel_group = gtk_ui_manager_get_accel_group (manager);
- gtk_window_add_accel_group (GTK_WINDOW (window), accel_group);
- /* Workaround for bug #453193, bug #138609 and bug #559728 */
- g_signal_connect_after (accel_group, "accel-activate",
- G_CALLBACK (terminal_window_accel_activate_cb), window);
-
- /* Create the actions */
- /* Note that this action group name is used in terminal-accels.c; do not change it */
- priv->action_group = action_group = gtk_action_group_new ("Main");
- gtk_action_group_set_translation_domain (action_group, NULL);
- gtk_action_group_add_actions (action_group, menu_entries,
- G_N_ELEMENTS (menu_entries), window);
- gtk_action_group_add_toggle_actions (action_group,
- toggle_menu_entries,
- G_N_ELEMENTS (toggle_menu_entries),
- window);
- gtk_ui_manager_insert_action_group (manager, action_group, 0);
- g_object_unref (action_group);
-
- priv->clipboard = gtk_widget_get_clipboard (GTK_WIDGET (window), GDK_SELECTION_CLIPBOARD);
- update_edit_menu (priv->clipboard, NULL, window);
- g_signal_connect (priv->clipboard, "owner-change",
- G_CALLBACK (update_edit_menu), window);
-
- /* Idem for this action, since the window is not fullscreen. */
- action = gtk_action_group_get_action (priv->action_group, "PopupLeaveFullscreen");
- gtk_action_set_visible (action, FALSE);
-
-#ifndef ENABLE_SAVE
- action = gtk_action_group_get_action (priv->action_group, "FileSaveContents");
- gtk_action_set_visible (action, FALSE);
-#endif
-
- /* Load the UI */
- error = NULL;
- priv->ui_id = gtk_ui_manager_add_ui_from_resource (manager,
- TERMINAL_RESOURCES_PATH_PREFIX "/ui/terminal.xml",
- &error);
- g_assert_no_error (error);
-
- priv->menubar = gtk_ui_manager_get_widget (manager, "/menubar");
- gtk_box_pack_start (GTK_BOX (priv->main_vbox),
- priv->menubar,
- FALSE, FALSE, 0);
-
+ g_simple_action_set_enabled (lookup_action (window, "leave-fullscreen"), FALSE);
+
+ /* Hide "menubar-visible" when the menubar is shown by the shell */
+ g_object_get (gtk_widget_get_settings (GTK_WIDGET (window)),
+ "gtk-shell-shows-menubar", &shell_shows_menubar,
+ NULL);
+ if (shell_shows_menubar) {
+ g_simple_action_set_enabled (lookup_action (window, "menubar-visible"), FALSE);
+ } else {
+ priv->menubar = gtk_menu_bar_new_from_model (terminal_app_get_menubar (app));
+ gtk_box_pack_start (GTK_BOX (priv->main_vbox),
+ priv->menubar,
+ FALSE, FALSE, 0);
+
+ terminal_window_set_menubar_visible (window, TRUE);
+ priv->use_default_menubar_visibility = TRUE;
+ }
/* Maybe make Inspector available */
- action = gtk_action_group_get_action (priv->action_group, "HelpInspector");
+ action = lookup_action (window, "inspector");
gtk_debug_settings = terminal_app_get_gtk_debug_settings (app);
if (gtk_debug_settings != NULL)
g_settings_bind (gtk_debug_settings,
"enable-inspector-keybinding",
action,
- "visible",
+ "enabled",
G_SETTINGS_BIND_GET | G_SETTINGS_BIND_NO_SENSITIVITY);
else
- gtk_action_set_visible (action, FALSE);
-
- /* Add tabs menu */
- priv->tabs_menu = terminal_tabs_menu_new (window);
+ g_simple_action_set_enabled (action, FALSE);
- profiles_list = terminal_app_get_profiles_list (app);
- terminal_window_profile_list_changed_cb (profiles_list, window);
- g_signal_connect (profiles_list, "children-changed",
- G_CALLBACK (terminal_window_profile_list_changed_cb), window);
-
- terminal_window_encoding_list_changed_cb (app, window);
- g_signal_connect (app, "encoding-list-changed",
- G_CALLBACK (terminal_window_encoding_list_changed_cb), window);
-
- terminal_window_set_menubar_visible (window, TRUE);
- priv->use_default_menubar_visibility = TRUE;
-
- terminal_window_update_size_to_menu (window);
+ priv->clipboard = gtk_widget_get_clipboard (GTK_WIDGET (window), GDK_SELECTION_CLIPBOARD);
+ clipboard_targets_changed_cb (app, priv->clipboard, window);
+ g_signal_connect (app, "clipboard-targets-changed",
+ G_CALLBACK (clipboard_targets_changed_cb), window);
terminal_window_fill_notebook_action_box (window);
@@ -2938,20 +2366,16 @@ terminal_window_dispose (GObject *object)
{
TerminalWindow *window = TERMINAL_WINDOW (object);
TerminalWindowPrivate *priv = window->priv;
- TerminalApp *app;
- TerminalSettingsList *profiles_list;
- GSList *list, *l;
+ TerminalApp *app = terminal_app_get ();
priv->disposed = TRUE;
- /* Deactivate open popup menus. This fixes a crash if the window is closed
- * while the context menu is open.
- */
- list = gtk_ui_manager_get_toplevels (priv->ui_manager, GTK_UI_MANAGER_POPUP);
- for (l = list; l != NULL; l = l->next)
- if (GTK_IS_MENU (l->data))
- gtk_menu_popdown (GTK_MENU (l->data));
- g_slist_free (list);
+ if (priv->clipboard != NULL) {
+ g_signal_handlers_disconnect_by_func (app,
+ G_CALLBACK (clipboard_targets_changed_cb),
+ window);
+ priv->clipboard = NULL;
+ }
remove_popup_info (window);
@@ -2963,30 +2387,6 @@ terminal_window_dispose (GObject *object)
priv->search_popover = NULL;
}
- if (priv->tabs_menu)
- {
- g_object_unref (priv->tabs_menu);
- priv->tabs_menu = NULL;
- }
-
- if (priv->profiles_action_group != NULL)
- disconnect_profiles_from_actions_in_group (priv->profiles_action_group);
- if (priv->new_terminal_action_group != NULL)
- disconnect_profiles_from_actions_in_group (priv->new_terminal_action_group);
-
- app = terminal_app_get ();
- profiles_list = terminal_app_get_profiles_list (app);
- g_signal_handlers_disconnect_by_func (profiles_list,
- G_CALLBACK (terminal_window_profile_list_changed_cb),
- window);
- g_signal_handlers_disconnect_by_func (app,
- G_CALLBACK (terminal_window_encoding_list_changed_cb),
- window);
-
- g_signal_handlers_disconnect_by_func (priv->clipboard,
- G_CALLBACK (update_edit_menu),
- window);
-
G_OBJECT_CLASS (terminal_window_parent_class)->dispose (object);
}
@@ -2996,8 +2396,6 @@ terminal_window_finalize (GObject *object)
TerminalWindow *window = TERMINAL_WINDOW (object);
TerminalWindowPrivate *priv = window->priv;
- g_object_unref (priv->ui_manager);
-
if (priv->confirm_close_dialog)
gtk_dialog_response (GTK_DIALOG (priv->confirm_close_dialog),
GTK_RESPONSE_DELETE_EVENT);
@@ -3030,7 +2428,7 @@ terminal_window_show (GtkWidget *widget)
widget_allocation.width, widget_allocation.height,
widget_allocation.x, widget_allocation.y);
- /* Because of the unexpected reentrancy caused by notebook_page_added_callback()
+ /* Because of the unexpected reentrancy caused by adding the tab to the notebook
* showing the TerminalWindow, we can get here when the first page has been
* added but not yet set current. By setting the page current, we get the
* right size when we first show the window */
@@ -3053,18 +2451,14 @@ terminal_window_new (GApplication *app)
{
return g_object_new (TERMINAL_TYPE_WINDOW,
"application", app,
-#ifdef ENABLE_DEBUG
- "show-menubar", _terminal_debug_on (TERMINAL_DEBUG_APPMENU),
-#else
"show-menubar", FALSE,
-#endif
NULL);
}
static void
-profile_set_callback (TerminalScreen *screen,
- GSettings *old_profile,
- TerminalWindow *window)
+profile_set_cb (TerminalScreen *screen,
+ GSettings *old_profile,
+ TerminalWindow *window)
{
TerminalWindowPrivate *priv = window->priv;
@@ -3084,12 +2478,12 @@ sync_screen_title (TerminalScreen *screen,
{
TerminalWindowPrivate *priv = window->priv;
const char *title;
-
+
if (screen != priv->active_screen)
return;
title = terminal_screen_get_title (screen);
- gtk_window_set_title (GTK_WINDOW (window),
+ gtk_window_set_title (GTK_WINDOW (window),
title && title[0] ? title : _("Terminal"));
}
@@ -3177,6 +2571,16 @@ screen_hyperlink_hover_uri_changed (TerminalScreen *screen,
gtk_widget_set_tooltip_text (GTK_WIDGET (screen), label);
}
+static void
+screen_encoding_changed_cb (TerminalScreen *screen,
+ GParamSpec *psepc,
+ gpointer user_data)
+{
+ TerminalWindow *window = user_data;
+
+ terminal_window_update_encoding_menu_active_encoding (window);
+}
+
/* MDI container callbacks */
static void
@@ -3267,21 +2671,18 @@ terminal_window_set_menubar_visible (TerminalWindow *window,
gboolean setting)
{
TerminalWindowPrivate *priv = window->priv;
- GtkAction *action;
+
+ if (priv->menubar == NULL)
+ return;
/* it's been set now, so don't override when adding a screen.
* this side effect must happen before we short-circuit below.
*/
priv->use_default_menubar_visibility = FALSE;
-
- if (setting == priv->menubar_visible)
- return;
- priv->menubar_visible = setting;
+ g_simple_action_set_state (lookup_action (window, "menubar-visible"),
+ g_variant_new_boolean (setting));
- action = gtk_action_group_get_action (priv->action_group, "ViewMenubar");
- gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), setting);
-
g_object_set (priv->menubar, "visible", setting, NULL);
/* FIXMEchpe: use gtk_widget_get_realized instead? */
@@ -3295,19 +2696,11 @@ terminal_window_set_menubar_visible (TerminalWindow *window,
}
}
-gboolean
-terminal_window_get_menubar_visible (TerminalWindow *window)
-{
- TerminalWindowPrivate *priv = window->priv;
-
- return priv->menubar_visible;
-}
-
GtkWidget *
terminal_window_get_mdi_container (TerminalWindow *window)
{
TerminalWindowPrivate *priv = window->priv;
-
+
g_return_val_if_fail (TERMINAL_IS_WINDOW (window), NULL);
return GTK_WIDGET (priv->mdi_container);
@@ -3372,20 +2765,48 @@ terminal_window_get_active (TerminalWindow *window)
return terminal_mdi_container_get_active_screen (priv->mdi_container);
}
+static void
+notebook_show_context_menu (TerminalWindow *window,
+ GdkEvent *event,
+ guint button,
+ guint32 timestamp)
+{
+ TerminalWindowPrivate *priv = window->priv;
+ GtkNotebook *notebook = GTK_NOTEBOOK (priv->mdi_container);
+ int page_num;
+ GtkWidget *tab, *tab_label;
+
+ page_num = gtk_notebook_get_current_page (notebook);
+ tab = gtk_notebook_get_nth_page (notebook, page_num);
+ tab_label = gtk_notebook_get_tab_label (notebook, tab);
+
+ /* Load the UI */
+ gs_unref_object GMenu *menu;
+ terminal_util_load_objects_resource ("/org/gnome/terminal/ui/notebook-menu.ui",
+ "notebook-popup", &menu,
+ NULL);
+
+ GtkWidget *popup_menu = context_menu_new (G_MENU_MODEL (menu), GTK_WIDGET (window));
+
+ gtk_widget_set_halign (popup_menu, GTK_ALIGN_START);
+ gtk_menu_popup (GTK_MENU (popup_menu), NULL, NULL,
+ position_menu_under_widget, tab_label,
+ button, timestamp);
+
+ if (button == 0)
+ gtk_menu_shell_select_first (GTK_MENU_SHELL (popup_menu), FALSE);
+}
+
static gboolean
notebook_button_press_cb (GtkWidget *widget,
GdkEventButton *event,
TerminalWindow *window)
{
- TerminalWindowPrivate *priv = window->priv;
GtkNotebook *notebook = GTK_NOTEBOOK (widget);
- GtkWidget *tab;
- GtkWidget *menu;
- GtkAction *action;
int tab_clicked;
if (event->type != GDK_BUTTON_PRESS ||
- event->button != 3 ||
+ event->button != GDK_BUTTON_SECONDARY ||
(event->state & gtk_accelerator_get_default_mod_mask ()) != 0)
return FALSE;
@@ -3396,18 +2817,7 @@ notebook_button_press_cb (GtkWidget *widget,
/* switch to the page the mouse is over */
gtk_notebook_set_current_page (notebook, tab_clicked);
- action = gtk_action_group_get_action (priv->action_group, "NotebookPopup");
- gtk_action_activate (action);
-
- menu = gtk_ui_manager_get_widget (priv->ui_manager, "/NotebookPopup");
- if (gtk_menu_get_attach_widget (GTK_MENU (menu)))
- gtk_menu_detach (GTK_MENU (menu));
- tab = gtk_notebook_get_nth_page (notebook, tab_clicked);
- gtk_menu_attach_to_widget (GTK_MENU (menu), tab, NULL);
- gtk_menu_popup (GTK_MENU (menu), NULL, NULL,
- NULL, NULL,
- event->button, event->time);
-
+ notebook_show_context_menu (window, (GdkEvent*)event, event->button, event->time);
return TRUE;
}
@@ -3416,32 +2826,14 @@ notebook_popup_menu_cb (GtkWidget *widget,
TerminalWindow *window)
{
TerminalWindowPrivate *priv = window->priv;
- GtkNotebook *notebook = GTK_NOTEBOOK (priv->mdi_container);
- GtkWidget *focus_widget, *tab, *tab_label, *menu;
- GtkAction *action;
- int page_num;
+ GtkWidget *focus_widget;
focus_widget = gtk_window_get_focus (GTK_WINDOW (window));
/* Only respond if the notebook is the actual focus */
if (focus_widget != GTK_WIDGET (priv->mdi_container))
return FALSE;
- page_num = gtk_notebook_get_current_page (notebook);
- tab = gtk_notebook_get_nth_page (notebook, page_num);
- tab_label = gtk_notebook_get_tab_label (notebook, tab);
-
- action = gtk_action_group_get_action (priv->action_group, "NotebookPopup");
- gtk_action_activate (action);
-
- menu = gtk_ui_manager_get_widget (priv->ui_manager, "/NotebookPopup");
- if (gtk_menu_get_attach_widget (GTK_MENU (menu)))
- gtk_menu_detach (GTK_MENU (menu));
- gtk_menu_attach_to_widget (GTK_MENU (menu), tab_label, NULL);
- gtk_menu_popup (GTK_MENU (menu), NULL, NULL,
- position_menu_under_widget, tab_label,
- 0, gtk_get_current_event_time ());
- gtk_menu_shell_select_first (GTK_MENU_SHELL (menu), FALSE);
-
+ notebook_show_context_menu (window, NULL, 0, gtk_get_current_event_time ());
return TRUE;
}
@@ -3500,7 +2892,7 @@ mdi_screen_switched_cb (TerminalMdiContainer *container,
window);
terminal_window_update_size (window);
- terminal_window_update_tabs_menu_sensitivity (window);
+ terminal_window_update_tabs_actions_sensitivity (window);
terminal_window_update_encoding_menu_active_encoding (window);
terminal_window_update_terminal_menu (window);
terminal_window_update_set_profile_menu_active_profile (window);
@@ -3523,7 +2915,7 @@ mdi_screen_added_cb (TerminalMdiContainer *container,
g_signal_connect (G_OBJECT (screen),
"profile-set",
- G_CALLBACK (profile_set_callback),
+ G_CALLBACK (profile_set_cb),
window);
/* FIXME: only connect on the active screen, not all screens! */
@@ -3537,13 +2929,15 @@ mdi_screen_added_cb (TerminalMdiContainer *container,
G_CALLBACK (screen_font_any_changed_cb), window);
g_signal_connect (screen, "notify::font-scale",
G_CALLBACK (screen_font_any_changed_cb), window);
+ g_signal_connect (screen, "notify::encoding",
+ G_CALLBACK (screen_encoding_changed_cb), window);
g_signal_connect (screen, "selection-changed",
G_CALLBACK (terminal_window_update_copy_sensitivity), window);
g_signal_connect (screen, "hyperlink-hover-uri-changed",
G_CALLBACK (screen_hyperlink_hover_uri_changed), window);
g_signal_connect (screen, "show-popup-menu",
- G_CALLBACK (screen_show_popup_menu_callback), window);
+ G_CALLBACK (screen_show_popup_menu_cb), window);
g_signal_connect (screen, "match-clicked",
G_CALLBACK (screen_match_clicked_cb), window);
g_signal_connect (screen, "resize-window",
@@ -3552,7 +2946,7 @@ mdi_screen_added_cb (TerminalMdiContainer *container,
g_signal_connect (screen, "close-screen",
G_CALLBACK (screen_close_cb), window);
- terminal_window_update_tabs_menu_sensitivity (window);
+ terminal_window_update_tabs_actions_sensitivity (window);
terminal_window_update_search_sensitivity (screen, window);
#if 0
@@ -3601,7 +2995,7 @@ mdi_screen_removed_cb (TerminalMdiContainer *container,
window, screen);
g_signal_handlers_disconnect_by_func (G_OBJECT (screen),
- G_CALLBACK (profile_set_callback),
+ G_CALLBACK (profile_set_cb),
window);
g_signal_handlers_disconnect_by_func (G_OBJECT (screen),
@@ -3621,6 +3015,10 @@ mdi_screen_removed_cb (TerminalMdiContainer *container,
window);
g_signal_handlers_disconnect_by_func (G_OBJECT (screen),
+ G_CALLBACK (screen_encoding_changed_cb),
+ window);
+
+ g_signal_handlers_disconnect_by_func (G_OBJECT (screen),
G_CALLBACK (terminal_window_update_copy_sensitivity),
window);
@@ -3629,7 +3027,7 @@ mdi_screen_removed_cb (TerminalMdiContainer *container,
window);
g_signal_handlers_disconnect_by_func (screen,
- G_CALLBACK (screen_show_popup_menu_callback),
+ G_CALLBACK (screen_show_popup_menu_cb),
window);
g_signal_handlers_disconnect_by_func (screen,
@@ -3658,7 +3056,7 @@ mdi_screen_removed_cb (TerminalMdiContainer *container,
return;
}
- terminal_window_update_tabs_menu_sensitivity (window);
+ terminal_window_update_tabs_actions_sensitivity (window);
terminal_window_update_search_sensitivity (screen, window);
if (pages == 1)
@@ -3670,6 +3068,13 @@ mdi_screen_removed_cb (TerminalMdiContainer *container,
}
}
+static void
+mdi_screens_reordered_cb (TerminalMdiContainer *container,
+ TerminalWindow *window)
+{
+ terminal_window_update_tabs_actions_sensitivity (window);
+}
+
gboolean
terminal_window_parse_geometry (TerminalWindow *window,
const char *geometry)
@@ -3809,9 +3214,6 @@ terminal_window_update_geometry (TerminalWindow *window)
hints.base_width = chrome_width + csd_width;
hints.base_height = chrome_height + csd_height;
-#define MIN_WIDTH_CHARS 4
-#define MIN_HEIGHT_CHARS 1
-
hints.width_inc = char_width;
hints.height_inc = char_height;
@@ -3970,195 +3372,6 @@ confirm_close_window_or_tab (TerminalWindow *window,
return TRUE;
}
-static void
-file_close_window_callback (GtkAction *action,
- TerminalWindow *window)
-{
- terminal_window_request_close (window);
-}
-
-static void
-file_close_tab_callback (GtkAction *action,
- TerminalWindow *window)
-{
- TerminalWindowPrivate *priv = window->priv;
- TerminalScreen *active_screen = priv->active_screen;
-
- if (!active_screen)
- return;
-
- if (confirm_close_window_or_tab (window, active_screen))
- return;
-
- terminal_window_remove_screen (window, active_screen);
-}
-
-static void
-edit_preferences_callback (GtkAction *action,
- TerminalWindow *window)
-{
- terminal_app_edit_preferences (terminal_app_get (), GTK_WINDOW (window));
-}
-
-static void
-edit_current_profile_callback (GtkAction *action,
- TerminalWindow *window)
-{
- TerminalWindowPrivate *priv = window->priv;
-
- terminal_app_edit_profile (terminal_app_get (),
- terminal_screen_get_profile (priv->active_screen),
- GTK_WINDOW (window),
- NULL);
-}
-
-static void
-file_new_profile_callback (GtkAction *action,
- TerminalWindow *window)
-{
- TerminalWindowPrivate *priv = window->priv;
-
- terminal_app_new_profile (terminal_app_get (),
- terminal_screen_get_profile (priv->active_screen),
- GTK_WINDOW (window));
-}
-
-static void
-view_menubar_toggled_callback (GtkToggleAction *action,
- TerminalWindow *window)
-{
- terminal_window_set_menubar_visible (window, gtk_toggle_action_get_active (action));
-}
-
-static void
-view_fullscreen_toggled_callback (GtkToggleAction *action,
- TerminalWindow *window)
-{
- g_return_if_fail (gtk_widget_get_realized (GTK_WIDGET (window)));
-
- if (gtk_toggle_action_get_active (action))
- gtk_window_fullscreen (GTK_WINDOW (window));
- else
- gtk_window_unfullscreen (GTK_WINDOW (window));
-}
-
-static void
-terminal_add_encoding_callback (GtkAction *action,
- TerminalWindow *window)
-{
- terminal_app_edit_encodings (terminal_app_get (),
- GTK_WINDOW (window));
-}
-
-static void
-terminal_reset_callback (GtkAction *action,
- TerminalWindow *window)
-{
- TerminalWindowPrivate *priv = window->priv;
-
- if (priv->active_screen == NULL)
- return;
-
- vte_terminal_reset (VTE_TERMINAL (priv->active_screen), TRUE, FALSE);
-}
-
-static void
-terminal_reset_clear_callback (GtkAction *action,
- TerminalWindow *window)
-{
- TerminalWindowPrivate *priv = window->priv;
-
- if (priv->active_screen == NULL)
- return;
-
- vte_terminal_reset (VTE_TERMINAL (priv->active_screen), TRUE, TRUE);
-}
-
-static void
-terminal_readonly_toggled_callback (GtkToggleAction *action,
- TerminalWindow *window)
-{
- TerminalWindowPrivate *priv = window->priv;
-
- if (priv->active_screen == NULL)
- return;
-
- vte_terminal_set_input_enabled(VTE_TERMINAL(priv->active_screen),
- !gtk_toggle_action_get_active (action));
-}
-
-static void
-tabs_next_or_previous_tab_cb (GtkAction *action,
- TerminalWindow *window)
-{
- TerminalWindowPrivate *priv = window->priv;
- const char *name;
- guint keyval = 0;
-
- name = gtk_action_get_name (action);
- if (strcmp (name, "TabsNext") == 0) {
- keyval = GDK_KEY_Page_Down;
- } else if (strcmp (name, "TabsPrevious") == 0) {
- keyval = GDK_KEY_Page_Up;
- }
-
- /* FIXMEchpe this is GtkNotebook specific */
- gtk_bindings_activate (G_OBJECT (priv->mdi_container),
- keyval,
- GDK_CONTROL_MASK);
-}
-
-static void
-tabs_move_left_callback (GtkAction *action,
- TerminalWindow *window)
-{
- TerminalWindowPrivate *priv = window->priv;
-
- terminal_mdi_container_reorder_screen (priv->mdi_container,
- terminal_mdi_container_get_active_screen (priv->mdi_container),
- -1);
-}
-
-static void
-tabs_move_right_callback (GtkAction *action,
- TerminalWindow *window)
-{
- TerminalWindowPrivate *priv = window->priv;
-
- terminal_mdi_container_reorder_screen (priv->mdi_container,
- terminal_mdi_container_get_active_screen (priv->mdi_container),
- +1);
-}
-
-static void
-help_contents_callback (GtkAction *action,
- TerminalWindow *window)
-{
- terminal_util_show_help (NULL, GTK_WINDOW (window));
-}
-
-static void
-help_about_callback (GtkAction *action,
- TerminalWindow *window)
-{
- terminal_util_show_about (NULL);
-}
-
-static void
-help_inspector_callback (GtkAction *action,
- TerminalWindow *window)
-{
- gtk_window_set_interactive_debugging (TRUE);
-}
-
-GtkUIManager *
-terminal_window_get_ui_manager (TerminalWindow *window)
-{
- TerminalWindowPrivate *priv = window->priv;
-
- return priv->ui_manager;
-}
-
void
terminal_window_request_close (TerminalWindow *window)
{
@@ -4170,14 +3383,6 @@ terminal_window_request_close (TerminalWindow *window)
gtk_widget_destroy (GTK_WIDGET (window));
}
-GtkActionGroup *
-terminal_window_get_main_action_group (TerminalWindow *window)
-{
- TerminalWindowPrivate *priv = window->priv;
-
- return priv->action_group;
-}
-
const char *
terminal_window_get_uuid (TerminalWindow *window)
{
diff --git a/src/terminal-window.h b/src/terminal-window.h
index f090835..a76469a 100644
--- a/src/terminal-window.h
+++ b/src/terminal-window.h
@@ -70,7 +70,6 @@ void terminal_window_move_screen (TerminalWindow *source_window,
*/
void terminal_window_set_menubar_visible (TerminalWindow *window,
gboolean setting);
-gboolean terminal_window_get_menubar_visible (TerminalWindow *window);
void terminal_window_update_size (TerminalWindow *window);
@@ -89,8 +88,6 @@ GtkWidget* terminal_window_get_mdi_container (TerminalWindow *window);
void terminal_window_request_close (TerminalWindow *window);
-GtkActionGroup *terminal_window_get_main_action_group (TerminalWindow *window);
-
const char *terminal_window_get_uuid (TerminalWindow *window);
G_END_DECLS
diff --git a/src/terminal.c b/src/terminal.c
index 149c480..b3ebe9c 100644
--- a/src/terminal.c
+++ b/src/terminal.c
@@ -20,7 +20,6 @@
*/
#include "config.h"
-#define _GNU_SOURCE
#include <errno.h>
#include <locale.h>
diff --git a/src/terminal.gresource.xml b/src/terminal.gresource.xml
index 9638b5b..411c570 100644
--- a/src/terminal.gresource.xml
+++ b/src/terminal.gresource.xml
@@ -17,13 +17,14 @@
-->
<gresources>
<gresource prefix="/org/gnome/terminal">
- <file alias="ui/terminal.xml" compressed="true" preprocess="xml-stripblanks">terminal.xml</file>
- <file alias="ui/terminal.about" compressed="true">terminal.about</file>
- <file alias="ui/search-popover.ui" compressed="true"
preprocess="xml-stripblanks">search-popover.ui</file>
+ <file alias="css/terminal.css" compressed="true">terminal.common.css</file>
+ <file alias="gtk/menus.ui" compressed="true" preprocess="xml-stripblanks">terminal-appmenu.ui</file>
+ <file alias="ui/menubar.ui" compressed="true" preprocess="xml-stripblanks">terminal-menubar.ui</file>
+ <file alias="ui/notebook-menu.ui" compressed="true"
preprocess="xml-stripblanks">terminal-notebook-menu.ui</file>
<file alias="ui/preferences.ui" compressed="true" preprocess="xml-stripblanks">preferences.ui</file>
<file alias="ui/profile-preferences.ui" compressed="true"
preprocess="xml-stripblanks">profile-preferences.ui</file>
+ <file alias="ui/search-popover.ui" compressed="true"
preprocess="xml-stripblanks">search-popover.ui</file>
+ <file alias="ui/terminal.about" compressed="true">terminal.about</file>
<file alias="ui/window.ui" compressed="true" preprocess="xml-stripblanks">terminal-window.ui</file>
- <file alias="gtk/menus.ui" compressed="true" preprocess="xml-stripblanks">terminal-menus.ui</file>
- <file alias="css/terminal.css" compressed="true">terminal.common.css</file>
</gresource>
</gresources>
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]