通过文件描述符或套接字轮询X事件

3

由于X是一个服务器,是否有一种方法可以通过套接字而不是使用XNextEvent来监听X事件?

我有一个程序,通过在主线程中运行的循环中调用epoll_wait来监视系统事件。由于我无法找出如何通过文件描述符监听X事件,所以我不得不采取运行专用循环以在单独的线程中运行XNextEvent并在调用事件发生时的函数时放置互斥锁。

这是我编写的用于轮询X事件的函数,如果有人感兴趣,我目前仅监听与键盘布局切换相关的事件。

void* xevent_loop(void*) {
  int xkbEventType;
  XkbQueryExtension(dpy, 0, &xkbEventType, 0, 0, 0);
  XkbSelectEventDetails(dpy,
    XkbUseCoreKbd, XkbStateNotify, XkbAllStateComponentsMask,
    XkbGroupStateMask);
  XSync(dpy, False);

  for (XEvent e;;) {
    XNextEvent(dpy, &e);
    if (e.type == xkbEventType) {
      XkbEvent* xkbe = (XkbEvent*) &e;
      if (xkbe->any.xkb_type == XkbStateNotify) {
        pthread_mutex_lock(&setroot_mutex);
        fmt_kbd_layout(xkbe->state.group);
        setroot();
        pthread_mutex_unlock(&setroot_mutex);
      }
    }
  }
  return NULL;
}

(警告:完全未经测试的想法):使用XPeekEvent()在一个线程中循环等待事件,当有事件排队时,通知主线程(可以使用eventfd或其他你喜欢的方式),让它读取排队的事件(XPending()会告诉你有多少个事件)。 - undefined
1个回答

5

您可以使用显示器上的宏ConnectionNumber(dpy)来获取连接的文件描述符。请参见man ConnectionNumber

ConnectionNumber宏返回指定显示器的连接号。

这可以在 select()poll() 中用来检查事件是否准备好。定义在 /usr/include/X11/Xlib.h


谢谢!看起来ConnectionNumber宏从显示结构体中获取了fd成员,该成员有一个标注为网络套接字的注释。当我在套接字上调用read时,我应该期望读取什么?我可能会得到一些事件结构体而不是可读的文本。 - undefined
你不应该使用read()函数,而是应该使用select()poll()或者epoll()函数。如果它显示准备好接收EPOLLIN事件,则调用XNextEvent()函数来获取数据。然后返回到轮询循环以等待下一个事件。 - undefined
明白了,那应该可以。但是出于好奇,除了事件准备状态之外,插座本身没有携带任何其他信息吗? - undefined
X11连接套接字并不特殊。您可以像使用任何套接字一样使用它,但您读取/写入的数据流非常结构化且相当复杂。您可以在协议文档pdf的开头看到其中一些细节。 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接