Switch to using an opaque block cursor
The text is rendered in the background color on top of the opaque block cursor. We use the background color since applications can change both cursor and background colors, so it is up to the application to ensure the colors have good contrast. Fix #126
This commit is contained in:
parent
2d0c6a43c5
commit
df4df76d24
@ -1,10 +1,9 @@
|
|||||||
#version GLSL_VERSION
|
#version GLSL_VERSION
|
||||||
uniform uvec2 dimensions; // xnum, ynum
|
uniform uvec4 dimensions; // xnum, ynum, cursor.x, cursor.y
|
||||||
uniform vec4 steps; // xstart, ystart, dx, dy
|
uniform vec4 steps; // xstart, ystart, dx, dy
|
||||||
uniform vec2 sprite_layout; // dx, dy
|
uniform vec2 sprite_layout; // dx, dy
|
||||||
uniform ivec2 color_indices; // which color to use as fg and which as bg
|
uniform ivec2 color_indices; // which color to use as fg and which as bg
|
||||||
uniform uvec4 default_colors; // The default colors
|
uniform uint default_colors[6]; // The default colors
|
||||||
uniform uint url_color; // The color to use for the URL highlight
|
|
||||||
uniform uvec4 url_range; // The range for the currently highlighted URL (start_x, end_x, start_y, end_y)
|
uniform uvec4 url_range; // The range for the currently highlighted URL (start_x, end_x, start_y, end_y)
|
||||||
uniform ColorTable {
|
uniform ColorTable {
|
||||||
uint color_table[256]; // The color table
|
uint color_table[256]; // The color table
|
||||||
@ -83,10 +82,18 @@ float in_range(uvec4 range, uint x, uint y) {
|
|||||||
return 0.0;
|
return 0.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float is_cursor(uint x, uint y) {
|
||||||
|
if (x == dimensions[2] && y == dimensions[3]) return 1.0;
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
uint instance_id = uint(gl_InstanceID);
|
uint instance_id = uint(gl_InstanceID);
|
||||||
|
// The current cell being rendered
|
||||||
uint r = instance_id / dimensions.x;
|
uint r = instance_id / dimensions.x;
|
||||||
uint c = instance_id - r * dimensions.x;
|
uint c = instance_id - r * dimensions.x;
|
||||||
|
|
||||||
|
// The position of this vertex, at a corner of the cell
|
||||||
float left = steps[0] + c * steps[2];
|
float left = steps[0] + c * steps[2];
|
||||||
float top = steps[1] - r * steps[3];
|
float top = steps[1] - r * steps[3];
|
||||||
vec2 xpos = vec2(left, left + steps[2]);
|
vec2 xpos = vec2(left, left + steps[2]);
|
||||||
@ -94,15 +101,23 @@ void main() {
|
|||||||
uvec2 pos = pos_map[gl_VertexID];
|
uvec2 pos = pos_map[gl_VertexID];
|
||||||
gl_Position = vec4(xpos[pos.x], ypos[pos.y], 0, 1);
|
gl_Position = vec4(xpos[pos.x], ypos[pos.y], 0, 1);
|
||||||
|
|
||||||
|
// The character sprite being rendered
|
||||||
sprite_pos = to_sprite_pos(pos, sprite_coords.x, sprite_coords.y, sprite_coords.z & SHORT_MASK);
|
sprite_pos = to_sprite_pos(pos, sprite_coords.x, sprite_coords.y, sprite_coords.z & SHORT_MASK);
|
||||||
|
|
||||||
|
// Foreground and background colors
|
||||||
uint text_attrs = sprite_coords[3];
|
uint text_attrs = sprite_coords[3];
|
||||||
int fg_index = color_indices[(text_attrs >> 6) & REVERSE_MASK];
|
int fg_index = color_indices[(text_attrs >> 6) & REVERSE_MASK];
|
||||||
int bg_index = color_indices[1 - fg_index];
|
int bg_index = color_indices[1 - fg_index];
|
||||||
uint resolved_fg = as_color(colors[fg_index], default_colors[fg_index]);
|
uint resolved_fg = as_color(colors[fg_index], default_colors[fg_index]);
|
||||||
foreground = apply_selection(color_to_vec(resolved_fg), default_colors[2]);
|
foreground = apply_selection(color_to_vec(resolved_fg), default_colors[2]);
|
||||||
background = apply_selection(to_color(colors[bg_index], default_colors[bg_index]), default_colors[3]);
|
background = apply_selection(to_color(colors[bg_index], default_colors[bg_index]), default_colors[3]);
|
||||||
|
float cursor = is_cursor(c, r);
|
||||||
|
foreground = cursor * background + (1.0 - cursor) * foreground;
|
||||||
|
background = cursor * color_to_vec(default_colors[4]) + (1.0 - cursor) * background;
|
||||||
|
|
||||||
|
// Underline and strike through (rendered via sprites)
|
||||||
float in_url = in_range(url_range, c, r);
|
float in_url = in_range(url_range, c, r);
|
||||||
decoration_fg = mix_vecs(in_url, color_to_vec(url_color), to_color(colors[2], resolved_fg));
|
decoration_fg = mix_vecs(in_url, color_to_vec(default_colors[5]), to_color(colors[2], resolved_fg));
|
||||||
underline_pos = mix_vecs(in_url, to_sprite_pos(pos, TWO, ZERO, ZERO), to_sprite_pos(pos, (text_attrs >> 2) & DECORATION_MASK, ZERO, ZERO));
|
underline_pos = mix_vecs(in_url, to_sprite_pos(pos, TWO, ZERO, ZERO), to_sprite_pos(pos, (text_attrs >> 2) & DECORATION_MASK, ZERO, ZERO));
|
||||||
strike_pos = to_sprite_pos(pos, ((text_attrs >> 7) & STRIKE_MASK) * THREE, ZERO, ZERO);
|
strike_pos = to_sprite_pos(pos, ((text_attrs >> 7) & STRIKE_MASK) * THREE, ZERO, ZERO);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -451,9 +451,12 @@ cursor_width(double w, bool vert) {
|
|||||||
extern void cocoa_update_title(PyObject*);
|
extern void cocoa_update_title(PyObject*);
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
render_cursor(Window *w, double now) {
|
collect_cursor_info(CursorRenderInfo *ans, Window *w, double now) {
|
||||||
ScreenRenderData *rd = &w->render_data;
|
ScreenRenderData *rd = &w->render_data;
|
||||||
if (rd->screen->scrolled_by || !screen_is_cursor_visible(rd->screen)) return;
|
if (rd->screen->scrolled_by || !screen_is_cursor_visible(rd->screen)) {
|
||||||
|
ans->is_visible = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
double time_since_start_blink = now - global_state.cursor_blink_zero_time;
|
double time_since_start_blink = now - global_state.cursor_blink_zero_time;
|
||||||
bool cursor_blinking = OPT(cursor_blink_interval) > 0 && global_state.application_focused && time_since_start_blink <= OPT(cursor_stop_blinking_after) ? true : false;
|
bool cursor_blinking = OPT(cursor_blink_interval) > 0 && global_state.application_focused && time_since_start_blink <= OPT(cursor_stop_blinking_after) ? true : false;
|
||||||
bool do_draw_cursor = true;
|
bool do_draw_cursor = true;
|
||||||
@ -466,37 +469,50 @@ render_cursor(Window *w, double now) {
|
|||||||
double delay = (bucket / 1000.0) - time_since_start_blink;
|
double delay = (bucket / 1000.0) - time_since_start_blink;
|
||||||
set_maximum_wait(delay);
|
set_maximum_wait(delay);
|
||||||
}
|
}
|
||||||
if (do_draw_cursor) {
|
if (!do_draw_cursor) { ans->is_visible = false; return; }
|
||||||
|
ans->is_visible = true;
|
||||||
|
ColorProfile *cp = rd->screen->color_profile;
|
||||||
Cursor *cursor = rd->screen->cursor;
|
Cursor *cursor = rd->screen->cursor;
|
||||||
|
ans->shape = cursor->shape ? cursor->shape : OPT(cursor_shape);
|
||||||
|
ans->color = colorprofile_to_color(cp, cp->overridden.cursor_color, cp->configured.cursor_color);
|
||||||
|
if (ans->shape == CURSOR_BLOCK) return;
|
||||||
double left = rd->xstart + cursor->x * rd->dx;
|
double left = rd->xstart + cursor->x * rd->dx;
|
||||||
double top = rd->ystart - cursor->y * rd->dy;
|
double top = rd->ystart - cursor->y * rd->dy;
|
||||||
int shape = cursor->shape ? cursor->shape : OPT(cursor_shape);
|
|
||||||
unsigned long mult = MAX(1, screen_current_char_width(rd->screen));
|
unsigned long mult = MAX(1, screen_current_char_width(rd->screen));
|
||||||
double right = left + (shape == CURSOR_BEAM ? cursor_width(1.5, true) : rd->dx * mult);
|
double right = left + (ans->shape == CURSOR_BEAM ? cursor_width(1.5, true) : rd->dx * mult);
|
||||||
double bottom = top - rd->dy;
|
double bottom = top - rd->dy;
|
||||||
if (shape == CURSOR_UNDERLINE) top = bottom + cursor_width(2.0, false);
|
if (ans->shape == CURSOR_UNDERLINE) top = bottom + cursor_width(2.0, false);
|
||||||
bool semi_transparent = OPT(cursor_opacity) < 1.0 && shape == CURSOR_BLOCK ? true : false;
|
ans->left = left; ans->right = right; ans->top = top; ans->bottom = bottom;
|
||||||
ColorProfile *cp = rd->screen->color_profile;
|
}
|
||||||
color_type col = colorprofile_to_color(cp, cp->overridden.cursor_color, cp->configured.cursor_color);
|
|
||||||
draw_cursor(semi_transparent, global_state.application_focused, col, OPT(cursor_opacity), left, right, top, bottom);
|
static inline void
|
||||||
|
update_window_title(Window *w) {
|
||||||
|
if (w->title && w->title != global_state.application_title) {
|
||||||
|
global_state.application_title = w->title;
|
||||||
|
glfwSetWindowTitle(glfw_window_id, PyUnicode_AsUTF8(w->title));
|
||||||
|
#ifdef __APPLE__
|
||||||
|
cocoa_update_title(w->title);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
render(double now) {
|
render(double now) {
|
||||||
double time_since_last_render = now - last_render_at;
|
double time_since_last_render = now - last_render_at;
|
||||||
|
static CursorRenderInfo cursor_info;
|
||||||
if (time_since_last_render < OPT(repaint_delay)) {
|
if (time_since_last_render < OPT(repaint_delay)) {
|
||||||
set_maximum_wait(OPT(repaint_delay) - time_since_last_render);
|
set_maximum_wait(OPT(repaint_delay) - time_since_last_render);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
draw_borders();
|
draw_borders();
|
||||||
|
cursor_info.is_visible = false;
|
||||||
#define TD global_state.tab_bar_render_data
|
#define TD global_state.tab_bar_render_data
|
||||||
if (TD.screen && global_state.num_tabs > 1) draw_cells(TD.vao_idx, TD.xstart, TD.ystart, TD.dx, TD.dy, TD.screen);
|
if (TD.screen && global_state.num_tabs > 1) draw_cells(TD.vao_idx, TD.xstart, TD.ystart, TD.dx, TD.dy, TD.screen, &cursor_info);
|
||||||
#undef TD
|
#undef TD
|
||||||
if (global_state.num_tabs) {
|
if (global_state.num_tabs) {
|
||||||
Tab *tab = global_state.tabs + global_state.active_tab;
|
Tab *tab = global_state.tabs + global_state.active_tab;
|
||||||
for (size_t i = 0; i < tab->num_windows; i++) {
|
for (unsigned int i = 0; i < tab->num_windows; i++) {
|
||||||
Window *w = tab->windows + i;
|
Window *w = tab->windows + i;
|
||||||
#define WD w->render_data
|
#define WD w->render_data
|
||||||
if (w->visible && WD.screen) {
|
if (w->visible && WD.screen) {
|
||||||
@ -508,22 +524,20 @@ render(double now) {
|
|||||||
} else w->last_drag_scroll_at = 0;
|
} else w->last_drag_scroll_at = 0;
|
||||||
} else set_maximum_wait(now - w->last_drag_scroll_at);
|
} else set_maximum_wait(now - w->last_drag_scroll_at);
|
||||||
}
|
}
|
||||||
draw_cells(WD.vao_idx, WD.xstart, WD.ystart, WD.dx, WD.dy, WD.screen);
|
bool is_active_window = i == tab->active_window;
|
||||||
|
if (is_active_window) {
|
||||||
|
collect_cursor_info(&cursor_info, w, now);
|
||||||
|
update_window_title(w);
|
||||||
|
} else cursor_info.is_visible = false;
|
||||||
|
draw_cells(WD.vao_idx, WD.xstart, WD.ystart, WD.dx, WD.dy, WD.screen, &cursor_info);
|
||||||
|
if (is_active_window && cursor_info.is_visible && cursor_info.shape != CURSOR_BLOCK) draw_cursor(&cursor_info);
|
||||||
if (WD.screen->start_visual_bell_at != 0) {
|
if (WD.screen->start_visual_bell_at != 0) {
|
||||||
double bell_left = global_state.opts.visual_bell_duration - (now - WD.screen->start_visual_bell_at);
|
double bell_left = global_state.opts.visual_bell_duration - (now - WD.screen->start_visual_bell_at);
|
||||||
set_maximum_wait(bell_left);
|
set_maximum_wait(bell_left);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Window *w = tab->windows + tab->active_window;
|
|
||||||
if (w->visible && WD.screen) render_cursor(w, now);
|
|
||||||
if (w->title && w->title != global_state.application_title) {
|
|
||||||
global_state.application_title = w->title;
|
|
||||||
glfwSetWindowTitle(glfw_window_id, PyUnicode_AsUTF8(w->title));
|
|
||||||
#ifdef __APPLE__
|
|
||||||
cocoa_update_title(w->title);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
#undef WD
|
#undef WD
|
||||||
}
|
}
|
||||||
glfwSwapBuffers(glfw_window_id);
|
glfwSwapBuffers(glfw_window_id);
|
||||||
|
|||||||
@ -47,10 +47,6 @@ def to_bool(x):
|
|||||||
return x.lower() in 'y yes true'.split()
|
return x.lower() in 'y yes true'.split()
|
||||||
|
|
||||||
|
|
||||||
def to_opacity(x):
|
|
||||||
return max(0.3, min(float(x), 1))
|
|
||||||
|
|
||||||
|
|
||||||
def parse_mods(parts):
|
def parse_mods(parts):
|
||||||
|
|
||||||
def map_mod(m):
|
def map_mod(m):
|
||||||
@ -212,7 +208,6 @@ type_map = {
|
|||||||
'font_size': to_font_size,
|
'font_size': to_font_size,
|
||||||
'font_size_delta': positive_float,
|
'font_size_delta': positive_float,
|
||||||
'cursor_shape': to_cursor_shape,
|
'cursor_shape': to_cursor_shape,
|
||||||
'cursor_opacity': to_opacity,
|
|
||||||
'open_url_modifiers': to_open_url_modifiers,
|
'open_url_modifiers': to_open_url_modifiers,
|
||||||
'repaint_delay': positive_int,
|
'repaint_delay': positive_int,
|
||||||
'input_delay': positive_int,
|
'input_delay': positive_int,
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
#version GLSL_VERSION
|
#version GLSL_VERSION
|
||||||
uniform vec4 color;
|
uniform vec3 color;
|
||||||
out vec4 final_color;
|
out vec4 final_color;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
final_color = color;
|
final_color = vec4(color, 1);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
#version GLSL_VERSION
|
#version GLSL_VERSION
|
||||||
uniform vec2 xpos;
|
uniform vec4 pos;
|
||||||
uniform vec2 ypos;
|
|
||||||
|
|
||||||
const uvec2 pos_map[] = uvec2[4](
|
const uvec2 pos_map[] = uvec2[4](
|
||||||
uvec2(1, 0), // right, top
|
uvec2(1, 0), // right, top
|
||||||
@ -10,6 +9,8 @@ const uvec2 pos_map[] = uvec2[4](
|
|||||||
);
|
);
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
|
vec2 xpos = vec2(pos[0], pos[2]);
|
||||||
|
vec2 ypos = vec2(pos[1], pos[3]);
|
||||||
uvec2 pos = pos_map[gl_VertexID];
|
uvec2 pos = pos_map[gl_VertexID];
|
||||||
gl_Position = vec4(xpos[pos[0]], ypos[pos[1]], 0, 1);
|
gl_Position = vec4(xpos[pos[0]], ypos[pos[1]], 0, 1);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -49,10 +49,7 @@ selection_background #FFFACD
|
|||||||
url_color #0087BD
|
url_color #0087BD
|
||||||
|
|
||||||
# The cursor color
|
# The cursor color
|
||||||
cursor #ffffff
|
cursor #cccccc
|
||||||
|
|
||||||
# The cursor opacity
|
|
||||||
cursor_opacity 0.7
|
|
||||||
|
|
||||||
# The cursor shape can be one of (block, beam, underline)
|
# The cursor shape can be one of (block, beam, underline)
|
||||||
cursor_shape block
|
cursor_shape block
|
||||||
|
|||||||
@ -552,33 +552,32 @@ destroy_sprite_map() {
|
|||||||
|
|
||||||
// Cell {{{
|
// Cell {{{
|
||||||
|
|
||||||
enum CellUniforms { CELL_dimensions, CELL_default_colors, CELL_color_indices, CELL_steps, CELL_sprites, CELL_sprite_layout, CELL_url_color, CELL_url_range, CELL_color_table, NUM_CELL_UNIFORMS };
|
enum CellUniforms { CELL_dimensions, CELL_default_colors, CELL_color_indices, CELL_steps, CELL_sprites, CELL_sprite_layout, CELL_url_range, CELL_color_table, NUM_CELL_UNIFORMS };
|
||||||
static GLint cell_uniform_locations[NUM_CELL_UNIFORMS] = {0};
|
static GLint cell_uniform_locations[NUM_CELL_UNIFORMS] = {0};
|
||||||
|
static GLint cell_uniform_indices[NUM_CELL_UNIFORMS] = {0};
|
||||||
static GLint cell_color_table_stride = 0, cell_color_table_offset = 0, cell_color_table_size = 0, cell_color_table_block_index = 0;
|
static GLint cell_color_table_stride = 0, cell_color_table_offset = 0, cell_color_table_size = 0, cell_color_table_block_index = 0;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
init_cell_program() {
|
init_cell_program() {
|
||||||
Program *p = programs + CELL_PROGRAM;
|
Program *p = programs + CELL_PROGRAM;
|
||||||
int left = NUM_CELL_UNIFORMS;
|
int left = NUM_CELL_UNIFORMS;
|
||||||
GLint ctable_idx = 0;
|
|
||||||
for (int i = 0; i < p->num_of_uniforms; i++, left--) {
|
for (int i = 0; i < p->num_of_uniforms; i++, left--) {
|
||||||
#define SET_LOC(which) if (strcmp(p->uniforms[i].name, #which) == 0) cell_uniform_locations[CELL_##which] = p->uniforms[i].location
|
#define SET_LOC(which) if (strcmp(p->uniforms[i].name, #which) == 0 || strcmp(p->uniforms[i].name, #which "[0]") == 0) { cell_uniform_locations[CELL_##which] = p->uniforms[i].location; cell_uniform_indices[CELL_##which] = i; }
|
||||||
SET_LOC(dimensions);
|
SET_LOC(dimensions)
|
||||||
else SET_LOC(default_colors);
|
else SET_LOC(color_table)
|
||||||
else SET_LOC(color_indices);
|
else SET_LOC(default_colors)
|
||||||
else SET_LOC(steps);
|
else SET_LOC(color_indices)
|
||||||
else SET_LOC(sprites);
|
else SET_LOC(steps)
|
||||||
else SET_LOC(sprite_layout);
|
else SET_LOC(sprites)
|
||||||
else SET_LOC(url_range);
|
else SET_LOC(sprite_layout)
|
||||||
else SET_LOC(url_color);
|
else SET_LOC(url_range)
|
||||||
else if (strcmp(p->uniforms[i].name, "color_table[0]") == 0) { ctable_idx = i; cell_uniform_locations[CELL_color_table] = p->uniforms[i].location; }
|
|
||||||
else { fatal("Unknown uniform in cell program: %s", p->uniforms[i].name); }
|
else { fatal("Unknown uniform in cell program: %s", p->uniforms[i].name); }
|
||||||
}
|
}
|
||||||
if (left) { fatal("Left over uniforms in cell program"); }
|
if (left) { fatal("Left over uniforms in cell program"); }
|
||||||
cell_color_table_block_index = block_index(CELL_PROGRAM, "ColorTable");
|
cell_color_table_block_index = block_index(CELL_PROGRAM, "ColorTable");
|
||||||
cell_color_table_size = block_size(CELL_PROGRAM, cell_color_table_block_index);
|
cell_color_table_size = block_size(CELL_PROGRAM, cell_color_table_block_index);
|
||||||
cell_color_table_stride = cell_color_table_size / (256 * sizeof(GLuint));
|
cell_color_table_stride = cell_color_table_size / (256 * sizeof(GLuint));
|
||||||
cell_color_table_offset = block_offset(CELL_PROGRAM, ctable_idx);
|
cell_color_table_offset = block_offset(CELL_PROGRAM, cell_uniform_indices[CELL_color_table]);
|
||||||
#undef SET_LOC
|
#undef SET_LOC
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -601,10 +600,9 @@ create_cell_vao() {
|
|||||||
#undef A1
|
#undef A1
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool cell_constants_sent = false;
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
draw_cells_impl(ssize_t vao_idx, GLfloat xstart, GLfloat ystart, GLfloat dx, GLfloat dy, Screen *screen) {
|
draw_cells_impl(ssize_t vao_idx, GLfloat xstart, GLfloat ystart, GLfloat dx, GLfloat dy, Screen *screen, CursorRenderInfo *cursor) {
|
||||||
size_t sz;
|
size_t sz;
|
||||||
void *address;
|
void *address;
|
||||||
bool inverted = screen_invert_colors(screen);
|
bool inverted = screen_invert_colors(screen);
|
||||||
@ -625,16 +623,20 @@ draw_cells_impl(ssize_t vao_idx, GLfloat xstart, GLfloat ystart, GLfloat dx, GLf
|
|||||||
copy_color_table_to_buffer(screen->color_profile, address, cell_color_table_offset, cell_color_table_stride);
|
copy_color_table_to_buffer(screen->color_profile, address, cell_color_table_offset, cell_color_table_stride);
|
||||||
unmap_vao_buffer(vao_idx, 2);
|
unmap_vao_buffer(vao_idx, 2);
|
||||||
}
|
}
|
||||||
|
index_type cx = screen->columns, cy = screen->lines;
|
||||||
|
if (cursor->is_visible && cursor->shape == CURSOR_BLOCK) { cx = screen->cursor->x, cy = screen->cursor->y; }
|
||||||
int sprite_map_unit = bind_sprite_map();
|
int sprite_map_unit = bind_sprite_map();
|
||||||
render_dirty_sprites(render_and_send_dirty_sprites);
|
render_dirty_sprites(render_and_send_dirty_sprites);
|
||||||
#define UL(name) cell_uniform_locations[CELL_##name]
|
#define UL(name) cell_uniform_locations[CELL_##name]
|
||||||
bind_program(CELL_PROGRAM);
|
bind_program(CELL_PROGRAM);
|
||||||
bind_vao_uniform_buffer(vao_idx, 2, cell_color_table_block_index);
|
bind_vao_uniform_buffer(vao_idx, 2, cell_color_table_block_index);
|
||||||
glUniform2ui(UL(dimensions), screen->columns, screen->lines); check_gl();
|
glUniform4ui(UL(dimensions), screen->columns, screen->lines, cx, cy); check_gl();
|
||||||
glUniform4f(UL(steps), xstart, ystart, dx, dy); check_gl();
|
glUniform4f(UL(steps), xstart, ystart, dx, dy); check_gl();
|
||||||
glUniform2i(UL(color_indices), inverted & 1, 1 - (inverted & 1)); check_gl();
|
glUniform2i(UL(color_indices), inverted & 1, 1 - (inverted & 1)); check_gl();
|
||||||
#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)
|
||||||
glUniform4ui(UL(default_colors), COLOR(default_fg), COLOR(default_bg), COLOR(highlight_fg), COLOR(highlight_bg)); check_gl();
|
static GLuint colors[6];
|
||||||
|
colors[0] = COLOR(default_fg); colors[1] = COLOR(default_bg); colors[2] = COLOR(highlight_fg); colors[3] = COLOR(highlight_bg); colors[4] = cursor->color; colors[5] = OPT(url_color);
|
||||||
|
glUniform1uiv(UL(default_colors), sizeof(colors)/sizeof(colors[0]), colors); check_gl();
|
||||||
#undef COLOR
|
#undef COLOR
|
||||||
GLuint start_x, start_y, end_x, end_y;
|
GLuint start_x, start_y, end_x, end_y;
|
||||||
screen_url_range(screen, &start_x, &start_y, &end_x, &end_y);
|
screen_url_range(screen, &start_x, &start_y, &end_x, &end_y);
|
||||||
@ -643,10 +645,6 @@ draw_cells_impl(ssize_t vao_idx, GLfloat xstart, GLfloat ystart, GLfloat dx, GLf
|
|||||||
unsigned int x, y, z;
|
unsigned int x, y, z;
|
||||||
sprite_map_current_layout(&x, &y, &z);
|
sprite_map_current_layout(&x, &y, &z);
|
||||||
glUniform2f(UL(sprite_layout), 1.0 / (float)x, 1.0 / (float)y); check_gl();
|
glUniform2f(UL(sprite_layout), 1.0 / (float)x, 1.0 / (float)y); check_gl();
|
||||||
if (!cell_constants_sent) {
|
|
||||||
glUniform1ui(UL(url_color), OPT(url_color)); check_gl();
|
|
||||||
cell_constants_sent = true;
|
|
||||||
}
|
|
||||||
bind_vertex_array(vao_idx);
|
bind_vertex_array(vao_idx);
|
||||||
glDrawArraysInstanced(GL_TRIANGLE_FAN, 0, 4, screen->lines * screen->columns); check_gl();
|
glDrawArraysInstanced(GL_TRIANGLE_FAN, 0, 4, screen->lines * screen->columns); check_gl();
|
||||||
unbind_vertex_array();
|
unbind_vertex_array();
|
||||||
@ -657,7 +655,7 @@ draw_cells_impl(ssize_t vao_idx, GLfloat xstart, GLfloat ystart, GLfloat dx, GLf
|
|||||||
// }}}
|
// }}}
|
||||||
|
|
||||||
// Cursor {{{
|
// Cursor {{{
|
||||||
enum CursorUniforms { CURSOR_color, CURSOR_xpos, CURSOR_ypos, NUM_CURSOR_UNIFORMS };
|
enum CursorUniforms { CURSOR_color, CURSOR_pos, NUM_CURSOR_UNIFORMS };
|
||||||
static GLint cursor_uniform_locations[NUM_CURSOR_UNIFORMS] = {0};
|
static GLint cursor_uniform_locations[NUM_CURSOR_UNIFORMS] = {0};
|
||||||
static ssize_t cursor_vertex_array;
|
static ssize_t cursor_vertex_array;
|
||||||
|
|
||||||
@ -669,8 +667,7 @@ init_cursor_program() {
|
|||||||
for (int i = 0; i < p->num_of_uniforms; i++, left--) {
|
for (int i = 0; i < p->num_of_uniforms; i++, left--) {
|
||||||
#define SET_LOC(which) if (strcmp(p->uniforms[i].name, #which) == 0) cursor_uniform_locations[CURSOR_##which] = p->uniforms[i].location
|
#define SET_LOC(which) if (strcmp(p->uniforms[i].name, #which) == 0) cursor_uniform_locations[CURSOR_##which] = p->uniforms[i].location
|
||||||
SET_LOC(color);
|
SET_LOC(color);
|
||||||
else SET_LOC(xpos);
|
else SET_LOC(pos);
|
||||||
else SET_LOC(ypos);
|
|
||||||
else { fatal("Unknown uniform in cursor program"); }
|
else { fatal("Unknown uniform in cursor program"); }
|
||||||
}
|
}
|
||||||
if (left) { fatal("Left over uniforms in cursor program"); }
|
if (left) { fatal("Left over uniforms in cursor program"); }
|
||||||
@ -678,19 +675,12 @@ init_cursor_program() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
draw_cursor_impl(bool semi_transparent, bool is_focused, color_type color, float alpha, float left, float right, float top, float bottom) {
|
draw_cursor_impl(CursorRenderInfo *cursor) {
|
||||||
if (semi_transparent) { glEnable(GL_BLEND); check_gl(); }
|
bind_program(CURSOR_PROGRAM); bind_vertex_array(cursor_vertex_array); check_gl();
|
||||||
bind_program(CURSOR_PROGRAM); bind_vertex_array(cursor_vertex_array);
|
glUniform3f(cursor_uniform_locations[CURSOR_color], ((cursor->color >> 16) & 0xff) / 255.0, ((cursor->color >> 8) & 0xff) / 255.0, (cursor->color & 0xff) / 255.0); check_gl();
|
||||||
glUniform4f(cursor_uniform_locations[CURSOR_color], ((color >> 16) & 0xff) / 255.0, ((color >> 8) & 0xff) / 255.0, (color & 0xff) / 255.0, alpha);
|
glUniform4f(cursor_uniform_locations[CURSOR_pos], cursor->left, cursor->top, cursor->right, cursor->bottom); check_gl();
|
||||||
check_gl();
|
glDrawArrays(global_state.application_focused ? GL_TRIANGLE_FAN : GL_LINE_LOOP, 0, 4); check_gl();
|
||||||
glUniform2f(cursor_uniform_locations[CURSOR_xpos], left, right);
|
|
||||||
check_gl();
|
|
||||||
glUniform2f(cursor_uniform_locations[CURSOR_ypos], top, bottom);
|
|
||||||
check_gl();
|
|
||||||
glDrawArrays(is_focused ? GL_TRIANGLE_FAN : GL_LINE_LOOP, 0, 4);
|
|
||||||
check_gl();
|
|
||||||
unbind_vertex_array(); unbind_program();
|
unbind_vertex_array(); unbind_program();
|
||||||
if (semi_transparent) { glDisable(GL_BLEND); check_gl(); }
|
|
||||||
}
|
}
|
||||||
// }}}
|
// }}}
|
||||||
|
|
||||||
@ -826,14 +816,6 @@ PYWRAP1(map_vao_buffer) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
NO_ARG(init_cursor_program)
|
NO_ARG(init_cursor_program)
|
||||||
PYWRAP1(draw_cursor) {
|
|
||||||
int semi_transparent, is_focused;
|
|
||||||
unsigned int color;
|
|
||||||
float alpha, left, right, top, bottom;
|
|
||||||
PA("ppIfffff", &semi_transparent, &is_focused, &color, &alpha, &left, &right, &top, &bottom);
|
|
||||||
draw_cursor(semi_transparent, is_focused, color, alpha, left, right, top, bottom);
|
|
||||||
Py_RETURN_NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
NO_ARG(init_borders_program)
|
NO_ARG(init_borders_program)
|
||||||
PYWRAP1(add_borders_rect) { unsigned int a, b, c, d, e; PA("IIIII", &a, &b, &c, &d, &e); add_borders_rect(a, b, c, d, e); Py_RETURN_NONE; }
|
PYWRAP1(add_borders_rect) { unsigned int a, b, c, d, e; PA("IIIII", &a, &b, &c, &d, &e); add_borders_rect(a, b, c, d, e); Py_RETURN_NONE; }
|
||||||
@ -841,15 +823,6 @@ TWO_INT(send_borders_rects)
|
|||||||
|
|
||||||
NO_ARG(init_cell_program)
|
NO_ARG(init_cell_program)
|
||||||
NO_ARG_INT(create_cell_vao)
|
NO_ARG_INT(create_cell_vao)
|
||||||
PYWRAP1(draw_cells) {
|
|
||||||
float xstart, ystart, dx, dy;
|
|
||||||
int vao_idx;
|
|
||||||
Screen *screen;
|
|
||||||
|
|
||||||
PA("iffffO", &vao_idx, &xstart, &ystart, &dx, &dy, &screen);
|
|
||||||
draw_cells_impl(vao_idx, xstart, ystart, dx, dy, screen);
|
|
||||||
Py_RETURN_NONE;
|
|
||||||
}
|
|
||||||
NO_ARG(destroy_sprite_map)
|
NO_ARG(destroy_sprite_map)
|
||||||
PYWRAP1(layout_sprite_map) {
|
PYWRAP1(layout_sprite_map) {
|
||||||
unsigned int cell_width, cell_height;
|
unsigned int cell_width, cell_height;
|
||||||
@ -899,7 +872,6 @@ PYWRAP0(check_for_extensions) {
|
|||||||
#define MW(name, arg_type) {#name, (PyCFunction)py##name, arg_type, NULL}
|
#define MW(name, arg_type) {#name, (PyCFunction)py##name, arg_type, NULL}
|
||||||
static PyMethodDef module_methods[] = {
|
static PyMethodDef module_methods[] = {
|
||||||
{"glewInit", (PyCFunction)glew_init, METH_NOARGS, NULL},
|
{"glewInit", (PyCFunction)glew_init, METH_NOARGS, NULL},
|
||||||
{"draw_cells", (PyCFunction)pydraw_cells, METH_VARARGS, NULL},
|
|
||||||
M(compile_program, METH_VARARGS),
|
M(compile_program, METH_VARARGS),
|
||||||
MW(check_for_extensions, METH_NOARGS),
|
MW(check_for_extensions, METH_NOARGS),
|
||||||
MW(create_vao, METH_NOARGS),
|
MW(create_vao, METH_NOARGS),
|
||||||
@ -911,7 +883,6 @@ static PyMethodDef module_methods[] = {
|
|||||||
MW(bind_program, METH_O),
|
MW(bind_program, METH_O),
|
||||||
MW(unbind_program, METH_NOARGS),
|
MW(unbind_program, METH_NOARGS),
|
||||||
MW(init_cursor_program, METH_NOARGS),
|
MW(init_cursor_program, METH_NOARGS),
|
||||||
MW(draw_cursor, METH_VARARGS),
|
|
||||||
MW(init_borders_program, METH_NOARGS),
|
MW(init_borders_program, METH_NOARGS),
|
||||||
MW(add_borders_rect, METH_VARARGS),
|
MW(add_borders_rect, METH_VARARGS),
|
||||||
MW(send_borders_rects, METH_VARARGS),
|
MW(send_borders_rects, METH_VARARGS),
|
||||||
|
|||||||
@ -154,7 +154,6 @@ PYWRAP1(set_options) {
|
|||||||
S(cursor_blink_interval, PyFloat_AsDouble);
|
S(cursor_blink_interval, PyFloat_AsDouble);
|
||||||
S(cursor_stop_blinking_after, PyFloat_AsDouble);
|
S(cursor_stop_blinking_after, PyFloat_AsDouble);
|
||||||
S(cursor_shape, PyLong_AsLong);
|
S(cursor_shape, PyLong_AsLong);
|
||||||
S(cursor_opacity, PyFloat_AsDouble);
|
|
||||||
S(mouse_hide_wait, PyFloat_AsDouble);
|
S(mouse_hide_wait, PyFloat_AsDouble);
|
||||||
S(wheel_scroll_multiplier, PyFloat_AsDouble);
|
S(wheel_scroll_multiplier, PyFloat_AsDouble);
|
||||||
S(open_url_modifiers, PyLong_AsUnsignedLong);
|
S(open_url_modifiers, PyLong_AsUnsignedLong);
|
||||||
|
|||||||
@ -10,7 +10,7 @@
|
|||||||
#define OPT(name) global_state.opts.name
|
#define OPT(name) global_state.opts.name
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
double visual_bell_duration, cursor_blink_interval, cursor_stop_blinking_after, mouse_hide_wait, click_interval, cursor_opacity, wheel_scroll_multiplier;
|
double visual_bell_duration, cursor_blink_interval, cursor_stop_blinking_after, mouse_hide_wait, click_interval, wheel_scroll_multiplier;
|
||||||
bool enable_audio_bell;
|
bool enable_audio_bell;
|
||||||
CursorShape cursor_shape;
|
CursorShape cursor_shape;
|
||||||
unsigned int open_url_modifiers;
|
unsigned int open_url_modifiers;
|
||||||
@ -77,6 +77,14 @@ typedef struct {
|
|||||||
} GlobalState;
|
} GlobalState;
|
||||||
|
|
||||||
extern GlobalState global_state;
|
extern GlobalState global_state;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
bool is_visible;
|
||||||
|
CursorShape shape;
|
||||||
|
double left, right, top, bottom;
|
||||||
|
color_type color;
|
||||||
|
} CursorRenderInfo;
|
||||||
|
|
||||||
bool drag_scroll(Window *);
|
bool drag_scroll(Window *);
|
||||||
|
|
||||||
#define call_boss(name, ...) { \
|
#define call_boss(name, ...) { \
|
||||||
@ -88,6 +96,6 @@ bool drag_scroll(Window *);
|
|||||||
#define EXTERNAL_FUNC(name, ret, ...) typedef ret (*name##_func)(__VA_ARGS__); extern name##_func name
|
#define EXTERNAL_FUNC(name, ret, ...) typedef ret (*name##_func)(__VA_ARGS__); extern name##_func name
|
||||||
#define EXTERNAL_FUNC0(name, ret) typedef ret (*name##_func)(); extern name##_func name
|
#define EXTERNAL_FUNC0(name, ret) typedef ret (*name##_func)(); extern name##_func name
|
||||||
EXTERNAL_FUNC0(draw_borders, void);
|
EXTERNAL_FUNC0(draw_borders, void);
|
||||||
EXTERNAL_FUNC(draw_cells, void, ssize_t, float, float, float, float, Screen *);
|
EXTERNAL_FUNC(draw_cells, void, ssize_t, float, float, float, float, Screen *, CursorRenderInfo *);
|
||||||
EXTERNAL_FUNC(draw_cursor, void, bool, bool, color_type, float, float, float, float, float);
|
EXTERNAL_FUNC(draw_cursor, void, CursorRenderInfo *);
|
||||||
EXTERNAL_FUNC(update_viewport_size, void, int, int);
|
EXTERNAL_FUNC(update_viewport_size, void, int, int);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user