wayland_server/display.rs
1use std::{
2 os::unix::io::{AsFd, BorrowedFd},
3 os::unix::net::UnixStream,
4 sync::Arc,
5};
6
7use wayland_backend::{
8 protocol::ObjectInfo,
9 server::{Backend, ClientData, GlobalId, Handle, InitError, InvalidId, ObjectId},
10};
11
12use crate::{
13 Client, Resource,
14 global::{GlobalData, GlobalDispatch},
15};
16
17/// The Wayland display
18///
19/// This struct is the core of your Wayland compositor. You'll use it in your event loop to drive the
20/// protocol processing of all your clients. All other interactions with the protocol itself are done
21/// through the [`DisplayHandle`] struct, on which the `State` type parameter is erased for convenience.
22///
23/// ## Usage
24///
25/// The main loop of a Wayland compositor generally needs to wait on several sources of events, using
26/// tools like `epoll` (on Linux). The Wayland display can be integrated in this mechanism by getting the
27/// file descriptor as from [`.backend()`][Self::backend()][`.poll_fd()`][Backend::poll_fd()] and invoking
28/// the [`dispatch_clients()`][Self::dispatch_clients()] method whenever it becomes readable.
29///
30/// To ensure all clients receive the events your compositor sends them, you also need to regularly invoke
31/// the [`flush_clients()`][Self::flush_clients()] method, which will write the outgoing buffers into the
32/// sockets.
33#[derive(Debug)]
34pub struct Display<State: 'static> {
35 backend: Backend<State>,
36}
37
38impl<State: 'static> Display<State> {
39 /// Create a new Wayland display
40 ///
41 /// Can only fail if both the `server_system` and `dlopen` features of `wayland-backend` were enabled,
42 /// and the `libwayland-server.so` library could not be found.
43 pub fn new() -> Result<Display<State>, InitError> {
44 Ok(Display { backend: Backend::new()? })
45 }
46
47 /// Retrieve a [`DisplayHandle`] for this [`Display`].
48 ///
49 /// This is the type with which all of your interactions with the Wayland protocol are done.
50 pub fn handle(&self) -> DisplayHandle {
51 DisplayHandle { handle: self.backend.handle() }
52 }
53
54 /// Dispatch all requests received from clients to their respective callbacks.
55 ///
56 /// The `state` argument is the main state of your compositor, which will be accessible from most of your
57 /// callbacks.
58 pub fn dispatch_clients(&mut self, state: &mut State) -> std::io::Result<usize> {
59 self.backend.dispatch_all_clients(state)
60 }
61
62 /// Flush outgoing buffers into their respective sockets.
63 pub fn flush_clients(&mut self) -> std::io::Result<()> {
64 self.backend.flush(None)
65 }
66
67 /// Access the underlying [`Backend`] of this [`Display`]
68 pub fn backend(&mut self) -> &mut Backend<State> {
69 &mut self.backend
70 }
71}
72
73impl<State> AsFd for Display<State> {
74 /// Provides fd from [`Backend::poll_fd`] for polling.
75 fn as_fd(&self) -> BorrowedFd<'_> {
76 self.backend.poll_fd()
77 }
78}
79
80/// A handle to the Wayland display
81///
82/// A display handle may be constructed from a [`Handle`] using it's [`From`] implementation.
83#[derive(Clone)]
84pub struct DisplayHandle {
85 pub(crate) handle: Handle,
86}
87
88impl std::fmt::Debug for DisplayHandle {
89 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
90 f.debug_struct("DisplayHandle").finish_non_exhaustive()
91 }
92}
93
94impl DisplayHandle {
95 /// Returns the underlying [`Handle`] from `wayland-backend`.
96 pub fn backend_handle(&self) -> Handle {
97 self.handle.clone()
98 }
99
100 /// Insert a new client in your [`Display`]
101 ///
102 /// This client will be associated with the provided [`ClientData`], that you can then retrieve from
103 /// it via [`Client::get_data()`], and its requests will be processed by the [`Display`] and your
104 /// callbacks.
105 pub fn insert_client(
106 &mut self,
107 stream: UnixStream,
108 data: Arc<dyn ClientData>,
109 ) -> std::io::Result<Client> {
110 let id = self.handle.insert_client(stream, data.clone())?;
111 Ok(Client { id, data })
112 }
113
114 /// Retrieve the [`Client`] which owns the object represented by the given ID
115 pub fn get_client(&self, id: ObjectId) -> Result<Client, InvalidId> {
116 let client_id = self.handle.get_client(id)?;
117 Client::from_id(self, client_id)
118 }
119
120 /// Create a new protocol global
121 ///
122 /// This global will be advertized to clients through the `wl_registry` according to the rules
123 /// defined by your [`GlobalDispatch`] implementation for the given interface. Whenever a client
124 /// binds this global, the associated [`GlobalDispatch::bind()`] method will be invoked on your
125 /// `State`.
126 pub fn create_global<State, I: Resource + 'static, U>(&self, version: u32, data: U) -> GlobalId
127 where
128 State: 'static,
129 U: GlobalDispatch<I, State> + Send + Sync + 'static,
130 {
131 self.handle.create_global::<State>(
132 I::interface(),
133 version,
134 Arc::new(GlobalData { data, _types: std::marker::PhantomData }),
135 )
136 }
137
138 /// Disable this global
139 ///
140 /// Clients will be notified of the global removal, and it will not be advertized to new clients. However
141 /// the state associated with this global is not freed, so clients which already know about it can still
142 /// bind it.
143 pub fn disable_global<State: 'static>(&self, id: GlobalId) {
144 self.handle.disable_global::<State>(id)
145 }
146
147 /// Remove this global
148 ///
149 /// Clients will be notified of the global removal if it was not already disabled. The state associated
150 /// with this global is freed, meaning clients trying to bind it will receive a protocol error.
151 ///
152 /// When removing a global, it is recommended to first disable it using
153 /// [`disable_global()`][Self::disable_global()] to allow some time for clients to register that
154 /// the global is getting removed, to avoid a race where a client would be killed because it bound a global
155 /// at the same as the server decided to remove it. After the global has been disabled for some time (like
156 /// a few seconds) it should be safe to actually remove it.
157 pub fn remove_global<State: 'static>(&self, id: GlobalId) {
158 self.handle.remove_global::<State>(id)
159 }
160
161 /// Access the protocol information for a Wayland object
162 ///
163 /// Returns an error if the object is no longer valid.
164 pub fn object_info(&self, id: ObjectId) -> Result<ObjectInfo, InvalidId> {
165 self.handle.object_info(id)
166 }
167
168 /// Send an event to given Wayland object
169 ///
170 /// This is intended to be a low-level method. You can alternatively use the methods on the
171 /// type representing your object, or [`Resource::send_event()`], which may be more convenient.
172 pub fn send_event<I: Resource>(
173 &self,
174 resource: &I,
175 event: I::Event<'_>,
176 ) -> Result<(), InvalidId> {
177 let msg = resource.write_event(self, event)?;
178 self.handle.send_event(msg)
179 }
180
181 /// Trigger a protocol error on this object
182 ///
183 /// This is intended to be a low-level method. See [`Resource::post_error()`], for a more convenient
184 /// method.
185 pub fn post_error<I: Resource>(&self, resource: &I, code: u32, error: String) {
186 self.handle.post_error(resource.id(), code, std::ffi::CString::new(error).unwrap())
187 }
188
189 /// Access the object data associated with this object
190 ///
191 /// This is intended to be a low-level method. See [`Resource::object_data()`], for a more convenient
192 /// method.
193 pub fn get_object_data(
194 &self,
195 id: ObjectId,
196 ) -> Result<Arc<dyn std::any::Any + Send + Sync + 'static>, InvalidId> {
197 self.handle.get_object_data_any(id)
198 }
199
200 /// Flush outgoing buffers into their respective sockets.
201 pub fn flush_clients(&mut self) -> std::io::Result<()> {
202 self.handle.flush(None)
203 }
204
205 /// Set default client maximum buffer size.
206 #[cfg(feature = "libwayland_1_23")]
207 pub fn set_default_max_buffer_size(&self, max_buffer_size: usize) {
208 self.handle.set_default_max_buffer_size(max_buffer_size);
209 }
210}
211
212impl From<Handle> for DisplayHandle {
213 /// Creates a [`DisplayHandle`] using a [`Handle`] from `wayland-backend`.
214 fn from(handle: Handle) -> Self {
215 Self { handle }
216 }
217}