如何等到窗口被映射和可见

And*_*eas 6 c linux x11 xlib

等待X11窗口映射和查看的正确方法是什么?确切地说,我想等到我可以安全地调用XSetInputFocus()而不会遇到以下错误导致X服务器回火的任何风险:

// X Error of failed request:  BadMatch (invalid parameter attributes)
// Major opcode of failed request:  42 (X_SetInputFocus)    
Run Code Online (Sandbox Code Playgroud)

目前这种错误经常发生,尤其是在慢速X服务器上或者在使用libXrandr更改了监视器分辨率后立即尝试打开新窗口时.

我已经有了这个问题的解决方案,但它非常hacky因为它轮询window属性所以我想知道是否有更清洁的版本.

这是我目前的做法:

static Bool predicate(Display *display, XEvent *ev, XPointer arg)
{
    return(ev->type == MapNotify);
}

static void waitmapnotify(struct osdisplayinfo *osd)
{
    XEvent ev;
    XWindowAttributes xwa;

    XPeekIfEvent(osd->display, &ev, predicate, NULL);

    do {
        XGetWindowAttributes(osd->display, osd->window, &xwa);
        usleep(1);
    } while(xwa.map_state != IsViewable);   
}
Run Code Online (Sandbox Code Playgroud)

这段代码工作得很好,但它很hacky所以我在这里讨论它 - 以防万一有一个更干净的方式来做这件事.

ser*_*ico 0

据我所知,X11 lib 没有公开任何用于 X11 事件处理的回调机制。(一旦了解了事件过滤模型,您就可以轻松构建自己的事件过滤模型)

您可能想要在 X11 事件队列上循环,因为我认为为此目的而设计应该更有效。此外,您可以配置事件过滤器,以便您仅获取特定窗口感兴趣的事件。

一个有用的(尽管已过时)链接可能是: Linux Journal X11 教程检查第二页,了解有关安装过滤器和从 X11 队列获取事件的示例。