From 3031ddfc16bbe39b5fe324b0495041c59245347c 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 | 3 +++ wayland.c | 19 ++++++++++++++----- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 92b1d2ac..b7a0a1f7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,9 @@ ### Fixed +* Resize very slow when window is hidden + (https://codeberg.org/dnkl/foot/issues/190). + ## 1.5.3 diff --git a/wayland.c b/wayland.c index a663db4d..5553b4ef 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