diff --git a/kitty/cursor_trail.c b/kitty/cursor_trail.c index 68525b2e7..1240407f3 100644 --- a/kitty/cursor_trail.c +++ b/kitty/cursor_trail.c @@ -1,50 +1,59 @@ #include "state.h" +#include "float.h" inline static float norm(float x, float y) { return sqrtf(x * x + y * y); } -inline static bool -get_cursor_edge(float *left, float *right, float *top, float *bottom, Window *w) { +static void +update_cursor_trail_target(CursorTrail *ct, Window *w) { +#define EDGE(axis, index) ct->cursor_edge_##axis[index] #define WD w->render_data - *left = WD.xstart + WD.screen->cursor_render_info.x * WD.dx; - *bottom = WD.ystart - (WD.screen->cursor_render_info.y + 1) * WD.dy; + float left = FLT_MAX, right = FLT_MAX, top = FLT_MAX, bottom = FLT_MAX; switch (WD.screen->cursor_render_info.shape) { case CURSOR_BLOCK: case CURSOR_HOLLOW: - *right = *left + WD.dx; - *top = *bottom + WD.dy; - return true; case CURSOR_BEAM: - *right = *left + WD.dx / WD.screen->cell_size.width * OPT(cursor_beam_thickness); - *top = *bottom + WD.dy; - return true; case CURSOR_UNDERLINE: - *right = *left + WD.dx; - *top = *bottom + WD.dy / WD.screen->cell_size.height * OPT(cursor_underline_thickness); - return true; + left = WD.xstart + WD.screen->cursor_render_info.x * WD.dx; + bottom = WD.ystart - (WD.screen->cursor_render_info.y + 1) * WD.dy; default: - return false; + break; + } + switch (WD.screen->cursor_render_info.shape) { + case CURSOR_BLOCK: + case CURSOR_HOLLOW: + right = left + WD.dx; + top = bottom + WD.dy; + break; + case CURSOR_BEAM: + right = left + WD.dx / WD.screen->cell_size.width * OPT(cursor_beam_thickness); + top = bottom + WD.dy; + break; + case CURSOR_UNDERLINE: + right = left + WD.dx; + top = bottom + WD.dy / WD.screen->cell_size.height * OPT(cursor_underline_thickness); + break; + default: + break; + } + if (left != FLT_MAX) { + EDGE(x, 0) = left; + EDGE(x, 1) = right; + EDGE(y, 0) = top; + EDGE(y, 1) = bottom; + ct->screen = WD.screen; } } -bool -update_cursor_trail(CursorTrail *ct, Window *w, monotonic_t now, OSWindow *os_window) { +static bool +update_cursor_trail_corners(CursorTrail *ct, Window *w, monotonic_t now, OSWindow *os_window) { // the trail corners move towards the cursor corner at a speed proportional to their distance from the cursor corner. // equivalent to exponential ease out animation. - static const int ci[4][2] = {{1, 0}, {1, 1}, {0, 1}, {0, 0}}; const float dx_threshold = WD.dx / WD.screen->cell_size.width; const float dy_threshold = WD.dy / WD.screen->cell_size.height; - bool needs_render_prev = ct->needs_render; - ct->needs_render = false; - -#define EDGE(axis, index) ct->cursor_edge_##axis[index] - - if (!WD.screen->paused_rendering.expires_at && !get_cursor_edge(&EDGE(x, 0), &EDGE(x, 1), &EDGE(y, 0), &EDGE(y, 1), w)) { - return needs_render_prev; - } // the decay time for the trail to reach 1/1024 of its distance from the cursor corner float decay_fast = OPT(cursor_trail_decay_fast); @@ -55,7 +64,8 @@ update_cursor_trail(CursorTrail *ct, Window *w, monotonic_t now, OSWindow *os_wi ct->corner_x[i] = EDGE(x, ci[i][0]); ct->corner_y[i] = EDGE(y, ci[i][1]); } - } else if (OPT(cursor_trail) < now - WD.screen->cursor->position_changed_by_client_at && ct->updated_at < now) { + } + else if (ct->updated_at < now) { float cursor_center_x = (EDGE(x, 0) + EDGE(x, 1)) * 0.5f; float cursor_center_y = (EDGE(y, 0) + EDGE(y, 1)) * 0.5f; float cursor_diag_2 = norm(EDGE(x, 1) - EDGE(x, 0), EDGE(y, 1) - EDGE(y, 0)) * 0.5f; @@ -83,24 +93,34 @@ update_cursor_trail(CursorTrail *ct, Window *w, monotonic_t now, OSWindow *os_wi ct->corner_y[i] += dy * step; } } + ct->updated_at = now; for (int i = 0; i < 4; ++i) { float dx = fabsf(EDGE(x, ci[i][0]) - ct->corner_x[i]); float dy = fabsf(EDGE(y, ci[i][1]) - ct->corner_y[i]); if (dx_threshold <= dx || dy_threshold <= dy) { - ct->needs_render = true; - break; + return true; } } + return false; +} - if (ct->needs_render) { - ColorProfile *cp = WD.screen->color_profile; - ct->color = colorprofile_to_color(cp, cp->overridden.cursor_color, cp->configured.cursor_color).rgb; +bool +update_cursor_trail(CursorTrail *ct, Window *w, monotonic_t now, OSWindow *os_window) { + if (!WD.screen->paused_rendering.expires_at && OPT(cursor_trail) < now - WD.screen->cursor->position_changed_by_client_at) { + update_cursor_trail_target(ct, w); + } + + bool needs_render_prev = ct->needs_render; + ct->needs_render = false; + + if (update_cursor_trail_corners(ct, w, now, os_window)) { + ct->needs_render = true; } -#undef EDGE // returning true here will cause the cells to be drawn return ct->needs_render || needs_render_prev; } #undef WD +#undef EDGE diff --git a/kitty/screen.h b/kitty/screen.h index 71e78ecfb..e71c6ac6a 100644 --- a/kitty/screen.h +++ b/kitty/screen.h @@ -97,6 +97,7 @@ typedef struct { struct { unsigned int cursor_x, cursor_y, scrolled_by; index_type lines, columns; + color_type cursor_bg; } last_rendered; bool is_dirty, scroll_changed, reload_all_gpu_data; Cursor *cursor; diff --git a/kitty/shaders.c b/kitty/shaders.c index 38a5cc3ab..e64440169 100644 --- a/kitty/shaders.c +++ b/kitty/shaders.c @@ -385,6 +385,9 @@ cell_update_uniform_block(ssize_t vao_idx, Screen *screen, int uniform_buffer, c #undef COLOR rd->url_color = OPT(url_color); rd->url_style = OPT(url_style); + // store last rendered cursor color for trail rendering + screen->last_rendered.cursor_bg = rd->cursor_bg; + unmap_vao_buffer(vao_idx, uniform_buffer); rd = NULL; } @@ -1154,7 +1157,7 @@ draw_cursor_trail(CursorTrail *trail) { glUniform2fv(trail_program_layout.uniforms.cursor_edge_x, 1, trail->cursor_edge_x); glUniform2fv(trail_program_layout.uniforms.cursor_edge_y, 1, trail->cursor_edge_y); - color_vec3(trail_program_layout.uniforms.trail_color, trail->color); + color_vec3(trail_program_layout.uniforms.trail_color, trail->screen->last_rendered.cursor_bg); glDrawArrays(GL_TRIANGLE_FAN, 0, 4); diff --git a/kitty/state.h b/kitty/state.h index 08a592001..a121073c7 100644 --- a/kitty/state.h +++ b/kitty/state.h @@ -218,7 +218,7 @@ typedef struct { typedef struct { bool needs_render; monotonic_t updated_at; - color_type color; + Screen* screen; float corner_x[4]; float corner_y[4]; float cursor_edge_x[2];