window 经理:wm 为 运行 时,新启动的应用程序不可见

window manager: Newly launched applications are not visible while the wm is running

TL;DR

我正在编写一个简单的重设 window 管理器。我正在 Xephyr 的帮助下对其进行测试。虽然 window 管理器是 运行,但在此期间启动的任何应用程序都不会在屏幕上显示(不可见),而在 window 管理器启动之前启动的任何应用程序都会显示(可见)。

完整问题

我正在编写一个简单的重设 window 管理器。目前我只处理两个事件 XCB_CREATE_NOTIFYXCB_BUTTON_PRESS。我已经在根 window.

上注册了 XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECTXCB_EVENT_MASK_EXPOSURE

我正在用 Xephyr 测试 wm。并且在测试 wm 启动后启动的任何应用程序时,不会在屏幕上显示(不可见),而在启动 wm 之前启动的应用程序会完美显示(可见)。

我在某处读到,在根 window 上注册 EXPOSURE 事件可以解决问题,但对我来说似乎并非如此。下面是我的 CREATE_NOTIFY 事件代码,它试图重新设置客户端 window 的父级并将其映射到屏幕上(我认为这是我做错的地方):

case XCB_CREATE_NOTIFY:
    {
        xcb_create_notify_event_t *cre;
        cre = (xcb_create_notify_event_t *)evt;

        xcb_window_t frame = xcb_generate_id(conn);
        uint32_t frameMask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
        uint32_t fM_values[2];
        fM_values[0] = custTeal->pixel; //custTeal is a custom Teal color that I've defined
        fM_values[1] = XCB_EVENT_MASK_BUTTON_PRESS | XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_POINTER_MOTION;

        xcb_window_t toBeMapped = cre->window;
        xcb_get_geometry_reply_t *tbm_window_geo = xcb_get_geometry_reply(conn,xcb_get_geometry(conn,toBeMapped),NULL);

        xcb_create_window(conn,0,frame,screen->root,tbm_window_geo->x,tbm_window_geo->y,(tbm_window_geo->width+4),(tbm_window_geo->height+4),1,XCB_WINDOW_CLASS_INPUT_OUTPUT,screen->root_visual,frameMask,fM_values);

        xcb_reparent_window(conn,toBeMapped,frame,2,2);

        xcb_map_window(conn,frame);
        xcb_map_window(conn,toBeMapped);

        xcb_flush(conn);
    }
    break;

我不知道我做错了什么(我对此很陌生)。 我是否也必须处理 EXPOSE 事件?我该如何处理?

测试

我正在使用

启动 Xephyr
Xephyr -br -ac -noreset -screen 1240x720 :2 &

并启动新的应用程序(以 xterm 为例):

DISPLAY=:2 xterm &

现在,在启动 wm 之前启动的任何应用程序(或 wm 不是 运行 时)都可以在 Xephyr 中完美显示。但是我启动wm后,启动任何应用程序都不显示。

SubstructureRedirect 意味着当其他东西试图映射 window 时,X11 服务器反而生成一个 MapRequest 事件并将其发送到 WM。因此,您应该处理 XCB_MAP_REQUEST 事件。最简单的方法是 xcb_map_window 来自事件的 window。