简体   繁体   English

C、Linux中子进程的复杂键盘输入

[英]Complex keyboard input to child process in C, Linux

Ive been trying to solve this one for some time but im unable to come up with a solution.一段时间以来,我一直在尝试解决这个问题,但我无法提出解决方案。 I need a child process to understand complex WASD keyboard input (with complex I mean detect that both W and A or many other keys are being pressed at the same time) but I think that this is impossible in C due to the way characters are read from the terminal.我需要一个子进程来理解复杂的 WASD 键盘输入(复杂的意思是检测同时按下 W 和 A 或许多其他键)但我认为由于字符的读取方式,这在 C 中是不可能的从终端。 My parent process only best result (taken from another post) is the following:我的父进程只有最好的结果(取自另一篇文章)如下:

int kbhit(){
    struct timeval tv;
    fd_set fds;
    tv.tv_sec = 0;
    tv.tv_usec = 0;
    FD_ZERO(&fds);
    FD_SET(STDIN_FILENO, &fds);
    select(STDIN_FILENO+1, &fds, NULL, NULL, &tv);
    return FD_ISSET(STDIN_FILENO, &fds);
}
int main(){
    system("stty raw -echo"); //No need to newline to read key and disables showing pressed key
    char command;
    unsigned short count = 0;
    while(1){
       while(1){
          if(kbhit()){count = 0; command = getchar(); break;}
          if(count > 5) {count = 0; command = 'f'; break;}
          count++;
          //Add code to somehow wait a few milliseconds
       }
       //Use read key/command...
       //If a certain key is read break out of loop
   }
   system("stty sane echo"); //Return terminal to normal state
   return EXIT_SUCCESS;
}

This is way too "hacky" and it does not detect multiple simultaneous key presses and I need a child process to read these keys, this code does not work under a fork since the keyboard is being sent to the parent, the child has no new STDIN (I think).这太“hacky”了,它没有检测到多个同时按下的按键,我需要一个子进程来读取这些键,这段代码在 fork 下不起作用,因为键盘被发送给父进程,孩子没有新的标准输入(我认为)。 I cant rewrite my entire program in another language due to many low level things im doing elsewhere.由于我在其他地方做了很多低级的事情,我不能用另一种语言重写我的整个程序。 Ive thought of the following solutions but im unsure of which one to go for:我想到了以下解决方案,但我不确定 go 是哪一个:

  • Have the child process use system("xterm") to open a new terminal and send keys over this one, this does not solve the multiple keys same time problem and from my first tests im unable to link this new terminal to the running process as this terminal just runs a fresh bash session. Code blocks until this terminal is closed.让子进程使用系统(“xterm”)打开一个新终端并通过这个终端发送密钥,这不能解决多个密钥同时出现的问题,并且从我的第一次测试中我无法将这个新终端链接到正在运行的进程这个终端刚刚运行一个新的 bash session。代码块直到这个终端被关闭。
  • Use another language like c++ or java that does support easily reading simultaneous key presses and somehow "pipe" this to the child process.使用另一种语言,如 c++ 或 java,它确实支持轻松读取同时按键并以某种方式将其“管道”到子进程。 I guess the child would fork and have the other process run this new code with a system call.我猜孩子会分叉并让另一个进程通过系统调用运行这个新代码。 Im unsure of how to send this to the other process (sockets maybe?).我不确定如何将其发送到其他进程(也许是套接字?)。

Are there other better ways of doing this?还有其他更好的方法吗? Would option 2 work?选项 2 可行吗? Im lost and stuck, any help is welcome!我迷路了,被困住了,欢迎任何帮助!

The simplest way to do it will be by creating events.最简单的方法是创建事件。 for example例如

struct SKeyEvent
{
char key;
uint8_t pressed;
};

so when a key is pressed you can use a callback function to update the structure with the key and 0, 1, 2 1 and 2. 1 = pressed, 2=released and followed right away by 0 = idle.因此,当按下一个键时,您可以使用回调 function 来使用键和 0、1、2、1 和 2 更新结构。1 = 按下,2 = 释放,然后立即跟随 0 = 空闲。 so when I pressed A the function callback will be called with {key:'A', 1} if you press W same {'W', 1} so you know that A and W are pressed simultaneously.所以当我按下 A 时,如果你按下 W 相同的 {'W', 1},那么 function 回调将通过 {key:'A', 1} 调用,这样你就知道同时按下了 A 和 W。 when a touch is released you will receive 2 calls for example {'A': 2}, {'A':0}释放触摸后,您将收到 2 个电话,例如 {'A': 2}, {'A':0}

I solved this instead of reading characters from the terminal (does not work since you can only input one char a time...) by reading the actual keyboard device (/dev/...).我解决了这个问题,而不是通过读取实际的键盘设备 (/dev/...) 从终端读取字符(不起作用,因为您一次只能输入一个字符...)。 There are some examples of this around.周围有一些这样的例子。

The downside is that it captures all keyboard input and you now need to run the program as superuser but it works...缺点是它捕获所有键盘输入,您现在需要以超级用户身份运行该程序,但它可以工作......

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

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