new GApplication 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 "gapplicationimpl.h"
26
27 #include "gioenumtypes.h"
28 #include "gio-marshal.h"
29 #include "gioenums.h"
30 #include "gfile.h"
31
32 #include <string.h>
33
34 struct _GApplicationPrivate
35 {
36   GApplicationFlags  flags;
37   gchar             *id;
38
39   GHashTable        *actions; /* string -> GApplicationAction */
40   GMainLoop         *mainloop;
41
42   guint              inactivity_timeout_id;
43   guint              inactivity_timeout;
44   guint              use_count;
45
46   guint              is_registered : 1;
47   guint              is_remote : 1;
48
49   GApplicationImpl  *impl;
50 };
51
52 enum
53 {
54   PROP_NONE,
55   PROP_APPLICATION_ID,
56   PROP_FLAGS,
57   PROP_IS_REGISTERED,
58   PROP_IS_REMOTE,
59   PROP_INACTIVITY_TIMEOUT
60 };
61
62 enum
63 {
64   SIGNAL_STARTUP,
65   SIGNAL_ACTIVATE,
66   SIGNAL_OPEN,
67   SIGNAL_ACTION,
68   SIGNAL_COMMAND_LINE,
69   NR_SIGNALS
70 };
71
72 static guint g_application_signals[NR_SIGNALS];
73
74 G_DEFINE_TYPE (GApplication, g_application, G_TYPE_OBJECT)
75
76 /* vfunc defaults {{{1 */
77 static void
78 g_application_real_before_emit (GApplication *application,
79                                 GVariant     *platform_data)
80 {
81 }
82
83 static void
84 g_application_real_after_emit (GApplication *application,
85                                GVariant     *platform_data)
86 {
87 }
88
89 static void
90 g_application_real_startup (GApplication *application)
91 {
92 }
93
94 static void
95 g_application_real_activate (GApplication *application)
96 {
97   if (!g_signal_has_handler_pending (application,
98                                      g_application_signals[SIGNAL_ACTIVATE],
99                                      0, TRUE))
100     {
101       static gboolean warned;
102
103       if (warned)
104         return;
105
106       g_warning ("Your application does not implement "
107                  "g_application_activate() and has no handlers connected "
108                  "to the 'activate' signal.  It should do one of these.");
109       warned = TRUE;
110     }
111 }
112
113 static void
114 g_application_real_open (GApplication  *application,
115                          GFile        **files,
116                          gint           n_files,
117                          const gchar   *hint)
118 {
119   if (!g_signal_has_handler_pending (application,
120                                      g_application_signals[SIGNAL_OPEN],
121                                      0, TRUE))
122     {
123       static gboolean warned;
124
125       if (warned)
126         return;
127
128       g_warning ("Your application claims to support opening files "
129                  "but does not implement g_application_open() and has no "
130                  "handlers connected to the 'open' signal.");
131       warned = TRUE;
132     }
133 }
134
135 static gboolean
136 g_application_real_local_command_line (GApplication  *application,
137                                        GVariant     **arguments,
138                                        int           *exit_status)
139 {
140   if (0)
141     return FALSE;
142
143   else
144     {
145       GError *error = NULL;
146       gint n_args;
147
148       if (!g_application_register (application, NULL, &error))
149         {
150           g_critical ("%s", error->message);
151           g_error_free (error);
152           *exit_status = 1;
153           return TRUE;
154         }
155
156       n_args = g_variant_n_children (*arguments);
157
158       if (application->priv->flags & G_APPLICATION_FLAGS_IS_SERVICE)
159         {
160           if (n_args > 1)
161             {
162               g_printerr ("GApplication service mode takes no arguments.\n");
163               application->priv->flags &= ~G_APPLICATION_FLAGS_IS_SERVICE;
164             }
165
166           return TRUE;
167         }
168
169       if (n_args <= 1)
170         {
171           g_application_activate (application);
172           *exit_status = 0;
173         }
174
175       else
176         {
177           if (~application->priv->flags & G_APPLICATION_FLAGS_HANDLES_OPEN)
178             {
179               g_critical ("This application can not open files.");
180               *exit_status = 1;
181             }
182           else
183             {
184               GFile **files;
185               gint n_files;
186               gint i;
187
188               n_files = n_args - 1;
189               files = g_new (GFile *, n_files);
190
191               for (i = 0; i < n_files; i++)
192                 {
193                   const gchar *arg;
194
195                   g_variant_get_child (*arguments, i + 1, "^&ay", &arg);
196                   files[i] = g_file_new_for_commandline_arg (arg);
197                 }
198
199               g_application_open (application, files, n_files, "");
200
201               for (i = 0; i < n_files; i++)
202                 g_object_unref (files[i]);
203               g_free (files);
204
205               *exit_status = 0;
206             }
207         }
208
209       return TRUE;
210     }
211 }
212
213 static void
214 g_application_real_add_platform_data (GApplication    *application,
215                                       GVariantBuilder *builder)
216 {
217 }
218
219 static void
220 g_application_real_quit_mainloop (GApplication *application)
221 {
222   if (application->priv->mainloop != NULL)
223     g_main_loop_quit (application->priv->mainloop);
224 }
225
226 static void
227 g_application_real_run_mainloop (GApplication *application)
228 {
229   if (application->priv->mainloop == NULL)
230     application->priv->mainloop = g_main_loop_new (NULL, FALSE);
231
232   g_main_loop_run (application->priv->mainloop);
233 }
234
235 /* GObject implementation stuff {{{1 */
236 static void
237 g_application_set_property (GObject *object, guint prop_id,
238                             const GValue *value, GParamSpec *pspec)
239 {
240   GApplication *application = G_APPLICATION (object);
241
242   switch (prop_id)
243     {
244     case PROP_APPLICATION_ID:
245       g_application_set_application_id (application,
246                                         g_value_get_string (value));
247       break;
248
249     case PROP_FLAGS:
250       g_application_set_flags (application, g_value_get_flags (value));
251       break;
252
253     case PROP_INACTIVITY_TIMEOUT:
254       g_application_set_inactivity_timeout (application,
255                                             g_value_get_uint (value));
256       break;
257
258     default:
259       g_assert_not_reached ();
260     }
261 }
262
263 static void
264 g_application_get_property (GObject *object, guint prop_id,
265                             GValue *value, GParamSpec *pspec)
266 {
267   GApplication *application = G_APPLICATION (object);
268
269   switch (prop_id)
270     {
271     case PROP_APPLICATION_ID:
272       g_value_set_string (value,
273                           g_application_get_application_id (application));
274       break;
275
276     case PROP_FLAGS:
277       g_value_set_flags (value,
278                          g_application_get_flags (application));
279       break;
280
281     case PROP_IS_REGISTERED:
282       g_value_set_boolean (value,
283                            g_application_get_is_registered (application));
284       break;
285
286     case PROP_IS_REMOTE:
287       g_value_set_boolean (value,
288                            g_application_get_is_remote (application));
289       break;
290
291     case PROP_INACTIVITY_TIMEOUT:
292       g_value_set_uint (value,
293                         g_application_get_inactivity_timeout (application));
294       break;
295
296     default:
297       g_assert_not_reached ();
298     }
299 }
300
301 static void
302 g_application_constructed (GObject *object)
303 {
304   GApplication *application = G_APPLICATION (object);
305
306   g_assert (application->priv->id != NULL);
307 }
308
309 static void
310 g_application_finalize (GObject *object)
311 {
312   GApplication *application = G_APPLICATION (object);
313
314   if (application->priv->impl)
315     g_application_impl_destroy (application->priv->impl);
316   g_free (application->priv->id);
317
318   if (application->priv->mainloop)
319     g_main_loop_unref (application->priv->mainloop);
320
321   G_OBJECT_CLASS (g_application_parent_class)
322     ->finalize (object);
323 }
324
325 static void
326 g_application_init (GApplication *application)
327 {
328   application->priv = G_TYPE_INSTANCE_GET_PRIVATE (application,
329                                                    G_TYPE_APPLICATION,
330                                                    GApplicationPrivate);
331 }
332
333 static void
334 g_application_class_init (GApplicationClass *class)
335 {
336   GObjectClass *object_class = G_OBJECT_CLASS (class);
337
338   object_class->constructed = g_application_constructed;
339   object_class->finalize = g_application_finalize;
340   object_class->get_property = g_application_get_property;
341   object_class->set_property = g_application_set_property;
342
343   class->before_emit = g_application_real_before_emit;
344   class->after_emit = g_application_real_after_emit;
345   class->startup = g_application_real_startup;
346   class->activate = g_application_real_activate;
347   class->open = g_application_real_open;
348   class->local_command_line = g_application_real_local_command_line;
349   class->add_platform_data = g_application_real_add_platform_data;
350   class->quit_mainloop = g_application_real_quit_mainloop;
351   class->run_mainloop = g_application_real_run_mainloop;
352
353   g_object_class_install_property (object_class, PROP_APPLICATION_ID,
354     g_param_spec_string ("application-id", "application identifier",
355                          "Unique identifier for the application",
356                          NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT |
357                          G_PARAM_STATIC_STRINGS));
358
359   g_object_class_install_property (object_class, PROP_FLAGS,
360     g_param_spec_flags ("flags", "application flags",
361                         "Flags specifying the behaviour of the application",
362                          G_TYPE_APPLICATION_FLAGS, G_APPLICATION_FLAGS_NONE,
363                          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
364
365   g_object_class_install_property (object_class, PROP_IS_REGISTERED,
366     g_param_spec_boolean ("is-registered", "is registered",
367                           "If g_application_register() has been called",
368                           FALSE, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
369
370   g_object_class_install_property (object_class, PROP_IS_REMOTE,
371     g_param_spec_boolean ("is-remote", "is remote",
372                           "If this application instance is remote",
373                           FALSE, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
374
375
376   g_application_signals[SIGNAL_STARTUP] =
377     g_signal_new ("startup", G_TYPE_APPLICATION, G_SIGNAL_RUN_LAST,
378                   G_STRUCT_OFFSET (GApplicationClass, startup),
379                   NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
380
381   g_application_signals[SIGNAL_ACTIVATE] =
382     g_signal_new ("activate", G_TYPE_APPLICATION, G_SIGNAL_RUN_LAST,
383                   G_STRUCT_OFFSET (GApplicationClass, activate),
384                   NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
385
386   g_application_signals[SIGNAL_OPEN] =
387     g_signal_new ("open", G_TYPE_APPLICATION, G_SIGNAL_RUN_LAST,
388                   G_STRUCT_OFFSET (GApplicationClass, open),
389                   NULL, NULL, _gio_marshal_VOID__POINTER_INT_STRING,
390                   G_TYPE_NONE, 3, G_TYPE_POINTER, G_TYPE_INT, G_TYPE_STRING);
391
392   g_type_class_add_private (class, sizeof (GApplicationPrivate));
393 }
394
395 static GVariant *
396 get_platform_data (GApplication *application)
397 {
398   GVariantBuilder *builder;
399   GVariant *result;
400
401   builder = g_variant_builder_new (G_VARIANT_TYPE ("a{sv}"));
402
403   {
404     gchar *cwd = g_get_current_dir ();
405     g_variant_builder_add (builder, "{sv}", "cwd",
406                            g_variant_new_bytestring (cwd));
407     g_free (cwd);
408   }
409
410   G_APPLICATION_GET_CLASS (application)->
411     add_platform_data (application, builder);
412
413   result = g_variant_builder_end (builder);
414   g_variant_builder_unref (builder);
415
416   return result;
417 }
418
419 /* Application ID validity {{{1 */
420
421 /**
422  * g_application_id_is_valid:
423  * @application_id: a potential application identifier
424  * @returns: %TRUE if @application_id is valid
425  *
426  * Checks if @application_id is a valid application ID.  A valid ID is
427  * required for calls to g_application_new() and
428  * g_application_set_application_id().
429  **/
430 gboolean
431 g_application_id_is_valid (const gchar *application_id)
432 {
433   gboolean allow_dot;
434
435   if (strlen (application_id) > 255)
436     return FALSE;
437
438   if (!g_ascii_isalpha (*application_id))
439     return FALSE;
440
441   application_id++;
442   allow_dot = FALSE;
443   for (; *application_id; application_id++)
444     {
445       if (g_ascii_isalnum (*application_id) ||
446           (*application_id == '-') ||
447           (*application_id == '_'))
448         allow_dot = TRUE;
449       else if (allow_dot && *application_id == '.')
450         allow_dot = FALSE;
451       else
452         return FALSE;
453     }
454
455   return TRUE;
456 }
457
458 /* Public Constructor {{{1 */
459 /**
460  * g_application_new:
461  * @application_id: the application id
462  * @flags: the application flags
463  * @returns: a new #GApplication instance
464  *
465  * Creates a new #GApplication instance.
466  *
467  * This function calls g_type_init() for you.
468  *
469  * The application id must be valid.  See g_application_id_is_valid().
470  **/
471 GApplication *
472 g_application_new (const gchar       *application_id,
473                    GApplicationFlags  flags)
474 {
475   g_return_val_if_fail (g_application_id_is_valid (application_id), NULL);
476
477   g_type_init ();
478
479   return g_object_new (G_TYPE_APPLICATION,
480                        "application-id", application_id,
481                        "flags", flags,
482                        NULL);
483 }
484
485 /* Simple get/set: application id, flags, inactivity timeout {{{1 */
486 /**
487  * g_application_get_application_id:
488  * @application: a #GApplication
489  * @returns: the identifier for @application, owned by @application
490  *
491  * Gets the unique identifier for @application.
492  *
493  * Since: 2.28
494  **/
495 const gchar *
496 g_application_get_application_id (GApplication *application)
497 {
498   g_return_val_if_fail (G_IS_APPLICATION (application), NULL);
499
500   return application->priv->id;
501 }
502
503 /**
504  * g_application_set_application_id:
505  * @application: a #GApplication
506  * @application_id: the identifier for @application
507  *
508  * Sets the unique identifier for @application.
509  *
510  * The application id can only be modified if @application has not yet
511  * been registered.
512  *
513  * The application id must be valid.  See g_application_id_is_valid().
514  *
515  * Since: 2.28
516  **/
517 void
518 g_application_set_application_id (GApplication *application,
519                                   const gchar  *application_id)
520 {
521   g_return_if_fail (G_IS_APPLICATION (application));
522
523   if (g_strcmp0 (application->priv->id, application_id) != 0)
524     {
525       g_return_if_fail (g_application_id_is_valid (application_id));
526       g_return_if_fail (!application->priv->is_registered);
527
528       g_free (application->priv->id);
529       application->priv->id = g_strdup (application_id);
530
531       g_object_notify (G_OBJECT (application), "application-id");
532     }
533 }
534
535 /**
536  * g_application_get_flags:
537  * @application: a #GApplication
538  * @returns: the flags for @application
539  *
540  * Gets the flags for @application.
541  *
542  * See #GApplicationFlags.
543  *
544  * Since: 2.28
545  **/
546 GApplicationFlags
547 g_application_get_flags (GApplication *application)
548 {
549   g_return_val_if_fail (G_IS_APPLICATION (application), 0);
550
551   return application->priv->flags;
552 }
553
554 /**
555  * g_application_set_flags:
556  * @application: a #GApplication
557  * @flags: the flags for @application
558  *
559  * Sets the flags for @application.
560  *
561  * The flags can only be modified if @application has not yet been
562  * registered.
563  *
564  * See #GApplicationFlags.
565  *
566  * Since: 2.28
567  **/
568 void
569 g_application_set_flags (GApplication      *application,
570                          GApplicationFlags  flags)
571 {
572   g_return_if_fail (G_IS_APPLICATION (application));
573
574   if (application->priv->flags != flags)
575     {
576       g_return_if_fail (!application->priv->is_registered);
577
578       application->priv->flags = flags;
579
580       g_object_notify (G_OBJECT (application), "flags");
581     }
582 }
583
584 /**
585  * g_application_get_inactivity_timeout:
586  * @application: a #GApplication
587  *
588  * Gets the current inactivity timeout for the application.
589  *
590  * This is the amount of time (in milliseconds) after the last call to
591  * g_application_release() before the application stops running.
592  *
593  * Returns: the timeout, in milliseconds
594  *
595  * Since: 2.28
596  **/
597 guint
598 g_application_get_inactivity_timeout (GApplication *application)
599 {
600   g_return_val_if_fail (G_IS_APPLICATION (application), 0);
601
602   return application->priv->inactivity_timeout;
603 }
604
605 /**
606  * g_application_set_inactivity_timeout:
607  * @application: a #GApplication
608  * @inactivity_timeout: the timeout, in milliseconds
609  *
610  * Sets the current inactivity timeout for the application.
611  *
612  * This is the amount of time (in milliseconds) after the last call to
613  * g_application_release() before the application stops running.
614  *
615  * This call has no side effects of its own.  The value set here is only
616  * used for next time g_application_release() drops the use count to
617  * zero.  Any timeouts currently in progress are not impacted.
618  *
619  * Returns: the timeout, in milliseconds
620  *
621  * Since: 2.28
622  **/
623 void
624 g_application_set_inactivity_timeout (GApplication *application,
625                                       guint         inactivity_timeout)
626 {
627   g_return_if_fail (G_IS_APPLICATION (application));
628
629   if (application->priv->inactivity_timeout != inactivity_timeout)
630     {
631       application->priv->inactivity_timeout = inactivity_timeout;
632
633       g_object_notify (G_OBJECT (application), "inactivity-timeout");
634     }
635 }
636 /* Read-only property getters (is registered, is remote) {{{1 */
637 /**
638  * g_application_get_is_registered:
639  * @application: a #GApplication
640  * @returns: %TRUE if @application is registered
641  *
642  * Checks if @application is registered.
643  *
644  * An application is registered if g_application_register() has been
645  * successfully called.
646  *
647  * Since: 2.28
648  **/
649 gboolean
650 g_application_get_is_registered (GApplication *application)
651 {
652   g_return_val_if_fail (G_IS_APPLICATION (application), FALSE);
653
654   return application->priv->is_registered;
655 }
656
657 /**
658  * g_application_get_is_remote:
659  * @application: a #GApplication
660  * @returns: %TRUE if @application is remote
661  *
662  * Checks if @application is remote.
663  *
664  * If @application is remote then it means that another instance of
665  * application already exists (the 'primary' instance).  Calls to
666  * perform actions on @application will result in the actions being
667  * performed by the primary instance.
668  *
669  * The value of this property can not be accessed before
670  * g_application_register() has been called.  See
671  * g_application_get_is_registered().
672  *
673  * Since: 2.28
674  **/
675 gboolean
676 g_application_get_is_remote (GApplication *application)
677 {
678   g_return_val_if_fail (G_IS_APPLICATION (application), FALSE);
679   g_return_val_if_fail (application->priv->is_registered, FALSE);
680
681   return application->priv->is_remote;
682 }
683
684 /* Register {{{1 */
685 /**
686  * g_application_register:
687  * @application: a #GApplication
688  * @cancellable: a #GCancellable, or %NULL
689  * @error: a pointer to a NULL #GError, or %NULL
690  * @returns: %TRUE if registration succeeded
691  *
692  * Attempts registration of the application.
693  *
694  * This is the point at which the application discovers if it is the
695  * primary instance or merely acting as a remote for an already-existing
696  * primary instance.
697  *
698  * If the application has already been registered then %TRUE is
699  * returned with no work performed.
700  *
701  * The startup() virtual function is invoked if registration succeeds
702  * and @application is the primary instance.
703  *
704  * In the event of an error (such as @cancellable being cancelled, or a
705  * failure to connect to the session bus), %FALSE is returned and @error
706  * is set appropriately.
707  *
708  * Note: the return value of this function is not an indicator that this
709  * instance is or is not the primary instance of the application.  See
710  * g_application_get_is_remote() for that.
711  *
712  * Since: 2.28
713  **/
714 gboolean
715 g_application_register (GApplication  *application,
716                         GCancellable  *cancellable,
717                         GError       **error)
718 {
719   g_return_val_if_fail (G_IS_APPLICATION (application), FALSE);
720
721   if (!application->priv->is_registered)
722     {
723       gboolean is_remote;
724       gboolean try;
725
726       /* don't try to be the primary instance if
727        * G_APPLICATION_FLAGS_IS_LAUNCHER was specified.
728        */
729       try = !(application->priv->flags & G_APPLICATION_FLAGS_IS_LAUNCHER);
730
731       application->priv->impl =
732         g_application_impl_register (application, application->priv->id,
733                                      application->priv->flags,
734                                      &is_remote, cancellable, error);
735
736       if (application->priv->impl == NULL)
737         return FALSE;
738
739       application->priv->is_remote = is_remote;
740       application->priv->is_registered = TRUE;
741
742       g_object_notify (G_OBJECT (application), "is-registered");
743
744       if (!is_remote)
745         g_signal_emit (application, g_application_signals[SIGNAL_STARTUP], 0);
746     }
747
748   return TRUE;
749 }
750
751 /* Hold/release {{{1 */
752 /**
753  * g_application_hold:
754  * @application: a #GApplication
755  *
756  * Increases the use count of @application.
757  *
758  * Use this function to indicate that the application has a reason to
759  * continue to run.  For example, g_application_hold() is called by Gtk
760  * when a toplevel window is on the screen.
761  *
762  * To cancel the hold, call g_application_release().
763  **/
764 void
765 g_application_hold (GApplication *application)
766 {
767   if (application->priv->inactivity_timeout_id)
768     {
769       g_source_remove (application->priv->inactivity_timeout_id);
770       application->priv->inactivity_timeout_id = 0;
771     }
772
773   application->priv->use_count++;
774 }
775
776 static gboolean
777 inactivity_timeout_expired (gpointer data)
778 {
779   GApplication *application = G_APPLICATION (data);
780
781   G_APPLICATION_GET_CLASS (application)
782     ->quit_mainloop (application);
783
784   return FALSE;
785 }
786
787
788 /**
789  * g_application_release:
790  * @application: a #GApplication
791  *
792  * Decrease the use count of @application.
793  *
794  * When the use count reaches zero, the application will stop running.
795  *
796  * Never call this function except to cancel the effect of a previous
797  * call to g_application_hold().
798  **/
799 void
800 g_application_release (GApplication *application)
801 {
802   application->priv->use_count--;
803
804   if (application->priv->use_count == 0)
805     {
806       if (application->priv->inactivity_timeout)
807         application->priv->inactivity_timeout_id =
808           g_timeout_add (application->priv->inactivity_timeout,
809                          inactivity_timeout_expired, application);
810
811       else
812         G_APPLICATION_GET_CLASS (application)
813           ->quit_mainloop (application);
814     }
815 }
816
817 /* Activate, Open {{{1 */
818 /**
819  * g_application_activate:
820  * @application: a #GApplication
821  *
822  * Activates the application.
823  *
824  * In essence, this results in the activate() virtual function being
825  * invoked in the primary instance.
826  *
827  * The application must be registered before calling this function.
828  *
829  * Since: 2.28
830  **/
831 void
832 g_application_activate (GApplication *application)
833 {
834   g_return_if_fail (G_IS_APPLICATION (application));
835   g_return_if_fail (application->priv->is_registered);
836
837   if (application->priv->is_remote)
838     g_application_impl_activate (application->priv->impl,
839                                  get_platform_data (application));
840
841   else
842     g_signal_emit (application, g_application_signals[SIGNAL_ACTIVATE], 0);
843 }
844
845 /**
846  * g_application_open:
847  * @application: a #GApplication
848  * @files: an array of #GFile<!-- -->s to open
849  * @n_files: the length of the @files array
850  * @hint: a hint (or ""), but never %NULL
851  *
852  * Opens the given files.
853  *
854  * In essence, this results in the open() virtual function being invoked
855  * in the primary instance.
856  *
857  * @n_files must be greater than zero.
858  *
859  * @hint is simply passed through to the open() virtual function.  It is
860  * intended to be used by applications that have multiple modes for
861  * opening files (eg: "view" vs "edit", etc).  Unless you have a need
862  * for this functionality, you should use "".
863  *
864  * The application must be registered before calling this function and
865  * it must have the %G_APPLICATION_FLAGS_CAN_OPEN flag set.  The open()
866  * virtual function should also be implemented in order for anything
867  * meaningful to happen.
868  *
869  * Since: 2.28
870  **/
871 void
872 g_application_open (GApplication  *application,
873                     GFile        **files,
874                     gint           n_files,
875                     const gchar   *hint)
876 {
877   g_return_if_fail (G_IS_APPLICATION (application));
878   g_return_if_fail (application->priv->flags &
879                     G_APPLICATION_FLAGS_HANDLES_OPEN);
880   g_return_if_fail (application->priv->is_registered);
881
882   if (application->priv->is_remote)
883     g_application_impl_open (application->priv->impl,
884                              files, n_files, hint,
885                              get_platform_data (application));
886
887   else
888     g_signal_emit (application, g_application_signals[SIGNAL_OPEN],
889                    0, files, n_files, hint);
890 }
891
892 /* Run {{{1 */
893 /**
894  * g_application_run:
895  * @application: a #GApplication
896  * @argc: the argc from main()
897  * @argv: the argv from main()
898  * @returns: the exit status
899  *
900  * Runs the application.
901  *
902  * This function is intended to be run from main() and its return value
903  * is intended to be returned by main().
904  *
905  * First, the handle_command_line() virtual function is invoked.  This
906  * function always runs on the local instance.  If that function returns
907  * %FALSE then the application is registered and the command_line()
908  * virtual function is invoked in the primary instance (which may or may
909  * not be this instance).
910  *
911  * If the application has the %G_APPLICATION_FLAGS_REMOTE_COMMAND_LINE
912  * flag set then the default implementation of handle_command_line()
913  * always returns %FALSE immediately, resulting in the commandline
914  * always being handled in the primary instance.
915  *
916  * Otherwise, the default implementation of handle_command_line() tries
917  * to do a couple of things that are probably reasoanble for most
918  * applications.  First, g_application_register() is called to attempt
919  * to register the application.  If that works, then the command line
920  * arguments are inspected.  If no commandline arguments are given, then
921  * g_application_activate() is called.  If commandline arguments are
922  * given and the %G_APPLICATION_FLAGS_CAN_OPEN flags is set then they
923  * are assumed to be filenames and g_application_open() is called.
924  *
925  * If you are interested in doing more complicated local handling of the
926  * commandline then you should override handle_command_line().
927  *
928  * If, after the above is done, the use count of the application is zero
929  * then the exit status is returned immediately.  If the use count is
930  * non-zero then the mainloop is run until the use count falls to zero,
931  * at which point 0 is returned.
932  *
933  * Since: 2.28
934  **/
935 int
936 g_application_run (GApplication  *application,
937                    int            argc,
938                    char         **argv)
939 {
940   g_return_val_if_fail (G_IS_APPLICATION (application), 1);
941   g_return_val_if_fail (argc == 0 || argv != NULL, 1);
942
943   return g_application_run_with_arguments (application,
944     g_variant_new_bytestring_array ((const gchar **) argv, argc));
945 }
946
947 /**
948  * g_application_run_with_arguments:
949  * @application: a #GApplication
950  * @arguments: a bytestring array #GVariant
951  * @returns: the exit status
952  *
953  * This is a bindings-friendly version of g_application_run().
954  *
955  * This function will consume @arguments if it is floating.
956  **/
957 int
958 g_application_run_with_arguments (GApplication *application,
959                                   GVariant     *arguments)
960 {
961   int status;
962
963   g_return_val_if_fail (G_IS_APPLICATION (application), 1);
964   g_return_val_if_fail (G_IS_APPLICATION (application), 1);
965
966   g_variant_ref_sink (arguments);
967
968   if (g_get_prgname () == NULL && g_variant_n_children (arguments))
969     {
970       const gchar *argv0;
971       gchar *prgname;
972
973       g_variant_get_child (arguments, 0, "^&ay", &argv0);
974       prgname = g_path_get_basename (argv0);
975       g_set_prgname (prgname);
976       g_free (prgname);
977     }
978
979   if (!G_APPLICATION_GET_CLASS (application)
980         ->local_command_line (application, &arguments, &status))
981     {
982       g_assert_not_reached ();
983     }
984
985   g_variant_unref (arguments);
986
987   if (application->priv->use_count ||
988       application->priv->flags & G_APPLICATION_FLAGS_IS_SERVICE)
989     {
990       if (!application->priv->use_count)
991         application->priv->inactivity_timeout_id =
992           g_timeout_add (10000, inactivity_timeout_expired, application);
993
994
995       G_APPLICATION_GET_CLASS (application)
996         ->run_mainloop (application);
997       status = 0;
998     }
999
1000   if (application->priv->impl)
1001     g_application_impl_flush (application->priv->impl);
1002
1003   return status;
1004 }
1005
1006 /* Epilogue {{{1 */
1007 /* vim:set foldmethod=marker: */