apprt/embedded: new_window can be called without a parent

This commit is contained in:
Mitchell Hashimoto
2024-09-24 17:00:38 -07:00
parent bea24f7725
commit 1b31663865
6 changed files with 45 additions and 22 deletions

View File

@ -78,6 +78,12 @@ class TerminalManager {
window.toggleFullScreen(nil) window.toggleFullScreen(nil)
} }
// If our app isn't active, we make it active. All new_window actions
// force our app to be active.
if !NSApp.isActive {
NSApp.activate(ignoringOtherApps: true)
}
// We're dispatching this async because otherwise the lastCascadePoint doesn't // We're dispatching this async because otherwise the lastCascadePoint doesn't
// take effect. Our best theory is there is some next-event-loop-tick logic // take effect. Our best theory is there is some next-event-loop-tick logic
// that Cocoa is doing that we need to be after. // that Cocoa is doing that we need to be after.

View File

@ -631,7 +631,11 @@ extension Ghostty {
} }
static func newWindow(_ userdata: UnsafeMutableRawPointer?, config: ghostty_surface_config_s) { static func newWindow(_ userdata: UnsafeMutableRawPointer?, config: ghostty_surface_config_s) {
let surface = self.surfaceUserdata(from: userdata) let surface: SurfaceView? = if let userdata {
self.surfaceUserdata(from: userdata)
} else {
nil
}
NotificationCenter.default.post( NotificationCenter.default.post(
name: Notification.ghosttyNewWindow, name: Notification.ghosttyNewWindow,

View File

@ -317,6 +317,7 @@ pub fn performAction(
.unbind => unreachable, .unbind => unreachable,
.ignore => {}, .ignore => {},
.quit => try self.setQuit(), .quit => try self.setQuit(),
.new_window => try self.newWindow(rt_app, .{ .parent = null }),
.open_config => try self.openConfig(rt_app), .open_config => try self.openConfig(rt_app),
.reload_config => try self.reloadConfig(rt_app), .reload_config => try self.reloadConfig(rt_app),
.close_all_windows => { .close_all_windows => {

View File

@ -3416,19 +3416,22 @@ fn showMouse(self: *Surface) void {
/// will ever return false. We can expand this in the future if it becomes /// will ever return false. We can expand this in the future if it becomes
/// useful. We did previous/next tab so we could implement #498. /// useful. We did previous/next tab so we could implement #498.
pub fn performBindingAction(self: *Surface, action: input.Binding.Action) !bool { pub fn performBindingAction(self: *Surface, action: input.Binding.Action) !bool {
// Handle app-scoped bindings by sending it to the app. // Forward app-scoped actions to the app. Some app-scoped actions are
switch (action.scope()) { // special-cased here because they do some special things when performed
.app => { // from the surface.
try self.app.performAction( if (action.scoped(.app)) |app_action| {
switch (app_action) {
.new_window => try self.app.newWindow(
self.rt_app,
.{ .parent = self },
),
else => try self.app.performAction(
self.rt_app, self.rt_app,
action.scoped(.app).?, action.scoped(.app).?,
); ),
}
return true; return true;
},
// Surface fallthrough and handle
.surface => {},
} }
switch (action.scoped(.surface).?) { switch (action.scoped(.surface).?) {
@ -3653,8 +3656,6 @@ pub fn performBindingAction(self: *Surface, action: input.Binding.Action) !bool
v, v,
), ),
.new_window => try self.app.newWindow(self.rt_app, .{ .parent = self }),
.new_tab => { .new_tab => {
if (@hasDecl(apprt.Surface, "newTab")) { if (@hasDecl(apprt.Surface, "newTab")) {
try self.rt_surface.newTab(); try self.rt_surface.newTab();

View File

@ -86,7 +86,8 @@ pub const App = struct {
/// New tab with options. /// New tab with options.
new_tab: ?*const fn (SurfaceUD, apprt.Surface.Options) callconv(.C) void = null, new_tab: ?*const fn (SurfaceUD, apprt.Surface.Options) callconv(.C) void = null,
/// New window with options. /// New window with options. The surface may be null if there is no
/// target surface.
new_window: ?*const fn (SurfaceUD, apprt.Surface.Options) callconv(.C) void = null, new_window: ?*const fn (SurfaceUD, apprt.Surface.Options) callconv(.C) void = null,
/// Control the inspector visibility /// Control the inspector visibility
@ -495,14 +496,19 @@ pub const App = struct {
} }
pub fn newWindow(self: *App, parent: ?*CoreSurface) !void { pub fn newWindow(self: *App, parent: ?*CoreSurface) !void {
_ = self; // If we have a parent, the surface logic handles it.
// Right now we only support creating a new window with a parent
// through this code.
// The other case is handled by the embedding runtime.
if (parent) |surface| { if (parent) |surface| {
try surface.rt_surface.newWindow(); try surface.rt_surface.newWindow();
return;
} }
// No parent, call the new window callback.
const func = self.opts.new_window orelse {
log.info("runtime embedder does not support new_window", .{});
return;
};
func(null, .{});
} }
}; };

View File

@ -279,7 +279,8 @@ pub const Action = union(enum) {
/// available values. /// available values.
write_selection_file: WriteScreenAction, write_selection_file: WriteScreenAction,
/// Open a new window. /// Open a new window. If the application isn't currently focused,
/// this will bring it to the front.
new_window: void, new_window: void,
/// Open a new tab. /// Open a new tab.
@ -562,6 +563,10 @@ pub const Action = union(enum) {
.quit, .quit,
=> .app, => .app,
// These are app but can be special-cased in a surface context.
.new_window,
=> .app,
// Obviously surface actions. // Obviously surface actions.
.csi, .csi,
.esc, .esc,
@ -593,12 +598,12 @@ pub const Action = union(enum) {
.toggle_window_decorations, .toggle_window_decorations,
.toggle_secure_input, .toggle_secure_input,
.crash, .crash,
=> .surface,
// These are less obvious surface actions. They're surface // These are less obvious surface actions. They're surface
// actions because they are relevant to the surface they // actions because they are relevant to the surface they
// come from. For example `new_window` needs to be sourced to // come from. For example `new_window` needs to be sourced to
// a surface so inheritance can be done correctly. // a surface so inheritance can be done correctly.
.new_window,
.new_tab, .new_tab,
.previous_tab, .previous_tab,
.next_tab, .next_tab,