Something went wrong. Try again.
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198const std = @import("std");const Allocator = std.mem.Allocator;
const apprt = @import("../apprt.zig");const build_config = @import("../build_config.zig");const App = @import("../App.zig");const Surface = @import("../Surface.zig");const renderer = @import("../renderer.zig");const terminal = @import("../terminal/main.zig");const Config = @import("../config.zig").Config;const MessageData = @import("../datastruct/main.zig").MessageData;
/// 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 = 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. Additional details about the child /// command are given in the `ChildExited` struct. child_exited: ChildExited,
/// 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,
/// 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: terminal.osc.color.ColoredTarget,
/// Notifies the surface that a tick of the timer that is timing /// out selection scrolling has occurred. "selection scrolling" /// is when the user has clicked and dragged the mouse outside /// the viewport of the terminal and the terminal is scrolling /// the viewport to follow the mouse cursor. selection_scroll_tick: bool,
/// The terminal has reported a change in the working directory. pwd_change: WriteReq,
/// The terminal encountered a bell character. ring_bell,
/// Report the progress of an action using a GUI element progress_report: terminal.osc.Command.ProgressReport,
/// A command has started in the shell, start a timer. start_command,
/// A command has finished in the shell, stop the timer and send out /// notifications as appropriate. The optional u8 is the exit code /// of the command. stop_command: ?u8,
/// The scrollbar state changed for the surface. scrollbar: terminal.Scrollbar,
/// Search progress update search_total: ?usize,
/// Selected search index change search_selected: ?usize,
pub const ReportTitleStyle = enum { csi_21_t,
// This enum is a placeholder for future title styles. };
pub const ChildExited = extern struct { exit_code: u32, runtime_ms: u64,
/// Make this a valid gobject if we're in a GTK environment. pub const getGObjectType = switch (build_config.app_runtime) { .gtk, => @import("gobject").ext.defineBoxed( ChildExited, .{ .name = "GhosttyApprtChildExited" }, ),
.none => void, }; };};
/// 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); }};
/// Context for new surface creation to determine inheritance behaviorpub const NewSurfaceContext = enum(c_int) { window = 0, tab = 1, split = 2,};
pub fn shouldInheritWorkingDirectory(context: NewSurfaceContext, config: *const Config) bool { return switch (context) { .window => config.@"window-inherit-working-directory", .tab => config.@"tab-inherit-working-directory", .split => config.@"split-inherit-working-directory", };}
/// 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, context: NewSurfaceContext,) Allocator.Error!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 (shouldInheritWorkingDirectory(context, config)) { if (try p.pwd(alloc)) |pwd| { copy.@"working-directory" = .{ .path = pwd }; } } }
return copy;}