poll_integration/common/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 {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 /// advertise offered mime type
392 ///
393 /// Sent immediately after creating the wl_data_offer object. One
394 /// event per offered mime type.
395 ///
396 /// # Arguments
397 ///
398 /// - `mime_type`: offered mime type
399 #[inline]
400 fn offer(&self, _slf: &WlDataOfferRef, mime_type: &str) {
401 let _ = mime_type;
402 }
403
404 /// notify the source-side available actions
405 ///
406 /// This event indicates the actions offered by the data source. It
407 /// will be sent immediately after creating the wl_data_offer object,
408 /// or anytime the source side changes its offered actions through
409 /// wl_data_source.set_actions.
410 ///
411 /// # Arguments
412 ///
413 /// - `source_actions`: actions offered by the data source
414 #[inline]
415 fn source_actions(&self, _slf: &WlDataOfferRef, source_actions: WlDataDeviceManagerDndAction) {
416 let _ = source_actions;
417 }
418
419 /// notify the selected action
420 ///
421 /// This event indicates the action selected by the compositor after
422 /// matching the source/destination side actions. Only one action (or
423 /// none) will be offered here.
424 ///
425 /// This event can be emitted multiple times during the drag-and-drop
426 /// operation in response to destination side action changes through
427 /// wl_data_offer.set_actions.
428 ///
429 /// This event will no longer be emitted after wl_data_device.drop
430 /// happened on the drag-and-drop destination, the client must
431 /// honor the last action received, or the last preferred one set
432 /// through wl_data_offer.set_actions when handling an "ask" action.
433 ///
434 /// Compositors may also change the selected action on the fly, mainly
435 /// in response to keyboard modifier changes during the drag-and-drop
436 /// operation.
437 ///
438 /// The most recent action received is always the valid one. Prior to
439 /// receiving wl_data_device.drop, the chosen action may change (e.g.
440 /// due to keyboard modifiers being pressed). At the time of receiving
441 /// wl_data_device.drop the drag-and-drop destination must honor the
442 /// last action received.
443 ///
444 /// Action changes may still happen after wl_data_device.drop,
445 /// especially on "ask" actions, where the drag-and-drop destination
446 /// may choose another action afterwards. Action changes happening
447 /// at this stage are always the result of inter-client negotiation, the
448 /// compositor shall no longer be able to induce a different action.
449 ///
450 /// Upon "ask" actions, it is expected that the drag-and-drop destination
451 /// may potentially choose a different action and/or mime type,
452 /// based on wl_data_offer.source_actions and finally chosen by the
453 /// user (e.g. popping up a menu with the available options). The
454 /// final wl_data_offer.set_actions and wl_data_offer.accept requests
455 /// must happen before the call to wl_data_offer.finish.
456 ///
457 /// # Arguments
458 ///
459 /// - `dnd_action`: action selected by the compositor
460 #[inline]
461 fn action(&self, _slf: &WlDataOfferRef, dnd_action: WlDataDeviceManagerDndAction) {
462 let _ = dnd_action;
463 }
464}
465
466impl WlDataOfferEventHandler for private::NoOpEventHandler {}
467
468// SAFETY: INTERFACE is a valid wl_interface
469unsafe impl<H> EventHandler for private::EventHandler<H>
470where
471 H: WlDataOfferEventHandler,
472{
473 const WL_INTERFACE: &'static wl_interface = &INTERFACE;
474
475 #[allow(unused_variables)]
476 unsafe fn handle_event(
477 &self,
478 queue: &Queue,
479 slf: &UntypedBorrowedProxy,
480 opcode: u32,
481 args: *mut wl_argument,
482 ) {
483 // SAFETY: This function required that slf has the interface INTERFACE
484 let slf = unsafe { proxy::low_level::from_untyped_borrowed::<WlDataOfferRef>(slf) };
485 match opcode {
486 0 => {
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 string
490 // - if the pointer is not null, then it is a c string
491 let arg0 = unsafe { convert_string_arg("wl_data_offer", "mime_type", args[0].s) };
492 self.0.offer(slf, arg0);
493 }
494 1 => {
495 // SAFETY: INTERFACE requires that there are 1 arguments
496 let args = unsafe { &*args.cast::<[wl_argument; 1]>() };
497 // SAFETY: - INTERFACE requires that args[0] contains a uint
498 let arg0 = unsafe { WlDataDeviceManagerDndAction(args[0].u) };
499 self.0.source_actions(slf, arg0);
500 }
501 2 => {
502 // SAFETY: INTERFACE requires that there are 1 arguments
503 let args = unsafe { &*args.cast::<[wl_argument; 1]>() };
504 // SAFETY: - INTERFACE requires that args[0] contains a uint
505 let arg0 = unsafe { WlDataDeviceManagerDndAction(args[0].u) };
506 self.0.action(slf, arg0);
507 }
508 _ => {
509 invalid_opcode("wl_data_offer", opcode);
510 }
511 }
512 }
513}
514
515impl<H> CreateEventHandler<H> for private::ProxyApi
516where
517 H: WlDataOfferEventHandler,
518{
519 type EventHandler = private::EventHandler<H>;
520
521 #[inline]
522 fn create_event_handler(handler: H) -> Self::EventHandler {
523 private::EventHandler(handler)
524 }
525}
526
527impl WlDataOffer {
528 /// Since when the error.invalid_finish enum variant is available.
529 #[allow(dead_code)]
530 pub const ENM__ERROR_INVALID_FINISH__SINCE: u32 = 1;
531 /// Since when the error.invalid_action_mask enum variant is available.
532 #[allow(dead_code)]
533 pub const ENM__ERROR_INVALID_ACTION_MASK__SINCE: u32 = 1;
534 /// Since when the error.invalid_action enum variant is available.
535 #[allow(dead_code)]
536 pub const ENM__ERROR_INVALID_ACTION__SINCE: u32 = 1;
537 /// Since when the error.invalid_offer enum variant is available.
538 #[allow(dead_code)]
539 pub const ENM__ERROR_INVALID_OFFER__SINCE: u32 = 1;
540}
541
542#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
543#[allow(dead_code)]
544pub struct WlDataOfferError(pub u32);
545
546impl WlDataOfferError {
547 /// finish request was called untimely
548 #[allow(dead_code)]
549 pub const INVALID_FINISH: Self = Self(0);
550
551 /// action mask contains invalid values
552 #[allow(dead_code)]
553 pub const INVALID_ACTION_MASK: Self = Self(1);
554
555 /// action argument has an invalid value
556 #[allow(dead_code)]
557 pub const INVALID_ACTION: Self = Self(2);
558
559 /// offer doesn't accept this request
560 #[allow(dead_code)]
561 pub const INVALID_OFFER: Self = Self(3);
562}
563
564impl Debug for WlDataOfferError {
565 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
566 let name = match *self {
567 Self::INVALID_FINISH => "INVALID_FINISH",
568 Self::INVALID_ACTION_MASK => "INVALID_ACTION_MASK",
569 Self::INVALID_ACTION => "INVALID_ACTION",
570 Self::INVALID_OFFER => "INVALID_OFFER",
571 _ => return Debug::fmt(&self.0, f),
572 };
573 f.write_str(name)
574 }
575}
576
577/// Functional event handlers.
578pub mod event_handlers {
579 use super::*;
580
581 /// Event handler for offer events.
582 pub struct Offer<F>(F);
583 impl<F> WlDataOfferEventHandler for Offer<F>
584 where
585 F: Fn(&WlDataOfferRef, &str),
586 {
587 #[inline]
588 fn offer(&self, _slf: &WlDataOfferRef, mime_type: &str) {
589 self.0(_slf, mime_type)
590 }
591 }
592
593 /// Event handler for source_actions events.
594 pub struct SourceActions<F>(F);
595 impl<F> WlDataOfferEventHandler for SourceActions<F>
596 where
597 F: Fn(&WlDataOfferRef, WlDataDeviceManagerDndAction),
598 {
599 #[inline]
600 fn source_actions(
601 &self,
602 _slf: &WlDataOfferRef,
603 source_actions: WlDataDeviceManagerDndAction,
604 ) {
605 self.0(_slf, source_actions)
606 }
607 }
608
609 /// Event handler for action events.
610 pub struct Action<F>(F);
611 impl<F> WlDataOfferEventHandler for Action<F>
612 where
613 F: Fn(&WlDataOfferRef, WlDataDeviceManagerDndAction),
614 {
615 #[inline]
616 fn action(&self, _slf: &WlDataOfferRef, dnd_action: WlDataDeviceManagerDndAction) {
617 self.0(_slf, dnd_action)
618 }
619 }
620
621 impl WlDataOffer {
622 /// Creates an event handler for offer events.
623 ///
624 /// The event handler ignores all other events.
625 #[allow(dead_code)]
626 pub fn on_offer<F>(f: F) -> Offer<F>
627 where
628 F: Fn(&WlDataOfferRef, &str),
629 {
630 Offer(f)
631 }
632
633 /// Creates an event handler for source_actions events.
634 ///
635 /// The event handler ignores all other events.
636 #[allow(dead_code)]
637 pub fn on_source_actions<F>(f: F) -> SourceActions<F>
638 where
639 F: Fn(&WlDataOfferRef, WlDataDeviceManagerDndAction),
640 {
641 SourceActions(f)
642 }
643
644 /// Creates an event handler for action events.
645 ///
646 /// The event handler ignores all other events.
647 #[allow(dead_code)]
648 pub fn on_action<F>(f: F) -> Action<F>
649 where
650 F: Fn(&WlDataOfferRef, WlDataDeviceManagerDndAction),
651 {
652 Action(f)
653 }
654 }
655}