Search code examples
xorgxcb

I get drawing artifacts when drawing onto a transparent xcb window. How do I fix this?


Illustratory image

I am trying to create transparent windows with xcb and have the transparency information be provided by a compositor.

I have succeeded in creating transparent windows, and drawing to them with cairo, however, my problem should be self-explanatory in the image I provided.
For some reason, I am getting artifacts in the second window from the first window. I don't know how to fix this exactly.

Here's the lua code I am using:

local init_x = 80
local init_y = 280
local init_width = 300
local init_height = 200

local win_id = swin.create(init_x, init_y, init_width, init_height)
local pix_id = spixmap.create(init_width, init_height)

local surf = scairo.create_from_pixmap(pix_id, init_width, init_height)
local lsurf = lgi.cairo.Surface(surf, true)
local cr = lgi.cairo.Context(lsurf)

-- the source operator should use data from the compositor
cr:set_operator(lgi.cairo.Operator.SOURCE)
-- paint the window transparent. 
cr:paint_with_alpha(0.0)

cr:rectangle(0, 0, 40, 40)
cr:set_source_rgb(0.8, 0.1, 0.8)
cr:fill()

swin.map(win_id)
spixmap.draw_portion_to_window(pix_id, win_id, 0, 0, init_width, init_height)

The lua code is obviously a simplification of the C code, but nonetheless, I don't think I am doing anything wrong.

I would add more details, but I don't want to pollute the post. If you want to know something, ask, and I will edit my post.


Solution

  • Could it be that you are seeing garbage from uninitialised memory? Specifically, when you send a CreatePixmap request, the X11 server just allocates memory, but does not initialise it in any way.

    I have to admit I do not quite understand what your Lua code is doing, but the following comment raised a red flag:

    -- paint the window transparent. 
    cr:paint_with_alpha(0.0)
    

    The comment suggests that you think that makes the cairo surface completely transparent (fills everything with alpha=0). But instead, this line just does not do anything at all.

    To clear a cairo surface to transparent, you want:

    cr:set_operator(lgi.cairo.Operator.CLEAR)
    cr:paint()