From 6212f98dd3c8430cb9eb97d421f7ac92f5a5367d Mon Sep 17 00:00:00 2001 From: Aivars Vaivods Date: Fri, 11 Jul 2025 22:49:28 +0300 Subject: [PATCH] Fixed bar not reappearing after being fully hidden Somewhere between versions 0.16 and 0.18 wlroots implemented rendering code optimizations. One of optimizations was to not call frame callback for invisible surfaces. This caused bar to not reappear, if it was fully hidden behind non-transparent window. --- bar/backend.h | 1 + bar/bar.c | 2 +- bar/wayland.c | 35 +++++++++++++++++++++++++++++------ 3 files changed, 31 insertions(+), 7 deletions(-) diff --git a/bar/backend.h b/bar/backend.h index b7a9fcb..1247d2b 100644 --- a/bar/backend.h +++ b/bar/backend.h @@ -11,6 +11,7 @@ struct backend { void (*on_mouse)(struct bar *bar, enum mouse_event event, enum mouse_button btn, int x, int y)); void (*commit)(const struct bar *bar); void (*refresh)(const struct bar *bar); + void (*update_visibility)(const struct bar *bar); void (*set_cursor)(struct bar *bar, const char *cursor); const char *(*output_name)(const struct bar *bar); }; diff --git a/bar/bar.c b/bar/bar.c index cbbcf09..bbb9998 100644 --- a/bar/bar.c +++ b/bar/bar.c @@ -186,7 +186,7 @@ set_visible(struct bar *bar, bool visible) return; b->visible = visible; - bar->refresh(bar); + b->backend.iface->update_visibility(bar); } static const char * diff --git a/bar/wayland.c b/bar/wayland.c index bac7752..cee82a5 100644 --- a/bar/wayland.c +++ b/bar/wayland.c @@ -115,6 +115,7 @@ struct wayland_backend { /* We're already waiting for a frame done callback */ bool render_scheduled; + bool bar_shown; tll(struct buffer) buffers; /* List of SHM buffers */ struct buffer *next_buffer; /* Bar is rendering to this one */ @@ -729,6 +730,7 @@ layer_surface_configure(void *data, struct zwlr_layer_surface_v1 *surface, uint3 backend->height = h * backend->scale; zwlr_layer_surface_v1_ack_configure(surface, serial); + refresh(backend->bar); } static void @@ -775,6 +777,7 @@ create_surface(struct wayland_backend *backend) case BAR_LAYER_BOTTOM: case BAR_LAYER_HIDDEN: layer = ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM; + backend->bar_shown = false; break; case BAR_LAYER_TOP: @@ -1238,24 +1241,32 @@ loop(struct bar *_bar, void (*expose)(const struct bar *bar), goto out; } - assert(command == 1); + assert((command == 1) || (command == 2)); if (command == 1) { count++; do_expose = true; } + else if (command == 2) { + do_expose = false; + break; + } } LOG_DBG("coalesced %zu expose commands", count); - if (bar->layer == BAR_LAYER_HIDDEN) { - zwlr_layer_surface_v1_set_layer( - backend->layer_surface, - (bar->visible) ? ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY : ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM); - } if (do_expose) { expose(_bar); } } + if ((bar->layer == BAR_LAYER_HIDDEN) && (bar->visible != backend->bar_shown)) { + zwlr_layer_surface_v1_set_layer( + backend->layer_surface, + (bar->visible) ? ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY : ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM); + wl_surface_commit(backend->surface); + wl_display_flush(backend->display); + backend->bar_shown = bar->visible; + } + if (fds[1].revents & POLLIN) { if (wl_display_read_events(backend->display) < 0) { LOG_ERRNO("failed to read events from the Wayland socket"); @@ -1428,6 +1439,17 @@ refresh(const struct bar *_bar) } } +static void +update_visibility(const struct bar *_bar) +{ + const struct private *bar = _bar->private; + const struct wayland_backend *backend = bar->backend.data; + + if (write(backend->pipe_fds[1], &(uint8_t){2}, sizeof(uint8_t)) != sizeof(uint8_t)) { + LOG_ERRNO("failed to signal 'update_visibility' to main thread"); + } +} + static void set_cursor(struct bar *_bar, const char *cursor) { @@ -1468,6 +1490,7 @@ const struct backend wayland_backend_iface = { .loop = &loop, .commit = &commit, .refresh = &refresh, + .update_visibility = &update_visibility, .set_cursor = &set_cursor, .output_name = &bar_output_name, };