mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-14 15:56:13 +03:00
core: more actions
This commit is contained in:
@ -3735,11 +3735,15 @@ pub fn performBindingAction(self: *Surface, action: input.Binding.Action) !bool
|
||||
{},
|
||||
),
|
||||
|
||||
.toggle_fullscreen => {
|
||||
if (@hasDecl(apprt.Surface, "toggleFullscreen")) {
|
||||
self.rt_surface.toggleFullscreen(self.config.macos_non_native_fullscreen);
|
||||
} else log.warn("runtime doesn't implement toggleFullscreen", .{});
|
||||
.toggle_fullscreen => try self.rt_app.performAction(
|
||||
.{ .surface = self },
|
||||
.toggle_fullscreen,
|
||||
switch (self.config.macos_non_native_fullscreen) {
|
||||
.false => .native,
|
||||
.true => .macos_non_native,
|
||||
.@"visible-menu" => .macos_non_native_visible_menu,
|
||||
},
|
||||
),
|
||||
|
||||
.toggle_window_decorations => try self.rt_app.performAction(
|
||||
.{ .surface = self },
|
||||
@ -3761,11 +3765,16 @@ pub fn performBindingAction(self: *Surface, action: input.Binding.Action) !bool
|
||||
}
|
||||
},
|
||||
|
||||
.inspector => |mode| {
|
||||
if (@hasDecl(apprt.Surface, "controlInspector")) {
|
||||
self.rt_surface.controlInspector(mode);
|
||||
} else log.warn("runtime doesn't implement controlInspector", .{});
|
||||
.inspector => |mode| try self.rt_app.performAction(
|
||||
.{ .surface = self },
|
||||
.inspector,
|
||||
switch (mode) {
|
||||
inline else => |tag| @field(
|
||||
apprt.action.Inspector,
|
||||
@tagName(tag),
|
||||
),
|
||||
},
|
||||
),
|
||||
|
||||
.close_surface => self.close(),
|
||||
|
||||
@ -4152,11 +4161,6 @@ fn completeClipboardReadOSC52(
|
||||
}
|
||||
|
||||
fn showDesktopNotification(self: *Surface, title: [:0]const u8, body: [:0]const u8) !void {
|
||||
if (comptime !@hasDecl(apprt.Surface, "showDesktopNotification")) {
|
||||
log.warn("runtime doesn't support desktop notifications", .{});
|
||||
return;
|
||||
}
|
||||
|
||||
// Wyhash is used to hash the contents of the desktop notification to limit
|
||||
// how fast identical notifications can be sent sequentially.
|
||||
const hash_algorithm = std.hash.Wyhash;
|
||||
@ -4192,7 +4196,14 @@ fn showDesktopNotification(self: *Surface, title: [:0]const u8, body: [:0]const
|
||||
|
||||
self.app.last_notification_time = now;
|
||||
self.app.last_notification_digest = new_digest;
|
||||
try self.rt_surface.showDesktopNotification(title, body);
|
||||
try self.rt_app.performAction(
|
||||
.{ .surface = self },
|
||||
.desktop_notification,
|
||||
.{
|
||||
.title = title,
|
||||
.body = body,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
fn crashThreadState(self: *Surface) crash.sentry.ThreadState {
|
||||
@ -4205,9 +4216,11 @@ fn crashThreadState(self: *Surface) crash.sentry.ThreadState {
|
||||
/// Tell the surface to present itself to the user. This may involve raising the
|
||||
/// window and switching tabs.
|
||||
fn presentSurface(self: *Surface) !void {
|
||||
if (@hasDecl(apprt.Surface, "presentSurface")) {
|
||||
self.rt_surface.presentSurface();
|
||||
} else log.warn("runtime doesn't support presentSurface", .{});
|
||||
try self.rt_app.performAction(
|
||||
.{ .surface = self },
|
||||
.present_terminal,
|
||||
{},
|
||||
);
|
||||
}
|
||||
|
||||
pub const face_ttf = @embedFile("font/res/JetBrainsMono-Regular.ttf");
|
||||
|
@ -28,6 +28,9 @@ pub const Action = union(enum) {
|
||||
/// Close all open windows.
|
||||
close_all_windows,
|
||||
|
||||
/// Toggle fullscreen mode.
|
||||
toggle_fullscreen: Fullscreen,
|
||||
|
||||
/// Toggle whether window directions are shown.
|
||||
toggle_window_decorations,
|
||||
|
||||
@ -48,6 +51,15 @@ pub const Action = union(enum) {
|
||||
/// to take up the entire window.
|
||||
toggle_split_zoom,
|
||||
|
||||
/// Present the target terminal whether its a tab, split, or window.
|
||||
present_terminal,
|
||||
|
||||
/// Control whether the inspector is shown or hidden.
|
||||
inspector: Inspector,
|
||||
|
||||
/// Show a desktop notification.
|
||||
desktop_notification: DesktopNotification,
|
||||
|
||||
/// Open the Ghostty configuration. This is platform-specific about
|
||||
/// what it means; it can mean opening a dedicated UI or just opening
|
||||
/// a file in a text editor.
|
||||
@ -130,8 +142,31 @@ pub const GotoTab = enum(c_int) {
|
||||
_,
|
||||
};
|
||||
|
||||
/// The fullscreen mode to toggle to if we're moving to fullscreen.
|
||||
pub const Fullscreen = enum(c_int) {
|
||||
native,
|
||||
|
||||
/// macOS has a non-native fullscreen mode that is more like a maximized
|
||||
/// window. This is much faster to enter and exit than the native mode.
|
||||
macos_non_native,
|
||||
macos_non_native_visible_menu,
|
||||
};
|
||||
|
||||
pub const SecureInput = enum(c_int) {
|
||||
on,
|
||||
off,
|
||||
toggle,
|
||||
};
|
||||
|
||||
/// The inspector mode to toggle to if we're toggling the inspector.
|
||||
pub const Inspector = enum(c_int) {
|
||||
toggle,
|
||||
show,
|
||||
hide,
|
||||
};
|
||||
|
||||
/// The desktop notification to show.
|
||||
pub const DesktopNotification = struct {
|
||||
title: [:0]const u8,
|
||||
body: [:0]const u8,
|
||||
};
|
||||
|
@ -92,7 +92,7 @@ pub const App = struct {
|
||||
new_window: ?*const fn (SurfaceUD, apprt.Surface.Options) callconv(.C) void = null,
|
||||
|
||||
/// Control the inspector visibility
|
||||
control_inspector: ?*const fn (SurfaceUD, input.InspectorMode) callconv(.C) void = null,
|
||||
control_inspector: ?*const fn (SurfaceUD, apprt.action.Inspector) callconv(.C) void = null,
|
||||
|
||||
/// Close the current surface given by this function.
|
||||
close_surface: ?*const fn (SurfaceUD, bool) callconv(.C) void = null,
|
||||
@ -125,7 +125,8 @@ pub const App = struct {
|
||||
/// Called when the cell size changes.
|
||||
set_cell_size: ?*const fn (SurfaceUD, u32, u32) callconv(.C) void = null,
|
||||
|
||||
/// Show a desktop notification to the user.
|
||||
/// Show a desktop notification to the user. The surface may be null
|
||||
/// if the notification is global.
|
||||
show_desktop_notification: ?*const fn (SurfaceUD, [*:0]const u8, [*:0]const u8) void = null,
|
||||
|
||||
/// Called when the health of the renderer changes.
|
||||
@ -507,6 +508,29 @@ pub const App = struct {
|
||||
func(null, .{});
|
||||
}
|
||||
|
||||
fn toggleFullscreen(
|
||||
self: *App,
|
||||
target: apprt.Target,
|
||||
fullscreen: apprt.action.Fullscreen,
|
||||
) void {
|
||||
const func = self.opts.toggle_fullscreen orelse {
|
||||
log.info("runtime embedder does not toggle_fullscreen", .{});
|
||||
return;
|
||||
};
|
||||
|
||||
switch (target) {
|
||||
.app => {},
|
||||
.surface => |v| func(
|
||||
v.rt_surface.userdata,
|
||||
switch (fullscreen) {
|
||||
.native => .false,
|
||||
.macos_non_native => .true,
|
||||
.macos_non_native_visible_menu => .@"visible-menu",
|
||||
},
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
fn newTab(self: *const App, target: apprt.Target) void {
|
||||
const func = self.opts.new_tab orelse {
|
||||
log.info("runtime embedder does not support new_tab", .{});
|
||||
@ -614,6 +638,38 @@ pub const App = struct {
|
||||
}
|
||||
}
|
||||
|
||||
fn controlInspector(
|
||||
self: *const App,
|
||||
target: apprt.Target,
|
||||
value: apprt.action.Inspector,
|
||||
) void {
|
||||
const func = self.opts.control_inspector orelse {
|
||||
log.info("runtime embedder does not support the terminal inspector", .{});
|
||||
return;
|
||||
};
|
||||
|
||||
switch (target) {
|
||||
.app => {},
|
||||
.surface => |v| func(v.rt_surface.userdata, value),
|
||||
}
|
||||
}
|
||||
|
||||
fn showDesktopNotification(
|
||||
self: *const App,
|
||||
target: apprt.Target,
|
||||
notification: apprt.action.DesktopNotification,
|
||||
) void {
|
||||
const func = self.opts.show_desktop_notification orelse {
|
||||
log.info("runtime embedder does not support show_desktop_notification", .{});
|
||||
return;
|
||||
};
|
||||
|
||||
func(switch (target) {
|
||||
.app => null,
|
||||
.surface => |v| v.rt_surface.userdata,
|
||||
}, notification.title, notification.body);
|
||||
}
|
||||
|
||||
fn setPasswordInput(self: *App, target: apprt.Target, v: apprt.action.SecureInput) void {
|
||||
switch (v) {
|
||||
inline .on, .off => |tag| {
|
||||
@ -655,6 +711,7 @@ pub const App = struct {
|
||||
.app => null,
|
||||
.surface => |v| v,
|
||||
}),
|
||||
.toggle_fullscreen => self.toggleFullscreen(target, value),
|
||||
|
||||
.new_tab => self.newTab(target),
|
||||
.goto_tab => self.gotoTab(target, value),
|
||||
@ -664,9 +721,12 @@ pub const App = struct {
|
||||
.toggle_split_zoom => self.toggleSplitZoom(target),
|
||||
.goto_split => self.gotoSplit(target, value),
|
||||
.open_config => try configpkg.edit.open(self.core_app.alloc),
|
||||
.inspector => self.controlInspector(target, value),
|
||||
.desktop_notification => self.showDesktopNotification(target, value),
|
||||
.secure_input => self.setPasswordInput(target, value),
|
||||
|
||||
// Unimplemented
|
||||
.present_terminal,
|
||||
.close_all_windows,
|
||||
.toggle_window_decorations,
|
||||
.quit_timer,
|
||||
@ -889,15 +949,6 @@ pub const Surface = struct {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn controlInspector(self: *const Surface, mode: input.InspectorMode) void {
|
||||
const func = self.app.opts.control_inspector orelse {
|
||||
log.info("runtime embedder does not support the terminal inspector", .{});
|
||||
return;
|
||||
};
|
||||
|
||||
func(self.userdata, mode);
|
||||
}
|
||||
|
||||
pub fn close(self: *const Surface, process_alive: bool) void {
|
||||
const func = self.app.opts.close_surface orelse {
|
||||
log.info("runtime embedder does not support closing a surface", .{});
|
||||
@ -1185,15 +1236,6 @@ pub const Surface = struct {
|
||||
};
|
||||
}
|
||||
|
||||
pub fn toggleFullscreen(self: *Surface, nonNativeFullscreen: configpkg.NonNativeFullscreen) void {
|
||||
const func = self.app.opts.toggle_fullscreen orelse {
|
||||
log.info("runtime embedder does not toggle_fullscreen", .{});
|
||||
return;
|
||||
};
|
||||
|
||||
func(self.userdata, nonNativeFullscreen);
|
||||
}
|
||||
|
||||
fn newWindow(self: *const Surface) !void {
|
||||
const func = self.app.opts.new_window orelse {
|
||||
log.info("runtime embedder does not support new_window", .{});
|
||||
@ -1249,20 +1291,6 @@ pub const Surface = struct {
|
||||
return .{ .x = pos.x * scale.x, .y = pos.y * scale.y };
|
||||
}
|
||||
|
||||
/// Show a desktop notification.
|
||||
pub fn showDesktopNotification(
|
||||
self: *const Surface,
|
||||
title: [:0]const u8,
|
||||
body: [:0]const u8,
|
||||
) !void {
|
||||
const func = self.app.opts.show_desktop_notification orelse {
|
||||
log.info("runtime embedder does not support show_desktop_notification", .{});
|
||||
return;
|
||||
};
|
||||
|
||||
func(self.userdata, title, body);
|
||||
}
|
||||
|
||||
/// Update the health of the renderer.
|
||||
pub fn updateRendererHealth(self: *const Surface, health: renderer.Health) void {
|
||||
const func = self.app.opts.update_renderer_health orelse {
|
||||
|
@ -147,6 +147,8 @@ pub const App = struct {
|
||||
.surface => |v| v,
|
||||
}),
|
||||
|
||||
.toggle_fullscreen => self.toggleFullscreen(target),
|
||||
|
||||
.open_config => try configpkg.edit.open(self.app.alloc),
|
||||
|
||||
// Unimplemented
|
||||
@ -155,11 +157,14 @@ pub const App = struct {
|
||||
.resize_split,
|
||||
.equalize_splits,
|
||||
.toggle_split_zoom,
|
||||
.present_terminal,
|
||||
.close_all_windows,
|
||||
.toggle_window_decorations,
|
||||
.goto_tab,
|
||||
.inspector,
|
||||
.quit_timer,
|
||||
.secure_input,
|
||||
.desktop_notification,
|
||||
=> log.info("unimplemented action={}", .{action}),
|
||||
}
|
||||
}
|
||||
@ -182,8 +187,12 @@ pub const App = struct {
|
||||
}
|
||||
|
||||
/// Toggle the window to fullscreen mode.
|
||||
pub fn toggleFullscreen(self: *App, surface: *Surface) void {
|
||||
fn toggleFullscreen(self: *App, target: apprt.Target) void {
|
||||
_ = self;
|
||||
const surface: *Surface = switch (target) {
|
||||
.app => return,
|
||||
.surface => |v| v.rt_surface,
|
||||
};
|
||||
const win = surface.window;
|
||||
|
||||
if (surface.isFullscreen()) {
|
||||
@ -562,10 +571,6 @@ pub const Surface = struct {
|
||||
return self.window.getMonitor() != null;
|
||||
}
|
||||
|
||||
pub fn toggleFullscreen(self: *Surface, _: Config.NonNativeFullscreen) void {
|
||||
self.app.toggleFullscreen(self);
|
||||
}
|
||||
|
||||
/// Close this surface.
|
||||
pub fn close(self: *Surface, processActive: bool) void {
|
||||
_ = processActive;
|
||||
|
@ -438,7 +438,7 @@ pub const Action = union(enum) {
|
||||
};
|
||||
|
||||
// Extern because it is used in the embedded runtime ABI.
|
||||
pub const InspectorMode = enum(c_int) {
|
||||
pub const InspectorMode = enum {
|
||||
toggle,
|
||||
show,
|
||||
hide,
|
||||
|
Reference in New Issue
Block a user