簡體   English   中英

C - Xlib - BadWindow使用XGetWindowProperty作為窗口標題時出錯

[英]C - Xlib - BadWindow Error using XGetWindowProperty for window title

我想在C中使用Xlib獲取所有打開窗口標題的列表。我正在運行Ubuntu 12.04。 我使用以下代碼來完成此任務:

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

Window *list(Display *disp, unsigned long *len)
{
    Atom prop = XInternAtom(disp, "_NET_CLIENT_LIST", False), type;
    int form;
    unsigned long remain;
    unsigned char *list;

    XGetWindowProperty(disp, XDefaultRootWindow(disp), prop, 0, 1024, False, XA_WINDOW,
                            &type, &form, &len, &remain, &list);
    return (Window *)list;
}
char *name(Display *disp, Window window)
{
    Atom prop = XInternAtom(disp, "WM_NAME", False), type;
    int form;
    unsigned long remain, len;
    unsigned char *list;

    XGetWindowProperty(disp, window, prop, 0, 1024, False, AnyPropertyType,
                            &type, &form, &len, &remain, &list);
    return (char*)list;
}
int main(int argc, char *argv[])
{
    Display *disp;
    Window *wlist;
    unsigned long len;
    char *wname;

    disp = XOpenDisplay(NULL);

    wlist = (Window*)list(disp, &len);

    int i;
    for(i = 0; i < (int)len; i++){
            if(wlist[i] != 0){
                    wname = name(disp, wlist[i]);
                    printf("%d: %s\n", i, wname);
                    free(wname);
            }
    }
return 0;
}

現在我遇到的問題是,這通過大多數窗口,然后給我一個BadWindow錯誤:

0: DNDCollectionWindow
1: launcher 
2: Desktop
3: panel
4: Dash
5: Hud
6: Switcher
7: Update Manager
8: Terminal
9: Ask a Question - Stack Overflow - Mozilla Firefox
X Error of failed request:  BadWindow (invalid Window parameter)
  Major opcode of failed request:  20 (X_GetProperty)
  Resource id in failed request:  0x41
  Serial number of failed request:  22
  Current serial number in output stream:  22

所以我想知道是否有人知道是什么導致了這個/如何解決它?

據我所知,list函數返回的是一些我無法檢索名稱的窗口,但我不確定。

提前致謝!

根據我的評論,由於代碼列在問題中,我收到編譯器警告:

在函數'list'中:14:29:警告:從不兼容的指針類型[默認啟用]傳遞'XGetWindowProperty'的參數10

  &type, &form, &len, &remain, &list); ^ 

在包含的文件中...:/usr/include/X11/Xlib.h:2688:12:注意:預期'long unsigned int '但參數類型為'long unsigned int * '

通過從第10個參數中刪除address-of運算符來修復,將&len更改為len ,因為它作為unsigned long *len傳遞給list()

注意:在name()函數中,因為它被聲明為unsigned long len ,所以需要address-of運算符。

因此,我開始使用以下代碼編譯而沒有警告:

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

Window *list(Display *disp, unsigned long *len)
{
    Atom prop = XInternAtom(disp, "_NET_CLIENT_LIST", False), type;
    int form;
    unsigned long remain;
    unsigned char *list;

    XGetWindowProperty(disp, XDefaultRootWindow(disp), prop, 0, 1024, False, XA_WINDOW,
                            &type, &form, len, &remain, &list);
    return (Window *)list;
}
char *name(Display *disp, Window window)
{
    Atom prop = XInternAtom(disp, "WM_NAME", False), type;
    int form;
    unsigned long remain, len;
    unsigned char *list;

    XGetWindowProperty(disp, window, prop, 0, 1024, False, AnyPropertyType,
                            &type, &form, &len, &remain, &list);
    return (char*)list;
}
int main(int argc, char *argv[])
{
    Display *disp;
    Window *wlist;
    unsigned long len;
    char *wname;

    disp = XOpenDisplay(NULL);

    wlist = (Window*)list(disp, &len);

    int i;
    for(i = 0; i < (int)len; i++){
            if(wlist[i] != 0){
                    wname = name(disp, wlist[i]);
                    printf("%d: %s\n", i, wname);
                    free(wname);
            }
    }
return 0;
}

最初我沒有得到BadWindow錯誤,所以我在第38行插入了sleep( 3 ) ,就在for循環之前,給了我足夠的時間關閉窗口以試圖復制行為。

果然,這再現了錯誤: BadWindow (invalid Window parameter)


掃描它最初出現的代碼if( wlist[i]==0 )應該踢出無效的窗口句柄,但事實並非如此。 另外,在name()函數本身插入if( !window )測試同樣是徒勞的。

但是,函數XSetErrorHandler可能有一些用處,我已經包含你的代碼,修改后,以顯示用法:

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

int catcher( Display *disp, XErrorEvent *xe )
{
        printf( "Something had happened, bruh.\n" );
        return 0;
}

Window *list(Display *disp, unsigned long *len)
{
    Atom prop = XInternAtom(disp, "_NET_CLIENT_LIST", False), type;
    int form;
    unsigned long remain;
    unsigned char *list;

    XGetWindowProperty(disp, XDefaultRootWindow(disp), prop, 0, 1024, False, XA_WINDOW,
                            &type, &form, len, &remain, &list);
    return (Window *)list;
}
char *name(Display *disp, Window window)
{
    Atom prop = XInternAtom(disp, "WM_NAME", False), type;
    int form;
    unsigned long remain, len;
    unsigned char *list;

    XGetWindowProperty(disp, window, prop, 0, 1024, False, AnyPropertyType,
                            &type, &form, &len, &remain, &list);
    return (char*)list;
}
int main(int argc, char *argv[])
{
    Display *disp;
    Window *wlist;
    unsigned long len;
    char *wname;

    disp = XOpenDisplay(NULL);

    wlist = (Window*)list(disp, &len);

    sleep( 3 ); // <-- inserted to give me time to close an open window

    XSetErrorHandler( catcher ); // <-- inserted to set error handler

    int i;
    for(i = 0; i < (int)len; i++){
    //        if(wlist[i] != 0){    // <-- apparently futile?
                    wname = name(disp, wlist[i]);
                    printf("%d: %s\n", i, wname);
                    free(wname);
    //        }
    }

    XSetErrorHandler( NULL ); // <-- restore the default error handler
    return 0;
}

我只是創建了一個小函數int catcher( Display*, XErrorEvent * )來捕獲錯誤,避免運行時終止。

如果你有更多的編碼要遵循,我已經包含了對XErrorHandler()的第二次調用,傳遞NULL以恢復默認處理程序。


其他一些注釋,首先通過殺死我創建的最后一個窗口來測試此代碼,但這還不足以確定它是否會在收到錯誤后繼續進行。 所以我做了第二次測試,其中我殺死了列表末尾之前的窗口,並驗證了成功。


最后幾點說明:

顯然錯誤處理程序過於簡化了。 捕獲錯誤時,將顯示該消息,程序將繼續運行。 但是,窗口項仍然打印,但反映為(null) ...

例如:

7: neo – Dolphin
8: neo – Dolphin
Something had happened, bruh.
9: (null)
10: neo – Dolphin

希望這可以讓你開始......我將留下有趣的部分,例如檢測“發生了什么錯誤”,並調整列表的編號/顯示對你來說;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM