mirror of
https://github.com/kovidgoyal/kitty.git
synced 2026-06-25 18:37:50 +00:00
Make visual bell flash much more gentle
Right now visual bell makes background flash sharply with bright white (when configured with darkish color theme). This causes eye strain, especially prominent in unlit environments. This change makes background bounce smoothly between regular bg color and highlight (selection) bg color for the configured visual bell duration. Intensity is animated with cubic easing functions. It currently peaks at 20% of the duration, this is hardcoded. Mark functions computing intensity and easing as inline Do smarter blending of visual bell flash Blend highlight color with pegtop's softlight mode over both background and half as much over foreground. This should help with flash visibility in light themed and inverted colors contexts. Blend flash in BACKGROUND pass also Revert "Do smarter blending of visual bell flash" This reverts commit9a269d55c7. Revert "Blend flash in BACKGROUND pass also" This reverts commit756332cb9d. Revert "Make visual bell flash much more gentle" This reverts commitcbfe5d59ad. Render flash overlay in a separate drawcall Trigger frequent repaints to make for smooth animation Attenuate flash a bit more
This commit is contained in:
parent
477a652b44
commit
aff6fdfa84
4 changed files with 60 additions and 7 deletions
|
|
@ -615,7 +615,7 @@ prepare_to_render_os_window(OSWindow *os_window, monotonic_t now, unsigned int *
|
|||
}
|
||||
|
||||
static void
|
||||
render_os_window(OSWindow *os_window, monotonic_t now, unsigned int active_window_id, color_type active_window_bg, unsigned int num_visible_windows, bool all_windows_have_same_bg) {
|
||||
render_os_window(OSWindow *os_window, unsigned int active_window_id, color_type active_window_bg, unsigned int num_visible_windows, bool all_windows_have_same_bg) {
|
||||
// ensure all pixels are cleared to background color at least once in every buffer
|
||||
if (os_window->clear_count++ < 3) blank_os_window(os_window);
|
||||
Tab *tab = os_window->tabs + os_window->active_tab;
|
||||
|
|
@ -637,8 +637,7 @@ render_os_window(OSWindow *os_window, monotonic_t now, unsigned int active_windo
|
|||
bool is_active_window = i == tab->active_window;
|
||||
draw_cells(WD.vao_idx, WD.gvao_idx, WD.xstart, WD.ystart, WD.dx * x_ratio, WD.dy * y_ratio, WD.screen, os_window, is_active_window, true);
|
||||
if (WD.screen->start_visual_bell_at != 0) {
|
||||
monotonic_t bell_left = OPT(visual_bell_duration) - (now - WD.screen->start_visual_bell_at);
|
||||
set_maximum_wait(bell_left);
|
||||
set_maximum_wait(OPT(repaint_delay));
|
||||
}
|
||||
w->cursor_visible_at_last_render = WD.screen->cursor_render_info.is_visible; w->last_cursor_x = WD.screen->cursor_render_info.x; w->last_cursor_y = WD.screen->cursor_render_info.y; w->last_cursor_shape = WD.screen->cursor_render_info.shape;
|
||||
}
|
||||
|
|
@ -726,7 +725,7 @@ render(monotonic_t now, bool input_read) {
|
|||
if (prepare_to_render_os_window(w, now, &active_window_id, &active_window_bg, &num_visible_windows, &all_windows_have_same_bg, scan_for_animated_images)) needs_render = true;
|
||||
if (w->last_active_window_id != active_window_id || w->last_active_tab != w->active_tab || w->focused_at_last_render != w->is_focused) needs_render = true;
|
||||
if (w->render_calls < 3 && w->bgimage && w->bgimage->texture_id) needs_render = true;
|
||||
if (needs_render) render_os_window(w, now, active_window_id, active_window_bg, num_visible_windows, all_windows_have_same_bg);
|
||||
if (needs_render) render_os_window(w, active_window_id, active_window_bg, num_visible_windows, all_windows_have_same_bg);
|
||||
if (w->is_focused) change_menubar_title(w->window_title);
|
||||
}
|
||||
last_render_at = now;
|
||||
|
|
|
|||
|
|
@ -1512,12 +1512,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;
|
||||
}
|
||||
|
||||
static inline float
|
||||
ease_out_cubic(float phase) {
|
||||
return 1.0f - powf(1.0f - phase, 3.0f);
|
||||
}
|
||||
|
||||
static inline 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;
|
||||
}
|
||||
|
||||
static inline 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
|
||||
|
|
|
|||
|
|
@ -207,6 +207,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);
|
||||
|
|
|
|||
|
|
@ -458,6 +458,23 @@ draw_tint(bool premult, Screen *screen, GLfloat xstart, GLfloat ystart, GLfloat
|
|||
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
|
||||
}
|
||||
|
||||
void
|
||||
draw_visual_bell_flash(GLfloat intensity, GLfloat xstart, GLfloat ystart, GLfloat w, GLfloat h, Screen *screen) {
|
||||
glEnable(GL_BLEND);
|
||||
// BLEND_PREMULT
|
||||
glBlendFuncSeparate(GL_ONE, GL_ONE_MINUS_SRC_ALPHA, GL_ZERO, GL_ONE);
|
||||
bind_program(TINT_PROGRAM);
|
||||
// TODO config option worth?
|
||||
GLfloat attenuation = 0.4f;
|
||||
color_type flash = colorprofile_to_color(screen->color_profile, screen->color_profile->overridden.highlight_bg, screen->color_profile->configured.highlight_bg);
|
||||
#define C(shift) ((((GLfloat)((flash >> shift) & 0xFF)) / 255.0f) * intensity * attenuation)
|
||||
glUniform4f(tint_program_layout.tint_color_location, C(16), C(8), C(0), intensity * attenuation);
|
||||
#undef C
|
||||
glUniform4f(tint_program_layout.edges_location, xstart, ystart - h, xstart + w, ystart);
|
||||
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
|
||||
glDisable(GL_BLEND);
|
||||
}
|
||||
|
||||
static void
|
||||
draw_cells_interleaved(ssize_t vao_idx, ssize_t gvao_idx, Screen *screen, OSWindow *w, GLfloat xstart, GLfloat ystart, GLfloat width, GLfloat height) {
|
||||
glEnable(GL_BLEND);
|
||||
|
|
@ -650,6 +667,11 @@ draw_cells(ssize_t vao_idx, ssize_t gvao_idx, GLfloat xstart, GLfloat ystart, GL
|
|||
vao_idx, gvao_idx, screen, os_window, xstart, ystart, w, h);
|
||||
else draw_cells_simple(vao_idx, gvao_idx, screen);
|
||||
}
|
||||
|
||||
float intensity = screen_visual_bell_intensity(screen);
|
||||
if (intensity > 0.0f) {
|
||||
draw_visual_bell_flash((GLfloat)intensity, xstart, ystart, w, h, screen);
|
||||
}
|
||||
}
|
||||
// }}}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue