Merge pull request #10363 from manaflow-ai/issue-10103-copy-mode-selection-bleed
Fix terminal Copy Mode selection scope across split panes
This commit is contained in:
+3
@@ -27,6 +27,9 @@ public protocol TerminalSurfaceNativeViewing: NSView, TerminalSurfaceHosting {
|
||||
@discardableResult
|
||||
func toggleKeyboardCopyMode() -> Bool
|
||||
|
||||
/// Ends keyboard copy mode and clears its selection when focus leaves the view.
|
||||
func cancelKeyboardCopyMode()
|
||||
|
||||
/// Re-applies the window background for the active surface.
|
||||
func applyWindowBackgroundIfActive()
|
||||
|
||||
|
||||
+3
@@ -21,6 +21,9 @@ extension TerminalSurface {
|
||||
/// Applies a focus state to the runtime surface (deduplicated).
|
||||
@MainActor
|
||||
public func setFocus(_ focused: Bool, force: Bool = false) {
|
||||
if !focused {
|
||||
surfaceView.cancelKeyboardCopyMode()
|
||||
}
|
||||
// Only send focus events when the state changes to avoid redundant
|
||||
// prompt redraws with zsh themes like Powerlevel10k.
|
||||
guard force || focused != desiredFocusState else { return }
|
||||
|
||||
+6
-1
@@ -9,7 +9,8 @@ final class FakeTerminalSurfaceNativeView: NSView {
|
||||
weak var attachedController: (any TerminalSurfaceControlling)?
|
||||
var attachedSurfaceController: (any TerminalSurfaceControlling)? { attachedController }
|
||||
var currentKeyStateIndicatorText: String? { nil }
|
||||
var isKeyboardCopyModeActive: Bool { false }
|
||||
var isKeyboardCopyModeActive = false
|
||||
private(set) var keyboardCopyModeCancellationCount = 0
|
||||
var shouldDeferRuntimeInput = false
|
||||
var runtimeInputDeferralResponses: [Bool] = []
|
||||
var runtimeInputDeferralCallCount = 0
|
||||
@@ -18,6 +19,10 @@ final class FakeTerminalSurfaceNativeView: NSView {
|
||||
var mobileMouseButtonEvents: [String] = []
|
||||
|
||||
func toggleKeyboardCopyMode() -> Bool { false }
|
||||
func cancelKeyboardCopyMode() {
|
||||
keyboardCopyModeCancellationCount += 1
|
||||
isKeyboardCopyModeActive = false
|
||||
}
|
||||
func applyWindowBackgroundIfActive() {}
|
||||
func forceRefreshSurface() -> Bool { true }
|
||||
func runtimeSurfaceDidBecomeReady() {}
|
||||
|
||||
+12
@@ -184,6 +184,18 @@ struct TerminalSurfaceExplicitInputTests {
|
||||
#expect(fixture.paneHost.explicitInputCount == 1)
|
||||
}
|
||||
|
||||
@Test func losingFocusCancelsKeyboardCopyModeOnTheSurface() {
|
||||
let fixture = makeFixture()
|
||||
defer { fixture.surface.releaseSurfaceForTesting() }
|
||||
fixture.nativeView.isKeyboardCopyModeActive = true
|
||||
|
||||
fixture.surface.setFocus(true)
|
||||
fixture.surface.setFocus(false)
|
||||
|
||||
#expect(fixture.nativeView.keyboardCopyModeCancellationCount == 1)
|
||||
#expect(!fixture.nativeView.isKeyboardCopyModeActive)
|
||||
}
|
||||
|
||||
@Test func mobileGesturesNotifyPaneHost() {
|
||||
let fixture = makeFixture()
|
||||
defer { fixture.surface.releaseSurfaceForTesting() }
|
||||
|
||||
@@ -4521,6 +4521,14 @@ class GhosttyNSView: NSView, NSUserInterfaceValidations {
|
||||
return true
|
||||
}
|
||||
|
||||
func cancelKeyboardCopyMode() {
|
||||
guard keyboardCopyModeActive else { return }
|
||||
if let surface {
|
||||
_ = GhosttyRuntimeCInterop.clearSelection(surface)
|
||||
}
|
||||
setKeyboardCopyModeActive(false)
|
||||
}
|
||||
|
||||
private func setKeyboardCopyModeActive(_ active: Bool) {
|
||||
keyboardCopyModeInputState.reset()
|
||||
keyboardCopyModeSelectionKind = nil
|
||||
@@ -5341,6 +5349,7 @@ class GhosttyNSView: NSView, NSUserInterfaceValidations {
|
||||
imeConsumedKeyUps.removeAll()
|
||||
manualNamedKeyConsumedKeyUps.removeAll()
|
||||
desiredFocus = false
|
||||
cancelKeyboardCopyMode()
|
||||
terminalSurface?.hostedView.cancelSuppressedFirstResponderFocusReapply()
|
||||
terminalSurface?.recordExternalFocusState(false)
|
||||
}
|
||||
@@ -10105,6 +10114,9 @@ final class GhosttySurfaceScrollView: NSView {
|
||||
|
||||
func setActive(_ active: Bool) {
|
||||
let wasActive = isActive
|
||||
if !active {
|
||||
surfaceView.cancelKeyboardCopyMode()
|
||||
}
|
||||
isActive = active
|
||||
#if DEBUG
|
||||
if wasActive != active {
|
||||
|
||||
Reference in New Issue
Block a user