Support S8C1T mode

That is, eight bit control codes. When in S8C1T mode, kitty will send
only eight bit control codes to the client.
This commit is contained in:
Kovid Goyal 2017-12-03 16:57:08 +05:30
parent ed9b332da5
commit c17c6cae4c
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
17 changed files with 5716 additions and 5637 deletions

View File

@ -9,14 +9,13 @@
from .config import MINIMUM_FONT_SIZE, cached_values, initial_window_size
from .constants import set_boss, wakeup
from .fast_data_types import (
GLFW_KEY_DOWN, GLFW_KEY_UP, ChildMonitor, create_os_window,
current_os_window, destroy_global_data, destroy_sprite_map,
get_clipboard_string, glfw_post_empty_event, layout_sprite_map,
mark_os_window_for_close, show_window, toggle_fullscreen,
viewport_for_window
ChildMonitor, create_os_window, current_os_window, destroy_global_data,
destroy_sprite_map, get_clipboard_string, glfw_post_empty_event,
layout_sprite_map, mark_os_window_for_close, show_window,
toggle_fullscreen, viewport_for_window
)
from .fonts.render import prerender, resize_fonts, set_font_family
from .keys import get_key_map, get_shortcut
from .keys import get_shortcut
from .session import create_session
from .tabs import SpecialWindow, TabManager
from .utils import (
@ -288,12 +287,6 @@ def switch_focus_to(self, window_idx):
old_focus.focus_changed(False)
tab.active_window.focus_changed(True)
def send_fake_scroll(self, window_idx, amt, upwards):
tab = self.active_tab
w = tab.windows[window_idx]
k = get_key_map(w.screen)[GLFW_KEY_UP if upwards else GLFW_KEY_DOWN]
w.write_to_child(k * amt)
def open_url(self, url):
if url:
open_url(url, self.opts.open_url_with)

View File

@ -151,10 +151,10 @@ decoration_as_sgr(uint8_t decoration) {
const char*
cursor_as_sgr(Cursor *self, Cursor *prev) {
static char buf[128], *p;
static char buf[128];
#define SZ sizeof(buf) - (p - buf) - 2
#define P(fmt, ...) { p += snprintf(p, SZ, fmt ";", __VA_ARGS__); }
p = buf;
char *p = buf;
if (self->bold != prev->bold) P("%d", self->bold ? 1 : 22);
if (self->italic != prev->italic) P("%d", self->italic ? 3 : 23);
if (self->reverse != prev->reverse) P("%d", self->reverse ? 7 : 27);

View File

@ -12,6 +12,7 @@
#undef _DARWIN_C_SOURCE
#endif
#include "data-types.h"
#include "control-codes.h"
#include "modes.h"
#include <stddef.h>
#include <termios.h>
@ -229,8 +230,6 @@ PyInit_fast_data_types(void) {
PyModule_AddIntConstant(m, "REVERSE", REVERSE_SHIFT);
PyModule_AddIntConstant(m, "STRIKETHROUGH", STRIKE_SHIFT);
PyModule_AddIntConstant(m, "DECORATION", DECORATION_SHIFT);
PyModule_AddStringMacro(m, BRACKETED_PASTE_START);
PyModule_AddStringMacro(m, BRACKETED_PASTE_END);
PyModule_AddStringMacro(m, ERROR_PREFIX);
PyModule_AddIntMacro(m, CURSOR_BLOCK);
PyModule_AddIntMacro(m, CURSOR_BEAM);
@ -239,6 +238,10 @@ PyInit_fast_data_types(void) {
PyModule_AddIntMacro(m, DECCOLM);
PyModule_AddIntMacro(m, DECOM);
PyModule_AddIntMacro(m, IRM);
PyModule_AddIntMacro(m, CSI);
PyModule_AddIntMacro(m, DCS);
PyModule_AddIntMacro(m, APC);
PyModule_AddIntMacro(m, OSC);
}
return m;

View File

@ -270,6 +270,7 @@ void change_wcwidth(bool use9);
void set_mouse_cursor(MouseShape);
void mouse_event(int, int);
void scroll_event(double, double);
void fake_scroll(bool);
void set_special_key_combo(int glfw_key, int mods);
void on_text_input(unsigned int codepoint, int mods);
void on_key_input(int key, int scancode, int action, int mods);

View File

@ -515,7 +515,7 @@ create_add_response(GraphicsManager UNUSED *self, bool data_loaded, uint32_t iid
if (!data_loaded) return NULL;
snprintf(add_response, 10, "OK");
}
snprintf(rbuf, sizeof(rbuf)/sizeof(rbuf[0]) - 1, "\033_Gi=%u;%s\033\\", iid, add_response);
snprintf(rbuf, sizeof(rbuf)/sizeof(rbuf[0]) - 1, "Gi=%u;%s", iid, add_response);
return rbuf;
}
return NULL;

View File

@ -9,6 +9,7 @@
#include "state.h"
#include "screen.h"
#include "glfw-wrapper.h"
#include "control-codes.h"
const char*
key_to_bytes(int glfw_key, bool smkx, bool extended, int mods, int action) {
@ -133,6 +134,16 @@ get_localized_key(int key, int scancode) {
}
}
static inline void
send_key_to_child(Window *w, int key, int mods, int action) {
Screen *screen = w->render_data.screen;
const char *data = key_to_bytes(key, screen->modes.mDECCKM, screen->modes.mEXTENDED_KEYBOARD, mods, action);
if (data) {
if (screen->modes.mEXTENDED_KEYBOARD) write_escape_code_to_child(screen, APC, data + 1);
else schedule_write_to_child(w->id, (data + 1), *data);
}
}
void
on_key_input(int key, int scancode, int action, int mods) {
Window *w = active_window();
@ -168,11 +179,19 @@ on_key_input(int key, int scancode, int action, int mods) {
(action == GLFW_REPEAT && screen->modes.mDECARM) ||
screen->modes.mEXTENDED_KEYBOARD
) {
const char *data = key_to_bytes(lkey, screen->modes.mDECCKM, screen->modes.mEXTENDED_KEYBOARD, mods, action);
if (data) schedule_write_to_child(w->id, (data + 1), *data);
send_key_to_child(w, lkey, mods, action);
}
}
void
fake_scroll(bool upwards) {
Window *w = active_window();
if (!w) return;
Screen *screen = w->render_data.screen;
send_key_to_child(w, upwards ? GLFW_KEY_UP : GLFW_KEY_DOWN, 0, GLFW_PRESS);
if (screen->modes.mEXTENDED_KEYBOARD) send_key_to_child(w, upwards ? GLFW_KEY_UP : GLFW_KEY_DOWN, 0, GLFW_RELEASE);
}
#define PYWRAP1(name) static PyObject* py##name(PyObject UNUSED *self, PyObject *args)
#define PA(fmt, ...) if(!PyArg_ParseTuple(args, fmt, __VA_ARGS__)) return NULL;
#define M(name, arg_type) {#name, (PyCFunction)py##name, arg_type, NULL}

11124
kitty/keys.h generated

File diff suppressed because it is too large Load Diff

View File

@ -144,7 +144,7 @@ def extended_key_event(key, mods, action):
m |= 0x4
if mods & defines.GLFW_MOD_SUPER:
m |= 0x8
return '\033_K{}{}{}\033\\'.format(
return 'K{}{}{}'.format(
action_map[action], base64_encode(m), name
).encode('ascii')

View File

@ -73,8 +73,8 @@
// Bracketed paste mode
// http://cirw.in/blog/bracketed-paste
#define BRACKETED_PASTE (2004 << 5)
#define BRACKETED_PASTE_START "\033[200~"
#define BRACKETED_PASTE_END "\033[201~"
#define BRACKETED_PASTE_START "200~"
#define BRACKETED_PASTE_END "201~"
// Styled underlines
#define STYLED_UNDERLINES (2016 << 5)

View File

@ -11,6 +11,7 @@
#include <limits.h>
#include <math.h>
#include "glfw-wrapper.h"
#include "control-codes.h"
static MouseShape mouse_cursor_shape = BEAM;
typedef enum MouseActions { PRESS, RELEASE, DRAG, MOVE } MouseAction;
@ -41,7 +42,7 @@ button_map(int button) {
static char mouse_event_buf[64];
size_t
int
encode_mouse_event(Window *w, int button, MouseAction action, int mods) {
unsigned int x = w->mouse_cell_x + 1, y = w->mouse_cell_y + 1; // 1 based indexing
unsigned int cb = 0;
@ -60,14 +61,14 @@ encode_mouse_event(Window *w, int button, MouseAction action, int mods) {
if (mods & GLFW_MOD_CONTROL) cb |= CONTROL_INDICATOR;
switch(screen->modes.mouse_tracking_protocol) {
case SGR_PROTOCOL:
return snprintf(mouse_event_buf, sizeof(mouse_event_buf), "\033[<%d;%d;%d%s", cb, x, y, action == RELEASE ? "m" : "M");
return snprintf(mouse_event_buf, sizeof(mouse_event_buf), "<%d;%d;%d%s", cb, x, y, action == RELEASE ? "m" : "M");
break;
case URXVT_PROTOCOL:
return snprintf(mouse_event_buf, sizeof(mouse_event_buf), "\033[%d;%d;%dM", cb + 32, x, y);
return snprintf(mouse_event_buf, sizeof(mouse_event_buf), "%d;%d;%dM", cb + 32, x, y);
break;
case UTF8_PROTOCOL:
mouse_event_buf[0] = 033; mouse_event_buf[1] = '['; mouse_event_buf[2] = 'M'; mouse_event_buf[3] = cb + 32;
unsigned int sz = 4;
mouse_event_buf[0] = 'M'; mouse_event_buf[1] = cb + 32;
unsigned int sz = 2;
sz += encode_utf8(x + 32, mouse_event_buf + sz);
sz += encode_utf8(y + 32, mouse_event_buf + sz);
return sz;
@ -75,8 +76,8 @@ encode_mouse_event(Window *w, int button, MouseAction action, int mods) {
default:
if (x > 223 || y > 223) return 0;
else {
mouse_event_buf[0] = 033; mouse_event_buf[1] = '['; mouse_event_buf[2] = 'M'; mouse_event_buf[3] = cb + 32; mouse_event_buf[4] = x + 32; mouse_event_buf[5] = y + 32;
return 6;
mouse_event_buf[0] = 'M'; mouse_event_buf[1] = cb + 32; mouse_event_buf[2] = x + 32; mouse_event_buf[3] = y + 32;
return 4;
}
break;
}
@ -190,8 +191,8 @@ HANDLER(handle_move_event) {
}
} else {
if (!mouse_cell_changed) return;
size_t sz = encode_mouse_event(w, MAX(0, button), button >=0 ? DRAG : MOVE, 0);
if (sz) schedule_write_to_child(w->id, mouse_event_buf, sz);
int sz = encode_mouse_event(w, MAX(0, button), button >=0 ? DRAG : MOVE, 0);
if (sz > 0) { mouse_event_buf[sz] = 0; write_escape_code_to_child(screen, CSI, mouse_event_buf); }
}
}
@ -279,8 +280,8 @@ HANDLER(handle_button_event) {
break;
}
} else {
size_t sz = encode_mouse_event(w, button, is_release ? RELEASE : PRESS, modifiers);
if (sz) schedule_write_to_child(w->id, mouse_event_buf, sz);
int sz = encode_mouse_event(w, button, is_release ? RELEASE : PRESS, modifiers);
if (sz > 0) { mouse_event_buf[sz] = 0; write_escape_code_to_child(screen, CSI, mouse_event_buf); }
}
}
@ -354,10 +355,10 @@ scroll_event(double UNUSED xoffset, double yoffset) {
screen_history_scroll(screen, abs(s), upwards);
} else {
if (screen->modes.mouse_tracking_mode) {
size_t sz = encode_mouse_event(w, upwards ? GLFW_MOUSE_BUTTON_4 : GLFW_MOUSE_BUTTON_5, PRESS, 0);
if (sz) schedule_write_to_child(w->id, mouse_event_buf, sz);
int sz = encode_mouse_event(w, upwards ? GLFW_MOUSE_BUTTON_4 : GLFW_MOUSE_BUTTON_5, PRESS, 0);
if (sz > 0) { mouse_event_buf[sz] = 0; write_escape_code_to_child(screen, CSI, mouse_event_buf); }
} else {
call_boss(send_fake_scroll, "IiO", window_idx, abs(s), upwards ? Py_True : Py_False);
fake_scroll(upwards);
}
}
}

View File

@ -276,6 +276,16 @@ handle_esc_mode_char(Screen *screen, uint32_t ch, PyObject DUMP_UNUSED *dump_cal
REPORT_ERROR("Unknown charset: 0x%x", ch); break;
}
break;
case ' ':
switch(ch) {
case 'F':
case 'G':
REPORT_COMMAND(screen_set_8bit_controls, ch == 'G');
screen_set_8bit_controls(screen, ch == 'G');
break;
}
REPORT_ERROR("Unhandled ESC SP escape code: 0x%x", ch); break;
break;
default:
REPORT_ERROR("Unhandled charset related escape code: 0x%x 0x%x", screen->parser_buf[0], ch); break;
}

View File

@ -19,6 +19,7 @@
#include "unicode-data.h"
#include "modes.h"
#include "wcwidth9.h"
#include "control-codes.h"
static const ScreenModes empty_modes = {0, .mDECAWM=true, .mDECTCEM=true, .mDECARM=true};
static Selection EMPTY_SELECTION = {0};
@ -104,9 +105,9 @@ screen_reset(Screen *self) {
linebuf_clear(self->linebuf, BLANK_CHAR);
grman_clear(self->grman);
self->modes = empty_modes;
#define RC(name) self->color_profile->overridden.name = 0
RC(default_fg); RC(default_bg); RC(cursor_color); RC(highlight_fg); RC(highlight_bg);
#undef RC
#define R(name) self->color_profile->overridden.name = 0
R(default_fg); R(default_bg); R(cursor_color); R(highlight_fg); R(highlight_bg);
#undef R
RESET_CHARSETS;
self->margin_top = 0; self->margin_bottom = self->lines - 1;
screen_normal_keypad_mode(self);
@ -355,13 +356,37 @@ write_to_child(Screen *self, const char *data, size_t sz) {
if (self->test_child != Py_None) { PyObject *r = PyObject_CallMethod(self->test_child, "write", "y#", data, sz); if (r == NULL) PyErr_Print(); Py_CLEAR(r); }
}
#define write_str_to_child(s) write_to_child(self, (s), sizeof((s)) - 1)
void
write_escape_code_to_child(Screen *self, unsigned char which, const char *data) {
static char buf[512];
size_t sz;
switch(which) {
case DCS:
sz = snprintf(buf, sizeof(buf) - 1, "%s%s%s", self->modes.eight_bit_controls ? "\x90" : "\033P", data, self->modes.eight_bit_controls ? "\x9c" : "\033\\");
break;
case CSI:
sz = snprintf(buf, sizeof(buf) - 1, "%s%s", self->modes.eight_bit_controls ? "\x9b" : "\033[", data);
break;
case OSC:
sz = snprintf(buf, sizeof(buf) - 1, "%s%s%s", self->modes.eight_bit_controls ? "\x9d" : "\033]", data, self->modes.eight_bit_controls ? "\x9c" : "\033\\");
break;
case PM:
sz = snprintf(buf, sizeof(buf) - 1, "%s%s%s", self->modes.eight_bit_controls ? "\x9e" : "\033^", data, self->modes.eight_bit_controls ? "\x9c" : "\033\\");
break;
case APC:
sz = snprintf(buf, sizeof(buf) - 1, "%s%s%s", self->modes.eight_bit_controls ? "\x9f" : "\033_", data, self->modes.eight_bit_controls ? "\x9c" : "\033\\");
break;
default:
fatal("Unknown escape code to write: %u", which);
}
write_to_child(self, buf, sz);
}
void
screen_handle_graphics_command(Screen *self, const GraphicsCommand *cmd, const uint8_t *payload) {
unsigned int x = self->cursor->x, y = self->cursor->y;
const char *response = grman_handle_command(self->grman, cmd, payload, self->cursor, &self->is_dirty);
if (response != NULL) write_to_child(self, response, strlen(response));
if (response != NULL) write_escape_code_to_child(self, APC, response);
if (x != self->cursor->x || y != self->cursor->y) {
if (self->cursor->x >= self->columns) { self->cursor->x = 0; self->cursor->y++; }
if (self->cursor->y > self->margin_bottom) screen_scroll(self, self->cursor->y - self->margin_bottom);
@ -470,14 +495,20 @@ set_mode_from_const(Screen *self, unsigned int mode, bool val) {
#undef MOUSE_MODE
}
void screen_set_mode(Screen *self, unsigned int mode) {
void
screen_set_mode(Screen *self, unsigned int mode) {
set_mode_from_const(self, mode, true);
}
void screen_reset_mode(Screen *self, unsigned int mode) {
void
screen_reset_mode(Screen *self, unsigned int mode) {
set_mode_from_const(self, mode, false);
}
void
screen_set_8bit_controls(Screen *self, bool yes) {
self->modes.eight_bit_controls = yes;
}
// }}}
// Cursor {{{
@ -944,10 +975,10 @@ report_device_attributes(Screen *self, unsigned int mode, char start_modifier) {
if (mode == 0) {
switch(start_modifier) {
case 0:
write_str_to_child("\x1b[?62;c"); // VT-220 with no extra info
write_escape_code_to_child(self, CSI, "?62;c");
break;
case '>':
write_str_to_child("\x1b[>1;" xstr(PRIMARY_VERSION) ";" xstr(SECONDARY_VERSION) "c"); // VT-220 + primary version + secondary version
write_escape_code_to_child(self, CSI, ">1;" xstr(PRIMARY_VERSION) ";" xstr(SECONDARY_VERSION) "c"); // VT-220 + primary version + secondary version
break;
}
}
@ -958,10 +989,10 @@ report_device_status(Screen *self, unsigned int which, bool private) {
// We dont implement the private device status codes, since I haven't come
// across any programs that use them
unsigned int x, y;
static char buf[50];
static char buf[64];
switch(which) {
case 5: // device status
write_str_to_child("\x1b[0n");
write_escape_code_to_child(self, CSI, "0n");
break;
case 6: // cursor position
x = self->cursor->x; y = self->cursor->y;
@ -971,8 +1002,8 @@ report_device_status(Screen *self, unsigned int which, bool private) {
}
if (self->modes.mDECOM) y -= MAX(y, self->margin_top);
// 1-based indexing
int sz = snprintf(buf, sizeof(buf) - 1, "\x1b[%s%u;%uR", (private ? "?": ""), y + 1, x + 1);
if (sz > 0) write_to_child(self, buf, sz);
int sz = snprintf(buf, sizeof(buf) - 1, "%s%u;%uR", (private ? "?": ""), y + 1, x + 1);
if (sz > 0) write_escape_code_to_child(self, CSI, buf);
break;
}
}
@ -1002,8 +1033,8 @@ report_mode_status(Screen *self, unsigned int which, bool private) {
case STYLED_UNDERLINES:
ans = 3; break;
}
int sz = snprintf(buf, sizeof(buf) - 1, "\x1b[%s%u;%u$y", (private ? "?" : ""), which, ans);
if (sz > 0) write_to_child(self, buf, sz);
int sz = snprintf(buf, sizeof(buf) - 1, "%s%u;%u$y", (private ? "?" : ""), which, ans);
if (sz > 0) write_escape_code_to_child(self, CSI, buf);
}
void
@ -1093,16 +1124,16 @@ screen_request_capabilities(Screen *self, char c, PyObject *q) {
case CURSOR_BEAM:
shape = self->cursor->blink ? 5 : 6; break;
}
shape = snprintf(buf, sizeof(buf), "\033P1$r%d q\033\\", shape);
shape = snprintf(buf, sizeof(buf), "1$r%d q", shape);
} else if (strcmp("m", query) == 0) {
// SGR
shape = snprintf(buf, sizeof(buf), "\033P1$r%sm\033\\", cursor_as_sgr(self->cursor, &blank_cursor));
shape = snprintf(buf, sizeof(buf), "1$r%sm", cursor_as_sgr(self->cursor, &blank_cursor));
} else if (strcmp("r", query) == 0) {
shape = snprintf(buf, sizeof(buf), "\033P1$r%u;%ur\033\\", self->margin_top + 1, self->margin_bottom + 1);
shape = snprintf(buf, sizeof(buf), "1$r%u;%ur", self->margin_top + 1, self->margin_bottom + 1);
} else {
shape = snprintf(buf, sizeof(buf), "\033P0$r%s\033\\", query);
shape = snprintf(buf, sizeof(buf), "0$r%s", query);
}
if (shape) write_to_child(self, buf, shape);
if (shape > 0) write_escape_code_to_child(self, DCS, buf);
break;
}
}
@ -1523,6 +1554,23 @@ toggle_alt_screen(Screen *self) {
Py_RETURN_NONE;
}
static PyObject*
send_escape_code_to_child(Screen *self, PyObject *args) {
int code;
char *text;
if (!PyArg_ParseTuple(args, "is", &code, &text)) return NULL;
write_escape_code_to_child(self, code, text);
Py_RETURN_NONE;
}
static PyObject*
paste(Screen *self, PyObject *bytes) {
if (self->modes.mBRACKETED_PASTE) write_escape_code_to_child(self, CSI, BRACKETED_PASTE_START);
write_to_child(self, PyBytes_AS_STRING(bytes), PyBytes_GET_SIZE(bytes));
if (self->modes.mBRACKETED_PASTE) write_escape_code_to_child(self, CSI, BRACKETED_PASTE_END);
Py_RETURN_NONE;
}
WRAP2(cursor_position, 1, 1)
#define COUNT_WRAP(name) WRAP1(name, 1)
@ -1580,8 +1628,10 @@ static PyMethodDef methods[] = {
MND(rescale_images, METH_VARARGS)
MND(text_for_selection, METH_NOARGS)
MND(scroll, METH_VARARGS)
MND(send_escape_code_to_child, METH_VARARGS)
MND(toggle_alt_screen, METH_NOARGS)
MND(reset_callbacks, METH_NOARGS)
MND(paste, METH_O)
{"select_graphic_rendition", (PyCFunction)_select_graphic_rendition, METH_VARARGS, ""},
{NULL} /* Sentinel */

View File

@ -15,6 +15,7 @@ typedef struct {
mBRACKETED_PASTE, mFOCUS_TRACKING, mEXTENDED_KEYBOARD;
MouseTrackingMode mouse_tracking_mode;
MouseTrackingProtocol mouse_tracking_protocol;
bool eight_bit_controls; // S8C1T
} ScreenModes;
typedef struct {
@ -66,6 +67,7 @@ void parse_worker_dump(Screen *screen, PyObject *dump_callback);
void screen_align(Screen*);
void screen_restore_cursor(Screen *);
void screen_save_cursor(Screen *);
void write_escape_code_to_child(Screen *self, unsigned char which, const char *data);
void screen_cursor_position(Screen*, unsigned int, unsigned int);
void screen_cursor_back(Screen *self, unsigned int count/*=1*/, int move_direction/*=-1*/);
void screen_erase_in_line(Screen *, unsigned int, bool);
@ -111,6 +113,7 @@ void set_dynamic_color(Screen *self, unsigned int code, PyObject*);
void set_color_table_color(Screen *self, unsigned int code, PyObject*);
uint32_t* translation_table(uint32_t which);
void screen_request_capabilities(Screen *, char, PyObject *);
void screen_set_8bit_controls(Screen *, bool);
void report_device_attributes(Screen *self, unsigned int UNUSED mode, char start_modifier);
void select_graphic_rendition(Screen *self, unsigned int *params, unsigned int count);
void report_device_status(Screen *self, unsigned int which, bool UNUSED);

View File

@ -452,6 +452,6 @@ def get_capabilities(query_string):
if qname in string_capabilities and '%' not in val:
val = key_as_bytes(qname).decode('ascii')
ans.append(q + '=' + hexlify(str(val).encode('utf-8')).decode('ascii'))
return b'\033P1+r' + ';'.join(ans).encode('utf-8') + b'\033\\'
return '1+r' + ';'.join(ans)
except Exception:
return b'\033P0+r' + query_string.encode('utf-8') + b'\033\\'
return '0+r' + query_string

View File

@ -12,13 +12,12 @@
ScreenGeometry, WindowGeometry, appname, get_boss, wakeup
)
from .fast_data_types import (
BLIT_PROGRAM, BRACKETED_PASTE_END, BRACKETED_PASTE_START, CELL_BG_PROGRAM,
CELL_FG_PROGRAM, CELL_PROGRAM, CELL_SPECIAL_PROGRAM, CURSOR_PROGRAM,
GRAPHICS_PREMULT_PROGRAM, GRAPHICS_PROGRAM, SCROLL_FULL, SCROLL_LINE,
SCROLL_PAGE, Screen, add_window, compile_program, glfw_post_empty_event,
init_cell_program, init_cursor_program, set_clipboard_string,
set_window_render_data, update_window_title, update_window_visibility,
viewport_for_window
BLIT_PROGRAM, CELL_BG_PROGRAM, CELL_FG_PROGRAM, CELL_PROGRAM,
CELL_SPECIAL_PROGRAM, CSI, CURSOR_PROGRAM, DCS, GRAPHICS_PREMULT_PROGRAM,
GRAPHICS_PROGRAM, OSC, SCROLL_FULL, SCROLL_LINE, SCROLL_PAGE, Screen,
add_window, compile_program, glfw_post_empty_event, init_cell_program,
init_cursor_program, set_clipboard_string, set_window_render_data,
update_window_title, update_window_visibility, viewport_for_window
)
from .keys import keyboard_mode_name
from .rgb import to_color
@ -171,10 +170,10 @@ def use_utf8(self, on):
def focus_changed(self, focused):
if focused:
if self.screen.focus_tracking_enabled:
self.write_to_child(b'\x1b[I')
self.screen.send_escape_code_to_child(CSI, 'I')
else:
if self.screen.focus_tracking_enabled:
self.write_to_child(b'\x1b[O')
self.screen.send_escape_code_to_child(CSI, 'O')
def title_changed(self, new_title):
if self.override_title is None:
@ -206,11 +205,11 @@ def item(raw):
if dirtied:
self.screen.mark_as_dirty()
def report_color(self, osc, r, g, b):
def report_color(self, code, r, g, b):
r |= r << 8
g |= g << 8
b |= b << 8
self.write_to_child('\033]{};rgb:{:04x}/{:04x}/{:04x}\033\\'.format(osc, r, g, b))
self.screen.send_escape_code_to_child(OSC, '{};rgb:{:04x}/{:04x}/{:04x}'.format(code, r, g, b))
def set_dynamic_color(self, code, value):
if isinstance(value, bytes):
@ -257,7 +256,7 @@ def set_color_table_color(self, code, value):
self.refresh()
def request_capabilities(self, q):
self.write_to_child(get_capabilities(q))
self.screen.send_escape_code_to_child(DCS, get_capabilities(q))
# }}}
@ -290,9 +289,8 @@ def paste(self, text):
if isinstance(text, str):
text = text.encode('utf-8')
if self.screen.in_bracketed_paste_mode:
bpe = BRACKETED_PASTE_END.encode('ascii')
text = BRACKETED_PASTE_START.encode('ascii') + text.replace(bpe, b'') + bpe
self.write_to_child(text)
text = text.replace(b'\033[201~', b'')
self.screen.paste(text)
def copy_to_clipboard(self):
text = self.text_for_selection()

View File

@ -29,7 +29,8 @@ def set_color_table_color(self, code, data):
def request_capabilities(self, q):
from kitty.terminfo import get_capabilities
self.write(get_capabilities(q))
c = get_capabilities(q)
self.write(c.encode('ascii'))
def use_utf8(self, on):
self.iutf8 = on

View File

@ -198,7 +198,7 @@ def test_dcs_codes(self):
q = hexlify(b'kind').decode('ascii')
pb('a\033P+q{}\x9cbcde'.format(q), 'a', ('screen_request_capabilities', 43, q), 'bcde')
self.ae(str(s.line(0)), 'abcde')
self.ae(c.wtcbuf, '\033P1+r{}={}\033\\'.format(q, '1b5b313b3242').encode('ascii'))
self.ae(c.wtcbuf, '1+r{}={}'.format(q, '1b5b313b3242').encode('ascii'))
c.clear()
pb('\033P$q q\033\\', ('screen_request_capabilities', ord('$'), ' q'))
self.ae(c.wtcbuf, b'\033P1$r1 q\033\\')