编写你自己的Terminal emulator

作者: 霡霂976447044 | 来源:发表于2020-01-16 16:55 被阅读0次

    原文: https://vincent.bernat.ch/en/blog/2017-write-own-terminal

    安装开发依赖环境

    在apt包管理器系中,使用以下命令安装

    apt install libvte-2.91-dev
    

    介绍

    VTE是一个使用GTK构建的一个终端模拟器库, 能够处理DPI的更改。很多终端模拟器软件都基于VTE库,包括GNOME Terminal, XFCE Terminal, Deepin Terminal,Guake等等。这个库非常简洁,你可以很快就写出来一个自己终端模拟器。

    下面就来写一个例子。

    一个简单的终端

    我们先写一个默认的终端,会使用C语言编写。另一个可选的是使用Vala。

    #include <vte/vte.h>
    
    int
    main(int argc, char *argv[])
    {
        GtkWidget *window, *terminal;
    
        /* 初始化GTK,窗口和terminal */
        gtk_init(&argc, &argv);
        terminal = vte_terminal_new();
        window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
        gtk_window_set_title(GTK_WINDOW(window), "myterm");
    
        /* Start a new shell */
        gchar **envp = g_get_environ();
        gchar **command = (gchar *[]){g_strdup(g_environ_getenv(envp, "SHELL")), NULL };
        g_strfreev(envp);
        vte_terminal_spawn_async(VTE_TERMINAL(terminal),
            VTE_PTY_DEFAULT,
            NULL,       /* working directory  */
            command,    /* command */
            NULL,       /* environment */
            0,          /* spawn flags */
            NULL, NULL, /* child setup */
            NULL,       /* child pid */
            -1,         /* timeout */
            NULL, NULL, NULL);
    
        /* 连接一些信号 */
        g_signal_connect(window, "delete-event", gtk_main_quit, NULL);
        g_signal_connect(terminal, "child-exited", gtk_main_quit, NULL);
    
        /* 将组件添加到窗口, 然后进入事件循环 */
        gtk_container_add(GTK_CONTAINER(window), terminal);
        gtk_widget_show_all(window);
        gtk_main();
    }
    

    使用以下命令进行编译:

    gcc -O2 -Wall $(pkg-config --cflags vte-2.91) term.c -o term $(pkg-config --libs vte-2.91)
    

    然后运行./term

    基于VTE的Terminal

    更多定制

    你可以在VTE文档更改终端默认特性,下面有三个例子。

    颜色配置

    使用以下代码定义自己的颜色

    #define CLR_R(x)   (((x) & 0xff0000) >> 16)
    #define CLR_G(x)   (((x) & 0x00ff00) >>  8)
    #define CLR_B(x)   (((x) & 0x0000ff) >>  0)
    #define CLR_16(x)  ((double)(x) / 0xff)
    #define CLR_GDK(x) (const GdkRGBA){ .red = CLR_16(CLR_R(x)), \
                                        .green = CLR_16(CLR_G(x)), \
                                        .blue = CLR_16(CLR_B(x)), \
                                        .alpha = 0 }
    vte_terminal_set_colors(VTE_TERMINAL(terminal),
        &CLR_GDK(0xffffff),
        &(GdkRGBA){ .alpha = 0.85 },
        (const GdkRGBA[]){
            CLR_GDK(0x111111),
            CLR_GDK(0xd36265),
            CLR_GDK(0xaece91),
            CLR_GDK(0xe7e18c),
            CLR_GDK(0x5297cf),
            CLR_GDK(0x963c59),
            CLR_GDK(0x5E7175),
            CLR_GDK(0xbebebe),
            CLR_GDK(0x666666),
            CLR_GDK(0xef8171),
            CLR_GDK(0xcfefb3),
            CLR_GDK(0xfff796),
            CLR_GDK(0x74b8ef),
            CLR_GDK(0xb85e7b),
            CLR_GDK(0xA3BABF),
            CLR_GDK(0xffffff)
    }, 16);
    

    效果如下


    截图_2020-01-16_16-43-29.png

    杂项设置

    VTE可以设置很多选项来来改变默认的配置

    vte_terminal_set_scrollback_lines(VTE_TERMINAL(terminal), 0);
    vte_terminal_set_scroll_on_output(VTE_TERMINAL(terminal), FALSE);
    vte_terminal_set_scroll_on_keystroke(VTE_TERMINAL(terminal), TRUE);
    vte_terminal_set_mouse_autohide(VTE_TERMINAL(terminal), TRUE);
    

    分别可以设置

    • 关闭滚动缓冲
    • 输出的时候不会自滚动
    • 按键时自动滚到末尾
    • 鼠标自动隐藏

    改变标题

    static gboolean
    on_title_changed(GtkWidget *terminal, gpointer user_data)
    {
        GtkWindow *window = user_data;
        gtk_window_set_title(window,
            vte_terminal_get_window_title(VTE_TERMINAL(terminal))?:"Terminal");
        return TRUE;
    }
    
    

    然后,在main方法里连接信号,让程序一旦运行就调用改变标题

    g_signal_connect(terminal, "window-title-changed", 
        G_CALLBACK(on_title_changed), GTK_WINDOW(window));
    

    相关文章

      网友评论

        本文标题:编写你自己的Terminal emulator

        本文链接:https://www.haomeiwen.com/subject/aygfzctx.html