diff --git a/include/ghostty.h b/include/ghostty.h index ca70456d8..f4836f210 100644 --- a/include/ghostty.h +++ b/include/ghostty.h @@ -512,6 +512,21 @@ typedef struct { ghostty_input_trigger_s trigger; } ghostty_action_key_sequence_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.ColorChange +typedef struct { + ghostty_action_color_kind_e kind; + uint8_t r; + uint8_t g; + uint8_t b; +} ghostty_action_color_change_s; + // apprt.Action.Key typedef enum { GHOSTTY_ACTION_NEW_WINDOW, @@ -545,6 +560,7 @@ typedef enum { GHOSTTY_ACTION_QUIT_TIMER, GHOSTTY_ACTION_SECURE_INPUT, GHOSTTY_ACTION_KEY_SEQUENCE, + GHOSTTY_ACTION_COLOR_CHANGE, } ghostty_action_tag_e; typedef union { @@ -567,6 +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_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 82d1240eb..2797f647f 100644 --- a/src/Surface.zig +++ b/src/Surface.zig @@ -799,6 +799,22 @@ pub fn handleMessage(self: *Surface, msg: Message) !void { }, .unlocked); }, + .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}); try self.rt_app.performAction( diff --git a/src/apprt/action.zig b/src/apprt/action.zig index 2c37ca270..feb2e2ba4 100644 --- a/src/apprt/action.zig +++ b/src/apprt/action.zig @@ -186,6 +186,10 @@ pub const Action = union(Key) { /// key mode because other input may be ignored. key_sequence: KeySequence, + /// 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) { new_window, @@ -219,6 +223,7 @@ pub const Action = union(Key) { quit_timer, secure_input, key_sequence, + color_change, }; /// Sync with: ghostty_action_u @@ -448,3 +453,20 @@ pub const KeySequence = union(enum) { }; } }; + +pub const ColorChange = extern struct { + kind: ColorKind, + 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 1dde97c9c..638f52bab 100644 --- a/src/apprt/glfw.zig +++ b/src/apprt/glfw.zig @@ -223,6 +223,7 @@ pub const App = struct { .mouse_over_link, .cell_size, .renderer_health, + .color_change, => log.info("unimplemented action={}", .{action}), } } diff --git a/src/apprt/gtk/App.zig b/src/apprt/gtk/App.zig index af664d720..017fc0ed4 100644 --- a/src/apprt/gtk/App.zig +++ b/src/apprt/gtk/App.zig @@ -485,6 +485,7 @@ pub fn performAction( .key_sequence, .render_inspector, .renderer_health, + .color_change, => log.warn("unimplemented action={}", .{action}), } } diff --git a/src/apprt/surface.zig b/src/apprt/surface.zig index daa2ad547..07eb1d466 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, + /// 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 90a33e8b7..5fe2e95e3 100644 --- a/src/termio/stream_handler.zig +++ b/src/termio/stream_handler.zig @@ -1229,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(