use super::data::Bitmap;
pub type BitmapReader = Box<dyn FnOnce() -> Option<Bitmap> + Send>;
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum TextRead {
Text(String),
NoText,
Unreachable,
}
pub trait ClipboardSource: Send {
fn read_text(&mut self) -> TextRead;
fn can_read_bitmaps(&self) -> bool;
fn bitmap_reader(&mut self) -> BitmapReader;
fn write_text(&mut self, text: String);
}
#[cfg(feature = "clipboard")]
pub struct OsClipboard;
#[cfg(feature = "clipboard")]
impl ClipboardSource for OsClipboard {
fn read_text(&mut self) -> TextRead {
let Ok(mut clipboard) = arboard::Clipboard::new() else {
return TextRead::Unreachable;
};
clipboard
.get_text()
.map_or(TextRead::NoText, TextRead::Text)
}
fn can_read_bitmaps(&self) -> bool {
true
}
fn bitmap_reader(&mut self) -> BitmapReader {
Box::new(|| {
let image = arboard::Clipboard::new().ok()?.get_image().ok()?;
Some(Bitmap {
width: image.width as u32,
height: image.height as u32,
rgba: image.bytes.into_owned(),
})
})
}
fn write_text(&mut self, text: String) {
super::osc52_copy(&text);
write_os_text(text);
}
}
#[cfg(all(feature = "clipboard", target_os = "linux"))]
fn write_os_text(text: String) {
use arboard::SetExtLinux;
std::thread::spawn(move || {
if let Ok(mut cb) = arboard::Clipboard::new() {
let _ = cb.set().wait().text(text);
}
});
}
#[cfg(all(feature = "clipboard", not(target_os = "linux")))]
fn write_os_text(text: String) {
if let Ok(mut cb) = arboard::Clipboard::new() {
let _ = cb.set_text(&text);
}
}
pub struct TerminalClipboard;
impl ClipboardSource for TerminalClipboard {
fn read_text(&mut self) -> TextRead {
TextRead::Unreachable
}
fn can_read_bitmaps(&self) -> bool {
false
}
fn bitmap_reader(&mut self) -> BitmapReader {
Box::new(|| None)
}
fn write_text(&mut self, text: String) {
super::osc52_copy(&text);
}
}
pub struct NullClipboard;
impl ClipboardSource for NullClipboard {
fn read_text(&mut self) -> TextRead {
TextRead::Unreachable
}
fn can_read_bitmaps(&self) -> bool {
false
}
fn bitmap_reader(&mut self) -> BitmapReader {
Box::new(|| None)
}
fn write_text(&mut self, _text: String) {}
}
pub fn default_source() -> Box<dyn ClipboardSource> {
#[cfg(feature = "clipboard")]
{
Box::new(OsClipboard)
}
#[cfg(not(feature = "clipboard"))]
{
Box::new(TerminalClipboard)
}
}