diff --git a/Cargo.lock b/Cargo.lock index c3e139e8e..359e344bb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -352,6 +352,20 @@ dependencies = [ "vec_map", ] +[[package]] +name = "clipboard-master" +version = "3.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cd1cb2f0df685eb4a61c656faeb6ef391ad776943d3723afb12bdcbceff824d" +dependencies = [ + "objc", + "objc-foundation", + "objc_id", + "winapi 0.3.9", + "windows-win", + "x11-clipboard", +] + [[package]] name = "clipboard-win" version = "4.2.1" @@ -2860,6 +2874,7 @@ dependencies = [ "cc", "cfg-if 1.0.0", "clap", + "clipboard-master", "cocoa", "core-foundation 0.9.1", "core-graphics", @@ -3771,6 +3786,15 @@ dependencies = [ "winapi 0.3.9", ] +[[package]] +name = "windows-win" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d4243ec23afe4e9b4e668b3c0a0e973f1b8265f6a46223cfcbc16fd267480c0" +dependencies = [ + "winapi 0.3.9", +] + [[package]] name = "winreg" version = "0.6.2" @@ -3814,6 +3838,15 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85e60b0d1b5f99db2556934e21937020776a5d31520bf169e851ac44e6420214" +[[package]] +name = "x11-clipboard" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b397ace6e980510de59a4fe3d4c758dffab231d6d747ce9fa1aba6b6035d5f32" +dependencies = [ + "xcb", +] + [[package]] name = "x11rb" version = "0.8.1" @@ -3826,6 +3859,16 @@ dependencies = [ "winapi-wsapoll", ] +[[package]] +name = "xcb" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62056f63138b39116f82a540c983cc11f1c90cd70b3d492a70c25eaa50bd22a6" +dependencies = [ + "libc", + "log", +] + [[package]] name = "yansi" version = "0.5.0" diff --git a/Cargo.toml b/Cargo.toml index 75504a06f..b4b8ad48c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -51,6 +51,7 @@ mac_address = "1.1" sciter-rs = { git = "https://github.com/open-trade/rust-sciter", branch = "dyn" } ctrlc = "3.2" arboard = "2.0" +clipboard-master = "3" [target.'cfg(target_os = "windows")'.dependencies] #systray = { git = "https://github.com/open-trade/systray-rs" } diff --git a/src/server/clipboard_service.rs b/src/server/clipboard_service.rs index 25597d11c..3e94d2824 100644 --- a/src/server/clipboard_service.rs +++ b/src/server/clipboard_service.rs @@ -1,3 +1,7 @@ +use std::sync::mpsc::Sender; + +use clipboard_master::{CallbackResult, ClipboardHandler, Master}; + use super::*; pub use crate::common::{ check_clipboard, ClipboardContext, CLIPBOARD_INTERVAL as INTERVAL, CLIPBOARD_NAME as NAME, @@ -27,12 +31,28 @@ impl super::service::Reset for State { } } +struct ClipHandle { + tx: Sender, +} + +impl ClipboardHandler for ClipHandle { + fn on_clipboard_change(&mut self) -> CallbackResult { + let _ = self.tx.send(true); + CallbackResult::Next + } +} + pub fn new() -> GenericService { let sp = GenericService::new(NAME, true); - sp.repeat::(INTERVAL, run); + sp.listen::(notify, run); sp } +fn notify(tx: Sender) -> ResultType<()> { + Master::new(ClipHandle { tx }).run()?; + Ok(()) +} + fn run(sp: GenericService, state: &mut State) -> ResultType<()> { if let Some(ctx) = state.ctx.as_mut() { if let Some(msg) = check_clipboard(ctx, None) { diff --git a/src/server/service.rs b/src/server/service.rs index b60f5a8d4..3e8c840a2 100644 --- a/src/server/service.rs +++ b/src/server/service.rs @@ -1,5 +1,6 @@ use super::*; use std::{ + sync::{self, mpsc::Sender}, thread::{self, JoinHandle}, time, }; @@ -153,6 +154,39 @@ impl> ServiceTmpl { } } + pub fn listen(&self, notify: N, callback: F) + where + N: 'static + FnMut(Sender) -> ResultType<()> + Send, + F: 'static + FnMut(Self, &mut S) -> ResultType<()> + Send, + S: 'static + Default + Reset, + { + let mut notify = notify; + let mut callback = callback; + let sp = self.clone(); + let (tx, rx) = sync::mpsc::channel(); + thread::spawn(move || { + let _ = notify(tx); + }); + + let thread = thread::spawn(move || { + let mut state = S::default(); + while let Ok(changed) = rx.recv() { + if changed && sp.active() { + if sp.has_subscribes() { + if let Err(err) = callback(sp.clone(), &mut state) { + log::error!("Error of {} service: {}", sp.name(), err); + #[cfg(windows)] + crate::platform::windows::try_change_desktop(); + } + } else { + state.reset(); + } + } + } + }); + self.0.write().unwrap().handle = Some(thread); + } + pub fn repeat(&self, interval_ms: u64, callback: F) where F: 'static + FnMut(Self, &mut S) -> ResultType<()> + Send,