//! Smithay Clipboard //! //! Provides access to the Wayland clipboard for gui applications. The user should have surface //! around. use std::ffi::c_void; use std::io::Result; use std::sync::mpsc::{self, Receiver, Sender}; use sctk::reexports::client::Display; mod env; mod mime; mod worker; /// Access to a Wayland clipboard. pub struct Clipboard { request_sender: Sender, request_receiver: Receiver>, clipboard_thread: Option>, } impl Clipboard { /// Creates new clipboard which will be running on its own thread with its own event queue to /// handle clipboard requests. pub fn new(display: *mut c_void) -> Self { let display = unsafe { Display::from_external_display(display as *mut _) }; // Create channel to send data to clipboard thread. let (request_sender, clipboard_request_receiver) = mpsc::channel(); // Create channel to get data from the clipboard thread. let (clipboard_reply_sender, request_receiver) = mpsc::channel(); let name = String::from("smithay-clipboard"); let clipboard_thread = worker::spawn(name, display, clipboard_request_receiver, clipboard_reply_sender); 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 { let _ = self.request_sender.send(worker::Command::Load); 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.")) } } /// Store to a clipboard. /// /// Stores to a clipboard on a last observed seat. pub fn store>(&self, text: T) { let request = worker::Command::Store(text.into()); let _ = self.request_sender.send(request); } /// Load primary clipboard data. /// /// Loads content from a primary clipboard on a last observed seat. pub fn load_primary(&self) -> Result { let _ = self.request_sender.send(worker::Command::LoadPrimary); 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.")) } } /// Store to a primary clipboard. /// /// Stores to a primary clipboard on a last observed seat. pub fn store_primary>(&self, text: T) { let request = worker::Command::StorePrimary(text.into()); let _ = self.request_sender.send(request); } } impl Drop for Clipboard { fn drop(&mut self) { // Shutdown smithay-clipboard. let _ = self.request_sender.send(worker::Command::Exit); if let Some(clipboard_thread) = self.clipboard_thread.take() { let _ = clipboard_thread.join(); } } }