This commit is contained in:
Kovid Goyal 2024-10-20 10:06:48 +05:30
commit 65f0571b2c
No known key found for this signature in database
GPG key ID: 06BC317B515ACE7C
4 changed files with 58 additions and 34 deletions

View file

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

View file

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

View file

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

View file

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