GApplication: fill in action group implementation
[platform/upstream/glib.git] / gio / gapplication.c
1 /*
2  * Copyright © 2010 Codethink Limited
3  *
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU Lesser General Public License as published
6  * by the Free Software Foundation; either version 2 of the licence or (at
7  * your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General
15  * Public License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
17  * Boston, MA 02111-1307, USA.
18  *
19  * Authors: Ryan Lortie <desrt@desrt.ca>
20  */
21
22 /* Prologue {{{1 */
23 #include "gapplication.h"
24
25 #include "gapplicationcommandline.h"
26 #include "gapplicationimpl.h"
27 #include "gactiongroup.h"
28
29 #include "gioenumtypes.h"
30 #include "gio-marshal.h"
31 #include "gioenums.h"
32 #include "gfile.h"
33
34 #include <string.h>
35
36 struct _GApplicationPrivate
37 {
38   GApplicationFlags  flags;
39   gchar             *id;
40
41   GActionGroup      *actions;
42   GMainLoop         *mainloop;
43
44   guint              inactivity_timeout_id;
45   guint              inactivity_timeout;
46   guint              use_count;
47
48   guint              is_registered : 1;
49   guint              is_remote : 1;
50
51   GApplicationImpl  *impl;
52 };
53
54 enum
55 {
56   PROP_NONE,
57   PROP_APPLICATION_ID,
58   PROP_FLAGS,
59   PROP_IS_REGISTERED,
60   PROP_IS_REMOTE,
61   PROP_INACTIVITY_TIMEOUT,
62   PROP_ACTION_GROUP
63 };
64
65 enum
66 {
67   SIGNAL_STARTUP,
68   SIGNAL_ACTIVATE,
69   SIGNAL_OPEN,
70   SIGNAL_ACTION,
71   SIGNAL_COMMAND_LINE,
72   NR_SIGNALS
73 };
74
75 static guint g_application_signals[NR_SIGNALS];
76
77 static void g_application_action_group_iface_init (GActionGroupInterface *);
78 G_DEFINE_TYPE_WITH_CODE (GApplication, g_application, G_TYPE_OBJECT,
79  G_IMPLEMENT_INTERFACE (G_TYPE_ACTION_GROUP,
80    g_application_action_group_iface_init))
81
82 /* vfunc defaults {{{1 */
83 static void
84 g_application_real_before_emit (GApplication *application,
85                                 GVariant     *platform_data)
86 {
87 }
88
89 static void
90 g_application_real_after_emit (GApplication *application,
91                                GVariant     *platform_data)
92 {
93 }
94
95 static void
96 g_application_real_startup (GApplication *application)
97 {
98 }
99
100 static void
101 g_application_real_activate (GApplication *application)
102 {
103   if (!g_signal_has_handler_pending (application,
104                                      g_application_signals[SIGNAL_ACTIVATE],
105                                      0, TRUE))
106     {
107       static gboolean warned;
108
109       if (warned)
110         return;
111
112       g_warning ("Your application does not implement "
113                  "g_application_activate() and has no handlers connected "
114                  "to the 'activate' signal.  It should do one of these.");
115       warned = TRUE;
116     }
117 }
118
119 static void
120 g_application_real_open (GApplication  *application,
121                          GFile        **files,
122                          gint           n_files,
123                          const gchar   *hint)
124 {
125   if (!g_signal_has_handler_pending (application,
126                                      g_application_signals[SIGNAL_OPEN],
127                                      0, TRUE))
128     {
129       static gboolean warned;
130
131       if (warned)
132         return;
133
134       g_warning ("Your application claims to support opening files "
135                  "but does not implement g_application_open() and has no "
136                  "handlers connected to the 'open' signal.");
137       warned = TRUE;
138     }
139 }
140
141 static int
142 g_application_real_command_line (GApplication            *application,
143                                  GApplicationCommandLine *cmdline)
144 {
145   static gboolean warned;
146
147   if (warned) 
148     return 1;
149
150   g_warning ("Your application claims to support custom command line "
151              "handling but does not implement g_application_command_line() "
152              "and has no handlers connected to the 'command-line' signal.");
153
154   warned = TRUE;
155
156   return 1;
157 }
158
159 static gboolean
160 g_application_real_local_command_line (GApplication  *application,
161                                        GVariant     **arguments,
162                                        int           *exit_status)
163 {
164   if (application->priv->flags & G_APPLICATION_HANDLES_COMMAND_LINE)
165     return FALSE;
166
167   else
168     {
169       GError *error = NULL;
170       gint n_args;
171
172       if (!g_application_register (application, NULL, &error))
173         {
174           g_critical ("%s", error->message);
175           g_error_free (error);
176           *exit_status = 1;
177           return TRUE;
178         }
179
180       n_args = g_variant_n_children (*arguments);
181
182       if (application->priv->flags & G_APPLICATION_IS_SERVICE)
183         {
184           if (n_args > 1)
185             {
186               g_printerr ("GApplication service mode takes no arguments.\n");
187               application->priv->flags &= ~G_APPLICATION_IS_SERVICE;
188             }
189
190           return TRUE;
191         }
192
193       if (n_args <= 1)
194         {
195           g_application_activate (application);
196           *exit_status = 0;
197         }
198
199       else
200         {
201           if (~application->priv->flags & G_APPLICATION_HANDLES_OPEN)
202             {
203               g_critical ("This application can not open files.");
204               *exit_status = 1;
205             }
206           else
207             {
208               GFile **files;
209               gint n_files;
210               gint i;
211
212               n_files = n_args - 1;
213               files = g_new (GFile *, n_files);
214
215               for (i = 0; i < n_files; i++)
216                 {
217                   const gchar *arg;
218
219                   g_variant_get_child (*arguments, i + 1, "^&ay", &arg);
220                   files[i] = g_file_new_for_commandline_arg (arg);
221                 }
222
223               g_application_open (application, files, n_files, "");
224
225               for (i = 0; i < n_files; i++)
226                 g_object_unref (files[i]);
227               g_free (files);
228
229               *exit_status = 0;
230             }
231         }
232
233       return TRUE;
234     }
235 }
236
237 static void
238 g_application_real_add_platform_data (GApplication    *application,
239                                       GVariantBuilder *builder)
240 {
241 }
242
243 static void
244 g_application_real_quit_mainloop (GApplication *application)
245 {
246   if (application->priv->mainloop != NULL)
247     g_main_loop_quit (application->priv->mainloop);
248 }
249
250 static void
251 g_application_real_run_mainloop (GApplication *application)
252 {
253   if (application->priv->mainloop == NULL)
254     application->priv->mainloop = g_main_loop_new (NULL, FALSE);
255
256   g_main_loop_run (application->priv->mainloop);
257 }
258
259 /* GObject implementation stuff {{{1 */
260 static void
261 g_application_set_property (GObject *object, guint prop_id,
262                             const GValue *value, GParamSpec *pspec)
263 {
264   GApplication *application = G_APPLICATION (object);
265
266   switch (prop_id)
267     {
268     case PROP_APPLICATION_ID:
269       g_application_set_application_id (application,
270                                         g_value_get_string (value));
271       break;
272
273     case PROP_FLAGS:
274       g_application_set_flags (application, g_value_get_flags (value));
275       break;
276
277     case PROP_INACTIVITY_TIMEOUT:
278       g_application_set_inactivity_timeout (application,
279                                             g_value_get_uint (value));
280       break;
281
282     case PROP_ACTION_GROUP:
283       g_application_set_action_group (application,
284                                       g_value_get_object (value));
285       break;
286
287     default:
288       g_assert_not_reached ();
289     }
290 }
291
292 /**
293  * g_application_set_action_group:
294  * @application: a #GApplication
295  * @action_group: a #GActionGroup, or %NULL
296  *
297  * Sets or unsets the group of actions associated with the application.
298  *
299  * These actions are the actions that can be remotely invoked.
300  *
301  * It is an error to call this function after the application has been
302  * registered.
303  *
304  * Since: 2.28
305  **/
306 void
307 g_application_set_action_group (GApplication *application,
308                                 GActionGroup *action_group)
309 {
310   g_return_if_fail (G_IS_APPLICATION (application));
311   g_return_if_fail (application->priv->is_registered);
312
313   if (application->priv->actions != NULL)
314     g_object_unref (application->priv->actions);
315
316   application->priv->actions = action_group;
317
318   if (application->priv->actions != NULL)
319     g_object_ref (application->priv->actions);
320 }
321
322 static void
323 g_application_get_property (GObject *object, guint prop_id,
324                             GValue *value, GParamSpec *pspec)
325 {
326   GApplication *application = G_APPLICATION (object);
327
328   switch (prop_id)
329     {
330     case PROP_APPLICATION_ID:
331       g_value_set_string (value,
332                           g_application_get_application_id (application));
333       break;
334
335     case PROP_FLAGS:
336       g_value_set_flags (value,
337                          g_application_get_flags (application));
338       break;
339
340     case PROP_IS_REGISTERED:
341       g_value_set_boolean (value,
342                            g_application_get_is_registered (application));
343       break;
344
345     case PROP_IS_REMOTE:
346       g_value_set_boolean (value,
347                            g_application_get_is_remote (application));
348       break;
349
350     case PROP_INACTIVITY_TIMEOUT:
351       g_value_set_uint (value,
352                         g_application_get_inactivity_timeout (application));
353       break;
354
355     default:
356       g_assert_not_reached ();
357     }
358 }
359
360 static void
361 g_application_constructed (GObject *object)
362 {
363   GApplication *application = G_APPLICATION (object);
364
365   g_assert (application->priv->id != NULL);
366 }
367
368 static void
369 g_application_finalize (GObject *object)
370 {
371   GApplication *application = G_APPLICATION (object);
372
373   if (application->priv->impl)
374     g_application_impl_destroy (application->priv->impl);
375   g_free (application->priv->id);
376
377   if (application->priv->mainloop)
378     g_main_loop_unref (application->priv->mainloop);
379
380   G_OBJECT_CLASS (g_application_parent_class)
381     ->finalize (object);
382 }
383
384 static void
385 g_application_init (GApplication *application)
386 {
387   application->priv = G_TYPE_INSTANCE_GET_PRIVATE (application,
388                                                    G_TYPE_APPLICATION,
389                                                    GApplicationPrivate);
390 }
391
392 static gboolean
393 first_wins_accumulator (GSignalInvocationHint *ihint,
394                         GValue                *return_accu,
395                         const GValue          *handler_return,
396                         gpointer               data)
397 {
398   g_value_copy (handler_return, return_accu);
399
400   return FALSE;
401 }
402
403 static void
404 g_application_class_init (GApplicationClass *class)
405 {
406   GObjectClass *object_class = G_OBJECT_CLASS (class);
407
408   object_class->constructed = g_application_constructed;
409   object_class->finalize = g_application_finalize;
410   object_class->get_property = g_application_get_property;
411   object_class->set_property = g_application_set_property;
412
413   class->before_emit = g_application_real_before_emit;
414   class->after_emit = g_application_real_after_emit;
415   class->startup = g_application_real_startup;
416   class->activate = g_application_real_activate;
417   class->open = g_application_real_open;
418   class->command_line = g_application_real_command_line;
419   class->local_command_line = g_application_real_local_command_line;
420   class->add_platform_data = g_application_real_add_platform_data;
421   class->quit_mainloop = g_application_real_quit_mainloop;
422   class->run_mainloop = g_application_real_run_mainloop;
423
424   g_object_class_install_property (object_class, PROP_APPLICATION_ID,
425     g_param_spec_string ("application-id", "application identifier",
426                          "Unique identifier for the application",
427                          NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT |
428                          G_PARAM_STATIC_STRINGS));
429
430   g_object_class_install_property (object_class, PROP_FLAGS,
431     g_param_spec_flags ("flags", "application flags",
432                         "Flags specifying the behaviour of the application",
433                          G_TYPE_APPLICATION_FLAGS, G_APPLICATION_FLAGS_NONE,
434                          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
435
436   g_object_class_install_property (object_class, PROP_IS_REGISTERED,
437     g_param_spec_boolean ("is-registered", "is registered",
438                           "If g_application_register() has been called",
439                           FALSE, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
440
441   g_object_class_install_property (object_class, PROP_IS_REMOTE,
442     g_param_spec_boolean ("is-remote", "is remote",
443                           "If this application instance is remote",
444                           FALSE, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
445
446   g_object_class_install_property (object_class, PROP_INACTIVITY_TIMEOUT,
447     g_param_spec_boolean ("inactivity-timeout", "inactivity timeout",
448                           "time (ms) to stay alive after becoming idle",
449                           FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
450
451   g_object_class_install_property (object_class, PROP_ACTION_GROUP,
452     g_param_spec_object ("action-group", "action group",
453                          "the group of actions that the application exports",
454                          G_TYPE_ACTION_GROUP, 
455                          G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS));
456
457   g_application_signals[SIGNAL_STARTUP] =
458     g_signal_new ("startup", G_TYPE_APPLICATION, G_SIGNAL_RUN_LAST,
459                   G_STRUCT_OFFSET (GApplicationClass, startup),
460                   NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
461
462   g_application_signals[SIGNAL_ACTIVATE] =
463     g_signal_new ("activate", G_TYPE_APPLICATION, G_SIGNAL_RUN_LAST,
464                   G_STRUCT_OFFSET (GApplicationClass, activate),
465                   NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
466
467   g_application_signals[SIGNAL_OPEN] =
468     g_signal_new ("open", G_TYPE_APPLICATION, G_SIGNAL_RUN_LAST,
469                   G_STRUCT_OFFSET (GApplicationClass, open),
470                   NULL, NULL, _gio_marshal_VOID__POINTER_INT_STRING,
471                   G_TYPE_NONE, 3, G_TYPE_POINTER, G_TYPE_INT, G_TYPE_STRING);
472
473   g_application_signals[SIGNAL_COMMAND_LINE] =
474     g_signal_new ("command-line", G_TYPE_APPLICATION, G_SIGNAL_RUN_LAST,
475                   G_STRUCT_OFFSET (GApplicationClass, command_line),
476                   first_wins_accumulator, NULL, _gio_marshal_INT__OBJECT,
477                   G_TYPE_INT, 1, G_TYPE_APPLICATION_COMMAND_LINE);
478
479   g_type_class_add_private (class, sizeof (GApplicationPrivate));
480 }
481
482 static GVariant *
483 get_platform_data (GApplication *application)
484 {
485   GVariantBuilder *builder;
486   GVariant *result;
487
488   builder = g_variant_builder_new (G_VARIANT_TYPE ("a{sv}"));
489
490   {
491     gchar *cwd = g_get_current_dir ();
492     g_variant_builder_add (builder, "{sv}", "cwd",
493                            g_variant_new_bytestring (cwd));
494     g_free (cwd);
495   }
496
497   G_APPLICATION_GET_CLASS (application)->
498     add_platform_data (application, builder);
499
500   result = g_variant_builder_end (builder);
501   g_variant_builder_unref (builder);
502
503   return result;
504 }
505
506 /* Application ID validity {{{1 */
507
508 /**
509  * g_application_id_is_valid:
510  * @application_id: a potential application identifier
511  * @returns: %TRUE if @application_id is valid
512  *
513  * Checks if @application_id is a valid application ID.  A valid ID is
514  * required for calls to g_application_new() and
515  * g_application_set_application_id().
516  **/
517 gboolean
518 g_application_id_is_valid (const gchar *application_id)
519 {
520   gboolean allow_dot;
521
522   if (strlen (application_id) > 255)
523     return FALSE;
524
525   if (!g_ascii_isalpha (*application_id))
526     return FALSE;
527
528   application_id++;
529   allow_dot = FALSE;
530   for (; *application_id; application_id++)
531     {
532       if (g_ascii_isalnum (*application_id) ||
533           (*application_id == '-') ||
534           (*application_id == '_'))
535         allow_dot = TRUE;
536       else if (allow_dot && *application_id == '.')
537         allow_dot = FALSE;
538       else
539         return FALSE;
540     }
541
542   return TRUE;
543 }
544
545 /* Public Constructor {{{1 */
546 /**
547  * g_application_new:
548  * @application_id: the application id
549  * @flags: the application flags
550  * @returns: a new #GApplication instance
551  *
552  * Creates a new #GApplication instance.
553  *
554  * This function calls g_type_init() for you.
555  *
556  * The application id must be valid.  See g_application_id_is_valid().
557  **/
558 GApplication *
559 g_application_new (const gchar       *application_id,
560                    GApplicationFlags  flags)
561 {
562   g_return_val_if_fail (g_application_id_is_valid (application_id), NULL);
563
564   g_type_init ();
565
566   return g_object_new (G_TYPE_APPLICATION,
567                        "application-id", application_id,
568                        "flags", flags,
569                        NULL);
570 }
571
572 /* Simple get/set: application id, flags, inactivity timeout {{{1 */
573 /**
574  * g_application_get_application_id:
575  * @application: a #GApplication
576  * @returns: the identifier for @application, owned by @application
577  *
578  * Gets the unique identifier for @application.
579  *
580  * Since: 2.28
581  **/
582 const gchar *
583 g_application_get_application_id (GApplication *application)
584 {
585   g_return_val_if_fail (G_IS_APPLICATION (application), NULL);
586
587   return application->priv->id;
588 }
589
590 /**
591  * g_application_set_application_id:
592  * @application: a #GApplication
593  * @application_id: the identifier for @application
594  *
595  * Sets the unique identifier for @application.
596  *
597  * The application id can only be modified if @application has not yet
598  * been registered.
599  *
600  * The application id must be valid.  See g_application_id_is_valid().
601  *
602  * Since: 2.28
603  **/
604 void
605 g_application_set_application_id (GApplication *application,
606                                   const gchar  *application_id)
607 {
608   g_return_if_fail (G_IS_APPLICATION (application));
609
610   if (g_strcmp0 (application->priv->id, application_id) != 0)
611     {
612       g_return_if_fail (g_application_id_is_valid (application_id));
613       g_return_if_fail (!application->priv->is_registered);
614
615       g_free (application->priv->id);
616       application->priv->id = g_strdup (application_id);
617
618       g_object_notify (G_OBJECT (application), "application-id");
619     }
620 }
621
622 /**
623  * g_application_get_flags:
624  * @application: a #GApplication
625  * @returns: the flags for @application
626  *
627  * Gets the flags for @application.
628  *
629  * See #GApplicationFlags.
630  *
631  * Since: 2.28
632  **/
633 GApplicationFlags
634 g_application_get_flags (GApplication *application)
635 {
636   g_return_val_if_fail (G_IS_APPLICATION (application), 0);
637
638   return application->priv->flags;
639 }
640
641 /**
642  * g_application_set_flags:
643  * @application: a #GApplication
644  * @flags: the flags for @application
645  *
646  * Sets the flags for @application.
647  *
648  * The flags can only be modified if @application has not yet been
649  * registered.
650  *
651  * See #GApplicationFlags.
652  *
653  * Since: 2.28
654  **/
655 void
656 g_application_set_flags (GApplication      *application,
657                          GApplicationFlags  flags)
658 {
659   g_return_if_fail (G_IS_APPLICATION (application));
660
661   if (application->priv->flags != flags)
662     {
663       g_return_if_fail (!application->priv->is_registered);
664
665       application->priv->flags = flags;
666
667       g_object_notify (G_OBJECT (application), "flags");
668     }
669 }
670
671 /**
672  * g_application_get_inactivity_timeout:
673  * @application: a #GApplication
674  *
675  * Gets the current inactivity timeout for the application.
676  *
677  * This is the amount of time (in milliseconds) after the last call to
678  * g_application_release() before the application stops running.
679  *
680  * Returns: the timeout, in milliseconds
681  *
682  * Since: 2.28
683  **/
684 guint
685 g_application_get_inactivity_timeout (GApplication *application)
686 {
687   g_return_val_if_fail (G_IS_APPLICATION (application), 0);
688
689   return application->priv->inactivity_timeout;
690 }
691
692 /**
693  * g_application_set_inactivity_timeout:
694  * @application: a #GApplication
695  * @inactivity_timeout: the timeout, in milliseconds
696  *
697  * Sets the current inactivity timeout for the application.
698  *
699  * This is the amount of time (in milliseconds) after the last call to
700  * g_application_release() before the application stops running.
701  *
702  * This call has no side effects of its own.  The value set here is only
703  * used for next time g_application_release() drops the use count to
704  * zero.  Any timeouts currently in progress are not impacted.
705  *
706  * Returns: the timeout, in milliseconds
707  *
708  * Since: 2.28
709  **/
710 void
711 g_application_set_inactivity_timeout (GApplication *application,
712                                       guint         inactivity_timeout)
713 {
714   g_return_if_fail (G_IS_APPLICATION (application));
715
716   if (application->priv->inactivity_timeout != inactivity_timeout)
717     {
718       application->priv->inactivity_timeout = inactivity_timeout;
719
720       g_object_notify (G_OBJECT (application), "inactivity-timeout");
721     }
722 }
723 /* Read-only property getters (is registered, is remote) {{{1 */
724 /**
725  * g_application_get_is_registered:
726  * @application: a #GApplication
727  * @returns: %TRUE if @application is registered
728  *
729  * Checks if @application is registered.
730  *
731  * An application is registered if g_application_register() has been
732  * successfully called.
733  *
734  * Since: 2.28
735  **/
736 gboolean
737 g_application_get_is_registered (GApplication *application)
738 {
739   g_return_val_if_fail (G_IS_APPLICATION (application), FALSE);
740
741   return application->priv->is_registered;
742 }
743
744 /**
745  * g_application_get_is_remote:
746  * @application: a #GApplication
747  * @returns: %TRUE if @application is remote
748  *
749  * Checks if @application is remote.
750  *
751  * If @application is remote then it means that another instance of
752  * application already exists (the 'primary' instance).  Calls to
753  * perform actions on @application will result in the actions being
754  * performed by the primary instance.
755  *
756  * The value of this property can not be accessed before
757  * g_application_register() has been called.  See
758  * g_application_get_is_registered().
759  *
760  * Since: 2.28
761  **/
762 gboolean
763 g_application_get_is_remote (GApplication *application)
764 {
765   g_return_val_if_fail (G_IS_APPLICATION (application), FALSE);
766   g_return_val_if_fail (application->priv->is_registered, FALSE);
767
768   return application->priv->is_remote;
769 }
770
771 /* Register {{{1 */
772 /**
773  * g_application_register:
774  * @application: a #GApplication
775  * @cancellable: a #GCancellable, or %NULL
776  * @error: a pointer to a NULL #GError, or %NULL
777  * @returns: %TRUE if registration succeeded
778  *
779  * Attempts registration of the application.
780  *
781  * This is the point at which the application discovers if it is the
782  * primary instance or merely acting as a remote for an already-existing
783  * primary instance.
784  *
785  * If the application has already been registered then %TRUE is
786  * returned with no work performed.
787  *
788  * The startup() virtual function is invoked if registration succeeds
789  * and @application is the primary instance.
790  *
791  * In the event of an error (such as @cancellable being cancelled, or a
792  * failure to connect to the session bus), %FALSE is returned and @error
793  * is set appropriately.
794  *
795  * Note: the return value of this function is not an indicator that this
796  * instance is or is not the primary instance of the application.  See
797  * g_application_get_is_remote() for that.
798  *
799  * Since: 2.28
800  **/
801 gboolean
802 g_application_register (GApplication  *application,
803                         GCancellable  *cancellable,
804                         GError       **error)
805 {
806   g_return_val_if_fail (G_IS_APPLICATION (application), FALSE);
807
808   if (!application->priv->is_registered)
809     {
810       gboolean is_remote;
811       gboolean try;
812
813       /* don't try to be the primary instance if
814        * G_APPLICATION_IS_LAUNCHER was specified.
815        */
816       try = !(application->priv->flags & G_APPLICATION_IS_LAUNCHER);
817
818       application->priv->impl =
819         g_application_impl_register (application, application->priv->id,
820                                      application->priv->flags,
821                                      &is_remote, cancellable, error);
822
823       if (application->priv->impl == NULL)
824         return FALSE;
825
826       application->priv->is_remote = is_remote;
827       application->priv->is_registered = TRUE;
828
829       g_object_notify (G_OBJECT (application), "is-registered");
830
831       if (!is_remote)
832         g_signal_emit (application, g_application_signals[SIGNAL_STARTUP], 0);
833     }
834
835   return TRUE;
836 }
837
838 /* Hold/release {{{1 */
839 /**
840  * g_application_hold:
841  * @application: a #GApplication
842  *
843  * Increases the use count of @application.
844  *
845  * Use this function to indicate that the application has a reason to
846  * continue to run.  For example, g_application_hold() is called by Gtk
847  * when a toplevel window is on the screen.
848  *
849  * To cancel the hold, call g_application_release().
850  **/
851 void
852 g_application_hold (GApplication *application)
853 {
854   if (application->priv->inactivity_timeout_id)
855     {
856       g_source_remove (application->priv->inactivity_timeout_id);
857       application->priv->inactivity_timeout_id = 0;
858     }
859
860   application->priv->use_count++;
861 }
862
863 static gboolean
864 inactivity_timeout_expired (gpointer data)
865 {
866   GApplication *application = G_APPLICATION (data);
867
868   G_APPLICATION_GET_CLASS (application)
869     ->quit_mainloop (application);
870
871   return FALSE;
872 }
873
874
875 /**
876  * g_application_release:
877  * @application: a #GApplication
878  *
879  * Decrease the use count of @application.
880  *
881  * When the use count reaches zero, the application will stop running.
882  *
883  * Never call this function except to cancel the effect of a previous
884  * call to g_application_hold().
885  **/
886 void
887 g_application_release (GApplication *application)
888 {
889   application->priv->use_count--;
890
891   if (application->priv->use_count == 0)
892     {
893       if (application->priv->inactivity_timeout)
894         application->priv->inactivity_timeout_id =
895           g_timeout_add (application->priv->inactivity_timeout,
896                          inactivity_timeout_expired, application);
897
898       else
899         G_APPLICATION_GET_CLASS (application)
900           ->quit_mainloop (application);
901     }
902 }
903
904 /* Activate, Open {{{1 */
905 /**
906  * g_application_activate:
907  * @application: a #GApplication
908  *
909  * Activates the application.
910  *
911  * In essence, this results in the activate() virtual function being
912  * invoked in the primary instance.
913  *
914  * The application must be registered before calling this function.
915  *
916  * Since: 2.28
917  **/
918 void
919 g_application_activate (GApplication *application)
920 {
921   g_return_if_fail (G_IS_APPLICATION (application));
922   g_return_if_fail (application->priv->is_registered);
923
924   if (application->priv->is_remote)
925     g_application_impl_activate (application->priv->impl,
926                                  get_platform_data (application));
927
928   else
929     g_signal_emit (application, g_application_signals[SIGNAL_ACTIVATE], 0);
930 }
931
932 /**
933  * g_application_open:
934  * @application: a #GApplication
935  * @files: an array of #GFile<!-- -->s to open
936  * @n_files: the length of the @files array
937  * @hint: a hint (or ""), but never %NULL
938  *
939  * Opens the given files.
940  *
941  * In essence, this results in the open() virtual function being invoked
942  * in the primary instance.
943  *
944  * @n_files must be greater than zero.
945  *
946  * @hint is simply passed through to the open() virtual function.  It is
947  * intended to be used by applications that have multiple modes for
948  * opening files (eg: "view" vs "edit", etc).  Unless you have a need
949  * for this functionality, you should use "".
950  *
951  * The application must be registered before calling this function and
952  * it must have the %G_APPLICATION_CAN_OPEN flag set.  The open()
953  * virtual function should also be implemented in order for anything
954  * meaningful to happen.
955  *
956  * Since: 2.28
957  **/
958 void
959 g_application_open (GApplication  *application,
960                     GFile        **files,
961                     gint           n_files,
962                     const gchar   *hint)
963 {
964   g_return_if_fail (G_IS_APPLICATION (application));
965   g_return_if_fail (application->priv->flags &
966                     G_APPLICATION_HANDLES_OPEN);
967   g_return_if_fail (application->priv->is_registered);
968
969   if (application->priv->is_remote)
970     g_application_impl_open (application->priv->impl,
971                              files, n_files, hint,
972                              get_platform_data (application));
973
974   else
975     g_signal_emit (application, g_application_signals[SIGNAL_OPEN],
976                    0, files, n_files, hint);
977 }
978
979 /* Run {{{1 */
980 /**
981  * g_application_run:
982  * @application: a #GApplication
983  * @argc: the argc from main()
984  * @argv: the argv from main()
985  * @returns: the exit status
986  *
987  * Runs the application.
988  *
989  * This function is intended to be run from main() and its return value
990  * is intended to be returned by main().
991  *
992  * First, the handle_command_line() virtual function is invoked.  This
993  * function always runs on the local instance.  If that function returns
994  * %FALSE then the application is registered and the command_line()
995  * virtual function is invoked in the primary instance (which may or may
996  * not be this instance).
997  *
998  * If the application has the %G_APPLICATION_REMOTE_COMMAND_LINE
999  * flag set then the default implementation of handle_command_line()
1000  * always returns %FALSE immediately, resulting in the commandline
1001  * always being handled in the primary instance.
1002  *
1003  * Otherwise, the default implementation of handle_command_line() tries
1004  * to do a couple of things that are probably reasoanble for most
1005  * applications.  First, g_application_register() is called to attempt
1006  * to register the application.  If that works, then the command line
1007  * arguments are inspected.  If no commandline arguments are given, then
1008  * g_application_activate() is called.  If commandline arguments are
1009  * given and the %G_APPLICATION_CAN_OPEN flags is set then they
1010  * are assumed to be filenames and g_application_open() is called.
1011  *
1012  * If you are interested in doing more complicated local handling of the
1013  * commandline then you should override handle_command_line().
1014  *
1015  * If, after the above is done, the use count of the application is zero
1016  * then the exit status is returned immediately.  If the use count is
1017  * non-zero then the mainloop is run until the use count falls to zero,
1018  * at which point 0 is returned.
1019  *
1020  * Since: 2.28
1021  **/
1022 int
1023 g_application_run (GApplication  *application,
1024                    int            argc,
1025                    char         **argv)
1026 {
1027   g_return_val_if_fail (G_IS_APPLICATION (application), 1);
1028   g_return_val_if_fail (argc == 0 || argv != NULL, 1);
1029
1030   return g_application_run_with_arguments (application,
1031     g_variant_new_bytestring_array ((const gchar **) argv, argc));
1032 }
1033
1034 /**
1035  * g_application_run_with_arguments:
1036  * @application: a #GApplication
1037  * @arguments: a bytestring array #GVariant
1038  * @returns: the exit status
1039  *
1040  * This is a bindings-friendly version of g_application_run().
1041  *
1042  * This function will consume @arguments if it is floating.
1043  **/
1044 int
1045 g_application_run_with_arguments (GApplication *application,
1046                                   GVariant     *arguments)
1047 {
1048   int status;
1049
1050   g_return_val_if_fail (G_IS_APPLICATION (application), 1);
1051   g_return_val_if_fail (G_IS_APPLICATION (application), 1);
1052
1053   g_variant_ref_sink (arguments);
1054
1055   if (g_get_prgname () == NULL && g_variant_n_children (arguments))
1056     {
1057       const gchar *argv0;
1058       gchar *prgname;
1059
1060       g_variant_get_child (arguments, 0, "^&ay", &argv0);
1061       prgname = g_path_get_basename (argv0);
1062       g_set_prgname (prgname);
1063       g_free (prgname);
1064     }
1065
1066   if (!G_APPLICATION_GET_CLASS (application)
1067         ->local_command_line (application, &arguments, &status))
1068     {
1069       GError *error = NULL;
1070
1071       if (!g_application_register (application, NULL, &error))
1072         {
1073           g_printerr ("%s", error->message);
1074           g_error_free (error);
1075           return 1;
1076         }
1077
1078       if (application->priv->is_remote)
1079         {
1080           GVariant *platform_data;
1081
1082           platform_data = get_platform_data (application);
1083           status = g_application_impl_command_line (application->priv->impl,
1084                                                     arguments, platform_data);
1085         }
1086       else
1087         {
1088           GApplicationCommandLine *cmdline;
1089
1090           cmdline = g_object_new (G_TYPE_APPLICATION_COMMAND_LINE,
1091                                   "arguments", arguments, NULL);
1092           g_signal_emit (application,
1093                          g_application_signals[SIGNAL_COMMAND_LINE],
1094                          0, cmdline, &status);
1095           g_object_unref (cmdline);
1096         }
1097     }
1098
1099   g_variant_unref (arguments);
1100
1101   if (application->priv->flags & G_APPLICATION_IS_SERVICE &&
1102       !application->priv->use_count &&
1103       !application->priv->inactivity_timeout_id)
1104     {
1105       application->priv->inactivity_timeout_id =
1106         g_timeout_add (10000, inactivity_timeout_expired, application);
1107     }
1108
1109   if (application->priv->use_count ||
1110       application->priv->inactivity_timeout_id)
1111     {
1112       G_APPLICATION_GET_CLASS (application)
1113         ->run_mainloop (application);
1114       status = 0;
1115     }
1116
1117   if (application->priv->impl)
1118     g_application_impl_flush (application->priv->impl);
1119
1120   return status;
1121 }
1122
1123 static gboolean
1124 g_application_has_action (GActionGroup *action_group,
1125                           const gchar  *action_name)
1126 {
1127   GApplication *application = G_APPLICATION (action_group);
1128
1129   g_return_val_if_fail (application->priv->is_registered, FALSE);
1130
1131   return application->priv->actions &&
1132          g_action_group_has_action (application->priv->actions, action_name);
1133 }
1134
1135 static gchar **
1136 g_application_list_actions (GActionGroup *action_group)
1137 {
1138   GApplication *application = G_APPLICATION (action_group);
1139
1140   g_return_val_if_fail (application->priv->is_registered, NULL);
1141
1142   if (application->priv->actions != NULL)
1143     return g_action_group_list_actions (application->priv->actions);
1144
1145   else
1146     /* empty string array */
1147     return g_new0 (gchar *, 1);
1148 }
1149
1150 static gboolean
1151 g_application_get_action_enabled (GActionGroup *action_group,
1152                                   const gchar  *action_name)
1153 {
1154   GApplication *application = G_APPLICATION (action_group);
1155
1156   g_return_val_if_fail (application->priv->actions != NULL, FALSE);
1157   g_return_val_if_fail (application->priv->is_registered, FALSE);
1158
1159   return g_action_group_get_action_enabled (application->priv->actions,
1160                                             action_name);
1161 }
1162
1163 static const GVariantType *
1164 g_application_get_action_parameter_type (GActionGroup *action_group,
1165                                          const gchar  *action_name)
1166 {
1167   GApplication *application = G_APPLICATION (action_group);
1168
1169   g_return_val_if_fail (application->priv->actions != NULL, NULL);
1170   g_return_val_if_fail (application->priv->is_registered, NULL);
1171
1172   return g_action_group_get_action_parameter_type (application->priv->actions,
1173                                                    action_name);
1174 }
1175
1176 static const GVariantType *
1177 g_application_get_action_state_type (GActionGroup *action_group,
1178                                      const gchar  *action_name)
1179 {
1180   GApplication *application = G_APPLICATION (action_group);
1181
1182   g_return_val_if_fail (application->priv->actions != NULL, NULL);
1183   g_return_val_if_fail (application->priv->is_registered, NULL);
1184
1185   return g_action_group_get_action_state_type (application->priv->actions,
1186                                                action_name);
1187 }
1188
1189 static GVariant *
1190 g_application_get_action_state_hint (GActionGroup *action_group,
1191                                      const gchar  *action_name)
1192 {
1193   GApplication *application = G_APPLICATION (action_group);
1194
1195   g_return_val_if_fail (application->priv->actions != NULL, NULL);
1196   g_return_val_if_fail (application->priv->is_registered, NULL);
1197
1198   return g_action_group_get_action_state_hint (application->priv->actions,
1199                                                action_name);
1200 }
1201
1202 static GVariant *
1203 g_application_get_action_state (GActionGroup *action_group,
1204                                 const gchar  *action_name)
1205 {
1206   GApplication *application = G_APPLICATION (action_group);
1207
1208   g_return_val_if_fail (application->priv->actions != NULL, NULL);
1209   g_return_val_if_fail (application->priv->is_registered, NULL);
1210
1211   return g_action_group_get_action_state (application->priv->actions,
1212                                           action_name);
1213 }
1214
1215 static void
1216 g_application_change_action_state (GActionGroup *action_group,
1217                                    const gchar  *action_name,
1218                                    GVariant     *value)
1219 {
1220   GApplication *application = G_APPLICATION (action_group);
1221
1222   g_return_if_fail (application->priv->actions != NULL);
1223   g_return_if_fail (application->priv->is_registered);
1224
1225   g_action_group_change_action_state (application->priv->actions,
1226                                       action_name, value);
1227 }
1228
1229 static void
1230 g_application_activate_action (GActionGroup *action_group,
1231                                const gchar  *action_name,
1232                                GVariant     *parameter)
1233 {
1234   GApplication *application = G_APPLICATION (action_group);
1235
1236   g_return_if_fail (application->priv->actions != NULL);
1237   g_return_if_fail (application->priv->is_registered);
1238
1239   g_action_group_activate_action (application->priv->actions,
1240                                   action_name, parameter);
1241 }
1242
1243 static void
1244 g_application_action_group_iface_init (GActionGroupInterface *iface)
1245 {
1246   iface->has_action = g_application_has_action;
1247   iface->list_actions = g_application_list_actions;
1248
1249   iface->get_action_enabled = g_application_get_action_enabled;
1250   iface->get_action_parameter_type = g_application_get_action_parameter_type;
1251   iface->get_action_state_type = g_application_get_action_state_type;
1252   iface->get_action_state_hint = g_application_get_action_state_hint;
1253   iface->get_action_state = g_application_get_action_state;
1254   iface->change_action_state = g_application_change_action_state;
1255   iface->activate_action = g_application_activate_action;
1256 }
1257
1258 /* Epilogue {{{1 */
1259 /* vim:set foldmethod=marker: */