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.
This commit is contained in:
Aivars Vaivods 2025-07-11 22:49:28 +03:00
parent 3dce815fe3
commit 6212f98dd3
3 changed files with 31 additions and 7 deletions

View file

@ -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);
};

View file

@ -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 *

View file

@ -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,
};