diff --git a/kitty/client.py b/kitty/client.py index 3e8da20f0..8f313992c 100644 --- a/kitty/client.py +++ b/kitty/client.py @@ -122,6 +122,10 @@ def draw(*a): write(' '.join(a)) +def screen_manipulate_title_stack(op, which): + write(CSI + '%d;%dt' % (op, which)) + + def report_device_attributes(mode, char): x = CSI if char: diff --git a/kitty/parser.c b/kitty/parser.c index 53fe6f9c0..12b305d2e 100644 --- a/kitty/parser.c +++ b/kitty/parser.c @@ -703,20 +703,28 @@ dispatch_csi(Screen *screen, PyObject DUMP_UNUSED *dump_callback) { REPORT_ERROR("Unknown CSI s sequence with start and end modifiers: '%c' '%c' and %u parameters", start_modifier, end_modifier, num_params); break; case 't': - if (!start_modifier && !end_modifier && num_params == 1) { - switch(params[0]) { - case 14: - case 16: - case 18: - CALL_CSI_HANDLER1(screen_report_size, 0); - break; - default: - REPORT_ERROR("Unknown CSI t sequences with parameter: '%u'", params[0]); - break; - } + if (!num_params) { + REPORT_ERROR("Unknown CSI t sequence with start and end modifiers: '%c' '%c' and no parameters", start_modifier, end_modifier); break; } - REPORT_ERROR("Unknown CSI t sequence with start and end modifiers: '%c' '%c' and %u parameters", start_modifier, end_modifier, num_params); + if (start_modifier || end_modifier) { + REPORT_ERROR("Unknown CSI t sequence with start and end modifiers: '%c' '%c', %u parameters and first parameter: %u", start_modifier, end_modifier, num_params, params[0]); + break; + } + switch(params[0]) { + case 14: + case 16: + case 18: + CALL_CSI_HANDLER1(screen_report_size, 0); + break; + case 22: + case 23: + CALL_CSI_HANDLER2(screen_manipulate_title_stack, 22, 0); + break; + default: + REPORT_ERROR("Unknown CSI t window manipulation sequence with %u parameters and first parameter: %u", num_params, params[0]); + break; + } break; case 'u': if (!start_modifier && !end_modifier && !num_params) { diff --git a/kitty/screen.c b/kitty/screen.c index ffe8e539a..0000f5e36 100644 --- a/kitty/screen.c +++ b/kitty/screen.c @@ -1254,6 +1254,15 @@ screen_report_size(Screen *self, unsigned int which) { } } +void +screen_manipulate_title_stack(Screen *self, unsigned int op, unsigned int which) { + CALLBACK("manipulate_title_stack", "OOO", + op == 23 ? Py_True : Py_False, + which == 0 || which == 2 ? Py_True : Py_False, + which == 0 || which == 1 ? Py_True : Py_False + ); +} + void report_device_status(Screen *self, unsigned int which, bool private) { // We don't implement the private device status codes, since I haven't come diff --git a/kitty/screen.h b/kitty/screen.h index 65cb710f7..06a463230 100644 --- a/kitty/screen.h +++ b/kitty/screen.h @@ -191,6 +191,7 @@ bool screen_open_url(Screen*); void screen_dirty_sprite_positions(Screen *self); void screen_rescale_images(Screen *self); void screen_report_size(Screen *, unsigned int which); +void screen_manipulate_title_stack(Screen *, unsigned int op, unsigned int which); void screen_draw_overlay_text(Screen *self, const char *utf8_text); #define DECLARE_CH_SCREEN_HANDLER(name) void screen_##name(Screen *screen); DECLARE_CH_SCREEN_HANDLER(bell) diff --git a/kitty/window.py b/kitty/window.py index bc3751d68..ab344543b 100644 --- a/kitty/window.py +++ b/kitty/window.py @@ -110,6 +110,7 @@ class Window: self.overlay_for = None self.default_title = os.path.basename(child.argv[0] or appname) self.child_title = self.default_title + self.title_stack = deque(maxlen=10) self.allow_remote_control = child.allow_remote_control self.id = add_window(tab.os_window_id, tab.id, self.title) if not self.id: @@ -413,6 +414,16 @@ class Window: write('c', set_clipboard_string) if 'write-primary' in self.opts.clipboard_control: write('p', set_primary_selection) + + def manipulate_title_stack(self, pop, title, icon): + if title: + if pop: + if self.title_stack: + self.child_title = self.title_stack.popleft() + self.title_updated() + else: + if self.child_title: + self.title_stack.append(self.child_title) # }}} def text_for_selection(self):