root/tools/perf/ui/setup.c
// SPDX-License-Identifier: GPL-2.0
#include <dlfcn.h>
#include <signal.h>
#include <unistd.h>

#include <subcmd/pager.h>
#include "../util/debug.h"
#include "../util/hist.h"
#include "ui.h"

struct mutex ui__lock;
void *perf_gtk_handle;
int use_browser = -1;

#define PERF_GTK_DSO "libperf-gtk.so"

#ifdef HAVE_GTK2_SUPPORT

static int setup_gtk_browser(void)
{
        int (*perf_ui_init)(void);

        if (perf_gtk_handle)
                return 0;

        perf_gtk_handle = dlopen(PERF_GTK_DSO, RTLD_LAZY);
        if (perf_gtk_handle == NULL) {
                char buf[PATH_MAX];
                scnprintf(buf, sizeof(buf), "%s/%s", LIBDIR, PERF_GTK_DSO);
                perf_gtk_handle = dlopen(buf, RTLD_LAZY);
        }
        if (perf_gtk_handle == NULL)
                return -1;

        perf_ui_init = dlsym(perf_gtk_handle, "perf_gtk__init");
        if (perf_ui_init == NULL)
                goto out_close;

        if (perf_ui_init() == 0)
                return 0;

out_close:
        dlclose(perf_gtk_handle);
        return -1;
}

static void exit_gtk_browser(bool wait_for_ok)
{
        void (*perf_ui_exit)(bool);

        if (perf_gtk_handle == NULL)
                return;

        perf_ui_exit = dlsym(perf_gtk_handle, "perf_gtk__exit");
        if (perf_ui_exit == NULL)
                goto out_close;

        perf_ui_exit(wait_for_ok);

out_close:
        dlclose(perf_gtk_handle);

        perf_gtk_handle = NULL;
}
#else
static inline int setup_gtk_browser(void) { return -1; }
static inline void exit_gtk_browser(bool wait_for_ok __maybe_unused) {}
#endif

int stdio__config_color(const struct option *opt __maybe_unused,
                        const char *mode, int unset __maybe_unused)
{
        perf_use_color_default = perf_config_colorbool("color.ui", mode, -1);
        return 0;
}

void setup_browser(bool fallback_to_pager)
{
        mutex_init(&ui__lock);
        if (use_browser < 2 && (!isatty(1) || dump_trace))
                use_browser = 0;

        /* default to TUI */
        if (use_browser < 0)
                use_browser = 1;

        switch (use_browser) {
        case 2:
                if (setup_gtk_browser() == 0)
                        break;
                printf("GTK browser requested but could not find %s\n",
                       PERF_GTK_DSO);
                sleep(1);
                use_browser = 1;
                /* fall through */
        case 1:
                if (ui__init() == 0)
                        break;
                /* fall through */
        default:
                use_browser = 0;
                if (fallback_to_pager)
                        setup_pager();
                break;
        }
}

void exit_browser(bool wait_for_ok)
{
        switch (use_browser) {
        case 2:
                exit_gtk_browser(wait_for_ok);
                break;

        case 1:
                ui__exit(wait_for_ok);
                break;

        default:
                break;
        }
        mutex_destroy(&ui__lock);
}

void pthread__block_sigwinch(void)
{
        sigset_t set;

        sigemptyset(&set);
        sigaddset(&set, SIGWINCH);
        pthread_sigmask(SIG_BLOCK, &set, NULL);
}

void pthread__unblock_sigwinch(void)
{
        sigset_t set;

        sigemptyset(&set);
        sigaddset(&set, SIGWINCH);
        pthread_sigmask(SIG_UNBLOCK, &set, NULL);
}