Linux xcb_grab_键无错误,但事件循环未捕获(全局热键)

Linux xcb_grab_键无错误,但事件循环未捕获(全局热键),linux,x11,xcb,Linux,X11,Xcb,我正在尝试在Linux上设置一个全局热键 我最初使用的是x11(libX11.so),但是我必须从一个线程中执行。我试过了,但是XPendingEvent和XNextEvent最终会使应用程序崩溃 所以我切换到xcb(libxcb.So.1)。没有错误,我甚至使用xcb\u request\u check进行检查,但是事件循环没有拾取任何内容。一旦启动循环,我只会得到一个如下所示的事件: { response_type: 0, pad0: 10, sequence: 2,

我正在尝试在Linux上设置一个全局热键

我最初使用的是x11(
libX11.so
),但是我必须从一个线程中执行。我试过了,但是
XPendingEvent
XNextEvent
最终会使应用程序崩溃

所以我切换到xcb(
libxcb.So.1
)。没有错误,我甚至使用
xcb\u request\u check
进行检查,但是事件循环没有拾取任何内容。一旦启动循环,我只会得到一个如下所示的事件:

{
    response_type: 0,
    pad0: 10,
    sequence: 2,
    pad: [620, 2162688, 0, 0, 0, 0, 0],
    full_sequence: 2
}
这是我的代码,我实际上是在js ctypes中这样做的,但我减少了所有内容,只显示尽可能简单的不可知代码:

conn = xcb_connect(null, null);

keysyms = xcb_key_symbols_alloc(conn);

keycodesPtr = xcb_key_symbols_get_keycode(keysyms, XK_Space);

setup = xcb_get_setup(conn);

screens = xcb_setup_roots_iterator(setup);
screensCnt = screens.rem;

for (var i=0; i<screensCnt; i++) {
    rez_grab = xcb_grab_key(conn, 1, screens.data.root, XCB_MOD_MASK_ANY, keycodesPtr[0], XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC);

    rez_err = xcb_request_check(conn, rez_grab);
    // rez_err is null

    xcb_screen_next(&screens);
}

xcb_flush(conn);

// start event loop
while (true) {
    ev = xcb_poll_for_event(conn);

    console.log(ev);

    if (ev != null) {
        free(ev);
    }

    Sleep(50);
}
conn=xcb_connect(空,空);
keysyms=xcb\u key\u symbols\u alloc(conn);
keycodesPtr=xcb_key_symbols_get_keycode(键符号,XK_空格);
设置=xcb\u获取\u设置(连接);
屏幕=xcb\u设置\u根\u迭代器(设置);
screensCnt=screens.rem;

对于(var i=0;i终于算出了!!啊算出了这个!我用的是
XCB\u MOD\u MASK\u ANY
,这个常数在Debian上有效,但在Ubuntu上无效,这是我用来测试的。我把它改成了num lock、caps lock等,现在它可以工作了!)

这真是太疯狂了,我不知道
XCB\u MOD\u MASK\u ANY
常量在Ubuntu上不起作用-

var rez_grab = ostypes.API('xcb_grab_key')(conn, 1, screens.data.contents.root, ostypes.CONST.XCB_MOD_MASK_ANY, keycodesArr[j], ostypes.CONST.XCB_GRAB_MODE_ASYNC, ostypes.CONST.XCB_GRAB_MODE_ASYNC);
我也试过@n.m的代码。在ubuntu上它不起作用,但在debian上起作用-

#include <xcb/xcb.h>
#define XK_LATIN1
#include <xcb/xcb_keysyms.h>
#include <X11/keysymdef.h>
#include <stdio.h>
#include <stdlib.h>

int
main ()
{
  xcb_connection_t *conn;

  conn = xcb_connect (NULL, NULL);

  xcb_key_symbols_t * keysyms = xcb_key_symbols_alloc(conn);

  xcb_keycode_t * keycodesPtr = xcb_key_symbols_get_keycode(keysyms, XK_space);

  const xcb_setup_t* setup = xcb_get_setup(conn);

  xcb_screen_iterator_t screens = xcb_setup_roots_iterator(setup);
  int screensCnt = screens.rem;

  for (int i=0; i<screensCnt; i++) {

      xcb_void_cookie_t rez_grab = xcb_grab_key(conn, 1, screens.data->root, XCB_MOD_MASK_ANY, keycodesPtr[0], XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC);

      const static uint32_t values[] = { XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_BUTTON_PRESS };

      xcb_change_window_attributes (conn, screens.data->root, XCB_CW_EVENT_MASK, values);

      xcb_screen_next(&screens);
  }

  xcb_flush(conn);

  // start event loop
  while (1) {
      xcb_generic_event_t *ev = xcb_wait_for_event(conn);

      if (ev && ((ev->response_type & ~0x80) == XCB_KEY_PRESS))
      {
          xcb_key_press_event_t *kp = (xcb_key_press_event_t *)ev;
          printf ("Got key press %d\n", (int)kp->event);
      }

      if (ev != NULL) {
          free(ev);
      }
  }

  return 0;
}
#包括
#定义XK_拉丁语1
#包括
#包括
#包括
#包括
int
主要()
{
xcb_连接接头;
conn=xcb_connect(空,空);
xcb_键符号_t*键符号=xcb_键符号_alloc(conn);
xcb_keycode_t*keycodesPtr=xcb_key_symbols_get_keycode(keysyms,XK_空格);
const xcb_setup\u t*setup=xcb_get_setup(conn);
xcb\u screen\u iterator\u t screens=xcb\u setup\u root\u iterator(setup);
int screensCnt=screens.rem;
对于(int i=0;iroot、XCB_MOD_MASK_ANY、keycodesPtr[0]、XCB_GRAB_MODE_ASYNC、XCB_GRAB_MODE_ASYNC);
const static uint32_t value[]={XCB_EVENT_MASK_EXPOSURE}XCB_EVENT_MASK_BUTTON_PRESS};
xcb\u更改\u窗口\u属性(conn,screens.data->root,xcb\u CW\u事件\u掩码,值);
xcb_屏幕_下一步(&screens);
}
xcb_冲洗(连接);
//启动事件循环
而(1){
xcb_通用_事件_t*ev=xcb_等待_事件(conn);
如果(ev&((ev->响应类型&~0x80)=XCB_键&)
{
xcb键按下事件kp=(xcb键按下事件t*)ev;
printf(“获得按键%d\n”,(int)kp->event);
}
如果(ev!=NULL){
免费(ev);
}
}
返回0;
}

我不理解“while(true)”的真实值是什么。您能否创建一个更简单的工作代码来重现您的问题。有时候,这样做会引导你找到解决方案。非常感谢@cedlemo的关注。我只是修改代码使其简单化我真正的代码就在这里--它基本上是我试图创建的一个无休止的事件循环,所以我知道我指定的热键何时被按下。我知道
grab_key
,所以除了我的热键外,该键对任何地方都没有影响。但它不起作用:(我基于它-但我在一个线程中,所以它可能会有所不同。您为根窗口设置了属性吗?。不,我不知道这有什么关系。我使用
gcc-o grab-grab.c-std=gnu99-lxcb-lxcb keysyms
,您可能必须添加
-I
和/或
-L
标志,但没有其他标志。那么您是否成功地生成了甚至更多的标志没有任何修改器的按键的ts?因为我在Ubuntu上,我遇到了同样的问题,
XCB\u MOD\u MASK\u any
不工作…(但是所有其他的MOD MASK,比如
XCB\u MOD\u MASK\u SHIFT
XCB\u MOD\u MASK\u 1
似乎都能工作)@是的,我注册了这样的听众——如果没有MOD,只需输入
XCB_NONE
,即
0
。以下是我用于各种MOD的代码——如果它对您有效,请发布另一个问题,我很乐意提供答案,并获得接受答案的分数。:)这是一个关于mods-@tale上同调的好话题。需要注意的关键是大写锁和num锁被算作修饰符。因此,对于
xcb\u NONE
,必须使用xcb\u抓取键,然后对于num lock
xcb\u MOD\u MASK\u lock
,再对于大写锁
xcb\u MOD\u MASK\u,必须使用
xcb\u抓取键最后,再次询问numlock和capslock是否都处于启用状态,原因是
XCB\u MOD\u MASK\u 2\XCB\u MOD\u MASK\u LOCK
更新了为什么
XCB\u MOD\u MASK\u Any
不起作用?找到了答案-为什么
XCB\u MOD\u MASK\u Any
不起作用可能是因为钥匙已经被抓到了:
#include <xcb/xcb.h>
#define XK_LATIN1
#include <xcb/xcb_keysyms.h>
#include <X11/keysymdef.h>
#include <stdio.h>
#include <stdlib.h>

int
main ()
{
  xcb_connection_t *conn;

  conn = xcb_connect (NULL, NULL);

  xcb_key_symbols_t * keysyms = xcb_key_symbols_alloc(conn);

  xcb_keycode_t * keycodesPtr = xcb_key_symbols_get_keycode(keysyms, XK_space);

  const xcb_setup_t* setup = xcb_get_setup(conn);

  xcb_screen_iterator_t screens = xcb_setup_roots_iterator(setup);
  int screensCnt = screens.rem;

  for (int i=0; i<screensCnt; i++) {

      xcb_void_cookie_t rez_grab = xcb_grab_key(conn, 1, screens.data->root, XCB_MOD_MASK_ANY, keycodesPtr[0], XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC);

      const static uint32_t values[] = { XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_BUTTON_PRESS };

      xcb_change_window_attributes (conn, screens.data->root, XCB_CW_EVENT_MASK, values);

      xcb_screen_next(&screens);
  }

  xcb_flush(conn);

  // start event loop
  while (1) {
      xcb_generic_event_t *ev = xcb_wait_for_event(conn);

      if (ev && ((ev->response_type & ~0x80) == XCB_KEY_PRESS))
      {
          xcb_key_press_event_t *kp = (xcb_key_press_event_t *)ev;
          printf ("Got key press %d\n", (int)kp->event);
      }

      if (ev != NULL) {
          free(ev);
      }
  }

  return 0;
}