2017-04-25 385 views
1

使用XCB获取活动窗口(具有输入焦点的窗口)的正确方法是什么?使用XCB获取活动窗口的WId

reply = xcb_get_input_focus_reply(connection, xcb_get_input_focus(connection), nullptr); 
std::cout << "WId: " << reply->focus; 

这似乎是工作有时,有时不。

我还看到有人提到查询_NET_ACTIVE_WINDOW根窗口属性,但我无法弄清楚这是如何完成的,并且总是支持XCB?

编辑:该方法上面xcb_get_input_focus只是其中的一部分,得到了reply->焦点后,您需要通过xcb_query_tree跟进父窗口。

回答

2

该解决方案适用于我,它或多或少地从一些X11代码迁移到XCB。基本上得到焦点窗口,并跟踪父窗口的路径,直到窗口ID等于父或根ID,这就是顶层窗口。

WId ImageGrabber::getActiveWindow() 
{ 
    xcb_connection_t* connection = QX11Info::connection(); 
    xcb_get_input_focus_reply_t* focusReply; 
    xcb_query_tree_cookie_t treeCookie; 
    xcb_query_tree_reply_t* treeReply; 

    focusReply = xcb_get_input_focus_reply(connection, xcb_get_input_focus(connection), nullptr); 
    xcb_window_t window = focusReply->focus; 
    while (1) { 
     treeCookie = xcb_query_tree(connection, window); 
     treeReply = xcb_query_tree_reply(connection, treeCookie, nullptr); 
     if (!treeReply) { 
      window = 0; 
      break; 
     } 
     if (window == treeReply->root || treeReply->parent == treeReply->root) { 
      break; 
     } else { 
      window = treeReply->parent; 
     } 
     free(treeReply); 
    } 
    free(treeReply); 
    return window; 
} 
+0

此代码是越野车。你应该抓住所有这些服务器,否则当你通过树时输入焦点可能会改变。请参阅XGrabServer/xcb_grab_server。 –

+0

作为参考,可以看一下[this](https://github.com/i3/i3/blob/next/i3-input/main.c#L320),其中服务器是在输入焦点操作周围抓取的。 –

+0

感谢您指出这一点,确实是一个有效的观点。 所以基本上我需要'xcb_grab_server(conn)'服务器在开始时和'xcb_ungrab_server(conn)'当我完成并找到父项? –

2

据我所知,EWMH兼容窗口管理器预计将根窗口的属性设置为当前活动窗口的窗口ID。

为了得到它,

  1. 使用xcb_intern_atom以获取
  2. 原子值获取根窗口ID,例如使用xcb_setup_roots_iterator(xcb_get_setup(connection)).data->root
  3. 使用xcb_get_property,xcb_get_property_replyxcb_get_property_value来获取根窗口属性的值。

的类型为CARDINAL,对于XCB目的,它的大小为32位。

或者您可以使用libxcb-ewmh将此任务包装到xcb_ewmh_get_active_window函数中。

+0

也许你可以提供一个解决方案的例子吗?我无法实现它。据我所知,'xcb_intern_atom'可以用来检查原子'_NET_ACTIVE_WINDOW'的状态,但是应该在什么窗口使用? –

+0

为了完整起见,'xcb_intern_atom'只返回给定命名原子的'xcb_atom_t'值(你应该通过它''_NET_ACTIVE_WINDOW“'和'strlen(”_ NET_ACTIVE_WINDOW“)')。 传递根窗口,得到的原子作为要获取的属性,并将'XCB_ATOM_CARDINAL'作为其类型到'xcb_get_property'获取'xcb_get_property_cookie_t'。将cookie传递给'xcb_get_property_reply'以获得'xcb_get_property_reply_t *'。 WID将是'*(uint32_t *)xcb_get_property_value(...)';不要忘记释放回复。 – aitap

+0

绝大多数依靠EWMH的案例都是正确的方法和你想要的。然而,EWMH提示并不一定要引用当前具有输入焦点的窗口(而且通常不会),所以这是@dporobic实际上想要做什么的问题。 –