1 | use std::{ |
2 | os::unix::io::{AsFd, OwnedFd}, |
3 | sync::Mutex, |
4 | }; |
5 | |
6 | use crate::reexports::client::{Connection, Dispatch, QueueHandle, Proxy}; |
7 | use crate::reexports::protocols::wp::primary_selection::zv1::client::zwp_primary_selection_offer_v1::ZwpPrimarySelectionOfferV1; |
8 | |
9 | use crate::data_device_manager::ReadPipe; |
10 | |
11 | use super::PrimarySelectionManagerState; |
12 | |
13 | /// Wrapper around the [`ZwpPrimarySelectionOfferV1`]. |
14 | #[derive (Debug, Clone, PartialEq, Eq)] |
15 | pub struct PrimarySelectionOffer { |
16 | pub(crate) offer: ZwpPrimarySelectionOfferV1, |
17 | } |
18 | |
19 | impl 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 | |
57 | impl<State> Dispatch<ZwpPrimarySelectionOfferV1, PrimarySelectionOfferData, State> |
58 | for PrimarySelectionManagerState |
59 | where |
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)] |
82 | pub struct PrimarySelectionOfferData { |
83 | mimes: Mutex<Vec<String>>, |
84 | } |
85 | |