macOS: implement move_tab_to_new_window (#14216)

Closes #2630 for macOS. #13621 added the `move_tab_to_new_window` action
and the GTK side; this does the same on macOS with AppKit.

With native tabs a tab is already a window, so the action forwards to
AppKit's own `moveTabToNewWindow:`. It's a no-op when the window is
alone in its tab group, same as the Window menu item. The "only
implemented on Linux" note comes off the doc comment in `Binding.zig`.
Tested on macOS 26, from a keybind and from the command palette. I have
no macOS 13-15 machine.

Full disclosure, written with Claude Code, I directed it, read every
line, and tested the result.
This commit is contained in:
Lukas
2026-09-13 17:46:00 +02:00
committed by GitHub
2 changed files with 28 additions and 3 deletions

View File

@@ -621,6 +621,9 @@ extension Ghostty {
case GHOSTTY_ACTION_MOVE_TAB:
return moveTab(app, target: target, move: action.action.move_tab)
case GHOSTTY_ACTION_MOVE_TAB_TO_NEW_WINDOW:
return moveTabToNewWindow(app, target: target)
case GHOSTTY_ACTION_GOTO_TAB:
return gotoTab(app, target: target, tab: action.action.goto_tab)
@@ -1278,6 +1281,31 @@ extension Ghostty {
return true
}
private static func moveTabToNewWindow(
_ app: ghostty_app_t,
target: ghostty_target_s) -> Bool {
switch target.tag {
case GHOSTTY_TARGET_APP:
Ghostty.logger.warning("move tab to new window does nothing with an app target")
return false
case GHOSTTY_TARGET_SURFACE:
guard let surface = target.target.surface else { return false }
guard let surfaceView = self.surfaceView(from: surface) else { return false }
// See gotoTab for notes on this check. A lone tab is already
// a window of its own, so there is nothing to move.
guard (surfaceView.window?.tabGroup?.windows.count ?? 0) > 1 else { return false }
surfaceView.window?.moveTabToNewWindow(nil)
default:
assertionFailure()
}
return true
}
private static func gotoTab(
_ app: ghostty_app_t,
target: ghostty_target_s,

View File

@@ -588,9 +588,6 @@ pub const Action = union(enum) {
move_tab: isize,
/// Move a tab to a new window.
///
/// Only implemented on Linux, but there's a native tab menu provided by
/// macOS.
move_tab_to_new_window,
/// Toggle the tab overview.