diff --git a/kitty/child-monitor.c b/kitty/child-monitor.c index bde96ccad..7464a0d3e 100644 --- a/kitty/child-monitor.c +++ b/kitty/child-monitor.c @@ -809,7 +809,7 @@ render_prepared_os_window(OSWindow *os_window, unsigned int active_window_id, co w->cursor_opacity_at_last_render = WD.screen->cursor_render_info.opacity; w->last_cursor_shape = WD.screen->cursor_render_info.shape; } } - if (true) draw_cursor_trail(&tab->cursor_trail); + if (true && tab->cursor_trail.needs_render) draw_cursor_trail(&tab->cursor_trail); if (os_window->live_resize.in_progress) draw_resizing_text(os_window); swap_window_buffers(os_window); os_window->last_active_tab = os_window->active_tab; os_window->last_num_tabs = os_window->num_tabs; os_window->last_active_window_id = active_window_id; diff --git a/kitty/cursor_trail.c b/kitty/cursor_trail.c index e8d308062..abe4f441a 100644 --- a/kitty/cursor_trail.c +++ b/kitty/cursor_trail.c @@ -38,36 +38,37 @@ update_cursor_trail(CursorTrail *ct, Window *w, monotonic_t now) { 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; - float cursor_edge_x[2], cursor_edge_y[2]; - if (!get_cursor_edge(&cursor_edge_x[0], &cursor_edge_x[1], - &cursor_edge_y[0], &cursor_edge_y[1], w)) { - return false; + if (!get_cursor_edge(&ct->cursor_edge_x[0], &ct->cursor_edge_x[1], + &ct->cursor_edge_y[0], &ct->cursor_edge_y[1], w)) { + return needs_render_prev; } // todo - make these configurable // the decay time for the trail to reach 1/1024 of its distance from the cursor corner float decay_fast = 0.10f; - float decay_slow = 0.40f; + float decay_slow = 0.80f; if (OPT(input_delay) < now - WD.screen->cursor->updated_at && ct->updated_at < now) { - float cursor_center_x = (cursor_edge_x[0] + cursor_edge_x[1]) * 0.5f; - float cursor_center_y = (cursor_edge_y[0] + cursor_edge_y[1]) * 0.5f; - float cursor_diag_2 = norm(cursor_edge_x[1] - cursor_edge_x[0], cursor_edge_y[1] - cursor_edge_y[0]) * 0.5; + float cursor_center_x = (ct->cursor_edge_x[0] + ct->cursor_edge_x[1]) * 0.5f; + float cursor_center_y = (ct->cursor_edge_y[0] + ct->cursor_edge_y[1]) * 0.5f; + float cursor_diag_2 = norm(ct->cursor_edge_x[1] - ct->cursor_edge_x[0], ct->cursor_edge_y[1] - ct->cursor_edge_y[0]) * 0.5; float dt = monotonic_t_to_s_double(now - ct->updated_at); for (int i = 0; i < 4; ++i) { - float dx = cursor_edge_x[ci[i][0]] - ct->corner_x[i]; - float dy = cursor_edge_y[ci[i][1]] - ct->corner_y[i]; + float dx = ct->cursor_edge_x[ci[i][0]] - ct->corner_x[i]; + float dy = ct->cursor_edge_y[ci[i][1]] - ct->corner_y[i]; if (fabsf(dx) < dx_threshold && fabsf(dy) < dy_threshold) { - ct->corner_x[i] = cursor_edge_x[ci[i][0]]; - ct->corner_y[i] = cursor_edge_y[ci[i][1]]; + ct->corner_x[i] = ct->cursor_edge_x[ci[i][0]]; + ct->corner_y[i] = ct->cursor_edge_y[ci[i][1]]; continue; } // Corner that is closer to the cursor moves faster. // It creates dynamic effect that looks like the trail is being pulled towards the cursor. - float dot = (dx * (cursor_edge_x[ci[i][0]] - cursor_center_x) + - dy * (cursor_edge_y[ci[i][1]] - cursor_center_y)) / + float dot = (dx * (ct->cursor_edge_x[ci[i][0]] - cursor_center_x) + + dy * (ct->cursor_edge_y[ci[i][1]] - cursor_center_y)) / cursor_diag_2 / norm(dx, dy); float decay_seconds = decay_slow + (decay_fast - decay_slow) * (1.0f + dot) * 0.5f; @@ -79,12 +80,14 @@ update_cursor_trail(CursorTrail *ct, Window *w, monotonic_t now) { } ct->updated_at = now; for (int i = 0; i < 4; ++i) { - float dx = fabsf(cursor_edge_x[ci[i][0]] - ct->corner_x[i]); - float dy = fabsf(cursor_edge_y[ci[i][1]] - ct->corner_y[i]); + float dx = fabsf(ct->cursor_edge_x[ci[i][0]] - ct->corner_x[i]); + float dy = fabsf(ct->cursor_edge_y[ci[i][1]] - ct->corner_y[i]); if (dx_threshold <= dx || dy_threshold <= dy) { - return true; + ct->needs_render = true; + break; } } #undef WD - return false; + // returning true here will cause the cells to be drawn + return ct->needs_render || needs_render_prev; } diff --git a/kitty/shaders.c b/kitty/shaders.c index 3af977352..da8c2614e 100644 --- a/kitty/shaders.c +++ b/kitty/shaders.c @@ -1147,15 +1147,15 @@ init_trail_program(void) { void draw_cursor_trail(CursorTrail *trail) { glEnable(GL_BLEND); - // BLEND_PREMULT - /*glBlendFuncSeparate(GL_ONE, GL_ONE_MINUS_SRC_ALPHA, GL_ZERO, GL_ONE);*/ BLEND_ONTO_OPAQUE; - bind_program(TRAIL_PROGRAM); glUniform4fv(trail_program_layout.uniforms.x_coords, 1, trail->corner_x); glUniform4fv(trail_program_layout.uniforms.y_coords, 1, trail->corner_y); + 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); + // todo - get cursor color from opt float trail_color[4] = {1.0f, 1.0f, 1.0f, 1.0f}; glUniform4fv(trail_program_layout.uniforms.trail_color, 1, trail_color); diff --git a/kitty/state.h b/kitty/state.h index 0f46dfa1e..ae6f83b1a 100644 --- a/kitty/state.h +++ b/kitty/state.h @@ -214,8 +214,11 @@ typedef struct { typedef struct { monotonic_t updated_at; + bool needs_render; float corner_x[4]; float corner_y[4]; + float cursor_edge_x[2]; + float cursor_edge_y[2]; } CursorTrail; typedef struct { diff --git a/kitty/trail_fragment.glsl b/kitty/trail_fragment.glsl index 9b516b455..5f64ee230 100644 --- a/kitty/trail_fragment.glsl +++ b/kitty/trail_fragment.glsl @@ -1,6 +1,14 @@ +uniform vec2 cursor_edge_x; +uniform vec2 cursor_edge_y; uniform vec4 trail_color; -out vec4 color; +in vec2 frag_pos; +out vec4 final_color; void main() { - color = trail_color; + if (cursor_edge_x[0] <= frag_pos.x && frag_pos.x <= cursor_edge_x[1] && + cursor_edge_y[1] <= frag_pos.y && frag_pos.y <= cursor_edge_y[0]) { + discard; + } else { + final_color = trail_color; + } } diff --git a/kitty/trail_vertex.glsl b/kitty/trail_vertex.glsl index 781db8805..a4610bebf 100644 --- a/kitty/trail_vertex.glsl +++ b/kitty/trail_vertex.glsl @@ -1,6 +1,9 @@ uniform vec4 x_coords; uniform vec4 y_coords; +out vec2 frag_pos; + void main() { - gl_Position = vec4(x_coords[gl_VertexID], y_coords[gl_VertexID], -1.0, 1.0); + frag_pos = vec2(x_coords[gl_VertexID], y_coords[gl_VertexID]); + gl_Position = vec4(x_coords[gl_VertexID], y_coords[gl_VertexID], 1.0, 1.0); }