Discussion:
[Xcb] Window transparency and clearing a window
Sheheryar Parvaz
2017-10-09 22:49:08 UTC
Permalink
Hi,


I'm using Cairo with the XCB backend for rendering, to create a docking window. However, I'd like the bar to have transparency but can't seem to figure out how to make the window transparent and/or clear the window.


For transparency, I can't seem to figure out how to make the window transparent. Even pseudo-transparency would be fine. I've heard of the possibility of copying the root pixmap, but have no idea how to do so.


Every time Cairo draws to the surface, it overwrites what was previously there. This is probably due to the fact that the window isn't truly transparent, and so isn't being cleared.


Could someone explain how to create a transparent XCB window or simulate it?
Uli Schlachter
2017-10-13 18:06:44 UTC
Permalink
Hi,

first of: This is not really a XCB question, but I guess there aren't
that many questions where one can ask X11 questions.

On 10.10.2017 00:49, Sheheryar Parvaz wrote:
[...]
> For transparency, I can't seem to figure out how to make the window transparent. Even pseudo-transparency would be fine. I've heard of the possibility of copying the root pixmap, but have no idea how to do so.

For pseudo-transparency, the convention is to save the pixmap XID in the
_XROOTPMAP_ID (or ESETROOT_PMAP_ID) property of the root window. With
that, you can just copy the contents of this pixmap to your window. To
handle changes to the background, you'd have to monitor PropertyNotify
message on the root window to get informed when the value of this
property changes.

If this property is not there, you are out of luck.

[...]> Every time Cairo draws to the surface, it overwrites what was
previously there. This is probably due to the fact that the window isn't
truly transparent, and so isn't being cleared.
>
>
> Could someone explain how to create a transparent XCB window or simulate it?

You want a window with depth 32. If you have that (and correctly tell
cairo about it), you can just cairo to draw a transparent background
[1]. Note that this only works if a compositing manager is running,
otherwise the visible results will be equivalent to a black background
(I think). The convention to check if a compositing manager is running
is to check if the _NET_WM_CM_Sn selection is owned. See ICCCM for
details (or be lazy and copy from [2], but please honour the GPL).

Cheers,
Uli

[1]: cairo_set_source_rgba(cr, 0, 0, 0, 0); cairo_set_operator(cr,
CAIRO_OPERATOR_SOURCE); cairo_paint(cr);
[2]:
https://github.com/awesomeWM/awesome/blob/a1376557917a8859222c49f59ba42373c02905c7/luaa.c#L179-L211
--
- He made himself, me nothing, you nothing out of the dust
- Er machte sich mir nichts, dir nichts aus dem Staub
Sheheryar Parvaz
2017-10-17 01:04:37 UTC
Permalink
First of all, thank you very much for your response, it is very helpful since documentation on X11 is hard to find. In my case, I want to be able to use pseudo-transparency and true transparency depending on what is available, so help on both methods is appreciated.


> You want a window with depth 32. If you have that (and correctly tell
> cairo about it), you can just cairo to draw a transparent background
> [1].


For true transparency, I can't seem to set the depth properly using xcb_create_window(...), since I have no idea what unit the depth parameter is even supposed to be! Giving it 32 does not work, the only value that seems to work for me is XCB_COPY_FROM_PARENT. Essentially, I have no idea if my window already has a depth of 32-bit or not.

I'm assuming it isn't since cairo seems to be drawing a black background. By the way, the only mask I have set is CW_EVENT_MASK. This could be the reason why, but I have no idea.


I am also having trouble thinking about how to do pseudo-transparency. For now, I am copying the root pixmap to the window, then telling cairo to draw over it, using the default cairo operator. However, once the root pixmap changes, I would have to copy the pixmap then redo the drawing process. This is not the most efficient way, and I'm curious as to if there is a better way that I haven't though of.


Thank you again, and hopefully this is the right place to discuss this.

________________________________
Ingo Bürk
2017-10-17 19:46:35 UTC
Permalink
Hi,

> since documentation on X11 is hard to find
Yes, and IMHO the best approach is to find software doing what you want
to do and see how they do it – when it comes to windows, window managers
might be a good choice (such as awesome or i3, shameless plug for Uli
and me here).

Another thing to watch out for with (true) transparency is that you need
to define both a back pixel and a border pixel in the window attributes.
I'm not sure whether this changed in recent releases of Xorg, but it
used to be the case. See [1], beautifully demonstrating that even Uli
went through these problems before, albeit many years ago. :-)

> For true transparency, I can't seem to set the depth properly using
> xcb_create_window(...), since I have no idea what unit the depth
> parameter is even supposed to be! Giving it 32 does not work, the only
> value that seems to work for me is XCB_COPY_FROM_PARENT.
As I mentioned above, just look at the code of existing software. For
the case of i3 (only one of many!), you will find what you're looking
for in x_con_init() in src/x.c.

> Essentially, I have no idea if my window already has a depth of 32-bit
> or not.
You can check the depth of a window using "xwininfo -frame", for example.

> However, once the root pixmap changes, I would have to copy the pixmap
> then redo the drawing process.
Well, that's the nature of fake transparency. It doesn't do well with
changing backgrounds, in particular quickly changing backgrounds. It
will always look sloppy; it's fake transparency, after all. If you want
it to be correct, use true transparency (requiring compositing). There's
only so much you can do.

> I'm curious as to if there is a better way that I haven't though of.
One improvement you could make is to render your window's content to a
separate pixmap (or, in this case, cairo surface) and do the same for
the root window. When the background changes, you don't need to rerender
your own content, but only overlay the updated background and your
content's surface.

There's certainly a lot one can do, but I wouldn't bother with that
quite yet. Drawing a few rectangles and some text isn't so expensive
that any machine from this decade should have serious problem with it,
assuming you've done everything else correctly. X11 protocol can be
frickle, especially if you don't understand it, so I'd focus on getting
an understanding of how it works and how your client should behave
first; also to ensure it actually adheres to the specifications.

[1] https://stackoverflow.com/questions/3645632


Regards

Ingo


On 10/17/2017 03:04 AM, Sheheryar Parvaz wrote:
>
> First of all, thank you very much for your response, it is very
> helpful since documentation on X11 is hard to find. In my case, I want
> to be able to use pseudo-transparency and true transparency depending
> on what is available, so help on both methods is appreciated.
>
>
> > You want a window with depth 32. If you have that (and correctly tell
> > cairo about it), you can just cairo to draw a transparent background
> > [1].
>
>
> For true transparency, I can't seem to set the depth properly using
> xcb_create_window(...), since I have no idea what unit the depth
> parameter is even supposed to be! Giving it 32 does not work, the only
> value that seems to work for me is XCB_COPY_FROM_PARENT. Essentially,
> I have no idea if my window already has a depth of 32-bit or not.
>
> I'm assuming it isn't since cairo seems to be drawing a black
> background. By the way, the only mask I have set is CW_EVENT_MASK.
> This could be the reason why, but I have no idea.
>
>
> I am also having trouble thinking about how to do pseudo-transparency.
> For now, I am copying the root pixmap to the window, then telling
> cairo to draw over it, using the default cairo operator. However, once
> the root pixmap changes, I would have to copy the pixmap then redo the
> drawing process. This is not the most efficient way, and I'm curious
> as to if there is a better way that I haven't though of.
>
>
> Thank you again, and hopefully this is the right place to discuss this.
> ------------------------------------------------------------------------
>
>
> _______________________________________________
> Xcb mailing list
> ***@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/xcb
Loading...