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.
This commit is contained in:
Gregory Anders
2024-11-23 17:40:54 -06:00
parent f14e8d989c
commit 4042041b61
2 changed files with 33 additions and 29 deletions

View File

@ -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,
};
};

View File

@ -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 => {