simple_window/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        data: *mut u8,
480        slf: &UntypedBorrowedProxy,
481        opcode: u32,
482        args: *mut wl_argument,
483    ) {
484        // SAFETY: This function requires that slf has the interface INTERFACE
485        let slf = unsafe { proxy::low_level::from_untyped_borrowed::<WlDataOfferRef>(slf) };
486        match opcode {
487            0 => {
488                // SAFETY: INTERFACE requires that there are 1 arguments
489                let args = unsafe { &*args.cast::<[wl_argument; 1]>() };
490                // SAFETY: - INTERFACE requires that args[0] contains a string
491                //         - if the pointer is not null, then it is a c string
492                let arg0 = unsafe { convert_string_arg("wl_data_offer", "mime_type", args[0].s) };
493                self.0.offer(slf, arg0);
494            }
495            1 => {
496                // SAFETY: INTERFACE requires that there are 1 arguments
497                let args = unsafe { &*args.cast::<[wl_argument; 1]>() };
498                // SAFETY: - INTERFACE requires that args[0] contains a uint
499                let arg0 = unsafe { WlDataDeviceManagerDndAction(args[0].u) };
500                self.0.source_actions(slf, arg0);
501            }
502            2 => {
503                // SAFETY: INTERFACE requires that there are 1 arguments
504                let args = unsafe { &*args.cast::<[wl_argument; 1]>() };
505                // SAFETY: - INTERFACE requires that args[0] contains a uint
506                let arg0 = unsafe { WlDataDeviceManagerDndAction(args[0].u) };
507                self.0.action(slf, arg0);
508            }
509            _ => {
510                invalid_opcode("wl_data_offer", opcode);
511            }
512        }
513    }
514}
515
516impl<H> CreateEventHandler<H> for private::ProxyApi
517where
518    H: WlDataOfferEventHandler,
519{
520    type EventHandler = private::EventHandler<H>;
521
522    #[inline]
523    fn create_event_handler(handler: H) -> Self::EventHandler {
524        private::EventHandler(handler)
525    }
526}
527
528impl WlDataOffer {
529    /// Since when the error.invalid_finish enum variant is available.
530    #[allow(dead_code)]
531    pub const ENM__ERROR_INVALID_FINISH__SINCE: u32 = 1;
532    /// Since when the error.invalid_action_mask enum variant is available.
533    #[allow(dead_code)]
534    pub const ENM__ERROR_INVALID_ACTION_MASK__SINCE: u32 = 1;
535    /// Since when the error.invalid_action enum variant is available.
536    #[allow(dead_code)]
537    pub const ENM__ERROR_INVALID_ACTION__SINCE: u32 = 1;
538    /// Since when the error.invalid_offer enum variant is available.
539    #[allow(dead_code)]
540    pub const ENM__ERROR_INVALID_OFFER__SINCE: u32 = 1;
541}
542
543#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
544#[allow(dead_code)]
545pub struct WlDataOfferError(pub u32);
546
547impl WlDataOfferError {
548    /// finish request was called untimely
549    #[allow(dead_code)]
550    pub const INVALID_FINISH: Self = Self(0);
551
552    /// action mask contains invalid values
553    #[allow(dead_code)]
554    pub const INVALID_ACTION_MASK: Self = Self(1);
555
556    /// action argument has an invalid value
557    #[allow(dead_code)]
558    pub const INVALID_ACTION: Self = Self(2);
559
560    /// offer doesn't accept this request
561    #[allow(dead_code)]
562    pub const INVALID_OFFER: Self = Self(3);
563}
564
565impl Debug for WlDataOfferError {
566    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
567        let name = match *self {
568            Self::INVALID_FINISH => "INVALID_FINISH",
569            Self::INVALID_ACTION_MASK => "INVALID_ACTION_MASK",
570            Self::INVALID_ACTION => "INVALID_ACTION",
571            Self::INVALID_OFFER => "INVALID_OFFER",
572            _ => return Debug::fmt(&self.0, f),
573        };
574        f.write_str(name)
575    }
576}
577
578/// Functional event handlers.
579pub mod event_handlers {
580    use super::*;
581
582    /// Event handler for offer events.
583    pub struct Offer<F>(F);
584    impl<F> WlDataOfferEventHandler for Offer<F>
585    where
586        F: Fn(&WlDataOfferRef, &str),
587    {
588        #[inline]
589        fn offer(&self, _slf: &WlDataOfferRef, mime_type: &str) {
590            self.0(_slf, mime_type)
591        }
592    }
593
594    /// Event handler for source_actions events.
595    pub struct SourceActions<F>(F);
596    impl<F> WlDataOfferEventHandler for SourceActions<F>
597    where
598        F: Fn(&WlDataOfferRef, WlDataDeviceManagerDndAction),
599    {
600        #[inline]
601        fn source_actions(
602            &self,
603            _slf: &WlDataOfferRef,
604            source_actions: WlDataDeviceManagerDndAction,
605        ) {
606            self.0(_slf, source_actions)
607        }
608    }
609
610    /// Event handler for action events.
611    pub struct Action<F>(F);
612    impl<F> WlDataOfferEventHandler for Action<F>
613    where
614        F: Fn(&WlDataOfferRef, WlDataDeviceManagerDndAction),
615    {
616        #[inline]
617        fn action(&self, _slf: &WlDataOfferRef, dnd_action: WlDataDeviceManagerDndAction) {
618            self.0(_slf, dnd_action)
619        }
620    }
621
622    impl WlDataOffer {
623        /// Creates an event handler for offer events.
624        ///
625        /// The event handler ignores all other events.
626        #[allow(dead_code)]
627        pub fn on_offer<F>(f: F) -> Offer<F>
628        where
629            F: Fn(&WlDataOfferRef, &str),
630        {
631            Offer(f)
632        }
633
634        /// Creates an event handler for source_actions events.
635        ///
636        /// The event handler ignores all other events.
637        #[allow(dead_code)]
638        pub fn on_source_actions<F>(f: F) -> SourceActions<F>
639        where
640            F: Fn(&WlDataOfferRef, WlDataDeviceManagerDndAction),
641        {
642            SourceActions(f)
643        }
644
645        /// Creates an event handler for action events.
646        ///
647        /// The event handler ignores all other events.
648        #[allow(dead_code)]
649        pub fn on_action<F>(f: F) -> Action<F>
650        where
651            F: Fn(&WlDataOfferRef, WlDataDeviceManagerDndAction),
652        {
653            Action(f)
654        }
655    }
656}