alacritty/copypasta

Setting clipboard on Fedora 33 / GNOME / Wayland does not work

ignatenkobrain opened this issue · 23 comments

I have this simple code from example:

use copypasta::{ClipboardContext, ClipboardProvider};

fn main() {
    let mut ctx = ClipboardContext::new().unwrap();
    println!("{:?}", ctx.get_contents());
    ctx.set_contents("some string".to_owned()).unwrap();
}

Running it twice shows:

❯ cargo run
    Finished dev [unoptimized + debuginfo] target(s) in 0.05s
     Running `target/debug/foo`
Ok("master")

foo on  master [?] is 📦 v0.1.0 via 🦀 v1.43.1 
❯ cargo run
    Finished dev [unoptimized + debuginfo] target(s) in 0.04s
     Running `target/debug/foo`
Ok("")

foo on  master [?] is 📦 v0.1.0 via 🦀 v1.43.1 

so it seems it sets buffer to empty instead of some string. I am not sure how to debug this, so let me know and I will happily provide as much details as needed.

This probably doesn't work because there's no clipboard manager. So whenever something is read from the clipboard, it is requested from the other application which stores it. If you shut that application down, the clipboard gets cleared.

If you try pasting the clipboard while the program is still running, it should work.

@chrisduerr oh, that's unfortunate. I was thinking about porting ffsend to this crate. and its purpose is to copy link to the clipboard and close itself.

That doesn't work on Linux unless you keep around a background worker permanently. This can be done with this crate too of course. That's just generally how clipboards work on Linux.

@chrisduerr I am pretty sure that if I copy text from gedit, then close it, it will stay in my buffer. So there must be some way how to do it, though I don't know how that works.

@fmuellner do you have any ideas here?

I am pretty sure that if I copy text from gedit, then close it, it will stay in my buffer.

It actually won't, until a process is kept around to buffer it. That shouldn't be news, it has been working like that for centuries. Where do you think that data would be stored? On X11, when a clipboard is read, the data is requested from the program.

Closing since it's working as intended on Wayland/X11.

This crate isn't for clipboard managers. on Wayland you need a window to work with clipboard, since the protocol is tied to keyboard focus. However there're protocols like data-device-control to overcome this, which GNOME doesn't support, anyway, this is not a goal of this crate. This crate is purely for gui clients.

Also, you're using X11 clipboard, which is what created by default, on Wayland, you need to provide display.

Okay, I totally missed in your original code example that you didn't even pass a display to the clipboard context. By default on Linux this creates an X11 clipboard: https://github.com/alacritty/copypasta/blob/master/src/lib.rs#L60

@kchibisov has confirmed that when you create a clipboard using a display, the data is persisted by GNOME on Wayland since it seems to be running a clipboard manager by default.

Unfortunately there is no cross-compositor way to access the clipboard without a focused window present.

This is the

pub unsafe fn create_clipboards_from_external(display: *mut c_void) -> (Primary, Clipboard) {
which creates a wayland clipboard, but it'll still require a window for you. But on GNOME you have clipboard manager by default for at least all Wayland clients.

@kchibisov @chrisduerr thanks for providing hints. Probably it would make sense to put this as an example in source code so that people like me that are not really aware of these tiny details could just use same approach?

Thanks a lot!

The example of how it works look at https://github.com/smithay/smithay-clipboard example, since copy pasta is just a thin wrapper over it to call store/load methods. But you can't access clipboard from the CLI on Wayland, only from gui apps.

@kchibisov I think it is not entirely true. I just tried https://github.com/bugaevc/wl-clipboard and using wl-copy from the project works just fine. it copies text without having a gtk window or anything like that.

I guess the key here was using some kind of wl_display_connect but it does not mean that I need to have some real window. If I understand correctly.

@ignatenkobrain it's a bug that it works IIRC, it shouldn't work, unless GNOME added a magic protocol. The keyboard focus is a requirement in protocol, wl-clipboard is using hack with invisible window IIRC on GNOME.

@kchibisov so would not it make sense to implement same hack in copypasta / smithay-clipboard that would do same? I mean that it actually works, it would be quite useful for people that want to use them with wayland.

@kchibisov @chrisduerr if I understand conversation here correctly, all you need to do is to have wayland client that offers clipoard (aka sets content). If, for example, gedit closes - buffer should disappear but it does not.. So why is that a hack then? You open invisible window so technically it can offer clipboard data so that gnome just takes it and keeps even after window is closed. Am I wrong?

so would not it make sense to implement same hack in copypasta / smithay-clipboard that would do same?

I mean it's a bug that it even works, like why should we support a hack. That won't be possible in smithay-clipboard, because it's goal to assist wayland clients which has a window, you're free to implement it and providing a crate, but I'm not sure how it could be integrated. On sway/wlroots compositors you have wlr-data-control, which could be restricted at some point to cli only apps.

If, for example, gedit closes - buffer should disappear but it does not.

GNOME on wayland has clipboard manager by itself, that's why it works, if you close alacritty, which is using copypasta, it'll have content as well, but you can't access it, because of the way it works.

So, if you try wl-clipboard on weston, you'll notice that each time you access it, your application (terminal) loses focus and gains it after some time after, because of that invisible surface trick.

@ignatenkobrain gedit works because gedit opens a window. It doesn't use wl-clipboard. If you pass a display to our crate it will work too. Currently you're just creating an X11 clipboard, so that can't work right on Wayland obviously since it'll make use of XWayland. So if you want us to behave exactly like gedit, we already do.

The problem with supporting a hack that spawns its own window of course is that it doesn't work well and likely won't work anymore at some point in the future. So at that point we're just adding support for broken code, which really doesn't sound like a great idea. If you're writing a Wayland application that's supposed to work well, you shouldn't use this at all.

If you pass a display to our crate it will work too.

I'll try to do so.

So at that point we're just adding support for broken code, which really doesn't sound like a great idea.

Fair enough.

If you're writing a Wayland application that's supposed to work well, you shouldn't use this at all.

I'm just looking how to improve ffsend CLI application - replace xsel/xclip/whatsoever with some simpler crate that will be able to set clipboard for all platforms (windows, linux/x11, linux/wayland). Not really trying to build a rocket or anything like that :)

Regarding X11 support (and keeping the clipboard after the application exits): in various previous discussions it was said that solutions/workarounds for this won't be implemented.

I therefore released the copypasta-ext crate as an extension to provide additional clipboard providers, such as an X11 forking one.

For example:

use copypasta_ext::prelude::*;

// Fork and keep contents after exit
copypasta_ext::x11_fork::ClipboardContext::new().unwrap()
    .set_contents("some string".into()).unwrap();

// Invoke xclip/xsel and keep contents after exit
copypasta_ext::x11_bin::ClipboardContext::new().unwrap()
    .set_contents("some string".into()).unwrap();

Just posted this here as a signpost, some might find it useful. See the README for more information.

Now the X11 forking approach seems to be controversial. However, for me in ffsend, I don't want to require users to install all kinds of clipboard managers (fragmentation on Linux is a real problem here) just to allow clipboard usage. ffsend is a single-shot CLI application, I don't want to keep blocking the users' shell (so ffsend remains running) until the clipboard contents are changed either. This approach using X11 forking (or others) solves that issue. The other clipboard providers in copypasta-ext are fine alternatives.

I definitely would never recommend anyone to use this approach. It's completely backwards from how this should be solved and creates an absolute mess.

If you want your clipboard to be managed, just install a clipboard manager. If such a clipboard manager is present, copypasta will work just fine even after the application is closed. That's the entire goal of clipboard managers after all and that's the solution to the problem.

However this issue is obviously about the incorrect usage of our library due to improper API documentation.