mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-01-11 23:16:14 +01:00
Rework GApplication API to use GInitable
https://bugzilla.gnome.org/show_bug.cgi?id=620952
This commit is contained in:
parent
25ba90ffdd
commit
102c5f6a7d
@ -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__
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
|
||||||
}
|
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
@ -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))
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user