summaryrefslogtreecommitdiff
path: root/src/config.zig
diff options
context:
space:
mode:
authorGabriel Schneider <[email protected]>2026-09-16 14:46:16 -0300
committerGabriel Schneider <[email protected]>2026-10-01 00:12:14 -0300
commit717afaf3177a2e0925b18ae3445119efe808b129 (patch)
tree45a2196711de78d8d1e2db6cb5e5c51271676c2f /src/config.zig
parent7cbd44dd1cfe97126e7fc996214e458525d2980c (diff)
downloadpardes-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.zig49
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);