smithay_client_toolkit/primary_selection/
offer.rs

1use std::{
2    os::unix::io::{AsFd, OwnedFd},
3    sync::Mutex,
4};
5
6use crate::reexports::client::{Connection, Dispatch, QueueHandle, Proxy};
7use crate::reexports::protocols::wp::primary_selection::zv1::client::zwp_primary_selection_offer_v1::ZwpPrimarySelectionOfferV1;
8
9use crate::data_device_manager::ReadPipe;
10
11use super::PrimarySelectionManagerState;
12
13/// Wrapper around the [`ZwpPrimarySelectionOfferV1`].
14#[derive(Debug, Clone, PartialEq, Eq)]
15pub struct PrimarySelectionOffer {
16    pub(crate) offer: ZwpPrimarySelectionOfferV1,
17}
18
19impl PrimarySelectionOffer {
20    /// Inspect the mime types available on the given offer.
21    pub fn with_mime_types<T, F: Fn(&[String]) -> T>(&self, callback: F) -> T {
22        let mime_types =
23            self.offer.data::<PrimarySelectionOfferData>().unwrap().mimes.lock().unwrap();
24        callback(mime_types.as_ref())
25    }
26
27    /// Request to receive the data of a given mime type.
28    ///
29    /// You can call this function several times.
30    ///
31    /// Note that you should *not* read the contents right away in a
32    /// blocking way, as you may deadlock your application doing so.
33    /// At least make sure you flush your events to the server before
34    /// doing so.
35    ///
36    /// Fails if too many file descriptors were already open and a pipe
37    /// could not be created.
38    pub fn receive(&self, mime_type: String) -> std::io::Result<ReadPipe> {
39        use rustix::pipe::{pipe_with, PipeFlags};
40        // create a pipe
41        let (readfd, writefd) = pipe_with(PipeFlags::CLOEXEC)?;
42
43        self.receive_to_fd(mime_type, writefd);
44
45        Ok(ReadPipe::from(readfd))
46    }
47
48    /// Request to receive the data of a given mime type, writen to `writefd`.
49    ///
50    /// The provided file destructor must be a valid FD for writing, and will be closed
51    /// once the contents are written.
52    pub fn receive_to_fd(&self, mime_type: String, writefd: OwnedFd) {
53        self.offer.receive(mime_type, writefd.as_fd());
54    }
55}
56
57impl<State> Dispatch<ZwpPrimarySelectionOfferV1, PrimarySelectionOfferData, State>
58    for PrimarySelectionManagerState
59where
60    State: Dispatch<ZwpPrimarySelectionOfferV1, PrimarySelectionOfferData>,
61{
62    fn event(
63        _: &mut State,
64        _: &ZwpPrimarySelectionOfferV1,
65        event: <ZwpPrimarySelectionOfferV1 as wayland_client::Proxy>::Event,
66        data: &PrimarySelectionOfferData,
67        _: &Connection,
68        _: &QueueHandle<State>,
69    ) {
70        use wayland_protocols::wp::primary_selection::zv1::client::zwp_primary_selection_offer_v1::Event;
71        match event {
72            Event::Offer { mime_type } => {
73                data.mimes.lock().unwrap().push(mime_type);
74            }
75            _ => unreachable!(),
76        }
77    }
78}
79
80/// The data associated with the [`ZwpPrimarySelectionOfferV1`].
81#[derive(Debug, Default)]
82pub struct PrimarySelectionOfferData {
83    mimes: Mutex<Vec<String>>,
84}