Skip to content

Commit 51a2678

Browse files
committed
Keep lastFocusState in sync with AppKit responder focus calls
The becomeFirstResponder, resignFirstResponder, and ctrl-key fast paths call ghostty_surface_set_focus directly without updating lastFocusState. This could cause the dedup guard in setFocus() to skip a needed call, or createSurface() to replay a stale state on surface recreation. Add recordExternalFocusState() and call it alongside each direct C focus call so lastFocusState stays authoritative.
1 parent 328c6d6 commit 51a2678

1 file changed

Lines changed: 10 additions & 0 deletions

File tree

Sources/GhosttyTerminalView.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3680,6 +3680,13 @@ final class TerminalSurface: Identifiable, ObservableObject {
36803680
surfaceView.applyWindowBackgroundIfActive()
36813681
}
36823682

3683+
/// Keep `lastFocusState` in sync when the hosted view's responder chain
3684+
/// calls `ghostty_surface_set_focus` directly (bypassing `setFocus`).
3685+
/// Without this, `createSurface` would replay a stale state on recreation.
3686+
func recordExternalFocusState(_ focused: Bool) {
3687+
lastFocusState = focused
3688+
}
3689+
36833690
func setFocus(_ focused: Bool) {
36843691
// Only send focus events when the state changes to avoid redundant
36853692
// prompt redraws with zsh themes like Powerlevel10k.
@@ -4960,6 +4967,7 @@ class GhosttyNSView: NSView, NSUserInterfaceValidations {
49604967
]
49614968
)
49624969
}
4970+
terminalSurface?.recordExternalFocusState(true)
49634971
ghostty_surface_set_focus(surface, true)
49644972

49654973
// Ghostty only restarts its vsync display link on display-id changes while focused.
@@ -4983,6 +4991,7 @@ class GhosttyNSView: NSView, NSUserInterfaceValidations {
49834991
let now = CACurrentMediaTime()
49844992
let deltaMs = (now - lastScrollEventTime) * 1000
49854993
Self.focusLog("resignFirstResponder: surface=\(terminalSurface?.id.uuidString ?? "nil") deltaSinceScrollMs=\(String(format: "%.2f", deltaMs))")
4994+
terminalSurface?.recordExternalFocusState(false)
49864995
ghostty_surface_set_focus(surface, false)
49874996
}
49884997
return result
@@ -5270,6 +5279,7 @@ class GhosttyNSView: NSView, NSUserInterfaceValidations {
52705279
// This avoids intermittent drops after rapid split close/reparent transitions.
52715280
let flags = event.modifierFlags.intersection(.deviceIndependentFlagsMask)
52725281
if flags.contains(.control) && !flags.contains(.command) && !flags.contains(.option) && !hasMarkedText() {
5282+
terminalSurface?.recordExternalFocusState(true)
52735283
ghostty_surface_set_focus(surface, true)
52745284
var keyEvent = ghostty_input_key_s()
52755285
keyEvent.action = event.isARepeat ? GHOSTTY_ACTION_REPEAT : GHOSTTY_ACTION_PRESS

0 commit comments

Comments
 (0)