[glib/application: 135/135] GApplication is starting to work...



commit 034c5483402013b93fe52bd0de14db920638aaac
Author: Ryan Lortie <desrt desrt ca>
Date:   Thu Aug 5 19:57:27 2010 -0400

    GApplication is starting to work...

 gio/Makefile.am                       |    2 +
 gio/gapplication.c                    |  783 +++++++++++++++------------------
 gio/gapplication.h                    |   21 +-
 gio/gapplicationimpl-dbus-interface.c |   90 ++++
 gio/gapplicationimpl-dbus-private.h   |   29 ++
 gio/gapplicationimpl-dbus.c           |  310 +++++++++++++
 gio/gapplicationinvocation.c          |   22 +-
 gio/gdbusapplication.c                |  424 ------------------
 gio/gioenums.h                        |   20 +
 9 files changed, 838 insertions(+), 863 deletions(-)
---
diff --git a/gio/Makefile.am b/gio/Makefile.am
index 44f3b59..32064be 100644
--- a/gio/Makefile.am
+++ b/gio/Makefile.am
@@ -260,6 +260,8 @@ SUBDIRS += tests
 
 libgio_2_0_la_SOURCES =		\
 	gappinfo.c 		\
+	gapplicationimpl-dbus-interface.h \
+	gapplicationimpl-dbus-interface.c \
 	gapplicationinvocation.c\
 	gapplication.c		\
 	gapplication.h		\
diff --git a/gio/gapplication.c b/gio/gapplication.c
index 669c5c6..cd5ed1f 100644
--- a/gio/gapplication.c
+++ b/gio/gapplication.c
@@ -1,5 +1,6 @@
 /* GIO - GLib Input, Output and Streaming Library
  *
+ * Coypright © 2010 Codethink Limited
  * Copyright © 2010 Red Hat, Inc
  *
  * This library is free software; you can redistribute it and/or
@@ -19,6 +20,7 @@
  *
  * Authors: Colin Walters <walters verbum org>
  *          Emmanuele Bassi <ebassi linux intel com>
+ *          Ryan Lortie <desrt desrt ca>
  */
 
 #include "config.h"
@@ -38,7 +40,8 @@
 #include "gdbusconnection.h"
 #include "gdbusintrospection.h"
 #include "gdbusmethodinvocation.h"
-
+#include "gioenumtypes.h"
+#include "gapplicationinvocation.h"
 
 /**
  * SECTION: gapplication
@@ -167,92 +170,86 @@
  * </refsect2>
  */
 
-static void initable_iface_init       (GInitableIface      *initable_iface);
+G_DEFINE_TYPE (GApplication, g_application, G_TYPE_OBJECT)
+
+typedef struct _GApplicationImpl GApplicationImpl;
+
+static void     g_application_impl_init     (GApplicationImpl  *impl,
+                                             gpointer           app);
+
+static void     g_application_impl_set_id   (GApplicationImpl  *impl,
+                                             const gchar       *appid);
+
+static gboolean g_application_impl_register (GApplicationImpl  *impl,
+                                             gboolean          *is_remote,
+                                             GCancellable      *cancellable,
+                                             GError           **error);
+
+static void     g_application_impl_activate (GApplicationImpl  *impl,
+                                             GVariant          *platform_data);
+
+static void     g_application_impl_open     (GApplicationImpl  *impl,
+                                             GFile            **files,
+                                             gint               n_files,
+                                             const gchar       *hint,
+                                             GVariant          *platform_data);
+
+static void     g_application_impl_action   (GApplicationImpl  *impl,
+                                             const gchar       *action_name,
+                                             GVariant          *parameters,
+                                             GVariant          *platform_data);
+
+static int      g_application_impl_cmdline  (GApplicationImpl  *impl,
+                                             GVariant          *arguments,
+                                             GVariant          *platform_data);
 
-G_DEFINE_TYPE_WITH_CODE (GApplication, g_application, G_TYPE_OBJECT,
-                         G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, initable_iface_init));
+static void     g_application_impl_flush    (GApplicationImpl  *impl);
 
+#ifdef G_OS_UNIX
+#include "gapplicationimpl-dbus.c"
+#else
+#include "gnullapplication.c"
+#endif
 
 enum
 {
   PROP_0,
 
   PROP_APPLICATION_ID,
+  PROP_FLAGS,
   PROP_IS_REMOTE
 };
 
-enum
-{
-  QUIT_WITH_DATA,
-  ACTION_WITH_DATA,
-  PREPARE_ACTIVATION,
-
-  LAST_SIGNAL
-};
-
-static guint application_signals[LAST_SIGNAL] = { 0 };
-
 typedef struct {
   gchar *name;
   gchar *description;
-  guint enabled : 1;
+
+  GVariantType *type;
+  gboolean enabled;
 } GApplicationAction;
 
 struct _GApplicationPrivate
 {
   gchar *appid;
+
   GHashTable *actions; /* name -> GApplicationAction */
   GMainLoop *mainloop;
 
-  GVariant *argv;
-  GVariant *platform_data;
+  guint is_remote  : 1;
+  guint registered : 1;
 
-  guint do_register  : 1;
-  guint default_quit : 1;
-  guint is_remote    : 1;
-  guint registration_tried : 1;
+  GApplicationFlags flags;
+  guint use_count;
+  guint inactivity_timeout;
 
   guint actions_changed_id;
-#ifdef G_OS_UNIX
-  gchar *dbus_path;
-  GDBusConnection *session_bus;
-#endif
+
+  GApplicationImpl impl;
 };
 
 static GApplication *primary_application = NULL;
 static GHashTable *instances_for_appid = NULL;
 
-static gboolean initable_init (GInitable     *initable,
-			       GCancellable  *cancellable,
-			       GError       **error);
-
-static gboolean _g_application_platform_init                    (GApplication  *app,
-								 GCancellable  *cancellable,
-								 GError       **error); 
-static gboolean _g_application_platform_register                (GApplication  *app,
-								 gboolean      *unique,
-								 GCancellable  *cancellable,
-								 GError       **error); 
-
-static void     _g_application_platform_remote_invoke_action    (GApplication  *app,
-                                                                 const gchar   *action,
-                                                                 GVariant      *platform_data);
-static void     _g_application_platform_remote_quit             (GApplication  *app,
-                                                                 GVariant      *platform_data);
-static void     _g_application_platform_on_actions_changed      (GApplication  *app);
-
-static void
-initable_iface_init (GInitableIface *initable_iface)
-{
-  initable_iface->init = initable_init;
-}
-
-#ifdef G_OS_UNIX
-#include "gdbusapplication.c"
-#else
-#include "gnullapplication.c"
-#endif
-
 static gboolean
 _g_application_validate_id (const char *id)
 {
@@ -295,58 +292,27 @@ application_for_appid (const char *appid)
   return g_hash_table_lookup (instances_for_appid, appid);
 }
 
-static gboolean
-g_application_default_quit_with_data (GApplication *application,
-				      GVariant     *platform_data)
-{
-  g_return_val_if_fail (application->priv->mainloop != NULL, FALSE);
-  g_main_loop_quit (application->priv->mainloop);
-
-  return TRUE;
-}
-
-static gint
-g_application_default_run (GApplication *application,
-                           GVariant     *arguments,
-                           GVariant     *platform_data)
-{
-  if (application->priv->mainloop == NULL)
-    application->priv->mainloop = g_main_loop_new (NULL, TRUE);
-
-  g_main_loop_run (application->priv->mainloop);
-
-  return 0;
-}
-
 static GVariant *
-append_cwd_to_platform_data (GVariant *platform_data)
+g_application_get_platform_data (GApplication *application)
 {
-  GVariantBuilder builder;
-  gchar *cwd;
+  GVariantBuilder *builder;
   GVariant *result;
 
-  cwd = g_get_current_dir ();
+  builder = g_variant_builder_new (G_VARIANT_TYPE ("a{sv}"));
 
-  g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}"));
-  if (cwd)
-    g_variant_builder_add (&builder, "{sv}",
-			   "cwd",
-			   g_variant_new_bytestring (cwd));
-  g_free (cwd);
+  {
+    gchar *cwd = g_get_current_dir ();
+    g_variant_builder_add (builder, "{sv}", "cwd",
+                           g_variant_new_bytestring (cwd));
+    g_free (cwd);
+  }
+
+  G_APPLICATION_GET_CLASS (application)->
+    add_platform_data (application, builder);
+
+  result = g_variant_builder_end (builder);
+  g_variant_builder_unref (builder);
 
-  if (platform_data)
-    {
-      GVariantIter iter;
-      GVariant *item;
-
-      g_variant_iter_init (&iter, platform_data);
-      while (g_variant_iter_next (&iter, "@{sv}", &item))
-	{
-	  g_variant_builder_add_value (&builder, item);
-	  g_variant_unref (item);
-	}
-    }
-  result = g_variant_builder_end (&builder);
   return result;
 }
 
@@ -357,8 +323,6 @@ timeout_handle_actions_changed (gpointer user_data)
 
   application->priv->actions_changed_id = 0;
 
-  _g_application_platform_on_actions_changed (application);
-
   return FALSE;
 }
 
@@ -371,24 +335,6 @@ queue_actions_change_notification (GApplication *application)
     priv->actions_changed_id = g_timeout_add (0, timeout_handle_actions_changed, application);
 }
 
-static gboolean
-initable_init (GInitable     *initable,
-               GCancellable  *cancellable,
-               GError       **error)
-{
-  GApplication *app = G_APPLICATION (initable);
-  gboolean unique;
-
-  if (!_g_application_platform_init (app, cancellable, error))
-    return FALSE;
-
-  if (app->priv->do_register
-      && !_g_application_platform_register (app, &unique, cancellable ,error))
-    return FALSE;
-
-  return TRUE;
-}
-
 static void
 g_application_action_free (gpointer data)
 {
@@ -442,12 +388,14 @@ g_application_action_free (gpointer data)
  * Since: 2.26
  */
 GApplication *
-g_application_new (const gchar *appid)
+g_application_new (const gchar       *appid,
+                   GApplicationFlags  flags)
 {
   g_type_init ();
 
   return g_object_new (G_TYPE_APPLICATION,
                        "application-id", appid,
+                       "flags", flags,
                        NULL);
 }
 
@@ -498,17 +446,25 @@ g_application_try_new (const gchar *appid)
  * Returns: %TRUE if registration was successful
  */
 gboolean
-g_application_register (GApplication *application)
+g_application_register (GApplication  *application,
+                        GCancellable  *cancellable,
+                        GError       **error)
 {
-  gboolean unique;
+  gboolean is_remote;
 
   g_return_val_if_fail (G_IS_APPLICATION (application), FALSE);
-  g_return_val_if_fail (application->priv->is_remote, FALSE);
-  g_return_val_if_fail (!application->priv->registration_tried, FALSE);
 
-  if (!_g_application_platform_register (application, &unique, NULL, NULL))
+  if (application->priv->registered)
+    return TRUE;
+
+  if (!g_application_impl_register (&application->priv->impl,
+                                    &is_remote, cancellable, error))
     return FALSE;
-  return unique;
+
+  application->priv->is_remote = is_remote;
+  application->priv->registered = TRUE;
+
+  return TRUE;
 }
 
 /**
@@ -586,67 +542,6 @@ g_application_remove_action (GApplication *application,
 }
 
 /**
- * g_application_invoke_action:
- * @application: a #GApplication
- * @name: the name of the action to invoke
- * @platform_data: (allow-none): platform-specific event data
- *
- * Invokes the action @name of the passed #GApplication.
- *
- * This function has different behavior depending on whether @application
- * is acting as a proxy for another process.  In the normal case where
- * the current process is hosting the application, and the specified
- * action exists and is enabled, the #GApplication::action signal will
- * be emitted.
- *
- * If @application is a proxy, then the specified action will be invoked
- * in the remote process. It is not necessary to call
- * g_application_add_action() in the current process in order to invoke
- * one remotely.
- *
- * Since: 2.26
- */
-void
-g_application_invoke_action (GApplication *application,
-                             const gchar  *name,
-                             GVariant     *platform_data)
-{
-  GApplicationPrivate *priv;
-  GApplicationAction *action;
-
-  g_return_if_fail (G_IS_APPLICATION (application));
-  g_return_if_fail (name != NULL);
-  g_return_if_fail (platform_data == NULL
-                    || g_variant_is_of_type (platform_data, G_VARIANT_TYPE ("a{sv}")));
-  
-  if (platform_data == NULL)
-    platform_data = g_variant_new_array (G_VARIANT_TYPE ("{sv}"), NULL, 0);
-  else
-    g_variant_ref (platform_data);
-
-  priv = application->priv;
-  
-  if (priv->is_remote)
-    {
-      _g_application_platform_remote_invoke_action (application, name, platform_data);
-      goto out;
-    }
-
-  action = g_hash_table_lookup (priv->actions, name);
-  g_return_if_fail (action != NULL);
-  if (!action->enabled)
-    goto out;
-
-  g_signal_emit (application, application_signals[ACTION_WITH_DATA],
-                 g_quark_from_string (name),
-                 name,
-                 platform_data);
-
- out:
-  g_variant_unref (platform_data);
-}
-
-/**
  * g_application_list_actions:
  * @application: a #GApplication
  *
@@ -747,7 +642,7 @@ g_application_get_action_description (GApplication *application,
                                       const gchar  *name)
 {
   GApplicationAction *action;
-  
+
   g_return_val_if_fail (G_IS_APPLICATION (application), NULL);
   g_return_val_if_fail (name != NULL, NULL);
   g_return_val_if_fail (!application->priv->is_remote, NULL);
@@ -758,7 +653,6 @@ g_application_get_action_description (GApplication *application,
   return action->description;
 }
 
-
 /**
  * g_application_get_action_enabled:
  * @application: a #GApplication
@@ -792,81 +686,6 @@ g_application_get_action_enabled (GApplication *application,
 }
 
 /**
- * g_application_run:
- * @application: a #GApplication
- *
- * Starts the application.
- *
- * The default implementation of this virtual function will simply run
- * a main loop.
- *
- * It is an error to call this function if @application is a proxy for
- * a remote application.
- *
- * Since: 2.26
- */
-int
-g_application_run (GApplication  *application,
-                   int            argc,
-                   char         **argv)
-{
-  GVariant *arguments;
-
-  g_return_val_if_fail (G_IS_APPLICATION (application), 1);
-
-  arguments = g_variant_new_bytestring_array ((const gchar **) argv, argc);
-
-  return G_APPLICATION_GET_CLASS (application)->run (application, arguments);
-}
-
-/**
- * g_application_quit_with_data:
- * @application: a #GApplication
- * @platform_data: (allow-none): platform-specific data
- *
- * Request that the application quits.
- *
- * This function has different behavior depending on whether @application
- * is acting as a proxy for another process.  In the normal case where
- * the current process is hosting the application, the default
- * implementation will quit the main loop created by g_application_run().
- *
- * If @application is a proxy, then the remote process will be asked
- * to quit.
- *
- * Returns: %TRUE if the application accepted the request, %FALSE otherwise
- *
- * Since: 2.26
- */
-gboolean
-g_application_quit_with_data (GApplication *application,
-			      GVariant     *platform_data)
-{
-  gboolean retval = FALSE;
-
-  g_return_val_if_fail (G_IS_APPLICATION (application), FALSE);
-  g_return_val_if_fail (platform_data == NULL
-			|| g_variant_is_of_type (platform_data, G_VARIANT_TYPE ("a{sv}")), FALSE);
-
-  if (platform_data == NULL)
-    platform_data = g_variant_new_array (G_VARIANT_TYPE ("{sv}"), NULL, 0);
-  else
-    g_variant_ref (platform_data);
-
-  if (application->priv->is_remote)
-    {
-       _g_application_platform_remote_quit (application, platform_data);
-       retval = TRUE;
-    }
-  else
-    g_signal_emit (application, application_signals[QUIT_WITH_DATA], 0, platform_data, &retval);
-
-  g_variant_unref (platform_data);
-
-  return retval;
-}
-
-/**
  * g_application_get_instance:
  *
  * In the normal case where there is exactly one #GApplication instance
@@ -930,10 +749,15 @@ g_application_init (GApplication *app)
   app->priv->actions = g_hash_table_new_full (g_str_hash, g_str_equal,
                                               NULL,
                                               g_application_action_free);
-  app->priv->default_quit = TRUE;
-  app->priv->do_register = TRUE;
-  app->priv->is_remote = TRUE;
-  app->priv->platform_data = g_variant_new_array (G_VARIANT_TYPE ("{sv}"), NULL, 0);
+  g_application_impl_init (&app->priv->impl, app);
+}
+
+GApplicationFlags
+g_application_get_flags (GApplication *application)
+{
+  g_return_val_if_fail (G_IS_APPLICATION (application), 0);
+
+  return application->priv->flags;
 }
 
 static void
@@ -950,6 +774,9 @@ g_application_get_property (GObject    *object,
       g_value_set_string (value, g_application_get_id (app));
       break;
 
+    case PROP_FLAGS:
+      g_value_set_flags (value, g_application_get_flags (app));
+
     case PROP_IS_REMOTE:
       g_value_set_boolean (value, g_application_is_remote (app));
       break;
@@ -972,6 +799,11 @@ g_application_set_property (GObject      *object,
     case PROP_APPLICATION_ID:
       g_return_if_fail (_g_application_validate_id (g_value_get_string (value)));
       app->priv->appid = g_value_dup_string (value);
+      g_application_impl_set_id (&app->priv->impl, app->priv->appid);
+      break;
+
+    case PROP_FLAGS:
+      app->priv->flags = g_value_get_flags (value);
       break;
 
     default:
@@ -979,46 +811,13 @@ g_application_set_property (GObject      *object,
     }
 }
 
-static GObject*
-g_application_constructor (GType                  type,
-                           guint                  n_construct_properties,
-                           GObjectConstructParam *construct_params)
-{
-  GApplication *app;
-  GObject *object;
-  const char *appid = NULL;
-  guint i;
-
-  for (i = 0; i < n_construct_properties; i++)
-    {
-      GObjectConstructParam *param = &construct_params[i];
-      if (strcmp (param->pspec->name, "application-id") == 0)
-        appid = g_value_get_string (param->value);
-    }
-
-  g_return_val_if_fail (appid != NULL, NULL);
-
-  app = application_for_appid (appid);
-  if (app != NULL)
-    return g_object_ref (app);
-
-  object = (* G_OBJECT_CLASS (g_application_parent_class)->constructor) (type,
-                                                                         n_construct_properties,
-                                                                         construct_params);
-  app = G_APPLICATION (object);
-
-  if (primary_application == NULL)
-    primary_application = app;
-  g_hash_table_insert (instances_for_appid, g_strdup (appid), app);
-
-  return object;
-}
-
 static void
 g_application_finalize (GObject *object)
 {
   GApplication *app = G_APPLICATION (object);
 
+  g_application_impl_destroy (&app->priv->impl);
+
   g_free (app->priv->appid);
   if (app->priv->actions)
     g_hash_table_unref (app->priv->actions);
@@ -1027,13 +826,90 @@ g_application_finalize (GObject *object)
   if (app->priv->mainloop)
     g_main_loop_unref (app->priv->mainloop);
 
-#ifdef G_OS_UNIX
-  g_free (app->priv->dbus_path);
-  if (app->priv->session_bus)
-    g_object_unref (app->priv->session_bus);
-#endif
+  G_OBJECT_CLASS (g_application_parent_class)
+    ->finalize (object);
+}
+
+static gboolean
+g_application_process_cmdline (GApplication  *application,
+                               GVariant     **arguments,
+                               int           *exit_status)
+{
+  return FALSE;
+}
+
+static void
+g_application_add_platform_data (GApplication    *application,
+                                 GVariantBuilder *builder)
+{
+}
+
+static GApplicationInvocation *
+g_application_create_invocation (GApplication *application,
+                                 GVariant     *arguments,
+                                 GVariant     *platform_data)
+{
+  return g_object_new (G_TYPE_APPLICATION_INVOCATION,
+                       "arguments", arguments,
+                       "platform-data", platform_data,
+                       NULL);
+}
 
-  G_OBJECT_CLASS (g_application_parent_class)->finalize (object);
+static int
+g_application_emit_cmdline (GApplication           *application,
+                            GApplicationInvocation *invocation)
+{
+  return G_APPLICATION_GET_CLASS (application)
+    ->cmdline (application, invocation);
+}
+
+int
+g_application_real_cmdline (GApplication           *application,
+                            GApplicationInvocation *invocation)
+{
+  g_warning ("G_APPLICATION_FLAGS_REMOTE_CMDLINE specified but the "
+             "cmdline() virtual function has not been implemented");
+
+  return 1;
+}
+
+static void
+g_application_real_run_mainloop (GApplication *application)
+{
+  if (application->priv->mainloop == NULL)
+    application->priv->mainloop = g_main_loop_new (NULL, TRUE);
+
+  g_main_loop_run (application->priv->mainloop);
+}
+
+static void
+g_application_real_quit_mainloop (GApplication *application)
+{
+  g_main_loop_quit (application->priv->mainloop);
+}
+
+void
+g_application_startup (GApplication *application)
+{
+}
+
+static void
+g_application_emit_activate (GApplication *application,
+                             GVariant     *platform_data)
+{
+  G_APPLICATION_GET_CLASS (application)
+    ->activate (application);
+}
+
+static void
+g_application_emit_open (GApplication  *application,
+                         GFile        **files,
+                         gint           n_files,
+                         const gchar   *hint,
+                         GVariant      *platform_data)
+{
+  G_APPLICATION_GET_CLASS (application)
+    ->open (application, files, n_files, hint);
 }
 
 static void
@@ -1041,87 +917,26 @@ g_application_class_init (GApplicationClass *klass)
 {
   GObjectClass *gobject_class G_GNUC_UNUSED = G_OBJECT_CLASS (klass);
 
+  klass->process_cmdline = g_application_process_cmdline;
+  klass->add_platform_data = g_application_add_platform_data;
+  klass->create_invocation = g_application_create_invocation;
+  klass->emit_cmdline = g_application_emit_cmdline;
+  klass->cmdline = g_application_real_cmdline;
+  klass->run_mainloop = g_application_real_run_mainloop;
+  klass->quit_mainloop = g_application_real_quit_mainloop;
+  klass->startup = g_application_startup;
+  klass->emit_activate = g_application_emit_activate;
+  klass->emit_open = g_application_emit_open;
+
   g_type_class_add_private (klass, sizeof (GApplicationPrivate));
 
-  gobject_class->constructor = g_application_constructor;
   gobject_class->set_property = g_application_set_property;
   gobject_class->get_property = g_application_get_property;
 
   gobject_class->finalize = g_application_finalize;
 
-  klass->run = g_application_default_run;
-  klass->quit_with_data = g_application_default_quit_with_data;
-
-  /**
-   * GApplication::quit-with-data:
-   * @application: the object on which the signal is emitted
-   * @platform_data: Platform-specific data, or %NULL
-   *
-   * This signal is emitted when the Quit action is invoked on the
-   * application.
-   *
-   * The default handler for this signal exits the mainloop of the
-   * application.
-   *
-   * Returns: %TRUE if the signal has been handled, %FALSE to continue
-   *   signal emission
-   */
-  application_signals[QUIT_WITH_DATA] =
-    g_signal_new (g_intern_static_string ("quit-with-data"),
-                  G_OBJECT_CLASS_TYPE (klass),
-                  G_SIGNAL_RUN_LAST,
-                  G_STRUCT_OFFSET (GApplicationClass, quit_with_data),
-                  g_signal_accumulator_true_handled, NULL,
-                  _gio_marshal_BOOLEAN__VARIANT,
-                  G_TYPE_BOOLEAN, 1,
-                  G_TYPE_VARIANT);
-
-  /**
-   * GApplication::action-with-data:
-   * @application: the object on which the signal is emitted
-   * @name: The name of the activated action
-   * @platform_data: Platform-specific data, or %NULL
-   *
-   * This signal is emitted when an action is activated. The action name
-   * is passed as the first argument, but also as signal detail, so it
-   * is possible to connect to this signal for individual actions.
-   *
-   * The signal is never emitted for disabled actions.
-   */
-  application_signals[ACTION_WITH_DATA] =
-    g_signal_new (g_intern_static_string ("action-with-data"),
-                  G_OBJECT_CLASS_TYPE (klass),
-                  G_SIGNAL_RUN_FIRST | G_SIGNAL_NO_RECURSE | G_SIGNAL_DETAILED,
-                  G_STRUCT_OFFSET (GApplicationClass, action_with_data),
-                  NULL, NULL,
-                  _gio_marshal_VOID__STRING_VARIANT,
-                  G_TYPE_NONE, 2,
-                  G_TYPE_STRING,
-                  G_TYPE_VARIANT);
-
-   /**
-   * GApplication::prepare-activation:
-   * @application: the object on which the signal is emitted
-   * @arguments: A #GVariant with the signature "aay"
-   * @platform_data: A #GVariant with the signature "a{sv}", or %NULL
-   *
-   * This signal is emitted when a non-primary process for a given
-   * application is invoked while your application is running; for
-   * example, when a file browser launches your program to open a
-   * file.  The raw operating system arguments are passed in the
-   * @arguments variant.  Additional platform-dependent data is
-   * stored in @platform_data.
-   */
-  application_signals[PREPARE_ACTIVATION] =
-    g_signal_new (g_intern_static_string ("prepare-activation"),
-                  G_OBJECT_CLASS_TYPE (klass),
-                  G_SIGNAL_RUN_LAST,
-                  G_STRUCT_OFFSET (GApplicationClass, prepare_activation),
-                  NULL, NULL,
-                  _gio_marshal_VOID__VARIANT_VARIANT,
-                  G_TYPE_NONE, 2,
-                  G_TYPE_VARIANT,
-                  G_TYPE_VARIANT);
+  //klass->run = g_application_default_run;
+  //klass->quit_with_data = g_application_default_quit_with_data;
 
   /**
    * GApplication:application-id:
@@ -1154,6 +969,22 @@ g_application_class_init (GApplicationClass *klass)
                                                          P_("Whether this application is a proxy for another process"),
                                                          TRUE,
                                                          G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
+
+  /**
+   * GApplication:flags:
+   *
+   * The flags that define the behaviour of this application.
+   **/
+  g_object_class_install_property (gobject_class,
+                                   PROP_FLAGS,
+                                   g_param_spec_flags ("flags",
+                                                       P_("Application Flags"),
+                                                       P_("Application Flags"),
+                                                       G_TYPE_APPLICATION_FLAGS,
+                                                       G_APPLICATION_FLAGS_NONE,
+                                                       G_PARAM_READWRITE |
+                                                       G_PARAM_CONSTRUCT_ONLY |
+                                                       G_PARAM_STATIC_STRINGS));
 }
 
 
@@ -1169,7 +1000,7 @@ g_application_class_init (GApplicationClass *klass)
  *
  * If this process is the first instance of the application that was
  * invoked then the 'open' signal is emitted.
- *
+ */
 
 /**
  * g_application_invoke_variant:
@@ -1182,49 +1013,103 @@ g_application_class_init (GApplicationClass *klass)
  * This is a bindings-friendly version of g_application_invoke().
  **/
 int
-g_application_invoke_variant (GApplication *application,
-                              GVariant     *arguments)
+g_application_cmdline_with_arguments (GApplication *application,
+                                      GVariant     *arguments)
 {
   GApplicationClass *class = G_APPLICATION_GET_CLASS (application);
+  GError *error = NULL;
   int exit_status;
 
   g_variant_ref_sink (arguments);
 
-  if (class->preprocess_args (application, &arguments, &exit_status))
+  if (class->process_cmdline (application, &arguments, &exit_status))
     {
       g_variant_unref (arguments);
       return exit_status;
     }
 
-  g_application_register (application);
+  if (!g_application_register (application, NULL, &error))
+    {
+      g_critical ("%s", error->message);
+      g_variant_unref (arguments);
+      g_error_free (error);
 
-  if (g_application_is_remote (application))
+      return 1;
+    }
+
+  if (application->priv->flags & G_APPLICATION_FLAGS_REMOTE_CMDLINE)
     {
-      GVariantBuilder *builder;
-      GVariant *platform_data;
+      if (g_application_is_remote (application))
+        {
+          GVariant *platform_data;
+
+          platform_data = g_application_get_platform_data (application);
+          exit_status = g_application_impl_cmdline (&application->priv->impl,
+                                                    arguments, platform_data);
+        }
+      else
+        {
+          GApplicationInvocation *invocation;
+
+          invocation = G_APPLICATION_GET_CLASS (application)
+            ->create_invocation (application, arguments, NULL);
 
-      builder = g_variant_builder_new (G_VARIANT_TYPE ("a{sv}"));
-      class->add_platform_data (application, builder);
-      platform_data = g_variant_builder_end (builder);
-      g_variant_builder_free (builder);
+          exit_status = class->emit_cmdline (application, invocation);
 
-      status = remote_impl_run (arguments, platform_data);
+          g_object_unref (invocation);
+
+          if (exit_status == 0)
+            class->run_mainloop (application);
+        }
     }
-  else
+
+  else /* not G_APPLICATION_FLAGS_REMOTE_CMDLINE */
     {
-      GApplicationInvocation *invocation;
+      gint n;
+
+      n = g_variant_n_children (arguments);
 
-      invocation = class->create_invocation (application, arguments, NULL);
-      class->prepare_invocation (application, invocation);
-      exit_status = class->invoked (application, invocation);
-      g_object_unref (invocation);
+      if (n < 2)
+        g_application_activate (application);
 
-      if (exit_status == 0)
-        class->run_mainloop (application);
+      else
+        {
+          if (application->priv->flags & G_APPLICATION_FLAGS_CAN_OPEN)
+            {
+              GFile **files;
+              gint i;
+
+              files = g_new (GFile *, (n - 1) + 1);
+              for (i = 0; i < n - 1; i++)
+                {
+                  const gchar *arg;
+
+                  g_variant_get_child (arguments, i + 1, "^&ay", &arg);
+                  files[i] = g_file_new_for_commandline_arg (arg);
+                }
+              files[i] = NULL;
+
+              g_application_open (application, files, n - 1, "");
+            }
+
+          else
+            {
+              g_critical ("This application does not open files.");
+              exit_status = 1;
+            }
+        }
     }
 
   g_variant_unref (arguments);
 
+  if (application->priv->use_count)
+    {
+      G_APPLICATION_GET_CLASS (application)->run_mainloop (application);
+      exit_status = 0;
+    }
+
+  g_application_impl_flush (&application->priv->impl);
+
   return exit_status;
 }
 
@@ -1266,13 +1151,13 @@ g_application_invoke_variant (GApplication *application,
  * status of the process calling it.
  **/
 int
-g_application_invoke (GApplication *application,
-                      int argc, char **argv)
+g_application_cmdline (GApplication *application,
+                       int argc, char **argv)
 {
   GVariant *args;
 
-  args = g_variant_bytestring_array_new ((const gchar **) argv, argc);
-  return g_application_invoke_with_arguments (args);
+  args = g_variant_new_bytestring_array ((const gchar **) argv, argc);
+  return g_application_cmdline_with_arguments (application, args);
 }
 
 /**
@@ -1293,12 +1178,26 @@ g_application_hold (GApplication *application)
   if (application->priv->inactivity_timeout)
     {
       g_source_remove (application->priv->inactivity_timeout);
-      application->priv->inactivity_timeout;
+      application->priv->inactivity_timeout = 0;
     }
 
   application->priv->use_count++;
 }
 
+void
+g_application_quit_mainloop (GApplication *app)
+{
+  G_APPLICATION_GET_CLASS (app)
+    ->quit_mainloop (app);
+}
+
+void
+g_application_run_mainloop (GApplication *app)
+{
+  G_APPLICATION_GET_CLASS (app)
+    ->run_mainloop (app);
+}
+
 /**
  * g_application_release:
  * @application: a #GApplication
@@ -1316,7 +1215,7 @@ g_application_release (GApplication *application)
   application->priv->use_count--;
 
   if (application->priv->use_count == 0)
-    g_application_quit (application);
+    g_application_quit_mainloop (application);
 }
 
 static gboolean
@@ -1326,11 +1225,27 @@ g_application_inactivity_timeout (gpointer data)
 
   g_message ("exiting application due to inactivity");
   application->priv->inactivity_timeout = 0;
-  g_application_quit (application);
+  g_application_quit_mainloop (application);
 
   return FALSE;
 }
 
+void
+g_application_activate (GApplication *application)
+{
+  g_print ("act\n");
+  if (g_application_is_remote (application))
+    {
+      GVariant *platform_data;
+
+      platform_data = g_application_get_platform_data (application);
+      g_application_impl_activate (&application->priv->impl, platform_data);
+    }
+  else
+    G_APPLICATION_GET_CLASS (application)
+      ->activate (application);
+}
+
 /**
  * g_application_run_service:
  * @application: a #GApplication
@@ -1364,17 +1279,43 @@ g_application_inactivity_timeout (gpointer data)
 int
 g_application_run_service (GApplication *application)
 {
+  GError *error = NULL;
+
   g_return_val_if_fail (G_IS_APPLICATION (application), 1);
-  g_return_val_if_fail (application->priv->disposition ==
-                          G_APPLICATION_DISPOSITION_SERVICE ||
-                        !application->priv->registered, 1);
 
-  g_application_set_disposition (application,
-                                 G_APPLICATION_DISPOSITION_SERVICE);
-  g_application_register (application);
+  if (!g_application_register (application, NULL, &error))
+    {
+      g_critical ("%s", error->message);
+      g_error_free (error);
+
+      return 1;
+    }
 
   application->priv->inactivity_timeout =
     g_timeout_add (10000, g_application_inactivity_timeout, application);
 
   g_application_run_mainloop (application);
+
+  return 0;
+}
+
+void
+g_application_open (GApplication  *application,
+                    GFile        **files,
+                    gint           n_files,
+                    const gchar   *hint)
+{
+  if (g_application_is_remote (application))
+    {
+      GVariant *platform_data;
+
+      platform_data = g_application_get_platform_data (application);
+      g_application_impl_open (&application->priv->impl,
+                               files, n_files, hint, platform_data);
+    }
+  else
+    {
+      G_APPLICATION_GET_CLASS (application)
+        ->open (application, files, n_files, hint);
+    }
 }
diff --git a/gio/gapplication.h b/gio/gapplication.h
index 91a646a..19c6ad5 100644
--- a/gio/gapplication.h
+++ b/gio/gapplication.h
@@ -97,7 +97,7 @@ struct _GApplicationClass
   /* vfuncs */
   void                     (* add_platform_data)  (GApplication            *application,
                                                    GVariantBuilder         *builder);
-  gboolean                 (* process_arguments)  (GApplication            *application,
+  gboolean                 (* process_cmdline)    (GApplication            *application,
                                                    GVariant               **arguments,
                                                    gint                    *exit_status);
 
@@ -105,10 +105,12 @@ struct _GApplicationClass
                                                    GVariant                *arguments,
                                                    GVariant                *platform_data);
 
-  void                     (* emit_invocation)    (GApplication            *application,
+  int                      (* emit_cmdline)       (GApplication            *application,
                                                    GApplicationInvocation  *invocation);
   void                     (* emit_open)          (GApplication            *application,
-                                                   GFile                   *file,
+                                                   GFile                  **files,
+                                                   gint                     n_files,
+                                                   const gchar             *hint,
                                                    GVariant                *platform_data);
   void                     (* emit_activate)      (GApplication            *application,
                                                    GVariant                *platform_data);
@@ -117,19 +119,12 @@ struct _GApplicationClass
                                                    GVariant                *platform_data);
 
   void                     (* quit_mainloop)      (GApplication            *application);
-  int                      (* run_mainloop)       (GApplication            *application);
+  void                     (* run_mainloop)       (GApplication            *application);
 
   /*< private >*/
   gpointer padding[12];
 };
 
-typedef enum
-{
-  G_APPLICATION_FLAGS_NONE,
-  G_APPLICATION_FLAGS_CAN_OPEN          = (1 << 0),
-  G_APPLICATION_FLAGS_REMOTE_CMDLINE    = (1 << 1)
-} GApplicationFlags;
-
 GType                   g_application_get_type                          (void) G_GNUC_CONST;
 
 GApplication *          g_application_get_instance                      (void);
@@ -138,7 +133,9 @@ gboolean                g_application_is_supported                      (void);
 GApplication *          g_application_new                               (const gchar              *appid,
                                                                          GApplicationFlags         flags);
 
-gboolean                g_application_register                          (GApplication             *application);
+gboolean                g_application_register                          (GApplication             *application,
+                                                                         GCancellable             *cancellable,
+                                                                         GError                  **error);
 gboolean                g_application_is_remote                         (GApplication             *application);
 void                    g_application_set_flags                         (GApplication             *application,
                                                                          GApplicationFlags         flags);
diff --git a/gio/gapplicationimpl-dbus-interface.c b/gio/gapplicationimpl-dbus-interface.c
new file mode 100644
index 0000000..e395830
--- /dev/null
+++ b/gio/gapplicationimpl-dbus-interface.c
@@ -0,0 +1,90 @@
+/*
+ * Copyright © 2010 Codethink Limited
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the licence, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Ryan Lortie <desrt desrt ca>
+ */
+
+#include "gapplicationimpl-dbus-private.h"
+
+static GDBusArgInfo platform_data_arg = { -1, (gchar *) "platform_data", (gchar *) "a{sv}" };
+
+static GDBusArgInfo open_uris_arg = { -1, (gchar *) "uris", (gchar *) "as" };
+static GDBusArgInfo open_hint_arg = { -1, (gchar *) "hint", (gchar *) "s" };
+
+static GDBusArgInfo invoke_action_name_arg = { -1, (gchar *) "name", (gchar *) "s" };
+static GDBusArgInfo invoke_action_args_arg = { -1, (gchar *) "args", (gchar *) "v" };
+
+static GDBusArgInfo cmdline_path_arg = { -1, (gchar *) "path", (gchar *) "o" };
+static GDBusArgInfo cmdline_arguments_arg = { -1, (gchar *) "arguments", (gchar *) "aay" };
+static GDBusArgInfo cmdline_exit_status_arg = { -1, (gchar *) "exit_status", (gchar *) "i" };
+
+static GDBusArgInfo list_actions_actions_arg = { -1, (gchar *) "actions", (gchar *) "a{s(sgb)}" };
+
+static const GDBusArgInfo *activate_in[] = { &platform_data_arg, NULL };
+static const GDBusArgInfo *activate_out[] = { NULL };
+
+static const GDBusArgInfo *open_in[] = { &open_uris_arg, &open_hint_arg, &platform_data_arg, NULL };
+static const GDBusArgInfo *open_out[] = { NULL };
+
+static const GDBusArgInfo *list_actions_in[] = { NULL };
+static const GDBusArgInfo *list_actions_out[] = { &list_actions_actions_arg, NULL };
+
+static const GDBusArgInfo *invoke_action_in[] = { &invoke_action_name_arg, &invoke_action_args_arg, NULL };
+static const GDBusArgInfo *invoke_action_out[] = { NULL };
+
+static const GDBusArgInfo *cmdline_in[] = { &cmdline_path_arg, &cmdline_arguments_arg, &platform_data_arg, NULL };
+static const GDBusArgInfo *cmdline_out[] = { &cmdline_exit_status_arg, NULL };
+
+static const GDBusMethodInfo activate_method = {
+  -1, (gchar *) "Activate",
+  (GDBusArgInfo **) activate_in,
+  (GDBusArgInfo **) activate_out
+};
+
+static const GDBusMethodInfo open_method = {
+  -1, (gchar *) "Open",
+  (GDBusArgInfo **) open_in,
+  (GDBusArgInfo **) open_out
+};
+
+static const GDBusMethodInfo list_actions_method = {
+  -1, (gchar *) "ListActions",
+  (GDBusArgInfo **) list_actions_in,
+  (GDBusArgInfo **) list_actions_out
+};
+
+static const GDBusMethodInfo invoke_action_method = {
+  -1, (gchar *) "InvokeAction",
+  (GDBusArgInfo **) invoke_action_in,
+  (GDBusArgInfo **) invoke_action_out
+};
+
+static const GDBusMethodInfo cmdline_method = {
+  -1, (gchar *) "Cmdline",
+  (GDBusArgInfo **) cmdline_in,
+  (GDBusArgInfo **) cmdline_out
+};
+
+static const GDBusMethodInfo *methods[] = {
+  &activate_method, &open_method, &list_actions_method, &invoke_action_method, &cmdline_method, NULL
+};
+
+const GDBusInterfaceInfo org_gtk_Application = {
+  -1, (gchar *) "org.gtk.Application",
+  (GDBusMethodInfo **) methods
+};
diff --git a/gio/gapplicationimpl-dbus-private.h b/gio/gapplicationimpl-dbus-private.h
new file mode 100644
index 0000000..0181df7
--- /dev/null
+++ b/gio/gapplicationimpl-dbus-private.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright © 2010 Codethink Limited
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the licence, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Ryan Lortie <desrt desrt ca>
+ */
+
+#ifndef __GAPPLICATIONIMPL_DBUS_PRIVATE_H__
+#define __GAPPLICATIONIMPL_DBUS_PRIVATE_H__
+
+#include "gdbusintrospection.h"
+
+G_GNUC_INTERNAL extern const GDBusInterfaceInfo org_gtk_Application;
+
+#endif
diff --git a/gio/gapplicationimpl-dbus.c b/gio/gapplicationimpl-dbus.c
new file mode 100644
index 0000000..e6e5c52
--- /dev/null
+++ b/gio/gapplicationimpl-dbus.c
@@ -0,0 +1,310 @@
+/*
+ * Copyright © 2010 Codethink Limited
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Authors: Ryan Lortie <desrt desrt ca>
+ */
+
+#include "gapplicationimpl-dbus-private.h"
+#include "gfile.h"
+
+struct _GApplicationImpl
+{
+  GDBusConnection *session_bus;
+  const gchar     *bus_name;
+  gchar           *object_path;
+  guint            object_id;
+  gpointer         app;
+};
+
+static void
+g_application_impl_method_call (GDBusConnection       *connection,
+                                const gchar           *sender,
+                                const gchar           *object_path,
+                                const gchar           *interface_name,
+                                const gchar           *method_name,
+                                GVariant              *parameters,
+                                GDBusMethodInvocation *invocation,
+                                gpointer               user_data)
+{
+  GApplicationImpl *impl = user_data;
+
+  if (strcmp (method_name, "Activate") == 0)
+    {
+      GVariant *platform_data;
+
+      g_variant_get (parameters, "(a{sv})", &platform_data);
+      G_APPLICATION_GET_CLASS (impl->app)
+        ->emit_activate (impl->app, platform_data);
+      g_variant_unref (platform_data);
+    }
+
+  else if (strcmp (method_name, "Open") == 0)
+    {
+      GVariant *platform_data;
+      const gchar *hint;
+      GVariant *array;
+      GFile **files;
+      gint n, i;
+
+      g_variant_get (parameters, "(@ass a{sv})",
+                     &array, &hint, &platform_data);
+
+      n = g_variant_n_children (array);
+      files = g_new (GFile *, n + 1);
+
+      for (i = 0; i < n; i++)
+        {
+          const gchar *uri;
+
+          g_variant_get_child (array, i, "&s", &uri);
+          files[i] = g_file_new_for_uri (uri);
+        }
+      g_variant_unref (array);
+      files[n] = NULL;
+
+      G_APPLICATION_GET_CLASS (impl->app)
+        ->emit_open (impl->app, files, n, hint, platform_data);
+
+      g_variant_unref (platform_data);
+
+      for (i = 0; i < n; i++)
+        g_object_unref (files[i]);
+      g_free (files);
+    }
+
+  else if (strcmp (method_name, "ListActions") == 0)
+    {
+    }
+
+  else if (strcmp (method_name, "InvokeAction") == 0)
+    {
+    }
+
+  else if (strcmp (method_name, "Cmdline") == 0)
+    {
+      GVariant *arguments, *platform_data;
+      //GApplicationInvocation *invocation;
+      const gchar *remote_path;
+
+      g_variant_get (parameters, "(&o aay@a{sv})",
+                     &remote_path, &arguments, &platform_data);
+
+      //invocation = g_application_create_invocation (application,
+      //                                              arguments,
+      //                                              platform_data);
+      g_variant_unref (platform_data);
+      g_variant_unref (arguments);
+
+      /* XXX hook up the stuff... */
+
+      //g_application_emit_invocation (invocation);
+      //g_object_unref (invocation);
+    }
+
+  else
+    g_assert_not_reached ();
+}
+
+static gchar *
+application_path_from_appid (const gchar *appid)
+{
+  gchar *appid_path, *iter;
+
+  appid_path = g_strconcat ("/", appid, NULL);
+  for (iter = appid_path; *iter; iter++)
+    {
+      if (*iter == '.')
+        *iter = '/';
+    }
+
+  return appid_path;
+}
+
+void
+g_application_impl_init (GApplicationImpl *impl,
+                         gpointer          app)
+{
+  impl->app = app;
+}
+
+static void
+g_application_impl_set_id (GApplicationImpl *impl,
+                           const gchar      *appid)
+{
+  impl->bus_name = appid;
+  impl->object_path = application_path_from_appid (appid);
+}
+
+static void
+g_application_impl_destroy (GApplicationImpl *impl)
+{
+  if (impl->session_bus)
+    {
+      if (impl->object_id)
+        g_dbus_connection_unregister_object (impl->session_bus,
+                                             impl->object_id);
+
+      g_object_unref (impl->session_bus);
+    }
+  else
+    g_assert (impl->object_id == 0);
+
+  g_free (impl->object_path);
+}
+
+static gboolean
+g_application_impl_register (GApplicationImpl  *impl,
+                             gboolean          *is_remote,
+                             GCancellable      *cancellable,
+                             GError           **error)
+{
+  const static GDBusInterfaceVTable vtable = {
+    g_application_impl_method_call
+  };
+  GVariant *reply;
+  guint32 rval;
+
+  g_print ("eh\n");
+
+  g_assert (impl->session_bus == NULL);
+
+  impl->session_bus = g_bus_get_sync (G_BUS_TYPE_SESSION,
+                                      cancellable, error);
+
+  if (impl->session_bus == NULL)
+    return FALSE;
+
+  g_print ("reg %s %s\n", org_gtk_Application.name, impl->object_path);
+  impl->object_id = g_dbus_connection_register_object (impl->session_bus,
+                                                       impl->object_path,
+                                                       (GDBusInterfaceInfo *)
+                                                         &org_gtk_Application,
+                                                       &vtable,
+                                                       impl, NULL,
+                                                       error);
+
+  if (impl->object_id == 0)
+    {
+      g_object_unref (impl->session_bus);
+      impl->session_bus = NULL;
+
+      return FALSE;
+    }
+
+  reply = g_dbus_connection_call_sync (impl->session_bus,
+                                       "org.freedesktop.DBus",
+                                       "/org/freedesktop/DBus",
+                                       "org.freedesktop.DBus",
+                                       "RequestName",
+                                       g_variant_new ("(su)",
+                                       /* DBUS_NAME_FLAG_DO_NOT_QUEUE: 0x4 */
+                                                      impl->bus_name, 0x4),
+                                       G_VARIANT_TYPE ("(u)"),
+                                       0, -1, cancellable, error);
+
+  if (reply == NULL)
+    {
+      g_dbus_connection_unregister_object (impl->session_bus,
+                                           impl->object_id);
+      impl->object_id = 0;
+
+      g_object_unref (impl->session_bus);
+      impl->session_bus = NULL;
+
+      return FALSE;
+    }
+
+  g_variant_get (reply, "(u)", &rval);
+  g_variant_unref (reply);
+
+  /* DBUS_REQUEST_NAME_REPLY_EXISTS: 3 */
+  if ((*is_remote = (rval == 3)))
+    {
+      g_dbus_connection_unregister_object (impl->session_bus,
+                                           impl->object_id);
+      impl->object_id = 0;
+    }
+
+  return TRUE;
+}
+
+static void
+g_application_impl_activate (GApplicationImpl *impl,
+                             GVariant         *platform_data)
+{
+  g_dbus_connection_call (impl->session_bus,
+                          impl->bus_name,
+                          impl->object_path,
+                          "org.gtk.Application",
+                          "Activate",
+                          g_variant_new ("(@a{sv})", platform_data),
+                          NULL, 0, -1, NULL, NULL, NULL);
+}
+
+static void
+g_application_impl_open (GApplicationImpl  *impl,
+                         GFile            **files,
+                         gint               n_files,
+                         const gchar       *hint,
+                         GVariant          *platform_data)
+{
+  GVariantBuilder builder;
+  gint i;
+
+  g_variant_builder_init (&builder, G_VARIANT_TYPE ("(assa{sv})"));
+  g_variant_builder_open (&builder, G_VARIANT_TYPE_STRING_ARRAY);
+  for (i = 0; i < n_files; i++)
+    {
+      gchar *uri = g_file_get_uri (files[i]);
+      g_variant_builder_add (&builder, "s", uri);
+      g_free (uri);
+    }
+  g_variant_builder_close (&builder);
+  g_variant_builder_add (&builder, "s", hint);
+  g_variant_builder_add_value (&builder, platform_data);
+
+  g_dbus_connection_call (impl->session_bus,
+                          impl->bus_name,
+                          impl->object_path,
+                          "org.gtk.Application",
+                          "Open",
+                          g_variant_builder_end (&builder),
+                          NULL, 0, -1, NULL, NULL, NULL);
+}
+
+static void
+g_application_impl_action (GApplicationImpl *impl,
+                           const gchar      *action_name,
+                           GVariant         *parameters,
+                           GVariant         *platform_data)
+{
+}
+
+static int
+g_application_impl_cmdline (GApplicationImpl *impl,
+                            GVariant         *arguments,
+                            GVariant         *platform_data)
+{
+  return 1;
+}
+
+static void
+g_application_impl_flush (GApplicationImpl *impl)
+{
+  g_dbus_connection_flush_sync (impl->session_bus, NULL, NULL);
+}
diff --git a/gio/gapplicationinvocation.c b/gio/gapplicationinvocation.c
index f180465..fbe18f0 100644
--- a/gio/gapplicationinvocation.c
+++ b/gio/gapplicationinvocation.c
@@ -215,7 +215,8 @@ g_application_invocation_set_property (GObject *object, guint prop_id,
     case PROP_PLATFORM_DATA:
       g_assert (invocation->priv->platform_data == NULL);
       invocation->priv->platform_data = g_value_dup_variant (value);
-      grok_platform_data (invocation);
+      if (invocation->priv->platform_data != NULL)
+        grok_platform_data (invocation);
       break;
 
     default:
@@ -228,8 +229,9 @@ g_application_invocation_finalize (GObject *object)
 {
   GApplicationInvocation *invocation = G_APPLICATION_INVOCATION (object);
 
-  remote_impl_exit (&invocation->priv->remote_impl,
-                    invocation->priv->exit_status);
+  if (IS_REMOTE (invocation))
+    remote_impl_exit (&invocation->priv->remote_impl,
+                      invocation->priv->exit_status);
 
   if (invocation->priv->platform_data)
     g_variant_unref (invocation->priv->platform_data);
@@ -245,6 +247,10 @@ g_application_invocation_finalize (GObject *object)
 static void
 g_application_invocation_init (GApplicationInvocation *invocation)
 {
+  invocation->priv =
+    G_TYPE_INSTANCE_GET_PRIVATE (invocation,
+                                 G_TYPE_APPLICATION_INVOCATION,
+                                 GApplicationInvocationPrivate);
 }
 
 static void
@@ -260,18 +266,22 @@ g_application_invocation_class_init (GApplicationInvocationClass *class)
     g_param_spec_variant ("arguments", "commandline arguments",
                           "the commandline that caused this invocation",
                           G_VARIANT_TYPE_BYTESTRING_ARRAY, NULL,
-                          G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
+                          G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY |
+                          G_PARAM_STATIC_STRINGS));
 
   g_object_class_install_property (object_class, PROP_PLATFORM_DATA,
     g_param_spec_variant ("platform-data", "platform data",
                           "platform-specific data for the invocation",
                           G_VARIANT_TYPE ("a{sv}"), NULL,
-                          G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
+                          G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY |
+                          G_PARAM_STATIC_STRINGS));
 
   g_object_class_install_property (object_class, PROP_IS_REMOTE,
     g_param_spec_boolean ("is-remote", "is remote",
                           "TRUE if this is a remote invocation", FALSE,
-                          G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
+                          G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
+
+  g_type_class_add_private (class, sizeof (GApplicationInvocationPrivate));
 }
 
 GVariant *
diff --git a/gio/gioenums.h b/gio/gioenums.h
index 8027cf6..8135ee0 100644
--- a/gio/gioenums.h
+++ b/gio/gioenums.h
@@ -1199,6 +1199,26 @@ typedef enum
   G_DBUS_MESSAGE_BYTE_ORDER_LITTLE_ENDIAN = 'l'
 } GDBusMessageByteOrder;
 
+/**
+ * GApplicationFlags:
+ * @G_APPLICATION_FLAGS_NONE: Default
+ * @G_APPLICATION_FLAGS_CAN_OPEN: This application can open files.
+ * @G_APPLICATION_FLAGS_REMOTE_CMDLINE: This application is interested
+ *   in advanced handling of commandline invocations (ie: by sending the
+ *   commandline to the remote instance).
+ *
+ * Flags used to define the behaviour of a #GApplication.
+ *
+ * Since: 2.26
+ **/
+typedef enum
+{
+  G_APPLICATION_FLAGS_NONE,
+  G_APPLICATION_FLAGS_CAN_OPEN          = (1 << 0),
+  G_APPLICATION_FLAGS_REMOTE_CMDLINE    = (1 << 1)
+} GApplicationFlags;
+
+
 G_END_DECLS
 
 #endif /* __GIO_ENUMS_H__ */



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