wl_proxy/protocols/wayland/wl_subcompositor.rs
1//! sub-surface compositing
2//!
3//! The global interface exposing sub-surface compositing capabilities.
4//! A wl_surface, that has sub-surfaces associated, is called the
5//! parent surface. Sub-surfaces can be arbitrarily nested and create
6//! a tree of sub-surfaces.
7//!
8//! The root surface in a tree of sub-surfaces is the main
9//! surface. The main surface cannot be a sub-surface, because
10//! sub-surfaces must always have a parent.
11//!
12//! A main surface with its sub-surfaces forms a (compound) window.
13//! For window management purposes, this set of wl_surface objects is
14//! to be considered as a single window, and it should also behave as
15//! such.
16//!
17//! The aim of sub-surfaces is to offload some of the compositing work
18//! within a window from clients to the compositor. A prime example is
19//! a video player with decorations and video in separate wl_surface
20//! objects. This should allow the compositor to pass YUV video buffer
21//! processing to dedicated overlay hardware when possible.
22
23use crate::protocol_helpers::prelude::*;
24use super::super::all_types::*;
25
26/// A wl_subcompositor object.
27///
28/// See the documentation of [the module][self] for the interface description.
29pub struct WlSubcompositor {
30 core: ObjectCore,
31 handler: HandlerHolder<dyn WlSubcompositorHandler>,
32}
33
34struct DefaultHandler;
35
36impl WlSubcompositorHandler for DefaultHandler { }
37
38impl ConcreteObject for WlSubcompositor {
39 const XML_VERSION: u32 = 1;
40 const INTERFACE: ObjectInterface = ObjectInterface::WlSubcompositor;
41 const INTERFACE_NAME: &str = "wl_subcompositor";
42}
43
44impl WlSubcompositor {
45 /// Sets a new handler.
46 pub fn set_handler(&self, handler: impl WlSubcompositorHandler) {
47 self.set_boxed_handler(Box::new(handler));
48 }
49
50 /// Sets a new, already boxed handler.
51 pub fn set_boxed_handler(&self, handler: Box<dyn WlSubcompositorHandler>) {
52 if self.core.state.destroyed.get() {
53 return;
54 }
55 self.handler.set(Some(handler));
56 }
57}
58
59impl Debug for WlSubcompositor {
60 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
61 f.debug_struct("WlSubcompositor")
62 .field("server_obj_id", &self.core.server_obj_id.get())
63 .field("client_id", &self.core.client_id.get())
64 .field("client_obj_id", &self.core.client_obj_id.get())
65 .finish()
66 }
67}
68
69impl WlSubcompositor {
70 /// Since when the destroy message is available.
71 pub const MSG__DESTROY__SINCE: u32 = 1;
72
73 /// unbind from the subcompositor interface
74 ///
75 /// Informs the server that the client will not be using this
76 /// protocol object anymore. This does not affect any other
77 /// objects, wl_subsurface objects included.
78 #[inline]
79 pub fn try_send_destroy(
80 &self,
81 ) -> Result<(), ObjectError> {
82 let core = self.core();
83 let Some(id) = core.server_obj_id.get() else {
84 return Err(ObjectError(ObjectErrorKind::ReceiverNoServerId));
85 };
86 #[cfg(feature = "logging")]
87 if self.core.state.log {
88 #[cold]
89 fn log(state: &State, id: u32) {
90 let (millis, micros) = time_since_epoch();
91 let prefix = &state.log_prefix;
92 let args = format_args!("[{millis:7}.{micros:03}] {prefix}server <= wl_subcompositor#{}.destroy()\n", id);
93 state.log(args);
94 }
95 log(&self.core.state, id);
96 }
97 let Some(endpoint) = &self.core.state.server else {
98 return Ok(());
99 };
100 if !endpoint.flush_queued.replace(true) {
101 self.core.state.add_flushable_endpoint(endpoint, None);
102 }
103 let mut outgoing_ref = endpoint.outgoing.borrow_mut();
104 let outgoing = &mut *outgoing_ref;
105 let mut fmt = outgoing.formatter();
106 fmt.words([
107 id,
108 0,
109 ]);
110 self.core.handle_server_destroy();
111 Ok(())
112 }
113
114 /// unbind from the subcompositor interface
115 ///
116 /// Informs the server that the client will not be using this
117 /// protocol object anymore. This does not affect any other
118 /// objects, wl_subsurface objects included.
119 #[inline]
120 pub fn send_destroy(
121 &self,
122 ) {
123 let res = self.try_send_destroy(
124 );
125 if let Err(e) = res {
126 log_send("wl_subcompositor.destroy", &e);
127 }
128 }
129
130 /// Since when the get_subsurface message is available.
131 pub const MSG__GET_SUBSURFACE__SINCE: u32 = 1;
132
133 /// give a surface the role sub-surface
134 ///
135 /// Create a sub-surface interface for the given surface, and
136 /// associate it with the given parent surface. This turns a
137 /// plain wl_surface into a sub-surface.
138 ///
139 /// The to-be sub-surface must not already have another role, and it
140 /// must not have an existing wl_subsurface object. Otherwise the
141 /// bad_surface protocol error is raised.
142 ///
143 /// Adding sub-surfaces to a parent is a double-buffered operation on the
144 /// parent (see wl_surface.commit). The effect of adding a sub-surface
145 /// becomes visible on the next time the state of the parent surface is
146 /// applied.
147 ///
148 /// The parent surface must not be one of the child surface's descendants,
149 /// and the parent must be different from the child surface, otherwise the
150 /// bad_parent protocol error is raised.
151 ///
152 /// This request modifies the behaviour of wl_surface.commit request on
153 /// the sub-surface, see the documentation on wl_subsurface interface.
154 ///
155 /// # Arguments
156 ///
157 /// - `id`: the new sub-surface object ID
158 /// - `surface`: the surface to be turned into a sub-surface
159 /// - `parent`: the parent surface
160 #[inline]
161 pub fn try_send_get_subsurface(
162 &self,
163 id: &Rc<WlSubsurface>,
164 surface: &Rc<WlSurface>,
165 parent: &Rc<WlSurface>,
166 ) -> Result<(), ObjectError> {
167 let (
168 arg0,
169 arg1,
170 arg2,
171 ) = (
172 id,
173 surface,
174 parent,
175 );
176 let arg0_obj = arg0;
177 let arg0 = arg0_obj.core();
178 let arg1 = arg1.core();
179 let arg2 = arg2.core();
180 let core = self.core();
181 let Some(id) = core.server_obj_id.get() else {
182 return Err(ObjectError(ObjectErrorKind::ReceiverNoServerId));
183 };
184 let arg1_id = match arg1.server_obj_id.get() {
185 None => return Err(ObjectError(ObjectErrorKind::ArgNoServerId("surface"))),
186 Some(id) => id,
187 };
188 let arg2_id = match arg2.server_obj_id.get() {
189 None => return Err(ObjectError(ObjectErrorKind::ArgNoServerId("parent"))),
190 Some(id) => id,
191 };
192 arg0.generate_server_id(arg0_obj.clone())
193 .map_err(|e| ObjectError(ObjectErrorKind::GenerateServerId("id", e)))?;
194 let arg0_id = arg0.server_obj_id.get().unwrap_or(0);
195 #[cfg(feature = "logging")]
196 if self.core.state.log {
197 #[cold]
198 fn log(state: &State, id: u32, arg0: u32, arg1: u32, arg2: u32) {
199 let (millis, micros) = time_since_epoch();
200 let prefix = &state.log_prefix;
201 let args = format_args!("[{millis:7}.{micros:03}] {prefix}server <= wl_subcompositor#{}.get_subsurface(id: wl_subsurface#{}, surface: wl_surface#{}, parent: wl_surface#{})\n", id, arg0, arg1, arg2);
202 state.log(args);
203 }
204 log(&self.core.state, id, arg0_id, arg1_id, arg2_id);
205 }
206 let Some(endpoint) = &self.core.state.server else {
207 return Ok(());
208 };
209 if !endpoint.flush_queued.replace(true) {
210 self.core.state.add_flushable_endpoint(endpoint, None);
211 }
212 let mut outgoing_ref = endpoint.outgoing.borrow_mut();
213 let outgoing = &mut *outgoing_ref;
214 let mut fmt = outgoing.formatter();
215 fmt.words([
216 id,
217 1,
218 arg0_id,
219 arg1_id,
220 arg2_id,
221 ]);
222 Ok(())
223 }
224
225 /// give a surface the role sub-surface
226 ///
227 /// Create a sub-surface interface for the given surface, and
228 /// associate it with the given parent surface. This turns a
229 /// plain wl_surface into a sub-surface.
230 ///
231 /// The to-be sub-surface must not already have another role, and it
232 /// must not have an existing wl_subsurface object. Otherwise the
233 /// bad_surface protocol error is raised.
234 ///
235 /// Adding sub-surfaces to a parent is a double-buffered operation on the
236 /// parent (see wl_surface.commit). The effect of adding a sub-surface
237 /// becomes visible on the next time the state of the parent surface is
238 /// applied.
239 ///
240 /// The parent surface must not be one of the child surface's descendants,
241 /// and the parent must be different from the child surface, otherwise the
242 /// bad_parent protocol error is raised.
243 ///
244 /// This request modifies the behaviour of wl_surface.commit request on
245 /// the sub-surface, see the documentation on wl_subsurface interface.
246 ///
247 /// # Arguments
248 ///
249 /// - `id`: the new sub-surface object ID
250 /// - `surface`: the surface to be turned into a sub-surface
251 /// - `parent`: the parent surface
252 #[inline]
253 pub fn send_get_subsurface(
254 &self,
255 id: &Rc<WlSubsurface>,
256 surface: &Rc<WlSurface>,
257 parent: &Rc<WlSurface>,
258 ) {
259 let res = self.try_send_get_subsurface(
260 id,
261 surface,
262 parent,
263 );
264 if let Err(e) = res {
265 log_send("wl_subcompositor.get_subsurface", &e);
266 }
267 }
268
269 /// give a surface the role sub-surface
270 ///
271 /// Create a sub-surface interface for the given surface, and
272 /// associate it with the given parent surface. This turns a
273 /// plain wl_surface into a sub-surface.
274 ///
275 /// The to-be sub-surface must not already have another role, and it
276 /// must not have an existing wl_subsurface object. Otherwise the
277 /// bad_surface protocol error is raised.
278 ///
279 /// Adding sub-surfaces to a parent is a double-buffered operation on the
280 /// parent (see wl_surface.commit). The effect of adding a sub-surface
281 /// becomes visible on the next time the state of the parent surface is
282 /// applied.
283 ///
284 /// The parent surface must not be one of the child surface's descendants,
285 /// and the parent must be different from the child surface, otherwise the
286 /// bad_parent protocol error is raised.
287 ///
288 /// This request modifies the behaviour of wl_surface.commit request on
289 /// the sub-surface, see the documentation on wl_subsurface interface.
290 ///
291 /// # Arguments
292 ///
293 /// - `surface`: the surface to be turned into a sub-surface
294 /// - `parent`: the parent surface
295 #[inline]
296 pub fn new_try_send_get_subsurface(
297 &self,
298 surface: &Rc<WlSurface>,
299 parent: &Rc<WlSurface>,
300 ) -> Result<Rc<WlSubsurface>, ObjectError> {
301 let id = self.core.create_child();
302 self.try_send_get_subsurface(
303 &id,
304 surface,
305 parent,
306 )?;
307 Ok(id)
308 }
309
310 /// give a surface the role sub-surface
311 ///
312 /// Create a sub-surface interface for the given surface, and
313 /// associate it with the given parent surface. This turns a
314 /// plain wl_surface into a sub-surface.
315 ///
316 /// The to-be sub-surface must not already have another role, and it
317 /// must not have an existing wl_subsurface object. Otherwise the
318 /// bad_surface protocol error is raised.
319 ///
320 /// Adding sub-surfaces to a parent is a double-buffered operation on the
321 /// parent (see wl_surface.commit). The effect of adding a sub-surface
322 /// becomes visible on the next time the state of the parent surface is
323 /// applied.
324 ///
325 /// The parent surface must not be one of the child surface's descendants,
326 /// and the parent must be different from the child surface, otherwise the
327 /// bad_parent protocol error is raised.
328 ///
329 /// This request modifies the behaviour of wl_surface.commit request on
330 /// the sub-surface, see the documentation on wl_subsurface interface.
331 ///
332 /// # Arguments
333 ///
334 /// - `surface`: the surface to be turned into a sub-surface
335 /// - `parent`: the parent surface
336 #[inline]
337 pub fn new_send_get_subsurface(
338 &self,
339 surface: &Rc<WlSurface>,
340 parent: &Rc<WlSurface>,
341 ) -> Rc<WlSubsurface> {
342 let id = self.core.create_child();
343 self.send_get_subsurface(
344 &id,
345 surface,
346 parent,
347 );
348 id
349 }
350}
351
352/// A message handler for [`WlSubcompositor`] proxies.
353pub trait WlSubcompositorHandler: Any {
354 /// Event handler for wl_display.delete_id messages deleting the ID of this object.
355 ///
356 /// The default handler forwards the event to the client, if any.
357 #[inline]
358 fn delete_id(&mut self, slf: &Rc<WlSubcompositor>) {
359 slf.core.delete_id();
360 }
361
362 /// unbind from the subcompositor interface
363 ///
364 /// Informs the server that the client will not be using this
365 /// protocol object anymore. This does not affect any other
366 /// objects, wl_subsurface objects included.
367 #[inline]
368 fn handle_destroy(
369 &mut self,
370 slf: &Rc<WlSubcompositor>,
371 ) {
372 if !slf.core.forward_to_server.get() {
373 return;
374 }
375 let res = slf.try_send_destroy(
376 );
377 if let Err(e) = res {
378 log_forward("wl_subcompositor.destroy", &e);
379 }
380 }
381
382 /// give a surface the role sub-surface
383 ///
384 /// Create a sub-surface interface for the given surface, and
385 /// associate it with the given parent surface. This turns a
386 /// plain wl_surface into a sub-surface.
387 ///
388 /// The to-be sub-surface must not already have another role, and it
389 /// must not have an existing wl_subsurface object. Otherwise the
390 /// bad_surface protocol error is raised.
391 ///
392 /// Adding sub-surfaces to a parent is a double-buffered operation on the
393 /// parent (see wl_surface.commit). The effect of adding a sub-surface
394 /// becomes visible on the next time the state of the parent surface is
395 /// applied.
396 ///
397 /// The parent surface must not be one of the child surface's descendants,
398 /// and the parent must be different from the child surface, otherwise the
399 /// bad_parent protocol error is raised.
400 ///
401 /// This request modifies the behaviour of wl_surface.commit request on
402 /// the sub-surface, see the documentation on wl_subsurface interface.
403 ///
404 /// # Arguments
405 ///
406 /// - `id`: the new sub-surface object ID
407 /// - `surface`: the surface to be turned into a sub-surface
408 /// - `parent`: the parent surface
409 ///
410 /// All borrowed proxies passed to this function are guaranteed to be
411 /// immutable and non-null.
412 #[inline]
413 fn handle_get_subsurface(
414 &mut self,
415 slf: &Rc<WlSubcompositor>,
416 id: &Rc<WlSubsurface>,
417 surface: &Rc<WlSurface>,
418 parent: &Rc<WlSurface>,
419 ) {
420 if !slf.core.forward_to_server.get() {
421 return;
422 }
423 let res = slf.try_send_get_subsurface(
424 id,
425 surface,
426 parent,
427 );
428 if let Err(e) = res {
429 log_forward("wl_subcompositor.get_subsurface", &e);
430 }
431 }
432}
433
434impl ObjectPrivate for WlSubcompositor {
435 fn new(state: &Rc<State>, version: u32) -> Rc<Self> {
436 Rc::<Self>::new_cyclic(|slf| Self {
437 core: ObjectCore::new(state, slf.clone(), ObjectInterface::WlSubcompositor, version),
438 handler: Default::default(),
439 })
440 }
441
442 fn delete_id(self: Rc<Self>) -> Result<(), (ObjectError, Rc<dyn Object>)> {
443 let Some(mut handler) = self.handler.try_borrow_mut() else {
444 return Err((ObjectError(ObjectErrorKind::HandlerBorrowed), self));
445 };
446 if let Some(handler) = &mut *handler {
447 handler.delete_id(&self);
448 } else {
449 self.core.delete_id();
450 }
451 Ok(())
452 }
453
454 fn handle_request(self: Rc<Self>, client: &Rc<Client>, msg: &[u32], fds: &mut VecDeque<Rc<OwnedFd>>) -> Result<(), ObjectError> {
455 let Some(mut handler) = self.handler.try_borrow_mut() else {
456 return Err(ObjectError(ObjectErrorKind::HandlerBorrowed));
457 };
458 let handler = &mut *handler;
459 match msg[1] & 0xffff {
460 0 => {
461 if msg.len() != 2 {
462 return Err(ObjectError(ObjectErrorKind::WrongMessageSize(msg.len() as u32 * 4, 8)));
463 }
464 #[cfg(feature = "logging")]
465 if self.core.state.log {
466 #[cold]
467 fn log(state: &State, client_id: u64, id: u32) {
468 let (millis, micros) = time_since_epoch();
469 let prefix = &state.log_prefix;
470 let args = format_args!("[{millis:7}.{micros:03}] {prefix}client#{:<4} -> wl_subcompositor#{}.destroy()\n", client_id, id);
471 state.log(args);
472 }
473 log(&self.core.state, client.endpoint.id, msg[0]);
474 }
475 self.core.handle_client_destroy();
476 if let Some(handler) = handler {
477 (**handler).handle_destroy(&self);
478 } else {
479 DefaultHandler.handle_destroy(&self);
480 }
481 }
482 1 => {
483 let [
484 arg0,
485 arg1,
486 arg2,
487 ] = msg[2..] else {
488 return Err(ObjectError(ObjectErrorKind::WrongMessageSize(msg.len() as u32 * 4, 20)));
489 };
490 #[cfg(feature = "logging")]
491 if self.core.state.log {
492 #[cold]
493 fn log(state: &State, client_id: u64, id: u32, arg0: u32, arg1: u32, arg2: u32) {
494 let (millis, micros) = time_since_epoch();
495 let prefix = &state.log_prefix;
496 let args = format_args!("[{millis:7}.{micros:03}] {prefix}client#{:<4} -> wl_subcompositor#{}.get_subsurface(id: wl_subsurface#{}, surface: wl_surface#{}, parent: wl_surface#{})\n", client_id, id, arg0, arg1, arg2);
497 state.log(args);
498 }
499 log(&self.core.state, client.endpoint.id, msg[0], arg0, arg1, arg2);
500 }
501 let arg0_id = arg0;
502 let arg0 = WlSubsurface::new(&self.core.state, self.core.version);
503 arg0.core().set_client_id(client, arg0_id, arg0.clone())
504 .map_err(|e| ObjectError(ObjectErrorKind::SetClientId(arg0_id, "id", e)))?;
505 let arg1_id = arg1;
506 let Some(arg1) = client.endpoint.lookup(arg1_id) else {
507 return Err(ObjectError(ObjectErrorKind::NoClientObject(client.endpoint.id, arg1_id)));
508 };
509 let Ok(arg1) = (arg1 as Rc<dyn Any>).downcast::<WlSurface>() else {
510 let o = client.endpoint.lookup(arg1_id).unwrap();
511 return Err(ObjectError(ObjectErrorKind::WrongObjectType("surface", o.core().interface, ObjectInterface::WlSurface)));
512 };
513 let arg2_id = arg2;
514 let Some(arg2) = client.endpoint.lookup(arg2_id) else {
515 return Err(ObjectError(ObjectErrorKind::NoClientObject(client.endpoint.id, arg2_id)));
516 };
517 let Ok(arg2) = (arg2 as Rc<dyn Any>).downcast::<WlSurface>() else {
518 let o = client.endpoint.lookup(arg2_id).unwrap();
519 return Err(ObjectError(ObjectErrorKind::WrongObjectType("parent", o.core().interface, ObjectInterface::WlSurface)));
520 };
521 let arg0 = &arg0;
522 let arg1 = &arg1;
523 let arg2 = &arg2;
524 if let Some(handler) = handler {
525 (**handler).handle_get_subsurface(&self, arg0, arg1, arg2);
526 } else {
527 DefaultHandler.handle_get_subsurface(&self, arg0, arg1, arg2);
528 }
529 }
530 n => {
531 let _ = client;
532 let _ = msg;
533 let _ = fds;
534 let _ = handler;
535 return Err(ObjectError(ObjectErrorKind::UnknownMessageId(n)));
536 }
537 }
538 Ok(())
539 }
540
541 fn handle_event(self: Rc<Self>, server: &Endpoint, msg: &[u32], fds: &mut VecDeque<Rc<OwnedFd>>) -> Result<(), ObjectError> {
542 let Some(mut handler) = self.handler.try_borrow_mut() else {
543 return Err(ObjectError(ObjectErrorKind::HandlerBorrowed));
544 };
545 let handler = &mut *handler;
546 match msg[1] & 0xffff {
547 n => {
548 let _ = server;
549 let _ = msg;
550 let _ = fds;
551 let _ = handler;
552 return Err(ObjectError(ObjectErrorKind::UnknownMessageId(n)));
553 }
554 }
555 }
556
557 fn get_request_name(&self, id: u32) -> Option<&'static str> {
558 let name = match id {
559 0 => "destroy",
560 1 => "get_subsurface",
561 _ => return None,
562 };
563 Some(name)
564 }
565
566 fn get_event_name(&self, id: u32) -> Option<&'static str> {
567 let _ = id;
568 None
569 }
570}
571
572impl Object for WlSubcompositor {
573 fn core(&self) -> &ObjectCore {
574 &self.core
575 }
576
577 fn unset_handler(&self) {
578 self.handler.set(None);
579 }
580
581 fn get_handler_any_ref(&self) -> Result<HandlerRef<'_, dyn Any>, HandlerAccessError> {
582 let borrowed = self.handler.try_borrow().ok_or(HandlerAccessError::AlreadyBorrowed)?;
583 if borrowed.is_none() {
584 return Err(HandlerAccessError::NoHandler);
585 }
586 Ok(HandlerRef::map(borrowed, |handler| &**handler.as_ref().unwrap() as &dyn Any))
587 }
588
589 fn get_handler_any_mut(&self) -> Result<HandlerMut<'_, dyn Any>, HandlerAccessError> {
590 let borrowed = self.handler.try_borrow_mut().ok_or(HandlerAccessError::AlreadyBorrowed)?;
591 if borrowed.is_none() {
592 return Err(HandlerAccessError::NoHandler);
593 }
594 Ok(HandlerMut::map(borrowed, |handler| &mut **handler.as_mut().unwrap() as &mut dyn Any))
595 }
596}
597
598impl WlSubcompositor {
599 /// Since when the error.bad_surface enum variant is available.
600 pub const ENM__ERROR_BAD_SURFACE__SINCE: u32 = 1;
601 /// Since when the error.bad_parent enum variant is available.
602 pub const ENM__ERROR_BAD_PARENT__SINCE: u32 = 1;
603}
604
605#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
606pub struct WlSubcompositorError(pub u32);
607
608impl WlSubcompositorError {
609 /// the to-be sub-surface is invalid
610 pub const BAD_SURFACE: Self = Self(0);
611
612 /// the to-be sub-surface parent is invalid
613 pub const BAD_PARENT: Self = Self(1);
614}
615
616impl Debug for WlSubcompositorError {
617 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
618 let name = match *self {
619 Self::BAD_SURFACE => "BAD_SURFACE",
620 Self::BAD_PARENT => "BAD_PARENT",
621 _ => return Debug::fmt(&self.0, f),
622 };
623 f.write_str(name)
624 }
625}