use crate::common::*;
use crate::Result;
use std::io::{self, Read};
use wl_clipboard_rs::{
copy::{self, clear, Options, ServeRequests},
paste, utils,
};
pub struct WaylandClipboardContext {
supports_primary_selection: bool,
}
impl ClipboardProvider for WaylandClipboardContext {
fn new() -> Result<WaylandClipboardContext> {
let supports_primary_selection = match utils::is_primary_selection_supported() {
Ok(v) => v,
Err(utils::PrimarySelectionCheckError::NoSeats) => false,
Err(e) => return Err(e.into()),
};
Ok(WaylandClipboardContext {
supports_primary_selection,
})
}
fn get_contents(&mut self) -> Result<String> {
if self.supports_primary_selection {
match paste::get_contents(
paste::ClipboardType::Primary,
paste::Seat::Unspecified,
paste::MimeType::Text,
) {
Ok((mut reader, _)) => {
return Ok(read_into_string(&mut reader).map_err(Box::new)?);
}
Err(e) => match e {
paste::Error::NoSeats
| paste::Error::ClipboardEmpty
| paste::Error::NoMimeType => return Ok("".to_string()),
_ => (),
},
}
}
let mut reader = match paste::get_contents(
paste::ClipboardType::Regular,
paste::Seat::Unspecified,
paste::MimeType::Text,
) {
Ok((reader, _)) => reader,
Err(
paste::Error::NoSeats | paste::Error::ClipboardEmpty | paste::Error::NoMimeType,
) => return Ok("".to_string()),
Err(e) => return Err(e.into()),
};
Ok(read_into_string(&mut reader).map_err(Box::new)?)
}
fn set_contents(&mut self, data: String) -> Result<()> {
let mut options = Options::new();
options
.seat(copy::Seat::All)
.trim_newline(false)
.foreground(false)
.serve_requests(ServeRequests::Unlimited);
if self.supports_primary_selection {
options.clipboard(copy::ClipboardType::Both);
} else {
options.clipboard(copy::ClipboardType::Regular);
}
options
.copy(
copy::Source::Bytes(data.into_bytes().into()),
copy::MimeType::Text,
)
.map_err(Into::into)
}
fn clear(&mut self) -> Result<()> {
if self.supports_primary_selection {
clear(copy::ClipboardType::Both, copy::Seat::All).map_err(Into::into)
} else {
clear(copy::ClipboardType::Regular, copy::Seat::All).map_err(Into::into)
}
}
}
fn read_into_string<R: Read>(reader: &mut R) -> io::Result<String> {
let mut contents = String::new();
reader.read_to_string(&mut contents)?;
Ok(contents)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
#[ignore]
fn wayland_test() {
let mut clipboard =
WaylandClipboardContext::new().expect("couldn't create a Wayland clipboard");
clipboard
.set_contents("foo bar baz".to_string())
.expect("couldn't set contents of Wayland clipboard");
assert_eq!(
clipboard
.get_contents()
.expect("couldn't get contents of Wayland clipboard"),
"foo bar baz"
);
}
}