Open yaa110 opened 5 years ago
This is a known tradeoff/design decision around a limitation of x11. This was documented in a comment back when x11-clipboard
lived in-tree (https://github.com/aweinstock314/rust-clipboard/blob/9a13971d023c5c4975d286bea70a7b139c0954b4/src/x11_clipboard.rs#L263-L279). I'll probably address this by copying that comment back in tree (and possibly adding the feature to create a clipboard context that forks, with a warning about the issues around locks/destructors).
I realize this might be out of scope, but is there a way of detecting when the contents of the clipboard have been accessed, from rust-clipboard? I want to write a tool to receive input from stdin and copy that to the clipboard. I'd be fine with the process hanging until the contents had been pasted out (in fact, that could be ideal), but I'm not sure how i'd know when that had occurred.
I guess this might require something like a variation on set_contents
that would block until the contents had been read back out?
Thank you for addressing this in detail. As someone who is learning Rust, would you be able to give brief details on the problems involved with using fork?
This is a real pity as it renders the library essentially useless for my purposes.
Assuming this is a wontfix
, I've created the clipboard-ext
crate to extend upon this. It provides some additional clipboard providers for X11 that do implement the noted workarounds such as forking or invoking xclip
/xsel
.
For example, these will keep clipboard contents after exit:
use clipboard_ext::prelude::*;
// Fork and keep contents
clipboard_ext::x11_fork::ClipboardContext::new().unwrap()
.set_contents("some string".into()).unwrap();
// Invoke xclip/xsel and keep contents
clipboard_ext::x11_bin::ClipboardContext::new().unwrap()
.set_contents("some string".into()).unwrap();
See the README for more information.
I did a bit of digging to see how much work it would be to enable the paste detection functionality that I mention in https://github.com/aweinstock314/rust-clipboard/issues/61#issuecomment-479347425, and it appears pretty nontrivial, since this package uses various lower-level libraries for the actual clipboard bits.
@brownjohnf I've done exactly this in clipboard-ext
which I mentioned in https://github.com/aweinstock314/rust-clipboard/issues/61#issuecomment-585942224.
You'd have to use the x11-clipboard
crate for this which provides access to the lower level X11 library. This is alright though, because this is the only provider you'd need to implement this for anyway. It provides the load_wait
function which blocks until clipboard content is changed.
See my implementation and usage here: https://github.com/timvisee/rust-clipboard-ext/blob/a47cc13807ca19bc2c815b07688a27235ad9b4f7/src/x11_fork.rs#L90-L107
Following up here with my own ~hack~ solution, which is to use the nix
crate's fork
functionality to spawn a temporary child:
match fork() {
Ok(ForkResult::Child) => {
let mut ctx: ClipboardContext = ClipboardProvider::new().unwrap();
ctx.set_contents(password.value.to_owned()).unwrap();
std::thread::sleep(std::time::Duration::from_secs(10));
// optionally clear the clipboard here
}
Err(_) => return Err("clipboard fork failed".into()),
_ => {}
}
This only works on platforms that have a fork
, of course.
Edit: This also shouldn't be done in library code. It's safe-ish in the context I intend to use it in, but not necessarily others.
Please consider the following code: