gpui: Convert macOS clipboard file URLs to paths for paste
- On macOS, pasting now inserts the actual file path when the clipboard contains a file URL (public.file-url/public.url) - Terminal paste remains text-only; no temp files or data URLs are created. If only raw image bytes exist on the clipboard, paste is a no-op. - Scope: macOS only; no dependency changes. - Added a test (test_file_url_converts_to_path) that verifies URL→path conversion using a unique pasteboard. Release Notes: - On macOS, pasting now inserts the actual file path when the clipboard contains a file URL (enables image paste support for Claude Code)
This commit is contained in:
parent
11545c669e
commit
36ab2f1ede
1 changed files with 70 additions and 0 deletions
|
@ -1103,6 +1103,39 @@ impl Platform for MacPlatform {
|
|||
}
|
||||
}
|
||||
|
||||
// Next, check for file URL flavors and convert to a file system path string.
|
||||
// Some screenshot tools place only a file URL on the clipboard (no plain text).
|
||||
{
|
||||
// Try the modern UTType identifiers first.
|
||||
let file_url_type: id = ns_string("public.file-url");
|
||||
let url_type: id = ns_string("public.url");
|
||||
|
||||
let url_data = if msg_send![types, containsObject: file_url_type] {
|
||||
pasteboard.dataForType(file_url_type)
|
||||
} else if msg_send![types, containsObject: url_type] {
|
||||
pasteboard.dataForType(url_type)
|
||||
} else {
|
||||
nil
|
||||
};
|
||||
|
||||
if url_data != nil && !url_data.bytes().is_null() {
|
||||
let bytes = slice::from_raw_parts(
|
||||
url_data.bytes() as *mut u8,
|
||||
url_data.length() as usize,
|
||||
);
|
||||
if let Ok(text) = std::str::from_utf8(bytes) {
|
||||
// Convert the URL string to a file path if possible.
|
||||
let ns = ns_string(text);
|
||||
let url: id = msg_send![class!(NSURL), URLWithString: ns];
|
||||
if url != nil && msg_send![url, isFileURL] {
|
||||
if let Ok(path) = ns_url_to_path(url) {
|
||||
return Some(ClipboardItem::new_string(path.to_string_lossy().into_owned()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If it wasn't a string, try the various supported image types.
|
||||
for format in ImageFormat::iter() {
|
||||
if let Some(item) = try_clipboard_image(pasteboard, format) {
|
||||
|
@ -1661,6 +1694,43 @@ mod tests {
|
|||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_file_url_converts_to_path() {
|
||||
let platform = build_platform();
|
||||
|
||||
// Create a file URL for an arbitrary test path and write it to the pasteboard.
|
||||
// This path does not need to exist; we only validate URL→path conversion.
|
||||
let mock_path = "/tmp/zed-clipboard-file-url-test";
|
||||
unsafe {
|
||||
// Build an NSURL from the file path
|
||||
let url: id = msg_send![class!(NSURL), fileURLWithPath: ns_string(mock_path)];
|
||||
let abs: id = msg_send![url, absoluteString];
|
||||
|
||||
// Encode the URL string as UTF-8 bytes
|
||||
let len: usize = msg_send![abs, lengthOfBytesUsingEncoding: NSUTF8StringEncoding];
|
||||
let bytes_ptr = abs.UTF8String() as *const u8;
|
||||
let data = NSData::dataWithBytes_length_(
|
||||
nil,
|
||||
bytes_ptr as *const c_void,
|
||||
len as u64,
|
||||
);
|
||||
|
||||
// Write as public.file-url to the unique pasteboard
|
||||
let file_url_type: id = ns_string("public.file-url");
|
||||
platform
|
||||
.0
|
||||
.lock()
|
||||
.pasteboard
|
||||
.setData_forType(data, file_url_type);
|
||||
}
|
||||
|
||||
// Ensure the clipboard read maps the file URL to the expected path string
|
||||
assert_eq!(
|
||||
platform.read_from_clipboard(),
|
||||
Some(ClipboardItem::new_string(mock_path.to_string()))
|
||||
);
|
||||
}
|
||||
|
||||
fn build_platform() -> MacPlatform {
|
||||
let platform = MacPlatform::new(false);
|
||||
platform.0.lock().pasteboard = unsafe { NSPasteboard::pasteboardWithUniqueName(nil) };
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue