Search code examples
x11xlibxcb

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


In my reparenting window manager I have some code to create a frame 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,
        )?;

The issue I run into is that when attr.depth is 32 (I respect it instead of COPY_FROM_PARENT so that transparency works, see Opacity in a reparenting WM), the frame window also ends up being transparent. That is not what I want. (of course, only when a compositor is running)

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


Solution

  • I am no longer so sure about my first answer, but I'll take another stab at this.

    You write:

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

    What exactly does "is a solid color" mean and where does this solid color come from? Try using 0xffffffff for this value and see if this makes things work. This should be "completely opaque white" on any sane X11 server.

    Since you are looking at Awesome's source code, look at its color.c. An alpha component was bolted on to X11's design. Thus, "all of X11" pretends that transparency does not exist. There is a comment in color.c about how it guesses where to place the alpha component.

    I expect that most X11 servers use pixel values like 0xAARRGGBB, so e.g. 0x80ff0000 would be semi-transparent red. But this is a worse guess than what color.c does.