繁体   English   中英

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

[英]Capturing Mouse in Virtual Terminal with ANSI Escape

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

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

我试过\e[?1003h ,它开始用鼠标事件填充屏幕。 (很酷,)然而? 我如何在 C 或 C++ 程序中捕获这些?

我看到了一个我想用 PHP 做的事情的例子: https ://stackoverflow.com/a/58390575/1770034

但是,当我尝试将代码移植到 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
}

我也试过scanf ,它只是锁定,直到我按下回车键,我不相信它正在看到鼠标事件。

编辑

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

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

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>

int main()
{
    system("stty -echo"); //don't show mouse events on screen
    system("stty -icanon");
    fprintf(stderr, "\e[?1003h\e[?1015h\e[?1006h"); //use stderr since not buffered turn on mouse event capture
    char buffer[16] = " ";
    char previousBuffer[16] = " ";

    //Make standard in not be blocking
    int flags = fcntl(stdin->_fileno, F_GETFL, 0);
    fcntl(stdin->_fileno, F_SETFL, flags | O_NONBLOCK);

    for (int hunSeconds = 0; hunSeconds < 500; hunSeconds++) //Run for 50 seconds
    {
        read(fileno(stdin), buffer, 16); //read mouse input
        if (strcmp(buffer, previousBuffer) != 0) //only show event if it is different
        {
            fprintf(stderr, "%s", buffer);
            strncpy(previousBuffer, buffer, 16);
        }
        usleep(100); // sleep for .1 seconds
    }
    printf("\e[?1000l"); //turn off mouse events
    system("stty echo"); //turn on screen echo again
    return 0;
}

两个问题:

  • printf是(使用stdout )缓冲的,因此不能保证转义序列在尝试读取之前到达终端。
  • stdin不一定是终端(尽管它可能是)。 同样, fread被缓冲(您可能不会像您希望的那样迅速得到结果)。

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

read(fileno(stdin), buffer, 16)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM