[英]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.