mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-12-31 18:52:12 +00:00
macos: open dragged windows where they are dropped
This commit is contained in:
@@ -734,6 +734,9 @@ class BaseTerminalController: NSWindowController,
|
||||
// it is already a single split.
|
||||
guard surfaceTree.isSplit else { return }
|
||||
|
||||
// Extract the drop position from the notification
|
||||
let dropPoint = notification.userInfo?[Notification.Name.ghosttySurfaceDragEndedNoTargetPointKey] as? NSPoint
|
||||
|
||||
// Remove the surface from our tree
|
||||
let removedTree = surfaceTree.remove(targetNode)
|
||||
|
||||
@@ -748,7 +751,7 @@ class BaseTerminalController: NSWindowController,
|
||||
}
|
||||
|
||||
replaceSurfaceTree(removedTree, moveFocusFrom: focusedSurface)
|
||||
_ = TerminalController.newWindow(ghostty, tree: newTree)
|
||||
_ = TerminalController.newWindow(ghostty, tree: newTree, position: dropPoint)
|
||||
}
|
||||
|
||||
// MARK: Local Events
|
||||
|
||||
@@ -277,9 +277,15 @@ class TerminalController: BaseTerminalController, TabGroupCloseCoordinator.Contr
|
||||
|
||||
/// Create a new window with an existing split tree.
|
||||
/// The window will be sized to match the tree's current view bounds if available.
|
||||
/// - Parameters:
|
||||
/// - ghostty: The Ghostty app instance.
|
||||
/// - tree: The split tree to use for the new window.
|
||||
/// - position: Optional screen position (top-left corner) for the new window.
|
||||
/// If nil, the window will cascade from the last cascade point.
|
||||
static func newWindow(
|
||||
_ ghostty: Ghostty.App,
|
||||
tree: SplitTree<Ghostty.SurfaceView>
|
||||
tree: SplitTree<Ghostty.SurfaceView>,
|
||||
position: NSPoint? = nil
|
||||
) -> TerminalController {
|
||||
let c = TerminalController.init(ghostty, withSurfaceTree: tree)
|
||||
|
||||
@@ -295,7 +301,12 @@ class TerminalController: BaseTerminalController, TabGroupCloseCoordinator.Contr
|
||||
}
|
||||
|
||||
if !window.styleMask.contains(.fullScreen) {
|
||||
Self.lastCascadePoint = window.cascadeTopLeft(from: Self.lastCascadePoint)
|
||||
if let position {
|
||||
window.setFrameTopLeftPoint(position)
|
||||
window.constrainToScreen()
|
||||
} else {
|
||||
Self.lastCascadePoint = window.cascadeTopLeft(from: Self.lastCascadePoint)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -177,7 +177,11 @@ extension Ghostty {
|
||||
}
|
||||
|
||||
onDragStateChanged?(true)
|
||||
beginDraggingSession(with: [item], event: event, source: self)
|
||||
let session = beginDraggingSession(with: [item], event: event, source: self)
|
||||
|
||||
// We need to disable this so that endedAt happens immediately for our
|
||||
// drags outside of any targets.
|
||||
session.animatesToStartingPositionsOnCancelOrFail = false
|
||||
}
|
||||
|
||||
// MARK: NSDraggingSource
|
||||
@@ -229,7 +233,8 @@ extension Ghostty {
|
||||
if !endsInWindow {
|
||||
NotificationCenter.default.post(
|
||||
name: .ghosttySurfaceDragEndedNoTarget,
|
||||
object: surfaceView
|
||||
object: surfaceView,
|
||||
userInfo: [Foundation.Notification.Name.ghosttySurfaceDragEndedNoTargetPointKey: screenPoint]
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -245,4 +250,7 @@ extension Notification.Name {
|
||||
/// released outside a valid drop target) and was not cancelled by the user
|
||||
/// pressing escape. The notification's object is the SurfaceView that was dragged.
|
||||
static let ghosttySurfaceDragEndedNoTarget = Notification.Name("ghosttySurfaceDragEndedNoTarget")
|
||||
|
||||
/// Key for the screen point where the drag ended in the userInfo dictionary.
|
||||
static let ghosttySurfaceDragEndedNoTargetPointKey = "endedAtPoint"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user