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