fix(tui): resize at startup #17795

* fix(test): screen.lua nil index
  When actual_rows and expected_rows are different avoid a nil index.
* fix(tui): resize at startup
  The deleted code is not needed after 402b4e8.
  It caused the condition to false positive when the function was called
  more than once before startup (first normal mode). Being itself what
  set the dimension and not the user, locking the size of the screen to
  an incorrect size.
  Make got_winch an int to mitigate: tui_grid_resize changing the size
  of the host terminal between the signal handler and the call to
  sigwinch_cb. Since the actual signal handler uv__signal_handle doesn't
  directly call the callback, the event loop does.

Fixes #17285
Fixes #15044
Fixes #11330
This commit is contained in:
Javier Lopez
2022-07-04 15:09:47 -05:00
committed by Justin M. Keyes
parent 5baa99944a
commit 49a9fb2d98
3 changed files with 26 additions and 19 deletions

View File

@@ -137,8 +137,7 @@ struct TUIData {
char *space_buf; char *space_buf;
}; };
static bool volatile got_winch = false; static int got_winch = 0;
static bool did_user_set_dimensions = false;
static bool cursor_style_enabled = false; static bool cursor_style_enabled = false;
#ifdef INCLUDE_GENERATED_DECLARATIONS #ifdef INCLUDE_GENERATED_DECLARATIONS
@@ -536,7 +535,7 @@ static void sigcont_cb(SignalWatcher *watcher, int signum, void *data)
static void sigwinch_cb(SignalWatcher *watcher, int signum, void *data) static void sigwinch_cb(SignalWatcher *watcher, int signum, void *data)
{ {
got_winch = true; got_winch++;
UI *ui = data; UI *ui = data;
if (tui_is_stopped(ui)) { if (tui_is_stopped(ui)) {
return; return;
@@ -989,7 +988,7 @@ static void tui_grid_resize(UI *ui, Integer g, Integer width, Integer height)
r->right = MIN(r->right, grid->width); r->right = MIN(r->right, grid->width);
} }
if (!got_winch && (!data->is_starting || did_user_set_dimensions)) { if (!got_winch && !data->is_starting) {
// Resize the _host_ terminal. // Resize the _host_ terminal.
UNIBI_SET_NUM_VAR(data->params[0], (int)height); UNIBI_SET_NUM_VAR(data->params[0], (int)height);
UNIBI_SET_NUM_VAR(data->params[1], (int)width); UNIBI_SET_NUM_VAR(data->params[1], (int)width);
@@ -999,7 +998,7 @@ static void tui_grid_resize(UI *ui, Integer g, Integer width, Integer height)
reset_scroll_region(ui, ui->width == grid->width); reset_scroll_region(ui, ui->width == grid->width);
} }
} else { // Already handled the SIGWINCH signal; avoid double-resize. } else { // Already handled the SIGWINCH signal; avoid double-resize.
got_winch = false; got_winch = got_winch > 0 ? got_winch - 1 : 0;
grid->row = -1; grid->row = -1;
} }
} }
@@ -1507,23 +1506,13 @@ static void tui_guess_size(UI *ui)
TUIData *data = ui->data; TUIData *data = ui->data;
int width = 0, height = 0; int width = 0, height = 0;
// 1 - look for non-default 'columns' and 'lines' options during startup // 1 - try from a system call(ioctl/TIOCGWINSZ on unix)
if (data->is_starting && (Columns != DFLT_COLS || Rows != DFLT_ROWS)) {
did_user_set_dimensions = true;
assert(Columns >= 0);
assert(Rows >= 0);
width = Columns;
height = Rows;
goto end;
}
// 2 - try from a system call(ioctl/TIOCGWINSZ on unix)
if (data->out_isatty if (data->out_isatty
&& !uv_tty_get_winsize(&data->output_handle.tty, &width, &height)) { && !uv_tty_get_winsize(&data->output_handle.tty, &width, &height)) {
goto end; goto end;
} }
// 3 - use $LINES/$COLUMNS if available // 2 - use $LINES/$COLUMNS if available
const char *val; const char *val;
int advance; int advance;
if ((val = os_getenv("LINES")) if ((val = os_getenv("LINES"))
@@ -1533,7 +1522,7 @@ static void tui_guess_size(UI *ui)
goto end; goto end;
} }
// 4 - read from terminfo if available // 3 - read from terminfo if available
height = unibi_get_num(data->ut, unibi_lines); height = unibi_get_num(data->ut, unibi_lines);
width = unibi_get_num(data->ut, unibi_columns); width = unibi_get_num(data->ut, unibi_columns);

View File

@@ -86,6 +86,24 @@ describe('TUI', function()
assert_alive() assert_alive()
end) end)
it('resize at startup', function()
-- Issues: #17285 #15044 #11330
screen:try_resize(50, 10)
feed_command([[call termopen([v:progpath, '--clean', '--cmd', 'let start = reltime() | while v:true | if reltimefloat(reltime(start)) > 2 | break | endif | endwhile']) | sleep 500m | vs new]])
screen:expect([[
{1: } {1:│} |
{4:~ }{1:│}{4:~ }|
{4:~ }{1:│}{4:~ }|
{4:~ }{1:│}{4:~ }|
{4:~ }{1:│}{4:~ }|
{4:~ }{1:│}{5:[No Name] 0,0-1 All}|
{4:~ }{1:│} |
{5:new }{MATCH:<.*[/\]nvim }|
|
{3:-- TERMINAL --} |
]])
end)
it('accepts resize while pager is active', function() it('accepts resize while pager is active', function()
child_session:request("nvim_command", [[ child_session:request("nvim_command", [[
set more set more

View File

@@ -380,7 +380,7 @@ function Screen:expect(expected, attr_ids, ...)
for i, row in ipairs(expected_rows) do for i, row in ipairs(expected_rows) do
msg_expected_rows[i] = row msg_expected_rows[i] = row
local m = (row ~= actual_rows[i] and row:match('{MATCH:(.*)}') or nil) local m = (row ~= actual_rows[i] and row:match('{MATCH:(.*)}') or nil)
if row ~= actual_rows[i] and (not m or not actual_rows[i]:match(m)) then if row ~= actual_rows[i] and (not m or not (actual_rows[i] and actual_rows[i]:match(m))) then
msg_expected_rows[i] = '*' .. msg_expected_rows[i] msg_expected_rows[i] = '*' .. msg_expected_rows[i]
if i <= #actual_rows then if i <= #actual_rows then
actual_rows[i] = '*' .. actual_rows[i] actual_rows[i] = '*' .. actual_rows[i]