mirror of
https://github.com/kovidgoyal/kitty.git
synced 2026-10-24 22:28:29 +00:00
A tab change reveal animation
This commit is contained in:
parent
e796c60d3e
commit
40b646a54a
4 changed files with 120 additions and 0 deletions
|
|
@ -2359,6 +2359,7 @@ run_custom_end_shader(OSWindow *os_window, float sx, float sy, monotonic_t now)
|
|||
float mouse_pos[4];
|
||||
float mouse_button_pressed[4];
|
||||
float active_window_geometry[4];
|
||||
float central_area[4];
|
||||
float cursor_trail_corners_x[4];
|
||||
float cursor_trail_corners_y[4];
|
||||
float cursor_trail_edge[4];
|
||||
|
|
@ -2474,6 +2475,17 @@ run_custom_end_shader(OSWindow *os_window, float sx, float sy, monotonic_t now)
|
|||
d->active_window_geometry[2] = (float)(active_win_geom.right - active_win_geom.left) / vpw;
|
||||
d->active_window_geometry[3] = (float)(active_win_geom.bottom - active_win_geom.top) / vph;
|
||||
}
|
||||
if (vpw > 0 && vph > 0) {
|
||||
Region central_rgn = {0}, tab_bar_rgn = {0};
|
||||
os_window_regions(os_window, ¢ral_rgn, &tab_bar_rgn);
|
||||
d->central_area[0] = (float)central_rgn.left / vpw;
|
||||
d->central_area[1] = 1.f - (float)central_rgn.bottom / vph;
|
||||
d->central_area[2] = (float)(central_rgn.right - central_rgn.left) / vpw;
|
||||
d->central_area[3] = (float)(central_rgn.bottom - central_rgn.top) / vph;
|
||||
} else {
|
||||
d->central_area[2] = 1.f;
|
||||
d->central_area[3] = 1.f;
|
||||
}
|
||||
unmap_vao_buffer(custom_end_vao_idx, 0);
|
||||
bind_vao_uniform_buffer(custom_end_vao_idx, 0, CUSTOM_END_DATA_BINDING_POINT);
|
||||
|
||||
|
|
|
|||
7
kitty/shaders/custom/tab-focus.pipeline
Normal file
7
kitty/shaders/custom/tab-focus.pipeline
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
startgroup
|
||||
animation_start tab-change
|
||||
animation_stop 600
|
||||
animation_curve ease-out
|
||||
animation_step 16
|
||||
shaders tab-focus
|
||||
endgroup
|
||||
96
kitty/shaders/custom/tab-focus.slang
Normal file
96
kitty/shaders/custom/tab-focus.slang
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
#language slang 2026
|
||||
// Copyright (C) 2026 Kovid Goyal <kovid at kovidgoyal.net>
|
||||
// Distributed under terms of the GPLv3 license.
|
||||
//
|
||||
// Tab-change reveal shader
|
||||
// Plays a brief reveal animation whenever the active tab changes.
|
||||
// The reveal direction for wipe-based modes is derived from d.central_area:
|
||||
// the wipe starts at whichever edge of the content area is furthest from the
|
||||
// viewport boundary — that edge is where the tab bar sits.
|
||||
//
|
||||
// ANIMATION_TYPE selects the effect:
|
||||
// 0 = FADE — uniform brightness fade-in over the whole screen
|
||||
// 1 = WIPE — a single swept edge travelling away from the tab bar
|
||||
// 2 = BLINDS — sequential strip reveals sweeping away from the tab bar
|
||||
// 3 = IRIS — circular iris expanding from the centre of the content area
|
||||
|
||||
import kitty_custom_shader_types;
|
||||
|
||||
// 0=FADE, 1=WIPE, 2=BLINDS, 3=IRIS
|
||||
extern static const int ANIMATION_TYPE = 1;
|
||||
|
||||
// Number of strips for ANIMATION_TYPE == 2 (BLINDS).
|
||||
extern static const int NUM_BLINDS = 8;
|
||||
|
||||
// Soft-edge width in UV units used by WIPE and IRIS.
|
||||
extern static const float EDGE_SOFTNESS = 0.04;
|
||||
|
||||
// Returns a value in [0, 1] for this pixel: 0 at the tab-bar edge of the
|
||||
// content area, 1 at the opposite edge. The wipe sweeps from 0 toward 1.
|
||||
float wipe_pixel_pos(float2 uv, float4 ca) {
|
||||
float gap_left = ca.x;
|
||||
float gap_right = 1.0 - (ca.x + ca.z);
|
||||
float gap_bottom = ca.y;
|
||||
float gap_top = 1.0 - (ca.y + ca.w);
|
||||
float max_gap = max(max(gap_left, gap_right), max(gap_bottom, gap_top));
|
||||
|
||||
float pos;
|
||||
if (max_gap == gap_top) {
|
||||
// Tab bar at top — sweep from top-of-content downward
|
||||
pos = (ca.y + ca.w - uv.y) / ca.w;
|
||||
} else if (max_gap == gap_bottom) {
|
||||
// Tab bar at bottom — sweep from bottom-of-content upward
|
||||
pos = (uv.y - ca.y) / ca.w;
|
||||
} else if (max_gap == gap_left) {
|
||||
// Tab bar at left — sweep from left-of-content rightward
|
||||
pos = (uv.x - ca.x) / ca.z;
|
||||
} else {
|
||||
// Tab bar at right — sweep from right-of-content leftward
|
||||
pos = (ca.x + ca.z - uv.x) / ca.z;
|
||||
}
|
||||
return clamp(pos, 0.0, 1.0);
|
||||
}
|
||||
|
||||
public float4 fragment_main(
|
||||
float4 color,
|
||||
KittyTextures t,
|
||||
KittyCustomShaderData d,
|
||||
float4 viewport,
|
||||
float animation_progress
|
||||
) {
|
||||
float4 ca = d.central_area;
|
||||
if (ca.z <= 0.0 || ca.w <= 0.0) return color;
|
||||
|
||||
float p = animation_progress;
|
||||
float brightness;
|
||||
|
||||
if (ANIMATION_TYPE == 0) {
|
||||
// FADE: uniform ramp over the whole frame
|
||||
brightness = p;
|
||||
} else if (ANIMATION_TYPE == 1) {
|
||||
// WIPE: single swept edge with soft falloff
|
||||
float pixel_pos = wipe_pixel_pos(t.pos, ca);
|
||||
// 1.0 where revealed (pixel_pos < p), 0.0 where not yet reached
|
||||
brightness = 1.0 - smoothstep(p - EDGE_SOFTNESS, p + EDGE_SOFTNESS, pixel_pos);
|
||||
} else if (ANIMATION_TYPE == 2) {
|
||||
// BLINDS: strips opening in sequence from the tab-bar side
|
||||
float pixel_pos = wipe_pixel_pos(t.pos, ca);
|
||||
float inv_n = 1.0 / float(NUM_BLINDS);
|
||||
float strip_idx = floor(pixel_pos * float(NUM_BLINDS));
|
||||
float strip_start = strip_idx * inv_n;
|
||||
// Progress local to this strip: 0 when it starts opening, 1 when fully open
|
||||
float strip_p = clamp((p - strip_start) / inv_n, 0.0, 1.0);
|
||||
// Position within the strip (0 at tab-bar side, 1 at far side)
|
||||
float local = fract(pixel_pos * float(NUM_BLINDS));
|
||||
float soft = 0.1;
|
||||
brightness = 1.0 - smoothstep(strip_p - soft, strip_p + soft, local);
|
||||
} else {
|
||||
// IRIS: circular reveal expanding from the centre of the content area
|
||||
float2 ca_center = ca.xy + ca.zw * 0.5;
|
||||
float half_diag = length(ca.zw * 0.5);
|
||||
float dist = length(t.pos - ca_center) / max(half_diag, 0.001);
|
||||
brightness = 1.0 - smoothstep(p - EDGE_SOFTNESS, p + EDGE_SOFTNESS, dist);
|
||||
}
|
||||
|
||||
return float4(color.rgb * brightness, color.a);
|
||||
}
|
||||
|
|
@ -22,6 +22,11 @@ public struct KittyCustomShaderData {
|
|||
// .xy = lower-left corner of the window, .zw = width and height.
|
||||
// All components are zero when no active window was rendered this frame.
|
||||
public float4 active_window_geometry;
|
||||
// Geometry of the central content area of the OS window (the tab area, excluding any tab bar)
|
||||
// in UV co-ordinates (origin bottom-left).
|
||||
// .xy = lower-left corner, .zw = width and height.
|
||||
// Equals the full viewport when no tab bar is visible.
|
||||
public float4 central_area;
|
||||
|
||||
// Cursor trail state (UV coordinates, origin bottom-left, (1,1) top-right).
|
||||
// All fields are zero when the cursor_trail kitty option is disabled or the trail is inactive.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue