wl_proxy/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 crate::protocol_helpers::prelude::*;
11use super::super::all_types::*;
12
13/// A wl_data_offer object.
14///
15/// See the documentation of [the module][self] for the interface description.
16pub struct WlDataOffer {
17    core: ObjectCore,
18    handler: HandlerHolder<dyn WlDataOfferHandler>,
19}
20
21struct DefaultHandler;
22
23impl WlDataOfferHandler for DefaultHandler { }
24
25impl ConcreteObject for WlDataOffer {
26    const XML_VERSION: u32 = 3;
27    const INTERFACE: ObjectInterface = ObjectInterface::WlDataOffer;
28    const INTERFACE_NAME: &str = "wl_data_offer";
29}
30
31impl WlDataOffer {
32    /// Sets a new handler.
33    pub fn set_handler(&self, handler: impl WlDataOfferHandler) {
34        self.set_boxed_handler(Box::new(handler));
35    }
36
37    /// Sets a new, already boxed handler.
38    pub fn set_boxed_handler(&self, handler: Box<dyn WlDataOfferHandler>) {
39        if self.core.state.destroyed.get() {
40            return;
41        }
42        self.handler.set(Some(handler));
43    }
44}
45
46impl Debug for WlDataOffer {
47    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
48        f.debug_struct("WlDataOffer")
49            .field("server_obj_id", &self.core.server_obj_id.get())
50            .field("client_id", &self.core.client_id.get())
51            .field("client_obj_id", &self.core.client_obj_id.get())
52            .finish()
53    }
54}
55
56impl WlDataOffer {
57    /// Since when the accept message is available.
58    pub const MSG__ACCEPT__SINCE: u32 = 1;
59
60    /// accept one of the offered mime types
61    ///
62    /// Indicate that the client can accept the given mime type, or
63    /// NULL for not accepted.
64    ///
65    /// For objects of version 2 or older, this request is used by the
66    /// client to give feedback whether the client can receive the given
67    /// mime type, or NULL if none is accepted; the feedback does not
68    /// determine whether the drag-and-drop operation succeeds or not.
69    ///
70    /// For objects of version 3 or newer, this request determines the
71    /// final result of the drag-and-drop operation. If the end result
72    /// is that no mime types were accepted, the drag-and-drop operation
73    /// will be cancelled and the corresponding drag source will receive
74    /// wl_data_source.cancelled. Clients may still use this event in
75    /// conjunction with wl_data_source.action for feedback.
76    ///
77    /// # Arguments
78    ///
79    /// - `serial`: serial number of the accept request
80    /// - `mime_type`: mime type accepted by the client
81    #[inline]
82    pub fn try_send_accept(
83        &self,
84        serial: u32,
85        mime_type: Option<&str>,
86    ) -> Result<(), ObjectError> {
87        let (
88            arg0,
89            arg1,
90        ) = (
91            serial,
92            mime_type,
93        );
94        let core = self.core();
95        let Some(id) = core.server_obj_id.get() else {
96            return Err(ObjectError(ObjectErrorKind::ReceiverNoServerId));
97        };
98        #[cfg(feature = "logging")]
99        if self.core.state.log {
100            #[cold]
101            fn log(state: &State, id: u32, arg0: u32, arg1: Option<&str>) {
102                let (millis, micros) = time_since_epoch();
103                let prefix = &state.log_prefix;
104                let args = format_args!("[{millis:7}.{micros:03}] {prefix}server      <= wl_data_offer#{}.accept(serial: {}, mime_type: {:?})\n", id, arg0, arg1);
105                state.log(args);
106            }
107            log(&self.core.state, id, arg0, arg1);
108        }
109        let Some(endpoint) = &self.core.state.server else {
110            return Ok(());
111        };
112        if !endpoint.flush_queued.replace(true) {
113            self.core.state.add_flushable_endpoint(endpoint, None);
114        }
115        let mut outgoing_ref = endpoint.outgoing.borrow_mut();
116        let outgoing = &mut *outgoing_ref;
117        let mut fmt = outgoing.formatter();
118        fmt.words([
119            id,
120            0,
121            arg0,
122        ]);
123        if let Some(arg1) = arg1 {
124            fmt.string(arg1);
125        } else {
126            fmt.words([0]);
127        }
128        Ok(())
129    }
130
131    /// accept one of the offered mime types
132    ///
133    /// Indicate that the client can accept the given mime type, or
134    /// NULL for not accepted.
135    ///
136    /// For objects of version 2 or older, this request is used by the
137    /// client to give feedback whether the client can receive the given
138    /// mime type, or NULL if none is accepted; the feedback does not
139    /// determine whether the drag-and-drop operation succeeds or not.
140    ///
141    /// For objects of version 3 or newer, this request determines the
142    /// final result of the drag-and-drop operation. If the end result
143    /// is that no mime types were accepted, the drag-and-drop operation
144    /// will be cancelled and the corresponding drag source will receive
145    /// wl_data_source.cancelled. Clients may still use this event in
146    /// conjunction with wl_data_source.action for feedback.
147    ///
148    /// # Arguments
149    ///
150    /// - `serial`: serial number of the accept request
151    /// - `mime_type`: mime type accepted by the client
152    #[inline]
153    pub fn send_accept(
154        &self,
155        serial: u32,
156        mime_type: Option<&str>,
157    ) {
158        let res = self.try_send_accept(
159            serial,
160            mime_type,
161        );
162        if let Err(e) = res {
163            log_send("wl_data_offer.accept", &e);
164        }
165    }
166
167    /// Since when the receive message is available.
168    pub const MSG__RECEIVE__SINCE: u32 = 1;
169
170    /// request that the data is transferred
171    ///
172    /// To transfer the offered data, the client issues this request
173    /// and indicates the mime type it wants to receive.  The transfer
174    /// happens through the passed file descriptor (typically created
175    /// with the pipe system call).  The source client writes the data
176    /// in the mime type representation requested and then closes the
177    /// file descriptor.
178    ///
179    /// The receiving client reads from the read end of the pipe until
180    /// EOF and then closes its end, at which point the transfer is
181    /// complete.
182    ///
183    /// This request may happen multiple times for different mime types,
184    /// both before and after wl_data_device.drop. Drag-and-drop destination
185    /// clients may preemptively fetch data or examine it more closely to
186    /// determine acceptance.
187    ///
188    /// # Arguments
189    ///
190    /// - `mime_type`: mime type desired by receiver
191    /// - `fd`: file descriptor for data transfer
192    #[inline]
193    pub fn try_send_receive(
194        &self,
195        mime_type: &str,
196        fd: &Rc<OwnedFd>,
197    ) -> Result<(), ObjectError> {
198        let (
199            arg0,
200            arg1,
201        ) = (
202            mime_type,
203            fd,
204        );
205        let core = self.core();
206        let Some(id) = core.server_obj_id.get() else {
207            return Err(ObjectError(ObjectErrorKind::ReceiverNoServerId));
208        };
209        #[cfg(feature = "logging")]
210        if self.core.state.log {
211            #[cold]
212            fn log(state: &State, id: u32, arg0: &str, arg1: i32) {
213                let (millis, micros) = time_since_epoch();
214                let prefix = &state.log_prefix;
215                let args = format_args!("[{millis:7}.{micros:03}] {prefix}server      <= wl_data_offer#{}.receive(mime_type: {:?}, fd: {})\n", id, arg0, arg1);
216                state.log(args);
217            }
218            log(&self.core.state, id, arg0, arg1.as_raw_fd());
219        }
220        let Some(endpoint) = &self.core.state.server else {
221            return Ok(());
222        };
223        if !endpoint.flush_queued.replace(true) {
224            self.core.state.add_flushable_endpoint(endpoint, None);
225        }
226        let mut outgoing_ref = endpoint.outgoing.borrow_mut();
227        let outgoing = &mut *outgoing_ref;
228        let mut fmt = outgoing.formatter();
229        fmt.words([
230            id,
231            1,
232        ]);
233        fmt.string(arg0);
234        fmt.fds.push_back(arg1.clone());
235        Ok(())
236    }
237
238    /// request that the data is transferred
239    ///
240    /// To transfer the offered data, the client issues this request
241    /// and indicates the mime type it wants to receive.  The transfer
242    /// happens through the passed file descriptor (typically created
243    /// with the pipe system call).  The source client writes the data
244    /// in the mime type representation requested and then closes the
245    /// file descriptor.
246    ///
247    /// The receiving client reads from the read end of the pipe until
248    /// EOF and then closes its end, at which point the transfer is
249    /// complete.
250    ///
251    /// This request may happen multiple times for different mime types,
252    /// both before and after wl_data_device.drop. Drag-and-drop destination
253    /// clients may preemptively fetch data or examine it more closely to
254    /// determine acceptance.
255    ///
256    /// # Arguments
257    ///
258    /// - `mime_type`: mime type desired by receiver
259    /// - `fd`: file descriptor for data transfer
260    #[inline]
261    pub fn send_receive(
262        &self,
263        mime_type: &str,
264        fd: &Rc<OwnedFd>,
265    ) {
266        let res = self.try_send_receive(
267            mime_type,
268            fd,
269        );
270        if let Err(e) = res {
271            log_send("wl_data_offer.receive", &e);
272        }
273    }
274
275    /// Since when the destroy message is available.
276    pub const MSG__DESTROY__SINCE: u32 = 1;
277
278    /// destroy data offer
279    ///
280    /// Destroy the data offer.
281    #[inline]
282    pub fn try_send_destroy(
283        &self,
284    ) -> Result<(), ObjectError> {
285        let core = self.core();
286        let Some(id) = core.server_obj_id.get() else {
287            return Err(ObjectError(ObjectErrorKind::ReceiverNoServerId));
288        };
289        #[cfg(feature = "logging")]
290        if self.core.state.log {
291            #[cold]
292            fn log(state: &State, id: u32) {
293                let (millis, micros) = time_since_epoch();
294                let prefix = &state.log_prefix;
295                let args = format_args!("[{millis:7}.{micros:03}] {prefix}server      <= wl_data_offer#{}.destroy()\n", id);
296                state.log(args);
297            }
298            log(&self.core.state, id);
299        }
300        let Some(endpoint) = &self.core.state.server else {
301            return Ok(());
302        };
303        if !endpoint.flush_queued.replace(true) {
304            self.core.state.add_flushable_endpoint(endpoint, None);
305        }
306        let mut outgoing_ref = endpoint.outgoing.borrow_mut();
307        let outgoing = &mut *outgoing_ref;
308        let mut fmt = outgoing.formatter();
309        fmt.words([
310            id,
311            2,
312        ]);
313        self.core.handle_server_destroy();
314        Ok(())
315    }
316
317    /// destroy data offer
318    ///
319    /// Destroy the data offer.
320    #[inline]
321    pub fn send_destroy(
322        &self,
323    ) {
324        let res = self.try_send_destroy(
325        );
326        if let Err(e) = res {
327            log_send("wl_data_offer.destroy", &e);
328        }
329    }
330
331    /// Since when the offer message is available.
332    pub const MSG__OFFER__SINCE: u32 = 1;
333
334    /// advertise offered mime type
335    ///
336    /// Sent immediately after creating the wl_data_offer object.  One
337    /// event per offered mime type.
338    ///
339    /// # Arguments
340    ///
341    /// - `mime_type`: offered mime type
342    #[inline]
343    pub fn try_send_offer(
344        &self,
345        mime_type: &str,
346    ) -> Result<(), ObjectError> {
347        let (
348            arg0,
349        ) = (
350            mime_type,
351        );
352        let core = self.core();
353        let client_ref = core.client.borrow();
354        let Some(client) = &*client_ref else {
355            return Err(ObjectError(ObjectErrorKind::ReceiverNoClient));
356        };
357        let id = core.client_obj_id.get().unwrap_or(0);
358        #[cfg(feature = "logging")]
359        if self.core.state.log {
360            #[cold]
361            fn log(state: &State, client_id: u64, id: u32, arg0: &str) {
362                let (millis, micros) = time_since_epoch();
363                let prefix = &state.log_prefix;
364                let args = format_args!("[{millis:7}.{micros:03}] {prefix}client#{:<4} <= wl_data_offer#{}.offer(mime_type: {:?})\n", client_id, id, arg0);
365                state.log(args);
366            }
367            log(&self.core.state, client.endpoint.id, id, arg0);
368        }
369        let endpoint = &client.endpoint;
370        if !endpoint.flush_queued.replace(true) {
371            self.core.state.add_flushable_endpoint(endpoint, Some(client));
372        }
373        let mut outgoing_ref = endpoint.outgoing.borrow_mut();
374        let outgoing = &mut *outgoing_ref;
375        let mut fmt = outgoing.formatter();
376        fmt.words([
377            id,
378            0,
379        ]);
380        fmt.string(arg0);
381        Ok(())
382    }
383
384    /// advertise offered mime type
385    ///
386    /// Sent immediately after creating the wl_data_offer object.  One
387    /// event per offered mime type.
388    ///
389    /// # Arguments
390    ///
391    /// - `mime_type`: offered mime type
392    #[inline]
393    pub fn send_offer(
394        &self,
395        mime_type: &str,
396    ) {
397        let res = self.try_send_offer(
398            mime_type,
399        );
400        if let Err(e) = res {
401            log_send("wl_data_offer.offer", &e);
402        }
403    }
404
405    /// Since when the finish message is available.
406    pub const MSG__FINISH__SINCE: u32 = 3;
407
408    /// the offer will no longer be used
409    ///
410    /// Notifies the compositor that the drag destination successfully
411    /// finished the drag-and-drop operation.
412    ///
413    /// Upon receiving this request, the compositor will emit
414    /// wl_data_source.dnd_finished on the drag source client.
415    ///
416    /// It is a client error to perform other requests than
417    /// wl_data_offer.destroy after this one. It is also an error to perform
418    /// this request after a NULL mime type has been set in
419    /// wl_data_offer.accept or no action was received through
420    /// wl_data_offer.action.
421    ///
422    /// If wl_data_offer.finish request is received for a non drag and drop
423    /// operation, the invalid_finish protocol error is raised.
424    #[inline]
425    pub fn try_send_finish(
426        &self,
427    ) -> Result<(), ObjectError> {
428        let core = self.core();
429        let Some(id) = core.server_obj_id.get() else {
430            return Err(ObjectError(ObjectErrorKind::ReceiverNoServerId));
431        };
432        #[cfg(feature = "logging")]
433        if self.core.state.log {
434            #[cold]
435            fn log(state: &State, id: u32) {
436                let (millis, micros) = time_since_epoch();
437                let prefix = &state.log_prefix;
438                let args = format_args!("[{millis:7}.{micros:03}] {prefix}server      <= wl_data_offer#{}.finish()\n", id);
439                state.log(args);
440            }
441            log(&self.core.state, id);
442        }
443        let Some(endpoint) = &self.core.state.server else {
444            return Ok(());
445        };
446        if !endpoint.flush_queued.replace(true) {
447            self.core.state.add_flushable_endpoint(endpoint, None);
448        }
449        let mut outgoing_ref = endpoint.outgoing.borrow_mut();
450        let outgoing = &mut *outgoing_ref;
451        let mut fmt = outgoing.formatter();
452        fmt.words([
453            id,
454            3,
455        ]);
456        Ok(())
457    }
458
459    /// the offer will no longer be used
460    ///
461    /// Notifies the compositor that the drag destination successfully
462    /// finished the drag-and-drop operation.
463    ///
464    /// Upon receiving this request, the compositor will emit
465    /// wl_data_source.dnd_finished on the drag source client.
466    ///
467    /// It is a client error to perform other requests than
468    /// wl_data_offer.destroy after this one. It is also an error to perform
469    /// this request after a NULL mime type has been set in
470    /// wl_data_offer.accept or no action was received through
471    /// wl_data_offer.action.
472    ///
473    /// If wl_data_offer.finish request is received for a non drag and drop
474    /// operation, the invalid_finish protocol error is raised.
475    #[inline]
476    pub fn send_finish(
477        &self,
478    ) {
479        let res = self.try_send_finish(
480        );
481        if let Err(e) = res {
482            log_send("wl_data_offer.finish", &e);
483        }
484    }
485
486    /// Since when the set_actions message is available.
487    pub const MSG__SET_ACTIONS__SINCE: u32 = 3;
488
489    /// set the available/preferred drag-and-drop actions
490    ///
491    /// Sets the actions that the destination side client supports for
492    /// this operation. This request may trigger the emission of
493    /// wl_data_source.action and wl_data_offer.action events if the compositor
494    /// needs to change the selected action.
495    ///
496    /// This request can be called multiple times throughout the
497    /// drag-and-drop operation, typically in response to wl_data_device.enter
498    /// or wl_data_device.motion events.
499    ///
500    /// This request determines the final result of the drag-and-drop
501    /// operation. If the end result is that no action is accepted,
502    /// the drag source will receive wl_data_source.cancelled.
503    ///
504    /// The dnd_actions argument must contain only values expressed in the
505    /// wl_data_device_manager.dnd_actions enum, and the preferred_action
506    /// argument must only contain one of those values set, otherwise it
507    /// will result in a protocol error.
508    ///
509    /// While managing an "ask" action, the destination drag-and-drop client
510    /// may perform further wl_data_offer.receive requests, and is expected
511    /// to perform one last wl_data_offer.set_actions request with a preferred
512    /// action other than "ask" (and optionally wl_data_offer.accept) before
513    /// requesting wl_data_offer.finish, in order to convey the action selected
514    /// by the user. If the preferred action is not in the
515    /// wl_data_offer.source_actions mask, an error will be raised.
516    ///
517    /// If the "ask" action is dismissed (e.g. user cancellation), the client
518    /// is expected to perform wl_data_offer.destroy right away.
519    ///
520    /// This request can only be made on drag-and-drop offers, a protocol error
521    /// will be raised otherwise.
522    ///
523    /// # Arguments
524    ///
525    /// - `dnd_actions`: actions supported by the destination client
526    /// - `preferred_action`: action preferred by the destination client
527    #[inline]
528    pub fn try_send_set_actions(
529        &self,
530        dnd_actions: WlDataDeviceManagerDndAction,
531        preferred_action: WlDataDeviceManagerDndAction,
532    ) -> Result<(), ObjectError> {
533        let (
534            arg0,
535            arg1,
536        ) = (
537            dnd_actions,
538            preferred_action,
539        );
540        let core = self.core();
541        let Some(id) = core.server_obj_id.get() else {
542            return Err(ObjectError(ObjectErrorKind::ReceiverNoServerId));
543        };
544        #[cfg(feature = "logging")]
545        if self.core.state.log {
546            #[cold]
547            fn log(state: &State, id: u32, arg0: WlDataDeviceManagerDndAction, arg1: WlDataDeviceManagerDndAction) {
548                let (millis, micros) = time_since_epoch();
549                let prefix = &state.log_prefix;
550                let args = format_args!("[{millis:7}.{micros:03}] {prefix}server      <= wl_data_offer#{}.set_actions(dnd_actions: {:?}, preferred_action: {:?})\n", id, arg0, arg1);
551                state.log(args);
552            }
553            log(&self.core.state, id, arg0, arg1);
554        }
555        let Some(endpoint) = &self.core.state.server else {
556            return Ok(());
557        };
558        if !endpoint.flush_queued.replace(true) {
559            self.core.state.add_flushable_endpoint(endpoint, None);
560        }
561        let mut outgoing_ref = endpoint.outgoing.borrow_mut();
562        let outgoing = &mut *outgoing_ref;
563        let mut fmt = outgoing.formatter();
564        fmt.words([
565            id,
566            4,
567            arg0.0,
568            arg1.0,
569        ]);
570        Ok(())
571    }
572
573    /// set the available/preferred drag-and-drop actions
574    ///
575    /// Sets the actions that the destination side client supports for
576    /// this operation. This request may trigger the emission of
577    /// wl_data_source.action and wl_data_offer.action events if the compositor
578    /// needs to change the selected action.
579    ///
580    /// This request can be called multiple times throughout the
581    /// drag-and-drop operation, typically in response to wl_data_device.enter
582    /// or wl_data_device.motion events.
583    ///
584    /// This request determines the final result of the drag-and-drop
585    /// operation. If the end result is that no action is accepted,
586    /// the drag source will receive wl_data_source.cancelled.
587    ///
588    /// The dnd_actions argument must contain only values expressed in the
589    /// wl_data_device_manager.dnd_actions enum, and the preferred_action
590    /// argument must only contain one of those values set, otherwise it
591    /// will result in a protocol error.
592    ///
593    /// While managing an "ask" action, the destination drag-and-drop client
594    /// may perform further wl_data_offer.receive requests, and is expected
595    /// to perform one last wl_data_offer.set_actions request with a preferred
596    /// action other than "ask" (and optionally wl_data_offer.accept) before
597    /// requesting wl_data_offer.finish, in order to convey the action selected
598    /// by the user. If the preferred action is not in the
599    /// wl_data_offer.source_actions mask, an error will be raised.
600    ///
601    /// If the "ask" action is dismissed (e.g. user cancellation), the client
602    /// is expected to perform wl_data_offer.destroy right away.
603    ///
604    /// This request can only be made on drag-and-drop offers, a protocol error
605    /// will be raised otherwise.
606    ///
607    /// # Arguments
608    ///
609    /// - `dnd_actions`: actions supported by the destination client
610    /// - `preferred_action`: action preferred by the destination client
611    #[inline]
612    pub fn send_set_actions(
613        &self,
614        dnd_actions: WlDataDeviceManagerDndAction,
615        preferred_action: WlDataDeviceManagerDndAction,
616    ) {
617        let res = self.try_send_set_actions(
618            dnd_actions,
619            preferred_action,
620        );
621        if let Err(e) = res {
622            log_send("wl_data_offer.set_actions", &e);
623        }
624    }
625
626    /// Since when the source_actions message is available.
627    pub const MSG__SOURCE_ACTIONS__SINCE: u32 = 3;
628
629    /// notify the source-side available actions
630    ///
631    /// This event indicates the actions offered by the data source. It
632    /// will be sent immediately after creating the wl_data_offer object,
633    /// or anytime the source side changes its offered actions through
634    /// wl_data_source.set_actions.
635    ///
636    /// # Arguments
637    ///
638    /// - `source_actions`: actions offered by the data source
639    #[inline]
640    pub fn try_send_source_actions(
641        &self,
642        source_actions: WlDataDeviceManagerDndAction,
643    ) -> Result<(), ObjectError> {
644        let (
645            arg0,
646        ) = (
647            source_actions,
648        );
649        let core = self.core();
650        let client_ref = core.client.borrow();
651        let Some(client) = &*client_ref else {
652            return Err(ObjectError(ObjectErrorKind::ReceiverNoClient));
653        };
654        let id = core.client_obj_id.get().unwrap_or(0);
655        #[cfg(feature = "logging")]
656        if self.core.state.log {
657            #[cold]
658            fn log(state: &State, client_id: u64, id: u32, arg0: WlDataDeviceManagerDndAction) {
659                let (millis, micros) = time_since_epoch();
660                let prefix = &state.log_prefix;
661                let args = format_args!("[{millis:7}.{micros:03}] {prefix}client#{:<4} <= wl_data_offer#{}.source_actions(source_actions: {:?})\n", client_id, id, arg0);
662                state.log(args);
663            }
664            log(&self.core.state, client.endpoint.id, id, arg0);
665        }
666        let endpoint = &client.endpoint;
667        if !endpoint.flush_queued.replace(true) {
668            self.core.state.add_flushable_endpoint(endpoint, Some(client));
669        }
670        let mut outgoing_ref = endpoint.outgoing.borrow_mut();
671        let outgoing = &mut *outgoing_ref;
672        let mut fmt = outgoing.formatter();
673        fmt.words([
674            id,
675            1,
676            arg0.0,
677        ]);
678        Ok(())
679    }
680
681    /// notify the source-side available actions
682    ///
683    /// This event indicates the actions offered by the data source. It
684    /// will be sent immediately after creating the wl_data_offer object,
685    /// or anytime the source side changes its offered actions through
686    /// wl_data_source.set_actions.
687    ///
688    /// # Arguments
689    ///
690    /// - `source_actions`: actions offered by the data source
691    #[inline]
692    pub fn send_source_actions(
693        &self,
694        source_actions: WlDataDeviceManagerDndAction,
695    ) {
696        let res = self.try_send_source_actions(
697            source_actions,
698        );
699        if let Err(e) = res {
700            log_send("wl_data_offer.source_actions", &e);
701        }
702    }
703
704    /// Since when the action message is available.
705    pub const MSG__ACTION__SINCE: u32 = 3;
706
707    /// notify the selected action
708    ///
709    /// This event indicates the action selected by the compositor after
710    /// matching the source/destination side actions. Only one action (or
711    /// none) will be offered here.
712    ///
713    /// This event can be emitted multiple times during the drag-and-drop
714    /// operation in response to destination side action changes through
715    /// wl_data_offer.set_actions.
716    ///
717    /// This event will no longer be emitted after wl_data_device.drop
718    /// happened on the drag-and-drop destination, the client must
719    /// honor the last action received, or the last preferred one set
720    /// through wl_data_offer.set_actions when handling an "ask" action.
721    ///
722    /// Compositors may also change the selected action on the fly, mainly
723    /// in response to keyboard modifier changes during the drag-and-drop
724    /// operation.
725    ///
726    /// The most recent action received is always the valid one. Prior to
727    /// receiving wl_data_device.drop, the chosen action may change (e.g.
728    /// due to keyboard modifiers being pressed). At the time of receiving
729    /// wl_data_device.drop the drag-and-drop destination must honor the
730    /// last action received.
731    ///
732    /// Action changes may still happen after wl_data_device.drop,
733    /// especially on "ask" actions, where the drag-and-drop destination
734    /// may choose another action afterwards. Action changes happening
735    /// at this stage are always the result of inter-client negotiation, the
736    /// compositor shall no longer be able to induce a different action.
737    ///
738    /// Upon "ask" actions, it is expected that the drag-and-drop destination
739    /// may potentially choose a different action and/or mime type,
740    /// based on wl_data_offer.source_actions and finally chosen by the
741    /// user (e.g. popping up a menu with the available options). The
742    /// final wl_data_offer.set_actions and wl_data_offer.accept requests
743    /// must happen before the call to wl_data_offer.finish.
744    ///
745    /// # Arguments
746    ///
747    /// - `dnd_action`: action selected by the compositor
748    #[inline]
749    pub fn try_send_action(
750        &self,
751        dnd_action: WlDataDeviceManagerDndAction,
752    ) -> Result<(), ObjectError> {
753        let (
754            arg0,
755        ) = (
756            dnd_action,
757        );
758        let core = self.core();
759        let client_ref = core.client.borrow();
760        let Some(client) = &*client_ref else {
761            return Err(ObjectError(ObjectErrorKind::ReceiverNoClient));
762        };
763        let id = core.client_obj_id.get().unwrap_or(0);
764        #[cfg(feature = "logging")]
765        if self.core.state.log {
766            #[cold]
767            fn log(state: &State, client_id: u64, id: u32, arg0: WlDataDeviceManagerDndAction) {
768                let (millis, micros) = time_since_epoch();
769                let prefix = &state.log_prefix;
770                let args = format_args!("[{millis:7}.{micros:03}] {prefix}client#{:<4} <= wl_data_offer#{}.action(dnd_action: {:?})\n", client_id, id, arg0);
771                state.log(args);
772            }
773            log(&self.core.state, client.endpoint.id, id, arg0);
774        }
775        let endpoint = &client.endpoint;
776        if !endpoint.flush_queued.replace(true) {
777            self.core.state.add_flushable_endpoint(endpoint, Some(client));
778        }
779        let mut outgoing_ref = endpoint.outgoing.borrow_mut();
780        let outgoing = &mut *outgoing_ref;
781        let mut fmt = outgoing.formatter();
782        fmt.words([
783            id,
784            2,
785            arg0.0,
786        ]);
787        Ok(())
788    }
789
790    /// notify the selected action
791    ///
792    /// This event indicates the action selected by the compositor after
793    /// matching the source/destination side actions. Only one action (or
794    /// none) will be offered here.
795    ///
796    /// This event can be emitted multiple times during the drag-and-drop
797    /// operation in response to destination side action changes through
798    /// wl_data_offer.set_actions.
799    ///
800    /// This event will no longer be emitted after wl_data_device.drop
801    /// happened on the drag-and-drop destination, the client must
802    /// honor the last action received, or the last preferred one set
803    /// through wl_data_offer.set_actions when handling an "ask" action.
804    ///
805    /// Compositors may also change the selected action on the fly, mainly
806    /// in response to keyboard modifier changes during the drag-and-drop
807    /// operation.
808    ///
809    /// The most recent action received is always the valid one. Prior to
810    /// receiving wl_data_device.drop, the chosen action may change (e.g.
811    /// due to keyboard modifiers being pressed). At the time of receiving
812    /// wl_data_device.drop the drag-and-drop destination must honor the
813    /// last action received.
814    ///
815    /// Action changes may still happen after wl_data_device.drop,
816    /// especially on "ask" actions, where the drag-and-drop destination
817    /// may choose another action afterwards. Action changes happening
818    /// at this stage are always the result of inter-client negotiation, the
819    /// compositor shall no longer be able to induce a different action.
820    ///
821    /// Upon "ask" actions, it is expected that the drag-and-drop destination
822    /// may potentially choose a different action and/or mime type,
823    /// based on wl_data_offer.source_actions and finally chosen by the
824    /// user (e.g. popping up a menu with the available options). The
825    /// final wl_data_offer.set_actions and wl_data_offer.accept requests
826    /// must happen before the call to wl_data_offer.finish.
827    ///
828    /// # Arguments
829    ///
830    /// - `dnd_action`: action selected by the compositor
831    #[inline]
832    pub fn send_action(
833        &self,
834        dnd_action: WlDataDeviceManagerDndAction,
835    ) {
836        let res = self.try_send_action(
837            dnd_action,
838        );
839        if let Err(e) = res {
840            log_send("wl_data_offer.action", &e);
841        }
842    }
843}
844
845/// A message handler for [`WlDataOffer`] proxies.
846pub trait WlDataOfferHandler: Any {
847    /// Event handler for wl_display.delete_id messages deleting the ID of this object.
848    ///
849    /// The default handler forwards the event to the client, if any.
850    #[inline]
851    fn delete_id(&mut self, slf: &Rc<WlDataOffer>) {
852        slf.core.delete_id();
853    }
854
855    /// accept one of the offered mime types
856    ///
857    /// Indicate that the client can accept the given mime type, or
858    /// NULL for not accepted.
859    ///
860    /// For objects of version 2 or older, this request is used by the
861    /// client to give feedback whether the client can receive the given
862    /// mime type, or NULL if none is accepted; the feedback does not
863    /// determine whether the drag-and-drop operation succeeds or not.
864    ///
865    /// For objects of version 3 or newer, this request determines the
866    /// final result of the drag-and-drop operation. If the end result
867    /// is that no mime types were accepted, the drag-and-drop operation
868    /// will be cancelled and the corresponding drag source will receive
869    /// wl_data_source.cancelled. Clients may still use this event in
870    /// conjunction with wl_data_source.action for feedback.
871    ///
872    /// # Arguments
873    ///
874    /// - `serial`: serial number of the accept request
875    /// - `mime_type`: mime type accepted by the client
876    #[inline]
877    fn handle_accept(
878        &mut self,
879        slf: &Rc<WlDataOffer>,
880        serial: u32,
881        mime_type: Option<&str>,
882    ) {
883        if !slf.core.forward_to_server.get() {
884            return;
885        }
886        let res = slf.try_send_accept(
887            serial,
888            mime_type,
889        );
890        if let Err(e) = res {
891            log_forward("wl_data_offer.accept", &e);
892        }
893    }
894
895    /// request that the data is transferred
896    ///
897    /// To transfer the offered data, the client issues this request
898    /// and indicates the mime type it wants to receive.  The transfer
899    /// happens through the passed file descriptor (typically created
900    /// with the pipe system call).  The source client writes the data
901    /// in the mime type representation requested and then closes the
902    /// file descriptor.
903    ///
904    /// The receiving client reads from the read end of the pipe until
905    /// EOF and then closes its end, at which point the transfer is
906    /// complete.
907    ///
908    /// This request may happen multiple times for different mime types,
909    /// both before and after wl_data_device.drop. Drag-and-drop destination
910    /// clients may preemptively fetch data or examine it more closely to
911    /// determine acceptance.
912    ///
913    /// # Arguments
914    ///
915    /// - `mime_type`: mime type desired by receiver
916    /// - `fd`: file descriptor for data transfer
917    #[inline]
918    fn handle_receive(
919        &mut self,
920        slf: &Rc<WlDataOffer>,
921        mime_type: &str,
922        fd: &Rc<OwnedFd>,
923    ) {
924        if !slf.core.forward_to_server.get() {
925            return;
926        }
927        let res = slf.try_send_receive(
928            mime_type,
929            fd,
930        );
931        if let Err(e) = res {
932            log_forward("wl_data_offer.receive", &e);
933        }
934    }
935
936    /// destroy data offer
937    ///
938    /// Destroy the data offer.
939    #[inline]
940    fn handle_destroy(
941        &mut self,
942        slf: &Rc<WlDataOffer>,
943    ) {
944        if !slf.core.forward_to_server.get() {
945            return;
946        }
947        let res = slf.try_send_destroy(
948        );
949        if let Err(e) = res {
950            log_forward("wl_data_offer.destroy", &e);
951        }
952    }
953
954    /// advertise offered mime type
955    ///
956    /// Sent immediately after creating the wl_data_offer object.  One
957    /// event per offered mime type.
958    ///
959    /// # Arguments
960    ///
961    /// - `mime_type`: offered mime type
962    #[inline]
963    fn handle_offer(
964        &mut self,
965        slf: &Rc<WlDataOffer>,
966        mime_type: &str,
967    ) {
968        if !slf.core.forward_to_client.get() {
969            return;
970        }
971        let res = slf.try_send_offer(
972            mime_type,
973        );
974        if let Err(e) = res {
975            log_forward("wl_data_offer.offer", &e);
976        }
977    }
978
979    /// the offer will no longer be used
980    ///
981    /// Notifies the compositor that the drag destination successfully
982    /// finished the drag-and-drop operation.
983    ///
984    /// Upon receiving this request, the compositor will emit
985    /// wl_data_source.dnd_finished on the drag source client.
986    ///
987    /// It is a client error to perform other requests than
988    /// wl_data_offer.destroy after this one. It is also an error to perform
989    /// this request after a NULL mime type has been set in
990    /// wl_data_offer.accept or no action was received through
991    /// wl_data_offer.action.
992    ///
993    /// If wl_data_offer.finish request is received for a non drag and drop
994    /// operation, the invalid_finish protocol error is raised.
995    #[inline]
996    fn handle_finish(
997        &mut self,
998        slf: &Rc<WlDataOffer>,
999    ) {
1000        if !slf.core.forward_to_server.get() {
1001            return;
1002        }
1003        let res = slf.try_send_finish(
1004        );
1005        if let Err(e) = res {
1006            log_forward("wl_data_offer.finish", &e);
1007        }
1008    }
1009
1010    /// set the available/preferred drag-and-drop actions
1011    ///
1012    /// Sets the actions that the destination side client supports for
1013    /// this operation. This request may trigger the emission of
1014    /// wl_data_source.action and wl_data_offer.action events if the compositor
1015    /// needs to change the selected action.
1016    ///
1017    /// This request can be called multiple times throughout the
1018    /// drag-and-drop operation, typically in response to wl_data_device.enter
1019    /// or wl_data_device.motion events.
1020    ///
1021    /// This request determines the final result of the drag-and-drop
1022    /// operation. If the end result is that no action is accepted,
1023    /// the drag source will receive wl_data_source.cancelled.
1024    ///
1025    /// The dnd_actions argument must contain only values expressed in the
1026    /// wl_data_device_manager.dnd_actions enum, and the preferred_action
1027    /// argument must only contain one of those values set, otherwise it
1028    /// will result in a protocol error.
1029    ///
1030    /// While managing an "ask" action, the destination drag-and-drop client
1031    /// may perform further wl_data_offer.receive requests, and is expected
1032    /// to perform one last wl_data_offer.set_actions request with a preferred
1033    /// action other than "ask" (and optionally wl_data_offer.accept) before
1034    /// requesting wl_data_offer.finish, in order to convey the action selected
1035    /// by the user. If the preferred action is not in the
1036    /// wl_data_offer.source_actions mask, an error will be raised.
1037    ///
1038    /// If the "ask" action is dismissed (e.g. user cancellation), the client
1039    /// is expected to perform wl_data_offer.destroy right away.
1040    ///
1041    /// This request can only be made on drag-and-drop offers, a protocol error
1042    /// will be raised otherwise.
1043    ///
1044    /// # Arguments
1045    ///
1046    /// - `dnd_actions`: actions supported by the destination client
1047    /// - `preferred_action`: action preferred by the destination client
1048    #[inline]
1049    fn handle_set_actions(
1050        &mut self,
1051        slf: &Rc<WlDataOffer>,
1052        dnd_actions: WlDataDeviceManagerDndAction,
1053        preferred_action: WlDataDeviceManagerDndAction,
1054    ) {
1055        if !slf.core.forward_to_server.get() {
1056            return;
1057        }
1058        let res = slf.try_send_set_actions(
1059            dnd_actions,
1060            preferred_action,
1061        );
1062        if let Err(e) = res {
1063            log_forward("wl_data_offer.set_actions", &e);
1064        }
1065    }
1066
1067    /// notify the source-side available actions
1068    ///
1069    /// This event indicates the actions offered by the data source. It
1070    /// will be sent immediately after creating the wl_data_offer object,
1071    /// or anytime the source side changes its offered actions through
1072    /// wl_data_source.set_actions.
1073    ///
1074    /// # Arguments
1075    ///
1076    /// - `source_actions`: actions offered by the data source
1077    #[inline]
1078    fn handle_source_actions(
1079        &mut self,
1080        slf: &Rc<WlDataOffer>,
1081        source_actions: WlDataDeviceManagerDndAction,
1082    ) {
1083        if !slf.core.forward_to_client.get() {
1084            return;
1085        }
1086        let res = slf.try_send_source_actions(
1087            source_actions,
1088        );
1089        if let Err(e) = res {
1090            log_forward("wl_data_offer.source_actions", &e);
1091        }
1092    }
1093
1094    /// notify the selected action
1095    ///
1096    /// This event indicates the action selected by the compositor after
1097    /// matching the source/destination side actions. Only one action (or
1098    /// none) will be offered here.
1099    ///
1100    /// This event can be emitted multiple times during the drag-and-drop
1101    /// operation in response to destination side action changes through
1102    /// wl_data_offer.set_actions.
1103    ///
1104    /// This event will no longer be emitted after wl_data_device.drop
1105    /// happened on the drag-and-drop destination, the client must
1106    /// honor the last action received, or the last preferred one set
1107    /// through wl_data_offer.set_actions when handling an "ask" action.
1108    ///
1109    /// Compositors may also change the selected action on the fly, mainly
1110    /// in response to keyboard modifier changes during the drag-and-drop
1111    /// operation.
1112    ///
1113    /// The most recent action received is always the valid one. Prior to
1114    /// receiving wl_data_device.drop, the chosen action may change (e.g.
1115    /// due to keyboard modifiers being pressed). At the time of receiving
1116    /// wl_data_device.drop the drag-and-drop destination must honor the
1117    /// last action received.
1118    ///
1119    /// Action changes may still happen after wl_data_device.drop,
1120    /// especially on "ask" actions, where the drag-and-drop destination
1121    /// may choose another action afterwards. Action changes happening
1122    /// at this stage are always the result of inter-client negotiation, the
1123    /// compositor shall no longer be able to induce a different action.
1124    ///
1125    /// Upon "ask" actions, it is expected that the drag-and-drop destination
1126    /// may potentially choose a different action and/or mime type,
1127    /// based on wl_data_offer.source_actions and finally chosen by the
1128    /// user (e.g. popping up a menu with the available options). The
1129    /// final wl_data_offer.set_actions and wl_data_offer.accept requests
1130    /// must happen before the call to wl_data_offer.finish.
1131    ///
1132    /// # Arguments
1133    ///
1134    /// - `dnd_action`: action selected by the compositor
1135    #[inline]
1136    fn handle_action(
1137        &mut self,
1138        slf: &Rc<WlDataOffer>,
1139        dnd_action: WlDataDeviceManagerDndAction,
1140    ) {
1141        if !slf.core.forward_to_client.get() {
1142            return;
1143        }
1144        let res = slf.try_send_action(
1145            dnd_action,
1146        );
1147        if let Err(e) = res {
1148            log_forward("wl_data_offer.action", &e);
1149        }
1150    }
1151}
1152
1153impl ObjectPrivate for WlDataOffer {
1154    fn new(state: &Rc<State>, version: u32) -> Rc<Self> {
1155        Rc::<Self>::new_cyclic(|slf| Self {
1156            core: ObjectCore::new(state, slf.clone(), ObjectInterface::WlDataOffer, version),
1157            handler: Default::default(),
1158        })
1159    }
1160
1161    fn delete_id(self: Rc<Self>) -> Result<(), (ObjectError, Rc<dyn Object>)> {
1162        let Some(mut handler) = self.handler.try_borrow_mut() else {
1163            return Err((ObjectError(ObjectErrorKind::HandlerBorrowed), self));
1164        };
1165        if let Some(handler) = &mut *handler {
1166            handler.delete_id(&self);
1167        } else {
1168            self.core.delete_id();
1169        }
1170        Ok(())
1171    }
1172
1173    fn handle_request(self: Rc<Self>, client: &Rc<Client>, msg: &[u32], fds: &mut VecDeque<Rc<OwnedFd>>) -> Result<(), ObjectError> {
1174        let Some(mut handler) = self.handler.try_borrow_mut() else {
1175            return Err(ObjectError(ObjectErrorKind::HandlerBorrowed));
1176        };
1177        let handler = &mut *handler;
1178        match msg[1] & 0xffff {
1179            0 => {
1180                let mut offset = 2;
1181                let Some(&arg0) = msg.get(offset) else {
1182                    return Err(ObjectError(ObjectErrorKind::MissingArgument("serial")));
1183                };
1184                offset += 1;
1185                let arg1;
1186                (arg1, offset) = parse_string::<NullableString>(msg, offset, "mime_type")?;
1187                if offset != msg.len() {
1188                    return Err(ObjectError(ObjectErrorKind::TrailingBytes));
1189                }
1190                #[cfg(feature = "logging")]
1191                if self.core.state.log {
1192                    #[cold]
1193                    fn log(state: &State, client_id: u64, id: u32, arg0: u32, arg1: Option<&str>) {
1194                        let (millis, micros) = time_since_epoch();
1195                        let prefix = &state.log_prefix;
1196                        let args = format_args!("[{millis:7}.{micros:03}] {prefix}client#{:<4} -> wl_data_offer#{}.accept(serial: {}, mime_type: {:?})\n", client_id, id, arg0, arg1);
1197                        state.log(args);
1198                    }
1199                    log(&self.core.state, client.endpoint.id, msg[0], arg0, arg1);
1200                }
1201                if let Some(handler) = handler {
1202                    (**handler).handle_accept(&self, arg0, arg1);
1203                } else {
1204                    DefaultHandler.handle_accept(&self, arg0, arg1);
1205                }
1206            }
1207            1 => {
1208                let mut offset = 2;
1209                let arg0;
1210                (arg0, offset) = parse_string::<NonNullString>(msg, offset, "mime_type")?;
1211                if offset != msg.len() {
1212                    return Err(ObjectError(ObjectErrorKind::TrailingBytes));
1213                }
1214                let Some(arg1) = fds.pop_front() else {
1215                    return Err(ObjectError(ObjectErrorKind::MissingFd("fd")));
1216                };
1217                let arg1 = &arg1;
1218                #[cfg(feature = "logging")]
1219                if self.core.state.log {
1220                    #[cold]
1221                    fn log(state: &State, client_id: u64, id: u32, arg0: &str, arg1: i32) {
1222                        let (millis, micros) = time_since_epoch();
1223                        let prefix = &state.log_prefix;
1224                        let args = format_args!("[{millis:7}.{micros:03}] {prefix}client#{:<4} -> wl_data_offer#{}.receive(mime_type: {:?}, fd: {})\n", client_id, id, arg0, arg1);
1225                        state.log(args);
1226                    }
1227                    log(&self.core.state, client.endpoint.id, msg[0], arg0, arg1.as_raw_fd());
1228                }
1229                if let Some(handler) = handler {
1230                    (**handler).handle_receive(&self, arg0, arg1);
1231                } else {
1232                    DefaultHandler.handle_receive(&self, arg0, arg1);
1233                }
1234            }
1235            2 => {
1236                if msg.len() != 2 {
1237                    return Err(ObjectError(ObjectErrorKind::WrongMessageSize(msg.len() as u32 * 4, 8)));
1238                }
1239                #[cfg(feature = "logging")]
1240                if self.core.state.log {
1241                    #[cold]
1242                    fn log(state: &State, client_id: u64, id: u32) {
1243                        let (millis, micros) = time_since_epoch();
1244                        let prefix = &state.log_prefix;
1245                        let args = format_args!("[{millis:7}.{micros:03}] {prefix}client#{:<4} -> wl_data_offer#{}.destroy()\n", client_id, id);
1246                        state.log(args);
1247                    }
1248                    log(&self.core.state, client.endpoint.id, msg[0]);
1249                }
1250                self.core.handle_client_destroy();
1251                if let Some(handler) = handler {
1252                    (**handler).handle_destroy(&self);
1253                } else {
1254                    DefaultHandler.handle_destroy(&self);
1255                }
1256            }
1257            3 => {
1258                if msg.len() != 2 {
1259                    return Err(ObjectError(ObjectErrorKind::WrongMessageSize(msg.len() as u32 * 4, 8)));
1260                }
1261                #[cfg(feature = "logging")]
1262                if self.core.state.log {
1263                    #[cold]
1264                    fn log(state: &State, client_id: u64, id: u32) {
1265                        let (millis, micros) = time_since_epoch();
1266                        let prefix = &state.log_prefix;
1267                        let args = format_args!("[{millis:7}.{micros:03}] {prefix}client#{:<4} -> wl_data_offer#{}.finish()\n", client_id, id);
1268                        state.log(args);
1269                    }
1270                    log(&self.core.state, client.endpoint.id, msg[0]);
1271                }
1272                if let Some(handler) = handler {
1273                    (**handler).handle_finish(&self);
1274                } else {
1275                    DefaultHandler.handle_finish(&self);
1276                }
1277            }
1278            4 => {
1279                let [
1280                    arg0,
1281                    arg1,
1282                ] = msg[2..] else {
1283                    return Err(ObjectError(ObjectErrorKind::WrongMessageSize(msg.len() as u32 * 4, 16)));
1284                };
1285                let arg0 = WlDataDeviceManagerDndAction(arg0);
1286                let arg1 = WlDataDeviceManagerDndAction(arg1);
1287                #[cfg(feature = "logging")]
1288                if self.core.state.log {
1289                    #[cold]
1290                    fn log(state: &State, client_id: u64, id: u32, arg0: WlDataDeviceManagerDndAction, arg1: WlDataDeviceManagerDndAction) {
1291                        let (millis, micros) = time_since_epoch();
1292                        let prefix = &state.log_prefix;
1293                        let args = format_args!("[{millis:7}.{micros:03}] {prefix}client#{:<4} -> wl_data_offer#{}.set_actions(dnd_actions: {:?}, preferred_action: {:?})\n", client_id, id, arg0, arg1);
1294                        state.log(args);
1295                    }
1296                    log(&self.core.state, client.endpoint.id, msg[0], arg0, arg1);
1297                }
1298                if let Some(handler) = handler {
1299                    (**handler).handle_set_actions(&self, arg0, arg1);
1300                } else {
1301                    DefaultHandler.handle_set_actions(&self, arg0, arg1);
1302                }
1303            }
1304            n => {
1305                let _ = client;
1306                let _ = msg;
1307                let _ = fds;
1308                let _ = handler;
1309                return Err(ObjectError(ObjectErrorKind::UnknownMessageId(n)));
1310            }
1311        }
1312        Ok(())
1313    }
1314
1315    fn handle_event(self: Rc<Self>, server: &Endpoint, msg: &[u32], fds: &mut VecDeque<Rc<OwnedFd>>) -> Result<(), ObjectError> {
1316        let Some(mut handler) = self.handler.try_borrow_mut() else {
1317            return Err(ObjectError(ObjectErrorKind::HandlerBorrowed));
1318        };
1319        let handler = &mut *handler;
1320        match msg[1] & 0xffff {
1321            0 => {
1322                let mut offset = 2;
1323                let arg0;
1324                (arg0, offset) = parse_string::<NonNullString>(msg, offset, "mime_type")?;
1325                if offset != msg.len() {
1326                    return Err(ObjectError(ObjectErrorKind::TrailingBytes));
1327                }
1328                #[cfg(feature = "logging")]
1329                if self.core.state.log {
1330                    #[cold]
1331                    fn log(state: &State, id: u32, arg0: &str) {
1332                        let (millis, micros) = time_since_epoch();
1333                        let prefix = &state.log_prefix;
1334                        let args = format_args!("[{millis:7}.{micros:03}] {prefix}server      -> wl_data_offer#{}.offer(mime_type: {:?})\n", id, arg0);
1335                        state.log(args);
1336                    }
1337                    log(&self.core.state, msg[0], arg0);
1338                }
1339                if let Some(handler) = handler {
1340                    (**handler).handle_offer(&self, arg0);
1341                } else {
1342                    DefaultHandler.handle_offer(&self, arg0);
1343                }
1344            }
1345            1 => {
1346                let [
1347                    arg0,
1348                ] = msg[2..] else {
1349                    return Err(ObjectError(ObjectErrorKind::WrongMessageSize(msg.len() as u32 * 4, 12)));
1350                };
1351                let arg0 = WlDataDeviceManagerDndAction(arg0);
1352                #[cfg(feature = "logging")]
1353                if self.core.state.log {
1354                    #[cold]
1355                    fn log(state: &State, id: u32, arg0: WlDataDeviceManagerDndAction) {
1356                        let (millis, micros) = time_since_epoch();
1357                        let prefix = &state.log_prefix;
1358                        let args = format_args!("[{millis:7}.{micros:03}] {prefix}server      -> wl_data_offer#{}.source_actions(source_actions: {:?})\n", id, arg0);
1359                        state.log(args);
1360                    }
1361                    log(&self.core.state, msg[0], arg0);
1362                }
1363                if let Some(handler) = handler {
1364                    (**handler).handle_source_actions(&self, arg0);
1365                } else {
1366                    DefaultHandler.handle_source_actions(&self, arg0);
1367                }
1368            }
1369            2 => {
1370                let [
1371                    arg0,
1372                ] = msg[2..] else {
1373                    return Err(ObjectError(ObjectErrorKind::WrongMessageSize(msg.len() as u32 * 4, 12)));
1374                };
1375                let arg0 = WlDataDeviceManagerDndAction(arg0);
1376                #[cfg(feature = "logging")]
1377                if self.core.state.log {
1378                    #[cold]
1379                    fn log(state: &State, id: u32, arg0: WlDataDeviceManagerDndAction) {
1380                        let (millis, micros) = time_since_epoch();
1381                        let prefix = &state.log_prefix;
1382                        let args = format_args!("[{millis:7}.{micros:03}] {prefix}server      -> wl_data_offer#{}.action(dnd_action: {:?})\n", id, arg0);
1383                        state.log(args);
1384                    }
1385                    log(&self.core.state, msg[0], arg0);
1386                }
1387                if let Some(handler) = handler {
1388                    (**handler).handle_action(&self, arg0);
1389                } else {
1390                    DefaultHandler.handle_action(&self, arg0);
1391                }
1392            }
1393            n => {
1394                let _ = server;
1395                let _ = msg;
1396                let _ = fds;
1397                let _ = handler;
1398                return Err(ObjectError(ObjectErrorKind::UnknownMessageId(n)));
1399            }
1400        }
1401        Ok(())
1402    }
1403
1404    fn get_request_name(&self, id: u32) -> Option<&'static str> {
1405        let name = match id {
1406            0 => "accept",
1407            1 => "receive",
1408            2 => "destroy",
1409            3 => "finish",
1410            4 => "set_actions",
1411            _ => return None,
1412        };
1413        Some(name)
1414    }
1415
1416    fn get_event_name(&self, id: u32) -> Option<&'static str> {
1417        let name = match id {
1418            0 => "offer",
1419            1 => "source_actions",
1420            2 => "action",
1421            _ => return None,
1422        };
1423        Some(name)
1424    }
1425}
1426
1427impl Object for WlDataOffer {
1428    fn core(&self) -> &ObjectCore {
1429        &self.core
1430    }
1431
1432    fn unset_handler(&self) {
1433        self.handler.set(None);
1434    }
1435
1436    fn get_handler_any_ref(&self) -> Result<HandlerRef<'_, dyn Any>, HandlerAccessError> {
1437        let borrowed = self.handler.try_borrow().ok_or(HandlerAccessError::AlreadyBorrowed)?;
1438        if borrowed.is_none() {
1439            return Err(HandlerAccessError::NoHandler);
1440        }
1441        Ok(HandlerRef::map(borrowed, |handler| &**handler.as_ref().unwrap() as &dyn Any))
1442    }
1443
1444    fn get_handler_any_mut(&self) -> Result<HandlerMut<'_, dyn Any>, HandlerAccessError> {
1445        let borrowed = self.handler.try_borrow_mut().ok_or(HandlerAccessError::AlreadyBorrowed)?;
1446        if borrowed.is_none() {
1447            return Err(HandlerAccessError::NoHandler);
1448        }
1449        Ok(HandlerMut::map(borrowed, |handler| &mut **handler.as_mut().unwrap() as &mut dyn Any))
1450    }
1451}
1452
1453impl WlDataOffer {
1454    /// Since when the error.invalid_finish enum variant is available.
1455    pub const ENM__ERROR_INVALID_FINISH__SINCE: u32 = 1;
1456    /// Since when the error.invalid_action_mask enum variant is available.
1457    pub const ENM__ERROR_INVALID_ACTION_MASK__SINCE: u32 = 1;
1458    /// Since when the error.invalid_action enum variant is available.
1459    pub const ENM__ERROR_INVALID_ACTION__SINCE: u32 = 1;
1460    /// Since when the error.invalid_offer enum variant is available.
1461    pub const ENM__ERROR_INVALID_OFFER__SINCE: u32 = 1;
1462}
1463
1464#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
1465pub struct WlDataOfferError(pub u32);
1466
1467impl WlDataOfferError {
1468    /// finish request was called untimely
1469    pub const INVALID_FINISH: Self = Self(0);
1470
1471    /// action mask contains invalid values
1472    pub const INVALID_ACTION_MASK: Self = Self(1);
1473
1474    /// action argument has an invalid value
1475    pub const INVALID_ACTION: Self = Self(2);
1476
1477    /// offer doesn't accept this request
1478    pub const INVALID_OFFER: Self = Self(3);
1479}
1480
1481impl Debug for WlDataOfferError {
1482    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1483        let name = match *self {
1484            Self::INVALID_FINISH => "INVALID_FINISH",
1485            Self::INVALID_ACTION_MASK => "INVALID_ACTION_MASK",
1486            Self::INVALID_ACTION => "INVALID_ACTION",
1487            Self::INVALID_OFFER => "INVALID_OFFER",
1488            _ => return Debug::fmt(&self.0, f),
1489        };
1490        f.write_str(name)
1491    }
1492}