summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormbkma <[email protected]>2026-02-01 08:12:15 +0100
committermbkma <[email protected]>2026-02-02 00:11:25 +0100
commitf03c3fa5d195bd26232a5a4a1a1d761b2187a6b7 (patch)
tree5fce2241d3424d66874c69fa57d86c844d5008a6
parent72e82009ab236c2edb16827905b0aeb5bfc61a11 (diff)
downloadmate-terminal-application.tar.bz2
mate-terminal-application.tar.xz
port to GtkApplicationapplication
-rw-r--r--src/meson.build2
-rw-r--r--src/terminal-accels.c108
-rw-r--r--src/terminal-accels.h3
-rw-r--r--src/terminal-actions.c603
-rw-r--r--src/terminal-actions.h85
-rw-r--r--src/terminal-app.c343
-rw-r--r--src/terminal-app.h12
-rw-r--r--src/terminal-encoding.c2
-rw-r--r--src/terminal-window.c86
-rw-r--r--src/terminal-window.h10
-rw-r--r--src/terminal.c538
11 files changed, 1121 insertions, 671 deletions
diff --git a/src/meson.build b/src/meson.build
index a8cd1b1..67748d1 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -36,6 +36,8 @@ sources = [
'terminal.c',
'terminal-accels.c',
'terminal-accels.h',
+ 'terminal-actions.c',
+ 'terminal-actions.h',
'terminal-app.c',
'terminal-app.h',
'terminal-close-button.h',
diff --git a/src/terminal-accels.c b/src/terminal-accels.c
index 06b35e4..f2fa795 100644
--- a/src/terminal-accels.c
+++ b/src/terminal-accels.c
@@ -379,6 +379,7 @@ static gboolean binding_from_value (GVariant *value,
GdkModifierType *accelerator_mods);
static gboolean sync_idle_cb (gpointer data);
+static void update_gaction_accel_for_key (const gchar *gsettings_key);
static guint sync_idle_id = 0;
static GtkAccelGroup *notification_group = NULL;
@@ -578,6 +579,9 @@ keys_change_notify (GSettings *settings,
if (edit_keys_store)
gtk_tree_model_foreach (GTK_TREE_MODEL (edit_keys_store), update_model_foreach, key_entry);
+ /* Also update GAction accelerator if this key has one */
+ update_gaction_accel_for_key (key);
+
g_variant_unref(val);
}
@@ -1091,3 +1095,107 @@ done:
gtk_window_set_transient_for (GTK_WINDOW (edit_keys_dialog), transient_parent);
gtk_window_present (GTK_WINDOW (edit_keys_dialog));
}
+
+/* GAction accelerator mapping
+ * Maps GSettings keys to GAction names for gtk_application_set_accels_for_action
+ */
+typedef struct {
+ const char *gsettings_key;
+ const char *action_name;
+} GActionAccelEntry;
+
+static const char *
+get_gaction_name_for_gsettings_key (const gchar *gsettings_key);
+
+static void
+update_gaction_accel_for_key (const gchar *gsettings_key)
+{
+ GApplication *app;
+ const char *action_name;
+ char *binding;
+ const char *accels[2] = { NULL, NULL };
+
+ app = g_application_get_default ();
+ if (!GTK_IS_APPLICATION (app))
+ return;
+
+ action_name = get_gaction_name_for_gsettings_key (gsettings_key);
+ if (!action_name)
+ return;
+
+ binding = g_settings_get_string (settings_keybindings, gsettings_key);
+
+ if (binding && *binding && g_strcmp0 (binding, "disabled") != 0)
+ accels[0] = binding;
+
+ gtk_application_set_accels_for_action (GTK_APPLICATION (app), action_name, accels);
+
+ g_free (binding);
+}
+
+static const GActionAccelEntry gaction_accels[] = {
+ { KEY_NEW_TAB, "win.new-tab" },
+ { KEY_NEW_WINDOW, "app.new-window" },
+ { KEY_CLOSE_TAB, "win.close-tab" },
+ { KEY_CLOSE_WINDOW, "win.close-window" },
+ { KEY_COPY, "win.copy" },
+ { KEY_PASTE, "win.paste" },
+ { KEY_SELECT_ALL, "win.select-all" },
+ { KEY_FULL_SCREEN, "win.fullscreen" },
+ { KEY_TOGGLE_MENUBAR, "win.menubar" },
+ { KEY_PREV_TAB, "win.prev-tab" },
+ { KEY_NEXT_TAB, "win.next-tab" },
+ { KEY_MOVE_TAB_LEFT, "win.move-tab-left" },
+ { KEY_MOVE_TAB_RIGHT, "win.move-tab-right" },
+ { KEY_SEARCH_FIND_NEXT, "win.find-next" },
+ { KEY_SEARCH_FIND_PREVIOUS, "win.find-prev" },
+ { KEY_RESET, "win.reset" },
+ { KEY_RESET_AND_CLEAR, "win.reset-clear" },
+ { KEY_HELP, "app.help" },
+};
+
+static const char *
+get_gaction_name_for_gsettings_key (const gchar *gsettings_key)
+{
+ guint i;
+
+ for (i = 0; i < G_N_ELEMENTS (gaction_accels); i++)
+ {
+ if (g_strcmp0 (gaction_accels[i].gsettings_key, gsettings_key) == 0)
+ return gaction_accels[i].action_name;
+ }
+
+ return NULL;
+}
+
+void
+terminal_accels_set_gaction_accels (GtkApplication *app)
+{
+ guint i;
+
+ g_return_if_fail (GTK_IS_APPLICATION (app));
+ g_return_if_fail (settings_keybindings != NULL);
+
+ for (i = 0; i < G_N_ELEMENTS (gaction_accels); i++)
+ {
+ const GActionAccelEntry *entry = &gaction_accels[i];
+ char *binding;
+ const char *accels[2] = { NULL, NULL };
+
+ binding = g_settings_get_string (settings_keybindings, entry->gsettings_key);
+
+ /* Check if binding is valid (not empty, not "disabled") */
+ if (binding && *binding && g_strcmp0 (binding, "disabled") != 0)
+ {
+ accels[0] = binding;
+ gtk_application_set_accels_for_action (app, entry->action_name, accels);
+ }
+ else
+ {
+ /* Set empty accelerator list (clears any existing) */
+ gtk_application_set_accels_for_action (app, entry->action_name, accels);
+ }
+
+ g_free (binding);
+ }
+}
diff --git a/src/terminal-accels.h b/src/terminal-accels.h
index 4fddc2f..00fb8cb 100644
--- a/src/terminal-accels.h
+++ b/src/terminal-accels.h
@@ -29,6 +29,9 @@ void terminal_accels_init (void);
void terminal_accels_shutdown (void);
+/* Set up accelerators for GActions */
+void terminal_accels_set_gaction_accels (GtkApplication *app);
+
void terminal_edit_keys_dialog_show (GtkWindow *transient_parent);
G_END_DECLS
diff --git a/src/terminal-actions.c b/src/terminal-actions.c
new file mode 100644
index 0000000..0afc1f4
--- /dev/null
+++ b/src/terminal-actions.c
@@ -0,0 +1,603 @@
+/*
+ * Copyright (C) 2012-2021 MATE Developers
+ *
+ * Mate-terminal 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.
+ *
+ * Mate-terminal 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/>.
+ */
+
+#include <config.h>
+
+#include <string.h>
+#include <gtk/gtk.h>
+#include <vte/vte.h>
+
+#include "terminal-actions.h"
+#include "terminal-app.h"
+#include "terminal-intl.h"
+#include "terminal-screen.h"
+#include "terminal-util.h"
+#include "terminal-window.h"
+
+/*
+ * Application-level action callbacks
+ */
+
+static void
+action_quit (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
+{
+ GtkApplication *app = GTK_APPLICATION (user_data);
+ GList *windows;
+
+ /* Close all windows - this will trigger quit */
+ windows = gtk_application_get_windows (app);
+ while (windows)
+ {
+ GtkWidget *window = GTK_WIDGET (windows->data);
+ windows = windows->next;
+ gtk_widget_destroy (window);
+ }
+}
+
+static void
+action_new_window (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
+{
+ TerminalApp *app = TERMINAL_APP (user_data);
+ TerminalWindow *window;
+ TerminalProfile *profile;
+
+ profile = terminal_app_get_profile_for_new_term (app);
+ if (!profile)
+ return;
+
+ window = terminal_app_new_window (app, gdk_screen_get_default ());
+ terminal_app_new_terminal (app, window, profile,
+ NULL, NULL, NULL, NULL, 1.0);
+ gtk_window_present (GTK_WINDOW (window));
+}
+
+static void
+action_preferences (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
+{
+ TerminalApp *app = TERMINAL_APP (user_data);
+ GtkWindow *parent = NULL;
+ GList *windows;
+
+ windows = gtk_application_get_windows (GTK_APPLICATION (app));
+ if (windows)
+ parent = GTK_WINDOW (windows->data);
+
+ terminal_app_manage_profiles (app, parent);
+}
+
+static void
+action_help (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
+{
+ GtkApplication *app = GTK_APPLICATION (user_data);
+ GtkWindow *parent = NULL;
+ GList *windows;
+
+ windows = gtk_application_get_windows (app);
+ if (windows)
+ parent = GTK_WINDOW (windows->data);
+
+ terminal_util_show_help (NULL, parent);
+}
+
+/* Application action entries */
+static const GActionEntry app_actions[] = {
+ { TERMINAL_ACTION_QUIT, action_quit, NULL, NULL, NULL },
+ { TERMINAL_ACTION_NEW_WINDOW, action_new_window, NULL, NULL, NULL },
+ { TERMINAL_ACTION_PREFERENCES, action_preferences, NULL, NULL, NULL },
+ { TERMINAL_ACTION_HELP, action_help, NULL, NULL, NULL },
+};
+
+/*
+ * Window-level action callbacks
+ */
+
+static TerminalWindow *
+get_terminal_window (gpointer user_data)
+{
+ if (TERMINAL_IS_WINDOW (user_data))
+ return TERMINAL_WINDOW (user_data);
+ return NULL;
+}
+
+static void
+action_new_tab (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
+{
+ TerminalWindow *window = get_terminal_window (user_data);
+ if (!window)
+ return;
+
+ TerminalApp *app = terminal_app_get ();
+ TerminalProfile *profile = terminal_app_get_profile_for_new_term (app);
+
+ if (profile)
+ {
+ TerminalScreen *screen = terminal_window_get_active (window);
+ char *working_dir = NULL;
+
+ if (screen)
+ working_dir = terminal_screen_get_current_dir_with_fallback (screen);
+
+ terminal_app_new_terminal (app, window, profile,
+ NULL, NULL,
+ working_dir,
+ screen ? terminal_screen_get_initial_environment (screen) : NULL,
+ 1.0);
+ g_free (working_dir);
+ }
+}
+
+static void
+action_close_tab (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
+{
+ TerminalWindow *window = get_terminal_window (user_data);
+ if (!window)
+ return;
+
+ TerminalScreen *screen = terminal_window_get_active (window);
+ if (screen)
+ terminal_window_remove_screen (window, screen);
+}
+
+static void
+action_close_window (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
+{
+ TerminalWindow *window = get_terminal_window (user_data);
+ if (!window)
+ return;
+
+ gtk_widget_destroy (GTK_WIDGET (window));
+}
+
+static void
+action_copy (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
+{
+ TerminalWindow *window = get_terminal_window (user_data);
+ if (!window)
+ return;
+
+ TerminalScreen *screen = terminal_window_get_active (window);
+ if (screen)
+ vte_terminal_copy_clipboard_format (VTE_TERMINAL (screen), VTE_FORMAT_TEXT);
+}
+
+static void
+action_paste (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
+{
+ TerminalWindow *window = get_terminal_window (user_data);
+ if (!window)
+ return;
+
+ TerminalScreen *screen = terminal_window_get_active (window);
+ if (screen)
+ vte_terminal_paste_clipboard (VTE_TERMINAL (screen));
+}
+
+static void
+action_select_all (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
+{
+ TerminalWindow *window = get_terminal_window (user_data);
+ if (!window)
+ return;
+
+ TerminalScreen *screen = terminal_window_get_active (window);
+ if (screen)
+ vte_terminal_select_all (VTE_TERMINAL (screen));
+}
+
+static void
+action_fullscreen (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
+{
+ TerminalWindow *window = get_terminal_window (user_data);
+ if (!window)
+ return;
+
+ GVariant *state = g_action_get_state (G_ACTION (action));
+ gboolean active = g_variant_get_boolean (state);
+
+ g_simple_action_set_state (action, g_variant_new_boolean (!active));
+
+ if (!active)
+ gtk_window_fullscreen (GTK_WINDOW (window));
+ else
+ gtk_window_unfullscreen (GTK_WINDOW (window));
+
+ g_variant_unref (state);
+}
+
+static void
+action_menubar (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
+{
+ TerminalWindow *window = get_terminal_window (user_data);
+ if (!window)
+ return;
+
+ GVariant *state = g_action_get_state (G_ACTION (action));
+ gboolean visible = g_variant_get_boolean (state);
+
+ g_simple_action_set_state (action, g_variant_new_boolean (!visible));
+ terminal_window_set_menubar_visible (window, !visible);
+
+ g_variant_unref (state);
+}
+
+static void
+action_prev_tab (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
+{
+ TerminalWindow *window = get_terminal_window (user_data);
+ if (!window)
+ return;
+
+ GtkWidget *notebook = terminal_window_get_notebook (window);
+ if (notebook)
+ {
+ int page = gtk_notebook_get_current_page (GTK_NOTEBOOK (notebook));
+ if (page > 0)
+ gtk_notebook_set_current_page (GTK_NOTEBOOK (notebook), page - 1);
+ else
+ {
+ int n_pages = gtk_notebook_get_n_pages (GTK_NOTEBOOK (notebook));
+ gtk_notebook_set_current_page (GTK_NOTEBOOK (notebook), n_pages - 1);
+ }
+ }
+}
+
+static void
+action_next_tab (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
+{
+ TerminalWindow *window = get_terminal_window (user_data);
+ if (!window)
+ return;
+
+ GtkWidget *notebook = terminal_window_get_notebook (window);
+ if (notebook)
+ {
+ int page = gtk_notebook_get_current_page (GTK_NOTEBOOK (notebook));
+ int n_pages = gtk_notebook_get_n_pages (GTK_NOTEBOOK (notebook));
+ if (page < n_pages - 1)
+ gtk_notebook_set_current_page (GTK_NOTEBOOK (notebook), page + 1);
+ else
+ gtk_notebook_set_current_page (GTK_NOTEBOOK (notebook), 0);
+ }
+}
+
+static void
+action_move_tab_left (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
+{
+ TerminalWindow *window = get_terminal_window (user_data);
+ if (!window)
+ return;
+
+ GtkWidget *notebook = terminal_window_get_notebook (window);
+ if (notebook)
+ {
+ int page = gtk_notebook_get_current_page (GTK_NOTEBOOK (notebook));
+ if (page > 0)
+ {
+ GtkWidget *child = gtk_notebook_get_nth_page (GTK_NOTEBOOK (notebook), page);
+ gtk_notebook_reorder_child (GTK_NOTEBOOK (notebook), child, page - 1);
+ }
+ }
+}
+
+static void
+action_move_tab_right (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
+{
+ TerminalWindow *window = get_terminal_window (user_data);
+ if (!window)
+ return;
+
+ GtkWidget *notebook = terminal_window_get_notebook (window);
+ if (notebook)
+ {
+ int page = gtk_notebook_get_current_page (GTK_NOTEBOOK (notebook));
+ int n_pages = gtk_notebook_get_n_pages (GTK_NOTEBOOK (notebook));
+ if (page < n_pages - 1)
+ {
+ GtkWidget *child = gtk_notebook_get_nth_page (GTK_NOTEBOOK (notebook), page);
+ gtk_notebook_reorder_child (GTK_NOTEBOOK (notebook), child, page + 1);
+ }
+ }
+}
+
+static void
+action_find_next (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
+{
+ TerminalWindow *window = get_terminal_window (user_data);
+ if (!window)
+ return;
+
+ TerminalScreen *screen = terminal_window_get_active (window);
+ if (screen)
+ vte_terminal_search_find_next (VTE_TERMINAL (screen));
+}
+
+static void
+action_find_prev (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
+{
+ TerminalWindow *window = get_terminal_window (user_data);
+ if (!window)
+ return;
+
+ TerminalScreen *screen = terminal_window_get_active (window);
+ if (screen)
+ vte_terminal_search_find_previous (VTE_TERMINAL (screen));
+}
+
+static void
+action_reset (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
+{
+ TerminalWindow *window = get_terminal_window (user_data);
+ if (!window)
+ return;
+
+ TerminalScreen *screen = terminal_window_get_active (window);
+ if (screen)
+ vte_terminal_reset (VTE_TERMINAL (screen), TRUE, FALSE);
+}
+
+static void
+action_reset_clear (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
+{
+ TerminalWindow *window = get_terminal_window (user_data);
+ if (!window)
+ return;
+
+ TerminalScreen *screen = terminal_window_get_active (window);
+ if (screen)
+ vte_terminal_reset (VTE_TERMINAL (screen), TRUE, TRUE);
+}
+
+static void
+action_new_profile (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
+{
+ TerminalWindow *window = get_terminal_window (user_data);
+ TerminalApp *app = terminal_app_get ();
+
+ terminal_app_new_profile (app,
+ terminal_app_get_profile_for_new_term (app),
+ window ? GTK_WINDOW (window) : NULL);
+}
+
+static void
+action_keybindings (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
+{
+ TerminalWindow *window = get_terminal_window (user_data);
+ TerminalApp *app = terminal_app_get ();
+
+ terminal_app_edit_keybindings (app, window ? GTK_WINDOW (window) : NULL);
+}
+
+static void
+action_current_profile (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
+{
+ TerminalWindow *window = get_terminal_window (user_data);
+ if (!window)
+ return;
+
+ TerminalApp *app = terminal_app_get ();
+ TerminalScreen *screen = terminal_window_get_active (window);
+ if (screen)
+ {
+ TerminalProfile *profile = terminal_screen_get_profile (screen);
+ if (profile)
+ terminal_app_edit_profile (app, profile, GTK_WINDOW (window), NULL);
+ }
+}
+
+static void
+action_zoom_in (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
+{
+ TerminalWindow *window = get_terminal_window (user_data);
+ if (!window)
+ return;
+
+ TerminalScreen *screen = terminal_window_get_active (window);
+ if (screen)
+ {
+ double zoom = vte_terminal_get_font_scale (VTE_TERMINAL (screen));
+ vte_terminal_set_font_scale (VTE_TERMINAL (screen), zoom * 1.1);
+ terminal_window_update_size (window, screen, TRUE);
+ }
+}
+
+static void
+action_zoom_out (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
+{
+ TerminalWindow *window = get_terminal_window (user_data);
+ if (!window)
+ return;
+
+ TerminalScreen *screen = terminal_window_get_active (window);
+ if (screen)
+ {
+ double zoom = vte_terminal_get_font_scale (VTE_TERMINAL (screen));
+ vte_terminal_set_font_scale (VTE_TERMINAL (screen), zoom / 1.1);
+ terminal_window_update_size (window, screen, TRUE);
+ }
+}
+
+static void
+action_zoom_normal (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
+{
+ TerminalWindow *window = get_terminal_window (user_data);
+ if (!window)
+ return;
+
+ TerminalScreen *screen = terminal_window_get_active (window);
+ if (screen)
+ {
+ vte_terminal_set_font_scale (VTE_TERMINAL (screen), 1.0);
+ terminal_window_update_size (window, screen, TRUE);
+ }
+}
+
+static void
+action_find (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
+{
+ TerminalWindow *window = get_terminal_window (user_data);
+ if (!window)
+ return;
+
+ terminal_window_show_find_dialog (window);
+}
+
+static void
+action_set_title (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
+{
+ TerminalWindow *window = get_terminal_window (user_data);
+ if (!window)
+ return;
+
+ terminal_window_show_set_title_dialog (window);
+}
+
+static void
+action_detach_tab (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
+{
+ TerminalWindow *window = get_terminal_window (user_data);
+ if (!window)
+ return;
+
+ TerminalScreen *screen = terminal_window_get_active (window);
+ if (screen)
+ terminal_window_detach_screen (window, screen);
+}
+
+static void
+action_about (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
+{
+ TerminalWindow *window = get_terminal_window (user_data);
+ GtkWindow *parent = window ? GTK_WINDOW (window) : NULL;
+
+ terminal_window_show_about_dialog (parent);
+}
+
+/* Window action entries */
+static const GActionEntry win_actions[] = {
+ { TERMINAL_ACTION_NEW_TAB, action_new_tab, NULL, NULL, NULL },
+ { TERMINAL_ACTION_NEW_PROFILE, action_new_profile, NULL, NULL, NULL },
+ { TERMINAL_ACTION_CLOSE_TAB, action_close_tab, NULL, NULL, NULL },
+ { TERMINAL_ACTION_CLOSE_WINDOW, action_close_window, NULL, NULL, NULL },
+ { TERMINAL_ACTION_COPY, action_copy, NULL, NULL, NULL },
+ { TERMINAL_ACTION_PASTE, action_paste, NULL, NULL, NULL },
+ { TERMINAL_ACTION_SELECT_ALL, action_select_all, NULL, NULL, NULL },
+ { TERMINAL_ACTION_KEYBINDINGS, action_keybindings, NULL, NULL, NULL },
+ { TERMINAL_ACTION_CURRENT_PROFILE, action_current_profile, NULL, NULL, NULL },
+ { TERMINAL_ACTION_ZOOM_IN, action_zoom_in, NULL, NULL, NULL },
+ { TERMINAL_ACTION_ZOOM_OUT, action_zoom_out, NULL, NULL, NULL },
+ { TERMINAL_ACTION_ZOOM_NORMAL, action_zoom_normal, NULL, NULL, NULL },
+ { TERMINAL_ACTION_FULLSCREEN, action_fullscreen, NULL, "false", NULL },
+ { TERMINAL_ACTION_MENUBAR, action_menubar, NULL, "true", NULL },
+ { TERMINAL_ACTION_FIND, action_find, NULL, NULL, NULL },
+ { TERMINAL_ACTION_FIND_NEXT, action_find_next, NULL, NULL, NULL },
+ { TERMINAL_ACTION_FIND_PREV, action_find_prev, NULL, NULL, NULL },
+ { TERMINAL_ACTION_SET_TITLE, action_set_title, NULL, NULL, NULL },
+ { TERMINAL_ACTION_RESET, action_reset, NULL, NULL, NULL },
+ { TERMINAL_ACTION_RESET_CLEAR, action_reset_clear, NULL, NULL, NULL },
+ { TERMINAL_ACTION_PREV_TAB, action_prev_tab, NULL, NULL, NULL },
+ { TERMINAL_ACTION_NEXT_TAB, action_next_tab, NULL, NULL, NULL },
+ { TERMINAL_ACTION_MOVE_TAB_LEFT, action_move_tab_left, NULL, NULL, NULL },
+ { TERMINAL_ACTION_MOVE_TAB_RIGHT, action_move_tab_right, NULL, NULL, NULL },
+ { TERMINAL_ACTION_DETACH_TAB, action_detach_tab, NULL, NULL, NULL },
+ { "about", action_about, NULL, NULL, NULL },
+};
+
+/*
+ * Public API
+ */
+
+void
+terminal_actions_init_app (GtkApplication *app)
+{
+ g_return_if_fail (GTK_IS_APPLICATION (app));
+
+ g_action_map_add_action_entries (G_ACTION_MAP (app),
+ app_actions,
+ G_N_ELEMENTS (app_actions),
+ app);
+}
+
+void
+terminal_actions_init_window (GtkApplicationWindow *window)
+{
+ g_return_if_fail (GTK_IS_APPLICATION_WINDOW (window));
+
+ g_action_map_add_action_entries (G_ACTION_MAP (window),
+ win_actions,
+ G_N_ELEMENTS (win_actions),
+ window);
+}
diff --git a/src/terminal-actions.h b/src/terminal-actions.h
new file mode 100644
index 0000000..05d0dba
--- /dev/null
+++ b/src/terminal-actions.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2012-2021 MATE Developers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef TERMINAL_ACTIONS_H
+#define TERMINAL_ACTIONS_H
+
+#include <gio/gio.h>
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+/* Initialize application-level actions */
+void terminal_actions_init_app (GtkApplication *app);
+
+/* Initialize window-level actions */
+void terminal_actions_init_window (GtkApplicationWindow *window);
+
+/* Action name definitions for accelerator binding */
+
+/* Application-level actions (prefix: app.) */
+#define TERMINAL_ACTION_QUIT "quit"
+#define TERMINAL_ACTION_NEW_WINDOW "new-window"
+#define TERMINAL_ACTION_PREFERENCES "preferences"
+#define TERMINAL_ACTION_HELP "help"
+#define TERMINAL_ACTION_ABOUT "about"
+
+/* Window-level actions (prefix: win.) */
+#define TERMINAL_ACTION_NEW_TAB "new-tab"
+#define TERMINAL_ACTION_NEW_PROFILE "new-profile"
+#define TERMINAL_ACTION_SAVE_CONTENTS "save-contents"
+#define TERMINAL_ACTION_CLOSE_TAB "close-tab"
+#define TERMINAL_ACTION_CLOSE_WINDOW "close-window"
+
+#define TERMINAL_ACTION_COPY "copy"
+#define TERMINAL_ACTION_PASTE "paste"
+#define TERMINAL_ACTION_PASTE_URIS "paste-uris"
+#define TERMINAL_ACTION_SELECT_ALL "select-all"
+#define TERMINAL_ACTION_PROFILES "profiles"
+#define TERMINAL_ACTION_KEYBINDINGS "keybindings"
+#define TERMINAL_ACTION_CURRENT_PROFILE "current-profile"
+
+#define TERMINAL_ACTION_ZOOM_IN "zoom-in"
+#define TERMINAL_ACTION_ZOOM_OUT "zoom-out"
+#define TERMINAL_ACTION_ZOOM_NORMAL "zoom-normal"
+#define TERMINAL_ACTION_FULLSCREEN "fullscreen"
+#define TERMINAL_ACTION_MENUBAR "menubar"
+
+#define TERMINAL_ACTION_FIND "find"
+#define TERMINAL_ACTION_FIND_NEXT "find-next"
+#define TERMINAL_ACTION_FIND_PREV "find-prev"
+#define TERMINAL_ACTION_FIND_CLEAR "find-clear"
+
+#define TERMINAL_ACTION_SET_TITLE "set-title"
+#define TERMINAL_ACTION_RESET "reset"
+#define TERMINAL_ACTION_RESET_CLEAR "reset-clear"
+#define TERMINAL_ACTION_ADD_ENCODING "add-encoding"
+
+#define TERMINAL_ACTION_PREV_TAB "prev-tab"
+#define TERMINAL_ACTION_NEXT_TAB "next-tab"
+#define TERMINAL_ACTION_MOVE_TAB_LEFT "move-tab-left"
+#define TERMINAL_ACTION_MOVE_TAB_RIGHT "move-tab-right"
+#define TERMINAL_ACTION_DETACH_TAB "detach-tab"
+
+#define TERMINAL_ACTION_PREV_PROFILE "prev-profile"
+#define TERMINAL_ACTION_NEXT_PROFILE "next-profile"
+
+G_END_DECLS
+
+#endif /* TERMINAL_ACTIONS_H */
diff --git a/src/terminal-app.c b/src/terminal-app.c
index 831f42f..58e71bc 100644
--- a/src/terminal-app.c
+++ b/src/terminal-app.c
@@ -32,6 +32,7 @@
#include "terminal-debug.h"
#include "terminal-app.h"
#include "terminal-accels.h"
+#include "terminal-actions.h"
#include "terminal-screen.h"
#include "terminal-screen-container.h"
#include "terminal-window.h"
@@ -70,22 +71,18 @@
*
*/
-GSettings *settings_global;
-
struct _TerminalAppClass
{
- GObjectClass parent_class;
+ GtkApplicationClass parent_class;
- void (* quit) (TerminalApp *app);
void (* profile_list_changed) (TerminalApp *app);
void (* encoding_list_changed) (TerminalApp *app);
};
struct _TerminalApp
{
- GObject parent_instance;
+ GtkApplication parent_instance;
- GList *windows;
GtkWidget *new_profile_dialog;
GtkWidget *manage_profiles_dialog;
GtkWidget *manage_profiles_list;
@@ -94,6 +91,7 @@ struct _TerminalApp
GtkWidget *manage_profiles_delete_button;
GtkWidget *manage_profiles_default_menu;
+ GSettings *settings_global;
GSettings *settings_font;
GHashTable *profiles;
@@ -120,7 +118,6 @@ enum
enum
{
- QUIT,
PROFILE_LIST_CHANGED,
ENCODING_LIST_CHANGED,
LAST_SIGNAL
@@ -140,8 +137,6 @@ enum
SOURCE_SESSION = 1
};
-static TerminalApp *global_app = NULL;
-
#define MONOSPACE_FONT_SCHEMA "org.mate.interface"
#define MONOSPACE_FONT_KEY "monospace-font-name"
#define DEFAULT_MONOSPACE_FONT ("Monospace 10")
@@ -157,6 +152,9 @@ static TerminalApp *global_app = NULL;
#define ENCODING_LIST_KEY "active-encodings"
+/* Define the type - inherits from GtkApplication */
+G_DEFINE_TYPE (TerminalApp, terminal_app, GTK_TYPE_APPLICATION)
+
/* two following functions were copied from libmate-desktop to get rid
* of dependency on it
*
@@ -323,16 +321,6 @@ profiles_lookup_by_visible_name_foreach (gpointer key,
info->result = value;
}
-static void
-terminal_window_destroyed (TerminalWindow *window,
- TerminalApp *app)
-{
- app->windows = g_list_remove (app->windows, window);
-
- if (app->windows == NULL)
- g_signal_emit (app, signals[QUIT], 0);
-}
-
static TerminalProfile *
terminal_app_create_profile (TerminalApp *app,
const char *name)
@@ -361,7 +349,7 @@ terminal_app_create_profile (TerminalApp *app,
}
static void
-terminal_app_delete_profile (TerminalProfile *profile)
+terminal_app_delete_profile (TerminalApp *app, TerminalProfile *profile)
{
const char *profile_name;
char *profile_dir;
@@ -370,7 +358,7 @@ terminal_app_delete_profile (TerminalProfile *profile)
profile_name = terminal_profile_get_property_string (profile, TERMINAL_PROFILE_NAME);
profile_dir = g_strconcat (CONF_PROFILE_PREFIX, profile_name, "/", NULL);
- gsettings_remove_all_from_strv (settings_global, PROFILE_LIST_KEY, profile_name);
+ gsettings_remove_all_from_strv (app->settings_global, PROFILE_LIST_KEY, profile_name);
/* And remove the profile directory */
DConfClient *client = dconf_client_new ();
@@ -548,7 +536,7 @@ profile_combo_box_changed_cb (GtkWidget *widget,
if (!profile)
return;
- g_settings_set_string (settings_global, DEFAULT_PROFILE_KEY,
+ g_settings_set_string (app->settings_global, DEFAULT_PROFILE_KEY,
terminal_profile_get_property_string (profile, TERMINAL_PROFILE_NAME));
/* Even though the GSettings change notification does this, it happens too late.
@@ -629,12 +617,16 @@ profile_list_delete_confirm_response_cb (GtkWidget *dialog,
int response)
{
TerminalProfile *profile;
+ TerminalApp *app;
profile = TERMINAL_PROFILE (g_object_get_data (G_OBJECT (dialog), "profile"));
g_assert (profile != NULL);
if (response == GTK_RESPONSE_ACCEPT)
- terminal_app_delete_profile (profile);
+ {
+ app = terminal_app_get ();
+ terminal_app_delete_profile (app, profile);
+ }
gtk_widget_destroy (dialog);
}
@@ -682,7 +674,7 @@ profile_list_delete_button_clicked_cb (GtkWidget *button,
GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_MESSAGE_QUESTION,
GTK_BUTTONS_NONE,
- _("Delete profile ā€œ%sā€?"),
+ _("Delete profile \"%s\"?"),
terminal_profile_get_property_string (selected_profile, TERMINAL_PROFILE_VISIBLE_NAME));
mate_dialog_add_button (GTK_DIALOG (dialog),
@@ -1145,7 +1137,7 @@ new_profile_response_cb (GtkWidget *new_profile_dialog,
GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_MESSAGE_QUESTION,
GTK_BUTTONS_YES_NO,
- _("You already have a profile called ā€œ%sā€. Do you want to create another profile with the same name?"), name);
+ _("You already have a profile called \"%s\". Do you want to create another profile with the same name?"), name);
/* Alternative button order was set automatically by GtkMessageDialog */
retval = gtk_dialog_run (GTK_DIALOG (confirm_dialog));
gtk_widget_destroy (confirm_dialog);
@@ -1163,7 +1155,7 @@ new_profile_response_cb (GtkWidget *new_profile_dialog,
new_profile /* adopts the refcount */);
/* And now save the new profile name to GSettings */
- gsettings_append_strv (settings_global,
+ gsettings_append_strv (app->settings_global,
PROFILE_LIST_KEY,
new_profile_name);
@@ -1389,18 +1381,19 @@ static void
terminal_app_client_quit_cb (EggSMClient *client,
TerminalApp *app)
{
- g_signal_emit (app, signals[QUIT], 0);
+ g_application_quit (G_APPLICATION (app));
}
#endif /* HAVE_SMCLIENT */
-/* Class implementation */
-
-G_DEFINE_TYPE (TerminalApp, terminal_app, G_TYPE_OBJECT)
+/* GtkApplication vfuncs */
static void
-terminal_app_init (TerminalApp *app)
+terminal_app_startup (GApplication *application)
{
- global_app = app;
+ TerminalApp *app = TERMINAL_APP (application);
+
+ /* Chain up */
+ G_APPLICATION_CLASS (terminal_app_parent_class)->startup (application);
gtk_window_set_default_icon_name (MATE_TERMINAL_ICON_NAME);
@@ -1412,20 +1405,20 @@ terminal_app_init (TerminalApp *app)
app->encodings = terminal_encodings_get_builtins ();
- settings_global = g_settings_new (CONF_GLOBAL_SCHEMA);
+ app->settings_global = g_settings_new (CONF_GLOBAL_SCHEMA);
app->settings_font = g_settings_new (MONOSPACE_FONT_SCHEMA);
- g_signal_connect (settings_global,
+ g_signal_connect (app->settings_global,
"changed::" PROFILE_LIST_KEY,
G_CALLBACK(terminal_app_profile_list_notify_cb),
app);
- g_signal_connect (settings_global,
+ g_signal_connect (app->settings_global,
"changed::" DEFAULT_PROFILE_KEY,
G_CALLBACK(terminal_app_default_profile_notify_cb),
app);
- g_signal_connect (settings_global,
+ g_signal_connect (app->settings_global,
"changed::" ENCODING_LIST_KEY,
G_CALLBACK(terminal_app_encoding_list_notify_cb),
app);
@@ -1435,33 +1428,33 @@ terminal_app_init (TerminalApp *app)
G_CALLBACK(terminal_app_system_font_notify_cb),
app);
- g_signal_connect (settings_global,
+ g_signal_connect (app->settings_global,
"changed::" ENABLE_MNEMONICS_KEY,
G_CALLBACK(terminal_app_enable_mnemonics_notify_cb),
app);
- g_signal_connect (settings_global,
+ g_signal_connect (app->settings_global,
"changed::" ENABLE_MENU_BAR_ACCEL_KEY,
G_CALLBACK(terminal_app_enable_menu_accels_notify_cb),
app);
/* Load the settings */
- terminal_app_profile_list_notify_cb (settings_global,
+ terminal_app_profile_list_notify_cb (app->settings_global,
PROFILE_LIST_KEY,
app);
- terminal_app_default_profile_notify_cb (settings_global,
+ terminal_app_default_profile_notify_cb (app->settings_global,
DEFAULT_PROFILE_KEY,
app);
- terminal_app_encoding_list_notify_cb (settings_global,
+ terminal_app_encoding_list_notify_cb (app->settings_global,
ENCODING_LIST_KEY,
app);
terminal_app_system_font_notify_cb (app->settings_font,
MONOSPACE_FONT_KEY,
app);
- terminal_app_enable_menu_accels_notify_cb (settings_global,
+ terminal_app_enable_menu_accels_notify_cb (app->settings_global,
ENABLE_MENU_BAR_ACCEL_KEY,
app);
- terminal_app_enable_mnemonics_notify_cb (settings_global,
+ terminal_app_enable_mnemonics_notify_cb (app->settings_global,
ENABLE_MNEMONICS_KEY,
app);
@@ -1471,73 +1464,182 @@ terminal_app_init (TerminalApp *app)
terminal_accels_init ();
-#ifdef HAVE_SMCLIENT
- EggSMClient *sm_client;
- char *desktop_file;
+ /* Initialize application-level GActions */
+ terminal_actions_init_app (GTK_APPLICATION (app));
- desktop_file = g_build_filename (TERM_DATADIR,
- "applications",
- PACKAGE ".desktop",
- NULL);
- egg_set_desktop_file_without_defaults (desktop_file);
- g_free (desktop_file);
+ /* Set up accelerators for GActions */
+ terminal_accels_set_gaction_accels (GTK_APPLICATION (app));
- sm_client = egg_sm_client_get ();
- g_signal_connect (sm_client, "save-state",
- G_CALLBACK (terminal_app_save_state_cb), app);
- g_signal_connect (sm_client, "quit",
- G_CALLBACK (terminal_app_client_quit_cb), app);
+#ifdef HAVE_SMCLIENT
+ {
+ EggSMClient *sm_client;
+ char *desktop_file;
+
+ desktop_file = g_build_filename (TERM_DATADIR,
+ "applications",
+ PACKAGE ".desktop",
+ NULL);
+ egg_set_desktop_file_without_defaults (desktop_file);
+ g_free (desktop_file);
+
+ sm_client = egg_sm_client_get ();
+ g_signal_connect (sm_client, "save-state",
+ G_CALLBACK (terminal_app_save_state_cb), app);
+ g_signal_connect (sm_client, "quit",
+ G_CALLBACK (terminal_app_client_quit_cb), app);
+ }
#endif /* HAVE_SMCLIENT */
}
static void
-terminal_app_finalize (GObject *object)
+terminal_app_activate (GApplication *application)
{
- TerminalApp *app = TERMINAL_APP (object);
+ TerminalApp *app = TERMINAL_APP (application);
+ GList *windows;
+
+ /* If we have windows, just present the first one */
+ windows = gtk_application_get_windows (GTK_APPLICATION (app));
+ if (windows != NULL)
+ {
+ gtk_window_present (GTK_WINDOW (windows->data));
+ return;
+ }
+
+ /* Otherwise create a new window with default profile */
+ TerminalWindow *window;
+ TerminalProfile *profile;
+
+ window = terminal_app_new_window (app, gdk_screen_get_default ());
+ profile = terminal_app_get_profile_for_new_term (app);
+
+ terminal_app_new_terminal (app, window, profile,
+ NULL, NULL, NULL, NULL, 1.0);
+
+ gtk_window_present (GTK_WINDOW (window));
+}
+
+static int
+terminal_app_command_line (GApplication *application,
+ GApplicationCommandLine *command_line)
+{
+ TerminalApp *app = TERMINAL_APP (application);
+ TerminalOptions *options = NULL;
+ GError *error = NULL;
+ int argc;
+ char **argv;
+ const char *working_directory;
+ const char *startup_id;
+ gboolean allow_resume;
+
+ argv = g_application_command_line_get_arguments (command_line, &argc);
+ working_directory = g_application_command_line_get_cwd (command_line);
+ startup_id = g_application_command_line_getenv (command_line, "DESKTOP_STARTUP_ID");
+
+ /* Determine if we're resuming from session */
+ allow_resume = g_application_command_line_get_is_remote (command_line) == FALSE;
+
+ options = terminal_options_parse (working_directory,
+ NULL, /* display_name - get from environment */
+ startup_id,
+ NULL, /* envv - we get it from command line */
+ TRUE, /* remote args */
+ TRUE, /* do_not_use_factory */
+ &argc, &argv,
+ &error,
+ NULL);
+
+ if (options == NULL)
+ {
+ g_application_command_line_printerr (command_line,
+ _("Failed to parse arguments: %s\n"),
+ error->message);
+ g_error_free (error);
+ g_strfreev (argv);
+ return EXIT_FAILURE;
+ }
+
+ if (!terminal_app_handle_options (app, options, allow_resume, &error))
+ {
+ g_application_command_line_printerr (command_line,
+ "Error handling options: %s\n",
+ error->message);
+ g_error_free (error);
+ terminal_options_free (options);
+ g_strfreev (argv);
+ return EXIT_FAILURE;
+ }
+
+ terminal_options_free (options);
+ g_strfreev (argv);
+
+ return EXIT_SUCCESS;
+}
+
+static void
+terminal_app_shutdown (GApplication *application)
+{
+ TerminalApp *app = TERMINAL_APP (application);
#ifdef HAVE_SMCLIENT
- EggSMClient *sm_client;
+ {
+ EggSMClient *sm_client;
- sm_client = egg_sm_client_get ();
- g_signal_handlers_disconnect_matched (sm_client, G_SIGNAL_MATCH_DATA,
- 0, 0, NULL, NULL, app);
+ sm_client = egg_sm_client_get ();
+ g_signal_handlers_disconnect_matched (sm_client, G_SIGNAL_MATCH_DATA,
+ 0, 0, NULL, NULL, app);
+ }
#endif /* HAVE_SMCLIENT */
- g_signal_handlers_disconnect_by_func (settings_global,
+ g_signal_handlers_disconnect_by_func (app->settings_global,
G_CALLBACK(terminal_app_profile_list_notify_cb),
app);
- g_signal_handlers_disconnect_by_func (settings_global,
+ g_signal_handlers_disconnect_by_func (app->settings_global,
G_CALLBACK(terminal_app_default_profile_notify_cb),
app);
- g_signal_handlers_disconnect_by_func (settings_global,
+ g_signal_handlers_disconnect_by_func (app->settings_global,
G_CALLBACK(terminal_app_encoding_list_notify_cb),
app);
g_signal_handlers_disconnect_by_func (app->settings_font,
G_CALLBACK(terminal_app_system_font_notify_cb),
app);
- g_signal_handlers_disconnect_by_func (settings_global,
+ g_signal_handlers_disconnect_by_func (app->settings_global,
G_CALLBACK(terminal_app_enable_menu_accels_notify_cb),
app);
- g_signal_handlers_disconnect_by_func (settings_global,
+ g_signal_handlers_disconnect_by_func (app->settings_global,
G_CALLBACK(terminal_app_enable_mnemonics_notify_cb),
app);
- g_object_unref (settings_global);
- g_object_unref (app->settings_font);
+ g_clear_object (&app->settings_global);
+ g_clear_object (&app->settings_font);
g_free (app->default_profile_id);
+ app->default_profile_id = NULL;
g_hash_table_destroy (app->profiles);
+ app->profiles = NULL;
g_hash_table_destroy (app->encodings);
+ app->encodings = NULL;
- pango_font_description_free (app->system_font_desc);
+ if (app->system_font_desc)
+ {
+ pango_font_description_free (app->system_font_desc);
+ app->system_font_desc = NULL;
+ }
terminal_accels_shutdown ();
- G_OBJECT_CLASS (terminal_app_parent_class)->finalize (object);
+ /* Chain up */
+ G_APPLICATION_CLASS (terminal_app_parent_class)->shutdown (application);
+}
+
+/* GObject vfuncs */
- global_app = NULL;
+static void
+terminal_app_finalize (GObject *object)
+{
+ /* Most cleanup is done in shutdown */
+ G_OBJECT_CLASS (terminal_app_parent_class)->finalize (object);
}
static void
@@ -1583,11 +1685,11 @@ terminal_app_set_property (GObject *object,
{
case PROP_ENABLE_MENU_BAR_ACCEL:
app->enable_menu_accels = g_value_get_boolean (value);
- g_settings_set_boolean (settings_global, ENABLE_MENU_BAR_ACCEL_KEY, app->enable_menu_accels);
+ g_settings_set_boolean (app->settings_global, ENABLE_MENU_BAR_ACCEL_KEY, app->enable_menu_accels);
break;
case PROP_ENABLE_MNEMONICS:
app->enable_mnemonics = g_value_get_boolean (value);
- g_settings_set_boolean (settings_global, ENABLE_MNEMONICS_KEY, app->enable_mnemonics);
+ g_settings_set_boolean (app->settings_global, ENABLE_MNEMONICS_KEY, app->enable_mnemonics);
break;
case PROP_DEFAULT_PROFILE:
case PROP_SYSTEM_FONT:
@@ -1599,30 +1701,19 @@ terminal_app_set_property (GObject *object,
}
static void
-terminal_app_real_quit (TerminalApp *app)
-{
- gtk_main_quit();
-}
-
-static void
terminal_app_class_init (TerminalAppClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GApplicationClass *application_class = G_APPLICATION_CLASS (klass);
object_class->finalize = terminal_app_finalize;
object_class->get_property = terminal_app_get_property;
object_class->set_property = terminal_app_set_property;
- klass->quit = terminal_app_real_quit;
-
- signals[QUIT] =
- g_signal_new (I_("quit"),
- G_OBJECT_CLASS_TYPE (object_class),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (TerminalAppClass, quit),
- NULL, NULL,
- g_cclosure_marshal_VOID__VOID,
- G_TYPE_NONE, 0);
+ application_class->startup = terminal_app_startup;
+ application_class->activate = terminal_app_activate;
+ application_class->command_line = terminal_app_command_line;
+ application_class->shutdown = terminal_app_shutdown;
signals[PROFILE_LIST_CHANGED] =
g_signal_new (I_("profile-list-changed"),
@@ -1671,28 +1762,32 @@ terminal_app_class_init (TerminalAppClass *klass)
G_PARAM_READABLE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
}
+static void
+terminal_app_init (TerminalApp *app)
+{
+ /* Initialization is done in startup vfunc */
+}
+
/* Public API */
TerminalApp*
terminal_app_get (void)
{
- if (global_app == NULL)
- {
- g_object_new (TERMINAL_TYPE_APP, NULL);
- g_assert (global_app != NULL);
- }
+ GApplication *app;
- return global_app;
+ app = g_application_get_default ();
+ if (app != NULL && TERMINAL_IS_APP (app))
+ return TERMINAL_APP (app);
+
+ return NULL;
}
-void
-terminal_app_shutdown (void)
+GSettings*
+terminal_app_get_global_settings (TerminalApp *app)
{
- if (global_app == NULL)
- return;
+ g_return_val_if_fail (TERMINAL_IS_APP (app), NULL);
- g_object_unref (global_app);
- g_assert (global_app == NULL);
+ return app->settings_global;
}
/**
@@ -1881,9 +1976,7 @@ terminal_app_new_window (TerminalApp *app,
window = terminal_window_new ();
- app->windows = g_list_append (app->windows, window);
- g_signal_connect (window, "destroy",
- G_CALLBACK (terminal_window_destroyed), app);
+ gtk_application_add_window (GTK_APPLICATION (app), GTK_WINDOW (window));
if (screen)
gtk_window_set_screen (GTK_WINDOW (window), screen);
@@ -1948,23 +2041,35 @@ terminal_app_get_current_window (TerminalApp *app,
GdkScreen *from_screen,
int workspace)
{
- GList *res = NULL;
+ GList *windows;
+ GList *res;
TerminalWindow *ret = NULL;
- if (app->windows == NULL)
- return NULL;
+ windows = gtk_application_get_windows (GTK_APPLICATION (app));
+ if (windows == NULL)
+ return NULL;
- res = g_list_last (app->windows);
+ res = g_list_last (windows);
g_assert (from_screen != NULL);
while (res)
{
int win_workspace;
+
+ if (!TERMINAL_IS_WINDOW (res->data))
+ {
+ res = g_list_previous (res);
+ continue;
+ }
+
if (gtk_window_get_screen(GTK_WINDOW(res->data)) != from_screen)
- continue;
+ {
+ res = g_list_previous (res);
+ continue;
+ }
- win_workspace = terminal_app_get_workspace_for_window(res->data);
+ win_workspace = terminal_app_get_workspace_for_window(TERMINAL_WINDOW(res->data));
/* Same workspace or if the window is set to show up on all workspaces */
if (win_workspace == workspace || win_workspace == -1)
@@ -2060,7 +2165,7 @@ terminal_app_get_encodings (TerminalApp *app)
*
* Ensures there's a #TerminalEncoding for @charset available.
*/
-TerminalEncoding *
+ TerminalEncoding *
terminal_app_ensure_encoding (TerminalApp *app,
const char *charset)
{
@@ -2111,6 +2216,7 @@ void
terminal_app_save_config (TerminalApp *app,
GKeyFile *key_file)
{
+ GList *windows;
GList *lw;
guint n = 0;
GPtrArray *window_names_array;
@@ -2122,13 +2228,18 @@ terminal_app_save_config (TerminalApp *app,
g_key_file_set_integer (key_file, TERMINAL_CONFIG_GROUP, TERMINAL_CONFIG_PROP_VERSION, TERMINAL_CONFIG_VERSION);
g_key_file_set_integer (key_file, TERMINAL_CONFIG_GROUP, TERMINAL_CONFIG_PROP_COMPAT_VERSION, TERMINAL_CONFIG_COMPAT_VERSION);
- window_names_array = g_ptr_array_sized_new (g_list_length (app->windows) + 1);
+ windows = gtk_application_get_windows (GTK_APPLICATION (app));
+ window_names_array = g_ptr_array_sized_new (g_list_length (windows) + 1);
- for (lw = app->windows; lw != NULL; lw = lw->next)
+ for (lw = windows; lw != NULL; lw = lw->next)
{
- TerminalWindow *window = TERMINAL_WINDOW (lw->data);
+ TerminalWindow *window;
char *group;
+ if (!TERMINAL_IS_WINDOW (lw->data))
+ continue;
+
+ window = TERMINAL_WINDOW (lw->data);
group = g_strdup_printf ("Window%u", n++);
g_ptr_array_add (window_names_array, group);
diff --git a/src/terminal-app.h b/src/terminal-app.h
index ebb78c1..98b15fa 100644
--- a/src/terminal-app.h
+++ b/src/terminal-app.h
@@ -73,7 +73,10 @@ G_BEGIN_DECLS
#define TERMINAL_APP_ENABLE_MNEMONICS "enable-mnemonics"
#define TERMINAL_APP_SYSTEM_FONT "system-font"
-/* TerminalApp */
+/* Application ID for GtkApplication */
+#define TERMINAL_APPLICATION_ID "org.mate.Terminal"
+
+/* TerminalApp - now inherits from GtkApplication */
#define TERMINAL_TYPE_APP (terminal_app_get_type ())
#define TERMINAL_APP(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), TERMINAL_TYPE_APP, TerminalApp))
@@ -84,14 +87,15 @@ G_BEGIN_DECLS
typedef struct _TerminalAppClass TerminalAppClass;
typedef struct _TerminalApp TerminalApp;
-
-extern GSettings *settings_global;
+typedef struct _TerminalAppPrivate TerminalAppPrivate;
GType terminal_app_get_type (void);
+/* Get the application instance - now uses g_application_get_default() internally */
TerminalApp* terminal_app_get (void);
-void terminal_app_shutdown (void);
+/* Get GSettings for global settings */
+GSettings* terminal_app_get_global_settings (TerminalApp *app);
gboolean terminal_app_handle_options (TerminalApp *app,
TerminalOptions *options,
diff --git a/src/terminal-encoding.c b/src/terminal-encoding.c
index a470c99..c132985 100644
--- a/src/terminal-encoding.c
+++ b/src/terminal-encoding.c
@@ -302,7 +302,7 @@ update_active_encodings_gsettings (void)
strings = g_array_append_val (strings, id_string);
}
- g_settings_set_strv (settings_global, "active-encodings", (const gchar **) strings->data);
+ g_settings_set_strv (terminal_app_get_global_settings (terminal_app_get ()), "active-encodings", (const gchar **) strings->data);
g_array_free (strings, TRUE);
g_slist_foreach (list, (GFunc) terminal_encoding_unref, NULL);
diff --git a/src/terminal-window.c b/src/terminal-window.c
index 75e5fd8..12fe9de 100644
--- a/src/terminal-window.c
+++ b/src/terminal-window.c
@@ -30,6 +30,7 @@
#include <gdk/gdkkeysyms.h>
#include "terminal-accels.h"
+#include "terminal-actions.h"
#include "terminal-app.h"
#include "terminal-debug.h"
#include "terminal-encoding.h"
@@ -45,8 +46,6 @@
#include "skey-popup.h"
#endif
-static gboolean detach_tab = FALSE;
-
struct _TerminalWindowPrivate
{
GtkActionGroup *action_group;
@@ -162,10 +161,10 @@ static gboolean terminal_window_focus_in_event (GtkWidget *widget,
static gboolean notebook_button_press_cb (GtkWidget *notebook,
GdkEventButton *event,
- GSettings *settings);
+ gpointer user_data);
static gboolean window_key_press_cb (GtkWidget *notebook,
GdkEventKey *event,
- GSettings *settings);
+ gpointer user_data);
static gboolean notebook_popup_menu_cb (GtkWidget *notebook,
TerminalWindow *window);
static void notebook_page_selected_callback (GtkWidget *notebook,
@@ -269,7 +268,7 @@ sync_screen_icon_title (TerminalScreen *screen,
GParamSpec *psepc,
TerminalWindow *window);
-G_DEFINE_TYPE_WITH_PRIVATE (TerminalWindow, terminal_window, GTK_TYPE_WINDOW)
+G_DEFINE_TYPE_WITH_PRIVATE (TerminalWindow, terminal_window, GTK_TYPE_APPLICATION_WINDOW)
/* Menubar mnemonics & accel settings handling */
@@ -2260,6 +2259,9 @@ terminal_window_init (TerminalWindow *window)
priv = window->priv = terminal_window_get_instance_private (window);
+ /* Initialize GAction for this window */
+ terminal_actions_init_window (GTK_APPLICATION_WINDOW (window));
+
g_signal_connect (G_OBJECT (window), "delete_event",
G_CALLBACK(terminal_window_delete_event),
NULL);
@@ -2294,9 +2296,9 @@ terminal_window_init (TerminalWindow *window)
gtk_notebook_set_show_tabs (GTK_NOTEBOOK (priv->notebook), FALSE);
gtk_notebook_set_group_name (GTK_NOTEBOOK (priv->notebook), I_("mate-terminal-window"));
g_signal_connect (priv->notebook, "button-press-event",
- G_CALLBACK (notebook_button_press_cb), settings_global);
+ G_CALLBACK (notebook_button_press_cb), NULL);
g_signal_connect (window, "key-press-event",
- G_CALLBACK (window_key_press_cb), settings_global);
+ G_CALLBACK (window_key_press_cb), NULL);
g_signal_connect (priv->notebook, "popup-menu",
G_CALLBACK (notebook_popup_menu_cb), window);
g_signal_connect_after (priv->notebook, "switch-page",
@@ -2727,9 +2729,10 @@ terminal_window_add_screen (TerminalWindow *window,
TRUE);
}
-void
-terminal_window_remove_screen (TerminalWindow *window,
- TerminalScreen *screen)
+static void
+remove_screen_internal (TerminalWindow *window,
+ TerminalScreen *screen,
+ gboolean detach)
{
TerminalWindowPrivate *priv = window->priv;
TerminalScreenContainer *screen_container;
@@ -2739,18 +2742,22 @@ terminal_window_remove_screen (TerminalWindow *window,
update_tab_visibility (window, -1);
screen_container = terminal_screen_container_get_from_screen (screen);
- if (detach_tab)
- {
+ if (detach)
gtk_notebook_detach_tab (GTK_NOTEBOOK (priv->notebook),
GTK_WIDGET (screen_container));
- detach_tab = FALSE;
- }
else
gtk_container_remove (GTK_CONTAINER (priv->notebook),
GTK_WIDGET (screen_container));
}
void
+terminal_window_remove_screen (TerminalWindow *window,
+ TerminalScreen *screen)
+{
+ remove_screen_internal (window, screen, FALSE);
+}
+
+void
terminal_window_move_screen (TerminalWindow *source_window,
TerminalWindow *dest_window,
TerminalScreen *screen,
@@ -2775,9 +2782,7 @@ terminal_window_move_screen (TerminalWindow *source_window,
g_object_ref_sink (screen_container);
g_object_ref_sink (screen);
- detach_tab = TRUE;
-
- terminal_window_remove_screen (source_window, screen);
+ remove_screen_internal (source_window, screen, TRUE);
/* Now we can safely remove the screen from the container and let the container die */
gtk_container_remove (GTK_CONTAINER (gtk_widget_get_parent (GTK_WIDGET (screen))), GTK_WIDGET (screen));
@@ -3034,11 +3039,12 @@ terminal_window_get_active (TerminalWindow *window)
static gboolean
notebook_button_press_cb (GtkWidget *widget,
GdkEventButton *event,
- GSettings *settings)
+ gpointer user_data)
{
TerminalWindow *window = TERMINAL_WINDOW (gtk_widget_get_toplevel (widget));
TerminalWindowPrivate *priv = window->priv;
GtkNotebook *notebook = GTK_NOTEBOOK (widget);
+ GSettings *settings = terminal_app_get_global_settings (terminal_app_get ());
GtkWidget *tab;
GtkWidget *menu;
GtkAction *action;
@@ -3122,8 +3128,9 @@ notebook_button_press_cb (GtkWidget *widget,
static gboolean
window_key_press_cb (GtkWidget *widget,
GdkEventKey *event,
- GSettings *settings)
+ gpointer user_data)
{
+ GSettings *settings = terminal_app_get_global_settings (terminal_app_get ());
if (g_settings_get_boolean (settings, "ctrl-tab-switch-tabs") &&
event->state & GDK_CONTROL_MASK)
{
@@ -3732,7 +3739,7 @@ confirm_close_window_or_tab (TerminalWindow *window,
int n_tabs;
char *confirm_msg;
- if (!g_settings_get_boolean (settings_global, "confirm-window-close"))
+ if (!g_settings_get_boolean (terminal_app_get_global_settings (terminal_app_get ()), "confirm-window-close"))
return FALSE;
if (screen)
@@ -4622,6 +4629,45 @@ terminal_window_get_ui_manager (TerminalWindow *window)
return priv->ui_manager;
}
+/* Public wrapper functions for GAction callbacks */
+
+void
+terminal_window_show_find_dialog (TerminalWindow *window)
+{
+ g_return_if_fail (TERMINAL_IS_WINDOW (window));
+ search_find_callback (NULL, window);
+}
+
+void
+terminal_window_show_set_title_dialog (TerminalWindow *window)
+{
+ g_return_if_fail (TERMINAL_IS_WINDOW (window));
+ terminal_set_title_callback (NULL, window);
+}
+
+void
+terminal_window_detach_screen (TerminalWindow *window, TerminalScreen *screen)
+{
+ g_return_if_fail (TERMINAL_IS_WINDOW (window));
+ g_return_if_fail (TERMINAL_IS_SCREEN (screen));
+ tabs_detach_tab_callback (NULL, window);
+}
+
+void
+terminal_window_show_about_dialog (GtkWindow *parent)
+{
+ if (parent && TERMINAL_IS_WINDOW (parent))
+ help_about_callback (NULL, TERMINAL_WINDOW (parent));
+ else
+ {
+ /* Create a temporary window for the about dialog */
+ GtkApplication *app = GTK_APPLICATION (g_application_get_default ());
+ GList *windows = gtk_application_get_windows (app);
+ if (windows)
+ help_about_callback (NULL, TERMINAL_WINDOW (windows->data));
+ }
+}
+
void
terminal_window_save_state (TerminalWindow *window,
GKeyFile *key_file,
diff --git a/src/terminal-window.h b/src/terminal-window.h
index 86b8e28..659f2ee 100644
--- a/src/terminal-window.h
+++ b/src/terminal-window.h
@@ -39,14 +39,14 @@ typedef struct _TerminalWindowPrivate TerminalWindowPrivate;
struct _TerminalWindow
{
- GtkWindow parent_instance;
+ GtkApplicationWindow parent_instance;
TerminalWindowPrivate *priv;
};
struct _TerminalWindowClass
{
- GtkWindowClass parent_class;
+ GtkApplicationWindowClass parent_class;
};
@@ -110,6 +110,12 @@ terminal_window_update_copy_selection (TerminalScreen *screen,
TerminalWindow *terminal_window_get_latest_focused (TerminalWindow *window1,
TerminalWindow *window2);
+/* Public functions for GAction callbacks */
+void terminal_window_show_find_dialog (TerminalWindow *window);
+void terminal_window_show_set_title_dialog (TerminalWindow *window);
+void terminal_window_detach_screen (TerminalWindow *window, TerminalScreen *screen);
+void terminal_window_show_about_dialog (GtkWindow *parent);
+
G_END_DECLS
#endif /* TERMINAL_WINDOW_H */
diff --git a/src/terminal.c b/src/terminal.c
index 7909fdf..c9a044b 100644
--- a/src/terminal.c
+++ b/src/terminal.c
@@ -38,431 +38,15 @@
#include "eggsmclient.h"
#endif /* HAVE_SMCLIENT */
-#include "terminal-accels.h"
#include "terminal-app.h"
#include "terminal-debug.h"
#include "terminal-intl.h"
-#include "terminal-options.h"
-#include "terminal-util.h"
-
-#define TERMINAL_FACTORY_SERVICE_NAME_PREFIX "org.mate.Terminal.Display"
-#define TERMINAL_FACTORY_SERVICE_PATH "/org/mate/Terminal/Factory"
-#define TERMINAL_FACTORY_INTERFACE_NAME "org.mate.Terminal.Factory"
-
-static char *
-ay_to_string (GVariant *variant,
- GError **error)
-{
- gsize len;
- const char *data;
-
- data = g_variant_get_fixed_array (variant, &len, sizeof (char));
- if (len == 0)
- return NULL;
-
- /* Make sure there are no embedded NULs */
- if (memchr (data, '\0', len) != NULL)
- {
- g_set_error_literal (error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
- "String is shorter than claimed");
- return NULL;
- }
-
- return g_strndup (data, len);
-}
-
-static char **
-ay_to_strv (GVariant *variant,
- int *argc)
-{
- GPtrArray *argv;
- const char *data, *nullbyte;
- gsize data_len;
- gssize len;
-
- data = g_variant_get_fixed_array (variant, &data_len, sizeof (char));
- if (data_len == 0 || data_len > G_MAXSSIZE)
- {
- if (argc != NULL)
- *argc = 0;
- return NULL;
- }
-
- argv = g_ptr_array_new ();
-
- len = data_len;
- do
- {
- gssize string_len;
-
- nullbyte = memchr (data, '\0', len);
-
- string_len = nullbyte ? (gssize) (nullbyte - data) : len;
- g_ptr_array_add (argv, g_strndup (data, string_len));
-
- len -= string_len + 1;
- data += string_len + 1;
- }
- while (len > 0);
-
- if (argc)
- *argc = argv->len;
-
- /* NULL terminate */
- g_ptr_array_add (argv, NULL);
- return (char **) g_ptr_array_free (argv, FALSE);
-}
-
-static GVariant *
-string_to_ay (const char *string)
-{
- gsize len;
- char *data;
-
- len = strlen (string);
- data = g_strndup (string, len);
-
- return g_variant_new_from_data (G_VARIANT_TYPE ("ay"), data, len, TRUE, g_free, data);
-}
-
-typedef struct
-{
- char *factory_name;
- TerminalOptions *options;
- int exit_code;
- char **argv;
- int argc;
-} OwnData;
-
-static void
-method_call_cb (GDBusConnection *connection,
- const char *sender,
- const char *object_path,
- const char *interface_name,
- const char *method_name,
- GVariant *parameters,
- GDBusMethodInvocation *invocation,
- gpointer user_data)
-{
- if (g_strcmp0 (method_name, "HandleArguments") == 0)
- {
- TerminalOptions *options = NULL;
- GVariant *v_wd, *v_display, *v_sid, *v_envv, *v_argv;
- char *working_directory = NULL, *display_name = NULL, *startup_id = NULL;
- int initial_workspace = -1;
- char **envv = NULL, **argv = NULL;
- int argc;
- GError *error = NULL;
-
- g_variant_get (parameters, "(@ay@ay@ay@ayi@ay)",
- &v_wd, &v_display, &v_sid, &v_envv, &initial_workspace, &v_argv);
-
- working_directory = ay_to_string (v_wd, &error);
- if (error)
- goto out;
- display_name = ay_to_string (v_display, &error);
- if (error)
- goto out;
- startup_id = ay_to_string (v_sid, &error);
- if (error)
- goto out;
- envv = ay_to_strv (v_envv, NULL);
- argv = ay_to_strv (v_argv, &argc);
-
- _terminal_debug_print (TERMINAL_DEBUG_FACTORY,
- "Factory invoked with working-dir='%s' display='%s' startup-id='%s'"
- "workspace='%d'\n",
- working_directory ? working_directory : "(null)",
- display_name ? display_name : "(null)",
- startup_id ? startup_id : "(null)",
- initial_workspace);
-
- options = terminal_options_parse (working_directory,
- display_name,
- startup_id,
- envv,
- TRUE,
- TRUE,
- &argc, &argv,
- &error,
- NULL);
-
- if (options != NULL)
- {
- options->initial_workspace = initial_workspace;
-
- terminal_app_handle_options (terminal_app_get (), options, FALSE /* no resume */, &error);
- terminal_options_free (options);
- }
-
-out:
- g_variant_unref (v_wd);
- g_free (working_directory);
- g_variant_unref (v_display);
- g_free (display_name);
- g_variant_unref (v_sid);
- g_free (startup_id);
- g_variant_unref (v_envv);
- g_strfreev (envv);
- g_variant_unref (v_argv);
- g_strfreev (argv);
-
- if (error == NULL)
- {
- g_dbus_method_invocation_return_value (invocation, g_variant_new ("()"));
- }
- else
- {
- g_dbus_method_invocation_return_gerror (invocation, error);
- g_error_free (error);
- }
- }
-}
-
-static void
-bus_acquired_cb (GDBusConnection *connection,
- const char *name,
- gpointer user_data)
-{
- static const char dbus_introspection_xml[] =
- "<node name='/org/mate/Terminal'>"
- "<interface name='org.mate.Terminal.Factory'>"
- "<method name='HandleArguments'>"
- "<arg type='ay' name='working_directory' direction='in' />"
- "<arg type='ay' name='display_name' direction='in' />"
- "<arg type='ay' name='startup_id' direction='in' />"
- "<arg type='ay' name='environment' direction='in' />"
- "<arg type='i' name='workspace' direction='in' />"
- "<arg type='ay' name='arguments' direction='in' />"
- "</method>"
- "</interface>"
- "</node>";
-
- static const GDBusInterfaceVTable interface_vtable =
- {
- method_call_cb,
- NULL,
- NULL,
- { 0 }
- };
-
- OwnData *data = (OwnData *) user_data;
- GDBusNodeInfo *introspection_data;
- guint registration_id;
- GError *error = NULL;
-
- _terminal_debug_print (TERMINAL_DEBUG_FACTORY,
- "Bus %s acquired\n", name);
-
- introspection_data = g_dbus_node_info_new_for_xml (dbus_introspection_xml, NULL);
- g_assert (introspection_data != NULL);
-
- registration_id = g_dbus_connection_register_object (connection,
- TERMINAL_FACTORY_SERVICE_PATH,
- introspection_data->interfaces[0],
- &interface_vtable,
- NULL, NULL,
- &error);
- g_dbus_node_info_unref (introspection_data);
-
- if (registration_id == 0)
- {
- g_printerr ("Failed to register object: %s\n", error->message);
- g_error_free (error);
- data->exit_code = EXIT_FAILURE;
- gtk_main_quit ();
- }
-}
-
-static void
-name_acquired_cb (GDBusConnection *connection,
- const char *name,
- gpointer user_data)
-{
- OwnData *data = (OwnData *) user_data;
- GError *error = NULL;
-
- _terminal_debug_print (TERMINAL_DEBUG_FACTORY,
- "Acquired the name %s on the session bus\n", name);
-
- if (data->options == NULL)
- {
- /* Name re-acquired!? */
- g_assert_not_reached ();
- }
-
- if (!terminal_app_handle_options (terminal_app_get (), data->options, TRUE /* do resume */, &error))
- {
- g_printerr ("Failed to handle options: %s\n", error->message);
- g_error_free (error);
- data->exit_code = EXIT_FAILURE;
- gtk_main_quit ();
- }
-
- terminal_options_free (data->options);
- data->options = NULL;
-}
-
-static void
-name_lost_cb (GDBusConnection *connection,
- const char *name,
- gpointer user_data)
-{
- OwnData *data = (OwnData *) user_data;
- GError *error = NULL;
- char **envv;
- int i;
- GVariantBuilder builder;
- GVariant *value;
- GString *string;
- char *s;
- gsize len;
-
- _terminal_debug_print (TERMINAL_DEBUG_FACTORY,
- "Lost the name %s on the session bus\n", name);
-
- /* Couldn't get the connection? No way to continue! */
- if (connection == NULL)
- {
- data->exit_code = EXIT_FAILURE;
- gtk_main_quit ();
- return;
- }
-
- if (data->options == NULL)
- {
- /* Already handled */
- data->exit_code = EXIT_SUCCESS;
- gtk_main_quit ();
- return;
- }
-
- _terminal_debug_print (TERMINAL_DEBUG_FACTORY,
- "Forwarding arguments to existing instance\n");
-
- g_variant_builder_init (&builder, G_VARIANT_TYPE ("(ayayayayiay)"));
-
- g_variant_builder_add (&builder, "@ay", string_to_ay (data->options->default_working_dir));
- g_variant_builder_add (&builder, "@ay", string_to_ay (data->options->display_name));
- g_variant_builder_add (&builder, "@ay", string_to_ay (data->options->startup_id));
-
- string = g_string_new (NULL);
- envv = g_get_environ ();
- for (i = 0; envv[i]; ++i)
- {
- if (i > 0)
- g_string_append_c (string, '\0');
-
- g_string_append (string, envv[i]);
- }
- g_strfreev (envv);
-
- len = string->len;
- s = g_string_free (string, FALSE);
- g_variant_builder_add (&builder, "@ay",
- g_variant_new_from_data (G_VARIANT_TYPE ("ay"), s, len, TRUE, g_free, s));
-
- g_variant_builder_add (&builder, "@i", g_variant_new_int32 (data->options->initial_workspace));
-
- string = g_string_new (NULL);
-
- for (i = 0; i < data->argc; ++i)
- {
- if (i > 0)
- g_string_append_c (string, '\0');
- g_string_append (string, data->argv[i]);
- }
-
- len = string->len;
- s = g_string_free (string, FALSE);
- g_variant_builder_add (&builder, "@ay",
- g_variant_new_from_data (G_VARIANT_TYPE ("ay"), s, len, TRUE, g_free, s));
-
- value = g_dbus_connection_call_sync (connection,
- data->factory_name,
- TERMINAL_FACTORY_SERVICE_PATH,
- TERMINAL_FACTORY_INTERFACE_NAME,
- "HandleArguments",
- g_variant_builder_end (&builder),
- G_VARIANT_TYPE ("()"),
- G_DBUS_CALL_FLAGS_NONE,
- -1,
- NULL,
- &error);
- if (value == NULL)
- {
- g_printerr ("Failed to forward arguments: %s\n", error->message);
- g_error_free (error);
- data->exit_code = EXIT_FAILURE;
- gtk_main_quit ();
- }
- else
- {
- g_variant_unref (value);
- data->exit_code = EXIT_SUCCESS;
- }
-
- terminal_options_free (data->options);
- data->options = NULL;
-
- gtk_main_quit ();
-}
-
-static char *
-get_factory_name_for_display (const char *display_name)
-{
- GString *name;
- const char *p;
-
- name = g_string_sized_new (strlen (TERMINAL_FACTORY_SERVICE_NAME_PREFIX) + strlen (display_name) + 1 /* NUL */);
- g_string_append (name, TERMINAL_FACTORY_SERVICE_NAME_PREFIX);
-
- for (p = display_name; *p; ++p)
- {
- if (g_ascii_isalnum (*p))
- g_string_append_c (name, *p);
- else
- g_string_append_c (name, '_');
- }
-
- _terminal_debug_print (TERMINAL_DEBUG_FACTORY,
- "Factory name is \"%s\"\n", name->str);
-
- return g_string_free (name, FALSE);
-}
-
-static int
-get_initial_workspace (void)
-{
- int ret = -1;
- GdkWindow *window;
- guchar *data = NULL;
- GdkAtom atom;
- GdkAtom cardinal_atom;
-
- window = gdk_get_default_root_window();
-
- atom = gdk_atom_intern_static_string ("_NET_CURRENT_DESKTOP");
- cardinal_atom = gdk_atom_intern_static_string ("CARDINAL");
-
- if (gdk_property_get (window, atom, cardinal_atom, 0, 8, FALSE, NULL, NULL, NULL, &data)) {
- ret = *(int *)data;
- g_free (data);
- }
- return ret;
-}
int
main (int argc, char **argv)
{
- int i;
- char **argv_copy;
- int argc_copy;
- const char *startup_id, *home_dir;
- TerminalOptions *options;
- GError *error = NULL;
- char *working_directory;
- int ret = EXIT_SUCCESS;
+ TerminalApp *app;
+ int ret;
setlocale (LC_ALL, "");
@@ -472,120 +56,18 @@ main (int argc, char **argv)
_terminal_debug_init ();
- /* Make a NULL-terminated copy since we may need it later */
- argv_copy = g_new (char *, argc + 1);
- for (i = 0; i < argc; ++i)
- argv_copy [i] = argv [i];
- argv_copy [i] = NULL;
- argc_copy = argc;
-
- startup_id = g_getenv ("DESKTOP_STARTUP_ID");
-
- working_directory = g_get_current_dir ();
-
- /* Now change directory to $HOME so we don't prevent unmounting, e.g. if the
- * factory is started by caja-open-terminal. See bug #565328.
- * On failure back to /.
- */
- home_dir = g_get_home_dir ();
- if (home_dir == NULL || chdir (home_dir) < 0)
- if (chdir ("/") < 0)
- g_warning ("Could not change working directory.");
-
- options = terminal_options_parse (working_directory,
- NULL,
- startup_id,
- NULL,
- FALSE,
- FALSE,
- &argc, &argv,
- &error,
-#ifdef HAVE_SMCLIENT
- gtk_get_option_group (TRUE),
- egg_sm_client_get_option_group (),
-#endif /* HAVE_SMCLIENT */
- NULL);
- g_free (working_directory);
-
- if (options == NULL)
- {
- g_printerr (_("Failed to parse arguments: %s\n"), error->message);
- g_error_free (error);
- exit (EXIT_FAILURE);
- }
-
g_set_application_name (_("Terminal"));
- /* Unset the these env variables, so they doesn't end up
- * in the factory's env and thus in the terminals' envs.
- */
- g_unsetenv ("DESKTOP_STARTUP_ID");
- g_unsetenv ("GIO_LAUNCHED_DESKTOP_FILE_PID");
- g_unsetenv ("GIO_LAUNCHED_DESKTOP_FILE");
-
- if (options->startup_id == NULL)
- {
- options->startup_id = g_strdup_printf ("_TIME%" G_GINT64_FORMAT,
- g_get_monotonic_time () / 1000);
- }
-
- gdk_init (&argc, &argv);
- const char *display_name = gdk_display_get_name (gdk_display_get_default ());
- options->display_name = g_strdup (display_name);
-
- if (options->use_factory)
- {
- OwnData *data;
- guint owner_id;
-
- data = g_new (OwnData, 1);
- data->factory_name = get_factory_name_for_display (display_name);
- data->options = options;
- data->exit_code = -1;
- data->argv = argv_copy;
- data->argc = argc_copy;
-
- gtk_init(&argc, &argv);
- options->initial_workspace = get_initial_workspace ();
-
- owner_id = g_bus_own_name (G_BUS_TYPE_SESSION,
- data->factory_name,
- G_BUS_NAME_OWNER_FLAGS_NONE,
- bus_acquired_cb,
- name_acquired_cb,
- name_lost_cb,
- data, NULL);
-
- gtk_main ();
-
- ret = data->exit_code;
- g_bus_unown_name (owner_id);
-
- g_free (data->factory_name);
- g_free (data);
-
- }
- else
- {
- gtk_init(&argc, &argv);
- terminal_app_handle_options (terminal_app_get (), options, TRUE /* allow resume */, &error);
- terminal_options_free (options);
-
- if (error == NULL)
- {
- gtk_main ();
- }
- else
- {
- g_printerr ("Error handling options: %s\n", error->message);
- g_error_free (error);
- ret = EXIT_FAILURE;
- }
- }
+ /* Create the GtkApplication */
+ app = g_object_new (TERMINAL_TYPE_APP,
+ "application-id", TERMINAL_APPLICATION_ID,
+ "flags", G_APPLICATION_HANDLES_COMMAND_LINE,
+ NULL);
- terminal_app_shutdown ();
+ /* Run the application */
+ ret = g_application_run (G_APPLICATION (app), argc, argv);
- g_free (argv_copy);
+ g_object_unref (app);
return ret;
}