poll_integration/common/protocols/wayland/
wl_data_offer.rs

1//! offer to transfer data
2//!
3//! A wl_data_offer represents a piece of data offered for transfer
4//! by another client (the source client).  It is used by the
5//! copy-and-paste and drag-and-drop mechanisms.  The offer
6//! describes the different mime types that the data can be
7//! converted to and provides the mechanism for transferring the
8//! data directly from the source client.
9
10use {super::super::all_types::*, ::wl_client::builder::prelude::*};
11
12static INTERFACE: wl_interface = wl_interface {
13    name: c"wl_data_offer".as_ptr(),
14    version: 3,
15    method_count: 5,
16    methods: {
17        static MESSAGES: [wl_message; 5] = [
18            wl_message {
19                name: c"accept".as_ptr(),
20                signature: c"u?s".as_ptr(),
21                types: {
22                    static TYPES: [Option<&'static wl_interface>; 2] = [None, None];
23                    TYPES.as_ptr().cast()
24                },
25            },
26            wl_message {
27                name: c"receive".as_ptr(),
28                signature: c"sh".as_ptr(),
29                types: {
30                    static TYPES: [Option<&'static wl_interface>; 2] = [None, None];
31                    TYPES.as_ptr().cast()
32                },
33            },
34            wl_message {
35                name: c"destroy".as_ptr(),
36                signature: c"".as_ptr(),
37                types: {
38                    static TYPES: [Option<&'static wl_interface>; 0] = [];
39                    TYPES.as_ptr().cast()
40                },
41            },
42            wl_message {
43                name: c"finish".as_ptr(),
44                signature: c"".as_ptr(),
45                types: {
46                    static TYPES: [Option<&'static wl_interface>; 0] = [];
47                    TYPES.as_ptr().cast()
48                },
49            },
50            wl_message {
51                name: c"set_actions".as_ptr(),
52                signature: c"uu".as_ptr(),
53                types: {
54                    static TYPES: [Option<&'static wl_interface>; 2] = [None, None];
55                    TYPES.as_ptr().cast()
56                },
57            },
58        ];
59        MESSAGES.as_ptr()
60    },
61    event_count: 3,
62    events: {
63        static MESSAGES: [wl_message; 3] = [
64            wl_message {
65                name: c"offer".as_ptr(),
66                signature: c"s".as_ptr(),
67                types: {
68                    static TYPES: [Option<&'static wl_interface>; 1] = [None];
69                    TYPES.as_ptr().cast()
70                },
71            },
72            wl_message {
73                name: c"source_actions".as_ptr(),
74                signature: c"u".as_ptr(),
75                types: {
76                    static TYPES: [Option<&'static wl_interface>; 1] = [None];
77                    TYPES.as_ptr().cast()
78                },
79            },
80            wl_message {
81                name: c"action".as_ptr(),
82                signature: c"u".as_ptr(),
83                types: {
84                    static TYPES: [Option<&'static wl_interface>; 1] = [None];
85                    TYPES.as_ptr().cast()
86                },
87            },
88        ];
89        MESSAGES.as_ptr()
90    },
91};
92
93/// An owned wl_data_offer proxy.
94///
95/// See the documentation of [the module][self] for the interface description.
96#[derive(Clone, Eq, PartialEq)]
97#[repr(transparent)]
98pub struct WlDataOffer {
99    /// This proxy has the interface INTERFACE.
100    proxy: UntypedOwnedProxy,
101}
102
103/// A borrowed wl_data_offer proxy.
104///
105/// See the documentation of [the module][self] for the interface description.
106#[derive(Eq, PartialEq)]
107#[repr(transparent)]
108pub struct WlDataOfferRef {
109    /// This proxy has the interface INTERFACE.
110    proxy: UntypedBorrowedProxy,
111}
112
113// SAFETY: WlDataOffer is a transparent wrapper around UntypedOwnedProxy
114unsafe impl UntypedOwnedProxyWrapper for WlDataOffer {}
115
116// SAFETY: - INTERFACE is a valid wl_interface
117//         - The only invariant is that self.proxy has a compatible interface
118unsafe impl OwnedProxy for WlDataOffer {
119    const INTERFACE: &'static str = "wl_data_offer";
120    const WL_INTERFACE: &'static wl_interface = &INTERFACE;
121    const NO_OP_EVENT_HANDLER: Self::NoOpEventHandler =
122        private::EventHandler(private::NoOpEventHandler);
123    const MAX_VERSION: u32 = 3;
124
125    type Borrowed = WlDataOfferRef;
126    type Api = private::ProxyApi;
127    type NoOpEventHandler = private::EventHandler<private::NoOpEventHandler>;
128}
129
130// SAFETY: WlDataOfferRef is a transparent wrapper around UntypedBorrowedProxy
131unsafe impl UntypedBorrowedProxyWrapper for WlDataOfferRef {}
132
133// SAFETY: - The only invariant is that self.proxy has a compatible interface
134unsafe impl BorrowedProxy for WlDataOfferRef {
135    type Owned = WlDataOffer;
136}
137
138impl Deref for WlDataOffer {
139    type Target = WlDataOfferRef;
140
141    fn deref(&self) -> &Self::Target {
142        proxy::low_level::deref(self)
143    }
144}
145
146mod private {
147    pub struct ProxyApi;
148
149    #[allow(dead_code)]
150    pub struct EventHandler<H>(pub(super) H);
151
152    #[allow(dead_code)]
153    pub struct NoOpEventHandler;
154}
155
156impl Debug for WlDataOffer {
157    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
158        write!(f, "wl_data_offer#{}", self.proxy.id())
159    }
160}
161
162impl Debug for WlDataOfferRef {
163    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
164        write!(f, "wl_data_offer#{}", self.proxy.id())
165    }
166}
167
168impl PartialEq<WlDataOfferRef> for WlDataOffer {
169    fn eq(&self, other: &WlDataOfferRef) -> bool {
170        self.proxy == other.proxy
171    }
172}
173
174impl PartialEq<WlDataOffer> for WlDataOfferRef {
175    fn eq(&self, other: &WlDataOffer) -> bool {
176        self.proxy == other.proxy
177    }
178}
179
180#[allow(dead_code)]
181impl WlDataOffer {
182    /// Since when the destroy request is available.
183    #[allow(dead_code)]
184    pub const REQ__DESTROY__SINCE: u32 = 1;
185
186    /// destroy data offer
187    ///
188    /// Destroy the data offer.
189    #[inline]
190    pub fn destroy(&self) {
191        let mut args = [];
192        // SAFETY: - self.proxy has the interface INTERFACE
193        //         - 2 < INTERFACE.method_count = 5
194        //         - the request signature is ``
195        unsafe {
196            self.proxy.send_destructor(2, &mut args);
197        }
198    }
199}
200
201#[allow(dead_code)]
202impl WlDataOfferRef {
203    /// accept one of the offered mime types
204    ///
205    /// Indicate that the client can accept the given mime type, or
206    /// NULL for not accepted.
207    ///
208    /// For objects of version 2 or older, this request is used by the
209    /// client to give feedback whether the client can receive the given
210    /// mime type, or NULL if none is accepted; the feedback does not
211    /// determine whether the drag-and-drop operation succeeds or not.
212    ///
213    /// For objects of version 3 or newer, this request determines the
214    /// final result of the drag-and-drop operation. If the end result
215    /// is that no mime types were accepted, the drag-and-drop operation
216    /// will be cancelled and the corresponding drag source will receive
217    /// wl_data_source.cancelled. Clients may still use this event in
218    /// conjunction with wl_data_source.action for feedback.
219    ///
220    /// # Arguments
221    ///
222    /// - `serial`: serial number of the accept request
223    /// - `mime_type`: mime type accepted by the client
224    #[inline]
225    pub fn accept(&self, serial: u32, mime_type: Option<&str>) {
226        let (arg0, arg1) = (serial, mime_type);
227        with_cstr_cache(|cache| {
228            let str1_offset = cache.len();
229            if let Some(arg1) = arg1 {
230                cache.extend_from_slice(arg1.as_bytes());
231                cache.push(0);
232            }
233            let mut str1 = ptr::null();
234            if arg1.is_some() {
235                str1 = cache[str1_offset..].as_ptr().cast();
236            }
237            let mut args = [wl_argument { u: arg0 }, wl_argument { s: str1 }];
238            // SAFETY: - self.proxy has the interface INTERFACE
239            //         - 0 < INTERFACE.method_count = 5
240            //         - the request signature is `u?s`
241            unsafe {
242                self.proxy.send_request(0, &mut args);
243            }
244        })
245    }
246
247    /// request that the data is transferred
248    ///
249    /// To transfer the offered data, the client issues this request
250    /// and indicates the mime type it wants to receive.  The transfer
251    /// happens through the passed file descriptor (typically created
252    /// with the pipe system call).  The source client writes the data
253    /// in the mime type representation requested and then closes the
254    /// file descriptor.
255    ///
256    /// The receiving client reads from the read end of the pipe until
257    /// EOF and then closes its end, at which point the transfer is
258    /// complete.
259    ///
260    /// This request may happen multiple times for different mime types,
261    /// both before and after wl_data_device.drop. Drag-and-drop destination
262    /// clients may preemptively fetch data or examine it more closely to
263    /// determine acceptance.
264    ///
265    /// # Arguments
266    ///
267    /// - `mime_type`: mime type desired by receiver
268    /// - `fd`: file descriptor for data transfer
269    #[inline]
270    pub fn receive(&self, mime_type: &str, fd: BorrowedFd<'_>) {
271        let (arg0, arg1) = (mime_type, fd);
272        with_cstr_cache(|cache| {
273            let str0_offset = cache.len();
274            cache.extend_from_slice(arg0.as_bytes());
275            cache.push(0);
276            let str0 = cache[str0_offset..].as_ptr().cast();
277            let mut args = [
278                wl_argument { s: str0 },
279                wl_argument {
280                    h: arg1.as_raw_fd(),
281                },
282            ];
283            // SAFETY: - self.proxy has the interface INTERFACE
284            //         - 1 < INTERFACE.method_count = 5
285            //         - the request signature is `sh`
286            unsafe {
287                self.proxy.send_request(1, &mut args);
288            }
289        })
290    }
291
292    /// the offer will no longer be used
293    ///
294    /// Notifies the compositor that the drag destination successfully
295    /// finished the drag-and-drop operation.
296    ///
297    /// Upon receiving this request, the compositor will emit
298    /// wl_data_source.dnd_finished on the drag source client.
299    ///
300    /// It is a client error to perform other requests than
301    /// wl_data_offer.destroy after this one. It is also an error to perform
302    /// this request after a NULL mime type has been set in
303    /// wl_data_offer.accept or no action was received through
304    /// wl_data_offer.action.
305    ///
306    /// If wl_data_offer.finish request is received for a non drag and drop
307    /// operation, the invalid_finish protocol error is raised.
308    #[inline]
309    pub fn finish(&self) {
310        let mut args = [];
311        // SAFETY: - self.proxy has the interface INTERFACE
312        //         - 3 < INTERFACE.method_count = 5
313        //         - the request signature is ``
314        unsafe {
315            self.proxy.send_request(3, &mut args);
316        }
317    }
318
319    /// set the available/preferred drag-and-drop actions
320    ///
321    /// Sets the actions that the destination side client supports for
322    /// this operation. This request may trigger the emission of
323    /// wl_data_source.action and wl_data_offer.action events if the compositor
324    /// needs to change the selected action.
325    ///
326    /// This request can be called multiple times throughout the
327    /// drag-and-drop operation, typically in response to wl_data_device.enter
328    /// or wl_data_device.motion events.
329    ///
330    /// This request determines the final result of the drag-and-drop
331    /// operation. If the end result is that no action is accepted,
332    /// the drag source will receive wl_data_source.cancelled.
333    ///
334    /// The dnd_actions argument must contain only values expressed in the
335    /// wl_data_device_manager.dnd_actions enum, and the preferred_action
336    /// argument must only contain one of those values set, otherwise it
337    /// will result in a protocol error.
338    ///
339    /// While managing an "ask" action, the destination drag-and-drop client
340    /// may perform further wl_data_offer.receive requests, and is expected
341    /// to perform one last wl_data_offer.set_actions request with a preferred
342    /// action other than "ask" (and optionally wl_data_offer.accept) before
343    /// requesting wl_data_offer.finish, in order to convey the action selected
344    /// by the user. If the preferred action is not in the
345    /// wl_data_offer.source_actions mask, an error will be raised.
346    ///
347    /// If the "ask" action is dismissed (e.g. user cancellation), the client
348    /// is expected to perform wl_data_offer.destroy right away.
349    ///
350    /// This request can only be made on drag-and-drop offers, a protocol error
351    /// will be raised otherwise.
352    ///
353    /// # Arguments
354    ///
355    /// - `dnd_actions`: actions supported by the destination client
356    /// - `preferred_action`: action preferred by the destination client
357    #[inline]
358    pub fn set_actions(
359        &self,
360        dnd_actions: WlDataDeviceManagerDndAction,
361        preferred_action: WlDataDeviceManagerDndAction,
362    ) {
363        let (arg0, arg1) = (dnd_actions, preferred_action);
364        let mut args = [wl_argument { u: arg0.0 }, wl_argument { u: arg1.0 }];
365        // SAFETY: - self.proxy has the interface INTERFACE
366        //         - 4 < INTERFACE.method_count = 5
367        //         - the request signature is `uu`
368        unsafe {
369            self.proxy.send_request(4, &mut args);
370        }
371    }
372}
373
374impl WlDataOffer {
375    /// Since when the offer event is available.
376    #[allow(dead_code)]
377    pub const EVT__OFFER__SINCE: u32 = 1;
378
379    /// Since when the source_actions event is available.
380    #[allow(dead_code)]
381    pub const EVT__SOURCE_ACTIONS__SINCE: u32 = 3;
382
383    /// Since when the action event is available.
384    #[allow(dead_code)]
385    pub const EVT__ACTION__SINCE: u32 = 3;
386}
387
388/// An event handler for [WlDataOffer] proxies.
389#[allow(dead_code)]
390pub trait WlDataOfferEventHandler {
391    /// advertise offered mime type
392    ///
393    /// Sent immediately after creating the wl_data_offer object.  One
394    /// event per offered mime type.
395    ///
396    /// # Arguments
397    ///
398    /// - `mime_type`: offered mime type
399    #[inline]
400    fn offer(&self, _slf: &WlDataOfferRef, mime_type: &str) {
401        let _ = mime_type;
402    }
403
404    /// notify the source-side available actions
405    ///
406    /// This event indicates the actions offered by the data source. It
407    /// will be sent immediately after creating the wl_data_offer object,
408    /// or anytime the source side changes its offered actions through
409    /// wl_data_source.set_actions.
410    ///
411    /// # Arguments
412    ///
413    /// - `source_actions`: actions offered by the data source
414    #[inline]
415    fn source_actions(&self, _slf: &WlDataOfferRef, source_actions: WlDataDeviceManagerDndAction) {
416        let _ = source_actions;
417    }
418
419    /// notify the selected action
420    ///
421    /// This event indicates the action selected by the compositor after
422    /// matching the source/destination side actions. Only one action (or
423    /// none) will be offered here.
424    ///
425    /// This event can be emitted multiple times during the drag-and-drop
426    /// operation in response to destination side action changes through
427    /// wl_data_offer.set_actions.
428    ///
429    /// This event will no longer be emitted after wl_data_device.drop
430    /// happened on the drag-and-drop destination, the client must
431    /// honor the last action received, or the last preferred one set
432    /// through wl_data_offer.set_actions when handling an "ask" action.
433    ///
434    /// Compositors may also change the selected action on the fly, mainly
435    /// in response to keyboard modifier changes during the drag-and-drop
436    /// operation.
437    ///
438    /// The most recent action received is always the valid one. Prior to
439    /// receiving wl_data_device.drop, the chosen action may change (e.g.
440    /// due to keyboard modifiers being pressed). At the time of receiving
441    /// wl_data_device.drop the drag-and-drop destination must honor the
442    /// last action received.
443    ///
444    /// Action changes may still happen after wl_data_device.drop,
445    /// especially on "ask" actions, where the drag-and-drop destination
446    /// may choose another action afterwards. Action changes happening
447    /// at this stage are always the result of inter-client negotiation, the
448    /// compositor shall no longer be able to induce a different action.
449    ///
450    /// Upon "ask" actions, it is expected that the drag-and-drop destination
451    /// may potentially choose a different action and/or mime type,
452    /// based on wl_data_offer.source_actions and finally chosen by the
453    /// user (e.g. popping up a menu with the available options). The
454    /// final wl_data_offer.set_actions and wl_data_offer.accept requests
455    /// must happen before the call to wl_data_offer.finish.
456    ///
457    /// # Arguments
458    ///
459    /// - `dnd_action`: action selected by the compositor
460    #[inline]
461    fn action(&self, _slf: &WlDataOfferRef, dnd_action: WlDataDeviceManagerDndAction) {
462        let _ = dnd_action;
463    }
464}
465
466impl WlDataOfferEventHandler for private::NoOpEventHandler {}
467
468// SAFETY: INTERFACE is a valid wl_interface
469unsafe impl<H> EventHandler for private::EventHandler<H>
470where
471    H: WlDataOfferEventHandler,
472{
473    const WL_INTERFACE: &'static wl_interface = &INTERFACE;
474
475    #[allow(unused_variables)]
476    unsafe fn handle_event(
477        &self,
478        queue: &Queue,
479        slf: &UntypedBorrowedProxy,
480        opcode: u32,
481        args: *mut wl_argument,
482    ) {
483        // SAFETY: This function required that slf has the interface INTERFACE
484        let slf = unsafe { proxy::low_level::from_untyped_borrowed::<WlDataOfferRef>(slf) };
485        match opcode {
486            0 => {
487                // SAFETY: INTERFACE requires that there are 1 arguments
488                let args = unsafe { &*args.cast::<[wl_argument; 1]>() };
489                // SAFETY: - INTERFACE requires that args[0] contains a string
490                //         - if the pointer is not null, then it is a c string
491                let arg0 = unsafe { convert_string_arg("wl_data_offer", "mime_type", args[0].s) };
492                self.0.offer(slf, arg0);
493            }
494            1 => {
495                // SAFETY: INTERFACE requires that there are 1 arguments
496                let args = unsafe { &*args.cast::<[wl_argument; 1]>() };
497                // SAFETY: - INTERFACE requires that args[0] contains a uint
498                let arg0 = unsafe { WlDataDeviceManagerDndAction(args[0].u) };
499                self.0.source_actions(slf, arg0);
500            }
501            2 => {
502                // SAFETY: INTERFACE requires that there are 1 arguments
503                let args = unsafe { &*args.cast::<[wl_argument; 1]>() };
504                // SAFETY: - INTERFACE requires that args[0] contains a uint
505                let arg0 = unsafe { WlDataDeviceManagerDndAction(args[0].u) };
506                self.0.action(slf, arg0);
507            }
508            _ => {
509                invalid_opcode("wl_data_offer", opcode);
510            }
511        }
512    }
513}
514
515impl<H> CreateEventHandler<H> for private::ProxyApi
516where
517    H: WlDataOfferEventHandler,
518{
519    type EventHandler = private::EventHandler<H>;
520
521    #[inline]
522    fn create_event_handler(handler: H) -> Self::EventHandler {
523        private::EventHandler(handler)
524    }
525}
526
527impl WlDataOffer {
528    /// Since when the error.invalid_finish enum variant is available.
529    #[allow(dead_code)]
530    pub const ENM__ERROR_INVALID_FINISH__SINCE: u32 = 1;
531    /// Since when the error.invalid_action_mask enum variant is available.
532    #[allow(dead_code)]
533    pub const ENM__ERROR_INVALID_ACTION_MASK__SINCE: u32 = 1;
534    /// Since when the error.invalid_action enum variant is available.
535    #[allow(dead_code)]
536    pub const ENM__ERROR_INVALID_ACTION__SINCE: u32 = 1;
537    /// Since when the error.invalid_offer enum variant is available.
538    #[allow(dead_code)]
539    pub const ENM__ERROR_INVALID_OFFER__SINCE: u32 = 1;
540}
541
542#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
543#[allow(dead_code)]
544pub struct WlDataOfferError(pub u32);
545
546impl WlDataOfferError {
547    /// finish request was called untimely
548    #[allow(dead_code)]
549    pub const INVALID_FINISH: Self = Self(0);
550
551    /// action mask contains invalid values
552    #[allow(dead_code)]
553    pub const INVALID_ACTION_MASK: Self = Self(1);
554
555    /// action argument has an invalid value
556    #[allow(dead_code)]
557    pub const INVALID_ACTION: Self = Self(2);
558
559    /// offer doesn't accept this request
560    #[allow(dead_code)]
561    pub const INVALID_OFFER: Self = Self(3);
562}
563
564impl Debug for WlDataOfferError {
565    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
566        let name = match *self {
567            Self::INVALID_FINISH => "INVALID_FINISH",
568            Self::INVALID_ACTION_MASK => "INVALID_ACTION_MASK",
569            Self::INVALID_ACTION => "INVALID_ACTION",
570            Self::INVALID_OFFER => "INVALID_OFFER",
571            _ => return Debug::fmt(&self.0, f),
572        };
573        f.write_str(name)
574    }
575}
576
577/// Functional event handlers.
578pub mod event_handlers {
579    use super::*;
580
581    /// Event handler for offer events.
582    pub struct Offer<F>(F);
583    impl<F> WlDataOfferEventHandler for Offer<F>
584    where
585        F: Fn(&WlDataOfferRef, &str),
586    {
587        #[inline]
588        fn offer(&self, _slf: &WlDataOfferRef, mime_type: &str) {
589            self.0(_slf, mime_type)
590        }
591    }
592
593    /// Event handler for source_actions events.
594    pub struct SourceActions<F>(F);
595    impl<F> WlDataOfferEventHandler for SourceActions<F>
596    where
597        F: Fn(&WlDataOfferRef, WlDataDeviceManagerDndAction),
598    {
599        #[inline]
600        fn source_actions(
601            &self,
602            _slf: &WlDataOfferRef,
603            source_actions: WlDataDeviceManagerDndAction,
604        ) {
605            self.0(_slf, source_actions)
606        }
607    }
608
609    /// Event handler for action events.
610    pub struct Action<F>(F);
611    impl<F> WlDataOfferEventHandler for Action<F>
612    where
613        F: Fn(&WlDataOfferRef, WlDataDeviceManagerDndAction),
614    {
615        #[inline]
616        fn action(&self, _slf: &WlDataOfferRef, dnd_action: WlDataDeviceManagerDndAction) {
617            self.0(_slf, dnd_action)
618        }
619    }
620
621    impl WlDataOffer {
622        /// Creates an event handler for offer events.
623        ///
624        /// The event handler ignores all other events.
625        #[allow(dead_code)]
626        pub fn on_offer<F>(f: F) -> Offer<F>
627        where
628            F: Fn(&WlDataOfferRef, &str),
629        {
630            Offer(f)
631        }
632
633        /// Creates an event handler for source_actions events.
634        ///
635        /// The event handler ignores all other events.
636        #[allow(dead_code)]
637        pub fn on_source_actions<F>(f: F) -> SourceActions<F>
638        where
639            F: Fn(&WlDataOfferRef, WlDataDeviceManagerDndAction),
640        {
641            SourceActions(f)
642        }
643
644        /// Creates an event handler for action events.
645        ///
646        /// The event handler ignores all other events.
647        #[allow(dead_code)]
648        pub fn on_action<F>(f: F) -> Action<F>
649        where
650            F: Fn(&WlDataOfferRef, WlDataDeviceManagerDndAction),
651        {
652            Action(f)
653        }
654    }
655}