mirror of
https://github.com/neovim/neovim.git
synced 2025-09-06 03:18:16 +00:00
fix(tui): do not remove SIGWINCH handler when resize events are enabled (#35221)
When Nvim is started in one terminal emulator, suspended, and later resumed in a different terminal emulator (as can happen when using e.g. a multiplexer), the new terminal emulator will not have all of the same modes enabled that the original terminal emulator had. This is a problem in particular for in-band resize events because we were disabling the SIGWINCH signal handler when we determined that the terminal supported this mode. However, if the new terminal does not support this mode then the SIGWINCH handler remains disabled, and Neovim no longer properly resizes. Instead of disabling the SIGWINCH handler, we track the state of the resize events mode internally. If the mode is enabled then we return early from the SIGWINCH handler before performing any ioctls or other system calls. But if the mode is not enabled we proceed as normal.
This commit is contained in:
@@ -112,7 +112,15 @@ struct TUIData {
|
|||||||
bool set_cursor_color_as_str;
|
bool set_cursor_color_as_str;
|
||||||
bool cursor_has_color;
|
bool cursor_has_color;
|
||||||
bool is_starting;
|
bool is_starting;
|
||||||
bool did_set_grapheme_cluster_mode;
|
bool resize_events_enabled;
|
||||||
|
|
||||||
|
// Terminal modes that Nvim enabled that it must disable on exit
|
||||||
|
struct {
|
||||||
|
bool grapheme_clusters : 1;
|
||||||
|
bool theme_updates : 1;
|
||||||
|
bool resize_events : 1;
|
||||||
|
} modes;
|
||||||
|
|
||||||
FILE *screenshot;
|
FILE *screenshot;
|
||||||
cursorentry_T cursor_shapes[SHAPE_IDX_COUNT];
|
cursorentry_T cursor_shapes[SHAPE_IDX_COUNT];
|
||||||
HlAttrs clear_attrs;
|
HlAttrs clear_attrs;
|
||||||
@@ -245,19 +253,23 @@ void tui_handle_term_mode(TUIData *tui, TermMode mode, TermModeState state)
|
|||||||
case kTermModeGraphemeClusters:
|
case kTermModeGraphemeClusters:
|
||||||
if (!is_set) {
|
if (!is_set) {
|
||||||
tui_set_term_mode(tui, mode, true);
|
tui_set_term_mode(tui, mode, true);
|
||||||
tui->did_set_grapheme_cluster_mode = true;
|
tui->modes.grapheme_clusters = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case kTermModeThemeUpdates:
|
case kTermModeThemeUpdates:
|
||||||
if (!is_set) {
|
if (!is_set) {
|
||||||
tui_set_term_mode(tui, mode, true);
|
tui_set_term_mode(tui, mode, true);
|
||||||
|
tui->modes.theme_updates = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case kTermModeResizeEvents:
|
case kTermModeResizeEvents:
|
||||||
signal_watcher_stop(&tui->winch_handle);
|
|
||||||
if (!is_set) {
|
if (!is_set) {
|
||||||
tui_set_term_mode(tui, mode, true);
|
tui_set_term_mode(tui, mode, true);
|
||||||
|
tui->modes.resize_events = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We track both whether the mode is enabled AND if Nvim was the one to enable it
|
||||||
|
tui->resize_events_enabled = true;
|
||||||
break;
|
break;
|
||||||
case kTermModeLeftAndRightMargins:
|
case kTermModeLeftAndRightMargins:
|
||||||
tui->has_left_and_right_margin_mode = true;
|
tui->has_left_and_right_margin_mode = true;
|
||||||
@@ -365,7 +377,10 @@ static void terminfo_start(TUIData *tui)
|
|||||||
tui->overflow = false;
|
tui->overflow = false;
|
||||||
tui->set_cursor_color_as_str = false;
|
tui->set_cursor_color_as_str = false;
|
||||||
tui->cursor_has_color = false;
|
tui->cursor_has_color = false;
|
||||||
tui->did_set_grapheme_cluster_mode = false;
|
tui->resize_events_enabled = false;
|
||||||
|
tui->modes.grapheme_clusters = false;
|
||||||
|
tui->modes.resize_events = false;
|
||||||
|
tui->modes.theme_updates = false;
|
||||||
tui->showing_mode = SHAPE_IDX_N;
|
tui->showing_mode = SHAPE_IDX_N;
|
||||||
tui->unibi_ext.set_cursor_color = -1;
|
tui->unibi_ext.set_cursor_color = -1;
|
||||||
tui->unibi_ext.reset_cursor_color = -1;
|
tui->unibi_ext.reset_cursor_color = -1;
|
||||||
@@ -529,7 +544,9 @@ static void terminfo_disable(TUIData *tui)
|
|||||||
{
|
{
|
||||||
// Disable theme update notifications. We do this first to avoid getting any
|
// Disable theme update notifications. We do this first to avoid getting any
|
||||||
// more notifications after we reset the cursor and any color palette changes.
|
// more notifications after we reset the cursor and any color palette changes.
|
||||||
tui_set_term_mode(tui, kTermModeThemeUpdates, false);
|
if (tui->modes.theme_updates) {
|
||||||
|
tui_set_term_mode(tui, kTermModeThemeUpdates, false);
|
||||||
|
}
|
||||||
|
|
||||||
// Destroy output stuff
|
// Destroy output stuff
|
||||||
tui_mode_change(tui, NULL_STRING, SHAPE_IDX_N);
|
tui_mode_change(tui, NULL_STRING, SHAPE_IDX_N);
|
||||||
@@ -542,9 +559,12 @@ static void terminfo_disable(TUIData *tui)
|
|||||||
// Reset the key encoding
|
// Reset the key encoding
|
||||||
tui_reset_key_encoding(tui);
|
tui_reset_key_encoding(tui);
|
||||||
|
|
||||||
// Disable resize events
|
// Disable terminal modes that we enabled
|
||||||
tui_set_term_mode(tui, kTermModeResizeEvents, false);
|
if (tui->modes.resize_events) {
|
||||||
if (tui->did_set_grapheme_cluster_mode) {
|
tui_set_term_mode(tui, kTermModeResizeEvents, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tui->modes.grapheme_clusters) {
|
||||||
tui_set_term_mode(tui, kTermModeGraphemeClusters, false);
|
tui_set_term_mode(tui, kTermModeGraphemeClusters, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -690,7 +710,7 @@ static void sigwinch_cb(SignalWatcher *watcher, int signum, void *cbdata)
|
|||||||
{
|
{
|
||||||
got_winch++;
|
got_winch++;
|
||||||
TUIData *tui = cbdata;
|
TUIData *tui = cbdata;
|
||||||
if (tui_is_stopped(tui)) {
|
if (tui_is_stopped(tui) || tui->resize_events_enabled) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user