feat: support custom mime types
This commit is contained in:
parent
eebb02816e
commit
3e56207b3a
7 changed files with 335 additions and 116 deletions
99
src/lib.rs
99
src/lib.rs
|
|
@ -8,18 +8,22 @@ use std::ffi::c_void;
|
|||
use std::io::Result;
|
||||
use std::sync::mpsc::{self, Receiver};
|
||||
|
||||
use mime::{AllowedMimeTypes, AsMimeTypes, MimeType};
|
||||
use sctk::reexports::calloop::channel::{self, Sender};
|
||||
use sctk::reexports::client::backend::Backend;
|
||||
use sctk::reexports::client::Connection;
|
||||
use state::SelectionTarget;
|
||||
use text::Text;
|
||||
|
||||
mod mime;
|
||||
pub mod mime;
|
||||
mod state;
|
||||
mod text;
|
||||
mod worker;
|
||||
|
||||
/// Access to a Wayland clipboard.
|
||||
pub struct Clipboard {
|
||||
request_sender: Sender<worker::Command>,
|
||||
request_receiver: Receiver<Result<String>>,
|
||||
request_receiver: Receiver<Result<(Vec<u8>, MimeType)>>,
|
||||
clipboard_thread: Option<std::thread::JoinHandle<()>>,
|
||||
}
|
||||
|
||||
|
|
@ -46,14 +50,21 @@ impl Clipboard {
|
|||
Self { request_receiver, request_sender, clipboard_thread }
|
||||
}
|
||||
|
||||
/// Load clipboard data.
|
||||
///
|
||||
/// Loads content from a clipboard on a last observed seat.
|
||||
pub fn load(&self) -> Result<String> {
|
||||
let _ = self.request_sender.send(worker::Command::Load);
|
||||
fn load_inner<T: AllowedMimeTypes + 'static>(&self, target: SelectionTarget) -> Result<T>
|
||||
where
|
||||
<T as TryFrom<(Vec<u8>, MimeType)>>::Error: std::error::Error + Send + Sync,
|
||||
{
|
||||
let _ = self.request_sender.send(worker::Command::Load(T::allowed().to_vec(), target));
|
||||
|
||||
if let Ok(reply) = self.request_receiver.recv() {
|
||||
reply
|
||||
match reply {
|
||||
Ok((data, mime)) => {
|
||||
T::try_from((data, mime)).map_err(|err| std::io::Error::other(err))
|
||||
},
|
||||
Err(err) => {
|
||||
return Err(err);
|
||||
},
|
||||
}
|
||||
} else {
|
||||
// The clipboard thread is dead, however we shouldn't crash downstream, so
|
||||
// propogating an error.
|
||||
|
|
@ -61,35 +72,73 @@ impl Clipboard {
|
|||
}
|
||||
}
|
||||
|
||||
/// Store to a clipboard.
|
||||
/// Load custom clipboard data.
|
||||
///
|
||||
/// Stores to a clipboard on a last observed seat.
|
||||
pub fn store<T: Into<String>>(&self, text: T) {
|
||||
let request = worker::Command::Store(text.into());
|
||||
let _ = self.request_sender.send(request);
|
||||
/// Load the requested type from a clipboard on the last observed seat.
|
||||
pub fn load<T: AllowedMimeTypes + 'static>(&self) -> Result<T>
|
||||
where
|
||||
<T as TryFrom<(Vec<u8>, MimeType)>>::Error: std::error::Error + Send + Sync,
|
||||
{
|
||||
self.load_inner(SelectionTarget::Clipboard)
|
||||
}
|
||||
|
||||
/// Load clipboard data.
|
||||
///
|
||||
/// Loads content from a clipboard on a last observed seat.
|
||||
pub fn load_text(&self) -> Result<String> {
|
||||
self.load::<Text>().map(|t| t.0)
|
||||
}
|
||||
|
||||
/// Load custom primary clipboard data.
|
||||
///
|
||||
/// Load the requested type from a primary clipboard on the last observed
|
||||
/// seat.
|
||||
pub fn load_primary<T: AllowedMimeTypes + 'static>(&self) -> Result<T>
|
||||
where
|
||||
<T as TryFrom<(Vec<u8>, MimeType)>>::Error: std::error::Error + Send + Sync,
|
||||
{
|
||||
self.load_inner(SelectionTarget::Primary)
|
||||
}
|
||||
|
||||
/// Load primary clipboard data.
|
||||
///
|
||||
/// Loads content from a primary clipboard on a last observed seat.
|
||||
pub fn load_primary(&self) -> Result<String> {
|
||||
let _ = self.request_sender.send(worker::Command::LoadPrimary);
|
||||
pub fn load_primary_text(&self) -> Result<String> {
|
||||
self.load_primary::<Text>().map(|t| t.0)
|
||||
}
|
||||
|
||||
if let Ok(reply) = self.request_receiver.recv() {
|
||||
reply
|
||||
} else {
|
||||
// The clipboard thread is dead, however we shouldn't crash downstream, so
|
||||
// propogating an error.
|
||||
Err(std::io::Error::new(std::io::ErrorKind::Other, "clipboard is dead."))
|
||||
}
|
||||
fn store_inner<T: AsMimeTypes + Send + 'static>(&self, data: T, target: SelectionTarget) {
|
||||
let request = worker::Command::Store(Box::new(data), target);
|
||||
let _ = self.request_sender.send(request);
|
||||
}
|
||||
|
||||
/// Store custom data to a clipboard.
|
||||
///
|
||||
/// Stores data of the provided type to a clipboard on a last observed seat.
|
||||
pub fn store<T: AsMimeTypes + Send + 'static>(&self, data: T) {
|
||||
self.store_inner(data, SelectionTarget::Clipboard);
|
||||
}
|
||||
|
||||
/// Store to a clipboard.
|
||||
///
|
||||
/// Stores to a clipboard on a last observed seat.
|
||||
pub fn store_text<T: Into<String>>(&self, text: T) {
|
||||
self.store(Text(text.into()));
|
||||
}
|
||||
|
||||
/// Store custom data to a primary clipboard.
|
||||
///
|
||||
/// Stores data of the provided type to a primary clipboard on a last
|
||||
/// observed seat.
|
||||
pub fn store_primary<T: AsMimeTypes + Send + 'static>(&self, data: T) {
|
||||
self.store_inner(data, SelectionTarget::Primary);
|
||||
}
|
||||
|
||||
/// Store to a primary clipboard.
|
||||
///
|
||||
/// Stores to a primary clipboard on a last observed seat.
|
||||
pub fn store_primary<T: Into<String>>(&self, text: T) {
|
||||
let request = worker::Command::StorePrimary(text.into());
|
||||
let _ = self.request_sender.send(request);
|
||||
pub fn store_primary_text<T: Into<String>>(&self, text: T) {
|
||||
self.store_primary(Text(text.into()));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue