//! Handler utilities for the various selection protocols. //! //! Wayland originally only had a singe way to deal with the user clipboard with the help of //! `wl_data_device` protocol. However the demand for *primary* selection as well as writing //! clipboard managers made it into developing protocol extension for the said cases. //! //! The following selection providers are supported: //! //! - The [`data_device`](data_device/index.html) module to work with the traditional clipboard selection. //! - The [`primary_selection`](primary_selection/index.html) module to work with the primary selection. //! - The [`wlr_data_control`](wlr_data_control/index.html) module to hook data control into //! clipboard and primary selection use std::os::unix::io::OwnedFd; use crate::input::{Seat, SeatHandler}; pub mod data_device; pub mod ext_data_control; pub mod primary_selection; pub mod wlr_data_control; mod device; mod offer; mod seat_data; mod source; pub use source::SelectionSource; /// Events that are generated by interactions of the clients with the data device. pub trait SelectionHandler: Sized + SeatHandler { /// UserData attached to server-side selections. type SelectionUserData: Clone + Send + Sync + 'static; /// A client has set the selection #[allow(unused_variables)] fn new_selection(&mut self, ty: SelectionTarget, source: Option, seat: Seat) {} /// A client requested to read the server-set selection. /// /// * `mime_type` - the requested mime type /// * `fd` - the fd to write into #[allow(unused_variables)] fn send_selection( &mut self, ty: SelectionTarget, mime_type: String, fd: OwnedFd, seat: Seat, user_data: &Self::SelectionUserData, ) { } } /// The target for the selection request. #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum SelectionTarget { /// The target for the request is primary selection. Primary, /// The target for the request is clipboard selection. Clipboard, } pub(crate) mod private { /// `selection_dispatch!(self; Enum(foo) => foo.something())` /// expands to the equivalent of /// ```ignore /// match self { /// Enum::DataDevice(foo) => foo.something(), /// Enum::Primary(foo) => foo.something(), /// Enum::WlrDataControl(foo) => foo.something(), /// Enum::ExtDataControl(foo) => foo.something(), /// } /// ``` /// /// And `selection_dispatch!(self, other; Enum(foo), EnumNext(zoo) => foo.something(zoo))` expands /// to the equivalent of /// ```ignore /// match (self, other) { /// (Enum::DataDevice(foo), EnumNext::DataDevice(zoo)) => foo.something(zoo), /// (Enum::Primary(foo), EnumNext::Primary(zoo)) => foo.something(zoo), /// (Enum::WlrDataControl(foo), EnumNext::WlrDataControl(zoo)) => foo.something(zoo), /// (Enum::ExtDataControl(foo), EnumNext::ExtDataControl(zoo)) => foo.something(zoo), /// _ => unreachable!(), /// } /// ``` /// /// The result can be converted to another enum by adding `; as AnotherEnum` macro_rules! selection_dispatch { ($what:ident; $enum:ident ( $($c1:tt)* ) => $x:expr) => { match $what { $enum::DataDevice($($c1)*) => $x, $enum::Primary($($c1)*) => $x, $enum::WlrDataControl($($c1)*) => $x, $enum::ExtDataControl($($c1)*) => $x, } }; ($what:ident$(, $what_next:ident)+; $enum:ident ( $($c1:tt)*) $(, $enum_next:ident ( $($c2:tt)* ) )+ => $x:expr) => { match ($what$(, $what_next)*) { ($enum::DataDevice($($c1)*)$(, $enum_next::DataDevice($($c2)*))*) => $x, ($enum::Primary($($c1)*)$(, $enum_next::Primary($($c2)*))*) => $x, ($enum::WlrDataControl($($c1)*)$(, $enum_next::WlrDataControl($($c2)*))*) => $x, ($enum::ExtDataControl($($c1)*)$(, $enum_next::ExtDataControl($($c2)*))*) => $x, _ => unreachable!(), } }; } pub(crate) use selection_dispatch; }