simple_window/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 data: *mut u8,
480 slf: &UntypedBorrowedProxy,
481 opcode: u32,
482 args: *mut wl_argument,
483 ) {
484 // SAFETY: This function requires that slf has the interface INTERFACE
485 let slf = unsafe { proxy::low_level::from_untyped_borrowed::<WlDataOfferRef>(slf) };
486 match opcode {
487 0 => {
488 // SAFETY: INTERFACE requires that there are 1 arguments
489 let args = unsafe { &*args.cast::<[wl_argument; 1]>() };
490 // SAFETY: - INTERFACE requires that args[0] contains a string
491 // - if the pointer is not null, then it is a c string
492 let arg0 = unsafe { convert_string_arg("wl_data_offer", "mime_type", args[0].s) };
493 self.0.offer(slf, arg0);
494 }
495 1 => {
496 // SAFETY: INTERFACE requires that there are 1 arguments
497 let args = unsafe { &*args.cast::<[wl_argument; 1]>() };
498 // SAFETY: - INTERFACE requires that args[0] contains a uint
499 let arg0 = unsafe { WlDataDeviceManagerDndAction(args[0].u) };
500 self.0.source_actions(slf, arg0);
501 }
502 2 => {
503 // SAFETY: INTERFACE requires that there are 1 arguments
504 let args = unsafe { &*args.cast::<[wl_argument; 1]>() };
505 // SAFETY: - INTERFACE requires that args[0] contains a uint
506 let arg0 = unsafe { WlDataDeviceManagerDndAction(args[0].u) };
507 self.0.action(slf, arg0);
508 }
509 _ => {
510 invalid_opcode("wl_data_offer", opcode);
511 }
512 }
513 }
514}
515
516impl<H> CreateEventHandler<H> for private::ProxyApi
517where
518 H: WlDataOfferEventHandler,
519{
520 type EventHandler = private::EventHandler<H>;
521
522 #[inline]
523 fn create_event_handler(handler: H) -> Self::EventHandler {
524 private::EventHandler(handler)
525 }
526}
527
528impl WlDataOffer {
529 /// Since when the error.invalid_finish enum variant is available.
530 #[allow(dead_code)]
531 pub const ENM__ERROR_INVALID_FINISH__SINCE: u32 = 1;
532 /// Since when the error.invalid_action_mask enum variant is available.
533 #[allow(dead_code)]
534 pub const ENM__ERROR_INVALID_ACTION_MASK__SINCE: u32 = 1;
535 /// Since when the error.invalid_action enum variant is available.
536 #[allow(dead_code)]
537 pub const ENM__ERROR_INVALID_ACTION__SINCE: u32 = 1;
538 /// Since when the error.invalid_offer enum variant is available.
539 #[allow(dead_code)]
540 pub const ENM__ERROR_INVALID_OFFER__SINCE: u32 = 1;
541}
542
543#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
544#[allow(dead_code)]
545pub struct WlDataOfferError(pub u32);
546
547impl WlDataOfferError {
548 /// finish request was called untimely
549 #[allow(dead_code)]
550 pub const INVALID_FINISH: Self = Self(0);
551
552 /// action mask contains invalid values
553 #[allow(dead_code)]
554 pub const INVALID_ACTION_MASK: Self = Self(1);
555
556 /// action argument has an invalid value
557 #[allow(dead_code)]
558 pub const INVALID_ACTION: Self = Self(2);
559
560 /// offer doesn't accept this request
561 #[allow(dead_code)]
562 pub const INVALID_OFFER: Self = Self(3);
563}
564
565impl Debug for WlDataOfferError {
566 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
567 let name = match *self {
568 Self::INVALID_FINISH => "INVALID_FINISH",
569 Self::INVALID_ACTION_MASK => "INVALID_ACTION_MASK",
570 Self::INVALID_ACTION => "INVALID_ACTION",
571 Self::INVALID_OFFER => "INVALID_OFFER",
572 _ => return Debug::fmt(&self.0, f),
573 };
574 f.write_str(name)
575 }
576}
577
578/// Functional event handlers.
579pub mod event_handlers {
580 use super::*;
581
582 /// Event handler for offer events.
583 pub struct Offer<F>(F);
584 impl<F> WlDataOfferEventHandler for Offer<F>
585 where
586 F: Fn(&WlDataOfferRef, &str),
587 {
588 #[inline]
589 fn offer(&self, _slf: &WlDataOfferRef, mime_type: &str) {
590 self.0(_slf, mime_type)
591 }
592 }
593
594 /// Event handler for source_actions events.
595 pub struct SourceActions<F>(F);
596 impl<F> WlDataOfferEventHandler for SourceActions<F>
597 where
598 F: Fn(&WlDataOfferRef, WlDataDeviceManagerDndAction),
599 {
600 #[inline]
601 fn source_actions(
602 &self,
603 _slf: &WlDataOfferRef,
604 source_actions: WlDataDeviceManagerDndAction,
605 ) {
606 self.0(_slf, source_actions)
607 }
608 }
609
610 /// Event handler for action events.
611 pub struct Action<F>(F);
612 impl<F> WlDataOfferEventHandler for Action<F>
613 where
614 F: Fn(&WlDataOfferRef, WlDataDeviceManagerDndAction),
615 {
616 #[inline]
617 fn action(&self, _slf: &WlDataOfferRef, dnd_action: WlDataDeviceManagerDndAction) {
618 self.0(_slf, dnd_action)
619 }
620 }
621
622 impl WlDataOffer {
623 /// Creates an event handler for offer events.
624 ///
625 /// The event handler ignores all other events.
626 #[allow(dead_code)]
627 pub fn on_offer<F>(f: F) -> Offer<F>
628 where
629 F: Fn(&WlDataOfferRef, &str),
630 {
631 Offer(f)
632 }
633
634 /// Creates an event handler for source_actions events.
635 ///
636 /// The event handler ignores all other events.
637 #[allow(dead_code)]
638 pub fn on_source_actions<F>(f: F) -> SourceActions<F>
639 where
640 F: Fn(&WlDataOfferRef, WlDataDeviceManagerDndAction),
641 {
642 SourceActions(f)
643 }
644
645 /// Creates an event handler for action events.
646 ///
647 /// The event handler ignores all other events.
648 #[allow(dead_code)]
649 pub fn on_action<F>(f: F) -> Action<F>
650 where
651 F: Fn(&WlDataOfferRef, WlDataDeviceManagerDndAction),
652 {
653 Action(f)
654 }
655 }
656}