Linux / X11输入库无需创建窗口

时间:2022-10-31 12:10:00

Is there a good library to use for gathering user input in Linux from the mouse/keyboard/joystick that doesn't force you to create a visible window to do so? SDL lets you get user input in a reasonable way, but seems to force you to create a window, which is troublesome if you have abstracted control so the control machine doesn't have to be the same as the render machine. However, if the control and render machines are the same, this results in an ugly little SDL window on top of your display.

是否有一个很好的库用于从鼠标/键盘/操纵杆收集Linux中的用户输入,这不会强制您创建可见窗口? SDL允许您以合理的方式获得用户输入,但似乎迫使您创建一个窗口,如果您具有抽象控制,这很麻烦,因此控制机器不必与渲染机器相同。但是,如果控制和渲染机器相同,则会在显示器顶部形成一个丑陋的小SDL窗口。

Edit To Clarify:
The renderer has an output window, in its normal use case, that window is full screen, except when they are both running on the same computer, just so it is possible to give the controller focus. There can actually be multiple renderers displaying a different view of the same data on different computers all controlled by the same controller, hence the total decoupling of the input from the output (Making taking advantage of the built in X11 client/server stuff for display less useable) Also, multiple controller applications for one renderer is also possible. Communication between the controllers and renderers is via sockets.

编辑澄清:渲染器有一个输出窗口,在正常使用情况下,该窗口是全屏的,除非它们都在同一台计算机上运行,​​这样就可以给控制器聚焦。实际上可以有多个渲染器在同一控制器控制的不同计算机上显示相同数据的不同视图,因此输入与输出完全解耦(利用内置X11客户端/服务器的东西来显示更少另外,一个渲染器的多个控制器应用程序也是可能的。控制器和渲染器之间的通信是通过套接字进行的。

2 个解决方案

#1


7  

OK, if you're under X11 and you want to get the kbd, you need to do a grab. If you're not, my only good answer is ncurses from a terminal.

好吧,如果你在X11之下并想要获得kbd,你需要抓住它。如果你不是,我唯一的好答案是来自终端的ncurses。

Here's how you grab everything from the keyboard and release again:

以下是您从键盘获取所有内容并再次发布的方法:

/* Demo code, needs more error checking, compile
 * with "gcc nameofthisfile.c -lX11".

/* weird formatting for markdown follows.  argh! */

#include <X11/Xlib.h>

int main(int argc, char **argv)
{
   Display *dpy;
   XEvent ev;
   char *s;
   unsigned int kc;
   int quit = 0;

   if (NULL==(dpy=XOpenDisplay(NULL))) {
      perror(argv[0]);
      exit(1);
   }

   /*
    * You might want to warp the pointer to somewhere that you know
    * is not associated with anything that will drain events.
    *  (void)XWarpPointer(dpy, None, DefaultRootWindow(dpy), 0, 0, 0, 0, x, y);
    */

   XGrabKeyboard(dpy, DefaultRootWindow(dpy),
                 True, GrabModeAsync, GrabModeAsync, CurrentTime);

   printf("KEYBOARD GRABBED!  Hit 'q' to quit!\n"
          "If this job is killed or you get stuck, use Ctrl-Alt-F1\n"
          "to switch to a console (if possible) and run something that\n"
          "ungrabs the keyboard.\n");


   /* A very simple event loop: start at "man XEvent" for more info. */
   /* Also see "apropos XGrab" for various ways to lock down access to
    * certain types of info. coming out of or going into the server */
   for (;!quit;) {
      XNextEvent(dpy, &ev);
      switch (ev.type) {
         case KeyPress:
            kc = ((XKeyPressedEvent*)&ev)->keycode;
            s = XKeysymToString(XKeycodeToKeysym(dpy, kc, 0));
            /* s is NULL or a static no-touchy return string. */
            if (s) printf("KEY:%s\n", s);
            if (!strcmp(s, "q")) quit=~0;
            break;
         case Expose:
               /* Often, it's a good idea to drain residual exposes to
                * avoid visiting Blinky's Fun Club. */
               while (XCheckTypedEvent(dpy, Expose, &ev)) /* empty body */ ;
            break;
         case ButtonPress:
         case ButtonRelease:
         case KeyRelease:
         case MotionNotify:
         case ConfigureNotify:
         default:
            break;
      }
   }

   XUngrabKeyboard(dpy, CurrentTime);

   if (XCloseDisplay(dpy)) {
      perror(argv[0]);
      exit(1);
   }

   return 0;
}

Run this from a terminal and all kbd events should hit it. I'm testing it under Xorg but it uses venerable, stable Xlib mechanisms.

从终端运行此命令,所有kbd事件都应该点击它。我正在Xorg下测试它,但它使用了古老的,稳定的Xlib机制。

Hope this helps.

希望这可以帮助。

BE CAREFUL with grabs under X. When you're new to them, sometimes it's a good idea to start a time delay process that will ungrab the server when you're testing code and let it sit and run and ungrab every couple of minutes. It saves having to kill or switch away from the server to externally reset state.

小心翼翼地抓住X.当你刚接触它们时,有时候开始一个时间延迟过程是一个好主意,当你测试代码并让它每隔几分钟就能让它静坐和运行时,它会解开服务器。它节省了必须杀死或切换远离服务器到外部重置状态。

From here, I'll leave it to you to decide how to multiplex renderes. Read the XGrabKeyboard docs and XEvent docs to get started. If you have small windows exposed at the screen corners, you could jam the pointer into one corner to select a controller. XWarpPointer can shove the pointer to one of them as well from code.

从这里开始,我将留给您决定如何复用渲染。阅读XGrabKeyboard文档和XEvent文档以开始使用。如果您在屏幕角落露出小窗口,则可能会将指针卡在一个角落以选择控制器。 XWarpPointer也可以将指针从代码推送到其中一个指针。

One more point: you can grab the pointer as well, and other resources. If you had one controller running on the box in front of which you sit, you could use keyboard and mouse input to switch it between open sockets with different renderers. You shouldn't need to resize the output window to less than full screen anymore with this approach, ever. With more work, you could actually drop alpha-blended overlays on top using the SHAPE and COMPOSITE extensions to get a nice overlay feature in response to user input (which might count as gilding the lily).

还有一点:你也可以抓住指针和其他资源。如果您在前面的盒子上运行了一个控制器,则可以使用键盘和鼠标输入在具有不同渲染器的打开套接字之间切换。您不应该再使用这种方法将输出窗口的大小调整为低于全屏幕。通过更多的工作,你可以使用SHAPE和COMPOSITE扩展将alpha混合叠加层放在顶部以获得一个很好的叠加功能以响应用户输入(这可能算作镀金百合)。

#2


2  

For the mouse you can use GPM.

对于鼠标,您可以使用GPM。

I'm not sure off the top of my head for keyboard or joystick.

键盘或操纵杆让我无法理解。

It probably wouldn't be too bad to read directly off there /dev files if need be.

如果需要,直接读取/ dev文件可能不会太糟糕。

Hope it helps

希望能帮助到你

#1


7  

OK, if you're under X11 and you want to get the kbd, you need to do a grab. If you're not, my only good answer is ncurses from a terminal.

好吧,如果你在X11之下并想要获得kbd,你需要抓住它。如果你不是,我唯一的好答案是来自终端的ncurses。

Here's how you grab everything from the keyboard and release again:

以下是您从键盘获取所有内容并再次发布的方法:

/* Demo code, needs more error checking, compile
 * with "gcc nameofthisfile.c -lX11".

/* weird formatting for markdown follows.  argh! */

#include <X11/Xlib.h>

int main(int argc, char **argv)
{
   Display *dpy;
   XEvent ev;
   char *s;
   unsigned int kc;
   int quit = 0;

   if (NULL==(dpy=XOpenDisplay(NULL))) {
      perror(argv[0]);
      exit(1);
   }

   /*
    * You might want to warp the pointer to somewhere that you know
    * is not associated with anything that will drain events.
    *  (void)XWarpPointer(dpy, None, DefaultRootWindow(dpy), 0, 0, 0, 0, x, y);
    */

   XGrabKeyboard(dpy, DefaultRootWindow(dpy),
                 True, GrabModeAsync, GrabModeAsync, CurrentTime);

   printf("KEYBOARD GRABBED!  Hit 'q' to quit!\n"
          "If this job is killed or you get stuck, use Ctrl-Alt-F1\n"
          "to switch to a console (if possible) and run something that\n"
          "ungrabs the keyboard.\n");


   /* A very simple event loop: start at "man XEvent" for more info. */
   /* Also see "apropos XGrab" for various ways to lock down access to
    * certain types of info. coming out of or going into the server */
   for (;!quit;) {
      XNextEvent(dpy, &ev);
      switch (ev.type) {
         case KeyPress:
            kc = ((XKeyPressedEvent*)&ev)->keycode;
            s = XKeysymToString(XKeycodeToKeysym(dpy, kc, 0));
            /* s is NULL or a static no-touchy return string. */
            if (s) printf("KEY:%s\n", s);
            if (!strcmp(s, "q")) quit=~0;
            break;
         case Expose:
               /* Often, it's a good idea to drain residual exposes to
                * avoid visiting Blinky's Fun Club. */
               while (XCheckTypedEvent(dpy, Expose, &ev)) /* empty body */ ;
            break;
         case ButtonPress:
         case ButtonRelease:
         case KeyRelease:
         case MotionNotify:
         case ConfigureNotify:
         default:
            break;
      }
   }

   XUngrabKeyboard(dpy, CurrentTime);

   if (XCloseDisplay(dpy)) {
      perror(argv[0]);
      exit(1);
   }

   return 0;
}

Run this from a terminal and all kbd events should hit it. I'm testing it under Xorg but it uses venerable, stable Xlib mechanisms.

从终端运行此命令,所有kbd事件都应该点击它。我正在Xorg下测试它,但它使用了古老的,稳定的Xlib机制。

Hope this helps.

希望这可以帮助。

BE CAREFUL with grabs under X. When you're new to them, sometimes it's a good idea to start a time delay process that will ungrab the server when you're testing code and let it sit and run and ungrab every couple of minutes. It saves having to kill or switch away from the server to externally reset state.

小心翼翼地抓住X.当你刚接触它们时,有时候开始一个时间延迟过程是一个好主意,当你测试代码并让它每隔几分钟就能让它静坐和运行时,它会解开服务器。它节省了必须杀死或切换远离服务器到外部重置状态。

From here, I'll leave it to you to decide how to multiplex renderes. Read the XGrabKeyboard docs and XEvent docs to get started. If you have small windows exposed at the screen corners, you could jam the pointer into one corner to select a controller. XWarpPointer can shove the pointer to one of them as well from code.

从这里开始,我将留给您决定如何复用渲染。阅读XGrabKeyboard文档和XEvent文档以开始使用。如果您在屏幕角落露出小窗口,则可能会将指针卡在一个角落以选择控制器。 XWarpPointer也可以将指针从代码推送到其中一个指针。

One more point: you can grab the pointer as well, and other resources. If you had one controller running on the box in front of which you sit, you could use keyboard and mouse input to switch it between open sockets with different renderers. You shouldn't need to resize the output window to less than full screen anymore with this approach, ever. With more work, you could actually drop alpha-blended overlays on top using the SHAPE and COMPOSITE extensions to get a nice overlay feature in response to user input (which might count as gilding the lily).

还有一点:你也可以抓住指针和其他资源。如果您在前面的盒子上运行了一个控制器,则可以使用键盘和鼠标输入在具有不同渲染器的打开套接字之间切换。您不应该再使用这种方法将输出窗口的大小调整为低于全屏幕。通过更多的工作,你可以使用SHAPE和COMPOSITE扩展将alpha混合叠加层放在顶部以获得一个很好的叠加功能以响应用户输入(这可能算作镀金百合)。

#2


2  

For the mouse you can use GPM.

对于鼠标,您可以使用GPM。

I'm not sure off the top of my head for keyboard or joystick.

键盘或操纵杆让我无法理解。

It probably wouldn't be too bad to read directly off there /dev files if need be.

如果需要,直接读取/ dev文件可能不会太糟糕。

Hope it helps

希望能帮助到你