如何为深度为 32 的 window 设置不透明背景

How to set an opaque background for window with depth=32

在我的重新设置 window 管理器中,我有一些代码可以创建框架 window:

let screen = &self.conn.setup().roots[self.scrno];
        let geom = self.conn.get_geometry(ev.window)?.reply()?;
        let attr = self.conn.get_window_attributes(ev.window)?.reply()?;
        let frame_win = self.conn.generate_id()?;
        let frame_cmap = self.conn.generate_id()?;
        self.conn.create_colormap(
            xproto::ColormapAlloc::NONE,
            frame_cmap,
            ev.window,
            attr.visual,
        )?;
        self.conn
            .change_property32(
                xproto::PropMode::REPLACE,
                ev.window,
                self.net_atoms[ewmh::Net::WMWindowOpacity as usize],
                xproto::AtomEnum::CARDINAL,
                &[1],
            )?
            .check()?;
        let win_aux = xproto::CreateWindowAux::new()
            .event_mask(
                xproto::EventMask::EXPOSURE
                    | xproto::EventMask::SUBSTRUCTURE_REDIRECT
                    | xproto::EventMask::SUBSTRUCTURE_NOTIFY
                    | xproto::EventMask::BUTTON_PRESS
                    | xproto::EventMask::BUTTON_RELEASE
                    | xproto::EventMask::POINTER_MOTION
                    | xproto::EventMask::ENTER_WINDOW
                    | xproto::EventMask::PROPERTY_CHANGE,
            )
            .background_pixel(self.config.background_pixel)
            .border_pixel(self.config.border_pixel)
            .colormap(frame_cmap);
        self.conn.create_window(
            geom.depth,
            frame_win,
            screen.root,
            geom.x,
            geom.y,
            geom.width,
            geom.height + self.config.title_height as u16,
            self.config.border_width as u16,
            xproto::WindowClass::INPUT_OUTPUT,
            attr.visual,
            &win_aux,
        )?;

我 运行 遇到的问题是当 attr.depth 是 32 时(我尊重它而不是 COPY_FROM_PARENT 以便透明度起作用,参见 ),框架window 也最终变得透明。那不是我想要的。 (当然,只有当合成器是运行ning时)

如果 background_pixel 是纯色,为什么 window 背景是透明的,我该如何解决这个问题?

尝试删除这段代码:

        self.conn
            .change_property32(
                xproto::PropMode::REPLACE,
                ev.window,
                self.net_atoms[ewmh::Net::WMWindowOpacity as usize],
                xproto::AtomEnum::CARDINAL,
                &[1],
            )?
            .check()?;

由于您已经在查看 AwesomeWM 代码(您在另一个答案中这么说),这里是它的一段代码(针对这个答案稍微简化了;我只删除了一些 ifs):

void
xwindow_set_opacity(xcb_window_t win, double opacity)
{
            uint32_t real_opacity = opacity * 0xffffffff;
            xcb_change_property(globalconf.connection, XCB_PROP_MODE_REPLACE, win,
                                _NET_WM_WINDOW_OPACITY, XCB_ATOM_CARDINAL, 32, 1L, &real_opacity);
}

您可能会从此代码中猜到,“完全透明”的值为零,“完全不透明”的值为 0xffffffff。您将此 属性 设置为值 1,对应于约 .000000023 百分比不透明的百分比值。对我来说听起来“几乎完全透明”。

我不再那么确定我的第一个答案,但我会再试一次。

你写:

Why is the window background transparent if background_pixel is a solid color, and how do I remedy the issue?

“是纯色”到底是什么意思,这种纯色从何而来?尝试使用 0xffffffff 作为该值,看看是否可以正常工作。在任何正常的 X11 服务器上,这应该是“完全不透明的白色”。

既然你在看 Awesome 的源代码,那就看看它的 color.c。一个 alpha 组件被固定在 X11 的设计上。因此,“所有 X11”假装透明度不存在。 color.c 中有一条关于它如何猜测放置 alpha 组件的位置的评论。

我希望大多数 X11 服务器使用像 0xAARRGGBB 这样的像素值,例如0x80ff0000 将是半透明的红色。但这是一个比 color.c 更糟糕的猜测。