#![deny(unsafe_op_in_unsafe_fn)]
use objc2::rc::Id;
use objc2::runtime::{AnyClass, AnyObject, ProtocolObject};
use objc2::ClassType;
use objc2_app_kit::{NSPasteboard, NSPasteboardTypeString};
use objc2_foundation::{NSArray, NSCopying, NSString};
pub fn get_text_1(pasteboard: &NSPasteboard) -> Option<Id<NSString>> {
unsafe { pasteboard.stringForType(NSPasteboardTypeString) }
}
pub fn get_text_2(pasteboard: &NSPasteboard) -> Option<Id<NSString>> {
let string_class = {
let cls: *const AnyClass = NSString::class();
let cls = cls as *mut AnyObject;
unsafe { Id::from_raw(cls).unwrap() }
};
let class_array = NSArray::from_vec(vec![string_class]);
let objects = unsafe { pasteboard.readObjectsForClasses_options(&class_array, None) };
let obj: *const AnyObject = objects?.first()?;
let obj = obj as *mut NSString;
Some(unsafe { Id::retain(obj) }.unwrap())
}
pub fn set_text(pasteboard: &NSPasteboard, text: &NSString) {
let _ = unsafe { pasteboard.clearContents() };
let obj = ProtocolObject::from_id(text.copy());
let objects = NSArray::from_vec(vec![obj]);
let res = unsafe { pasteboard.writeObjects(&objects) };
if !res {
panic!("Failed writing to pasteboard");
}
}
fn main() {
let pasteboard = unsafe { NSPasteboard::generalPasteboard() };
let impl_1 = get_text_1(&pasteboard);
let impl_2 = get_text_2(&pasteboard);
println!("Pasteboard text from implementation 1 was: {impl_1:?}");
println!("Pasteboard text from implementation 2 was: {impl_2:?}");
assert_eq!(impl_1, impl_2);
let s = NSString::from_str("Hello, world!");
set_text(&pasteboard, &s);
println!("Now the pasteboard text should be: {s:?}");
assert_eq!(Some(s), get_text_1(&pasteboard));
}