static char* expand_terminal(char* cmd, gboolean keep_open, GError** error) { FmTerminal* term; const char* opts; char* ret; /* if %s is not found, fallback to -e */ static FmTerminal xterm_def = { .program = "xterm", .open_arg = "-e" }; term = fm_terminal_dup_default(NULL); /* bug #3457335: Crash on application start with Terminal=true. */ if(!term) /* fallback to xterm if a terminal emulator is not found. */ { /* FIXME: we should not hard code xterm here. :-( * It's better to prompt the user and let he or she set * his preferred terminal emulator. */ term = &xterm_def; } if(keep_open && term->noclose_arg) opts = term->noclose_arg; else opts = term->open_arg; if(term->custom_args) ret = g_strdup_printf("%s %s %s %s", term->program, term->custom_args, opts, cmd); else ret = g_strdup_printf("%s %s %s", term->program, opts, cmd); if(term != &xterm_def) g_object_unref(term); return ret; } static gboolean do_launch(GAppInfo* appinfo, const char* full_desktop_path, GKeyFile* kf, GList* gfiles, GAppLaunchContext* ctx, GError** err) { gboolean ret = FALSE; char* cmd, *path; char** argv; int argc; gboolean use_terminal; GAppInfoCreateFlags flags; cmd = expand_exec_macros(appinfo, full_desktop_path, kf, gfiles); if(G_LIKELY(kf)) use_terminal = g_key_file_get_boolean(kf, "Desktop Entry", "Terminal", NULL); else { flags = GPOINTER_TO_UINT(g_object_get_data(G_OBJECT(appinfo), "flags")); use_terminal = (flags & G_APP_INFO_CREATE_NEEDS_TERMINAL) != 0; } if(use_terminal) { /* FIXME: is it right key to mark this option? */ gboolean keep_open = FALSE; char* term_cmd; if(G_LIKELY(kf)) keep_open = g_key_file_get_boolean(kf, "Desktop Entry", "X-KeepTerminal", NULL); term_cmd = expand_terminal(cmd, keep_open, err); g_free(cmd); if(!term_cmd) return FALSE; cmd = term_cmd; } g_debug("launch command: <%s>", cmd); if(g_shell_parse_argv(cmd, &argc, &argv, err)) { struct ChildSetup data; if(ctx) { gboolean use_sn; if(G_LIKELY(kf) && g_key_file_has_key(kf, "Desktop Entry", "StartupNotify", NULL)) use_sn = g_key_file_get_boolean(kf, "Desktop Entry", "StartupNotify", NULL); else if(fm_config->force_startup_notify) { /* if the app doesn't explicitly ask us not to use sn, * and fm_config->force_startup_notify is TRUE, then * use it by default, unless it's a console app. */ use_sn = !use_terminal; /* we only use sn for GUI apps by default */ /* FIXME: console programs should use sn_id of terminal emulator instead. */ } else use_sn = FALSE; data.display = g_app_launch_context_get_display(ctx, appinfo, gfiles); if(use_sn) data.sn_id = g_app_launch_context_get_startup_notify_id(ctx, appinfo, gfiles); else data.sn_id = NULL; } else { data.display = NULL; data.sn_id = NULL; } g_debug("sn_id = %s", data.sn_id); if(G_LIKELY(kf)) path = g_key_file_get_string(kf, "Desktop Entry", "Path", NULL); else path = NULL; ret = g_spawn_async(path, argv, NULL, G_SPAWN_SEARCH_PATH, child_setup, &data, NULL, err); g_free(path); g_free(data.display); g_free(data.sn_id); g_strfreev(argv); } g_free(cmd); return ret; }
gboolean do_launch (GAppInfo *appinfo, const char *full_desktop_path, GKeyFile *kf, GList *gfiles, GAppLaunchContext *ctx, GError **err) { gboolean ret = FALSE; char *cmd, *path; char **argv; int argc; gboolean use_terminal; GAppInfoCreateFlags flags; cmd = expand_exec_macros (appinfo, full_desktop_path, kf, gfiles); if (G_LIKELY (kf)) use_terminal = g_key_file_get_boolean (kf, "Desktop Entry", "Terminal", NULL); else { flags = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (appinfo), "flags")); use_terminal = (flags & G_APP_INFO_CREATE_NEEDS_TERMINAL) != 0; } if (use_terminal) { char *term_cmd = expand_terminal (cmd); g_free (cmd); cmd = term_cmd; } g_debug ("launch command: <%s>", cmd); if (g_shell_parse_argv (cmd, &argc, &argv, err)) { struct ChildSetup data; if (ctx) { gboolean use_sn; if (G_LIKELY (kf)) use_sn = g_key_file_get_boolean (kf, "Desktop Entry", "StartupNotify", NULL); else use_sn = TRUE; data.display = g_app_launch_context_get_display (ctx, appinfo, gfiles); if (!use_sn) { /* if the app doesn't explicitly ask us not to use sn, use it by default, unless it's a console app.*/ if (!kf || !g_key_file_has_key (kf, "Desktop Entry", "StartupNotify", NULL)) use_sn = !use_terminal; // we only use sn for GUI apps by default // FIXME_pcm: console programs should use sn_id of terminal emulator instead. } if (use_sn) data.sn_id = g_app_launch_context_get_startup_notify_id (ctx, appinfo, gfiles); else data.sn_id = NULL; } else { data.display = NULL; data.sn_id = NULL; } g_debug ("sn_id = %s", data.sn_id); if (G_LIKELY (kf)) path = g_key_file_get_string (kf, "Desktop Entry", "Path", NULL); else path = NULL; ret = g_spawn_async (path, argv, NULL, G_SPAWN_SEARCH_PATH, child_setup, &data, NULL, err); g_free (path); g_free (data.display); g_free (data.sn_id); g_strfreev (argv); } g_free (cmd); return ret; }