mirror of
https://github.com/kovidgoyal/kitty.git
synced 2026-10-20 12:19:36 +00:00
Custom shaders: Support tinting complete inactive windows
This commit is contained in:
parent
a54b409785
commit
cf33820973
6 changed files with 80 additions and 2 deletions
|
|
@ -204,6 +204,9 @@ Detailed list of changes
|
|||
|
||||
- Support for :doc:`/custom-shaders` for adding various graphical effects (:iss:`10344`)
|
||||
|
||||
- Custom shaders: Allow tinting inactive windows toward a configurable color,
|
||||
preserving the tab bar and active window padding.
|
||||
|
||||
- Various throughput performance improvements for a 15-35% real world improvement depending on workload
|
||||
|
||||
- Add :opt:`window_border_radius` for rounded window borders (:pull:`10421`)
|
||||
|
|
|
|||
|
|
@ -79,6 +79,29 @@ mouse shader. In the first group we have the crt shader and its color has been
|
|||
customised. The second group defines the spotlight shader and specifies exactly
|
||||
when the spotlight animation should start and stop.
|
||||
|
||||
For example, to blend inactive windows toward gray instead of black, save the
|
||||
following as :file:`shaders/dim-gray.pipeline` in your kitty config directory and
|
||||
set ``custom_shaders dim-gray`` and ``inactive_text_alpha 1`` in :file:`kitty.conf`::
|
||||
|
||||
startgroup
|
||||
var float HIGHLIGHT_INTENSITY = 0
|
||||
var float BORDER_WIDTH = 0
|
||||
var float INACTIVE_DIM = 0.74
|
||||
var float3 INACTIVE_DIM_COLOR = float3(0.2158605)
|
||||
var bool DIM_CENTRAL_AREA_ONLY = true
|
||||
var bool INCLUDE_WINDOW_PADDING = true
|
||||
shaders focus-highlight
|
||||
endgroup
|
||||
|
||||
This uses the same shader as ``dim-inactive-windows``. ``INACTIVE_DIM`` is the
|
||||
fraction of the original color retained: ``0.74`` blends in 26% of the target
|
||||
color. ``INACTIVE_DIM_COLOR`` is in linear RGB; ``0.2158605`` corresponds to
|
||||
sRGB ``#808080``. The default target is black, preserving the existing dimming
|
||||
effect. The two optional flags preserve the tab bar and include the active
|
||||
window's padding in its unchanged area. Explicit cell backgrounds and images
|
||||
are blended together with text, while transparency and colors reported to
|
||||
terminal applications are preserved.
|
||||
|
||||
|
||||
Anatomy of a custom shader
|
||||
----------------------------
|
||||
|
|
|
|||
|
|
@ -2433,6 +2433,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 active_window_padding[4];
|
||||
float bell_window_geometry[4];
|
||||
float central_area[4];
|
||||
float cursor_trail_corners_x[4];
|
||||
|
|
@ -2475,6 +2476,13 @@ run_custom_end_shader(OSWindow *os_window, float sx, float sy, monotonic_t now)
|
|||
if (t->num_windows) {
|
||||
Window *w = t->windows + t->active_window;
|
||||
active_win_geom = w->render_data.geometry;
|
||||
if (os_window->viewport_width && os_window->viewport_height) {
|
||||
const float width = (float)os_window->viewport_width, height = (float)os_window->viewport_height;
|
||||
d->active_window_padding[0] = (float)(w->padding.left + w->size_mismatch_padding.left) / width;
|
||||
d->active_window_padding[1] = (float)(w->padding.bottom + w->size_mismatch_padding.bottom) / height;
|
||||
d->active_window_padding[2] = (float)(w->padding.right + w->size_mismatch_padding.right) / width;
|
||||
d->active_window_padding[3] = (float)(w->padding.top + w->size_mismatch_padding.top) / height;
|
||||
}
|
||||
Screen *s = w->render_data.screen;
|
||||
if (s) {
|
||||
active_bg = colorprofile_to_color(s->color_profile, s->color_profile->overridden.default_bg, s->color_profile->configured.default_bg).rgb;
|
||||
|
|
|
|||
|
|
@ -16,14 +16,28 @@ static const float HIGHLIGHT_INTENSITY = 0.30;
|
|||
static const float BORDER_WIDTH = 0.04;
|
||||
// Peak additive brightness multiplier at the window border edge.
|
||||
static const float BORDER_GLOW = 0.55;
|
||||
// Dim factor applied to pixels outside the active window (1.0 = unchanged, 0.0 = black).
|
||||
// Fraction of the original color retained outside the active window (1.0 = unchanged, 0.0 = blend target).
|
||||
static const float INACTIVE_DIM = 0.3;
|
||||
// Blend target in linear RGB; black preserves the original dimming behavior.
|
||||
static const float3 INACTIVE_DIM_COLOR = float3(0.0);
|
||||
// Keep the tab bar outside the effect when requested by a pipeline.
|
||||
static const bool DIM_CENTRAL_AREA_ONLY = false;
|
||||
// Include the active window's padding in its unchanged/highlighted area.
|
||||
static const bool INCLUDE_WINDOW_PADDING = false;
|
||||
|
||||
public float4
|
||||
fragment_main(float4 color, KittyTextures t, KittyCustomShaderData d) {
|
||||
if (DIM_CENTRAL_AREA_ONLY) {
|
||||
float4 area = d.central_area;
|
||||
if (any(t.pos < area.xy) || any(t.pos > area.xy + area.zw)) return color;
|
||||
}
|
||||
float4 g = d.active_window_geometry;
|
||||
// Pass through unchanged if no active window geometry is known.
|
||||
if (g.z <= 0.0 || g.w <= 0.0) return color;
|
||||
if (INCLUDE_WINDOW_PADDING) {
|
||||
g.xy -= d.active_window_padding.xy;
|
||||
g.zw += d.active_window_padding.xy + d.active_window_padding.zw;
|
||||
}
|
||||
|
||||
float2 uv = t.pos;
|
||||
float2 winMin = g.xy;
|
||||
|
|
@ -48,5 +62,5 @@ fragment_main(float4 color, KittyTextures t, KittyCustomShaderData d) {
|
|||
}
|
||||
// Slightly dim inactive areas to draw the eye to the focused window.
|
||||
float dim = lerp(1.0, INACTIVE_DIM, strength);
|
||||
return float4(color.rgb * dim, color.a);
|
||||
return float4(lerp(INACTIVE_DIM_COLOR, color.rgb, dim), color.a);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,6 +22,9 @@ 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;
|
||||
// Effective padding of the active window, including cell-size compensation.
|
||||
// .xy = left/bottom, .zw = right/top, in viewport UV units.
|
||||
public float4 active_window_padding;
|
||||
// Geometry of the most recently belled window in UV co-ordinates (origin bottom-left).
|
||||
// .xy = lower-left corner of the window, .zw = width and height.
|
||||
// If the belled window is not currently visible in the active tab/layout, equals central_area.
|
||||
|
|
|
|||
|
|
@ -33,6 +33,33 @@ _SUPPORT_SHADER_NAMES = frozenset(('types', 'pipeline'))
|
|||
|
||||
|
||||
class TestSlang(BaseTest):
|
||||
def test_inactive_window_tint_pipeline(self):
|
||||
if not shutil.which(slangc()[0]):
|
||||
self.skipTest(f'slangc ({slangc()[0]}) not found in PATH')
|
||||
|
||||
pipeline = parse_pipeline_definition(
|
||||
"""
|
||||
startgroup
|
||||
var float HIGHLIGHT_INTENSITY = 0
|
||||
var float BORDER_WIDTH = 0
|
||||
var float INACTIVE_DIM = 0.74
|
||||
var float3 INACTIVE_DIM_COLOR = float3(0.2158605)
|
||||
var bool DIM_CENTRAL_AREA_ONLY = true
|
||||
var bool INCLUDE_WINDOW_PADDING = true
|
||||
shaders focus-highlight
|
||||
endgroup
|
||||
""".splitlines(),
|
||||
'dim-gray',
|
||||
)
|
||||
with tempfile.TemporaryDirectory() as cache_dir:
|
||||
clear_caches()
|
||||
try:
|
||||
vertex, fragment, _ = build_custom_shader_pipeline_glsl(pipeline, cache_dir=cache_dir)
|
||||
finally:
|
||||
clear_caches()
|
||||
self.assertTrue(vertex)
|
||||
self.assertTrue(fragment)
|
||||
|
||||
def test_slang_parser(self):
|
||||
def check(src: str, expected: SlangFile) -> None:
|
||||
actual = parse_slang_text(src)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue