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
34pub struct Libwayland(());
42
43#[repr(C)] struct 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 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 opcode: 0,
253 args: vec![Argument::U(0)],
254 };
255 self.send_event(display_mut, event);
256 }
257 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 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 0 => {
281 if interface != WlDummy::WL_INTERFACE {
282 unreachable!();
283 }
284 ret = self.create_proxy(version, display_mut, proxy, interface);
285 }
286 1 => {
288 let args = &*args.cast::<[wl_argument; 1]>();
289 let event = Event {
290 proxy: proxy_ptr.cast(),
291 interface: WlRoot::WL_INTERFACE,
292 opcode: 0,
294 args: vec![Argument::O(args[0].o.cast())],
295 };
296 self.send_event(display_mut, event);
297 }
298 2 => {}
300 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 opcode: 0,
311 args: vec![Argument::S(display.name.clone())],
312 };
313 self.send_event(display_mut, event);
314 }
315 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 opcode: 1,
323 args: vec![Argument::N(new)],
324 };
325 self.send_event(display_mut, event);
326 }
327 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 opcode: 0,
339 args: vec![Argument::S(string)],
340 };
341 self.send_event(display_mut, event);
342 }
343 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 0 => {}
356 1 => {
358 if interface != WlDummy::WL_INTERFACE {
359 unreachable!();
360 }
361 ret = self.create_proxy(version, display_mut, proxy, interface);
362 }
363 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}