ghostty/src/apprt/surface.zig
Leah Amelia Chen a0760cabd6 gtk: implement bell
Co-authored-by: Jeffrey C. Ollie <jeff@ocjtech.us>
2025-04-14 23:44:13 +08:00

139 lines
4.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,
/// 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;
}