From 4042041b61314d165187b2651b47b335a6e3badb Mon Sep 17 00:00:00 2001 From: Gregory Anders Date: Sat, 23 Nov 2024 17:40:54 -0600 Subject: [PATCH] termio: track whether fg/bg color is explicitly set Make the foreground_color and background_color fields in the Terminal struct optional values so that we can determine if a foreground or background color was explicitly set with an OSC 10 or OSC 11 sequence. This makes the logic a bit simpler to reason about (i.e. `foreground_color` is now always "the color set by an OSC 10 sequence" while `default_foreground_color` is always "the color set by the config file") and also fixes an issue where an OSC 10 or OSC 11 query would not report the correct color after a config update changed the foreground or background color. The `cursor_color` field was already optional, with the same semantics (it is only non-null when explicitly set with an OSC 12) so this brings all three of these fields into alignment. --- src/termio/Termio.zig | 6 ++-- src/termio/stream_handler.zig | 56 +++++++++++++++++++---------------- 2 files changed, 33 insertions(+), 29 deletions(-) diff --git a/src/termio/Termio.zig b/src/termio/Termio.zig index 9ed3ffc94..e7b391419 100644 --- a/src/termio/Termio.zig +++ b/src/termio/Termio.zig @@ -200,9 +200,9 @@ pub fn init(self: *Termio, alloc: Allocator, opts: termio.Options) !void { .default_cursor_style = opts.config.cursor_style, .default_cursor_blink = opts.config.cursor_blink, .default_cursor_color = default_cursor_color, - .cursor_color = default_cursor_color, - .foreground_color = opts.config.foreground.toTerminalRGB(), - .background_color = opts.config.background.toTerminalRGB(), + .cursor_color = null, + .foreground_color = null, + .background_color = null, }; }; diff --git a/src/termio/stream_handler.zig b/src/termio/stream_handler.zig index 4e82b5a19..2fc9e92af 100644 --- a/src/termio/stream_handler.zig +++ b/src/termio/stream_handler.zig @@ -52,20 +52,20 @@ pub const StreamHandler = struct { default_cursor_blink: ?bool, default_cursor_color: ?terminal.color.RGB, - /// Actual cursor color. This can be changed with OSC 12. + /// Actual cursor color. This can be changed with OSC 12. If unset, falls + /// back to the default cursor color. cursor_color: ?terminal.color.RGB, /// The default foreground and background color are those set by the user's - /// config file. These can be overridden by terminal applications using OSC - /// 10 and OSC 11, respectively. + /// config file. default_foreground_color: terminal.color.RGB, default_background_color: terminal.color.RGB, - /// The actual foreground and background color. Normally this will be the - /// same as the default foreground and background color, unless changed by a - /// terminal application. - foreground_color: terminal.color.RGB, - background_color: terminal.color.RGB, + /// The foreground and background color as set by an OSC 10 or OSC 11 + /// sequence. If unset then the respective color falls back to the default + /// value. + foreground_color: ?terminal.color.RGB, + background_color: ?terminal.color.RGB, /// The response to use for ENQ requests. The memory is owned by /// whoever owns StreamHandler. @@ -1197,9 +1197,12 @@ pub const StreamHandler = struct { const color = switch (kind) { .palette => |i| self.terminal.color_palette.colors[i], - .foreground => self.foreground_color, - .background => self.background_color, - .cursor => self.cursor_color orelse self.foreground_color, + .foreground => self.foreground_color orelse self.default_foreground_color, + .background => self.background_color orelse self.default_background_color, + .cursor => self.cursor_color orelse + self.default_cursor_color orelse + self.foreground_color orelse + self.default_foreground_color, }; var msg: termio.Message = .{ .write_small = .{} }; @@ -1342,34 +1345,35 @@ pub const StreamHandler = struct { } }, .foreground => { - self.foreground_color = self.default_foreground_color; + self.foreground_color = null; _ = self.renderer_mailbox.push(.{ - .foreground_color = self.foreground_color, + .foreground_color = self.default_foreground_color, }, .{ .forever = {} }); self.surfaceMessageWriter(.{ .color_change = .{ .kind = .foreground, - .color = self.foreground_color, + .color = self.default_foreground_color, } }); }, .background => { - self.background_color = self.default_background_color; + self.background_color = null; _ = self.renderer_mailbox.push(.{ - .background_color = self.background_color, + .background_color = self.default_background_color, }, .{ .forever = {} }); self.surfaceMessageWriter(.{ .color_change = .{ .kind = .background, - .color = self.background_color, + .color = self.default_background_color, } }); }, .cursor => { - self.cursor_color = self.default_cursor_color; + self.cursor_color = null; + _ = self.renderer_mailbox.push(.{ - .cursor_color = self.cursor_color, + .cursor_color = self.default_cursor_color, }, .{ .forever = {} }); - if (self.cursor_color) |color| { + if (self.default_cursor_color) |color| { self.surfaceMessageWriter(.{ .color_change = .{ .kind = .cursor, .color = color, @@ -1422,9 +1426,9 @@ pub const StreamHandler = struct { const color: terminal.color.RGB = switch (key) { .palette => |palette| self.terminal.color_palette.colors[palette], .special => |special| switch (special) { - .foreground => self.foreground_color, - .background => self.background_color, - .cursor => self.cursor_color, + .foreground => self.foreground_color orelse self.default_foreground_color, + .background => self.background_color orelse self.default_background_color, + .cursor => self.cursor_color orelse self.default_cursor_color, else => { log.warn("ignoring unsupported kitty color protocol key: {}", .{key}); continue; @@ -1485,15 +1489,15 @@ pub const StreamHandler = struct { .special => |special| { const msg: renderer.Message = switch (special) { .foreground => msg: { - self.foreground_color = self.default_foreground_color; + self.foreground_color = null; break :msg .{ .foreground_color = self.default_foreground_color }; }, .background => msg: { - self.background_color = self.default_background_color; + self.background_color = null; break :msg .{ .background_color = self.default_background_color }; }, .cursor => msg: { - self.cursor_color = self.default_cursor_color; + self.cursor_color = null; break :msg .{ .cursor_color = self.default_cursor_color }; }, else => {