From deeb8ac54f71d4322a778336db9a7aec411c23ce Mon Sep 17 00:00:00 2001 From: Gabriel Schneider Date: Mon, 28 Sep 2026 16:44:51 -0300 Subject: G1: Lift, soft elevation shadows (off by default) `Lift` (a GUI toggle, capability lift) lifts the focused pane on a critically damped spring (animation.Spring: closed form, about 240 ms to settle, velocity kept across retargets, settled = no frames) and floats notices. The core puts the lift on the regions (Region.lift, on the wire); the GUI casts from it: a soft shadow is decor, an erf rectangle on one quad grown by 3 sigma (decor.frag, flag 0x10000000), in the quad's own space so a track's transform carries it; darken-only, the caster's rect left alone, alpha pre-warped for linear light and IGN-dithered. Cast last in its group, so a neighbour's rails and rules darken with its text; a notice's before its rule. Strength is capped per theme so text over the darkest shadow keeps min(its contrast, 4.5) (test over the native themes). Opt-in until the focus lift/dim default is decided. Feel review material: docs/effects.md. Test-mode PARDES_TEST_SERIES keeps every captured frame. Shared files touched: pardes.zig (two fields, one nextWake line), detached/wire.zig (lift on the region), config.zig, builtins.zig (capability), gui.zig. Not touched: Messages.zig, mouse.zig, tty, host_io. --- src/config.zig | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) (limited to 'src/config.zig') diff --git a/src/config.zig b/src/config.zig index 186b29a1..0ed8726a 100644 --- a/src/config.zig +++ b/src/config.zig @@ -115,6 +115,7 @@ pub const leader_path = paths: { if (builtins.capabilities.window_opacity) table.set(.WindowOpacity, null); if (builtins.capabilities.window_blur) table.set(.WindowBlur, null); if (builtins.capabilities.ligatures) table.set(.Ligatures, null); + if (builtins.capabilities.lift) table.set(.Lift, null); if (builtins.capabilities.panel_transitions) { table.set(.PanelSlide, "as"); table.set(.PanelZoom, "az"); @@ -618,6 +619,10 @@ pub const Runtime = struct { /// A font's programming ligatures (`->`, `!=`) draw across their cells. /// Only a shell that shapes text has the setting (`Capabilities.ligatures`). ligatures: bool = true, + /// The focused pane and the notices stand off the page on soft shadows + /// (G1, docs/render-pipeline.md ยง9.1). Opt-in until the focus lift's + /// default is decided. Only a pixel shell draws it (`Capabilities.lift`). + lift: bool = false, /// Builtins announce themselves on the message row. verbose: bool = true, /// A message falls into its row and dissolves out of it. @@ -808,6 +813,8 @@ pub const Runtime = struct { window_blur: bool = false, /// The shell shapes text, so it can draw ligatures and stop drawing them. ligatures: bool = false, + /// The shell draws soft shadows under what stands off the page. + lift: bool = false, }; pub const Capability = std.meta.FieldEnum(Capabilities); @@ -815,7 +822,7 @@ pub const Runtime = struct { /// The message timings a setting word sets, each in milliseconds. pub const MessageTime = enum { linger, fall, dissolve }; - pub const Toggle = enum { colors, wrap, tree_context_tag_style, tag_bottom, debug, focus_tint, column_tags, syntax_bold, verbose, message_animation, ligatures }; + pub const Toggle = enum { colors, wrap, tree_context_tag_style, tag_bottom, debug, focus_tint, column_tags, syntax_bold, verbose, message_animation, ligatures, lift }; /// The bundled post pass, a Shadertoy file in shaders/post/. pub const Scene = enum { crt }; @@ -863,6 +870,7 @@ pub const Runtime = struct { .{ .word = "Verbose", .action = .{ .toggle = .verbose } }, .{ .word = "MessageAnimation", .action = .{ .toggle = .message_animation } }, .{ .word = "Ligatures", .action = .{ .toggle = .ligatures }, .availability = .ligatures }, + .{ .word = "Lift", .action = .{ .toggle = .lift }, .availability = .lift }, .{ .word = "MessageLinger", .action = .{ .message_ms = .linger } }, .{ .word = "MessageFall", .action = .{ .message_ms = .fall } }, .{ .word = "MessageDissolve", .action = .{ .message_ms = .dissolve } }, @@ -924,9 +932,9 @@ pub const Runtime = struct { @compileError("scene effects must use the scene-shader capability"), // A toggle is plain state any shell can hold, except one for // what only some shells draw: that one exists where they do. - .toggle => |field| if (field == .ligatures) { - if (setting.availability != .ligatures) - @compileError("the ligatures toggle must use the ligatures capability"); + .toggle => |field| if (field == .ligatures or field == .lift) { + if (setting.availability == null or !std.mem.eql(u8, @tagName(setting.availability.?), @tagName(field))) + @compileError("a pixel shell's toggle must use its own capability: " ++ @tagName(field)); } else if (setting.availability != null) @compileError("unconditional toggles cannot carry a backend capability"), else => if (setting.availability != null) @@ -1447,6 +1455,7 @@ pub const Runtime = struct { .window_opacity = true, .window_blur = true, .ligatures = true, + .lift = true, }, .state = &state, }; @@ -1485,6 +1494,7 @@ pub const Runtime = struct { .verbose => "Verbose off\n", .message_animation => "MessageAnimation off\n", .ligatures => "Ligatures off\n", + .lift => "Lift on\n", }, .shell => "Shell requested (new panes) fish\n", .tagline_size => "TaglineSize 73\n", -- cgit v1.3