1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
use std::io;
use std::os::unix::io::RawFd;
use std::sync::Arc;
use crate::protocol::wl_display::WlDisplay;
use wayland_sys::client::*;
use crate::{ConnectError, Proxy};
use super::{EventQueueInner, ProxyInner};
pub(crate) struct DisplayInner {
proxy: Proxy<WlDisplay>,
display: Arc<DisplayGuard>,
}
pub(crate) struct DisplayGuard {
ptr: *mut wl_display,
external: bool,
}
unsafe impl Send for DisplayInner {}
unsafe impl Sync for DisplayInner {}
unsafe fn make_display(ptr: *mut wl_display) -> Result<Arc<DisplayInner>, ConnectError> {
if ptr.is_null() {
return Err(ConnectError::NoCompositorListening);
}
let mut inner = DisplayInner {
proxy: Proxy::from_c_ptr(ptr as *mut _),
display: Arc::new(DisplayGuard { ptr, external: false }),
};
inner.proxy.inner.display = Some(Arc::downgrade(&inner.display));
Ok(Arc::new(inner))
}
impl DisplayInner {
pub unsafe fn from_fd(fd: RawFd) -> Result<Arc<DisplayInner>, ConnectError> {
if !::wayland_sys::client::is_lib_available() {
return Err(ConnectError::NoWaylandLib);
}
let display_ptr = ffi_dispatch!(WAYLAND_CLIENT_HANDLE, wl_display_connect_to_fd, fd);
make_display(display_ptr)
}
pub(crate) fn get_connection_fd(&self) -> ::std::os::unix::io::RawFd {
unsafe { ffi_dispatch!(WAYLAND_CLIENT_HANDLE, wl_display_get_fd, self.ptr()) }
}
pub(crate) fn ptr(&self) -> *mut wl_display {
self.display.ptr
}
pub(crate) fn flush(&self) -> io::Result<()> {
let ret = unsafe { ffi_dispatch!(WAYLAND_CLIENT_HANDLE, wl_display_flush, self.ptr()) };
if ret >= 0 {
Ok(())
} else {
Err(io::Error::last_os_error())
}
}
pub(crate) fn create_event_queue(me: &Arc<DisplayInner>) -> EventQueueInner {
unsafe {
let ptr = ffi_dispatch!(WAYLAND_CLIENT_HANDLE, wl_display_create_queue, me.ptr());
EventQueueInner::new(me.clone(), ptr)
}
}
pub(crate) fn get_proxy(&self) -> &Proxy<WlDisplay> {
&self.proxy
}
pub(crate) fn protocol_error(&self) -> Option<crate::ProtocolError> {
let ret = unsafe { ffi_dispatch!(WAYLAND_CLIENT_HANDLE, wl_display_get_error, self.ptr()) };
if ret == ::nix::errno::Errno::EPROTO as i32 {
let mut interface = ::std::ptr::null_mut();
let mut id = 0;
let code = unsafe {
ffi_dispatch!(
WAYLAND_CLIENT_HANDLE,
wl_display_get_protocol_error,
self.ptr(),
&mut interface,
&mut id
)
};
let interface_name = unsafe { ::std::ffi::CStr::from_ptr((*interface).name) };
Some(crate::ProtocolError {
code,
object_id: id,
object_interface: interface_name.to_str().unwrap_or("<unknown>"),
message: String::new(),
})
} else {
None
}
}
pub(crate) unsafe fn from_external(display_ptr: *mut wl_display) -> Arc<DisplayInner> {
Arc::new(DisplayInner {
proxy: Proxy::wrap(ProxyInner::from_external_display(display_ptr as *mut _)),
display: Arc::new(DisplayGuard { ptr: display_ptr, external: true }),
})
}
}
impl Drop for DisplayGuard {
fn drop(&mut self) {
if !self.external {
unsafe {
ffi_dispatch!(WAYLAND_CLIENT_HANDLE, wl_display_disconnect, self.ptr);
}
}
}
}