Opaque elements in transparent window in Xorg

131 Views Asked by At

I am developing a simple X11 application with cairo and xcb. I was wondering if there is any way to to put fully opaque elements (for example icons) in a window with a transparent background.

For the transparency I am using _NET_WM_WINDOW_OPACITY. I am also using the shape extension for a custom shape.

Note that I don't want a fully transparent window, but a certain opacity in the background with opaque icons/text.

This is where I create the window

    const uint32_t value_mask = XCB_CW_BACK_PIXMAP | XCB_CW_BACK_PIXEL | XCB_CW_BORDER_PIXEL
                              | XCB_CW_OVERRIDE_REDIRECT | XCB_CW_EVENT_MASK | XCB_CW_COLORMAP;

    const uint32_t event_mask = XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_STRUCTURE_NOTIFY
                              | XCB_EVENT_MASK_KEY_PRESS | XCB_EVENT_MASK_FOCUS_CHANGE
                              | XCB_EVENT_MASK_BUTTON_RELEASE | XCB_EVENT_MASK_BUTTON_PRESS;

    xcb_colormap_t colormap = xcb_generate_id(win->con->connection);
    xcb_create_colormap(win->con->connection, XCB_COLORMAP_ALLOC_NONE, colormap, win->con->screen->root, win->con->visual_type->visual_id);

    const uint32_t value_list[] = {
        XCB_NONE,   // back pixmap
        0x00000000, // back pixel
        0x00000000, // border pixel
        true,       // override redirect
        event_mask, // event mask
        colormap    // colormap
    };

    win->window = xcb_generate_id(win->con->connection);
    xcb_create_window(win->con->connection,
                      XCB_COPY_FROM_PARENT,
                      win->window, win->con->screen->root,
                      win->x, win->y,
                      win->width, win->height,
                      0, // border
                      XCB_WINDOW_CLASS_INPUT_OUTPUT,
                      win->con->screen->root_visual,
                      value_mask,
                      value_list);

This is where I create a buffer with cairo

    cairo_surface_t *surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height);

    cairo_t *cr = cairo_create(surface);
    cairo_set_fill_rule(cr, CAIRO_FILL_RULE_EVEN_ODD);
    cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);

    double alpha = 0.8;

    cairo_set_source_rgba(cr, 0.3, 0.3, 0.3, alpha);
    cairo_paint(cr);
//...

And finally this is where I paint the window

    cairo_xcb_surface_set_size(win->surface, width, height);
    xcb_clear_area(win->con->connection, false, win->window, 0, 0, 0, 0);

    cairo_set_source_surface(win->cr, surface, 0, 0);
    cairo_paint(win->cr);
    cairo_show_page(win->cr);


0

There are 0 best solutions below