You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于Xcb的自定义WM中根窗口背景在startx+picom下不显示的问题求助

解决窗口管理器搭配Picom时根窗口背景不显示的问题

结合你的代码和现象分析,问题核心是Picom等合成器接管屏幕渲染后,你的背景更新流程没有触发合成器的重绘,且pixmap被提前销毁导致合成器无法读取数据。以下是具体修复方案:

1. 延迟销毁Pixmap,确保合成器完成采样

你当前在设置背景后立即调用tsoil.destroy(s)销毁pixmap,但Picom可能还没完成从pixmap读取像素数据就被释放了——这就是为什么关闭WM时合成器重新扫描资源会短暂闪现背景。

修改Lua代码,延迟销毁pixmap,比如用GLib定时器(如果你的WM集成了GLib):

local function set_wallpaper_from_path(path)
    -- ... 原有代码 ...

    root.set_wallpaper_by_pixmap_id(s.pixmap_id)
    print(s.cr.status)

    -- 延迟2秒销毁,给Picom足够时间采样
    lgi.GLib.Timeout.add_seconds(2, function()
        tsoil.destroy(s)
        return false -- 只执行一次
    end)
end

或者如果你的WM有退出回调,也可以把pixmap销毁逻辑放在WM退出时执行,避免提前释放。

2. 发送_NET_WM_WALLPAPER客户端消息通知合成器

Picom依赖X的客户端消息来感知根窗口背景变化,仅修改窗口属性和调用xcb_clear_area不足以触发合成器重绘。在你的C代码中添加发送该消息的逻辑:

#include <string.h>

int luaS_root_set_wallpaper_by_pixmap_id(lua_State *L)
{
    xcb_pixmap_t pixmap_id = luaL_checkinteger(L, 1);

    // 原有设置背景pixmap的代码
    xcb_change_window_attributes(
        ss.connection,
        ss.screen->root,
        XCB_CW_BACK_PIXMAP,
        &pixmap_id
    );

    // 修改exposures参数为1,触发Expose事件
    xcb_clear_area(
        ss.connection,
        1, // 改为1,强制触发Expose
        ss.screen->root,
        0, 0, 0, 0
    );

    // 发送_NET_WM_WALLPAPER消息通知合成器
    xcb_intern_atom_cookie_t atom_cookie = xcb_intern_atom(ss.connection, 0, strlen("_NET_WM_WALLPAPER"), "_NET_WM_WALLPAPER");
    xcb_intern_atom_reply_t *atom_reply = xcb_intern_atom_reply(ss.connection, atom_cookie, NULL);
    if (atom_reply) {
        xcb_client_message_event_t evt = {
            .response_type = XCB_CLIENT_MESSAGE,
            .format = 32,
            .window = ss.screen->root,
            .type = atom_reply->atom,
            .data.data32[0] = pixmap_id,
            .data.data32[1] = 0, // 刷新整个屏幕
            .data.data32[2] = 0,
            .data.data32[3] = 0,
            .data.data32[4] = 0
        };
        xcb_send_event(ss.connection, 0, ss.screen->root, 
                       XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT | XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY, 
                       (const char*)&evt);
        free(atom_reply);
    }

    xcb_flush(ss.connection); // 确保事件立即发送到X服务器
    return 0;
}

建议提前在WM初始化时获取_NET_WM_WALLPAPER的atom,避免每次调用都重复查询,提升效率。

3. 确保Pixmap的视觉格式与根窗口匹配

如果tsoil.create内部创建pixmap时使用的视觉格式(深度、颜色空间)和根窗口不匹配,Picom可能无法正确渲染。检查tsoil.create的实现,确保使用根窗口的参数:

// 示例:tsoil_create内部创建pixmap的正确方式
xcb_pixmap_t tsoil_create(int width, int height) {
    return xcb_create_pixmap(
        ss.connection,
        ss.screen->root_depth, // 使用根窗口的深度
        width, height,
        ss.screen->root // 以根窗口为参考,继承视觉属性
    );
}

验证方案

按上述步骤修改后,重新编译WM并搭配Picom启动:

  • 背景应该能正常显示,不会再出现黑屏
  • 关闭WM时也不会有短暂闪现的问题(因为Pixmap在延迟后销毁,合成器已完成采样)

内容的提问来源于stack exchange,提问作者DesertCarMechanic

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 04:35:59