use anyhow::Result;
use image::RgbaImage;
#[cfg(all(unix, not(target_os = "macos")))]
pub fn copy_image(img: &RgbaImage) -> Result<()> {
let wl_err = match copy_with_wl_copy(img) {
Ok(()) => return Ok(()),
Err(err) => err,
};
copy_with_arboard(img)
.map_err(|arboard_err| anyhow::anyhow!("wl-copy: {wl_err}; arboard: {arboard_err}"))
}
#[cfg(any(target_os = "macos", windows))]
pub fn copy_image(img: &RgbaImage) -> Result<()> {
copy_with_arboard(img)
}
fn copy_with_arboard(img: &RgbaImage) -> Result<()> {
use anyhow::Context;
let mut clipboard = arboard::Clipboard::new().context("opening clipboard")?;
clipboard
.set_image(arboard::ImageData {
width: img.width() as usize,
height: img.height() as usize,
bytes: std::borrow::Cow::Borrowed(img.as_raw()),
})
.context("setting clipboard image")
}
#[cfg(all(unix, not(target_os = "macos")))]
fn copy_with_wl_copy(img: &RgbaImage) -> Result<()> {
use std::io::Write;
use std::process::{Command, Stdio};
use anyhow::{Context, anyhow};
let mut png = Vec::new();
img.write_to(&mut std::io::Cursor::new(&mut png), image::ImageFormat::Png)
.context("encoding png")?;
let mut child = Command::new("wl-copy")
.args(["-t", "image/png"])
.stdin(Stdio::piped())
.stdout(Stdio::null())
.stderr(Stdio::null())
.spawn()
.context("spawning wl-copy (is wl-clipboard installed?)")?;
child
.stdin
.take()
.context("wl-copy stdin unavailable")?
.write_all(&png)
.context("writing png to wl-copy")?;
let status = child.wait().context("waiting for wl-copy")?;
if !status.success() {
return Err(anyhow!("wl-copy exited with {status}"));
}
Ok(())
}