Skip to content

Commit c393c16

Browse files
committed
Implement rendering of multi cursors in the shaders
1 parent b2f543f commit c393c16

File tree

7 files changed

+32
-29
lines changed

7 files changed

+32
-29
lines changed

kitty/cell_vertex.glsl

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -64,10 +64,8 @@ out float effective_text_alpha;
6464
const uint BYTE_MASK = uint(0xFF);
6565
const uint SPRITE_INDEX_MASK = uint(0x7fffffff);
6666
const uint SPRITE_COLORED_MASK = uint(0x80000000);
67-
const uint SPRITE_COLORED_SHIFT = uint(31);
68-
const uint ZERO = uint(0);
69-
const uint ONE = uint(1);
70-
const uint TWO = uint(2);
67+
const uint SPRITE_COLORED_SHIFT = 31u;
68+
const uint ONE = 1u;
7169
const uint DECORATION_MASK = uint({DECORATION_MASK});
7270

7371
vec3 color_to_vec(uint c) {
@@ -168,9 +166,14 @@ CellData set_vertex_position() {
168166
sprite_pos = to_sprite_pos(pos, sprite_idx[0] & SPRITE_INDEX_MASK);
169167
colored_sprite = float((sprite_idx[0] & SPRITE_COLORED_MASK) >> SPRITE_COLORED_SHIFT);
170168
#endif
171-
float is_block_cursor = one_if_equal_zero_otherwise(cursor_shape, 1u);
172-
float has_cursor = is_cursor(column, row);
173-
return CellData(has_cursor, has_cursor * is_block_cursor, pos, cursor_shape_map[cursor_shape]);
169+
float has_main_cursor = is_cursor(column, row);
170+
float multicursor_shape = float((is_selected >> 2) & 3u);
171+
float multicursor_uses_main_cursor_shape = float((is_selected >> 4) & ONE);
172+
multicursor_shape = if_one_then(multicursor_uses_main_cursor_shape, cursor_shape, multicursor_shape);
173+
float final_cursor_shape = if_one_then(has_main_cursor, cursor_shape, multicursor_shape);
174+
float has_cursor = zero_or_one(final_cursor_shape);
175+
float is_block_cursor = has_cursor * one_if_equal_zero_otherwise(final_cursor_shape, 1.0);
176+
return CellData(has_cursor, is_block_cursor, pos, cursor_shape_map[int(final_cursor_shape)]);
174177
}
175178

176179
float background_opacity_for(uint bg, uint colorval, float opacity_if_matched) { // opacity_if_matched if bg == colorval else 1
@@ -261,7 +264,7 @@ void main() {
261264
foreground = color_to_vec(fg_as_uint);
262265
float has_dim = float((text_attrs >> DIM_SHIFT) & ONE);
263266
effective_text_alpha = inactive_text_alpha * mix(1.0, dim_opacity, has_dim);
264-
float in_url = float((is_selected & TWO) >> 1);
267+
float in_url = float((is_selected >> 1) & ONE);
265268
decoration_fg = if_one_then(in_url, color_to_vec(url_color), to_color(colors[2], fg_as_uint));
266269
// Selection
267270
vec3 selection_color = if_one_then(use_cell_bg_for_selection_fg, bg, color_to_vec(highlight_fg));

kitty/child-monitor.c

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -652,9 +652,7 @@ pyset_iutf8(ChildMonitor *self, PyObject *args) {
652652

653653
static bool
654654
cursor_needs_render(Window *w) {
655-
#define cri w->render_data.screen->cursor_render_info
656-
return w->cursor_opacity_at_last_render != cri.opacity || w->render_data.screen->last_rendered.cursor_x != cri.x || w->render_data.screen->last_rendered.cursor_y != cri.y || w->last_cursor_shape != cri.shape;
657-
#undef cri
655+
return memcmp(&w->render_data.screen->last_rendered.cursor, &w->render_data.screen->cursor_render_info, sizeof(CursorRenderInfo)) != 0;
658656
}
659657

660658
static bool
@@ -670,11 +668,13 @@ collect_cursor_info(CursorRenderInfo *ans, Window *w, monotonic_t now, OSWindow
670668
cursor = rd->screen->paused_rendering.expires_at ? &rd->screen->paused_rendering.cursor : rd->screen->cursor;
671669
ans->x = cursor->x; ans->y = cursor->y;
672670
}
673-
ans->opacity = 0;
674-
if (rd->screen->scrolled_by || !screen_is_cursor_visible(rd->screen)) return cursor_needs_render(w);
671+
ans->is_visible = false; ans->multicursor_count = 0; ans->opacity = 1;
672+
if (rd->screen->scrolled_by) return cursor_needs_render(w);
673+
ans->multicursor_count = screen_multi_cursor_count(rd->screen);
674+
ans->is_visible = screen_is_cursor_visible(rd->screen);
675+
if (!ans->is_visible && ans->multicursor_count == 0) return cursor_needs_render(w);
675676
monotonic_t time_since_start_blink = now - os_window->cursor_blink_zero_time;
676677
bool cursor_blinking = OPT(cursor_blink_interval) > 0 && !cursor->non_blinking && os_window->is_focused && (OPT(cursor_stop_blinking_after) == 0 || time_since_start_blink <= OPT(cursor_stop_blinking_after));
677-
ans->opacity = 1;
678678
if (cursor_blinking) {
679679
if (animation_is_valid(OPT(animation.cursor))) {
680680
monotonic_t duration = OPT(cursor_blink_interval) * 2;
@@ -812,7 +812,6 @@ render_prepared_os_window(OSWindow *os_window, unsigned int active_window_id, co
812812
if (is_active_window) active_window = w;
813813
draw_cells(&WD, os_window, is_active_window, false, num_of_visible_windows == 1, w);
814814
if (WD.screen->start_visual_bell_at != 0) set_maximum_wait(ANIMATION_SAMPLE_WAIT);
815-
w->cursor_opacity_at_last_render = WD.screen->cursor_render_info.opacity; w->last_cursor_shape = WD.screen->cursor_render_info.shape;
816815
}
817816
}
818817
setup_os_window_for_rendering(os_window, tab, active_window, false);

kitty/data-types.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -221,9 +221,9 @@ typedef struct {
221221
} Cursor;
222222

223223
typedef struct {
224-
bool is_focused, render_even_when_unfocused;
224+
bool is_focused, render_even_when_unfocused, is_visible;
225225
CursorShape shape;
226-
unsigned int x, y;
226+
unsigned x, y, multicursor_count;
227227
float opacity;
228228
} CursorRenderInfo;
229229

kitty/screen.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1900,6 +1900,11 @@ screen_is_cursor_visible(const Screen *self) {
19001900
return self->paused_rendering.expires_at ? self->paused_rendering.cursor_visible : self->modes.mDECTCEM;
19011901
}
19021902

1903+
unsigned
1904+
screen_multi_cursor_count(const Screen *self) {
1905+
return self->paused_rendering.expires_at ? self->paused_rendering.extra_cursors.count : self->extra_cursors.count;
1906+
}
1907+
19031908
void
19041909
screen_backspace(Screen *self) {
19051910
screen_cursor_move(self, 1, -1, true);
@@ -3470,7 +3475,7 @@ screen_update_cell_data(Screen *self, void *address, FONTS_DATA_HANDLE fonts_dat
34703475
lnum = y - self->scrolled_by;
34713476
linebuf_init_line(self->linebuf, lnum);
34723477
if (self->linebuf->line->attrs.has_dirty_text ||
3473-
(cursor_has_moved && (self->cursor->y == lnum || self->last_rendered.cursor_y == lnum))) {
3478+
(cursor_has_moved && (self->cursor->y == lnum || self->last_rendered.cursor.y == lnum))) {
34743479
render_line(fonts_data, self->linebuf->line, lnum, self->cursor, self->disable_ligatures, self->lc);
34753480
screen_render_line_graphics(self, self->linebuf->line, y - self->scrolled_by);
34763481
if (self->linebuf->line->attrs.has_dirty_text && screen_has_marker(self)) mark_text_in_line(

kitty/screen.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,9 +109,10 @@ typedef struct {
109109
id_type window_id;
110110
Selections selections, url_ranges;
111111
struct {
112-
unsigned int cursor_x, cursor_y, scrolled_by;
112+
unsigned int scrolled_by;
113113
index_type lines, columns;
114114
color_type cursor_bg;
115+
CursorRenderInfo cursor;
115116
} last_rendered;
116117
bool is_dirty, scroll_changed, reload_all_gpu_data;
117118
Cursor *cursor;
@@ -265,6 +266,7 @@ bool screen_has_selection(Screen*);
265266
bool screen_invert_colors(Screen *self);
266267
void screen_update_cell_data(Screen *self, void *address, FONTS_DATA_HANDLE, bool cursor_has_moved);
267268
bool screen_is_cursor_visible(const Screen *self);
269+
unsigned screen_multi_cursor_count(const Screen *self);
268270
bool screen_selection_range_for_line(Screen *self, index_type y, index_type *start, index_type *end);
269271
bool screen_selection_range_for_word(Screen *self, const index_type x, const index_type y, index_type *, index_type *, index_type *start, index_type *end, bool);
270272
void screen_start_selection(Screen *self, index_type x, index_type y, bool, bool, SelectionExtendMode);

kitty/shaders.c

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -476,7 +476,7 @@ cell_update_uniform_block(ssize_t vao_idx, Screen *screen, int uniform_buffer, C
476476
// Cursor position
477477
Line *line_for_cursor = NULL;
478478
rd->cursor_opacity = MAX(0, MIN(cursor->opacity, 1));
479-
if (rd->cursor_opacity != 0) {
479+
if (rd->cursor_opacity != 0 && cursor->is_visible) {
480480
rd->cursor_x1 = cursor->x, rd->cursor_y1 = cursor->y;
481481
rd->cursor_x2 = cursor->x, rd->cursor_y2 = cursor->y;
482482
CursorShape cs = (cursor->is_focused || OPT(cursor_shape_unfocused) == NO_CURSOR_SHAPE) ? cursor->shape : OPT(cursor_shape_unfocused);
@@ -559,8 +559,8 @@ cell_prepare_to_render(ssize_t vao_idx, Screen *screen, FONTS_DATA_HANDLE fonts_
559559
ensure_sprite_map(fonts_data);
560560
const Cursor *cursor = screen->paused_rendering.expires_at ? &screen->paused_rendering.cursor : screen->cursor;
561561

562-
bool cursor_pos_changed = cursor->x != screen->last_rendered.cursor_x
563-
|| cursor->y != screen->last_rendered.cursor_y;
562+
bool cursor_pos_changed = cursor->x != screen->last_rendered.cursor.x \
563+
|| cursor->y != screen->last_rendered.cursor.y;
564564
bool disable_ligatures = screen->disable_ligatures == DISABLE_LIGATURES_CURSOR;
565565
bool screen_resized = screen->last_rendered.columns != screen->columns || screen->last_rendered.lines != screen->lines;
566566

@@ -576,11 +576,6 @@ cell_prepare_to_render(ssize_t vao_idx, Screen *screen, FONTS_DATA_HANDLE fonts_
576576
if (!screen->paused_rendering.cell_data_updated) update_cell_data;
577577
} else if (screen->reload_all_gpu_data || screen->scroll_changed || screen->is_dirty || screen_resized || (disable_ligatures && cursor_pos_changed)) update_cell_data;
578578

579-
if (cursor_pos_changed) {
580-
screen->last_rendered.cursor_x = cursor->x;
581-
screen->last_rendered.cursor_y = cursor->y;
582-
}
583-
584579
#define update_selection_data { \
585580
sz = (size_t)screen->lines * screen->columns; \
586581
address = alloc_and_map_vao_buffer(vao_idx, sz, selection_buffer, GL_STREAM_DRAW, GL_WRITE_ONLY); \
@@ -607,6 +602,7 @@ cell_prepare_to_render(ssize_t vao_idx, Screen *screen, FONTS_DATA_HANDLE fonts_
607602
#undef update_cell_data
608603
screen->last_rendered.columns = screen->columns;
609604
screen->last_rendered.lines = screen->lines;
605+
screen->last_rendered.cursor = screen->cursor_render_info;
610606

611607
return changed;
612608
}

kitty/state.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -193,8 +193,6 @@ typedef struct WindowBarData {
193193
typedef struct Window {
194194
id_type id;
195195
bool visible;
196-
float cursor_opacity_at_last_render;
197-
CursorShape last_cursor_shape;
198196
PyObject *title;
199197
WindowRenderData render_data;
200198
WindowLogoRenderData window_logo;

0 commit comments

Comments
 (0)