Re: Problem in cairo + xcb where alpha blending is cumulative (becoming more opaque with each render)
Uli Schlachter <[email protected]> Thu, 27 Sep 2018 09:56:01 +0200
| Newsgroups | gmane.comp.lib.cairo |
|---|---|
| Message-ID | <[email protected]> |
Hi, On 26.09.2018 07:51, Ryan Flannery wrote: > The raw transparency piece works fine and is > easy in cairo + xcb, sorry to tell you this, but the problem is in the raw transparency part. You only *think* that you have transparency. Also, "is easy" is the total opposite of the truth. Again, sorry. When a new window is mapped, its content is undefined. In practice this means that the window contains whatever was visible at this position before. Thus, you think you have transparency when you draw ontop of this. However, this is wrong. Try apply the attached patch move.patch. What this patch does is to wait for the window to become visible and then it moves the window. You will notice that together with the window, its content is moved. Thus, making it obvious that your transparency does not work. The black background that you see is the working case *if your window had an alpha channel*. Because it does not have an alpha channel, you only see black. To create a transparent window in X11, first of all, the user has to be using a compositing manager (compiz, compton, xcompmgr, ...). Without this, there is no real transparency. The _NET_WM_CMs selection can be used to figure out if a compositing manager is running. Next, you need to create a window with a 32bit visual (and also tell cairo that your window is using this visual). For this part, I refer you to: https://stackoverflow.com/questions/3645632/how-to-create-a-window-with-a-bit-depth-of-32 The attached patch fix.patch gives me a window with either a black background (if no compositing manager is running) or a transparent black background (if a compositing manager is running; I used compton). Cheers, Uli -- Sent from my Game Boy. -- cairo mailing list [email protected] https://lists.cairographics.org/mailman/listinfo/cairo
move.patch
(text/x-diff, 3 KB)
--- cairo_example.c.orig 2018-09-27 09:37:28.775992348 +0200
+++ cairo_example.c 2018-09-27 09:54:32.519404799 +0200
@@ -119,6 +119,8 @@ main()
xcb_map_window(xcon, xwindow);
cairo_clear_background();
xcb_flush(xcon);
+ sleep(1);
+ xcb_configure_window(xcon, xwindow, XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y, (uint32_t[]) { 300, 300 });
/* begin main draw loop */
for (int i = 0; i < 11; i++) {
@@ -137,9 +139,9 @@ main()
/* END: pop group/buffer (exposing it) and render */
cairo_pop_group_to_source(cairo);
- /*cairo_set_operator(cairo, CAIRO_OPERATOR_SOURCE); XXX Makes the background black (?) */
+ cairo_set_operator(cairo, CAIRO_OPERATOR_SOURCE);
cairo_paint(cairo);
- /*cairo_set_operator(cairo, CAIRO_OPERATOR_OVER); only done if th eprevious cairo_set_operator() is done */
+ cairo_set_operator(cairo, CAIRO_OPERATOR_OVER);
xcb_flush(xcon);
sleep(1);
}
@@ -170,12 +172,12 @@ get_xvisual(xcb_screen_t *screen)
{
xcb_depth_iterator_t i = xcb_screen_allowed_depths_iterator(screen);
for (; i.rem; xcb_depth_next(&i)) {
+ if (i.data->depth != 32)
+ continue;
xcb_visualtype_iterator_t vi;
vi = xcb_depth_visuals_iterator(i.data);
for (; vi.rem; xcb_visualtype_next(&vi)) {
- if (screen->root_visual == vi.data->visual_id) {
- return vi.data;
- }
+ return vi.data;
}
}
@@ -256,16 +258,13 @@ wm_hints()
xatoms[NET_WM_STRUT_PARTIAL], XCB_ATOM_CARDINAL, 32, 12, struts);
xcb_change_property(xcon, XCB_PROP_MODE_REPLACE, xwindow,
xatoms[NET_WM_STRUT], XCB_ATOM_CARDINAL, 32, 4, struts);
-
- /* remove window from window manager tabbing */
- const uint32_t val[] = { 1 };
- xcb_change_window_attributes(xcon, xwindow,
- XCB_CW_OVERRIDE_REDIRECT, val);
}
void
setup_xcb()
{
+ xcb_colormap_t colormap;
+
xcon = xcb_connect(NULL, &default_screen);
if (xcb_connection_has_error(xcon)) {
xcb_disconnect(xcon);
@@ -278,23 +277,29 @@ setup_xcb()
if (NULL == (xvisual = get_xvisual(xscreen)))
errx(1, "Failed to retrieve X visual context");
- static uint32_t valwin[2] = {
+ colormap = xcb_generate_id(xcon);
+ xcb_create_colormap(xcon, XCB_COLORMAP_ALLOC_NONE, colormap, xscreen->root, xvisual->visual_id);
+
+ uint32_t valwin[5] = {
XCB_NONE,
- XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_BUTTON_PRESS
+ 0,
+ 1,
+ XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_BUTTON_PRESS,
+ colormap
};
xwindow = xcb_generate_id(xcon);
xcb_create_window(
xcon,
- XCB_COPY_FROM_PARENT,
+ 32,
xwindow,
xscreen->root,
x, y,
y, h,
1, /* border width */
XCB_WINDOW_CLASS_INPUT_OUTPUT,
- xscreen->root_visual,
- XCB_CW_EVENT_MASK | XCB_CW_BACK_PIXMAP,
+ xvisual->visual_id,
+ XCB_CW_BACK_PIXMAP | XCB_CW_BORDER_PIXEL | XCB_CW_OVERRIDE_REDIRECT | XCB_CW_EVENT_MASK | XCB_CW_COLORMAP,
valwin);
wm_hints();
fix.patch
(text/x-diff, 3 KB)
--- cairo_example.c.orig 2018-09-27 09:37:28.775992348 +0200
+++ cairo_example.c 2018-09-27 09:54:32.519404799 +0200
@@ -119,6 +119,8 @@ main()
xcb_map_window(xcon, xwindow);
cairo_clear_background();
xcb_flush(xcon);
+ sleep(1);
+ xcb_configure_window(xcon, xwindow, XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y, (uint32_t[]) { 300, 300 });
/* begin main draw loop */
for (int i = 0; i < 11; i++) {
@@ -137,9 +139,9 @@ main()
/* END: pop group/buffer (exposing it) and render */
cairo_pop_group_to_source(cairo);
- /*cairo_set_operator(cairo, CAIRO_OPERATOR_SOURCE); XXX Makes the background black (?) */
+ cairo_set_operator(cairo, CAIRO_OPERATOR_SOURCE);
cairo_paint(cairo);
- /*cairo_set_operator(cairo, CAIRO_OPERATOR_OVER); only done if th eprevious cairo_set_operator() is done */
+ cairo_set_operator(cairo, CAIRO_OPERATOR_OVER);
xcb_flush(xcon);
sleep(1);
}
@@ -170,12 +172,12 @@ get_xvisual(xcb_screen_t *screen)
{
xcb_depth_iterator_t i = xcb_screen_allowed_depths_iterator(screen);
for (; i.rem; xcb_depth_next(&i)) {
+ if (i.data->depth != 32)
+ continue;
xcb_visualtype_iterator_t vi;
vi = xcb_depth_visuals_iterator(i.data);
for (; vi.rem; xcb_visualtype_next(&vi)) {
- if (screen->root_visual == vi.data->visual_id) {
- return vi.data;
- }
+ return vi.data;
}
}
@@ -256,16 +258,13 @@ wm_hints()
xatoms[NET_WM_STRUT_PARTIAL], XCB_ATOM_CARDINAL, 32, 12, struts);
xcb_change_property(xcon, XCB_PROP_MODE_REPLACE, xwindow,
xatoms[NET_WM_STRUT], XCB_ATOM_CARDINAL, 32, 4, struts);
-
- /* remove window from window manager tabbing */
- const uint32_t val[] = { 1 };
- xcb_change_window_attributes(xcon, xwindow,
- XCB_CW_OVERRIDE_REDIRECT, val);
}
void
setup_xcb()
{
+ xcb_colormap_t colormap;
+
xcon = xcb_connect(NULL, &default_screen);
if (xcb_connection_has_error(xcon)) {
xcb_disconnect(xcon);
@@ -278,23 +277,29 @@ setup_xcb()
if (NULL == (xvisual = get_xvisual(xscreen)))
errx(1, "Failed to retrieve X visual context");
- static uint32_t valwin[2] = {
+ colormap = xcb_generate_id(xcon);
+ xcb_create_colormap(xcon, XCB_COLORMAP_ALLOC_NONE, colormap, xscreen->root, xvisual->visual_id);
+
+ uint32_t valwin[5] = {
XCB_NONE,
- XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_BUTTON_PRESS
+ 0,
+ 1,
+ XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_BUTTON_PRESS,
+ colormap
};
xwindow = xcb_generate_id(xcon);
xcb_create_window(
xcon,
- XCB_COPY_FROM_PARENT,
+ 32,
xwindow,
xscreen->root,
x, y,
y, h,
1, /* border width */
XCB_WINDOW_CLASS_INPUT_OUTPUT,
- xscreen->root_visual,
- XCB_CW_EVENT_MASK | XCB_CW_BACK_PIXMAP,
+ xvisual->visual_id,
+ XCB_CW_BACK_PIXMAP | XCB_CW_BORDER_PIXEL | XCB_CW_OVERRIDE_REDIRECT | XCB_CW_EVENT_MASK | XCB_CW_COLORMAP,
valwin);
wm_hints();