aweinstock314 / rust-clipboard

System Clipboard interfacing library in Rust
Apache License 2.0
368 stars 75 forks source link

discussion: feasibility for clipboard change events #48

Open cdaringe opened 6 years ago

cdaringe commented 6 years ago

hello, i'm interested on being notified when my clipboard changes.

i saw that there may be a way to get clipboard events. would that be something you feel (a) would be feasible for the system types you currently support and (b) would belong in this lib?

thx!

DoumanAsh commented 6 years ago

If anyone will find it interesting: On windows i cam up with simple workaround for console applications to get notified on clipboard change events properly https://github.com/DoumanAsh/clipboard-master

Basic sequence of actions:

  1. Add window, you can create dummy window as console application, to clipboard updates using AddClipboardFormatListener
  2. Listen for WM_CLIPBOARDUPDATE messages(each time clipboard is changed, message is sent)
  3. To remove yourself from listening use RemoveClipboardFormatListener

I'm not familiar with Linux/MacOS ways to do it, but considering that Qt does it, it should be possible.

aweinstock314 commented 6 years ago

cdaringe's link demonstrates how to do it on MacOS (via some swift code, which can be adapted to use msg_send!).

It looks like x11-clipboard doesn't have an event loop for this feature yet, but it's probably possible to adapt the existing getter loop (i.e. from Clipboard::load), and ideally factor out some common event loop that can be used for both the getter and the notifier.

Since it's supportable on all the platforms so far, it's in-scope for the library.

As far as interface goes, does adding a function like get_change_notifier(&self) -> Receiver</* something like an enum over formats or a String */> to the ClipboardProvider trait seem reasonable?

cc @DoumanAsh @quininer

quininer commented 6 years ago

In X11 this can be implement with FixesExt, but I don't have much time. I'd be happy if someone could help.

https://github.com/quininer/x11-clipboard/issues/3

DoumanAsh commented 6 years ago

@aweinstock314 By Receiver do you mean it is going to be channel's end? It might be fine API but it would imply that thread will be started implicitly to wait for clipboard changes. I wouldn't recommend returning content of clipboard and instead the Receiver should be over simple enum:

enum ClipboardStateChange<T> {
    NewContent,
    Error(T)

As clipboard is global on windows, having option to read/write in multiple threads is a bad idea.

But I also think there should be configuration option to identify type of clipboard change. For example user might be interested only in plain text or image.

So maybe it could be something like:

let listener = ClipboardListenerBuilder::new().listen(Event::Text).listen(Event::Image)
let clipboard_change = clipboard.enable_listener(listener);

I guess having it as both iterator or channel's receiver would be good.

P.s. for Windows I'm also thinking maybe moving into clipboard crate itself.