diff --git a/kitty/cell_vertex.glsl b/kitty/cell_vertex.glsl index d57bb1f49..f146f7ebd 100644 --- a/kitty/cell_vertex.glsl +++ b/kitty/cell_vertex.glsl @@ -12,7 +12,7 @@ // Inputs {{{ layout(std140) uniform CellRenderData { - float xstart, ystart, dx, dy, sprite_dx, sprite_dy, background_opacity, cursor_text_uses_bg; + float xstart, ystart, dx, dy, sprite_dx, sprite_dy, background_opacity, cursor_text_uses_bg, visual_bell_intensity; uint default_fg, default_bg, highlight_fg, highlight_bg, cursor_color, cursor_text_color, url_color, url_style, inverted; @@ -236,6 +236,7 @@ void main() { #if defined(SPECIAL) || defined(SIMPLE) // Selection and cursor + bg = max(bg, choose_color(visual_bell_intensity, color_to_vec(highlight_bg), bg)); bg = choose_color(float(is_selected & ONE), color_to_vec(highlight_bg), bg); background = choose_color(cell_has_block_cursor, color_to_vec(cursor_color), bg); #if !defined(TRANSPARENT) && defined(SPECIAL) diff --git a/kitty/screen.c b/kitty/screen.c index 9bc5c6eb1..54c399867 100644 --- a/kitty/screen.c +++ b/kitty/screen.c @@ -1324,12 +1324,43 @@ screen_use_latin1(Screen *self, bool on) { bool screen_invert_colors(Screen *self) { bool inverted = false; + if (self->modes.mDECSCNM) inverted = true; + return inverted; +} + +float +ease_out_cubic(float phase) { + return 1.0f - powf(1.0f - phase, 3.0f); +} + +float +ease_in_out_cubic(float phase) { + return phase < 0.5f ? + 4.0f * powf(phase, 3.0f) : + 1.0f - powf(-2.0f * phase + 2.0f, 3.0f) / 2.0f; +} + +float +visual_bell_intensity(float phase) { + float peak = 0.2f; + float fade = 1.0f - peak; + if (phase < peak) + return ease_out_cubic(phase / peak); + else + return ease_in_out_cubic((1.0f - phase) / fade); +} + +float +screen_visual_bell_intensity(Screen *self) { if (self->start_visual_bell_at > 0) { - if (monotonic() - self->start_visual_bell_at <= OPT(visual_bell_duration)) inverted = true; + monotonic_t progress = monotonic() - self->start_visual_bell_at; + monotonic_t duration = OPT(visual_bell_duration); + if (progress <= duration) { + return visual_bell_intensity((float)progress / duration); + } else self->start_visual_bell_at = 0; } - if (self->modes.mDECSCNM) inverted = inverted ? false : true; - return inverted; + return 0.0f; } void diff --git a/kitty/screen.h b/kitty/screen.h index 2f26d88d4..3ab286024 100644 --- a/kitty/screen.h +++ b/kitty/screen.h @@ -194,6 +194,7 @@ void screen_apply_selection(Screen *self, void *address, size_t size); bool screen_is_selection_dirty(Screen *self); bool screen_has_selection(Screen*); bool screen_invert_colors(Screen *self); +float screen_visual_bell_intensity(Screen *self); void screen_update_cell_data(Screen *self, void *address, FONTS_DATA_HANDLE, bool cursor_has_moved); bool screen_is_cursor_visible(Screen *self); bool screen_selection_range_for_line(Screen *self, index_type y, index_type *start, index_type *end); diff --git a/kitty/shaders.c b/kitty/shaders.c index 60433c328..f76161da1 100644 --- a/kitty/shaders.c +++ b/kitty/shaders.c @@ -250,9 +250,9 @@ send_graphics_data_to_gpu(size_t image_count, ssize_t gvao_idx, const ImageRende } static inline void -cell_update_uniform_block(ssize_t vao_idx, Screen *screen, int uniform_buffer, GLfloat xstart, GLfloat ystart, GLfloat dx, GLfloat dy, CursorRenderInfo *cursor, bool inverted, OSWindow *os_window) { +cell_update_uniform_block(ssize_t vao_idx, Screen *screen, int uniform_buffer, GLfloat xstart, GLfloat ystart, GLfloat dx, GLfloat dy, CursorRenderInfo *cursor, bool inverted, GLfloat visual_bell_intensity, OSWindow *os_window) { struct CellRenderData { - GLfloat xstart, ystart, dx, dy, sprite_dx, sprite_dy, background_opacity, cursor_text_uses_bg; + GLfloat xstart, ystart, dx, dy, sprite_dx, sprite_dy, background_opacity, cursor_text_uses_bg, visual_bell_intensity; GLuint default_fg, default_bg, highlight_fg, highlight_bg, cursor_color, cursor_text_color, url_color, url_style, inverted; @@ -295,6 +295,7 @@ cell_update_uniform_block(ssize_t vao_idx, Screen *screen, int uniform_buffer, G rd->sprite_dx = 1.0f / (float)x; rd->sprite_dy = 1.0f / (float)y; rd->inverted = inverted ? 1 : 0; rd->background_opacity = os_window->is_semi_transparent ? os_window->background_opacity : 1.0f; + rd->visual_bell_intensity = visual_bell_intensity; #define COLOR(name) colorprofile_to_color(screen->color_profile, screen->color_profile->overridden.name, screen->color_profile->configured.name) rd->default_fg = COLOR(default_fg); rd->default_bg = COLOR(default_bg); rd->highlight_fg = COLOR(highlight_fg); rd->highlight_bg = COLOR(highlight_bg); @@ -617,8 +618,9 @@ void draw_cells(ssize_t vao_idx, ssize_t gvao_idx, GLfloat xstart, GLfloat ystart, GLfloat dx, GLfloat dy, Screen *screen, OSWindow *os_window, bool is_active_window, bool can_be_focused) { CELL_BUFFERS; bool inverted = screen_invert_colors(screen); + GLfloat intensity = (GLfloat)screen_visual_bell_intensity(screen); - cell_update_uniform_block(vao_idx, screen, uniform_buffer, xstart, ystart, dx, dy, &screen->cursor_render_info, inverted, os_window); + cell_update_uniform_block(vao_idx, screen, uniform_buffer, xstart, ystart, dx, dy, &screen->cursor_render_info, inverted, intensity, os_window); bind_vao_uniform_buffer(vao_idx, uniform_buffer, cell_program_layouts[CELL_PROGRAM].render_data.index); bind_vertex_array(vao_idx);