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: String } => {
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}
85