Skip to content

Commit 19414bc

Browse files
committed
ui(grid): hand cursor for cmd+drag pane move
Open-hand while Cmd is held over a hovered pane (matches the dashed- border hint), closed-hand once the magnetic drag is in flight. Wired via .backport.pointerStyle on the leaf body; macOS <15 is a no-op, matching the OS floor of the magnetic gesture itself. magneticActive is mirrored from the gesture closures rather than @ObservedObject on the controller so per-tick translation updates don't churn the SwiftUI body. defer-reset on .onEnded covers the case where Cmd is released before the activation distance is hit.
1 parent 12d5f2f commit 19414bc

1 file changed

Lines changed: 23 additions & 0 deletions

File tree

macos/Sources/Features/Splits/TerminalSplitTreeView.swift

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,11 @@ private struct TerminalSplitLeaf: View {
169169
@State private var dropState: DropState = .idle
170170
@State private var isSelfDragging: Bool = false
171171
@State private var hovered: Bool = false
172+
/// True while a Cmd+drag magnetic resize originated from this leaf is in
173+
/// flight. Mirrored from the gesture closures rather than observed on the
174+
/// MagneticDragController so per-tick translation updates don't churn the
175+
/// SwiftUI body. Drives the closed-hand cursor during the actual drag.
176+
@State private var magneticActive: Bool = false
172177

173178
/// Show the focus indicator only inside a split/grid where it carries
174179
/// information — a single full-window surface is unambiguously focused.
@@ -275,6 +280,16 @@ private struct TerminalSplitLeaf: View {
275280
// Cmd+drag = magnetic grid resize. Runs simultaneously so terminal
276281
// selection (plain drag) and surface clicks are unaffected.
277282
.simultaneousGesture(magneticDragGesture)
283+
// Hand cursor for the Cmd+drag move affordance: open-hand the
284+
// moment Cmd is held over a pane (matches the dashed-border hint),
285+
// closed-hand once the drag is actually in flight. nil otherwise
286+
// so the underlying surface cursor (iBeam etc.) is unaffected.
287+
// No-op on macOS < 15 (Backport.pointerStyle returns content
288+
// unchanged), which is acceptable since the magnetic gesture
289+
// itself targets the same OS floor as the rest of the grid UI.
290+
.backport.pointerStyle(
291+
magneticActive ? .grabActive :
292+
(cmdMonitor.isHeld && hovered ? .grabIdle : nil))
278293
.accessibilityElement(children: .contain)
279294
.accessibilityLabel("Terminal pane")
280295
}
@@ -296,12 +311,20 @@ private struct TerminalSplitLeaf: View {
296311
in: rootTree,
297312
rootSize: rootSize)
298313
guard started else { return }
314+
// Flip to closed-hand for the duration of the drag. Set on
315+
// the begin transition only so we don't churn state on every
316+
// tick.
317+
magneticActive = true
299318
}
300319
// Deferred commit: only update the overlay state, do NOT touch the
301320
// surface tree. This avoids per-frame Metal pipeline rebuilds.
302321
magnetic.update(translation: value.translation, location: value.location)
303322
}
304323
.onEnded { _ in
324+
// Always reset the cursor flag on drag end, even if the gesture
325+
// never produced a snapshot (e.g. Cmd was released before the
326+
// activation distance was reached).
327+
defer { magneticActive = false }
305328
guard let snap = magnetic.snapshot else { return }
306329
// Drop priority — first match wins:
307330
// 1. cursor in window edge band → edge snap (source fills that

0 commit comments

Comments
 (0)