mirror of
https://github.com/ghostty-org/ghostty.git
synced 2026-04-23 15:55:19 +00:00
Merge pull request #2485 from axdank/move_current_Tab
gui: add move_current_tab action
This commit is contained in:
@@ -40,6 +40,11 @@ class TerminalController: BaseTerminalController {
|
||||
selector: #selector(onToggleFullscreen),
|
||||
name: Ghostty.Notification.ghosttyToggleFullscreen,
|
||||
object: nil)
|
||||
center.addObserver(
|
||||
self,
|
||||
selector: #selector(onMoveTab),
|
||||
name: .ghosttyMoveTab,
|
||||
object: nil)
|
||||
center.addObserver(
|
||||
self,
|
||||
selector: #selector(onGotoTab),
|
||||
@@ -482,6 +487,44 @@ class TerminalController: BaseTerminalController {
|
||||
|
||||
//MARK: - Notifications
|
||||
|
||||
@objc private func onMoveTab(notification: SwiftUI.Notification) {
|
||||
guard let target = notification.object as? Ghostty.SurfaceView else { return }
|
||||
guard target == self.focusedSurface else { return }
|
||||
guard let window = self.window else { return }
|
||||
|
||||
// Get the move action
|
||||
guard let action = notification.userInfo?[Notification.Name.GhosttyMoveTabKey] as? Ghostty.Action.MoveTab else { return }
|
||||
guard action.amount != 0 else { return }
|
||||
|
||||
// Determine our current selected index
|
||||
guard let windowController = window.windowController else { return }
|
||||
guard let tabGroup = windowController.window?.tabGroup else { return }
|
||||
guard let selectedWindow = tabGroup.selectedWindow else { return }
|
||||
let tabbedWindows = tabGroup.windows
|
||||
guard tabbedWindows.count > 0 else { return }
|
||||
guard let selectedIndex = tabbedWindows.firstIndex(where: { $0 == selectedWindow }) else { return }
|
||||
|
||||
// Determine the final index we want to insert our tab
|
||||
let finalIndex: Int
|
||||
if action.amount < 0 {
|
||||
finalIndex = selectedIndex - min(selectedIndex, -action.amount)
|
||||
} else {
|
||||
let remaining: Int = tabbedWindows.count - 1 - selectedIndex
|
||||
finalIndex = selectedIndex + min(remaining, action.amount)
|
||||
}
|
||||
|
||||
// If our index is the same we do nothing
|
||||
guard finalIndex != selectedIndex else { return }
|
||||
|
||||
// Get our parent
|
||||
let parent = tabbedWindows[finalIndex]
|
||||
|
||||
// Move our current selected window to the proper index
|
||||
tabGroup.removeWindow(selectedWindow)
|
||||
parent.addTabbedWindow(selectedWindow, ordered: action.amount < 0 ? .below : .above)
|
||||
selectedWindow.makeKeyAndOrderFront(nil)
|
||||
}
|
||||
|
||||
@objc private func onGotoTab(notification: SwiftUI.Notification) {
|
||||
guard let target = notification.object as? Ghostty.SurfaceView else { return }
|
||||
guard target == self.focusedSurface else { return }
|
||||
|
||||
15
macos/Sources/Ghostty/Ghostty.Action.swift
Normal file
15
macos/Sources/Ghostty/Ghostty.Action.swift
Normal file
@@ -0,0 +1,15 @@
|
||||
import GhosttyKit
|
||||
|
||||
extension Ghostty {
|
||||
struct Action {}
|
||||
}
|
||||
|
||||
extension Ghostty.Action {
|
||||
struct MoveTab {
|
||||
let amount: Int
|
||||
|
||||
init(c: ghostty_action_move_tab_s) {
|
||||
self.amount = c.amount
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -458,6 +458,9 @@ extension Ghostty {
|
||||
case GHOSTTY_ACTION_TOGGLE_FULLSCREEN:
|
||||
toggleFullscreen(app, target: target, mode: action.action.toggle_fullscreen)
|
||||
|
||||
case GHOSTTY_ACTION_MOVE_TAB:
|
||||
moveTab(app, target: target, move: action.action.move_tab)
|
||||
|
||||
case GHOSTTY_ACTION_GOTO_TAB:
|
||||
gotoTab(app, target: target, tab: action.action.goto_tab)
|
||||
|
||||
@@ -666,6 +669,31 @@ extension Ghostty {
|
||||
appDelegate.toggleVisibility(self)
|
||||
}
|
||||
|
||||
private static func moveTab(
|
||||
_ app: ghostty_app_t,
|
||||
target: ghostty_target_s,
|
||||
move: ghostty_action_move_tab_s) {
|
||||
switch (target.tag) {
|
||||
case GHOSTTY_TARGET_APP:
|
||||
Ghostty.logger.warning("move tab does nothing with an app target")
|
||||
return
|
||||
|
||||
case GHOSTTY_TARGET_SURFACE:
|
||||
guard let surface = target.target.surface else { return }
|
||||
guard let surfaceView = self.surfaceView(from: surface) else { return }
|
||||
NotificationCenter.default.post(
|
||||
name: .ghosttyMoveTab,
|
||||
object: surfaceView,
|
||||
userInfo: [
|
||||
SwiftUI.Notification.Name.GhosttyMoveTabKey: Action.MoveTab(c: move),
|
||||
]
|
||||
)
|
||||
|
||||
default:
|
||||
assertionFailure()
|
||||
}
|
||||
}
|
||||
|
||||
private static func gotoTab(
|
||||
_ app: ghostty_app_t,
|
||||
target: ghostty_target_s,
|
||||
|
||||
@@ -203,8 +203,16 @@ extension Ghostty {
|
||||
|
||||
}
|
||||
|
||||
// MARK: Surface Notifications
|
||||
// MARK: Surface Notification
|
||||
|
||||
extension Notification.Name {
|
||||
/// Goto tab. Has tab index in the userinfo.
|
||||
static let ghosttyMoveTab = Notification.Name("com.mitchellh.ghostty.moveTab")
|
||||
static let GhosttyMoveTabKey = ghosttyMoveTab.rawValue
|
||||
}
|
||||
|
||||
// NOTE: I am moving all of these to Notification.Name extensions over time. This
|
||||
// namespace was the old namespace.
|
||||
extension Ghostty.Notification {
|
||||
/// Used to pass a configuration along when creating a new tab/window/split.
|
||||
static let NewSurfaceConfigKey = "com.mitchellh.ghostty.newSurfaceConfig"
|
||||
|
||||
Reference in New Issue
Block a user