use std::panic::RefUnwindSafe;
use std::panic::UnwindSafe;
use objc2::rc::{autoreleasepool, Id};
use objc2::runtime::ProtocolObject;
use objc2::{msg_send_id, ClassType};
use objc2_app_kit::{NSPasteboard, NSPasteboardTypeFileURL, NSPasteboardTypeString};
use objc2_foundation::{NSArray, NSString, NSURL};
use crate::common::*;
pub struct OSXClipboardContext {
pasteboard: Id<NSPasteboard>,
}
unsafe impl Send for OSXClipboardContext {}
unsafe impl Sync for OSXClipboardContext {}
impl UnwindSafe for OSXClipboardContext {}
impl RefUnwindSafe for OSXClipboardContext {}
impl OSXClipboardContext {
pub fn new() -> Result<OSXClipboardContext> {
let pasteboard: Option<Id<NSPasteboard>> =
unsafe { msg_send_id![NSPasteboard::class(), generalPasteboard] };
let pasteboard = pasteboard.ok_or("NSPasteboard#generalPasteboard returned null")?;
Ok(OSXClipboardContext { pasteboard })
}
}
impl ClipboardProvider for OSXClipboardContext {
fn get_contents(&mut self) -> Result<String> {
autoreleasepool(|_| {
let types = unsafe { self.pasteboard.types() }.unwrap();
let has_file = unsafe { types.containsObject(NSPasteboardTypeFileURL) };
let has_str = unsafe { types.containsObject(NSPasteboardTypeString) };
if !has_str {
return Err("NSPasteboard#types doesn't contain NSPasteboardTypeString".into());
}
let text = if has_file {
let file_url_string =
unsafe { self.pasteboard.stringForType(NSPasteboardTypeFileURL) }
.ok_or("NSPasteboard#stringForType returned null")?;
let file_url = unsafe { NSURL::URLWithString(&file_url_string) }
.ok_or("NSURL#URLWithString returned null")?;
unsafe { file_url.path() }.ok_or("NSURL#path returned null")?
} else {
unsafe { self.pasteboard.stringForType(NSPasteboardTypeString) }
.ok_or("NSPasteboard#stringForType returned null")?
};
Ok(text.to_string())
})
}
fn set_contents(&mut self, data: String) -> Result<()> {
let string_array =
NSArray::from_vec(vec![ProtocolObject::from_id(NSString::from_str(&data))]);
unsafe { self.pasteboard.clearContents() };
let success = unsafe { self.pasteboard.writeObjects(&string_array) };
if success {
Ok(())
} else {
Err("NSPasteboard#writeObjects: returned false".into())
}
}
}