Skip to content
51 changes: 16 additions & 35 deletions src/osx_clipboard.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,23 +12,23 @@
// See the License for the specific language governing permissions and
// limitations under the License.

use std::mem::transmute;

use objc::runtime::{Class, Object};
use objc::{msg_send, sel, sel_impl};
use objc_foundation::{INSArray, INSObject, INSString};
use objc_foundation::{NSArray, NSDictionary, NSObject, NSString};
use objc_id::{Id, Owned};

use crate::common::*;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The whitespace before crate imports was intentional. Same as the whitespace after std. This way the alphabetic ordering doesn't get in the way of the logical ordering of relevance.

Please revert the removal of whitespace before the crate::common import.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

use objc::rc::autoreleasepool;
use objc::runtime::{Class, Object, Sel};
use objc::{msg_send, sel, sel_impl};
use objc_foundation::{INSArray, INSString};
use objc_foundation::{NSArray, NSString};
use objc_id::Id;
Comment thread
chrisduerr marked this conversation as resolved.

pub struct OSXClipboardContext {
pasteboard: Id<Object>,
}

// required to bring NSPasteboard into the path of the class-resolver
#[link(name = "AppKit", kind = "framework")]
extern "C" {}
extern "C" {
pub static NSPasteboardTypeString: Sel;
}

impl OSXClipboardContext {
pub fn new() -> Result<OSXClipboardContext> {
Expand All @@ -44,30 +44,19 @@ impl OSXClipboardContext {

impl ClipboardProvider for OSXClipboardContext {
fn get_contents(&mut self) -> Result<String> {
let string_class: Id<NSObject> = {
let cls: Id<Class> = unsafe { Id::from_ptr(class("NSString")) };
unsafe { transmute(cls) }
};
let classes: Id<NSArray<NSObject, Owned>> = NSArray::from_vec(vec![string_class]);
let options: Id<NSDictionary<NSObject, NSObject>> = NSDictionary::new();
let string_array: Id<NSArray<NSString>> = unsafe {
let obj: *mut NSArray<NSString> =
msg_send![self.pasteboard, readObjectsForClasses:&*classes options:&*options];
if obj.is_null() {
return Err("pasteboard#readObjectsForClasses:options: returned null".into());
}
Id::from_ptr(obj)
};
if string_array.count() == 0 {
Err("pasteboard#readObjectsForClasses:options: returned empty".into())
let nsstring: *mut NSString =
unsafe { msg_send![self.pasteboard, stringForType: NSPasteboardTypeString] };
if nsstring.is_null() {
Err("pasteboard#stringForType returned null".into())
} else {
Ok(string_array[0].as_str().to_owned())
let nsstring: Id<NSString> = unsafe { Id::from_retained_ptr(nsstring) };
Ok(autoreleasepool(|| nsstring.as_str().to_owned()))
Comment thread
chrisduerr marked this conversation as resolved.
}
}

fn set_contents(&mut self, data: String) -> Result<()> {
let string_array = NSArray::from_vec(vec![NSString::from_str(&data)]);
let _: usize = unsafe { msg_send![self.pasteboard, clearContents] };
let _: () = unsafe { msg_send![self.pasteboard, clearContents] };
Comment thread
chrisduerr marked this conversation as resolved.
Outdated
let success: bool = unsafe { msg_send![self.pasteboard, writeObjects: string_array] };
if success {
Ok(())
Expand All @@ -76,11 +65,3 @@ impl ClipboardProvider for OSXClipboardContext {
}
}
}

// this is a convenience function that both cocoa-rs and
// glutin define, which seems to depend on the fact that
// Option::None has the same representation as a null pointer
#[inline]
pub fn class(name: &str) -> *mut Class {
unsafe { transmute(Class::get(name)) }
}