Fix cursor rendering when on first cell of multicell

This commit is contained in:
Kovid Goyal 2024-12-19 05:51:23 +05:30
parent f67c58034c
commit bbcb7dc24c
No known key found for this signature in database
GPG key ID: 06BC317B515ACE7C
4 changed files with 38 additions and 26 deletions

View file

@ -9,7 +9,8 @@ layout(std140) uniform CellRenderData {
uint default_fg, highlight_fg, highlight_bg, cursor_fg, cursor_bg, url_color, url_style, inverted;
uint xnum, ynum, sprites_xnum, sprites_ynum, cursor_fg_sprite_idx, cell_height;
float cursor_x, cursor_y, cursor_w, cursor_opacity;
uint cursor_x1, cursor_x2, cursor_y1, cursor_y2;
float cursor_opacity;
// must have unique entries with 0 being default_bg and unset being UINT32_MAX
uint bg_colors0, bg_colors1, bg_colors2, bg_colors3, bg_colors4, bg_colors5, bg_colors6, bg_colors7;
@ -81,6 +82,11 @@ float one_if_equal_zero_otherwise(int a, int b) {
return 1.0f - clamp(abs(float(a) - float(b)), 0.0f, 1.0f);
}
float one_if_equal_zero_otherwise(uint a, uint b) {
return 1.0f - clamp(abs(float(a) - float(b)), 0.0f, 1.0f);
}
uint resolve_color(uint c, uint defval) {
// Convert a cell color to an actual color based on the color table
int t = int(c & BYTE_MASK);
@ -144,18 +150,10 @@ vec3 choose_color(float q, vec3 a, vec3 b) {
return mix(b, a, q);
}
float are_integers_equal(float a, float b) { // return 1 if equal otherwise 0
float delta = abs(a - b); // delta can be 0, 1 or larger
return step(delta, 0.5); // 0 if 0.5 < delta else 1
}
float is_cursor(uint xi, uint y) {
float x = float(xi);
float y_equal = are_integers_equal(float(y), cursor_y);
float x1_equal = are_integers_equal(x, cursor_x);
float x2_equal = are_integers_equal(x, cursor_w);
float x_equal = step(0.5, x1_equal + x2_equal);
return step(2.0, x_equal + y_equal);
float is_cursor(uint x, uint y) {
uint clamped_x = clamp(x, cursor_x1, cursor_x2);
uint clamped_y = clamp(y, cursor_y1, cursor_y2);
return one_if_equal_zero_otherwise(x, clamped_x) * one_if_equal_zero_otherwise(y, clamped_y);
}
// }}}

View file

@ -13,7 +13,6 @@
// TODO: Test handling of calt ligatures with scale see is_group_calt_ligature()
// TODO: Handle selection with multicell
// TODO: URL detection with multicell
// TODO: Cursor rendering over multicell
// TODO: Wrapping of multicell draw commands
// TODO: Handle rewrap and restitch of multiline chars
// TODO: Handle rewrap when a character is too wide/tall to fit on resized screen

View file

@ -369,7 +369,9 @@ cell_update_uniform_block(ssize_t vao_idx, Screen *screen, int uniform_buffer, c
GLuint default_fg, highlight_fg, highlight_bg, cursor_fg, cursor_bg, url_color, url_style, inverted;
GLuint xnum, ynum, sprites_xnum, sprites_ynum, cursor_fg_sprite_idx, cell_height;
GLfloat cursor_x, cursor_y, cursor_w, cursor_opacity;
GLuint cursor_x1, cursor_x2, cursor_y1, cursor_y2;
GLfloat cursor_opacity;
GLuint bg_colors0, bg_colors1, bg_colors2, bg_colors3, bg_colors4, bg_colors5, bg_colors6, bg_colors7;
GLfloat bg_opacities0, bg_opacities1, bg_opacities2, bg_opacities3, bg_opacities4, bg_opacities5, bg_opacities6, bg_opacities7;
};
@ -402,7 +404,8 @@ cell_update_uniform_block(ssize_t vao_idx, Screen *screen, int uniform_buffer, c
enum { BLOCK_IDX = 0, BEAM_IDX = 2, UNDERLINE_IDX = 3, UNFOCUSED_IDX = 4 };
Line *line_for_cursor = NULL;
if (cursor->opacity > 0) {
rd->cursor_x = cursor->x, rd->cursor_y = cursor->y;
rd->cursor_x1 = cursor->x, rd->cursor_y1 = cursor->y;
rd->cursor_x2 = cursor->x, rd->cursor_y2 = cursor->y;
rd->cursor_opacity = cursor->opacity;
CursorShape cs = (cursor->is_focused || OPT(cursor_shape_unfocused) == NO_CURSOR_SHAPE) ? cursor->shape : OPT(cursor_shape_unfocused);
switch(cs) {
@ -427,6 +430,24 @@ cell_update_uniform_block(ssize_t vao_idx, Screen *screen, int uniform_buffer, c
}
if (line_for_cursor) {
colors_for_cell(line_for_cursor, cp, &cell_color_x, &cell_fg, &cell_bg, &reversed);
const CPUCell *cursor_cell;
const bool large_cursor = ((cursor_cell = &line_for_cursor->cpu_cells[cursor->x])->is_multicell) && cursor_cell->x == 0 && cursor_cell->y == 0;
if (large_cursor) {
switch(cs) {
case CURSOR_BEAM:
rd->cursor_y2 += cursor_cell->scale - 1; break;
case CURSOR_UNDERLINE:
rd->cursor_y1 += cursor_cell->scale - 1;
rd->cursor_y2 = rd->cursor_y1;
rd->cursor_x2 += mcd_x_limit(cursor_cell) - 1;
break;
case CURSOR_BLOCK:
rd->cursor_y2 += cursor_cell->scale - 1;
rd->cursor_x2 += mcd_x_limit(cursor_cell) - 1;
break;
case CURSOR_HOLLOW: case NUM_OF_CURSOR_SHAPES: case NO_CURSOR_SHAPE: break;
};
}
}
if (IS_SPECIAL_COLOR(cursor_color)) {
if (line_for_cursor) pick_cursor_color(line_for_cursor, cp, cell_fg, cell_bg, cell_color_x, &rd->cursor_fg, &rd->cursor_bg, rd->default_fg, rd->bg_colors0);
@ -441,15 +462,9 @@ cell_update_uniform_block(ssize_t vao_idx, Screen *screen, int uniform_buffer, c
}
// store last rendered cursor color for trail rendering
screen->last_rendered.cursor_bg = rd->cursor_bg;
} else rd->cursor_x = screen->columns, rd->cursor_y = screen->lines;
rd->cursor_w = rd->cursor_x;
const CPUCell *cursor_cell;
if (
(rd->cursor_fg_sprite_idx == BLOCK_IDX || rd->cursor_fg_sprite_idx == UNDERLINE_IDX) &&
line_for_cursor && (cursor_cell = line_for_cursor->cpu_cells + cursor->x)->is_multicell &&
cursor_cell->x == 0
) {
rd->cursor_w = mcd_x_limit(cursor_cell);
} else {
rd->cursor_x1 = screen->columns + 1; rd->cursor_x2 = screen->columns;
rd->cursor_y1 = screen->lines + 1; rd->cursor_y2 = screen->lines;
}
rd->xnum = screen->columns; rd->ynum = screen->lines;

View file

@ -2,7 +2,7 @@
# License: GPLv3 Copyright: 2024, Kovid Goyal <kovid at kovidgoyal.net>
from kitty.fast_data_types import TEXT_SIZE_CODE, wcswidth, test_ch_and_idx
from kitty.fast_data_types import TEXT_SIZE_CODE, test_ch_and_idx, wcswidth
from . import BaseTest, parse_bytes
from . import draw_multicell as multicell