1 /* GIO - GLib Input, Output and Streaming Library
3 * Copyright (C) 2006-2007 Red Hat, Inc.
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General
16 * Public License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
18 * Boston, MA 02111-1307, USA.
20 * Author: Alexander Larsson <alexl@redhat.com>
26 #include "gappinfoprivate.h"
35 * @short_description: Application information and launch contexts
37 * @see_also: #GAppInfoMonitor
39 * #GAppInfo and #GAppLaunchContext are used for describing and launching
40 * applications installed on the system.
42 * As of GLib 2.20, URIs will always be converted to POSIX paths
43 * (using g_file_get_path()) when using g_app_info_launch() even if
44 * the application requested an URI and not a POSIX path. For example
45 * for an desktop-file based application with Exec key <literal>totem
46 * %U</literal> and a single URI,
47 * <literal>sftp://foo/file.avi</literal>, then
48 * <literal>/home/user/.gvfs/sftp on foo/file.avi</literal> will be
49 * passed. This will only work if a set of suitable GIO extensions
50 * (such as gvfs 2.26 compiled with FUSE support), is available and
51 * operational; if this is not the case, the URI will be passed
52 * unmodified to the application. Some URIs, such as
53 * <literal>mailto:</literal>, of course cannot be mapped to a POSIX
54 * path (in gvfs there's no FUSE mount for it); such URIs will be
55 * passed unmodified to the application.
57 * Specifically for gvfs 2.26 and later, the POSIX URI will be mapped
58 * back to the GIO URI in the #GFile constructors (since gvfs
59 * implements the #GVfs extension point). As such, if the application
60 * needs to examine the URI, it needs to use g_file_get_uri() or
61 * similar on #GFile. In other words, an application cannot assume
62 * that the URI passed to e.g. g_file_new_for_commandline_arg() is
63 * equal to the result of g_file_get_uri(). The following snippet
70 * file = g_file_new_for_commandline_arg (uri_from_commandline);
72 * uri = g_file_get_uri (file);
73 * strcmp (uri, uri_from_commandline) == 0; // FALSE
76 * if (g_file_has_uri_scheme (file, "cdda"))
78 * // do something special with uri
80 * g_object_unref (file);
83 * This code will work when both <literal>cdda://sr0/Track
84 * 1.wav</literal> and <literal>/home/user/.gvfs/cdda on sr0/Track
85 * 1.wav</literal> is passed to the application. It should be noted
86 * that it's generally not safe for applications to rely on the format
87 * of a particular URIs. Different launcher applications (e.g. file
88 * managers) may have different ideas of what a given URI means.
92 typedef GAppInfoIface GAppInfoInterface;
93 G_DEFINE_INTERFACE (GAppInfo, g_app_info, G_TYPE_OBJECT)
96 g_app_info_default_init (GAppInfoInterface *iface)
103 * @appinfo: a #GAppInfo.
105 * Creates a duplicate of a #GAppInfo.
107 * Returns: (transfer full): a duplicate of @appinfo.
110 g_app_info_dup (GAppInfo *appinfo)
112 GAppInfoIface *iface;
114 g_return_val_if_fail (G_IS_APP_INFO (appinfo), NULL);
116 iface = G_APP_INFO_GET_IFACE (appinfo);
118 return (* iface->dup) (appinfo);
123 * @appinfo1: the first #GAppInfo.
124 * @appinfo2: the second #GAppInfo.
126 * Checks if two #GAppInfo<!-- -->s are equal.
128 * Returns: %TRUE if @appinfo1 is equal to @appinfo2. %FALSE otherwise.
131 g_app_info_equal (GAppInfo *appinfo1,
134 GAppInfoIface *iface;
136 g_return_val_if_fail (G_IS_APP_INFO (appinfo1), FALSE);
137 g_return_val_if_fail (G_IS_APP_INFO (appinfo2), FALSE);
139 if (G_TYPE_FROM_INSTANCE (appinfo1) != G_TYPE_FROM_INSTANCE (appinfo2))
142 iface = G_APP_INFO_GET_IFACE (appinfo1);
144 return (* iface->equal) (appinfo1, appinfo2);
149 * @appinfo: a #GAppInfo.
151 * Gets the ID of an application. An id is a string that
152 * identifies the application. The exact format of the id is
153 * platform dependent. For instance, on Unix this is the
154 * desktop file id from the xdg menu specification.
156 * Note that the returned ID may be %NULL, depending on how
157 * the @appinfo has been constructed.
159 * Returns: a string containing the application's ID.
162 g_app_info_get_id (GAppInfo *appinfo)
164 GAppInfoIface *iface;
166 g_return_val_if_fail (G_IS_APP_INFO (appinfo), NULL);
168 iface = G_APP_INFO_GET_IFACE (appinfo);
170 return (* iface->get_id) (appinfo);
174 * g_app_info_get_name:
175 * @appinfo: a #GAppInfo.
177 * Gets the installed name of the application.
179 * Returns: the name of the application for @appinfo.
182 g_app_info_get_name (GAppInfo *appinfo)
184 GAppInfoIface *iface;
186 g_return_val_if_fail (G_IS_APP_INFO (appinfo), NULL);
188 iface = G_APP_INFO_GET_IFACE (appinfo);
190 return (* iface->get_name) (appinfo);
194 * g_app_info_get_display_name:
195 * @appinfo: a #GAppInfo.
197 * Gets the display name of the application. The display name is often more
198 * descriptive to the user than the name itself.
200 * Returns: the display name of the application for @appinfo, or the name if
201 * no display name is available.
206 g_app_info_get_display_name (GAppInfo *appinfo)
208 GAppInfoIface *iface;
210 g_return_val_if_fail (G_IS_APP_INFO (appinfo), NULL);
212 iface = G_APP_INFO_GET_IFACE (appinfo);
214 if (iface->get_display_name == NULL)
215 return (* iface->get_name) (appinfo);
217 return (* iface->get_display_name) (appinfo);
221 * g_app_info_get_description:
222 * @appinfo: a #GAppInfo.
224 * Gets a human-readable description of an installed application.
226 * Returns: a string containing a description of the
227 * application @appinfo, or %NULL if none.
230 g_app_info_get_description (GAppInfo *appinfo)
232 GAppInfoIface *iface;
234 g_return_val_if_fail (G_IS_APP_INFO (appinfo), NULL);
236 iface = G_APP_INFO_GET_IFACE (appinfo);
238 return (* iface->get_description) (appinfo);
242 * g_app_info_get_executable:
243 * @appinfo: a #GAppInfo
245 * Gets the executable's name for the installed application.
247 * Returns: a string containing the @appinfo's application
251 g_app_info_get_executable (GAppInfo *appinfo)
253 GAppInfoIface *iface;
255 g_return_val_if_fail (G_IS_APP_INFO (appinfo), NULL);
257 iface = G_APP_INFO_GET_IFACE (appinfo);
259 return (* iface->get_executable) (appinfo);
264 * g_app_info_get_commandline:
265 * @appinfo: a #GAppInfo
267 * Gets the commandline with which the application will be
270 * Returns: a string containing the @appinfo's commandline,
271 * or %NULL if this information is not available
276 g_app_info_get_commandline (GAppInfo *appinfo)
278 GAppInfoIface *iface;
280 g_return_val_if_fail (G_IS_APP_INFO (appinfo), NULL);
282 iface = G_APP_INFO_GET_IFACE (appinfo);
284 if (iface->get_commandline)
285 return (* iface->get_commandline) (appinfo);
291 * g_app_info_set_as_default_for_type:
292 * @appinfo: a #GAppInfo.
293 * @content_type: the content type.
296 * Sets the application as the default handler for a given type.
298 * Returns: %TRUE on success, %FALSE on error.
301 g_app_info_set_as_default_for_type (GAppInfo *appinfo,
302 const char *content_type,
305 GAppInfoIface *iface;
307 g_return_val_if_fail (G_IS_APP_INFO (appinfo), FALSE);
308 g_return_val_if_fail (content_type != NULL, FALSE);
310 iface = G_APP_INFO_GET_IFACE (appinfo);
312 return (* iface->set_as_default_for_type) (appinfo, content_type, error);
316 * g_app_info_set_as_last_used_for_type:
317 * @appinfo: a #GAppInfo.
318 * @content_type: the content type.
321 * Sets the application as the last used application for a given type.
322 * This will make the application appear as first in the list returned
323 * by g_app_info_get_recommended_for_type(), regardless of the default
324 * application for that content type.
326 * Returns: %TRUE on success, %FALSE on error.
329 g_app_info_set_as_last_used_for_type (GAppInfo *appinfo,
330 const char *content_type,
333 GAppInfoIface *iface;
335 g_return_val_if_fail (G_IS_APP_INFO (appinfo), FALSE);
336 g_return_val_if_fail (content_type != NULL, FALSE);
338 iface = G_APP_INFO_GET_IFACE (appinfo);
340 return (* iface->set_as_last_used_for_type) (appinfo, content_type, error);
344 * g_app_info_set_as_default_for_extension:
345 * @appinfo: a #GAppInfo.
346 * @extension: a string containing the file extension (without the dot).
349 * Sets the application as the default handler for the given file extension.
351 * Returns: %TRUE on success, %FALSE on error.
354 g_app_info_set_as_default_for_extension (GAppInfo *appinfo,
355 const char *extension,
358 GAppInfoIface *iface;
360 g_return_val_if_fail (G_IS_APP_INFO (appinfo), FALSE);
361 g_return_val_if_fail (extension != NULL, FALSE);
363 iface = G_APP_INFO_GET_IFACE (appinfo);
365 if (iface->set_as_default_for_extension)
366 return (* iface->set_as_default_for_extension) (appinfo, extension, error);
368 g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
369 "g_app_info_set_as_default_for_extension not supported yet");
375 * g_app_info_add_supports_type:
376 * @appinfo: a #GAppInfo.
377 * @content_type: a string.
380 * Adds a content type to the application information to indicate the
381 * application is capable of opening files with the given content type.
383 * Returns: %TRUE on success, %FALSE on error.
386 g_app_info_add_supports_type (GAppInfo *appinfo,
387 const char *content_type,
390 GAppInfoIface *iface;
392 g_return_val_if_fail (G_IS_APP_INFO (appinfo), FALSE);
393 g_return_val_if_fail (content_type != NULL, FALSE);
395 iface = G_APP_INFO_GET_IFACE (appinfo);
397 if (iface->add_supports_type)
398 return (* iface->add_supports_type) (appinfo, content_type, error);
400 g_set_error_literal (error, G_IO_ERROR,
401 G_IO_ERROR_NOT_SUPPORTED,
402 "g_app_info_add_supports_type not supported yet");
409 * g_app_info_can_remove_supports_type:
410 * @appinfo: a #GAppInfo.
412 * Checks if a supported content type can be removed from an application.
414 * Returns: %TRUE if it is possible to remove supported
415 * content types from a given @appinfo, %FALSE if not.
418 g_app_info_can_remove_supports_type (GAppInfo *appinfo)
420 GAppInfoIface *iface;
422 g_return_val_if_fail (G_IS_APP_INFO (appinfo), FALSE);
424 iface = G_APP_INFO_GET_IFACE (appinfo);
426 if (iface->can_remove_supports_type)
427 return (* iface->can_remove_supports_type) (appinfo);
434 * g_app_info_remove_supports_type:
435 * @appinfo: a #GAppInfo.
436 * @content_type: a string.
439 * Removes a supported type from an application, if possible.
441 * Returns: %TRUE on success, %FALSE on error.
444 g_app_info_remove_supports_type (GAppInfo *appinfo,
445 const char *content_type,
448 GAppInfoIface *iface;
450 g_return_val_if_fail (G_IS_APP_INFO (appinfo), FALSE);
451 g_return_val_if_fail (content_type != NULL, FALSE);
453 iface = G_APP_INFO_GET_IFACE (appinfo);
455 if (iface->remove_supports_type)
456 return (* iface->remove_supports_type) (appinfo, content_type, error);
458 g_set_error_literal (error, G_IO_ERROR,
459 G_IO_ERROR_NOT_SUPPORTED,
460 "g_app_info_remove_supports_type not supported yet");
466 * g_app_info_get_supported_types:
467 * @appinfo: a #GAppInfo that can handle files
469 * Retrieves the list of content types that @app_info claims to support.
470 * If this information is not provided by the environment, this function
472 * This function does not take in consideration associations added with
473 * g_app_info_add_supports_type(), but only those exported directly by
476 * Returns: (transfer none) (array zero-terminated=1) (element-type utf8):
477 * a list of content types.
482 g_app_info_get_supported_types (GAppInfo *appinfo)
484 GAppInfoIface *iface;
486 g_return_val_if_fail (G_IS_APP_INFO (appinfo), NULL);
488 iface = G_APP_INFO_GET_IFACE (appinfo);
490 if (iface->get_supported_types)
491 return iface->get_supported_types (appinfo);
498 * g_app_info_get_icon:
499 * @appinfo: a #GAppInfo.
501 * Gets the icon for the application.
503 * Returns: (transfer none): the default #GIcon for @appinfo or %NULL
504 * if there is no default icon.
507 g_app_info_get_icon (GAppInfo *appinfo)
509 GAppInfoIface *iface;
511 g_return_val_if_fail (G_IS_APP_INFO (appinfo), NULL);
513 iface = G_APP_INFO_GET_IFACE (appinfo);
515 return (* iface->get_icon) (appinfo);
521 * @appinfo: a #GAppInfo
522 * @files: (allow-none) (element-type GFile): a #GList of #GFile objects
523 * @launch_context: (allow-none): a #GAppLaunchContext or %NULL
526 * Launches the application. Passes @files to the launched application
527 * as arguments, using the optional @launch_context to get information
528 * about the details of the launcher (like what screen it is on).
529 * On error, @error will be set accordingly.
531 * To launch the application without arguments pass a %NULL @files list.
533 * Note that even if the launch is successful the application launched
534 * can fail to start if it runs into problems during startup. There is
535 * no way to detect this.
537 * Some URIs can be changed when passed through a GFile (for instance
538 * unsupported URIs with strange formats like mailto:), so if you have
539 * a textual URI you want to pass in as argument, consider using
540 * g_app_info_launch_uris() instead.
542 * The launched application inherits the environment of the launching
543 * process, but it can be modified with g_app_launch_context_setenv() and
544 * g_app_launch_context_unsetenv().
546 * On UNIX, this function sets the <envar>GIO_LAUNCHED_DESKTOP_FILE</envar>
547 * environment variable with the path of the launched desktop file and
548 * <envar>GIO_LAUNCHED_DESKTOP_FILE_PID</envar> to the process
549 * id of the launched process. This can be used to ignore
550 * <envar>GIO_LAUNCHED_DESKTOP_FILE</envar>, should it be inherited
551 * by further processes. The <envar>DISPLAY</envar> and
552 * <envar>DESKTOP_STARTUP_ID</envar> environment variables are also
553 * set, based on information provided in @launch_context.
555 * Returns: %TRUE on successful launch, %FALSE otherwise.
558 g_app_info_launch (GAppInfo *appinfo,
560 GAppLaunchContext *launch_context,
563 GAppInfoIface *iface;
565 g_return_val_if_fail (G_IS_APP_INFO (appinfo), FALSE);
567 iface = G_APP_INFO_GET_IFACE (appinfo);
569 return (* iface->launch) (appinfo, files, launch_context, error);
574 * g_app_info_supports_uris:
575 * @appinfo: a #GAppInfo.
577 * Checks if the application supports reading files and directories from URIs.
579 * Returns: %TRUE if the @appinfo supports URIs.
582 g_app_info_supports_uris (GAppInfo *appinfo)
584 GAppInfoIface *iface;
586 g_return_val_if_fail (G_IS_APP_INFO (appinfo), FALSE);
588 iface = G_APP_INFO_GET_IFACE (appinfo);
590 return (* iface->supports_uris) (appinfo);
595 * g_app_info_supports_files:
596 * @appinfo: a #GAppInfo.
598 * Checks if the application accepts files as arguments.
600 * Returns: %TRUE if the @appinfo supports files.
603 g_app_info_supports_files (GAppInfo *appinfo)
605 GAppInfoIface *iface;
607 g_return_val_if_fail (G_IS_APP_INFO (appinfo), FALSE);
609 iface = G_APP_INFO_GET_IFACE (appinfo);
611 return (* iface->supports_files) (appinfo);
616 * g_app_info_launch_uris:
617 * @appinfo: a #GAppInfo
618 * @uris: (allow-none) (element-type utf8): a #GList containing URIs to launch.
619 * @launch_context: (allow-none): a #GAppLaunchContext or %NULL
622 * Launches the application. This passes the @uris to the launched application
623 * as arguments, using the optional @launch_context to get information
624 * about the details of the launcher (like what screen it is on).
625 * On error, @error will be set accordingly.
627 * To launch the application without arguments pass a %NULL @uris list.
629 * Note that even if the launch is successful the application launched
630 * can fail to start if it runs into problems during startup. There is
631 * no way to detect this.
633 * Returns: %TRUE on successful launch, %FALSE otherwise.
636 g_app_info_launch_uris (GAppInfo *appinfo,
638 GAppLaunchContext *launch_context,
641 GAppInfoIface *iface;
643 g_return_val_if_fail (G_IS_APP_INFO (appinfo), FALSE);
645 iface = G_APP_INFO_GET_IFACE (appinfo);
647 return (* iface->launch_uris) (appinfo, uris, launch_context, error);
652 * g_app_info_should_show:
653 * @appinfo: a #GAppInfo.
655 * Checks if the application info should be shown in menus that
656 * list available applications.
658 * Returns: %TRUE if the @appinfo should be shown, %FALSE otherwise.
661 g_app_info_should_show (GAppInfo *appinfo)
663 GAppInfoIface *iface;
665 g_return_val_if_fail (G_IS_APP_INFO (appinfo), FALSE);
667 iface = G_APP_INFO_GET_IFACE (appinfo);
669 return (* iface->should_show) (appinfo);
673 * g_app_info_launch_default_for_uri:
674 * @uri: the uri to show
675 * @launch_context: (allow-none): an optional #GAppLaunchContext.
678 * Utility function that launches the default application
679 * registered to handle the specified uri. Synchronous I/O
680 * is done on the uri to detect the type of the file if
683 * Returns: %TRUE on success, %FALSE on error.
686 g_app_info_launch_default_for_uri (const char *uri,
687 GAppLaunchContext *launch_context,
691 GAppInfo *app_info = NULL;
695 /* g_file_query_default_handler() calls
696 * g_app_info_get_default_for_uri_scheme() too, but we have to do it
697 * here anyway in case GFile can't parse @uri correctly.
699 uri_scheme = g_uri_parse_scheme (uri);
700 if (uri_scheme && uri_scheme[0] != '\0')
701 app_info = g_app_info_get_default_for_uri_scheme (uri_scheme);
708 file = g_file_new_for_uri (uri);
709 app_info = g_file_query_default_handler (file, NULL, error);
710 g_object_unref (file);
711 if (app_info == NULL)
714 /* We still use the original @uri rather than calling
715 * g_file_get_uri(), because GFile might have modified the URI
716 * in ways we don't want (eg, removing the fragment identifier
721 l.data = (char *)uri;
722 l.next = l.prev = NULL;
723 res = g_app_info_launch_uris (app_info, &l,
724 launch_context, error);
726 g_object_unref (app_info);
732 * g_app_info_can_delete:
733 * @appinfo: a #GAppInfo
735 * Obtains the information whether the #GAppInfo can be deleted.
736 * See g_app_info_delete().
738 * Returns: %TRUE if @appinfo can be deleted
743 g_app_info_can_delete (GAppInfo *appinfo)
745 GAppInfoIface *iface;
747 g_return_val_if_fail (G_IS_APP_INFO (appinfo), FALSE);
749 iface = G_APP_INFO_GET_IFACE (appinfo);
751 if (iface->can_delete)
752 return (* iface->can_delete) (appinfo);
760 * @appinfo: a #GAppInfo
762 * Tries to delete a #GAppInfo.
764 * On some platforms, there may be a difference between user-defined
765 * #GAppInfo<!-- -->s which can be deleted, and system-wide ones which
766 * cannot. See g_app_info_can_delete().
769 * Returns: %TRUE if @appinfo has been deleted
774 g_app_info_delete (GAppInfo *appinfo)
776 GAppInfoIface *iface;
778 g_return_val_if_fail (G_IS_APP_INFO (appinfo), FALSE);
780 iface = G_APP_INFO_GET_IFACE (appinfo);
782 if (iface->do_delete)
783 return (* iface->do_delete) (appinfo);
795 struct _GAppLaunchContextPrivate {
799 static guint signals[LAST_SIGNAL] = { 0 };
801 G_DEFINE_TYPE_WITH_PRIVATE (GAppLaunchContext, g_app_launch_context, G_TYPE_OBJECT)
804 * g_app_launch_context_new:
806 * Creates a new application launch context. This is not normally used,
807 * instead you instantiate a subclass of this, such as #GdkAppLaunchContext.
809 * Returns: a #GAppLaunchContext.
812 g_app_launch_context_new (void)
814 return g_object_new (G_TYPE_APP_LAUNCH_CONTEXT, NULL);
818 g_app_launch_context_finalize (GObject *object)
820 GAppLaunchContext *context = G_APP_LAUNCH_CONTEXT (object);
822 g_strfreev (context->priv->envp);
824 G_OBJECT_CLASS (g_app_launch_context_parent_class)->finalize (object);
828 g_app_launch_context_class_init (GAppLaunchContextClass *klass)
830 GObjectClass *object_class = G_OBJECT_CLASS (klass);
832 object_class->finalize = g_app_launch_context_finalize;
835 * GAppLaunchContext::launch-failed:
836 * @context: the object emitting the signal
837 * @startup_notify_id: the startup notification id for the failed launch
839 * The ::launch-failed signal is emitted when a #GAppInfo launch
840 * fails. The startup notification id is provided, so that the launcher
841 * can cancel the startup notification.
845 signals[LAUNCH_FAILED] = g_signal_new ("launch-failed",
846 G_OBJECT_CLASS_TYPE (object_class),
848 G_STRUCT_OFFSET (GAppLaunchContextClass, launch_failed),
850 G_TYPE_NONE, 1, G_TYPE_STRING);
853 * GAppLaunchContext::launched:
854 * @context: the object emitting the signal
855 * @info: the #GAppInfo that was just launched
856 * @platform_data: additional platform-specific data for this launch
858 * The ::launched signal is emitted when a #GAppInfo is successfully
859 * launched. The @platform_data is an GVariant dictionary mapping
860 * strings to variants (ie a{sv}), which contains additional,
861 * platform-specific data about this launch. On UNIX, at least the
862 * "pid" and "startup-notification-id" keys will be present.
866 signals[LAUNCHED] = g_signal_new ("launched",
867 G_OBJECT_CLASS_TYPE (object_class),
869 G_STRUCT_OFFSET (GAppLaunchContextClass, launched),
872 G_TYPE_APP_INFO, G_TYPE_VARIANT);
876 g_app_launch_context_init (GAppLaunchContext *context)
878 context->priv = g_app_launch_context_get_instance_private (context);
882 * g_app_launch_context_setenv:
883 * @context: a #GAppLaunchContext
884 * @variable: the environment variable to set
885 * @value: the value for to set the variable to.
887 * Arranges for @variable to be set to @value in the child's
888 * environment when @context is used to launch an application.
893 g_app_launch_context_setenv (GAppLaunchContext *context,
894 const char *variable,
897 if (!context->priv->envp)
898 context->priv->envp = g_get_environ ();
900 context->priv->envp =
901 g_environ_setenv (context->priv->envp, variable, value, TRUE);
905 * g_app_launch_context_unsetenv:
906 * @context: a #GAppLaunchContext
907 * @variable: the environment variable to remove
909 * Arranges for @variable to be unset in the child's environment
910 * when @context is used to launch an application.
915 g_app_launch_context_unsetenv (GAppLaunchContext *context,
916 const char *variable)
918 if (!context->priv->envp)
919 context->priv->envp = g_get_environ ();
921 context->priv->envp =
922 g_environ_unsetenv (context->priv->envp, variable);
926 * g_app_launch_context_get_environment:
927 * @context: a #GAppLaunchContext
929 * Gets the complete environment variable list to be passed to
930 * the child process when @context is used to launch an application.
931 * This is a %NULL-terminated array of strings, where each string has
932 * the form <literal>KEY=VALUE</literal>.
934 * Return value: (array zero-terminated=1) (transfer full): the
935 * child's environment
940 g_app_launch_context_get_environment (GAppLaunchContext *context)
942 if (!context->priv->envp)
943 context->priv->envp = g_get_environ ();
945 return g_strdupv (context->priv->envp);
949 * g_app_launch_context_get_display:
950 * @context: a #GAppLaunchContext
952 * @files: (element-type GFile): a #GList of #GFile objects
954 * Gets the display string for the @context. This is used to ensure new
955 * applications are started on the same display as the launching
956 * application, by setting the <envar>DISPLAY</envar> environment variable.
958 * Returns: a display string for the display.
961 g_app_launch_context_get_display (GAppLaunchContext *context,
965 GAppLaunchContextClass *class;
967 g_return_val_if_fail (G_IS_APP_LAUNCH_CONTEXT (context), NULL);
968 g_return_val_if_fail (G_IS_APP_INFO (info), NULL);
970 class = G_APP_LAUNCH_CONTEXT_GET_CLASS (context);
972 if (class->get_display == NULL)
975 return class->get_display (context, info, files);
979 * g_app_launch_context_get_startup_notify_id:
980 * @context: a #GAppLaunchContext
982 * @files: (element-type GFile): a #GList of of #GFile objects
984 * Initiates startup notification for the application and returns the
985 * <envar>DESKTOP_STARTUP_ID</envar> for the launched operation,
988 * Startup notification IDs are defined in the <ulink
989 * url="http://standards.freedesktop.org/startup-notification-spec/startup-notification-latest.txt">
990 * FreeDesktop.Org Startup Notifications standard</ulink>.
992 * Returns: a startup notification ID for the application, or %NULL if
996 g_app_launch_context_get_startup_notify_id (GAppLaunchContext *context,
1000 GAppLaunchContextClass *class;
1002 g_return_val_if_fail (G_IS_APP_LAUNCH_CONTEXT (context), NULL);
1003 g_return_val_if_fail (G_IS_APP_INFO (info), NULL);
1005 class = G_APP_LAUNCH_CONTEXT_GET_CLASS (context);
1007 if (class->get_startup_notify_id == NULL)
1010 return class->get_startup_notify_id (context, info, files);
1015 * g_app_launch_context_launch_failed:
1016 * @context: a #GAppLaunchContext.
1017 * @startup_notify_id: the startup notification id that was returned by g_app_launch_context_get_startup_notify_id().
1019 * Called when an application has failed to launch, so that it can cancel
1020 * the application startup notification started in g_app_launch_context_get_startup_notify_id().
1024 g_app_launch_context_launch_failed (GAppLaunchContext *context,
1025 const char *startup_notify_id)
1027 g_return_if_fail (G_IS_APP_LAUNCH_CONTEXT (context));
1028 g_return_if_fail (startup_notify_id != NULL);
1030 g_signal_emit (context, signals[LAUNCH_FAILED], 0, startup_notify_id);
1035 * SECTION:gappinfomonitor
1036 * @short_description: Monitor application information for changes
1038 * #GAppInfoMonitor is a very simple object used for monitoring the app
1039 * info database for changes (ie: newly installed or removed
1042 * Call g_app_info_monitor_get() to get a #GAppInfoMonitor and connect
1043 * to the "changed" signal.
1045 * In the usual case, applications should try to make note of the change
1046 * (doing things like invalidating caches) but not act on it. In
1047 * particular, applications should avoid making calls to #GAppInfo APIs
1048 * in response to the change signal, deferring these until the time that
1049 * the data is actually required. The exception to this case is when
1050 * application information is actually being displayed on the screen
1051 * (eg: during a search or when the list of all applications is shown).
1052 * The reason for this is that changes to the list of installed
1053 * applications often come in groups (like during system updates) and
1054 * rescanning the list on every change is pointless and expensive.
1062 * The only thing you can do with this is to get it via
1063 * g_app_info_monitor_get() and connect to the "changed" signal.
1068 /* We have one of each of these per main context and hand them out
1069 * according to the thread default main context at the time of the call
1070 * to g_app_info_monitor_get().
1072 * g_object_unref() is only ever called from the same context, so we
1073 * effectively have a single-threaded scenario for each GAppInfoMonitor.
1075 * We use a hashtable to cache the per-context monitor (but we do not
1076 * hold a ref). During finalize, we remove it. This is possible
1077 * because we don't have to worry about the usual races due to the
1078 * single-threaded nature of each object.
1080 * We keep a global list of all contexts that have a monitor for them,
1081 * which we have to access under a lock. When we dispatch the events to
1082 * be handled in each context, we don't pass the monitor, but the
1085 * We dispatch from the GLib worker context, so if we passed the
1086 * monitor, we would need to take a ref on it (in case it was destroyed
1087 * in its own thread meanwhile). The monitor holds a ref on a context
1088 * and the dispatch would mean that the context would hold a ref on the
1089 * monitor. If someone stopped iterating the context at just this
1090 * moment both the context and monitor would leak.
1092 * Instead, we dispatch the context to itself. We don't hold a ref.
1093 * There is the danger that the context will be destroyed during the
1094 * dispatch, but if that is the case then we just won't receive our
1097 * When the dispatch occurs we just lookup the monitor in the hashtable,
1098 * by context. We can now add and remove refs, since the context will
1099 * have been acquired.
1102 typedef struct _GAppInfoMonitorClass GAppInfoMonitorClass;
1104 struct _GAppInfoMonitor
1106 GObject parent_instance;
1107 GMainContext *context;
1110 struct _GAppInfoMonitorClass
1112 GObjectClass parent_class;
1115 static GHashTable *g_app_info_monitors;
1116 static GMutex g_app_info_monitor_lock;
1117 static guint g_app_info_monitor_changed_signal;
1119 G_DEFINE_TYPE (GAppInfoMonitor, g_app_info_monitor, G_TYPE_OBJECT)
1122 g_app_info_monitor_finalize (GObject *object)
1124 GAppInfoMonitor *monitor = G_APP_INFO_MONITOR (object);
1126 g_mutex_lock (&g_app_info_monitor_lock);
1127 g_hash_table_remove (g_app_info_monitors, monitor->context);
1128 g_mutex_unlock (&g_app_info_monitor_lock);
1130 G_OBJECT_CLASS (g_app_info_monitor_parent_class)->finalize (object);
1134 g_app_info_monitor_init (GAppInfoMonitor *monitor)
1139 g_app_info_monitor_class_init (GAppInfoMonitorClass *class)
1141 GObjectClass *object_class = G_OBJECT_CLASS (class);
1143 g_app_info_monitor_changed_signal = g_signal_new ("changed", G_TYPE_APP_INFO_MONITOR, G_SIGNAL_RUN_FIRST,
1144 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
1146 object_class->finalize = g_app_info_monitor_finalize;
1150 * g_app_info_monitor_get:
1152 * Gets the #GAppInfoMonitor for the current thread-default main
1155 * The #GAppInfoMonitor will emit a "changed" signal in the
1156 * thread-default main context whenever the list of installed
1157 * applications (as reported by g_app_info_get_all()) may have changed.
1159 * You must only call g_object_unref() on the return value from under
1160 * the same main context as you created it.
1162 * Returns: (transfer full): a reference to a #GAppInfoMonitor
1167 g_app_info_monitor_get (void)
1169 GAppInfoMonitor *monitor;
1170 GMainContext *context;
1172 context = g_main_context_get_thread_default ();
1174 context = g_main_context_default ();
1176 g_return_val_if_fail (g_main_context_acquire (context), NULL);
1178 g_mutex_lock (&g_app_info_monitor_lock);
1179 if (!g_app_info_monitors)
1180 g_app_info_monitors = g_hash_table_new (NULL, NULL);
1182 monitor = g_hash_table_lookup (g_app_info_monitors, context);
1183 g_mutex_unlock (&g_app_info_monitor_lock);
1187 monitor = g_object_new (G_TYPE_APP_INFO_MONITOR, NULL);
1188 monitor->context = g_main_context_ref (context);
1190 g_mutex_lock (&g_app_info_monitor_lock);
1191 g_hash_table_insert (g_app_info_monitors, context, monitor);
1192 g_mutex_unlock (&g_app_info_monitor_lock);
1195 g_object_ref (monitor);
1197 g_main_context_release (context);
1203 g_app_info_monitor_emit (gpointer user_data)
1205 GMainContext *context = user_data;
1206 GAppInfoMonitor *monitor;
1208 g_mutex_lock (&g_app_info_monitor_lock);
1209 monitor = g_hash_table_lookup (g_app_info_monitors, context);
1210 g_mutex_unlock (&g_app_info_monitor_lock);
1212 /* It is possible that the monitor was already destroyed by the time
1213 * we get here, so make sure it's not NULL.
1215 if (monitor != NULL)
1217 /* We don't have to worry about another thread disposing the
1218 * monitor but we do have to worry about the possibility that one
1219 * of the attached handlers may do so.
1221 * Take a ref so that the monitor doesn't disappear in the middle
1224 g_object_ref (monitor);
1225 g_signal_emit (monitor, g_app_info_monitor_changed_signal, 0);
1226 g_object_unref (monitor);
1233 g_app_info_monitor_fire (void)
1235 GHashTableIter iter;
1238 g_mutex_lock (&g_app_info_monitor_lock);
1240 if (g_app_info_monitors)
1242 g_hash_table_iter_init (&iter, g_app_info_monitors);
1243 while (g_hash_table_iter_next (&iter, &context, NULL))
1247 idle = g_idle_source_new ();
1248 g_source_set_callback (idle, g_app_info_monitor_emit, context, NULL);
1249 g_source_attach (idle, context);
1250 g_source_unref (idle);
1254 g_mutex_unlock (&g_app_info_monitor_lock);