From dd20789249721ff953d75334f9af90a38c7ff854 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Mon, 28 May 2018 13:47:42 +0530 Subject: [PATCH] Add support for the CSI t escape code to query window and cell sizes --- graphics-protocol.asciidoc | 4 ++++ kitty/parser.c | 16 ++++++++++++++++ kitty/screen.c | 28 ++++++++++++++++++++++++++++ kitty/screen.h | 1 + kitty_tests/parser.py | 3 +++ 5 files changed, 52 insertions(+) diff --git a/graphics-protocol.asciidoc b/graphics-protocol.asciidoc index 13ce4fb36..51c787aab 100644 --- a/graphics-protocol.asciidoc +++ b/graphics-protocol.asciidoc @@ -56,6 +56,10 @@ print('number of columns: {}, number of rows: {}, screen width: {}, screen heigh Note that some terminals return `0` for the width and height values. Such terminals should be modified to return the correct values. Examples of terminals that return correct values: `kitty, xterm` +You can also use the *CSI t* escape code to get the screen size. Send `[14t` to *stdout* and kitty will reply on *stdin* with +`[4;;t` where *height* and *width* are the window size in pixels. This escape code is supported in many terminals, +not just kitty. + == The graphics escape code All graphics escape codes are of the form: diff --git a/kitty/parser.c b/kitty/parser.c index aa334d4ea..0776949b9 100644 --- a/kitty/parser.c +++ b/kitty/parser.c @@ -694,6 +694,22 @@ 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; + } + break; + } + REPORT_ERROR("Unknown CSI t sequence with start and end modifiers: '%c' '%c' and %u parameters", start_modifier, end_modifier, num_params); + break; case 'u': if (!start_modifier && !end_modifier && !num_params) { REPORT_COMMAND(screen_restore_cursor); diff --git a/kitty/screen.c b/kitty/screen.c index 3aa2b747e..892f85a33 100644 --- a/kitty/screen.c +++ b/kitty/screen.c @@ -1113,6 +1113,34 @@ report_device_attributes(Screen *self, unsigned int mode, char start_modifier) { } } +void +screen_report_size(Screen *self, unsigned int which) { + char buf[32] = {0}; + unsigned int code = 0; + unsigned int width = 0, height = 0; + switch(which) { + case 14: + code = 4; + width = self->cell_size.width * self->columns; + height = self->cell_size.height * self->lines; + break; + case 16: + code = 6; + width = self->cell_size.width; + height = self->cell_size.height; + break; + case 18: + code = 8; + width = self->columns; + height = self->lines; + break; + } + if (code) { + snprintf(buf, sizeof(buf), "%u;%u;%ut", code, height, width); + write_escape_code_to_child(self, CSI, buf); + } +} + void report_device_status(Screen *self, unsigned int which, bool private) { // We dont implement the private device status codes, since I haven't come diff --git a/kitty/screen.h b/kitty/screen.h index e7e4d088c..0d79147db 100644 --- a/kitty/screen.h +++ b/kitty/screen.h @@ -172,6 +172,7 @@ void screen_handle_graphics_command(Screen *self, const GraphicsCommand *cmd, co 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); #define DECLARE_CH_SCREEN_HANDLER(name) void screen_##name(Screen *screen); DECLARE_CH_SCREEN_HANDLER(bell) DECLARE_CH_SCREEN_HANDLER(backspace) diff --git a/kitty_tests/parser.py b/kitty_tests/parser.py index 3f79ffcde..b64553e3b 100644 --- a/kitty_tests/parser.py +++ b/kitty_tests/parser.py @@ -160,6 +160,9 @@ class TestParser(BaseTest): pb('\033[?1$p', ('report_mode_status', 1, 1)) self.ae(c.wtcbuf, b'\033[?1;2$y') pb('\033[2;4r', ('screen_set_margins', 2, 4)) + c.clear() + pb('\033[14t', ('screen_report_size', 14)) + self.ae(c.wtcbuf, b'\033[4;100;50t') self.ae(s.margin_top, 1), self.ae(s.margin_bottom, 3) pb('\033[r', ('screen_set_margins', 0, 0)) self.ae(s.margin_top, 0), self.ae(s.margin_bottom, 4)