static void egg_set_desktop_file_internal (const char *desktop_file_path, gboolean set_defaults) { GError *error = NULL; G_LOCK (egg_desktop_file); if (egg_desktop_file) egg_desktop_file_free (egg_desktop_file); egg_desktop_file = egg_desktop_file_new (desktop_file_path, &error); if (error) { g_warning ("Could not load desktop file '%s': %s", desktop_file_path, error->message); g_error_free (error); } if (set_defaults && egg_desktop_file != NULL) { /* Set localized application name and default window icon */ if (egg_desktop_file->name) g_set_application_name (egg_desktop_file->name); if (egg_desktop_file->icon) { if (g_path_is_absolute (egg_desktop_file->icon)) gtk_window_set_default_icon_from_file (egg_desktop_file->icon, NULL); else gtk_window_set_default_icon_name (egg_desktop_file->icon); } } G_UNLOCK (egg_desktop_file); }
/** * egg_desktop_file_launch: * @desktop_file: an #EggDesktopFile * @documents: a list of URIs or paths to documents to open * @error: error pointer * @...: additional options * * Launches @desktop_file with the given arguments. Additional options * can be specified as follows: * * %EGG_DESKTOP_FILE_LAUNCH_CLEARENV: (no arguments) * clears the environment in the child process * %EGG_DESKTOP_FILE_LAUNCH_PUTENV: (char **variables) * adds the NAME=VALUE strings in the given %NULL-terminated * array to the child process's environment * %EGG_DESKTOP_FILE_LAUNCH_SCREEN: (GdkScreen *screen) * causes the application to be launched on the given screen * %EGG_DESKTOP_FILE_LAUNCH_WORKSPACE: (int workspace) * causes the application to be launched on the given workspace * %EGG_DESKTOP_FILE_LAUNCH_DIRECTORY: (char *dir) * causes the application to be launched in the given directory * %EGG_DESKTOP_FILE_LAUNCH_TIME: (guint32 launch_time) * sets the "launch time" for the application. If the user * interacts with another window after @launch_time but before * the launched application creates its first window, the window * manager may choose to not give focus to the new application. * Passing 0 for @launch_time will explicitly request that the * application not receive focus. * %EGG_DESKTOP_FILE_LAUNCH_FLAGS (GSpawnFlags flags) * Sets additional #GSpawnFlags to use. See g_spawn_async() for * more details. * %EGG_DESKTOP_FILE_LAUNCH_SETUP_FUNC (GSpawnChildSetupFunc, gpointer) * Sets the child setup callback and the data to pass to it. * (See g_spawn_async() for more details.) * * %EGG_DESKTOP_FILE_LAUNCH_RETURN_PID (GPid **pid) * On a successful launch, sets *@pid to the PID of the launched * application. * %EGG_DESKTOP_FILE_LAUNCH_RETURN_STARTUP_ID (char **startup_id) * On a successful launch, sets *@startup_id to the Startup * Notification "startup id" of the launched application. * %EGG_DESKTOP_FILE_LAUNCH_RETURN_STDIN_PIPE (int *fd) * On a successful launch, sets *@fd to the file descriptor of * a pipe connected to the application's stdin. * %EGG_DESKTOP_FILE_LAUNCH_RETURN_STDOUT_PIPE (int *fd) * On a successful launch, sets *@fd to the file descriptor of * a pipe connected to the application's stdout. * %EGG_DESKTOP_FILE_LAUNCH_RETURN_STDERR_PIPE (int *fd) * On a successful launch, sets *@fd to the file descriptor of * a pipe connected to the application's stderr. * * The options should be terminated with a single %NULL. * * If @documents contains multiple documents, but * egg_desktop_file_accepts_multiple() returns %FALSE for * @desktop_file, then egg_desktop_file_launch() will actually launch * multiple instances of the application. In that case, the return * value (as well as any values passed via * %EGG_DESKTOP_FILE_LAUNCH_RETURN_PID, etc) will only reflect the * first instance of the application that was launched (but the * %EGG_DESKTOP_FILE_LAUNCH_SETUP_FUNC will be called for each * instance). * * Return value: %TRUE if the application was successfully launched. **/ gboolean egg_desktop_file_launch (EggDesktopFile *desktop_file, GSList *documents, GError **error, ...) { va_list args; gboolean success; EggDesktopFile *app_desktop_file; switch (desktop_file->type) { case EGG_DESKTOP_FILE_TYPE_APPLICATION: va_start (args, error); success = egg_desktop_file_launchv (desktop_file, documents, args, error); va_end (args); break; case EGG_DESKTOP_FILE_TYPE_LINK: if (documents) { g_set_error (error, EGG_DESKTOP_FILE_ERROR, EGG_DESKTOP_FILE_ERROR_NOT_LAUNCHABLE, /* translators: The 'Type=Link' string is found in a * desktop file, and should not be translated. */ _("Can't pass document URIs to a 'Type=Link' desktop entry")); return FALSE; } if (!parse_link (desktop_file, &app_desktop_file, &documents, error)) return FALSE; va_start (args, error); success = egg_desktop_file_launchv (app_desktop_file, documents, args, error); va_end (args); egg_desktop_file_free (app_desktop_file); free_document_list (documents); break; case EGG_DESKTOP_FILE_TYPE_UNRECOGNIZED: case EGG_DESKTOP_FILE_TYPE_DIRECTORY: default: g_set_error (error, EGG_DESKTOP_FILE_ERROR, EGG_DESKTOP_FILE_ERROR_NOT_LAUNCHABLE, _("Not a launchable item")); success = FALSE; break; } return success; }
/** * egg_desktop_file_launch: * @desktop_file: an #EggDesktopFile * @documents: a list of URIs or paths to documents to open * @error: error pointer * @...: additional options * * Launches @desktop_file with the given arguments. Additional options * can be specified as follows: * * %EGG_DESKTOP_FILE_LAUNCH_CLEARENV: (no arguments) * clears the environment in the child process * %EGG_DESKTOP_FILE_LAUNCH_PUTENV: (char **variables) * adds the NAME=VALUE strings in the given %NULL-terminated * array to the child process's environment * %EGG_DESKTOP_FILE_LAUNCH_SCREEN: (GdkScreen *screen) * causes the application to be launched on the given screen * %EGG_DESKTOP_FILE_LAUNCH_WORKSPACE: (int workspace) * causes the application to be launched on the given workspace * %EGG_DESKTOP_FILE_LAUNCH_DIRECTORY: (char *dir) * causes the application to be launched in the given directory * %EGG_DESKTOP_FILE_LAUNCH_TIME: (guint32 launch_time) * sets the "launch time" for the application. If the user * interacts with another window after @launch_time but before * the launched application creates its first window, the window * manager may choose to not give focus to the new application. * Passing 0 for @launch_time will explicitly request that the * application not receive focus. * %EGG_DESKTOP_FILE_LAUNCH_FLAGS (GSpawnFlags flags) * Sets additional #GSpawnFlags to use. See g_spawn_async() for * more details. * %EGG_DESKTOP_FILE_LAUNCH_SETUP_FUNC (GSpawnChildSetupFunc, gpointer) * Sets the child setup callback and the data to pass to it. * (See g_spawn_async() for more details.) * * %EGG_DESKTOP_FILE_LAUNCH_RETURN_PID (GPid **pid) * On a successful launch, sets *@pid to the PID of the launched * application. * %EGG_DESKTOP_FILE_LAUNCH_RETURN_STARTUP_ID (char **startup_id) * On a successful launch, sets *@startup_id to the Startup * Notification "startup id" of the launched application. * %EGG_DESKTOP_FILE_LAUNCH_RETURN_STDIN_PIPE (int *fd) * On a successful launch, sets *@fd to the file descriptor of * a pipe connected to the application's stdin. * %EGG_DESKTOP_FILE_LAUNCH_RETURN_STDOUT_PIPE (int *fd) * On a successful launch, sets *@fd to the file descriptor of * a pipe connected to the application's stdout. * %EGG_DESKTOP_FILE_LAUNCH_RETURN_STDERR_PIPE (int *fd) * On a successful launch, sets *@fd to the file descriptor of * a pipe connected to the application's stderr. * * The options should be terminated with a single %NULL. * * If @documents contains multiple documents, but * egg_desktop_file_accepts_multiple() returns %FALSE for * @desktop_file, then egg_desktop_file_launch() will actually launch * multiple instances of the application. In that case, the return * value (as well as any values passed via * %EGG_DESKTOP_FILE_LAUNCH_RETURN_PID, etc) will only reflect the * first instance of the application that was launched (but the * %EGG_DESKTOP_FILE_LAUNCH_SETUP_FUNC will be called for each * instance). * * Return value: %TRUE if the application was successfully launched. **/ gboolean egg_desktop_file_launch (EggDesktopFile *desktop_file, GSList *documents, GError **error, ...) { va_list args; gboolean success; EggDesktopFile *app_desktop_file; switch (desktop_file->type) { case EGG_DESKTOP_FILE_TYPE_APPLICATION: va_start (args, error); success = egg_desktop_file_launchv (desktop_file, documents, args, error); va_end (args); break; case EGG_DESKTOP_FILE_TYPE_LINK: if (documents) { g_set_error (error, EGG_DESKTOP_FILE_ERROR, EGG_DESKTOP_FILE_ERROR_NOT_LAUNCHABLE, _("Can't pass documents to this desktop element")); return FALSE; } if (!parse_link (desktop_file, &app_desktop_file, &documents, error)) return FALSE; va_start (args, error); success = egg_desktop_file_launchv (app_desktop_file, documents, args, error); va_end (args); egg_desktop_file_free (app_desktop_file); free_document_list (documents); break; default: g_set_error (error, EGG_DESKTOP_FILE_ERROR, EGG_DESKTOP_FILE_ERROR_NOT_LAUNCHABLE, _("Not a launchable item")); success = FALSE; break; } return success; }
/** * egg_desktop_file_new_from_key_file: * @key_file: a #GKeyFile representing a desktop file * @source: the path or URI that @key_file was loaded from, or %NULL * @error: error pointer * * Creates a new #EggDesktopFile for @key_file. Assumes ownership of * @key_file (on success or failure); you should consider @key_file to * be freed after calling this function. * * Return value: the new #EggDesktopFile, or %NULL on error. **/ EggDesktopFile * egg_desktop_file_new_from_key_file (GKeyFile *key_file, const char *source, GError **error) { EggDesktopFile *desktop_file; char *version, *type; if (!g_key_file_has_group (key_file, EGG_DESKTOP_FILE_GROUP)) { g_set_error (error, EGG_DESKTOP_FILE_ERROR, EGG_DESKTOP_FILE_ERROR_INVALID, _("File is not a valid .desktop file")); g_key_file_free (key_file); return NULL; } version = g_key_file_get_value (key_file, EGG_DESKTOP_FILE_GROUP, EGG_DESKTOP_FILE_KEY_VERSION, NULL); if (version) { double version_num; char *end; version_num = g_ascii_strtod (version, &end); if (*end) { g_warning ("Invalid Version string '%s' in %s", version, source ? source : "(unknown)"); } else if (version_num > 1.0) { g_set_error (error, EGG_DESKTOP_FILE_ERROR, EGG_DESKTOP_FILE_ERROR_INVALID, /* translators: 'Version' is from a desktop file, and * should not be translated. '%s' would probably be a * version number. */ _("Unrecognized desktop file Version '%s'"), version); g_free (version); g_key_file_free (key_file); return NULL; } g_free (version); } desktop_file = g_new0 (EggDesktopFile, 1); desktop_file->key_file = key_file; if (g_path_is_absolute (source)) desktop_file->source = g_filename_to_uri (source, NULL, NULL); else desktop_file->source = g_strdup (source); desktop_file->name = g_key_file_get_locale_string (key_file, EGG_DESKTOP_FILE_GROUP, EGG_DESKTOP_FILE_KEY_NAME, NULL, error); if (!desktop_file->name) { egg_desktop_file_free (desktop_file); return NULL; } type = g_key_file_get_string (key_file, EGG_DESKTOP_FILE_GROUP, EGG_DESKTOP_FILE_KEY_TYPE, error); if (!type) { egg_desktop_file_free (desktop_file); return NULL; } if (!strcmp (type, "Application")) { char *exec, *p; desktop_file->type = EGG_DESKTOP_FILE_TYPE_APPLICATION; exec = g_key_file_get_string (key_file, EGG_DESKTOP_FILE_GROUP, EGG_DESKTOP_FILE_KEY_EXEC, error); if (!exec) { egg_desktop_file_free (desktop_file); g_free (type); return NULL; } /* See if it takes paths or URIs or neither */ for (p = exec; *p; p++) { if (*p == '%') { if (p[1] == '\0' || strchr ("FfUu", p[1])) { desktop_file->document_code = p[1]; break; } p++; } } g_free (exec); } else if (!strcmp (type, "Link")) { char *url; desktop_file->type = EGG_DESKTOP_FILE_TYPE_LINK; url = g_key_file_get_string (key_file, EGG_DESKTOP_FILE_GROUP, EGG_DESKTOP_FILE_KEY_URL, error); if (!url) { egg_desktop_file_free (desktop_file); g_free (type); return NULL; } g_free (url); } else if (!strcmp (type, "Directory")) desktop_file->type = EGG_DESKTOP_FILE_TYPE_DIRECTORY; else desktop_file->type = EGG_DESKTOP_FILE_TYPE_UNRECOGNIZED; g_free (type); /* Check the Icon key */ desktop_file->icon = g_key_file_get_string (key_file, EGG_DESKTOP_FILE_GROUP, EGG_DESKTOP_FILE_KEY_ICON, NULL); if (desktop_file->icon && !g_path_is_absolute (desktop_file->icon)) { char *ext; /* Lots of .desktop files still get this wrong */ ext = strrchr (desktop_file->icon, '.'); if (ext && (!strcmp (ext, ".png") || !strcmp (ext, ".xpm") || !strcmp (ext, ".svg"))) { g_warning ("Desktop file '%s' has malformed Icon key '%s'" "(should not include extension)", source ? source : "(unknown)", desktop_file->icon); *ext = '\0'; } } return desktop_file; }