summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormbkma <[email protected]>2026-02-01 08:12:15 +0100
committerVictor Kareh <[email protected]>2026-03-16 10:20:49 -0400
commit3092e0048390ed6373436ee2447256f65256c153 (patch)
tree054c285dc72167930899b8ea8f50991fe8d1c08a
parent40a129a26d9006e51dd63ddcde6cd2e210d30b92 (diff)
downloadmate-terminal-application.tar.bz2
mate-terminal-application.tar.xz
port to GtkApplicationapplication
-rw-r--r--src/terminal-app.c338
-rw-r--r--src/terminal-app.h12
-rw-r--r--src/terminal-encoding.c2
-rw-r--r--src/terminal-window.c51
-rw-r--r--src/terminal-window.h4
-rw-r--r--src/terminal.c538
6 files changed, 286 insertions, 659 deletions
diff --git a/src/terminal-app.c b/src/terminal-app.c
index 831f42f..5dcb99e 100644
--- a/src/terminal-app.c
+++ b/src/terminal-app.c
@@ -70,22 +70,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 +90,7 @@ struct _TerminalApp
GtkWidget *manage_profiles_delete_button;
GtkWidget *manage_profiles_default_menu;
+ GSettings *settings_global;
GSettings *settings_font;
GHashTable *profiles;
@@ -120,7 +117,6 @@ enum
enum
{
- QUIT,
PROFILE_LIST_CHANGED,
ENCODING_LIST_CHANGED,
LAST_SIGNAL
@@ -140,8 +136,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 +151,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 +320,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 +348,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 +357,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 ();
@@ -400,6 +387,7 @@ terminal_app_profile_cell_data_func (GtkTreeViewColumn *tree_column,
g_object_get_property (G_OBJECT (profile), "visible-name", &value);
g_object_set_property (G_OBJECT (cell), "text", &value);
g_value_unset (&value);
+ g_object_unref (profile);
}
static int
@@ -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);
@@ -1491,9 +1484,93 @@ terminal_app_init (TerminalApp *app)
}
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;
@@ -1503,41 +1580,56 @@ terminal_app_finalize (GObject *object)
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);
+}
- global_app = NULL;
+/* GObject vfuncs */
+
+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 +1675,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:
@@ -1598,31 +1690,65 @@ terminal_app_set_property (GObject *object,
}
}
-static void
-terminal_app_real_quit (TerminalApp *app)
+static gboolean
+terminal_app_local_command_line (GApplication *application,
+ char ***arguments,
+ int *exit_status)
{
- gtk_main_quit();
+ char **argv = *arguments;
+
+ /* Parse locally with strict option checking before any D-Bus contact.
+ * For --help* and --version this calls exit() in the local process.
+ * For unknown options it returns NULL so we can report the error locally. */
+ {
+ char **args = g_strdupv (argv);
+ int argc;
+ GError *error = NULL;
+ TerminalOptions *options;
+
+ for (argc = 0; args[argc] != NULL; argc++)
+ ;
+
+ options = terminal_options_parse (NULL, NULL, NULL, NULL,
+ FALSE, FALSE,
+ &argc, &args,
+ &error,
+#ifdef HAVE_SMCLIENT
+ gtk_get_option_group (FALSE),
+ egg_sm_client_get_option_group (),
+#endif /* HAVE_SMCLIENT */
+ NULL);
+ g_strfreev (args);
+
+ if (options == NULL)
+ {
+ g_printerr (_("Failed to parse arguments: %s\n"), error->message);
+ g_error_free (error);
+ *exit_status = EXIT_FAILURE;
+ return TRUE;
+ }
+
+ terminal_options_free (options);
+ }
+
+ return FALSE;
}
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->local_command_line = terminal_app_local_command_line;
+ 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 +1797,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 +2011,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,26 +2076,38 @@ 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)
+ /* Same workspace, or no specific workspace requested, or window is on all workspaces */
+ if (workspace == -1 || win_workspace == workspace || win_workspace == -1)
ret = terminal_window_get_latest_focused (ret, TERMINAL_WINDOW(res->data));
res = g_list_previous (res);
@@ -2111,6 +2251,7 @@ void
terminal_app_save_config (TerminalApp *app,
GKeyFile *key_file)
{
+ GList *windows;
GList *lw;
guint n = 0;
GPtrArray *window_names_array;
@@ -2122,13 +2263,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..f12f1c5 100644
--- a/src/terminal-window.c
+++ b/src/terminal-window.c
@@ -45,8 +45,6 @@
#include "skey-popup.h"
#endif
-static gboolean detach_tab = FALSE;
-
struct _TerminalWindowPrivate
{
GtkActionGroup *action_group;
@@ -162,10 +160,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 +267,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 */
@@ -2294,9 +2292,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",
@@ -2483,14 +2481,6 @@ terminal_window_finalize (GObject *object)
g_object_unref (priv->ui_manager);
- if (priv->confirm_close_dialog)
- gtk_dialog_response (GTK_DIALOG (priv->confirm_close_dialog),
- GTK_RESPONSE_DELETE_EVENT);
-
- if (priv->search_find_dialog)
- gtk_dialog_response (GTK_DIALOG (priv->search_find_dialog),
- GTK_RESPONSE_DELETE_EVENT);
-
g_free (priv->icon);
G_OBJECT_CLASS (terminal_window_parent_class)->finalize (object);
@@ -2727,9 +2717,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 +2730,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 +2770,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 +3027,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 +3116,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 +3727,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)
diff --git a/src/terminal-window.h b/src/terminal-window.h
index 86b8e28..c66acd4 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;
};
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;
}