[gnome-terminal] Change feactory interface



commit 67c373417d2eddcabb4e14a1d5e9ea21b058205b
Author: Christian Persch <chpe gnome org>
Date:   Sat Nov 19 22:54:48 2011 +0100

    Change feactory interface
    
    More changes to come. Add new gnome-terminal-client programme that will
    take over from gnome-terminal, which will remain only for legacy backward
    compatibiliy.

 src/Makefile.am            |   60 +++-
 src/client.c               |  721 ++++++++++++++++++++++++++++++++++++++++++++
 src/org.gnome.Terminal.xml |   19 +-
 src/server.c               |   40 +--
 src/terminal-app.c         |  347 ++++++++++------------
 src/terminal-app.h         |    6 +-
 src/terminal-controller.c  |  243 +++++++++++++++
 src/terminal-controller.h  |   63 ++++
 src/terminal-defines.h     |   37 +++
 src/terminal-options.c     |    2 +-
 src/terminal-options.h     |    1 +
 src/terminal-screen.c      |   50 +++-
 src/terminal-screen.h      |    8 +
 src/terminal.c             |  182 +++++++++++-
 14 files changed, 1521 insertions(+), 258 deletions(-)
---
diff --git a/src/Makefile.am b/src/Makefile.am
index b276393..abb1f96 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,6 +1,6 @@
 NULL =
 
-bin_PROGRAMS = gnome-terminal
+bin_PROGRAMS = gnome-terminal-client gnome-terminal
 libexec_PROGRAMS = gnome-terminal-server
 
 # Terminal server
@@ -12,8 +12,8 @@ BUILT_SOURCES = \
 	terminal-marshal.h \
 	terminal-type-builtins.c \
 	terminal-type-builtins.h \
-	terminal-factory.c \
-	terminal-factory.h \
+	terminal-gdbus-generated.c \
+	terminal-gdbus-generated.h \
 	$(NULL)
 
 gnome_terminal_server_SOURCES= \
@@ -28,15 +28,16 @@ gnome_terminal_server_SOURCES= \
 	terminal-app.h \
 	terminal-close-button.h \
 	terminal-close-button.c \
+	terminal-controller.c \
+	terminal-controller.h \
 	terminal-debug.c \
 	terminal-debug.h \
+	terminal-defines.h \
 	terminal-encoding.c \
 	terminal-encoding.h \
 	terminal-info-bar.c \
 	terminal-info-bar.h \
 	terminal-intl.h \
-	terminal-options.c \
-	terminal-options.h \
 	terminal-schemas.h \
 	terminal-screen.c \
 	terminal-screen.h \
@@ -142,30 +143,67 @@ org.gnome.Terminal.Factory0.service: Makefile
 		      echo "Name=org.gnome.Terminal.Factory0"; \
 		      echo "${libexecdir}/gnome-terminal-server") > $@
 
-terminal-factory.c terminal-factory.h: org.gnome.Terminal.xml Makefile
+terminal-gdbus-generated.c terminal-gdbus-generated.h: org.gnome.Terminal.xml Makefile
 	$(AM_V_GEN) $(GDBUS_CODEGEN) \
 			--interface-prefix=org.gnome.Terminal \
 			--c-namespace=Terminal \
 			--c-generate-object-manager \
-			--generate-c-code terminal-factory \
+			--generate-c-code terminal-gdbus-generated \
 			$<
 
-# Terminal remote
+# Terminal client
+
+gnome_terminal_client_SOURCES = \
+	client.c \
+	terminal-defines.h \
+	terminal-intl.h \
+	$(NULL)
+
+nodist_gnome_terminal_client_SOURCES = \
+	terminal-gdbus-generated.c \
+	terminal-gdbus-generated.h \
+	$(NULL)
+
+gnome_terminal_client_CPPFLAGS = \
+	-DTERMINAL_COMPILATION \
+	-DTERMINAL_CLIENT \
+	-DTERM_DATADIR="\"$(datadir)\"" \
+	-DTERM_LOCALEDIR="\"$(datadir)/locale\"" \
+	-DTERM_PKGDATADIR="\"$(pkgdatadir)\"" \
+	-DSN_API_NOT_YET_FROZEN \
+	-DGDK_MULTIHEAD_SAFE \
+	$(AM_CPPFLAGS)
+
+gnome_terminal_client_CFLAGS = \
+	$(TERM_CFLAGS) \
+	$(AM_CFLAGS)
+
+gnome_terminal_client_LDFLAGS = \
+	$(AM_LDFLAGS)
+
+gnome_terminal_client_LDADD = \
+	$(TERM_LIBS)
+
+# Legacy terminal client
 
 gnome_terminal_SOURCES= \
 	terminal.c \
 	terminal-debug.c \
 	terminal-debug.h \
-	terminal-factory.c \
-	terminal-factory.h \
+	terminal-defines.h \
 	terminal-intl.h \
 	terminal-options.c \
 	terminal-options.h \
 	$(NULL)
 
+nodist_gnome_terminal_SOURCES = \
+	terminal-gdbus-generated.c \
+	terminal-gdbus-generated.h \
+	$(NULL)
+
 gnome_terminal_CPPFLAGS = \
 	-DTERMINAL_COMPILATION \
-	-DTERMINAL_REMOTE \
+	-DTERMINAL_CLIENT \
 	-DTERM_DATADIR="\"$(datadir)\"" \
 	-DTERM_LOCALEDIR="\"$(datadir)/locale\"" \
 	-DTERM_PKGDATADIR="\"$(pkgdatadir)\"" \
diff --git a/src/client.c b/src/client.c
new file mode 100644
index 0000000..29ed919
--- /dev/null
+++ b/src/client.c
@@ -0,0 +1,721 @@
+/*
+ * Copyright  2001, 2002 Havoc Pennington
+ * Copyright  2002, 2008-2010 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/>.
+ */
+
+/* Code copied and adapted from glib/gio/gdbus-tool.c:
+ *  * Author: David Zeuthen <davidz redhat com>
+ */
+
+#include <config.h>
+
+#include <errno.h>
+#include <locale.h>
+#include <stdlib.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <glib.h>
+#include <gio/gio.h>
+
+#include <gtk/gtk.h>
+#include <gdk/gdkx.h>
+
+#include "terminal-intl.h"
+#include "terminal-gdbus-generated.h"
+#include "terminal-defines.h"
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+G_GNUC_UNUSED static void completion_debug (const gchar *format, ...);
+
+/* Uncomment to get debug traces in /tmp/gdbus-completion-debug.txt (nice
+ * to not have it interfere with stdout/stderr)
+ */
+#if 0
+G_GNUC_UNUSED static void
+completion_debug (const gchar *format, ...)
+{
+  va_list var_args;
+  gchar *s;
+  static FILE *f = NULL;
+
+  va_start (var_args, format);
+  s = g_strdup_vprintf (format, var_args);
+  if (f == NULL)
+    {
+      f = fopen ("/tmp/gdbus-completion-debug.txt", "a+");
+    }
+  fprintf (f, "%s\n", s);
+  g_free (s);
+}
+#else
+static void
+completion_debug (const gchar *format, ...)
+{
+}
+#endif
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static void
+remove_arg (gint num, gint *argc, gchar **argv[])
+{
+  gint n;
+
+  g_assert (num <= (*argc));
+
+  for (n = num; (*argv)[n] != NULL; n++)
+    (*argv)[n] = (*argv)[n+1];
+  (*argv)[n] = NULL;
+  (*argc) = (*argc) - 1;
+}
+
+static void
+usage (gint *argc, gchar **argv[], gboolean use_stdout)
+{
+  GOptionContext *o;
+  gchar *s;
+  gchar *program_name;
+
+  o = g_option_context_new (_("COMMAND"));
+  g_option_context_set_help_enabled (o, FALSE);
+  /* Ignore parsing result */
+  g_option_context_parse (o, argc, argv, NULL);
+  program_name = g_path_get_basename ((*argv)[0]);
+  s = g_strdup_printf (_("Commands:\n"
+                         "  help    Shows this information\n"
+                         "  open    Create a new terminal\n"
+                         "\n"
+                         "Use \"%s COMMAND --help\" to get help on each command.\n"),
+                       program_name);
+  g_free (program_name);
+  g_option_context_set_description (o, s);
+  g_free (s);
+  s = g_option_context_get_help (o, FALSE, NULL);
+  if (use_stdout)
+    g_print ("%s", s);
+  else
+    g_printerr ("%s", s);
+  g_free (s);
+  g_option_context_free (o);
+}
+
+static void
+modify_argv0_for_command (gint *argc, gchar **argv[], const gchar *command)
+{
+  gchar *s;
+  gchar *program_name;
+
+  /* TODO:
+   *  1. get a g_set_prgname() ?; or
+   *  2. save old argv[0] and restore later
+   */
+
+  g_assert (g_strcmp0 ((*argv)[1], command) == 0);
+  remove_arg (1, argc, argv);
+
+  program_name = g_path_get_basename ((*argv)[0]);
+  s = g_strdup_printf ("%s %s", (*argv)[0], command);
+  (*argv)[0] = s;
+  g_free (program_name);
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+/* Copied from libnautilus/nautilus-program-choosing.c; Needed in case
+ * we have no DESKTOP_STARTUP_ID (with its accompanying timestamp).
+ */
+static char *
+slowly_and_stupidly_obtain_timestamp (void)
+{
+  Display *xdisplay;
+  Window xwindow;
+  XEvent event;
+
+  xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
+
+  {
+    XSetWindowAttributes attrs;
+    Atom atom_name;
+    Atom atom_type;
+    const char *name;
+
+    attrs.override_redirect = True;
+    attrs.event_mask = PropertyChangeMask | StructureNotifyMask;
+
+    xwindow =
+      XCreateWindow (xdisplay,
+                     RootWindow (xdisplay, 0),
+                     -100, -100, 1, 1,
+                     0,
+                     CopyFromParent,
+                     CopyFromParent,
+                     (Visual *)CopyFromParent,
+                     CWOverrideRedirect | CWEventMask,
+                     &attrs);
+
+    atom_name = XInternAtom (xdisplay, "WM_NAME", TRUE);
+    g_assert (atom_name != None);
+    atom_type = XInternAtom (xdisplay, "STRING", TRUE);
+    g_assert (atom_type != None);
+
+    name = "Fake Window";
+    XChangeProperty (xdisplay,
+                     xwindow, atom_name,
+                     atom_type,
+                     8, PropModeReplace, (unsigned char *)name, strlen (name));
+  }
+
+  XWindowEvent (xdisplay,
+                xwindow,
+                PropertyChangeMask,
+                &event);
+
+  XDestroyWindow(xdisplay, xwindow);
+
+  return g_strdup_printf ("_TIME%lu", event.xproperty.time);
+}
+
+typedef struct
+{
+  /* Window options */
+  char       *startup_id;
+  const char *display_name;
+  int         screen_number;
+  char       *geometry;
+  char       *role;
+
+  gboolean    menubar_state;
+  gboolean    start_fullscreen;
+  gboolean    start_maximized;
+
+  /* Terminal options */
+  char  **exec_argv; /* not owned! */
+  int     exec_argc;
+
+  char   *working_directory;
+  char   *profile;
+  char   *title;
+  double  zoom;
+
+  /* Flags */
+  guint menubar_state_set : 1;
+  guint zoom_set          : 1;
+  guint active            : 1;
+} OptionData;
+
+static gboolean
+option_zoom_cb (const gchar *option_name,
+                const gchar *value,
+                gpointer     user_data,
+                GError     **error)
+{
+  OptionData *data = user_data;
+  double zoom;
+  char *end;
+
+  /* Try reading a locale-style double first, in case it was
+    * typed by a person, then fall back to ascii_strtod (we
+    * always save session in C locale format)
+    */
+  end = NULL;
+  errno = 0;
+  zoom = g_strtod (value, &end);
+  if (end == NULL || *end != '\0')
+    {
+      g_set_error (error,
+                   G_OPTION_ERROR,
+                   G_OPTION_ERROR_BAD_VALUE,
+                   _("\"%s\" is not a valid zoom factor"),
+                   value);
+      return FALSE;
+    }
+
+
+  data->zoom = zoom;
+  data->zoom_set = TRUE;
+
+  return TRUE;
+}
+
+static GOptionContext *
+get_goption_context (OptionData *data)
+{
+  const GOptionEntry window_goptions[] = {
+    { "maximize", 0, 0, G_OPTION_ARG_NONE, &data->start_maximized,
+      N_("Maximise the window"), NULL },
+    { "fullscreen", 0, 0, G_OPTION_ARG_NONE, &data->start_fullscreen,
+      N_("Full-screen the window"), NULL },
+    { "geometry", 0, 0, G_OPTION_ARG_STRING, &data->geometry,
+      N_("Set the window size; for example: 80x24, or 80x24+200+200 (COLSxROWS+X+Y)"),
+      N_("GEOMETRY") },
+    { "role", 0, 0, G_OPTION_ARG_STRING, &data->role,
+      N_("Set the window role"), N_("ROLE") },
+    { NULL, 0, 0, 0, NULL, NULL, NULL }
+  };
+
+  const GOptionEntry terminal_goptions[] = {
+    { "profile", 0, 0, G_OPTION_ARG_STRING, &data->profile,
+      N_("Use the given profile instead of the default profile"),
+      N_("PROFILE-NAME") },
+    { "title", 0, 0, G_OPTION_ARG_STRING, &data->title,
+      N_("Set the terminal title"), N_("TITLE") },
+    { "cwd", 0, 0, G_OPTION_ARG_STRING, &data->working_directory,
+      N_("Set the working directory"), N_("DIRNAME") },
+    { "zoom", 0, 0, G_OPTION_ARG_CALLBACK, option_zoom_cb,
+      N_("Set the terminal's zoom factor (1.0 = normal size)"),
+      N_("ZOOM") },
+    { NULL, 0, 0, 0, NULL, NULL, NULL }
+  };
+
+  GOptionContext *context;
+  GOptionGroup *group;
+
+  context = g_option_context_new (NULL);
+  g_option_context_set_translation_domain (context, GETTEXT_PACKAGE);
+  g_option_context_set_description (context, N_("GNOME Terminal Client"));
+  g_option_context_set_ignore_unknown_options (context, FALSE);
+
+  group = g_option_group_new ("window-options",
+                              N_("Window options:"),
+                              N_("Show window options"),
+                              data,
+                              NULL);
+  g_option_group_set_translation_domain (group, GETTEXT_PACKAGE);
+  g_option_group_add_entries (group, window_goptions);
+  g_option_context_add_group (context, group);
+
+  group = g_option_group_new ("terminal-options",
+                              N_("Terminal options:"),
+                              N_("Show per-terminal options"),
+                              data,
+                              NULL);
+  g_option_group_set_translation_domain (group, GETTEXT_PACKAGE);
+  g_option_group_add_entries (group, terminal_goptions);
+  g_option_context_add_group (context, group);
+
+  g_option_context_add_group (context, gtk_get_option_group (TRUE));
+
+  return context;
+}
+
+static void
+option_data_free (OptionData *data)
+{
+  if (data == NULL)
+    return;
+
+  g_free (data->startup_id);
+  g_free (data->geometry);
+  g_free (data->role);
+
+  g_free (data->working_directory);
+  g_free (data->profile);
+  g_free (data->title);
+}
+
+static OptionData *
+parse_arguments (int *argcp,
+                 char ***argvp,
+                 GError **error)
+{
+  OptionData *data;
+  GOptionContext *context;
+  int argc = *argcp;
+  char **argv = *argvp;
+  int i;
+
+  data = g_new0 (OptionData, 1);
+
+  /* If there's a '--' argument with other arguments after it, 
+   * strip them off. Need to do this before parsing the options!
+   */
+  data->exec_argv = NULL;
+  data->exec_argc = 0;
+  for (i = 1; i < argc - 1; i++) {
+    if (strcmp (argv[i], "--") == 0) {
+      data->exec_argv = &argv[i + 1];
+      data->exec_argc = argc - (i + 1);
+
+      /* Truncate argv */
+      *argcp = argc = i - 1;
+      break;
+    }
+  }
+
+  data->working_directory = g_get_current_dir ();
+
+  /* Need to save this here before calling gtk_init! */
+  data->startup_id = g_strdup (g_getenv ("DESKTOP_STARTUP_ID"));
+
+  context = get_goption_context (data);
+  if (!g_option_context_parse (context, argcp, argvp, error)) {
+    option_data_free (data);
+    g_option_context_free (context);
+    return NULL;
+  }
+  g_option_context_free (context);
+
+  /* Do this here so that gdk_display is initialized */
+  if (data->startup_id == NULL)
+    data->startup_id = slowly_and_stupidly_obtain_timestamp ();
+
+  data->display_name = gdk_display_get_name (gdk_display_get_default ());
+
+  return data;
+}
+
+/**
+ * build_create_options_variant:
+ * 
+ * Returns: a floating #GVariant
+ */
+static GVariant *
+build_create_options_variant (OptionData *data)
+{
+  GVariantBuilder builder;
+
+  g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}"));
+
+  g_variant_builder_add (&builder, "{sv}",
+                         "display", g_variant_new_bytestring (data->display_name));
+
+  if (data->startup_id)
+    g_variant_builder_add (&builder, "{sv}", 
+                           "desktop-startup-id", g_variant_new_bytestring (data->startup_id));
+  if (data->geometry)
+    g_variant_builder_add (&builder, "{sv}", 
+                           "geometry", g_variant_new_string (data->geometry));
+  if (data->role)
+    g_variant_builder_add (&builder, "{sv}", 
+                           "role", g_variant_new_string (data->role));
+  if (data->start_maximized)
+    g_variant_builder_add (&builder, "{sv}", 
+                           "maximize-window", g_variant_new_boolean (TRUE));
+  if (data->start_fullscreen)
+    g_variant_builder_add (&builder, "{sv}", 
+                           "fullscreen-window", g_variant_new_boolean (TRUE));
+
+  return g_variant_builder_end (&builder);
+}
+
+/**
+ * build_exec_options_variant:
+ * 
+ * Returns: a floating #GVariant
+ */
+static GVariant *
+build_exec_options_variant (OptionData *data)
+{
+  GVariantBuilder builder;
+  char **envv;
+
+  g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}"));
+
+  if (data->working_directory)
+    g_variant_builder_add (&builder, "{sv}", 
+                           "cwd", g_variant_new_bytestring (data->working_directory));
+
+  envv = g_get_environ ();
+  if (envv) {
+    envv = g_environ_unsetenv (envv, "DESKTOP_STARTUP_ID");
+    envv = g_environ_unsetenv (envv, "GIO_LAUNCHED_DESKTOP_FILE_PID");
+    envv = g_environ_unsetenv (envv, "GIO_LAUNCHED_DESKTOP_FILE");
+
+    g_variant_builder_add (&builder, "{sv}",
+                           "environ",
+                           g_variant_new_bytestring_array ((const char * const *) envv, -1));
+    g_strfreev (envv);
+  }
+
+  return g_variant_builder_end (&builder);
+}
+
+static gboolean
+handle_open (int *argc,
+             char ***argv,
+             gboolean request_completion,
+             const gchar *completion_cur,
+             const gchar *completion_prev)
+{
+  OptionData *data;
+  TerminalFactory *factory;
+  TerminalReceiver *receiver;
+  GError *error = NULL;
+  char *object_path;
+
+  modify_argv0_for_command (argc, argv, "open");
+
+  data = parse_arguments (argc, argv, &error);
+  if (data == NULL) {
+    g_printerr ("Error parsing arguments: %s\n", error->message);
+    g_error_free (error);
+    return FALSE;
+  }
+
+  factory = terminal_factory_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION,
+                                                     G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES |
+                                                     G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS,
+                                                     TERMINAL_UNIQUE_NAME,
+                                                     TERMINAL_FACTORY_OBJECT_PATH,
+                                                     NULL /* cancellable */,
+                                                     &error);
+  if (factory == NULL) {
+    g_printerr ("Error constructing proxy for %s:%s: %s\n", 
+                TERMINAL_UNIQUE_NAME, TERMINAL_FACTORY_OBJECT_PATH,
+                error->message);
+    g_error_free (error);
+    option_data_free (data);
+    return FALSE;
+  }
+
+  if (!terminal_factory_call_create_instance_sync 
+         (factory,
+          build_create_options_variant (data),
+          &object_path,
+          NULL /* cancellable */,
+          &error)) {
+    g_printerr ("Error creating terminal: %s\n", error->message);
+    g_error_free (error);
+    g_object_unref (factory);
+    option_data_free (data);
+    return FALSE;
+  }
+
+  g_object_unref (factory);
+
+  receiver = terminal_receiver_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION,
+                                                       G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES,
+                                                       TERMINAL_UNIQUE_NAME,
+                                                       object_path,
+                                                       NULL /* cancellable */,
+                                                       &error);
+  if (receiver == NULL) {
+    g_printerr ("Failed to create proxy for terminal: %s\n", error->message);
+    g_error_free (error);
+    g_free (object_path);
+    option_data_free (data);
+    return FALSE;
+  }
+
+  g_free (object_path);
+
+  if (!terminal_receiver_call_exec_sync (receiver,
+                                         build_exec_options_variant (data),
+                                         g_variant_new_bytestring_array ((const char * const *) data->exec_argv, data->exec_argc),
+                                         NULL /* cancellable */,
+                                         &error)) {
+    g_printerr ("Error: %s\n", error->message);
+    g_error_free (error);
+    g_object_unref (receiver);
+    option_data_free (data);
+    return FALSE;
+  }
+
+  option_data_free (data);
+
+  g_object_unref (receiver);
+
+  return TRUE;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static gchar *
+pick_word_at (const gchar  *s,
+              gint          cursor,
+              gint         *out_word_begins_at)
+{
+  gint begin;
+  gint end;
+
+  if (s[0] == '\0')
+    {
+      if (out_word_begins_at != NULL)
+        *out_word_begins_at = -1;
+      return NULL;
+    }
+
+  if (g_ascii_isspace (s[cursor]) && ((cursor > 0 && g_ascii_isspace(s[cursor-1])) || cursor == 0))
+    {
+      if (out_word_begins_at != NULL)
+        *out_word_begins_at = cursor;
+      return g_strdup ("");
+    }
+
+  while (!g_ascii_isspace (s[cursor - 1]) && cursor > 0)
+    cursor--;
+  begin = cursor;
+
+  end = begin;
+  while (!g_ascii_isspace (s[end]) && s[end] != '\0')
+    end++;
+
+  if (out_word_begins_at != NULL)
+    *out_word_begins_at = begin;
+
+  return g_strndup (s + begin, end - begin);
+}
+
+gint
+main (gint argc, gchar *argv[])
+{
+  int ret;
+  const gchar *command;
+  gboolean request_completion;
+  gchar *completion_cur;
+  gchar *completion_prev;
+
+  setlocale (LC_ALL, "");
+
+  bindtextdomain (GETTEXT_PACKAGE, TERM_LOCALEDIR);
+  bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
+  textdomain (GETTEXT_PACKAGE);
+
+  g_type_init ();
+
+  ret = EXIT_FAILURE;
+  completion_cur = NULL;
+  completion_prev = NULL;
+
+  g_type_init ();
+
+  if (argc < 2)
+    {
+      usage (&argc, &argv, FALSE);
+      goto out;
+    }
+
+  request_completion = FALSE;
+
+  //completion_debug ("---- argc=%d --------------------------------------------------------", argc);
+
+ again:
+  command = argv[1];
+  if (g_strcmp0 (command, "help") == 0)
+    {
+      if (request_completion)
+        {
+          /* do nothing */
+        }
+      else
+        {
+          usage (&argc, &argv, TRUE);
+          ret = EXIT_SUCCESS;
+        }
+      goto out;
+    }
+  else if (g_strcmp0 (command, "open") == 0)
+    {
+      if (handle_open (&argc,
+                       &argv,
+                       request_completion,
+                       completion_cur,
+                       completion_prev))
+        ret = EXIT_SUCCESS;
+      goto out;
+    }
+  else if (g_strcmp0 (command, "complete") == 0 && argc == 4 && !request_completion)
+    {
+      const gchar *completion_line;
+      gchar **completion_argv;
+      gint completion_argc;
+      gint completion_point;
+      gchar *endp;
+      gint cur_begin;
+
+      request_completion = TRUE;
+
+      completion_line = argv[2];
+      completion_point = strtol (argv[3], &endp, 10);
+      if (endp == argv[3] || *endp != '\0')
+        goto out;
+
+#if 0
+      completion_debug ("completion_point=%d", completion_point);
+      completion_debug ("----");
+      completion_debug (" 0123456789012345678901234567890123456789012345678901234567890123456789");
+      completion_debug ("`%s'", completion_line);
+      completion_debug (" %*s^",
+                         completion_point, "");
+      completion_debug ("----");
+#endif
+
+      if (!g_shell_parse_argv (completion_line,
+                               &completion_argc,
+                               &completion_argv,
+                               NULL))
+        {
+          /* it's very possible the command line can't be parsed (for
+           * example, missing quotes etc) - in that case, we just
+           * don't autocomplete at all
+           */
+          goto out;
+        }
+
+      /* compute cur and prev */
+      completion_prev = NULL;
+      completion_cur = pick_word_at (completion_line, completion_point, &cur_begin);
+      if (cur_begin > 0)
+        {
+          gint prev_end;
+          for (prev_end = cur_begin - 1; prev_end >= 0; prev_end--)
+            {
+              if (!g_ascii_isspace (completion_line[prev_end]))
+                {
+                  completion_prev = pick_word_at (completion_line, prev_end, NULL);
+                  break;
+                }
+            }
+        }
+#if 0
+      completion_debug (" cur=`%s'", completion_cur);
+      completion_debug ("prev=`%s'", completion_prev);
+#endif
+
+      argc = completion_argc;
+      argv = completion_argv;
+
+      ret = EXIT_SUCCESS;
+
+      goto again;
+    }
+  else
+    {
+      if (request_completion)
+        {
+          g_print ("help \nopen \n");
+          ret = EXIT_SUCCESS;
+          goto out;
+        }
+      else
+        {
+          g_printerr ("Unknown command `%s'\n", command);
+          usage (&argc, &argv, FALSE);
+          goto out;
+        }
+    }
+
+ out:
+  g_free (completion_cur);
+  g_free (completion_prev);
+
+  return ret;
+}
diff --git a/src/org.gnome.Terminal.xml b/src/org.gnome.Terminal.xml
index ad00073..ba68dd5 100644
--- a/src/org.gnome.Terminal.xml
+++ b/src/org.gnome.Terminal.xml
@@ -20,12 +20,19 @@
 <node>
   <interface name="org.gnome.Terminal.Factory0">
     <annotation name="org.gtk.GDBus.C.Name" value="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="aay" name="environment" direction="in" />
-      <arg type="aay" name="arguments" direction="in" />
+    <method name="CreateInstance">
+      <arg type="a{sv}" name="options" direction="in" />
+      <arg type="o" name="receiver" direction="out" />
+    </method>
+  </interface>
+
+  <interface name="org.gnome.Terminal.Terminal0">
+    <annotation name="org.gtk.GDBus.C.Name" value="Receiver" />
+    <method name="Exec">
+      <arg type="a{sv}" name="options" direction="in" />
+      <arg type="aay" name="arguments" direction="in">
+        <annotation name="org.gtk.GDBus.C.ForceGVariant" value="true" />
+      </arg>
     </method>
   </interface>
 </node>
diff --git a/src/server.c b/src/server.c
index 680a603..ba245ac 100644
--- a/src/server.c
+++ b/src/server.c
@@ -31,28 +31,17 @@
 #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-factory.h"
+#include "terminal-gdbus-generated.h"
 #include "terminal-intl.h"
-#include "terminal-options.h"
 #include "terminal-util.h"
+#include "terminal-defines.h"
 
-#define TERMINAL_UNIQUE_NAME                  "org.gnome.Terminal"
-
-#define TERMINAL_OBJECT_PATH_PREFIX           "/org/gnome/Terminal"
-#define TERMINAL_OBJECT_INTERFACE_PREFIX      "org.gnome.Terminal"
-
-#define TERMINAL_FACTORY_OBJECT_PATH          TERMINAL_OBJECT_PATH_PREFIX "/Factory0"
-#define TERMINAL_FACTORY_INTERFACE_NAME       TERMINAL_OBJECT_INTERFACE_PREFIX ".Factory0"
+GDBusObjectManagerServer *object_manager;
 
 typedef struct {
-  GDBusObjectManagerServer *manager;
   int exit_code;
 } OwnData;
 
@@ -61,7 +50,6 @@ bus_acquired_cb (GDBusConnection *connection,
                  const char *name,
                  gpointer user_data)
 {
-  OwnData *data = (OwnData *) user_data;
   TerminalObjectSkeleton *object;
 
   _terminal_debug_print (TERMINAL_DEBUG_FACTORY,
@@ -69,11 +57,11 @@ bus_acquired_cb (GDBusConnection *connection,
 
   object = terminal_object_skeleton_new (TERMINAL_FACTORY_OBJECT_PATH);
   terminal_object_skeleton_set_factory (object, TERMINAL_FACTORY (terminal_app_get ()));
-  g_dbus_object_manager_server_export (data->manager, G_DBUS_OBJECT_SKELETON (object));
+  g_dbus_object_manager_server_export (object_manager, G_DBUS_OBJECT_SKELETON (object));
   g_object_unref (object);
 
   /* And export the object */
-  g_dbus_object_manager_server_set_connection (data->manager, connection);
+  g_dbus_object_manager_server_set_connection (object_manager, connection);
 }
 
 static void
@@ -100,6 +88,7 @@ name_lost_cb (GDBusConnection *connection,
   }
 
   data->exit_code = EXIT_FAILURE;
+
   gtk_main_quit ();
 }
 
@@ -109,7 +98,6 @@ main (int argc, char **argv)
   OwnData data;
   guint owner_id;
   const char *home_dir;
-  GdkDisplay *display;
   GError *error = NULL;
 
   setlocale (LC_ALL, "");
@@ -139,16 +127,9 @@ main (int argc, char **argv)
     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");
+  object_manager = g_dbus_object_manager_server_new (TERMINAL_OBJECT_PATH_PREFIX);
 
   data.exit_code = EXIT_FAILURE;
-  data.manager = g_dbus_object_manager_server_new (TERMINAL_OBJECT_PATH_PREFIX);
-
   owner_id = g_bus_own_name (G_BUS_TYPE_STARTER,
                              TERMINAL_UNIQUE_NAME,
                              G_BUS_NAME_OWNER_FLAGS_NONE,
@@ -161,7 +142,12 @@ main (int argc, char **argv)
 
   g_bus_unown_name (owner_id);
 
-  g_object_unref (data.manager);
+  g_dbus_object_manager_server_unexport (object_manager, TERMINAL_FACTORY_OBJECT_PATH);
+  if (data.exit_code == EXIT_SUCCESS)
+    g_dbus_connection_flush_sync (g_dbus_object_manager_server_get_connection (object_manager),
+                                  NULL /* cancellable */, NULL /* error */);
+  g_object_unref (object_manager);
+  object_manager = NULL;
 
   terminal_app_shutdown ();
 
diff --git a/src/terminal-app.c b/src/terminal-app.c
index 1040da0..ae18e24 100644
--- a/src/terminal-app.c
+++ b/src/terminal-app.c
@@ -37,7 +37,10 @@
 #include "profile-editor.h"
 #include "terminal-encoding.h"
 #include "terminal-schemas.h"
-#include "terminal-factory.h"
+#include "terminal-gdbus-generated.h"
+#include "terminal-controller.h"
+#include "terminal-defines.h"
+
 #include <string.h>
 #include <stdlib.h>
 #include <time.h>
@@ -53,6 +56,10 @@
 
 #define SYSTEM_PROXY_SETTINGS_SCHEMA            "org.gnome.system.proxy"
 
+#define CONTROLLER_SKELETON_DATA_KEY  "terminal-object-skeleton"
+
+extern GDBusObjectManagerServer *object_manager;
+
 /*
  * Session state is stored entirely in the RestartCommand command line.
  *
@@ -74,6 +81,8 @@ struct _TerminalApp
 {
   TerminalFactorySkeleton parent_instance;
 
+  GDBusObjectManagerServer *object_manager;
+  
   GList *windows;
   GtkWidget *new_profile_dialog;
   GtkWidget *manage_profiles_dialog;
@@ -1119,52 +1128,160 @@ terminal_app_client_quit_cb (EggSMClient *client,
 
 #endif /* WITH_SMCLIENT */
 
+static void
+screen_destroy_cb (GObject *screen,
+                   gpointer user_data)
+{
+  GDBusObjectSkeleton *skeleton;
+  const char *object_path;
+
+  skeleton = g_object_get_data (screen, CONTROLLER_SKELETON_DATA_KEY);
+  if (skeleton == NULL)
+    return;
+
+  object_path = g_dbus_object_get_object_path (G_DBUS_OBJECT (skeleton));
+  g_dbus_object_manager_server_unexport (object_manager, object_path);
+  g_object_set_data (screen, CONTROLLER_SKELETON_DATA_KEY, NULL);
+}
+
 /* Class implementation */
 
 static gboolean
-terminal_app_handle_arguments (TerminalFactory *factory,
-                               GDBusMethodInvocation *invocation,
-                               const char *working_directory,
-                               const char *display_name,
-                               const char *startup_id,
-                               const char * const *envv,
-                               const char * const *argv)
+terminal_app_create_instance (TerminalFactory *factory,
+                              GDBusMethodInvocation *invocation,
+                              GVariant *options)
 {
   TerminalApp *app = TERMINAL_APP (factory);
-  TerminalOptions *options;
-  int argc;
-  GError *error = NULL;
-
-  _terminal_debug_print (TERMINAL_DEBUG_FACTORY,
-                         "Factory invoked with working-dir='%s' display='%s' startup-id='%s'\n",
-                         working_directory, display_name, startup_id);
-
-  argc = g_strv_length ((char **) argv);
-  options = terminal_options_parse (working_directory,
-                                    display_name,
-                                    startup_id,
-                                    (char **) envv,
-                                    TRUE,
-                                    TRUE,
-                                    &argc, (char ***) &argv,
-                                    &error,
-                                    NULL);
-
-  if (options == NULL) {
-    g_dbus_method_invocation_take_error (invocation, error);
+  TerminalWindow *window;
+  TerminalScreen *screen;
+  TerminalController *controller;
+  TerminalObjectSkeleton *skeleton;
+  char *object_path;
+  GSettings *profile = NULL;
+  GdkScreen *gdk_screen;
+  const char *startup_id, *display_name, *working_directory;
+  int screen_number;
+  gboolean is_restored = FALSE;
+  gboolean start_fullscreen = FALSE;
+  gboolean start_maximized = FALSE;
+  gboolean force_menubar_state = FALSE, menubar_state = TRUE;
+  char *role = NULL;
+  char *title = NULL;
+  char *profile_name = NULL;
+  gboolean zoom_set = FALSE;
+  gdouble zoom = 1.0;
+  gboolean active = TRUE;
+  char *geometry = NULL;
+
+  if (!g_variant_lookup (options, "display", "^&ay", &display_name)) {
+    g_dbus_method_invocation_return_error (invocation, 
+                                           G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
+                                           "No display specified");
     goto out;
   }
 
-  if (!terminal_app_handle_options (app, options, FALSE /* no resume */, &error)) {
-    g_dbus_method_invocation_take_error (invocation, error);
+  screen_number = 0;
+  gdk_screen = terminal_app_get_screen_by_display_name (display_name, screen_number);
+  if (gdk_screen == NULL) {
+    g_dbus_method_invocation_return_error (invocation, 
+                                           G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
+                                           "No screen %d on display \"%s\"",
+                                           screen_number, display_name);
     goto out;
   }
 
-  terminal_factory_complete_handle_arguments (factory, invocation);
+  if (!g_variant_lookup (options, "desktop-startup-id", "^&ay", &startup_id))
+    startup_id = NULL;
+
+  if (startup_id != NULL)
+    _terminal_debug_print (TERMINAL_DEBUG_FACTORY,
+                           "Startup ID is '%s'\n", startup_id);
+  if (working_directory != NULL)
+    _terminal_debug_print (TERMINAL_DEBUG_FACTORY,
+                           "CWD is '%s'\n", working_directory);
+
+  if (!g_variant_lookup (options, "zoom", "d", &zoom))
+    zoom_set = FALSE;
+
+  window = terminal_app_new_window (app, gdk_screen);
+
+  /* Restored windows shouldn't demand attention; see bug #586308. */
+  if (is_restored)
+    terminal_window_set_is_restored (window);
+
+  if (startup_id != NULL)
+    gtk_window_set_startup_id (GTK_WINDOW (window), startup_id);
+
+  /* Overwrite the default, unique window role set in terminal_window_init */
+  if (role)
+    gtk_window_set_role (GTK_WINDOW (window), role);
+
+  if (force_menubar_state)
+    terminal_window_set_menubar_visible (window, menubar_state);
+
+  if (start_fullscreen)
+    gtk_window_fullscreen (GTK_WINDOW (window));
+  if (start_maximized)
+    gtk_window_maximize (GTK_WINDOW (window));
+
+  if (profile_name)
+    {
+      if (TRUE /* profile_is_id */)
+        profile = terminal_app_get_profile_by_name (app, profile_name);
+      else
+        profile = terminal_app_get_profile_by_visible_name (app, profile_name);
+
+      if (profile == NULL)
+        _terminal_debug_print (TERMINAL_DEBUG_FACTORY,
+                               "No such profile \"%s\", using default profile", 
+                               profile_name);
+    }
+  if (profile == NULL)
+    profile = g_object_ref (g_hash_table_lookup (app->profiles, "profile0"));
+  g_assert (profile);
+
+  screen = terminal_screen_new (profile, NULL, title, NULL, NULL, 
+                                zoom_set ? zoom : 1.0);
+  terminal_window_add_screen (window, screen, -1);
+  terminal_window_switch_screen (window, screen);
+  gtk_widget_grab_focus (GTK_WIDGET (screen));
+
+  // FIXMEchpe make this better!
+  object_path = g_strdup_printf (TERMINAL_CONTROLLER_OBJECT_PATH_PREFIX "/%u", (guint)g_random_int ());
+
+  skeleton = terminal_object_skeleton_new (object_path);
+  controller = terminal_controller_new (screen);
+  terminal_object_skeleton_set_receiver (skeleton, TERMINAL_RECEIVER (controller));
+  g_object_unref (controller);
+
+  g_dbus_object_manager_server_export (object_manager, G_DBUS_OBJECT_SKELETON (skeleton));
+  g_object_set_data_full (G_OBJECT (screen), CONTROLLER_SKELETON_DATA_KEY,
+                          skeleton, (GDestroyNotify) g_object_unref);
+  g_signal_connect (screen, "destroy",
+                    G_CALLBACK (screen_destroy_cb), app);
+
+  if (active)
+    terminal_window_switch_screen (window, screen);
+
+  if (geometry)
+    {
+      _terminal_debug_print (TERMINAL_DEBUG_GEOMETRY,
+                            "[window %p] applying geometry %s\n",
+                            window, geometry);
+
+      if (!terminal_window_parse_geometry (window, geometry))
+        _terminal_debug_print (TERMINAL_DEBUG_GEOMETRY,
+                               "Invalid geometry string \"%s\"", geometry);
+    }
+
+  gtk_window_present (GTK_WINDOW (window));
+
+  terminal_factory_complete_create_instance (factory, invocation, object_path);
+
+  g_free (object_path);
+  g_object_unref (profile);
 
 out:
-  if (options)
-    terminal_options_free (options);
 
   return TRUE; /* handled */
 }
@@ -1172,7 +1289,7 @@ out:
 static void
 terminal_factory_iface_init (TerminalFactoryIface *iface)
 {
-  iface->handle_handle_arguments = terminal_app_handle_arguments;
+  iface->handle_create_instance = terminal_app_create_instance;
 }
 
 G_DEFINE_TYPE_WITH_CODE (TerminalApp, terminal_app, TERMINAL_TYPE_FACTORY_SKELETON,
@@ -1345,163 +1462,6 @@ terminal_app_shutdown (void)
   g_settings_sync ();
 }
 
-/**
- * terminal_app_handle_options:
- * @app:
- * @options: a #TerminalOptions
- * @allow_resume: whether to merge the terminal configuration from the
- *   saved session on resume
- * @error: a #GError to fill in
- *
- * Processes @options. It loads or saves the terminal configuration, or
- * opens the specified windows and tabs.
- *
- * Returns: %TRUE if @options could be successfully handled, or %FALSE on
- *   error
- */
-gboolean
-terminal_app_handle_options (TerminalApp *app,
-                             TerminalOptions *options,
-                             gboolean allow_resume,
-                             GError **error)
-{
-  GList *lw;
-  GdkScreen *gdk_screen;
-
-  gdk_screen = terminal_app_get_screen_by_display_name (options->display_name,
-                                                        options->screen_number);
-
-  if (options->save_config)
-    {
-      if (options->remote_arguments)
-        return terminal_app_save_config_file (app, options->config_file, error);
-      
-      g_set_error_literal (error, TERMINAL_OPTION_ERROR, TERMINAL_OPTION_ERROR_NOT_IN_FACTORY,
-                            "Cannot use \"--save-config\" when starting the factory process");
-      return FALSE;
-    }
-
-  if (options->load_config)
-    {
-      GKeyFile *key_file;
-      gboolean result;
-
-      key_file = g_key_file_new ();
-      result = g_key_file_load_from_file (key_file, options->config_file, 0, error) &&
-               terminal_options_merge_config (options, key_file, SOURCE_DEFAULT, error);
-      g_key_file_free (key_file);
-
-      if (!result)
-        return FALSE;
-
-      /* fall-through on success */
-    }
-
-#ifdef WITH_SMCLIENT
-{
-  EggSMClient *sm_client;
-
-  sm_client = egg_sm_client_get ();
-
-  if (allow_resume && egg_sm_client_is_resumed (sm_client))
-    {
-      GKeyFile *key_file;
-
-      key_file = egg_sm_client_get_state_file (sm_client);
-      if (key_file != NULL &&
-          !terminal_options_merge_config (options, key_file, SOURCE_SESSION, error))
-        return FALSE;
-    }
-}
-#endif
-
-  /* Make sure we open at least one window */
-  terminal_options_ensure_window (options);
-
-  if (options->startup_id != NULL)
-    _terminal_debug_print (TERMINAL_DEBUG_FACTORY,
-                           "Startup ID is '%s'\n",
-                           options->startup_id);
-
-  for (lw = options->initial_windows;  lw != NULL; lw = lw->next)
-    {
-      InitialWindow *iw = lw->data;
-      TerminalWindow *window;
-      GList *lt;
-
-      g_assert (iw->tabs);
-
-      /* Create & setup new window */
-      window = terminal_app_new_window (app, gdk_screen);
-
-      /* Restored windows shouldn't demand attention; see bug #586308. */
-      if (iw->source_tag == SOURCE_SESSION)
-        terminal_window_set_is_restored (window);
-
-      if (options->startup_id != NULL)
-        gtk_window_set_startup_id (GTK_WINDOW (window), options->startup_id);
-
-      /* Overwrite the default, unique window role set in terminal_window_init */
-      if (iw->role)
-        gtk_window_set_role (GTK_WINDOW (window), iw->role);
-
-      if (iw->force_menubar_state)
-        terminal_window_set_menubar_visible (window, iw->menubar_state);
-
-      if (iw->start_fullscreen)
-        gtk_window_fullscreen (GTK_WINDOW (window));
-      if (iw->start_maximized)
-        gtk_window_maximize (GTK_WINDOW (window));
-
-      /* Now add the tabs */
-      for (lt = iw->tabs; lt != NULL; lt = lt->next)
-        {
-          InitialTab *it = lt->data;
-          GSettings *profile = NULL;
-          TerminalScreen *screen;
-
-          if (it->profile)
-            {
-              if (it->profile_is_id)
-                profile = terminal_app_get_profile_by_name (app, it->profile);
-              else
-                profile = terminal_app_get_profile_by_visible_name (app, it->profile);
-
-              if (profile == NULL)
-                g_printerr (_("No such profile \"%s\", using default profile\n"), it->profile);
-            }
-          if (profile == NULL)
-            profile = g_object_ref (g_hash_table_lookup (app->profiles, "profile0"));
-          g_assert (profile);
-
-          screen = terminal_app_new_terminal (app, window, profile,
-                                              it->exec_argv ? it->exec_argv : options->exec_argv,
-                                              it->title ? it->title : options->default_title,
-                                              it->working_dir ? it->working_dir : options->default_working_dir,
-                                              options->env,
-                                              it->zoom_set ? it->zoom : options->zoom);
-          g_object_unref (profile);
-
-          if (it->active)
-            terminal_window_switch_screen (window, screen);
-        }
-
-      if (iw->geometry)
-        {
-          _terminal_debug_print (TERMINAL_DEBUG_GEOMETRY,
-                                "[window %p] applying geometry %s\n",
-                                window, iw->geometry);
-
-          if (!terminal_window_parse_geometry (window, iw->geometry))
-            g_printerr (_("Invalid geometry string \"%s\"\n"), iw->geometry);
-        }
-
-      gtk_window_present (GTK_WINDOW (window));
-    }
-
-  return TRUE;
-}
-
 TerminalWindow *
 terminal_app_new_window (TerminalApp *app,
                          GdkScreen *screen)
@@ -1542,6 +1502,9 @@ terminal_app_new_terminal (TerminalApp     *app,
   terminal_window_switch_screen (window, screen);
   gtk_widget_grab_focus (GTK_WIDGET (screen));
 
+  /* Launch the child on idle */
+  _terminal_screen_launch_child_on_idle (screen);
+
   return screen;
 }
 
diff --git a/src/terminal-app.h b/src/terminal-app.h
index 13a2231..5ec789b 100644
--- a/src/terminal-app.h
+++ b/src/terminal-app.h
@@ -25,7 +25,6 @@
 
 #include "terminal-encoding.h"
 #include "terminal-screen.h"
-#include "terminal-options.h"
 
 G_BEGIN_DECLS
 
@@ -77,10 +76,7 @@ TerminalApp* terminal_app_get (void);
 
 void terminal_app_shutdown (void);
 
-gboolean terminal_app_handle_options (TerminalApp *app,
-                                      TerminalOptions *options,
-                                      gboolean allow_resume,
-                                      GError **error);
+GDBusObjectManagerServer *terminal_app_get_object_manager (TerminalApp *app);
 
 void terminal_app_edit_profile (TerminalApp *app,
                                 GSettings   *profile,
diff --git a/src/terminal-controller.c b/src/terminal-controller.c
new file mode 100644
index 0000000..657ecd0
--- /dev/null
+++ b/src/terminal-controller.c
@@ -0,0 +1,243 @@
+/*
+ * Copyright  2011 Christian Persch
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3, or (at your option)
+ *  any later version.
+ *
+ *  This program is distributed in the hope controller 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, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include "terminal-controller.h"
+#include "terminal-debug.h"
+
+#define TERMINAL_CONTROLLER_GET_PRIVATE(controller)(G_TYPE_INSTANCE_GET_PRIVATE ((controller), TERMINAL_TYPE_CONTROLLER, TerminalControllerPrivate))
+
+struct _TerminalControllerPrivate {
+  TerminalScreen *screen; /* unowned! */
+};
+
+enum {
+  PROP_0,
+  PROP_SCREEN
+};
+
+/* helper functions */
+
+static void
+terminal_controller_set_screen (TerminalController *controller,
+                                TerminalScreen *screen)
+{
+  TerminalControllerPrivate *priv;
+
+  g_return_if_fail (TERMINAL_IS_CONTROLLER (controller));
+  g_return_if_fail (screen == NULL || TERMINAL_IS_SCREEN (screen));
+
+  priv = controller->priv;
+  if (priv->screen == screen)
+    return;
+
+  if (priv->screen) {
+    g_signal_handlers_disconnect_by_func (priv->screen,
+                                          G_CALLBACK (_terminal_controller_unset_screen),
+                                          controller);
+  }
+
+  priv->screen = screen;
+  if (screen) {
+    g_signal_connect_swapped (screen, "destroy",
+                              G_CALLBACK (_terminal_controller_unset_screen), 
+                              controller);
+  }
+
+  g_object_notify (G_OBJECT (controller), "screen");
+}
+
+/* Class implementation */
+
+static gboolean 
+terminal_controller_exec (TerminalReceiver *receiver,
+                          GDBusMethodInvocation *invocation,
+                          GVariant *options,
+                          GVariant *arguments)
+{
+  TerminalController *controller = TERMINAL_CONTROLLER (receiver);
+  TerminalControllerPrivate *priv = controller->priv;
+  const char *working_directory;
+  char **exec_argv, **envv;
+  gsize exec_argc;
+  GError *error;
+
+  if (priv->screen == NULL) {
+    g_dbus_method_invocation_return_error_literal (invocation,
+                                                   G_DBUS_ERROR,
+                                                   G_DBUS_ERROR_FAILED,
+                                                   "Terminal already closed");
+    goto out;
+  }
+
+  if (!g_variant_lookup (options, "cwd", "^&ay", &working_directory))
+    working_directory = NULL;
+  if (!g_variant_lookup (options, "environ", "^a&ay", &envv))
+    envv = NULL;
+
+  if (working_directory != NULL)
+    _terminal_debug_print (TERMINAL_DEBUG_FACTORY,
+                           "CWD is '%s'\n", working_directory);
+
+  exec_argv = (char **) g_variant_get_bytestring_array (arguments, &exec_argc);
+
+  error = NULL;
+  if (!terminal_screen_exec (priv->screen,
+                             exec_argc > 0 ? exec_argv : NULL,
+                             envv,
+                             working_directory,
+                             &error)) {
+    g_dbus_method_invocation_take_error (invocation, error);
+  } else {
+    terminal_receiver_complete_exec (receiver, invocation);
+  }
+
+  g_free (exec_argv);
+  g_free (envv);
+
+out:
+
+  return TRUE; /* handled */
+}
+
+static void
+terminal_controller_iface_init (TerminalReceiverIface *iface)
+{
+  iface->handle_exec = terminal_controller_exec;
+}
+
+G_DEFINE_TYPE_WITH_CODE (TerminalController, terminal_controller, TERMINAL_TYPE_RECEIVER_SKELETON,
+                         G_IMPLEMENT_INTERFACE (TERMINAL_TYPE_RECEIVER, terminal_controller_iface_init))
+
+static void
+terminal_controller_init (TerminalController *controller)
+{
+  controller->priv = TERMINAL_CONTROLLER_GET_PRIVATE (controller);
+}
+
+static void
+terminal_controller_dispose (GObject *object)
+{
+  TerminalController *controller = TERMINAL_CONTROLLER (object);
+
+  terminal_controller_set_screen (controller, NULL);
+
+  G_OBJECT_CLASS (terminal_controller_parent_class)->dispose (object);
+}
+
+static void
+terminal_controller_get_property (GObject *object,
+                                  guint prop_id,
+                                  GValue *value,
+                                  GParamSpec *pspec)
+{
+  TerminalController *controller = TERMINAL_CONTROLLER (object);
+
+  switch (prop_id) {
+    case PROP_SCREEN:
+      g_value_set_object (value, terminal_controller_get_screen (controller));
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+static void
+terminal_controller_set_property (GObject *object,
+                                        guint prop_id,
+                                        const GValue *value,
+                                        GParamSpec *pspec)
+{
+  TerminalController *controller = TERMINAL_CONTROLLER (object);
+
+  switch (prop_id) {
+    case PROP_SCREEN:
+      terminal_controller_set_screen (controller, g_value_get_object (value));
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+static void
+terminal_controller_class_init (TerminalControllerClass *klass)
+{
+  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+  gobject_class->dispose = terminal_controller_dispose;
+  gobject_class->get_property = terminal_controller_get_property;
+  gobject_class->set_property = terminal_controller_set_property;
+
+  g_object_class_install_property
+     (gobject_class,
+      PROP_SCREEN,
+      g_param_spec_object ("screen", NULL, NULL,
+                          TERMINAL_TYPE_SCREEN,
+                          G_PARAM_READWRITE |
+                          G_PARAM_CONSTRUCT_ONLY |
+                          G_PARAM_STATIC_STRINGS));
+
+  g_type_class_add_private (gobject_class, sizeof (TerminalControllerPrivate));
+}
+
+/* public API */
+
+/**
+ * terminal_controller_new:
+ * @screen: a #TerminalScreen
+ *
+ * Returns: a new #TerminalController for @screen
+ */
+TerminalController *
+terminal_controller_new (TerminalScreen *screen)
+{
+  return g_object_new (TERMINAL_TYPE_CONTROLLER, 
+                       "screen", screen, 
+                       NULL);
+}
+
+/**
+ * terminal_controller_get_screen:
+ * @controller: a #TerminalController
+ * 
+ * Returns: (transfer none): the controller's #TerminalScreen, or %NULL
+ */
+TerminalScreen *
+terminal_controller_get_screen (TerminalController *controller)
+{
+  g_return_val_if_fail (TERMINAL_IS_CONTROLLER (controller), NULL);
+
+  return controller->priv->screen;
+}
+
+/**
+ * terminal_controller_get_screen:
+ * @controller: a #TerminalController
+ * 
+ * Unsets the controllers #TerminalScreen.
+ */
+void
+_terminal_controller_unset_screen (TerminalController *controller)
+{
+  g_return_if_fail (TERMINAL_IS_CONTROLLER (controller));
+
+  terminal_controller_set_screen (controller, NULL);
+}
\ No newline at end of file
diff --git a/src/terminal-controller.h b/src/terminal-controller.h
new file mode 100644
index 0000000..a7fa3f3
--- /dev/null
+++ b/src/terminal-controller.h
@@ -0,0 +1,63 @@
+/*
+ *  Copyright  2011 Christian Persch
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3, or (at your option)
+ *  any later version.
+ *
+ *  This program is distributed in the hope controller 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, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef TERMINAL_CONTROLLER_H
+#define TERMINAL_CONTROLLER_H
+
+#include <glib-object.h>
+
+#include "terminal-gdbus-generated.h"
+#include "terminal-screen.h"
+
+G_BEGIN_DECLS
+
+#define TERMINAL_TYPE_CONTROLLER         (terminal_controller_get_type ())
+#define TERMINAL_CONTROLLER(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), TERMINAL_TYPE_CONTROLLER, TerminalController))
+#define TERMINAL_CONTROLLER_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST((k), TERMINAL_TYPE_CONTROLLER, TerminalControllerClass))
+#define TERMINAL_IS_CONTROLLER(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), TERMINAL_TYPE_CONTROLLER))
+#define TERMINAL_IS_CONTROLLER_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE ((k), TERMINAL_TYPE_CONTROLLER))
+#define TERMINAL_CONTROLLER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), TERMINAL_TYPE_CONTROLLER, TerminalControllerClass))
+
+typedef struct _TerminalController        TerminalController;
+typedef struct _TerminalControllerClass   TerminalControllerClass;
+typedef struct _TerminalControllerPrivate TerminalControllerPrivate;
+
+struct _TerminalController
+{
+  TerminalReceiverSkeleton parent_instance;
+
+  /*< private >*/
+  TerminalControllerPrivate *priv;
+};
+
+struct _TerminalControllerClass
+{
+  TerminalReceiverSkeletonClass parent_class;
+};
+
+GType terminal_controller_get_type (void);
+
+TerminalController *terminal_controller_new (TerminalScreen *screen);
+
+TerminalScreen *terminal_controller_get_screen (TerminalController *controller);
+
+void _terminal_controller_unset_screen (TerminalController *controller);
+
+G_END_DECLS
+
+#endif /* !TERMINAL_CONTROLLER_H */
diff --git a/src/terminal-defines.h b/src/terminal-defines.h
new file mode 100644
index 0000000..aebcb9b
--- /dev/null
+++ b/src/terminal-defines.h
@@ -0,0 +1,37 @@
+/*
+ *  Copyright  2011 Christian Persch
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3, or (at your option)
+ *  any later version.
+ *
+ *  This program is distributed in the hope controller 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, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef TERMINAL_DEFINES_H
+#define TERMINAL_DEFINES_H
+
+G_BEGIN_DECLS
+
+#define TERMINAL_UNIQUE_NAME                    "org.gnome.Terminal"
+
+#define TERMINAL_OBJECT_PATH_PREFIX             "/org/gnome/Terminal"
+#define TERMINAL_OBJECT_INTERFACE_PREFIX        "org.gnome.Terminal"
+
+#define TERMINAL_FACTORY_OBJECT_PATH            TERMINAL_OBJECT_PATH_PREFIX "/Factory0"
+#define TERMINAL_FACTORY_INTERFACE_NAME         TERMINAL_OBJECT_INTERFACE_PREFIX ".Factory0"
+
+#define TERMINAL_CONTROLLER_OBJECT_PATH_PREFIX  TERMINAL_OBJECT_PATH_PREFIX "/Terminals"
+#define TEMRINAL_CONTROLLER_INTERFACE_NAME      TERMINAL_OBJECT_INTERFACE_PREFIX ".Terminal0"
+
+G_END_DECLS
+
+#endif /* !TERMINAL_DEFINES_H */
diff --git a/src/terminal-options.c b/src/terminal-options.c
index a4e179c..5e5a62a 100644
--- a/src/terminal-options.c
+++ b/src/terminal-options.c
@@ -1042,7 +1042,7 @@ get_goption_context (TerminalOptions *options)
       0,
       G_OPTION_ARG_CALLBACK,
       option_geometry_callback,
-      N_("Set the window size; for example: 80x24, or 80x24+200+200 (ROWSxCOLS+X+Y)"),
+      N_("Set the window size; for example: 80x24, or 80x24+200+200 (COLSxROWS+X+Y)"),
       N_("GEOMETRY")
     },
     {
diff --git a/src/terminal-options.h b/src/terminal-options.h
index 30f455f..536d6e9 100644
--- a/src/terminal-options.h
+++ b/src/terminal-options.h
@@ -87,6 +87,7 @@ typedef struct
 #define TERMINAL_OPTION_ERROR (g_quark_from_static_string ("terminal-option-error"))
 
 typedef enum {
+  TERMINAL_OPTION_ERROR_NOT_SUPPORTED,
   TERMINAL_OPTION_ERROR_NOT_IN_FACTORY,
   TERMINAL_OPTION_ERROR_EXCLUSIVE_OPTIONS,
   TERMINAL_OPTION_ERROR_INVALID_CONFIG_FILE,
diff --git a/src/terminal-screen.c b/src/terminal-screen.c
index eec3bf4..6394284 100644
--- a/src/terminal-screen.c
+++ b/src/terminal-screen.c
@@ -116,7 +116,7 @@ static void terminal_screen_change_font (TerminalScreen *screen);
 static gboolean terminal_screen_popup_menu (GtkWidget *widget);
 static gboolean terminal_screen_button_press (GtkWidget *widget,
                                               GdkEventButton *event);
-static void terminal_screen_launch_child_on_idle (TerminalScreen *screen);
+static gboolean terminal_screen_do_exec (TerminalScreen *screen, GError **error);
 static void terminal_screen_child_exited  (VteTerminal *terminal);
 
 static void terminal_screen_window_title_changed      (VteTerminal *vte_terminal,
@@ -676,12 +676,34 @@ terminal_screen_new (GSettings       *profile,
   terminal_screen_set_font_scale (screen, zoom);
   terminal_screen_set_font (screen);
 
-  /* Launch the child on idle */
-  terminal_screen_launch_child_on_idle (screen);
-
   return screen;
 }
 
+gboolean 
+terminal_screen_exec (TerminalScreen *screen,
+                      char          **argv,
+                      char          **envv,
+                      const char     *cwd,
+                      GError        **error)
+{
+  TerminalScreenPrivate *priv;
+
+  g_return_val_if_fail (TERMINAL_IS_SCREEN (screen), FALSE);
+  g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+  priv = screen->priv;
+
+  terminal_screen_set_initial_environment (screen, envv);
+
+  if (argv)
+    terminal_screen_set_override_command (screen, argv);
+
+  g_free (priv->initial_working_directory);
+  priv->initial_working_directory = g_strdup (cwd);
+
+  return terminal_screen_do_exec (screen, error);
+}
+
 const char*
 terminal_screen_get_raw_title (TerminalScreen *screen)
 {
@@ -1296,7 +1318,7 @@ info_bar_response_cb (GtkWidget *info_bar,
       break;
     case RESPONSE_RELAUNCH:
       gtk_widget_destroy (info_bar);
-      terminal_screen_launch_child_on_idle (screen);
+      _terminal_screen_launch_child_on_idle (screen);
       break;
     case RESPONSE_EDIT_PROFILE:
       terminal_app_edit_profile (terminal_app_get (),
@@ -1311,7 +1333,8 @@ info_bar_response_cb (GtkWidget *info_bar,
 }
 
 static gboolean
-terminal_screen_launch_child_cb (TerminalScreen *screen)
+terminal_screen_do_exec (TerminalScreen *screen,
+                         GError **error)
 {
   TerminalScreenPrivate *priv = screen->priv;
   VteTerminal *terminal = VTE_TERMINAL (screen);
@@ -1372,10 +1395,10 @@ terminal_screen_launch_child_cb (TerminalScreen *screen)
     gtk_info_bar_set_default_response (GTK_INFO_BAR (info_bar), GTK_RESPONSE_CANCEL);
     gtk_widget_show (info_bar);
 
-    g_error_free (err);
     g_strfreev (env);
     g_free (shell);
 
+    g_propagate_error (error, err);
     return FALSE;
   }
 
@@ -1386,11 +1409,18 @@ terminal_screen_launch_child_cb (TerminalScreen *screen)
   g_strfreev (argv);
   g_strfreev (env);
 
+  return TRUE;
+}
+
+static gboolean
+terminal_screen_launch_child_cb (TerminalScreen *screen)
+{
+  terminal_screen_do_exec (screen, NULL /* don't care */);
   return FALSE; /* don't run again */
 }
 
-static void
-terminal_screen_launch_child_on_idle (TerminalScreen *screen)
+void
+_terminal_screen_launch_child_on_idle (TerminalScreen *screen)
 {
   TerminalScreenPrivate *priv = screen->priv;
 
@@ -1732,7 +1762,7 @@ terminal_screen_child_exited (VteTerminal *terminal)
       g_signal_emit (screen, signals[CLOSE_SCREEN], 0);
       break;
     case TERMINAL_EXIT_RESTART:
-      terminal_screen_launch_child_on_idle (screen);
+      _terminal_screen_launch_child_on_idle (screen);
       break;
     case TERMINAL_EXIT_HOLD: {
       GtkWidget *info_bar;
diff --git a/src/terminal-screen.h b/src/terminal-screen.h
index 038326a..bba7d8a 100644
--- a/src/terminal-screen.h
+++ b/src/terminal-screen.h
@@ -81,6 +81,14 @@ TerminalScreen *terminal_screen_new (GSettings       *profile,
                                      char           **child_env,
                                      double           zoom);
 
+gboolean terminal_screen_exec (TerminalScreen *screen,
+                               char          **argv,
+                               char          **envv,
+                               const char     *cwd,
+                               GError        **error);
+
+void _terminal_screen_launch_child_on_idle (TerminalScreen *screen);
+
 void terminal_screen_set_profile (TerminalScreen *screen,
                                   GSettings      *profile);
 GSettings* terminal_screen_get_profile (TerminalScreen *screen);
diff --git a/src/terminal.c b/src/terminal.c
index 0ebd90f..2d8b2d3 100644
--- a/src/terminal.c
+++ b/src/terminal.c
@@ -41,15 +41,180 @@
 #include "terminal-debug.h"
 #include "terminal-intl.h"
 #include "terminal-options.h"
-#include "terminal-factory.h"
+#include "terminal-gdbus-generated.h"
+#include "terminal-defines.h"
+
+/**
+ * handle_options:
+ * @app:
+ * @options: a #TerminalOptions
+ * @allow_resume: whether to merge the terminal configuration from the
+ *   saved session on resume
+ * @error: a #GError to fill in
+ *
+ * Processes @options. It loads or saves the terminal configuration, or
+ * opens the specified windows and tabs.
+ *
+ * Returns: %TRUE if @options could be successfully handled, or %FALSE on
+ *   error
+ */
+static gboolean
+handle_options (TerminalFactory *factory,
+                TerminalOptions *options,
+                char **envv,
+                gboolean allow_resume,
+                GError **error)
+{
+#if 0
+  GList *lw;
+  GdkScreen *gdk_screen;
+
+  gdk_screen = terminal_app_get_screen_by_display_name (options->display_name,
+                                                        options->screen_number);
+
+  if (options->save_config)
+    {
+#if 0
+      if (options->remote_arguments)
+        return terminal_app_save_config_file (app, options->config_file, error);
+      
+      g_set_error_literal (error, TERMINAL_OPTION_ERROR, TERMINAL_OPTION_ERROR_NOT_IN_FACTORY,
+                            "Cannot use \"--save-config\" when starting the factory process");
+      return FALSE;
+#endif
+      g_set_error (error, TERMINAL_OPTION_ERROR, TERMINAL_OPTION_ERROR_NOT_SUPPORTED,
+                   "Not supported anymore");
+      return FALSE;
+    }
+
+  if (options->load_config)
+    {
+      GKeyFile *key_file;
+      gboolean result;
+
+      key_file = g_key_file_new ();
+      result = g_key_file_load_from_file (key_file, options->config_file, 0, error) &&
+               terminal_options_merge_config (options, key_file, SOURCE_DEFAULT, error);
+      g_key_file_free (key_file);
+
+      if (!result)
+        return FALSE;
+
+      /* fall-through on success */
+    }
+
+#ifdef WITH_SMCLIENT
+{
+  EggSMClient *sm_client;
+
+  sm_client = egg_sm_client_get ();
+
+  if (allow_resume && egg_sm_client_is_resumed (sm_client))
+    {
+      GKeyFile *key_file;
+
+      key_file = egg_sm_client_get_state_file (sm_client);
+      if (key_file != NULL &&
+          !terminal_options_merge_config (options, key_file, SOURCE_SESSION, error))
+        return FALSE;
+    }
+}
+#endif
+
+  /* Make sure we open at least one window */
+  terminal_options_ensure_window (options);
+
+  if (options->startup_id != NULL)
+    _terminal_debug_print (TERMINAL_DEBUG_FACTORY,
+                           "Startup ID is '%s'\n",
+                           options->startup_id);
+
+  for (lw = options->initial_windows;  lw != NULL; lw = lw->next)
+    {
+      InitialWindow *iw = lw->data;
+      GList *lt;
+#if 0
+      TerminalWindow *window;
 
-#define TERMINAL_UNIQUE_NAME                  "org.gnome.Terminal"
+      g_assert (iw->tabs);
 
-#define TERMINAL_OBJECT_PATH_PREFIX           "/org/gnome/Terminal"
-#define TERMINAL_OBJECT_INTERFACE_PREFIX      "org.gnome.Terminal"
+      /* Create & setup new window */
+      window = terminal_app_new_window (app, gdk_screen);
 
-#define TERMINAL_FACTORY_OBJECT_PATH          TERMINAL_OBJECT_PATH_PREFIX "/Factory0"
-#define TERMINAL_FACTORY_INTERFACE_NAME       TERMINAL_OBJECT_INTERFACE_PREFIX ".Factory0"
+      /* Restored windows shouldn't demand attention; see bug #586308. */
+      if (iw->source_tag == SOURCE_SESSION)
+        terminal_window_set_is_restored (window);
+
+      if (options->startup_id != NULL)
+        gtk_window_set_startup_id (GTK_WINDOW (window), options->startup_id);
+
+      /* Overwrite the default, unique window role set in terminal_window_init */
+      if (iw->role)
+        gtk_window_set_role (GTK_WINDOW (window), iw->role);
+
+      if (iw->force_menubar_state)
+        terminal_window_set_menubar_visible (window, iw->menubar_state);
+
+      if (iw->start_fullscreen)
+        gtk_window_fullscreen (GTK_WINDOW (window));
+      if (iw->start_maximized)
+        gtk_window_maximize (GTK_WINDOW (window));
+#endif
+
+      /* Now add the tabs */
+      for (lt = iw->tabs; lt != NULL; lt = lt->next)
+        {
+          InitialTab *it = lt->data;
+#if 0
+          GSettings *profile = NULL;
+          TerminalScreen *screen;
+
+          if (it->profile)
+            {
+              if (it->profile_is_id)
+                profile = terminal_app_get_profile_by_name (app, it->profile);
+              else
+                profile = terminal_app_get_profile_by_visible_name (app, it->profile);
+
+              if (profile == NULL)
+                g_printerr (_("No such profile \"%s\", using default profile\n"), it->profile);
+            }
+          if (profile == NULL)
+            profile = g_object_ref (g_hash_table_lookup (app->profiles, "profile0"));
+          g_assert (profile);
+
+          screen = terminal_app_new_terminal (app, window, profile,
+                                              it->exec_argv ? it->exec_argv : options->exec_argv,
+                                              it->title ? it->title : options->default_title,
+                                              it->working_dir ? it->working_dir : options->default_working_dir,
+                                              options->env,
+                                              it->zoom_set ? it->zoom : options->zoom);
+          g_object_unref (profile);
+
+          if (it->active)
+            terminal_window_switch_screen (window, screen);
+#endif
+        }
+
+#if 0
+      if (iw->geometry)
+        {
+          _terminal_debug_print (TERMINAL_DEBUG_GEOMETRY,
+                                "[window %p] applying geometry %s\n",
+                                window, iw->geometry);
+
+          if (!terminal_window_parse_geometry (window, iw->geometry))
+            g_printerr (_("Invalid geometry string \"%s\"\n"), iw->geometry);
+        }
+
+      gtk_window_present (GTK_WINDOW (window));
+#endif
+    }
+
+  return TRUE;
+#endif
+  return FALSE;
+}
 
 /* Copied from libnautilus/nautilus-program-choosing.c; Needed in case
  * we have no DESKTOP_STARTUP_ID (with its accompanying timestamp).
@@ -196,6 +361,7 @@ main (int argc, char **argv)
   }
 
   envv = g_get_environ ();
+#if 0
   if (!terminal_factory_call_handle_arguments_sync (factory,
                                                     working_directory ? working_directory : "",
                                                     display_name ? display_name : "",
@@ -207,6 +373,10 @@ main (int argc, char **argv)
     g_printerr ("Error opening terminal: %s\n", error->message);
     g_error_free (error);
   } else {
+#endif
+  if (!handle_options (factory, options, envv, TRUE /* allow resume */, &error)) {
+    g_printerr ("Failed to handle arguments: %s\n", error->message);
+  } else {
     exit_code = EXIT_SUCCESS;
   }
 



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