diff --git a/src/renderer/Metal.zig b/src/renderer/Metal.zig index 4247b8213..b37f440f4 100644 --- a/src/renderer/Metal.zig +++ b/src/renderer/Metal.zig @@ -76,18 +76,30 @@ size: renderer.Size, /// True if the window is focused focused: bool, -/// The actual foreground color. May differ from the config foreground color if -/// changed by a terminal application -foreground_color: terminal.color.RGB, +/// The foreground color set by an OSC 10 sequence. If unset then +/// default_foreground_color is used. +foreground_color: ?terminal.color.RGB, -/// The actual background color. May differ from the config background color if -/// changed by a terminal application -background_color: terminal.color.RGB, +/// Foreground color set in the user's config file. +default_foreground_color: terminal.color.RGB, -/// The actual cursor color. May differ from the config cursor color if changed -/// by a terminal application +/// The background color set by an OSC 11 sequence. If unset then +/// default_background_color is used. +background_color: ?terminal.color.RGB, + +/// Background color set in the user's config file. +default_background_color: terminal.color.RGB, + +/// The cursor color set by an OSC 12 sequence. If unset then +/// default_cursor_color is used. cursor_color: ?terminal.color.RGB, +/// Default cursor color when no color is set explicitly by an OSC 12 command. +/// This is cursor color as set in the user's config, if any. If no cursor color +/// is set in the user's config, then the cursor color is determined by the +/// current foreground color. +default_cursor_color: ?terminal.color.RGB, + /// When `cursor_color` is null, swap the foreground and background colors of /// the cell under the cursor for the cursor color. Otherwise, use the default /// foreground color as the cursor color. @@ -629,9 +641,12 @@ pub fn init(alloc: Allocator, options: renderer.Options) !Metal { .grid_metrics = font_critical.metrics, .size = options.size, .focused = true, - .foreground_color = options.config.foreground, - .background_color = options.config.background, - .cursor_color = options.config.cursor_color, + .foreground_color = null, + .default_foreground_color = options.config.foreground, + .background_color = null, + .default_background_color = options.config.background, + .cursor_color = null, + .default_cursor_color = options.config.cursor_color, .cursor_invert = options.config.cursor_invert, .current_background_color = options.config.background, @@ -919,15 +934,34 @@ pub fn updateFrame( } // Swap bg/fg if the terminal is reversed - const bg = self.background_color; - const fg = self.foreground_color; + const bg = self.background_color orelse self.default_background_color; + const fg = self.foreground_color orelse self.default_foreground_color; defer { - self.background_color = bg; - self.foreground_color = fg; + if (self.background_color) |*c| { + c.* = bg; + } else { + self.default_background_color = bg; + } + + if (self.foreground_color) |*c| { + c.* = fg; + } else { + self.default_foreground_color = fg; + } } + if (state.terminal.modes.get(.reverse_colors)) { - self.background_color = fg; - self.foreground_color = bg; + if (self.background_color) |*c| { + c.* = fg; + } else { + self.default_background_color = fg; + } + + if (self.foreground_color) |*c| { + c.* = bg; + } else { + self.default_foreground_color = bg; + } } // If our terminal screen size doesn't match our expected renderer @@ -1029,7 +1063,7 @@ pub fn updateFrame( } break :critical .{ - .bg = self.background_color, + .bg = self.background_color orelse self.default_background_color, .screen = screen_copy, .screen_type = state.terminal.active_screen, .mouse = state.mouse, @@ -1957,10 +1991,10 @@ pub fn changeConfig(self: *Metal, config: *DerivedConfig) !void { self.uniforms.min_contrast = config.min_contrast; // Set our new colors - self.background_color = config.background; - self.foreground_color = config.foreground; + self.default_background_color = config.background; + self.default_foreground_color = config.foreground; + self.default_cursor_color = if (!config.cursor_invert) config.cursor_color else null; self.cursor_invert = config.cursor_invert; - self.cursor_color = if (!config.cursor_invert) config.cursor_color else null; self.config.deinit(); self.config = config.*; @@ -2246,12 +2280,12 @@ fn rebuildCells( .extend => if (y == 0) { self.uniforms.padding_extend.up = !row.neverExtendBg( color_palette, - self.background_color, + self.background_color orelse self.default_background_color, ); } else if (y == self.cells.size.rows - 1) { self.uniforms.padding_extend.down = !row.neverExtendBg( color_palette, - self.background_color, + self.background_color orelse self.default_background_color, ); }, } @@ -2360,7 +2394,7 @@ fn rebuildCells( false; const bg_style = style.bg(cell, color_palette); - const fg_style = style.fg(color_palette, self.config.bold_is_bright) orelse self.foreground_color; + const fg_style = style.fg(color_palette, self.config.bold_is_bright) orelse self.foreground_color orelse self.default_foreground_color; // The final background color for the cell. const bg = bg: { @@ -2380,7 +2414,7 @@ fn rebuildCells( // If we don't have invert selection fg/bg set then we // just use the selection background if set, otherwise // the default fg color. - break :bg self.config.selection_background orelse self.foreground_color; + break :bg self.config.selection_background orelse self.foreground_color orelse self.default_foreground_color; } // Not selected @@ -2402,7 +2436,7 @@ fn rebuildCells( // If we don't have invert selection fg/bg set // then we just use the selection foreground if // set, otherwise the default bg color. - break :fg self.config.selection_foreground orelse self.background_color; + break :fg self.config.selection_foreground orelse self.background_color orelse self.default_background_color; } // Whether we need to use the bg color as our fg color: @@ -2411,7 +2445,7 @@ fn rebuildCells( // Note: if selected then invert sel fg / bg must be // false since we separately handle it if true above. break :fg if (style.flags.inverse != selected) - bg_style orelse self.background_color + bg_style orelse self.background_color orelse self.default_background_color else fg_style; }; @@ -2438,7 +2472,7 @@ fn rebuildCells( // If we have a background and its not the default background // then we apply background opacity - if (style.bg(cell, color_palette) != null and !rgb.eql(self.background_color)) { + if (style.bg(cell, color_palette) != null and !rgb.eql(self.background_color orelse self.default_background_color)) { break :bg_alpha default; } @@ -2601,12 +2635,12 @@ fn rebuildCells( // Prepare the cursor cell contents. const style = cursor_style_ orelse break :cursor; - const cursor_color = self.cursor_color orelse color: { + const cursor_color = self.cursor_color orelse self.default_cursor_color orelse color: { if (self.cursor_invert) { const sty = screen.cursor.page_pin.style(screen.cursor.page_cell); - break :color sty.fg(color_palette, self.config.bold_is_bright) orelse self.foreground_color; + break :color sty.fg(color_palette, self.config.bold_is_bright) orelse self.foreground_color orelse self.default_foreground_color; } else { - break :color self.foreground_color; + break :color self.foreground_color orelse self.default_foreground_color; } }; @@ -2634,11 +2668,11 @@ fn rebuildCells( const uniform_color = if (self.cursor_invert) blk: { const sty = screen.cursor.page_pin.style(screen.cursor.page_cell); - break :blk sty.bg(screen.cursor.page_cell, color_palette) orelse self.background_color; + break :blk sty.bg(screen.cursor.page_cell, color_palette) orelse self.background_color orelse self.default_background_color; } else if (self.config.cursor_text) |txt| txt else - self.background_color; + self.background_color orelse self.default_background_color; self.uniforms.cursor_color = .{ uniform_color.r, @@ -2928,8 +2962,8 @@ fn addPreeditCell( coord: terminal.Coordinate, ) !void { // Preedit is rendered inverted - const bg = self.foreground_color; - const fg = self.background_color; + const bg = self.foreground_color orelse self.default_foreground_color; + const fg = self.background_color orelse self.default_background_color; // Render the glyph for our preedit text const render_ = self.font_grid.renderCodepoint( diff --git a/src/renderer/OpenGL.zig b/src/renderer/OpenGL.zig index 1456ed3bb..72e0457e9 100644 --- a/src/renderer/OpenGL.zig +++ b/src/renderer/OpenGL.zig @@ -89,18 +89,30 @@ texture_color_resized: usize = 0, /// True if the window is focused focused: bool, -/// The actual foreground color. May differ from the config foreground color if -/// changed by a terminal application -foreground_color: terminal.color.RGB, +/// The foreground color set by an OSC 10 sequence. If unset then the default +/// value from the config file is used. +foreground_color: ?terminal.color.RGB, -/// The actual background color. May differ from the config background color if -/// changed by a terminal application -background_color: terminal.color.RGB, +/// Foreground color set in the user's config file. +default_foreground_color: terminal.color.RGB, -/// The actual cursor color. May differ from the config cursor color if changed -/// by a terminal application +/// The background color set by an OSC 11 sequence. If unset then the default +/// value from the config file is used. +background_color: ?terminal.color.RGB, + +/// Background color set in the user's config file. +default_background_color: terminal.color.RGB, + +/// The cursor color set by an OSC 12 sequence. If unset then +/// default_cursor_color is used. cursor_color: ?terminal.color.RGB, +/// Default cursor color when no color is set explicitly by an OSC 12 command. +/// This is cursor color as set in the user's config, if any. If no cursor color +/// is set in the user's config, then the cursor color is determined by the +/// current foreground color. +default_cursor_color: ?terminal.color.RGB, + /// When `cursor_color` is null, swap the foreground and background colors of /// the cell under the cursor for the cursor color. Otherwise, use the default /// foreground color as the cursor color. @@ -386,9 +398,12 @@ pub fn init(alloc: Allocator, options: renderer.Options) !OpenGL { .font_shaper_cache = font.ShaperCache.init(), .draw_background = options.config.background, .focused = true, - .foreground_color = options.config.foreground, - .background_color = options.config.background, - .cursor_color = options.config.cursor_color, + .foreground_color = null, + .default_foreground_color = options.config.foreground, + .background_color = null, + .default_background_color = options.config.background, + .cursor_color = null, + .default_cursor_color = options.config.cursor_color, .cursor_invert = options.config.cursor_invert, .surface_mailbox = options.surface_mailbox, .deferred_font_size = .{ .metrics = grid.metrics }, @@ -701,15 +716,34 @@ pub fn updateFrame( } // Swap bg/fg if the terminal is reversed - const bg = self.background_color; - const fg = self.foreground_color; + const bg = self.background_color orelse self.default_background_color; + const fg = self.foreground_color orelse self.default_foreground_color; defer { - self.background_color = bg; - self.foreground_color = fg; + if (self.background_color) |*c| { + c.* = bg; + } else { + self.default_background_color = bg; + } + + if (self.foreground_color) |*c| { + c.* = fg; + } else { + self.default_foreground_color = fg; + } } + if (state.terminal.modes.get(.reverse_colors)) { - self.background_color = fg; - self.foreground_color = bg; + if (self.background_color) |*c| { + c.* = fg; + } else { + self.default_background_color = fg; + } + + if (self.foreground_color) |*c| { + c.* = bg; + } else { + self.default_foreground_color = bg; + } } // If our terminal screen size doesn't match our expected renderer @@ -820,7 +854,7 @@ pub fn updateFrame( break :critical .{ .full_rebuild = full_rebuild, - .gl_bg = self.background_color, + .gl_bg = self.background_color orelse self.default_background_color, .screen = screen_copy, .screen_type = state.terminal.active_screen, .mouse = state.mouse, @@ -1298,12 +1332,12 @@ pub fn rebuildCells( .extend => if (y == 0) { self.padding_extend_top = !row.neverExtendBg( color_palette, - self.background_color, + self.background_color orelse self.default_background_color, ); } else if (y == self.size.grid().rows - 1) { self.padding_extend_bottom = !row.neverExtendBg( color_palette, - self.background_color, + self.background_color orelse self.default_background_color, ); }, } @@ -1412,7 +1446,7 @@ pub fn rebuildCells( false; const bg_style = style.bg(cell, color_palette); - const fg_style = style.fg(color_palette, self.config.bold_is_bright) orelse self.foreground_color; + const fg_style = style.fg(color_palette, self.config.bold_is_bright) orelse self.foreground_color orelse self.default_foreground_color; // The final background color for the cell. const bg = bg: { @@ -1432,7 +1466,7 @@ pub fn rebuildCells( // If we don't have invert selection fg/bg set then we // just use the selection background if set, otherwise // the default fg color. - break :bg self.config.selection_background orelse self.foreground_color; + break :bg self.config.selection_background orelse self.foreground_color orelse self.default_foreground_color; } // Not selected @@ -1454,7 +1488,7 @@ pub fn rebuildCells( // If we don't have invert selection fg/bg set // then we just use the selection foreground if // set, otherwise the default bg color. - break :fg self.config.selection_foreground orelse self.background_color; + break :fg self.config.selection_foreground orelse self.background_color orelse self.default_background_color; } // Whether we need to use the bg color as our fg color: @@ -1463,7 +1497,7 @@ pub fn rebuildCells( // Note: if selected then invert sel fg / bg must be // false since we separately handle it if true above. break :fg if (style.flags.inverse != selected) - bg_style orelse self.background_color + bg_style orelse self.background_color orelse self.default_background_color else fg_style; }; @@ -1490,7 +1524,7 @@ pub fn rebuildCells( // If we have a background and its not the default background // then we apply background opacity - if (style.bg(cell, color_palette) != null and !rgb.eql(self.background_color)) { + if (style.bg(cell, color_palette) != null and !rgb.eql(self.background_color orelse self.default_background_color)) { break :bg_alpha default; } @@ -1699,12 +1733,12 @@ pub fn rebuildCells( break :cursor_style; } - const cursor_color = self.cursor_color orelse color: { + const cursor_color = self.cursor_color orelse self.default_cursor_color orelse color: { if (self.cursor_invert) { const sty = screen.cursor.page_pin.style(screen.cursor.page_cell); - break :color sty.fg(color_palette, self.config.bold_is_bright) orelse self.foreground_color; + break :color sty.fg(color_palette, self.config.bold_is_bright) orelse self.foreground_color orelse self.default_foreground_color; } else { - break :color self.foreground_color; + break :color self.foreground_color orelse self.default_foreground_color; } }; @@ -1713,11 +1747,11 @@ pub fn rebuildCells( if (cell.mode.isFg() and cell.mode != .fg_color) { const cell_color = if (self.cursor_invert) blk: { const sty = screen.cursor.page_pin.style(screen.cursor.page_cell); - break :blk sty.bg(screen.cursor.page_cell, color_palette) orelse self.background_color; + break :blk sty.bg(screen.cursor.page_cell, color_palette) orelse self.background_color orelse self.default_background_color; } else if (self.config.cursor_text) |txt| txt else - self.background_color; + self.background_color orelse self.default_background_color; cell.r = cell_color.r; cell.g = cell_color.g; @@ -1742,8 +1776,8 @@ fn addPreeditCell( y: usize, ) !void { // Preedit is rendered inverted - const bg = self.foreground_color; - const fg = self.background_color; + const bg = self.foreground_color orelse self.default_foreground_color; + const fg = self.background_color orelse self.default_background_color; // Render the glyph for our preedit text const render_ = self.font_grid.renderCodepoint( @@ -2122,10 +2156,10 @@ pub fn changeConfig(self: *OpenGL, config: *DerivedConfig) !void { self.font_shaper_cache = font_shaper_cache; // Set our new colors - self.background_color = config.background; - self.foreground_color = config.foreground; + self.default_background_color = config.background; + self.default_foreground_color = config.foreground; + self.default_cursor_color = if (!config.cursor_invert) config.cursor_color else null; self.cursor_invert = config.cursor_invert; - self.cursor_color = if (!config.cursor_invert) config.cursor_color else null; // Update our uniforms self.deferred_config = .{}; diff --git a/src/renderer/message.zig b/src/renderer/message.zig index b420e554e..d6255661f 100644 --- a/src/renderer/message.zig +++ b/src/renderer/message.zig @@ -42,13 +42,11 @@ pub const Message = union(enum) { old_key: font.SharedGridSet.Key, }, - /// Change the foreground color. This can be done separately from changing - /// the config file in response to an OSC 10 command. - foreground_color: terminal.color.RGB, + /// Change the foreground color as set by an OSC 10 command, if any. + foreground_color: ?terminal.color.RGB, - /// Change the background color. This can be done separately from changing - /// the config file in response to an OSC 11 command. - background_color: terminal.color.RGB, + /// Change the background color as set by an OSC 11 command, if any. + background_color: ?terminal.color.RGB, /// Change the cursor color. This can be done separately from changing the /// config file in response to an OSC 12 command. diff --git a/src/termio/stream_handler.zig b/src/termio/stream_handler.zig index 64915f704..849e5c107 100644 --- a/src/termio/stream_handler.zig +++ b/src/termio/stream_handler.zig @@ -1347,7 +1347,7 @@ pub const StreamHandler = struct { .foreground => { self.foreground_color = null; _ = self.renderer_mailbox.push(.{ - .foreground_color = self.default_foreground_color, + .foreground_color = self.foreground_color, }, .{ .forever = {} }); self.surfaceMessageWriter(.{ .color_change = .{ @@ -1358,7 +1358,7 @@ pub const StreamHandler = struct { .background => { self.background_color = null; _ = self.renderer_mailbox.push(.{ - .background_color = self.default_background_color, + .background_color = self.background_color, }, .{ .forever = {} }); self.surfaceMessageWriter(.{ .color_change = .{ @@ -1370,7 +1370,7 @@ pub const StreamHandler = struct { self.cursor_color = null; _ = self.renderer_mailbox.push(.{ - .cursor_color = self.default_cursor_color, + .cursor_color = self.cursor_color, }, .{ .forever = {} }); if (self.default_cursor_color) |color| { @@ -1490,15 +1490,15 @@ pub const StreamHandler = struct { const msg: renderer.Message = switch (special) { .foreground => msg: { self.foreground_color = null; - break :msg .{ .foreground_color = self.default_foreground_color }; + break :msg .{ .foreground_color = self.foreground_color }; }, .background => msg: { self.background_color = null; - break :msg .{ .background_color = self.default_background_color }; + break :msg .{ .background_color = self.background_color }; }, .cursor => msg: { self.cursor_color = null; - break :msg .{ .cursor_color = self.default_cursor_color }; + break :msg .{ .cursor_color = self.cursor_color }; }, else => { log.warn(