Phase 3: drag pane past window edge to detach
Extends the existing header-drag gesture (which swaps panes inside the window) with an "outside the window" case: release the drag more than 60px past any viewport edge and the pane detaches into a new window via the same moveToNewWindow path the right-click menu uses. The 60px slop avoids triggering on accidental release over the OS titlebar / window chrome — without it any drag that ended above clientY=0 would fire as a detach, which is wrong because that area is still inside the user's window. No backend changes — Phase 2's transfer mechanism already handles everything; this just wires a second entry point. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
8ad51787fc
commit
6faf7e5e19
3 changed files with 32 additions and 6 deletions
|
|
@ -268,6 +268,12 @@ export default function LeafPane({ leaf }: { leaf: LeafNode }) {
|
|||
[orch.beginHeaderDrag, orch.setHeaderDragOver, leaf.id],
|
||||
);
|
||||
|
||||
/** How far past a viewport edge the cursor must travel before a release
|
||||
* is treated as "drag pane out of window" instead of "drop on empty
|
||||
* space inside this window". Picked so an accidental release on the OS
|
||||
* titlebar (~30px tall) stays inside the threshold. */
|
||||
const PANE_DRAG_OUT_MARGIN = 60;
|
||||
|
||||
const onToolbarPointerUp = useCallback(
|
||||
(e: ReactPointerEvent<HTMLDivElement>) => {
|
||||
const st = dragStartRef.current;
|
||||
|
|
@ -275,12 +281,26 @@ export default function LeafPane({ leaf }: { leaf: LeafNode }) {
|
|||
(e.currentTarget as HTMLElement).releasePointerCapture(e.pointerId);
|
||||
const wasDragging = st.dragging;
|
||||
dragStartRef.current = null;
|
||||
if (wasDragging) {
|
||||
document.body.style.cursor = "";
|
||||
if (!wasDragging) return;
|
||||
document.body.style.cursor = "";
|
||||
|
||||
const releasedFarOutside =
|
||||
e.clientX < -PANE_DRAG_OUT_MARGIN ||
|
||||
e.clientX > window.innerWidth + PANE_DRAG_OUT_MARGIN ||
|
||||
e.clientY < -PANE_DRAG_OUT_MARGIN ||
|
||||
e.clientY > window.innerHeight + PANE_DRAG_OUT_MARGIN;
|
||||
|
||||
if (releasedFarOutside) {
|
||||
// Cancel any in-flight swap state without committing, then pop
|
||||
// this pane into a fresh window. moveToNewWindow handles the
|
||||
// PTY-handoff + closeLeaf in the source.
|
||||
orch.endHeaderDrag(false);
|
||||
orch.moveToNewWindow(leaf.id);
|
||||
} else {
|
||||
orch.endHeaderDrag(true);
|
||||
}
|
||||
},
|
||||
[orch.endHeaderDrag],
|
||||
[orch.endHeaderDrag, orch.moveToNewWindow, leaf.id],
|
||||
);
|
||||
|
||||
const onToolbarPointerCancel = useCallback(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue