ghostty/src/apprt/surface.zig
2024-04-06 19:33:49 -07:00

107 lines
3.3 KiB
Zig

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,
/// 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
report_color_scheme: 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);
}
};
/// 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;
}