wl_client/
libwayland_test.rs

1#![allow(unsafe_op_in_unsafe_fn)]
2
3use {
4    crate::{
5        Fixed,
6        ffi::{
7            WL_MARSHAL_FLAG_DESTROY, wl_argument, wl_array, wl_dispatcher_func_t, wl_display,
8            wl_event_queue, wl_interface, wl_proxy,
9        },
10        protocols,
11        proxy::OwnedProxy,
12        test_protocols::core::{
13            wl_callback::WlCallback, wl_display::WlDisplay, wl_dummy::WlDummy,
14            wl_registry::WlRegistry, wl_root::WlRoot, wl_string::WlString,
15        },
16    },
17    isnt::std_1::{primitive::IsntMutPtrExt, vec::IsntVecExt},
18    parking_lot::{Condvar, Mutex},
19    std::{
20        cell::{Cell, UnsafeCell},
21        collections::VecDeque,
22        ffi::{CStr, CString, c_char, c_int, c_void},
23        io::{self, ErrorKind},
24        mem,
25        os::{
26            fd::{AsRawFd, FromRawFd, IntoRawFd, OwnedFd},
27            unix::net::UnixStream,
28        },
29        ptr::{self, NonNull},
30        sync::atomic::{AtomicBool, Ordering::Relaxed},
31    },
32};
33
34/// This type is a libwayland mock. It implements both the libwayland API (insofar as this
35/// crate uses it) and mocks a wayland compositor. This wayland compositor implements
36/// the wayland protocol from test_protocols/core.xml in the crate root.
37///
38/// This code is only compiled in unit tests and unlike the rest of the code it does not
39/// carefully document its unsafe code. All of the unit tests are run with miri which
40/// should alert us of any issues.
41pub struct Libwayland(());
42
43#[repr(C)] // Note: The proxy must be the first field.
44struct Display {
45    wl_display: Proxy,
46    name: CString,
47    default_queue: Queue,
48    lock: Mutex<()>,
49    condvar: Condvar,
50    client_fd: OwnedFd,
51    server_fd: OwnedFd,
52    data: UnsafeCell<DisplayMut>,
53    error: Cell<bool>,
54    destroy_blockers: Cell<u64>,
55    destroy_blocked: Cell<u64>,
56}
57
58struct DisplayMut {
59    leaked_memory: bool,
60    num_queues: usize,
61    new_events: Vec<Event>,
62    new_events_after_flush: Vec<Event>,
63    num_read_locks: u64,
64    read_serial: u64,
65    next_id: u32,
66}
67
68struct Event {
69    proxy: *mut Proxy,
70    interface: &'static wl_interface,
71    opcode: u32,
72    args: Vec<Argument>,
73}
74
75#[expect(dead_code)]
76enum Argument {
77    I(i32),
78    U(u32),
79    F(Fixed),
80    S(CString),
81    O(*mut Proxy),
82    N(*mut Proxy),
83    A(wl_array),
84    H(Option<OwnedFd>),
85}
86
87struct Proxy {
88    id: u32,
89    version: u32,
90    interface: *const wl_interface,
91    display: *mut Display,
92    is_wrapper: bool,
93    destroyed: AtomicBool,
94    data: UnsafeCell<ProxyMut>,
95    dispatcher_data: UnsafeCell<ProxyDispatcherData>,
96}
97
98struct ProxyMut {
99    ref_count: u64,
100    queue: *mut Queue,
101}
102
103struct ProxyDispatcherData {
104    func: Option<wl_dispatcher_func_t>,
105    data: *mut c_void,
106}
107
108struct Queue {
109    display: *mut Display,
110    _name: Option<String>,
111    data: UnsafeCell<QueueMut>,
112}
113
114struct QueueMut {
115    num_proxies: usize,
116    events: VecDeque<Event>,
117}
118
119impl Drop for Event {
120    fn drop(&mut self) {
121        unsafe {
122            dec_proxy_ref_count(self.proxy);
123        }
124        self.args.clear();
125    }
126}
127
128impl Drop for Argument {
129    fn drop(&mut self) {
130        unsafe {
131            match self {
132                Argument::A(array) => {
133                    let _vec =
134                        Vec::from_raw_parts(array.data.cast::<u8>(), array.size, array.alloc);
135                }
136                Argument::O(o) => {
137                    if o.is_not_null() {
138                        dec_proxy_ref_count(*o);
139                    }
140                }
141                Argument::N(o) => {
142                    if o.is_not_null() {
143                        (*(*(**o).display).data.get()).leaked_memory = true;
144                        dec_proxy_ref_count(*o);
145                    }
146                }
147                _ => {}
148            }
149        }
150    }
151}
152
153unsafe fn dec_proxy_ref_count(proxy_ptr: *mut Proxy) {
154    let proxy = &*proxy_ptr;
155    let proxy_mut = &mut *proxy.data.get();
156    proxy_mut.ref_count -= 1;
157    if proxy_mut.ref_count == 0 {
158        let queue = &*proxy_mut.queue;
159        let queue_mut = &mut *queue.data.get();
160        queue_mut.num_proxies -= 1;
161        let _ = Box::from_raw(proxy_ptr);
162    }
163}
164
165unsafe fn inc_proxy_ref_count(proxy_ptr: *mut Proxy) -> *mut Proxy {
166    assert!(!proxy_ptr.is_null());
167    let proxy = &*proxy_ptr;
168    let proxy_mut = &mut *proxy.data.get();
169    proxy_mut.ref_count += 1;
170    proxy_ptr
171}
172
173impl Libwayland {
174    pub fn open() -> io::Result<&'static Self> {
175        static SELF: Libwayland = Libwayland(());
176        Ok(&SELF)
177    }
178
179    pub(crate) unsafe fn wl_display_create_queue_with_name(
180        &self,
181        display_ptr: *mut wl_display,
182        name: *const c_char,
183    ) -> *mut wl_event_queue {
184        let display = &*display_ptr.cast::<Display>();
185        let _lock = display.lock.lock();
186        let display_mut = &mut *display.data.get();
187        display_mut.num_queues += 1;
188        let name = if name.is_null() {
189            None
190        } else {
191            Some(CStr::from_ptr(name).to_str().unwrap().to_string())
192        };
193        let queue = Box::into_raw(Box::new(Queue {
194            display: display_ptr.cast(),
195            _name: name,
196            data: UnsafeCell::new(QueueMut {
197                num_proxies: 0,
198                events: Default::default(),
199            }),
200        }));
201        queue.cast()
202    }
203
204    pub(crate) unsafe fn wl_event_queue_destroy(&self, queue: *mut wl_event_queue) {
205        let queue_ptr = queue.cast::<Queue>();
206        let queue = &*queue_ptr;
207        let display = &*queue.display;
208        let _lock = display.lock.lock();
209        let events = {
210            let queue_mut = &mut *queue.data.get();
211            mem::take(&mut queue_mut.events)
212        };
213        drop(events);
214        let queue_mut = &mut *queue.data.get();
215        assert_eq!(queue_mut.num_proxies, 0);
216        let display_mut = &mut *display.data.get();
217        display_mut.num_queues -= 1;
218        let _ = Box::from_raw(queue_ptr);
219    }
220
221    pub(crate) unsafe fn wl_proxy_marshal_array_flags(
222        &self,
223        proxy_ptr: *mut wl_proxy,
224        opcode: u32,
225        interface: *const wl_interface,
226        version: u32,
227        flags: u32,
228        args: *mut wl_argument,
229    ) -> *mut wl_proxy {
230        let proxy = &*proxy_ptr.cast::<Proxy>();
231        let display = &*proxy.display;
232        let _lock = display.lock.lock();
233        if display.error.get() {
234            return ptr::null_mut();
235        }
236        let display_mut = &mut *display.data.get();
237        let mut ret = ptr::null_mut();
238        if proxy.interface == WlDisplay::WL_INTERFACE {
239            match opcode {
240                // sync
241                0 => {
242                    if interface != WlCallback::WL_INTERFACE
243                        && interface != protocols::wayland::wl_callback::WlCallback::WL_INTERFACE
244                    {
245                        unreachable!();
246                    }
247                    ret = self.create_proxy(version, display_mut, proxy, interface);
248                    let event = Event {
249                        proxy: ret,
250                        interface: WlCallback::WL_INTERFACE,
251                        // done
252                        opcode: 0,
253                        args: vec![Argument::U(0)],
254                    };
255                    self.send_event(display_mut, event);
256                }
257                // get_registry
258                1 => {
259                    if interface != WlRegistry::WL_INTERFACE {
260                        unreachable!();
261                    }
262                    ret = self.create_proxy(version, display_mut, proxy, interface);
263                }
264                _ => unreachable!(),
265            }
266        } else if proxy.interface == WlRegistry::WL_INTERFACE {
267            match opcode {
268                // bind
269                0 => {
270                    if interface != WlRoot::WL_INTERFACE {
271                        unreachable!();
272                    }
273                    ret = self.create_proxy(version, display_mut, proxy, interface);
274                }
275                _ => unreachable!(),
276            }
277        } else if proxy.interface == WlRoot::WL_INTERFACE {
278            match opcode {
279                // create_dummy
280                0 => {
281                    if interface != WlDummy::WL_INTERFACE {
282                        unreachable!();
283                    }
284                    ret = self.create_proxy(version, display_mut, proxy, interface);
285                }
286                // ping_dummy
287                1 => {
288                    let args = &*args.cast::<[wl_argument; 1]>();
289                    let event = Event {
290                        proxy: proxy_ptr.cast(),
291                        interface: WlRoot::WL_INTERFACE,
292                        // pong_dummy
293                        opcode: 0,
294                        args: vec![Argument::O(args[0].o.cast())],
295                    };
296                    self.send_event(display_mut, event);
297                }
298                // destroy
299                2 => {}
300                // get_server_name
301                3 => {
302                    if interface != WlString::WL_INTERFACE {
303                        unreachable!();
304                    }
305                    ret = self.create_proxy(version, display_mut, proxy, interface);
306                    let event = Event {
307                        proxy: ret,
308                        interface: WlString::WL_INTERFACE,
309                        // string
310                        opcode: 0,
311                        args: vec![Argument::S(display.name.clone())],
312                    };
313                    self.send_event(display_mut, event);
314                }
315                // send_new_dummy
316                4 => {
317                    let new = self.create_proxy(version, display_mut, proxy, WlDummy::WL_INTERFACE);
318                    let event = Event {
319                        proxy: proxy_ptr.cast(),
320                        interface: WlRoot::WL_INTERFACE,
321                        // new_dummy
322                        opcode: 1,
323                        args: vec![Argument::N(new)],
324                    };
325                    self.send_event(display_mut, event);
326                }
327                // echo
328                5 => {
329                    if interface != WlString::WL_INTERFACE {
330                        unreachable!();
331                    }
332                    let string = CStr::from_ptr((*args.add(1)).s).to_owned();
333                    ret = self.create_proxy(version, display_mut, proxy, interface);
334                    let event = Event {
335                        proxy: ret,
336                        interface: WlString::WL_INTERFACE,
337                        // string
338                        opcode: 0,
339                        args: vec![Argument::S(string)],
340                    };
341                    self.send_event(display_mut, event);
342                }
343                // bind
344                6 => {
345                    if interface != WlDummy::WL_INTERFACE {
346                        unreachable!();
347                    }
348                    ret = self.create_proxy(version, display_mut, proxy, interface);
349                }
350                _ => unreachable!(),
351            }
352        } else if proxy.interface == WlDummy::WL_INTERFACE {
353            match opcode {
354                // destroy
355                0 => {}
356                // recycle
357                1 => {
358                    if interface != WlDummy::WL_INTERFACE {
359                        unreachable!();
360                    }
361                    ret = self.create_proxy(version, display_mut, proxy, interface);
362                }
363                // get_string
364                2 => {
365                    if interface != WlString::WL_INTERFACE {
366                        unreachable!();
367                    }
368                    ret = self.create_proxy(version, display_mut, proxy, interface);
369                }
370                _ => unreachable!(),
371            }
372        } else {
373            unreachable!();
374        }
375        if flags & WL_MARSHAL_FLAG_DESTROY != 0 {
376            self.destroy_proxy(proxy_ptr, false, false);
377        }
378        ret.cast()
379    }
380
381    unsafe fn send_event(&self, data: &mut DisplayMut, event: Event) {
382        inc_proxy_ref_count(event.proxy);
383        for arg in &event.args {
384            if let Argument::O(o) = arg {
385                inc_proxy_ref_count(*o);
386            }
387        }
388        data.new_events_after_flush.push(event);
389    }
390
391    unsafe fn create_proxy(
392        &self,
393        version: u32,
394        data: &mut DisplayMut,
395        parent: &Proxy,
396        interface: *const wl_interface,
397    ) -> *mut Proxy {
398        let queue = {
399            let proxy_mut = &*parent.data.get();
400            &*proxy_mut.queue
401        };
402        self.create_proxy_in_queue(version, data, queue, interface)
403    }
404
405    unsafe fn create_proxy_in_queue(
406        &self,
407        version: u32,
408        display_mut: &mut DisplayMut,
409        queue: &Queue,
410        interface: *const wl_interface,
411    ) -> *mut Proxy {
412        {
413            let queue_mut = &mut *queue.data.get();
414            queue_mut.num_proxies += 1;
415        }
416        let proxy = Box::into_raw(Box::new(Proxy {
417            id: display_mut.next_id,
418            version,
419            interface,
420            display: queue.display,
421            is_wrapper: false,
422            destroyed: Default::default(),
423            data: UnsafeCell::new(ProxyMut {
424                queue: ptr::from_ref(queue).cast_mut(),
425                ref_count: 1,
426            }),
427            dispatcher_data: UnsafeCell::new(ProxyDispatcherData {
428                func: None,
429                data: ptr::null_mut(),
430            }),
431        }));
432        display_mut.next_id += 1;
433        proxy
434    }
435
436    pub(crate) unsafe fn wl_proxy_create_wrapper(&self, proxy: *mut c_void) -> *mut c_void {
437        let proxy_ptr = proxy.cast::<Proxy>();
438        let proxy = &*proxy_ptr;
439        let display = &*proxy.display;
440        let _lock = display.lock.lock();
441        let proxy_mut = &mut *proxy.data.get();
442        let queue_ptr = proxy_mut.queue;
443        let queue = &*queue_ptr;
444        let queue_mut = &mut *queue.data.get();
445        queue_mut.num_proxies += 1;
446        let wrapper = Box::into_raw(Box::new(Proxy {
447            id: proxy.id,
448            version: proxy.version,
449            interface: proxy.interface,
450            display: proxy.display,
451            is_wrapper: true,
452            destroyed: Default::default(),
453            data: UnsafeCell::new(ProxyMut {
454                queue: queue_ptr,
455                ref_count: 1,
456            }),
457            dispatcher_data: UnsafeCell::new(ProxyDispatcherData {
458                func: None,
459                data: ptr::null_mut(),
460            }),
461        }));
462        wrapper.cast()
463    }
464
465    unsafe fn destroy_proxy(&self, proxy: *mut wl_proxy, wrapper: bool, lock: bool) {
466        let proxy_ptr = proxy.cast::<Proxy>();
467        let proxy = &*proxy_ptr;
468        assert_eq!(proxy.is_wrapper, wrapper);
469        let display = &*proxy.display;
470        let _lock = lock.then(|| {
471            let mut lock = display.lock.lock();
472            while display.destroy_blockers.get() > 0 {
473                display
474                    .destroy_blocked
475                    .set(display.destroy_blocked.get() + 1);
476                display.condvar.wait(&mut lock);
477                display
478                    .destroy_blocked
479                    .set(display.destroy_blocked.get() - 1);
480            }
481            lock
482        });
483        self.proxy_set_queue_locked(
484            proxy_ptr.cast(),
485            ptr::from_ref(&display.default_queue).cast_mut().cast(),
486        );
487        assert!(!proxy.destroyed.swap(true, Relaxed));
488        dec_proxy_ref_count(proxy_ptr);
489    }
490
491    pub(crate) unsafe fn wl_proxy_wrapper_destroy(&self, proxy: *mut c_void) {
492        self.destroy_proxy(proxy.cast(), true, true);
493    }
494
495    pub(crate) unsafe fn wl_proxy_destroy(&self, proxy: *mut wl_proxy) {
496        self.destroy_proxy(proxy.cast(), false, true);
497    }
498
499    pub(crate) unsafe fn wl_proxy_add_dispatcher(
500        &self,
501        proxy: *mut wl_proxy,
502        dispatcher_func: Option<wl_dispatcher_func_t>,
503        dispatcher_data: *mut c_void,
504        _data: *mut c_void,
505    ) {
506        let proxy = &*proxy.cast::<Proxy>();
507        let data = &mut *proxy.dispatcher_data.get();
508        assert!(data.func.is_none());
509        assert!(data.data.is_null());
510        data.func = dispatcher_func;
511        data.data = dispatcher_data;
512    }
513
514    pub(crate) unsafe fn wl_proxy_get_id(&self, proxy: *mut wl_proxy) -> u32 {
515        let proxy = &*proxy.cast::<Proxy>();
516        proxy.id
517    }
518
519    pub(crate) unsafe fn wl_proxy_get_version(&self, proxy: *mut wl_proxy) -> u32 {
520        let proxy = &*proxy.cast::<Proxy>();
521        proxy.version
522    }
523
524    unsafe fn proxy_set_queue_locked(&self, proxy: *mut wl_proxy, queue: *mut wl_event_queue) {
525        let proxy = &*proxy.cast::<Proxy>();
526        let display = &*proxy.display;
527        let new_queue = if queue.is_null() {
528            ptr::from_ref(&display.default_queue)
529        } else {
530            queue.cast::<Queue>()
531        };
532        let old_queue = {
533            let proxy_mut = &mut *proxy.data.get();
534            mem::replace(&mut proxy_mut.queue, new_queue.cast_mut())
535        };
536        {
537            let queue = &*old_queue;
538            let queue_mut = &mut *queue.data.get();
539            queue_mut.num_proxies -= 1;
540        }
541        {
542            let queue = &*new_queue;
543            assert_eq!(queue.display, proxy.display);
544            let queue_mut = &mut *queue.data.get();
545            queue_mut.num_proxies += 1;
546        }
547    }
548
549    pub(crate) unsafe fn wl_proxy_set_queue(
550        &self,
551        proxy_ptr: *mut wl_proxy,
552        queue: *mut wl_event_queue,
553    ) {
554        let proxy = &*proxy_ptr.cast::<Proxy>();
555        let display = &*proxy.display;
556        let _lock = display.lock.lock();
557        self.proxy_set_queue_locked(proxy_ptr, queue);
558    }
559
560    pub(crate) unsafe fn wl_display_connect(&self, name: *const c_char) -> *mut wl_display {
561        #[cfg(test)]
562        if test::FAIL_CONNECT.get() > 0 {
563            return ptr::null_mut();
564        }
565        let mut sockets = [0, 0];
566        #[cfg(target_os = "linux")]
567        let flags = libc::SOCK_STREAM | libc::SOCK_NONBLOCK | libc::SOCK_CLOEXEC;
568        #[cfg(not(target_os = "linux"))]
569        let flags = libc::SOCK_STREAM;
570        let ret = libc::socketpair(libc::AF_UNIX, flags, 0, sockets.as_mut_ptr());
571        assert_ne!(ret, -1);
572        let [c, s] = [
573            UnixStream::from(OwnedFd::from_raw_fd(sockets[0])),
574            UnixStream::from(OwnedFd::from_raw_fd(sockets[1])),
575        ];
576        #[cfg(not(target_os = "linux"))]
577        {
578            c.set_nonblocking(true).unwrap();
579            s.set_nonblocking(true).unwrap();
580        }
581        let display_ptr = Box::into_raw(Box::new(Display {
582            wl_display: Proxy {
583                id: 1,
584                version: 0,
585                interface: WlDisplay::WL_INTERFACE,
586                display: ptr::null_mut(),
587                is_wrapper: false,
588                destroyed: Default::default(),
589                data: UnsafeCell::new(ProxyMut {
590                    queue: ptr::null_mut(),
591                    ref_count: 1,
592                }),
593                dispatcher_data: UnsafeCell::new(ProxyDispatcherData {
594                    func: None,
595                    data: ptr::null_mut(),
596                }),
597            },
598            name: NonNull::new(name.cast_mut())
599                .map(|p| CStr::from_ptr(p.as_ptr()))
600                .unwrap_or(c"default-display")
601                .to_owned(),
602            lock: Default::default(),
603            condvar: Default::default(),
604            client_fd: c.into(),
605            server_fd: s.into(),
606            default_queue: Queue {
607                display: ptr::null_mut(),
608                _name: None,
609                data: UnsafeCell::new(QueueMut {
610                    num_proxies: 0,
611                    events: Default::default(),
612                }),
613            },
614            data: UnsafeCell::new(DisplayMut {
615                leaked_memory: false,
616                num_queues: 0,
617                new_events: vec![],
618                new_events_after_flush: vec![],
619                num_read_locks: 0,
620                read_serial: 0,
621                next_id: 2,
622            }),
623            error: Default::default(),
624            destroy_blockers: Cell::new(0),
625            destroy_blocked: Cell::new(0),
626        }));
627        (*display_ptr).wl_display.display = display_ptr;
628        (*display_ptr).wl_display.data.get_mut().queue = &raw mut (*display_ptr).default_queue;
629        (*display_ptr).default_queue.display = display_ptr;
630        display_ptr.cast()
631    }
632
633    pub(crate) unsafe fn wl_display_connect_to_fd(&self, _fd: c_int) -> *mut wl_display {
634        unreachable!()
635    }
636
637    pub(crate) unsafe fn wl_display_disconnect(&self, display: *mut wl_display) {
638        self.wl_display_flush(display);
639        let display_ptr = display.cast::<Display>();
640        let display = &*display_ptr;
641        let events = {
642            let display_mut = &mut *display.data.get();
643            mem::take(&mut display_mut.new_events)
644        };
645        drop(events);
646        let events = {
647            let queue_mut = &mut *display.default_queue.data.get();
648            mem::take(&mut queue_mut.events)
649        };
650        drop(events);
651        let display_mut = &mut *display.data.get();
652        assert_eq!(display_mut.num_queues, 0);
653        let queue_mut = &mut *display.default_queue.data.get();
654        assert_eq!(queue_mut.num_proxies, 0);
655        let leaked_memory = display_mut.leaked_memory;
656        let _ = Box::from_raw(display_ptr);
657        assert!(!leaked_memory);
658    }
659
660    pub(crate) unsafe fn wl_display_dispatch_queue_pending(
661        &self,
662        display: *mut wl_display,
663        queue_ptr: *mut wl_event_queue,
664    ) -> c_int {
665        let queue_ptr = queue_ptr.cast::<Queue>().cast_const();
666        let queue = &*queue_ptr;
667        assert_eq!(queue.display, display.cast());
668        let display = &*queue.display;
669        let mut lock = display.lock.lock();
670        if display.error.get() {
671            return -1;
672        }
673        let mut args = Vec::new();
674        let map_args = |args: &mut Vec<wl_argument>, event: &mut Event| {
675            args.clear();
676            for arg in &mut event.args {
677                let arg = match arg {
678                    Argument::I(v) => wl_argument { i: *v },
679                    Argument::U(v) => wl_argument { u: *v },
680                    Argument::F(v) => wl_argument { f: v.to_wire() },
681                    Argument::S(v) => wl_argument { s: v.as_ptr() },
682                    Argument::O(v) => {
683                        let proxy = &**v;
684                        let o = match proxy.destroyed.load(Relaxed) {
685                            true => ptr::null_mut(),
686                            false => (*v).cast(),
687                        };
688                        wl_argument { o }
689                    }
690                    Argument::N(v) => {
691                        let a = wl_argument { o: (*v).cast() };
692                        *v = ptr::null_mut();
693                        a
694                    }
695                    Argument::A(v) => wl_argument { a: v },
696                    Argument::H(v) => wl_argument {
697                        h: v.take().unwrap().into_raw_fd(),
698                    },
699                };
700                args.push(arg);
701            }
702        };
703        let default_queue = &display.default_queue;
704        let mut num_dispatched = 0;
705        for (queue, user_queue) in [(default_queue, false), (queue, true)] {
706            loop {
707                let queue_mut = &mut *queue.data.get();
708                let Some(mut event) = queue_mut.events.pop_front() else {
709                    break;
710                };
711                num_dispatched += 1;
712                let proxy = &*event.proxy;
713                if proxy.destroyed.load(Relaxed) {
714                    continue;
715                }
716                assert!(user_queue);
717                drop(lock);
718                let data = &mut *proxy.dispatcher_data.get();
719                if let Some(dispatcher) = data.func {
720                    map_args(&mut args, &mut event);
721                    dispatcher(
722                        data.data,
723                        event.proxy.cast(),
724                        event.opcode,
725                        event.interface.events.add(event.opcode as usize),
726                        args.as_mut_ptr(),
727                    );
728                }
729                lock = display.lock.lock();
730            }
731        }
732        num_dispatched
733    }
734
735    pub(crate) unsafe fn wl_display_flush(&self, display: *mut wl_display) -> c_int {
736        let display = &*display.cast::<Display>();
737        let _lock = display.lock.lock();
738        if display.error.get() {
739            return -1;
740        }
741        let display_mut = &mut *display.data.get();
742        if display_mut.new_events_after_flush.is_not_empty() {
743            display_mut
744                .new_events
745                .extend(display_mut.new_events_after_flush.drain(..));
746            let buf = 0u8;
747            let ret = libc::write(display.server_fd.as_raw_fd(), ptr::from_ref(&buf).cast(), 1);
748            if ret < 0 {
749                return -1;
750            }
751        }
752        0
753    }
754
755    pub(crate) unsafe fn wl_display_prepare_read(&self, display_ptr: *mut wl_display) -> c_int {
756        let display = &*display_ptr.cast::<Display>();
757        let _lock = display.lock.lock();
758        {
759            let queue_mut = &mut *display.default_queue.data.get();
760            if queue_mut.events.len() > 0 {
761                return -1;
762            }
763        }
764        {
765            let display_mut = &mut *display.data.get();
766            display_mut.num_read_locks += 1;
767        }
768        0
769    }
770
771    pub(crate) unsafe fn wl_display_prepare_read_queue(
772        &self,
773        display_ptr: *mut wl_display,
774        queue: *mut wl_event_queue,
775    ) -> c_int {
776        let queue = &*queue.cast::<Queue>();
777        assert_eq!(queue.display, display_ptr.cast());
778        let display = &*queue.display;
779        let _lock = display.lock.lock();
780        {
781            let queue_mut = &mut *queue.data.get();
782            if queue_mut.events.len() > 0 {
783                return -1;
784            }
785        }
786        {
787            let display_mut = &mut *display.data.get();
788            display_mut.num_read_locks += 1;
789        }
790        0
791    }
792
793    pub(crate) unsafe fn wl_display_cancel_read(&self, display: *mut wl_display) {
794        let display = &*display.cast::<Display>();
795        let _lock = display.lock.lock();
796        let display_mut = &mut *display.data.get();
797        display_mut.num_read_locks -= 1;
798        if display_mut.num_read_locks == 0 {
799            display_mut.read_serial += 1;
800            display.condvar.notify_all();
801        }
802    }
803
804    pub(crate) unsafe fn wl_display_read_events(&self, display: *mut wl_display) -> c_int {
805        let display = &*display.cast::<Display>();
806        let mut lock = display.lock.lock();
807        if display.error.get() {
808            return -1;
809        }
810        let display_mut = &mut *display.data.get();
811        display_mut.num_read_locks -= 1;
812
813        if display_mut.num_read_locks > 0 {
814            let serial = display_mut.read_serial;
815            loop {
816                display.condvar.wait(&mut lock);
817                let display_mut = &mut *display.data.get();
818                if serial != display_mut.read_serial {
819                    break;
820                }
821            }
822            return 0;
823        }
824
825        display_mut.read_serial += 1;
826        display.condvar.notify_all();
827        let mut buf = [0u8; 128];
828        loop {
829            let ret = libc::read(
830                display.client_fd.as_raw_fd(),
831                buf.as_mut_ptr().cast(),
832                buf.len(),
833            );
834            if ret == -1 {
835                if io::Error::last_os_error().kind() == ErrorKind::WouldBlock {
836                    break;
837                }
838                return -1;
839            }
840        }
841        for event in display_mut.new_events.drain(..) {
842            let proxy = &*event.proxy;
843            let proxy_mut = &mut *proxy.data.get();
844            let queue = &*proxy_mut.queue;
845            let queue_mut = &mut *queue.data.get();
846            queue_mut.events.push_back(event);
847        }
848        0
849    }
850
851    pub(crate) unsafe fn wl_display_get_fd(&self, display: *mut wl_display) -> c_int {
852        let display = &*display.cast::<Display>();
853        display.client_fd.as_raw_fd()
854    }
855
856    #[expect(dead_code)]
857    pub(crate) unsafe fn wl_display_create_queue(
858        &self,
859        display: *mut wl_display,
860    ) -> *mut wl_event_queue {
861        self.wl_display_create_queue_with_name(display, ptr::null_mut())
862    }
863
864    pub(crate) unsafe fn wl_proxy_get_queue(&self, proxy: *mut wl_proxy) -> *mut wl_event_queue {
865        let proxy = &*proxy.cast::<Proxy>();
866        let display = &*proxy.display;
867        let _lock = display.lock.lock();
868        let proxy_mut = &mut *proxy.data.get();
869        proxy_mut.queue.cast()
870    }
871
872    pub(crate) unsafe fn wl_proxy_get_display(&self, proxy: *mut wl_proxy) -> *mut wl_display {
873        let proxy = &*proxy.cast::<Proxy>();
874        proxy.display.cast()
875    }
876
877    pub(crate) unsafe fn wl_display_get_error(&self, display: *mut wl_display) -> c_int {
878        let display = &*display.cast::<Display>();
879        let _lock = display.lock.lock();
880        if display.error.get() { libc::EINVAL } else { 0 }
881    }
882}
883
884#[cfg(test)]
885mod test {
886    use {
887        crate::{Libwayland, ffi::wl_display, libwayland::Display, utils::on_drop::on_drop},
888        std::cell::Cell,
889    };
890
891    thread_local! {
892        pub(crate) static FAIL_CONNECT: Cell<u64> = const { Cell::new(0) };
893    }
894
895    impl Libwayland {
896        pub(crate) fn with_connect_error<T>(&self, f: impl FnOnce() -> T) -> T {
897            let old = FAIL_CONNECT.get();
898            let _on_drop = on_drop(|| FAIL_CONNECT.set(old));
899            FAIL_CONNECT.set(old + 1);
900            f()
901        }
902
903        pub(crate) unsafe fn inject_error(&self, display: *mut wl_display) {
904            let display = &*display.cast::<Display>();
905            let _lock = display.lock.lock();
906            display.error.set(true);
907        }
908
909        pub(crate) unsafe fn block_destroy(&self, display_ptr: *mut wl_display) -> BlockedDestroy {
910            let display = &*display_ptr.cast::<Display>();
911            let _lock = display.lock.lock();
912            display
913                .destroy_blockers
914                .set(display.destroy_blockers.get() + 1);
915            BlockedDestroy {
916                display: display_ptr,
917            }
918        }
919
920        pub(crate) unsafe fn has_blocked_destroy(&self, display_ptr: *mut wl_display) -> bool {
921            let display = &*display_ptr.cast::<Display>();
922            let _lock = display.lock.lock();
923            display.destroy_blocked.get() > 0
924        }
925    }
926
927    pub(crate) struct BlockedDestroy {
928        display: *mut wl_display,
929    }
930
931    unsafe impl Send for BlockedDestroy {}
932
933    impl Drop for BlockedDestroy {
934        fn drop(&mut self) {
935            unsafe {
936                let display = &*self.display.cast::<Display>();
937                let _lock = display.lock.lock();
938                display
939                    .destroy_blockers
940                    .set(display.destroy_blockers.get() - 1);
941                if display.destroy_blockers.get() == 0 {
942                    display.condvar.notify_all();
943                }
944            }
945        }
946    }
947}