diff --git a/kitty/char_grid.py b/kitty/char_grid.py index 53a98c122..93cf13654 100644 --- a/kitty/char_grid.py +++ b/kitty/char_grid.py @@ -15,9 +15,9 @@ from .constants import ( ) from .fast_data_types import ( CURSOR_BEAM, CURSOR_BLOCK, CURSOR_UNDERLINE, DATA_CELL_SIZE, GL_BLEND, - GL_LINE_LOOP, GL_TRIANGLE_FAN, GL_UNSIGNED_INT, ColorProfile, glDisable, - glDrawArrays, glDrawArraysInstanced, glEnable, glUniform1i, glUniform2f, - glUniform2i, glUniform2ui, glUniform4f + GL_LINE_LOOP, GL_TRIANGLE_FAN, GL_UNSIGNED_INT, glDisable, glDrawArrays, + glDrawArraysInstanced, glEnable, glUniform1i, glUniform2f, glUniform2i, + glUniform2ui, glUniform4f ) from .rgb import to_color from .shaders import ShaderProgram, load_shaders @@ -144,9 +144,8 @@ class CharGrid: self.render_buf_is_dirty = True self.render_data = None self.scrolled_by = 0 - self.color_profile = ColorProfile() - self.color_profile.update_ansi_color_table(build_ansi_color_table(opts)) self.screen = screen + self.screen.color_profile.update_ansi_color_table(build_ansi_color_table(opts)) self.opts = opts self.default_bg = color_as_int(opts.background) self.default_fg = color_as_int(opts.foreground) @@ -221,11 +220,11 @@ class CharGrid: fg = fg >> 8 if fg & 2 else self.default_fg bg = bg >> 8 if bg & 2 else self.default_bg cursor_changed, history_line_added_count = self.screen.update_cell_data( - sprites.backend, self.color_profile, addressof(self.main_sprite_map), fg, bg, force_full_refresh) + sprites.backend, addressof(self.main_sprite_map), fg, bg, force_full_refresh) if self.scrolled_by: self.scrolled_by = min(self.scrolled_by + history_line_added_count, self.screen.historybuf.count) self.screen.set_scroll_cell_data( - sprites.backend, self.color_profile, addressof(self.main_sprite_map), fg, bg, + sprites.backend, addressof(self.main_sprite_map), fg, bg, self.scrolled_by, addressof(self.scroll_sprite_map)) data = self.scroll_sprite_map if self.scrolled_by else self.main_sprite_map diff --git a/kitty/colors.c b/kitty/colors.c index 00058def0..f38e491b4 100644 --- a/kitty/colors.c +++ b/kitty/colors.c @@ -68,6 +68,11 @@ dealloc(ColorProfile* self) { Py_TYPE(self)->tp_free((PyObject*)self); } +ColorProfile* +alloc_color_profile() { + return (ColorProfile*)new(&ColorProfile_Type, NULL, NULL); +} + static PyObject* update_ansi_color_table(ColorProfile *self, PyObject *val) { diff --git a/kitty/data-types.h b/kitty/data-types.h index 8fbbaef9b..c75ea0f55 100644 --- a/kitty/data-types.h +++ b/kitty/data-types.h @@ -265,6 +265,7 @@ typedef struct { bool *tabstops, *main_tabstops, *alt_tabstops; ChangeTracker *change_tracker; ScreenModes modes; + ColorProfile *color_profile; uint32_t parser_buf[PARSER_BUF_SZ]; unsigned int parser_state, parser_text_start, parser_buf_pos; @@ -323,6 +324,7 @@ Cursor* alloc_cursor(); LineBuf* alloc_linebuf(unsigned int, unsigned int); HistoryBuf* alloc_historybuf(unsigned int, unsigned int); ChangeTracker* alloc_change_tracker(unsigned int, unsigned int); +ColorProfile* alloc_color_profile(); int init_LineBuf(PyObject *); int init_HistoryBuf(PyObject *); int init_Cursor(PyObject *); diff --git a/kitty/screen.c b/kitty/screen.c index 25a39ddcf..8fa88d5f2 100644 --- a/kitty/screen.c +++ b/kitty/screen.c @@ -51,12 +51,13 @@ new(PyTypeObject *type, PyObject *args, PyObject UNUSED *kwds) { RESET_CHARSETS; self->callbacks = callbacks; Py_INCREF(callbacks); self->cursor = alloc_cursor(); + self->color_profile = alloc_color_profile(); self->main_linebuf = alloc_linebuf(lines, columns); self->alt_linebuf = alloc_linebuf(lines, columns); self->linebuf = self->main_linebuf; self->change_tracker = alloc_change_tracker(lines, columns); self->historybuf = alloc_historybuf(MAX(scrollback, lines), columns); self->main_tabstops = PyMem_Calloc(2 * self->columns, sizeof(bool)); - if (self->cursor == NULL || self->main_linebuf == NULL || self->alt_linebuf == NULL || self->change_tracker == NULL || self->main_tabstops == NULL || self->historybuf == NULL) { + if (self->cursor == NULL || self->main_linebuf == NULL || self->alt_linebuf == NULL || self->change_tracker == NULL || self->main_tabstops == NULL || self->historybuf == NULL || self->color_profile == NULL) { Py_CLEAR(self); return NULL; } self->alt_tabstops = self->main_tabstops + self->columns * sizeof(bool); @@ -170,6 +171,7 @@ dealloc(Screen* self) { Py_CLEAR(self->alt_linebuf); Py_CLEAR(self->change_tracker); Py_CLEAR(self->historybuf); + Py_CLEAR(self->color_profile); PyMem_Free(self->main_tabstops); Py_TYPE(self)->tp_free((PyObject*)self); } // }}} @@ -1169,28 +1171,26 @@ change_scrollback_size(Screen *self, PyObject *args) { static PyObject* screen_update_cell_data(Screen *self, PyObject *args) { SpriteMap *spm; - ColorProfile *color_profile; PyObject *dp; unsigned int *data; unsigned long default_bg, default_fg; int force_screen_refresh; - if (!PyArg_ParseTuple(args, "O!O!O!kkp", &SpriteMap_Type, &spm, &ColorProfile_Type, &color_profile, &PyLong_Type, &dp, &default_fg, &default_bg, &force_screen_refresh)) return NULL; + if (!PyArg_ParseTuple(args, "O!O!kkp", &SpriteMap_Type, &spm, &PyLong_Type, &dp, &default_fg, &default_bg, &force_screen_refresh)) return NULL; data = PyLong_AsVoidPtr(dp); PyObject *cursor_changed = self->change_tracker->cursor_changed ? Py_True : Py_False; unsigned int history_line_added_count = self->change_tracker->history_line_added_count; - if (!tracker_update_cell_data(&(self->modes), self->change_tracker, self->linebuf, spm, color_profile, data, default_fg, default_bg, (bool)force_screen_refresh)) return NULL; + if (!tracker_update_cell_data(&(self->modes), self->change_tracker, self->linebuf, spm, self->color_profile, data, default_fg, default_bg, (bool)force_screen_refresh)) return NULL; return Py_BuildValue("OI", cursor_changed, history_line_added_count); } static PyObject* set_scroll_cell_data(Screen *self, PyObject *args) { SpriteMap *spm; - ColorProfile *color_profile; PyObject *dp, *sp; unsigned int *data, *src, scrolled_by; unsigned long default_bg, default_fg; - if (!PyArg_ParseTuple(args, "O!O!O!kkIO", &SpriteMap_Type, &spm, &ColorProfile_Type, &color_profile, &PyLong_Type, &sp, &default_fg, &default_bg, &scrolled_by, &dp)) return NULL; + if (!PyArg_ParseTuple(args, "O!O!kkIO", &SpriteMap_Type, &spm, &PyLong_Type, &sp, &default_fg, &default_bg, &scrolled_by, &dp)) return NULL; data = PyLong_AsVoidPtr(dp); src = PyLong_AsVoidPtr(sp); @@ -1199,7 +1199,7 @@ set_scroll_cell_data(Screen *self, PyObject *args) { for (index_type y = 0; y < MIN(self->lines, scrolled_by); y++) { historybuf_init_line(self->historybuf, scrolled_by - 1 - y, self->historybuf->line); self->historybuf->line->ynum = y; - if (!update_cell_range_data(&(self->modes), spm, self->historybuf->line, 0, self->columns - 1, color_profile, default_bg, default_fg, data)) return NULL; + if (!update_cell_range_data(&(self->modes), spm, self->historybuf->line, 0, self->columns - 1, self->color_profile, default_bg, default_fg, data)) return NULL; } if (scrolled_by < self->lines) { // Less than a full screen has been scrolled, copy some lines from the screen buffer to the scroll buffer @@ -1345,6 +1345,7 @@ static PyGetSetDef getsetters[] = { static PyMemberDef members[] = { {"callbacks", T_OBJECT_EX, offsetof(Screen, callbacks), 0, "callbacks"}, {"cursor", T_OBJECT_EX, offsetof(Screen, cursor), READONLY, "cursor"}, + {"color_profile", T_OBJECT_EX, offsetof(Screen, color_profile), READONLY, "color_profile"}, {"linebuf", T_OBJECT_EX, offsetof(Screen, linebuf), READONLY, "linebuf"}, {"historybuf", T_OBJECT_EX, offsetof(Screen, historybuf), READONLY, "historybuf"}, {"lines", T_UINT, offsetof(Screen, lines), READONLY, "lines"}, diff --git a/kitty/tabs.py b/kitty/tabs.py index 802ed259a..c6dd415af 100644 --- a/kitty/tabs.py +++ b/kitty/tabs.py @@ -16,7 +16,7 @@ from .constants import ( shell_path, viewport_size ) from .fast_data_types import ( - DATA_CELL_SIZE, DECAWM, ColorProfile, Screen, glfw_post_empty_event + DATA_CELL_SIZE, DECAWM, Screen, glfw_post_empty_event ) from .layout import Rect, all_layouts from .utils import color_as_int @@ -210,11 +210,10 @@ class TabManager: self.vao_id = None self.tabbar_lock = Lock() self.tabs = [Tab(opts, args, self.title_changed, t) for t in startup_session.tabs] + self.color_table = build_ansi_color_table(self.opts) self.cell_ranges = [] self.active_tab_idx = startup_session.active_tab_idx self.tabbar_dirty = True - self.color_profile = ColorProfile() - self.color_profile.update_ansi_color_table(build_ansi_color_table(opts)) self.default_fg = color_as_int(opts.inactive_tab_foreground) self.default_bg = color_as_int(opts.inactive_tab_background) self.tab_bar_blank_rects = () @@ -239,6 +238,7 @@ class TabManager: ncells = viewport_size.width // cell_size.width s = Screen(None, 1, ncells) s.reset_mode(DECAWM) + s.color_profile.update_ansi_color_table(self.color_table) self.sprite_map_type = (GLuint * (s.lines * s.columns * DATA_CELL_SIZE)) with self.tabbar_lock: self.sprite_map = self.sprite_map_type() @@ -339,7 +339,7 @@ class TabManager: break s.erase_in_line(0, False) # Ensure no long titles bleed after the last tab s.update_cell_data( - sprites.backend, self.color_profile, addressof(self.sprite_map), self.default_fg, self.default_bg, True) + sprites.backend, addressof(self.sprite_map), self.default_fg, self.default_bg, True) sprites.render_dirty_cells() if self.vao_id is None: self.vao_id = cell_program.create_sprite_map() diff --git a/kitty/window.py b/kitty/window.py index 5865b8018..ab2f5e00d 100644 --- a/kitty/window.py +++ b/kitty/window.py @@ -170,13 +170,14 @@ class Window: glfw_post_empty_event() def set_color_table_color(self, code, value): + cp = self.char_grid.screen.color_profile if code == 4: for c, val in parse_color_set(value): - self.char_grid.color_profile.set_color(c, val) + cp.set_color(c, val) self.refresh() elif code == 104: if not value.strip(): - self.char_grid.color_profile.reset_color_table() + cp.reset_color_table() else: for c in value.split(';'): try: @@ -184,7 +185,7 @@ class Window: except Exception: continue if 0 <= c <= 255: - self.char_grid.color_profile.reset_color(c) + cp.reset_color(c) self.refresh() def request_capabilities(self, q):