macos: defer overlapping clipboard completion

Fixes #/13074

Overlapping clipboard confirmations now defer denial until the next
main queue turn rather than completing inside the confirmation callback.

This prevents the native request state from being invalidated while its
callback is still active, avoiding the OSC 52 crash reported in #13074.

The deferred closure retains the originating surface view and completes
the ignored request with empty data, preserving the existing deny
behavior.
This commit is contained in:
Mitchell Hashimoto
2026-08-05 14:22:45 -07:00
parent 880eded158
commit 57c1baf43a

View File

@@ -1156,10 +1156,14 @@ class BaseTerminalController: NSWindowController,
guard let state = notification.userInfo?[Ghostty.Notification.ConfirmClipboardStateKey] as? UnsafeMutableRawPointer? else { return }
guard let request = notification.userInfo?[Ghostty.Notification.ConfirmClipboardRequestKey] as? Ghostty.ClipboardRequest else { return }
// If we already have a clipboard confirmation view up, we ignore this request.
// This shouldn't be possible...
// If we already have a clipboard confirmation view up, ignore this
// request. Complete it on the next run loop iteration so that we don't
// invalidate the state pointer from inside its confirmation callback.
guard self.clipboardConfirmation == nil else {
Ghostty.App.completeClipboardRequest(surface, data: "", state: state, confirmed: true)
DispatchQueue.main.async {
guard let surface = target.surface else { return }
Ghostty.App.completeClipboardRequest(surface, data: "", state: state, confirmed: true)
}
return
}