使用 ANSI Escape 在虚拟终端中捕获鼠标

Que*_*ble 8 c terminal ansi-escape

我开始通过 Google 的魔力在线了解 ANSI 转义序列。能够将光标定位\e[row;colH在屏幕上并设置输出的颜色(即:\e[31m)是很巧妙的。

接下来我想尝试看看如何在虚拟终端中捕获鼠标。我意识到这段代码不可移植,并且我知道我可以使用 ncurses 或其他一些curses 库,但这里的目标是学习它是如何工作的,而不是用它编写生产代码。

我已经尝试过了\e[?1003h,它开始用鼠标事件填充屏幕。(非常酷!)但是,如何在 C 或 C++ 程序中捕获这些?

我看到了我想用 PHP 做的一个例子:/sf/answers/4087340281/

然而,当我尝试将代码移植到 C 语言中时,它只是锁定在 while 循环中。(用 GDB 进行测试以找出答案。)

#include <stdio.h> //bring in printf and fread

int main()
{
    system("stty -echo"); //make the terminal not output mouse events
    system("stty -icanon"); //put stdin in raw mode
    printf("\e[?1003h\e[?1015h\e[?1006h"); //start getting mouse events
    char* buffer[255];
    while(fread(buffer, 16, 1, stdin)) // <-- suppose to read in the mouse events
    {
        printf("here"); //Did you actually work?!
    }
    printf("\e[?1000l"); //Turn off mouse events
    system("stty echo"); //Turn echoing of the display back on
    return 0; //end the program in a successful state
}
Run Code Online (Sandbox Code Playgroud)

我也尝试过scanf,它只是锁定,直到我按回车键,而且我不相信它看到了鼠标事件。

编辑

我现在有一些可以输出鼠标事件的工作代码。

以下是将已接受的答案应用于此问题的更新代码:

#include <stdio.h> //bring in printf and fread

int main()
{
    system("stty -echo"); //make the terminal not output mouse events
    system("stty -icanon"); //put stdin in raw mode
    printf("\e[?1003h\e[?1015h\e[?1006h"); //start getting mouse events
    char* buffer[255];
    while(fread(buffer, 16, 1, stdin)) // <-- suppose to read in the mouse events
    {
        printf("here"); //Did you actually work?!
    }
    printf("\e[?1000l"); //Turn off mouse events
    system("stty echo"); //Turn echoing of the display back on
    return 0; //end the program in a successful state
}
Run Code Online (Sandbox Code Playgroud)

Tho*_*key 2

两个问题:

  • printf是(使用stdout)缓冲的,因此不能保证转义序列在尝试读取之前到达终端。
  • stdin不一定是终端(尽管可能是)。再次强调,fread是缓冲的(您可能无法如您所愿地立即得到结果)。

由于stderr没有缓冲,因此使用该流发送转义序列将有所帮助。fread它可以帮助使用,而不是使用read,例如,

read(fileno(stdin), buffer, 16)
Run Code Online (Sandbox Code Playgroud)