From 220da88a9aa89c7dbbe10f5b3d97fc39619fac3e Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Wed, 13 Dec 2023 19:06:25 -0800 Subject: [PATCH] config: make unfocused-split-fill default to bg --- macos/Sources/Ghostty/SurfaceView.swift | 5 +- src/config/Config.zig | 6 +- src/config/c_get.zig | 134 ++++++++++++++++-------- 3 files changed, 98 insertions(+), 47 deletions(-) diff --git a/macos/Sources/Ghostty/SurfaceView.swift b/macos/Sources/Ghostty/SurfaceView.swift index 29f0dcf73..7c72b9237 100644 --- a/macos/Sources/Ghostty/SurfaceView.swift +++ b/macos/Sources/Ghostty/SurfaceView.swift @@ -67,7 +67,10 @@ extension Ghostty { private var unfocusedFill: Color { var rgb: UInt32 = 16777215 // white default let key = "unfocused-split-fill" - _ = ghostty_config_get(ghostty.config, &rgb, key, UInt(key.count)) + if (!ghostty_config_get(ghostty.config, &rgb, key, UInt(key.count))) { + let bg_key = "background" + _ = ghostty_config_get(ghostty.config, &rgb, bg_key, UInt(bg_key.count)); + } let red = Double(rgb & 0xff) let green = Double((rgb >> 8) & 0xff) diff --git a/src/config/Config.zig b/src/config/Config.zig index 1f930ed74..0700bee6a 100644 --- a/src/config/Config.zig +++ b/src/config/Config.zig @@ -312,13 +312,15 @@ palette: Palette = .{}, /// minimum value is 0.15. This value still looks weird but you can at least /// see what's going on. A value outside of the range 0.15 to 1 will be /// clamped to the nearest valid value. -@"unfocused-split-opacity": f64 = 0.85, +@"unfocused-split-opacity": f64 = 0.7, // The color to dim the unfocused split. Unfocused splits are dimmed by // rendering a semi-transparent rectangle over the split. This sets // the color of that rectangle and can be used to carefully control // the dimming effect. -@"unfocused-split-fill": Color = .{ .r = 255, .g = 255, .b = 255 }, +// +// This will default to the background color. +@"unfocused-split-fill": ?Color = null, /// The command to run, usually a shell. If this is not an absolute path, /// it'll be looked up in the PATH. If this is not set, a default will diff --git a/src/config/c_get.zig b/src/config/c_get.zig index 2a1ca95ab..2bc2ae10e 100644 --- a/src/config/c_get.zig +++ b/src/config/c_get.zig @@ -18,54 +18,66 @@ pub fn get(config: *const Config, k: Key, ptr_raw: *anyopaque) bool { switch (k) { inline else => |tag| { const value = fieldByKey(config, tag); - switch (@TypeOf(value)) { - ?[:0]const u8 => { - const ptr: *?[*:0]const u8 = @ptrCast(@alignCast(ptr_raw)); - ptr.* = if (value) |slice| @ptrCast(slice.ptr) else null; - }, - - bool => { - const ptr: *bool = @ptrCast(@alignCast(ptr_raw)); - ptr.* = value; - }, - - u8, u32 => { - const ptr: *c_uint = @ptrCast(@alignCast(ptr_raw)); - ptr.* = @intCast(value); - }, - - f32, f64 => { - const ptr: *f64 = @ptrCast(@alignCast(ptr_raw)); - ptr.* = @floatCast(value); - }, - - else => |T| switch (@typeInfo(T)) { - .Enum => { - const ptr: *[*:0]const u8 = @ptrCast(@alignCast(ptr_raw)); - ptr.* = @tagName(value); - }, - - .Struct => |info| { - // Packed structs that are less than or equal to the - // size of a C int can be passed directly as their - // bit representation. - if (info.layout != .Packed) return false; - const Backing = info.backing_integer orelse return false; - if (@bitSizeOf(Backing) > @bitSizeOf(c_uint)) return false; - - const ptr: *c_uint = @ptrCast(@alignCast(ptr_raw)); - ptr.* = @intCast(@as(Backing, @bitCast(value))); - }, - - else => return false, - }, - } - - return true; + return getValue(ptr_raw, value); }, } } +/// Get the value anytype and put it into the pointer. Returns false if +/// the type is not supported by the C API yet or the value is null. +fn getValue(ptr_raw: *anyopaque, value: anytype) bool { + switch (@TypeOf(value)) { + ?[:0]const u8 => { + const ptr: *?[*:0]const u8 = @ptrCast(@alignCast(ptr_raw)); + ptr.* = if (value) |slice| @ptrCast(slice.ptr) else null; + }, + + bool => { + const ptr: *bool = @ptrCast(@alignCast(ptr_raw)); + ptr.* = value; + }, + + u8, u32 => { + const ptr: *c_uint = @ptrCast(@alignCast(ptr_raw)); + ptr.* = @intCast(value); + }, + + f32, f64 => { + const ptr: *f64 = @ptrCast(@alignCast(ptr_raw)); + ptr.* = @floatCast(value); + }, + + else => |T| switch (@typeInfo(T)) { + .Optional => { + // If an optional has no value we return false. + const unwrapped = value orelse return false; + return getValue(ptr_raw, unwrapped); + }, + + .Enum => { + const ptr: *[*:0]const u8 = @ptrCast(@alignCast(ptr_raw)); + ptr.* = @tagName(value); + }, + + .Struct => |info| { + // Packed structs that are less than or equal to the + // size of a C int can be passed directly as their + // bit representation. + if (info.layout != .Packed) return false; + const Backing = info.backing_integer orelse return false; + if (@bitSizeOf(Backing) > @bitSizeOf(c_uint)) return false; + + const ptr: *c_uint = @ptrCast(@alignCast(ptr_raw)); + ptr.* = @intCast(@as(Backing, @bitCast(value))); + }, + + else => return false, + }, + } + + return true; +} + /// Get a value from the config by key. fn fieldByKey(self: *const Config, comptime k: Key) Value(k) { const field = comptime field: { @@ -109,3 +121,37 @@ test "enum" { const str = std.mem.sliceTo(cval, 0); try testing.expectEqualStrings("dark", str); } + +test "color" { + const testing = std.testing; + const alloc = testing.allocator; + + var c = try Config.default(alloc); + defer c.deinit(); + c.background = .{ .r = 255, .g = 0, .b = 0 }; + + var cval: c_uint = undefined; + try testing.expect(get(&c, .background, @ptrCast(&cval))); + try testing.expectEqual(@as(c_uint, 255), cval); +} + +test "optional" { + const testing = std.testing; + const alloc = testing.allocator; + + var c = try Config.default(alloc); + defer c.deinit(); + + { + c.@"unfocused-split-fill" = null; + var cval: c_uint = undefined; + try testing.expect(!get(&c, .@"unfocused-split-fill", @ptrCast(&cval))); + } + + { + c.@"unfocused-split-fill" = .{ .r = 255, .g = 0, .b = 0 }; + var cval: c_uint = undefined; + try testing.expect(get(&c, .@"unfocused-split-fill", @ptrCast(&cval))); + try testing.expectEqual(@as(c_uint, 255), cval); + } +}