【问题标题】:C - Xlib - BadWindow Error using XGetWindowProperty for window titleC - Xlib - BadWindow 错误使用 XGetWindowProperty 作为窗口标题
【发布时间】:2014-10-10 12:45:39
【问题描述】:

我想在 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

所以我想知道是否有人知道是什么导致了这个/如何解决它?

据我所知,列表函数正在返回一些我无法检索其名称的窗口,但我不确定。

提前致谢!

【问题讨论】:

  • 使用此处列出的代码,第 14 行产生编译器警告“预期为 'long unsigned int *' 但参数类型为 'long unsigned int **'”,然后是 main 中的 len(行后38) 为 0,循环未运行。我将参数 (#10) 从 &amp;len 更改为 len (因为它已经作为指针传递给 list() ),它编译时没有警告,并产生了所需的输出而没有错误。
  • 在另一个测试中,我在循环之前插入了一个sleep(),让我有时间关闭一个打开的窗口,并且错误已经重现。

标签: c window xlib


【解决方案1】:

根据我的 cmets,问题中列出了代码,我收到编译器警告:

在函数“列表”中:14:29:警告:传递参数 10 来自不兼容指针类型的“XGetWindowProperty”[由 默认]

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

在包含的文件中...: /usr/include/X11/Xlib.h:2688:12:注意:预期为“long unsigned int ”,但参数类型为“long unsigned int *

通过从第 10 个参数中删除地址操作符,将 &amp;len 更改为 len,因为它作为 unsigned long *len 被传递给 list(),从而解决了这个问题。

注意:在name() 函数中,由于它被声明为unsigned long len,因此必须使用地址运算符。

因此,我从以下代码开始,编译时没有警告:

#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 ) 应该踢出无效的窗口句柄,但实际上并非如此。此外,将if( !window ) 测试插入name() 函数本身同样是徒劳的。

但是,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

希望这可以帮助您开始... )

【讨论】:

  • 非常感谢您的详细解答!!!仍然试图让我的头脑围绕 Xlib!是的,这行得通,但是当它开始看起来我可能根本得不到答案时,我调查了其他替代方案并使用 XQueryTree 编写了一个解决方案!我把这个问题留到了,因为我很好奇是什么导致了这个问题,所以希望现在我可以把它当作一个学术练习。有趣的是,运行您的代码,我没有收到任何错误,也没有 (null)s。也许只是编译器警告导致它?我真的希望不会,如果是的话,我会觉得很愚蠢......再次感谢您的帮助! :D
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-09-10
  • 1970-01-01
  • 1970-01-01
  • 2015-07-21
  • 1970-01-01
  • 2012-02-10
相关资源
最近更新 更多