예제 #1
0
파일: fm-app-info.c 프로젝트: dforsi/libfm
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;
}
예제 #2
0
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;
}