diff options
| author | Gabriel Schneider <[email protected]> | 2026-09-16 14:46:16 -0300 |
|---|---|---|
| committer | Gabriel Schneider <[email protected]> | 2026-10-01 00:12:14 -0300 |
| commit | 717afaf3177a2e0925b18ae3445119efe808b129 (patch) | |
| tree | 45a2196711de78d8d1e2db6cb5e5c51271676c2f /src/config.zig | |
| parent | 7cbd44dd1cfe97126e7fc996214e458525d2980c (diff) | |
| download | pardes-717afaf3177a2e0925b18ae3445119efe808b129.tar.gz pardes-717afaf3177a2e0925b18ae3445119efe808b129.zip | |
Add macOS backdrop blur and preserve PDF ink opacity
Diffstat (limited to 'src/config.zig')
| -rw-r--r-- | src/config.zig | 49 |
1 files changed, 45 insertions, 4 deletions
diff --git a/src/config.zig b/src/config.zig index f91d95c6..440549b3 100644 --- a/src/config.zig +++ b/src/config.zig @@ -102,6 +102,7 @@ pub const leader_path = paths: { } if (pardes.platform == .gui) table.set(.Pet, null); if (builtins.capabilities.window_opacity) table.set(.WindowOpacity, null); + if (builtins.capabilities.window_blur) table.set(.WindowBlur, null); if (builtins.capabilities.panel_transitions) { table.set(.PanelSlide, "as"); table.set(.PanelZoom, "az"); @@ -540,6 +541,7 @@ pub const Runtime = struct { column_tags: bool = true, syntax_bold: bool = false, window_opacity: u8 = 100, + window_blur: u8 = 0, window_opacity_pending: bool = true, pet: enum { off, cat, frog } = .off, @@ -630,6 +632,7 @@ pub const Runtime = struct { scene_shaders: bool, tagline_font_size: bool, window_opacity: bool = false, + window_blur: bool = false, }; pub const Capability = std.meta.FieldEnum(Capabilities); @@ -644,6 +647,7 @@ pub const Runtime = struct { font, tagline_size, window_opacity, + window_blur, transition: layout.Transition, scene: Scene, }; @@ -655,7 +659,7 @@ pub const Runtime = struct { pub fn takesArg(setting: Setting) bool { return switch (setting.action) { - .shell, .theme, .font, .tagline_size, .window_opacity => true, + .shell, .theme, .font, .tagline_size, .window_opacity, .window_blur => true, else => false, }; } @@ -683,6 +687,7 @@ pub const Runtime = struct { .{ .word = "Font", .action = .font, .availability = .font_picker }, .{ .word = "TaglineSize", .action = .tagline_size, .availability = .font_picker }, .{ .word = "WindowOpacity", .action = .window_opacity, .availability = .window_opacity }, + .{ .word = "WindowBlur", .action = .window_blur, .availability = .window_blur }, .{ .word = "PanelSlide", .action = .{ .transition = .slide }, .availability = .panel_transitions }, .{ .word = "PanelZoom", .action = .{ .transition = .zoom }, .availability = .panel_transitions }, .{ .word = "PanelDissolve", .action = .{ .transition = .dissolve }, .availability = .panel_transitions }, @@ -726,6 +731,8 @@ pub const Runtime = struct { @compileError("native font settings must use the font-picker capability"), .window_opacity => if (setting.availability != .window_opacity) @compileError("window opacity must use the window-opacity capability"), + .window_blur => if (setting.availability != .window_blur) + @compileError("window blur must use the window-blur capability"), .transition => if (setting.availability != .panel_transitions) @compileError("panel effects must use the panel-transition capability"), .scene => if (setting.availability != .scene_shaders) @@ -737,8 +744,8 @@ pub const Runtime = struct { for (std.enums.values(Toggle)) |field| if (actionCount(.{ .toggle = field }) != 1) @compileError("runtime toggle must occur exactly once: " ++ @tagName(field)); if (actionCount(.shell) != 1 or actionCount(.theme) != 1 or actionCount(.font) != 1 or - actionCount(.tagline_size) != 1 or actionCount(.window_opacity) != 1) - @compileError("Shell, Theme, Font, TaglineSize, and WindowOpacity actions must each occur exactly once"); + actionCount(.tagline_size) != 1 or actionCount(.window_opacity) != 1 or actionCount(.window_blur) != 1) + @compileError("Shell, Theme, Font, TaglineSize, WindowOpacity, and WindowBlur actions must each occur exactly once"); for (std.enums.values(layout.Transition)) |effect| { const expected: comptime_int = @intFromBool(effect != .off); if (actionCount(.{ .transition = effect }) != expected) @@ -783,6 +790,13 @@ pub const Runtime = struct { state.window_opacity = percent; state.window_opacity_pending = true; }, + .window_blur => { + const text = std.mem.trim(u8, argument orelse return false, " \t\r\n"); + for (text) |byte| if (!std.ascii.isDigit(byte)) return false; + const percent = std.fmt.parseInt(u8, text, 10) catch return false; + if (percent > 100) return false; + state.window_blur = percent; + }, .transition => |effect| state.toggleTransition(effect), .scene => |effect| switch (effect) { inline else => |field| { @@ -849,6 +863,12 @@ pub const Runtime = struct { else try out.print("{s}: unsupported\n", .{setting.word}); }, + .window_blur => { + if (setting.enabled(context.capabilities)) + try out.print("{s}: {d}%\n", .{ setting.word, state.window_blur }) + else + try out.print("{s}: unsupported\n", .{setting.word}); + }, .shell => { const chosen = state.shell.requested.get(); try out.print( @@ -947,7 +967,7 @@ pub const Runtime = struct { for (settings[i + 1 ..]) |later| try std.testing.expect(!std.mem.eql(u8, setting.word, later.word)); try std.testing.expectEqual(switch (setting.action) { - .shell, .theme, .font, .tagline_size, .window_opacity => true, + .shell, .theme, .font, .tagline_size, .window_opacity, .window_blur => true, else => false, }, setting.takesArg()); } @@ -1011,6 +1031,22 @@ pub const Runtime = struct { try std.testing.expect(state.window_opacity_pending); } + test "window blur defaults off and validates without changing opacity" { + const setting = find("WindowBlur").?; + var state: Runtime = .{}; + try std.testing.expectEqual(@as(u8, 0), state.window_blur); + try std.testing.expectEqual(Capability.window_blur, setting.availability.?); + for ([_][]const u8{ "0", " 40\n", "100" }, [_]u8{ 0, 40, 100 }) |argument, expected| { + try std.testing.expect(apply(&state, setting, argument)); + try std.testing.expectEqual(expected, state.window_blur); + try std.testing.expectEqual(@as(u8, 100), state.window_opacity); + } + for ([_]?[]const u8{ null, "", " \t\n", "101", "-1", "+40", "40%", "0.5", "40 20", "4_0", "0x28", "999999999999999" }) |argument| { + try std.testing.expect(!apply(&state, setting, argument)); + try std.testing.expectEqual(@as(u8, 100), state.window_blur); + } + } + test "font request tuple rejects atomically" { var state: Runtime = .{}; try std.testing.expect(requestFont(&state, "/fonts/old.ttf", "Old", 1200)); @@ -1052,6 +1088,7 @@ pub const Runtime = struct { .scene_shaders = true, .tagline_font_size = true, .window_opacity = true, + .window_blur = true, }, .state = &state, }; @@ -1065,6 +1102,7 @@ pub const Runtime = struct { .shell => "fish", .tagline_size => "73", .window_opacity => "85", + .window_blur => "40", else => null, }; try std.testing.expect(apply(&state, setting, argument)); @@ -1086,6 +1124,7 @@ pub const Runtime = struct { .shell => "Shell requested (new panes): fish\n", .tagline_size => "TaglineSize: 73%\n", .window_opacity => "WindowOpacity: 85% (pending)\n", + .window_blur => "WindowBlur: 40%\n", .transition => |transition| switch (transition) { .off => unreachable, .slide => "Panel transition: PanelSlide\n", @@ -1160,6 +1199,8 @@ pub const Runtime = struct { const defaults_report = storage[0..out.end]; try std.testing.expect(std.mem.indexOf(u8, defaults_report, "WindowOpacity: unsupported\n") != null); try std.testing.expect(!find("WindowOpacity").?.enabled(defaults_context.capabilities)); + try std.testing.expect(std.mem.indexOf(u8, defaults_report, "WindowBlur: unsupported\n") != null); + try std.testing.expect(!find("WindowBlur").?.enabled(defaults_context.capabilities)); try std.testing.expect(find("WindowOpacity").?.enabled(context.capabilities)); try std.testing.expect(std.mem.indexOf(u8, defaults_report, "Shell requested (new panes): /bin/sh (default)\n") != null); try std.testing.expect(std.mem.indexOf(u8, defaults_report, "Shell effective (last spawn): (none)\n") != null); |
