const apprt = @import("../apprt.zig"); const App = @import("../App.zig"); const Surface = @import("../Surface.zig"); const renderer = @import("../renderer.zig"); const termio = @import("../termio.zig"); const terminal = @import("../terminal/main.zig"); const Config = @import("../config.zig").Config; /// The message types that can be sent to a single surface. pub const Message = union(enum) { /// Represents a write request. Magic number comes from the max size /// we want this union to be. pub const WriteReq = termio.MessageData(u8, 255); /// Set the title of the surface. /// TODO: we should change this to a "WriteReq" style structure in /// the termio message so that we can more efficiently send strings /// of any length set_title: [256]u8, /// Report the window title back to the terminal report_title: ReportTitleStyle, /// Set the mouse shape. set_mouse_shape: terminal.MouseShape, /// Read the clipboard and write to the pty. clipboard_read: apprt.Clipboard, /// Write the clipboard contents. clipboard_write: struct { clipboard_type: apprt.Clipboard, req: WriteReq, }, /// Change the configuration to the given configuration. The pointer is /// not valid after receiving this message so any config must be used /// and derived immediately. change_config: *const Config, /// Close the surface. This will only close the current surface that /// receives this, not the full application. close: void, /// The child process running in the surface has exited. This may trigger /// a surface close, it may not. child_exited: void, /// Show a desktop notification. desktop_notification: struct { /// Desktop notification title. title: [63:0]u8, /// Desktop notification body. body: [255:0]u8, }, /// Health status change for the renderer. renderer_health: renderer.Health, /// Report the color scheme. The bool parameter is whether to force or not. /// If force is true, the color scheme should be reported even if mode /// 2031 is not set. report_color_scheme: bool, /// Tell the surface to present itself to the user. This may require raising /// a window and switching tabs. present_surface: void, /// Notifies the surface that password input has started within /// the terminal. This should always be followed by a false value /// 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, }, /// The terminal has reported a change in the working directory. pwd_change: WriteReq, /// The terminal encountered a bell character. ring_bell, pub const ReportTitleStyle = enum { csi_21_t, // This enum is a placeholder for future title styles. }; }; /// A surface mailbox. pub const Mailbox = struct { surface: *Surface, app: App.Mailbox, /// Send a message to the surface. pub fn push( self: Mailbox, msg: Message, timeout: App.Mailbox.Queue.Timeout, ) App.Mailbox.Queue.Size { // Surface message sending is actually implemented on the app // thread, so we have to rewrap the message with our surface // pointer and send it to the app thread. return self.app.push(.{ .surface_message = .{ .surface = self.surface, .message = msg, }, }, timeout); } }; /// Returns a new config for a surface for the given app that should be /// used for any new surfaces. The resulting config should be deinitialized /// after the surface is initialized. pub fn newConfig(app: *const App, config: *const Config) !Config { // Create a shallow clone var copy = config.shallowClone(app.alloc); // Our allocator is our config's arena const alloc = copy._arena.?.allocator(); // Get our previously focused surface for some inherited values. const prev = app.focusedSurface(); if (prev) |p| { if (config.@"window-inherit-working-directory") { if (try p.pwd(alloc)) |pwd| { copy.@"working-directory" = pwd; } } } return copy; }