summaryrefslogtreecommitdiff
path: root/macos/Sources
diff options
context:
space:
mode:
Diffstat (limited to 'macos/Sources')
-rw-r--r--macos/Sources/Ghostty/SurfaceView_AppKit.swift45
1 files changed, 33 insertions, 12 deletions
diff --git a/macos/Sources/Ghostty/SurfaceView_AppKit.swift b/macos/Sources/Ghostty/SurfaceView_AppKit.swift
index 03c113209..22784d164 100644
--- a/macos/Sources/Ghostty/SurfaceView_AppKit.swift
+++ b/macos/Sources/Ghostty/SurfaceView_AppKit.swift
@@ -1815,18 +1815,39 @@ extension Ghostty.SurfaceView: NSServicesMenuRequestor {
forSendType sendType: NSPasteboard.PasteboardType?,
returnType: NSPasteboard.PasteboardType?
) -> Any? {
- // Types that we accept sent to us
- let accepted: [NSPasteboard.PasteboardType] = [.string, .init("public.utf8-plain-text")]
-
- // We can always receive the accepted types
- if (returnType == nil || accepted.contains(returnType!)) {
- return self
- }
-
- // If we have a selection we can send the accepted types too
- if ((self.surface != nil && ghostty_surface_has_selection(self.surface)) &&
- (sendType == nil || accepted.contains(sendType!))
- ) {
+ // This function confused me a bit so I'm going to add my own commentary on
+ // how this works. macOS sends this callback with the given send/return types and
+ // we must return the responder capable of handling the COMBINATION of those send
+ // and return types (or super up if we can't handle it).
+ //
+ // The "COMBINATION" bit is key: we might get sent a string (we can handle that)
+ // but get requested an image (we can't handle that at the time of writing this),
+ // so we must bubble up.
+
+ // Types we can receive
+ let receivable: [NSPasteboard.PasteboardType] = [.string, .init("public.utf8-plain-text")]
+
+ // Types that we can send. Currently the same as receivable but I'm separating
+ // this out so we can modify this in the future.
+ let sendable: [NSPasteboard.PasteboardType] = receivable
+
+ // The sendable types that require a selection (currently all)
+ let sendableRequiresSelection = sendable
+
+ // If we expect no data to be sent/received we can obviously handle it (that's
+ // the nil check), otherwise it must conform to the types we support on both sides.
+ if (returnType == nil || receivable.contains(returnType!)) &&
+ (sendType == nil || sendable.contains(sendType!)) {
+ // If we're expected to send back a type that requires selection, then
+ // verify that we have a selection. We do this within this block because
+ // validateRequestor is called a LOT and we want to prevent unnecessary
+ // performance hits because `ghostty_surface_has_selection` isn't free.
+ if let sendType, sendableRequiresSelection.contains(sendType) {
+ if surface == nil || !ghostty_surface_has_selection(surface) {
+ return super.validRequestor(forSendType: sendType, returnType: returnType)
+ }
+ }
+
return self
}