mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-08-02 14:57:31 +03:00
apprt/embedded: new_window can be called without a parent
This commit is contained in:
@ -78,6 +78,12 @@ class TerminalManager {
|
||||
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
|
||||
// take effect. Our best theory is there is some next-event-loop-tick logic
|
||||
// that Cocoa is doing that we need to be after.
|
||||
|
@ -631,7 +631,11 @@ extension Ghostty {
|
||||
}
|
||||
|
||||
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(
|
||||
name: Notification.ghosttyNewWindow,
|
||||
|
@ -317,6 +317,7 @@ pub fn performAction(
|
||||
.unbind => unreachable,
|
||||
.ignore => {},
|
||||
.quit => try self.setQuit(),
|
||||
.new_window => try self.newWindow(rt_app, .{ .parent = null }),
|
||||
.open_config => try self.openConfig(rt_app),
|
||||
.reload_config => try self.reloadConfig(rt_app),
|
||||
.close_all_windows => {
|
||||
|
@ -3416,19 +3416,22 @@ fn showMouse(self: *Surface) void {
|
||||
/// 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.
|
||||
pub fn performBindingAction(self: *Surface, action: input.Binding.Action) !bool {
|
||||
// Handle app-scoped bindings by sending it to the app.
|
||||
switch (action.scope()) {
|
||||
.app => {
|
||||
try self.app.performAction(
|
||||
// Forward app-scoped actions to the app. Some app-scoped actions are
|
||||
// special-cased here because they do some special things when performed
|
||||
// from the surface.
|
||||
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,
|
||||
action.scoped(.app).?,
|
||||
);
|
||||
|
||||
return true;
|
||||
},
|
||||
|
||||
// Surface fallthrough and handle
|
||||
.surface => {},
|
||||
),
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
switch (action.scoped(.surface).?) {
|
||||
@ -3653,8 +3656,6 @@ pub fn performBindingAction(self: *Surface, action: input.Binding.Action) !bool
|
||||
v,
|
||||
),
|
||||
|
||||
.new_window => try self.app.newWindow(self.rt_app, .{ .parent = self }),
|
||||
|
||||
.new_tab => {
|
||||
if (@hasDecl(apprt.Surface, "newTab")) {
|
||||
try self.rt_surface.newTab();
|
||||
|
@ -86,7 +86,8 @@ pub const App = struct {
|
||||
/// New tab with options.
|
||||
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,
|
||||
|
||||
/// Control the inspector visibility
|
||||
@ -495,14 +496,19 @@ pub const App = struct {
|
||||
}
|
||||
|
||||
pub fn newWindow(self: *App, parent: ?*CoreSurface) !void {
|
||||
_ = self;
|
||||
|
||||
// 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 we have a parent, the surface logic handles it.
|
||||
if (parent) |surface| {
|
||||
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, .{});
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -279,7 +279,8 @@ pub const Action = union(enum) {
|
||||
/// available values.
|
||||
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,
|
||||
|
||||
/// Open a new tab.
|
||||
@ -562,6 +563,10 @@ pub const Action = union(enum) {
|
||||
.quit,
|
||||
=> .app,
|
||||
|
||||
// These are app but can be special-cased in a surface context.
|
||||
.new_window,
|
||||
=> .app,
|
||||
|
||||
// Obviously surface actions.
|
||||
.csi,
|
||||
.esc,
|
||||
@ -593,12 +598,12 @@ pub const Action = union(enum) {
|
||||
.toggle_window_decorations,
|
||||
.toggle_secure_input,
|
||||
.crash,
|
||||
=> .surface,
|
||||
|
||||
// These are less obvious surface actions. They're surface
|
||||
// actions because they are relevant to the surface they
|
||||
// come from. For example `new_window` needs to be sourced to
|
||||
// a surface so inheritance can be done correctly.
|
||||
.new_window,
|
||||
.new_tab,
|
||||
.previous_tab,
|
||||
.next_tab,
|
||||
|
Reference in New Issue
Block a user