[gnome-terminal] Split into server and remote



commit e1d641726cf0dec350b33e62d78eb6df9186443e
Author: Christian Persch <chpe gnome org>
Date:   Wed Nov 16 19:14:38 2011 +0100

    Split into server and remote
    
    Make the''gnome-terminal' command simply invoke dbus.

 configure.ac           |   12 ++
 src/Makefile.am        |  106 ++++++++++---
 src/server.c           |  359 +++++++++++++++++++++++++++++++++++++++++++
 src/terminal-options.c |    6 +
 src/terminal-util.c    |    1 +
 src/terminal.c         |  399 +++++++----------------------------------------
 6 files changed, 522 insertions(+), 361 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index 3d67d3f..7f141f5 100644
--- a/configure.ac
+++ b/configure.ac
@@ -85,6 +85,17 @@ PKG_CHECK_MODULES([TERM],
    gsettings-desktop-schemas >= $GSETTINGS_DESKTOP_SCHEMAS_REQUIRED
    $PLATFORM_DEPS])
 
+# ****
+# DBus
+# ****
+
+AC_ARG_WITH([dbus-service-dir],
+  [AS_HELP_STRING([--with-dbus-service-dir=PATH],[dbus service file directory])],
+  [dbusservicedir="$withval"],
+  [dbusservicedir='${datadir}/dbus-1/services'])
+AC_SUBST([dbusservicedir])
+
+AC_ARG_WITH
 # *********
 # GSettings
 # *********
@@ -205,6 +216,7 @@ echo "
 gnome-terminal-$VERSION:
 
 	prefix:                 ${prefix}
+        DBus service dir:       ${dbusservicedir}
 	source code location:	${srcdir}
 	compiler:		${CC}
 
diff --git a/src/Makefile.am b/src/Makefile.am
index 6d83a04..be22ec5 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,6 +1,11 @@
 NULL =
 
 bin_PROGRAMS = gnome-terminal
+libexec_PROGRAMS = gnome-terminal-server
+
+# Terminal server
+
+dbusservice_DATA = org.gnome.Terminal.Factory0.service
 
 BUILT_SOURCES = \
 	terminal-marshal.c \
@@ -9,12 +14,12 @@ BUILT_SOURCES = \
 	terminal-type-builtins.h \
 	$(NULL)
 
-gnome_terminal_SOURCES= \
+gnome_terminal_server_SOURCES= \
 	eggshell.c \
 	eggshell.h \
 	profile-editor.c \
 	profile-editor.h \
-	terminal.c \
+	server.c \
 	terminal-accels.c \
 	terminal-accels.h \
 	terminal-app.c \
@@ -48,10 +53,11 @@ gnome_terminal_SOURCES= \
 	terminal-window.h \
 	$(NULL)
 
-nodist_gnome_terminal_SOURCES= $(BUILT_SOURCES)
+nodist_gnome_terminal_server_SOURCES= $(BUILT_SOURCES)
 
-gnome_terminal_CPPFLAGS = \
+gnome_terminal_server_CPPFLAGS = \
 	-DTERMINAL_COMPILATION \
+	-DTERMINAL_SERVER \
 	-DEXECUTABLE_NAME=\"gnome-terminal\" \
 	-DTERM_DATADIR="\"$(datadir)\"" \
 	-DTERM_LOCALEDIR="\"$(datadir)/locale\"" \
@@ -59,47 +65,40 @@ gnome_terminal_CPPFLAGS = \
 	-DTERM_HELPDIR="\"$(HELP_DIR)\"" \
 	-DSN_API_NOT_YET_FROZEN \
 	-DGDK_MULTIHEAD_SAFE \
-	-DG_DISABLE_SINGLE_INCLUDES \
-	-DPANGO_DISABLE_SINGLE_INCLUDES \
-	-DATK_DISABLE_SINGLE_INCLUDES \
-	-DGDK_DISABLE_SINGLE_INCLUDES \
-	-DGDK_PIXBUF_DISABLE_SINGLE_INCLUDES \
-	-DGTK_DISABLE_SINGLE_INCLUDES \
-	$(DISABLE_DEPRECATED) \
 	$(AM_CPPFLAGS)
 
-gnome_terminal_CFLAGS = \
+gnome_terminal_server_CFLAGS = \
 	$(TERM_CFLAGS) \
-	$(WARN_CFLAGS) \
 	$(AM_CFLAGS)
 
-gnome_terminal_LDFLAGS =
+gnome_terminal_server_LDFLAGS = \
+	$(AM_LDFLAGS)
 
-gnome_terminal_LDADD = \
+gnome_terminal_server_LDADD = \
 	$(TERM_LIBS)
 
 if WITH_SMCLIENT
-gnome_terminal_SOURCES += \
+gnome_terminal_server_SOURCES += \
 	eggsmclient.c \
 	eggsmclient.h \
 	eggsmclient-private.h \
 	$(NULL)
-gnome_terminal_CFLAGS += $(SMCLIENT_CFLAGS)
-gnome_terminal_LDADD += $(SMCLIENT_LIBS)
+gnome_terminal_server_CFLAGS += $(SMCLIENT_CFLAGS)
+gnome_terminal_server_LDADD += $(SMCLIENT_LIBS)
 
 if WITH_SMCLIENT_XSMP
-gnome_terminal_SOURCES += \
+gnome_terminal_server_SOURCES += \
 	eggdesktopfile.c \
 	eggdesktopfile.h \
 	eggsmclient-xsmp.c \
 	$(NULL)
-gnome_terminal_CPPFLAGS += -DEGG_SM_CLIENT_BACKEND_XSMP
+gnome_terminal_server_CPPFLAGS += -DEGG_SM_CLIENT_BACKEND_XSMP
 endif
 if WITH_SMCLIENT_WIN32
-gnome_terminal_SOURCES += eggsmclient-win32.c
+gnome_terminal_server_SOURCES += eggsmclient-win32.c
 endif
 if WITH_SMCLIENT_QUARTZ
-gnome_terminal_SOURCES += eggsmclient-osx.c
+gnome_terminal_server_SOURCES += eggsmclient-osx.c
 endif
 endif
 
@@ -136,6 +135,69 @@ terminal-marshal.c: $(srcdir)/terminal-marshal.list
 		&& mv terminal-marshal.c.tmp terminal-marshal.c ) \
 	|| ( rm -f terminal-marshal.c.tmp && exit 1 )
 
+org.gnome.Terminal.Factory0.service: Makefile
+	$(AM_V_GEN) ( echo "[D-BUS Service]"; \
+		      echo "Name=org.gnome.Terminal.Factory0"; \
+		      echo "${libexecdir}/gnome-terminal-server") > $@
+
+# Terminal remote
+
+gnome_terminal_SOURCES= \
+	terminal.c \
+	terminal-debug.c \
+	terminal-debug.h \
+	terminal-intl.h \
+	terminal-options.c \
+	terminal-options.h \
+	$(NULL)
+
+gnome_terminal_CPPFLAGS = \
+	-DTERMINAL_COMPILATION \
+	-DTERMINAL_REMOTE \
+	-DTERM_DATADIR="\"$(datadir)\"" \
+	-DTERM_LOCALEDIR="\"$(datadir)/locale\"" \
+	-DTERM_PKGDATADIR="\"$(pkgdatadir)\"" \
+	-DSN_API_NOT_YET_FROZEN \
+	-DGDK_MULTIHEAD_SAFE \
+	$(AM_CPPFLAGS)
+
+gnome_terminal_CFLAGS = \
+	$(TERM_CFLAGS) \
+	$(AM_CFLAGS)
+
+gnome_terminal_LDFLAGS = \
+	$(AM_LDFLAGS)
+
+gnome_terminal_LDADD = \
+	$(TERM_LIBS)
+
+
+if WITH_SMCLIENT
+gnome_terminal_SOURCES += \
+	eggsmclient.c \
+	eggsmclient.h \
+	eggsmclient-private.h \
+	$(NULL)
+gnome_terminal_CFLAGS += $(SMCLIENT_CFLAGS)
+gnome_terminal_LDADD += $(SMCLIENT_LIBS)
+
+if WITH_SMCLIENT_XSMP
+gnome_terminal_SOURCES += \
+	eggdesktopfile.c \
+	eggdesktopfile.h \
+	eggsmclient-xsmp.c \
+	$(NULL)
+gnome_terminal_CPPFLAGS += -DEGG_SM_CLIENT_BACKEND_XSMP
+endif
+if WITH_SMCLIENT_WIN32
+gnome_terminal_SOURCES += eggsmclient-win32.c
+endif
+if WITH_SMCLIENT_QUARTZ
+gnome_terminal_SOURCES += eggsmclient-osx.c
+endif
+endif
+
+# Pref migrator
 
 migrationdir = $(libexecdir)/GConf/gsettings
 migration_PROGRAMS = gnome-terminal-migration
diff --git a/src/server.c b/src/server.c
new file mode 100644
index 0000000..ceb2a6f
--- /dev/null
+++ b/src/server.c
@@ -0,0 +1,359 @@
+/*
+ * Copyright  2001, 2002 Havoc Pennington
+ * Copyright  2002 Red Hat, Inc.
+ * Copyright  2002 Sun Microsystems
+ * Copyright  2003 Mariano Suarez-Alvarez
+ * Copyright  2008, 2010, 2011 Christian Persch
+ *
+ * Gnome-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.
+ *
+ * Gnome-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 <errno.h>
+#include <locale.h>
+#include <stdlib.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <glib.h>
+#include <glib/gstdio.h>
+#include <gio/gio.h>
+
+#ifdef WITH_SMCLIENT
+#include "eggsmclient.h"
+#endif
+
+#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.gnome.Terminal.Factory0.Display"
+#define TERMINAL_FACTORY_SERVICE_PATH         "/org/gnome/Terminal/Factory"
+#define TERMINAL_FACTORY_INTERFACE_NAME       "org.gnome.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)
+      *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);
+}
+
+typedef struct {
+  char *factory_name;
+  int exit_code;
+} 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;
+    char **envv = NULL, **argv = NULL;
+    int argc;
+    GError *error = NULL;
+
+    g_variant_get (parameters, "(@ay ay@ay ay@ay)",
+                   &v_wd, &v_display, &v_sid, &v_envv, &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'\n",
+                          working_directory ? working_directory : "(null)",
+                          display_name ? display_name : "(null)",
+                          startup_id ? startup_id : "(null)");
+
+    options = terminal_options_parse (working_directory,
+                                      display_name,
+                                      startup_id,
+                                      envv,
+                                      TRUE,
+                                      TRUE,
+                                      &argc, &argv,
+                                      &error,
+                                      NULL);
+
+    if (options != NULL) {
+      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/gnome/Terminal'>"
+      "<interface name='org.gnome.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='ay' name='arguments' direction='in' />"
+        "</method>"
+      "</interface>"
+    "</node>";
+
+  static const GDBusInterfaceVTable interface_vtable = {
+    method_call_cb,
+    NULL,
+    NULL,
+  };
+
+  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) {
+    _terminal_debug_print (TERMINAL_DEBUG_FACTORY,
+                           "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)
+{
+  _terminal_debug_print (TERMINAL_DEBUG_FACTORY,
+                         "Acquired the name %s on the starter bus\n", name);
+}
+
+static void
+name_lost_cb (GDBusConnection *connection,
+              const char *name,
+              gpointer user_data)
+{
+  OwnData *data = (OwnData *) user_data;
+
+  if (connection) {
+    _terminal_debug_print (TERMINAL_DEBUG_FACTORY,
+                          "Lost the name %s on the starter bus\n", name);
+  } else {
+    g_printerr ("Failed to connect to starter bus\n");
+  }
+
+  data->exit_code = EXIT_FAILURE;
+  gtk_main_quit ();
+}
+
+static char *
+get_factory_name_for_display (const char *display_name)
+{
+#if 0
+  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);
+#endif
+  return g_strdup ("org.gnome.Terminal.Factory0");
+}
+
+int
+main (int argc, char **argv)
+{
+  OwnData data;
+  guint owner_id;
+  const char *home_dir;
+  GdkDisplay *display;
+  GError *error = NULL;
+
+  setlocale (LC_ALL, "");
+
+  bindtextdomain (GETTEXT_PACKAGE, TERM_LOCALEDIR);
+  bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
+  textdomain (GETTEXT_PACKAGE);
+
+  g_type_init ();
+
+  _terminal_debug_init ();
+
+  // FIXMEchpe: just use / here but make sure #565328 doesn't regress
+  /* Change directory to $HOME so we don't prevent unmounting, e.g. if the
+   * factory is started by nautilus-open-terminal. See bug #565328.
+   * On failure back to /.
+   */
+  home_dir = g_get_home_dir ();
+  if (home_dir == NULL || chdir (home_dir) < 0)
+    (void) chdir ("/");
+
+  g_set_application_name (_("Terminal"));
+
+  if (!gtk_init_with_args (&argc, &argv, "", NULL, NULL, &error)) {
+    g_printerr ("Failed to parse arguments: %s\n", error->message);
+    g_error_free (error);
+    exit (EXIT_FAILURE);
+  }
+
+  /* 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");
+
+  display = gdk_display_get_default ();
+  data.factory_name = get_factory_name_for_display (gdk_display_get_name (display));
+  data.exit_code = EXIT_FAILURE;
+
+  owner_id = g_bus_own_name (G_BUS_TYPE_STARTER,
+                             data.factory_name,
+                             G_BUS_NAME_OWNER_FLAGS_NONE,
+                             bus_acquired_cb,
+                             name_acquired_cb,
+                             name_lost_cb,
+                             &data, NULL);
+
+  gtk_main ();
+
+  g_bus_unown_name (owner_id);
+
+  g_free (data.factory_name);
+
+  terminal_app_shutdown ();
+
+  return data.exit_code;
+}
diff --git a/src/terminal-options.c b/src/terminal-options.c
index 55e5fdf..a4e179c 100644
--- a/src/terminal-options.c
+++ b/src/terminal-options.c
@@ -494,6 +494,7 @@ option_load_save_config_cb (const gchar *option_name,
                             gpointer     data,
                             GError     **error)
 {
+#ifdef TERMINAL_SERVER
   TerminalOptions *options = data;
 
   if (options->config_file)
@@ -506,6 +507,7 @@ option_load_save_config_cb (const gchar *option_name,
   options->config_file = terminal_util_resolve_relative_path (options->default_working_dir, value);
   options->load_config = strcmp (option_name, "--load-config") == 0;
   options->save_config = strcmp (option_name, "--save-config") == 0;
+#endif
 
   return TRUE;
 }
@@ -778,6 +780,8 @@ terminal_options_parse (const char *working_directory,
   return NULL;
 }
 
+#ifdef TERMINAL_SERVER
+
 /**
  * terminal_options_merge_config:
  * @options:
@@ -897,6 +901,8 @@ terminal_options_merge_config (TerminalOptions *options,
   return TRUE;
 }
 
+#endif /* TERMINAL_SERVIER */
+
 /**
  * terminal_options_ensure_window:
  * @options:
diff --git a/src/terminal-util.c b/src/terminal-util.c
index 135deb6..4e7d4a3 100644
--- a/src/terminal-util.c
+++ b/src/terminal-util.c
@@ -42,6 +42,7 @@
 #include "terminal-accels.h"
 #include "terminal-app.h"
 #include "terminal-intl.h"
+#include "terminal-screen.h"
 #include "terminal-util.h"
 #include "terminal-window.h"
 
diff --git a/src/terminal.c b/src/terminal.c
index ff25cb9..1e107c7 100644
--- a/src/terminal.c
+++ b/src/terminal.c
@@ -31,84 +31,21 @@
 #include <glib/gstdio.h>
 #include <gio/gio.h>
 
+#include <gtk/gtk.h>
 #include <gdk/gdkx.h>
 
 #ifdef WITH_SMCLIENT
 #include "eggsmclient.h"
 #endif
 
-#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.gnome.Terminal.Display"
+#define TERMINAL_FACTORY_SERVICE_NAME_PREFIX  "org.gnome.Terminal.Factory0.Display"
 #define TERMINAL_FACTORY_SERVICE_PATH         "/org/gnome/Terminal/Factory"
 #define TERMINAL_FACTORY_INTERFACE_NAME       "org.gnome.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)
-      *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)
 {
@@ -121,208 +58,28 @@ string_to_ay (const char *string)
   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;
-    char **envv = NULL, **argv = NULL;
-    int argc;
-    GError *error = NULL;
-
-    g_variant_get (parameters, "(@ay ay@ay ay@ay)",
-                   &v_wd, &v_display, &v_sid, &v_envv, &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'\n",
-                          working_directory ? working_directory : "(null)",
-                          display_name ? display_name : "(null)",
-                          startup_id ? startup_id : "(null)");
-
-    options = terminal_options_parse (working_directory,
-                                      display_name,
-                                      startup_id,
-                                      envv,
-                                      TRUE,
-                                      TRUE,
-                                      &argc, &argv,
-                                      &error,
-                                      NULL);
-
-    if (options != NULL) {
-      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/gnome/Terminal'>"
-      "<interface name='org.gnome.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='ay' name='arguments' direction='in' />"
-        "</method>"
-      "</interface>"
-    "</node>";
-
-  static const GDBusInterfaceVTable interface_vtable = {
-    method_call_cb,
-    NULL,
-    NULL,
-  };
-
-  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)
+/**
+ * options_to_variant:
+ * 
+ * Returns: a new floating #GVariant
+ */
+static GVariant *
+options_to_variant (TerminalOptions *options,
+                    char **argv,
+                    int argc)
 {
-  OwnData *data = (OwnData *) user_data;
-  GError *error = NULL;
   char **envv;
-  int envc, i;
+  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 ("(ayayayayay)"));
 
-  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));
+  g_variant_builder_add (&builder, "@ay", string_to_ay (options->default_working_dir));
+  g_variant_builder_add (&builder, "@ay", string_to_ay (options->display_name));
+  g_variant_builder_add (&builder, "@ay", string_to_ay (options->startup_id));
 
   string = g_string_new (NULL);
   envv = g_get_environ ();
@@ -342,11 +99,11 @@ name_lost_cb (GDBusConnection *connection,
 
   string = g_string_new (NULL);
 
-  for (i = 0; i < data->argc; ++i)
+  for (i = 0; i < argc; ++i)
     {
       if (i > 0)
         g_string_append_c (string, '\0');
-      g_string_append (string, data->argv[i]);
+      g_string_append (string, argv[i]);
     }
 
   len = string->len;
@@ -354,31 +111,7 @@ name_lost_cb (GDBusConnection *connection,
   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 ();
+  return g_variant_builder_end (&builder);
 }
 
 /* Copied from libnautilus/nautilus-program-choosing.c; Needed in case
@@ -432,9 +165,11 @@ slowly_and_stupidly_obtain_timestamp (Display *xdisplay)
   return event.xproperty.time;
 }
 
+
 static char *
 get_factory_name_for_display (const char *display_name)
 {
+#if 0
   GString *name;
   const char *p;
 
@@ -453,6 +188,8 @@ get_factory_name_for_display (const char *display_name)
                          "Factory name is \"%s\"\n", name->str);
 
   return g_string_free (name, FALSE);
+#endif
+  return g_strdup ("org.gnome.Terminal.Factory0");
 }
 
 int
@@ -461,12 +198,15 @@ main (int argc, char **argv)
   int i;
   char **argv_copy;
   int argc_copy;
-  const char *startup_id, *display_name, *home_dir;
+  const char *startup_id, *display_name;
+  char *factory_name = NULL;
   GdkDisplay *display;
   TerminalOptions *options;
+  GDBusConnection *connection;
   GError *error = NULL;
   char *working_directory;
-  int ret = EXIT_SUCCESS;
+  GVariant *server_retval;
+  int exit_code = EXIT_FAILURE;
 
   setlocale (LC_ALL, "");
 
@@ -474,8 +214,7 @@ main (int argc, char **argv)
   bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
   textdomain (GETTEXT_PACKAGE);
 
-  /* GConf uses ORBit2 which need GThread. See bug #565516 */
-  g_thread_init (NULL);
+  g_type_init ();
 
   _terminal_debug_init ();
 
@@ -487,17 +226,8 @@ main (int argc, char **argv)
   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 nautilus-open-terminal. See bug #565328.
-   * On failure back to /.
-   */
-  home_dir = g_get_home_dir ();
-  if (home_dir == NULL || chdir (home_dir) < 0)
-    (void) chdir ("/");
-
   options = terminal_options_parse (working_directory,
                                     NULL,
                                     startup_id,
@@ -517,11 +247,12 @@ main (int argc, char **argv)
   if (options == NULL) {
     g_printerr (_("Failed to parse arguments: %s\n"), error->message);
     g_error_free (error);
+    g_free (argv_copy);
     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.
    */
@@ -543,51 +274,41 @@ main (int argc, char **argv)
   display = gdk_display_get_default ();
   display_name = gdk_display_get_name (display);
   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;
-
-    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 {
 
-    terminal_app_handle_options (terminal_app_get (), options, TRUE /* allow resume */, &error);
-    terminal_options_free (options);
+  connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
+  if (connection == NULL) {
+    g_printerr ("Error connecting to bus: %s\n", error->message);
+    g_error_free (error);
+    goto out;
+  }
 
-    if (error == NULL) {
-      gtk_main ();
-    } else {
-      g_printerr ("Error handling options: %s\n", error->message);
-      g_error_free (error);
-      ret = EXIT_FAILURE;
-    }
+  factory_name = get_factory_name_for_display (options->display_name);
+  server_retval = g_dbus_connection_call_sync (connection,
+                                               factory_name,
+                                               TERMINAL_FACTORY_SERVICE_PATH,
+                                               TERMINAL_FACTORY_INTERFACE_NAME,
+                                               "HandleArguments",
+                                               options_to_variant (options, argv_copy, argc_copy),
+                                               G_VARIANT_TYPE ("()"),
+                                               G_DBUS_CALL_FLAGS_NONE,
+                                               -1,
+                                               NULL,
+                                               &error);
+  if (server_retval == NULL) {
+    g_printerr ("Error opening terminal: %s\n", error->message);
+    g_error_free (error);
+  } else {
+    g_variant_unref (server_retval);
+    exit_code = EXIT_SUCCESS;
   }
 
-  terminal_app_shutdown ();
+  g_free (factory_name);
+  g_object_unref (connection);
+
+out:
+  terminal_options_free (options);
 
   g_free (argv_copy);
 
-  return ret;
+  return exit_code;
 }



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