From b013e9aeaf6a7bd584bea69283dd45dbc3e008ac Mon Sep 17 00:00:00 2001 From: Yuxuan Shui Date: Sat, 13 Apr 2024 11:48:36 +0100 Subject: [PATCH] Default to only use ARGB visual for ARGB client windows Don't use the same visual for all windows. And add a --full-argb option to force ARGB visual for all windows, which is the current default behavior. Fixes #2408 --- awesome.c | 32 +++++++++++++++++--------------- color.c | 2 +- draw.c | 4 ++-- globalconf.h | 27 ++++++++++++++++++++------- objects/client.c | 40 ++++++++++++++++++++++++++++------------ objects/client.h | 2 +- objects/drawable.c | 8 +++++--- objects/drawable.h | 6 +++++- objects/drawin.c | 18 ++++++++++++++---- objects/window.c | 2 +- objects/window.h | 2 ++ options.c | 4 ++++ options.h | 1 + root.c | 8 ++++---- systray.c | 2 +- 15 files changed, 106 insertions(+), 52 deletions(-) diff --git a/awesome.c b/awesome.c index 2b17c725f..1ae586236 100644 --- a/awesome.c +++ b/awesome.c @@ -693,21 +693,23 @@ main(int argc, char **argv) if(xcb_connection_has_error(globalconf.connection)) fatal("cannot open display (error %d)", xcb_connection_has_error(globalconf.connection)); + if (!(default_init_flags & INIT_FLAG_ARGB)) + globalconf.argb_mode = ARGB_MODE_DISABLED; + else if (default_init_flags & INIT_FLAG_FULL_ARGB) + globalconf.argb_mode = ARGB_MODE_FULL; + else + globalconf.argb_mode = ARGB_MODE_ENABLED; globalconf.screen = xcb_aux_get_screen(globalconf.connection, globalconf.default_screen); - globalconf.default_visual = draw_default_visual(globalconf.screen); - if(default_init_flags & INIT_FLAG_ARGB) - globalconf.visual = draw_argb_visual(globalconf.screen); - if(!globalconf.visual) - globalconf.visual = globalconf.default_visual; - globalconf.default_depth = draw_visual_depth(globalconf.screen, globalconf.visual->visual_id); - globalconf.default_cmap = globalconf.screen->default_colormap; - if(globalconf.default_depth != globalconf.screen->root_depth) + globalconf.screen_visual = draw_default_visual(globalconf.screen); + globalconf.screen_depth = draw_visual_depth(globalconf.screen, globalconf.screen_visual->visual_id); + globalconf.screen_cmap = globalconf.screen->default_colormap; + if (globalconf.argb_mode != ARGB_MODE_DISABLED) { - // We need our own color map if we aren't using the default depth - globalconf.default_cmap = xcb_generate_id(globalconf.connection); + globalconf.argb_visual = draw_argb_visual(globalconf.screen); + globalconf.argb_cmap = xcb_generate_id(globalconf.connection); xcb_create_colormap(globalconf.connection, XCB_COLORMAP_ALLOC_NONE, - globalconf.default_cmap, globalconf.screen->root, - globalconf.visual->visual_id); + globalconf.argb_cmap, globalconf.screen->root, + globalconf.argb_visual->visual_id); } #ifdef WITH_XCB_ERRORS @@ -815,10 +817,10 @@ main(int argc, char **argv) * The window_no_focus is used for "nothing has the input focus". */ globalconf.focus.window_no_focus = xcb_generate_id(globalconf.connection); globalconf.gc = xcb_generate_id(globalconf.connection); - xcb_create_window(globalconf.connection, globalconf.default_depth, + xcb_create_window(globalconf.connection, globalconf.screen_depth, globalconf.focus.window_no_focus, globalconf.screen->root, -1, -1, 1, 1, 0, - XCB_COPY_FROM_PARENT, globalconf.visual->visual_id, + XCB_COPY_FROM_PARENT, globalconf.screen_visual->visual_id, XCB_CW_BACK_PIXEL | XCB_CW_BORDER_PIXEL | XCB_CW_OVERRIDE_REDIRECT | XCB_CW_COLORMAP, (const uint32_t []) @@ -826,7 +828,7 @@ main(int argc, char **argv) globalconf.screen->black_pixel, globalconf.screen->black_pixel, 1, - globalconf.default_cmap + globalconf.screen_cmap }); xwindow_set_class_instance(globalconf.focus.window_no_focus); xwindow_set_name_static(globalconf.focus.window_no_focus, "Awesome no input window"); diff --git a/color.c b/color.c index 53e7f1a7f..8f6ae81b7 100644 --- a/color.c +++ b/color.c @@ -159,7 +159,7 @@ color_init_unchecked(color_t *color, const char *colstr, ssize_t len, xcb_visual return req; } req.cookie_hexa = xcb_alloc_color_unchecked(globalconf.connection, - globalconf.default_cmap, + globalconf.screen_cmap, RGB_8TO16(red), RGB_8TO16(green), RGB_8TO16(blue)); diff --git a/draw.c b/draw.c index 83d3d3559..3b16d715d 100644 --- a/draw.c +++ b/draw.c @@ -242,10 +242,10 @@ uint8_t draw_visual_depth(const xcb_screen_t *s, xcb_visualid_t vis) void draw_test_cairo_xcb(void) { xcb_pixmap_t pixmap = xcb_generate_id(globalconf.connection); - xcb_create_pixmap(globalconf.connection, globalconf.default_depth, pixmap, + xcb_create_pixmap(globalconf.connection, globalconf.screen_depth, pixmap, globalconf.screen->root, 1, 1); cairo_surface_t *surface = cairo_xcb_surface_create(globalconf.connection, - pixmap, globalconf.visual, 1, 1); + pixmap, globalconf.screen_visual, 1, 1); if(cairo_surface_status(surface) != CAIRO_STATUS_SUCCESS) fatal("Could not set up display: got cairo surface with status %s", cairo_status_to_string(cairo_surface_status(surface))); diff --git a/globalconf.h b/globalconf.h index 970849bf5..cdd787971 100644 --- a/globalconf.h +++ b/globalconf.h @@ -77,6 +77,15 @@ ARRAY_TYPE(xproperty_t, xproperty) DO_ARRAY(sequence_pair_t, sequence_pair, DO_NOTHING) DO_ARRAY(xcb_window_t, window, DO_NOTHING) +enum argb_mode { + /** No window will be created with an ARGB visual */ + ARGB_MODE_DISABLED = 0, + /** Client window with an ARGB visual will be reparented an ARGB window */ + ARGB_MODE_ENABLED, + /** All windows will be created with an ARGB visual */ + ARGB_MODE_FULL +}; + /** Main configuration structure */ typedef struct { @@ -185,20 +194,24 @@ typedef struct } systray; /** The monitor of startup notifications */ SnMonitorContext *snmonitor; - /** The visual, used to draw */ - xcb_visualtype_t *visual; /** The screen's default visual */ - xcb_visualtype_t *default_visual; + xcb_visualtype_t *screen_visual; + /** An ARGB visual */ + xcb_visualtype_t *argb_visual; /** The screen's information */ xcb_screen_t *screen; /** A graphic context. */ xcb_gcontext_t gc; - /** Our default depth */ - uint8_t default_depth; - /** Our default color map */ - xcb_colormap_t default_cmap; + /** The screen's depth */ + uint8_t screen_depth; + /** The screen's default color map */ + xcb_colormap_t screen_cmap; + /** ARGB color map */ + xcb_colormap_t argb_cmap; /** Do we have to reban clients? */ bool need_lazy_banning; + /** Should we use ARGB visual for all windows? */ + enum argb_mode argb_mode; /** Tag list */ tag_array_t tags; /** List of registered xproperties */ diff --git a/objects/client.c b/objects/client.c index 6946dbc63..0e8bda088 100644 --- a/objects/client.c +++ b/objects/client.c @@ -1891,8 +1891,8 @@ client_get_nofocus_window(client_t *c) { if (c->nofocus_window == XCB_NONE) { c->nofocus_window = xcb_generate_id(globalconf.connection); - xcb_create_window(globalconf.connection, globalconf.default_depth, c->nofocus_window, c->frame_window, - -2, -2, 1, 1, 0, XCB_COPY_FROM_PARENT, globalconf.visual->visual_id, + xcb_create_window(globalconf.connection, globalconf.screen_depth, c->nofocus_window, c->frame_window, + -2, -2, 1, 1, 0, XCB_COPY_FROM_PARENT, globalconf.screen_visual->visual_id, 0, NULL); xcb_map_window(globalconf.connection, c->nofocus_window); xwindow_grabkeys(c->nofocus_window, &c->keys); @@ -2137,17 +2137,26 @@ client_manage(xcb_window_t w, xcb_get_geometry_reply_t *wgeom, xcb_get_window_at client_t *c = client_new(L); xcb_screen_t *s = globalconf.screen; + uint8_t depth = globalconf.screen_depth, window_depth = draw_visual_depth(globalconf.screen, wattr->visual); + xcb_colormap_t cmap = globalconf.screen_cmap; c->border_width_callback = (void (*) (void *, uint16_t, uint16_t)) border_width_callback; /* consider the window banned */ c->isbanned = true; /* Store window and visual */ c->window = w; - c->visualtype = draw_find_visual(globalconf.screen, wattr->visual); + c->client_visualtype = draw_find_visual(globalconf.screen, wattr->visual); c->frame_window = xcb_generate_id(globalconf.connection); - xcb_create_window(globalconf.connection, globalconf.default_depth, c->frame_window, s->root, + c->visualtype = globalconf.screen_visual; + if ((globalconf.argb_mode == ARGB_MODE_FULL || window_depth == 32) && globalconf.argb_mode != ARGB_MODE_DISABLED) + { + c->visualtype = globalconf.argb_visual; + depth = 32; + cmap = globalconf.argb_cmap; + } + xcb_create_window(globalconf.connection, depth, c->frame_window, s->root, wgeom->x, wgeom->y, wgeom->width, wgeom->height, - wgeom->border_width, XCB_COPY_FROM_PARENT, globalconf.visual->visual_id, + wgeom->border_width, XCB_COPY_FROM_PARENT, c->visualtype->visual_id, XCB_CW_BORDER_PIXEL | XCB_CW_BIT_GRAVITY | XCB_CW_WIN_GRAVITY | XCB_CW_OVERRIDE_REDIRECT | XCB_CW_EVENT_MASK | XCB_CW_COLORMAP, (const uint32_t []) @@ -2157,7 +2166,7 @@ client_manage(xcb_window_t w, xcb_get_geometry_reply_t *wgeom, xcb_get_window_at XCB_GRAVITY_NORTH_WEST, 1, FRAME_SELECT_INPUT_EVENT_MASK, - globalconf.default_cmap + cmap }); /* The client may already be mapped, thus we must be sure that we don't send @@ -3195,7 +3204,7 @@ client_set_icon_from_pixmaps(client_t *c, xcb_pixmap_t icon, xcb_pixmap_t mask) s_icon = cairo_xcb_surface_create_for_bitmap(globalconf.connection, globalconf.screen, icon, geom_icon_r->width, geom_icon_r->height); else - s_icon = cairo_xcb_surface_create(globalconf.connection, icon, globalconf.default_visual, + s_icon = cairo_xcb_surface_create(globalconf.connection, icon, globalconf.screen_visual, geom_icon_r->width, geom_icon_r->height); result = s_icon; @@ -3568,21 +3577,28 @@ client_refresh_partial(client_t *c, int16_t x, int16_t y, uint16_t width, uint16 static drawable_t * titlebar_get_drawable(lua_State *L, client_t *c, int cl_idx, client_titlebar_t bar) { + uint8_t depth = globalconf.screen_depth; + xcb_visualtype_t *visual = globalconf.screen_visual; + if (globalconf.argb_mode == ARGB_MODE_FULL) + { + visual = globalconf.argb_visual; + depth = 32; + } if (c->titlebar[bar].drawable == NULL) { cl_idx = luaA_absindex(L, cl_idx); switch (bar) { case CLIENT_TITLEBAR_TOP: - drawable_allocator(L, (drawable_refresh_callback *) client_refresh_titlebar_top, c); + drawable_allocator(L, depth, visual, (drawable_refresh_callback *) client_refresh_titlebar_top, c); break; case CLIENT_TITLEBAR_BOTTOM: - drawable_allocator(L, (drawable_refresh_callback *) client_refresh_titlebar_bottom, c); + drawable_allocator(L, depth, visual, (drawable_refresh_callback *) client_refresh_titlebar_bottom, c); break; case CLIENT_TITLEBAR_RIGHT: - drawable_allocator(L, (drawable_refresh_callback *) client_refresh_titlebar_right, c); + drawable_allocator(L, depth, visual, (drawable_refresh_callback *) client_refresh_titlebar_right, c); break; case CLIENT_TITLEBAR_LEFT: - drawable_allocator(L, (drawable_refresh_callback *) client_refresh_titlebar_left, c); + drawable_allocator(L, depth, visual, (drawable_refresh_callback *) client_refresh_titlebar_left, c); break; default: fatal("Unknown titlebar kind %d\n", (int) bar); @@ -4022,7 +4038,7 @@ luaA_client_get_content(lua_State *L, client_t *c) height -= c->titlebar[CLIENT_TITLEBAR_TOP].size + c->titlebar[CLIENT_TITLEBAR_BOTTOM].size; surface = cairo_xcb_surface_create(globalconf.connection, c->window, - c->visualtype, width, height); + c->client_visualtype, width, height); /* lua has to make sure to free the ref or we have a leak */ lua_pushlightuserdata(L, surface); diff --git a/objects/client.h b/objects/client.h index 70b05d195..2139f6cf0 100644 --- a/objects/client.h +++ b/objects/client.h @@ -173,7 +173,7 @@ struct client_t /** Size hints */ xcb_size_hints_t size_hints; /** The visualtype that c->window uses */ - xcb_visualtype_t *visualtype; + xcb_visualtype_t *client_visualtype; /** Do we honor the client's size hints? */ bool size_hints_honor; /** Machine the client is running on. */ diff --git a/objects/drawable.c b/objects/drawable.c index 0db78ca6a..a01df1e31 100644 --- a/objects/drawable.c +++ b/objects/drawable.c @@ -105,7 +105,7 @@ static lua_class_t drawable_class; LUA_OBJECT_FUNCS(drawable_class, drawable_t, drawable) drawable_t * -drawable_allocator(lua_State *L, drawable_refresh_callback *callback, void *data) +drawable_allocator(lua_State *L, uint8_t depth, xcb_visualtype_t *visual, drawable_refresh_callback *callback, void *data) { drawable_t *d = drawable_new(L); d->refresh_callback = callback; @@ -113,6 +113,8 @@ drawable_allocator(lua_State *L, drawable_refresh_callback *callback, void *data d->refreshed = false; d->surface = NULL; d->pixmap = XCB_NONE; + d->depth = depth; + d->visual = visual; return d; } @@ -147,10 +149,10 @@ drawable_set_geometry(lua_State *L, int didx, area_t geom) if (area_changed && geom.width > 0 && geom.height > 0) { d->pixmap = xcb_generate_id(globalconf.connection); - xcb_create_pixmap(globalconf.connection, globalconf.default_depth, d->pixmap, + xcb_create_pixmap(globalconf.connection, d->depth, d->pixmap, globalconf.screen->root, geom.width, geom.height); d->surface = cairo_xcb_surface_create(globalconf.connection, - d->pixmap, globalconf.visual, + d->pixmap, d->visual, geom.width, geom.height); luaA_object_emit_signal(L, didx, "property::surface", 0); } diff --git a/objects/drawable.h b/objects/drawable.h index 86bd0b696..f9bc51331 100644 --- a/objects/drawable.h +++ b/objects/drawable.h @@ -44,10 +44,14 @@ struct drawable_t drawable_refresh_callback *refresh_callback; /** Data for refresh callback. */ void *refresh_data; + /** Drawable depth */ + uint8_t depth; + /** Drawable visual */ + xcb_visualtype_t *visual; }; typedef struct drawable_t drawable_t; -drawable_t *drawable_allocator(lua_State *, drawable_refresh_callback *, void *); +drawable_t *drawable_allocator(lua_State *, uint8_t depth, xcb_visualtype_t *visual, drawable_refresh_callback *, void *); void drawable_set_geometry(lua_State *, int, area_t); void drawable_class_setup(lua_State *); diff --git a/objects/drawin.c b/objects/drawin.c index 3bbd93179..2ca61c839 100644 --- a/objects/drawin.c +++ b/objects/drawin.c @@ -416,6 +416,15 @@ drawin_allocator(lua_State *L) { xcb_screen_t *s = globalconf.screen; drawin_t *w = drawin_new(L); + uint8_t depth = globalconf.screen_depth; + xcb_visualtype_t *visual = globalconf.screen_visual; + xcb_colormap_t cmap = globalconf.screen_cmap; + if (globalconf.argb_mode == ARGB_MODE_FULL) + { + visual = globalconf.argb_visual; + cmap = globalconf.argb_cmap; + depth = 32; + } w->visible = false; @@ -425,15 +434,16 @@ drawin_allocator(lua_State *L) w->geometry.height = 1; w->geometry_dirty = false; w->type = _NET_WM_WINDOW_TYPE_NORMAL; + w->visualtype = visual; - drawable_allocator(L, (drawable_refresh_callback *) drawin_refresh_pixmap, w); + drawable_allocator(L, depth, visual, (drawable_refresh_callback *) drawin_refresh_pixmap, w); w->drawable = luaA_object_ref_item(L, -2, -1); w->window = xcb_generate_id(globalconf.connection); - xcb_create_window(globalconf.connection, globalconf.default_depth, w->window, s->root, + xcb_create_window(globalconf.connection, depth, w->window, s->root, w->geometry.x, w->geometry.y, w->geometry.width, w->geometry.height, - w->border_width, XCB_COPY_FROM_PARENT, globalconf.visual->visual_id, + w->border_width, XCB_COPY_FROM_PARENT, visual->visual_id, XCB_CW_BORDER_PIXEL | XCB_CW_BIT_GRAVITY | XCB_CW_OVERRIDE_REDIRECT | XCB_CW_EVENT_MASK | XCB_CW_COLORMAP | XCB_CW_CURSOR, @@ -448,7 +458,7 @@ drawin_allocator(lua_State *L) | XCB_EVENT_MASK_POINTER_MOTION | XCB_EVENT_MASK_BUTTON_PRESS | XCB_EVENT_MASK_BUTTON_RELEASE | XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_PROPERTY_CHANGE, - globalconf.default_cmap, + cmap, xcursor_new(globalconf.cursor_ctx, xcursor_font_fromstr(w->cursor)) }); xwindow_set_class_instance(w->window); diff --git a/objects/window.c b/objects/window.c index 371d06bcd..965916aba 100644 --- a/objects/window.c +++ b/objects/window.c @@ -195,7 +195,7 @@ luaA_window_set_border_color(lua_State *L, window_t *window) const char *color_name = luaL_checklstring(L, -1, &len); if(color_name && - color_init_reply(color_init_unchecked(&window->border_color, color_name, len, globalconf.visual))) + color_init_reply(color_init_unchecked(&window->border_color, color_name, len, window->visualtype))) { window->border_need_update = true; luaA_object_emit_signal(L, -3, "property::border_color", 0); diff --git a/objects/window.h b/objects/window.h index fbc5296cf..0e59d3da3 100644 --- a/objects/window.h +++ b/objects/window.h @@ -69,6 +69,8 @@ typedef enum color_t border_color; \ /** Border width */ \ uint16_t border_width; \ + /** The visual type */ \ + xcb_visualtype_t *visualtype; \ /** The window type */ \ window_type_t type; \ /** The border width callback */ \ diff --git a/options.c b/options.c index 3ef88b563..f10468265 100644 --- a/options.c +++ b/options.c @@ -418,6 +418,7 @@ options_check_args(int argc, char **argv, int *init_flags, string_array_t *paths { "screen" , ARG , NULL, 'm' }, { "api-level" , ARG , NULL, 'l' }, { "reap" , ARG , NULL, '\1' }, + { "full-argb" , NO_ARG, NULL, 'A' }, { NULL , NO_ARG, NULL, 0 } }; @@ -467,6 +468,9 @@ options_check_args(int argc, char **argv, int *init_flags, string_array_t *paths globalconf.had_overriden_depth = true; (*init_flags) &= ~INIT_FLAG_ARGB; break; + case 'A': + (*init_flags) |= INIT_FLAG_FULL_ARGB | INIT_FLAG_ARGB; + break; case 'r': (*init_flags) |= INIT_FLAG_REPLACE_WM; break; diff --git a/options.h b/options.h index 97e66e8c8..ee1372cdb 100644 --- a/options.h +++ b/options.h @@ -32,6 +32,7 @@ typedef enum { INIT_FLAG_AUTO_SCREEN = 0x1 << 3, INIT_FLAG_ALLOW_FALLBACK = 0x1 << 4, INIT_FLAG_FORCE_CMD_ARGS = 0x1 << 5, + INIT_FLAG_FULL_ARGB = 0x1 << 6, } awesome_init_config_t; char *options_detect_shebang(int argc, char **argv); diff --git a/root.c b/root.c index ef6aa2684..dcb4706c5 100644 --- a/root.c +++ b/root.c @@ -193,13 +193,13 @@ root_update_wallpaper(void) } /* Only the default visual makes sense, so just the default depth */ - if (geom_r->depth != draw_visual_depth(globalconf.screen, globalconf.default_visual->visual_id)) + if (geom_r->depth != draw_visual_depth(globalconf.screen, globalconf.screen_visual->visual_id)) warn("Got a pixmap with depth %d, but the default depth is %d, continuing anyway", - geom_r->depth, draw_visual_depth(globalconf.screen, globalconf.default_visual->visual_id)); + geom_r->depth, draw_visual_depth(globalconf.screen, globalconf.screen_visual->visual_id)); globalconf.wallpaper = cairo_xcb_surface_create(globalconf.connection, *rootpix, - globalconf.default_visual, + globalconf.screen_visual, geom_r->width, geom_r->height); @@ -530,7 +530,7 @@ luaA_root_get_content(lua_State *L) surface = cairo_xcb_surface_create(globalconf.connection, globalconf.screen->root, - globalconf.default_visual, + globalconf.screen_visual, globalconf.screen->width_in_pixels, globalconf.screen->height_in_pixels); diff --git a/systray.c b/systray.c index 99986549a..916bdf3f4 100644 --- a/systray.c +++ b/systray.c @@ -372,7 +372,7 @@ luaA_systray(lua_State *L) color_t bg_color; bool force_redraw = false; - if(color_init_reply(color_init_unchecked(&bg_color, bg, bg_len, globalconf.default_visual)) + if(color_init_reply(color_init_unchecked(&bg_color, bg, bg_len, globalconf.screen_visual)) && globalconf.systray.background_pixel != bg_color.pixel) { uint32_t config_back[] = { bg_color.pixel };