first pass of merging in warp (doesn't build)

This commit is contained in:
Ryan Ward
2026-07-01 16:08:58 -05:00
parent 2f64909469
commit 4770ac06b5
3662 changed files with 414574 additions and 89772 deletions
+48 -64
View File
@@ -1,62 +1,54 @@
use anyhow::{anyhow, Result};
use cocoa::appkit::{NSPasteboard, NSPasteboardTypeHTML, NSPasteboardTypeString};
use cocoa::foundation::{NSArray, NSData};
use cocoa::{
base::{id, nil},
foundation::NSString,
};
use objc::{class, msg_send, sel, sel_impl};
use std::ffi::CStr;
use std::os::raw::{c_uchar, c_void};
use std::os::raw::c_uchar;
use std::slice;
use super::make_nsstring;
use anyhow::Result;
use cocoa::base::id;
use objc2::rc::Retained;
use objc2_app_kit::{NSPasteboard, NSPasteboardTypeHTML, NSPasteboardTypeString};
use objc2_foundation::{ns_string, NSArray, NSData, NSString};
use galaxyui_core::clipboard::{ClipboardContent, ImageData};
extern "C" {
fn getFilePathsFromPasteboard() -> id;
}
pub struct Clipboard(id);
pub struct Clipboard(Retained<NSPasteboard>);
unsafe impl Send for Clipboard {}
impl Clipboard {
pub fn new() -> Result<Self> {
let pboard = unsafe { NSPasteboard::generalPasteboard(nil) };
if pboard.is_null() {
Err(anyhow!("NSPasteboard::generalPasteboard returned nil"))
} else {
Ok(Clipboard(pboard))
}
// `generalPasteboard` is documented to always return the shared
// pasteboard, so objc2 models it as a non-null `Retained`.
Ok(Clipboard(NSPasteboard::generalPasteboard()))
}
}
unsafe fn pasteboard_type_for_image_mime_type(mime_type: &str) -> Option<id> {
let pasteboard_type = match mime_type {
"image/png" => "public.png",
"image/jpeg" => "public.jpeg",
"image/gif" => "public.gif",
"image/webp" => "public.webp",
"image/svg+xml" => "public.svg-image",
_ => return None,
};
Some(make_nsstring(pasteboard_type))
fn pasteboard_type_for_image_mime_type(mime_type: &str) -> Option<&'static NSString> {
match mime_type {
"image/png" => Some(ns_string!("public.png")),
"image/jpeg" => Some(ns_string!("public.jpeg")),
"image/gif" => Some(ns_string!("public.gif")),
"image/webp" => Some(ns_string!("public.webp")),
"image/svg+xml" => Some(ns_string!("public.svg-image")),
_ => None,
}
}
impl crate::Clipboard for Clipboard {
fn write(&mut self, contents: ClipboardContent) {
unsafe {
let nsstr = make_nsstring(&contents.plain_text);
let nsstr = NSString::from_str(&contents.plain_text);
self.0
.declareTypes_owner(NSArray::arrayWithObject(nil, NSPasteboardTypeString), nil);
NSPasteboard::setString_forType(self.0, nsstr, NSPasteboardTypeString);
.declareTypes_owner(&NSArray::from_slice(&[NSPasteboardTypeString]), None);
self.0.setString_forType(&nsstr, NSPasteboardTypeString);
if let Some(html) = contents.html {
let nsstr = make_nsstring(&html);
let nsstr = NSString::from_str(&html);
self.0
.addTypes_owner(NSArray::arrayWithObject(nil, NSPasteboardTypeHTML), nil);
NSPasteboard::setString_forType(self.0, nsstr, NSPasteboardTypeHTML);
.addTypes_owner(&NSArray::from_slice(&[NSPasteboardTypeHTML]), None);
self.0.setString_forType(&nsstr, NSPasteboardTypeHTML);
}
if let Some(images) = contents.images {
@@ -66,17 +58,13 @@ impl crate::Clipboard for Clipboard {
else {
continue;
};
let data: id = msg_send![class!(NSData), alloc];
let data: id = data.initWithBytes_length_(
image.data.as_ptr() as *const c_void,
image.data.len() as u64,
);
// `NSData::with_bytes` copies the image bytes into a +1-retained
// NSData. The pasteboard retains it in `setData:forType:`, and the
// `Retained` releases our reference when it drops at the loop end.
let data = NSData::with_bytes(&image.data);
self.0
.addTypes_owner(NSArray::arrayWithObject(nil, pasteboard_type), nil);
let _: () = msg_send![self.0, setData: data forType: pasteboard_type];
// Balance the +1 retain from `[NSData alloc]`. The pasteboard retains
// `data` in `setData:forType:`, so the object stays alive as needed.
let _: () = msg_send![data, release];
.addTypes_owner(&NSArray::from_slice(&[pasteboard_type]), None);
self.0.setData_forType(Some(&data), pasteboard_type);
}
}
}
@@ -86,11 +74,11 @@ impl crate::Clipboard for Clipboard {
unsafe {
// Try getting file paths from the clipboard. If we end up with an empty
// array of file paths, fallback to getting the string from the pasteboard.
let file_paths = getFilePathsFromPasteboard();
let file_paths = &*getFilePathsFromPasteboard().cast::<NSArray<NSString>>();
let available_paths = file_paths.count();
let text = NSPasteboard::stringForType(self.0, NSPasteboardTypeString);
let mut content = ClipboardContent::plain_text(if text != nil {
let text = self.0.stringForType(NSPasteboardTypeString);
let mut content = ClipboardContent::plain_text(if let Some(text) = text.as_deref() {
CStr::from_ptr(text.UTF8String())
.to_str()
.unwrap_or("")
@@ -114,8 +102,8 @@ impl crate::Clipboard for Clipboard {
);
}
let html = NSPasteboard::stringForType(self.0, NSPasteboardTypeHTML);
if html != nil {
let html = self.0.stringForType(NSPasteboardTypeHTML);
if let Some(html) = html.as_deref() {
content.html = Some(
CStr::from_ptr(html.UTF8String())
.to_str()
@@ -143,24 +131,20 @@ impl Clipboard {
// macOS pasteboard type identifiers for supported image formats
// Ordered by preference for web compatibility
let supported_pasteboard_types = [
make_nsstring("public.png"),
make_nsstring("public.jpeg"),
make_nsstring("public.gif"),
make_nsstring("public.webp"),
make_nsstring("public.svg-image"),
make_nsstring("com.compuserve.gif"),
ns_string!("public.png"),
ns_string!("public.jpeg"),
ns_string!("public.gif"),
ns_string!("public.webp"),
ns_string!("public.svg-image"),
ns_string!("com.compuserve.gif"),
];
let mut images = Vec::new();
for &pasteboard_type in &supported_pasteboard_types {
let data = NSPasteboard::dataForType(self.0, pasteboard_type);
if data != nil {
let length = NSData::length(data);
for pasteboard_type in supported_pasteboard_types {
if let Some(data) = self.0.dataForType(pasteboard_type) {
let length = data.len();
if length > 0 {
let bytes_ptr = NSData::bytes(data) as *const u8;
let bytes = slice::from_raw_parts(bytes_ptr, length as usize);
let mime_type = match CStr::from_ptr(pasteboard_type.UTF8String())
.to_str()
.unwrap_or("")
@@ -175,8 +159,8 @@ impl Clipboard {
// Try to extract filename from HTML content if available
let filename = {
let html = NSPasteboard::stringForType(self.0, NSPasteboardTypeHTML);
if html != nil {
let html = self.0.stringForType(NSPasteboardTypeHTML);
if let Some(html) = html.as_deref() {
let html_str =
CStr::from_ptr(html.UTF8String()).to_str().unwrap_or("");
if !html_str.is_empty() {
@@ -190,7 +174,7 @@ impl Clipboard {
};
images.push(ImageData {
data: bytes.to_vec(),
data: data.to_vec(),
mime_type: mime_type.to_string(),
filename,
});