Preserve terminal focus for non-focus split opens
This commit is contained in:
parent
3afa345f3a
commit
4ee6640e35
2 changed files with 84 additions and 2 deletions
|
|
@ -960,6 +960,7 @@ final class Workspace: Identifiable, ObservableObject {
|
|||
isPinned: false
|
||||
)
|
||||
surfaceIdToPanelId[newTab.id] = newPanel.id
|
||||
let previousFocusedPanelId = focusedPanelId
|
||||
|
||||
// Capture the source terminal's hosted view before bonsplit mutates focusedPaneId,
|
||||
// so we can hand it to focusPanel as the "move focus FROM" view.
|
||||
|
|
@ -989,7 +990,17 @@ final class Workspace: Identifiable, ObservableObject {
|
|||
previousHostedView?.clearSuppressReparentFocus()
|
||||
}
|
||||
} else {
|
||||
scheduleFocusReconcile()
|
||||
// Bonsplit focuses the newly-created pane by default; restore the caller's
|
||||
// pre-split focus context when this split is explicitly non-focus-intent.
|
||||
if let previousFocusedPanelId, panels[previousFocusedPanelId] != nil {
|
||||
previousHostedView?.suppressReparentFocus()
|
||||
focusPanel(previousFocusedPanelId, previousHostedView: previousHostedView)
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + 0.05) {
|
||||
previousHostedView?.clearSuppressReparentFocus()
|
||||
}
|
||||
} else {
|
||||
scheduleFocusReconcile()
|
||||
}
|
||||
}
|
||||
|
||||
return newPanel
|
||||
|
|
@ -1089,6 +1100,7 @@ final class Workspace: Identifiable, ObservableObject {
|
|||
isPinned: false
|
||||
)
|
||||
surfaceIdToPanelId[newTab.id] = browserPanel.id
|
||||
let previousFocusedPanelId = focusedPanelId
|
||||
|
||||
// Create the split with the browser tab already present.
|
||||
// Mark this split as programmatic so didSplitPane doesn't auto-create a terminal.
|
||||
|
|
@ -1110,7 +1122,17 @@ final class Workspace: Identifiable, ObservableObject {
|
|||
previousHostedView?.clearSuppressReparentFocus()
|
||||
}
|
||||
} else {
|
||||
scheduleFocusReconcile()
|
||||
// Bonsplit focuses the newly-created pane by default; restore the caller's
|
||||
// pre-split focus context when this split is explicitly non-focus-intent.
|
||||
if let previousFocusedPanelId, panels[previousFocusedPanelId] != nil {
|
||||
previousHostedView?.suppressReparentFocus()
|
||||
focusPanel(previousFocusedPanelId, previousHostedView: previousHostedView)
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + 0.05) {
|
||||
previousHostedView?.clearSuppressReparentFocus()
|
||||
}
|
||||
} else {
|
||||
scheduleFocusReconcile()
|
||||
}
|
||||
}
|
||||
|
||||
installBrowserPanelSubscription(browserPanel)
|
||||
|
|
|
|||
|
|
@ -1800,6 +1800,66 @@ final class TabManagerReopenClosedBrowserFocusTests: XCTestCase {
|
|||
|
||||
@MainActor
|
||||
final class WorkspacePanelGitBranchTests: XCTestCase {
|
||||
private func drainMainQueue() {
|
||||
let expectation = expectation(description: "drain main queue")
|
||||
DispatchQueue.main.async {
|
||||
expectation.fulfill()
|
||||
}
|
||||
wait(for: [expectation], timeout: 1.0)
|
||||
}
|
||||
|
||||
func testBrowserSplitWithFocusFalsePreservesOriginalFocusedPanel() {
|
||||
let workspace = Workspace()
|
||||
guard let originalFocusedPanelId = workspace.focusedPanelId else {
|
||||
XCTFail("Expected initial focused panel")
|
||||
return
|
||||
}
|
||||
|
||||
guard let browserSplitPanel = workspace.newBrowserSplit(
|
||||
from: originalFocusedPanelId,
|
||||
orientation: .horizontal,
|
||||
focus: false
|
||||
) else {
|
||||
XCTFail("Expected browser split panel to be created")
|
||||
return
|
||||
}
|
||||
|
||||
drainMainQueue()
|
||||
|
||||
XCTAssertNotEqual(browserSplitPanel.id, originalFocusedPanelId)
|
||||
XCTAssertEqual(
|
||||
workspace.focusedPanelId,
|
||||
originalFocusedPanelId,
|
||||
"Expected non-focus browser split to preserve pre-split focus"
|
||||
)
|
||||
}
|
||||
|
||||
func testTerminalSplitWithFocusFalsePreservesOriginalFocusedPanel() {
|
||||
let workspace = Workspace()
|
||||
guard let originalFocusedPanelId = workspace.focusedPanelId else {
|
||||
XCTFail("Expected initial focused panel")
|
||||
return
|
||||
}
|
||||
|
||||
guard let terminalSplitPanel = workspace.newTerminalSplit(
|
||||
from: originalFocusedPanelId,
|
||||
orientation: .horizontal,
|
||||
focus: false
|
||||
) else {
|
||||
XCTFail("Expected terminal split panel to be created")
|
||||
return
|
||||
}
|
||||
|
||||
drainMainQueue()
|
||||
|
||||
XCTAssertNotEqual(terminalSplitPanel.id, originalFocusedPanelId)
|
||||
XCTAssertEqual(
|
||||
workspace.focusedPanelId,
|
||||
originalFocusedPanelId,
|
||||
"Expected non-focus terminal split to preserve pre-split focus"
|
||||
)
|
||||
}
|
||||
|
||||
func testClosingFocusedSplitRestoresBranchForRemainingFocusedPanel() {
|
||||
let workspace = Workspace()
|
||||
guard let firstPanelId = workspace.focusedPanelId else {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue