From cfc902361633915646cd1384830d758f16aa701d Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Mon, 13 Dec 2021 06:54:49 +0000 Subject: [PATCH] Windows: try to send only one term_size on request_resize. Previously, the Windows implementation of win_request_resize would call term_size() to tell the terminal about its new size, _before_ calling SetWindowPos to actually change the window size. If SetWindowPos ends up not getting the exact window size it asks for, Windows notifies the application by sending back a WM_SIZE message - synchronously, by calling back to the window procedure from within SetWindowPos. So after the first over-optimistic term_size(), the WM_SIZE handler would trigger a second one, resetting the terminal again to the _actual_ size. This was more or less harmless, since current handling of terminal resizes is such that no terminal data gets too confused: any lines pushed into the scrollback by the first term_size will be pulled back out by the second one if needed (or vice versa), and since commit 271de3e4ec5682e, individual termlines are not eagerly truncated by resizing them twice. However, it's more work than we really wanted to be doing, and it seems presumptuous to send term_size() before we know it's right! So now we send term_size() after SetWindowPos returns, unless it already got sent by a re-entrant call to the WM_SIZE handler _before_ SetWindowPos returned. That way, the terminal should get exactly one term_size() call in response to win_request_resize(), whether it got the size it was expecting or not. --- windows/window.c | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/windows/window.c b/windows/window.c index 851dafb5..aead39f4 100644 --- a/windows/window.c +++ b/windows/window.c @@ -1590,6 +1590,8 @@ static void deinit_fonts(void) trust_icon = INVALID_HANDLE_VALUE; } +static bool sent_term_size; /* only live during wintw_request_resize() */ + static void wintw_request_resize(TermWin *tw, int w, int h) { const struct BackendVtable *vt; @@ -1635,7 +1637,18 @@ static void wintw_request_resize(TermWin *tw, int w, int h) } } - term_size(term, h, w, conf_get_int(conf, CONF_savelines)); + /* + * We want to send exactly one term_size() to the terminal, + * telling it what size it ended up after this operation. + * + * If we don't get the size we asked for in SetWindowPos, then + * we'll be sent a WM_SIZE message, whose handler will make that + * call, all before SetWindowPos even returns to here. + * + * But if that _didn't_ happen, we'll need to call term_size + * ourselves afterwards. + */ + sent_term_size = false; if (conf_get_int(conf, CONF_resize_action) != RESIZE_FONT && !IsZoomed(wgs.term_hwnd)) { @@ -1648,6 +1661,9 @@ static void wintw_request_resize(TermWin *tw, int w, int h) } else reset_window(0); + if (!sent_term_size) + term_size(term, h, w, conf_get_int(conf, CONF_savelines)); + InvalidateRect(wgs.term_hwnd, NULL, true); } @@ -2088,6 +2104,11 @@ static void wm_size_resize_term(LPARAM lParam, bool border) } else { term_size(term, h, w, conf_get_int(conf, CONF_savelines)); + /* If this is happening re-entrantly during the call to + * SetWindowPos in wintw_request_resize, let it know that + * we've already done a term_size() so that it doesn't have + * to. */ + sent_term_size = true; } }