1 //! Client-side implementation of a Wayland protocol backend using `libwayland`
2 
3 use std::{
4     cell::RefCell,
5     ffi::CStr,
6     os::raw::{c_char, c_int, c_void},
7     os::unix::{io::RawFd, net::UnixStream, prelude::IntoRawFd},
8     sync::{
9         atomic::{AtomicBool, Ordering},
10         Arc, Mutex,
11     },
12 };
13 
14 use crate::{
15     core_interfaces::WL_DISPLAY_INTERFACE,
16     protocol::{
17         check_for_signature, same_interface, AllowNull, Argument, ArgumentType, Interface, Message,
18         ObjectInfo, ProtocolError, ANONYMOUS_INTERFACE,
19     },
20 };
21 use scoped_tls::scoped_thread_local;
22 use smallvec::SmallVec;
23 
24 use wayland_sys::{client::*, common::*, ffi_dispatch};
25 
26 pub use crate::types::client::{InvalidId, NoWaylandLib, WaylandError};
27 
28 use super::{free_arrays, RUST_MANAGED};
29 
30 scoped_thread_local!(static HANDLE: RefCell<&mut Handle>);
31 
32 /// A trait representing your data associated to an object
33 ///
34 /// You will only be given access to it as a `&` reference, so you
35 /// need to handle interior mutability by yourself.
36 ///
37 /// The methods of this trait will be invoked internally every time a
38 /// new object is created to initialize its data.
39 pub trait ObjectData: downcast_rs::DowncastSync {
40     /// Dispatch an event for the associated object
41     ///
42     /// If the event has a NewId argument, the callback must return the object data
43     /// for the newly created object
event( self: Arc<Self>, handle: &mut Handle, msg: Message<ObjectId>, ) -> Option<Arc<dyn ObjectData>>44     fn event(
45         self: Arc<Self>,
46         handle: &mut Handle,
47         msg: Message<ObjectId>,
48     ) -> Option<Arc<dyn ObjectData>>;
49     /// Notification that the object has been destroyed and is no longer active
destroyed(&self, object_id: ObjectId)50     fn destroyed(&self, object_id: ObjectId);
51     /// Helper for forwarding a Debug implementation of your `ObjectData` type
52     ///
53     /// By default will just print `ObjectData { ... }`
debug(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result54     fn debug(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
55         f.debug_struct("ObjectData").finish_non_exhaustive()
56     }
57 }
58 
59 #[cfg(not(tarpaulin_include))]
60 impl std::fmt::Debug for dyn ObjectData {
fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result61     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
62         self.debug(f)
63     }
64 }
65 
66 downcast_rs::impl_downcast!(sync ObjectData);
67 
68 /// An ID representing a Wayland object
69 #[derive(Clone)]
70 pub struct ObjectId {
71     id: u32,
72     ptr: *mut wl_proxy,
73     alive: Option<Arc<AtomicBool>>,
74     interface: &'static Interface,
75 }
76 
77 unsafe impl Send for ObjectId {}
78 unsafe impl Sync for ObjectId {}
79 
80 impl std::cmp::PartialEq for ObjectId {
eq(&self, other: &ObjectId) -> bool81     fn eq(&self, other: &ObjectId) -> bool {
82         match (&self.alive, &other.alive) {
83             (Some(ref a), Some(ref b)) => {
84                 // this is an object we manage
85                 Arc::ptr_eq(a, b)
86             }
87             (None, None) => {
88                 // this is an external (un-managed) object
89                 self.ptr == other.ptr
90                     && self.id == other.id
91                     && same_interface(self.interface, other.interface)
92             }
93             _ => false,
94         }
95     }
96 }
97 
98 impl std::cmp::Eq for ObjectId {}
99 
100 impl ObjectId {
101     /// Check if this is the null ID
is_null(&self) -> bool102     pub fn is_null(&self) -> bool {
103         self.ptr.is_null()
104     }
105 
106     /// Interface of the represented object
interface(&self) -> &'static Interface107     pub fn interface(&self) -> &'static Interface {
108         self.interface
109     }
110 
111     /// Return the protocol-level numerical ID of this object
112     ///
113     /// Protocol IDs are reused after object destruction, so this should not be used as a
114     /// unique identifier,
protocol_id(&self) -> u32115     pub fn protocol_id(&self) -> u32 {
116         self.id
117     }
118 
119     /// Creates an object id from a libwayland-client pointer.
120     ///
121     /// # Errors
122     ///
123     /// This function returns an [`InvalidId`] error if the interface of the proxy does not match the provided
124     /// interface.
125     ///
126     /// # Safety
127     ///
128     /// The provided pointer must be a valid pointer to a `wl_resource` and remain valid for as
129     /// long as the retrieved `ObjectId` is used.
from_ptr( interface: &'static Interface, ptr: *mut wl_proxy, ) -> Result<ObjectId, InvalidId>130     pub unsafe fn from_ptr(
131         interface: &'static Interface,
132         ptr: *mut wl_proxy,
133     ) -> Result<ObjectId, InvalidId> {
134         let ptr_iface_name =
135             CStr::from_ptr(ffi_dispatch!(WAYLAND_CLIENT_HANDLE, wl_proxy_get_class, ptr));
136         let provided_iface_name = CStr::from_ptr(
137             interface
138                 .c_ptr
139                 .expect("[wayland-backend-sys] Cannot use Interface without c_ptr!")
140                 .name,
141         );
142         if ptr_iface_name != provided_iface_name {
143             return Err(InvalidId);
144         }
145 
146         let id = ffi_dispatch!(WAYLAND_CLIENT_HANDLE, wl_proxy_get_id, ptr);
147 
148         // Test if the proxy is managed by us.
149         let is_rust_managed = ffi_dispatch!(WAYLAND_CLIENT_HANDLE, wl_proxy_get_listener, ptr)
150             == &RUST_MANAGED as *const u8 as *const _;
151 
152         let alive = if is_rust_managed {
153             let udata = &*(ffi_dispatch!(WAYLAND_CLIENT_HANDLE, wl_proxy_get_user_data, ptr)
154                 as *mut ProxyUserData);
155             Some(udata.alive.clone())
156         } else {
157             None
158         };
159 
160         Ok(ObjectId { id, ptr, alive, interface })
161     }
162 
163     /// Get the underlying libwayland pointer for this object
as_ptr(&self) -> *mut wl_proxy164     pub fn as_ptr(&self) -> *mut wl_proxy {
165         if self.alive.as_ref().map(|alive| alive.load(Ordering::Acquire)).unwrap_or(true) {
166             self.ptr
167         } else {
168             std::ptr::null_mut()
169         }
170     }
171 }
172 
173 #[cfg(not(tarpaulin_include))]
174 impl std::fmt::Display for ObjectId {
fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result175     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
176         write!(f, "{}@{}", self.interface.name, self.id)
177     }
178 }
179 
180 #[cfg(not(tarpaulin_include))]
181 impl std::fmt::Debug for ObjectId {
fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result182     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
183         write!(f, "ObjectId({})", self)
184     }
185 }
186 
187 struct ProxyUserData {
188     alive: Arc<AtomicBool>,
189     data: Arc<dyn ObjectData>,
190     interface: &'static Interface,
191 }
192 
193 /// Main handle of a backend to the Wayland protocol
194 ///
195 /// This type hosts most of the protocol-related functionality of the backend, and is the
196 /// main entry point for manipulating Wayland objects. It can be retrieved both from
197 /// the backend via [`Backend::handle()`](Backend::handle), and is given to you as argument
198 /// in most event callbacks.
199 #[derive(Debug)]
200 pub struct Handle {
201     display: *mut wl_display,
202     evq: *mut wl_event_queue,
203     display_id: ObjectId,
204     last_error: Option<WaylandError>,
205     pending_placeholder: Option<(&'static Interface, u32)>,
206 }
207 
208 /// A pure rust implementation of a Wayland client backend
209 ///
210 /// This type hosts the plumbing functionalities for interacting with the wayland protocol,
211 /// and most of the protocol-level interactions are made through the [`Handle`] type, accessed
212 /// via the [`handle()`](Backend::handle) method.
213 #[derive(Debug)]
214 pub struct Backend {
215     handle: Handle,
216 }
217 
218 unsafe impl Send for Backend {}
219 unsafe impl Sync for Backend {}
220 
221 impl Backend {
222     /// Try to initialize a Wayland backend on the provided unix stream
223     ///
224     /// The provided stream should correspond to an already established unix connection with
225     /// the Wayland server. This function fails if the system `libwayland` could not be loaded.
connect(stream: UnixStream) -> Result<Self, NoWaylandLib>226     pub fn connect(stream: UnixStream) -> Result<Self, NoWaylandLib> {
227         if !is_lib_available() {
228             return Err(NoWaylandLib);
229         }
230         let display = unsafe {
231             ffi_dispatch!(WAYLAND_CLIENT_HANDLE, wl_display_connect_to_fd, stream.into_raw_fd())
232         };
233         if display.is_null() {
234             panic!("[wayland-backend-sys] libwayland reported an allocation failure.");
235         }
236         // set the log trampoline
237         unsafe {
238             ffi_dispatch!(
239                 WAYLAND_CLIENT_HANDLE,
240                 wl_log_set_handler_client,
241                 wl_log_trampoline_to_rust_client
242             );
243         }
244         let display_alive = Arc::new(AtomicBool::new(true));
245         Ok(Self {
246             handle: Handle {
247                 display,
248                 evq: std::ptr::null_mut(),
249                 display_id: ObjectId {
250                     id: 1,
251                     ptr: display as *mut wl_proxy,
252                     alive: Some(display_alive),
253                     interface: &WL_DISPLAY_INTERFACE,
254                 },
255                 last_error: None,
256                 pending_placeholder: None,
257             },
258         })
259     }
260 
261     /// Flush all pending outgoing requests to the server
flush(&mut self) -> Result<(), WaylandError>262     pub fn flush(&mut self) -> Result<(), WaylandError> {
263         self.handle.no_last_error()?;
264         let ret =
265             unsafe { ffi_dispatch!(WAYLAND_CLIENT_HANDLE, wl_display_flush, self.handle.display) };
266         if ret < 0 {
267             Err(self
268                 .handle
269                 .store_if_not_wouldblock_and_return_error(std::io::Error::last_os_error()))
270         } else {
271             Ok(())
272         }
273     }
274 
275     /// Read events from the wayland socket if available, and invoke the associated callbacks
276     ///
277     /// This function will never block, and returns an I/O `WouldBlock` error if no event is available
278     /// to read.
279     ///
280     /// **Note:** this function should only be used if you know that you are the only thread
281     /// reading events from the wayland socket. If this may not be the case, see [`ReadEventsGuard`]
dispatch_events(&mut self) -> Result<usize, WaylandError>282     pub fn dispatch_events(&mut self) -> Result<usize, WaylandError> {
283         self.handle.no_last_error()?;
284         self.handle.try_read()?;
285         self.handle.dispatch_pending()
286     }
287 
288     /// Access the [`Handle`] associated with this backend
handle(&mut self) -> &mut Handle289     pub fn handle(&mut self) -> &mut Handle {
290         &mut self.handle
291     }
292 }
293 
294 impl Handle {
295     #[inline]
no_last_error(&self) -> Result<(), WaylandError>296     fn no_last_error(&self) -> Result<(), WaylandError> {
297         if let Some(ref err) = self.last_error {
298             Err(err.clone())
299         } else {
300             Ok(())
301         }
302     }
303 
304     #[inline]
store_and_return_error(&mut self, err: std::io::Error) -> WaylandError305     fn store_and_return_error(&mut self, err: std::io::Error) -> WaylandError {
306         // check if it was actually a protocol error
307         let err = if err.raw_os_error() == Some(nix::errno::Errno::EPROTO as i32) {
308             let mut object_id = 0;
309             let mut interface = std::ptr::null();
310             let code = unsafe {
311                 ffi_dispatch!(
312                     WAYLAND_CLIENT_HANDLE,
313                     wl_display_get_protocol_error,
314                     self.display,
315                     &mut interface,
316                     &mut object_id
317                 )
318             };
319             let object_interface = unsafe {
320                 if interface.is_null() {
321                     String::new()
322                 } else {
323                     let cstr = std::ffi::CStr::from_ptr((*interface).name);
324                     cstr.to_string_lossy().into()
325                 }
326             };
327             WaylandError::Protocol(ProtocolError {
328                 code,
329                 object_id,
330                 object_interface,
331                 message: String::new(),
332             })
333         } else {
334             WaylandError::Io(err)
335         };
336         log::error!("{}", err);
337         self.last_error = Some(err.clone());
338         err
339     }
340 
341     #[inline]
store_if_not_wouldblock_and_return_error(&mut self, e: std::io::Error) -> WaylandError342     fn store_if_not_wouldblock_and_return_error(&mut self, e: std::io::Error) -> WaylandError {
343         if e.kind() != std::io::ErrorKind::WouldBlock {
344             self.store_and_return_error(e)
345         } else {
346             e.into()
347         }
348     }
349 
dispatch_pending(&mut self) -> Result<usize, WaylandError>350     fn dispatch_pending(&mut self) -> Result<usize, WaylandError> {
351         let display = self.display;
352         let evq = self.evq;
353 
354         // We erase the lifetime of the Handle to be able to store it in the tls,
355         // it's safe as it'll only last until the end of this function call anyway
356         let ret =
357             HANDLE.set(&RefCell::new(unsafe { std::mem::transmute(&mut *self) }), || unsafe {
358                 if evq.is_null() {
359                     ffi_dispatch!(WAYLAND_CLIENT_HANDLE, wl_display_dispatch_pending, display)
360                 } else {
361                     ffi_dispatch!(
362                         WAYLAND_CLIENT_HANDLE,
363                         wl_display_dispatch_queue_pending,
364                         display,
365                         evq
366                     )
367                 }
368             });
369         if ret < 0 {
370             Err(self.store_if_not_wouldblock_and_return_error(std::io::Error::last_os_error()))
371         } else {
372             Ok(ret as usize)
373         }
374     }
375 
try_read(&mut self) -> Result<(), WaylandError>376     fn try_read(&mut self) -> Result<(), WaylandError> {
377         let ret = unsafe {
378             if self.evq.is_null() {
379                 ffi_dispatch!(WAYLAND_CLIENT_HANDLE, wl_display_prepare_read, self.display)
380             } else {
381                 ffi_dispatch!(
382                     WAYLAND_CLIENT_HANDLE,
383                     wl_display_prepare_read_queue,
384                     self.display,
385                     self.evq
386                 )
387             }
388         };
389         if ret < 0 {
390             return Ok(());
391         }
392         let ret =
393             unsafe { ffi_dispatch!(WAYLAND_CLIENT_HANDLE, wl_display_read_events, self.display) };
394         if ret < 0 {
395             Err(self.store_if_not_wouldblock_and_return_error(std::io::Error::last_os_error()))
396         } else {
397             Ok(())
398         }
399     }
400 }
401 
402 /// Guard for synchronizing event reading across multiple threads
403 ///
404 /// If multiple threads need to read events from the Wayland socket concurrently,
405 /// it is necessary to synchronize their access. Failing to do so may cause some of the
406 /// threads to not be notified of new events, and sleep much longer than appropriate.
407 ///
408 /// To correctly synchronize access, this type should be used. The guard is created using
409 /// the [`try_new()`](ReadEventsGuard::try_new) method. And the event reading is triggered by consuming
410 /// the guard using the [`read()`](ReadEventsGuard::read) method.
411 ///
412 /// If you plan to poll the Wayland socket for readiness, the file descriptor can be retrieved via
413 /// the [`connection_fd`](ReadEventsGuard::connection_fd) method. Note that for the synchronization to
414 /// correctly occur, you must *always* create the `ReadEventsGuard` *before* polling the socket.
415 ///
416 /// This synchronization is compatible with the "prepare_read" mechanism of the system libwayland,
417 /// and will correctly synchronize with other C libraries using the same Wayland socket.
418 #[derive(Debug)]
419 pub struct ReadEventsGuard {
420     backend: Arc<Mutex<Backend>>,
421     display: *mut wl_display,
422     done: bool,
423 }
424 
425 impl ReadEventsGuard {
426     /// Create a new reading guard
427     ///
428     /// This call will not block, but event callbacks may be invoked in the process
429     /// of preparing the guard.
try_new(backend: Arc<Mutex<Backend>>) -> Result<Self, WaylandError>430     pub fn try_new(backend: Arc<Mutex<Backend>>) -> Result<Self, WaylandError> {
431         let mut backend_guard = backend.lock().unwrap();
432         let display = backend_guard.handle.display;
433         let evq = backend_guard.handle.evq;
434 
435         // do the prepare_read() and dispatch as necessary
436         loop {
437             let ret = unsafe {
438                 if evq.is_null() {
439                     ffi_dispatch!(WAYLAND_CLIENT_HANDLE, wl_display_prepare_read, display)
440                 } else {
441                     ffi_dispatch!(
442                         WAYLAND_CLIENT_HANDLE,
443                         wl_display_prepare_read_queue,
444                         display,
445                         evq
446                     )
447                 }
448             };
449             if ret < 0 {
450                 backend_guard.handle.dispatch_pending()?;
451             } else {
452                 break;
453             }
454         }
455 
456         std::mem::drop(backend_guard);
457 
458         // prepare_read is done, we are ready
459         Ok(ReadEventsGuard { backend, display, done: false })
460     }
461 
462     /// Access the Wayland socket FD for polling
connection_fd(&self) -> RawFd463     pub fn connection_fd(&self) -> RawFd {
464         unsafe { ffi_dispatch!(WAYLAND_CLIENT_HANDLE, wl_display_get_fd, self.display) }
465     }
466 
467     /// Attempt to read events from the Wayland socket
468     ///
469     /// If multiple threads have a live reading guard, this method will block until all of them
470     /// are either dropped or have their `read()` method invoked, at which point on of the threads
471     /// will read events from the socket and invoke the callbacks for the received events. All
472     /// threads will then resume their execution.
473     ///
474     /// This returns the number of dispatched events, or `0` if an other thread handled the dispatching.
475     /// If no events are available to read from the socket, this returns a `WouldBlock` IO error.
read(mut self) -> Result<usize, WaylandError>476     pub fn read(mut self) -> Result<usize, WaylandError> {
477         self.done = true;
478         let ret =
479             unsafe { ffi_dispatch!(WAYLAND_CLIENT_HANDLE, wl_display_read_events, self.display) };
480         if ret < 0 {
481             // we have done the reading, and there is an error
482             Err(self
483                 .backend
484                 .lock()
485                 .unwrap()
486                 .handle
487                 .store_if_not_wouldblock_and_return_error(std::io::Error::last_os_error()))
488         } else {
489             // the read occured, dispatch pending events
490             self.backend.lock().unwrap().handle.dispatch_pending()
491         }
492     }
493 }
494 
495 impl Drop for ReadEventsGuard {
drop(&mut self)496     fn drop(&mut self) {
497         if !self.done {
498             unsafe {
499                 ffi_dispatch!(WAYLAND_CLIENT_HANDLE, wl_display_cancel_read, self.display);
500             }
501         }
502     }
503 }
504 
505 impl Handle {
506     /// Get the object ID for the `wl_display`
display_id(&self) -> ObjectId507     pub fn display_id(&self) -> ObjectId {
508         self.display_id.clone()
509     }
510 
511     /// Get the last error that occurred on this backend
512     ///
513     /// If this returns an error, your Wayland connection is already dead.
last_error(&self) -> Option<WaylandError>514     pub fn last_error(&self) -> Option<WaylandError> {
515         self.last_error.clone()
516     }
517 
518     /// Get the detailed information about a wayland object
519     ///
520     /// Returns an error if the provided object ID is no longer valid.
info(&self, id: ObjectId) -> Result<ObjectInfo, InvalidId>521     pub fn info(&self, id: ObjectId) -> Result<ObjectInfo, InvalidId> {
522         if !id.alive.as_ref().map(|a| a.load(Ordering::Acquire)).unwrap_or(true) || id.ptr.is_null()
523         {
524             return Err(InvalidId);
525         }
526 
527         let version = if id.id == 1 {
528             // special case the display, because libwayland returns a version of 0 for it
529             1
530         } else {
531             unsafe { ffi_dispatch!(WAYLAND_CLIENT_HANDLE, wl_proxy_get_version, id.ptr) }
532         };
533 
534         Ok(ObjectInfo { id: id.id, interface: id.interface, version })
535     }
536 
537     /// Create a null object ID
538     ///
539     /// This object ID is always invalid, and can be used as placeholder.
null_id(&mut self) -> ObjectId540     pub fn null_id(&mut self) -> ObjectId {
541         ObjectId { ptr: std::ptr::null_mut(), interface: &ANONYMOUS_INTERFACE, id: 0, alive: None }
542     }
543 
544     /// Create a placeholder ID for object creation
545     ///
546     /// This ID needs to be created beforehand and given as argument to a request creating a
547     /// new object ID. A specification must be specified if the interface and version cannot
548     /// be inferred from the protocol (for example object creation from the `wl_registry`).
549     ///
550     /// If a specification is provided it'll be checked against what can be deduced from the
551     /// protocol specification, and [`send_request`](Handle::send_request) will panic if they
552     /// do not match.
placeholder_id(&mut self, spec: Option<(&'static Interface, u32)>) -> ObjectId553     pub fn placeholder_id(&mut self, spec: Option<(&'static Interface, u32)>) -> ObjectId {
554         self.pending_placeholder = spec;
555         ObjectId {
556             ptr: std::ptr::null_mut(),
557             alive: None,
558             id: 0,
559             interface: spec.map(|(iface, _)| iface).unwrap_or(&ANONYMOUS_INTERFACE),
560         }
561     }
562 
563     /// Sends a request to the server
564     ///
565     /// Returns an error if the sender ID of the provided message is no longer valid.
566     ///
567     /// **Panic:**
568     ///
569     /// Several checks against the protocol specification are done, and this method will panic if they do
570     /// not pass:
571     ///
572     /// - the message opcode must be valid for the sender interface
573     /// - the argument list must match the prototype for the message associated with this opcode
574     /// - if the method creates a new object, a [`placeholder_id()`](Handle::placeholder_id) must be given
575     ///   in the argument list, either without a specification, or with a specification that matches the
576     ///   interface and version deduced from the protocol rules
577     ///
578     /// When using the system libwayland backend, the Wayland interfaces must have been generated with the C-ptr
579     /// support.
580     pub fn send_request(
581         &mut self,
582         Message { sender_id: id, opcode, args }: Message<ObjectId>,
583         data: Option<Arc<dyn ObjectData>>,
584     ) -> Result<ObjectId, InvalidId> {
585         if !id.alive.as_ref().map(|a| a.load(Ordering::Acquire)).unwrap_or(true) || id.ptr.is_null()
586         {
587             return Err(InvalidId);
588         }
589         let parent_version = if id.id == 1 {
590             1
591         } else {
592             unsafe { ffi_dispatch!(WAYLAND_CLIENT_HANDLE, wl_proxy_get_version, id.ptr) }
593         };
594         // check that the argument list is valid
595         let message_desc = match id.interface.requests.get(opcode as usize) {
596             Some(msg) => msg,
597             None => {
598                 panic!("Unknown opcode {} for object {}@{}.", opcode, id.interface.name, id.id);
599             }
600         };
601         if !check_for_signature(message_desc.signature, &args) {
602             panic!(
603                 "Unexpected signature for request {}@{}.{}: expected {:?}, got {:?}.",
604                 id.interface.name, id.id, message_desc.name, message_desc.signature, args
605             );
606         }
607 
608         // Prepare the child object data
609         let child_spec = if message_desc
610             .signature
611             .iter()
612             .any(|arg| matches!(arg, ArgumentType::NewId(_)))
613         {
614             if let Some((iface, version)) = self.pending_placeholder.take() {
615                 if let Some(child_interface) = message_desc.child_interface {
616                     if !same_interface(child_interface, iface) {
617                         panic!(
618                             "Wrong placeholder used when sending request {}@{}.{}: expected interface {} but got {}",
619                             id.interface.name,
620                             id.id,
621                             message_desc.name,
622                             child_interface.name,
623                             iface.name
624                         );
625                     }
626                     if version != parent_version {
627                         panic!(
628                             "Wrong placeholder used when sending request {}@{}.{}: expected version {} but got {}",
629                             id.interface.name,
630                             id.id,
631                             message_desc.name,
632                             parent_version,
633                             version
634                         );
635                     }
636                 }
637                 Some((iface, version))
638             } else if let Some(child_interface) = message_desc.child_interface {
639                 Some((child_interface, parent_version))
640             } else {
641                 panic!(
642                     "Wrong placeholder used when sending request {}@{}.{}: target interface must be specified for a generic constructor.",
643                     id.interface.name,
644                     id.id,
645                     message_desc.name
646                 );
647             }
648         } else {
649             None
650         };
651 
652         let child_interface_ptr = child_spec
653             .as_ref()
654             .map(|(i, _)| {
655                 i.c_ptr.expect("[wayland-backend-sys] Cannot use Interface without c_ptr!")
656                     as *const _
657             })
658             .unwrap_or(std::ptr::null());
659         let child_version = child_spec.as_ref().map(|(_, v)| *v).unwrap_or(parent_version);
660 
661         // check that all input objects are valid and create the [wl_argument]
662         let mut argument_list = SmallVec::<[wl_argument; 4]>::with_capacity(args.len());
663         let mut arg_interfaces = message_desc.arg_interfaces.iter();
664         for (i, arg) in args.iter().enumerate() {
665             match *arg {
666                 Argument::Uint(u) => argument_list.push(wl_argument { u }),
667                 Argument::Int(i) => argument_list.push(wl_argument { i }),
668                 Argument::Fixed(f) => argument_list.push(wl_argument { f }),
669                 Argument::Fd(h) => argument_list.push(wl_argument { h }),
670                 Argument::Array(ref a) => {
671                     let a = Box::new(wl_array {
672                         size: a.len(),
673                         alloc: a.len(),
674                         data: a.as_ptr() as *mut _,
675                     });
676                     argument_list.push(wl_argument { a: Box::into_raw(a) })
677                 }
678                 Argument::Str(ref s) => argument_list.push(wl_argument { s: s.as_ptr() }),
679                 Argument::Object(ref o) => {
680                     if !o.ptr.is_null() {
681                         if !id.alive.as_ref().map(|a| a.load(Ordering::Acquire)).unwrap_or(true) {
682                             unsafe { free_arrays(message_desc.signature, &argument_list) };
683                             return Err(InvalidId);
684                         }
685                         let next_interface = arg_interfaces.next().unwrap();
686                         if !same_interface(next_interface, o.interface) {
687                             panic!("Request {}@{}.{} expects an argument of interface {} but {} was provided instead.", id.interface.name, id.id, message_desc.name, next_interface.name, o.interface.name);
688                         }
689                     } else if !matches!(
690                         message_desc.signature[i],
691                         ArgumentType::Object(AllowNull::Yes)
692                     ) {
693                         panic!(
694                             "Request {}@{}.{} expects an non-null object argument.",
695                             id.interface.name, id.id, message_desc.name
696                         );
697                     }
698                     argument_list.push(wl_argument { o: o.ptr as *const _ })
699                 }
700                 Argument::NewId(_) => argument_list.push(wl_argument { n: 0 }),
701             }
702         }
703 
704         let ret = unsafe {
705             ffi_dispatch!(
706                 WAYLAND_CLIENT_HANDLE,
707                 wl_proxy_marshal_array_constructor_versioned,
708                 id.ptr,
709                 opcode as u32,
710                 argument_list.as_mut_ptr(),
711                 child_interface_ptr,
712                 child_version
713             )
714         };
715 
716         unsafe {
717             free_arrays(message_desc.signature, &argument_list);
718         }
719 
720         if ret.is_null() && child_spec.is_some() {
721             panic!("[wayland-backend-sys] libwayland reported an allocation failure.");
722         }
723 
724         // initialize the proxy
725         let child_id = if let Some((child_interface, _)) = child_spec {
726             let child_alive = Arc::new(AtomicBool::new(true));
727             let child_id = ObjectId {
728                 ptr: ret,
729                 alive: Some(child_alive.clone()),
730                 id: unsafe { ffi_dispatch!(WAYLAND_CLIENT_HANDLE, wl_proxy_get_id, ret) },
731                 interface: child_interface,
732             };
733             let child_udata = Box::new(ProxyUserData {
734                 alive: child_alive,
735                 data: data.expect(
736                     "Sending a request creating an object without providing an object data.",
737                 ),
738                 interface: child_interface,
739             });
740             unsafe {
741                 ffi_dispatch!(
742                     WAYLAND_CLIENT_HANDLE,
743                     wl_proxy_add_dispatcher,
744                     ret,
745                     dispatcher_func,
746                     &RUST_MANAGED as *const u8 as *const c_void,
747                     Box::into_raw(child_udata) as *mut c_void
748                 );
749             }
750             child_id
751         } else {
752             self.null_id()
753         };
754 
755         if message_desc.is_destructor {
756             if let Some(ref alive) = id.alive {
757                 let udata = unsafe {
758                     Box::from_raw(ffi_dispatch!(
759                         WAYLAND_CLIENT_HANDLE,
760                         wl_proxy_get_user_data,
761                         id.ptr
762                     ) as *mut ProxyUserData)
763                 };
764                 unsafe {
765                     ffi_dispatch!(
766                         WAYLAND_CLIENT_HANDLE,
767                         wl_proxy_set_user_data,
768                         id.ptr,
769                         std::ptr::null_mut()
770                     );
771                 }
772                 alive.store(false, Ordering::Release);
773                 udata.data.destroyed(id.clone());
774             }
775             unsafe {
776                 ffi_dispatch!(WAYLAND_CLIENT_HANDLE, wl_proxy_destroy, id.ptr);
777             }
778         }
779 
780         Ok(child_id)
781     }
782 
783     /// Access the object data associated with a given object ID
784     ///
785     /// Returns an error if the object ID is not longer valid or if it corresponds to a Wayland
786     /// object that is not managed by this backend (when multiple libraries share the same Wayland
787     /// socket via `libwayland`).
get_data(&self, id: ObjectId) -> Result<Arc<dyn ObjectData>, InvalidId>788     pub fn get_data(&self, id: ObjectId) -> Result<Arc<dyn ObjectData>, InvalidId> {
789         if !id.alive.as_ref().map(|a| a.load(Ordering::Acquire)).unwrap_or(false) {
790             return Err(InvalidId);
791         }
792 
793         if id.id == 1 {
794             // special case the display whose object data is not accessible
795             return Ok(Arc::new(DumbObjectData));
796         }
797 
798         let udata = unsafe {
799             &*(ffi_dispatch!(WAYLAND_CLIENT_HANDLE, wl_proxy_get_user_data, id.ptr)
800                 as *mut ProxyUserData)
801         };
802         Ok(udata.data.clone())
803     }
804 
805     /// Set the object data associated with a given object ID
806     ///
807     /// Returns an error if the object ID is not longer valid or if it corresponds to a Wayland
808     /// object that is not managed by this backend (when multiple libraries share the same Wayland
809     /// socket via `libwayland`).
set_data(&mut self, id: ObjectId, data: Arc<dyn ObjectData>) -> Result<(), InvalidId>810     pub fn set_data(&mut self, id: ObjectId, data: Arc<dyn ObjectData>) -> Result<(), InvalidId> {
811         if !id.alive.as_ref().map(|a| a.load(Ordering::Acquire)).unwrap_or(false) {
812             return Err(InvalidId);
813         }
814 
815         // Cannot touch the user_data of the display
816         if id.id == 1 {
817             return Err(InvalidId);
818         }
819 
820         let udata = unsafe {
821             &mut *(ffi_dispatch!(WAYLAND_CLIENT_HANDLE, wl_proxy_get_user_data, id.ptr)
822                 as *mut ProxyUserData)
823         };
824 
825         udata.data = data;
826 
827         Ok(())
828     }
829 }
830 
dispatcher_func( _: *const c_void, proxy: *mut c_void, opcode: u32, _: *const wl_message, args: *const wl_argument, ) -> c_int831 unsafe extern "C" fn dispatcher_func(
832     _: *const c_void,
833     proxy: *mut c_void,
834     opcode: u32,
835     _: *const wl_message,
836     args: *const wl_argument,
837 ) -> c_int {
838     let proxy = proxy as *mut wl_proxy;
839     let udata_ptr =
840         ffi_dispatch!(WAYLAND_CLIENT_HANDLE, wl_proxy_get_user_data, proxy) as *mut ProxyUserData;
841     let udata = &mut *udata_ptr;
842     let interface = udata.interface;
843     let message_desc = match interface.events.get(opcode as usize) {
844         Some(desc) => desc,
845         None => {
846             log::error!("Unknown event opcode {} for interface {}.", opcode, interface.name);
847             return -1;
848         }
849     };
850 
851     let mut parsed_args =
852         SmallVec::<[Argument<ObjectId>; 4]>::with_capacity(message_desc.signature.len());
853     let mut arg_interfaces = message_desc.arg_interfaces.iter().copied();
854     let mut created = None;
855     for (i, typ) in message_desc.signature.iter().enumerate() {
856         match typ {
857             ArgumentType::Uint => parsed_args.push(Argument::Uint((*args.add(i)).u)),
858             ArgumentType::Int => parsed_args.push(Argument::Int((*args.add(i)).i)),
859             ArgumentType::Fixed => parsed_args.push(Argument::Fixed((*args.add(i)).f)),
860             ArgumentType::Fd => parsed_args.push(Argument::Fd((*args.add(i)).h)),
861             ArgumentType::Array(_) => {
862                 let array = &*((*args.add(i)).a);
863                 let content = std::slice::from_raw_parts(array.data as *mut u8, array.size);
864                 parsed_args.push(Argument::Array(Box::new(content.into())));
865             }
866             ArgumentType::Str(_) => {
867                 let ptr = (*args.add(i)).s;
868                 let cstr = std::ffi::CStr::from_ptr(ptr);
869                 parsed_args.push(Argument::Str(Box::new(cstr.into())));
870             }
871             ArgumentType::Object(_) => {
872                 let obj = (*args.add(i)).o as *mut wl_proxy;
873                 if !obj.is_null() {
874                     // retrieve the object relevant info
875                     let obj_id = ffi_dispatch!(WAYLAND_CLIENT_HANDLE, wl_proxy_get_id, obj);
876                     // check if this is a local or distant proxy
877                     let next_interface = arg_interfaces.next().unwrap_or(&ANONYMOUS_INTERFACE);
878                     let listener = ffi_dispatch!(WAYLAND_CLIENT_HANDLE, wl_proxy_get_listener, obj);
879                     if listener == &RUST_MANAGED as *const u8 as *const c_void {
880                         let obj_udata =
881                             &*(ffi_dispatch!(WAYLAND_CLIENT_HANDLE, wl_proxy_get_user_data, obj)
882                                 as *mut ProxyUserData);
883                         if !same_interface(next_interface, obj_udata.interface) {
884                             log::error!(
885                                 "Received object {}@{} in {}.{} but expected interface {}.",
886                                 obj_udata.interface.name,
887                                 obj_id,
888                                 interface.name,
889                                 message_desc.name,
890                                 next_interface.name,
891                             );
892                             return -1;
893                         }
894                         parsed_args.push(Argument::Object(ObjectId {
895                             alive: Some(obj_udata.alive.clone()),
896                             ptr: obj,
897                             id: obj_id,
898                             interface: obj_udata.interface,
899                         }));
900                     } else {
901                         parsed_args.push(Argument::Object(ObjectId {
902                             alive: None,
903                             id: obj_id,
904                             ptr: obj,
905                             interface: next_interface,
906                         }));
907                     }
908                 } else {
909                     // libwayland-client.so checks nulls for us
910                     parsed_args.push(Argument::Object(ObjectId {
911                         alive: None,
912                         id: 0,
913                         ptr: std::ptr::null_mut(),
914                         interface: &ANONYMOUS_INTERFACE,
915                     }))
916                 }
917             }
918             ArgumentType::NewId(_) => {
919                 let obj = (*args.add(i)).o as *mut wl_proxy;
920                 // this is a newid, it needs to be initialized
921                 if !obj.is_null() {
922                     let child_interface = message_desc.child_interface.unwrap_or_else(|| {
923                         log::warn!(
924                             "Event {}.{} creates an anonymous object.",
925                             interface.name,
926                             opcode
927                         );
928                         &ANONYMOUS_INTERFACE
929                     });
930                     let child_alive = Arc::new(AtomicBool::new(true));
931                     let child_id = ObjectId {
932                         ptr: obj,
933                         alive: Some(child_alive.clone()),
934                         id: ffi_dispatch!(WAYLAND_CLIENT_HANDLE, wl_proxy_get_id, obj),
935                         interface: child_interface,
936                     };
937                     let child_udata = Box::into_raw(Box::new(ProxyUserData {
938                         alive: child_alive,
939                         data: Arc::new(UninitObjectData),
940                         interface: child_interface,
941                     }));
942                     created = Some((child_id.clone(), child_udata));
943                     ffi_dispatch!(
944                         WAYLAND_CLIENT_HANDLE,
945                         wl_proxy_add_dispatcher,
946                         obj,
947                         dispatcher_func,
948                         &RUST_MANAGED as *const u8 as *const c_void,
949                         child_udata as *mut c_void
950                     );
951                     parsed_args.push(Argument::NewId(child_id));
952                 } else {
953                     parsed_args.push(Argument::NewId(ObjectId {
954                         id: 0,
955                         ptr: std::ptr::null_mut(),
956                         alive: None,
957                         interface: &ANONYMOUS_INTERFACE,
958                     }))
959                 }
960             }
961         }
962     }
963 
964     let proxy_id = ffi_dispatch!(WAYLAND_CLIENT_HANDLE, wl_proxy_get_id, proxy);
965     let id = ObjectId {
966         alive: Some(udata.alive.clone()),
967         ptr: proxy,
968         id: proxy_id,
969         interface: udata.interface,
970     };
971 
972     let ret = HANDLE.with(|handle| {
973         udata.data.clone().event(
974             &mut **handle.borrow_mut(),
975             Message { sender_id: id.clone(), opcode: opcode as u16, args: parsed_args },
976         )
977     });
978 
979     if message_desc.is_destructor {
980         let udata = Box::from_raw(udata_ptr);
981         ffi_dispatch!(WAYLAND_CLIENT_HANDLE, wl_proxy_set_user_data, proxy, std::ptr::null_mut());
982         udata.alive.store(false, Ordering::Release);
983         udata.data.destroyed(id);
984         ffi_dispatch!(WAYLAND_CLIENT_HANDLE, wl_proxy_destroy, proxy);
985     }
986 
987     match (created, ret) {
988         (Some((_, child_udata_ptr)), Some(child_data)) => {
989             (*child_udata_ptr).data = child_data;
990         }
991         (Some((child_id, _)), None) => {
992             panic!("Callback creating object {} did not provide any object data.", child_id);
993         }
994         (None, Some(_)) => {
995             panic!("An object data was returned from a callback not creating any object");
996         }
997         (None, None) => {}
998     }
999 
1000     0
1001 }
1002 
1003 extern "C" {
wl_log_trampoline_to_rust_client(fmt: *const c_char, list: *const c_void)1004     fn wl_log_trampoline_to_rust_client(fmt: *const c_char, list: *const c_void);
1005 }
1006 
1007 impl Drop for Backend {
drop(&mut self)1008     fn drop(&mut self) {
1009         if self.handle.evq.is_null() {
1010             // we are own the connection, clone it
1011             unsafe {
1012                 ffi_dispatch!(WAYLAND_CLIENT_HANDLE, wl_display_disconnect, self.handle.display)
1013             }
1014         }
1015     }
1016 }
1017 
1018 struct DumbObjectData;
1019 
1020 impl ObjectData for DumbObjectData {
event( self: Arc<Self>, _handle: &mut Handle, _msg: Message<ObjectId>, ) -> Option<Arc<dyn ObjectData>>1021     fn event(
1022         self: Arc<Self>,
1023         _handle: &mut Handle,
1024         _msg: Message<ObjectId>,
1025     ) -> Option<Arc<dyn ObjectData>> {
1026         unreachable!()
1027     }
1028 
destroyed(&self, _object_id: ObjectId)1029     fn destroyed(&self, _object_id: ObjectId) {
1030         unreachable!()
1031     }
1032 }
1033 
1034 struct UninitObjectData;
1035 
1036 impl ObjectData for UninitObjectData {
event( self: Arc<Self>, _handle: &mut Handle, msg: Message<ObjectId>, ) -> Option<Arc<dyn ObjectData>>1037     fn event(
1038         self: Arc<Self>,
1039         _handle: &mut Handle,
1040         msg: Message<ObjectId>,
1041     ) -> Option<Arc<dyn ObjectData>> {
1042         panic!("Received a message on an uninitialized object: {:?}", msg);
1043     }
1044 
destroyed(&self, _object_id: ObjectId)1045     fn destroyed(&self, _object_id: ObjectId) {}
1046 
debug(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result1047     fn debug(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1048         f.debug_struct("UninitObjectData").finish()
1049     }
1050 }
1051