fix(terminal): avoid more busy_start lacking busy_stop (#32509)

Problem: after #32458, it may still be possible for `busy_start` UI events to be
emitted without matching `busy_stop`s in the terminal.

Solution: do `terminal_enter`'s cursor visibility check immediately after
setting/restoring State so it occurs before events. This ensures that if pending
escape sequences are processed while in `terminal_enter`, the cursor's initial
visibility is set before `is_focused` is checked by `term_settermprop`.

As a result, we can move the call to `showmode` back to where it was originally.
This commit is contained in:
Sean Dewar
2025-02-19 10:47:44 +00:00
committed by GitHub
parent a3eb49f638
commit f3ce67549c
2 changed files with 35 additions and 9 deletions

View File

@ -662,6 +662,10 @@ bool terminal_enter(void)
State = MODE_TERMINAL;
mapped_ctrl_c |= MODE_TERMINAL; // Always map CTRL-C to avoid interrupt.
RedrawingDisabled = false;
if (!s->term->cursor.visible) {
// Hide cursor if it should be hidden. Do so right after setting State, before events.
ui_busy_start();
}
// Disable these options in terminal-mode. They are nonsense because cursor is
// placed at end of buffer to "follow" output. #11072
@ -693,14 +697,10 @@ bool terminal_enter(void)
refresh_cursor(s->term);
adjust_topline(s->term, buf, 0); // scroll to end
showmode();
curwin->w_redr_status = true; // For mode() in statusline. #8323
redraw_custom_title_later();
if (!s->term->cursor.visible) {
// Hide cursor if it should be hidden
ui_busy_start();
}
ui_cursor_shape();
showmode();
apply_autocmds(EVENT_TERMENTER, NULL, NULL, false, curbuf);
may_trigger_modechanged();
@ -716,6 +716,11 @@ bool terminal_enter(void)
}
State = save_state;
RedrawingDisabled = s->save_rd;
if (!s->term->cursor.visible) {
// If cursor was hidden, show it again. Do so right after restoring State, before events.
ui_busy_stop();
}
apply_autocmds(EVENT_TERMLEAVE, NULL, NULL, false, curbuf);
// Restore the terminal cursor to what is set in 'guicursor'
@ -746,10 +751,6 @@ bool terminal_enter(void)
} else {
unshowmode(true);
}
if (!s->term->cursor.visible) {
// If cursor was hidden, show it again
ui_busy_stop();
}
ui_cursor_shape();
if (s->close) {
bool wipe = s->term->buf_handle != 0;

View File

@ -382,6 +382,31 @@ describe(':terminal cursor', function()
^ |
|*5
]])
feed('i')
screen:expect([[
tty ready |
|*5
{3:-- TERMINAL --} |
]])
-- Cursor currently hidden; request to show it while in a TermLeave autocmd.
-- Process events (via :sleep) to handle the escape sequence immediately.
command([[autocmd TermLeave * ++once call chansend(b:terminal_job_id, "\e[?25h") | sleep 1m]])
feed([[<C-\><C-N>]]) -- Exit terminal mode
screen:expect([[
tty ready |
^ |
|*5
]])
feed('i')
screen:expect([[
tty ready |
^ |
|*4
{3:-- TERMINAL --} |
]])
end)
end)