Centralise color management into ColorProfile

This commit is contained in:
Kovid Goyal 2017-08-29 10:58:34 +05:30
parent b50eaa9cbb
commit 1d888c9194
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
9 changed files with 103 additions and 63 deletions

View File

@ -121,7 +121,7 @@ def calculate_gl_geometry(window_geometry):
return ScreenGeometry(xstart, ystart, window_geometry.xnum, window_geometry.ynum, dx, dy) return ScreenGeometry(xstart, ystart, window_geometry.xnum, window_geometry.ynum, dx, dy)
def render_cells(vao_id, sg, cell_program, sprites, invert_colors=False): def render_cells(vao_id, sg, cell_program, sprites, color_profile, invert_colors=False):
ul = cell_program.uniform_location ul = cell_program.uniform_location
glUniform2ui(ul('dimensions'), sg.xnum, sg.ynum) glUniform2ui(ul('dimensions'), sg.xnum, sg.ynum)
glUniform2i(ul('color_indices'), 1 if invert_colors else 0, 0 if invert_colors else 1) glUniform2i(ul('color_indices'), 1 if invert_colors else 0, 0 if invert_colors else 1)
@ -145,15 +145,15 @@ class CharGrid:
self.render_data = None self.render_data = None
self.scrolled_by = 0 self.scrolled_by = 0
self.screen = screen self.screen = screen
self.screen.color_profile.update_ansi_color_table(build_ansi_color_table(opts))
self.opts = opts self.opts = opts
self.default_bg = color_as_int(opts.background) self.screen.color_profile.update_ansi_color_table(build_ansi_color_table(opts))
self.default_fg = color_as_int(opts.foreground) self.screen.color_profile.set_configured_colors(*map(color_as_int, (
opts.foreground, opts.background, opts.cursor, opts.selection_foreground, opts.selection_background)))
self.screen.color_profile.dirty = True
self.dpix, self.dpiy = get_logical_dpi() self.dpix, self.dpiy = get_logical_dpi()
self.opts = opts self.opts = opts
self.default_cursor = self.current_cursor = Cursor(0, 0, opts.cursor_shape, opts.cursor_blink_interval > 0) self.default_cursor = self.current_cursor = Cursor(0, 0, opts.cursor_shape, opts.cursor_blink_interval > 0)
self.opts = opts self.opts = opts
self.highlight_fg, self.highlight_bg = map(color_as_int, (opts.selection_foreground, opts.selection_background))
self.sprite_map_type = self.main_sprite_map = self.scroll_sprite_map = self.render_buf = None self.sprite_map_type = self.main_sprite_map = self.scroll_sprite_map = self.render_buf = None
def escape(chars): def escape(chars):
@ -198,8 +198,9 @@ class CharGrid:
if val is None: if val is None:
continue continue
dirtied = True dirtied = True
setattr(self.screen, which.name, val) setattr(self.screen.color_profile, which.name, val)
if dirtied: if dirtied:
self.screen.color_profile.dirty = True
self.screen.mark_as_dirty() self.screen.mark_as_dirty()
def scroll(self, amt, upwards=True): def scroll(self, amt, upwards=True):
@ -216,15 +217,12 @@ class CharGrid:
sprites = get_boss().sprites sprites = get_boss().sprites
is_dirty = self.screen.is_dirty() is_dirty = self.screen.is_dirty()
with sprites.lock: with sprites.lock:
fg, bg = self.screen.default_fg, self.screen.default_bg
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( cursor_changed, history_line_added_count = self.screen.update_cell_data(
sprites.backend, addressof(self.main_sprite_map), fg, bg, force_full_refresh) sprites.backend, addressof(self.main_sprite_map), force_full_refresh)
if self.scrolled_by: if self.scrolled_by:
self.scrolled_by = min(self.scrolled_by + history_line_added_count, self.screen.historybuf.count) self.scrolled_by = min(self.scrolled_by + history_line_added_count, self.screen.historybuf.count)
self.screen.set_scroll_cell_data( self.screen.set_scroll_cell_data(
sprites.backend, addressof(self.main_sprite_map), fg, bg, sprites.backend, addressof(self.main_sprite_map),
self.scrolled_by, addressof(self.scroll_sprite_map)) self.scrolled_by, addressof(self.scroll_sprite_map))
data = self.scroll_sprite_map if self.scrolled_by else self.main_sprite_map data = self.scroll_sprite_map if self.scrolled_by else self.main_sprite_map
@ -367,10 +365,8 @@ class CharGrid:
buf = self.selection_buf buf = self.selection_buf
if self.render_buf_is_dirty or sel != self.last_rendered_selection: if self.render_buf_is_dirty or sel != self.last_rendered_selection:
memmove(buf, self.render_buf, sizeof(type(buf))) memmove(buf, self.render_buf, sizeof(type(buf)))
fg = self.screen.highlight_fg fg = self.screen.color_profile.highlight_fg
fg = fg >> 8 if fg & 2 else self.highlight_fg bg = self.screen.color_profile.highlight_bg
bg = self.screen.highlight_bg
bg = bg >> 8 if bg & 2 else self.highlight_bg
self.screen.apply_selection(addressof(buf), start[0], start[1], end[0], end[1], fg, bg) self.screen.apply_selection(addressof(buf), start[0], start[1], end[0], end[1], fg, bg)
if self.render_buf_is_dirty or self.last_rendered_selection != sel: if self.render_buf_is_dirty or self.last_rendered_selection != sel:
cell_program.send_vertex_data(self.vao_id, buf) cell_program.send_vertex_data(self.vao_id, buf)
@ -379,7 +375,7 @@ class CharGrid:
return sg return sg
def render_cells(self, sg, cell_program, sprites, invert_colors=False): def render_cells(self, sg, cell_program, sprites, invert_colors=False):
render_cells(self.vao_id, sg, cell_program, sprites, invert_colors=invert_colors) render_cells(self.vao_id, sg, cell_program, sprites, self.screen.color_profile, invert_colors=invert_colors)
def render_cursor(self, sg, cursor_program, is_focused): def render_cursor(self, sg, cursor_program, is_focused):
cursor = self.current_cursor cursor = self.current_cursor
@ -395,8 +391,7 @@ class CharGrid:
ul = cursor_program.uniform_location ul = cursor_program.uniform_location
left = sg.xstart + cursor.x * sg.dx left = sg.xstart + cursor.x * sg.dx
top = sg.ystart - cursor.y * sg.dy top = sg.ystart - cursor.y * sg.dy
cc = self.screen.cursor_color col = color_from_int(self.screen.color_profile.cursor_color)
col = color_from_int(cc >> 8) if cc & 2 else self.opts.cursor
shape = cursor.shape or self.default_cursor.shape shape = cursor.shape or self.default_cursor.shape
alpha = self.opts.cursor_opacity alpha = self.opts.cursor_opacity
if alpha < 1.0 and shape == CURSOR_BLOCK: if alpha < 1.0 and shape == CURSOR_BLOCK:

View File

@ -6,6 +6,7 @@
*/ */
#include "data-types.h" #include "data-types.h"
#include <structmember.h>
static uint32_t FG_BG_256[256] = { static uint32_t FG_BG_256[256] = {
0x000000, // 0 0x000000, // 0
@ -59,12 +60,14 @@ new(PyTypeObject *type, PyObject UNUSED *args, PyObject UNUSED *kwds) {
if (FG_BG_256[255] == 0) create_256_color_table(); if (FG_BG_256[255] == 0) create_256_color_table();
memcpy(self->color_table, FG_BG_256, sizeof(FG_BG_256)); memcpy(self->color_table, FG_BG_256, sizeof(FG_BG_256));
memcpy(self->orig_color_table, FG_BG_256, sizeof(FG_BG_256)); memcpy(self->orig_color_table, FG_BG_256, sizeof(FG_BG_256));
self->dirty = Py_True; Py_INCREF(Py_True);
} }
return (PyObject*) self; return (PyObject*) self;
} }
static void static void
dealloc(ColorProfile* self) { dealloc(ColorProfile* self) {
Py_DECREF(self->dirty);
Py_TYPE(self)->tp_free((PyObject*)self); Py_TYPE(self)->tp_free((PyObject*)self);
} }
@ -88,6 +91,21 @@ update_ansi_color_table(ColorProfile *self, PyObject *val) {
Py_RETURN_NONE; Py_RETURN_NONE;
} }
color_type
colorprofile_to_color(ColorProfile *self, color_type entry, color_type defval) {
color_type t = entry & 0xFF, r;
switch(t) {
case 1:
r = (entry >> 8) & 0xff;
return self->color_table[r];
case 2:
return entry >> 8;
default:
return defval;
}
}
static PyObject* static PyObject*
as_color(ColorProfile *self, PyObject *val) { as_color(ColorProfile *self, PyObject *val) {
#define as_color_doc "Convert the specified terminal color into an (r, g, b) tuple based on the current profile values" #define as_color_doc "Convert the specified terminal color into an (r, g, b) tuple based on the current profile values"
@ -137,16 +155,55 @@ set_color(ColorProfile *self, PyObject *args) {
Py_RETURN_NONE; Py_RETURN_NONE;
} }
static PyObject*
set_configured_colors(ColorProfile *self, PyObject *args) {
#define set_configured_colors_doc "Set the configured colors"
if (!PyArg_ParseTuple(args, "II|III", &(self->configured.default_fg), &(self->configured.default_bg), &(self->configured.cursor_color), &(self->configured.highlight_fg), &(self->configured.highlight_bg))) return NULL;
Py_RETURN_NONE;
}
static PyObject*
color_table_address(ColorProfile *self) {
#define color_table_address_doc "Pointer address to start of color table"
return PyLong_FromVoidPtr((void*)self->color_table);
}
// Boilerplate {{{ // Boilerplate {{{
#define CGETSET(name) \
static PyObject* name##_get(ColorProfile *self, void UNUSED *closure) { return PyLong_FromUnsignedLong(colorprofile_to_color(self, self->overridden.name, self->configured.name)); } \
static int name##_set(ColorProfile *self, PyObject *val, void UNUSED *closure) { if (val == NULL) { PyErr_SetString(PyExc_TypeError, "Cannot delete attribute"); return -1; } self->overridden.name = (color_type) PyLong_AsUnsignedLong(val); return 0; }
CGETSET(default_fg)
CGETSET(default_bg)
CGETSET(cursor_color)
CGETSET(highlight_fg)
CGETSET(highlight_bg)
static PyGetSetDef getsetters[] = {
GETSET(default_fg)
GETSET(default_bg)
GETSET(cursor_color)
GETSET(highlight_fg)
GETSET(highlight_bg)
{NULL} /* Sentinel */
};
static PyMemberDef members[] = {
{"dirty", T_OBJECT_EX, offsetof(ColorProfile, dirty), 0, "dirty"},
{NULL}
};
static PyMethodDef methods[] = { static PyMethodDef methods[] = {
METHOD(update_ansi_color_table, METH_O) METHOD(update_ansi_color_table, METH_O)
METHOD(reset_color_table, METH_NOARGS) METHOD(reset_color_table, METH_NOARGS)
METHOD(color_table_address, METH_NOARGS)
METHOD(as_color, METH_O) METHOD(as_color, METH_O)
METHOD(reset_color, METH_O) METHOD(reset_color, METH_O)
METHOD(set_color, METH_VARARGS) METHOD(set_color, METH_VARARGS)
METHOD(set_configured_colors, METH_VARARGS)
{NULL} /* Sentinel */ {NULL} /* Sentinel */
}; };
@ -158,7 +215,9 @@ PyTypeObject ColorProfile_Type = {
.tp_dealloc = (destructor)dealloc, .tp_dealloc = (destructor)dealloc,
.tp_flags = Py_TPFLAGS_DEFAULT, .tp_flags = Py_TPFLAGS_DEFAULT,
.tp_doc = "ColorProfile", .tp_doc = "ColorProfile",
.tp_members = members,
.tp_methods = methods, .tp_methods = methods,
.tp_getset = getsetters,
.tp_new = new, .tp_new = new,
}; };

View File

@ -177,12 +177,17 @@ PyTypeObject Cursor_Type;
PyTypeObject Face_Type; PyTypeObject Face_Type;
PyTypeObject Window_Type; PyTypeObject Window_Type;
typedef struct {
color_type default_fg, default_bg, cursor_color, highlight_fg, highlight_bg;
} DynamicColor;
typedef struct { typedef struct {
PyObject_HEAD PyObject_HEAD
PyObject *dirty;
uint32_t color_table[256]; uint32_t color_table[256];
uint32_t orig_color_table[256]; uint32_t orig_color_table[256];
DynamicColor configured, overridden;
} ColorProfile; } ColorProfile;
PyTypeObject ColorProfile_Type; PyTypeObject ColorProfile_Type;
@ -271,7 +276,6 @@ typedef struct {
unsigned int parser_state, parser_text_start, parser_buf_pos; unsigned int parser_state, parser_text_start, parser_buf_pos;
bool parser_has_pending_text; bool parser_has_pending_text;
uint8_t read_buf[READ_BUF_SZ]; uint8_t read_buf[READ_BUF_SZ];
uint32_t default_fg, default_bg, highlight_fg, highlight_bg, cursor_color;
} Screen; } Screen;
PyTypeObject Screen_Type; PyTypeObject Screen_Type;
@ -347,7 +351,7 @@ void cursor_reset(Cursor*);
Cursor* cursor_copy(Cursor*); Cursor* cursor_copy(Cursor*);
void cursor_copy_to(Cursor *src, Cursor *dest); void cursor_copy_to(Cursor *src, Cursor *dest);
void cursor_reset_display_attrs(Cursor*); void cursor_reset_display_attrs(Cursor*);
bool update_cell_range_data(ScreenModes *modes, SpriteMap *, Line *, unsigned int, unsigned int, ColorProfile *, const uint32_t, const uint32_t, unsigned int *); bool update_cell_range_data(ScreenModes *modes, SpriteMap *, Line *, unsigned int, unsigned int, ColorProfile *, unsigned int *);
PyObject* line_text_at(char_type, combining_type); PyObject* line_text_at(char_type, combining_type);
void line_clear_text(Line *self, unsigned int at, unsigned int num, int ch); void line_clear_text(Line *self, unsigned int at, unsigned int num, int ch);
@ -378,6 +382,8 @@ double timers_timeout(Timers*);
void timers_call(Timers*); void timers_call(Timers*);
bool timers_add_if_missing(Timers *self, double delay, PyObject *callback, PyObject *args); bool timers_add_if_missing(Timers *self, double delay, PyObject *callback, PyObject *args);
color_type colorprofile_to_color(ColorProfile *self, color_type entry, color_type defval);
unsigned int safe_wcwidth(uint32_t ch); unsigned int safe_wcwidth(uint32_t ch);
void change_wcwidth(bool use9); void change_wcwidth(bool use9);
void screen_align(Screen*); void screen_align(Screen*);

View File

@ -45,9 +45,6 @@ new(PyTypeObject *type, PyObject *args, PyObject UNUSED *kwds) {
self->columns = columns; self->lines = lines; self->columns = columns; self->lines = lines;
self->modes = empty_modes; self->modes = empty_modes;
self->margin_top = 0; self->margin_bottom = self->lines - 1; self->margin_top = 0; self->margin_bottom = self->lines - 1;
self->default_fg = 0; self->default_bg = 0;
self->highlight_fg = 0; self->highlight_bg = 0;
self->cursor_color = 0;
RESET_CHARSETS; RESET_CHARSETS;
self->callbacks = callbacks; Py_INCREF(callbacks); self->callbacks = callbacks; Py_INCREF(callbacks);
self->cursor = alloc_cursor(); self->cursor = alloc_cursor();
@ -73,9 +70,9 @@ screen_reset(Screen *self) {
if (self->linebuf == self->alt_linebuf) screen_toggle_screen_buffer(self); if (self->linebuf == self->alt_linebuf) screen_toggle_screen_buffer(self);
linebuf_clear(self->linebuf, BLANK_CHAR); linebuf_clear(self->linebuf, BLANK_CHAR);
self->modes = empty_modes; self->modes = empty_modes;
self->default_fg = 0; self->default_bg = 0; #define RC(name) self->color_profile->overridden.name = 0
self->highlight_fg = 0; self->highlight_bg = 0; RC(default_fg); RC(default_bg); RC(cursor_color); RC(highlight_fg); RC(highlight_bg);
self->cursor_color = 0; #undef RC
RESET_CHARSETS; RESET_CHARSETS;
self->margin_top = 0; self->margin_bottom = self->lines - 1; self->margin_top = 0; self->margin_bottom = self->lines - 1;
screen_normal_keypad_mode(self); screen_normal_keypad_mode(self);
@ -1173,14 +1170,13 @@ screen_update_cell_data(Screen *self, PyObject *args) {
SpriteMap *spm; SpriteMap *spm;
PyObject *dp; PyObject *dp;
unsigned int *data; unsigned int *data;
unsigned long default_bg, default_fg;
int force_screen_refresh; int force_screen_refresh;
if (!PyArg_ParseTuple(args, "O!O!kkp", &SpriteMap_Type, &spm, &PyLong_Type, &dp, &default_fg, &default_bg, &force_screen_refresh)) return NULL; if (!PyArg_ParseTuple(args, "O!O!p", &SpriteMap_Type, &spm, &PyLong_Type, &dp, &force_screen_refresh)) return NULL;
data = PyLong_AsVoidPtr(dp); data = PyLong_AsVoidPtr(dp);
PyObject *cursor_changed = self->change_tracker->cursor_changed ? Py_True : Py_False; 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; 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, self->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, (bool)force_screen_refresh)) return NULL;
return Py_BuildValue("OI", cursor_changed, history_line_added_count); return Py_BuildValue("OI", cursor_changed, history_line_added_count);
} }
@ -1189,8 +1185,7 @@ set_scroll_cell_data(Screen *self, PyObject *args) {
SpriteMap *spm; SpriteMap *spm;
PyObject *dp, *sp; PyObject *dp, *sp;
unsigned int *data, *src, scrolled_by; unsigned int *data, *src, scrolled_by;
unsigned long default_bg, default_fg; if (!PyArg_ParseTuple(args, "O!O!IO", &SpriteMap_Type, &spm, &PyLong_Type, &sp, &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); data = PyLong_AsVoidPtr(dp);
src = PyLong_AsVoidPtr(sp); src = PyLong_AsVoidPtr(sp);
@ -1199,7 +1194,7 @@ set_scroll_cell_data(Screen *self, PyObject *args) {
for (index_type y = 0; y < MIN(self->lines, scrolled_by); y++) { for (index_type y = 0; y < MIN(self->lines, scrolled_by); y++) {
historybuf_init_line(self->historybuf, scrolled_by - 1 - y, self->historybuf->line); historybuf_init_line(self->historybuf, scrolled_by - 1 - y, self->historybuf->line);
self->historybuf->line->ynum = y; self->historybuf->line->ynum = y;
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 (!update_cell_range_data(&(self->modes), spm, self->historybuf->line, 0, self->columns - 1, self->color_profile, data)) return NULL;
} }
if (scrolled_by < self->lines) { if (scrolled_by < self->lines) {
// Less than a full screen has been scrolled, copy some lines from the screen buffer to the scroll buffer // Less than a full screen has been scrolled, copy some lines from the screen buffer to the scroll buffer
@ -1352,11 +1347,6 @@ static PyMemberDef members[] = {
{"columns", T_UINT, offsetof(Screen, columns), READONLY, "columns"}, {"columns", T_UINT, offsetof(Screen, columns), READONLY, "columns"},
{"margin_top", T_UINT, offsetof(Screen, margin_top), READONLY, "margin_top"}, {"margin_top", T_UINT, offsetof(Screen, margin_top), READONLY, "margin_top"},
{"margin_bottom", T_UINT, offsetof(Screen, margin_bottom), READONLY, "margin_bottom"}, {"margin_bottom", T_UINT, offsetof(Screen, margin_bottom), READONLY, "margin_bottom"},
{"default_fg", T_COL, offsetof(Screen, default_fg), 0, "default_fg"},
{"default_bg", T_COL, offsetof(Screen, default_bg), 0, "default_bg"},
{"highlight_fg", T_COL, offsetof(Screen, highlight_fg), 0, "highlight_fg"},
{"highlight_bg", T_COL, offsetof(Screen, highlight_bg), 0, "highlight_bg"},
{"cursor_color", T_COL, offsetof(Screen, cursor_color), 0, "cursor_color"},
{NULL} {NULL}
}; };

View File

@ -138,27 +138,15 @@ position_for(SpriteMap *self, PyObject *args) {
return Py_BuildValue("III", pos->x, pos->y, pos->z); return Py_BuildValue("III", pos->x, pos->y, pos->z);
} }
static inline uint32_t
to_color(ColorProfile *self, uint32_t entry, uint32_t defval) {
unsigned int t = entry & 0xFF, r;
switch(t) {
case 1:
r = (entry >> 8) & 0xff;
return self->color_table[r];
case 2:
return entry >> 8;
default:
return defval;
}
}
bool bool
update_cell_range_data(ScreenModes *modes, SpriteMap *self, Line *line, unsigned int xstart, unsigned int xmax, ColorProfile *color_profile, const uint32_t default_bg, const uint32_t default_fg, unsigned int *data) { update_cell_range_data(ScreenModes *modes, SpriteMap *self, Line *line, unsigned int xstart, unsigned int xmax, ColorProfile *color_profile, unsigned int *data) {
SpritePosition *sp; SpritePosition *sp;
char_type previous_ch=0, ch; char_type previous_ch=0, ch;
uint8_t previous_width = 0; uint8_t previous_width = 0;
int err = 0; int err = 0;
const bool screen_reversed = modes->mDECSCNM; const bool screen_reversed = modes->mDECSCNM;
color_type fg = colorprofile_to_color(color_profile, color_profile->overridden.default_fg, color_profile->configured.default_fg);
color_type bg = colorprofile_to_color(color_profile, color_profile->overridden.default_bg, color_profile->configured.default_bg);
size_t base = line->ynum * line->xnum * DATA_CELL_SIZE; size_t base = line->ynum * line->xnum * DATA_CELL_SIZE;
for (size_t i = xstart, offset = base + xstart * DATA_CELL_SIZE; i <= xmax; i++, offset += DATA_CELL_SIZE) { for (size_t i = xstart, offset = base + xstart * DATA_CELL_SIZE; i <= xmax; i++, offset += DATA_CELL_SIZE) {
@ -173,9 +161,9 @@ update_cell_range_data(ScreenModes *modes, SpriteMap *self, Line *line, unsigned
data[offset] = sp->x; data[offset] = sp->x;
data[offset+1] = sp->y; data[offset+1] = sp->y;
data[offset+2] = sp->z; data[offset+2] = sp->z;
data[offset+(reverse ? 4 : 3)] = to_color(color_profile, line->cells[i].fg & COL_MASK, default_fg); data[offset+(reverse ? 4 : 3)] = colorprofile_to_color(color_profile, line->cells[i].fg & COL_MASK, fg);
data[offset+(reverse ? 3 : 4)] = to_color(color_profile, line->cells[i].bg & COL_MASK, default_bg); data[offset+(reverse ? 3 : 4)] = colorprofile_to_color(color_profile, line->cells[i].bg & COL_MASK, bg);
unsigned int decoration_fg = to_color(color_profile, line->cells[i].decoration_fg & COL_MASK, data[offset+3]); unsigned int decoration_fg = colorprofile_to_color(color_profile, line->cells[i].decoration_fg & COL_MASK, data[offset+3]);
data[offset+5] = (decoration_fg & COL_MASK) | (decoration << 24) | (strikethrough << 26); data[offset+5] = (decoration_fg & COL_MASK) | (decoration << 24) | (strikethrough << 26);
previous_ch = ch; previous_width = (attrs) & WIDTH_MASK; previous_ch = ch; previous_width = (attrs) & WIDTH_MASK;
} }

View File

@ -239,6 +239,8 @@ class TabManager:
s = Screen(None, 1, ncells) s = Screen(None, 1, ncells)
s.reset_mode(DECAWM) s.reset_mode(DECAWM)
s.color_profile.update_ansi_color_table(self.color_table) s.color_profile.update_ansi_color_table(self.color_table)
s.color_profile.set_configured_colors(self.default_fg, self.default_bg)
s.color_profile.dirty = True
self.sprite_map_type = (GLuint * (s.lines * s.columns * DATA_CELL_SIZE)) self.sprite_map_type = (GLuint * (s.lines * s.columns * DATA_CELL_SIZE))
with self.tabbar_lock: with self.tabbar_lock:
self.sprite_map = self.sprite_map_type() self.sprite_map = self.sprite_map_type()
@ -339,7 +341,7 @@ class TabManager:
break break
s.erase_in_line(0, False) # Ensure no long titles bleed after the last tab s.erase_in_line(0, False) # Ensure no long titles bleed after the last tab
s.update_cell_data( s.update_cell_data(
sprites.backend, addressof(self.sprite_map), self.default_fg, self.default_bg, True) sprites.backend, addressof(self.sprite_map), True)
sprites.render_dirty_cells() sprites.render_dirty_cells()
if self.vao_id is None: if self.vao_id is None:
self.vao_id = cell_program.create_sprite_map() self.vao_id = cell_program.create_sprite_map()
@ -364,4 +366,4 @@ class TabManager:
with self.tabbar_lock: with self.tabbar_lock:
if self.tabbar_dirty: if self.tabbar_dirty:
self.update_tab_bar_data(sprites, cell_program) self.update_tab_bar_data(sprites, cell_program)
render_cells(self.vao_id, self.screen_geometry, cell_program, sprites) render_cells(self.vao_id, self.screen_geometry, cell_program, sprites, self.tab_bar_screen.color_profile)

View File

@ -97,15 +97,13 @@ update_cell_range(ChangeTracker *self, PyObject *args) {
Py_RETURN_NONE; Py_RETURN_NONE;
} }
bool tracker_update_cell_data(ScreenModes *modes, ChangeTracker *self, LineBuf *lb, SpriteMap *spm, ColorProfile *color_profile, unsigned int *data, unsigned long default_fg, unsigned long default_bg, bool force_screen_refresh) { bool tracker_update_cell_data(ScreenModes *modes, ChangeTracker *self, LineBuf *lb, SpriteMap *spm, ColorProfile *color_profile, unsigned int *data, bool force_screen_refresh) {
unsigned int y; unsigned int y;
Py_ssize_t start; Py_ssize_t start;
default_fg &= COL_MASK;
default_bg &= COL_MASK;
#define UPDATE_RANGE(xstart, xmax) \ #define UPDATE_RANGE(xstart, xmax) \
linebuf_init_line(lb, y); \ linebuf_init_line(lb, y); \
if (!update_cell_range_data(modes, spm, lb->line, (xstart), (xmax), color_profile, default_bg, default_fg, data)) return false; if (!update_cell_range_data(modes, spm, lb->line, (xstart), (xmax), color_profile, data)) return false;
if (self->screen_changed || force_screen_refresh) { if (self->screen_changed || force_screen_refresh) {
for (y = 0; y < self->ynum; y++) { for (y = 0; y < self->ynum; y++) {

View File

@ -52,4 +52,4 @@ static inline void tracker_reset(ChangeTracker *self) {
PyObject* tracker_consolidate_changes(ChangeTracker *self); PyObject* tracker_consolidate_changes(ChangeTracker *self);
bool tracker_resize(ChangeTracker *self, unsigned int ynum, unsigned int xnum); bool tracker_resize(ChangeTracker *self, unsigned int ynum, unsigned int xnum);
bool tracker_update_cell_data(ScreenModes*, ChangeTracker *, LineBuf *, SpriteMap *, ColorProfile *, unsigned int *, unsigned long, unsigned long, bool); bool tracker_update_cell_data(ScreenModes*, ChangeTracker *, LineBuf *, SpriteMap *, ColorProfile *, unsigned int *, bool);

View File

@ -174,6 +174,7 @@ class Window:
if code == 4: if code == 4:
for c, val in parse_color_set(value): for c, val in parse_color_set(value):
cp.set_color(c, val) cp.set_color(c, val)
cp.dirty = True
self.refresh() self.refresh()
elif code == 104: elif code == 104:
if not value.strip(): if not value.strip():
@ -186,6 +187,7 @@ class Window:
continue continue
if 0 <= c <= 255: if 0 <= c <= 255:
cp.reset_color(c) cp.reset_color(c)
cp.dirty = True
self.refresh() self.refresh()
def request_capabilities(self, q): def request_capabilities(self, q):