When doing a reset also reset termios to its initial state

This commit is contained in:
Kovid Goyal 2025-10-15 07:56:45 +05:30
parent 7c237dcb02
commit ee9a5386b9
No known key found for this signature in database
GPG key ID: 06BC317B515ACE7C
4 changed files with 22 additions and 1 deletions

View file

@ -3,6 +3,7 @@
import os
import sys
import termios
from collections import defaultdict
from collections.abc import Generator, Sequence
from contextlib import contextmanager, suppress
@ -326,6 +327,7 @@ def fork(self) -> int | None:
else:
stdin_read_fd = stdin_write_fd = -1
self.final_env, must_run_startup_command_via_kitten = self.get_final_env()
self.initial_termios_state = termios.tcgetattr(master)
argv = list(self.argv)
cwd = self.cwd
pass_fds = self.pass_fds
@ -543,7 +545,6 @@ def foreground_environ(self) -> dict[str, str]:
def send_signal_for_key(self, key_num: bytes) -> bool:
import signal
import termios
if self.child_fd is None:
return False
t = termios.tcgetattr(self.child_fd)
@ -561,3 +562,10 @@ def send_signal_for_key(self, key_num: bytes) -> bool:
pgrp = os.tcgetpgrp(self.child_fd)
os.killpg(pgrp, s)
return True
def reset_termios_state(self) -> None:
if s := getattr(self, 'initial_termios_state', None):
try:
termios.tcsetattr(s, termios.TCSANOW)
except OSError:
pass

View file

@ -213,6 +213,7 @@ screen_reset(Screen *self) {
set_dynamic_color(self, 110, NULL);
set_dynamic_color(self, 111, NULL);
set_color_table_color(self, 104, NULL);
CALLBACK("on_reset", NULL)
}
void

View file

@ -1333,6 +1333,9 @@ def report_color(self, code: str, col: Color) -> None:
b |= b << 8
self.screen.send_escape_code_to_child(ESC_OSC, f'{code};rgb:{r:04x}/{g:04x}/{b:04x}')
def on_reset(self) -> None:
self.child.reset_termios_state()
def notify_child_of_resize(self) -> None:
pty_size = self.last_reported_pty_size
if pty_size[0] > -1 and self.screen.in_band_resize_notification:

View file

@ -60,6 +60,10 @@ def write(self, data) -> None:
def notify_child_of_resize(self):
self.num_of_resize_events += 1
def on_reset(self) -> None:
if self.pty is not None:
self.pty.reset_termios_state()
def color_control(self, code, data) -> None:
from kitty.window import color_control
response = color_control(self.color_profile, code, data)
@ -331,6 +335,7 @@ def __init__(
from kitty.child import openpty
self.master_fd, self.slave_fd = openpty()
self.child_pid = 0
self.initial_termios_state = termios.tcgetattr(self.master_fd)
else:
self.child_pid, self.master_fd = fork()
self.is_child = self.child_pid == CHILD
@ -364,6 +369,10 @@ def __init__(
self.screen = Screen(self.callbacks, rows, columns, scrollback, cell_width, cell_height, 0, self.callbacks)
self.received_bytes = b''
def reset_termios_state(self):
if s := getattr(self, 'initial_termios_state', None):
termios.tcsetattr(self.master_fd, s)
def turn_off_echo(self):
s = termios.tcgetattr(self.master_fd)
s[3] &= ~termios.ECHO