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}