Rework GApplication API to use GInitable

https://bugzilla.gnome.org/show_bug.cgi?id=620952
This commit is contained in:
Colin Walters 2010-06-16 00:18:09 -04:00
parent 25ba90ffdd
commit 102c5f6a7d
7 changed files with 396 additions and 195 deletions

View File

@ -33,6 +33,7 @@
#include "glibintl.h" #include "glibintl.h"
#include "gioerror.h" #include "gioerror.h"
#include "ginitable.h"
#include "gdbusconnection.h" #include "gdbusconnection.h"
#include "gdbusintrospection.h" #include "gdbusintrospection.h"
@ -130,6 +131,11 @@
* application instance when a second instance fails to take the bus name. * application instance when a second instance fails to take the bus name.
* @arguments contains the commandline arguments given to the second instance * @arguments contains the commandline arguments given to the second instance
* and @data contains platform-specific additional data. * and @data contains platform-specific additional data.
*
* On all platforms, @data is guaranteed to have a key "cwd" of type
* singature "ay" which contains the working directory of the invoked
* executable.
*
* </para> * </para>
* <para> * <para>
* The <methodname>InvokeAction</methodname> function can be called to * The <methodname>InvokeAction</methodname> function can be called to
@ -161,15 +167,22 @@
* </refsect2> * </refsect2>
*/ */
G_DEFINE_TYPE (GApplication, g_application, G_TYPE_OBJECT); static void initable_iface_init (GInitableIface *initable_iface);
G_DEFINE_TYPE_WITH_CODE (GApplication, g_application, G_TYPE_OBJECT,
G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, initable_iface_init));
enum enum
{ {
PROP_0, PROP_0,
PROP_APPLICATION_ID, PROP_APPLICATION_ID,
PROP_REGISTER,
PROP_DEFAULT_QUIT, PROP_DEFAULT_QUIT,
PROP_IS_REMOTE PROP_IS_REMOTE,
PROP_ARGV,
PROP_PLATFORM_DATA
}; };
enum enum
@ -195,6 +208,10 @@ struct _GApplicationPrivate
GHashTable *actions; /* name -> GApplicationAction */ GHashTable *actions; /* name -> GApplicationAction */
GMainLoop *mainloop; GMainLoop *mainloop;
GVariant *argv;
GVariant *platform_data;
guint do_register : 1;
guint default_quit : 1; guint default_quit : 1;
guint is_remote : 1; guint is_remote : 1;
@ -209,18 +226,31 @@ struct _GApplicationPrivate
static GApplication *primary_application = NULL; static GApplication *primary_application = NULL;
static GHashTable *instances_for_appid = NULL; static GHashTable *instances_for_appid = NULL;
static void _g_application_platform_init (GApplication *app); static gboolean initable_init (GInitable *initable,
static gboolean _g_application_platform_acquire_single_instance (GApplication *app, GCancellable *cancellable,
GError **error); 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, static void _g_application_platform_remote_invoke_action (GApplication *app,
const gchar *action, const gchar *action,
GVariant *platform_data); GVariant *platform_data);
static void _g_application_platform_remote_quit (GApplication *app, static void _g_application_platform_remote_quit (GApplication *app,
GVariant *platform_data); GVariant *platform_data);
static void _g_application_platform_activate (GApplication *app,
GVariant *data) G_GNUC_NORETURN;
static void _g_application_platform_on_actions_changed (GApplication *app); 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 #ifdef G_OS_UNIX
#include "gdbusapplication.c" #include "gdbusapplication.c"
#else #else
@ -288,45 +318,25 @@ g_application_default_run (GApplication *application)
g_main_loop_run (application->priv->mainloop); g_main_loop_run (application->priv->mainloop);
} }
static void static GVariant *
_g_application_handle_activation (GApplication *app, variant_from_argv (int argc,
int argc, char **argv)
char **argv,
GVariant *platform_data)
{ {
GVariantBuilder builder; GVariantBuilder builder;
GVariant *message;
int i; int i;
g_variant_builder_init (&builder, G_VARIANT_TYPE ("(aaya{sv})")); g_variant_builder_init (&builder, G_VARIANT_TYPE ("aay"));
g_variant_builder_open (&builder, G_VARIANT_TYPE ("aay"));
for (i = 1; i < argc; i++) for (i = 1; i < argc; i++)
{ {
int j;
guint8 *argv_bytes; guint8 *argv_bytes;
g_variant_builder_open (&builder, G_VARIANT_TYPE ("ay"));
argv_bytes = (guint8*) argv[i]; argv_bytes = (guint8*) argv[i];
for (j = 0; argv_bytes[j]; j++) g_variant_builder_add_value (&builder,
g_variant_builder_add_value (&builder, g_variant_new_byte_array (argv_bytes, -1));
g_variant_new_byte (argv_bytes[j]));
g_variant_builder_close (&builder);
} }
g_variant_builder_close (&builder);
return g_variant_builder_end (&builder);
if (platform_data)
g_variant_builder_add (&builder, "@a{sv}", platform_data);
else
{
g_variant_builder_open (&builder, G_VARIANT_TYPE ("a{sv}"));
g_variant_builder_close (&builder);
}
message = g_variant_builder_end (&builder);
_g_application_platform_activate (app, message);
g_variant_unref (message);
} }
static gboolean static gboolean
@ -350,6 +360,24 @@ queue_actions_change_notification (GApplication *application)
priv->actions_changed_id = g_timeout_add (0, timeout_handle_actions_changed, 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 static void
g_application_action_free (gpointer data) g_application_action_free (gpointer data)
{ {
@ -364,15 +392,35 @@ g_application_action_free (gpointer data)
} }
} }
/** /**
* g_application_new: * g_application_new:
* @appid: System-dependent application identifier * @appid: System-dependent application identifier
* @argc: Number of arguments in @argv
* @argv: (allow-none) (array length=argc): Argument vector, usually from the <parameter>argv</parameter> parameter of main()
* *
* Create a new #GApplication. The application is initially in * Create a new #GApplication. This uses a platform-specific
* "remote" mode. Almost certainly, you want to call * mechanism to ensure the current process is the unique owner of the
* g_application_register() immediately after this function, which * application (as defined by the @appid). If successful, the
* will finish initialization. * #GApplication:is-remote property will be %FALSE, and it is safe to
* continue creating other resources such as graphics windows.
*
* If the given @appid is already running in another process, the the
* GApplication::activate_with_data signal will be emitted in the
* remote process, with the data from @argv and other
* platform-specific data available. Subsequently the
* #GApplication:default-exit property will be evaluated. If it's
* %TRUE, then the current process will terminate. If %FALSE, then
* the application remains in the #GApplication:is-remote state, and
* you can e.g. call g_application_invoke_action().
*
* This function may do synchronous I/O to obtain unique ownership
* of the application id, and will block the calling thread in this
* case.
*
* If the environment does not support the basic functionality of
* #GApplication, this function will invoke g_error(), which by
* default is a fatal operation. This may arise for example on
* UNIX systems using D-Bus when the session bus is not available.
* *
* As a convenience, this function is defined to call g_type_init() as * As a convenience, this function is defined to call g_type_init() as
* its very first action. * its very first action.
@ -382,79 +430,133 @@ g_application_action_free (gpointer data)
* Since: 2.26 * Since: 2.26
*/ */
GApplication * GApplication *
g_application_new (const gchar *appid) g_application_new (const gchar *appid,
int argc,
char **argv)
{ {
GObject *app;
GError *error = NULL;
GVariant *argv_variant;
g_type_init (); g_type_init ();
return G_APPLICATION (g_object_new (G_TYPE_APPLICATION, "application-id", appid, NULL)); g_return_val_if_fail (appid != NULL, NULL);
}
argv_variant = variant_from_argv (argc, argv);
/**
* g_application_register_with_data: app = g_initable_new (G_TYPE_APPLICATION,
* @application: A #GApplication NULL,
* @argc: System argument count &error,
* @argv: (array length=argc): System argument vector "application-id", appid,
* @platform_data: (allow-none): Arbitrary platform-specific data, must have signature "a{sv}" "argv", argv_variant,
* NULL);
* Ensure the current process is the unique owner of the application. if (!app)
* If successful, the #GApplication:is-remote property will be changed
* to %FALSE, and it is safe to continue creating other resources
* such as graphics windows.
*
* If the given @appid is already running in another process, the
* #GApplication:default-exit property will be evaluated. If it's
* %TRUE, then a platform-specific action such as bringing any
* graphics windows associated with the application to the foreground
* may be initiated. After that, the current process will terminate.
* If %FALSE, then the application remains in the #GApplication:is-remote
* state, and you can e.g. call g_application_invoke_action().
*
* This function may do synchronous I/O to obtain unique ownership
* of the application id, and will block the calling thread in this
* case.
*/
void
g_application_register_with_data (GApplication *application,
gint argc,
gchar **argv,
GVariant *platform_data)
{
g_return_if_fail (application->priv->appid != NULL);
g_return_if_fail (application->priv->is_remote);
g_return_if_fail (platform_data == NULL
|| g_variant_is_of_type (platform_data, G_VARIANT_TYPE ("a{sv}")));
if (!_g_application_platform_acquire_single_instance (application, NULL))
{ {
if (application->priv->default_quit) g_error ("%s", error->message);
_g_application_handle_activation (application, argc, argv, platform_data); g_clear_error (&error);
else return NULL;
return;
} }
return G_APPLICATION (app);
application->priv->is_remote = FALSE;
_g_application_platform_init (application);
} }
/** /**
* g_application_new_and_register: * g_application_try_new:
* @appid: An application identifier * @appid: System-dependent application identifier
* @argc: System argument count * @argc: Number of arguments in @argv
* @argv: (array length=argc): System argument vector * @argv: (allow-none) (array length=argc): Argument vector, usually from the <parameter>argv</parameter> parameter of main()
* @error: a #GError
* *
* This is a convenience function which combines g_application_new() * This function is similar to g_application_new(), but allows for
* with g_application_register_with_data(). Therefore, it may block * more graceful fallback if the environment doesn't support the
* the calling thread just like g_application_register_with_data(). * basic #GApplication functionality.
*
* Returns: (transfer full): An application instance
*
* Since: 2.26
*/ */
GApplication * GApplication *
g_application_new_and_register (const gchar *appid, g_application_try_new (const gchar *appid,
gint argc, int argc,
gchar **argv) char **argv,
GError **error)
{ {
GApplication *app = g_application_new (appid); GVariant *argv_variant;
g_application_register_with_data (app, argc, argv, NULL);
return app; g_type_init ();
g_return_val_if_fail (appid != NULL, NULL);
argv_variant = variant_from_argv (argc, argv);
return G_APPLICATION (g_initable_new (G_TYPE_APPLICATION,
NULL,
error,
"application-id", appid,
"argv", argv_variant,
NULL));
}
/**
* g_application_unregistered_try_new:
* @appid: System-dependent application identifier
* @argc: Number of arguments in @argv
* @argv: (allow-none) (array length=argc): Argument vector, usually from the <parameter>argv</parameter> parameter of main()
* @error: a #GError
*
* This function is similar to g_application_try_new(), but also
* sets the GApplication:register property to %FALSE. You can later
* call g_application_register() to complete initialization.
*
* Returns: (transfer full): An application instance
*
* Since: 2.26
*/
GApplication *
g_application_unregistered_try_new (const gchar *appid,
int argc,
char **argv,
GError **error)
{
GVariant *argv_variant;
g_type_init ();
g_return_val_if_fail (appid != NULL, NULL);
argv_variant = variant_from_argv (argc, argv);
return G_APPLICATION (g_initable_new (G_TYPE_APPLICATION,
NULL,
error,
"application-id", appid,
"argv", argv_variant,
"register", FALSE,
NULL));
}
/**
* g_application_register:
* @app: a #GApplication
*
* By default, #GApplication ensures process uniqueness when
* initialized, but this behavior is controlled by the
* GApplication:register property. If it was given as %FALSE at
* construction time, this function allows you to later attempt
* to ensure uniqueness.
*
* Returns: %TRUE if registration was successful
*/
gboolean
g_application_register (GApplication *app)
{
gboolean unique;
g_return_val_if_fail (G_IS_APPLICATION (app), FALSE);
g_return_val_if_fail (app->priv->is_remote, FALSE);
if (!_g_application_platform_register (app, &unique, NULL, NULL))
return FALSE;
return unique;
} }
/** /**
@ -563,25 +665,33 @@ g_application_invoke_action (GApplication *application,
g_return_if_fail (G_IS_APPLICATION (application)); g_return_if_fail (G_IS_APPLICATION (application));
g_return_if_fail (name != NULL); g_return_if_fail (name != NULL);
g_return_if_fail (platform_data == NULL g_return_if_fail (platform_data == NULL
|| g_variant_is_of_type (platform_data, "a{sv}")); || 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; priv = application->priv;
if (priv->is_remote) if (priv->is_remote)
{ {
_g_application_platform_remote_invoke_action (application, name, platform_data); _g_application_platform_remote_invoke_action (application, name, platform_data);
return; goto out;
} }
action = g_hash_table_lookup (priv->actions, name); action = g_hash_table_lookup (priv->actions, name);
g_return_if_fail (action != NULL); g_return_if_fail (action != NULL);
if (!action->enabled) if (!action->enabled)
return; goto out;
g_signal_emit (application, application_signals[ACTION_WITH_DATA], g_signal_emit (application, application_signals[ACTION_WITH_DATA],
g_quark_from_string (name), g_quark_from_string (name),
name, name,
platform_data); platform_data);
out:
g_variant_unref (platform_data);
} }
/** /**
@ -779,7 +889,12 @@ g_application_quit_with_data (GApplication *application,
g_return_val_if_fail (G_IS_APPLICATION (application), FALSE); g_return_val_if_fail (G_IS_APPLICATION (application), FALSE);
g_return_val_if_fail (platform_data == NULL g_return_val_if_fail (platform_data == NULL
|| g_variant_is_of_type (platform_data, "a{sv}"), FALSE); || 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) if (application->priv->is_remote)
{ {
@ -789,6 +904,8 @@ g_application_quit_with_data (GApplication *application,
else else
g_signal_emit (application, application_signals[QUIT_WITH_DATA], 0, platform_data, &retval); g_signal_emit (application, application_signals[QUIT_WITH_DATA], 0, platform_data, &retval);
g_variant_unref (platform_data);
return retval; return retval;
} }
@ -855,6 +972,7 @@ g_application_init (GApplication *app)
NULL, NULL,
g_application_action_free); g_application_action_free);
app->priv->default_quit = TRUE; app->priv->default_quit = TRUE;
app->priv->do_register = TRUE;
app->priv->is_remote = TRUE; app->priv->is_remote = TRUE;
} }
@ -880,6 +998,18 @@ g_application_get_property (GObject *object,
g_value_set_boolean (value, g_application_is_remote (app)); g_value_set_boolean (value, g_application_is_remote (app));
break; break;
case PROP_REGISTER:
g_value_set_boolean (value, app->priv->do_register);
break;
case PROP_ARGV:
g_value_set_boxed (value, app->priv->argv);
break;
case PROP_PLATFORM_DATA:
g_value_set_boxed (value, app->priv->platform_data);
break;
default: default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
} }
@ -904,6 +1034,28 @@ g_application_set_property (GObject *object,
app->priv->default_quit = g_value_get_boolean (value); app->priv->default_quit = g_value_get_boolean (value);
break; break;
case PROP_REGISTER:
app->priv->do_register = g_value_get_boolean (value);
break;
case PROP_ARGV:
{
GVariant *argv = g_value_get_boxed (value);
g_return_if_fail (argv == NULL ||
g_variant_is_of_type (argv, G_VARIANT_TYPE ("aay")));
app->priv->argv = argv;
}
break;
case PROP_PLATFORM_DATA:
{
GVariant *platform_data = g_value_get_boxed (value);
g_return_if_fail (platform_data == NULL ||
g_variant_is_of_type (platform_data, G_VARIANT_TYPE ("a{sv}")));
app->priv->platform_data = platform_data;
}
break;
default: default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
} }
@ -1053,7 +1205,7 @@ g_application_class_init (GApplicationClass *klass)
G_TYPE_VARIANT, G_TYPE_VARIANT,
G_TYPE_VARIANT); G_TYPE_VARIANT);
/** /**
* GApplication:application-id: * GApplication:application-id:
* *
* The unique identifier for this application. See the documentation for * The unique identifier for this application. See the documentation for
@ -1070,6 +1222,40 @@ g_application_class_init (GApplicationClass *klass)
G_PARAM_CONSTRUCT_ONLY | G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS)); G_PARAM_STATIC_STRINGS));
/**
* GApplication:argv:
*
* The argument vector given to this application. It must be a #GVariant
* with a type signature "aay".
*
*/
g_object_class_install_property (gobject_class,
PROP_ARGV,
g_param_spec_boxed ("argv",
P_("Argument vector"),
P_("System argument vector with type signature aay"),
G_TYPE_VARIANT,
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS));
/**
* GApplication:platform-data:
*
* Platform-specific data retrieved from the operating system
* environment. It must be a #GVariant with type signature "a{sv}".
*
*/
g_object_class_install_property (gobject_class,
PROP_PLATFORM_DATA,
g_param_spec_boxed ("platform-data",
P_("Platform data"),
P_("Environmental data, must have type signature a{sv}"),
G_TYPE_VARIANT,
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS));
/** /**
* GApplication:default-quit: * GApplication:default-quit:
* *
@ -1103,6 +1289,23 @@ g_application_class_init (GApplicationClass *klass)
P_("Whether this application is a proxy for another process"), P_("Whether this application is a proxy for another process"),
TRUE, TRUE,
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
/**
* GApplication:register:
*
* If this property is %FALSE, the application construction will not attempt
* to ensure process uniqueness, and the application is guaranteed to be in the
* remote state. See GApplication:is-remote.
*/
g_object_class_install_property (gobject_class,
PROP_REGISTER,
g_param_spec_boolean ("register",
P_("Register"),
P_("If false, do not "),
TRUE,
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS));
} }
#define __G_APPLICATION_C__ #define __G_APPLICATION_C__

View File

@ -102,16 +102,21 @@ struct _GApplicationClass
}; };
GType g_application_get_type (void) G_GNUC_CONST; GType g_application_get_type (void) G_GNUC_CONST;
GApplication * g_application_new (const gchar *appid); GApplication * g_application_new (const gchar *appid,
int argc,
char **argv);
void g_application_register_with_data (GApplication *application, GApplication * g_application_try_new (const gchar *appid,
gint argc, int argc,
gchar **argv, char **argv,
GVariant *platform_data); GError **error);
GApplication * g_application_new_and_register (const gchar *appid, GApplication * g_application_unregistered_try_new (const gchar *appid,
gint argc, int argc,
gchar **argv); char **argv,
GError **error);
gboolean g_application_register (GApplication *application);
GApplication * g_application_get_instance (void); GApplication * g_application_get_instance (void);
G_CONST_RETURN gchar * g_application_get_id (GApplication *application); G_CONST_RETURN gchar * g_application_get_id (GApplication *application);

View File

@ -259,15 +259,6 @@ static GDBusInterfaceVTable application_dbus_vtable =
NULL NULL
}; };
static GVariant *
create_empty_vardict ()
{
GVariantBuilder builder;
g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}"));
return g_variant_builder_end (&builder);
}
static gchar * static gchar *
application_path_from_appid (const gchar *appid) application_path_from_appid (const gchar *appid)
{ {
@ -284,42 +275,32 @@ application_path_from_appid (const gchar *appid)
return appid_path; return appid_path;
} }
static void static gboolean
ensure_bus (GApplication *app) _g_application_platform_init (GApplication *app,
GCancellable *cancellable,
GError **error)
{ {
GError *error = NULL;
if (app->priv->session_bus == NULL) if (app->priv->session_bus == NULL)
app->priv->session_bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error); app->priv->session_bus = g_bus_get_sync (G_BUS_TYPE_SESSION, cancellable, error);
if (app->priv->session_bus == NULL) if (!app->priv->session_bus)
{ return FALSE;
g_error ("%s", error->message);
g_error_free (error);
}
if (app->priv->dbus_path == NULL) if (!app->priv->dbus_path)
app->priv->dbus_path = application_path_from_appid (app->priv->appid); app->priv->dbus_path = application_path_from_appid (app->priv->appid);
} return TRUE;
static void
_g_application_platform_init (GApplication *app)
{
} }
static gboolean static gboolean
_g_application_platform_acquire_single_instance (GApplication *app, _g_application_platform_register (GApplication *app,
GError **error) gboolean *unique,
GCancellable *cancellable,
GError **error)
{ {
GVariant *request_result; GVariant *request_result;
guint32 request_status; guint32 request_status;
gboolean result; gboolean result;
guint registration_id; guint registration_id;
ensure_bus (app);
if (app->priv->session_bus == NULL)
return FALSE;
registration_id = g_dbus_connection_register_object (app->priv->session_bus, registration_id = g_dbus_connection_register_object (app->priv->session_bus,
app->priv->dbus_path, app->priv->dbus_path,
&application_dbus_interface_info, &application_dbus_interface_info,
@ -336,7 +317,7 @@ _g_application_platform_acquire_single_instance (GApplication *app,
"org.freedesktop.DBus", "org.freedesktop.DBus",
"RequestName", "RequestName",
g_variant_new ("(su)", app->priv->appid, 0x4), g_variant_new ("(su)", app->priv->appid, 0x4),
NULL, 0, -1, NULL, error); NULL, 0, -1, cancellable, error);
if (request_result == NULL) if (request_result == NULL)
{ {
@ -351,19 +332,46 @@ _g_application_platform_acquire_single_instance (GApplication *app,
g_variant_unref (request_result); g_variant_unref (request_result);
if (request_status != 1 && request_status != 4) *unique = (request_status == 1 || request_status == 4);
{
if (request_status == 3)
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "Another process has name \"%s\"", app->priv->appid);
else
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED, "Unknown error");
result = FALSE;
goto done;
}
result = TRUE; result = TRUE;
if (*unique)
{
app->priv->is_remote = FALSE;
}
else if (app->priv->default_quit)
{
GVariantBuilder builder;
GVariant *message;
GVariant *result;
g_variant_builder_init (&builder, G_VARIANT_TYPE ("(aaya{sv})"));
g_variant_builder_add (&builder, "@aay", app->priv->argv);
if (app->priv->platform_data)
g_variant_builder_add (&builder, "@a{sv}", app->priv->platform_data);
else
{
g_variant_builder_open (&builder, G_VARIANT_TYPE ("a{sv}"));
g_variant_builder_close (&builder);
}
message = g_variant_builder_end (&builder);
result = g_dbus_connection_call_sync (app->priv->session_bus,
app->priv->appid,
app->priv->dbus_path,
G_APPLICATION_IFACE,
"Activate",
message,
NULL, 0, -1, NULL, NULL);
if (result)
g_variant_unref (result);
exit (0);
}
done: done:
if (!result) if (!result)
g_dbus_connection_unregister_object (app->priv->session_bus, registration_id); g_dbus_connection_unregister_object (app->priv->session_bus, registration_id);
@ -387,8 +395,6 @@ _g_application_platform_remote_invoke_action (GApplication *app,
{ {
GVariant *result; GVariant *result;
ensure_bus (app);
result = g_dbus_connection_call_sync (app->priv->session_bus, result = g_dbus_connection_call_sync (app->priv->session_bus,
app->priv->appid, app->priv->appid,
app->priv->dbus_path, app->priv->dbus_path,
@ -396,7 +402,7 @@ _g_application_platform_remote_invoke_action (GApplication *app,
"InvokeAction", "InvokeAction",
g_variant_new ("(s@a{sv})", g_variant_new ("(s@a{sv})",
action, action,
platform_data || create_empty_vardict ()), platform_data),
NULL, 0, -1, NULL, NULL); NULL, 0, -1, NULL, NULL);
if (result) if (result)
g_variant_unref (result); g_variant_unref (result);
@ -408,38 +414,15 @@ _g_application_platform_remote_quit (GApplication *app,
{ {
GVariant *result; GVariant *result;
ensure_bus (app);
result = g_dbus_connection_call_sync (app->priv->session_bus, result = g_dbus_connection_call_sync (app->priv->session_bus,
app->priv->appid, app->priv->appid,
app->priv->dbus_path, app->priv->dbus_path,
G_APPLICATION_IFACE, G_APPLICATION_IFACE,
"Quit", "Quit",
g_variant_new ("(@a{sv})", g_variant_new ("(@a{sv})",
platform_data || create_empty_vardict ()), platform_data),
NULL, 0, -1, NULL, NULL); NULL, 0, -1, NULL, NULL);
if (result) if (result)
g_variant_unref (result); g_variant_unref (result);
} }
static void
_g_application_platform_activate (GApplication *app,
GVariant *data)
{
GVariant *result;
ensure_bus (app);
result = g_dbus_connection_call_sync (app->priv->session_bus,
app->priv->appid,
app->priv->dbus_path,
G_APPLICATION_IFACE,
"Activate",
data,
NULL, 0, -1, NULL, NULL);
if (result)
g_variant_unref (result);
exit (0);
}

View File

@ -30,7 +30,6 @@ g_vfs_get_local
#if IN_FILE(__G_APPLICATION_C__) #if IN_FILE(__G_APPLICATION_C__)
g_application_get_type G_GNUC_CONST g_application_get_type G_GNUC_CONST
g_application_new g_application_new
g_application_new_and_register
g_application_get_instance g_application_get_instance
g_application_get_id g_application_get_id
g_application_set_action_enabled g_application_set_action_enabled
@ -38,10 +37,12 @@ g_application_get_action_enabled
g_application_get_action_description g_application_get_action_description
g_application_add_action g_application_add_action
g_application_remove_action g_application_remove_action
g_application_register_with_data
g_application_invoke_action g_application_invoke_action
g_application_list_actions g_application_list_actions
g_application_run g_application_run
g_application_register
g_application_try_new
g_application_unregistered_try_new
g_application_quit_with_data g_application_quit_with_data
g_application_is_remote g_application_is_remote
#endif #endif

View File

@ -25,14 +25,19 @@
#include "gioerror.h" #include "gioerror.h"
static void static gboolean
_g_application_platform_init (GApplication *app) _g_application_platform_init (GApplication *app,
GCancellable *cancellable,
GError **error)
{ {
return TRUE;
} }
static gboolean static gboolean
_g_application_platform_acquire_single_instance (GApplication *app, _g_application_platform_register (GApplication *app,
GError **error) gboolean *unique,
GCancellable *cancellable,
GError **error)
{ {
return TRUE; return TRUE;
} }

View File

@ -149,7 +149,7 @@ test_basic (void)
{ {
GApplication *app; GApplication *app;
app = g_application_new_and_register ("org.gtk.TestApplication", 0, NULL); app = g_application_new ("org.gtk.TestApplication", 0, NULL);
g_application_add_action (app, "About", "Print an about message"); g_application_add_action (app, "About", "Print an about message");
g_signal_connect (app, "action-with-data::About", G_CALLBACK (on_app_action), NULL); g_signal_connect (app, "action-with-data::About", G_CALLBACK (on_app_action), NULL);

View File

@ -60,9 +60,13 @@ main (int argc, char *argv[])
} }
#endif #endif
app = g_application_new ("org.gtk.test.app"); app = g_application_unregistered_try_new ("org.gtk.test.app",
argc, argv, NULL);
if (!(argc > 1 && strcmp (argv[1], "--non-unique") == 0)) if (!(argc > 1 && strcmp (argv[1], "--non-unique") == 0))
g_application_register_with_data (app, argc, argv, NULL); {
if (!g_application_register (app))
exit (0);
}
if (g_application_is_remote (app)) if (g_application_is_remote (app))
{ {