Fix changing cursor_text_color via remote control not working

Fixes #1229
This commit is contained in:
Kovid Goyal
2018-12-16 17:12:49 +05:30
parent 37ee693de2
commit f8ebba3954
9 changed files with 72 additions and 28 deletions

View File

@@ -18,6 +18,9 @@ Changelog
- Fix Private use Unicode area characters followed by spaces at the end of text - Fix Private use Unicode area characters followed by spaces at the end of text
not being rendered correctly (:iss:`1210`) not being rendered correctly (:iss:`1210`)
- Fix changing :opt:`cursor_text_color` via remote control not working
(:iss:`1229`)
0.13.1 [2018-12-06] 0.13.1 [2018-12-06]
------------------------------ ------------------------------

View File

@@ -106,6 +106,7 @@ class Boss:
set_draw_minimal_borders(opts) set_draw_minimal_borders(opts)
self.window_id_map = WeakValueDictionary() self.window_id_map = WeakValueDictionary()
self.startup_colors = {k: opts[k] for k in opts if isinstance(opts[k], Color)} self.startup_colors = {k: opts[k] for k in opts if isinstance(opts[k], Color)}
self.startup_cursor_text_color = opts.cursor_text_color
self.pending_sequences = None self.pending_sequences = None
self.cached_values = cached_values self.cached_values = cached_values
self.os_window_map = {} self.os_window_map = {}
@@ -951,11 +952,13 @@ class Boss:
if tm is not None: if tm is not None:
tm.move_tab(-1) tm.move_tab(-1)
def patch_colors(self, spec, configured=False): def patch_colors(self, spec, cursor_text_color, configured=False):
if configured: if configured:
for k, v in spec.items(): for k, v in spec.items():
if hasattr(self.opts, k): if hasattr(self.opts, k):
setattr(self.opts, k, color_from_int(v)) setattr(self.opts, k, color_from_int(v))
if cursor_text_color is not False:
self.opts.cursor_text_color = cursor_text_color
for tm in self.all_tab_managers: for tm in self.all_tab_managers:
tm.tab_bar.patch_colors(spec) tm.tab_bar.patch_colors(spec)
patch_global_colors(spec, configured) patch_global_colors(spec, configured)

View File

@@ -5,13 +5,12 @@
#define REVERSE_SHIFT {REVERSE_SHIFT} #define REVERSE_SHIFT {REVERSE_SHIFT}
#define STRIKE_SHIFT {STRIKE_SHIFT} #define STRIKE_SHIFT {STRIKE_SHIFT}
#define DIM_SHIFT {DIM_SHIFT} #define DIM_SHIFT {DIM_SHIFT}
#define CURSOR_TEXT_COLOR {CURSOR_TEXT_COLOR}
// Inputs {{{ // Inputs {{{
layout(std140) uniform CellRenderData { layout(std140) uniform CellRenderData {
float xstart, ystart, dx, dy, sprite_dx, sprite_dy, background_opacity; float xstart, ystart, dx, dy, sprite_dx, sprite_dy, background_opacity, cursor_text_uses_bg;
uint default_fg, default_bg, highlight_fg, highlight_bg, cursor_color, url_color, url_style, inverted; uint default_fg, default_bg, highlight_fg, highlight_bg, cursor_color, cursor_text_color, url_color, url_style, inverted;
uint xnum, ynum, cursor_fg_sprite_idx; uint xnum, ynum, cursor_fg_sprite_idx;
float cursor_x, cursor_y, cursor_w; float cursor_x, cursor_y, cursor_w;
@@ -182,8 +181,9 @@ void main() {
// Cursor // Cursor
cursor_color_vec = vec4(color_to_vec(cursor_color), 1.0); cursor_color_vec = vec4(color_to_vec(cursor_color), 1.0);
foreground = choose_color(cell_has_block_cursor, CURSOR_TEXT_COLOR, foreground); vec3 final_cursor_text_color = mix(color_to_vec(cursor_text_color), bg, cursor_text_uses_bg);
decoration_fg = choose_color(cell_has_block_cursor, CURSOR_TEXT_COLOR, decoration_fg); foreground = choose_color(cell_has_block_cursor, final_cursor_text_color, foreground);
decoration_fg = choose_color(cell_has_block_cursor, final_cursor_text_color, decoration_fg);
cursor_pos = to_sprite_pos(pos, cursor_fg_sprite_idx * uint(cell_has_cursor), ZERO, ZERO); cursor_pos = to_sprite_pos(pos, cursor_fg_sprite_idx * uint(cell_has_cursor), ZERO, ZERO);
#endif #endif
// }}} // }}}

View File

@@ -684,7 +684,7 @@ this option, any color arguments are ignored and --configured and --all are impl
) )
def cmd_set_colors(global_opts, opts, args): def cmd_set_colors(global_opts, opts, args):
from .rgb import color_as_int, Color from .rgb import color_as_int, Color
colors = {} colors, cursor_text_color = {}, False
if not opts.reset: if not opts.reset:
for spec in args: for spec in args:
if '=' in spec: if '=' in spec:
@@ -692,15 +692,17 @@ def cmd_set_colors(global_opts, opts, args):
else: else:
with open(os.path.expanduser(spec), encoding='utf-8', errors='replace') as f: with open(os.path.expanduser(spec), encoding='utf-8', errors='replace') as f:
colors.update(parse_config(f)) colors.update(parse_config(f))
cursor_text_color = colors.pop('cursor_text_color', False)
colors = {k: color_as_int(v) for k, v in colors.items() if isinstance(v, Color)} colors = {k: color_as_int(v) for k, v in colors.items() if isinstance(v, Color)}
return { return {
'title': ' '.join(args), 'match_window': opts.match, 'match_tab': opts.match_tab, 'title': ' '.join(args), 'match_window': opts.match, 'match_tab': opts.match_tab,
'all': opts.all or opts.reset, 'configured': opts.configured or opts.reset, 'colors': colors, 'reset': opts.reset 'all': opts.all or opts.reset, 'configured': opts.configured or opts.reset,
'colors': colors, 'reset': opts.reset, 'cursor_text_color': cursor_text_color
} }
def set_colors(boss, window, payload): def set_colors(boss, window, payload):
from .rgb import color_as_int from .rgb import color_as_int, Color
if payload['all']: if payload['all']:
windows = tuple(boss.all_windows) windows = tuple(boss.all_windows)
else: else:
@@ -717,10 +719,14 @@ def set_colors(boss, window, payload):
windows += tuple(tab) windows += tuple(tab)
if payload['reset']: if payload['reset']:
payload['colors'] = {k: color_as_int(v) for k, v in boss.startup_colors.items()} payload['colors'] = {k: color_as_int(v) for k, v in boss.startup_colors.items()}
payload['cursor_text_color'] = boss.startup_cursor_text_color
profiles = tuple(w.screen.color_profile for w in windows) profiles = tuple(w.screen.color_profile for w in windows)
from .fast_data_types import patch_color_profiles from .fast_data_types import patch_color_profiles
patch_color_profiles(payload['colors'], profiles, payload['configured']) cursor_text_color = payload.get('cursor_text_color', False)
boss.patch_colors(payload['colors'], payload['configured']) if isinstance(cursor_text_color, (tuple, list, Color)):
cursor_text_color = color_as_int(Color(*cursor_text_color))
patch_color_profiles(payload['colors'], cursor_text_color, profiles, payload['configured'])
boss.patch_colors(payload['colors'], cursor_text_color, payload['configured'])
default_bg_changed = 'background' in payload['colors'] default_bg_changed = 'background' in payload['colors']
for w in windows: for w in windows:
if default_bg_changed: if default_bg_changed:

View File

@@ -100,8 +100,8 @@ update_ansi_color_table(ColorProfile *self, PyObject *val) {
static PyObject* static PyObject*
patch_color_profiles(PyObject *module UNUSED, PyObject *args) { patch_color_profiles(PyObject *module UNUSED, PyObject *args) {
PyObject *spec, *profiles, *v; ColorProfile *self; int change_configured; PyObject *spec, *profiles, *v; ColorProfile *self; int change_configured; PyObject *cursor_text_color;
if (!PyArg_ParseTuple(args, "O!O!p", &PyDict_Type, &spec, &PyTuple_Type, &profiles, &change_configured)) return NULL; if (!PyArg_ParseTuple(args, "O!OO!p", &PyDict_Type, &spec, &cursor_text_color, &PyTuple_Type, &profiles, &change_configured)) return NULL;
char key[32] = {0}; char key[32] = {0};
for (size_t i = 0; i < arraysz(FG_BG_256); i++) { for (size_t i = 0; i < arraysz(FG_BG_256); i++) {
snprintf(key, sizeof(key) - 1, "color%zu", i); snprintf(key, sizeof(key) - 1, "color%zu", i);
@@ -131,6 +131,22 @@ patch_color_profiles(PyObject *module UNUSED, PyObject *args) {
S(foreground, default_fg); S(background, default_bg); S(cursor, cursor_color); S(foreground, default_fg); S(background, default_bg); S(cursor, cursor_color);
S(selection_foreground, highlight_fg); S(selection_background, highlight_bg); S(selection_foreground, highlight_fg); S(selection_background, highlight_bg);
#undef S #undef S
if (cursor_text_color != Py_False) {
for (Py_ssize_t i = 0; i < PyTuple_GET_SIZE(profiles); i++) {
self = (ColorProfile*)PyTuple_GET_ITEM(profiles, i);
self->overridden.cursor_text_color = 0x111111;
self->overridden.cursor_text_uses_bg = 3;
if (cursor_text_color != Py_None) {
self->overridden.cursor_text_color = (PyLong_AsUnsignedLong(cursor_text_color) << 8) | 2;
self->overridden.cursor_text_uses_bg = 1;
}
if (change_configured) {
self->configured.cursor_text_color = self->overridden.cursor_text_color;
self->configured.cursor_text_uses_bg = self->overridden.cursor_text_uses_bg;
}
self->dirty = true;
}
}
Py_RETURN_NONE; Py_RETURN_NONE;
} }
@@ -149,6 +165,14 @@ colorprofile_to_color(ColorProfile *self, color_type entry, color_type defval) {
} }
} }
float
cursor_text_as_bg(ColorProfile *self) {
if (self->overridden.cursor_text_uses_bg & 1) {
return self->overridden.cursor_text_uses_bg & 2 ? 1.f : 0.f;
}
return self->configured.cursor_text_uses_bg & 2 ? 1.f : 0.f;
}
static PyObject* static PyObject*
as_dict(ColorProfile *self, PyObject *args UNUSED) { as_dict(ColorProfile *self, PyObject *args UNUSED) {
@@ -174,7 +198,7 @@ as_dict(ColorProfile *self, PyObject *args UNUSED) {
if (ret != 0) { Py_CLEAR(ans); return NULL; } \ if (ret != 0) { Py_CLEAR(ans); return NULL; } \
}} }}
D(default_fg, foreground); D(default_bg, background); D(default_fg, foreground); D(default_bg, background);
D(cursor_color, cursor); D(highlight_fg, selection_foreground); D(cursor_color, cursor); D(cursor_text_color, cursor_text); D(highlight_fg, selection_foreground);
D(highlight_bg, selection_background); D(highlight_bg, selection_background);
#undef D #undef D
@@ -236,7 +260,11 @@ set_color(ColorProfile *self, PyObject *args) {
static PyObject* static PyObject*
set_configured_colors(ColorProfile *self, PyObject *args) { set_configured_colors(ColorProfile *self, PyObject *args) {
#define set_configured_colors_doc "Set the configured colors" #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; if (!PyArg_ParseTuple(
args, "II|IIIII",
&(self->configured.default_fg), &(self->configured.default_bg),
&(self->configured.cursor_color), &(self->configured.cursor_text_color), &(self->configured.cursor_text_uses_bg),
&(self->configured.highlight_fg), &(self->configured.highlight_bg))) return NULL;
self->dirty = true; self->dirty = true;
Py_RETURN_NONE; Py_RETURN_NONE;
} }
@@ -286,6 +314,7 @@ default_color_table(PyObject *self UNUSED, PyObject *args UNUSED) {
CGETSET(default_fg) CGETSET(default_fg)
CGETSET(default_bg) CGETSET(default_bg)
CGETSET(cursor_color) CGETSET(cursor_color)
CGETSET(cursor_text_color)
CGETSET(highlight_fg) CGETSET(highlight_fg)
CGETSET(highlight_bg) CGETSET(highlight_bg)
@@ -293,6 +322,7 @@ static PyGetSetDef getsetters[] = {
GETSET(default_fg) GETSET(default_fg)
GETSET(default_bg) GETSET(default_bg)
GETSET(cursor_color) GETSET(cursor_color)
GETSET(cursor_text_color)
GETSET(highlight_fg) GETSET(highlight_fg)
GETSET(highlight_bg) GETSET(highlight_bg)
{NULL} /* Sentinel */ {NULL} /* Sentinel */

View File

@@ -210,7 +210,7 @@ typedef struct {
} CursorRenderInfo; } CursorRenderInfo;
typedef struct { typedef struct {
color_type default_fg, default_bg, cursor_color, highlight_fg, highlight_bg; color_type default_fg, default_bg, cursor_color, cursor_text_color, cursor_text_uses_bg, highlight_fg, highlight_bg;
} DynamicColor; } DynamicColor;
typedef struct { typedef struct {
@@ -285,6 +285,7 @@ bool schedule_write_to_child(unsigned long id, unsigned int num, ...);
bool set_iutf8(int, bool); bool set_iutf8(int, bool);
color_type colorprofile_to_color(ColorProfile *self, color_type entry, color_type defval); color_type colorprofile_to_color(ColorProfile *self, color_type entry, color_type defval);
float cursor_text_as_bg(ColorProfile *self);
void copy_color_table_to_buffer(ColorProfile *self, color_type *address, int offset, size_t stride); void copy_color_table_to_buffer(ColorProfile *self, color_type *address, int offset, size_t stride);
void colorprofile_push_dynamic_colors(ColorProfile*); void colorprofile_push_dynamic_colors(ColorProfile*);
void colorprofile_pop_dynamic_colors(ColorProfile*); void colorprofile_pop_dynamic_colors(ColorProfile*);

View File

@@ -83,13 +83,10 @@ def talk_to_instance(args):
def load_all_shaders(semi_transparent=0): def load_all_shaders(semi_transparent=0):
load_shader_programs(semi_transparent, load_all_shaders.cursor_text_color) load_shader_programs(semi_transparent)
load_borders_program() load_borders_program()
load_all_shaders.cursor_text_color = None
def init_glfw(debug_keyboard=False): def init_glfw(debug_keyboard=False):
glfw_module = 'cocoa' if is_macos else ('wayland' if is_wayland else 'x11') glfw_module = 'cocoa' if is_macos else ('wayland' if is_wayland else 'x11')
if not glfw_init(glfw_path(glfw_module), debug_keyboard): if not glfw_init(glfw_path(glfw_module), debug_keyboard):
@@ -122,7 +119,6 @@ def _run_app(opts, args):
new_os_window_trigger = get_new_os_window_trigger(opts) new_os_window_trigger = get_new_os_window_trigger(opts)
if is_macos and opts.macos_custom_beam_cursor: if is_macos and opts.macos_custom_beam_cursor:
set_custom_ibeam_cursor() set_custom_ibeam_cursor()
load_all_shaders.cursor_text_color = opts.cursor_text_color
if not is_wayland and not is_macos: # no window icons on wayland if not is_wayland and not is_macos: # no window icons on wayland
with open(logo_data_file, 'rb') as f: with open(logo_data_file, 'rb') as f:
set_default_window_icon(f.read(), 256, 256) set_default_window_icon(f.read(), 256, 256)

View File

@@ -219,9 +219,9 @@ static struct CellUniformData cell_uniform_data = {0, .prev_inactive_text_alpha=
static inline void static inline void
cell_update_uniform_block(ssize_t vao_idx, Screen *screen, int uniform_buffer, GLfloat xstart, GLfloat ystart, GLfloat dx, GLfloat dy, CursorRenderInfo *cursor, bool inverted, OSWindow *os_window) { cell_update_uniform_block(ssize_t vao_idx, Screen *screen, int uniform_buffer, GLfloat xstart, GLfloat ystart, GLfloat dx, GLfloat dy, CursorRenderInfo *cursor, bool inverted, OSWindow *os_window) {
struct CellRenderData { struct CellRenderData {
GLfloat xstart, ystart, dx, dy, sprite_dx, sprite_dy, background_opacity; GLfloat xstart, ystart, dx, dy, sprite_dx, sprite_dy, background_opacity, cursor_text_uses_bg;
GLuint default_fg, default_bg, highlight_fg, highlight_bg, cursor_color, url_color, url_style, inverted; GLuint default_fg, default_bg, highlight_fg, highlight_bg, cursor_color, cursor_text_color, url_color, url_style, inverted;
GLuint xnum, ynum, cursor_fg_sprite_idx; GLuint xnum, ynum, cursor_fg_sprite_idx;
GLfloat cursor_x, cursor_y, cursor_w; GLfloat cursor_x, cursor_y, cursor_w;
@@ -260,8 +260,10 @@ cell_update_uniform_block(ssize_t vao_idx, Screen *screen, int uniform_buffer, G
#define COLOR(name) colorprofile_to_color(screen->color_profile, screen->color_profile->overridden.name, screen->color_profile->configured.name) #define COLOR(name) colorprofile_to_color(screen->color_profile, screen->color_profile->overridden.name, screen->color_profile->configured.name)
rd->default_fg = COLOR(default_fg); rd->default_bg = COLOR(default_bg); rd->highlight_fg = COLOR(highlight_fg); rd->highlight_bg = COLOR(highlight_bg); rd->default_fg = COLOR(default_fg); rd->default_bg = COLOR(default_bg); rd->highlight_fg = COLOR(highlight_fg); rd->highlight_bg = COLOR(highlight_bg);
rd->cursor_text_color = COLOR(cursor_text_color);
#undef COLOR #undef COLOR
rd->cursor_color = cursor->color; rd->url_color = OPT(url_color); rd->url_style = OPT(url_style); rd->cursor_color = cursor->color; rd->url_color = OPT(url_color); rd->url_style = OPT(url_style);
rd->cursor_text_uses_bg = cursor_text_as_bg(screen->color_profile);
unmap_vao_buffer(vao_idx, uniform_buffer); rd = NULL; unmap_vao_buffer(vao_idx, uniform_buffer); rd = NULL;
} }

View File

@@ -56,14 +56,13 @@ def calculate_gl_geometry(window_geometry, viewport_width, viewport_height, cell
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 load_shader_programs(semi_transparent=0, cursor_text_color=None): def load_shader_programs(semi_transparent=0):
compile_program(BLIT_PROGRAM, *load_shaders('blit')) compile_program(BLIT_PROGRAM, *load_shaders('blit'))
v, f = load_shaders('cell') v, f = load_shaders('cell')
def color_as_vec3(x): def color_as_vec3(x):
return 'vec3({}, {}, {})'.format(x.red / 255, x.green / 255, x.blue / 255) return 'vec3({}, {}, {})'.format(x.red / 255, x.green / 255, x.blue / 255)
cursor_text_color = color_as_vec3(cursor_text_color) if cursor_text_color else 'bg'
for which, p in { for which, p in {
'SIMPLE': CELL_PROGRAM, 'SIMPLE': CELL_PROGRAM,
'BACKGROUND': CELL_BG_PROGRAM, 'BACKGROUND': CELL_BG_PROGRAM,
@@ -76,7 +75,6 @@ def load_shader_programs(semi_transparent=0, cursor_text_color=None):
'STRIKE_SHIFT': STRIKETHROUGH, 'STRIKE_SHIFT': STRIKETHROUGH,
'DIM_SHIFT': DIM, 'DIM_SHIFT': DIM,
'DECORATION_SHIFT': DECORATION, 'DECORATION_SHIFT': DECORATION,
'CURSOR_TEXT_COLOR': cursor_text_color,
}.items(): }.items():
vv = vv.replace('{{{}}}'.format(gln), str(pyn), 1) vv = vv.replace('{{{}}}'.format(gln), str(pyn), 1)
if semi_transparent: if semi_transparent:
@@ -95,8 +93,13 @@ def load_shader_programs(semi_transparent=0, cursor_text_color=None):
def setup_colors(screen, opts): def setup_colors(screen, opts):
screen.color_profile.update_ansi_color_table(build_ansi_color_table(opts)) screen.color_profile.update_ansi_color_table(build_ansi_color_table(opts))
cursor_text_color = opts.cursor_text_color or (12, 12, 12)
cursor_text_color_as_bg = 3 if cursor_text_color is None else 1
screen.color_profile.set_configured_colors(*map(color_as_int, ( screen.color_profile.set_configured_colors(*map(color_as_int, (
opts.foreground, opts.background, opts.cursor, opts.selection_foreground, opts.selection_background))) opts.foreground, opts.background, opts.cursor,
cursor_text_color, (0, 0, cursor_text_color_as_bg),
opts.selection_foreground, opts.selection_background)
))
def text_sanitizer(as_ansi, add_wrap_markers): def text_sanitizer(as_ansi, add_wrap_markers):