mirror of
https://github.com/kovidgoyal/kitty.git
synced 2026-05-13 16:37:27 +00:00
parent
24049a1a5a
commit
14741b1b29
8 changed files with 41 additions and 19 deletions
|
|
@ -135,6 +135,11 @@ Detailed list of changes
|
|||
- Fix :opt:`background_opacity` being non-linear with light color themes
|
||||
(:iss:`8869`)
|
||||
|
||||
- Add support for blinking text. Text marked as blinking now blinks in exact
|
||||
rhythm with the cursor. The blinking animation and max duration are
|
||||
controlled by :opt:`cursor_blink_interval` and
|
||||
:opt:`cursor_stop_blinking_after`. (:pull:`8551`)
|
||||
|
||||
- Wayland: Fix incorrect window size calculation when transitioning from
|
||||
full screen to non-full screen with client side decorations (:iss:`8826`)
|
||||
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ layout(std140) uniform CellRenderData {
|
|||
|
||||
uint columns, lines, sprites_xnum, sprites_ynum, cursor_shape, cell_width, cell_height;
|
||||
uint cursor_x1, cursor_x2, cursor_y1, cursor_y2;
|
||||
float cursor_opacity, inactive_text_alpha, dim_opacity;
|
||||
float cursor_opacity, inactive_text_alpha, dim_opacity, blink_opacity;
|
||||
|
||||
// must have unique entries with 0 being default_bg and unset being UINT32_MAX
|
||||
uint bg_colors0, bg_colors1, bg_colors2, bg_colors3, bg_colors4, bg_colors5, bg_colors6, bg_colors7;
|
||||
|
|
@ -262,8 +262,9 @@ void main() {
|
|||
#ifndef ONLY_BACKGROUND // background does not depend on foreground
|
||||
fg_as_uint = has_mark * color_table[NUM_COLORS + MARK_MASK + mark] + (ONE - has_mark) * fg_as_uint;
|
||||
foreground = color_to_vec(fg_as_uint);
|
||||
float has_dim = float((text_attrs >> DIM_SHIFT) & ONE);
|
||||
effective_text_alpha = inactive_text_alpha * mix(1.0, dim_opacity, has_dim);
|
||||
float has_dim = float((text_attrs >> DIM_SHIFT) & ONE), has_blink = float((text_attrs >> BLINK_SHIFT) & ONE);
|
||||
effective_text_alpha = inactive_text_alpha * if_one_then(has_dim, dim_opacity, 1.0) * if_one_then(
|
||||
has_blink, blink_opacity, 1.0);
|
||||
float in_url = float((is_selected >> 1) & ONE);
|
||||
decoration_fg = if_one_then(in_url, color_to_vec(url_color), to_color(colors[2], fg_as_uint));
|
||||
// Selection
|
||||
|
|
|
|||
|
|
@ -668,26 +668,32 @@ collect_cursor_info(CursorRenderInfo *ans, Window *w, monotonic_t now, OSWindow
|
|||
cursor = rd->screen->paused_rendering.expires_at ? &rd->screen->paused_rendering.cursor : rd->screen->cursor;
|
||||
ans->x = cursor->x; ans->y = cursor->y;
|
||||
}
|
||||
ans->is_visible = false; ans->multicursor_count = 0; ans->opacity = 1;
|
||||
if (rd->screen->scrolled_by) return cursor_needs_render(w);
|
||||
ans->multicursor_count = screen_multi_cursor_count(rd->screen);
|
||||
ans->is_visible = screen_is_cursor_visible(rd->screen);
|
||||
if (!ans->is_visible && ans->multicursor_count == 0) return cursor_needs_render(w);
|
||||
ans->is_visible = false; ans->multicursor_count = 0; ans->cursor_opacity = 1; ans->text_blink_opacity = 1;
|
||||
if (!rd->screen->scrolled_by) {
|
||||
ans->multicursor_count = screen_multi_cursor_count(rd->screen);
|
||||
ans->is_visible = screen_is_cursor_visible(rd->screen);
|
||||
}
|
||||
if (!ans->is_visible && ans->multicursor_count == 0 && !rd->screen->sgr_blink_was_used) return cursor_needs_render(w);
|
||||
monotonic_t time_since_start_blink = now - os_window->cursor_blink_zero_time;
|
||||
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));
|
||||
if (cursor_blinking) {
|
||||
const bool allow_blinking = OPT(cursor_blink_interval) > 0;
|
||||
const bool blink_has_ceased = OPT(cursor_stop_blinking_after) != 0 && time_since_start_blink > OPT(cursor_stop_blinking_after);
|
||||
const bool cursor_blinking = !cursor->non_blinking && os_window->is_focused;
|
||||
float blink_opacity = 1.f;
|
||||
if (allow_blinking && !blink_has_ceased && (cursor_blinking || rd->screen->sgr_blink_was_used)) {
|
||||
if (animation_is_valid(OPT(animation.cursor))) {
|
||||
monotonic_t duration = OPT(cursor_blink_interval) * 2;
|
||||
monotonic_t time_into_cycle = time_since_start_blink % duration;
|
||||
double frac_into_cycle = (double)time_into_cycle / (double)duration;
|
||||
ans->opacity = (float)apply_easing_curve(OPT(animation.cursor), frac_into_cycle, duration);
|
||||
blink_opacity = (float)apply_easing_curve(OPT(animation.cursor), frac_into_cycle, duration);
|
||||
set_maximum_wait(ANIMATION_SAMPLE_WAIT);
|
||||
} else {
|
||||
monotonic_t n = time_since_start_blink / OPT(cursor_blink_interval);
|
||||
ans->opacity = 1 - n % 2;
|
||||
blink_opacity = 1 - n % 2;
|
||||
set_maximum_wait((n + 1) * OPT(cursor_blink_interval) - time_since_start_blink);
|
||||
}
|
||||
}
|
||||
ans->text_blink_opacity = blink_opacity;
|
||||
ans->cursor_opacity = cursor_blinking ? blink_opacity: 1.0f;
|
||||
ans->shape = cursor->shape ? cursor->shape : OPT(cursor_shape);
|
||||
ans->is_focused = os_window->is_focused;
|
||||
return cursor_needs_render(w);
|
||||
|
|
@ -776,7 +782,13 @@ prepare_to_render_os_window(OSWindow *os_window, monotonic_t now, unsigned int *
|
|||
if (collect_cursor_info(&WD.screen->cursor_render_info, w, now, os_window)) needs_render = true;
|
||||
WD.screen->cursor_render_info.is_focused = false;
|
||||
} else {
|
||||
WD.screen->cursor_render_info.opacity = 0;
|
||||
if (WD.screen->sgr_blink_was_used) {
|
||||
if (collect_cursor_info(&WD.screen->cursor_render_info, w, now, os_window)) needs_render = true;
|
||||
WD.screen->cursor_render_info.is_focused = false;
|
||||
} else {
|
||||
WD.screen->cursor_render_info.text_blink_opacity = 1;
|
||||
}
|
||||
WD.screen->cursor_render_info.cursor_opacity = 0;
|
||||
}
|
||||
}
|
||||
if (scan_for_animated_images) {
|
||||
|
|
|
|||
|
|
@ -227,7 +227,7 @@ typedef struct {
|
|||
bool is_focused, render_even_when_unfocused, is_visible;
|
||||
CursorShape shape;
|
||||
unsigned x, y, multicursor_count;
|
||||
float opacity;
|
||||
float cursor_opacity, text_blink_opacity;
|
||||
} CursorRenderInfo;
|
||||
|
||||
typedef enum DynamicColorType {
|
||||
|
|
|
|||
|
|
@ -363,14 +363,16 @@ it will go from opaque to transparent and then back again over the next half. Yo
|
|||
different easing functions for the two halves, for example: :code:`-1 linear ease-out`. kitty
|
||||
supports all the :link:`CSS easing functions <https://developer.mozilla.org/en-US/docs/Web/CSS/easing-function>`.
|
||||
Note that turning on animations uses extra power as it means the screen is redrawn multiple times
|
||||
per blink interval. See also, :opt:`cursor_stop_blinking_after`.
|
||||
per blink interval. See also, :opt:`cursor_stop_blinking_after`. This setting also controls blinking
|
||||
text, which blinks in exact rhythm with the cursor.
|
||||
''')
|
||||
|
||||
opt('cursor_stop_blinking_after', '15.0',
|
||||
option_type='positive_float', ctype='time',
|
||||
long_text='''
|
||||
Stop blinking cursor after the specified number of seconds of keyboard
|
||||
inactivity. Set to zero to never stop blinking.
|
||||
inactivity. Set to zero to never stop blinking. This setting also controls
|
||||
blinking text, which blinks in exact rhythm with the cursor.
|
||||
''')
|
||||
|
||||
opt('cursor_trail', '0',
|
||||
|
|
|
|||
|
|
@ -1399,6 +1399,7 @@ select_graphic_rendition(Screen *self, int *params, unsigned int count, bool is_
|
|||
}
|
||||
} else {
|
||||
cursor_from_sgr(self->cursor, params, count, is_group);
|
||||
self->sgr_blink_was_used |= self->cursor->sgr.blink;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -114,7 +114,7 @@ typedef struct {
|
|||
color_type cursor_bg;
|
||||
CursorRenderInfo cursor;
|
||||
} last_rendered;
|
||||
bool is_dirty, scroll_changed, reload_all_gpu_data;
|
||||
bool is_dirty, scroll_changed, reload_all_gpu_data, sgr_blink_was_used;
|
||||
Cursor *cursor;
|
||||
Savepoint main_savepoint, alt_savepoint;
|
||||
PyObject *callbacks, *test_child;
|
||||
|
|
|
|||
|
|
@ -442,7 +442,7 @@ cell_update_uniform_block(ssize_t vao_idx, Screen *screen, int uniform_buffer, C
|
|||
|
||||
GLuint columns, lines, sprites_xnum, sprites_ynum, cursor_shape, cell_width, cell_height;
|
||||
GLuint cursor_x1, cursor_x2, cursor_y1, cursor_y2;
|
||||
GLfloat cursor_opacity, inactive_text_alpha, dim_opacity;
|
||||
GLfloat cursor_opacity, inactive_text_alpha, dim_opacity, blink_opacity;
|
||||
|
||||
GLuint bg_colors0, bg_colors1, bg_colors2, bg_colors3, bg_colors4, bg_colors5, bg_colors6, bg_colors7;
|
||||
GLfloat bg_opacities0, bg_opacities1, bg_opacities2, bg_opacities3, bg_opacities4, bg_opacities5, bg_opacities6, bg_opacities7;
|
||||
|
|
@ -475,7 +475,8 @@ cell_update_uniform_block(ssize_t vao_idx, Screen *screen, int uniform_buffer, C
|
|||
rd->use_cell_for_selection_bg = IS_SPECIAL_COLOR(highlight_bg) ? 1. : 0.;
|
||||
// Cursor position
|
||||
Line *line_for_cursor = NULL;
|
||||
rd->cursor_opacity = MAX(0, MIN(cursor->opacity, 1));
|
||||
rd->cursor_opacity = MAX(0, MIN(cursor->cursor_opacity, 1));
|
||||
rd->blink_opacity = MAX(0, MIN(cursor->text_blink_opacity, 1));
|
||||
if (rd->cursor_opacity != 0 && cursor->is_visible) {
|
||||
rd->cursor_x1 = cursor->x, rd->cursor_y1 = cursor->y;
|
||||
rd->cursor_x2 = cursor->x, rd->cursor_y2 = cursor->y;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue