simple_window/common/protocols_data/wayland/wl_data_source.rs
1//! offer to transfer data
2//!
3//! The wl_data_source object is the source side of a wl_data_offer.
4//! It is created by the source client in a data transfer and
5//! provides a way to describe the offered data and a way to respond
6//! to requests to transfer the data.
7
8use {super::super::all_types::*, ::wl_client::builder::prelude::*};
9
10static INTERFACE: wl_interface = wl_interface {
11 name: c"wl_data_source".as_ptr(),
12 version: 3,
13 method_count: 3,
14 methods: {
15 static MESSAGES: [wl_message; 3] = [
16 wl_message {
17 name: c"offer".as_ptr(),
18 signature: c"s".as_ptr(),
19 types: {
20 static TYPES: [Option<&'static wl_interface>; 1] = [None];
21 TYPES.as_ptr().cast()
22 },
23 },
24 wl_message {
25 name: c"destroy".as_ptr(),
26 signature: c"".as_ptr(),
27 types: {
28 static TYPES: [Option<&'static wl_interface>; 0] = [];
29 TYPES.as_ptr().cast()
30 },
31 },
32 wl_message {
33 name: c"set_actions".as_ptr(),
34 signature: c"u".as_ptr(),
35 types: {
36 static TYPES: [Option<&'static wl_interface>; 1] = [None];
37 TYPES.as_ptr().cast()
38 },
39 },
40 ];
41 MESSAGES.as_ptr()
42 },
43 event_count: 6,
44 events: {
45 static MESSAGES: [wl_message; 6] = [
46 wl_message {
47 name: c"target".as_ptr(),
48 signature: c"?s".as_ptr(),
49 types: {
50 static TYPES: [Option<&'static wl_interface>; 1] = [None];
51 TYPES.as_ptr().cast()
52 },
53 },
54 wl_message {
55 name: c"send".as_ptr(),
56 signature: c"sh".as_ptr(),
57 types: {
58 static TYPES: [Option<&'static wl_interface>; 2] = [None, None];
59 TYPES.as_ptr().cast()
60 },
61 },
62 wl_message {
63 name: c"cancelled".as_ptr(),
64 signature: c"".as_ptr(),
65 types: {
66 static TYPES: [Option<&'static wl_interface>; 0] = [];
67 TYPES.as_ptr().cast()
68 },
69 },
70 wl_message {
71 name: c"dnd_drop_performed".as_ptr(),
72 signature: c"".as_ptr(),
73 types: {
74 static TYPES: [Option<&'static wl_interface>; 0] = [];
75 TYPES.as_ptr().cast()
76 },
77 },
78 wl_message {
79 name: c"dnd_finished".as_ptr(),
80 signature: c"".as_ptr(),
81 types: {
82 static TYPES: [Option<&'static wl_interface>; 0] = [];
83 TYPES.as_ptr().cast()
84 },
85 },
86 wl_message {
87 name: c"action".as_ptr(),
88 signature: c"u".as_ptr(),
89 types: {
90 static TYPES: [Option<&'static wl_interface>; 1] = [None];
91 TYPES.as_ptr().cast()
92 },
93 },
94 ];
95 MESSAGES.as_ptr()
96 },
97};
98
99/// An owned wl_data_source proxy.
100///
101/// See the documentation of [the module][self] for the interface description.
102#[derive(Clone, Eq, PartialEq)]
103#[repr(transparent)]
104pub struct WlDataSource {
105 /// This proxy has the interface INTERFACE.
106 proxy: UntypedOwnedProxy,
107}
108
109/// A borrowed wl_data_source proxy.
110///
111/// See the documentation of [the module][self] for the interface description.
112#[derive(Eq, PartialEq)]
113#[repr(transparent)]
114pub struct WlDataSourceRef {
115 /// This proxy has the interface INTERFACE.
116 proxy: UntypedBorrowedProxy,
117}
118
119// SAFETY: WlDataSource is a transparent wrapper around UntypedOwnedProxy
120unsafe impl UntypedOwnedProxyWrapper for WlDataSource {}
121
122// SAFETY: - INTERFACE is a valid wl_interface
123// - The only invariant is that self.proxy has a compatible interface
124unsafe impl OwnedProxy for WlDataSource {
125 const INTERFACE: &'static str = "wl_data_source";
126 const WL_INTERFACE: &'static wl_interface = &INTERFACE;
127 const NO_OP_EVENT_HANDLER: Self::NoOpEventHandler =
128 private::EventHandler(private::NoOpEventHandler);
129 const MAX_VERSION: u32 = 3;
130
131 type Borrowed = WlDataSourceRef;
132 type Api = private::ProxyApi;
133 type NoOpEventHandler = private::EventHandler<private::NoOpEventHandler>;
134}
135
136// SAFETY: WlDataSourceRef is a transparent wrapper around UntypedBorrowedProxy
137unsafe impl UntypedBorrowedProxyWrapper for WlDataSourceRef {}
138
139// SAFETY: - The only invariant is that self.proxy has a compatible interface
140unsafe impl BorrowedProxy for WlDataSourceRef {
141 type Owned = WlDataSource;
142}
143
144impl Deref for WlDataSource {
145 type Target = WlDataSourceRef;
146
147 fn deref(&self) -> &Self::Target {
148 proxy::low_level::deref(self)
149 }
150}
151
152mod private {
153 pub struct ProxyApi;
154
155 #[allow(dead_code)]
156 pub struct EventHandler<H>(pub(super) H);
157
158 #[allow(dead_code)]
159 pub struct NoOpEventHandler;
160}
161
162impl Debug for WlDataSource {
163 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
164 write!(f, "wl_data_source#{}", self.proxy.id())
165 }
166}
167
168impl Debug for WlDataSourceRef {
169 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
170 write!(f, "wl_data_source#{}", self.proxy.id())
171 }
172}
173
174impl PartialEq<WlDataSourceRef> for WlDataSource {
175 fn eq(&self, other: &WlDataSourceRef) -> bool {
176 self.proxy == other.proxy
177 }
178}
179
180impl PartialEq<WlDataSource> for WlDataSourceRef {
181 fn eq(&self, other: &WlDataSource) -> bool {
182 self.proxy == other.proxy
183 }
184}
185
186#[allow(dead_code)]
187impl WlDataSource {
188 /// Since when the destroy request is available.
189 #[allow(dead_code)]
190 pub const REQ__DESTROY__SINCE: u32 = 1;
191
192 /// destroy the data source
193 ///
194 /// Destroy the data source.
195 #[inline]
196 pub fn destroy(&self) {
197 let mut args = [];
198 // SAFETY: - self.proxy has the interface INTERFACE
199 // - 1 < INTERFACE.method_count = 3
200 // - the request signature is ``
201 unsafe {
202 self.proxy.send_destructor(1, &mut args);
203 }
204 }
205}
206
207#[allow(dead_code)]
208impl WlDataSourceRef {
209 /// add an offered mime type
210 ///
211 /// This request adds a mime type to the set of mime types
212 /// advertised to targets. Can be called several times to offer
213 /// multiple types.
214 ///
215 /// # Arguments
216 ///
217 /// - `mime_type`: mime type offered by the data source
218 #[inline]
219 pub fn offer(&self, mime_type: &str) {
220 let (arg0,) = (mime_type,);
221 with_cstr_cache(|cache| {
222 let str0_offset = cache.len();
223 cache.extend_from_slice(arg0.as_bytes());
224 cache.push(0);
225 let str0 = cache[str0_offset..].as_ptr().cast();
226 let mut args = [wl_argument { s: str0 }];
227 // SAFETY: - self.proxy has the interface INTERFACE
228 // - 0 < INTERFACE.method_count = 3
229 // - the request signature is `s`
230 unsafe {
231 self.proxy.send_request(0, &mut args);
232 }
233 })
234 }
235
236 /// set the available drag-and-drop actions
237 ///
238 /// Sets the actions that the source side client supports for this
239 /// operation. This request may trigger wl_data_source.action and
240 /// wl_data_offer.action events if the compositor needs to change the
241 /// selected action.
242 ///
243 /// The dnd_actions argument must contain only values expressed in the
244 /// wl_data_device_manager.dnd_actions enum, otherwise it will result
245 /// in a protocol error.
246 ///
247 /// This request must be made once only, and can only be made on sources
248 /// used in drag-and-drop, so it must be performed before
249 /// wl_data_device.start_drag. Attempting to use the source other than
250 /// for drag-and-drop will raise a protocol error.
251 ///
252 /// # Arguments
253 ///
254 /// - `dnd_actions`: actions supported by the data source
255 #[inline]
256 pub fn set_actions(&self, dnd_actions: WlDataDeviceManagerDndAction) {
257 let (arg0,) = (dnd_actions,);
258 let mut args = [wl_argument { u: arg0.0 }];
259 // SAFETY: - self.proxy has the interface INTERFACE
260 // - 2 < INTERFACE.method_count = 3
261 // - the request signature is `u`
262 unsafe {
263 self.proxy.send_request(2, &mut args);
264 }
265 }
266}
267
268impl WlDataSource {
269 /// Since when the target event is available.
270 #[allow(dead_code)]
271 pub const EVT__TARGET__SINCE: u32 = 1;
272
273 /// Since when the send event is available.
274 #[allow(dead_code)]
275 pub const EVT__SEND__SINCE: u32 = 1;
276
277 /// Since when the cancelled event is available.
278 #[allow(dead_code)]
279 pub const EVT__CANCELLED__SINCE: u32 = 1;
280
281 /// Since when the dnd_drop_performed event is available.
282 #[allow(dead_code)]
283 pub const EVT__DND_DROP_PERFORMED__SINCE: u32 = 3;
284
285 /// Since when the dnd_finished event is available.
286 #[allow(dead_code)]
287 pub const EVT__DND_FINISHED__SINCE: u32 = 3;
288
289 /// Since when the action event is available.
290 #[allow(dead_code)]
291 pub const EVT__ACTION__SINCE: u32 = 3;
292}
293
294/// An event handler for [WlDataSource] proxies.
295#[allow(dead_code)]
296pub trait WlDataSourceEventHandler {
297 type Data: 'static;
298
299 /// a target accepts an offered mime type
300 ///
301 /// Sent when a target accepts pointer_focus or motion events. If
302 /// a target does not accept any of the offered types, type is NULL.
303 ///
304 /// Used for feedback during drag-and-drop.
305 ///
306 /// # Arguments
307 ///
308 /// - `mime_type`: mime type accepted by the target
309 #[inline]
310 fn target(&self, _data: &mut Self::Data, _slf: &WlDataSourceRef, mime_type: Option<&str>) {
311 let _ = mime_type;
312 }
313
314 /// send the data
315 ///
316 /// Request for data from the client. Send the data as the
317 /// specified mime type over the passed file descriptor, then
318 /// close it.
319 ///
320 /// # Arguments
321 ///
322 /// - `mime_type`: mime type for the data
323 /// - `fd`: file descriptor for the data
324 #[inline]
325 fn send(&self, _data: &mut Self::Data, _slf: &WlDataSourceRef, mime_type: &str, fd: OwnedFd) {
326 let _ = mime_type;
327 let _ = fd;
328 }
329
330 /// selection was cancelled
331 ///
332 /// This data source is no longer valid. There are several reasons why
333 /// this could happen:
334 ///
335 /// - The data source has been replaced by another data source.
336 /// - The drag-and-drop operation was performed, but the drop destination
337 /// did not accept any of the mime types offered through
338 /// wl_data_source.target.
339 /// - The drag-and-drop operation was performed, but the drop destination
340 /// did not select any of the actions present in the mask offered through
341 /// wl_data_source.action.
342 /// - The drag-and-drop operation was performed but didn't happen over a
343 /// surface.
344 /// - The compositor cancelled the drag-and-drop operation (e.g. compositor
345 /// dependent timeouts to avoid stale drag-and-drop transfers).
346 ///
347 /// The client should clean up and destroy this data source.
348 ///
349 /// For objects of version 2 or older, wl_data_source.cancelled will
350 /// only be emitted if the data source was replaced by another data
351 /// source.
352 #[inline]
353 fn cancelled(&self, _data: &mut Self::Data, _slf: &WlDataSourceRef) {}
354
355 /// the drag-and-drop operation physically finished
356 ///
357 /// The user performed the drop action. This event does not indicate
358 /// acceptance, wl_data_source.cancelled may still be emitted afterwards
359 /// if the drop destination does not accept any mime type.
360 ///
361 /// However, this event might however not be received if the compositor
362 /// cancelled the drag-and-drop operation before this event could happen.
363 ///
364 /// Note that the data_source may still be used in the future and should
365 /// not be destroyed here.
366 #[inline]
367 fn dnd_drop_performed(&self, _data: &mut Self::Data, _slf: &WlDataSourceRef) {}
368
369 /// the drag-and-drop operation concluded
370 ///
371 /// The drop destination finished interoperating with this data
372 /// source, so the client is now free to destroy this data source and
373 /// free all associated data.
374 ///
375 /// If the action used to perform the operation was "move", the
376 /// source can now delete the transferred data.
377 #[inline]
378 fn dnd_finished(&self, _data: &mut Self::Data, _slf: &WlDataSourceRef) {}
379
380 /// notify the selected action
381 ///
382 /// This event indicates the action selected by the compositor after
383 /// matching the source/destination side actions. Only one action (or
384 /// none) will be offered here.
385 ///
386 /// This event can be emitted multiple times during the drag-and-drop
387 /// operation, mainly in response to destination side changes through
388 /// wl_data_offer.set_actions, and as the data device enters/leaves
389 /// surfaces.
390 ///
391 /// It is only possible to receive this event after
392 /// wl_data_source.dnd_drop_performed if the drag-and-drop operation
393 /// ended in an "ask" action, in which case the final wl_data_source.action
394 /// event will happen immediately before wl_data_source.dnd_finished.
395 ///
396 /// Compositors may also change the selected action on the fly, mainly
397 /// in response to keyboard modifier changes during the drag-and-drop
398 /// operation.
399 ///
400 /// The most recent action received is always the valid one. The chosen
401 /// action may change alongside negotiation (e.g. an "ask" action can turn
402 /// into a "move" operation), so the effects of the final action must
403 /// always be applied in wl_data_offer.dnd_finished.
404 ///
405 /// Clients can trigger cursor surface changes from this point, so
406 /// they reflect the current action.
407 ///
408 /// # Arguments
409 ///
410 /// - `dnd_action`: action selected by the compositor
411 #[inline]
412 fn action(
413 &self,
414 _data: &mut Self::Data,
415 _slf: &WlDataSourceRef,
416 dnd_action: WlDataDeviceManagerDndAction,
417 ) {
418 let _ = dnd_action;
419 }
420}
421
422impl WlDataSourceEventHandler for private::NoOpEventHandler {
423 type Data = ();
424}
425
426// SAFETY: - INTERFACE is a valid wl_interface
427// - mutable_type always returns the same value
428unsafe impl<H> EventHandler for private::EventHandler<H>
429where
430 H: WlDataSourceEventHandler,
431{
432 const WL_INTERFACE: &'static wl_interface = &INTERFACE;
433
434 #[inline]
435 fn mutable_type() -> Option<(TypeId, &'static str)> {
436 let id = TypeId::of::<H::Data>();
437 let name = std::any::type_name::<H::Data>();
438 Some((id, name))
439 }
440
441 #[allow(unused_variables)]
442 unsafe fn handle_event(
443 &self,
444 queue: &Queue,
445 data: *mut u8,
446 slf: &UntypedBorrowedProxy,
447 opcode: u32,
448 args: *mut wl_argument,
449 ) {
450 // SAFETY: This function requires that slf has the interface INTERFACE
451 let slf = unsafe { proxy::low_level::from_untyped_borrowed::<WlDataSourceRef>(slf) };
452 // SAFETY: This function requires that data is `&mut T` where `T`
453 // has the type id returned by `Self::mutable_type`, i.e.,
454 // `T = H::Data`.
455 let data: &mut H::Data = unsafe { &mut *data.cast() };
456 match opcode {
457 0 => {
458 // SAFETY: INTERFACE requires that there are 1 arguments
459 let args = unsafe { &*args.cast::<[wl_argument; 1]>() };
460 // SAFETY: - INTERFACE requires that args[0] contains a string
461 // - if the pointer is not null, then it is a c string
462 let arg0 = unsafe {
463 convert_optional_string_arg("wl_data_source", "mime_type", args[0].s)
464 };
465 self.0.target(data, slf, arg0);
466 }
467 1 => {
468 // SAFETY: INTERFACE requires that there are 2 arguments
469 let args = unsafe { &*args.cast::<[wl_argument; 2]>() };
470 // SAFETY: - INTERFACE requires that args[0] contains a string
471 // - if the pointer is not null, then it is a c string
472 let arg0 = unsafe { convert_string_arg("wl_data_source", "mime_type", args[0].s) };
473 // SAFETY: - INTERFACE requires that args[1] contains a file descriptor
474 let arg1 = unsafe { OwnedFd::from_raw_fd(args[1].h) };
475 self.0.send(data, slf, arg0, arg1);
476 }
477 2 => {
478 self.0.cancelled(data, slf);
479 }
480 3 => {
481 self.0.dnd_drop_performed(data, slf);
482 }
483 4 => {
484 self.0.dnd_finished(data, slf);
485 }
486 5 => {
487 // SAFETY: INTERFACE requires that there are 1 arguments
488 let args = unsafe { &*args.cast::<[wl_argument; 1]>() };
489 // SAFETY: - INTERFACE requires that args[0] contains a uint
490 let arg0 = unsafe { WlDataDeviceManagerDndAction(args[0].u) };
491 self.0.action(data, slf, arg0);
492 }
493 _ => {
494 invalid_opcode("wl_data_source", opcode);
495 }
496 }
497 }
498}
499
500impl<H> CreateEventHandler<H> for private::ProxyApi
501where
502 H: WlDataSourceEventHandler,
503{
504 type EventHandler = private::EventHandler<H>;
505
506 #[inline]
507 fn create_event_handler(handler: H) -> Self::EventHandler {
508 private::EventHandler(handler)
509 }
510}
511
512impl WlDataSource {
513 /// Since when the error.invalid_action_mask enum variant is available.
514 #[allow(dead_code)]
515 pub const ENM__ERROR_INVALID_ACTION_MASK__SINCE: u32 = 1;
516 /// Since when the error.invalid_source enum variant is available.
517 #[allow(dead_code)]
518 pub const ENM__ERROR_INVALID_SOURCE__SINCE: u32 = 1;
519}
520
521#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
522#[allow(dead_code)]
523pub struct WlDataSourceError(pub u32);
524
525impl WlDataSourceError {
526 /// action mask contains invalid values
527 #[allow(dead_code)]
528 pub const INVALID_ACTION_MASK: Self = Self(0);
529
530 /// source doesn't accept this request
531 #[allow(dead_code)]
532 pub const INVALID_SOURCE: Self = Self(1);
533}
534
535impl Debug for WlDataSourceError {
536 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
537 let name = match *self {
538 Self::INVALID_ACTION_MASK => "INVALID_ACTION_MASK",
539 Self::INVALID_SOURCE => "INVALID_SOURCE",
540 _ => return Debug::fmt(&self.0, f),
541 };
542 f.write_str(name)
543 }
544}
545
546/// Functional event handlers.
547pub mod event_handlers {
548 use super::*;
549
550 /// Event handler for target events.
551 pub struct Target<T, F>(F, PhantomData<fn(&mut T)>);
552 impl<T, F> WlDataSourceEventHandler for Target<T, F>
553 where
554 T: 'static,
555 F: Fn(&mut T, &WlDataSourceRef, Option<&str>),
556 {
557 type Data = T;
558
559 #[inline]
560 fn target(&self, _data: &mut T, _slf: &WlDataSourceRef, mime_type: Option<&str>) {
561 self.0(_data, _slf, mime_type)
562 }
563 }
564
565 /// Event handler for send events.
566 pub struct Send<T, F>(F, PhantomData<fn(&mut T)>);
567 impl<T, F> WlDataSourceEventHandler for Send<T, F>
568 where
569 T: 'static,
570 F: Fn(&mut T, &WlDataSourceRef, &str, OwnedFd),
571 {
572 type Data = T;
573
574 #[inline]
575 fn send(&self, _data: &mut T, _slf: &WlDataSourceRef, mime_type: &str, fd: OwnedFd) {
576 self.0(_data, _slf, mime_type, fd)
577 }
578 }
579
580 /// Event handler for cancelled events.
581 pub struct Cancelled<T, F>(F, PhantomData<fn(&mut T)>);
582 impl<T, F> WlDataSourceEventHandler for Cancelled<T, F>
583 where
584 T: 'static,
585 F: Fn(&mut T, &WlDataSourceRef),
586 {
587 type Data = T;
588
589 #[inline]
590 fn cancelled(&self, _data: &mut T, _slf: &WlDataSourceRef) {
591 self.0(_data, _slf)
592 }
593 }
594
595 /// Event handler for dnd_drop_performed events.
596 pub struct DndDropPerformed<T, F>(F, PhantomData<fn(&mut T)>);
597 impl<T, F> WlDataSourceEventHandler for DndDropPerformed<T, F>
598 where
599 T: 'static,
600 F: Fn(&mut T, &WlDataSourceRef),
601 {
602 type Data = T;
603
604 #[inline]
605 fn dnd_drop_performed(&self, _data: &mut T, _slf: &WlDataSourceRef) {
606 self.0(_data, _slf)
607 }
608 }
609
610 /// Event handler for dnd_finished events.
611 pub struct DndFinished<T, F>(F, PhantomData<fn(&mut T)>);
612 impl<T, F> WlDataSourceEventHandler for DndFinished<T, F>
613 where
614 T: 'static,
615 F: Fn(&mut T, &WlDataSourceRef),
616 {
617 type Data = T;
618
619 #[inline]
620 fn dnd_finished(&self, _data: &mut T, _slf: &WlDataSourceRef) {
621 self.0(_data, _slf)
622 }
623 }
624
625 /// Event handler for action events.
626 pub struct Action<T, F>(F, PhantomData<fn(&mut T)>);
627 impl<T, F> WlDataSourceEventHandler for Action<T, F>
628 where
629 T: 'static,
630 F: Fn(&mut T, &WlDataSourceRef, WlDataDeviceManagerDndAction),
631 {
632 type Data = T;
633
634 #[inline]
635 fn action(
636 &self,
637 _data: &mut T,
638 _slf: &WlDataSourceRef,
639 dnd_action: WlDataDeviceManagerDndAction,
640 ) {
641 self.0(_data, _slf, dnd_action)
642 }
643 }
644
645 impl WlDataSource {
646 /// Creates an event handler for target events.
647 ///
648 /// The event handler ignores all other events.
649 #[allow(dead_code)]
650 pub fn on_target<T, F>(f: F) -> Target<T, F>
651 where
652 T: 'static,
653 F: Fn(&mut T, &WlDataSourceRef, Option<&str>),
654 {
655 Target(f, PhantomData)
656 }
657
658 /// Creates an event handler for send events.
659 ///
660 /// The event handler ignores all other events.
661 #[allow(dead_code)]
662 pub fn on_send<T, F>(f: F) -> Send<T, F>
663 where
664 T: 'static,
665 F: Fn(&mut T, &WlDataSourceRef, &str, OwnedFd),
666 {
667 Send(f, PhantomData)
668 }
669
670 /// Creates an event handler for cancelled events.
671 ///
672 /// The event handler ignores all other events.
673 #[allow(dead_code)]
674 pub fn on_cancelled<T, F>(f: F) -> Cancelled<T, F>
675 where
676 T: 'static,
677 F: Fn(&mut T, &WlDataSourceRef),
678 {
679 Cancelled(f, PhantomData)
680 }
681
682 /// Creates an event handler for dnd_drop_performed events.
683 ///
684 /// The event handler ignores all other events.
685 #[allow(dead_code)]
686 pub fn on_dnd_drop_performed<T, F>(f: F) -> DndDropPerformed<T, F>
687 where
688 T: 'static,
689 F: Fn(&mut T, &WlDataSourceRef),
690 {
691 DndDropPerformed(f, PhantomData)
692 }
693
694 /// Creates an event handler for dnd_finished events.
695 ///
696 /// The event handler ignores all other events.
697 #[allow(dead_code)]
698 pub fn on_dnd_finished<T, F>(f: F) -> DndFinished<T, F>
699 where
700 T: 'static,
701 F: Fn(&mut T, &WlDataSourceRef),
702 {
703 DndFinished(f, PhantomData)
704 }
705
706 /// Creates an event handler for action events.
707 ///
708 /// The event handler ignores all other events.
709 #[allow(dead_code)]
710 pub fn on_action<T, F>(f: F) -> Action<T, F>
711 where
712 T: 'static,
713 F: Fn(&mut T, &WlDataSourceRef, WlDataDeviceManagerDndAction),
714 {
715 Action(f, PhantomData)
716 }
717 }
718}