From 71782da245b16d7566e7818ab8b41d8a1f9057ff Mon Sep 17 00:00:00 2001 From: Ivan Malison Date: Sun, 6 Aug 2023 17:51:18 -0600 Subject: [PATCH 01/17] Add nix flake --- flake.lock | 80 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ flake.nix | 34 +++++++++++++++++++++++ 2 files changed, 114 insertions(+) create mode 100644 flake.lock create mode 100644 flake.nix diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000000..6afc8e3eb4 --- /dev/null +++ b/flake.lock @@ -0,0 +1,80 @@ +{ + "nodes": { + "flake-utils": { + "inputs": { + "systems": "systems" + }, + "locked": { + "lastModified": 1689068808, + "narHash": "sha256-6ixXo3wt24N/melDWjq70UuHQLxGV8jZvooRanIHXw0=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "919d646de7be200f3bf08cb76ae1f09402b6f9b4", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "git-ignore-nix": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1660459072, + "narHash": "sha256-8DFJjXG8zqoONA1vXtgeKXy68KdJL5UaXR8NtVMUbx8=", + "owner": "hercules-ci", + "repo": "gitignore.nix", + "rev": "a20de23b925fd8264fd7fad6454652e142fd7f73", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "ref": "master", + "repo": "gitignore.nix", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1691186842, + "narHash": "sha256-wxBVCvZUwq+XS4N4t9NqsHV4E64cPVqQ2fdDISpjcw0=", + "path": "/nix/store/d42v5grfq77vr10r336kks0qjp0wij8d-source", + "rev": "18036c0be90f4e308ae3ebcab0e14aae0336fe42", + "type": "path" + }, + "original": { + "id": "nixpkgs", + "type": "indirect" + } + }, + "root": { + "inputs": { + "flake-utils": "flake-utils", + "git-ignore-nix": "git-ignore-nix", + "nixpkgs": "nixpkgs" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000000..76c0db06c1 --- /dev/null +++ b/flake.nix @@ -0,0 +1,34 @@ +{ + inputs = { + flake-utils.url = github:numtide/flake-utils; + git-ignore-nix = { + url = github:hercules-ci/gitignore.nix/master; + inputs.nixpkgs.follows = "nixpkgs"; + }; + }; + outputs = { + self, flake-utils, nixpkgs, git-ignore-nix, ... + }: flake-utils.lib.eachDefaultSystem (system: let + overlay = self: super: { + picom = super.picom.overrideAttrs (oldAttrs: rec { + pname = "picom"; + buildInputs = [ + self.pcre2 self.xorg.xcbutil + ] ++ self.lib.remove self.xorg.libXinerama ( + self.lib.remove self.pcre oldAttrs.buildInputs + ); + src = git-ignore-nix.lib.gitignoreSource ./.; + }); + }; + pkgs = import nixpkgs { inherit system overlays; config.allowBroken = true; }; + overlays = [ overlay ]; + in rec { + inherit overlay overlays; + defaultPackage = pkgs.picom; + devShell = defaultPackage.overrideAttrs { + buildInputs = defaultPackage.buildInputs ++ [ + pkgs.clang-tools + ]; + }; + }); +} From 249f6818577287ccaf026b3b17da36c8a1331f24 Mon Sep 17 00:00:00 2001 From: Maxim Solovyov Date: Thu, 3 Aug 2023 00:48:57 +0300 Subject: [PATCH 02/17] backend: make target window a parameter of the init backend operation to address a todo --- src/backend/backend.h | 6 +----- src/backend/dummy/dummy.c | 3 ++- src/backend/gl/egl.c | 4 ++-- src/backend/gl/glx.c | 4 ++-- src/backend/xrender/xrender.c | 4 ++-- src/diagnostic.c | 2 +- src/picom.c | 3 ++- 7 files changed, 12 insertions(+), 14 deletions(-) diff --git a/src/backend/backend.h b/src/backend/backend.h index 3ed7a761a8..fd3212f1f6 100644 --- a/src/backend/backend.h +++ b/src/backend/backend.h @@ -119,11 +119,7 @@ struct backend_operations { // =========== Initialization =========== /// Initialize the backend, prepare for rendering to the target window. - /// Here is how you should choose target window: - /// 1) if ps->overlay is not XCB_NONE, use that - /// 2) use ps->root otherwise - // TODO(yshui) make the target window a parameter - backend_t *(*init)(session_t *)attr_nonnull(1); + backend_t *(*init)(session_t *, xcb_window_t)attr_nonnull(1); void (*deinit)(backend_t *backend_data) attr_nonnull(1); /// Called when rendering will be stopped for an unknown amount of diff --git a/src/backend/dummy/dummy.c b/src/backend/dummy/dummy.c index 4e3d713873..5e6f13cf9f 100644 --- a/src/backend/dummy/dummy.c +++ b/src/backend/dummy/dummy.c @@ -28,7 +28,8 @@ struct dummy_data { struct backend_image mask; }; -struct backend_base *dummy_init(struct session *ps attr_unused) { +struct backend_base * +dummy_init(struct session *ps attr_unused, xcb_window_t target attr_unused) { auto ret = (struct backend_base *)ccalloc(1, struct dummy_data); ret->c = &ps->c; ret->loop = ps->loop; diff --git a/src/backend/gl/egl.c b/src/backend/gl/egl.c index a78c1903da..1156dd5922 100644 --- a/src/backend/gl/egl.c +++ b/src/backend/gl/egl.c @@ -130,7 +130,7 @@ static bool egl_set_swap_interval(int interval, EGLDisplay dpy) { /** * Initialize OpenGL. */ -static backend_t *egl_init(session_t *ps) { +static backend_t *egl_init(session_t *ps, xcb_window_t target) { bool success = false; struct egl_data *gd = NULL; @@ -212,7 +212,7 @@ static backend_t *egl_init(session_t *ps) { // clang-format on gd->target_win = eglCreatePlatformWindowSurfaceProc( - gd->display, config, (xcb_window_t[]){session_get_target_window(ps)}, NULL); + gd->display, config, (xcb_window_t[]){target}, NULL); if (gd->target_win == EGL_NO_SURFACE) { log_error("Failed to create EGL surface."); goto end; diff --git a/src/backend/gl/glx.c b/src/backend/gl/glx.c index 681bd17470..cb55d4d9b0 100644 --- a/src/backend/gl/glx.c +++ b/src/backend/gl/glx.c @@ -227,13 +227,13 @@ static bool glx_set_swap_interval(int interval, Display *dpy, GLXDrawable drawab /** * Initialize OpenGL. */ -static backend_t *glx_init(session_t *ps) { +static backend_t *glx_init(session_t *ps, xcb_window_t target) { bool success = false; glxext_init(ps->c.dpy, ps->c.screen); auto gd = ccalloc(1, struct _glx_data); init_backend_base(&gd->gl.base, ps); - gd->target_win = session_get_target_window(ps); + gd->target_win = target; XVisualInfo *pvis = NULL; diff --git a/src/backend/xrender/xrender.c b/src/backend/xrender/xrender.c index c359fc4efa..b175ceaf21 100644 --- a/src/backend/xrender/xrender.c +++ b/src/backend/xrender/xrender.c @@ -869,7 +869,7 @@ static void get_blur_size(void *blur_context, int *width, int *height) { *height = ctx->resize_height; } -static backend_t *backend_xrender_init(session_t *ps) { +static backend_t *backend_xrender_init(session_t *ps, xcb_window_t target) { if (ps->o.dithered_present) { log_warn("\"dithered-present\" is not supported by the xrender backend."); } @@ -888,7 +888,7 @@ static backend_t *backend_xrender_init(session_t *ps) { xd->black_pixel = solid_picture(&ps->c, true, 1, 0, 0, 0); xd->white_pixel = solid_picture(&ps->c, true, 1, 1, 1, 1); - xd->target_win = session_get_target_window(ps); + xd->target_win = target; xcb_render_create_picture_value_list_t pa = { .subwindowmode = XCB_SUBWINDOW_MODE_INCLUDE_INFERIORS, }; diff --git a/src/diagnostic.c b/src/diagnostic.c index 1159d9eabc..ce93cfc0c2 100644 --- a/src/diagnostic.c +++ b/src/diagnostic.c @@ -39,7 +39,7 @@ void print_diagnostics(session_t *ps, const char *config_file, bool compositor_r for (int i = 0; i < NUM_BKEND; i++) { if (backend_list[i] && backend_list[i]->diagnostics) { printf("\n### Backend: %s\n\n", BACKEND_STRS[i]); - auto data = backend_list[i]->init(ps); + auto data = backend_list[i]->init(ps, session_get_target_window(ps)); if (!data) { printf(" Cannot initialize this backend\n"); } else { diff --git a/src/picom.c b/src/picom.c index bf18523f9f..c9772e3b17 100644 --- a/src/picom.c +++ b/src/picom.c @@ -605,7 +605,8 @@ static bool initialize_backend(session_t *ps) { assert(!ps->backend_data); // Reinitialize win_data assert(backend_list[ps->o.backend]); - ps->backend_data = backend_list[ps->o.backend]->init(ps); + ps->backend_data = + backend_list[ps->o.backend]->init(ps, session_get_target_window(ps)); if (!ps->backend_data) { log_fatal("Failed to initialize backend, aborting..."); quit(ps); From 825cc563e18a4823285615336a250484d56d9473 Mon Sep 17 00:00:00 2001 From: Maxim Solovyov Date: Thu, 3 Aug 2023 00:53:44 +0300 Subject: [PATCH 03/17] backend: egl: simplify usage of the target window parameter in egl_init --- src/backend/gl/egl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/backend/gl/egl.c b/src/backend/gl/egl.c index 1156dd5922..ca70359173 100644 --- a/src/backend/gl/egl.c +++ b/src/backend/gl/egl.c @@ -211,8 +211,8 @@ static backend_t *egl_init(session_t *ps, xcb_window_t target) { } // clang-format on - gd->target_win = eglCreatePlatformWindowSurfaceProc( - gd->display, config, (xcb_window_t[]){target}, NULL); + gd->target_win = + eglCreatePlatformWindowSurfaceProc(gd->display, config, &target, NULL); if (gd->target_win == EGL_NO_SURFACE) { log_error("Failed to create EGL surface."); goto end; From 156423c0104fbac7f3eb7c50c0fa4812345968fc Mon Sep 17 00:00:00 2001 From: Maxim Solovyov Date: Thu, 3 Aug 2023 01:04:56 +0300 Subject: [PATCH 04/17] backend: dummy: change type of ps parameter to session_t in dummy_init --- src/backend/dummy/dummy.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/backend/dummy/dummy.c b/src/backend/dummy/dummy.c index 5e6f13cf9f..f4fa5f459f 100644 --- a/src/backend/dummy/dummy.c +++ b/src/backend/dummy/dummy.c @@ -28,8 +28,7 @@ struct dummy_data { struct backend_image mask; }; -struct backend_base * -dummy_init(struct session *ps attr_unused, xcb_window_t target attr_unused) { +struct backend_base *dummy_init(session_t *ps attr_unused, xcb_window_t target attr_unused) { auto ret = (struct backend_base *)ccalloc(1, struct dummy_data); ret->c = &ps->c; ret->loop = ps->loop; From 8bf82857c4542877b4e2fa36761acb70f6fa2e2d Mon Sep 17 00:00:00 2001 From: Maxim Solovyov Date: Thu, 3 Aug 2023 01:38:34 +0300 Subject: [PATCH 05/17] backend: name default backend operation implementations consistently --- src/backend/backend.h | 6 +++--- src/backend/backend_common.c | 4 ++-- src/backend/backend_common.h | 4 ++-- src/backend/dummy/dummy.c | 2 +- src/backend/xrender/xrender.c | 2 +- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/backend/backend.h b/src/backend/backend.h index 3ed7a761a8..6a05a55090 100644 --- a/src/backend/backend.h +++ b/src/backend/backend.h @@ -215,18 +215,18 @@ struct backend_operations { struct xvisual_info fmt, bool owned); /// Create a shadow context for rendering shadows with radius `radius`. - /// Default implementation: default_backend_create_shadow_context + /// Default implementation: default_create_shadow_context struct backend_shadow_context *(*create_shadow_context)(backend_t *backend_data, double radius); /// Destroy a shadow context - /// Default implementation: default_backend_destroy_shadow_context + /// Default implementation: default_destroy_shadow_context void (*destroy_shadow_context)(backend_t *backend_data, struct backend_shadow_context *ctx); /// Create a shadow image based on the parameters. Resulting image should have a /// size of `width + radisu * 2` x `height + radius * 2`. Radius is set when the /// shadow context is created. - /// Default implementation: default_backend_render_shadow + /// Default implementation: default_render_shadow /// /// Required. void *(*render_shadow)(backend_t *backend_data, int width, int height, diff --git a/src/backend/backend_common.c b/src/backend/backend_common.c index 3388b78516..eef214593b 100644 --- a/src/backend/backend_common.c +++ b/src/backend/backend_common.c @@ -293,8 +293,8 @@ bool build_shadow(struct x_connection *c, double opacity, const int width, return false; } -void *default_backend_render_shadow(backend_t *backend_data, int width, int height, - struct backend_shadow_context *sctx, struct color color) { +void *default_render_shadow(backend_t *backend_data, int width, int height, + struct backend_shadow_context *sctx, struct color color) { const conv *kernel = (void *)sctx; xcb_render_picture_t shadow_pixel = solid_picture(backend_data->c, true, 1, color.red, color.green, color.blue); diff --git a/src/backend/backend_common.h b/src/backend/backend_common.h index 2e49cecf71..a58d816c0a 100644 --- a/src/backend/backend_common.h +++ b/src/backend/backend_common.h @@ -62,8 +62,8 @@ bool default_is_win_transparent(void *, win *, void *); /// caveat as `default_is_win_transparent` applies. bool default_is_frame_transparent(void *, win *, void *); -void *default_backend_render_shadow(backend_t *backend_data, int width, int height, - struct backend_shadow_context *sctx, struct color color); +void *default_render_shadow(backend_t *backend_data, int width, int height, + struct backend_shadow_context *sctx, struct color color); /// Implement `render_shadow` with `shadow_from_mask`. void * diff --git a/src/backend/dummy/dummy.c b/src/backend/dummy/dummy.c index 4e3d713873..19e88ddc85 100644 --- a/src/backend/dummy/dummy.c +++ b/src/backend/dummy/dummy.c @@ -184,7 +184,7 @@ struct backend_operations dummy_ops = { .bind_pixmap = dummy_bind_pixmap, .create_shadow_context = default_create_shadow_context, .destroy_shadow_context = default_destroy_shadow_context, - .render_shadow = default_backend_render_shadow, + .render_shadow = default_render_shadow, .make_mask = dummy_make_mask, .release_image = dummy_release_image, .is_image_transparent = dummy_is_image_transparent, diff --git a/src/backend/xrender/xrender.c b/src/backend/xrender/xrender.c index c359fc4efa..5c7d786ef4 100644 --- a/src/backend/xrender/xrender.c +++ b/src/backend/xrender/xrender.c @@ -981,7 +981,7 @@ struct backend_operations xrender_ops = { .release_image = release_image, .create_shadow_context = default_create_shadow_context, .destroy_shadow_context = default_destroy_shadow_context, - .render_shadow = default_backend_render_shadow, + .render_shadow = default_render_shadow, .make_mask = make_mask, //.prepare_win = prepare_win, //.release_win = release_win, From bd3134efd982397a3c51a48a7d7f13e25b87c41d Mon Sep 17 00:00:00 2001 From: Maxim Solovyov Date: Thu, 3 Aug 2023 01:42:00 +0300 Subject: [PATCH 06/17] backend: xrender: remove obsolete commented out backend operations --- src/backend/xrender/xrender.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/backend/xrender/xrender.c b/src/backend/xrender/xrender.c index 5c7d786ef4..f7ef8616c1 100644 --- a/src/backend/xrender/xrender.c +++ b/src/backend/xrender/xrender.c @@ -983,8 +983,6 @@ struct backend_operations xrender_ops = { .destroy_shadow_context = default_destroy_shadow_context, .render_shadow = default_render_shadow, .make_mask = make_mask, - //.prepare_win = prepare_win, - //.release_win = release_win, .is_image_transparent = default_is_image_transparent, .buffer_age = buffer_age, .max_buffer_age = 2, From 44800ed845fad3fb0638891764a3b17084c96c3a Mon Sep 17 00:00:00 2001 From: Maxim Solovyov Date: Thu, 3 Aug 2023 01:44:54 +0300 Subject: [PATCH 07/17] backend: remove default implementations of obsolete backend operations --- src/backend/backend_common.h | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/backend/backend_common.h b/src/backend/backend_common.h index a58d816c0a..da9ccd0235 100644 --- a/src/backend/backend_common.h +++ b/src/backend/backend_common.h @@ -54,14 +54,6 @@ solid_picture(struct x_connection *, bool argb, double a, double r, double g, do xcb_image_t *make_shadow(struct x_connection *c, const conv *kernel, double opacity, int width, int height); -/// The default implementation of `is_win_transparent`, it simply looks at win::mode. So -/// this is not suitable for backends that alter the content of windows -bool default_is_win_transparent(void *, win *, void *); - -/// The default implementation of `is_frame_transparent`, it uses win::frame_opacity. Same -/// caveat as `default_is_win_transparent` applies. -bool default_is_frame_transparent(void *, win *, void *); - void *default_render_shadow(backend_t *backend_data, int width, int height, struct backend_shadow_context *sctx, struct color color); From e07b1d7a127950b4633fa5459341ab234e9e5bc6 Mon Sep 17 00:00:00 2001 From: Maxim Solovyov Date: Sun, 10 Sep 2023 22:32:02 +0300 Subject: [PATCH 08/17] backend: gl: convert the shadow color to the premultiplied format to respect the globally set glBlendFunc and thus get the correct and expected result --- src/backend/gl/gl_common.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/backend/gl/gl_common.c b/src/backend/gl/gl_common.c index d437fdd7bd..786e82f413 100644 --- a/src/backend/gl/gl_common.c +++ b/src/backend/gl/gl_common.c @@ -1347,8 +1347,11 @@ void *gl_shadow_from_mask(backend_t *base, void *mask, glBindTexture(GL_TEXTURE_2D, tmp_texture); glUseProgram(gd->shadow_shader.prog); - glUniform4f(gd->shadow_shader.uniform_color, (GLfloat)color.red, - (GLfloat)color.green, (GLfloat)color.blue, (GLfloat)color.alpha); + // The shadow color is converted to the premultiplied format to respect the + // globally set glBlendFunc and thus get the correct and expected result. + glUniform4f(gd->shadow_shader.uniform_color, (GLfloat)(color.red * color.alpha), + (GLfloat)(color.green * color.alpha), + (GLfloat)(color.blue * color.alpha), (GLfloat)color.alpha); // clang-format off GLuint indices[] = {0, 1, 2, 2, 3, 0}; From 47bb825b2c4965d1874d983c7128af0fbfb6b4cb Mon Sep 17 00:00:00 2001 From: Yuxuan Shui Date: Sun, 17 Dec 2023 08:39:02 +0000 Subject: [PATCH 09/17] backend: glx: don't return false from a function returning void * Signed-off-by: Yuxuan Shui --- src/backend/gl/glx.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/backend/gl/glx.c b/src/backend/gl/glx.c index cb55d4d9b0..78143a2b77 100644 --- a/src/backend/gl/glx.c +++ b/src/backend/gl/glx.c @@ -371,12 +371,12 @@ glx_bind_pixmap(backend_t *base, xcb_pixmap_t pixmap, struct xvisual_info fmt, b if (fmt.visual_depth > OPENGL_MAX_DEPTH) { log_error("Requested depth %d higher than max possible depth %d.", fmt.visual_depth, OPENGL_MAX_DEPTH); - return false; + return NULL; } if (fmt.visual_depth < 0) { log_error("Pixmap %#010x with invalid depth %d", pixmap, fmt.visual_depth); - return false; + return NULL; } auto r = From 1b97f18e5f037d40a59f2dab9a32037b7a735f96 Mon Sep 17 00:00:00 2001 From: Yuxuan Shui Date: Sun, 17 Dec 2023 08:50:47 +0000 Subject: [PATCH 10/17] compiler: bring the unreachable macro in line with C23 Signed-off-by: Yuxuan Shui --- src/c2.c | 2 +- src/compiler.h | 10 ++++++---- src/utils.c | 2 +- src/win.c | 2 +- 4 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/c2.c b/src/c2.c index d82448aa24..7f1f80e0f7 100644 --- a/src/c2.c +++ b/src/c2.c @@ -1336,7 +1336,7 @@ static xcb_atom_t c2_get_atom_type(const c2_l_t *pleaf) { case C2_L_TDRAWABLE: return XCB_ATOM_DRAWABLE; default: assert(0); break; } - unreachable; + unreachable(); } /** diff --git a/src/compiler.h b/src/compiler.h index 76326707b0..af8fb83190 100644 --- a/src/compiler.h +++ b/src/compiler.h @@ -101,10 +101,12 @@ # endif #endif -#if defined(__GNUC__) || defined(__clang__) -# define unreachable __builtin_unreachable() -#else -# define unreachable do {} while(0) +#ifndef unreachable +# if defined(__GNUC__) || defined(__clang__) +# define unreachable() __builtin_unreachable() +# else +# define unreachable() do {} while(0) +# endif #endif #ifndef __has_include diff --git a/src/utils.c b/src/utils.c index d26afa331e..5709fa21d2 100644 --- a/src/utils.c +++ b/src/utils.c @@ -30,7 +30,7 @@ void report_allocation_failure(const char *func, const char *file, unsigned int ssize_t _ attr_unused = writev(STDERR_FILENO, v, ARR_SIZE(v)); abort(); - unreachable; + unreachable(); } /// diff --git a/src/win.c b/src/win.c index bd19b3d412..6dccbed652 100644 --- a/src/win.c +++ b/src/win.c @@ -2433,7 +2433,7 @@ bool win_check_fade_finished(session_t *ps, struct managed_win *w) { case WSTATE_DESTROYING: destroy_win_finish(ps, &w->base); return true; case WSTATE_MAPPING: map_win_finish(w); return false; case WSTATE_FADING: w->state = WSTATE_MAPPED; break; - default: unreachable; + default: unreachable(); } } From e92745671baf07cce8044c99451418f1aa29f25a Mon Sep 17 00:00:00 2001 From: Yuxuan Shui Date: Sun, 17 Dec 2023 08:55:23 +0000 Subject: [PATCH 11/17] compiler: use C23 auto when available One annoying thing is C23 still defines auto as a storage class despite it now being used for type inference. As a consequence we must write "auto const" instead of the more natural "const auto". Signed-off-by: Yuxuan Shui --- src/backend/xrender/xrender.c | 20 ++++++++++---------- src/compiler.h | 2 ++ src/picom.c | 4 ++-- src/render.c | 20 ++++++++++---------- src/win.c | 6 +++--- 5 files changed, 27 insertions(+), 25 deletions(-) diff --git a/src/backend/xrender/xrender.c b/src/backend/xrender/xrender.c index cc6e5f430a..5d04ff272b 100644 --- a/src/backend/xrender/xrender.c +++ b/src/backend/xrender/xrender.c @@ -176,8 +176,8 @@ static xcb_render_picture_t process_mask(struct _xrender_data *xd, struct xrende *allocated = false; return inner->pict; } - const auto tmpw = to_u16_checked(inner->width); - const auto tmph = to_u16_checked(inner->height); + auto const tmpw = to_u16_checked(inner->width); + auto const tmph = to_u16_checked(inner->height); *allocated = true; x_clear_picture_clip_region(xd->base.c, inner->pict); auto ret = x_create_picture_with_visual( @@ -226,13 +226,13 @@ compose_impl(struct _xrender_data *xd, struct xrender_image *xrimg, coord_t dst, region_t reg; bool has_alpha = inner->has_alpha || img->opacity != 1; - const auto tmpw = to_u16_checked(inner->width); - const auto tmph = to_u16_checked(inner->height); - const auto tmpew = to_u16_checked(img->ewidth); - const auto tmpeh = to_u16_checked(img->eheight); + auto const tmpw = to_u16_checked(inner->width); + auto const tmph = to_u16_checked(inner->height); + auto const tmpew = to_u16_checked(img->ewidth); + auto const tmpeh = to_u16_checked(img->eheight); // Remember: the mask has a 1-pixel border - const auto mask_dst_x = to_i16_checked(dst.x - mask_dst.x + 1); - const auto mask_dst_y = to_i16_checked(dst.y - mask_dst.y + 1); + auto const mask_dst_x = to_i16_checked(dst.x - mask_dst.x + 1); + auto const mask_dst_y = to_i16_checked(dst.y - mask_dst.y + 1); const xcb_render_color_t dim_color = { .red = 0, .green = 0, .blue = 0, .alpha = (uint16_t)(0xffff * img->dim)}; @@ -395,8 +395,8 @@ static bool blur(backend_t *backend_data, double opacity, void *ctx_, void *mask resize_region(®_op, bctx->resize_width, bctx->resize_height); const pixman_box32_t *extent_resized = pixman_region32_extents(®_op_resized); - const auto height_resized = to_u16_checked(extent_resized->y2 - extent_resized->y1); - const auto width_resized = to_u16_checked(extent_resized->x2 - extent_resized->x1); + auto const height_resized = to_u16_checked(extent_resized->y2 - extent_resized->y1); + auto const width_resized = to_u16_checked(extent_resized->x2 - extent_resized->x1); static const char *filter0 = "Nearest"; // The "null" filter static const char *filter = "convolution"; diff --git a/src/compiler.h b/src/compiler.h index af8fb83190..302bc7bbed 100644 --- a/src/compiler.h +++ b/src/compiler.h @@ -7,7 +7,9 @@ #endif // clang-format off +#if __STDC_VERSION__ <= 201710L #define auto __auto_type +#endif #define likely(x) __builtin_expect(!!(x), 1) #define unlikely(x) __builtin_expect(!!(x), 0) #define likely_if(x) if (likely(x)) diff --git a/src/picom.c b/src/picom.c index c9772e3b17..1302f51465 100644 --- a/src/picom.c +++ b/src/picom.c @@ -265,7 +265,7 @@ void schedule_render(session_t *ps, bool triggered_by_vblank) { goto schedule; } - const auto deadline = ps->last_msc_instant + (unsigned long)divisor * frame_time; + auto const deadline = ps->last_msc_instant + (unsigned long)divisor * frame_time; unsigned int available = 0; if (deadline > now_us) { available = (unsigned int)(deadline - now_us); @@ -1158,7 +1158,7 @@ static int register_cm(session_t *ps) { // Set WM_CLIENT_MACHINE. As per EWMH, because we set _NET_WM_PID, we must also // set WM_CLIENT_MACHINE. { - const auto hostname_max = (unsigned long)sysconf(_SC_HOST_NAME_MAX); + auto const hostname_max = (unsigned long)sysconf(_SC_HOST_NAME_MAX); char *hostname = malloc(hostname_max); if (gethostname(hostname, hostname_max) == 0) { diff --git a/src/render.c b/src/render.c index 3a7e844842..ec50d8a3ec 100644 --- a/src/render.c +++ b/src/render.c @@ -474,10 +474,10 @@ void paint_one(session_t *ps, struct managed_win *w, const region_t *reg_paint) } else { // Painting parameters const margin_t extents = win_calc_frame_extents(w); - const auto t = extents.top; - const auto l = extents.left; - const auto b = extents.bottom; - const auto r = extents.right; + auto const t = extents.top; + auto const l = extents.left; + auto const b = extents.bottom; + auto const r = extents.right; #define COMP_BDR(cx, cy, cwid, chei) \ paint_region(ps, w, (cx), (cy), (cwid), (chei), w->frame_opacity * w->opacity, \ @@ -888,8 +888,8 @@ win_blur_background(session_t *ps, struct managed_win *w, xcb_render_picture_t t const region_t *reg_paint) { const int16_t x = w->g.x; const int16_t y = w->g.y; - const auto wid = to_u16_checked(w->widthb); - const auto hei = to_u16_checked(w->heightb); + auto const wid = to_u16_checked(w->widthb); + auto const hei = to_u16_checked(w->heightb); const int cr = w ? w->corner_radius : 0; double factor_center = 1.0; @@ -1174,8 +1174,8 @@ void paint_all(session_t *ps, struct managed_win *t) { if (w->corner_radius > 0 && ps->o.backend == BKEND_GLX) { const int16_t x = w->g.x; const int16_t y = w->g.y; - const auto wid = to_u16_checked(w->widthb); - const auto hei = to_u16_checked(w->heightb); + auto const wid = to_u16_checked(w->widthb); + auto const hei = to_u16_checked(w->heightb); glx_bind_texture(ps, &w->glx_texture_bg, x, y, wid, hei); } #endif @@ -1195,8 +1195,8 @@ void paint_all(session_t *ps, struct managed_win *t) { // Rounded corners for XRender is implemented inside render() // Round window corners if (w->corner_radius > 0 && ps->o.backend == BKEND_GLX) { - const auto wid = to_u16_checked(w->widthb); - const auto hei = to_u16_checked(w->heightb); + auto const wid = to_u16_checked(w->widthb); + auto const hei = to_u16_checked(w->heightb); glx_round_corners_dst(ps, w, w->glx_texture_bg, w->g.x, w->g.y, wid, hei, (float)ps->psglx->z - 0.5F, diff --git a/src/win.c b/src/win.c index 6dccbed652..901b646cae 100644 --- a/src/win.c +++ b/src/win.c @@ -2758,7 +2758,7 @@ void win_clear_flags(struct managed_win *w, uint64_t flags) { } void win_set_properties_stale(struct managed_win *w, const xcb_atom_t *props, int nprops) { - const auto bits_per_element = sizeof(*w->stale_props) * 8; + auto const bits_per_element = sizeof(*w->stale_props) * 8; size_t new_capacity = w->stale_props_capacity; // Calculate the new capacity of the properties array @@ -2793,12 +2793,12 @@ static void win_clear_all_properties_stale(struct managed_win *w) { } static bool win_fetch_and_unset_property_stale(struct managed_win *w, xcb_atom_t prop) { - const auto bits_per_element = sizeof(*w->stale_props) * 8; + auto const bits_per_element = sizeof(*w->stale_props) * 8; if (prop >= w->stale_props_capacity * bits_per_element) { return false; } - const auto mask = 1UL << (prop % bits_per_element); + auto const mask = 1UL << (prop % bits_per_element); bool ret = w->stale_props[prop / bits_per_element] & mask; w->stale_props[prop / bits_per_element] &= ~mask; return ret; From 268e1d890ab7d982cbcbec034c3ccebd09c8b10b Mon Sep 17 00:00:00 2001 From: Yuxuan Shui Date: Sun, 17 Dec 2023 23:34:34 +0000 Subject: [PATCH 12/17] core: exit if paint_preprocess fails This usually means there is another compositor running. If we don't do this picom will spin forever. Fixes #1104 Signed-off-by: Yuxuan Shui --- src/picom.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/picom.c b/src/picom.c index 1302f51465..fa9182bf12 100644 --- a/src/picom.c +++ b/src/picom.c @@ -1741,6 +1741,11 @@ static void draw_callback_impl(EV_P_ session_t *ps, int revents attr_unused) { auto bottom = paint_preprocess(ps, &fade_running, &animation); ps->tmout_unredir_hit = false; + if (!bottom) { + log_fatal("Pre-render preparation has failed, exiting..."); + exit(1); + } + if (!was_redirected && ps->redirected) { // paint_preprocess redirected the screen, which might change the state of // some of the windows (e.g. the window image might become stale). From 7366553be2b825495c5b1e09be09d0fabde4b9b4 Mon Sep 17 00:00:00 2001 From: Yuxuan Shui Date: Sun, 17 Dec 2023 23:44:56 +0000 Subject: [PATCH 13/17] core: distinguish preprocess failure and no window to render paint_process would return NULL for both of these cases, but we should exit in the failure case, and continue going in the other. Signed-off-by: Yuxuan Shui --- src/picom.c | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/src/picom.c b/src/picom.c index fa9182bf12..6f3c2908d9 100644 --- a/src/picom.c +++ b/src/picom.c @@ -769,13 +769,19 @@ static void handle_root_flags(session_t *ps) { } } -static struct managed_win * -paint_preprocess(session_t *ps, bool *fade_running, bool *animation) { +/** + * Go through the window stack and calculate some parameters for rendering. + * + * @return whether the operation succeeded + */ +static bool paint_preprocess(session_t *ps, bool *fade_running, bool *animation, + struct managed_win **out_bottom) { // XXX need better, more general name for `fade_running`. It really // means if fade is still ongoing after the current frame is rendered struct managed_win *bottom = NULL; *fade_running = false; *animation = false; + *out_bottom = NULL; // Fading step calculation long long steps = 0L; @@ -1036,12 +1042,13 @@ paint_preprocess(session_t *ps, bool *fade_running, bool *animation) { ev_timer_stop(ps->loop, &ps->unredir_timer); if (!ps->redirected) { if (!redirect_start(ps)) { - return NULL; + return false; } } } - return bottom; + *out_bottom = bottom; + return true; } void root_damaged(session_t *ps) { @@ -1738,14 +1745,14 @@ static void draw_callback_impl(EV_P_ session_t *ps, int revents attr_unused) { bool fade_running = false; bool animation = false; bool was_redirected = ps->redirected; - auto bottom = paint_preprocess(ps, &fade_running, &animation); - ps->tmout_unredir_hit = false; - - if (!bottom) { + struct managed_win *bottom = NULL; + if (!paint_preprocess(ps, &fade_running, &animation, &bottom)) { log_fatal("Pre-render preparation has failed, exiting..."); exit(1); } + ps->tmout_unredir_hit = false; + if (!was_redirected && ps->redirected) { // paint_preprocess redirected the screen, which might change the state of // some of the windows (e.g. the window image might become stale). From aed2a205ed30a5c65ad86f98a3bfae4b1ae3bff8 Mon Sep 17 00:00:00 2001 From: Yuxuan Shui Date: Mon, 18 Dec 2023 04:11:18 +0000 Subject: [PATCH 14/17] log: add a new log level, verbose Signed-off-by: Yuxuan Shui --- src/log.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/log.h b/src/log.h index e40fe3c8f4..6d74126c06 100644 --- a/src/log.h +++ b/src/log.h @@ -9,11 +9,19 @@ enum log_level { LOG_LEVEL_INVALID = -1, + /// Very noisy debug messages, many lines per frame. LOG_LEVEL_TRACE = 0, + /// Frequent debug messages, a few lines per frame. + LOG_LEVEL_VERBOSE, + /// Less frequent debug messages. LOG_LEVEL_DEBUG, + /// Informational messages. LOG_LEVEL_INFO, + /// Warnings. LOG_LEVEL_WARN, + /// Errors. LOG_LEVEL_ERROR, + /// Fatal errors. LOG_LEVEL_FATAL, }; @@ -31,6 +39,7 @@ enum log_level { } \ } while (0) #define log_trace(x, ...) LOG_UNLIKELY(TRACE, x, ##__VA_ARGS__) +#define log_verbose(x, ...) LOG_UNLIKELY(VERBOSE, x, ##__VA_ARGS__) #define log_debug(x, ...) LOG_UNLIKELY(DEBUG, x, ##__VA_ARGS__) #define log_info(x, ...) LOG(INFO, x, ##__VA_ARGS__) #define log_warn(x, ...) LOG(WARN, x, ##__VA_ARGS__) From c7ec4c2c1624cdfd2ad8936e3cdf70023f62459b Mon Sep 17 00:00:00 2001 From: Yuxuan Shui Date: Mon, 18 Dec 2023 04:15:27 +0000 Subject: [PATCH 15/17] log: fix printing and parsing of the verbose log level Signed-off-by: Yuxuan Shui --- src/log.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/log.c b/src/log.c index 870d755750..99f310a654 100644 --- a/src/log.c +++ b/src/log.c @@ -68,6 +68,7 @@ log_default_writev(struct log_target *tgt, const struct iovec *vec, int vcnt) { static attr_const const char *log_level_to_string(enum log_level level) { switch (level) { case LOG_LEVEL_TRACE: return "TRACE"; + case LOG_LEVEL_VERBOSE: return "VERBOSE"; case LOG_LEVEL_DEBUG: return "DEBUG"; case LOG_LEVEL_INFO: return "INFO"; case LOG_LEVEL_WARN: return "WARN"; @@ -81,6 +82,9 @@ enum log_level string_to_log_level(const char *str) { if (strcasecmp(str, "TRACE") == 0) { return LOG_LEVEL_TRACE; } + if (strcasecmp(str, "VERBOSE") == 0) { + return LOG_LEVEL_VERBOSE; + } if (strcasecmp(str, "DEBUG") == 0) { return LOG_LEVEL_DEBUG; } @@ -234,12 +238,10 @@ struct log_target *null_logger_new(void) { static void null_logger_write(struct log_target *tgt attr_unused, const char *str attr_unused, size_t len attr_unused) { - return; } static void null_logger_writev(struct log_target *tgt attr_unused, const struct iovec *vec attr_unused, int vcnt attr_unused) { - return; } static const struct log_ops null_logger_ops = { From e60cb65672e585ad250a123794185350c0f41f18 Mon Sep 17 00:00:00 2001 From: Yuxuan Shui Date: Mon, 18 Dec 2023 04:18:18 +0000 Subject: [PATCH 16/17] log: give verbose log level a color Signed-off-by: Yuxuan Shui --- src/log.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/log.c b/src/log.c index 99f310a654..664b9f41be 100644 --- a/src/log.c +++ b/src/log.c @@ -277,6 +277,7 @@ static void file_logger_destroy(struct log_target *tgt) { static const char *terminal_colorize_begin(enum log_level level) { switch (level) { case LOG_LEVEL_TRACE: return ANSI("30;2"); + case LOG_LEVEL_VERBOSE: case LOG_LEVEL_DEBUG: return ANSI("37;2"); case LOG_LEVEL_INFO: return ANSI("92"); case LOG_LEVEL_WARN: return ANSI("33"); From fd9c52d0ee97154a84433b48a4a4f2beecb25053 Mon Sep 17 00:00:00 2001 From: Bernd Busse Date: Thu, 19 Jan 2023 23:52:58 +0100 Subject: [PATCH 17/17] backend: xrender: force 32bit ARGB visual when adding rounded corners Force the temporary picture to a 32-bit ARGB visual when masking it for rounded corners to keep the transparency information. Otherwise, windows with a 24-bit visual would get black corners instead. Authored-by: Bernd Busse Signed-off-by: Yuxuan Shui --- src/backend/xrender/xrender.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/backend/xrender/xrender.c b/src/backend/xrender/xrender.c index 5d04ff272b..b2ec3f2301 100644 --- a/src/backend/xrender/xrender.c +++ b/src/backend/xrender/xrender.c @@ -250,10 +250,16 @@ compose_impl(struct _xrender_data *xd, struct xrender_image *xrimg, coord_t dst, } if (((img->color_inverted || img->dim != 0) && has_alpha) || img->corner_radius != 0) { // Apply image properties using a temporary image, because the source - // image is transparent. Otherwise the properties can be applied directly - // on the target image. + // image is transparent or will get transparent corners. Otherwise the + // properties can be applied directly on the target image. + // Also force a 32-bit ARGB visual for transparent corners, otherwise the + // corners become black. + auto visual = + (img->corner_radius != 0 && inner->depth != 32) + ? x_get_visual_for_standard(xd->base.c, XCB_PICT_STANDARD_ARGB_32) + : inner->visual; auto tmp_pict = x_create_picture_with_visual( - xd->base.c, inner->width, inner->height, inner->visual, 0, NULL); + xd->base.c, inner->width, inner->height, visual, 0, NULL); // Set clip region translated to source coordinate x_set_picture_clip_region(xd->base.c, tmp_pict, to_i16_checked(-dst.x),