Centralise color management into ColorProfile
This commit is contained in:
parent
b50eaa9cbb
commit
1d888c9194
@ -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:
|
||||||
|
|||||||
@ -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,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -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*);
|
||||||
|
|||||||
@ -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}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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)
|
||||||
|
|||||||
@ -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++) {
|
||||||
|
|||||||
@ -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);
|
||||||
|
|||||||
@ -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):
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user