Skip to content

Naive clipboard support #19106

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 15 commits into
base: main
Choose a base branch
from
Open

Naive clipboard support #19106

wants to merge 15 commits into from

Conversation

ickshonpe
Copy link
Contributor

@ickshonpe ickshonpe commented May 6, 2025

Objective

Add a platform-agnostic interface for interacting with the clipboard.

Solution

New crate bevy_clipboard that has a ClipboardPlugin. The clipboard is accessed using methods on the Clipboard resource. It only has two methods get_text and set_text which return Results, with errors if the clipboard is unavailable.

On windows the Clipboard resource is a unit struct and a new arboard clipboard instance is created and dropped for each clipboard access. On unix targets the Clipboard resource holds a clipboard instance it reuses each time.

Doesn't support images or android and wasm targets. Almost everything is done by the arboard crate.

I'm not sure that clipboard support needs its own crate but I wasn't sure where to put it if not.

Testing

Add this system to an app:

fn clipboard_test(mut clipboard: ResMut<Clipboard>) {
    let text = clipboard.get_text().unwrap();
    info!("clipboard contents = {}", text);
    info!("set clipboard text");
    clipboard.set_text("Hello bevy!").unwrap();
    let text = clipboard.get_text().unwrap();
    info!("clipboard contents = {}", text);
}

If working should output:

2025-05-06T22:51:56.918208Z  INFO text: clipboard contents = Hello world!
2025-05-06T22:51:56.918317Z  INFO text: set clipboard text
2025-05-06T22:51:56.918574Z  INFO text: clipboard contents = Hello bevy!

ickshonpe added 4 commits May 6, 2025 23:58
Enabled with the `bevy_clipboard` feature.
Supports setting and getting text to and from the clipboard.
Only supports desktop targets.
Enabled with the `bevy_clipboard` feature.
Supports setting and getting text to and from the clipboard.
Only supports desktop targets.
@ickshonpe ickshonpe added C-Feature A new feature, making something new possible A-Utils Utility functions and types labels May 6, 2025
@alice-i-cecile alice-i-cecile added A-UI Graphical user interfaces, styles, layouts, and widgets A-Editor Graphical tools to make Bevy games X-Controversial There is active debate or serious implications around merging this PR S-Needs-Review Needs reviewer attention (from anyone!) to move forward labels May 6, 2025
@alice-i-cecile
Copy link
Member

Marked as X-Controversial due to a new crate, but I strongly think we need this as part of the engine in some form. Both for games and the editor!

@mockersf
Copy link
Member

mockersf commented May 6, 2025

I don't like the crate for that which is pretty much just a resource wrapping arboard...

And not sure I like the fake resource that can't work on not supported platforms

///
/// Returns error if clipboard is empty or contents are not UTF-8 text.
pub fn get_text(&mut self) -> Result<String, arboard::Error> {
Err(arboard::Error::ClipboardNotSupported)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Question: why can't Clipboard store the string itself? Then use arboard in addition when it is supported?

I guess that only works when setting directly through the resource. But might be an okay tradeoff

Copy link
Contributor Author

@ickshonpe ickshonpe May 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought about this but felt like it might be confusing for users if copy and paste is only working internally.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What platforms are unsupported? It might be an okay tradeoff to still allow some amount of clipboard behavior

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

arboard seems to support Linux, Mac and Windows. So there's at least Web that is unsupported, and many no_std targets.
I also feel like ultra basic support is still better than no support at all ? Maybe with a warning emitted if the plugin is enabled on an unsupported platform ?

&mut self,
text: T,
) -> Result<(), arboard::Error> {
arboard::Clipboard::new().and_then(|mut clipboard| clipboard.set_text(text))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think dropping the Clipboard may not work on Linux ?
See arboard's documentation about platform-specific behaviors (and also issue #88 and PR #89 for more info)

Copy link
Contributor Author

@ickshonpe ickshonpe May 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah seems like drop-after-use is only needed on windows.

@ickshonpe
Copy link
Contributor Author

ickshonpe commented May 7, 2025

I don't like the crate for that which is pretty much just a resource wrapping arboard...

This PR is really trivial, but image and android and wasm support will add a lot more complexity. I'm being lazy here, I've got way too many things I working on atm so I was thinking if I just get desktop text clipboard support going someone else will pick this up and fill out the rest of the implementation.

I'm not sure it's an important enough feature to deserve its own crate, but I'm not sure if it belongs in any of the exisiting crates either. Maybe bevy_window but using the clipboard doesn't require a window.

And not sure I like the fake resource that can't work on not supported platforms

The idea is that you can only use the clipboard with a ResMut<Clipboard> to ensure that access is exclusive. Maybe there's a better way to implement it, I'm not sure.

ickshonpe and others added 7 commits May 7, 2025 12:06
* On unix targets an instance of `arboard::Clipboard` is stored in the `Clipboard` resource.
* Removed the desktop and dummy modules.
* Made `arboard` dependency conditional.
@Henauxg
Copy link
Contributor

Henauxg commented May 7, 2025

For crates candidates, I've had a look and did not find much either. Doesn't fit in bevy_text, nor bevy_input. Could always force it in bevy_utils but that's no great either. There's maybe bevy_app which already has a TerminalCtrlCHandlerPlugin plugin using the ctrlc dependency, but I'm not sure that tying clipboard to App is a good choice.

There's a potential savior in bevy_winit. I've seen that clipboard handling might be on the roadmap for 0.31 or later ? See #162 and #2156
So it may make sense to snuck it into bevy_winit, while waiting for it to be available directly from winit ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-Editor Graphical tools to make Bevy games A-UI Graphical user interfaces, styles, layouts, and widgets A-Utils Utility functions and types C-Feature A new feature, making something new possible S-Needs-Review Needs reviewer attention (from anyone!) to move forward X-Controversial There is active debate or serious implications around merging this PR
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants