wl_proxy/protocols/wayland/
wl_data_device.rs

1//! data transfer device
2//!
3//! There is one wl_data_device per seat which can be obtained
4//! from the global wl_data_device_manager singleton.
5//!
6//! A wl_data_device provides access to inter-client data transfer
7//! mechanisms such as copy-and-paste and drag-and-drop.
8
9use crate::protocol_helpers::prelude::*;
10use super::super::all_types::*;
11
12/// A wl_data_device object.
13///
14/// See the documentation of [the module][self] for the interface description.
15pub struct WlDataDevice {
16    core: ObjectCore,
17    handler: HandlerHolder<dyn WlDataDeviceHandler>,
18}
19
20struct DefaultHandler;
21
22impl WlDataDeviceHandler for DefaultHandler { }
23
24impl ConcreteObject for WlDataDevice {
25    const XML_VERSION: u32 = 3;
26    const INTERFACE: ObjectInterface = ObjectInterface::WlDataDevice;
27    const INTERFACE_NAME: &str = "wl_data_device";
28}
29
30impl WlDataDevice {
31    /// Sets a new handler.
32    pub fn set_handler(&self, handler: impl WlDataDeviceHandler) {
33        self.set_boxed_handler(Box::new(handler));
34    }
35
36    /// Sets a new, already boxed handler.
37    pub fn set_boxed_handler(&self, handler: Box<dyn WlDataDeviceHandler>) {
38        if self.core.state.destroyed.get() {
39            return;
40        }
41        self.handler.set(Some(handler));
42    }
43}
44
45impl Debug for WlDataDevice {
46    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
47        f.debug_struct("WlDataDevice")
48            .field("server_obj_id", &self.core.server_obj_id.get())
49            .field("client_id", &self.core.client_id.get())
50            .field("client_obj_id", &self.core.client_obj_id.get())
51            .finish()
52    }
53}
54
55impl WlDataDevice {
56    /// Since when the start_drag message is available.
57    pub const MSG__START_DRAG__SINCE: u32 = 1;
58
59    /// start drag-and-drop operation
60    ///
61    /// This request asks the compositor to start a drag-and-drop
62    /// operation on behalf of the client.
63    ///
64    /// The source argument is the data source that provides the data
65    /// for the eventual data transfer. If source is NULL, enter, leave
66    /// and motion events are sent only to the client that initiated the
67    /// drag and the client is expected to handle the data passing
68    /// internally. If source is destroyed, the drag-and-drop session will be
69    /// cancelled.
70    ///
71    /// The origin surface is the surface where the drag originates and
72    /// the client must have an active implicit grab that matches the
73    /// serial.
74    ///
75    /// The icon surface is an optional (can be NULL) surface that
76    /// provides an icon to be moved around with the cursor.  Initially,
77    /// the top-left corner of the icon surface is placed at the cursor
78    /// hotspot, but subsequent wl_surface.offset requests can move the
79    /// relative position. Attach requests must be confirmed with
80    /// wl_surface.commit as usual. The icon surface is given the role of
81    /// a drag-and-drop icon. If the icon surface already has another role,
82    /// it raises a protocol error.
83    ///
84    /// The input region is ignored for wl_surfaces with the role of a
85    /// drag-and-drop icon.
86    ///
87    /// The given source may not be used in any further set_selection or
88    /// start_drag requests. Attempting to reuse a previously-used source
89    /// may send a used_source error.
90    ///
91    /// # Arguments
92    ///
93    /// - `source`: data source for the eventual transfer
94    /// - `origin`: surface where the drag originates
95    /// - `icon`: drag-and-drop icon surface
96    /// - `serial`: serial number of the implicit grab on the origin
97    #[inline]
98    pub fn try_send_start_drag(
99        &self,
100        source: Option<&Rc<WlDataSource>>,
101        origin: &Rc<WlSurface>,
102        icon: Option<&Rc<WlSurface>>,
103        serial: u32,
104    ) -> Result<(), ObjectError> {
105        let (
106            arg0,
107            arg1,
108            arg2,
109            arg3,
110        ) = (
111            source,
112            origin,
113            icon,
114            serial,
115        );
116        let arg0 = arg0.map(|a| a.core());
117        let arg1 = arg1.core();
118        let arg2 = arg2.map(|a| a.core());
119        let core = self.core();
120        let Some(id) = core.server_obj_id.get() else {
121            return Err(ObjectError(ObjectErrorKind::ReceiverNoServerId));
122        };
123        let arg0_id = match arg0 {
124            None => 0,
125            Some(arg0) => match arg0.server_obj_id.get() {
126                None => return Err(ObjectError(ObjectErrorKind::ArgNoServerId("source"))),
127                Some(id) => id,
128            },
129        };
130        let arg1_id = match arg1.server_obj_id.get() {
131            None => return Err(ObjectError(ObjectErrorKind::ArgNoServerId("origin"))),
132            Some(id) => id,
133        };
134        let arg2_id = match arg2 {
135            None => 0,
136            Some(arg2) => match arg2.server_obj_id.get() {
137                None => return Err(ObjectError(ObjectErrorKind::ArgNoServerId("icon"))),
138                Some(id) => id,
139            },
140        };
141        #[cfg(feature = "logging")]
142        if self.core.state.log {
143            #[cold]
144            fn log(state: &State, id: u32, arg0: u32, arg1: u32, arg2: u32, arg3: u32) {
145                let (millis, micros) = time_since_epoch();
146                let prefix = &state.log_prefix;
147                let args = format_args!("[{millis:7}.{micros:03}] {prefix}server      <= wl_data_device#{}.start_drag(source: wl_data_source#{}, origin: wl_surface#{}, icon: wl_surface#{}, serial: {})\n", id, arg0, arg1, arg2, arg3);
148                state.log(args);
149            }
150            log(&self.core.state, id, arg0_id, arg1_id, arg2_id, arg3);
151        }
152        let Some(endpoint) = &self.core.state.server else {
153            return Ok(());
154        };
155        if !endpoint.flush_queued.replace(true) {
156            self.core.state.add_flushable_endpoint(endpoint, None);
157        }
158        let mut outgoing_ref = endpoint.outgoing.borrow_mut();
159        let outgoing = &mut *outgoing_ref;
160        let mut fmt = outgoing.formatter();
161        fmt.words([
162            id,
163            0,
164            arg0_id,
165            arg1_id,
166            arg2_id,
167            arg3,
168        ]);
169        Ok(())
170    }
171
172    /// start drag-and-drop operation
173    ///
174    /// This request asks the compositor to start a drag-and-drop
175    /// operation on behalf of the client.
176    ///
177    /// The source argument is the data source that provides the data
178    /// for the eventual data transfer. If source is NULL, enter, leave
179    /// and motion events are sent only to the client that initiated the
180    /// drag and the client is expected to handle the data passing
181    /// internally. If source is destroyed, the drag-and-drop session will be
182    /// cancelled.
183    ///
184    /// The origin surface is the surface where the drag originates and
185    /// the client must have an active implicit grab that matches the
186    /// serial.
187    ///
188    /// The icon surface is an optional (can be NULL) surface that
189    /// provides an icon to be moved around with the cursor.  Initially,
190    /// the top-left corner of the icon surface is placed at the cursor
191    /// hotspot, but subsequent wl_surface.offset requests can move the
192    /// relative position. Attach requests must be confirmed with
193    /// wl_surface.commit as usual. The icon surface is given the role of
194    /// a drag-and-drop icon. If the icon surface already has another role,
195    /// it raises a protocol error.
196    ///
197    /// The input region is ignored for wl_surfaces with the role of a
198    /// drag-and-drop icon.
199    ///
200    /// The given source may not be used in any further set_selection or
201    /// start_drag requests. Attempting to reuse a previously-used source
202    /// may send a used_source error.
203    ///
204    /// # Arguments
205    ///
206    /// - `source`: data source for the eventual transfer
207    /// - `origin`: surface where the drag originates
208    /// - `icon`: drag-and-drop icon surface
209    /// - `serial`: serial number of the implicit grab on the origin
210    #[inline]
211    pub fn send_start_drag(
212        &self,
213        source: Option<&Rc<WlDataSource>>,
214        origin: &Rc<WlSurface>,
215        icon: Option<&Rc<WlSurface>>,
216        serial: u32,
217    ) {
218        let res = self.try_send_start_drag(
219            source,
220            origin,
221            icon,
222            serial,
223        );
224        if let Err(e) = res {
225            log_send("wl_data_device.start_drag", &e);
226        }
227    }
228
229    /// Since when the set_selection message is available.
230    pub const MSG__SET_SELECTION__SINCE: u32 = 1;
231
232    /// copy data to the selection
233    ///
234    /// This request asks the compositor to set the selection
235    /// to the data from the source on behalf of the client.
236    ///
237    /// To unset the selection, set the source to NULL.
238    ///
239    /// The given source may not be used in any further set_selection or
240    /// start_drag requests. Attempting to reuse a previously-used source
241    /// may send a used_source error.
242    ///
243    /// # Arguments
244    ///
245    /// - `source`: data source for the selection
246    /// - `serial`: serial number of the event that triggered this request
247    #[inline]
248    pub fn try_send_set_selection(
249        &self,
250        source: Option<&Rc<WlDataSource>>,
251        serial: u32,
252    ) -> Result<(), ObjectError> {
253        let (
254            arg0,
255            arg1,
256        ) = (
257            source,
258            serial,
259        );
260        let arg0 = arg0.map(|a| a.core());
261        let core = self.core();
262        let Some(id) = core.server_obj_id.get() else {
263            return Err(ObjectError(ObjectErrorKind::ReceiverNoServerId));
264        };
265        let arg0_id = match arg0 {
266            None => 0,
267            Some(arg0) => match arg0.server_obj_id.get() {
268                None => return Err(ObjectError(ObjectErrorKind::ArgNoServerId("source"))),
269                Some(id) => id,
270            },
271        };
272        #[cfg(feature = "logging")]
273        if self.core.state.log {
274            #[cold]
275            fn log(state: &State, id: u32, arg0: u32, arg1: u32) {
276                let (millis, micros) = time_since_epoch();
277                let prefix = &state.log_prefix;
278                let args = format_args!("[{millis:7}.{micros:03}] {prefix}server      <= wl_data_device#{}.set_selection(source: wl_data_source#{}, serial: {})\n", id, arg0, arg1);
279                state.log(args);
280            }
281            log(&self.core.state, id, arg0_id, arg1);
282        }
283        let Some(endpoint) = &self.core.state.server else {
284            return Ok(());
285        };
286        if !endpoint.flush_queued.replace(true) {
287            self.core.state.add_flushable_endpoint(endpoint, None);
288        }
289        let mut outgoing_ref = endpoint.outgoing.borrow_mut();
290        let outgoing = &mut *outgoing_ref;
291        let mut fmt = outgoing.formatter();
292        fmt.words([
293            id,
294            1,
295            arg0_id,
296            arg1,
297        ]);
298        Ok(())
299    }
300
301    /// copy data to the selection
302    ///
303    /// This request asks the compositor to set the selection
304    /// to the data from the source on behalf of the client.
305    ///
306    /// To unset the selection, set the source to NULL.
307    ///
308    /// The given source may not be used in any further set_selection or
309    /// start_drag requests. Attempting to reuse a previously-used source
310    /// may send a used_source error.
311    ///
312    /// # Arguments
313    ///
314    /// - `source`: data source for the selection
315    /// - `serial`: serial number of the event that triggered this request
316    #[inline]
317    pub fn send_set_selection(
318        &self,
319        source: Option<&Rc<WlDataSource>>,
320        serial: u32,
321    ) {
322        let res = self.try_send_set_selection(
323            source,
324            serial,
325        );
326        if let Err(e) = res {
327            log_send("wl_data_device.set_selection", &e);
328        }
329    }
330
331    /// Since when the data_offer message is available.
332    pub const MSG__DATA_OFFER__SINCE: u32 = 1;
333
334    /// introduce a new wl_data_offer
335    ///
336    /// The data_offer event introduces a new wl_data_offer object,
337    /// which will subsequently be used in either the
338    /// data_device.enter event (for drag-and-drop) or the
339    /// data_device.selection event (for selections).  Immediately
340    /// following the data_device.data_offer event, the new data_offer
341    /// object will send out data_offer.offer events to describe the
342    /// mime types it offers.
343    ///
344    /// # Arguments
345    ///
346    /// - `id`: the new data_offer object
347    #[inline]
348    pub fn try_send_data_offer(
349        &self,
350        id: &Rc<WlDataOffer>,
351    ) -> Result<(), ObjectError> {
352        let (
353            arg0,
354        ) = (
355            id,
356        );
357        let arg0_obj = arg0;
358        let arg0 = arg0_obj.core();
359        let core = self.core();
360        let client_ref = core.client.borrow();
361        let Some(client) = &*client_ref else {
362            return Err(ObjectError(ObjectErrorKind::ReceiverNoClient));
363        };
364        let id = core.client_obj_id.get().unwrap_or(0);
365        arg0.generate_client_id(client, arg0_obj.clone())
366            .map_err(|e| ObjectError(ObjectErrorKind::GenerateClientId("id", e)))?;
367        let arg0_id = arg0.client_obj_id.get().unwrap_or(0);
368        #[cfg(feature = "logging")]
369        if self.core.state.log {
370            #[cold]
371            fn log(state: &State, client_id: u64, id: u32, arg0: u32) {
372                let (millis, micros) = time_since_epoch();
373                let prefix = &state.log_prefix;
374                let args = format_args!("[{millis:7}.{micros:03}] {prefix}client#{:<4} <= wl_data_device#{}.data_offer(id: wl_data_offer#{})\n", client_id, id, arg0);
375                state.log(args);
376            }
377            log(&self.core.state, client.endpoint.id, id, arg0_id);
378        }
379        let endpoint = &client.endpoint;
380        if !endpoint.flush_queued.replace(true) {
381            self.core.state.add_flushable_endpoint(endpoint, Some(client));
382        }
383        let mut outgoing_ref = endpoint.outgoing.borrow_mut();
384        let outgoing = &mut *outgoing_ref;
385        let mut fmt = outgoing.formatter();
386        fmt.words([
387            id,
388            0,
389            arg0_id,
390        ]);
391        Ok(())
392    }
393
394    /// introduce a new wl_data_offer
395    ///
396    /// The data_offer event introduces a new wl_data_offer object,
397    /// which will subsequently be used in either the
398    /// data_device.enter event (for drag-and-drop) or the
399    /// data_device.selection event (for selections).  Immediately
400    /// following the data_device.data_offer event, the new data_offer
401    /// object will send out data_offer.offer events to describe the
402    /// mime types it offers.
403    ///
404    /// # Arguments
405    ///
406    /// - `id`: the new data_offer object
407    #[inline]
408    pub fn send_data_offer(
409        &self,
410        id: &Rc<WlDataOffer>,
411    ) {
412        let res = self.try_send_data_offer(
413            id,
414        );
415        if let Err(e) = res {
416            log_send("wl_data_device.data_offer", &e);
417        }
418    }
419
420    /// introduce a new wl_data_offer
421    ///
422    /// The data_offer event introduces a new wl_data_offer object,
423    /// which will subsequently be used in either the
424    /// data_device.enter event (for drag-and-drop) or the
425    /// data_device.selection event (for selections).  Immediately
426    /// following the data_device.data_offer event, the new data_offer
427    /// object will send out data_offer.offer events to describe the
428    /// mime types it offers.
429    #[inline]
430    pub fn new_try_send_data_offer(
431        &self,
432    ) -> Result<Rc<WlDataOffer>, ObjectError> {
433        let id = self.core.create_child();
434        self.try_send_data_offer(
435            &id,
436        )?;
437        Ok(id)
438    }
439
440    /// introduce a new wl_data_offer
441    ///
442    /// The data_offer event introduces a new wl_data_offer object,
443    /// which will subsequently be used in either the
444    /// data_device.enter event (for drag-and-drop) or the
445    /// data_device.selection event (for selections).  Immediately
446    /// following the data_device.data_offer event, the new data_offer
447    /// object will send out data_offer.offer events to describe the
448    /// mime types it offers.
449    #[inline]
450    pub fn new_send_data_offer(
451        &self,
452    ) -> Rc<WlDataOffer> {
453        let id = self.core.create_child();
454        self.send_data_offer(
455            &id,
456        );
457        id
458    }
459
460    /// Since when the enter message is available.
461    pub const MSG__ENTER__SINCE: u32 = 1;
462
463    /// initiate drag-and-drop session
464    ///
465    /// This event is sent when an active drag-and-drop pointer enters
466    /// a surface owned by the client.  The position of the pointer at
467    /// enter time is provided by the x and y arguments, in surface-local
468    /// coordinates.
469    ///
470    /// # Arguments
471    ///
472    /// - `serial`: serial number of the enter event
473    /// - `surface`: client surface entered
474    /// - `x`: surface-local x coordinate
475    /// - `y`: surface-local y coordinate
476    /// - `id`: source data_offer object
477    #[inline]
478    pub fn try_send_enter(
479        &self,
480        serial: u32,
481        surface: &Rc<WlSurface>,
482        x: Fixed,
483        y: Fixed,
484        id: Option<&Rc<WlDataOffer>>,
485    ) -> Result<(), ObjectError> {
486        let (
487            arg0,
488            arg1,
489            arg2,
490            arg3,
491            arg4,
492        ) = (
493            serial,
494            surface,
495            x,
496            y,
497            id,
498        );
499        let arg1 = arg1.core();
500        let arg4 = arg4.map(|a| a.core());
501        let core = self.core();
502        let client_ref = core.client.borrow();
503        let Some(client) = &*client_ref else {
504            return Err(ObjectError(ObjectErrorKind::ReceiverNoClient));
505        };
506        let id = core.client_obj_id.get().unwrap_or(0);
507        if arg1.client_id.get() != Some(client.endpoint.id) {
508            return Err(ObjectError(ObjectErrorKind::ArgNoClientId("surface", client.endpoint.id)));
509        }
510        if let Some(arg4) = arg4 {
511            if arg4.client_id.get() != Some(client.endpoint.id) {
512                return Err(ObjectError(ObjectErrorKind::ArgNoClientId("id", client.endpoint.id)));
513            }
514        }
515        let arg1_id = arg1.client_obj_id.get().unwrap_or(0);
516        let arg4_id = arg4.and_then(|arg4| arg4.client_obj_id.get()).unwrap_or(0);
517        #[cfg(feature = "logging")]
518        if self.core.state.log {
519            #[cold]
520            fn log(state: &State, client_id: u64, id: u32, arg0: u32, arg1: u32, arg2: Fixed, arg3: Fixed, arg4: u32) {
521                let (millis, micros) = time_since_epoch();
522                let prefix = &state.log_prefix;
523                let args = format_args!("[{millis:7}.{micros:03}] {prefix}client#{:<4} <= wl_data_device#{}.enter(serial: {}, surface: wl_surface#{}, x: {}, y: {}, id: wl_data_offer#{})\n", client_id, id, arg0, arg1, arg2, arg3, arg4);
524                state.log(args);
525            }
526            log(&self.core.state, client.endpoint.id, id, arg0, arg1_id, arg2, arg3, arg4_id);
527        }
528        let endpoint = &client.endpoint;
529        if !endpoint.flush_queued.replace(true) {
530            self.core.state.add_flushable_endpoint(endpoint, Some(client));
531        }
532        let mut outgoing_ref = endpoint.outgoing.borrow_mut();
533        let outgoing = &mut *outgoing_ref;
534        let mut fmt = outgoing.formatter();
535        fmt.words([
536            id,
537            1,
538            arg0,
539            arg1_id,
540            arg2.to_wire() as u32,
541            arg3.to_wire() as u32,
542            arg4_id,
543        ]);
544        Ok(())
545    }
546
547    /// initiate drag-and-drop session
548    ///
549    /// This event is sent when an active drag-and-drop pointer enters
550    /// a surface owned by the client.  The position of the pointer at
551    /// enter time is provided by the x and y arguments, in surface-local
552    /// coordinates.
553    ///
554    /// # Arguments
555    ///
556    /// - `serial`: serial number of the enter event
557    /// - `surface`: client surface entered
558    /// - `x`: surface-local x coordinate
559    /// - `y`: surface-local y coordinate
560    /// - `id`: source data_offer object
561    #[inline]
562    pub fn send_enter(
563        &self,
564        serial: u32,
565        surface: &Rc<WlSurface>,
566        x: Fixed,
567        y: Fixed,
568        id: Option<&Rc<WlDataOffer>>,
569    ) {
570        let res = self.try_send_enter(
571            serial,
572            surface,
573            x,
574            y,
575            id,
576        );
577        if let Err(e) = res {
578            log_send("wl_data_device.enter", &e);
579        }
580    }
581
582    /// Since when the leave message is available.
583    pub const MSG__LEAVE__SINCE: u32 = 1;
584
585    /// end drag-and-drop session
586    ///
587    /// This event is sent when the drag-and-drop pointer leaves the
588    /// surface and the session ends.  The client must destroy the
589    /// wl_data_offer introduced at enter time at this point.
590    #[inline]
591    pub fn try_send_leave(
592        &self,
593    ) -> Result<(), ObjectError> {
594        let core = self.core();
595        let client_ref = core.client.borrow();
596        let Some(client) = &*client_ref else {
597            return Err(ObjectError(ObjectErrorKind::ReceiverNoClient));
598        };
599        let id = core.client_obj_id.get().unwrap_or(0);
600        #[cfg(feature = "logging")]
601        if self.core.state.log {
602            #[cold]
603            fn log(state: &State, client_id: u64, id: u32) {
604                let (millis, micros) = time_since_epoch();
605                let prefix = &state.log_prefix;
606                let args = format_args!("[{millis:7}.{micros:03}] {prefix}client#{:<4} <= wl_data_device#{}.leave()\n", client_id, id);
607                state.log(args);
608            }
609            log(&self.core.state, client.endpoint.id, id);
610        }
611        let endpoint = &client.endpoint;
612        if !endpoint.flush_queued.replace(true) {
613            self.core.state.add_flushable_endpoint(endpoint, Some(client));
614        }
615        let mut outgoing_ref = endpoint.outgoing.borrow_mut();
616        let outgoing = &mut *outgoing_ref;
617        let mut fmt = outgoing.formatter();
618        fmt.words([
619            id,
620            2,
621        ]);
622        Ok(())
623    }
624
625    /// end drag-and-drop session
626    ///
627    /// This event is sent when the drag-and-drop pointer leaves the
628    /// surface and the session ends.  The client must destroy the
629    /// wl_data_offer introduced at enter time at this point.
630    #[inline]
631    pub fn send_leave(
632        &self,
633    ) {
634        let res = self.try_send_leave(
635        );
636        if let Err(e) = res {
637            log_send("wl_data_device.leave", &e);
638        }
639    }
640
641    /// Since when the motion message is available.
642    pub const MSG__MOTION__SINCE: u32 = 1;
643
644    /// drag-and-drop session motion
645    ///
646    /// This event is sent when the drag-and-drop pointer moves within
647    /// the currently focused surface. The new position of the pointer
648    /// is provided by the x and y arguments, in surface-local
649    /// coordinates.
650    ///
651    /// # Arguments
652    ///
653    /// - `time`: timestamp with millisecond granularity
654    /// - `x`: surface-local x coordinate
655    /// - `y`: surface-local y coordinate
656    #[inline]
657    pub fn try_send_motion(
658        &self,
659        time: u32,
660        x: Fixed,
661        y: Fixed,
662    ) -> Result<(), ObjectError> {
663        let (
664            arg0,
665            arg1,
666            arg2,
667        ) = (
668            time,
669            x,
670            y,
671        );
672        let core = self.core();
673        let client_ref = core.client.borrow();
674        let Some(client) = &*client_ref else {
675            return Err(ObjectError(ObjectErrorKind::ReceiverNoClient));
676        };
677        let id = core.client_obj_id.get().unwrap_or(0);
678        #[cfg(feature = "logging")]
679        if self.core.state.log {
680            #[cold]
681            fn log(state: &State, client_id: u64, id: u32, arg0: u32, arg1: Fixed, arg2: Fixed) {
682                let (millis, micros) = time_since_epoch();
683                let prefix = &state.log_prefix;
684                let args = format_args!("[{millis:7}.{micros:03}] {prefix}client#{:<4} <= wl_data_device#{}.motion(time: {}, x: {}, y: {})\n", client_id, id, arg0, arg1, arg2);
685                state.log(args);
686            }
687            log(&self.core.state, client.endpoint.id, id, arg0, arg1, arg2);
688        }
689        let endpoint = &client.endpoint;
690        if !endpoint.flush_queued.replace(true) {
691            self.core.state.add_flushable_endpoint(endpoint, Some(client));
692        }
693        let mut outgoing_ref = endpoint.outgoing.borrow_mut();
694        let outgoing = &mut *outgoing_ref;
695        let mut fmt = outgoing.formatter();
696        fmt.words([
697            id,
698            3,
699            arg0,
700            arg1.to_wire() as u32,
701            arg2.to_wire() as u32,
702        ]);
703        Ok(())
704    }
705
706    /// drag-and-drop session motion
707    ///
708    /// This event is sent when the drag-and-drop pointer moves within
709    /// the currently focused surface. The new position of the pointer
710    /// is provided by the x and y arguments, in surface-local
711    /// coordinates.
712    ///
713    /// # Arguments
714    ///
715    /// - `time`: timestamp with millisecond granularity
716    /// - `x`: surface-local x coordinate
717    /// - `y`: surface-local y coordinate
718    #[inline]
719    pub fn send_motion(
720        &self,
721        time: u32,
722        x: Fixed,
723        y: Fixed,
724    ) {
725        let res = self.try_send_motion(
726            time,
727            x,
728            y,
729        );
730        if let Err(e) = res {
731            log_send("wl_data_device.motion", &e);
732        }
733    }
734
735    /// Since when the drop message is available.
736    pub const MSG__DROP__SINCE: u32 = 1;
737
738    /// end drag-and-drop session successfully
739    ///
740    /// The event is sent when a drag-and-drop operation is ended
741    /// because the implicit grab is removed.
742    ///
743    /// The drag-and-drop destination is expected to honor the last action
744    /// received through wl_data_offer.action, if the resulting action is
745    /// "copy" or "move", the destination can still perform
746    /// wl_data_offer.receive requests, and is expected to end all
747    /// transfers with a wl_data_offer.finish request.
748    ///
749    /// If the resulting action is "ask", the action will not be considered
750    /// final. The drag-and-drop destination is expected to perform one last
751    /// wl_data_offer.set_actions request, or wl_data_offer.destroy in order
752    /// to cancel the operation.
753    #[inline]
754    pub fn try_send_drop(
755        &self,
756    ) -> Result<(), ObjectError> {
757        let core = self.core();
758        let client_ref = core.client.borrow();
759        let Some(client) = &*client_ref else {
760            return Err(ObjectError(ObjectErrorKind::ReceiverNoClient));
761        };
762        let id = core.client_obj_id.get().unwrap_or(0);
763        #[cfg(feature = "logging")]
764        if self.core.state.log {
765            #[cold]
766            fn log(state: &State, client_id: u64, id: u32) {
767                let (millis, micros) = time_since_epoch();
768                let prefix = &state.log_prefix;
769                let args = format_args!("[{millis:7}.{micros:03}] {prefix}client#{:<4} <= wl_data_device#{}.drop()\n", client_id, id);
770                state.log(args);
771            }
772            log(&self.core.state, client.endpoint.id, id);
773        }
774        let endpoint = &client.endpoint;
775        if !endpoint.flush_queued.replace(true) {
776            self.core.state.add_flushable_endpoint(endpoint, Some(client));
777        }
778        let mut outgoing_ref = endpoint.outgoing.borrow_mut();
779        let outgoing = &mut *outgoing_ref;
780        let mut fmt = outgoing.formatter();
781        fmt.words([
782            id,
783            4,
784        ]);
785        Ok(())
786    }
787
788    /// end drag-and-drop session successfully
789    ///
790    /// The event is sent when a drag-and-drop operation is ended
791    /// because the implicit grab is removed.
792    ///
793    /// The drag-and-drop destination is expected to honor the last action
794    /// received through wl_data_offer.action, if the resulting action is
795    /// "copy" or "move", the destination can still perform
796    /// wl_data_offer.receive requests, and is expected to end all
797    /// transfers with a wl_data_offer.finish request.
798    ///
799    /// If the resulting action is "ask", the action will not be considered
800    /// final. The drag-and-drop destination is expected to perform one last
801    /// wl_data_offer.set_actions request, or wl_data_offer.destroy in order
802    /// to cancel the operation.
803    #[inline]
804    pub fn send_drop(
805        &self,
806    ) {
807        let res = self.try_send_drop(
808        );
809        if let Err(e) = res {
810            log_send("wl_data_device.drop", &e);
811        }
812    }
813
814    /// Since when the selection message is available.
815    pub const MSG__SELECTION__SINCE: u32 = 1;
816
817    /// advertise new selection
818    ///
819    /// The selection event is sent out to notify the client of a new
820    /// wl_data_offer for the selection for this device.  The
821    /// data_device.data_offer and the data_offer.offer events are
822    /// sent out immediately before this event to introduce the data
823    /// offer object.  The selection event is sent to a client
824    /// immediately before receiving keyboard focus and when a new
825    /// selection is set while the client has keyboard focus.  The
826    /// data_offer is valid until a new data_offer or NULL is received
827    /// or until the client loses keyboard focus.  Switching surface with
828    /// keyboard focus within the same client doesn't mean a new selection
829    /// will be sent.  The client must destroy the previous selection
830    /// data_offer, if any, upon receiving this event.
831    ///
832    /// # Arguments
833    ///
834    /// - `id`: selection data_offer object
835    #[inline]
836    pub fn try_send_selection(
837        &self,
838        id: Option<&Rc<WlDataOffer>>,
839    ) -> Result<(), ObjectError> {
840        let (
841            arg0,
842        ) = (
843            id,
844        );
845        let arg0 = arg0.map(|a| a.core());
846        let core = self.core();
847        let client_ref = core.client.borrow();
848        let Some(client) = &*client_ref else {
849            return Err(ObjectError(ObjectErrorKind::ReceiverNoClient));
850        };
851        let id = core.client_obj_id.get().unwrap_or(0);
852        if let Some(arg0) = arg0 {
853            if arg0.client_id.get() != Some(client.endpoint.id) {
854                return Err(ObjectError(ObjectErrorKind::ArgNoClientId("id", client.endpoint.id)));
855            }
856        }
857        let arg0_id = arg0.and_then(|arg0| arg0.client_obj_id.get()).unwrap_or(0);
858        #[cfg(feature = "logging")]
859        if self.core.state.log {
860            #[cold]
861            fn log(state: &State, client_id: u64, id: u32, arg0: u32) {
862                let (millis, micros) = time_since_epoch();
863                let prefix = &state.log_prefix;
864                let args = format_args!("[{millis:7}.{micros:03}] {prefix}client#{:<4} <= wl_data_device#{}.selection(id: wl_data_offer#{})\n", client_id, id, arg0);
865                state.log(args);
866            }
867            log(&self.core.state, client.endpoint.id, id, arg0_id);
868        }
869        let endpoint = &client.endpoint;
870        if !endpoint.flush_queued.replace(true) {
871            self.core.state.add_flushable_endpoint(endpoint, Some(client));
872        }
873        let mut outgoing_ref = endpoint.outgoing.borrow_mut();
874        let outgoing = &mut *outgoing_ref;
875        let mut fmt = outgoing.formatter();
876        fmt.words([
877            id,
878            5,
879            arg0_id,
880        ]);
881        Ok(())
882    }
883
884    /// advertise new selection
885    ///
886    /// The selection event is sent out to notify the client of a new
887    /// wl_data_offer for the selection for this device.  The
888    /// data_device.data_offer and the data_offer.offer events are
889    /// sent out immediately before this event to introduce the data
890    /// offer object.  The selection event is sent to a client
891    /// immediately before receiving keyboard focus and when a new
892    /// selection is set while the client has keyboard focus.  The
893    /// data_offer is valid until a new data_offer or NULL is received
894    /// or until the client loses keyboard focus.  Switching surface with
895    /// keyboard focus within the same client doesn't mean a new selection
896    /// will be sent.  The client must destroy the previous selection
897    /// data_offer, if any, upon receiving this event.
898    ///
899    /// # Arguments
900    ///
901    /// - `id`: selection data_offer object
902    #[inline]
903    pub fn send_selection(
904        &self,
905        id: Option<&Rc<WlDataOffer>>,
906    ) {
907        let res = self.try_send_selection(
908            id,
909        );
910        if let Err(e) = res {
911            log_send("wl_data_device.selection", &e);
912        }
913    }
914
915    /// Since when the release message is available.
916    pub const MSG__RELEASE__SINCE: u32 = 2;
917
918    /// destroy data device
919    ///
920    /// This request destroys the data device.
921    #[inline]
922    pub fn try_send_release(
923        &self,
924    ) -> Result<(), ObjectError> {
925        let core = self.core();
926        let Some(id) = core.server_obj_id.get() else {
927            return Err(ObjectError(ObjectErrorKind::ReceiverNoServerId));
928        };
929        #[cfg(feature = "logging")]
930        if self.core.state.log {
931            #[cold]
932            fn log(state: &State, id: u32) {
933                let (millis, micros) = time_since_epoch();
934                let prefix = &state.log_prefix;
935                let args = format_args!("[{millis:7}.{micros:03}] {prefix}server      <= wl_data_device#{}.release()\n", id);
936                state.log(args);
937            }
938            log(&self.core.state, id);
939        }
940        let Some(endpoint) = &self.core.state.server else {
941            return Ok(());
942        };
943        if !endpoint.flush_queued.replace(true) {
944            self.core.state.add_flushable_endpoint(endpoint, None);
945        }
946        let mut outgoing_ref = endpoint.outgoing.borrow_mut();
947        let outgoing = &mut *outgoing_ref;
948        let mut fmt = outgoing.formatter();
949        fmt.words([
950            id,
951            2,
952        ]);
953        self.core.handle_server_destroy();
954        Ok(())
955    }
956
957    /// destroy data device
958    ///
959    /// This request destroys the data device.
960    #[inline]
961    pub fn send_release(
962        &self,
963    ) {
964        let res = self.try_send_release(
965        );
966        if let Err(e) = res {
967            log_send("wl_data_device.release", &e);
968        }
969    }
970}
971
972/// A message handler for [`WlDataDevice`] proxies.
973pub trait WlDataDeviceHandler: Any {
974    /// Event handler for wl_display.delete_id messages deleting the ID of this object.
975    ///
976    /// The default handler forwards the event to the client, if any.
977    #[inline]
978    fn delete_id(&mut self, slf: &Rc<WlDataDevice>) {
979        slf.core.delete_id();
980    }
981
982    /// start drag-and-drop operation
983    ///
984    /// This request asks the compositor to start a drag-and-drop
985    /// operation on behalf of the client.
986    ///
987    /// The source argument is the data source that provides the data
988    /// for the eventual data transfer. If source is NULL, enter, leave
989    /// and motion events are sent only to the client that initiated the
990    /// drag and the client is expected to handle the data passing
991    /// internally. If source is destroyed, the drag-and-drop session will be
992    /// cancelled.
993    ///
994    /// The origin surface is the surface where the drag originates and
995    /// the client must have an active implicit grab that matches the
996    /// serial.
997    ///
998    /// The icon surface is an optional (can be NULL) surface that
999    /// provides an icon to be moved around with the cursor.  Initially,
1000    /// the top-left corner of the icon surface is placed at the cursor
1001    /// hotspot, but subsequent wl_surface.offset requests can move the
1002    /// relative position. Attach requests must be confirmed with
1003    /// wl_surface.commit as usual. The icon surface is given the role of
1004    /// a drag-and-drop icon. If the icon surface already has another role,
1005    /// it raises a protocol error.
1006    ///
1007    /// The input region is ignored for wl_surfaces with the role of a
1008    /// drag-and-drop icon.
1009    ///
1010    /// The given source may not be used in any further set_selection or
1011    /// start_drag requests. Attempting to reuse a previously-used source
1012    /// may send a used_source error.
1013    ///
1014    /// # Arguments
1015    ///
1016    /// - `source`: data source for the eventual transfer
1017    /// - `origin`: surface where the drag originates
1018    /// - `icon`: drag-and-drop icon surface
1019    /// - `serial`: serial number of the implicit grab on the origin
1020    ///
1021    /// All borrowed proxies passed to this function are guaranteed to be
1022    /// immutable and non-null.
1023    #[inline]
1024    fn handle_start_drag(
1025        &mut self,
1026        slf: &Rc<WlDataDevice>,
1027        source: Option<&Rc<WlDataSource>>,
1028        origin: &Rc<WlSurface>,
1029        icon: Option<&Rc<WlSurface>>,
1030        serial: u32,
1031    ) {
1032        if !slf.core.forward_to_server.get() {
1033            return;
1034        }
1035        let res = slf.try_send_start_drag(
1036            source,
1037            origin,
1038            icon,
1039            serial,
1040        );
1041        if let Err(e) = res {
1042            log_forward("wl_data_device.start_drag", &e);
1043        }
1044    }
1045
1046    /// copy data to the selection
1047    ///
1048    /// This request asks the compositor to set the selection
1049    /// to the data from the source on behalf of the client.
1050    ///
1051    /// To unset the selection, set the source to NULL.
1052    ///
1053    /// The given source may not be used in any further set_selection or
1054    /// start_drag requests. Attempting to reuse a previously-used source
1055    /// may send a used_source error.
1056    ///
1057    /// # Arguments
1058    ///
1059    /// - `source`: data source for the selection
1060    /// - `serial`: serial number of the event that triggered this request
1061    ///
1062    /// All borrowed proxies passed to this function are guaranteed to be
1063    /// immutable and non-null.
1064    #[inline]
1065    fn handle_set_selection(
1066        &mut self,
1067        slf: &Rc<WlDataDevice>,
1068        source: Option<&Rc<WlDataSource>>,
1069        serial: u32,
1070    ) {
1071        if !slf.core.forward_to_server.get() {
1072            return;
1073        }
1074        let res = slf.try_send_set_selection(
1075            source,
1076            serial,
1077        );
1078        if let Err(e) = res {
1079            log_forward("wl_data_device.set_selection", &e);
1080        }
1081    }
1082
1083    /// introduce a new wl_data_offer
1084    ///
1085    /// The data_offer event introduces a new wl_data_offer object,
1086    /// which will subsequently be used in either the
1087    /// data_device.enter event (for drag-and-drop) or the
1088    /// data_device.selection event (for selections).  Immediately
1089    /// following the data_device.data_offer event, the new data_offer
1090    /// object will send out data_offer.offer events to describe the
1091    /// mime types it offers.
1092    ///
1093    /// # Arguments
1094    ///
1095    /// - `id`: the new data_offer object
1096    #[inline]
1097    fn handle_data_offer(
1098        &mut self,
1099        slf: &Rc<WlDataDevice>,
1100        id: &Rc<WlDataOffer>,
1101    ) {
1102        if !slf.core.forward_to_client.get() {
1103            return;
1104        }
1105        let res = slf.try_send_data_offer(
1106            id,
1107        );
1108        if let Err(e) = res {
1109            log_forward("wl_data_device.data_offer", &e);
1110        }
1111    }
1112
1113    /// initiate drag-and-drop session
1114    ///
1115    /// This event is sent when an active drag-and-drop pointer enters
1116    /// a surface owned by the client.  The position of the pointer at
1117    /// enter time is provided by the x and y arguments, in surface-local
1118    /// coordinates.
1119    ///
1120    /// # Arguments
1121    ///
1122    /// - `serial`: serial number of the enter event
1123    /// - `surface`: client surface entered
1124    /// - `x`: surface-local x coordinate
1125    /// - `y`: surface-local y coordinate
1126    /// - `id`: source data_offer object
1127    ///
1128    /// All borrowed proxies passed to this function are guaranteed to be
1129    /// immutable and non-null.
1130    #[inline]
1131    fn handle_enter(
1132        &mut self,
1133        slf: &Rc<WlDataDevice>,
1134        serial: u32,
1135        surface: &Rc<WlSurface>,
1136        x: Fixed,
1137        y: Fixed,
1138        id: Option<&Rc<WlDataOffer>>,
1139    ) {
1140        if !slf.core.forward_to_client.get() {
1141            return;
1142        }
1143        if let Some(client_id) = slf.core.client_id.get() {
1144            if let Some(client_id_2) = surface.core().client_id.get() {
1145                if client_id != client_id_2 {
1146                    return;
1147                }
1148            }
1149            if let Some(id) = id {
1150                if let Some(client_id_2) = id.core().client_id.get() {
1151                    if client_id != client_id_2 {
1152                        return;
1153                    }
1154                }
1155            }
1156        }
1157        let res = slf.try_send_enter(
1158            serial,
1159            surface,
1160            x,
1161            y,
1162            id,
1163        );
1164        if let Err(e) = res {
1165            log_forward("wl_data_device.enter", &e);
1166        }
1167    }
1168
1169    /// end drag-and-drop session
1170    ///
1171    /// This event is sent when the drag-and-drop pointer leaves the
1172    /// surface and the session ends.  The client must destroy the
1173    /// wl_data_offer introduced at enter time at this point.
1174    #[inline]
1175    fn handle_leave(
1176        &mut self,
1177        slf: &Rc<WlDataDevice>,
1178    ) {
1179        if !slf.core.forward_to_client.get() {
1180            return;
1181        }
1182        let res = slf.try_send_leave(
1183        );
1184        if let Err(e) = res {
1185            log_forward("wl_data_device.leave", &e);
1186        }
1187    }
1188
1189    /// drag-and-drop session motion
1190    ///
1191    /// This event is sent when the drag-and-drop pointer moves within
1192    /// the currently focused surface. The new position of the pointer
1193    /// is provided by the x and y arguments, in surface-local
1194    /// coordinates.
1195    ///
1196    /// # Arguments
1197    ///
1198    /// - `time`: timestamp with millisecond granularity
1199    /// - `x`: surface-local x coordinate
1200    /// - `y`: surface-local y coordinate
1201    #[inline]
1202    fn handle_motion(
1203        &mut self,
1204        slf: &Rc<WlDataDevice>,
1205        time: u32,
1206        x: Fixed,
1207        y: Fixed,
1208    ) {
1209        if !slf.core.forward_to_client.get() {
1210            return;
1211        }
1212        let res = slf.try_send_motion(
1213            time,
1214            x,
1215            y,
1216        );
1217        if let Err(e) = res {
1218            log_forward("wl_data_device.motion", &e);
1219        }
1220    }
1221
1222    /// end drag-and-drop session successfully
1223    ///
1224    /// The event is sent when a drag-and-drop operation is ended
1225    /// because the implicit grab is removed.
1226    ///
1227    /// The drag-and-drop destination is expected to honor the last action
1228    /// received through wl_data_offer.action, if the resulting action is
1229    /// "copy" or "move", the destination can still perform
1230    /// wl_data_offer.receive requests, and is expected to end all
1231    /// transfers with a wl_data_offer.finish request.
1232    ///
1233    /// If the resulting action is "ask", the action will not be considered
1234    /// final. The drag-and-drop destination is expected to perform one last
1235    /// wl_data_offer.set_actions request, or wl_data_offer.destroy in order
1236    /// to cancel the operation.
1237    #[inline]
1238    fn handle_drop(
1239        &mut self,
1240        slf: &Rc<WlDataDevice>,
1241    ) {
1242        if !slf.core.forward_to_client.get() {
1243            return;
1244        }
1245        let res = slf.try_send_drop(
1246        );
1247        if let Err(e) = res {
1248            log_forward("wl_data_device.drop", &e);
1249        }
1250    }
1251
1252    /// advertise new selection
1253    ///
1254    /// The selection event is sent out to notify the client of a new
1255    /// wl_data_offer for the selection for this device.  The
1256    /// data_device.data_offer and the data_offer.offer events are
1257    /// sent out immediately before this event to introduce the data
1258    /// offer object.  The selection event is sent to a client
1259    /// immediately before receiving keyboard focus and when a new
1260    /// selection is set while the client has keyboard focus.  The
1261    /// data_offer is valid until a new data_offer or NULL is received
1262    /// or until the client loses keyboard focus.  Switching surface with
1263    /// keyboard focus within the same client doesn't mean a new selection
1264    /// will be sent.  The client must destroy the previous selection
1265    /// data_offer, if any, upon receiving this event.
1266    ///
1267    /// # Arguments
1268    ///
1269    /// - `id`: selection data_offer object
1270    ///
1271    /// All borrowed proxies passed to this function are guaranteed to be
1272    /// immutable and non-null.
1273    #[inline]
1274    fn handle_selection(
1275        &mut self,
1276        slf: &Rc<WlDataDevice>,
1277        id: Option<&Rc<WlDataOffer>>,
1278    ) {
1279        if !slf.core.forward_to_client.get() {
1280            return;
1281        }
1282        if let Some(client_id) = slf.core.client_id.get() {
1283            if let Some(id) = id {
1284                if let Some(client_id_2) = id.core().client_id.get() {
1285                    if client_id != client_id_2 {
1286                        return;
1287                    }
1288                }
1289            }
1290        }
1291        let res = slf.try_send_selection(
1292            id,
1293        );
1294        if let Err(e) = res {
1295            log_forward("wl_data_device.selection", &e);
1296        }
1297    }
1298
1299    /// destroy data device
1300    ///
1301    /// This request destroys the data device.
1302    #[inline]
1303    fn handle_release(
1304        &mut self,
1305        slf: &Rc<WlDataDevice>,
1306    ) {
1307        if !slf.core.forward_to_server.get() {
1308            return;
1309        }
1310        let res = slf.try_send_release(
1311        );
1312        if let Err(e) = res {
1313            log_forward("wl_data_device.release", &e);
1314        }
1315    }
1316}
1317
1318impl ObjectPrivate for WlDataDevice {
1319    fn new(state: &Rc<State>, version: u32) -> Rc<Self> {
1320        Rc::<Self>::new_cyclic(|slf| Self {
1321            core: ObjectCore::new(state, slf.clone(), ObjectInterface::WlDataDevice, version),
1322            handler: Default::default(),
1323        })
1324    }
1325
1326    fn delete_id(self: Rc<Self>) -> Result<(), (ObjectError, Rc<dyn Object>)> {
1327        let Some(mut handler) = self.handler.try_borrow_mut() else {
1328            return Err((ObjectError(ObjectErrorKind::HandlerBorrowed), self));
1329        };
1330        if let Some(handler) = &mut *handler {
1331            handler.delete_id(&self);
1332        } else {
1333            self.core.delete_id();
1334        }
1335        Ok(())
1336    }
1337
1338    fn handle_request(self: Rc<Self>, client: &Rc<Client>, msg: &[u32], fds: &mut VecDeque<Rc<OwnedFd>>) -> Result<(), ObjectError> {
1339        let Some(mut handler) = self.handler.try_borrow_mut() else {
1340            return Err(ObjectError(ObjectErrorKind::HandlerBorrowed));
1341        };
1342        let handler = &mut *handler;
1343        match msg[1] & 0xffff {
1344            0 => {
1345                let [
1346                    arg0,
1347                    arg1,
1348                    arg2,
1349                    arg3,
1350                ] = msg[2..] else {
1351                    return Err(ObjectError(ObjectErrorKind::WrongMessageSize(msg.len() as u32 * 4, 24)));
1352                };
1353                #[cfg(feature = "logging")]
1354                if self.core.state.log {
1355                    #[cold]
1356                    fn log(state: &State, client_id: u64, id: u32, arg0: u32, arg1: u32, arg2: u32, arg3: u32) {
1357                        let (millis, micros) = time_since_epoch();
1358                        let prefix = &state.log_prefix;
1359                        let args = format_args!("[{millis:7}.{micros:03}] {prefix}client#{:<4} -> wl_data_device#{}.start_drag(source: wl_data_source#{}, origin: wl_surface#{}, icon: wl_surface#{}, serial: {})\n", client_id, id, arg0, arg1, arg2, arg3);
1360                        state.log(args);
1361                    }
1362                    log(&self.core.state, client.endpoint.id, msg[0], arg0, arg1, arg2, arg3);
1363                }
1364                let arg0 = if arg0 == 0 {
1365                    None
1366                } else {
1367                    let arg0_id = arg0;
1368                    let Some(arg0) = client.endpoint.lookup(arg0_id) else {
1369                        return Err(ObjectError(ObjectErrorKind::NoClientObject(client.endpoint.id, arg0_id)));
1370                    };
1371                    let Ok(arg0) = (arg0 as Rc<dyn Any>).downcast::<WlDataSource>() else {
1372                        let o = client.endpoint.lookup(arg0_id).unwrap();
1373                        return Err(ObjectError(ObjectErrorKind::WrongObjectType("source", o.core().interface, ObjectInterface::WlDataSource)));
1374                    };
1375                    Some(arg0)
1376                };
1377                let arg1_id = arg1;
1378                let Some(arg1) = client.endpoint.lookup(arg1_id) else {
1379                    return Err(ObjectError(ObjectErrorKind::NoClientObject(client.endpoint.id, arg1_id)));
1380                };
1381                let Ok(arg1) = (arg1 as Rc<dyn Any>).downcast::<WlSurface>() else {
1382                    let o = client.endpoint.lookup(arg1_id).unwrap();
1383                    return Err(ObjectError(ObjectErrorKind::WrongObjectType("origin", o.core().interface, ObjectInterface::WlSurface)));
1384                };
1385                let arg2 = if arg2 == 0 {
1386                    None
1387                } else {
1388                    let arg2_id = arg2;
1389                    let Some(arg2) = client.endpoint.lookup(arg2_id) else {
1390                        return Err(ObjectError(ObjectErrorKind::NoClientObject(client.endpoint.id, arg2_id)));
1391                    };
1392                    let Ok(arg2) = (arg2 as Rc<dyn Any>).downcast::<WlSurface>() else {
1393                        let o = client.endpoint.lookup(arg2_id).unwrap();
1394                        return Err(ObjectError(ObjectErrorKind::WrongObjectType("icon", o.core().interface, ObjectInterface::WlSurface)));
1395                    };
1396                    Some(arg2)
1397                };
1398                let arg0 = arg0.as_ref();
1399                let arg1 = &arg1;
1400                let arg2 = arg2.as_ref();
1401                if let Some(handler) = handler {
1402                    (**handler).handle_start_drag(&self, arg0, arg1, arg2, arg3);
1403                } else {
1404                    DefaultHandler.handle_start_drag(&self, arg0, arg1, arg2, arg3);
1405                }
1406            }
1407            1 => {
1408                let [
1409                    arg0,
1410                    arg1,
1411                ] = msg[2..] else {
1412                    return Err(ObjectError(ObjectErrorKind::WrongMessageSize(msg.len() as u32 * 4, 16)));
1413                };
1414                #[cfg(feature = "logging")]
1415                if self.core.state.log {
1416                    #[cold]
1417                    fn log(state: &State, client_id: u64, id: u32, arg0: u32, arg1: u32) {
1418                        let (millis, micros) = time_since_epoch();
1419                        let prefix = &state.log_prefix;
1420                        let args = format_args!("[{millis:7}.{micros:03}] {prefix}client#{:<4} -> wl_data_device#{}.set_selection(source: wl_data_source#{}, serial: {})\n", client_id, id, arg0, arg1);
1421                        state.log(args);
1422                    }
1423                    log(&self.core.state, client.endpoint.id, msg[0], arg0, arg1);
1424                }
1425                let arg0 = if arg0 == 0 {
1426                    None
1427                } else {
1428                    let arg0_id = arg0;
1429                    let Some(arg0) = client.endpoint.lookup(arg0_id) else {
1430                        return Err(ObjectError(ObjectErrorKind::NoClientObject(client.endpoint.id, arg0_id)));
1431                    };
1432                    let Ok(arg0) = (arg0 as Rc<dyn Any>).downcast::<WlDataSource>() else {
1433                        let o = client.endpoint.lookup(arg0_id).unwrap();
1434                        return Err(ObjectError(ObjectErrorKind::WrongObjectType("source", o.core().interface, ObjectInterface::WlDataSource)));
1435                    };
1436                    Some(arg0)
1437                };
1438                let arg0 = arg0.as_ref();
1439                if let Some(handler) = handler {
1440                    (**handler).handle_set_selection(&self, arg0, arg1);
1441                } else {
1442                    DefaultHandler.handle_set_selection(&self, arg0, arg1);
1443                }
1444            }
1445            2 => {
1446                if msg.len() != 2 {
1447                    return Err(ObjectError(ObjectErrorKind::WrongMessageSize(msg.len() as u32 * 4, 8)));
1448                }
1449                #[cfg(feature = "logging")]
1450                if self.core.state.log {
1451                    #[cold]
1452                    fn log(state: &State, client_id: u64, id: u32) {
1453                        let (millis, micros) = time_since_epoch();
1454                        let prefix = &state.log_prefix;
1455                        let args = format_args!("[{millis:7}.{micros:03}] {prefix}client#{:<4} -> wl_data_device#{}.release()\n", client_id, id);
1456                        state.log(args);
1457                    }
1458                    log(&self.core.state, client.endpoint.id, msg[0]);
1459                }
1460                self.core.handle_client_destroy();
1461                if let Some(handler) = handler {
1462                    (**handler).handle_release(&self);
1463                } else {
1464                    DefaultHandler.handle_release(&self);
1465                }
1466            }
1467            n => {
1468                let _ = client;
1469                let _ = msg;
1470                let _ = fds;
1471                let _ = handler;
1472                return Err(ObjectError(ObjectErrorKind::UnknownMessageId(n)));
1473            }
1474        }
1475        Ok(())
1476    }
1477
1478    fn handle_event(self: Rc<Self>, server: &Endpoint, msg: &[u32], fds: &mut VecDeque<Rc<OwnedFd>>) -> Result<(), ObjectError> {
1479        let Some(mut handler) = self.handler.try_borrow_mut() else {
1480            return Err(ObjectError(ObjectErrorKind::HandlerBorrowed));
1481        };
1482        let handler = &mut *handler;
1483        match msg[1] & 0xffff {
1484            0 => {
1485                let [
1486                    arg0,
1487                ] = msg[2..] else {
1488                    return Err(ObjectError(ObjectErrorKind::WrongMessageSize(msg.len() as u32 * 4, 12)));
1489                };
1490                #[cfg(feature = "logging")]
1491                if self.core.state.log {
1492                    #[cold]
1493                    fn log(state: &State, id: u32, arg0: u32) {
1494                        let (millis, micros) = time_since_epoch();
1495                        let prefix = &state.log_prefix;
1496                        let args = format_args!("[{millis:7}.{micros:03}] {prefix}server      -> wl_data_device#{}.data_offer(id: wl_data_offer#{})\n", id, arg0);
1497                        state.log(args);
1498                    }
1499                    log(&self.core.state, msg[0], arg0);
1500                }
1501                let arg0_id = arg0;
1502                let arg0 = WlDataOffer::new(&self.core.state, self.core.version);
1503                arg0.core().set_server_id(arg0_id, arg0.clone())
1504                    .map_err(|e| ObjectError(ObjectErrorKind::SetServerId(arg0_id, "id", e)))?;
1505                let arg0 = &arg0;
1506                if let Some(handler) = handler {
1507                    (**handler).handle_data_offer(&self, arg0);
1508                } else {
1509                    DefaultHandler.handle_data_offer(&self, arg0);
1510                }
1511            }
1512            1 => {
1513                let [
1514                    arg0,
1515                    arg1,
1516                    arg2,
1517                    arg3,
1518                    arg4,
1519                ] = msg[2..] else {
1520                    return Err(ObjectError(ObjectErrorKind::WrongMessageSize(msg.len() as u32 * 4, 28)));
1521                };
1522                let arg2 = Fixed::from_wire(arg2 as i32);
1523                let arg3 = Fixed::from_wire(arg3 as i32);
1524                #[cfg(feature = "logging")]
1525                if self.core.state.log {
1526                    #[cold]
1527                    fn log(state: &State, id: u32, arg0: u32, arg1: u32, arg2: Fixed, arg3: Fixed, arg4: u32) {
1528                        let (millis, micros) = time_since_epoch();
1529                        let prefix = &state.log_prefix;
1530                        let args = format_args!("[{millis:7}.{micros:03}] {prefix}server      -> wl_data_device#{}.enter(serial: {}, surface: wl_surface#{}, x: {}, y: {}, id: wl_data_offer#{})\n", id, arg0, arg1, arg2, arg3, arg4);
1531                        state.log(args);
1532                    }
1533                    log(&self.core.state, msg[0], arg0, arg1, arg2, arg3, arg4);
1534                }
1535                let arg1_id = arg1;
1536                let Some(arg1) = server.lookup(arg1_id) else {
1537                    return Err(ObjectError(ObjectErrorKind::NoServerObject(arg1_id)));
1538                };
1539                let Ok(arg1) = (arg1 as Rc<dyn Any>).downcast::<WlSurface>() else {
1540                    let o = server.lookup(arg1_id).unwrap();
1541                    return Err(ObjectError(ObjectErrorKind::WrongObjectType("surface", o.core().interface, ObjectInterface::WlSurface)));
1542                };
1543                let arg4 = if arg4 == 0 {
1544                    None
1545                } else {
1546                    let arg4_id = arg4;
1547                    let Some(arg4) = server.lookup(arg4_id) else {
1548                        return Err(ObjectError(ObjectErrorKind::NoServerObject(arg4_id)));
1549                    };
1550                    let Ok(arg4) = (arg4 as Rc<dyn Any>).downcast::<WlDataOffer>() else {
1551                        let o = server.lookup(arg4_id).unwrap();
1552                        return Err(ObjectError(ObjectErrorKind::WrongObjectType("id", o.core().interface, ObjectInterface::WlDataOffer)));
1553                    };
1554                    Some(arg4)
1555                };
1556                let arg1 = &arg1;
1557                let arg4 = arg4.as_ref();
1558                if let Some(handler) = handler {
1559                    (**handler).handle_enter(&self, arg0, arg1, arg2, arg3, arg4);
1560                } else {
1561                    DefaultHandler.handle_enter(&self, arg0, arg1, arg2, arg3, arg4);
1562                }
1563            }
1564            2 => {
1565                if msg.len() != 2 {
1566                    return Err(ObjectError(ObjectErrorKind::WrongMessageSize(msg.len() as u32 * 4, 8)));
1567                }
1568                #[cfg(feature = "logging")]
1569                if self.core.state.log {
1570                    #[cold]
1571                    fn log(state: &State, id: u32) {
1572                        let (millis, micros) = time_since_epoch();
1573                        let prefix = &state.log_prefix;
1574                        let args = format_args!("[{millis:7}.{micros:03}] {prefix}server      -> wl_data_device#{}.leave()\n", id);
1575                        state.log(args);
1576                    }
1577                    log(&self.core.state, msg[0]);
1578                }
1579                if let Some(handler) = handler {
1580                    (**handler).handle_leave(&self);
1581                } else {
1582                    DefaultHandler.handle_leave(&self);
1583                }
1584            }
1585            3 => {
1586                let [
1587                    arg0,
1588                    arg1,
1589                    arg2,
1590                ] = msg[2..] else {
1591                    return Err(ObjectError(ObjectErrorKind::WrongMessageSize(msg.len() as u32 * 4, 20)));
1592                };
1593                let arg1 = Fixed::from_wire(arg1 as i32);
1594                let arg2 = Fixed::from_wire(arg2 as i32);
1595                #[cfg(feature = "logging")]
1596                if self.core.state.log {
1597                    #[cold]
1598                    fn log(state: &State, id: u32, arg0: u32, arg1: Fixed, arg2: Fixed) {
1599                        let (millis, micros) = time_since_epoch();
1600                        let prefix = &state.log_prefix;
1601                        let args = format_args!("[{millis:7}.{micros:03}] {prefix}server      -> wl_data_device#{}.motion(time: {}, x: {}, y: {})\n", id, arg0, arg1, arg2);
1602                        state.log(args);
1603                    }
1604                    log(&self.core.state, msg[0], arg0, arg1, arg2);
1605                }
1606                if let Some(handler) = handler {
1607                    (**handler).handle_motion(&self, arg0, arg1, arg2);
1608                } else {
1609                    DefaultHandler.handle_motion(&self, arg0, arg1, arg2);
1610                }
1611            }
1612            4 => {
1613                if msg.len() != 2 {
1614                    return Err(ObjectError(ObjectErrorKind::WrongMessageSize(msg.len() as u32 * 4, 8)));
1615                }
1616                #[cfg(feature = "logging")]
1617                if self.core.state.log {
1618                    #[cold]
1619                    fn log(state: &State, id: u32) {
1620                        let (millis, micros) = time_since_epoch();
1621                        let prefix = &state.log_prefix;
1622                        let args = format_args!("[{millis:7}.{micros:03}] {prefix}server      -> wl_data_device#{}.drop()\n", id);
1623                        state.log(args);
1624                    }
1625                    log(&self.core.state, msg[0]);
1626                }
1627                if let Some(handler) = handler {
1628                    (**handler).handle_drop(&self);
1629                } else {
1630                    DefaultHandler.handle_drop(&self);
1631                }
1632            }
1633            5 => {
1634                let [
1635                    arg0,
1636                ] = msg[2..] else {
1637                    return Err(ObjectError(ObjectErrorKind::WrongMessageSize(msg.len() as u32 * 4, 12)));
1638                };
1639                #[cfg(feature = "logging")]
1640                if self.core.state.log {
1641                    #[cold]
1642                    fn log(state: &State, id: u32, arg0: u32) {
1643                        let (millis, micros) = time_since_epoch();
1644                        let prefix = &state.log_prefix;
1645                        let args = format_args!("[{millis:7}.{micros:03}] {prefix}server      -> wl_data_device#{}.selection(id: wl_data_offer#{})\n", id, arg0);
1646                        state.log(args);
1647                    }
1648                    log(&self.core.state, msg[0], arg0);
1649                }
1650                let arg0 = if arg0 == 0 {
1651                    None
1652                } else {
1653                    let arg0_id = arg0;
1654                    let Some(arg0) = server.lookup(arg0_id) else {
1655                        return Err(ObjectError(ObjectErrorKind::NoServerObject(arg0_id)));
1656                    };
1657                    let Ok(arg0) = (arg0 as Rc<dyn Any>).downcast::<WlDataOffer>() else {
1658                        let o = server.lookup(arg0_id).unwrap();
1659                        return Err(ObjectError(ObjectErrorKind::WrongObjectType("id", o.core().interface, ObjectInterface::WlDataOffer)));
1660                    };
1661                    Some(arg0)
1662                };
1663                let arg0 = arg0.as_ref();
1664                if let Some(handler) = handler {
1665                    (**handler).handle_selection(&self, arg0);
1666                } else {
1667                    DefaultHandler.handle_selection(&self, arg0);
1668                }
1669            }
1670            n => {
1671                let _ = server;
1672                let _ = msg;
1673                let _ = fds;
1674                let _ = handler;
1675                return Err(ObjectError(ObjectErrorKind::UnknownMessageId(n)));
1676            }
1677        }
1678        Ok(())
1679    }
1680
1681    fn get_request_name(&self, id: u32) -> Option<&'static str> {
1682        let name = match id {
1683            0 => "start_drag",
1684            1 => "set_selection",
1685            2 => "release",
1686            _ => return None,
1687        };
1688        Some(name)
1689    }
1690
1691    fn get_event_name(&self, id: u32) -> Option<&'static str> {
1692        let name = match id {
1693            0 => "data_offer",
1694            1 => "enter",
1695            2 => "leave",
1696            3 => "motion",
1697            4 => "drop",
1698            5 => "selection",
1699            _ => return None,
1700        };
1701        Some(name)
1702    }
1703}
1704
1705impl Object for WlDataDevice {
1706    fn core(&self) -> &ObjectCore {
1707        &self.core
1708    }
1709
1710    fn unset_handler(&self) {
1711        self.handler.set(None);
1712    }
1713
1714    fn get_handler_any_ref(&self) -> Result<HandlerRef<'_, dyn Any>, HandlerAccessError> {
1715        let borrowed = self.handler.try_borrow().ok_or(HandlerAccessError::AlreadyBorrowed)?;
1716        if borrowed.is_none() {
1717            return Err(HandlerAccessError::NoHandler);
1718        }
1719        Ok(HandlerRef::map(borrowed, |handler| &**handler.as_ref().unwrap() as &dyn Any))
1720    }
1721
1722    fn get_handler_any_mut(&self) -> Result<HandlerMut<'_, dyn Any>, HandlerAccessError> {
1723        let borrowed = self.handler.try_borrow_mut().ok_or(HandlerAccessError::AlreadyBorrowed)?;
1724        if borrowed.is_none() {
1725            return Err(HandlerAccessError::NoHandler);
1726        }
1727        Ok(HandlerMut::map(borrowed, |handler| &mut **handler.as_mut().unwrap() as &mut dyn Any))
1728    }
1729}
1730
1731impl WlDataDevice {
1732    /// Since when the error.role enum variant is available.
1733    pub const ENM__ERROR_ROLE__SINCE: u32 = 1;
1734    /// Since when the error.used_source enum variant is available.
1735    pub const ENM__ERROR_USED_SOURCE__SINCE: u32 = 1;
1736}
1737
1738#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
1739pub struct WlDataDeviceError(pub u32);
1740
1741impl WlDataDeviceError {
1742    /// given wl_surface has another role
1743    pub const ROLE: Self = Self(0);
1744
1745    /// source has already been used
1746    pub const USED_SOURCE: Self = Self(1);
1747}
1748
1749impl Debug for WlDataDeviceError {
1750    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1751        let name = match *self {
1752            Self::ROLE => "ROLE",
1753            Self::USED_SOURCE => "USED_SOURCE",
1754            _ => return Debug::fmt(&self.0, f),
1755        };
1756        f.write_str(name)
1757    }
1758}