Merge branch 'cursor_trail' of https://github.com/jinhwanlazy/kitty
This commit is contained in:
commit
cbccda8061
16 changed files with 269 additions and 3 deletions
|
|
@ -751,6 +751,10 @@ prepare_to_render_os_window(OSWindow *os_window, monotonic_t now, unsigned int *
|
|||
WD.screen->cursor_render_info.is_focused = os_window->is_focused;
|
||||
set_os_window_title_from_window(w, os_window);
|
||||
*active_window_bg = window_bg;
|
||||
if (OPT(enable_cursor_trail) && update_cursor_trail(&tab->cursor_trail, w, now, os_window)) {
|
||||
needs_render = true;
|
||||
set_maximum_wait(OPT(repaint_delay));
|
||||
}
|
||||
} else {
|
||||
if (WD.screen->cursor_render_info.render_even_when_unfocused) {
|
||||
if (collect_cursor_info(&WD.screen->cursor_render_info, w, now, os_window)) needs_render = true;
|
||||
|
|
@ -808,6 +812,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 (OPT(enable_cursor_trail) && 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;
|
||||
|
|
|
|||
106
kitty/cursor_trail.c
Normal file
106
kitty/cursor_trail.c
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
#include "state.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) {
|
||||
#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;
|
||||
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;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
update_cursor_trail(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);
|
||||
float decay_slow = OPT(cursor_trail_decay_slow);
|
||||
|
||||
if (os_window->live_resize.in_progress) {
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
ct->corner_x[i] = EDGE(x, ci[i][0]);
|
||||
ct->corner_y[i] = EDGE(y, ci[i][1]);
|
||||
}
|
||||
}
|
||||
else if (OPT(input_delay) < now - WD.screen->cursor->updated_at && 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;
|
||||
float dt = (float)monotonic_t_to_s_double(now - ct->updated_at);
|
||||
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
float dx = EDGE(x, ci[i][0]) - ct->corner_x[i];
|
||||
float dy = EDGE(y, ci[i][1]) - ct->corner_y[i];
|
||||
if (fabsf(dx) < dx_threshold && fabsf(dy) < dy_threshold) {
|
||||
ct->corner_x[i] = EDGE(x, ci[i][0]);
|
||||
ct->corner_y[i] = 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 * (EDGE(x, ci[i][0]) - cursor_center_x) +
|
||||
dy * (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;
|
||||
float step = 1.0f - 1.0f / exp2f(10.0f * dt / decay_seconds);
|
||||
|
||||
ct->corner_x[i] += dx * step;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
#undef WD
|
||||
#undef EDGE
|
||||
// returning true here will cause the cells to be drawn
|
||||
return ct->needs_render || needs_render_prev;
|
||||
}
|
||||
|
|
@ -297,6 +297,7 @@ typedef struct {
|
|||
PyObject_HEAD
|
||||
|
||||
bool bold, italic, reverse, strikethrough, dim, non_blinking;
|
||||
monotonic_t updated_at;
|
||||
unsigned int x, y;
|
||||
uint8_t decoration;
|
||||
CursorShape shape;
|
||||
|
|
|
|||
|
|
@ -296,6 +296,7 @@ FC_WIDTH_NORMAL: int
|
|||
FC_SLANT_ROMAN: int
|
||||
FC_SLANT_ITALIC: int
|
||||
BORDERS_PROGRAM: int
|
||||
TRAIL_PROGRAM: int
|
||||
PRESS: int
|
||||
RELEASE: int
|
||||
DRAG: int
|
||||
|
|
@ -540,6 +541,8 @@ def add_borders_rect(
|
|||
def init_borders_program() -> None:
|
||||
pass
|
||||
|
||||
def init_trail_program() -> None:
|
||||
pass
|
||||
|
||||
def os_window_has_background_image(os_window_id: int) -> bool:
|
||||
pass
|
||||
|
|
|
|||
|
|
@ -350,6 +350,28 @@
|
|||
'''
|
||||
)
|
||||
|
||||
opt('enable_cursor_trail', 'no',
|
||||
option_type='to_bool', ctype='bool',
|
||||
long_text='''
|
||||
Enables or disables the cursor trail effect. When set to `yes`, a trailing
|
||||
effect is rendered behind the cursor as it moves, creating a motion trail.
|
||||
'''
|
||||
)
|
||||
|
||||
opt('cursor_trail_decay', '0.1 0.3',
|
||||
option_type='cursor_trail_decay',
|
||||
ctype='!cursor_trail_decay',
|
||||
long_text='''
|
||||
Controls the decay times for the cursor trail effect when :code:`enable_cursor_trail`
|
||||
is set to :code:`yes`. This option accepts two positive float values specifying the
|
||||
fastest and slowest decay times in seconds. The first value corresponds to the
|
||||
fastest decay time (minimum), and the second value corresponds to the slowest
|
||||
decay time (maximum). The second value must be equal to or greater than the
|
||||
first value. Smaller values result in a faster decay of the cursor trail.
|
||||
Adjust these values to control how quickly the cursor trail fades away.
|
||||
''',
|
||||
)
|
||||
|
||||
egr() # }}}
|
||||
|
||||
|
||||
|
|
|
|||
8
kitty/options/parse.py
generated
8
kitty/options/parse.py
generated
|
|
@ -10,7 +10,7 @@
|
|||
action_alias, active_tab_title_template, allow_hyperlinks, bell_on_tab, box_drawing_scale,
|
||||
clear_all_mouse_actions, clear_all_shortcuts, clipboard_control, clone_source_strategies,
|
||||
config_or_absolute_path, copy_on_select, cursor_blink_interval, cursor_text_color,
|
||||
deprecated_adjust_line_height, deprecated_hide_window_decorations_aliases,
|
||||
cursor_trail_decay, deprecated_adjust_line_height, deprecated_hide_window_decorations_aliases,
|
||||
deprecated_macos_show_window_title_in_menubar_alias, deprecated_send_text, disable_ligatures,
|
||||
edge_width, env, filter_notification, font_features, hide_window_decorations, macos_option_as_alt,
|
||||
macos_titlebar_color, menu_map, modify_font, narrow_symbols, notify_on_cmd_finish,
|
||||
|
|
@ -931,6 +931,9 @@ def cursor_stop_blinking_after(self, val: str, ans: typing.Dict[str, typing.Any]
|
|||
def cursor_text_color(self, val: str, ans: typing.Dict[str, typing.Any]) -> None:
|
||||
ans['cursor_text_color'] = cursor_text_color(val)
|
||||
|
||||
def cursor_trail_decay(self, val: str, ans: typing.Dict[str, typing.Any]) -> None:
|
||||
ans['cursor_trail_decay'] = cursor_trail_decay(val)
|
||||
|
||||
def cursor_underline_thickness(self, val: str, ans: typing.Dict[str, typing.Any]) -> None:
|
||||
ans['cursor_underline_thickness'] = positive_float(val)
|
||||
|
||||
|
|
@ -963,6 +966,9 @@ def editor(self, val: str, ans: typing.Dict[str, typing.Any]) -> None:
|
|||
def enable_audio_bell(self, val: str, ans: typing.Dict[str, typing.Any]) -> None:
|
||||
ans['enable_audio_bell'] = to_bool(val)
|
||||
|
||||
def enable_cursor_trail(self, val: str, ans: typing.Dict[str, typing.Any]) -> None:
|
||||
ans['enable_cursor_trail'] = to_bool(val)
|
||||
|
||||
def enabled_layouts(self, val: str, ans: typing.Dict[str, typing.Any]) -> None:
|
||||
ans['enabled_layouts'] = to_layout_names(val)
|
||||
|
||||
|
|
|
|||
30
kitty/options/to-c-generated.h
generated
30
kitty/options/to-c-generated.h
generated
|
|
@ -161,6 +161,32 @@ convert_from_opts_cursor_stop_blinking_after(PyObject *py_opts, Options *opts) {
|
|||
Py_DECREF(ret);
|
||||
}
|
||||
|
||||
static void
|
||||
convert_from_python_enable_cursor_trail(PyObject *val, Options *opts) {
|
||||
opts->enable_cursor_trail = PyObject_IsTrue(val);
|
||||
}
|
||||
|
||||
static void
|
||||
convert_from_opts_enable_cursor_trail(PyObject *py_opts, Options *opts) {
|
||||
PyObject *ret = PyObject_GetAttrString(py_opts, "enable_cursor_trail");
|
||||
if (ret == NULL) return;
|
||||
convert_from_python_enable_cursor_trail(ret, opts);
|
||||
Py_DECREF(ret);
|
||||
}
|
||||
|
||||
static void
|
||||
convert_from_python_cursor_trail_decay(PyObject *val, Options *opts) {
|
||||
cursor_trail_decay(val, opts);
|
||||
}
|
||||
|
||||
static void
|
||||
convert_from_opts_cursor_trail_decay(PyObject *py_opts, Options *opts) {
|
||||
PyObject *ret = PyObject_GetAttrString(py_opts, "cursor_trail_decay");
|
||||
if (ret == NULL) return;
|
||||
convert_from_python_cursor_trail_decay(ret, opts);
|
||||
Py_DECREF(ret);
|
||||
}
|
||||
|
||||
static void
|
||||
convert_from_python_scrollback_indicator_opacity(PyObject *val, Options *opts) {
|
||||
opts->scrollback_indicator_opacity = PyFloat_AsFloat(val);
|
||||
|
|
@ -1123,6 +1149,10 @@ convert_opts_from_python_opts(PyObject *py_opts, Options *opts) {
|
|||
if (PyErr_Occurred()) return false;
|
||||
convert_from_opts_cursor_stop_blinking_after(py_opts, opts);
|
||||
if (PyErr_Occurred()) return false;
|
||||
convert_from_opts_enable_cursor_trail(py_opts, opts);
|
||||
if (PyErr_Occurred()) return false;
|
||||
convert_from_opts_cursor_trail_decay(py_opts, opts);
|
||||
if (PyErr_Occurred()) return false;
|
||||
convert_from_opts_scrollback_indicator_opacity(py_opts, opts);
|
||||
if (PyErr_Occurred()) return false;
|
||||
convert_from_opts_scrollback_pager_history_size(py_opts, opts);
|
||||
|
|
|
|||
|
|
@ -180,6 +180,11 @@ visual_bell_duration(PyObject *src, Options *opts) {
|
|||
|
||||
#undef parse_animation
|
||||
|
||||
static inline void
|
||||
cursor_trail_decay(PyObject *src, Options *opts) {
|
||||
opts->cursor_trail_decay_fast = PyFloat_AsFloat(PyTuple_GET_ITEM(src, 0));
|
||||
opts->cursor_trail_decay_slow = PyFloat_AsFloat(PyTuple_GET_ITEM(src, 1));
|
||||
}
|
||||
|
||||
static void
|
||||
parse_font_mod_size(PyObject *val, float *sz, AdjustmentUnit *unit) {
|
||||
|
|
|
|||
4
kitty/options/types.py
generated
4
kitty/options/types.py
generated
|
|
@ -334,6 +334,7 @@
|
|||
'cursor_shape_unfocused',
|
||||
'cursor_stop_blinking_after',
|
||||
'cursor_text_color',
|
||||
'cursor_trail_decay',
|
||||
'cursor_underline_thickness',
|
||||
'default_pointer_shape',
|
||||
'detect_urls',
|
||||
|
|
@ -343,6 +344,7 @@
|
|||
'dynamic_background_opacity',
|
||||
'editor',
|
||||
'enable_audio_bell',
|
||||
'enable_cursor_trail',
|
||||
'enabled_layouts',
|
||||
'env',
|
||||
'exe_search_path',
|
||||
|
|
@ -510,6 +512,7 @@ class Options:
|
|||
cursor_shape_unfocused: int = 4
|
||||
cursor_stop_blinking_after: float = 15.0
|
||||
cursor_text_color: typing.Optional[kitty.fast_data_types.Color] = Color(17, 17, 17)
|
||||
cursor_trail_decay: typing.Tuple[float, float] = (0.1, 0.3)
|
||||
cursor_underline_thickness: float = 2.0
|
||||
default_pointer_shape: choices_for_default_pointer_shape = 'beam'
|
||||
detect_urls: bool = True
|
||||
|
|
@ -519,6 +522,7 @@ class Options:
|
|||
dynamic_background_opacity: bool = False
|
||||
editor: str = '.'
|
||||
enable_audio_bell: bool = True
|
||||
enable_cursor_trail: bool = False
|
||||
enabled_layouts: typing.List[str] = ['fat', 'grid', 'horizontal', 'splits', 'stack', 'tall', 'vertical']
|
||||
file_transfer_confirmation_bypass: str = ''
|
||||
focus_follows_mouse: bool = False
|
||||
|
|
|
|||
|
|
@ -558,6 +558,11 @@ def to_cursor_unfocused_shape(x: str) -> int:
|
|||
)
|
||||
)
|
||||
|
||||
def cursor_trail_decay(x: str) -> Tuple[float, float]:
|
||||
fast, slow = map(positive_float, x.split())
|
||||
slow = max(slow, fast)
|
||||
return fast, slow
|
||||
|
||||
|
||||
def scrollback_lines(x: str) -> int:
|
||||
ans = int(x)
|
||||
|
|
|
|||
|
|
@ -1765,6 +1765,7 @@ screen_cursor_position(Screen *self, unsigned int line, unsigned int column) {
|
|||
line += self->margin_top;
|
||||
line = MAX(self->margin_top, MIN(line, self->margin_bottom));
|
||||
}
|
||||
self->cursor->updated_at = monotonic();
|
||||
self->cursor->x = column; self->cursor->y = line;
|
||||
screen_ensure_bounds(self, false, in_margins);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
#define BLEND_ONTO_OPAQUE_WITH_OPAQUE_OUTPUT glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ZERO, GL_ONE); // blending onto opaque colors with final color having alpha 1
|
||||
#define BLEND_PREMULT glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); // blending of pre-multiplied colors
|
||||
|
||||
enum { CELL_PROGRAM, CELL_BG_PROGRAM, CELL_SPECIAL_PROGRAM, CELL_FG_PROGRAM, BORDERS_PROGRAM, GRAPHICS_PROGRAM, GRAPHICS_PREMULT_PROGRAM, GRAPHICS_ALPHA_MASK_PROGRAM, BGIMAGE_PROGRAM, TINT_PROGRAM, NUM_PROGRAMS };
|
||||
enum { CELL_PROGRAM, CELL_BG_PROGRAM, CELL_SPECIAL_PROGRAM, CELL_FG_PROGRAM, BORDERS_PROGRAM, GRAPHICS_PROGRAM, GRAPHICS_PREMULT_PROGRAM, GRAPHICS_ALPHA_MASK_PROGRAM, BGIMAGE_PROGRAM, TINT_PROGRAM, TRAIL_PROGRAM, NUM_PROGRAMS };
|
||||
enum { SPRITE_MAP_UNIT, GRAPHICS_UNIT, BGIMAGE_UNIT };
|
||||
|
||||
// Sprites {{{
|
||||
|
|
@ -1133,6 +1133,36 @@ draw_borders(ssize_t vao_idx, unsigned int num_border_rects, BorderRect *rect_bu
|
|||
|
||||
// }}}
|
||||
|
||||
// Cursor Trail {{{
|
||||
typedef struct {
|
||||
TrailUniforms uniforms;
|
||||
} TrailProgramLayout;
|
||||
static TrailProgramLayout trail_program_layout;
|
||||
|
||||
static void
|
||||
init_trail_program(void) {
|
||||
get_uniform_locations_trail(TRAIL_PROGRAM, &trail_program_layout.uniforms);
|
||||
}
|
||||
|
||||
void
|
||||
draw_cursor_trail(CursorTrail *trail) {
|
||||
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);
|
||||
|
||||
color_vec3(trail_program_layout.uniforms.trail_color, trail->color);
|
||||
|
||||
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
|
||||
|
||||
unbind_program();
|
||||
}
|
||||
|
||||
// }}}
|
||||
|
||||
// Python API {{{
|
||||
|
||||
static bool
|
||||
|
|
@ -1205,6 +1235,8 @@ NO_ARG(init_borders_program)
|
|||
|
||||
NO_ARG(init_cell_program)
|
||||
|
||||
NO_ARG(init_trail_program)
|
||||
|
||||
static PyObject*
|
||||
sprite_map_set_limits(PyObject UNUSED *self, PyObject *args) {
|
||||
unsigned int w, h;
|
||||
|
|
@ -1229,6 +1261,7 @@ static PyMethodDef module_methods[] = {
|
|||
MW(unbind_program, METH_NOARGS),
|
||||
MW(init_borders_program, METH_NOARGS),
|
||||
MW(init_cell_program, METH_NOARGS),
|
||||
MW(init_trail_program, METH_NOARGS),
|
||||
|
||||
{NULL, NULL, 0, NULL} /* Sentinel */
|
||||
};
|
||||
|
|
@ -1241,7 +1274,7 @@ finalize(void) {
|
|||
bool
|
||||
init_shaders(PyObject *module) {
|
||||
#define C(x) if (PyModule_AddIntConstant(module, #x, x) != 0) { PyErr_NoMemory(); return false; }
|
||||
C(CELL_PROGRAM); C(CELL_BG_PROGRAM); C(CELL_SPECIAL_PROGRAM); C(CELL_FG_PROGRAM); C(BORDERS_PROGRAM); C(GRAPHICS_PROGRAM); C(GRAPHICS_PREMULT_PROGRAM); C(GRAPHICS_ALPHA_MASK_PROGRAM); C(BGIMAGE_PROGRAM); C(TINT_PROGRAM);
|
||||
C(CELL_PROGRAM); C(CELL_BG_PROGRAM); C(CELL_SPECIAL_PROGRAM); C(CELL_FG_PROGRAM); C(BORDERS_PROGRAM); C(GRAPHICS_PROGRAM); C(GRAPHICS_PREMULT_PROGRAM); C(GRAPHICS_ALPHA_MASK_PROGRAM); C(BGIMAGE_PROGRAM); C(TINT_PROGRAM); C(TRAIL_PROGRAM);
|
||||
C(GLSL_VERSION);
|
||||
C(GL_VERSION);
|
||||
C(GL_VENDOR);
|
||||
|
|
|
|||
|
|
@ -27,9 +27,11 @@
|
|||
REVERSE,
|
||||
STRIKETHROUGH,
|
||||
TINT_PROGRAM,
|
||||
TRAIL_PROGRAM,
|
||||
compile_program,
|
||||
get_options,
|
||||
init_cell_program,
|
||||
init_trail_program,
|
||||
)
|
||||
|
||||
|
||||
|
|
@ -201,5 +203,8 @@ def resolve_graphics_fragment_defines(which: str, f: str) -> str:
|
|||
program_for('tint').compile(TINT_PROGRAM, allow_recompile)
|
||||
init_cell_program()
|
||||
|
||||
program_for('trail').compile(TRAIL_PROGRAM, allow_recompile)
|
||||
init_trail_program()
|
||||
|
||||
|
||||
load_shader_programs = LoadShaderPrograms()
|
||||
|
|
|
|||
|
|
@ -46,6 +46,9 @@ typedef struct {
|
|||
CursorShape cursor_shape, cursor_shape_unfocused;
|
||||
float cursor_beam_thickness;
|
||||
float cursor_underline_thickness;
|
||||
bool enable_cursor_trail;
|
||||
float cursor_trail_decay_fast;
|
||||
float cursor_trail_decay_slow;
|
||||
unsigned int url_style;
|
||||
unsigned int scrollback_pager_history_size;
|
||||
bool scrollback_fill_enlarged_window;
|
||||
|
|
@ -212,11 +215,22 @@ typedef struct {
|
|||
ssize_t vao_idx;
|
||||
} BorderRects;
|
||||
|
||||
typedef struct {
|
||||
bool needs_render;
|
||||
monotonic_t updated_at;
|
||||
color_type color;
|
||||
float corner_x[4];
|
||||
float corner_y[4];
|
||||
float cursor_edge_x[2];
|
||||
float cursor_edge_y[2];
|
||||
} CursorTrail;
|
||||
|
||||
typedef struct {
|
||||
id_type id;
|
||||
unsigned int active_window, num_windows, capacity;
|
||||
Window *windows;
|
||||
BorderRects border_rects;
|
||||
CursorTrail cursor_trail;
|
||||
} Tab;
|
||||
|
||||
enum RENDER_STATE { RENDER_FRAME_NOT_REQUESTED, RENDER_FRAME_REQUESTED, RENDER_FRAME_READY };
|
||||
|
|
@ -352,6 +366,8 @@ ssize_t create_border_vao(void);
|
|||
bool send_cell_data_to_gpu(ssize_t, float, float, float, float, Screen *, OSWindow *);
|
||||
void draw_cells(ssize_t, const WindowRenderData*, OSWindow *, bool, bool, bool, Window*);
|
||||
void draw_centered_alpha_mask(OSWindow *w, size_t screen_width, size_t screen_height, size_t width, size_t height, uint8_t *canvas, float);
|
||||
void draw_cursor_trail(CursorTrail *trail);
|
||||
bool update_cursor_trail(CursorTrail *ct, Window *w, monotonic_t now, OSWindow *os_window);
|
||||
void update_surface_size(int, int, uint32_t);
|
||||
void free_texture(uint32_t*);
|
||||
void free_framebuffer(uint32_t*);
|
||||
|
|
|
|||
15
kitty/trail_fragment.glsl
Normal file
15
kitty/trail_fragment.glsl
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
uniform vec2 cursor_edge_x;
|
||||
uniform vec2 cursor_edge_y;
|
||||
uniform vec3 trail_color;
|
||||
|
||||
in vec2 frag_pos;
|
||||
out vec4 final_color;
|
||||
|
||||
void main() {
|
||||
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 = vec4(trail_color, 1.0);
|
||||
}
|
||||
}
|
||||
9
kitty/trail_vertex.glsl
Normal file
9
kitty/trail_vertex.glsl
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
uniform vec4 x_coords;
|
||||
uniform vec4 y_coords;
|
||||
|
||||
out vec2 frag_pos;
|
||||
|
||||
void main() {
|
||||
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);
|
||||
}
|
||||
Loading…
Reference in a new issue