diff --git a/espanso-clipboard/build.rs b/espanso-clipboard/build.rs
index 325e9ac..3d50903 100644
--- a/espanso-clipboard/build.rs
+++ b/espanso-clipboard/build.rs
@@ -61,12 +61,12 @@ fn cc_config() {
#[cfg(target_os = "macos")]
fn cc_config() {
- println!("cargo:rerun-if-changed=src/mac/native.mm");
- println!("cargo:rerun-if-changed=src/mac/native.h");
+ println!("cargo:rerun-if-changed=src/cocoa/native.mm");
+ println!("cargo:rerun-if-changed=src/cocoa/native.h");
cc::Build::new()
.cpp(true)
- .include("src/mac/native.h")
- .file("src/mac/native.mm")
+ .include("src/cocoa/native.h")
+ .file("src/cocoa/native.mm")
.compile("espansoclipboard");
println!("cargo:rustc-link-lib=dylib=c++");
println!("cargo:rustc-link-lib=static=espansoclipboard");
diff --git a/espanso-clipboard/src/cocoa/ffi.rs b/espanso-clipboard/src/cocoa/ffi.rs
new file mode 100644
index 0000000..9528786
--- /dev/null
+++ b/espanso-clipboard/src/cocoa/ffi.rs
@@ -0,0 +1,28 @@
+/*
+ * This file is part of espanso.
+ *
+ * Copyright (C) 2019-2021 Federico Terzi
+ *
+ * espanso is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * espanso is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with espanso. If not, see .
+ */
+
+use std::os::raw::c_char;
+
+#[link(name = "espansoclipboard", kind = "static")]
+extern "C" {
+ pub fn clipboard_get_text(buffer: *mut c_char, buffer_size: i32) -> i32;
+ pub fn clipboard_set_text(text: *const c_char) -> i32;
+ pub fn clipboard_set_image(image_path: *const c_char) -> i32;
+ pub fn clipboard_set_html(html_descriptor: *const c_char, fallback_text: *const c_char) -> i32;
+}
diff --git a/espanso-clipboard/src/cocoa/mod.rs b/espanso-clipboard/src/cocoa/mod.rs
new file mode 100644
index 0000000..3add22e
--- /dev/null
+++ b/espanso-clipboard/src/cocoa/mod.rs
@@ -0,0 +1,100 @@
+/*
+ * This file is part of espanso.
+ *
+ * Copyright (C) 2019-2021 Federico Terzi
+ *
+ * espanso is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * espanso is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with espanso. If not, see .
+ */
+
+mod ffi;
+
+use std::{ffi::{CStr, CString}, path::PathBuf};
+
+use crate::Clipboard;
+use anyhow::Result;
+use log::error;
+use thiserror::Error;
+
+pub struct CocoaClipboard {}
+
+impl CocoaClipboard {
+ pub fn new() -> Result {
+ Ok(Self {})
+ }
+}
+
+impl Clipboard for CocoaClipboard {
+ fn get_text(&self) -> Option {
+ let mut buffer: [i8; 2048] = [0; 2048];
+ let native_result =
+ unsafe { ffi::clipboard_get_text(buffer.as_mut_ptr(), (buffer.len() - 1) as i32) };
+ if native_result > 0 {
+ let string = unsafe { CStr::from_ptr(buffer.as_ptr()) };
+ Some(string.to_string_lossy().to_string())
+ } else {
+ None
+ }
+ }
+
+ fn set_text(&self, text: &str) -> anyhow::Result<()> {
+ let string = CString::new(text)?;
+ let native_result = unsafe { ffi::clipboard_set_text(string.as_ptr()) };
+ if native_result > 0 {
+ Ok(())
+ } else {
+ Err(CocoaClipboardError::SetOperationFailed().into())
+ }
+ }
+
+ fn set_image(&self, image_path: &std::path::Path) -> anyhow::Result<()> {
+ if !image_path.exists() || !image_path.is_file() {
+ return Err(CocoaClipboardError::ImageNotFound(image_path.to_path_buf()).into());
+ }
+
+ let path = CString::new(image_path.to_string_lossy().to_string())?;
+ let native_result = unsafe { ffi::clipboard_set_image(path.as_ptr()) };
+
+ if native_result > 0 {
+ Ok(())
+ } else {
+ Err(CocoaClipboardError::SetOperationFailed().into())
+ }
+ }
+
+ fn set_html(&self, html: &str, fallback_text: Option<&str>) -> anyhow::Result<()> {
+ let html_string = CString::new(html)?;
+ let fallback_string = CString::new(fallback_text.unwrap_or_default())?;
+ let fallback_ptr = if fallback_text.is_some() {
+ fallback_string.as_ptr()
+ } else {
+ std::ptr::null()
+ };
+
+ let native_result = unsafe { ffi::clipboard_set_html(html_string.as_ptr(), fallback_ptr) };
+ if native_result > 0 {
+ Ok(())
+ } else {
+ Err(CocoaClipboardError::SetOperationFailed().into())
+ }
+ }
+}
+
+#[derive(Error, Debug)]
+pub enum CocoaClipboardError {
+ #[error("clipboard set operation failed")]
+ SetOperationFailed(),
+
+ #[error("image not found: `{0}`")]
+ ImageNotFound(PathBuf),
+}
diff --git a/espanso-clipboard/src/cocoa/native.h b/espanso-clipboard/src/cocoa/native.h
new file mode 100644
index 0000000..f22c0e8
--- /dev/null
+++ b/espanso-clipboard/src/cocoa/native.h
@@ -0,0 +1,30 @@
+/*
+ * This file is part of espanso.
+ *
+ * Copyright (C) 2019-2021 Federico Terzi
+ *
+ * espanso is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * espanso is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with espanso. If not, see .
+ */
+
+#ifndef ESPANSO_CLIPBOARD_H
+#define ESPANSO_CLIPBOARD_H
+
+#include
+
+extern "C" int32_t clipboard_get_text(char * buffer, int32_t buffer_size);
+extern "C" int32_t clipboard_set_text(char * text);
+extern "C" int32_t clipboard_set_image(char * image_path);
+extern "C" int32_t clipboard_set_html(char * html, char * fallback_text);
+
+#endif //ESPANSO_CLIPBOARD_H
\ No newline at end of file
diff --git a/espanso-clipboard/src/cocoa/native.mm b/espanso-clipboard/src/cocoa/native.mm
new file mode 100644
index 0000000..b60f56d
--- /dev/null
+++ b/espanso-clipboard/src/cocoa/native.mm
@@ -0,0 +1,87 @@
+/*
+ * This file is part of espanso.
+ *
+ * Copyright (C) 2019-2021 Federico Terzi
+ *
+ * espanso is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * espanso is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with espanso. If not, see .
+ */
+
+#include "native.h"
+#import
+#import
+#include
+
+int32_t clipboard_get_text(char * buffer, int32_t buffer_size) {
+ NSPasteboard *pasteboard = [NSPasteboard generalPasteboard];
+ for (id element in pasteboard.pasteboardItems) {
+ NSString *string = [element stringForType: NSPasteboardTypeString];
+ if (string != NULL) {
+ const char * text = [string UTF8String];
+ strncpy(buffer, text, buffer_size);
+
+ [string release];
+
+ return 1;
+ }
+ }
+ return 0;
+}
+
+int32_t clipboard_set_text(char * text) {
+ NSPasteboard *pasteboard = [NSPasteboard generalPasteboard];
+ NSArray *array = @[NSPasteboardTypeString];
+ [pasteboard declareTypes:array owner:nil];
+
+ NSString *nsText = [NSString stringWithUTF8String:text];
+ [pasteboard setString:nsText forType:NSPasteboardTypeString];
+}
+
+int32_t clipboard_set_image(char * image_path) {
+ NSString *pathString = [NSString stringWithUTF8String:image_path];
+ NSImage *image = [[NSImage alloc] initWithContentsOfFile:pathString];
+ int result = 0;
+
+ if (image != nil) {
+ NSPasteboard *pasteboard = [NSPasteboard generalPasteboard];
+ [pasteboard clearContents];
+ NSArray *copiedObjects = [NSArray arrayWithObject:image];
+ [pasteboard writeObjects:copiedObjects];
+ result = 1;
+ }
+ [image release];
+
+ return result;
+}
+
+int32_t clipboard_set_html(char * html, char * fallback_text) {
+ NSPasteboard *pasteboard = [NSPasteboard generalPasteboard];
+ NSArray *array = @[NSRTFPboardType, NSPasteboardTypeString];
+ [pasteboard declareTypes:array owner:nil];
+
+ NSString *nsHtml = [NSString stringWithUTF8String:html];
+ NSDictionary *documentAttributes = [NSDictionary dictionaryWithObjectsAndKeys:NSHTMLTextDocumentType, NSDocumentTypeDocumentAttribute, NSCharacterEncodingDocumentAttribute,[NSNumber numberWithInt:NSUTF8StringEncoding], nil];
+ NSAttributedString* atr = [[NSAttributedString alloc] initWithData:[nsHtml dataUsingEncoding:NSUTF8StringEncoding] options:documentAttributes documentAttributes:nil error:nil];
+
+ NSData *rtf = [atr RTFFromRange:NSMakeRange(0, [atr length])
+ documentAttributes:nil];
+
+ [pasteboard setData:rtf forType:NSRTFPboardType];
+
+ if (fallback_text) {
+ NSString *nsText = [NSString stringWithUTF8String:fallback_text];
+ [pasteboard setString:nsText forType:NSPasteboardTypeString];
+ }
+
+ return 1;
+}
\ No newline at end of file
diff --git a/espanso-clipboard/src/lib.rs b/espanso-clipboard/src/lib.rs
index c60cb69..efa1adf 100644
--- a/espanso-clipboard/src/lib.rs
+++ b/espanso-clipboard/src/lib.rs
@@ -34,7 +34,7 @@ mod x11;
mod wayland;
#[cfg(target_os = "macos")]
-mod mac;
+mod cocoa;
pub trait Clipboard {
fn get_text(&self) -> Option;
@@ -66,9 +66,9 @@ pub fn get_clipboard(_: ClipboardOptions) -> Result> {
}
#[cfg(target_os = "macos")]
-pub fn get_injector(_options: InjectorCreationOptions) -> Result> {
- info!("using MacInjector");
- Ok(Box::new(mac::MacInjector::new()))
+pub fn get_clipboard(_: ClipboardOptions) -> Result> {
+ info!("using CocoaClipboard");
+ Ok(Box::new(cocoa::CocoaClipboard::new()?))
}
#[cfg(target_os = "linux")]