From 02ee570c272e93b29621a4dfc2f546c1b8e1bb2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Tue, 10 Nov 2020 19:20:35 +0100 Subject: [PATCH] =?UTF-8?q?wayland:=20preempt=20render=20scheduling=20in?= =?UTF-8?q?=20=E2=80=98configure=E2=80=99=20events?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A configure event must be “committed”. In case of resizing, that means rendering a new frame and committing that surface. render_resize() will resize the grid and *schedule* a render refresh. However, if one is already pending, the refresh will take a very (relatively) long time - until the next frame callback is received. This poses a problem when the window is hidden, since in this case, the frame callback *never* comes. This in turn means we fail to commit a new surface in response to the ‘configure’ event. And that means the compositor needs to wait for a transaction timeout before continuing. The end effect is very slow and jerky window resizing when a hidden foot window is being resized. This can happen in tiled compositors, like Sway, where a window can be tabbed (and thus invisible), but still resized when its container is resized. Closes #190 --- CHANGELOG.md | 2 ++ wayland.c | 19 ++++++++++++++----- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 645b6eeb..468f897d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -68,6 +68,8 @@ not possible to add a command to these actions when used in mouse bindings, making them useless (https://codeberg.org/dnkl/foot/issues/183). +* Resize very slow when window is hidden + (https://codeberg.org/dnkl/foot/issues/190). ### Security diff --git a/wayland.c b/wayland.c index 37b47f30..b8cd9cd9 100644 --- a/wayland.c +++ b/wayland.c @@ -614,17 +614,26 @@ xdg_surface_configure(void *data, struct xdg_surface *xdg_surface, xdg_surface_ack_configure(xdg_surface, serial); - /* TODO: check with GNOME and tiling - presumably that didn't work - * unless we presented a *new* buffer, hence we used to do a force - * resize here */ - bool resized = render_resize(term, win->configure.width, win->configure.height); + if (term->window->frame_callback != NULL) { + /* + * Preempt render scheduling. + * + * Each configure event require a corresponding new + * surface+commit. Thus we cannot just schedule a pending + * refresh if there’s already a frame being rendered. + */ + wl_callback_destroy(term->window->frame_callback); + term->window->frame_callback = NULL; + } + + bool resized = render_resize( + term, win->configure.width, win->configure.height); if (win->configure.is_activated) term_visual_focus_in(term); else term_visual_focus_out(term); - /* TODO: remove - shouldn't be necessary with render_resize_force() */ if (!resized) { /* * If we didn't resize, we won't be committing a new surface