glib/gio/gapplication.c
Ryan Lortie d6ac6c1850 Rename methods on GActionGroup to include 'action'
Makes explicit the fact that you are interacting with the individual
action rather than the group and removes potential namespace conflicts
with classes implementing the interface (like g_application_activate()
vs g_application_activate_action()).
2010-10-19 01:16:46 +02:00

1161 lines
33 KiB
C

/*
* Copyright © 2010 Codethink Limited
*
* This program 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.
*
* Authors: Ryan Lortie <desrt@desrt.ca>
*/
/* Prologue {{{1 */
#include "gapplication.h"
#include "gapplicationcommandline.h"
#include "gapplicationimpl.h"
#include "gactiongroup.h"
#include "gioenumtypes.h"
#include "gio-marshal.h"
#include "gioenums.h"
#include "gfile.h"
#include <string.h>
struct _GApplicationPrivate
{
GApplicationFlags flags;
gchar *id;
GHashTable *actions; /* string -> GApplicationAction */
GMainLoop *mainloop;
guint inactivity_timeout_id;
guint inactivity_timeout;
guint use_count;
guint is_registered : 1;
guint is_remote : 1;
GApplicationImpl *impl;
};
enum
{
PROP_NONE,
PROP_APPLICATION_ID,
PROP_FLAGS,
PROP_IS_REGISTERED,
PROP_IS_REMOTE,
PROP_INACTIVITY_TIMEOUT
};
enum
{
SIGNAL_STARTUP,
SIGNAL_ACTIVATE,
SIGNAL_OPEN,
SIGNAL_ACTION,
SIGNAL_COMMAND_LINE,
NR_SIGNALS
};
static guint g_application_signals[NR_SIGNALS];
static void g_application_action_group_iface_init (GActionGroupInterface *);
G_DEFINE_TYPE_WITH_CODE (GApplication, g_application, G_TYPE_OBJECT,
G_IMPLEMENT_INTERFACE (G_TYPE_ACTION_GROUP,
g_application_action_group_iface_init))
/* vfunc defaults {{{1 */
static void
g_application_real_before_emit (GApplication *application,
GVariant *platform_data)
{
}
static void
g_application_real_after_emit (GApplication *application,
GVariant *platform_data)
{
}
static void
g_application_real_startup (GApplication *application)
{
}
static void
g_application_real_activate (GApplication *application)
{
if (!g_signal_has_handler_pending (application,
g_application_signals[SIGNAL_ACTIVATE],
0, TRUE))
{
static gboolean warned;
if (warned)
return;
g_warning ("Your application does not implement "
"g_application_activate() and has no handlers connected "
"to the 'activate' signal. It should do one of these.");
warned = TRUE;
}
}
static void
g_application_real_open (GApplication *application,
GFile **files,
gint n_files,
const gchar *hint)
{
if (!g_signal_has_handler_pending (application,
g_application_signals[SIGNAL_OPEN],
0, TRUE))
{
static gboolean warned;
if (warned)
return;
g_warning ("Your application claims to support opening files "
"but does not implement g_application_open() and has no "
"handlers connected to the 'open' signal.");
warned = TRUE;
}
}
static int
g_application_real_command_line (GApplication *application,
GApplicationCommandLine *cmdline)
{
static gboolean warned;
if (warned)
return 1;
g_warning ("Your application claims to support custom command line "
"handling but does not implement g_application_command_line() "
"and has no handlers connected to the 'command-line' signal.");
warned = TRUE;
return 1;
}
static gboolean
g_application_real_local_command_line (GApplication *application,
GVariant **arguments,
int *exit_status)
{
if (application->priv->flags & G_APPLICATION_HANDLES_COMMAND_LINE)
return FALSE;
else
{
GError *error = NULL;
gint n_args;
if (!g_application_register (application, NULL, &error))
{
g_critical ("%s", error->message);
g_error_free (error);
*exit_status = 1;
return TRUE;
}
n_args = g_variant_n_children (*arguments);
if (application->priv->flags & G_APPLICATION_IS_SERVICE)
{
if (n_args > 1)
{
g_printerr ("GApplication service mode takes no arguments.\n");
application->priv->flags &= ~G_APPLICATION_IS_SERVICE;
}
return TRUE;
}
if (n_args <= 1)
{
g_application_activate (application);
*exit_status = 0;
}
else
{
if (~application->priv->flags & G_APPLICATION_HANDLES_OPEN)
{
g_critical ("This application can not open files.");
*exit_status = 1;
}
else
{
GFile **files;
gint n_files;
gint i;
n_files = n_args - 1;
files = g_new (GFile *, n_files);
for (i = 0; i < n_files; i++)
{
const gchar *arg;
g_variant_get_child (*arguments, i + 1, "^&ay", &arg);
files[i] = g_file_new_for_commandline_arg (arg);
}
g_application_open (application, files, n_files, "");
for (i = 0; i < n_files; i++)
g_object_unref (files[i]);
g_free (files);
*exit_status = 0;
}
}
return TRUE;
}
}
static void
g_application_real_add_platform_data (GApplication *application,
GVariantBuilder *builder)
{
}
static void
g_application_real_quit_mainloop (GApplication *application)
{
if (application->priv->mainloop != NULL)
g_main_loop_quit (application->priv->mainloop);
}
static void
g_application_real_run_mainloop (GApplication *application)
{
if (application->priv->mainloop == NULL)
application->priv->mainloop = g_main_loop_new (NULL, FALSE);
g_main_loop_run (application->priv->mainloop);
}
/* GObject implementation stuff {{{1 */
static void
g_application_set_property (GObject *object, guint prop_id,
const GValue *value, GParamSpec *pspec)
{
GApplication *application = G_APPLICATION (object);
switch (prop_id)
{
case PROP_APPLICATION_ID:
g_application_set_application_id (application,
g_value_get_string (value));
break;
case PROP_FLAGS:
g_application_set_flags (application, g_value_get_flags (value));
break;
case PROP_INACTIVITY_TIMEOUT:
g_application_set_inactivity_timeout (application,
g_value_get_uint (value));
break;
default:
g_assert_not_reached ();
}
}
static void
g_application_get_property (GObject *object, guint prop_id,
GValue *value, GParamSpec *pspec)
{
GApplication *application = G_APPLICATION (object);
switch (prop_id)
{
case PROP_APPLICATION_ID:
g_value_set_string (value,
g_application_get_application_id (application));
break;
case PROP_FLAGS:
g_value_set_flags (value,
g_application_get_flags (application));
break;
case PROP_IS_REGISTERED:
g_value_set_boolean (value,
g_application_get_is_registered (application));
break;
case PROP_IS_REMOTE:
g_value_set_boolean (value,
g_application_get_is_remote (application));
break;
case PROP_INACTIVITY_TIMEOUT:
g_value_set_uint (value,
g_application_get_inactivity_timeout (application));
break;
default:
g_assert_not_reached ();
}
}
static void
g_application_constructed (GObject *object)
{
GApplication *application = G_APPLICATION (object);
g_assert (application->priv->id != NULL);
}
static void
g_application_finalize (GObject *object)
{
GApplication *application = G_APPLICATION (object);
if (application->priv->impl)
g_application_impl_destroy (application->priv->impl);
g_free (application->priv->id);
if (application->priv->mainloop)
g_main_loop_unref (application->priv->mainloop);
G_OBJECT_CLASS (g_application_parent_class)
->finalize (object);
}
static void
g_application_init (GApplication *application)
{
application->priv = G_TYPE_INSTANCE_GET_PRIVATE (application,
G_TYPE_APPLICATION,
GApplicationPrivate);
}
static gboolean
first_wins_accumulator (GSignalInvocationHint *ihint,
GValue *return_accu,
const GValue *handler_return,
gpointer data)
{
g_value_copy (handler_return, return_accu);
return FALSE;
}
static void
g_application_class_init (GApplicationClass *class)
{
GObjectClass *object_class = G_OBJECT_CLASS (class);
object_class->constructed = g_application_constructed;
object_class->finalize = g_application_finalize;
object_class->get_property = g_application_get_property;
object_class->set_property = g_application_set_property;
class->before_emit = g_application_real_before_emit;
class->after_emit = g_application_real_after_emit;
class->startup = g_application_real_startup;
class->activate = g_application_real_activate;
class->open = g_application_real_open;
class->command_line = g_application_real_command_line;
class->local_command_line = g_application_real_local_command_line;
class->add_platform_data = g_application_real_add_platform_data;
class->quit_mainloop = g_application_real_quit_mainloop;
class->run_mainloop = g_application_real_run_mainloop;
g_object_class_install_property (object_class, PROP_APPLICATION_ID,
g_param_spec_string ("application-id", "application identifier",
"Unique identifier for the application",
NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT |
G_PARAM_STATIC_STRINGS));
g_object_class_install_property (object_class, PROP_FLAGS,
g_param_spec_flags ("flags", "application flags",
"Flags specifying the behaviour of the application",
G_TYPE_APPLICATION_FLAGS, G_APPLICATION_FLAGS_NONE,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
g_object_class_install_property (object_class, PROP_IS_REGISTERED,
g_param_spec_boolean ("is-registered", "is registered",
"If g_application_register() has been called",
FALSE, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
g_object_class_install_property (object_class, PROP_IS_REMOTE,
g_param_spec_boolean ("is-remote", "is remote",
"If this application instance is remote",
FALSE, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
g_object_class_install_property (object_class, PROP_INACTIVITY_TIMEOUT,
g_param_spec_boolean ("inactivity-timeout", "inactivity timeout",
"time (ms) to stay alive after becoming idle",
0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
g_application_signals[SIGNAL_STARTUP] =
g_signal_new ("startup", G_TYPE_APPLICATION, G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GApplicationClass, startup),
NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
g_application_signals[SIGNAL_ACTIVATE] =
g_signal_new ("activate", G_TYPE_APPLICATION, G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GApplicationClass, activate),
NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
g_application_signals[SIGNAL_OPEN] =
g_signal_new ("open", G_TYPE_APPLICATION, G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GApplicationClass, open),
NULL, NULL, _gio_marshal_VOID__POINTER_INT_STRING,
G_TYPE_NONE, 3, G_TYPE_POINTER, G_TYPE_INT, G_TYPE_STRING);
g_application_signals[SIGNAL_COMMAND_LINE] =
g_signal_new ("command-line", G_TYPE_APPLICATION, G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GApplicationClass, command_line),
first_wins_accumulator, NULL, _gio_marshal_INT__OBJECT,
G_TYPE_INT, 1, G_TYPE_APPLICATION_COMMAND_LINE);
g_type_class_add_private (class, sizeof (GApplicationPrivate));
}
static GVariant *
get_platform_data (GApplication *application)
{
GVariantBuilder *builder;
GVariant *result;
builder = g_variant_builder_new (G_VARIANT_TYPE ("a{sv}"));
{
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);
return result;
}
/* Application ID validity {{{1 */
/**
* g_application_id_is_valid:
* @application_id: a potential application identifier
* @returns: %TRUE if @application_id is valid
*
* Checks if @application_id is a valid application ID. A valid ID is
* required for calls to g_application_new() and
* g_application_set_application_id().
**/
gboolean
g_application_id_is_valid (const gchar *application_id)
{
gboolean allow_dot;
if (strlen (application_id) > 255)
return FALSE;
if (!g_ascii_isalpha (*application_id))
return FALSE;
application_id++;
allow_dot = FALSE;
for (; *application_id; application_id++)
{
if (g_ascii_isalnum (*application_id) ||
(*application_id == '-') ||
(*application_id == '_'))
allow_dot = TRUE;
else if (allow_dot && *application_id == '.')
allow_dot = FALSE;
else
return FALSE;
}
return TRUE;
}
/* Public Constructor {{{1 */
/**
* g_application_new:
* @application_id: the application id
* @flags: the application flags
* @returns: a new #GApplication instance
*
* Creates a new #GApplication instance.
*
* This function calls g_type_init() for you.
*
* The application id must be valid. See g_application_id_is_valid().
**/
GApplication *
g_application_new (const gchar *application_id,
GApplicationFlags flags)
{
g_return_val_if_fail (g_application_id_is_valid (application_id), NULL);
g_type_init ();
return g_object_new (G_TYPE_APPLICATION,
"application-id", application_id,
"flags", flags,
NULL);
}
/* Simple get/set: application id, flags, inactivity timeout {{{1 */
/**
* g_application_get_application_id:
* @application: a #GApplication
* @returns: the identifier for @application, owned by @application
*
* Gets the unique identifier for @application.
*
* Since: 2.28
**/
const gchar *
g_application_get_application_id (GApplication *application)
{
g_return_val_if_fail (G_IS_APPLICATION (application), NULL);
return application->priv->id;
}
/**
* g_application_set_application_id:
* @application: a #GApplication
* @application_id: the identifier for @application
*
* Sets the unique identifier for @application.
*
* The application id can only be modified if @application has not yet
* been registered.
*
* The application id must be valid. See g_application_id_is_valid().
*
* Since: 2.28
**/
void
g_application_set_application_id (GApplication *application,
const gchar *application_id)
{
g_return_if_fail (G_IS_APPLICATION (application));
if (g_strcmp0 (application->priv->id, application_id) != 0)
{
g_return_if_fail (g_application_id_is_valid (application_id));
g_return_if_fail (!application->priv->is_registered);
g_free (application->priv->id);
application->priv->id = g_strdup (application_id);
g_object_notify (G_OBJECT (application), "application-id");
}
}
/**
* g_application_get_flags:
* @application: a #GApplication
* @returns: the flags for @application
*
* Gets the flags for @application.
*
* See #GApplicationFlags.
*
* Since: 2.28
**/
GApplicationFlags
g_application_get_flags (GApplication *application)
{
g_return_val_if_fail (G_IS_APPLICATION (application), 0);
return application->priv->flags;
}
/**
* g_application_set_flags:
* @application: a #GApplication
* @flags: the flags for @application
*
* Sets the flags for @application.
*
* The flags can only be modified if @application has not yet been
* registered.
*
* See #GApplicationFlags.
*
* Since: 2.28
**/
void
g_application_set_flags (GApplication *application,
GApplicationFlags flags)
{
g_return_if_fail (G_IS_APPLICATION (application));
if (application->priv->flags != flags)
{
g_return_if_fail (!application->priv->is_registered);
application->priv->flags = flags;
g_object_notify (G_OBJECT (application), "flags");
}
}
/**
* g_application_get_inactivity_timeout:
* @application: a #GApplication
*
* Gets the current inactivity timeout for the application.
*
* This is the amount of time (in milliseconds) after the last call to
* g_application_release() before the application stops running.
*
* Returns: the timeout, in milliseconds
*
* Since: 2.28
**/
guint
g_application_get_inactivity_timeout (GApplication *application)
{
g_return_val_if_fail (G_IS_APPLICATION (application), 0);
return application->priv->inactivity_timeout;
}
/**
* g_application_set_inactivity_timeout:
* @application: a #GApplication
* @inactivity_timeout: the timeout, in milliseconds
*
* Sets the current inactivity timeout for the application.
*
* This is the amount of time (in milliseconds) after the last call to
* g_application_release() before the application stops running.
*
* This call has no side effects of its own. The value set here is only
* used for next time g_application_release() drops the use count to
* zero. Any timeouts currently in progress are not impacted.
*
* Returns: the timeout, in milliseconds
*
* Since: 2.28
**/
void
g_application_set_inactivity_timeout (GApplication *application,
guint inactivity_timeout)
{
g_return_if_fail (G_IS_APPLICATION (application));
if (application->priv->inactivity_timeout != inactivity_timeout)
{
application->priv->inactivity_timeout = inactivity_timeout;
g_object_notify (G_OBJECT (application), "inactivity-timeout");
}
}
/* Read-only property getters (is registered, is remote) {{{1 */
/**
* g_application_get_is_registered:
* @application: a #GApplication
* @returns: %TRUE if @application is registered
*
* Checks if @application is registered.
*
* An application is registered if g_application_register() has been
* successfully called.
*
* Since: 2.28
**/
gboolean
g_application_get_is_registered (GApplication *application)
{
g_return_val_if_fail (G_IS_APPLICATION (application), FALSE);
return application->priv->is_registered;
}
/**
* g_application_get_is_remote:
* @application: a #GApplication
* @returns: %TRUE if @application is remote
*
* Checks if @application is remote.
*
* If @application is remote then it means that another instance of
* application already exists (the 'primary' instance). Calls to
* perform actions on @application will result in the actions being
* performed by the primary instance.
*
* The value of this property can not be accessed before
* g_application_register() has been called. See
* g_application_get_is_registered().
*
* Since: 2.28
**/
gboolean
g_application_get_is_remote (GApplication *application)
{
g_return_val_if_fail (G_IS_APPLICATION (application), FALSE);
g_return_val_if_fail (application->priv->is_registered, FALSE);
return application->priv->is_remote;
}
/* Register {{{1 */
/**
* g_application_register:
* @application: a #GApplication
* @cancellable: a #GCancellable, or %NULL
* @error: a pointer to a NULL #GError, or %NULL
* @returns: %TRUE if registration succeeded
*
* Attempts registration of the application.
*
* This is the point at which the application discovers if it is the
* primary instance or merely acting as a remote for an already-existing
* primary instance.
*
* If the application has already been registered then %TRUE is
* returned with no work performed.
*
* The startup() virtual function is invoked if registration succeeds
* and @application is the primary instance.
*
* In the event of an error (such as @cancellable being cancelled, or a
* failure to connect to the session bus), %FALSE is returned and @error
* is set appropriately.
*
* Note: the return value of this function is not an indicator that this
* instance is or is not the primary instance of the application. See
* g_application_get_is_remote() for that.
*
* Since: 2.28
**/
gboolean
g_application_register (GApplication *application,
GCancellable *cancellable,
GError **error)
{
g_return_val_if_fail (G_IS_APPLICATION (application), FALSE);
if (!application->priv->is_registered)
{
gboolean is_remote;
gboolean try;
/* don't try to be the primary instance if
* G_APPLICATION_IS_LAUNCHER was specified.
*/
try = !(application->priv->flags & G_APPLICATION_IS_LAUNCHER);
application->priv->impl =
g_application_impl_register (application, application->priv->id,
application->priv->flags,
&is_remote, cancellable, error);
if (application->priv->impl == NULL)
return FALSE;
application->priv->is_remote = is_remote;
application->priv->is_registered = TRUE;
g_object_notify (G_OBJECT (application), "is-registered");
if (!is_remote)
g_signal_emit (application, g_application_signals[SIGNAL_STARTUP], 0);
}
return TRUE;
}
/* Hold/release {{{1 */
/**
* g_application_hold:
* @application: a #GApplication
*
* Increases the use count of @application.
*
* Use this function to indicate that the application has a reason to
* continue to run. For example, g_application_hold() is called by Gtk
* when a toplevel window is on the screen.
*
* To cancel the hold, call g_application_release().
**/
void
g_application_hold (GApplication *application)
{
if (application->priv->inactivity_timeout_id)
{
g_source_remove (application->priv->inactivity_timeout_id);
application->priv->inactivity_timeout_id = 0;
}
application->priv->use_count++;
}
static gboolean
inactivity_timeout_expired (gpointer data)
{
GApplication *application = G_APPLICATION (data);
G_APPLICATION_GET_CLASS (application)
->quit_mainloop (application);
return FALSE;
}
/**
* g_application_release:
* @application: a #GApplication
*
* Decrease the use count of @application.
*
* When the use count reaches zero, the application will stop running.
*
* Never call this function except to cancel the effect of a previous
* call to g_application_hold().
**/
void
g_application_release (GApplication *application)
{
application->priv->use_count--;
if (application->priv->use_count == 0)
{
if (application->priv->inactivity_timeout)
application->priv->inactivity_timeout_id =
g_timeout_add (application->priv->inactivity_timeout,
inactivity_timeout_expired, application);
else
G_APPLICATION_GET_CLASS (application)
->quit_mainloop (application);
}
}
/* Activate, Open {{{1 */
/**
* g_application_activate:
* @application: a #GApplication
*
* Activates the application.
*
* In essence, this results in the activate() virtual function being
* invoked in the primary instance.
*
* The application must be registered before calling this function.
*
* Since: 2.28
**/
void
g_application_activate (GApplication *application)
{
g_return_if_fail (G_IS_APPLICATION (application));
g_return_if_fail (application->priv->is_registered);
if (application->priv->is_remote)
g_application_impl_activate (application->priv->impl,
get_platform_data (application));
else
g_signal_emit (application, g_application_signals[SIGNAL_ACTIVATE], 0);
}
/**
* g_application_open:
* @application: a #GApplication
* @files: an array of #GFile<!-- -->s to open
* @n_files: the length of the @files array
* @hint: a hint (or ""), but never %NULL
*
* Opens the given files.
*
* In essence, this results in the open() virtual function being invoked
* in the primary instance.
*
* @n_files must be greater than zero.
*
* @hint is simply passed through to the open() virtual function. It is
* intended to be used by applications that have multiple modes for
* opening files (eg: "view" vs "edit", etc). Unless you have a need
* for this functionality, you should use "".
*
* The application must be registered before calling this function and
* it must have the %G_APPLICATION_CAN_OPEN flag set. The open()
* virtual function should also be implemented in order for anything
* meaningful to happen.
*
* Since: 2.28
**/
void
g_application_open (GApplication *application,
GFile **files,
gint n_files,
const gchar *hint)
{
g_return_if_fail (G_IS_APPLICATION (application));
g_return_if_fail (application->priv->flags &
G_APPLICATION_HANDLES_OPEN);
g_return_if_fail (application->priv->is_registered);
if (application->priv->is_remote)
g_application_impl_open (application->priv->impl,
files, n_files, hint,
get_platform_data (application));
else
g_signal_emit (application, g_application_signals[SIGNAL_OPEN],
0, files, n_files, hint);
}
/* Run {{{1 */
/**
* g_application_run:
* @application: a #GApplication
* @argc: the argc from main()
* @argv: the argv from main()
* @returns: the exit status
*
* Runs the application.
*
* This function is intended to be run from main() and its return value
* is intended to be returned by main().
*
* First, the handle_command_line() virtual function is invoked. This
* function always runs on the local instance. If that function returns
* %FALSE then the application is registered and the command_line()
* virtual function is invoked in the primary instance (which may or may
* not be this instance).
*
* If the application has the %G_APPLICATION_REMOTE_COMMAND_LINE
* flag set then the default implementation of handle_command_line()
* always returns %FALSE immediately, resulting in the commandline
* always being handled in the primary instance.
*
* Otherwise, the default implementation of handle_command_line() tries
* to do a couple of things that are probably reasoanble for most
* applications. First, g_application_register() is called to attempt
* to register the application. If that works, then the command line
* arguments are inspected. If no commandline arguments are given, then
* g_application_activate() is called. If commandline arguments are
* given and the %G_APPLICATION_CAN_OPEN flags is set then they
* are assumed to be filenames and g_application_open() is called.
*
* If you are interested in doing more complicated local handling of the
* commandline then you should override handle_command_line().
*
* If, after the above is done, the use count of the application is zero
* then the exit status is returned immediately. If the use count is
* non-zero then the mainloop is run until the use count falls to zero,
* at which point 0 is returned.
*
* Since: 2.28
**/
int
g_application_run (GApplication *application,
int argc,
char **argv)
{
g_return_val_if_fail (G_IS_APPLICATION (application), 1);
g_return_val_if_fail (argc == 0 || argv != NULL, 1);
return g_application_run_with_arguments (application,
g_variant_new_bytestring_array ((const gchar **) argv, argc));
}
/**
* g_application_run_with_arguments:
* @application: a #GApplication
* @arguments: a bytestring array #GVariant
* @returns: the exit status
*
* This is a bindings-friendly version of g_application_run().
*
* This function will consume @arguments if it is floating.
**/
int
g_application_run_with_arguments (GApplication *application,
GVariant *arguments)
{
int status;
g_return_val_if_fail (G_IS_APPLICATION (application), 1);
g_return_val_if_fail (G_IS_APPLICATION (application), 1);
g_variant_ref_sink (arguments);
if (g_get_prgname () == NULL && g_variant_n_children (arguments))
{
const gchar *argv0;
gchar *prgname;
g_variant_get_child (arguments, 0, "^&ay", &argv0);
prgname = g_path_get_basename (argv0);
g_set_prgname (prgname);
g_free (prgname);
}
if (!G_APPLICATION_GET_CLASS (application)
->local_command_line (application, &arguments, &status))
{
GError *error = NULL;
if (!g_application_register (application, NULL, &error))
{
g_printerr ("%s", error->message);
g_error_free (error);
return 1;
}
if (application->priv->is_remote)
{
GVariant *platform_data;
platform_data = get_platform_data (application);
status = g_application_impl_command_line (application->priv->impl,
arguments, platform_data);
}
else
{
GApplicationCommandLine *cmdline;
cmdline = g_object_new (G_TYPE_APPLICATION_COMMAND_LINE,
"arguments", arguments, NULL);
g_signal_emit (application,
g_application_signals[SIGNAL_COMMAND_LINE],
0, cmdline, &status);
g_object_unref (cmdline);
}
}
g_variant_unref (arguments);
if (application->priv->flags & G_APPLICATION_IS_SERVICE &&
!application->priv->use_count &&
!application->priv->inactivity_timeout_id)
{
application->priv->inactivity_timeout_id =
g_timeout_add (10000, inactivity_timeout_expired, application);
}
if (application->priv->use_count ||
application->priv->inactivity_timeout_id)
{
G_APPLICATION_GET_CLASS (application)
->run_mainloop (application);
status = 0;
}
if (application->priv->impl)
g_application_impl_flush (application->priv->impl);
return status;
}
static gboolean
g_application_has_action (GActionGroup *action_group,
const gchar *action_name)
{
return FALSE;
}
static gchar **
g_application_list_actions (GActionGroup *action_group)
{
return NULL;
}
static gboolean
g_application_get_action_enabled (GActionGroup *action_group,
const gchar *action_name)
{
return FALSE;
}
static const GVariantType *
g_application_get_action_parameter_type (GActionGroup *action_group,
const gchar *action_name)
{
return NULL;
}
static const GVariantType *
g_application_get_action_state_type (GActionGroup *action_group,
const gchar *action_name)
{
return NULL;
}
static GVariant *
g_application_get_action_state_hint (GActionGroup *action_group,
const gchar *action_name)
{
return NULL;
}
static GVariant *
g_application_get_action_state (GActionGroup *action_group,
const gchar *action_name)
{
return NULL;
}
static void
g_application_change_action_state (GActionGroup *action_group,
const gchar *action_name,
GVariant *value)
{
}
static void
g_application_activate_action (GActionGroup *action_group,
const gchar *action_name,
GVariant *parameter)
{
}
static void
g_application_action_group_iface_init (GActionGroupInterface *iface)
{
iface->has_action = g_application_has_action;
iface->list_actions = g_application_list_actions;
iface->get_action_enabled = g_application_get_action_enabled;
iface->get_action_parameter_type = g_application_get_action_parameter_type;
iface->get_action_state_type = g_application_get_action_state_type;
iface->get_action_state_hint = g_application_get_action_state_hint;
iface->get_action_state = g_application_get_action_state;
iface->change_action_state = g_application_change_action_state;
iface->activate_action = g_application_activate_action;
}
/* Epilogue {{{1 */
/* vim:set foldmethod=marker: */