From a2a1d93d5cbc2c6e00193902b4d3ac09d161b330 Mon Sep 17 00:00:00 2001 From: CJ van den Berg Date: Mon, 28 Oct 2024 09:48:01 +0100 Subject: [PATCH 1/2] apprt: propagate OSC10/11 (set term fore/background color) through to apprt This is to allow the running apprt to set the UI theme to match the terminal application coloring. --- include/ghostty.h | 18 ++++++++++++++++++ src/Surface.zig | 16 ++++++++++++++++ src/apprt/action.zig | 20 ++++++++++++++++++++ src/apprt/glfw.zig | 2 ++ src/apprt/gtk/App.zig | 2 ++ src/apprt/surface.zig | 6 ++++++ src/termio/stream_handler.zig | 2 ++ 7 files changed, 66 insertions(+) diff --git a/include/ghostty.h b/include/ghostty.h index ca70456d8..b4735fc40 100644 --- a/include/ghostty.h +++ b/include/ghostty.h @@ -512,6 +512,20 @@ typedef struct { ghostty_input_trigger_s trigger; } ghostty_action_key_sequence_s; +// apprt.action.SetBackground +typedef struct { + uint8_t r; + uint8_t g; + uint8_t b; +} ghostty_action_set_background_s; + +// apprt.action.SetForeground +typedef struct { + uint8_t r; + uint8_t g; + uint8_t b; +} ghostty_action_set_foreground_s; + // apprt.Action.Key typedef enum { GHOSTTY_ACTION_NEW_WINDOW, @@ -545,6 +559,8 @@ typedef enum { GHOSTTY_ACTION_QUIT_TIMER, GHOSTTY_ACTION_SECURE_INPUT, GHOSTTY_ACTION_KEY_SEQUENCE, + GHOSTTY_ACTION_SET_BACKGROUND, + GHOSTTY_ACTION_SET_FOREGROUND, } ghostty_action_tag_e; typedef union { @@ -567,6 +583,8 @@ typedef union { ghostty_action_quit_timer_e quit_timer; ghostty_action_secure_input_e secure_input; ghostty_action_key_sequence_s key_sequence; + ghostty_action_set_background_s set_background; + ghostty_action_set_foreground_s set_foreground; } ghostty_action_u; typedef struct { diff --git a/src/Surface.zig b/src/Surface.zig index 82d1240eb..b14ffe706 100644 --- a/src/Surface.zig +++ b/src/Surface.zig @@ -799,6 +799,22 @@ pub fn handleMessage(self: *Surface, msg: Message) !void { }, .unlocked); }, + .set_background => |color| { + try self.rt_app.performAction( + .{ .surface = self }, + .set_background, + .{ .r = color.r, .g = color.g, .b = color.b }, + ); + }, + + .set_foreground => |color| { + try self.rt_app.performAction( + .{ .surface = self }, + .set_background, + .{ .r = color.r, .g = color.g, .b = color.b }, + ); + }, + .set_mouse_shape => |shape| { log.debug("changing mouse shape: {}", .{shape}); try self.rt_app.performAction( diff --git a/src/apprt/action.zig b/src/apprt/action.zig index 2c37ca270..1fc79a3a5 100644 --- a/src/apprt/action.zig +++ b/src/apprt/action.zig @@ -186,6 +186,12 @@ pub const Action = union(Key) { /// key mode because other input may be ignored. key_sequence: KeySequence, + /// The terminal background color was changed. + set_background: SetBackground, + + /// The terminal foreground color was changed. + set_foreground: SetForeground, + /// Sync with: ghostty_action_tag_e pub const Key = enum(c_int) { new_window, @@ -219,6 +225,8 @@ pub const Action = union(Key) { quit_timer, secure_input, key_sequence, + set_background, + set_foreground, }; /// Sync with: ghostty_action_u @@ -448,3 +456,15 @@ pub const KeySequence = union(enum) { }; } }; + +pub const SetBackground = extern struct { + r: u8, + g: u8, + b: u8, +}; + +pub const SetForeground = extern struct { + r: u8, + g: u8, + b: u8, +}; diff --git a/src/apprt/glfw.zig b/src/apprt/glfw.zig index 1dde97c9c..f9651a934 100644 --- a/src/apprt/glfw.zig +++ b/src/apprt/glfw.zig @@ -223,6 +223,8 @@ pub const App = struct { .mouse_over_link, .cell_size, .renderer_health, + .set_foreground, + .set_background, => log.info("unimplemented action={}", .{action}), } } diff --git a/src/apprt/gtk/App.zig b/src/apprt/gtk/App.zig index af664d720..b444f9da8 100644 --- a/src/apprt/gtk/App.zig +++ b/src/apprt/gtk/App.zig @@ -485,6 +485,8 @@ pub fn performAction( .key_sequence, .render_inspector, .renderer_health, + .set_foreground, + .set_background, => log.warn("unimplemented action={}", .{action}), } } diff --git a/src/apprt/surface.zig b/src/apprt/surface.zig index daa2ad547..7de83a78b 100644 --- a/src/apprt/surface.zig +++ b/src/apprt/surface.zig @@ -70,6 +70,12 @@ pub const Message = union(enum) { /// unless the surface exits. password_input: bool, + /// The terminal background color was changed. + set_background: terminal.color.RGB, + + /// The terminal foreground color was changed. + set_foreground: terminal.color.RGB, + pub const ReportTitleStyle = enum { csi_21_t, diff --git a/src/termio/stream_handler.zig b/src/termio/stream_handler.zig index 90a33e8b7..e53544842 100644 --- a/src/termio/stream_handler.zig +++ b/src/termio/stream_handler.zig @@ -1215,12 +1215,14 @@ pub const StreamHandler = struct { _ = self.renderer_mailbox.push(.{ .foreground_color = color, }, .{ .forever = {} }); + self.surfaceMessageWriter(.{ .set_background = color }); }, .background => { self.background_color = color; _ = self.renderer_mailbox.push(.{ .background_color = color, }, .{ .forever = {} }); + self.surfaceMessageWriter(.{ .set_background = color }); }, .cursor => { self.cursor_color = color; From 1065359b9a7b3ee597df47309854c5ee22d2c988 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Wed, 30 Oct 2024 16:31:59 -0400 Subject: [PATCH 2/2] apprt: rename set_bg/fg to "color_change" to report all color changes --- include/ghostty.h | 23 +++++++++---------- macos/Sources/Ghostty/Ghostty.App.swift | 2 ++ src/Surface.zig | 30 ++++++++++++------------- src/apprt/action.zig | 26 +++++++++++---------- src/apprt/glfw.zig | 3 +-- src/apprt/gtk/App.zig | 3 +-- src/apprt/surface.zig | 10 ++++----- src/termio/stream_handler.zig | 8 +++++-- 8 files changed, 55 insertions(+), 50 deletions(-) diff --git a/include/ghostty.h b/include/ghostty.h index b4735fc40..f4836f210 100644 --- a/include/ghostty.h +++ b/include/ghostty.h @@ -512,19 +512,20 @@ typedef struct { ghostty_input_trigger_s trigger; } ghostty_action_key_sequence_s; -// apprt.action.SetBackground -typedef struct { - uint8_t r; - uint8_t g; - uint8_t b; -} ghostty_action_set_background_s; +// apprt.action.ColorKind +typedef enum { + GHOSTTY_ACTION_COLOR_KIND_FOREGROUND = -1, + GHOSTTY_ACTION_COLOR_KIND_BACKGROUND = -2, + GHOSTTY_ACTION_COLOR_KIND_CURSOR = -3, +} ghostty_action_color_kind_e; -// apprt.action.SetForeground +// apprt.action.ColorChange typedef struct { + ghostty_action_color_kind_e kind; uint8_t r; uint8_t g; uint8_t b; -} ghostty_action_set_foreground_s; +} ghostty_action_color_change_s; // apprt.Action.Key typedef enum { @@ -559,8 +560,7 @@ typedef enum { GHOSTTY_ACTION_QUIT_TIMER, GHOSTTY_ACTION_SECURE_INPUT, GHOSTTY_ACTION_KEY_SEQUENCE, - GHOSTTY_ACTION_SET_BACKGROUND, - GHOSTTY_ACTION_SET_FOREGROUND, + GHOSTTY_ACTION_COLOR_CHANGE, } ghostty_action_tag_e; typedef union { @@ -583,8 +583,7 @@ typedef union { ghostty_action_quit_timer_e quit_timer; ghostty_action_secure_input_e secure_input; ghostty_action_key_sequence_s key_sequence; - ghostty_action_set_background_s set_background; - ghostty_action_set_foreground_s set_foreground; + ghostty_action_color_change_s color_change; } ghostty_action_u; typedef struct { diff --git a/macos/Sources/Ghostty/Ghostty.App.swift b/macos/Sources/Ghostty/Ghostty.App.swift index e5320a24a..07acf0f91 100644 --- a/macos/Sources/Ghostty/Ghostty.App.swift +++ b/macos/Sources/Ghostty/Ghostty.App.swift @@ -521,6 +521,8 @@ extension Ghostty { case GHOSTTY_ACTION_KEY_SEQUENCE: keySequence(app, target: target, v: action.action.key_sequence) + case GHOSTTY_ACTION_COLOR_CHANGE: + fallthrough case GHOSTTY_ACTION_CLOSE_ALL_WINDOWS: fallthrough case GHOSTTY_ACTION_TOGGLE_TAB_OVERVIEW: diff --git a/src/Surface.zig b/src/Surface.zig index b14ffe706..2797f647f 100644 --- a/src/Surface.zig +++ b/src/Surface.zig @@ -799,21 +799,21 @@ pub fn handleMessage(self: *Surface, msg: Message) !void { }, .unlocked); }, - .set_background => |color| { - try self.rt_app.performAction( - .{ .surface = self }, - .set_background, - .{ .r = color.r, .g = color.g, .b = color.b }, - ); - }, - - .set_foreground => |color| { - try self.rt_app.performAction( - .{ .surface = self }, - .set_background, - .{ .r = color.r, .g = color.g, .b = color.b }, - ); - }, + .color_change => |change| try self.rt_app.performAction( + .{ .surface = self }, + .color_change, + .{ + .kind = switch (change.kind) { + .background => .background, + .foreground => .foreground, + .cursor => .cursor, + .palette => |v| @enumFromInt(v), + }, + .r = change.color.r, + .g = change.color.g, + .b = change.color.b, + }, + ), .set_mouse_shape => |shape| { log.debug("changing mouse shape: {}", .{shape}); diff --git a/src/apprt/action.zig b/src/apprt/action.zig index 1fc79a3a5..feb2e2ba4 100644 --- a/src/apprt/action.zig +++ b/src/apprt/action.zig @@ -186,11 +186,9 @@ pub const Action = union(Key) { /// key mode because other input may be ignored. key_sequence: KeySequence, - /// The terminal background color was changed. - set_background: SetBackground, - - /// The terminal foreground color was changed. - set_foreground: SetForeground, + /// A terminal color was changed programmatically through things + /// such as OSC 10/11. + color_change: ColorChange, /// Sync with: ghostty_action_tag_e pub const Key = enum(c_int) { @@ -225,8 +223,7 @@ pub const Action = union(Key) { quit_timer, secure_input, key_sequence, - set_background, - set_foreground, + color_change, }; /// Sync with: ghostty_action_u @@ -457,14 +454,19 @@ pub const KeySequence = union(enum) { } }; -pub const SetBackground = extern struct { +pub const ColorChange = extern struct { + kind: ColorKind, r: u8, g: u8, b: u8, }; -pub const SetForeground = extern struct { - r: u8, - g: u8, - b: u8, +pub const ColorKind = enum(c_int) { + // Negative numbers indicate some named kind + foreground = -1, + background = -2, + cursor = -3, + + // 0+ values indicate a palette index + _, }; diff --git a/src/apprt/glfw.zig b/src/apprt/glfw.zig index f9651a934..638f52bab 100644 --- a/src/apprt/glfw.zig +++ b/src/apprt/glfw.zig @@ -223,8 +223,7 @@ pub const App = struct { .mouse_over_link, .cell_size, .renderer_health, - .set_foreground, - .set_background, + .color_change, => log.info("unimplemented action={}", .{action}), } } diff --git a/src/apprt/gtk/App.zig b/src/apprt/gtk/App.zig index b444f9da8..017fc0ed4 100644 --- a/src/apprt/gtk/App.zig +++ b/src/apprt/gtk/App.zig @@ -485,8 +485,7 @@ pub fn performAction( .key_sequence, .render_inspector, .renderer_health, - .set_foreground, - .set_background, + .color_change, => log.warn("unimplemented action={}", .{action}), } } diff --git a/src/apprt/surface.zig b/src/apprt/surface.zig index 7de83a78b..07eb1d466 100644 --- a/src/apprt/surface.zig +++ b/src/apprt/surface.zig @@ -70,11 +70,11 @@ pub const Message = union(enum) { /// unless the surface exits. password_input: bool, - /// The terminal background color was changed. - set_background: terminal.color.RGB, - - /// The terminal foreground color was changed. - set_foreground: terminal.color.RGB, + /// A terminal color was changed using OSC sequences. + color_change: struct { + kind: terminal.osc.Command.ColorKind, + color: terminal.color.RGB, + }, pub const ReportTitleStyle = enum { csi_21_t, diff --git a/src/termio/stream_handler.zig b/src/termio/stream_handler.zig index e53544842..5fe2e95e3 100644 --- a/src/termio/stream_handler.zig +++ b/src/termio/stream_handler.zig @@ -1215,14 +1215,12 @@ pub const StreamHandler = struct { _ = self.renderer_mailbox.push(.{ .foreground_color = color, }, .{ .forever = {} }); - self.surfaceMessageWriter(.{ .set_background = color }); }, .background => { self.background_color = color; _ = self.renderer_mailbox.push(.{ .background_color = color, }, .{ .forever = {} }); - self.surfaceMessageWriter(.{ .set_background = color }); }, .cursor => { self.cursor_color = color; @@ -1231,6 +1229,12 @@ pub const StreamHandler = struct { }, .{ .forever = {} }); }, } + + // Notify the surface of the color change + self.surfaceMessageWriter(.{ .color_change = .{ + .kind = kind, + .color = color, + } }); } pub fn resetColor(