diff options
authorDudemanguy <>2021-07-26 14:26:51 -0500
committerDudemanguy <>2021-07-26 15:05:33 -0500
commite2c24adebede2d269b0fa2df3f1a05a44343e8c0 (patch)
parentf8e62d3d82dd0a3d06f9a557d756f0ad78118cc7 (diff)
wayland: unset hidden state in frame callbackHEADmaster
More wayland weirdness. So previously, flipping a hidden state from true to false was done in vo_wayland_wait_frame. In theory, this would be after you get the frame callback and all those events so there's no problem. However since the function also does a bunch of flushing/dispatching/etc. to the default display queue so a lot of unknown things can happen before we actually set the hidden variable back to false. For example if a single image was paused and left on another virtual desktop long enough (~5 minutes) while also not having focus, switching back to that desktop could render it a black frame. This edge case was supposed to be handled by the surface being activated again in the toplevel event but apparently that doesn't always work. The fix is to just delete all of that junk and set wl->hidden = false in the frame callback. What's actually happening is kind of a mystery honestly. Probably the compositor drops the buffers after a while as an optimization (sensible) and forces a repaint if you switch back to the virtual desktop. Somehow wl->hidden not being set to false would not properly trigger a repaint (likely because it also sends a toplevel event which does stuff) thus you just get a black window. If you just make sure to set hidden in the frame callback, it appears like all of these problems and edge cases are solved. Since this event must happen first, that makes sense. That simplifies a lot of stuff and fixes some subtle bugs at the same time so just go with this approach.
1 files changed, 1 insertions, 8 deletions
diff --git a/video/out/wayland_common.c b/video/out/wayland_common.c
index 4157782c0c..3b6019d941 100644
--- a/video/out/wayland_common.c
+++ b/video/out/wayland_common.c
@@ -838,12 +838,6 @@ static void handle_toplevel_config(void *data, struct xdg_toplevel *toplevel,
wl->focused = !wl->focused;
wl->pending_vo_events |= VO_EVENT_FOCUS;
- if (wl->activated) {
- /* If the surface comes back into view, force a redraw. */
- vo_wayland_wait_frame(wl);
- wl->pending_vo_events |= VO_EVENT_EXPOSE;
- }
@@ -994,6 +988,7 @@ static void frame_callback(void *data, struct wl_callback *callback, uint32_t ti
wl->frame_wait = false;
+ wl->hidden = false;
static const struct wl_callback_listener frame_listener = {
@@ -1992,13 +1987,11 @@ void vo_wayland_wait_frame(struct vo_wayland_state *wl)
} else {
wl->timeout_count += 1;
- wl->hidden = false;
wl->timeout_count = 0;
- wl->hidden = false;
void vo_wayland_wait_events(struct vo *vo, int64_t until_time_us)