2017-04-25 39 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實際上想要做什麼的問題。 –