[gnome-terminal] server: Split off factory implementation



commit 19324e865cd129fb78fbd73b1d6b217ec5eb2544
Author: Christian Persch <chpe gnome org>
Date:   Fri Mar 30 19:02:50 2012 +0200

    server: Split off factory implementation
    
    Instead of making TerminalApp implement the factory, make this a separate
    object.

 src/server.c         |    8 +-
 src/terminal-app.c   |  272 +++++++------------------------------------------
 src/terminal-app.h   |    3 +
 src/terminal-gdbus.c |  205 +++++++++++++++++++++++++++++++++++++-
 src/terminal-gdbus.h |   28 +++++
 src/terminal-util.c  |   59 +++++++++++
 src/terminal-util.h  |    2 +
 7 files changed, 341 insertions(+), 236 deletions(-)
---
diff --git a/src/server.c b/src/server.c
index 58b1cfc..e6f0e8f 100644
--- a/src/server.c
+++ b/src/server.c
@@ -34,7 +34,7 @@
 #include "terminal-accels.h"
 #include "terminal-app.h"
 #include "terminal-debug.h"
-#include "terminal-gdbus-generated.h"
+#include "terminal-gdbus.h"
 #include "terminal-intl.h"
 #include "terminal-util.h"
 #include "terminal-defines.h"
@@ -78,12 +78,16 @@ bus_acquired_cb (GDBusConnection *connection,
                  gpointer user_data)
 {
   TerminalObjectSkeleton *object;
+  TerminalFactory *factory;
 
   _terminal_debug_print (TERMINAL_DEBUG_FACTORY,
                          "Bus %s acquired\n", name);
 
   object = terminal_object_skeleton_new (TERMINAL_FACTORY_OBJECT_PATH);
-  terminal_object_skeleton_set_factory (object, TERMINAL_FACTORY (terminal_app_get ()));
+  factory = terminal_factory_impl_new ();
+  terminal_object_skeleton_set_factory (object, factory);
+  g_object_unref (factory);
+
   g_dbus_object_manager_server_export (object_manager, G_DBUS_OBJECT_SKELETON (object));
   g_object_unref (object);
 
diff --git a/src/terminal-app.c b/src/terminal-app.c
index ad6cad5..c9516f2 100644
--- a/src/terminal-app.c
+++ b/src/terminal-app.c
@@ -37,7 +37,6 @@
 #include "profile-editor.h"
 #include "terminal-encoding.h"
 #include "terminal-schemas.h"
-#include "terminal-gdbus-generated.h"
 #include "terminal-gdbus.h"
 #include "terminal-defines.h"
 
@@ -49,8 +48,6 @@
 
 #define SYSTEM_PROXY_SETTINGS_SCHEMA            "org.gnome.system.proxy"
 
-#define CONTROLLER_SKELETON_DATA_KEY  "terminal-object-skeleton"
-
 extern GDBusObjectManagerServer *object_manager;
 
 /*
@@ -63,7 +60,7 @@ extern GDBusObjectManagerServer *object_manager;
  */
 
 struct _TerminalAppClass {
-  TerminalFactorySkeletonClass parent_class;
+  GObjectClass parent_class;
 
   void (* quit) (TerminalApp *app);
   void (* profile_list_changed) (TerminalApp *app);
@@ -72,7 +69,7 @@ struct _TerminalAppClass {
 
 struct _TerminalApp
 {
-  TerminalFactorySkeleton parent_instance;
+  GObject parent_instance;
 
   GList *windows;
   GtkWidget *new_profile_dialog;
@@ -114,64 +111,6 @@ static TerminalApp *global_app = NULL;
 
 /* Helper functions */
 
-static GdkScreen*
-terminal_app_get_screen_by_display_name (const char *display_name,
-                                         int screen_number)
-{
-  GdkDisplay *display = NULL;
-  GdkScreen *screen = NULL;
-
-  /* --screen=screen_number overrides --display */
-
-  if (display_name == NULL)
-    display = gdk_display_get_default ();
-  else
-    {
-      GSList *displays, *l;
-      const char *period;
-
-      period = strrchr (display_name, '.');
-      if (period)
-        {
-          gulong n;
-          char *end;
-
-          errno = 0;
-          end = NULL;
-          n = g_ascii_strtoull (period + 1, &end, 0);
-          if (errno == 0 && (period + 1) != end)
-            screen_number = n;
-        }
-
-      displays = gdk_display_manager_list_displays (gdk_display_manager_get ());
-      for (l = displays; l != NULL; l = l->next)
-        {
-          GdkDisplay *disp = l->data;
-
-          /* compare without the screen number part, if present */
-          if ((period && strncmp (gdk_display_get_name (disp), display_name, period - display_name) == 0) ||
-              (period == NULL && strcmp (gdk_display_get_name (disp), display_name) == 0))
-            {
-              display = disp;
-              break;
-            }
-        }
-      g_slist_free (displays);
-
-      if (display == NULL)
-        display = gdk_display_open (display_name); /* FIXME we never close displays */
-    }
-
-  if (display == NULL)
-    return NULL;
-  if (screen_number >= 0)
-    screen = gdk_display_get_screen (display, screen_number);
-  if (screen == NULL)
-    screen = gdk_display_get_default_screen (display);
-
-  return screen;
-}
-
 #if 0
 static int
 profiles_alphabetic_cmp (gconstpointer pa,
@@ -1094,178 +1033,9 @@ terminal_app_manage_profiles (TerminalApp     *app,
 #endif
 }
 
-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_create_instance (TerminalFactory *factory,
-                              GDBusMethodInvocation *invocation,
-                              GVariant *options)
-{
-  TerminalApp *app = TERMINAL_APP (factory);
-  TerminalWindow *window;
-  TerminalScreen *screen;
-  TerminalController *controller;
-  TerminalObjectSkeleton *skeleton;
-  char *object_path;
-  GSettings *profile = NULL;
-  GdkScreen *gdk_screen;
-  const char *startup_id, *display_name;
-  char *role, *geometry, *profile_name, *title;
-  int screen_number;
-  gboolean start_maximized, start_fullscreen;
-  gboolean present_window, present_window_set = FALSE;
-  gboolean zoom_set = FALSE;
-  gdouble zoom = 1.0;
-
-  gboolean menubar_state = TRUE, menubar_state_set = FALSE;
-  gboolean active = TRUE;
-
-  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;
-  }
-
-  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;
-  }
-
-  if (!g_variant_lookup (options, "desktop-startup-id", "^&ay", &startup_id))
-    startup_id = NULL;
-  if (!g_variant_lookup (options, "geometry", "&s", &geometry))
-    geometry = NULL;
-  if (!g_variant_lookup (options, "role", "&s", &role))
-    role = NULL;
-  if (!g_variant_lookup (options, "maximize-window", "b", &start_maximized))
-    start_maximized = FALSE;
-  if (!g_variant_lookup (options, "fullscreen-window", "b", &start_fullscreen))
-    start_fullscreen = FALSE;
-  if (!g_variant_lookup (options, "profile", "&s", &profile_name))
-    profile_name = NULL;
-  if (!g_variant_lookup (options, "title", "&s", &title))
-    title = NULL;
-
-  if (g_variant_lookup (options, "present-window", "b", &present_window)) {
-    present_window_set = TRUE;
-  }
-  if (g_variant_lookup (options, "zoom", "d", &zoom)) {
-    zoom_set = TRUE;
-  }
-
-  window = terminal_app_new_window (app, gdk_screen);
-
-  /* Restored windows shouldn't demand attention; see bug #586308. */
-  if (present_window_set && !present_window)
-    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 (menubar_state_set)
-    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:
-
-  return TRUE; /* handled */
-}
-
-static void
-terminal_factory_iface_init (TerminalFactoryIface *iface)
-{
-  iface->handle_create_instance = terminal_app_create_instance;
-}
-
-G_DEFINE_TYPE_WITH_CODE (TerminalApp, terminal_app, TERMINAL_TYPE_FACTORY_SKELETON,
-                         G_IMPLEMENT_INTERFACE (TERMINAL_TYPE_FACTORY, terminal_factory_iface_init))
+G_DEFINE_TYPE (TerminalApp, terminal_app, G_TYPE_OBJECT)
 
 static void
 terminal_app_init (TerminalApp *app)
@@ -1538,6 +1308,33 @@ terminal_app_get_profile_by_visible_name (TerminalApp *app,
   return NULL;
 }
 
+/**
+ * FIXME
+ */
+GSettings* terminal_app_get_profile (TerminalApp *app,
+                                     const char  *profile_name)
+{
+  GSettings *profile = NULL;
+
+  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 != NULL);
+  return profile;
+}
+
 GHashTable *
 terminal_app_get_encodings (TerminalApp *app)
 {
@@ -1716,3 +1513,12 @@ terminal_app_get_system_font (TerminalApp *app)
 
   return pango_font_description_from_string (font);
 }
+
+/**
+ * FIXME
+ */
+GDBusObjectManagerServer *
+terminal_app_get_object_manager (TerminalApp *app)
+{
+  return object_manager;
+}
\ No newline at end of file
diff --git a/src/terminal-app.h b/src/terminal-app.h
index a31256e..d6b80de 100644
--- a/src/terminal-app.h
+++ b/src/terminal-app.h
@@ -91,6 +91,9 @@ GSettings* terminal_app_get_profile_by_name (TerminalApp *app,
 GSettings* terminal_app_get_profile_by_visible_name (TerminalApp *app,
                                                      const char  *name);
 
+GSettings* terminal_app_get_profile (TerminalApp *app,
+                                     const char  *name);
+
 TerminalEncoding *terminal_app_ensure_encoding (TerminalApp *app,
                                                 const char *charset);
 
diff --git a/src/terminal-gdbus.c b/src/terminal-gdbus.c
index da74008..cfa040b 100644
--- a/src/terminal-gdbus.c
+++ b/src/terminal-gdbus.c
@@ -1,5 +1,5 @@
 /*
- * Copyright  2011 Christian Persch
+ * Copyright  2011, 2012 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
@@ -19,7 +19,14 @@
 #include "config.h"
 
 #include "terminal-gdbus.h"
+
+#include "terminal-app.h"
 #include "terminal-debug.h"
+#include "terminal-defines.h"
+#include "terminal-util.h"
+#include "terminal-window.h"
+
+/* ------------------------------------------------------------------------- */
 
 #define TERMINAL_CONTROLLER_GET_PRIVATE(controller)(G_TYPE_INSTANCE_GET_PRIVATE ((controller), TERMINAL_TYPE_CONTROLLER, TerminalControllerPrivate))
 
@@ -260,4 +267,200 @@ _terminal_controller_unset_screen (TerminalController *controller)
   g_return_if_fail (TERMINAL_IS_CONTROLLER (controller));
 
   terminal_controller_set_screen (controller, NULL);
+}
+
+/* ---------------------------------------------------------------------------
+ * TerminalFactoryImpl
+ * ---------------------------------------------------------------------------
+ */
+
+struct _TerminalFactoryImplPrivate {
+  gpointer dummy;
+};
+
+#define CONTROLLER_SKELETON_DATA_KEY  "terminal-object-skeleton"
+
+static void
+screen_destroy_cb (GObject *screen,
+                   gpointer user_data)
+{
+  GDBusObjectManagerServer *object_manager;
+  GDBusObjectSkeleton *skeleton;
+  const char *object_path;
+
+  skeleton = g_object_get_data (screen, CONTROLLER_SKELETON_DATA_KEY);
+  if (skeleton == NULL)
+    return;
+
+  object_manager = terminal_app_get_object_manager (terminal_app_get ());
+  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);
+}
+
+static gboolean
+terminal_factory_impl_create_instance (TerminalFactory *factory,
+                                       GDBusMethodInvocation *invocation,
+                                       GVariant *options)
+{
+  TerminalApp *app = terminal_app_get ();
+  GDBusObjectManagerServer *object_manager;
+  TerminalWindow *window;
+  TerminalScreen *screen;
+  TerminalController *controller;
+  TerminalObjectSkeleton *skeleton;
+  char *object_path;
+  GSettings *profile = NULL;
+  GdkScreen *gdk_screen;
+  const char *startup_id, *display_name;
+  char *role, *geometry, *profile_name, *title;
+  int screen_number;
+  gboolean start_maximized, start_fullscreen;
+  gboolean present_window, present_window_set = FALSE;
+  gboolean zoom_set = FALSE;
+  gdouble zoom = 1.0;
+
+  gboolean menubar_state = TRUE, menubar_state_set = FALSE;
+  gboolean active = TRUE;
+
+  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;
+  }
+
+  screen_number = 0;
+  gdk_screen = terminal_util_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;
+  }
+
+  if (!g_variant_lookup (options, "desktop-startup-id", "^&ay", &startup_id))
+    startup_id = NULL;
+  if (!g_variant_lookup (options, "geometry", "&s", &geometry))
+    geometry = NULL;
+  if (!g_variant_lookup (options, "role", "&s", &role))
+    role = NULL;
+  if (!g_variant_lookup (options, "maximize-window", "b", &start_maximized))
+    start_maximized = FALSE;
+  if (!g_variant_lookup (options, "fullscreen-window", "b", &start_fullscreen))
+    start_fullscreen = FALSE;
+  if (!g_variant_lookup (options, "profile", "&s", &profile_name))
+    profile_name = NULL;
+  if (!g_variant_lookup (options, "title", "&s", &title))
+    title = NULL;
+
+  if (g_variant_lookup (options, "present-window", "b", &present_window)) {
+    present_window_set = TRUE;
+  }
+  if (g_variant_lookup (options, "zoom", "d", &zoom)) {
+    zoom_set = TRUE;
+  }
+
+  window = terminal_app_new_window (app, gdk_screen);
+
+  /* Restored windows shouldn't demand attention; see bug #586308. */
+  if (present_window_set && !present_window)
+    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 (menubar_state_set)
+    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));
+
+  profile = terminal_app_get_profile (app, profile_name);
+  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);
+
+  object_manager = terminal_app_get_object_manager (app);
+  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:
+
+  return TRUE; /* handled */
+}
+
+static void
+terminal_factory_impl_iface_init (TerminalFactoryIface *iface)
+{
+  iface->handle_create_instance = terminal_factory_impl_create_instance;
+}
+
+G_DEFINE_TYPE_WITH_CODE (TerminalFactoryImpl, terminal_factory_impl, TERMINAL_TYPE_FACTORY_SKELETON,
+                         G_IMPLEMENT_INTERFACE (TERMINAL_TYPE_FACTORY, terminal_factory_impl_iface_init))
+
+static void
+terminal_factory_impl_init (TerminalFactoryImpl *impl)
+{
+  impl->priv = G_TYPE_INSTANCE_GET_PRIVATE (impl, TERMINAL_TYPE_FACTORY_IMPL, TerminalFactoryImplPrivate);
+}
+
+static void
+terminal_factory_impl_class_init (TerminalFactoryImplClass *klass)
+{
+  g_type_class_add_private (klass, sizeof (TerminalFactoryImplPrivate));
+}
+
+/**
+ * terminal_factory_impl_new:
+ *
+ * Returns: (transfer full): a new #TerminalFactoryImpl
+ */
+TerminalFactory *
+terminal_factory_impl_new (void)
+{
+  return g_object_new (TERMINAL_TYPE_FACTORY_IMPL, NULL);
 }
\ No newline at end of file
diff --git a/src/terminal-gdbus.h b/src/terminal-gdbus.h
index a7fa3f3..67dc465 100644
--- a/src/terminal-gdbus.h
+++ b/src/terminal-gdbus.h
@@ -58,6 +58,34 @@ TerminalScreen *terminal_controller_get_screen (TerminalController *controller);
 
 void _terminal_controller_unset_screen (TerminalController *controller);
 
+/* ------------------------------------------------------------------------- */
+
+#define TERMINAL_TYPE_FACTORY_IMPL              (terminal_factory_impl_get_type ())
+#define TERMINAL_FACTORY_IMPL(object)           (G_TYPE_CHECK_INSTANCE_CAST ((object), TERMINAL_TYPE_FACTORY_IMPL, TerminalFactoryImpl))
+#define TERMINAL_FACTORY_IMPL_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST ((klass), TERMINAL_TYPE_FACTORY_IMPL, TerminalFactoryImplClass))
+#define TERMINAL_IS_FACTORY_IMPL(object)        (G_TYPE_CHECK_INSTANCE_TYPE ((object), TERMINAL_TYPE_FACTORY_IMPL))
+#define TERMINAL_IS_FACTORY_IMPL_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass), TERMINAL_TYPE_FACTORY_IMPL))
+#define TERMINAL_FACTORY_IMPL_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), TERMINAL_TYPE_FACTORY_IMPL, TerminalFactoryImplClass))
+
+typedef struct _TerminalFactoryImpl        TerminalFactoryImpl;
+typedef struct _TerminalFactoryImplPrivate TerminalFactoryImplPrivate;
+typedef struct _TerminalFactoryImplClass   TerminalFactoryImplClass;
+
+struct _TerminalFactoryImplClass {
+  TerminalFactorySkeletonClass parent_class;
+};
+
+struct _TerminalFactoryImpl
+{
+  TerminalFactorySkeleton parent_instance;
+
+  TerminalFactoryImplPrivate *priv;
+};
+
+GType terminal_factory_impl_get_type (void);
+
+TerminalFactory *terminal_factory_impl_new (void);
+
 G_END_DECLS
 
 #endif /* !TERMINAL_CONTROLLER_H */
diff --git a/src/terminal-util.c b/src/terminal-util.c
index 1ae2923..567fa51 100644
--- a/src/terminal-util.c
+++ b/src/terminal-util.c
@@ -26,6 +26,7 @@
 #include <time.h>
 #include <unistd.h>
 #include <sys/types.h>
+#include <errno.h>
 
 #include <glib.h>
 
@@ -648,6 +649,64 @@ terminal_util_add_proxy_env (GHashTable *env_table)
     }
 }
 
+GdkScreen*
+terminal_util_get_screen_by_display_name (const char *display_name,
+                                          int screen_number)
+{
+  GdkDisplay *display = NULL;
+  GdkScreen *screen = NULL;
+
+  /* --screen=screen_number overrides --display */
+
+  if (display_name == NULL)
+    display = gdk_display_get_default ();
+  else
+    {
+      GSList *displays, *l;
+      const char *period;
+
+      period = strrchr (display_name, '.');
+      if (period)
+        {
+          gulong n;
+          char *end;
+
+          errno = 0;
+          end = NULL;
+          n = g_ascii_strtoull (period + 1, &end, 0);
+          if (errno == 0 && (period + 1) != end)
+            screen_number = n;
+        }
+
+      displays = gdk_display_manager_list_displays (gdk_display_manager_get ());
+      for (l = displays; l != NULL; l = l->next)
+        {
+          GdkDisplay *disp = l->data;
+
+          /* compare without the screen number part, if present */
+          if ((period && strncmp (gdk_display_get_name (disp), display_name, period - display_name) == 0) ||
+              (period == NULL && strcmp (gdk_display_get_name (disp), display_name) == 0))
+            {
+              display = disp;
+              break;
+            }
+        }
+      g_slist_free (displays);
+
+      if (display == NULL)
+        display = gdk_display_open (display_name); /* FIXME we never close displays */
+    }
+
+  if (display == NULL)
+    return NULL;
+  if (screen_number >= 0)
+    screen = gdk_display_get_screen (display, screen_number);
+  if (screen == NULL)
+    screen = gdk_display_get_default_screen (display);
+
+  return screen;
+}
+
 #ifdef GDK_WINDOWING_X11
 
 /* We don't want to hop desktops when we unrealize/realize.
diff --git a/src/terminal-util.h b/src/terminal-util.h
index 90f46b6..3715553 100644
--- a/src/terminal-util.h
+++ b/src/terminal-util.h
@@ -76,6 +76,8 @@ void terminal_util_key_file_set_argv      (GKeyFile *key_file,
 
 void terminal_util_add_proxy_env (GHashTable *env_table);
 
+GdkScreen *terminal_util_get_screen_by_display_name (const char *display_name,
+                                                     int screen_number);
 
 gboolean terminal_util_x11_get_net_wm_desktop (GdkWindow *window,
 					       guint32   *desktop);



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