mirror of
https://github.com/kovidgoyal/kitty
synced 2026-07-23 16:58:09 +02:00
@@ -92,6 +92,8 @@ Detailed list of changes
|
|||||||
|
|
||||||
- Splits layout: Fix the ``move_to_screen_edge`` action breaking when only a single window is present (:iss:`7621`)
|
- Splits layout: Fix the ``move_to_screen_edge`` action breaking when only a single window is present (:iss:`7621`)
|
||||||
|
|
||||||
|
- Add support for in-band window resize notifications (:iss:`7642`)
|
||||||
|
|
||||||
0.35.2 [2024-06-22]
|
0.35.2 [2024-06-22]
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
|||||||
@@ -1131,6 +1131,7 @@ class Screen:
|
|||||||
historybuf: HistoryBuf
|
historybuf: HistoryBuf
|
||||||
linebuf: LineBuf
|
linebuf: LineBuf
|
||||||
in_bracketed_paste_mode: bool
|
in_bracketed_paste_mode: bool
|
||||||
|
in_band_resize_notification: bool
|
||||||
cursor_visible: bool
|
cursor_visible: bool
|
||||||
scrolled_by: int
|
scrolled_by: int
|
||||||
cursor: Cursor
|
cursor: Cursor
|
||||||
|
|||||||
@@ -85,5 +85,8 @@
|
|||||||
// Pending updates mode
|
// Pending updates mode
|
||||||
#define PENDING_UPDATE (2026 << 5)
|
#define PENDING_UPDATE (2026 << 5)
|
||||||
|
|
||||||
|
// In-band resize notification mode
|
||||||
|
#define INBAND_RESIZE_NOTIFICATION (2048 << 5)
|
||||||
|
|
||||||
// Handle Ctrl-C/Ctrl-Z mode
|
// Handle Ctrl-C/Ctrl-Z mode
|
||||||
#define HANDLE_TERMIOS_SIGNALS (19997 << 5)
|
#define HANDLE_TERMIOS_SIGNALS (19997 << 5)
|
||||||
|
|||||||
@@ -1153,6 +1153,12 @@ set_mode_from_const(Screen *self, unsigned int mode, bool val) {
|
|||||||
log_error("Pending mode change to already current mode (%d) requested. Either pending mode expired or there is an application bug.", val);
|
log_error("Pending mode change to already current mode (%d) requested. Either pending mode expired or there is an application bug.", val);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case INBAND_RESIZE_NOTIFICATION:
|
||||||
|
if (val != self->modes.mINBAND_RESIZE_NOTIFICATION) {
|
||||||
|
self->modes.mINBAND_RESIZE_NOTIFICATION = val;
|
||||||
|
if (val) CALLBACK("notify_child_of_resize", NULL);
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
private = mode >= 1 << 5;
|
private = mode >= 1 << 5;
|
||||||
if (private) mode >>= 5;
|
if (private) mode >>= 5;
|
||||||
@@ -1662,6 +1668,7 @@ copy_specific_mode(Screen *self, unsigned int mode, const ScreenModes *src, Scre
|
|||||||
SIMPLE_MODE(DECARM)
|
SIMPLE_MODE(DECARM)
|
||||||
SIMPLE_MODE(BRACKETED_PASTE)
|
SIMPLE_MODE(BRACKETED_PASTE)
|
||||||
SIMPLE_MODE(FOCUS_TRACKING)
|
SIMPLE_MODE(FOCUS_TRACKING)
|
||||||
|
SIMPLE_MODE(INBAND_RESIZE_NOTIFICATION)
|
||||||
SIMPLE_MODE(DECCKM)
|
SIMPLE_MODE(DECCKM)
|
||||||
SIMPLE_MODE(DECTCEM)
|
SIMPLE_MODE(DECTCEM)
|
||||||
SIMPLE_MODE(DECAWM)
|
SIMPLE_MODE(DECAWM)
|
||||||
@@ -1702,6 +1709,7 @@ copy_specific_modes(Screen *self, const ScreenModes *src, ScreenModes *dest) {
|
|||||||
copy_specific_mode(self, DECARM, src, dest);
|
copy_specific_mode(self, DECARM, src, dest);
|
||||||
copy_specific_mode(self, BRACKETED_PASTE, src, dest);
|
copy_specific_mode(self, BRACKETED_PASTE, src, dest);
|
||||||
copy_specific_mode(self, FOCUS_TRACKING, src, dest);
|
copy_specific_mode(self, FOCUS_TRACKING, src, dest);
|
||||||
|
copy_specific_mode(self, INBAND_RESIZE_NOTIFICATION, src, dest);
|
||||||
copy_specific_mode(self, DECCKM, src, dest);
|
copy_specific_mode(self, DECCKM, src, dest);
|
||||||
copy_specific_mode(self, DECTCEM, src, dest);
|
copy_specific_mode(self, DECTCEM, src, dest);
|
||||||
copy_specific_mode(self, DECAWM, src, dest);
|
copy_specific_mode(self, DECAWM, src, dest);
|
||||||
@@ -2196,6 +2204,7 @@ report_mode_status(Screen *self, unsigned int which, bool private) {
|
|||||||
KNOWN_MODE(DECCKM);
|
KNOWN_MODE(DECCKM);
|
||||||
KNOWN_MODE(BRACKETED_PASTE);
|
KNOWN_MODE(BRACKETED_PASTE);
|
||||||
KNOWN_MODE(FOCUS_TRACKING);
|
KNOWN_MODE(FOCUS_TRACKING);
|
||||||
|
KNOWN_MODE(INBAND_RESIZE_NOTIFICATION);
|
||||||
#undef KNOWN_MODE
|
#undef KNOWN_MODE
|
||||||
case ALTERNATE_SCREEN:
|
case ALTERNATE_SCREEN:
|
||||||
ans = self->linebuf == self->alt_linebuf ? 1 : 2; break;
|
ans = self->linebuf == self->alt_linebuf ? 1 : 2; break;
|
||||||
@@ -3830,6 +3839,7 @@ WRAP0(clear_scrollback)
|
|||||||
|
|
||||||
MODE_GETSET(in_bracketed_paste_mode, BRACKETED_PASTE)
|
MODE_GETSET(in_bracketed_paste_mode, BRACKETED_PASTE)
|
||||||
MODE_GETSET(focus_tracking_enabled, FOCUS_TRACKING)
|
MODE_GETSET(focus_tracking_enabled, FOCUS_TRACKING)
|
||||||
|
MODE_GETSET(in_band_resize_notification, INBAND_RESIZE_NOTIFICATION)
|
||||||
MODE_GETSET(auto_repeat_enabled, DECARM)
|
MODE_GETSET(auto_repeat_enabled, DECARM)
|
||||||
MODE_GETSET(cursor_visible, DECTCEM)
|
MODE_GETSET(cursor_visible, DECTCEM)
|
||||||
MODE_GETSET(cursor_key_mode, DECCKM)
|
MODE_GETSET(cursor_key_mode, DECCKM)
|
||||||
@@ -4852,6 +4862,7 @@ static PyGetSetDef getsetters[] = {
|
|||||||
GETSET(in_bracketed_paste_mode)
|
GETSET(in_bracketed_paste_mode)
|
||||||
GETSET(auto_repeat_enabled)
|
GETSET(auto_repeat_enabled)
|
||||||
GETSET(focus_tracking_enabled)
|
GETSET(focus_tracking_enabled)
|
||||||
|
GETSET(in_band_resize_notification)
|
||||||
GETSET(cursor_visible)
|
GETSET(cursor_visible)
|
||||||
GETSET(cursor_key_mode)
|
GETSET(cursor_key_mode)
|
||||||
GETSET(disable_ligatures)
|
GETSET(disable_ligatures)
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ typedef enum ScrollTypes { SCROLL_LINE = -999999, SCROLL_PAGE, SCROLL_FULL } Scr
|
|||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
bool mLNM, mIRM, mDECTCEM, mDECSCNM, mDECOM, mDECAWM, mDECCOLM, mDECARM, mDECCKM,
|
bool mLNM, mIRM, mDECTCEM, mDECSCNM, mDECOM, mDECAWM, mDECCOLM, mDECARM, mDECCKM,
|
||||||
mBRACKETED_PASTE, mFOCUS_TRACKING, mDECSACE, mHANDLE_TERMIOS_SIGNALS;
|
mBRACKETED_PASTE, mFOCUS_TRACKING, mDECSACE, mHANDLE_TERMIOS_SIGNALS, mINBAND_RESIZE_NOTIFICATION;
|
||||||
MouseTrackingMode mouse_tracking_mode;
|
MouseTrackingMode mouse_tracking_mode;
|
||||||
MouseTrackingProtocol mouse_tracking_protocol;
|
MouseTrackingProtocol mouse_tracking_protocol;
|
||||||
} ScreenModes;
|
} ScreenModes;
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ from .fast_data_types import (
|
|||||||
CURSOR_BEAM,
|
CURSOR_BEAM,
|
||||||
CURSOR_BLOCK,
|
CURSOR_BLOCK,
|
||||||
CURSOR_UNDERLINE,
|
CURSOR_UNDERLINE,
|
||||||
|
ESC_CSI,
|
||||||
ESC_DCS,
|
ESC_DCS,
|
||||||
ESC_OSC,
|
ESC_OSC,
|
||||||
GLFW_MOD_CONTROL,
|
GLFW_MOD_CONTROL,
|
||||||
@@ -862,6 +863,8 @@ class Window:
|
|||||||
boss = get_boss()
|
boss = get_boss()
|
||||||
boss.child_monitor.resize_pty(self.id, *current_pty_size)
|
boss.child_monitor.resize_pty(self.id, *current_pty_size)
|
||||||
self.last_resized_at = monotonic()
|
self.last_resized_at = monotonic()
|
||||||
|
self.last_reported_pty_size = current_pty_size
|
||||||
|
self.notify_child_of_resize()
|
||||||
if not self.child_is_launched:
|
if not self.child_is_launched:
|
||||||
self.child.mark_terminal_ready()
|
self.child.mark_terminal_ready()
|
||||||
self.child_is_launched = True
|
self.child_is_launched = True
|
||||||
@@ -871,7 +874,6 @@ class Window:
|
|||||||
print(f'[{now:.3f}] Child launched', file=sys.stderr)
|
print(f'[{now:.3f}] Child launched', file=sys.stderr)
|
||||||
elif boss.args.debug_rendering:
|
elif boss.args.debug_rendering:
|
||||||
print(f'[{monotonic():.3f}] SIGWINCH sent to child in window: {self.id} with size: {current_pty_size}', file=sys.stderr)
|
print(f'[{monotonic():.3f}] SIGWINCH sent to child in window: {self.id} with size: {current_pty_size}', file=sys.stderr)
|
||||||
self.last_reported_pty_size = current_pty_size
|
|
||||||
else:
|
else:
|
||||||
mark_os_window_dirty(self.os_window_id)
|
mark_os_window_dirty(self.os_window_id)
|
||||||
|
|
||||||
@@ -1222,6 +1224,10 @@ class Window:
|
|||||||
identifier = sanitize_identifier_pat().sub('', identifier)
|
identifier = sanitize_identifier_pat().sub('', identifier)
|
||||||
self.screen.send_escape_code_to_child(ESC_OSC, f'99;i={identifier};')
|
self.screen.send_escape_code_to_child(ESC_OSC, f'99;i={identifier};')
|
||||||
|
|
||||||
|
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:
|
||||||
|
self.screen.send_escape_code_to_child(ESC_CSI, f'48;{pty_size[0]};{pty_size[1]};{pty_size[3]};{pty_size[2]}t')
|
||||||
|
|
||||||
def set_dynamic_color(self, code: int, value: Union[str, bytes, memoryview] = '') -> None:
|
def set_dynamic_color(self, code: int, value: Union[str, bytes, memoryview] = '') -> None:
|
||||||
if isinstance(value, (bytes, memoryview)):
|
if isinstance(value, (bytes, memoryview)):
|
||||||
|
|||||||
@@ -50,6 +50,9 @@ class Callbacks:
|
|||||||
def write(self, data) -> None:
|
def write(self, data) -> None:
|
||||||
self.wtcbuf += bytes(data)
|
self.wtcbuf += bytes(data)
|
||||||
|
|
||||||
|
def notify_child_of_resize(self):
|
||||||
|
self.num_of_resize_events += 1
|
||||||
|
|
||||||
def title_changed(self, data, is_base64=False) -> None:
|
def title_changed(self, data, is_base64=False) -> None:
|
||||||
self.titlebuf.append(process_title_from_child(data, is_base64, ''))
|
self.titlebuf.append(process_title_from_child(data, is_base64, ''))
|
||||||
|
|
||||||
@@ -106,6 +109,7 @@ class Callbacks:
|
|||||||
self.last_cmd_exit_status = sys.maxsize
|
self.last_cmd_exit_status = sys.maxsize
|
||||||
self.last_cmd_cmdline = ''
|
self.last_cmd_cmdline = ''
|
||||||
self.last_cmd_at = 0
|
self.last_cmd_at = 0
|
||||||
|
self.num_of_resize_events = 0
|
||||||
|
|
||||||
def on_bell(self) -> None:
|
def on_bell(self) -> None:
|
||||||
self.bell_count += 1
|
self.bell_count += 1
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
# License: GPL v3 Copyright: 2016, Kovid Goyal <kovid at kovidgoyal.net>
|
# License: GPL v3 Copyright: 2016, Kovid Goyal <kovid at kovidgoyal.net>
|
||||||
|
|
||||||
from kitty.fast_data_types import DECAWM, DECCOLM, DECOM, IRM, VT_PARSER_BUFFER_SIZE, Cursor
|
from kitty.fast_data_types import DECAWM, DECCOLM, DECOM, IRM, VT_PARSER_BUFFER_SIZE, Cursor, ESC_CSI
|
||||||
from kitty.marks import marker_from_function, marker_from_regex
|
from kitty.marks import marker_from_function, marker_from_regex
|
||||||
from kitty.window import pagerhist
|
from kitty.window import pagerhist
|
||||||
|
|
||||||
@@ -304,6 +304,14 @@ class TestScreen(BaseTest):
|
|||||||
s.draw('x' * len(str(s.line(1))))
|
s.draw('x' * len(str(s.line(1))))
|
||||||
s.resize(s.lines, s.columns + 4)
|
s.resize(s.lines, s.columns + 4)
|
||||||
self.ae(str(s.linebuf), 'xxx\nxx\nbb\n\n')
|
self.ae(str(s.linebuf), 'xxx\nxx\nbb\n\n')
|
||||||
|
s = self.create_screen()
|
||||||
|
c = s.callbacks
|
||||||
|
parse_bytes(s, b'\x1b[?2048$p') # ]
|
||||||
|
self.ae(c.wtcbuf, b'\x1b[?2048;2$y') # ]
|
||||||
|
c.clear()
|
||||||
|
parse_bytes(s, b'\x1b[?2048h\x1b[?2048$p') # ]
|
||||||
|
self.ae(c.wtcbuf, b'\x1b[?2048;1$y') # ]
|
||||||
|
self.ae(c.num_of_resize_events, 1)
|
||||||
|
|
||||||
def test_cursor_after_resize(self):
|
def test_cursor_after_resize(self):
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user