mirror of
https://github.com/kovidgoyal/kitty.git
synced 2026-10-21 04:32:05 +00:00
Custom shaders: Include border and margin in active_window_padding
active_window_padding only counted padding and cell-size compensation, so the space a layout reserves for the window border (and margin) was treated as outside the active window. With dim-inactive-windows this left a thin dimmed strip around the active window and dimmed the active border color. Use render_data.geometry.spaces, which is exactly what the layout reserved around the window. This respects layouts that do not reserve border space in minimal border mode, so the active area never extends into a neighboring window. Add a test that the reserved boxes of visible windows never overlap and stay within the central area.
This commit is contained in:
parent
b2f3c15aad
commit
8e80e96c64
6 changed files with 45 additions and 9 deletions
|
|
@ -209,7 +209,7 @@ Detailed list of changes
|
|||
color profile
|
||||
|
||||
- Custom shaders: The builtin :code:`dim-inactive-windows` shader no longer dims
|
||||
the tab bar and the padding around the active window (:iss:`10524`)
|
||||
the tab bar and the padding, border and margin around the active window (:iss:`10524`)
|
||||
|
||||
0.49.1 [2026-09-24]
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
|
|
|||
|
|
@ -99,7 +99,7 @@ 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 title bar and padding in its unchanged area. Explicit cell backgrounds
|
||||
window's title bar, margin, border and 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. ``animation_step 0`` makes this static
|
||||
effect redraw only when content or shader events change.
|
||||
|
|
|
|||
|
|
@ -2546,10 +2546,14 @@ run_custom_end_shader(OSWindow *os_window, float sx, float sy, monotonic_t now)
|
|||
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;
|
||||
// spaces is all the space the layout reserved around the window:
|
||||
// margin, border (only if the layout reserves it), padding and
|
||||
// cell-size compensation.
|
||||
const WindowGeometry *sg = &w->render_data.geometry;
|
||||
d->active_window_padding[0] = (float)sg->spaces.left / width;
|
||||
d->active_window_padding[1] = (float)sg->spaces.bottom / height;
|
||||
d->active_window_padding[2] = (float)sg->spaces.right / width;
|
||||
d->active_window_padding[3] = (float)sg->spaces.top / height;
|
||||
// The content geometry excludes the title bar. Include it before
|
||||
// extending to the outer padding, so the effect boundary cannot
|
||||
// cut through a title bar at either edge of the window.
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ static const float INACTIVE_DIM = 0.3;
|
|||
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 title bar and padding in its unchanged/highlighted area.
|
||||
// Include the active window's title bar, margin, border and padding in its unchanged/highlighted area.
|
||||
static const bool INCLUDE_WINDOW_PADDING = false;
|
||||
|
||||
public float4
|
||||
|
|
|
|||
|
|
@ -22,8 +22,8 @@ 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;
|
||||
// Extents beyond the active content, including a visible title bar, padding
|
||||
// and cell-size compensation.
|
||||
// Extents beyond the active content, including a visible title bar, margin,
|
||||
// border, padding and 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).
|
||||
|
|
|
|||
|
|
@ -1071,6 +1071,38 @@ class TestSplitBorderResize(BaseSplitGeometryTest):
|
|||
self.assertIsNone(data.vertical_id)
|
||||
|
||||
|
||||
class TestReservedSpaces(BaseSplitGeometryTest):
|
||||
def test_reserved_spaces_do_not_overlap(self):
|
||||
# Custom shaders treat the space a layout reserves around the active
|
||||
# window (WindowGeometry.spaces) as part of it, so the reserved boxes
|
||||
# of visible windows must fit in the central area without overlapping.
|
||||
central = Region((19, 47, 1518, 1146, 1500, 1100))
|
||||
for cls in (Tall, Grid, Horizontal, Stack, Splits):
|
||||
for minimal in (True, False):
|
||||
for num in (1, 2, 3, 5):
|
||||
layout = create_layout(cls)
|
||||
windows = create_windows(layout, num=num)
|
||||
self.stub_dimensions(layout, central, minimal)
|
||||
layout(windows)
|
||||
boxes = []
|
||||
for w in windows:
|
||||
if not w.is_visible_in_layout:
|
||||
continue
|
||||
g = w.geometry
|
||||
boxes.append((g.left - g.spaces.left, g.top - g.spaces.top, g.right + g.spaces.right, g.bottom + g.spaces.bottom))
|
||||
with self.subTest(layout=cls.name, minimal=minimal, num=num):
|
||||
self.assertTrue(boxes)
|
||||
for left, top, right, bottom in boxes:
|
||||
self.assertGreaterEqual(left, central.left)
|
||||
self.assertGreaterEqual(top, central.top)
|
||||
self.assertLessEqual(right, central.left + central.width)
|
||||
self.assertLessEqual(bottom, central.top + central.height)
|
||||
for i, a in enumerate(boxes):
|
||||
for b in boxes[i + 1 :]:
|
||||
overlaps = a[0] < b[2] and b[0] < a[2] and a[1] < b[3] and b[1] < a[3]
|
||||
self.assertFalse(overlaps, f'{a} overlaps {b}')
|
||||
|
||||
|
||||
class TestSplitDragGeometry(BaseSplitGeometryTest):
|
||||
def make_layout(self, shape, minimal=True, num=4):
|
||||
from types import SimpleNamespace
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue