diff options
Diffstat (limited to 'src/terminal.c')
| -rw-r--r-- | src/terminal.c | 538 |
1 files changed, 10 insertions, 528 deletions
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; } |
