Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/google-chrome/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
XCB&x2013;未在所有窗口上接收运动通知事件_C_Google Chrome_X11_Xcb - Fatal编程技术网

XCB&x2013;未在所有窗口上接收运动通知事件

XCB&x2013;未在所有窗口上接收运动通知事件,c,google-chrome,x11,xcb,C,Google Chrome,X11,Xcb,我试图得到任何指针移动的通知。因为我不想以窗口管理器的身份运行,所以我需要在所有窗口上设置XCB_EVENT\u MASK\u SUBSTRUCTURE\u NOTIFY | XCB_EVENT\u MASK\u POINTER\u MOTION,无论是在启动时还是在获得create NOTIFY事件时 一般来说,这似乎工作得很好,我在所有窗口上都会收到motion notify事件。然而,不知何故,谷歌Chrome windows并非如此。我随后通过显式查询检查了事件掩码,并且设置正确。我也没

我试图得到任何指针移动的通知。因为我不想以窗口管理器的身份运行,所以我需要在所有窗口上设置
XCB_EVENT\u MASK\u SUBSTRUCTURE\u NOTIFY | XCB_EVENT\u MASK\u POINTER\u MOTION
,无论是在启动时还是在获得create NOTIFY事件时

一般来说,这似乎工作得很好,我在所有窗口上都会收到motion notify事件。然而,不知何故,谷歌Chrome windows并非如此。我随后通过显式查询检查了事件掩码,并且设置正确。我也没有在传播掩码中看到任何异常

什么会导致Google Chrome不报告运动通知事件?好吧,X协议不允许这样做,除了Chrome肯定没有的主动指针抓取

以下是我如何在所有现有窗口上注册自己。我在根窗口上调用
register\u events
,每当我收到create notify事件时:

static void register_events(xcb_window_t window) {
    xcb_void_cookie_t cookie = xcb_change_window_attributes_checked(connection,                                         
        window, XCB_CW_EVENT_MASK, (uint32_t[]) { XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | XCB_EVENT_MASK_POINTER_MOTION | XCB_EVENT_MASK_LEAVE_WINDOW });
    xcb_generic_error_t *error = xcb_request_check(connection, cookie);
    if (error != NULL) {
        xcb_disconnect(connection);
        errx(EXIT_FAILURE, "could not subscribe to events on a window, bailing out");
    }   
}

static void register_existing_windows(void) {
    xcb_query_tree_reply_t *reply;
    if ((reply = xcb_query_tree_reply(connection, xcb_query_tree(connection, root), 0)) == NULL) {
        return;
    }   

    int len = xcb_query_tree_children_length(reply);
    xcb_window_t *children = xcb_query_tree_children(reply);
    for (int i = 0; i < len; i++) {
        register_events(children[i]);
    }   

    xcb_flush(connection);
    free(reply);
}
静态无效寄存器\u事件(xcb\u窗口\u t窗口){
xcb\u void\u cookie\u t cookie=xcb\u change\u window\u attributes\u checked(连接,
窗口,XCB_连续事件_掩码,(uint32_t[]){XCB_事件_掩码_子结构_通知| XCB_事件_掩码_指针_运动| XCB_事件_掩码_离开窗口});
xcb_generic_error_t*error=xcb_请求检查(连接、cookie);
if(错误!=NULL){
xcb_断开(连接);
errx(退出失败,“无法订阅窗口上的事件,退出”);
}   
}
静态无效寄存器\现有\窗口(无效){
xcb_查询_树_回复_t*回复;
if((reply=xcb\u query\u tree\u reply(连接,xcb\u query\u tree(连接,根),0))==NULL){
返回;
}   
int len=xcb_查询_树_子元素_长度(回复);
xcb_window_t*children=xcb_query_tree_children(应答);
对于(int i=0;i
Chrome窗口似乎完全由嵌套子窗口树组成。看来您需要遍历窗口树并监视所有窗口。此代码在我的整个Chrome窗口中拾取指针运动事件:

#include <stdio.h>
#include <stdlib.h>
#include <xcb/xcb.h>
#include <X11/Xlib.h>

static void register_events(xcb_connection_t *conn,
                            xcb_window_t window) {
  xcb_void_cookie_t cookie =
    xcb_change_window_attributes_checked(conn,
                                         window, XCB_CW_EVENT_MASK,
                                         (uint32_t[]) {
                                           XCB_EVENT_MASK_POINTER_MOTION });
  xcb_generic_error_t *error = xcb_request_check(conn, cookie);
  if (error != NULL) {
    xcb_disconnect(conn);
    exit(-1);
  }
}

static void register_existing_windows(xcb_connection_t *conn,
                                      xcb_window_t root) {
  int i, len;
  xcb_window_t *children;
  xcb_query_tree_reply_t *reply;
  if ((reply = xcb_query_tree_reply(conn,
                                    xcb_query_tree(conn, root), 0))
      == NULL)
    {
      return;
    }

  len = xcb_query_tree_children_length(reply);
  children = xcb_query_tree_children(reply);
  for (i = 0; i < len; i++) {
    register_events(conn, children[i]);
    register_existing_windows(conn, children[i]);
  }

  xcb_flush(conn);
}

void main(void) {
  int i=0;

  /* Open the connection to the X server */
  xcb_connection_t *conn = xcb_connect (NULL, NULL);

  /* Get the first screen */
  xcb_screen_t *screen = xcb_setup_roots_iterator (xcb_get_setup (conn)).data;

  register_existing_windows(conn, screen->root);

  while(1) {
    xcb_generic_event_t *evt;
    evt = xcb_wait_for_event(conn);
    printf("%i\n", i++);
  }
}
#包括
#包括
#包括
#包括
静态无效寄存器\u事件(xcb\u连接\u t*conn,
xcb_窗口(t窗口){
xcb\u void\u cookie\u t cookie=
xcb_更改_窗口_属性_检查(连接,
窗口,XCB\U CW\U事件\U掩码,
(uint32_t[){
XCB_事件_掩码_指针_运动});
xcb_generic_error_t*error=xcb_request_check(连接,cookie);
if(错误!=NULL){
xcb_断开(连接);
出口(-1);
}
}
静态无效寄存器\u现有\u窗口(xcb\u连接\u t*conn,
xcb_窗口(根){
int i,len;
xcb_window_t*儿童;
xcb_查询_树_回复_t*回复;
如果((reply=xcb\u query\u tree\u reply)(conn,
xcb_查询_树(连接,根,0))
==空)
{
返回;
}
len=xcb_查询_树_子项_长度(回复);
children=xcb\u查询树\u子项(应答);
对于(i=0;i根);
而(1){
xcb_通用事件_t*evt;
evt=xcb_等待_事件(conn);
printf(“%i\n”,i++);
}
}

(这只是为了证明概念,不是很好。)

虽然@Jay Kominek的回答很有帮助和有效,但我现在意识到使用Xinput扩展提供了更好的方法,因为它不会干扰任何应用程序


简单地在整个树上选择会导致各种问题,例如,hover不再在Chrome中工作。

xcb提供xcb\u grab\u指针来捕获指针事件,而不在特定窗口上注册

#include <stdlib.h>
#include <stdio.h>

#include <xcb/xcb.h>

void
print_modifiers (uint32_t mask)
{
  const char **mod, *mods[] = {
    "Shift", "Lock", "Ctrl", "Alt",
    "Mod2", "Mod3", "Mod4", "Mod5",
    "Button1", "Button2", "Button3", "Button4", "Button5"
  };
  printf ("Modifier mask: ");
  for (mod = mods ; mask; mask >>= 1, mod++)
    if (mask & 1)
      printf(*mod);
  putchar ('\n');
}

int
main ()
{
  xcb_connection_t    *c;
  xcb_screen_t        *screen;
  xcb_window_t         win;
  xcb_generic_event_t *e;
  uint32_t             mask = 0;

  /* Open the connection to the X server */
  c = xcb_connect (NULL, NULL);

  /* Get the first screen */
  screen = xcb_setup_roots_iterator (xcb_get_setup (c)).data;

  mask = XCB_EVENT_MASK_BUTTON_PRESS   |
              XCB_EVENT_MASK_BUTTON_RELEASE | XCB_EVENT_MASK_POINTER_MOTION;

  xcb_grab_pointer(c, false, screen->root, mask, XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC, XCB_NONE, XCB_NONE, XCB_CURRENT_TIME);

  xcb_flush (c);

  while ((e = xcb_wait_for_event (c))) {
    switch (e->response_type & ~0x80) {
    case XCB_BUTTON_PRESS: {
      xcb_button_press_event_t *ev = (xcb_button_press_event_t *)e;
      print_modifiers(ev->state);

      switch (ev->detail) {
      case 4:
        printf ("Wheel Button up in window %ld, at coordinates (%d,%d)\n",
                ev->event, ev->event_x, ev->event_y);
        break;
      case 5:
        printf ("Wheel Button down in window %ld, at coordinates (%d,%d)\n",
                ev->event, ev->event_x, ev->event_y);
        break;
      default:
        printf ("Button %d pressed in window %ld, at coordinates (%d,%d)\n",
                ev->detail, ev->event, ev->event_x, ev->event_y);
      }
      break;
    }
    case XCB_BUTTON_RELEASE: {
      xcb_button_release_event_t *ev = (xcb_button_release_event_t *)e;
      print_modifiers(ev->state);

      printf ("Button %d released in window %ld, at coordinates (%d,%d)\n",
              ev->detail, ev->event, ev->event_x, ev->event_y);
      break;
    }
    case XCB_MOTION_NOTIFY: {
      xcb_motion_notify_event_t *ev = (xcb_motion_notify_event_t *)e;

      printf ("Mouse moved in window %ld, at coordinates (%d,%d)\n",
              ev->event, ev->event_x, ev->event_y);
      break;
    }
    default:
      /* Unknown event type, ignore it */
      printf("Unknown event: %d\n", e->response_type);
      break;
    }
    /* Free the Generic Event */
    free (e);
  }

  return 0;
}
#包括
#包括
#包括
无效的
打印修改器(uint32遮罩)
{
常量字符**mod,*mods[]={
“Shift”、“Lock”、“Ctrl”、“Alt”,
“Mod2”、“Mod3”、“Mod4”、“Mod5”,
“按钮1”、“按钮2”、“按钮3”、“按钮4”、“按钮5”
};
printf(“修改器掩码:”);
对于(mod=mods;掩码;掩码>>=1,mod++)
如果(掩码和1)
printf(*mod);
putchar('\n');
}
int
主要()
{
xcb_连接_t*c;
xcb_screen_t*屏幕;
xcb_window_t win;
一般事件;
uint32_t mask=0;
/*打开与X服务器的连接*/
c=xcb_connect(空,空);
/*进入第一屏*/
screen=xcb_setup_root_迭代器(xcb_get_setup(c))。数据;
掩码=XCB\u事件\u掩码\u按钮\u按下|
XCB_事件_掩码_按钮_释放| XCB_事件_掩码_指针_运动;
xcb_抓取_指针(c,false,screen->root,mask,xcb_抓取_MODE_ASYNC,xcb_抓取_MODE_ASYNC,xcb_NONE,xcb_NONE,xcb_CURRENT_TIME);
xcb_冲洗(c);
而((e=xcb_等待_事件(c))){
开关(e->响应类型&~0x80){
外壳XCB按钮按下:{
xcb按钮按下事件ev=(xcb按钮按下事件ev*)e;
打印修改器(ev->state);
开关(电动汽车->详图){
案例4:
printf(“在窗口%ld的坐标(%d,%d)处向上旋转按钮)\n”,
电动汽车->事件,电动汽车->事件x,电动汽车->事件y);
打破
案例5:
printf(“在窗口%ld的坐标(%d,%d)处按下滚轮按钮)\n”,
电动汽车->事件,电动汽车->事件x,电动汽车->事件y);
打破
违约:
printf(“在坐标(%d,%d)\n处的窗口%ld中按下按钮%d”,
电动汽车->细节,电动汽车->事件,电动汽车->事件x,电动汽车->事件y);
}
打破
}
案例十