diff --git a/native/liblinuxbridge/bridge.cpp b/native/liblinuxbridge/bridge.cpp index bbe7fda..feab87a 100644 --- a/native/liblinuxbridge/bridge.cpp +++ b/native/liblinuxbridge/bridge.cpp @@ -202,4 +202,12 @@ void delete_string(int32_t count) { for (int i = 0; i Option { + let res = Command::new("xclip") + .args(&["-o", "-sel", "clip"]) + .output(); + + if let Ok(output) = res { + if output.status.success() { + let s = String::from_utf8_lossy(&output.stdout); + return Some((*s).to_owned()); + } + } + + None + } + + fn set_clipboard(&self, payload: &str) { + let mut res = Command::new("xclip") + .args(&["-sel", "clip"]) + .stdin(Stdio::piped()) + .spawn(); + + if let Ok(mut child) = res { + let mut stdin = child.stdin.as_mut(); + + if let Some(mut output) = stdin { + output.write_all(payload.as_bytes()); + +// let status = child.wait(); +// +// if let Ok(status) = status { +// if !status.success() { +// //TODO: log error +// } +// } + } + } + } +} + +impl LinuxClipboardManager { + +} \ No newline at end of file diff --git a/src/clipboard/mod.rs b/src/clipboard/mod.rs new file mode 100644 index 0000000..2606c4f --- /dev/null +++ b/src/clipboard/mod.rs @@ -0,0 +1,22 @@ +#[cfg(target_os = "windows")] +mod windows; + +#[cfg(target_os = "linux")] +mod linux; + +#[cfg(target_os = "macos")] +mod macos; + +pub trait ClipboardManager { + fn initialize(&self); + fn get_clipboard(&self) -> Option; + fn set_clipboard(&self, payload: &str); +} + +// LINUX IMPLEMENTATION +#[cfg(target_os = "linux")] +pub fn get_manager() -> impl ClipboardManager { + let manager = linux::LinuxClipboardManager{}; + manager.initialize(); + manager +} \ No newline at end of file diff --git a/src/engine.rs b/src/engine.rs index dff35b8..bdd62ed 100644 --- a/src/engine.rs +++ b/src/engine.rs @@ -1,19 +1,22 @@ use crate::matcher::{Match, MatchReceiver}; use crate::keyboard::KeyboardSender; use crate::config::Configs; +use crate::clipboard::ClipboardManager; +use std::sync::Arc; -pub struct Engine where S: KeyboardSender { +pub struct Engine where S: KeyboardSender, C: ClipboardManager { sender: S, + clipboard_manager: Arc, configs: Configs, } -impl Engine where S: KeyboardSender{ - pub fn new(sender: S, configs: Configs) -> Engine where S: KeyboardSender { - Engine{sender, configs } +impl Engine where S: KeyboardSender, C: ClipboardManager{ + pub fn new(sender: S, clipboard_manager: Arc, configs: Configs) -> Engine where S: KeyboardSender, C: ClipboardManager { + Engine{sender, clipboard_manager, configs } } } -impl MatchReceiver for Engine where S: KeyboardSender{ +impl MatchReceiver for Engine where S: KeyboardSender, C: ClipboardManager{ fn on_match(&self, m: &Match) { self.sender.delete_string(m.trigger.len() as i32); @@ -21,7 +24,9 @@ impl MatchReceiver for Engine where S: KeyboardSender{ // while on windows and macos, we need to emulate a Enter key press. if cfg!(target_os = "linux") { - self.sender.send_string(m.replace.as_str()); + self.clipboard_manager.set_clipboard(m.replace.as_str()); + self.sender.trigger_paste(); + //self.sender.send_string(m.replace.as_str()); }else{ // To handle newlines, substitute each "\n" char with an Enter key press. let splits = m.replace.lines(); diff --git a/src/keyboard/linux.rs b/src/keyboard/linux.rs index 997968c..91a3214 100644 --- a/src/keyboard/linux.rs +++ b/src/keyboard/linux.rs @@ -47,6 +47,12 @@ impl super::KeyboardSender for LinuxKeyboardSender { // On linux this is not needed, so NOOP } + fn trigger_paste(&self) { + unsafe { trigger_paste(); } + + // TODO: detect when in terminal and use trigger_terminal_paste() instead + } + fn delete_string(&self, count: i32) { unsafe {delete_string(count)} } @@ -94,4 +100,6 @@ extern { fn cleanup(); fn send_string(string: *const c_char); fn delete_string(count: i32); + fn trigger_paste(); + fn trigger_terminal_paste(); } \ No newline at end of file diff --git a/src/keyboard/mod.rs b/src/keyboard/mod.rs index 5e8aaf8..8f3bd96 100644 --- a/src/keyboard/mod.rs +++ b/src/keyboard/mod.rs @@ -18,6 +18,7 @@ pub trait KeyboardInterceptor { pub trait KeyboardSender { fn send_string(&self, s: &str); fn send_enter(&self); + fn trigger_paste(&self); fn delete_string(&self, count: i32); } diff --git a/src/main.rs b/src/main.rs index dca6129..d8b583d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,10 +1,11 @@ -use std::sync::mpsc; +use std::sync::{mpsc, Arc}; use crate::keyboard::KeyboardInterceptor; use crate::matcher::Matcher; use crate::matcher::scrolling::ScrollingMatcher; use crate::engine::Engine; use crate::config::Configs; use crate::ui::UIManager; +use crate::clipboard::ClipboardManager; use std::thread; use clap::{App, Arg}; use std::path::Path; @@ -14,6 +15,7 @@ mod matcher; mod engine; mod config; mod ui; +mod clipboard; const VERSION: &'static str = env!("CARGO_PKG_VERSION"); @@ -54,11 +56,16 @@ fn espanso_main(configs: Configs) { let ui_manager = ui::get_uimanager(); ui_manager.notify("Hello guys"); + let clipboard_manager = clipboard::get_manager(); + let clipboard_manager_arc = Arc::new(clipboard_manager); + let (txc, rxc) = mpsc::channel(); let sender = keyboard::get_sender(); - let engine = Engine::new(sender, configs.clone()); + let engine = Engine::new(sender, + Arc::clone(&clipboard_manager_arc), + configs.clone()); thread::spawn(move || { let matcher = ScrollingMatcher::new(configs.clone(), engine);