1 //! Server-side implementation of a Wayland protocol backend using `libwayland`
2
3 use std::{
4 ffi::{CStr, CString},
5 os::raw::{c_char, c_void},
6 os::unix::{
7 io::{IntoRawFd, RawFd},
8 net::UnixStream,
9 },
10 sync::{
11 atomic::{AtomicBool, Ordering},
12 Arc,
13 },
14 };
15
16 use crate::protocol::{
17 check_for_signature, same_interface, AllowNull, Argument, ArgumentType, Interface, Message,
18 ObjectInfo, ANONYMOUS_INTERFACE,
19 };
20 use scoped_tls::scoped_thread_local;
21 use smallvec::SmallVec;
22
23 use wayland_sys::{common::*, ffi_dispatch, server::*};
24
25 use super::{free_arrays, RUST_MANAGED};
26
27 pub use crate::types::server::{Credentials, DisconnectReason, GlobalInfo, InitError, InvalidId};
28
29 // First pointer is &mut Handle<D>, and second pointer is &mut D
30 scoped_thread_local!(static HANDLE: (*mut c_void, *mut c_void));
31
32 type PendingDestructor<D> = (Arc<dyn ObjectData<D>>, ClientId, ObjectId);
33
34 // Pointer is &mut Vec<PendingDestructor<D>>
35 scoped_thread_local!(static PENDING_DESTRUCTORS: *mut c_void);
36
37 /// A trait representing your data associated to an object
38 ///
39 /// You will only be given access to it as a `&` reference, so you
40 /// need to handle interior mutability by yourself.
41 ///
42 /// The methods of this trait will be invoked internally every time a
43 /// new object is created to initialize its data.
44 pub trait ObjectData<D>: downcast_rs::DowncastSync {
45 /// Dispatch a request for the associated object
46 ///
47 /// If the request has a NewId argument, the callback must return the object data
48 /// for the newly created object
request( self: Arc<Self>, handle: &mut Handle<D>, data: &mut D, client_id: ClientId, msg: Message<ObjectId>, ) -> Option<Arc<dyn ObjectData<D>>>49 fn request(
50 self: Arc<Self>,
51 handle: &mut Handle<D>,
52 data: &mut D,
53 client_id: ClientId,
54 msg: Message<ObjectId>,
55 ) -> Option<Arc<dyn ObjectData<D>>>;
56 /// Notification that the object has been destroyed and is no longer active
destroyed(&self, _: &mut D, client_id: ClientId, object_id: ObjectId)57 fn destroyed(&self, _: &mut D, client_id: ClientId, object_id: ObjectId);
58 /// Helper for forwarding a Debug implementation of your `ObjectData` type
59 ///
60 /// By default will just print `ObjectData { ... }`
debug(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result61 fn debug(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
62 f.debug_struct("ObjectData").finish_non_exhaustive()
63 }
64 }
65
66 downcast_rs::impl_downcast!(sync ObjectData<D>);
67
68 #[cfg(not(tarpaulin_include))]
69 impl<D> std::fmt::Debug for dyn ObjectData<D> {
fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result70 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
71 self.debug(f)
72 }
73 }
74
75 /// A trait representing the handling of new bound globals
76 pub trait GlobalHandler<D>: downcast_rs::DowncastSync {
77 /// Check if given client is allowed to interact with given global
78 ///
79 /// If this function returns false, the client will not be notified of the existence
80 /// of this global, and any attempt to bind it will result in a protocol error as if
81 /// the global did not exist.
82 ///
83 /// Default implementation always return true.
can_view( &self, _client_id: ClientId, _client_data: &Arc<dyn ClientData<D>>, _global_id: GlobalId, ) -> bool84 fn can_view(
85 &self,
86 _client_id: ClientId,
87 _client_data: &Arc<dyn ClientData<D>>,
88 _global_id: GlobalId,
89 ) -> bool {
90 true
91 }
92 /// A global has been bound
93 ///
94 /// Given client bound given global, creating given object.
95 ///
96 /// The method must return the object data for the newly created object.
bind( self: Arc<Self>, handle: &mut Handle<D>, data: &mut D, client_id: ClientId, global_id: GlobalId, object_id: ObjectId, ) -> Arc<dyn ObjectData<D>>97 fn bind(
98 self: Arc<Self>,
99 handle: &mut Handle<D>,
100 data: &mut D,
101 client_id: ClientId,
102 global_id: GlobalId,
103 object_id: ObjectId,
104 ) -> Arc<dyn ObjectData<D>>;
105 /// Helper for forwarding a Debug implementation of your `GlobalHandler` type
106 ///
107 /// By default will just print `GlobalHandler { ... }`
debug(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result108 fn debug(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
109 f.debug_struct("GlobalHandler").finish_non_exhaustive()
110 }
111 }
112
113 #[cfg(not(tarpaulin_include))]
114 impl<D> std::fmt::Debug for dyn GlobalHandler<D> {
fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result115 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
116 self.debug(f)
117 }
118 }
119
120 downcast_rs::impl_downcast!(sync GlobalHandler<D>);
121
122 /// A trait representing your data associated to a clientObjectData
123 pub trait ClientData<D>: downcast_rs::DowncastSync {
124 /// Notification that a client was initialized
initialized(&self, client_id: ClientId)125 fn initialized(&self, client_id: ClientId);
126
127 /// Notification that a client is disconnected
disconnected(&self, client_id: ClientId, reason: DisconnectReason)128 fn disconnected(&self, client_id: ClientId, reason: DisconnectReason);
129 /// Helper for forwarding a Debug implementation of your `ClientData` type
130 ///
131 /// By default will just print `GlobalHandler { ... }`
debug(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result132 fn debug(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
133 f.debug_struct("ClientData").finish_non_exhaustive()
134 }
135 }
136
137 #[cfg(not(tarpaulin_include))]
138 impl<D> std::fmt::Debug for dyn ClientData<D> {
fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result139 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
140 self.debug(f)
141 }
142 }
143
144 downcast_rs::impl_downcast!(sync ClientData<D>);
145
146 /// An id of an object on a wayland server.
147 #[derive(Clone)]
148 pub struct ObjectId {
149 id: u32,
150 ptr: *mut wl_resource,
151 alive: Option<Arc<AtomicBool>>,
152 interface: &'static Interface,
153 }
154
155 unsafe impl Send for ObjectId {}
156 unsafe impl Sync for ObjectId {}
157
158 impl std::cmp::PartialEq for ObjectId {
eq(&self, other: &ObjectId) -> bool159 fn eq(&self, other: &ObjectId) -> bool {
160 match (&self.alive, &other.alive) {
161 (Some(ref a), Some(ref b)) => {
162 // this is an object we manage
163 Arc::ptr_eq(a, b)
164 }
165 (None, None) => {
166 // this is an external object
167 self.ptr == other.ptr
168 && self.id == other.id
169 && same_interface(self.interface, other.interface)
170 }
171 _ => false,
172 }
173 }
174 }
175
176 impl std::cmp::Eq for ObjectId {}
177
178 #[cfg(not(tarpaulin_include))]
179 impl std::fmt::Display for ObjectId {
fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result180 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
181 write!(f, "{}@{}", self.interface.name, self.id)
182 }
183 }
184
185 #[cfg(not(tarpaulin_include))]
186 impl std::fmt::Debug for ObjectId {
fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result187 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
188 write!(f, "ObjectId({})", self)
189 }
190 }
191
192 impl ObjectId {
193 /// Returns whether this object is a null object.
is_null(&self) -> bool194 pub fn is_null(&self) -> bool {
195 self.ptr.is_null()
196 }
197
198 /// Returns the interface of this object.
interface(&self) -> &'static Interface199 pub fn interface(&self) -> &'static Interface {
200 self.interface
201 }
202
203 /// Check if two object IDs are associated with the same client
204 ///
205 /// *Note:* This may spuriously return `false` if one (or both) of the objects to compare
206 /// is no longer valid.
same_client_as(&self, other: &ObjectId) -> bool207 pub fn same_client_as(&self, other: &ObjectId) -> bool {
208 let my_client_ptr = match self.alive {
209 Some(ref alive) if !alive.load(Ordering::Acquire) => {
210 return false;
211 }
212 _ => unsafe { ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_resource_get_client, self.ptr) },
213 };
214 let other_client_ptr = match other.alive {
215 Some(ref alive) if !alive.load(Ordering::Acquire) => {
216 return false;
217 }
218 _ => unsafe { ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_resource_get_client, other.ptr) },
219 };
220
221 my_client_ptr == other_client_ptr
222 }
223
224 /// Return the protocol-level numerical ID of this object
225 ///
226 /// Protocol IDs are reused after object destruction, so this should not be used as a
227 /// unique identifier,
protocol_id(&self) -> u32228 pub fn protocol_id(&self) -> u32 {
229 self.id
230 }
231
232 /// Creates an object from a C pointer.
233 ///
234 /// # Errors
235 ///
236 /// This function returns an [`InvalidId`] error if the interface of the resource does not match the
237 /// provided interface.
238 ///
239 /// # Safety
240 ///
241 /// The provided pointer must be a valid pointer to a `wl_resource` and remain valid for as
242 /// long as the retrieved `ObjectId` is used.
from_ptr( interface: &'static Interface, ptr: *mut wl_resource, ) -> Result<ObjectId, InvalidId>243 pub unsafe fn from_ptr(
244 interface: &'static Interface,
245 ptr: *mut wl_resource,
246 ) -> Result<ObjectId, InvalidId> {
247 let iface_c_ptr =
248 interface.c_ptr.expect("[wayland-backend-sys] Cannot use Interface without c_ptr!");
249 let ptr_iface_name =
250 CStr::from_ptr(ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_resource_get_class, ptr));
251 let provided_iface_name = CStr::from_ptr(iface_c_ptr.name);
252 if ptr_iface_name != provided_iface_name {
253 return Err(InvalidId);
254 }
255
256 let id = ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_resource_get_id, ptr);
257
258 let is_rust_managed = ffi_dispatch!(
259 WAYLAND_SERVER_HANDLE,
260 wl_resource_instance_of,
261 ptr,
262 iface_c_ptr,
263 &RUST_MANAGED as *const u8 as *const _
264 ) != 0;
265
266 let alive = if is_rust_managed {
267 // Using () instead of the type parameter here is safe, because:
268 // 1) ResourceUserData is #[repr(C)], so its layout does not depend on D
269 // 2) we are only accessing the field `.alive`, which type is independent of D
270 //
271 let udata = ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_resource_get_user_data, ptr)
272 as *mut ResourceUserData<()>;
273 Some((*udata).alive.clone())
274 } else {
275 None
276 };
277
278 Ok(ObjectId { id, ptr, alive, interface })
279 }
280
281 /// Returns the pointer that represents this object.
282 ///
283 /// The pointer may be used to interoperate with libwayland.
as_ptr(&self) -> *mut wl_resource284 pub fn as_ptr(&self) -> *mut wl_resource {
285 if self.alive.as_ref().map(|alive| alive.load(Ordering::Acquire)).unwrap_or(true) {
286 self.ptr
287 } else {
288 std::ptr::null_mut()
289 }
290 }
291 }
292
293 /// An id of a client connected to the server.
294 #[derive(Debug, Clone)]
295 pub struct ClientId {
296 ptr: *mut wl_client,
297 alive: Arc<AtomicBool>,
298 }
299
300 unsafe impl Send for ClientId {}
301 unsafe impl Sync for ClientId {}
302
303 impl std::cmp::PartialEq for ClientId {
eq(&self, other: &ClientId) -> bool304 fn eq(&self, other: &ClientId) -> bool {
305 Arc::ptr_eq(&self.alive, &other.alive)
306 }
307 }
308
309 impl std::cmp::Eq for ClientId {}
310
311 /// The ID of a global
312 #[derive(Debug, Clone)]
313 pub struct GlobalId {
314 ptr: *mut wl_global,
315 alive: Arc<AtomicBool>,
316 }
317
318 unsafe impl Send for GlobalId {}
319 unsafe impl Sync for GlobalId {}
320
321 impl std::cmp::PartialEq for GlobalId {
eq(&self, other: &GlobalId) -> bool322 fn eq(&self, other: &GlobalId) -> bool {
323 Arc::ptr_eq(&self.alive, &other.alive)
324 }
325 }
326
327 impl std::cmp::Eq for GlobalId {}
328
329 #[repr(C)]
330 struct ResourceUserData<D> {
331 alive: Arc<AtomicBool>,
332 data: Arc<dyn ObjectData<D>>,
333 interface: &'static Interface,
334 }
335
336 struct ClientUserData<D> {
337 data: Arc<dyn ClientData<D>>,
338 alive: Arc<AtomicBool>,
339 }
340
341 struct GlobalUserData<D> {
342 handler: Arc<dyn GlobalHandler<D>>,
343 interface: &'static Interface,
344 version: u32,
345 disabled: bool,
346 alive: Arc<AtomicBool>,
347 ptr: *mut wl_global,
348 }
349
350 /// Main handle of a backend to the Wayland protocol
351 ///
352 /// This type hosts most of the protocol-related functionality of the backend, and is the
353 /// main entry point for manipulating Wayland objects. It can be retrieved both from
354 /// the backend via [`Backend::handle()`](Backend::handle), and is given to you as argument
355 /// in most event callbacks.
356 #[derive(Debug)]
357 pub struct Handle<D> {
358 display: *mut wl_display,
359 pending_destructors: Vec<PendingDestructor<D>>,
360 _data: std::marker::PhantomData<fn(&mut D)>,
361 }
362
363 /// A backend object that represents the state of a wayland server.
364 ///
365 /// A backend is used to drive a wayland server by receiving requests, dispatching messages to the appropriate
366 /// handlers and flushes requests to be sent back to the client.
367 #[derive(Debug)]
368 pub struct Backend<D> {
369 handle: Handle<D>,
370 }
371
372 unsafe impl<D> Send for Backend<D> {}
373 unsafe impl<D> Sync for Backend<D> {}
374
375 impl<D> Backend<D> {
376 /// Initialize a new Wayland backend
new() -> Result<Self, InitError>377 pub fn new() -> Result<Self, InitError> {
378 if !is_lib_available() {
379 return Err(InitError::NoWaylandLib);
380 }
381
382 let display = unsafe { ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_display_create,) };
383 if display.is_null() {
384 panic!("[wayland-backend-sys] libwayland reported an allocation failure.");
385 }
386
387 unsafe {
388 ffi_dispatch!(
389 WAYLAND_SERVER_HANDLE,
390 wl_log_set_handler_server,
391 wl_log_trampoline_to_rust_server
392 )
393 };
394
395 unsafe {
396 ffi_dispatch!(
397 WAYLAND_SERVER_HANDLE,
398 wl_display_set_global_filter,
399 display,
400 global_filter::<D>,
401 std::ptr::null_mut()
402 );
403 }
404
405 Ok(Backend {
406 handle: Handle {
407 display,
408 pending_destructors: Vec::new(),
409 _data: std::marker::PhantomData,
410 },
411 })
412 }
413
414 /// Initializes a connection to a client.
415 ///
416 /// The `data` parameter contains data that will be associated with the client.
insert_client( &mut self, stream: UnixStream, data: Arc<dyn ClientData<D>>, ) -> std::io::Result<ClientId>417 pub fn insert_client(
418 &mut self,
419 stream: UnixStream,
420 data: Arc<dyn ClientData<D>>,
421 ) -> std::io::Result<ClientId> {
422 let ret = unsafe {
423 ffi_dispatch!(
424 WAYLAND_SERVER_HANDLE,
425 wl_client_create,
426 self.handle.display,
427 stream.into_raw_fd()
428 )
429 };
430
431 if ret.is_null() {
432 return Err(std::io::Error::last_os_error());
433 }
434
435 Ok(unsafe { init_client::<D>(ret, data) })
436 }
437
438 /// Flushes pending events destined for a client.
439 ///
440 /// If no client is specified, all pending events are flushed to all clients.
flush(&mut self, client: Option<ClientId>) -> std::io::Result<()>441 pub fn flush(&mut self, client: Option<ClientId>) -> std::io::Result<()> {
442 if let Some(client_id) = client {
443 if client_id.alive.load(Ordering::Acquire) {
444 unsafe { ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_client_flush, client_id.ptr) }
445 }
446 } else {
447 // wl_display_flush_clients might invoke destructors
448 PENDING_DESTRUCTORS.set(
449 &(&mut self.handle.pending_destructors as *mut _ as *mut _),
450 || unsafe {
451 ffi_dispatch!(
452 WAYLAND_SERVER_HANDLE,
453 wl_display_flush_clients,
454 self.handle.display
455 );
456 },
457 );
458 }
459 Ok(())
460 }
461
462 /// Returns a handle which represents the server side state of the backend.
463 ///
464 /// The handle provides a variety of functionality, such as querying information about wayland objects,
465 /// obtaining data associated with a client and it's objects, and creating globals.
handle(&mut self) -> &mut Handle<D>466 pub fn handle(&mut self) -> &mut Handle<D> {
467 &mut self.handle
468 }
469
470 /// Returns the underlying file descriptor.
471 ///
472 /// The file descriptor may be monitored for activity with a polling mechanism such as epoll or kqueue.
473 /// When it becomes readable, this means there are pending messages that would be dispatched if you call
474 /// [`Backend::dispatch_all_clients`].
475 ///
476 /// The file descriptor should not be used for any other purpose than monitoring it.
poll_fd(&self) -> RawFd477 pub fn poll_fd(&self) -> RawFd {
478 unsafe {
479 let evl_ptr = ffi_dispatch!(
480 WAYLAND_SERVER_HANDLE,
481 wl_display_get_event_loop,
482 self.handle.display
483 );
484 ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_event_loop_get_fd, evl_ptr)
485 }
486 }
487
488 /// Dispatches all pending messages from the specified client.
489 ///
490 /// This method will not block if there are no pending messages.
491 ///
492 /// The provided `data` will be provided to the handler of messages received from the client.
493 ///
494 /// For performance reasons, use of this function should be integrated with an event loop, monitoring the
495 /// file descriptor associated with the client and only calling this method when messages are available.
496 ///
497 /// # Backend specific
498 ///
499 /// The `sys` backend may also dispatch other clients than the client being dispatched.
dispatch_client( &mut self, data: &mut D, _client_id: ClientId, ) -> std::io::Result<usize>500 pub fn dispatch_client(
501 &mut self,
502 data: &mut D,
503 _client_id: ClientId,
504 ) -> std::io::Result<usize> {
505 self.dispatch_all_clients(data)
506 }
507
508 /// Dispatches all pending messages from all clients.
509 ///
510 /// This method will not block if there are no pending messages.
511 ///
512 /// The provided `data` will be provided to the handler of messages received from the clients.
513 ///
514 /// For performance reasons, use of this function should be integrated with an event loop, monitoring the
515 /// file descriptor retrieved by [`Backend::poll_fd`] and only calling this method when messages are
516 /// available.
dispatch_all_clients(&mut self, data: &mut D) -> std::io::Result<usize>517 pub fn dispatch_all_clients(&mut self, data: &mut D) -> std::io::Result<usize> {
518 let display = self.handle.display;
519 let pointers = (&mut self.handle as *mut _ as *mut c_void, data as *mut _ as *mut c_void);
520 let ret = HANDLE.set(&pointers, || unsafe {
521 let evl_ptr = ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_display_get_event_loop, display);
522 ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_event_loop_dispatch, evl_ptr, 0)
523 });
524
525 for (object, client_id, object_id) in self.handle.pending_destructors.drain(..) {
526 object.destroyed(data, client_id, object_id);
527 }
528
529 if ret < 0 {
530 Err(std::io::Error::last_os_error())
531 } else {
532 Ok(ret as usize)
533 }
534 }
535
536 /// Access the underlying `*mut wl_display` pointer
display_ptr(&self) -> *mut wl_display537 pub fn display_ptr(&self) -> *mut wl_display {
538 self.handle.display
539 }
540 }
541
542 impl<D> Handle<D> {
543 /// Returns information about some object.
object_info(&self, id: ObjectId) -> Result<ObjectInfo, InvalidId>544 pub fn object_info(&self, id: ObjectId) -> Result<ObjectInfo, InvalidId> {
545 if !id.alive.as_ref().map(|alive| alive.load(Ordering::Acquire)).unwrap_or(true) {
546 return Err(InvalidId);
547 }
548
549 let version =
550 unsafe { ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_resource_get_version, id.ptr) } as u32;
551
552 Ok(ObjectInfo { id: id.id, version, interface: id.interface })
553 }
554
555 /// Returns the id of the client which owns the object.
get_client(&self, id: ObjectId) -> Result<ClientId, InvalidId>556 pub fn get_client(&self, id: ObjectId) -> Result<ClientId, InvalidId> {
557 if !id.alive.map(|alive| alive.load(Ordering::Acquire)).unwrap_or(true) {
558 return Err(InvalidId);
559 }
560
561 unsafe {
562 let client_ptr = ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_resource_get_client, id.ptr);
563 client_id_from_ptr::<D>(client_ptr).ok_or(InvalidId)
564 }
565 }
566
567 /// Returns the data associated with a client.
get_client_data(&self, id: ClientId) -> Result<Arc<dyn ClientData<D>>, InvalidId>568 pub fn get_client_data(&self, id: ClientId) -> Result<Arc<dyn ClientData<D>>, InvalidId> {
569 if !id.alive.load(Ordering::Acquire) {
570 return Err(InvalidId);
571 }
572
573 let data = unsafe {
574 match client_user_data::<D>(id.ptr) {
575 Some(ptr) => &mut *ptr,
576 None => return Err(InvalidId),
577 }
578 };
579
580 Ok(data.data.clone())
581 }
582
583 /// Retrive the [`Credentials`] of a client
get_client_credentials(&self, id: ClientId) -> Result<Credentials, InvalidId>584 pub fn get_client_credentials(&self, id: ClientId) -> Result<Credentials, InvalidId> {
585 if !id.alive.load(Ordering::Acquire) {
586 return Err(InvalidId);
587 }
588
589 let mut creds = Credentials { pid: 0, uid: 0, gid: 0 };
590
591 unsafe {
592 ffi_dispatch!(
593 WAYLAND_SERVER_HANDLE,
594 wl_client_get_credentials,
595 id.ptr,
596 &mut creds.pid,
597 &mut creds.uid,
598 &mut creds.gid
599 );
600 }
601
602 Ok(creds)
603 }
604
605 /// Returns an iterator over all clients connected to the server.
all_clients<'a>(&'a self) -> Box<dyn Iterator<Item = ClientId> + 'a>606 pub fn all_clients<'a>(&'a self) -> Box<dyn Iterator<Item = ClientId> + 'a> {
607 let mut client_list = unsafe {
608 ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_display_get_client_list, self.display)
609 };
610 Box::new(std::iter::from_fn(move || {
611 if client_list.is_null() {
612 None
613 } else {
614 unsafe {
615 let client =
616 ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_client_from_link, client_list);
617 let id = client_id_from_ptr::<D>(client);
618
619 let next = (*client_list).next;
620 if client_list == next {
621 client_list = std::ptr::null_mut();
622 } else {
623 client_list = next;
624 }
625
626 id
627 }
628 }
629 }))
630 }
631
632 /// Returns an iterator over all objects owned by a client.
all_objects_for<'a>( &'a self, _client_id: ClientId, ) -> Result<Box<dyn Iterator<Item = ObjectId> + 'a>, InvalidId>633 pub fn all_objects_for<'a>(
634 &'a self,
635 _client_id: ClientId,
636 ) -> Result<Box<dyn Iterator<Item = ObjectId> + 'a>, InvalidId> {
637 todo!()
638 }
639
640 /// Retrieve the `ObjectId` for a wayland object given its protocol numerical ID
object_for_protocol_id( &self, client_id: ClientId, interface: &'static Interface, protocol_id: u32, ) -> Result<ObjectId, InvalidId>641 pub fn object_for_protocol_id(
642 &self,
643 client_id: ClientId,
644 interface: &'static Interface,
645 protocol_id: u32,
646 ) -> Result<ObjectId, InvalidId> {
647 if !client_id.alive.load(Ordering::Acquire) {
648 return Err(InvalidId);
649 }
650 let resource = unsafe {
651 ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_client_get_object, client_id.ptr, protocol_id)
652 };
653 if resource.is_null() {
654 Err(InvalidId)
655 } else {
656 unsafe { ObjectId::from_ptr(interface, resource) }
657 }
658 }
659
660 /// Create a new object for given client
661 ///
662 /// To ensure state coherence of the protocol, the created object should be immediately
663 /// sent as a "New ID" argument in an event to the client.
create_object( &mut self, client: ClientId, interface: &'static Interface, version: u32, data: Arc<dyn ObjectData<D>>, ) -> Result<ObjectId, InvalidId>664 pub fn create_object(
665 &mut self,
666 client: ClientId,
667 interface: &'static Interface,
668 version: u32,
669 data: Arc<dyn ObjectData<D>>,
670 ) -> Result<ObjectId, InvalidId> {
671 if !client.alive.load(Ordering::Acquire) {
672 return Err(InvalidId);
673 }
674
675 let interface_ptr =
676 interface.c_ptr.expect("Interface without c_ptr are unsupported by the sys backend.");
677
678 let resource = unsafe {
679 ffi_dispatch!(
680 WAYLAND_SERVER_HANDLE,
681 wl_resource_create,
682 client.ptr,
683 interface_ptr,
684 version as i32,
685 0
686 )
687 };
688
689 Ok(unsafe { init_resource(resource, interface, Some(data)).0 })
690 }
691
692 /// Returns an object id that represents a null object.
null_id(&mut self) -> ObjectId693 pub fn null_id(&mut self) -> ObjectId {
694 ObjectId { ptr: std::ptr::null_mut(), id: 0, alive: None, interface: &ANONYMOUS_INTERFACE }
695 }
696
697 /// Send an event to the client
698 ///
699 /// Returns an error if the sender ID of the provided message is no longer valid.
700 ///
701 /// **Panic:**
702 ///
703 /// Checks against the protocol specification are done, and this method will panic if they do
704 /// not pass:
705 ///
706 /// - the message opcode must be valid for the sender interface
707 /// - the argument list must match the prototype for the message associated with this opcode
708 pub fn send_event(
709 &mut self,
710 Message { sender_id: id, opcode, args }: Message<ObjectId>,
711 ) -> Result<(), InvalidId> {
712 if !id.alive.as_ref().map(|a| a.load(Ordering::Acquire)).unwrap_or(true) || id.ptr.is_null()
713 {
714 return Err(InvalidId);
715 }
716
717 // check that the argument list is valid
718 let message_desc = match id.interface.events.get(opcode as usize) {
719 Some(msg) => msg,
720 None => {
721 panic!("Unknown opcode {} for object {}@{}.", opcode, id.interface.name, id.id);
722 }
723 };
724 if !check_for_signature(message_desc.signature, &args) {
725 panic!(
726 "Unexpected signature for request {}@{}.{}: expected {:?}, got {:?}.",
727 id.interface.name, id.id, message_desc.name, message_desc.signature, args
728 );
729 }
730
731 let mut argument_list = SmallVec::<[wl_argument; 4]>::with_capacity(args.len());
732 let mut arg_interfaces = message_desc.arg_interfaces.iter();
733 for (i, arg) in args.iter().enumerate() {
734 match *arg {
735 Argument::Uint(u) => argument_list.push(wl_argument { u }),
736 Argument::Int(i) => argument_list.push(wl_argument { i }),
737 Argument::Fixed(f) => argument_list.push(wl_argument { f }),
738 Argument::Fd(h) => argument_list.push(wl_argument { h }),
739 Argument::Array(ref a) => {
740 let a = Box::new(wl_array {
741 size: a.len(),
742 alloc: a.len(),
743 data: a.as_ptr() as *mut _,
744 });
745 argument_list.push(wl_argument { a: Box::into_raw(a) })
746 }
747 Argument::Str(ref s) => argument_list.push(wl_argument { s: s.as_ptr() }),
748 Argument::Object(ref o) => {
749 if !o.ptr.is_null() {
750 if !id.alive.as_ref().map(|a| a.load(Ordering::Acquire)).unwrap_or(true) {
751 unsafe { free_arrays(message_desc.signature, &argument_list) };
752 return Err(InvalidId);
753 }
754 // check that the object belongs to the right client
755 if self.get_client(id.clone()).unwrap().ptr
756 != self.get_client(o.clone()).unwrap().ptr
757 {
758 panic!("Attempting to send an event with objects from wrong client.");
759 }
760 let next_interface = arg_interfaces.next().unwrap();
761 if !same_interface(next_interface, o.interface) {
762 panic!("Event {}@{}.{} expects an argument of interface {} but {} was provided instead.", id.interface.name, id.id, message_desc.name, next_interface.name, o.interface.name);
763 }
764 } else if !matches!(
765 message_desc.signature[i],
766 ArgumentType::Object(AllowNull::Yes)
767 ) {
768 panic!(
769 "Event {}@{}.{} expects an non-null object argument.",
770 id.interface.name, id.id, message_desc.name
771 );
772 }
773 argument_list.push(wl_argument { o: o.ptr as *const _ })
774 }
775 Argument::NewId(ref o) => {
776 if !o.ptr.is_null() {
777 if !id.alive.as_ref().map(|a| a.load(Ordering::Acquire)).unwrap_or(true) {
778 unsafe { free_arrays(message_desc.signature, &argument_list) };
779 return Err(InvalidId);
780 }
781 // check that the object belongs to the right client
782 if self.get_client(id.clone()).unwrap().ptr
783 != self.get_client(o.clone()).unwrap().ptr
784 {
785 panic!("Attempting to send an event with objects from wrong client.");
786 }
787 let child_interface = match message_desc.child_interface {
788 Some(iface) => iface,
789 None => panic!("Trying to send event {}@{}.{} which creates an object without specifying its interface, this is unsupported.", id.interface.name, id.id, message_desc.name),
790 };
791 if !same_interface(child_interface, o.interface) {
792 panic!("Event {}@{}.{} expects an argument of interface {} but {} was provided instead.", id.interface.name, id.id, message_desc.name, child_interface.name, o.interface.name);
793 }
794 } else if !matches!(
795 message_desc.signature[i],
796 ArgumentType::NewId(AllowNull::Yes)
797 ) {
798 panic!(
799 "Event {}@{}.{} expects an non-null object argument.",
800 id.interface.name, id.id, message_desc.name
801 );
802 }
803 argument_list.push(wl_argument { o: o.ptr as *const _ })
804 }
805 }
806 }
807
808 unsafe {
809 ffi_dispatch!(
810 WAYLAND_SERVER_HANDLE,
811 wl_resource_post_event_array,
812 id.ptr,
813 opcode as u32,
814 argument_list.as_mut_ptr()
815 );
816 }
817
818 unsafe {
819 free_arrays(message_desc.signature, &argument_list);
820 }
821
822 if message_desc.is_destructor {
823 // wl_resource_destroy invokes a destructor
824 PENDING_DESTRUCTORS.set(
825 &(&mut self.pending_destructors as *mut _ as *mut _),
826 || unsafe {
827 ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_resource_destroy, id.ptr);
828 },
829 );
830 }
831
832 Ok(())
833 }
834
835 /// Returns the data associated with an object.
get_object_data(&self, id: ObjectId) -> Result<Arc<dyn ObjectData<D>>, InvalidId>836 pub fn get_object_data(&self, id: ObjectId) -> Result<Arc<dyn ObjectData<D>>, InvalidId> {
837 if !id.alive.as_ref().map(|alive| alive.load(Ordering::Acquire)).unwrap_or(false) {
838 return Err(InvalidId);
839 }
840
841 let udata = unsafe {
842 &*(ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_resource_get_user_data, id.ptr)
843 as *mut ResourceUserData<D>)
844 };
845
846 Ok(udata.data.clone())
847 }
848
849 /// Sets the data associated with some object.
set_object_data( &mut self, id: ObjectId, data: Arc<dyn ObjectData<D>>, ) -> Result<(), InvalidId>850 pub fn set_object_data(
851 &mut self,
852 id: ObjectId,
853 data: Arc<dyn ObjectData<D>>,
854 ) -> Result<(), InvalidId> {
855 if !id.alive.as_ref().map(|alive| alive.load(Ordering::Acquire)).unwrap_or(false) {
856 return Err(InvalidId);
857 }
858
859 let udata = unsafe {
860 &mut *(ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_resource_get_user_data, id.ptr)
861 as *mut ResourceUserData<D>)
862 };
863
864 udata.data = data;
865
866 Ok(())
867 }
868
869 /// Posts an error on an object. This will also disconnect the client which created the object.
post_error(&mut self, id: ObjectId, error_code: u32, message: CString)870 pub fn post_error(&mut self, id: ObjectId, error_code: u32, message: CString) {
871 if !id.alive.as_ref().map(|alive| alive.load(Ordering::Acquire)).unwrap_or(true) {
872 return;
873 }
874
875 unsafe {
876 ffi_dispatch!(
877 WAYLAND_SERVER_HANDLE,
878 wl_resource_post_error,
879 id.ptr,
880 error_code,
881 message.as_ptr()
882 )
883 }
884 }
885
886 /// Kills the connection to a client.
887 ///
888 /// The disconnection reason determines the error message that is sent to the client (if any).
kill_client(&mut self, client_id: ClientId, reason: DisconnectReason)889 pub fn kill_client(&mut self, client_id: ClientId, reason: DisconnectReason) {
890 if !client_id.alive.load(Ordering::Acquire) {
891 return;
892 }
893 if let Some(udata) = unsafe { client_user_data::<D>(client_id.ptr) } {
894 let udata = unsafe { &*udata };
895 udata.alive.store(false, Ordering::Release);
896 udata.data.disconnected(client_id.clone(), reason);
897 }
898
899 unsafe {
900 ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_client_destroy, client_id.ptr);
901 }
902 }
903
904 /// Creates a global of the specified interface and version and then advertises it to clients.
905 ///
906 /// The clients which the global is advertised to is determined by the implementation of the [`GlobalHandler`].
create_global( &mut self, interface: &'static Interface, version: u32, handler: Arc<dyn GlobalHandler<D>>, ) -> GlobalId907 pub fn create_global(
908 &mut self,
909 interface: &'static Interface,
910 version: u32,
911 handler: Arc<dyn GlobalHandler<D>>,
912 ) -> GlobalId {
913 let alive = Arc::new(AtomicBool::new(true));
914
915 let interface_ptr =
916 interface.c_ptr.expect("Interface without c_ptr are unsupported by the sys backend.");
917
918 let udata = Box::into_raw(Box::new(GlobalUserData {
919 handler,
920 alive: alive.clone(),
921 interface,
922 version,
923 disabled: false,
924 ptr: std::ptr::null_mut(),
925 }));
926
927 let ret = unsafe {
928 ffi_dispatch!(
929 WAYLAND_SERVER_HANDLE,
930 wl_global_create,
931 self.display,
932 interface_ptr,
933 version as i32,
934 udata as *mut c_void,
935 global_bind::<D>
936 )
937 };
938
939 if ret.is_null() {
940 panic!(
941 "[wayland-backend-sys] Invalid global specification or memory allocation failure."
942 );
943 }
944
945 unsafe {
946 (*udata).ptr = ret;
947 }
948
949 GlobalId { ptr: ret, alive }
950 }
951
952 /// Disables a global object that is currently active.
953 ///
954 /// The global removal will be signaled to all currently connected clients. New clients will not know of the global,
955 /// but the associated state and callbacks will not be freed. As such, clients that still try to bind the global
956 /// afterwards (because they have not yet realized it was removed) will succeed.
disable_global(&mut self, id: GlobalId)957 pub fn disable_global(&mut self, id: GlobalId) {
958 if !id.alive.load(Ordering::Acquire) {
959 return;
960 }
961
962 let udata = unsafe {
963 &mut *(ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_global_get_user_data, id.ptr)
964 as *mut GlobalUserData<D>)
965 };
966 udata.disabled = true;
967
968 unsafe {
969 ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_global_remove, id.ptr);
970 }
971 }
972
973 /// Removes a global object and free its resources.
974 ///
975 /// The global object will no longer be considered valid by the server, clients trying to bind it will be killed,
976 /// and the global ID is freed for re-use.
977 ///
978 /// It is advised to first disable a global and wait some amount of time before removing it, to ensure all clients
979 /// are correctly aware of its removal. Note that clients will generally not expect globals that represent a capability
980 /// of the server to be removed, as opposed to globals representing peripherals (like `wl_output` or `wl_seat`).
remove_global(&mut self, id: GlobalId)981 pub fn remove_global(&mut self, id: GlobalId) {
982 if !id.alive.load(Ordering::Acquire) {
983 return;
984 }
985
986 let udata = unsafe {
987 Box::from_raw(ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_global_get_user_data, id.ptr)
988 as *mut GlobalUserData<D>)
989 };
990 udata.alive.store(false, Ordering::Release);
991
992 unsafe {
993 ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_global_destroy, id.ptr);
994 }
995 }
996
997 /// Returns information about a global.
global_info(&self, id: GlobalId) -> Result<GlobalInfo, InvalidId>998 pub fn global_info(&self, id: GlobalId) -> Result<GlobalInfo, InvalidId> {
999 if !id.alive.load(Ordering::Acquire) {
1000 return Err(InvalidId);
1001 }
1002 let udata = unsafe {
1003 &*(ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_global_get_user_data, id.ptr)
1004 as *mut GlobalUserData<D>)
1005 };
1006
1007 Ok(GlobalInfo {
1008 interface: udata.interface,
1009 version: udata.version,
1010 disabled: udata.disabled,
1011 })
1012 }
1013
1014 /// Returns the handler which manages the visibility and notifies when a client has bound the global.
get_global_handler(&self, id: GlobalId) -> Result<Arc<dyn GlobalHandler<D>>, InvalidId>1015 pub fn get_global_handler(&self, id: GlobalId) -> Result<Arc<dyn GlobalHandler<D>>, InvalidId> {
1016 if !id.alive.load(Ordering::Acquire) {
1017 return Err(InvalidId);
1018 }
1019
1020 let udata = unsafe {
1021 Box::from_raw(ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_global_get_user_data, id.ptr)
1022 as *mut GlobalUserData<D>)
1023 };
1024 Ok(udata.handler.clone())
1025 }
1026 }
1027
init_client<D>(client: *mut wl_client, data: Arc<dyn ClientData<D>>) -> ClientId1028 unsafe fn init_client<D>(client: *mut wl_client, data: Arc<dyn ClientData<D>>) -> ClientId {
1029 let alive = Arc::new(AtomicBool::new(true));
1030 let client_data = Box::into_raw(Box::new(ClientUserData { alive: alive.clone(), data }));
1031
1032 let listener = signal::rust_listener_create(client_destroy_notify::<D>);
1033 signal::rust_listener_set_user_data(listener, client_data as *mut c_void);
1034
1035 ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_client_add_destroy_listener, client, listener);
1036
1037 ClientId { ptr: client, alive }
1038 }
1039
client_id_from_ptr<D>(client: *mut wl_client) -> Option<ClientId>1040 unsafe fn client_id_from_ptr<D>(client: *mut wl_client) -> Option<ClientId> {
1041 client_user_data::<D>(client)
1042 .map(|udata| ClientId { ptr: client, alive: (*udata).alive.clone() })
1043 }
1044
client_user_data<D>(client: *mut wl_client) -> Option<*mut ClientUserData<D>>1045 unsafe fn client_user_data<D>(client: *mut wl_client) -> Option<*mut ClientUserData<D>> {
1046 if client.is_null() {
1047 return None;
1048 }
1049 let listener = ffi_dispatch!(
1050 WAYLAND_SERVER_HANDLE,
1051 wl_client_get_destroy_listener,
1052 client,
1053 client_destroy_notify::<D>
1054 );
1055 if !listener.is_null() {
1056 Some(signal::rust_listener_get_user_data(listener) as *mut ClientUserData<D>)
1057 } else {
1058 None
1059 }
1060 }
1061
client_destroy_notify<D>(listener: *mut wl_listener, client_ptr: *mut c_void)1062 unsafe extern "C" fn client_destroy_notify<D>(listener: *mut wl_listener, client_ptr: *mut c_void) {
1063 let data =
1064 Box::from_raw(signal::rust_listener_get_user_data(listener) as *mut ClientUserData<D>);
1065 signal::rust_listener_destroy(listener);
1066 // only notify the killing if it was not already
1067 if data.alive.load(Ordering::Acquire) {
1068 data.alive.store(false, Ordering::Release);
1069 data.data.disconnected(
1070 ClientId { ptr: client_ptr as *mut wl_client, alive: data.alive.clone() },
1071 DisconnectReason::ConnectionClosed,
1072 );
1073 }
1074 }
1075
global_bind<D>( client: *mut wl_client, data: *mut c_void, version: u32, id: u32, )1076 unsafe extern "C" fn global_bind<D>(
1077 client: *mut wl_client,
1078 data: *mut c_void,
1079 version: u32,
1080 id: u32,
1081 ) {
1082 let global_udata = &mut *(data as *mut GlobalUserData<D>);
1083
1084 let global_id = GlobalId { alive: global_udata.alive.clone(), ptr: global_udata.ptr };
1085
1086 let client_id = match client_id_from_ptr::<D>(client) {
1087 Some(id) => id,
1088 None => return,
1089 };
1090
1091 // this must be Some(), checked at creation of the global
1092 let interface_ptr = global_udata.interface.c_ptr.unwrap();
1093
1094 HANDLE.with(|&(handle_ptr, data_ptr)| {
1095 let handle = &mut *(handle_ptr as *mut Handle<D>);
1096 let data = &mut *(data_ptr as *mut D);
1097 // create the object
1098 let resource = ffi_dispatch!(
1099 WAYLAND_SERVER_HANDLE,
1100 wl_resource_create,
1101 client,
1102 interface_ptr,
1103 version as i32,
1104 id
1105 );
1106 let (object_id, udata) = init_resource(resource, global_udata.interface, None);
1107 let obj_data =
1108 global_udata.handler.clone().bind(handle, data, client_id, global_id, object_id);
1109 (*udata).data = obj_data;
1110 })
1111 }
1112
global_filter<D>( client: *const wl_client, global: *const wl_global, _: *mut c_void, ) -> bool1113 unsafe extern "C" fn global_filter<D>(
1114 client: *const wl_client,
1115 global: *const wl_global,
1116 _: *mut c_void,
1117 ) -> bool {
1118 let client_udata = match client_user_data::<D>(client as *mut _) {
1119 Some(id) => &*id,
1120 None => return false,
1121 };
1122
1123 let client_id = ClientId { ptr: client as *mut _, alive: client_udata.alive.clone() };
1124
1125 let global_udata = &*(ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_global_get_user_data, global)
1126 as *mut GlobalUserData<D>);
1127
1128 let global_id = GlobalId { ptr: global as *mut wl_global, alive: global_udata.alive.clone() };
1129
1130 global_udata.handler.can_view(client_id, &client_udata.data, global_id)
1131 }
1132
init_resource<D>( resource: *mut wl_resource, interface: &'static Interface, data: Option<Arc<dyn ObjectData<D>>>, ) -> (ObjectId, *mut ResourceUserData<D>)1133 unsafe fn init_resource<D>(
1134 resource: *mut wl_resource,
1135 interface: &'static Interface,
1136 data: Option<Arc<dyn ObjectData<D>>>,
1137 ) -> (ObjectId, *mut ResourceUserData<D>) {
1138 let alive = Arc::new(AtomicBool::new(true));
1139 let udata = Box::into_raw(Box::new(ResourceUserData {
1140 data: data.unwrap_or_else(|| Arc::new(UninitObjectData)),
1141 interface,
1142 alive: alive.clone(),
1143 }));
1144 let id = ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_resource_get_id, resource);
1145
1146 ffi_dispatch!(
1147 WAYLAND_SERVER_HANDLE,
1148 wl_resource_set_dispatcher,
1149 resource,
1150 resource_dispatcher::<D>,
1151 &RUST_MANAGED as *const u8 as *const c_void,
1152 udata as *mut c_void,
1153 Some(resource_destructor::<D>)
1154 );
1155
1156 (ObjectId { interface, alive: Some(alive), id, ptr: resource }, udata)
1157 }
1158
resource_dispatcher<D>( _: *const c_void, resource: *mut c_void, opcode: u32, _: *const wl_message, args: *const wl_argument, ) -> i321159 unsafe extern "C" fn resource_dispatcher<D>(
1160 _: *const c_void,
1161 resource: *mut c_void,
1162 opcode: u32,
1163 _: *const wl_message,
1164 args: *const wl_argument,
1165 ) -> i32 {
1166 let resource = resource as *mut wl_resource;
1167 let udata_ptr = ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_resource_get_user_data, resource)
1168 as *mut ResourceUserData<D>;
1169 let udata = &mut *udata_ptr;
1170 let client = ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_resource_get_client, resource);
1171 let resource_id = ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_resource_get_id, resource);
1172 let version = ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_resource_get_version, resource);
1173 let interface = udata.interface;
1174 let message_desc = match interface.requests.get(opcode as usize) {
1175 Some(desc) => desc,
1176 None => {
1177 log::error!("Unknown event opcode {} for interface {}.", opcode, interface.name);
1178 return -1;
1179 }
1180 };
1181
1182 let mut parsed_args =
1183 SmallVec::<[Argument<ObjectId>; 4]>::with_capacity(message_desc.signature.len());
1184 let mut arg_interfaces = message_desc.arg_interfaces.iter().copied();
1185 let mut created = None;
1186 for (i, typ) in message_desc.signature.iter().enumerate() {
1187 match typ {
1188 ArgumentType::Uint => parsed_args.push(Argument::Uint((*args.add(i)).u)),
1189 ArgumentType::Int => parsed_args.push(Argument::Int((*args.add(i)).i)),
1190 ArgumentType::Fixed => parsed_args.push(Argument::Fixed((*args.add(i)).f)),
1191 ArgumentType::Fd => parsed_args.push(Argument::Fd((*args.add(i)).h)),
1192 ArgumentType::Array(_) => {
1193 let array = &*((*args.add(i)).a);
1194 let content = std::slice::from_raw_parts(array.data as *mut u8, array.size);
1195 parsed_args.push(Argument::Array(Box::new(content.into())));
1196 }
1197 ArgumentType::Str(_) => {
1198 let ptr = (*args.add(i)).s;
1199 let cstr = std::ffi::CStr::from_ptr(ptr);
1200 parsed_args.push(Argument::Str(Box::new(cstr.into())));
1201 }
1202 ArgumentType::Object(_) => {
1203 let obj = (*args.add(i)).o as *mut wl_resource;
1204 if !obj.is_null() {
1205 // retrieve the object relevant info
1206 let obj_id = ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_resource_get_id, obj);
1207 // check if this is a local or distant proxy
1208 let next_interface = arg_interfaces.next().unwrap_or(&ANONYMOUS_INTERFACE);
1209 let ret = ffi_dispatch!(
1210 WAYLAND_SERVER_HANDLE,
1211 wl_resource_instance_of,
1212 obj,
1213 next_interface.c_ptr.unwrap(),
1214 &RUST_MANAGED as *const u8 as *const c_void
1215 );
1216 if ret == 0 {
1217 // distant
1218 parsed_args.push(Argument::Object(ObjectId {
1219 alive: None,
1220 id: obj_id,
1221 ptr: obj,
1222 interface: next_interface,
1223 }));
1224 } else {
1225 // local
1226 let obj_udata = &mut *(ffi_dispatch!(
1227 WAYLAND_SERVER_HANDLE,
1228 wl_resource_get_user_data,
1229 obj
1230 )
1231 as *mut ResourceUserData<D>);
1232 parsed_args.push(Argument::Object(ObjectId {
1233 alive: Some(obj_udata.alive.clone()),
1234 ptr: obj,
1235 id: obj_id,
1236 interface: obj_udata.interface,
1237 }));
1238 }
1239 } else {
1240 // libwayland-server.so checks nulls for us
1241 parsed_args.push(Argument::Object(ObjectId {
1242 alive: None,
1243 id: 0,
1244 ptr: std::ptr::null_mut(),
1245 interface: &ANONYMOUS_INTERFACE,
1246 }))
1247 }
1248 }
1249 ArgumentType::NewId(_) => {
1250 let new_id = (*args.add(i)).n;
1251 // create the object
1252 if new_id != 0 {
1253 let child_interface = match message_desc.child_interface {
1254 Some(iface) => iface,
1255 None => panic!("Received request {}@{}.{} which creates an object without specifying its interface, this is unsupported.", udata.interface.name, resource_id, message_desc.name),
1256 };
1257 let (child_id, child_data_ptr) = HANDLE.with(|&(_handle_ptr, _)| {
1258 // create the object
1259 let resource = ffi_dispatch!(
1260 WAYLAND_SERVER_HANDLE,
1261 wl_resource_create,
1262 client,
1263 child_interface.c_ptr.unwrap(),
1264 version,
1265 new_id
1266 );
1267 init_resource::<D>(resource, child_interface, None)
1268 });
1269 created = Some((child_id.clone(), child_data_ptr));
1270 parsed_args.push(Argument::NewId(child_id));
1271 } else {
1272 parsed_args.push(Argument::NewId(ObjectId {
1273 alive: None,
1274 id: 0,
1275 ptr: std::ptr::null_mut(),
1276 interface: &ANONYMOUS_INTERFACE,
1277 }))
1278 }
1279 }
1280 }
1281 }
1282
1283 let object_id = ObjectId {
1284 ptr: resource,
1285 id: resource_id,
1286 interface: udata.interface,
1287 alive: Some(udata.alive.clone()),
1288 };
1289
1290 let client_id = client_id_from_ptr::<D>(client).unwrap();
1291
1292 let ret = HANDLE.with(|&(handle_ptr, data_ptr)| {
1293 let handle = &mut *(handle_ptr as *mut Handle<D>);
1294 let data = &mut *(data_ptr as *mut D);
1295 udata.data.clone().request(
1296 handle,
1297 data,
1298 client_id.clone(),
1299 Message { sender_id: object_id.clone(), opcode: opcode as u16, args: parsed_args },
1300 )
1301 });
1302
1303 if message_desc.is_destructor {
1304 ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_resource_destroy, resource);
1305 }
1306
1307 match (created, ret) {
1308 (Some((_, child_udata_ptr)), Some(child_data)) => {
1309 (*child_udata_ptr).data = child_data;
1310 }
1311 (Some((child_id, _)), None) => {
1312 panic!("Callback creating object {} did not provide any object data.", child_id);
1313 }
1314 (None, Some(_)) => {
1315 panic!("An object data was returned from a callback not creating any object");
1316 }
1317 (None, None) => {}
1318 }
1319
1320 0
1321 }
1322
resource_destructor<D>(resource: *mut wl_resource)1323 unsafe extern "C" fn resource_destructor<D>(resource: *mut wl_resource) {
1324 let udata =
1325 Box::from_raw(ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_resource_get_user_data, resource)
1326 as *mut ResourceUserData<D>);
1327 let id = ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_resource_get_id, resource);
1328 let client = ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_resource_get_client, resource);
1329 // if this destructor is invoked during cleanup, the client ptr is no longer valid
1330 let client_id = client_id_from_ptr::<D>(client)
1331 .unwrap_or(ClientId { ptr: std::ptr::null_mut(), alive: Arc::new(AtomicBool::new(false)) });
1332 udata.alive.store(false, Ordering::Release);
1333 let object_id = ObjectId {
1334 interface: udata.interface,
1335 ptr: resource,
1336 alive: Some(udata.alive.clone()),
1337 id,
1338 };
1339 if HANDLE.is_set() {
1340 HANDLE.with(|&(_, data_ptr)| {
1341 let data = &mut *(data_ptr as *mut D);
1342 udata.data.destroyed(data, client_id, object_id);
1343 });
1344 } else {
1345 PENDING_DESTRUCTORS.with(|&pending_ptr| {
1346 let pending = &mut *(pending_ptr as *mut Vec<PendingDestructor<D>>);
1347 pending.push((udata.data.clone(), client_id, object_id));
1348 })
1349 }
1350 }
1351
1352 extern "C" {
wl_log_trampoline_to_rust_server(fmt: *const c_char, list: *const c_void)1353 fn wl_log_trampoline_to_rust_server(fmt: *const c_char, list: *const c_void);
1354 }
1355
1356 struct UninitObjectData;
1357
1358 impl<D> ObjectData<D> for UninitObjectData {
request( self: Arc<Self>, _: &mut Handle<D>, _: &mut D, _: ClientId, msg: Message<ObjectId>, ) -> Option<Arc<dyn ObjectData<D>>>1359 fn request(
1360 self: Arc<Self>,
1361 _: &mut Handle<D>,
1362 _: &mut D,
1363 _: ClientId,
1364 msg: Message<ObjectId>,
1365 ) -> Option<Arc<dyn ObjectData<D>>> {
1366 panic!("Received a message on an uninitialized object: {:?}", msg);
1367 }
1368
destroyed(&self, _: &mut D, _: ClientId, _: ObjectId)1369 fn destroyed(&self, _: &mut D, _: ClientId, _: ObjectId) {}
1370
debug(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result1371 fn debug(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1372 f.debug_struct("UninitObjectData").finish()
1373 }
1374 }
1375