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:
Kovid Goyal 2017-09-17 13:03:02 +05:30
parent 2d0c6a43c5
commit df4df76d24
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
9 changed files with 103 additions and 103 deletions

View File

@ -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);
} }

View File

@ -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);

View File

@ -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,

View File

@ -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);
} }

View File

@ -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);
} }

View File

@ -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

View File

@ -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),

View File

@ -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);

View File

@ -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);