From 8e607f372bd248e7aa0a3ca264164d67a61cfb7e Mon Sep 17 00:00:00 2001 From: Matt Robenolt Date: Tue, 12 Dec 2023 16:34:41 -0800 Subject: [PATCH] Configurable unfocused dimming color --- macos/Sources/Ghostty/SurfaceView.swift | 34 ++++++++++++++++++++++--- src/config/Config.zig | 17 +++++++++++++ src/config/c_get.zig | 6 +++++ 3 files changed, 53 insertions(+), 4 deletions(-) diff --git a/macos/Sources/Ghostty/SurfaceView.swift b/macos/Sources/Ghostty/SurfaceView.swift index e83f08cc3..082406774 100644 --- a/macos/Sources/Ghostty/SurfaceView.swift +++ b/macos/Sources/Ghostty/SurfaceView.swift @@ -60,9 +60,32 @@ extension Ghostty { var opacity: Double = 0.85 let key = "unfocused-split-opacity" _ = ghostty_config_get(ghostty.config, &opacity, key, UInt(key.count)) + AppDelegate.logger.warning("ghostty_config_get(\(key))=\(opacity)") return 1 - opacity } + 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)) + AppDelegate.logger.warning("ghostty_config_get(\(key))=\(rgb)") + let red = Double((rgb >> 16) & 0xff) + let green = Double((rgb >> 8) & 0xff) + let blue = Double(rgb & 0xff) + AppDelegate.logger.warning("red=\(red) green=\(green) blue=\(blue)") + return Color.init( + red: 255, + green: 0, + blue: 0 + ) +// return Color.init( +// red: red, +// green: green, +// blue: blue, +// opacity: unfocusedOpacity +// ) + } + var body: some View { ZStack { // We use a GeometryReader to get the frame bounds so that our metal surface @@ -155,10 +178,13 @@ extension Ghostty { // because we want to keep our focused surface dark even if we don't have window // focus. if (isSplit && !surfaceFocus) { - Rectangle() - .fill(.white) - .allowsHitTesting(false) - .opacity(unfocusedOpacity) + let overlayOpacity = unfocusedOpacity; + if (overlayOpacity > 0) { + Rectangle() + .fill(unfocusedFill) + .allowsHitTesting(false) + .opacity(overlayOpacity) + } } } } diff --git a/src/config/Config.zig b/src/config/Config.zig index de8274cab..778d6c70e 100644 --- a/src/config/Config.zig +++ b/src/config/Config.zig @@ -314,6 +314,8 @@ palette: Palette = .{}, /// clamped to the nearest valid value. @"unfocused-split-opacity": f64 = 0.85, +@"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 /// be looked up from your system. The rules for the default lookup are: @@ -1989,6 +1991,21 @@ pub const Color = struct { return .{ .r = self.r, .g = self.g, .b = self.b }; } + // Pack into an integer + pub fn toInt(self: Color) u24 { + // u24 covers RGB, typically, an alpha would pack to a full u32 + return (@as(u24, self.r) << 16) + (@as(u24, self.g) << 8) + self.b; + } + + test "toInt" { + const testing = std.testing; + + try testing.exectEqual((Color{ .r = 0, .g = 0, .b = 0 }).toInt(), 0); + try testing.exectEqual((Color{ .r = 255, .g = 255, .b = 255 }).toInt(), 16777215); + try testing.exectEqual((Color{ .r = 100, .g = 20, .b = 12 }).toInt(), 6558732); + try testing.exectEqual((Color{ .r = 55, .g = 63, .b = 202 }).toInt(), 3620810); + } + pub fn parseCLI(input: ?[]const u8) !Color { return fromHex(input orelse return error.ValueRequired); } diff --git a/src/config/c_get.zig b/src/config/c_get.zig index 504e98a87..4a123674d 100644 --- a/src/config/c_get.zig +++ b/src/config/c_get.zig @@ -2,6 +2,7 @@ const std = @import("std"); const key = @import("key.zig"); const Config = @import("Config.zig"); +const Color = Config.Color; const Key = key.Key; const Value = key.Value; @@ -38,6 +39,11 @@ pub fn get(config: *const Config, k: Key, ptr_raw: *anyopaque) bool { ptr.* = @floatCast(value); }, + ?Color => { + const ptr: *?c_uint = @ptrCast(@alignCast(ptr_raw)); + ptr.* = if (value) |c| c.toInt() else null; + }, + else => |T| switch (@typeInfo(T)) { .Enum => { const ptr: *[*:0]const u8 = @ptrCast(@alignCast(ptr_raw));