[gnome-terminal] Port to GDBus
- From: Christian Persch <chpe src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-terminal] Port to GDBus
- Date: Sun, 13 Jun 2010 12:28:09 +0000 (UTC)
commit fdf01b94d14d7f9c4df7e9f762f851d0800c4927
Author: Christian Persch <chpe gnome org>
Date: Sat May 8 18:08:48 2010 +0200
Port to GDBus
... and remove dbus-glib dependency.
configure.ac | 16 +-
src/Makefile.am | 9 -
src/terminal-app.c | 71 +++-
src/terminal-app.h | 5 +-
src/terminal-factory-service.xml | 11 -
src/terminal-util.c | 138 --------
src/terminal-util.h | 12 -
src/terminal.c | 682 +++++++++++++++++++-------------------
8 files changed, 399 insertions(+), 545 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index 4ab16e3..da58eef 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,7 +1,7 @@
m4_define([gt_version_major],[2])
m4_define([gt_version_minor],[31])
m4_define([gt_version_micro],[3])
-m4_define([gt_version_extra],[git])
+m4_define([gt_version_extra],[-git])
m4_define([gt_version],[gt_version_major().gt_version_minor().gt_version_micro()gt_version_extra])
m4_define([gt_api_version],[0])
@@ -39,10 +39,10 @@ GNOME_COMPILE_WARNINGS([maximum])
AM_GLIB_GNU_GETTEXT
-GLIB_REQUIRED=2.16.0
+GLIB_REQUIRED=2.25.0
+GIO_REQUIRED=2.25.4
GTK_REQUIRED=2.14.0
-GCONF_REQUIRED=2.14.0
-DBUS_GLIB_REQUIRED=0.6
+GCONF_REQUIRED=2.31.3
VTE_REQUIRED=0.25.1
AC_MSG_CHECKING([which gtk+ version to compile against])
@@ -75,10 +75,9 @@ PKG_CHECK_MODULES([TERM],
[vte >= $VTE_REQUIRED
glib-2.0 >= $GLIB_REQUIRED
gthread-2.0
- gio-2.0
+ gio-2.0 >= $GIO_REQUIRED
gtk+-$GTK_API_VERSION >= $GTK_REQUIRED
gconf-2.0 >= $GCONF_REQUIRED
- dbus-glib-1 >= $DBUS_GLIB_REQUIRED
$PLATFORM_DEPS])
# Check the smclient backend
@@ -128,11 +127,6 @@ if test "$GTK_BUILDER_CONVERT" = "false"; then
AC_MSG_ERROR([gtk-builder-convert not found])
fi
-AC_PATH_PROG([DBUS_BINDING_TOOL],[dbus-binding-tool],[false])
-if test "$DBUS_BINDING_TOOL" = "false"; then
- AC_MSG_ERROR([dbus-binding-tool not found])
-fi
-
GNOME_DOC_INIT
# ****************************
diff --git a/src/Makefile.am b/src/Makefile.am
index bad5a38..c05e85f 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -5,8 +5,6 @@ SUBDIRS = skey
bin_PROGRAMS = gnome-terminal
BUILT_SOURCES = \
- terminal-factory-client.h \
- terminal-factory-server.h \
terminal-marshal.c \
terminal-marshal.h \
terminal-type-builtins.c \
@@ -142,12 +140,6 @@ terminal-marshal.c: $(srcdir)/terminal-marshal.list
&& mv terminal-marshal.c.tmp terminal-marshal.c ) \
|| ( rm -f terminal-marshal.c.tmp && exit 1 )
-terminal-factory-client.h: terminal-factory-service.xml
- $(AM_V_GEN) $(DBUS_BINDING_TOOL) --mode=glib-client --output=$@ $<
-
-terminal-factory-server.h: terminal-factory-service.xml
- $(AM_V_GEN) $(DBUS_BINDING_TOOL) --mode=glib-server --prefix=terminal_factory --output=$@ $<
-
schemadir = $(GCONF_SCHEMA_FILE_DIR)
schema_in_files = gnome-terminal.schemas.in
schema_DATA = gnome-terminal.schemas
@@ -183,7 +175,6 @@ CLEANFILES = \
$(BUILT_SOURCES)
EXTRA_DIST = \
- terminal-factory-service.xml \
terminal-marshal.list \
terminal-type-builtins.c.template \
terminal-type-builtins.h.template \
diff --git a/src/terminal-app.c b/src/terminal-app.c
index 39ea6bc..30592f4 100644
--- a/src/terminal-app.c
+++ b/src/terminal-app.c
@@ -43,6 +43,9 @@
#ifdef WITH_SMCLIENT
#include "eggsmclient.h"
+#ifdef GDK_WINDOWING_X11
+#include "eggdesktopfile.h"
+#endif
#endif
#define FALLBACK_PROFILE_ID "Default"
@@ -109,8 +112,6 @@ struct _TerminalApp
PangoFontDescription *system_font_desc;
gboolean enable_mnemonics;
gboolean enable_menu_accels;
-
- gboolean use_factory;
};
enum
@@ -146,6 +147,9 @@ enum
static TerminalApp *global_app = NULL;
+/* Evil hack alert: this is exported from libgconf-2 but not in a public header */
+extern gboolean gconf_spawn_daemon(GError** err);
+
#define MONOSPACE_FONT_DIR "/desktop/gnome/interface"
#define MONOSPACE_FONT_KEY MONOSPACE_FONT_DIR "/monospace_font_name"
#define DEFAULT_MONOSPACE_FONT ("Monospace 10")
@@ -1380,8 +1384,26 @@ G_DEFINE_TYPE (TerminalApp, terminal_app, G_TYPE_OBJECT)
static void
terminal_app_init (TerminalApp *app)
{
+ GError *error = NULL;
+
global_app = app;
+ /* If the gconf daemon isn't available (e.g. because there's no dbus
+ * session bus running), we'd crash later on. Tell the user about it
+ * now, and exit. See bug #561663.
+ * Don't use gconf_ping_daemon() here since the server may just not
+ * be running yet, but able to be started. See comments on bug #564649.
+ */
+ if (!gconf_spawn_daemon (&error))
+ {
+ g_printerr ("Failed to summon the GConf demon; exiting. %s\n", error->message);
+ g_error_free (error);
+
+ exit (EXIT_FAILURE);
+ }
+
+ gtk_window_set_default_icon_name (GNOME_TERMINAL_ICON_NAME);
+
/* Initialise defaults */
app->enable_mnemonics = DEFAULT_ENABLE_MNEMONICS;
app->enable_menu_accels = DEFAULT_ENABLE_MENU_BAR_ACCEL;
@@ -1457,6 +1479,16 @@ terminal_app_init (TerminalApp *app)
#ifdef WITH_SMCLIENT
{
EggSMClient *sm_client;
+#ifdef GDK_WINDOWING_X11
+ char *desktop_file;
+
+ desktop_file = g_build_filename (TERM_DATADIR,
+ "applications",
+ PACKAGE ".desktop",
+ NULL);
+ egg_set_desktop_file_without_defaults (desktop_file);
+ g_free (desktop_file);
+#endif /* GDK_WINDOWING_X11 */
sm_client = egg_sm_client_get ();
g_signal_connect (sm_client, "save-state",
@@ -1572,6 +1604,12 @@ terminal_app_set_property (GObject *object,
}
static void
+terminal_app_real_quit (TerminalApp *app)
+{
+ gtk_main_quit();
+}
+
+static void
terminal_app_class_init (TerminalAppClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
@@ -1580,6 +1618,8 @@ terminal_app_class_init (TerminalAppClass *klass)
object_class->get_property = terminal_app_get_property;
object_class->set_property = terminal_app_set_property;
+ klass->quit = terminal_app_real_quit;
+
signals[QUIT] =
g_signal_new (I_("quit"),
G_OBJECT_CLASS_TYPE (object_class),
@@ -1638,31 +1678,27 @@ terminal_app_class_init (TerminalAppClass *klass)
/* Public API */
-void
-terminal_app_initialize (gboolean use_factory)
+TerminalApp*
+terminal_app_get (void)
{
- g_assert (global_app == NULL);
- g_object_new (TERMINAL_TYPE_APP, NULL);
- g_assert (global_app != NULL);
+ if (global_app == NULL) {
+ g_object_new (TERMINAL_TYPE_APP, NULL);
+ g_assert (global_app != NULL);
+ }
- global_app->use_factory = use_factory;
+ return global_app;
}
void
terminal_app_shutdown (void)
{
- g_assert (global_app != NULL);
+ if (global_app == NULL)
+ return;
+
g_object_unref (global_app);
g_assert (global_app == NULL);
}
-TerminalApp*
-terminal_app_get (void)
-{
- g_assert (global_app != NULL);
- return global_app;
-}
-
/**
* terminal_app_handle_options:
* @app:
@@ -2025,9 +2061,6 @@ terminal_app_save_config (TerminalApp *app,
g_key_file_set_integer (key_file, TERMINAL_CONFIG_GROUP, TERMINAL_CONFIG_PROP_VERSION, TERMINAL_CONFIG_VERSION);
g_key_file_set_integer (key_file, TERMINAL_CONFIG_GROUP, TERMINAL_CONFIG_PROP_COMPAT_VERSION, TERMINAL_CONFIG_COMPAT_VERSION);
- /* FIXMEchpe this seems useless */
- g_key_file_set_boolean (key_file, TERMINAL_CONFIG_GROUP, TERMINAL_CONFIG_PROP_FACTORY, app->use_factory);
-
window_names_array = g_ptr_array_sized_new (g_list_length (app->windows) + 1);
for (lw = app->windows; lw != NULL; lw = lw->next)
diff --git a/src/terminal-app.h b/src/terminal-app.h
index 300d91a..4dda51d 100644
--- a/src/terminal-app.h
+++ b/src/terminal-app.h
@@ -34,7 +34,6 @@ G_BEGIN_DECLS
#define TERMINAL_CONFIG_COMPAT_VERSION (1) /* Bump this for incompatible changes */
#define TERMINAL_CONFIG_GROUP "GNOME Terminal Configuration"
-#define TERMINAL_CONFIG_PROP_FACTORY "FactoryEnabled"
#define TERMINAL_CONFIG_PROP_VERSION "Version"
#define TERMINAL_CONFIG_PROP_COMPAT_VERSION "CompatVersion"
#define TERMINAL_CONFIG_PROP_WINDOWS "Windows"
@@ -83,12 +82,10 @@ typedef struct _TerminalApp TerminalApp;
GType terminal_app_get_type (void);
-void terminal_app_initialize (gboolean use_factory);
+TerminalApp* terminal_app_get (void);
void terminal_app_shutdown (void);
-TerminalApp* terminal_app_get (void);
-
gboolean terminal_app_handle_options (TerminalApp *app,
TerminalOptions *options,
gboolean allow_resume,
diff --git a/src/terminal-util.c b/src/terminal-util.c
index 5ed9d2a..ddb9499 100644
--- a/src/terminal-util.c
+++ b/src/terminal-util.c
@@ -514,144 +514,6 @@ terminal_util_key_file_get_argv (GKeyFile *key_file,
return NULL;
}
-/* Why? Because dbus-glib sucks, that's why! */
-
-/**
- * terminal_util_string_to_array:
- * @string:
- *
- * Converts the string @string into a #GArray.
- *
- * Returns: a newly allocated #GArray containing @string's bytes.
- */
-GArray *
-terminal_util_string_to_array (const char *string)
-{
- GArray *array;
- gsize len = 0;
-
- if (string)
- len = strlen (string);
-
- array = g_array_sized_new (FALSE, FALSE, sizeof (guchar), len);
- return g_array_append_vals (array, string, len);
-}
-
-/**
- * terminal_util_strv_to_array:
- * @argc: the length of @argv
- * @argv: a string array
- *
- * Converts the string array @argv of length @argc into a #GArray.
- *
- * Returns: a newly allocated #GArray
- */
-GArray *
-terminal_util_strv_to_array (int argc,
- char **argv)
-{
- GArray *array;
- gsize len = 0;
- int i;
- const char nullbyte = 0;
-
- for (i = 0; i < argc; ++i)
- len += strlen (argv[i]);
- if (argc > 0)
- len += argc - 1;
-
- array = g_array_sized_new (FALSE, FALSE, sizeof (guchar), len);
-
- for (i = 0; i < argc; ++i) {
- g_array_append_vals (array, argv[i], strlen (argv[i]));
- if (i < argc)
- g_array_append_val (array, nullbyte);
- }
-
- return array;
-}
-
-/**
- * terminal_util_array_to_string:
- * @array:
- * @error: a #GError to fill in
- *
- * Converts @array into a string.
- *
- * Returns: a newly allocated string, or %NULL on error
- */
-char *
-terminal_util_array_to_string (const GArray *array,
- GError **error)
-{
- char *string;
- g_return_val_if_fail (array != NULL, NULL);
-
- string = g_strndup (array->data, array->len);
-
- /* Validate */
- if (strlen (string) < array->len) {
- g_set_error_literal (error,
- g_quark_from_static_string ("terminal-error"),
- 0,
- "String is shorter than claimed");
- return NULL;
- }
-
- return string;
-}
-
-/**
- * terminal_util_array_to_strv:
- * @array:
- * @argc: a location to store the length of the returned string array
- * @error: a #GError to fill in
- *
- * Converts @array into a string.
- *
- * Returns: a newly allocated string array of length * argc, or %NULL on error
- */
-char **
-terminal_util_array_to_strv (const GArray *array,
- int *argc,
- GError **error)
-{
- GPtrArray *argv;
- const char *data, *nullbyte;
- gssize len;
-
- g_return_val_if_fail (array != NULL, NULL);
-
- if (array->len == 0 || array->len > G_MAXSSIZE) {
- *argc = 0;
- return NULL;
- }
-
- argv = g_ptr_array_new ();
-
- len = array->len;
- data = array->data;
-
- do {
- gsize string_len;
-
- nullbyte = memchr (data, '\0', len);
-
- string_len = nullbyte ? (gsize) (nullbyte - data) : len;
- g_ptr_array_add (argv, g_strndup (data, string_len));
-
- len -= string_len + 1;
- data += string_len + 1;
- } while (len > 0);
-
- if (argc)
- *argc = argv->len;
-
- /* NULL terminate */
- g_ptr_array_add (argv, NULL);
- return (char **) g_ptr_array_free (argv, FALSE);
-}
-
/* Proxy stuff */
static char *
diff --git a/src/terminal-util.h b/src/terminal-util.h
index a705fc7..66f8b79 100644
--- a/src/terminal-util.h
+++ b/src/terminal-util.h
@@ -87,18 +87,6 @@ char **terminal_util_key_file_get_argv (GKeyFile *key_file,
int *argc,
GError **error);
-GArray *terminal_util_string_to_array (const char *string);
-
-GArray *terminal_util_strv_to_array (int argc,
- char **argv);
-
-char *terminal_util_array_to_string (const GArray *array,
- GError **error);
-
-char **terminal_util_array_to_strv (const GArray *array,
- int *argc,
- GError **error);
-
void terminal_util_add_proxy_env (GHashTable *env_table);
typedef enum {
diff --git a/src/terminal.c b/src/terminal.c
index 8160635..70d0a0b 100644
--- a/src/terminal.c
+++ b/src/terminal.c
@@ -29,19 +29,13 @@
#include <glib.h>
#include <glib/gstdio.h>
+#include <gio/gio.h>
#include <gdk/gdkx.h>
#ifdef WITH_SMCLIENT
#include "eggsmclient.h"
-#ifdef GDK_WINDOWING_X11
-#include "eggdesktopfile.h"
#endif
-#endif
-
-#include <dbus/dbus-protocol.h>
-#include <dbus/dbus-glib.h>
-#include <dbus/dbus-glib-bindings.h>
#include "terminal-accels.h"
#include "terminal-app.h"
@@ -54,54 +48,314 @@
#define TERMINAL_FACTORY_SERVICE_PATH "/org/gnome/Terminal/Factory"
#define TERMINAL_FACTORY_INTERFACE_NAME "org.gnome.Terminal.Factory"
-#define TERMINAL_TYPE_FACTORY (terminal_factory_get_type ())
-#define TERMINAL_FACTORY(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), TERMINAL_TYPE_FACTORY, TerminalFactory))
-#define TERMINAL_FACTORY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TERMINAL_TYPE_FACTORY, TerminalFactoryClass))
-#define TERMINAL_IS_FACTORY(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), TERMINAL_TYPE_FACTORY))
-#define TERMINAL_IS_FACTORY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TERMINAL_TYPE_FACTORY))
-#define TERMINAL_FACTORY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TERMINAL_TYPE_FACTORY, TerminalFactoryClass))
+/* The returned string is owned by @variant */
+static const char *
+ay_to_string (GVariant *variant,
+ GError **error)
+{
+ const char *string;
+ gsize len;
+
+ string = g_variant_get_byte_array (variant, &len);
+ if (len == 0)
+ return NULL;
+
+ /* Validate that the string is nul-terminated and full-length */
+ if (string[len - 1] != '\0') {
+ g_set_error_literal (error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
+ "String not nul-terminated!");
+ return NULL;
+ }
+ if (strlen (string) != (len - 1)) {
+ g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
+ "String is shorter than claimed (claimed %" G_GSIZE_FORMAT " actual %" G_GSIZE_FORMAT ")",
+ len, strlen (string));
+ return NULL;
+ }
-typedef struct _TerminalFactory TerminalFactory;
-typedef struct _TerminalFactoryClass TerminalFactoryClass;
-typedef struct _TerminalFactoryPrivate TerminalFactoryPrivate;
+ return string;
+}
-struct _TerminalFactory
+/* The returned strings are owned by @variant. Free the array itself with g_free(). */
+static char **
+aay_to_strv (GVariant *variant,
+ int *argc,
+ GError **error)
{
- GObject parent_instance;
-};
+ GVariant *item;
+ char **argv;
+ gsize i, n;
+
+ n = g_variant_n_children (variant);
+ if (argc)
+ *argc = n;
+ if (n == 0)
+ return NULL;
+
+ argv = g_new (char *, n + 1);
+
+ for (i = 0; i < n; ++i) {
+ item = g_variant_get_child_value (variant, i);
+ argv[i] = (char *) ay_to_string (item, error);
+ g_variant_unref (item);
+ if (*error != NULL)
+ goto err;
+ }
+
+ argv[n] = NULL;
+ return argv;
+
+err:
+ g_free (argv);
+ return NULL;
+}
-struct _TerminalFactoryClass
+typedef struct {
+ char *factory_name;
+ TerminalOptions *options;
+ int exit_code;
+ char **argv;
+ int argc;
+} OwnData;
+
+static void
+method_call_cb (GDBusConnection *connection,
+ const char *sender,
+ const char *object_path,
+ const char *interface_name,
+ const char *method_name,
+ GVariant *parameters,
+ GDBusMethodInvocation *invocation,
+ gpointer user_data)
{
- GObjectClass parent_class;
-};
-
-static gboolean
-terminal_factory_handle_arguments (TerminalFactory *factory,
- const GArray *working_directory_array,
- const GArray *display_name_array,
- const GArray *startup_id_array,
- const GArray *argv_array,
- const GArray *env_array,
- GError **error);
-
-#include "terminal-factory-client.h"
-#include "terminal-factory-server.h"
-
-static GType terminal_factory_get_type (void);
-
-G_DEFINE_TYPE_WITH_CODE (TerminalFactory, terminal_factory, G_TYPE_OBJECT,
- dbus_g_object_type_install_info (g_define_type_id,
- &dbus_glib_terminal_factory_object_info)
-);
+ if (g_strcmp0 (method_name, "HandleArguments") == 0) {
+ TerminalOptions *options = NULL;
+ GVariant *v_wd, *v_display, *v_sid, *v_envv, *v_argv;
+ const char *working_directory = NULL, *display_name = NULL, *startup_id = NULL;
+ char **envv = NULL, **argv = NULL;
+ int argc;
+ GError *error = NULL;
+
+ g_variant_get (parameters, "(@ay ay@ay aay@aay)",
+ &v_wd, &v_display, &v_sid, &v_envv, &v_argv);
+
+ working_directory = ay_to_string (v_wd, &error);
+ if (error)
+ goto out;
+ display_name = ay_to_string (v_display, &error);
+ if (error)
+ goto out;
+ startup_id = ay_to_string (v_sid, &error);
+ if (error)
+ goto out;
+ envv = aay_to_strv (v_envv, NULL, &error);
+ if (error)
+ goto out;
+ argv = aay_to_strv (v_argv, &argc, &error);
+ if (error)
+ goto out;
+
+ _terminal_debug_print (TERMINAL_DEBUG_FACTORY,
+ "Factory invoked with working-dir='%s' display='%s' startup-id='%s'\n",
+ working_directory ? working_directory : "(null)",
+ display_name ? display_name : "(null)",
+ startup_id ? startup_id : "(null)");
+
+ options = terminal_options_parse (working_directory,
+ display_name,
+ startup_id,
+ envv,
+ TRUE,
+ TRUE,
+ &argc, &argv,
+ &error,
+ NULL);
+
+ if (options != NULL) {
+ terminal_app_handle_options (terminal_app_get (), options, FALSE /* no resume */, &error);
+ terminal_options_free (options);
+ }
+ out:
+ g_variant_unref (v_wd);
+ g_variant_unref (v_display);
+ g_variant_unref (v_sid);
+ g_free (envv);
+ g_variant_unref (v_envv);
+ g_free (argv);
+ g_variant_unref (v_argv);
+
+ if (error == NULL) {
+ g_dbus_method_invocation_return_value (invocation, g_variant_new ("()"));
+ } else {
+ g_dbus_method_invocation_return_gerror (invocation, error);
+ g_error_free (error);
+ }
+ }
+}
+
+static void
+bus_acquired_cb (GDBusConnection *connection,
+ const char *name,
+ gpointer user_data)
+{
+ static const char dbus_introspection_xml[] =
+ "<node name='/org/gnome/Terminal'>"
+ "<interface name='org.gnome.Terminal.Factory'>"
+ "<method name='HandleArguments'>"
+ "<arg type='ay' name='working_directory' direction='in' />"
+ "<arg type='ay' name='display_name' direction='in' />"
+ "<arg type='ay' name='startup_id' direction='in' />"
+ "<arg type='aay' name='environment' direction='in' />"
+ "<arg type='aay' name='arguments' direction='in' />"
+ "</method>"
+ "</interface>"
+ "</node>";
+
+ static const GDBusInterfaceVTable interface_vtable = {
+ method_call_cb,
+ NULL,
+ NULL,
+ };
+
+ OwnData *data = (OwnData *) user_data;
+ GDBusNodeInfo *introspection_data;
+ guint registration_id;
+ GError *error = NULL;
+
+ _terminal_debug_print (TERMINAL_DEBUG_FACTORY,
+ "Bus %s acquired\n", name);
+
+ introspection_data = g_dbus_node_info_new_for_xml (dbus_introspection_xml, NULL);
+ g_assert (introspection_data != NULL);
+
+ registration_id = g_dbus_connection_register_object (connection,
+ TERMINAL_FACTORY_SERVICE_PATH,
+ introspection_data->interfaces[0],
+ &interface_vtable,
+ introspection_data,
+ (GDestroyNotify) g_dbus_node_info_unref,
+ &error);
+ if (registration_id == 0) {
+ g_printerr ("Failed to register object: %s\n", error->message);
+ g_error_free (error);
+ data->exit_code = EXIT_FAILURE;
+ gtk_main_quit ();
+ }
+}
+
static void
-terminal_factory_class_init (TerminalFactoryClass *factory_class)
+name_acquired_cb (GDBusConnection *connection,
+ const char *name,
+ gpointer user_data)
{
+ OwnData *data = (OwnData *) user_data;
+ GError *error = NULL;
+
+ _terminal_debug_print (TERMINAL_DEBUG_FACTORY,
+ "Acquired the name %s on the session bus\n", name);
+
+ if (data->options == NULL) {
+ /* Name re-acquired!? */
+ g_assert_not_reached ();
+ }
+
+
+ if (!terminal_app_handle_options (terminal_app_get (), data->options, FALSE /* no resume */, &error)) {
+ g_printerr ("Failed to handle options: %s\n", error->message);
+ g_error_free (error);
+ data->exit_code = EXIT_FAILURE;
+ gtk_main_quit ();
+ }
+
+ terminal_options_free (data->options);
+ data->options = NULL;
}
static void
-terminal_factory_init (TerminalFactory *factory)
+name_lost_cb (GDBusConnection *connection,
+ const char *name,
+ gpointer user_data)
{
+ OwnData *data = (OwnData *) user_data;
+ GError *error = NULL;
+ char **envv;
+ int envc, i;
+ GVariantBuilder builder;
+ GVariant *value;
+
+ _terminal_debug_print (TERMINAL_DEBUG_FACTORY,
+ "Lost the name %s on the session bus\n", name);
+
+ if (data->options == NULL) {
+ /* Already handled */
+ data->exit_code = EXIT_SUCCESS;
+ gtk_main_quit ();
+ return;
+ }
+
+ _terminal_debug_print (TERMINAL_DEBUG_FACTORY,
+ "Forwarding arguments to existing instance\n");
+
+ g_variant_builder_init (&builder, G_VARIANT_TYPE ("(ayayayaayaay)"));
+
+ g_variant_builder_add (&builder, "@ay",
+ g_variant_new_byte_array (data->options->default_working_dir ? data->options->default_working_dir : "", -1));
+ g_variant_builder_add (&builder, "@ay",
+ g_variant_new_byte_array (data->options->display_name ? data->options->display_name : "", -1));
+ g_variant_builder_add (&builder, "@ay",
+ g_variant_new_byte_array (data->options->startup_id ? data->options->startup_id : "", -1));
+
+ g_variant_builder_open (&builder, G_VARIANT_TYPE ("aay"));
+ envv = g_listenv ();
+ envc = g_strv_length (envv);
+ for (i = 0; i < envc; ++i)
+ {
+ const char *value;
+ char *str;
+
+ value = g_getenv (envv[i]);
+ if (value == NULL)
+ continue;
+
+ str = g_strdup_printf ("%s=%s", envv[i], value);
+ g_variant_builder_add (&builder, "@ay", g_variant_new_byte_array (str, -1));
+ g_free (str);
+ }
+ g_variant_builder_close (&builder);
+
+ g_variant_builder_open (&builder, G_VARIANT_TYPE ("aay"));
+ for (i = 0; i < data->argc; ++i)
+ g_variant_builder_add (&builder, "@ay",
+ g_variant_new_byte_array (data->argv[i], -1));
+ g_variant_builder_close (&builder);
+
+ value = g_dbus_connection_call_sync (connection,
+ data->factory_name,
+ TERMINAL_FACTORY_SERVICE_PATH,
+ TERMINAL_FACTORY_INTERFACE_NAME,
+ "HandleArguments",
+ g_variant_builder_end (&builder),
+ G_VARIANT_TYPE ("()"),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ NULL,
+ &error);
+ if (value == NULL) {
+ _terminal_debug_print (TERMINAL_DEBUG_FACTORY,
+ "Failed to forward arguments: %s\n", error->message);
+ g_error_free (error);
+ data->exit_code = EXIT_FAILURE;
+ gtk_main_quit ();
+ } else {
+ g_variant_unref (value);
+ data->exit_code = EXIT_SUCCESS;
+ }
+
+ terminal_options_free (data->options);
+ data->options = NULL;
+
+ gtk_main_quit ();
}
/* Settings storage works as follows:
@@ -126,8 +380,6 @@ terminal_factory_init (TerminalFactory *factory)
*
*/
-static TerminalFactory *factory = NULL;
-
/* Copied from libnautilus/nautilus-program-choosing.c; Needed in case
* we have no DESKTOP_STARTUP_ID (with its accompanying timestamp).
*/
@@ -179,39 +431,6 @@ slowly_and_stupidly_obtain_timestamp (Display *xdisplay)
return event.xproperty.time;
}
-static void
-about_url_hook (GtkAboutDialog *about,
- const char *uri,
- gpointer user_data)
-{
- GError *error = NULL;
-
- if (!gtk_show_uri (gtk_widget_get_screen (GTK_WIDGET (about)),
- uri,
- gtk_get_current_event_time (),
- &error))
- {
- terminal_util_show_error_dialog (GTK_WINDOW (about), NULL, error,
- "%s", _("Could not open link"));
- g_error_free (error);
- }
-}
-
-static void
-about_email_hook (GtkAboutDialog *about,
- const char *email_address,
- gpointer user_data)
-{
- char *escaped, *uri;
-
- escaped = g_uri_escape_string (email_address, NULL, FALSE);
- uri = g_strdup_printf ("mailto:%s", escaped);
- g_free (escaped);
-
- about_url_hook (about, uri, user_data);
- g_free (uri);
-}
-
static char *
get_factory_name_for_display (const char *display_name)
{
@@ -235,24 +454,16 @@ get_factory_name_for_display (const char *display_name)
return g_string_free (name, FALSE);
}
-/* Evil hack alert: this is exported from libgconf-2 but not in a public header */
-extern gboolean gconf_spawn_daemon(GError** err);
-
int
main (int argc, char **argv)
{
int i;
char **argv_copy;
int argc_copy;
- const char *startup_id, *display_name;
+ const char *startup_id, *display_name, *home_dir;
GdkDisplay *display;
TerminalOptions *options;
- DBusGConnection *connection;
- char *factory_name = NULL;
- DBusGProxy *proxy;
- guint32 request_name_ret;
GError *error = NULL;
- const char *home_dir;
char *working_directory;
int ret = EXIT_SUCCESS;
@@ -278,6 +489,14 @@ main (int argc, char **argv)
working_directory = g_get_current_dir ();
+ /* Now change directory to $HOME so we don't prevent unmounting, e.g. if the
+ * factory is started by nautilus-open-terminal. See bug #565328.
+ * On failure back to /.
+ */
+ home_dir = g_get_home_dir ();
+ if (home_dir == NULL || chdir (home_dir) < 0)
+ (void) chdir ("/");
+
options = terminal_options_parse (working_directory,
NULL,
startup_id,
@@ -294,12 +513,11 @@ main (int argc, char **argv)
g_free (working_directory);
- if (!options)
- {
- g_printerr (_("Failed to parse arguments: %s\n"), error->message);
- g_error_free (error);
- exit (1);
- }
+ if (options == NULL) {
+ g_printerr (_("Failed to parse arguments: %s\n"), error->message);
+ g_error_free (error);
+ exit (EXIT_FAILURE);
+ }
g_set_application_name (_("Terminal"));
@@ -324,268 +542,50 @@ main (int argc, char **argv)
display_name = gdk_display_get_name (display);
options->display_name = g_strdup (display_name);
- if (!options->use_factory)
- goto factory_disabled;
+ if (options->use_factory) {
+ OwnData *data;
+ guint owner_id;
- /* Now try to acquire register us as the terminal factory */
- connection = dbus_g_bus_get (DBUS_BUS_SESSION, &error);
- if (!connection)
- {
- g_printerr ("Failed to get the session bus: %s\nFalling back to non-factory mode.\n",
- error->message);
- g_clear_error (&error);
- goto factory_disabled;
- }
+ data = g_new (OwnData, 1);
+ data->factory_name = get_factory_name_for_display (display_name);
+ data->options = options;
+ data->exit_code = -1;
+ data->argv = argv_copy;
+ data->argc = argc_copy;
- proxy = dbus_g_proxy_new_for_name (connection,
- DBUS_SERVICE_DBUS,
- DBUS_PATH_DBUS,
- DBUS_INTERFACE_DBUS);
-#if 0
- dbus_g_proxy_add_signal (proxy, "NameOwnerChanged",
- G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
- G_TYPE_INVALID);
- dbus_g_proxy_connect_signal (proxy, "NameOwnerChanged",
- G_CALLBACK (name_owner_changed), factory, NULL);
-#endif
+ owner_id = g_bus_own_name (G_BUS_TYPE_SESSION,
+ data->factory_name,
+ G_BUS_NAME_OWNER_FLAGS_NONE,
+ bus_acquired_cb,
+ name_acquired_cb,
+ name_lost_cb,
+ data, NULL);
- factory_name = get_factory_name_for_display (display_name);
- if (!org_freedesktop_DBus_request_name (proxy,
- factory_name,
- DBUS_NAME_FLAG_DO_NOT_QUEUE,
- &request_name_ret,
- &error))
- {
- g_printerr ("Failed name request: %s\n", error->message);
- g_clear_error (&error);
- goto factory_disabled;
- }
+ gtk_main ();
- /* Forward to the existing factory and exit */
- if (request_name_ret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
- {
- char **env;
- const char *evalue;
- GPtrArray *env_ptr_array;
- int envc;
- GArray *working_directory_array, *display_name_array, *startup_id_array;
- GArray *env_array, *argv_array;
- gboolean retval;
-
- _terminal_debug_print (TERMINAL_DEBUG_FACTORY,
- "Forwarding arguments to existing instance\n");
-
- env = g_listenv ();
- envc = g_strv_length (env);
- env_ptr_array = g_ptr_array_sized_new (envc);
- for (i = 0; i < envc; ++i)
- {
- evalue = g_getenv (env[i]);
- if (evalue)
- g_ptr_array_add (env_ptr_array, g_strdup_printf ("%s=%s", env[i], evalue));
- }
- g_ptr_array_add (env_ptr_array, NULL);
-
- g_strfreev (env);
- env = (char **) g_ptr_array_free (env_ptr_array, FALSE);
-
- working_directory = g_get_current_dir ();
- working_directory_array = terminal_util_string_to_array (working_directory);
- display_name_array = terminal_util_string_to_array (options->display_name);
- startup_id_array = terminal_util_string_to_array (options->startup_id);
- env_array = terminal_util_strv_to_array (envc, env);
- argv_array = terminal_util_strv_to_array (argc_copy, argv_copy);
-
- proxy = dbus_g_proxy_new_for_name (connection,
- factory_name,
- TERMINAL_FACTORY_SERVICE_PATH,
- TERMINAL_FACTORY_INTERFACE_NAME);
- retval = org_gnome_Terminal_Factory_handle_arguments (proxy,
- working_directory_array,
- display_name_array,
- startup_id_array,
- env_array,
- argv_array,
- &error);
- g_free (working_directory);
- g_array_free (working_directory_array, TRUE);
- g_array_free (display_name_array, TRUE);
- g_array_free (startup_id_array, TRUE);
- g_array_free (env_array, TRUE);
- g_array_free (argv_array, TRUE);
- g_strfreev (env);
-
- if (!retval)
- {
- if (g_error_matches (error, DBUS_GERROR, DBUS_GERROR_UNKNOWN_METHOD))
- {
- /* Incompatible factory version, fall back, to new instance */
- g_printerr (_("Incompatible factory version; creating a new instance.\n"));
- g_clear_error (&error);
-
- goto factory_disabled;
- }
-
- g_printerr (_("Factory error: %s\n"), error->message);
- g_error_free (error);
- ret = EXIT_FAILURE;
- }
-
- g_free (argv_copy);
- terminal_options_free (options);
-
- exit (ret);
- }
-
- factory = g_object_new (TERMINAL_TYPE_FACTORY, NULL);
- dbus_g_connection_register_g_object (connection,
- TERMINAL_FACTORY_SERVICE_PATH,
- G_OBJECT (factory));
-
- /* Now we're registered as the factory. Proceed to open the terminal(s). */
-
-factory_disabled:
- g_free (argv_copy);
- g_free (factory_name);
-
- /* If the gconf daemon isn't available (e.g. because there's no dbus
- * session bus running), we'd crash later on. Tell the user about it
- * now, and exit. See bug #561663.
- * Don't use gconf_ping_daemon() here since the server may just not
- * be running yet, but able to be started. See comments on bug #564649.
- */
- if (!gconf_spawn_daemon (&error))
- {
- g_printerr ("Failed to summon the GConf demon; exiting. %s\n", error->message);
- g_error_free (error);
- exit (1);
- }
-
- gtk_window_set_default_icon_name (GNOME_TERMINAL_ICON_NAME);
+ ret = data->exit_code;
+ g_bus_unown_name (owner_id);
- gtk_about_dialog_set_url_hook (about_url_hook, NULL, NULL);
- gtk_about_dialog_set_email_hook (about_email_hook, NULL, NULL);
-
-#if defined(WITH_SMCLIENT) && defined(GDK_WINDOWING_X11)
- {
- char *desktop_file;
-
- desktop_file = g_build_filename (TERM_DATADIR,
- "applications",
- PACKAGE ".desktop",
- NULL);
- egg_set_desktop_file_without_defaults (desktop_file);
- g_free (desktop_file);
- }
-#endif
+ g_free (data->factory_name);
+ g_free (data);
- terminal_app_initialize (options->use_factory);
- g_signal_connect (terminal_app_get (), "quit", G_CALLBACK (gtk_main_quit), NULL);
+ } else {
- terminal_app_handle_options (terminal_app_get (), options, TRUE /* allow resume */, &error);
- terminal_options_free (options);
+ terminal_app_handle_options (terminal_app_get (), options, TRUE /* allow resume */, &error);
+ terminal_options_free (options);
- if (error)
- {
+ if (error == NULL) {
+ gtk_main ();
+ } else {
g_printerr ("Error handling options: %s\n", error->message);
- g_clear_error (&error);
-
+ g_error_free (error);
ret = EXIT_FAILURE;
- goto shutdown;
}
-
- /* Now change directory to $HOME so we don't prevent unmounting, e.g. if the
- * factory is started by nautilus-open-terminal. See bug #565328.
- * On failure back to /.
- */
- home_dir = g_get_home_dir ();
- if (home_dir == NULL || chdir (home_dir) < 0)
- (void) chdir ("/");
-
- gtk_main ();
-
-shutdown:
+ }
terminal_app_shutdown ();
- if (factory)
- g_object_unref (factory);
-
- return ret;
-}
-
-/* Factory stuff */
-
-static gboolean
-terminal_factory_handle_arguments (TerminalFactory *terminal_factory,
- const GArray *working_directory_array,
- const GArray *display_name_array,
- const GArray *startup_id_array,
- const GArray *env_array,
- const GArray *argv_array,
- GError **error)
-{
- TerminalOptions *options = NULL;
- char *working_directory = NULL, *display_name = NULL, *startup_id = NULL;
- char **env = NULL, **argv = NULL, **argv_copy = NULL;
- int argc;
- GError *arg_error = NULL;
- gboolean retval;
-
- working_directory = terminal_util_array_to_string (working_directory_array, &arg_error);
- if (arg_error)
- goto out;
- display_name = terminal_util_array_to_string (display_name_array, &arg_error);
- if (arg_error)
- goto out;
- startup_id = terminal_util_array_to_string (startup_id_array, &arg_error);
- if (arg_error)
- goto out;
- env = terminal_util_array_to_strv (env_array, NULL, &arg_error);
- if (arg_error)
- goto out;
- argv = terminal_util_array_to_strv (argv_array, &argc, &arg_error);
- if (arg_error)
- goto out;
-
- _terminal_debug_print (TERMINAL_DEBUG_FACTORY,
- "Factory invoked with working-dir='%s' display='%s' startup-id='%s'\n",
- working_directory ? working_directory : "(null)",
- display_name ? display_name : "(null)",
- startup_id ? startup_id : "(null)");
-
- /* Copy the arguments since terminal_options_parse potentially modifies the array */
- argv_copy = (char **) g_memdup (argv, (argc + 1) * sizeof (char *));
-
- options = terminal_options_parse (working_directory,
- display_name,
- startup_id,
- env,
- TRUE,
- TRUE,
- &argc, &argv_copy,
- error,
- NULL);
-
-out:
- g_free (working_directory);
- g_free (display_name);
- g_free (startup_id);
- g_strfreev (env);
- g_strfreev (argv);
g_free (argv_copy);
- if (arg_error)
- {
- g_propagate_error (error, arg_error);
- return FALSE;
- }
-
- if (!options)
- return FALSE;
-
- retval = terminal_app_handle_options (terminal_app_get (), options, FALSE /* no resume */, error);
-
- terminal_options_free (options);
- return retval;
+ return ret;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]