wayland_backend/rs/client_impl/
mod.rs

1//! Client-side rust implementation of a Wayland protocol backend
2
3use std::{
4    fmt,
5    os::unix::{
6        io::{AsRawFd, BorrowedFd, OwnedFd, RawFd},
7        net::UnixStream,
8    },
9    sync::{Arc, Condvar, Mutex, MutexGuard, Weak},
10};
11
12use crate::{
13    core_interfaces::WL_DISPLAY_INTERFACE,
14    debug,
15    protocol::{
16        check_for_signature, same_interface, same_interface_or_anonymous, AllowNull, Argument,
17        ArgumentType, Interface, Message, ObjectInfo, ProtocolError, ANONYMOUS_INTERFACE,
18        INLINE_ARGS,
19    },
20};
21use smallvec::SmallVec;
22
23use super::{
24    client::*,
25    map::{Object, ObjectMap, SERVER_ID_LIMIT},
26    socket::{BufferedSocket, Socket},
27    wire::MessageParseError,
28};
29
30#[derive(Debug, Clone)]
31struct Data {
32    client_destroyed: bool,
33    server_destroyed: bool,
34    user_data: Arc<dyn ObjectData>,
35    serial: u32,
36}
37
38/// An ID representing a Wayland object
39#[derive(Clone)]
40pub struct InnerObjectId {
41    serial: u32,
42    id: u32,
43    interface: &'static Interface,
44}
45
46impl std::cmp::PartialEq for InnerObjectId {
47    fn eq(&self, other: &Self) -> bool {
48        self.id == other.id
49            && self.serial == other.serial
50            && same_interface(self.interface, other.interface)
51    }
52}
53
54impl std::cmp::Eq for InnerObjectId {}
55
56impl std::hash::Hash for InnerObjectId {
57    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
58        self.serial.hash(state);
59        self.id.hash(state);
60    }
61}
62
63impl fmt::Display for InnerObjectId {
64    #[cfg_attr(unstable_coverage, coverage(off))]
65    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
66        write!(f, "{}@{}", self.interface.name, self.id)
67    }
68}
69
70impl fmt::Debug for InnerObjectId {
71    #[cfg_attr(unstable_coverage, coverage(off))]
72    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
73        write!(f, "ObjectId({}, {})", self, self.serial)
74    }
75}
76
77impl InnerObjectId {
78    pub fn is_null(&self) -> bool {
79        self.id == 0
80    }
81
82    pub fn interface(&self) -> &'static Interface {
83        self.interface
84    }
85
86    pub fn protocol_id(&self) -> u32 {
87        self.id
88    }
89}
90
91#[derive(Debug)]
92struct ProtocolState {
93    socket: BufferedSocket,
94    map: ObjectMap<Data>,
95    last_error: Option<WaylandError>,
96    last_serial: u32,
97    debug: bool,
98}
99
100#[derive(Debug)]
101struct ReadingState {
102    prepared_reads: usize,
103    read_condvar: Arc<Condvar>,
104    read_serial: usize,
105}
106
107#[derive(Debug)]
108pub struct ConnectionState {
109    protocol: Mutex<ProtocolState>,
110    read: Mutex<ReadingState>,
111}
112
113impl ConnectionState {
114    fn lock_protocol(&self) -> MutexGuard<'_, ProtocolState> {
115        self.protocol.lock().unwrap()
116    }
117
118    fn lock_read(&self) -> MutexGuard<'_, ReadingState> {
119        self.read.lock().unwrap()
120    }
121}
122
123#[derive(Clone, Debug)]
124pub struct InnerBackend {
125    state: Arc<ConnectionState>,
126}
127
128#[derive(Clone, Debug)]
129pub struct WeakInnerBackend {
130    state: Weak<ConnectionState>,
131}
132
133impl WeakInnerBackend {
134    pub fn upgrade(&self) -> Option<InnerBackend> {
135        Weak::upgrade(&self.state).map(|state| InnerBackend { state })
136    }
137}
138
139impl PartialEq for InnerBackend {
140    fn eq(&self, rhs: &Self) -> bool {
141        Arc::ptr_eq(&self.state, &rhs.state)
142    }
143}
144
145impl Eq for InnerBackend {}
146
147impl InnerBackend {
148    pub fn downgrade(&self) -> WeakInnerBackend {
149        WeakInnerBackend { state: Arc::downgrade(&self.state) }
150    }
151
152    pub fn connect(stream: UnixStream) -> Result<Self, NoWaylandLib> {
153        let socket = BufferedSocket::new(Socket::from(stream));
154        let mut map = ObjectMap::new();
155        map.insert_at(
156            1,
157            Object {
158                interface: &WL_DISPLAY_INTERFACE,
159                version: 1,
160                data: Data {
161                    client_destroyed: false,
162                    server_destroyed: false,
163                    user_data: Arc::new(DumbObjectData),
164                    serial: 0,
165                },
166            },
167        )
168        .unwrap();
169
170        let debug = debug::has_debug_client_env();
171
172        Ok(Self {
173            state: Arc::new(ConnectionState {
174                protocol: Mutex::new(ProtocolState {
175                    socket,
176                    map,
177                    last_error: None,
178                    last_serial: 0,
179                    debug,
180                }),
181                read: Mutex::new(ReadingState {
182                    prepared_reads: 0,
183                    read_condvar: Arc::new(Condvar::new()),
184                    read_serial: 0,
185                }),
186            }),
187        })
188    }
189
190    /// Flush all pending outgoing requests to the server
191    pub fn flush(&self) -> Result<(), WaylandError> {
192        let mut guard = self.state.lock_protocol();
193        guard.no_last_error()?;
194        if let Err(e) = guard.socket.flush() {
195            return Err(guard.store_if_not_wouldblock_and_return_error(e));
196        }
197        Ok(())
198    }
199
200    pub fn poll_fd(&self) -> BorrowedFd<'_> {
201        let raw_fd = self.state.lock_protocol().socket.as_raw_fd();
202        // This allows the lifetime of the BorrowedFd to be tied to &self rather than the lock guard,
203        // which is the real safety concern
204        unsafe { BorrowedFd::borrow_raw(raw_fd) }
205    }
206}
207
208#[derive(Debug)]
209pub struct InnerReadEventsGuard {
210    state: Arc<ConnectionState>,
211    done: bool,
212}
213
214impl InnerReadEventsGuard {
215    /// Create a new reading guard
216    ///
217    /// This call will not block, but event callbacks may be invoked in the process
218    /// of preparing the guard.
219    pub fn try_new(backend: InnerBackend) -> Option<Self> {
220        backend.state.lock_read().prepared_reads += 1;
221        Some(Self { state: backend.state, done: false })
222    }
223
224    /// Access the Wayland socket FD for polling
225    pub fn connection_fd(&self) -> BorrowedFd<'_> {
226        let raw_fd = self.state.lock_protocol().socket.as_raw_fd();
227        // This allows the lifetime of the BorrowedFd to be tied to &self rather than the lock guard,
228        // which is the real safety concern
229        unsafe { BorrowedFd::borrow_raw(raw_fd) }
230    }
231
232    /// Attempt to read events from the Wayland socket
233    ///
234    /// If multiple threads have a live reading guard, this method will block until all of them
235    /// are either dropped or have their `read()` method invoked, at which point on of the threads
236    /// will read events from the socket and invoke the callbacks for the received events. All
237    /// threads will then resume their execution.
238    ///
239    /// This returns the number of dispatched events, or `0` if an other thread handled the dispatching.
240    /// If no events are available to read from the socket, this returns a `WouldBlock` IO error.
241    pub fn read(mut self) -> Result<usize, WaylandError> {
242        let mut guard = self.state.lock_read();
243        guard.prepared_reads -= 1;
244        self.done = true;
245        if guard.prepared_reads == 0 {
246            // We should be the one reading
247            let ret = dispatch_events(self.state.clone());
248            // wake up other threads
249            guard.read_serial = guard.read_serial.wrapping_add(1);
250            guard.read_condvar.notify_all();
251            // forward the return value
252            ret
253        } else {
254            // We should wait for an other thread to read (or cancel)
255            let serial = guard.read_serial;
256            let condvar = guard.read_condvar.clone();
257            let _guard =
258                condvar.wait_while(guard, |backend| serial == backend.read_serial).unwrap();
259            self.state.lock_protocol().no_last_error()?;
260            Ok(0)
261        }
262    }
263}
264
265impl Drop for InnerReadEventsGuard {
266    fn drop(&mut self) {
267        if !self.done {
268            let mut guard = self.state.lock_read();
269            guard.prepared_reads -= 1;
270            if guard.prepared_reads == 0 {
271                // Cancel the read
272                guard.read_serial = guard.read_serial.wrapping_add(1);
273                guard.read_condvar.notify_all();
274            }
275        }
276    }
277}
278
279impl InnerBackend {
280    pub fn display_id(&self) -> ObjectId {
281        ObjectId { id: InnerObjectId { serial: 0, id: 1, interface: &WL_DISPLAY_INTERFACE } }
282    }
283
284    pub fn last_error(&self) -> Option<WaylandError> {
285        self.state.lock_protocol().last_error.clone()
286    }
287
288    pub fn info(&self, id: ObjectId) -> Result<ObjectInfo, InvalidId> {
289        let object = self.state.lock_protocol().get_object(id.id.clone())?;
290        if object.data.client_destroyed {
291            Err(InvalidId)
292        } else {
293            Ok(ObjectInfo { id: id.id.id, interface: object.interface, version: object.version })
294        }
295    }
296
297    pub fn null_id() -> ObjectId {
298        ObjectId { id: InnerObjectId { serial: 0, id: 0, interface: &ANONYMOUS_INTERFACE } }
299    }
300
301    pub fn destroy_object(&self, id: &ObjectId) -> Result<(), InvalidId> {
302        let mut guard = self.state.lock_protocol();
303        let object = guard.get_object(id.id.clone())?;
304        guard
305            .map
306            .with(id.id.id, |obj| {
307                if obj.data.client_destroyed {
308                    return Err(InvalidId);
309                }
310                obj.data.client_destroyed = true;
311                Ok(())
312            })
313            .unwrap()?;
314        object.data.user_data.destroyed(id.clone());
315        Ok(())
316    }
317
318    pub fn send_request(
319        &self,
320        Message { sender_id: ObjectId { id }, opcode, args }: Message<ObjectId, RawFd>,
321        data: Option<Arc<dyn ObjectData>>,
322        child_spec: Option<(&'static Interface, u32)>,
323    ) -> Result<ObjectId, InvalidId> {
324        let mut guard = self.state.lock_protocol();
325        let object = guard.get_object(id.clone())?;
326
327        let message_desc = match object.interface.requests.get(opcode as usize) {
328            Some(msg) => msg,
329            None => {
330                panic!("Unknown opcode {} for object {}@{}.", opcode, object.interface.name, id.id);
331            }
332        };
333
334        if object.data.client_destroyed {
335            if guard.debug {
336                debug::print_send_message(id.interface.name, id.id, message_desc.name, &args, true);
337            }
338            return Err(InvalidId);
339        }
340
341        if !check_for_signature(message_desc.signature, &args) {
342            panic!(
343                "Unexpected signature for request {}@{}.{}: expected {:?}, got {:?}.",
344                object.interface.name, id.id, message_desc.name, message_desc.signature, args
345            );
346        }
347
348        // Prepare the child object
349        let child_spec = if message_desc
350            .signature
351            .iter()
352            .any(|arg| matches!(arg, ArgumentType::NewId))
353        {
354            if let Some((iface, version)) = child_spec {
355                if let Some(child_interface) = message_desc.child_interface {
356                    if !same_interface(child_interface, iface) {
357                        panic!(
358                            "Error when sending request {}@{}.{}: expected interface {} but got {}",
359                            object.interface.name,
360                            id.id,
361                            message_desc.name,
362                            child_interface.name,
363                            iface.name
364                        );
365                    }
366                    if version != object.version {
367                        panic!(
368                            "Error when sending request {}@{}.{}: expected version {} but got {}",
369                            object.interface.name,
370                            id.id,
371                            message_desc.name,
372                            object.version,
373                            version
374                        );
375                    }
376                }
377                Some((iface, version))
378            } else if let Some(child_interface) = message_desc.child_interface {
379                Some((child_interface, object.version))
380            } else {
381                panic!(
382                    "Error when sending request {}@{}.{}: target interface must be specified for a generic constructor.",
383                    object.interface.name,
384                    id.id,
385                    message_desc.name
386                );
387            }
388        } else {
389            None
390        };
391
392        let child = if let Some((child_interface, child_version)) = child_spec {
393            let child_serial = guard.next_serial();
394
395            let child = Object {
396                interface: child_interface,
397                version: child_version,
398                data: Data {
399                    client_destroyed: false,
400                    server_destroyed: false,
401                    user_data: Arc::new(DumbObjectData),
402                    serial: child_serial,
403                },
404            };
405
406            let child_id = guard.map.client_insert_new(child);
407
408            guard
409                .map
410                .with(child_id, |obj| {
411                    obj.data.user_data = data.expect(
412                        "Sending a request creating an object without providing an object data.",
413                    );
414                })
415                .unwrap();
416            Some((child_id, child_serial, child_interface))
417        } else {
418            None
419        };
420
421        // Prepare the message in a debug-compatible way
422        let args = args.into_iter().map(|arg| {
423            if let Argument::NewId(ObjectId { id: p }) = arg {
424                if p.id != 0 {
425                    panic!("The newid provided when sending request {}@{}.{} is not a placeholder.", object.interface.name, id.id, message_desc.name);
426                }
427                if let Some((child_id, child_serial, child_interface)) = child {
428                    Argument::NewId(ObjectId { id: InnerObjectId { id: child_id, serial: child_serial, interface: child_interface}})
429                } else {
430                    unreachable!();
431                }
432            } else {
433                arg
434            }
435        }).collect::<SmallVec<[_; INLINE_ARGS]>>();
436
437        if guard.debug {
438            debug::print_send_message(
439                object.interface.name,
440                id.id,
441                message_desc.name,
442                &args,
443                false,
444            );
445        }
446        #[cfg(feature = "log")]
447        crate::log_debug!("Sending {}.{} ({})", id, message_desc.name, debug::DisplaySlice(&args));
448
449        // Send the message
450
451        let mut msg_args = SmallVec::with_capacity(args.len());
452        let mut arg_interfaces = message_desc.arg_interfaces.iter();
453        for (i, arg) in args.into_iter().enumerate() {
454            msg_args.push(match arg {
455                Argument::Array(a) => Argument::Array(a),
456                Argument::Int(i) => Argument::Int(i),
457                Argument::Uint(u) => Argument::Uint(u),
458                Argument::Str(s) => Argument::Str(s),
459                Argument::Fixed(f) => Argument::Fixed(f),
460                Argument::NewId(nid) => Argument::NewId(nid.id.id),
461                Argument::Fd(f) => Argument::Fd(f),
462                Argument::Object(o) => {
463                    let next_interface = arg_interfaces.next().unwrap();
464                    if o.id.id != 0 {
465                        let arg_object = guard.get_object(o.id.clone())?;
466                        if !same_interface_or_anonymous(next_interface, arg_object.interface) {
467                            panic!("Request {}@{}.{} expects an argument of interface {} but {} was provided instead.", object.interface.name, id.id, message_desc.name, next_interface.name, arg_object.interface.name);
468                        }
469                    } else if !matches!(message_desc.signature[i], ArgumentType::Object(AllowNull::Yes)) {
470                        panic!("Request {}@{}.{} expects an non-null object argument.", object.interface.name, id.id, message_desc.name);
471                    }
472                    Argument::Object(o.id.id)
473                }
474            });
475        }
476
477        let msg = Message { sender_id: id.id, opcode, args: msg_args };
478
479        if let Err(err) = guard.socket.write_message(&msg) {
480            guard.last_error = Some(WaylandError::Io(err));
481        }
482
483        // Handle destruction if relevant
484        if message_desc.is_destructor {
485            guard
486                .map
487                .with(id.id, |obj| {
488                    obj.data.client_destroyed = true;
489                })
490                .unwrap();
491            object.data.user_data.destroyed(ObjectId { id });
492        }
493        if let Some((child_id, child_serial, child_interface)) = child {
494            Ok(ObjectId {
495                id: InnerObjectId {
496                    id: child_id,
497                    serial: child_serial,
498                    interface: child_interface,
499                },
500            })
501        } else {
502            Ok(Self::null_id())
503        }
504    }
505
506    pub fn get_data(&self, id: ObjectId) -> Result<Arc<dyn ObjectData>, InvalidId> {
507        let object = self.state.lock_protocol().get_object(id.id)?;
508        Ok(object.data.user_data)
509    }
510
511    pub fn set_data(&self, id: ObjectId, data: Arc<dyn ObjectData>) -> Result<(), InvalidId> {
512        self.state
513            .lock_protocol()
514            .map
515            .with(id.id.id, move |objdata| {
516                if objdata.data.serial != id.id.serial {
517                    Err(InvalidId)
518                } else {
519                    objdata.data.user_data = data;
520                    Ok(())
521                }
522            })
523            .unwrap_or(Err(InvalidId))
524    }
525
526    // Nothing to do here, we don't have an inner queue
527    pub fn dispatch_inner_queue(&self) -> Result<usize, WaylandError> {
528        Ok(0)
529    }
530}
531
532impl ProtocolState {
533    fn next_serial(&mut self) -> u32 {
534        self.last_serial = self.last_serial.wrapping_add(1);
535        self.last_serial
536    }
537
538    #[inline]
539    fn no_last_error(&self) -> Result<(), WaylandError> {
540        if let Some(ref err) = self.last_error {
541            Err(err.clone())
542        } else {
543            Ok(())
544        }
545    }
546
547    #[inline]
548    fn store_and_return_error(&mut self, err: impl Into<WaylandError>) -> WaylandError {
549        let err = err.into();
550        crate::log_error!("{err}");
551        self.last_error = Some(err.clone());
552        err
553    }
554
555    #[inline]
556    fn store_if_not_wouldblock_and_return_error(&mut self, e: std::io::Error) -> WaylandError {
557        if e.kind() != std::io::ErrorKind::WouldBlock {
558            self.store_and_return_error(e)
559        } else {
560            e.into()
561        }
562    }
563
564    fn get_object(&self, id: InnerObjectId) -> Result<Object<Data>, InvalidId> {
565        let object = self.map.find(id.id).ok_or(InvalidId)?;
566        if object.data.serial != id.serial {
567            return Err(InvalidId);
568        }
569        Ok(object)
570    }
571
572    fn handle_display_event(&mut self, message: Message<u32, OwnedFd>) -> Result<(), WaylandError> {
573        if self.debug {
574            debug::print_dispatched_message(
575                "wl_display",
576                message.sender_id,
577                if message.opcode == 0 { "error" } else { "delete_id" },
578                &message.args,
579            );
580        }
581        match message.opcode {
582            0 => {
583                // wl_display.error
584                if let [Argument::Object(obj), Argument::Uint(code), Argument::Str(Some(ref message))] =
585                    message.args[..]
586                {
587                    let object = self.map.find(obj);
588                    let err = WaylandError::Protocol(ProtocolError {
589                        code,
590                        object_id: obj,
591                        object_interface: object
592                            .map(|obj| obj.interface.name)
593                            .unwrap_or("<unknown>")
594                            .into(),
595                        message: message.to_string_lossy().into(),
596                    });
597                    return Err(self.store_and_return_error(err));
598                } else {
599                    unreachable!()
600                }
601            }
602            1 => {
603                // wl_display.delete_id
604                if let [Argument::Uint(id)] = message.args[..] {
605                    let client_destroyed = self
606                        .map
607                        .with(id, |obj| {
608                            obj.data.server_destroyed = true;
609                            obj.data.client_destroyed
610                        })
611                        .unwrap_or(false);
612                    if client_destroyed {
613                        self.map.remove(id);
614                    }
615                } else {
616                    unreachable!()
617                }
618            }
619            _ => unreachable!(),
620        }
621        Ok(())
622    }
623}
624
625fn dispatch_events(state: Arc<ConnectionState>) -> Result<usize, WaylandError> {
626    let backend = Backend { backend: InnerBackend { state } };
627    let mut guard = backend.backend.state.lock_protocol();
628    guard.no_last_error()?;
629    let mut dispatched = 0;
630    loop {
631        // Attempt to read a message
632        let ProtocolState { ref mut socket, ref map, .. } = *guard;
633        let message = match socket.read_one_message(|id, opcode| {
634            map.find(id)
635                .and_then(|o| o.interface.events.get(opcode as usize))
636                .map(|desc| desc.signature)
637        }) {
638            Ok(msg) => msg,
639            Err(MessageParseError::MissingData) | Err(MessageParseError::MissingFD) => {
640                // need to read more data
641                if let Err(e) = guard.socket.fill_incoming_buffers() {
642                    if e.kind() != std::io::ErrorKind::WouldBlock {
643                        return Err(guard.store_and_return_error(e));
644                    } else if dispatched == 0 {
645                        return Err(e.into());
646                    } else {
647                        break;
648                    }
649                }
650                continue;
651            }
652            Err(MessageParseError::Malformed) => {
653                // malformed error, protocol error
654                let err = WaylandError::Protocol(ProtocolError {
655                    code: 0,
656                    object_id: 0,
657                    object_interface: "".into(),
658                    message: "Malformed Wayland message.".into(),
659                });
660                return Err(guard.store_and_return_error(err));
661            }
662        };
663
664        // We got a message, retrieve its associated object & details
665        // These lookups must succeed otherwise we would not have been able to parse this message
666        let receiver = guard.map.find(message.sender_id).unwrap();
667        let message_desc = receiver.interface.events.get(message.opcode as usize).unwrap();
668
669        // Short-circuit display-associated events
670        if message.sender_id == 1 {
671            guard.handle_display_event(message)?;
672            continue;
673        }
674
675        let mut created_id = None;
676
677        // Convert the arguments and create the new object if applicable
678        let mut args = SmallVec::with_capacity(message.args.len());
679        let mut arg_interfaces = message_desc.arg_interfaces.iter();
680        for arg in message.args.into_iter() {
681            args.push(match arg {
682                Argument::Array(a) => Argument::Array(a),
683                Argument::Int(i) => Argument::Int(i),
684                Argument::Uint(u) => Argument::Uint(u),
685                Argument::Str(s) => Argument::Str(s),
686                Argument::Fixed(f) => Argument::Fixed(f),
687                Argument::Fd(f) => Argument::Fd(f),
688                Argument::Object(o) => {
689                    if o != 0 {
690                        // Lookup the object to make the appropriate Id
691                        let obj = match guard.map.find(o) {
692                            Some(o) => o,
693                            None => {
694                                let err = WaylandError::Protocol(ProtocolError {
695                                    code: 0,
696                                    object_id: 0,
697                                    object_interface: "".into(),
698                                    message: format!("Unknown object {o}."),
699                                });
700                                return Err(guard.store_and_return_error(err));
701                            }
702                        };
703                        if let Some(next_interface) = arg_interfaces.next() {
704                            if !same_interface_or_anonymous(next_interface, obj.interface) {
705                                let err = WaylandError::Protocol(ProtocolError {
706                                    code: 0,
707                                    object_id: 0,
708                                    object_interface: "".into(),
709                                    message: format!(
710                                        "Protocol error: server sent object {} for interface {}, but it has interface {}.",
711                                        o, next_interface.name, obj.interface.name
712                                    ),
713                                });
714                                return Err(guard.store_and_return_error(err));
715                            }
716                        }
717                        Argument::Object(ObjectId { id: InnerObjectId { id: o, serial: obj.data.serial, interface: obj.interface }})
718                    } else {
719                        Argument::Object(ObjectId { id: InnerObjectId { id: 0, serial: 0, interface: &ANONYMOUS_INTERFACE }})
720                    }
721                }
722                Argument::NewId(new_id) => {
723                    // An object should be created
724                    let child_interface = match message_desc.child_interface {
725                        Some(iface) => iface,
726                        None => panic!("Received event {}@{}.{} which creates an object without specifying its interface, this is unsupported.", receiver.interface.name, message.sender_id, message_desc.name),
727                    };
728
729                    let child_udata = Arc::new(UninitObjectData);
730
731                    // if this ID belonged to a now destroyed server object, we can replace it
732                    if new_id >= SERVER_ID_LIMIT
733                        && guard.map.with(new_id, |obj| obj.data.client_destroyed).unwrap_or(false)
734                    {
735                        guard.map.remove(new_id);
736                    }
737
738                    let child_obj = Object {
739                        interface: child_interface,
740                        version: receiver.version,
741                        data: Data {
742                            client_destroyed: receiver.data.client_destroyed,
743                            server_destroyed: false,
744                            user_data: child_udata,
745                            serial: guard.next_serial(),
746                        }
747                    };
748
749                    let child_id = InnerObjectId { id: new_id, serial: child_obj.data.serial, interface: child_obj.interface };
750                    created_id = Some(child_id.clone());
751
752                    if let Err(()) = guard.map.insert_at(new_id, child_obj) {
753                        // abort parsing, this is an unrecoverable error
754                        let err = WaylandError::Protocol(ProtocolError {
755                            code: 0,
756                            object_id: 0,
757                            object_interface: "".into(),
758                            message: format!(
759                                "Protocol error: server tried to create \
760                                an object \"{}\" with invalid id {}.",
761                                child_interface.name, new_id
762                            ),
763                        });
764                        return Err(guard.store_and_return_error(err));
765                    }
766
767                    Argument::NewId(ObjectId { id: child_id })
768                }
769            });
770        }
771
772        if guard.debug {
773            debug::print_dispatched_message(
774                receiver.interface.name,
775                message.sender_id,
776                message_desc.name,
777                &args,
778            );
779        }
780
781        // If this event is send to an already destroyed object (by the client), swallow it
782        if receiver.data.client_destroyed {
783            continue;
784        }
785
786        // Invoke the user callback
787        let id = InnerObjectId {
788            id: message.sender_id,
789            serial: receiver.data.serial,
790            interface: receiver.interface,
791        };
792
793        // unlock the mutex while we invoke the user callback
794        std::mem::drop(guard);
795        #[cfg(feature = "log")]
796        crate::log_debug!(
797            "Dispatching {}.{} ({})",
798            id,
799            receiver.version,
800            debug::DisplaySlice(&args)
801        );
802        let ret = receiver
803            .data
804            .user_data
805            .clone()
806            .event(&backend, Message { sender_id: ObjectId { id }, opcode: message.opcode, args });
807        // lock it again to resume dispatching
808        guard = backend.backend.state.lock_protocol();
809
810        // If this event is a destructor, destroy the object
811        if message_desc.is_destructor {
812            guard
813                .map
814                .with(message.sender_id, |obj| {
815                    obj.data.server_destroyed = true;
816                    obj.data.client_destroyed = true;
817                })
818                .unwrap();
819            receiver.data.user_data.destroyed(ObjectId {
820                id: InnerObjectId {
821                    id: message.sender_id,
822                    serial: receiver.data.serial,
823                    interface: receiver.interface,
824                },
825            });
826        }
827
828        match (created_id, ret) {
829            (Some(child_id), Some(child_data)) => {
830                guard.map.with(child_id.id, |obj| obj.data.user_data = child_data).unwrap();
831            }
832            (None, None) => {}
833            (Some(child_id), None) => {
834                panic!("Callback creating object {child_id} did not provide any object data.");
835            }
836            (None, Some(_)) => {
837                panic!("An object data was returned from a callback not creating any object");
838            }
839        }
840
841        dispatched += 1;
842    }
843    Ok(dispatched)
844}