#[cfg(feature = "image-data")]
use std::{cell::RefCell, rc::Rc};
#[cfg(feature = "wayland-data-control")]
use crate::wayland_data_control_clipboard::WaylandDataControlClipboardContext;
#[cfg(feature = "wayland-data-control")]
use log::{info, warn};
#[cfg(feature = "image-data")]
use crate::ImageData;
use crate::{x11_clipboard::X11ClipboardContext, Error};
pub fn into_unknown<E: std::fmt::Display>(error: E) -> Error {
Error::Unknown { description: format!("{}", error) }
}
#[cfg(feature = "image-data")]
pub fn encode_as_png(image: &ImageData) -> Result<Vec<u8>, Error> {
#[derive(Clone)]
struct RcBuffer {
inner: Rc<RefCell<Vec<u8>>>,
}
impl std::io::Write for RcBuffer {
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
self.inner.borrow_mut().extend_from_slice(buf);
Ok(buf.len())
}
fn flush(&mut self) -> std::io::Result<()> {
Ok(())
}
}
if image.bytes.is_empty() || image.width == 0 || image.height == 0 {
return Err(Error::ConversionFailure);
}
let enc_output = RcBuffer { inner: Rc::new(RefCell::new(Vec::new())) };
let encoder = image::png::PngEncoder::new(enc_output.clone());
encoder
.encode(
image.bytes.as_ref(),
image.width as u32,
image.height as u32,
image::ColorType::Rgba8,
)
.map_err(|_| Error::ConversionFailure)?;
let bytes = Rc::try_unwrap(enc_output.inner).unwrap().into_inner();
Ok(bytes)
}
#[derive(Copy, Clone, Debug)]
pub enum LinuxClipboardKind {
Clipboard,
Primary,
Secondary,
}
pub trait ClipboardExtLinux {
fn set_text_with_clipboard(
&mut self,
text: String,
clipboard: LinuxClipboardKind,
) -> Result<(), Error>;
fn get_text_with_clipboard(&mut self, clipboard: LinuxClipboardKind) -> Result<String, Error>;
}
impl ClipboardExtLinux for super::Clipboard {
fn get_text_with_clipboard(&mut self, selection: LinuxClipboardKind) -> Result<String, Error> {
match &mut self.platform {
LinuxClipboard::X11(cb) => cb.get_text_with_clipboard(selection),
#[cfg(feature = "wayland-data-control")]
LinuxClipboard::WlDataControl(cb) => cb.get_text_with_clipboard(selection),
}
}
fn set_text_with_clipboard(
&mut self,
text: String,
selection: LinuxClipboardKind,
) -> Result<(), Error> {
match &mut self.platform {
LinuxClipboard::X11(cb) => cb.set_text_with_clipboard(text, selection),
#[cfg(feature = "wayland-data-control")]
LinuxClipboard::WlDataControl(cb) => cb.set_text_with_clipboard(text, selection),
}
}
}
pub enum LinuxClipboard {
X11(X11ClipboardContext),
#[cfg(feature = "wayland-data-control")]
WlDataControl(WaylandDataControlClipboardContext),
}
impl LinuxClipboard {
pub fn new() -> Result<Self, Error> {
#[cfg(feature = "wayland-data-control")]
{
if std::env::var_os("WAYLAND_DISPLAY").is_some() {
match WaylandDataControlClipboardContext::new() {
Ok(clipboard) => {
info!("Successfully initialized the Wayland data control clipboard.");
return Ok( Self::WlDataControl(clipboard))
},
Err(e) => warn!(
"Tried to initialize the wayland data control protocol clipboard, but failed. Falling back to the X11 clipboard protocol. The error was: {}",
e
),
}
}
}
Ok(Self::X11(X11ClipboardContext::new()?))
}
pub fn get_text(&mut self) -> Result<String, Error> {
match self {
Self::X11(cb) => cb.get_text(),
#[cfg(feature = "wayland-data-control")]
Self::WlDataControl(cb) => cb.get_text(),
}
}
pub fn set_text(&mut self, text: String) -> Result<(), Error> {
match self {
Self::X11(cb) => cb.set_text(text),
#[cfg(feature = "wayland-data-control")]
Self::WlDataControl(cb) => cb.set_text(text),
}
}
#[cfg(feature = "image-data")]
pub fn get_image(&mut self) -> Result<ImageData<'static>, Error> {
match self {
Self::X11(cb) => cb.get_image(),
#[cfg(feature = "wayland-data-control")]
Self::WlDataControl(cb) => cb.get_image(),
}
}
#[cfg(feature = "image-data")]
pub fn set_image(&mut self, image: ImageData) -> Result<(), Error> {
match self {
Self::X11(cb) => cb.set_image(image),
#[cfg(feature = "wayland-data-control")]
Self::WlDataControl(cb) => cb.set_image(image),
}
}
}