2015-01-12 132 views
0

我試圖用Xlib來控制Xterm。 爲此,我製作了一個帶有奇怪標題的Xterm。列出所有窗口並檢查他們的名字後。但是,我的Xterm的列表中沒有出現任何列表時出現的錯誤。下面是列出所有窗口的代碼:Xlib測試窗口名稱

void CMD::getWindowTerminal() 
{ 
    Atom a = XInternAtom(m_display, "_NET_CLIENT_LIST", true); 
    Atom actualType; 
    int format; 
    unsigned long numItems, bytesAfter; 
    unsigned char *data = 0; 
    int status = XGetWindowProperty(m_display, m_root_win, a, 0L, (~0L), false, 
           AnyPropertyType, &actualType, &format, &numItems, 
           &bytesAfter, &data); 

    if (status >= Success && numItems) 
    { 
     long *array = (long*) data; 
     for (unsigned long k = 0; k < numItems; k++) 
     { 
      // get window Id: 
      Window w = (Window) array[k]; 

      char* name = '\0'; 
      status = XFetchName(m_display, w, &name); 
      if (status >= Success) 
      { 
       std::cout << w << " " << name << std::endl; 
       if (name == NULL) 
       { 
        m_window_terminal = w; 
        std::cout << "TERMINAL FOUND" << std::endl; 
       } 
      } 
      XFree(name); 
     } 
     XFree(data); 
    } 
} 

回答

2

我無法重現錯誤;你的代碼找到我的xterm窗口。你在查詢你剛剛產生的xterm窗口嗎?如果是這樣,您可能會遇到競爭狀況,因爲您在xterm有機會創建它之前嘗試查找窗口。在這種情況下,一個糟糕的解決方案就是稍等一會再嘗試幾次。如果不是這種情況,我只能推測(更多)關於原因(我的猜測涉及行爲異常的窗口管理器或非常舊的軟件),但也許我可以提出一個解決方案:如果xterm不顯示在根窗口的_NET_CLIENT_LIST中,讓我們直接進入窗口樹,看看我們能否在那裏找到它。 C代碼,此位(移植到C++不應該是困難的,反正這足以嘗試一下)與XQueryTree遍歷窗口樹遞歸,所以它查詢所有窗口:

#include <stddef.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <unistd.h> 

#include <X11/Xlib.h> 
#include <X11/Xatom.h> 
#include <X11/keysym.h> 

Window window_from_name_search(Display *display, Window current, char const *needle) { 
    Window retval, root, parent, *children; 
    unsigned children_count; 
    char *name = NULL; 

    /* Check if this window has the name we seek */ 
    if(XFetchName(display, current, &name) > 0) { 
    int r = strcmp(needle, name); 
    XFree(name); 
    if(r == 0) { 
     return current; 
    } 
    } 

    retval = 0; 

    /* If it does not: check all subwindows recursively. */ 
    if(0 != XQueryTree(display, current, &root, &parent, &children, &children_count)) { 
    unsigned i; 
    for(i = 0; i < children_count; ++i) { 
     Window win = window_from_name_search(display, children[i], needle); 

     if(win != 0) { 
     retval = win; 
     break; 
     } 
    } 

    XFree(children); 
    } 

    return retval; 
} 

// frontend function: open display connection, start searching from the root window. 
Window window_from_name(char const *name) { 
    Display *display = XOpenDisplay(NULL); 
    Window w = window_from_name_search(display, XDefaultRootWindow(display), name); 
    XCloseDisplay(display); 
    return w; 
} 

,因爲它處理所有窗口,你的xterm窗口必須在其中。如果不是,請參考開始(關於可能的競爭條件的位)。如果不是這樣,那麼有些奇怪。

+0

重啓後Xterm出現在列表中。當程序關閉時,我需要解放使用的Window的內存?如果我需要我該怎麼做?謝謝。 – loustak

+0

經過對你的代碼進行了一些測試後,有時他沒有找到控制檯,因爲我認爲X服務器創建窗口,但不更新窗口列表。不是? – loustak

+0

這到底是什麼情況?你的代碼有時沒有找到窗口,或者我的代碼,或者兩者兼而有之?當你搜索它的代碼正在運行時,你有多確定窗口是完全構建的? – Wintermute

0

搜索後,如果我不添加一個cout該功能不起作用,爲什麼? 我在這裏添加了一個cout:

if(XFetchName(display, current, &name) > 0) { 
     int r = strcmp(needle, name); 
     std::cout << current << " : " << name << std::endl; 
     XFree(name); 
     if(r == 0) { 
      return current; 
     } 
}