wl_proxy/protocols/wayland/wl_subsurface.rs
1//! sub-surface interface to a wl_surface
2//!
3//! An additional interface to a wl_surface object, which has been
4//! made a sub-surface. A sub-surface has one parent surface. A
5//! sub-surface's size and position are not limited to that of the parent.
6//! Particularly, a sub-surface is not automatically clipped to its
7//! parent's area.
8//!
9//! A sub-surface becomes mapped, when a non-NULL wl_buffer is applied
10//! and the parent surface is mapped. The order of which one happens
11//! first is irrelevant. A sub-surface is hidden if the parent becomes
12//! hidden, or if a NULL wl_buffer is applied. These rules apply
13//! recursively through the tree of surfaces.
14//!
15//! The behaviour of a wl_surface.commit request on a sub-surface
16//! depends on the sub-surface's mode. The possible modes are
17//! synchronized and desynchronized, see methods
18//! wl_subsurface.set_sync and wl_subsurface.set_desync. Synchronized
19//! mode caches the wl_surface state to be applied when the parent's
20//! state gets applied, and desynchronized mode applies the pending
21//! wl_surface state directly. A sub-surface is initially in the
22//! synchronized mode.
23//!
24//! Sub-surfaces also have another kind of state, which is managed by
25//! wl_subsurface requests, as opposed to wl_surface requests. This
26//! state includes the sub-surface position relative to the parent
27//! surface (wl_subsurface.set_position), and the stacking order of
28//! the parent and its sub-surfaces (wl_subsurface.place_above and
29//! .place_below). This state is applied when the parent surface's
30//! wl_surface state is applied, regardless of the sub-surface's mode.
31//! As the exception, set_sync and set_desync are effective immediately.
32//!
33//! The main surface can be thought to be always in desynchronized mode,
34//! since it does not have a parent in the sub-surfaces sense.
35//!
36//! Even if a sub-surface is in desynchronized mode, it will behave as
37//! in synchronized mode, if its parent surface behaves as in
38//! synchronized mode. This rule is applied recursively throughout the
39//! tree of surfaces. This means, that one can set a sub-surface into
40//! synchronized mode, and then assume that all its child and grand-child
41//! sub-surfaces are synchronized, too, without explicitly setting them.
42//!
43//! Destroying a sub-surface takes effect immediately. If you need to
44//! synchronize the removal of a sub-surface to the parent surface update,
45//! unmap the sub-surface first by attaching a NULL wl_buffer, update parent,
46//! and then destroy the sub-surface.
47//!
48//! If the parent wl_surface object is destroyed, the sub-surface is
49//! unmapped.
50//!
51//! A sub-surface never has the keyboard focus of any seat.
52//!
53//! The wl_surface.offset request is ignored: clients must use set_position
54//! instead to move the sub-surface.
55
56use crate::protocol_helpers::prelude::*;
57use super::super::all_types::*;
58
59/// A wl_subsurface object.
60///
61/// See the documentation of [the module][self] for the interface description.
62pub struct WlSubsurface {
63 core: ObjectCore,
64 handler: HandlerHolder<dyn WlSubsurfaceHandler>,
65}
66
67struct DefaultHandler;
68
69impl WlSubsurfaceHandler for DefaultHandler { }
70
71impl ConcreteObject for WlSubsurface {
72 const XML_VERSION: u32 = 1;
73 const INTERFACE: ObjectInterface = ObjectInterface::WlSubsurface;
74 const INTERFACE_NAME: &str = "wl_subsurface";
75}
76
77impl WlSubsurface {
78 /// Sets a new handler.
79 pub fn set_handler(&self, handler: impl WlSubsurfaceHandler) {
80 self.set_boxed_handler(Box::new(handler));
81 }
82
83 /// Sets a new, already boxed handler.
84 pub fn set_boxed_handler(&self, handler: Box<dyn WlSubsurfaceHandler>) {
85 if self.core.state.destroyed.get() {
86 return;
87 }
88 self.handler.set(Some(handler));
89 }
90}
91
92impl Debug for WlSubsurface {
93 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
94 f.debug_struct("WlSubsurface")
95 .field("server_obj_id", &self.core.server_obj_id.get())
96 .field("client_id", &self.core.client_id.get())
97 .field("client_obj_id", &self.core.client_obj_id.get())
98 .finish()
99 }
100}
101
102impl WlSubsurface {
103 /// Since when the destroy message is available.
104 pub const MSG__DESTROY__SINCE: u32 = 1;
105
106 /// remove sub-surface interface
107 ///
108 /// The sub-surface interface is removed from the wl_surface object
109 /// that was turned into a sub-surface with a
110 /// wl_subcompositor.get_subsurface request. The wl_surface's association
111 /// to the parent is deleted. The wl_surface is unmapped immediately.
112 #[inline]
113 pub fn try_send_destroy(
114 &self,
115 ) -> Result<(), ObjectError> {
116 let core = self.core();
117 let Some(id) = core.server_obj_id.get() else {
118 return Err(ObjectError(ObjectErrorKind::ReceiverNoServerId));
119 };
120 #[cfg(feature = "logging")]
121 if self.core.state.log {
122 #[cold]
123 fn log(state: &State, id: u32) {
124 let (millis, micros) = time_since_epoch();
125 let prefix = &state.log_prefix;
126 let args = format_args!("[{millis:7}.{micros:03}] {prefix}server <= wl_subsurface#{}.destroy()\n", id);
127 state.log(args);
128 }
129 log(&self.core.state, id);
130 }
131 let Some(endpoint) = &self.core.state.server else {
132 return Ok(());
133 };
134 if !endpoint.flush_queued.replace(true) {
135 self.core.state.add_flushable_endpoint(endpoint, None);
136 }
137 let mut outgoing_ref = endpoint.outgoing.borrow_mut();
138 let outgoing = &mut *outgoing_ref;
139 let mut fmt = outgoing.formatter();
140 fmt.words([
141 id,
142 0,
143 ]);
144 self.core.handle_server_destroy();
145 Ok(())
146 }
147
148 /// remove sub-surface interface
149 ///
150 /// The sub-surface interface is removed from the wl_surface object
151 /// that was turned into a sub-surface with a
152 /// wl_subcompositor.get_subsurface request. The wl_surface's association
153 /// to the parent is deleted. The wl_surface is unmapped immediately.
154 #[inline]
155 pub fn send_destroy(
156 &self,
157 ) {
158 let res = self.try_send_destroy(
159 );
160 if let Err(e) = res {
161 log_send("wl_subsurface.destroy", &e);
162 }
163 }
164
165 /// Since when the set_position message is available.
166 pub const MSG__SET_POSITION__SINCE: u32 = 1;
167
168 /// reposition the sub-surface
169 ///
170 /// This schedules a sub-surface position change.
171 /// The sub-surface will be moved so that its origin (top left
172 /// corner pixel) will be at the location x, y of the parent surface
173 /// coordinate system. The coordinates are not restricted to the parent
174 /// surface area. Negative values are allowed.
175 ///
176 /// The scheduled coordinates will take effect whenever the state of the
177 /// parent surface is applied.
178 ///
179 /// If more than one set_position request is invoked by the client before
180 /// the commit of the parent surface, the position of a new request always
181 /// replaces the scheduled position from any previous request.
182 ///
183 /// The initial position is 0, 0.
184 ///
185 /// # Arguments
186 ///
187 /// - `x`: x coordinate in the parent surface
188 /// - `y`: y coordinate in the parent surface
189 #[inline]
190 pub fn try_send_set_position(
191 &self,
192 x: i32,
193 y: i32,
194 ) -> Result<(), ObjectError> {
195 let (
196 arg0,
197 arg1,
198 ) = (
199 x,
200 y,
201 );
202 let core = self.core();
203 let Some(id) = core.server_obj_id.get() else {
204 return Err(ObjectError(ObjectErrorKind::ReceiverNoServerId));
205 };
206 #[cfg(feature = "logging")]
207 if self.core.state.log {
208 #[cold]
209 fn log(state: &State, id: u32, arg0: i32, arg1: i32) {
210 let (millis, micros) = time_since_epoch();
211 let prefix = &state.log_prefix;
212 let args = format_args!("[{millis:7}.{micros:03}] {prefix}server <= wl_subsurface#{}.set_position(x: {}, y: {})\n", id, arg0, arg1);
213 state.log(args);
214 }
215 log(&self.core.state, id, arg0, arg1);
216 }
217 let Some(endpoint) = &self.core.state.server else {
218 return Ok(());
219 };
220 if !endpoint.flush_queued.replace(true) {
221 self.core.state.add_flushable_endpoint(endpoint, None);
222 }
223 let mut outgoing_ref = endpoint.outgoing.borrow_mut();
224 let outgoing = &mut *outgoing_ref;
225 let mut fmt = outgoing.formatter();
226 fmt.words([
227 id,
228 1,
229 arg0 as u32,
230 arg1 as u32,
231 ]);
232 Ok(())
233 }
234
235 /// reposition the sub-surface
236 ///
237 /// This schedules a sub-surface position change.
238 /// The sub-surface will be moved so that its origin (top left
239 /// corner pixel) will be at the location x, y of the parent surface
240 /// coordinate system. The coordinates are not restricted to the parent
241 /// surface area. Negative values are allowed.
242 ///
243 /// The scheduled coordinates will take effect whenever the state of the
244 /// parent surface is applied.
245 ///
246 /// If more than one set_position request is invoked by the client before
247 /// the commit of the parent surface, the position of a new request always
248 /// replaces the scheduled position from any previous request.
249 ///
250 /// The initial position is 0, 0.
251 ///
252 /// # Arguments
253 ///
254 /// - `x`: x coordinate in the parent surface
255 /// - `y`: y coordinate in the parent surface
256 #[inline]
257 pub fn send_set_position(
258 &self,
259 x: i32,
260 y: i32,
261 ) {
262 let res = self.try_send_set_position(
263 x,
264 y,
265 );
266 if let Err(e) = res {
267 log_send("wl_subsurface.set_position", &e);
268 }
269 }
270
271 /// Since when the place_above message is available.
272 pub const MSG__PLACE_ABOVE__SINCE: u32 = 1;
273
274 /// restack the sub-surface
275 ///
276 /// This sub-surface is taken from the stack, and put back just
277 /// above the reference surface, changing the z-order of the sub-surfaces.
278 /// The reference surface must be one of the sibling surfaces, or the
279 /// parent surface. Using any other surface, including this sub-surface,
280 /// will cause a protocol error.
281 ///
282 /// The z-order is double-buffered. Requests are handled in order and
283 /// applied immediately to a pending state. The final pending state is
284 /// copied to the active state the next time the state of the parent
285 /// surface is applied.
286 ///
287 /// A new sub-surface is initially added as the top-most in the stack
288 /// of its siblings and parent.
289 ///
290 /// # Arguments
291 ///
292 /// - `sibling`: the reference surface
293 #[inline]
294 pub fn try_send_place_above(
295 &self,
296 sibling: &Rc<WlSurface>,
297 ) -> Result<(), ObjectError> {
298 let (
299 arg0,
300 ) = (
301 sibling,
302 );
303 let arg0 = arg0.core();
304 let core = self.core();
305 let Some(id) = core.server_obj_id.get() else {
306 return Err(ObjectError(ObjectErrorKind::ReceiverNoServerId));
307 };
308 let arg0_id = match arg0.server_obj_id.get() {
309 None => return Err(ObjectError(ObjectErrorKind::ArgNoServerId("sibling"))),
310 Some(id) => id,
311 };
312 #[cfg(feature = "logging")]
313 if self.core.state.log {
314 #[cold]
315 fn log(state: &State, id: u32, arg0: u32) {
316 let (millis, micros) = time_since_epoch();
317 let prefix = &state.log_prefix;
318 let args = format_args!("[{millis:7}.{micros:03}] {prefix}server <= wl_subsurface#{}.place_above(sibling: wl_surface#{})\n", id, arg0);
319 state.log(args);
320 }
321 log(&self.core.state, id, arg0_id);
322 }
323 let Some(endpoint) = &self.core.state.server else {
324 return Ok(());
325 };
326 if !endpoint.flush_queued.replace(true) {
327 self.core.state.add_flushable_endpoint(endpoint, None);
328 }
329 let mut outgoing_ref = endpoint.outgoing.borrow_mut();
330 let outgoing = &mut *outgoing_ref;
331 let mut fmt = outgoing.formatter();
332 fmt.words([
333 id,
334 2,
335 arg0_id,
336 ]);
337 Ok(())
338 }
339
340 /// restack the sub-surface
341 ///
342 /// This sub-surface is taken from the stack, and put back just
343 /// above the reference surface, changing the z-order of the sub-surfaces.
344 /// The reference surface must be one of the sibling surfaces, or the
345 /// parent surface. Using any other surface, including this sub-surface,
346 /// will cause a protocol error.
347 ///
348 /// The z-order is double-buffered. Requests are handled in order and
349 /// applied immediately to a pending state. The final pending state is
350 /// copied to the active state the next time the state of the parent
351 /// surface is applied.
352 ///
353 /// A new sub-surface is initially added as the top-most in the stack
354 /// of its siblings and parent.
355 ///
356 /// # Arguments
357 ///
358 /// - `sibling`: the reference surface
359 #[inline]
360 pub fn send_place_above(
361 &self,
362 sibling: &Rc<WlSurface>,
363 ) {
364 let res = self.try_send_place_above(
365 sibling,
366 );
367 if let Err(e) = res {
368 log_send("wl_subsurface.place_above", &e);
369 }
370 }
371
372 /// Since when the place_below message is available.
373 pub const MSG__PLACE_BELOW__SINCE: u32 = 1;
374
375 /// restack the sub-surface
376 ///
377 /// The sub-surface is placed just below the reference surface.
378 /// See wl_subsurface.place_above.
379 ///
380 /// # Arguments
381 ///
382 /// - `sibling`: the reference surface
383 #[inline]
384 pub fn try_send_place_below(
385 &self,
386 sibling: &Rc<WlSurface>,
387 ) -> Result<(), ObjectError> {
388 let (
389 arg0,
390 ) = (
391 sibling,
392 );
393 let arg0 = arg0.core();
394 let core = self.core();
395 let Some(id) = core.server_obj_id.get() else {
396 return Err(ObjectError(ObjectErrorKind::ReceiverNoServerId));
397 };
398 let arg0_id = match arg0.server_obj_id.get() {
399 None => return Err(ObjectError(ObjectErrorKind::ArgNoServerId("sibling"))),
400 Some(id) => id,
401 };
402 #[cfg(feature = "logging")]
403 if self.core.state.log {
404 #[cold]
405 fn log(state: &State, id: u32, arg0: u32) {
406 let (millis, micros) = time_since_epoch();
407 let prefix = &state.log_prefix;
408 let args = format_args!("[{millis:7}.{micros:03}] {prefix}server <= wl_subsurface#{}.place_below(sibling: wl_surface#{})\n", id, arg0);
409 state.log(args);
410 }
411 log(&self.core.state, id, arg0_id);
412 }
413 let Some(endpoint) = &self.core.state.server else {
414 return Ok(());
415 };
416 if !endpoint.flush_queued.replace(true) {
417 self.core.state.add_flushable_endpoint(endpoint, None);
418 }
419 let mut outgoing_ref = endpoint.outgoing.borrow_mut();
420 let outgoing = &mut *outgoing_ref;
421 let mut fmt = outgoing.formatter();
422 fmt.words([
423 id,
424 3,
425 arg0_id,
426 ]);
427 Ok(())
428 }
429
430 /// restack the sub-surface
431 ///
432 /// The sub-surface is placed just below the reference surface.
433 /// See wl_subsurface.place_above.
434 ///
435 /// # Arguments
436 ///
437 /// - `sibling`: the reference surface
438 #[inline]
439 pub fn send_place_below(
440 &self,
441 sibling: &Rc<WlSurface>,
442 ) {
443 let res = self.try_send_place_below(
444 sibling,
445 );
446 if let Err(e) = res {
447 log_send("wl_subsurface.place_below", &e);
448 }
449 }
450
451 /// Since when the set_sync message is available.
452 pub const MSG__SET_SYNC__SINCE: u32 = 1;
453
454 /// set sub-surface to synchronized mode
455 ///
456 /// Change the commit behaviour of the sub-surface to synchronized
457 /// mode, also described as the parent dependent mode.
458 ///
459 /// In synchronized mode, wl_surface.commit on a sub-surface will
460 /// accumulate the committed state in a cache, but the state will
461 /// not be applied and hence will not change the compositor output.
462 /// The cached state is applied to the sub-surface immediately after
463 /// the parent surface's state is applied. This ensures atomic
464 /// updates of the parent and all its synchronized sub-surfaces.
465 /// Applying the cached state will invalidate the cache, so further
466 /// parent surface commits do not (re-)apply old state.
467 ///
468 /// See wl_subsurface for the recursive effect of this mode.
469 #[inline]
470 pub fn try_send_set_sync(
471 &self,
472 ) -> Result<(), ObjectError> {
473 let core = self.core();
474 let Some(id) = core.server_obj_id.get() else {
475 return Err(ObjectError(ObjectErrorKind::ReceiverNoServerId));
476 };
477 #[cfg(feature = "logging")]
478 if self.core.state.log {
479 #[cold]
480 fn log(state: &State, id: u32) {
481 let (millis, micros) = time_since_epoch();
482 let prefix = &state.log_prefix;
483 let args = format_args!("[{millis:7}.{micros:03}] {prefix}server <= wl_subsurface#{}.set_sync()\n", id);
484 state.log(args);
485 }
486 log(&self.core.state, id);
487 }
488 let Some(endpoint) = &self.core.state.server else {
489 return Ok(());
490 };
491 if !endpoint.flush_queued.replace(true) {
492 self.core.state.add_flushable_endpoint(endpoint, None);
493 }
494 let mut outgoing_ref = endpoint.outgoing.borrow_mut();
495 let outgoing = &mut *outgoing_ref;
496 let mut fmt = outgoing.formatter();
497 fmt.words([
498 id,
499 4,
500 ]);
501 Ok(())
502 }
503
504 /// set sub-surface to synchronized mode
505 ///
506 /// Change the commit behaviour of the sub-surface to synchronized
507 /// mode, also described as the parent dependent mode.
508 ///
509 /// In synchronized mode, wl_surface.commit on a sub-surface will
510 /// accumulate the committed state in a cache, but the state will
511 /// not be applied and hence will not change the compositor output.
512 /// The cached state is applied to the sub-surface immediately after
513 /// the parent surface's state is applied. This ensures atomic
514 /// updates of the parent and all its synchronized sub-surfaces.
515 /// Applying the cached state will invalidate the cache, so further
516 /// parent surface commits do not (re-)apply old state.
517 ///
518 /// See wl_subsurface for the recursive effect of this mode.
519 #[inline]
520 pub fn send_set_sync(
521 &self,
522 ) {
523 let res = self.try_send_set_sync(
524 );
525 if let Err(e) = res {
526 log_send("wl_subsurface.set_sync", &e);
527 }
528 }
529
530 /// Since when the set_desync message is available.
531 pub const MSG__SET_DESYNC__SINCE: u32 = 1;
532
533 /// set sub-surface to desynchronized mode
534 ///
535 /// Change the commit behaviour of the sub-surface to desynchronized
536 /// mode, also described as independent or freely running mode.
537 ///
538 /// In desynchronized mode, wl_surface.commit on a sub-surface will
539 /// apply the pending state directly, without caching, as happens
540 /// normally with a wl_surface. Calling wl_surface.commit on the
541 /// parent surface has no effect on the sub-surface's wl_surface
542 /// state. This mode allows a sub-surface to be updated on its own.
543 ///
544 /// If cached state exists when wl_surface.commit is called in
545 /// desynchronized mode, the pending state is added to the cached
546 /// state, and applied as a whole. This invalidates the cache.
547 ///
548 /// Note: even if a sub-surface is set to desynchronized, a parent
549 /// sub-surface may override it to behave as synchronized. For details,
550 /// see wl_subsurface.
551 ///
552 /// If a surface's parent surface behaves as desynchronized, then
553 /// the cached state is applied on set_desync.
554 #[inline]
555 pub fn try_send_set_desync(
556 &self,
557 ) -> Result<(), ObjectError> {
558 let core = self.core();
559 let Some(id) = core.server_obj_id.get() else {
560 return Err(ObjectError(ObjectErrorKind::ReceiverNoServerId));
561 };
562 #[cfg(feature = "logging")]
563 if self.core.state.log {
564 #[cold]
565 fn log(state: &State, id: u32) {
566 let (millis, micros) = time_since_epoch();
567 let prefix = &state.log_prefix;
568 let args = format_args!("[{millis:7}.{micros:03}] {prefix}server <= wl_subsurface#{}.set_desync()\n", id);
569 state.log(args);
570 }
571 log(&self.core.state, id);
572 }
573 let Some(endpoint) = &self.core.state.server else {
574 return Ok(());
575 };
576 if !endpoint.flush_queued.replace(true) {
577 self.core.state.add_flushable_endpoint(endpoint, None);
578 }
579 let mut outgoing_ref = endpoint.outgoing.borrow_mut();
580 let outgoing = &mut *outgoing_ref;
581 let mut fmt = outgoing.formatter();
582 fmt.words([
583 id,
584 5,
585 ]);
586 Ok(())
587 }
588
589 /// set sub-surface to desynchronized mode
590 ///
591 /// Change the commit behaviour of the sub-surface to desynchronized
592 /// mode, also described as independent or freely running mode.
593 ///
594 /// In desynchronized mode, wl_surface.commit on a sub-surface will
595 /// apply the pending state directly, without caching, as happens
596 /// normally with a wl_surface. Calling wl_surface.commit on the
597 /// parent surface has no effect on the sub-surface's wl_surface
598 /// state. This mode allows a sub-surface to be updated on its own.
599 ///
600 /// If cached state exists when wl_surface.commit is called in
601 /// desynchronized mode, the pending state is added to the cached
602 /// state, and applied as a whole. This invalidates the cache.
603 ///
604 /// Note: even if a sub-surface is set to desynchronized, a parent
605 /// sub-surface may override it to behave as synchronized. For details,
606 /// see wl_subsurface.
607 ///
608 /// If a surface's parent surface behaves as desynchronized, then
609 /// the cached state is applied on set_desync.
610 #[inline]
611 pub fn send_set_desync(
612 &self,
613 ) {
614 let res = self.try_send_set_desync(
615 );
616 if let Err(e) = res {
617 log_send("wl_subsurface.set_desync", &e);
618 }
619 }
620}
621
622/// A message handler for [`WlSubsurface`] proxies.
623pub trait WlSubsurfaceHandler: Any {
624 /// Event handler for wl_display.delete_id messages deleting the ID of this object.
625 ///
626 /// The default handler forwards the event to the client, if any.
627 #[inline]
628 fn delete_id(&mut self, slf: &Rc<WlSubsurface>) {
629 slf.core.delete_id();
630 }
631
632 /// remove sub-surface interface
633 ///
634 /// The sub-surface interface is removed from the wl_surface object
635 /// that was turned into a sub-surface with a
636 /// wl_subcompositor.get_subsurface request. The wl_surface's association
637 /// to the parent is deleted. The wl_surface is unmapped immediately.
638 #[inline]
639 fn handle_destroy(
640 &mut self,
641 slf: &Rc<WlSubsurface>,
642 ) {
643 if !slf.core.forward_to_server.get() {
644 return;
645 }
646 let res = slf.try_send_destroy(
647 );
648 if let Err(e) = res {
649 log_forward("wl_subsurface.destroy", &e);
650 }
651 }
652
653 /// reposition the sub-surface
654 ///
655 /// This schedules a sub-surface position change.
656 /// The sub-surface will be moved so that its origin (top left
657 /// corner pixel) will be at the location x, y of the parent surface
658 /// coordinate system. The coordinates are not restricted to the parent
659 /// surface area. Negative values are allowed.
660 ///
661 /// The scheduled coordinates will take effect whenever the state of the
662 /// parent surface is applied.
663 ///
664 /// If more than one set_position request is invoked by the client before
665 /// the commit of the parent surface, the position of a new request always
666 /// replaces the scheduled position from any previous request.
667 ///
668 /// The initial position is 0, 0.
669 ///
670 /// # Arguments
671 ///
672 /// - `x`: x coordinate in the parent surface
673 /// - `y`: y coordinate in the parent surface
674 #[inline]
675 fn handle_set_position(
676 &mut self,
677 slf: &Rc<WlSubsurface>,
678 x: i32,
679 y: i32,
680 ) {
681 if !slf.core.forward_to_server.get() {
682 return;
683 }
684 let res = slf.try_send_set_position(
685 x,
686 y,
687 );
688 if let Err(e) = res {
689 log_forward("wl_subsurface.set_position", &e);
690 }
691 }
692
693 /// restack the sub-surface
694 ///
695 /// This sub-surface is taken from the stack, and put back just
696 /// above the reference surface, changing the z-order of the sub-surfaces.
697 /// The reference surface must be one of the sibling surfaces, or the
698 /// parent surface. Using any other surface, including this sub-surface,
699 /// will cause a protocol error.
700 ///
701 /// The z-order is double-buffered. Requests are handled in order and
702 /// applied immediately to a pending state. The final pending state is
703 /// copied to the active state the next time the state of the parent
704 /// surface is applied.
705 ///
706 /// A new sub-surface is initially added as the top-most in the stack
707 /// of its siblings and parent.
708 ///
709 /// # Arguments
710 ///
711 /// - `sibling`: the reference surface
712 ///
713 /// All borrowed proxies passed to this function are guaranteed to be
714 /// immutable and non-null.
715 #[inline]
716 fn handle_place_above(
717 &mut self,
718 slf: &Rc<WlSubsurface>,
719 sibling: &Rc<WlSurface>,
720 ) {
721 if !slf.core.forward_to_server.get() {
722 return;
723 }
724 let res = slf.try_send_place_above(
725 sibling,
726 );
727 if let Err(e) = res {
728 log_forward("wl_subsurface.place_above", &e);
729 }
730 }
731
732 /// restack the sub-surface
733 ///
734 /// The sub-surface is placed just below the reference surface.
735 /// See wl_subsurface.place_above.
736 ///
737 /// # Arguments
738 ///
739 /// - `sibling`: the reference surface
740 ///
741 /// All borrowed proxies passed to this function are guaranteed to be
742 /// immutable and non-null.
743 #[inline]
744 fn handle_place_below(
745 &mut self,
746 slf: &Rc<WlSubsurface>,
747 sibling: &Rc<WlSurface>,
748 ) {
749 if !slf.core.forward_to_server.get() {
750 return;
751 }
752 let res = slf.try_send_place_below(
753 sibling,
754 );
755 if let Err(e) = res {
756 log_forward("wl_subsurface.place_below", &e);
757 }
758 }
759
760 /// set sub-surface to synchronized mode
761 ///
762 /// Change the commit behaviour of the sub-surface to synchronized
763 /// mode, also described as the parent dependent mode.
764 ///
765 /// In synchronized mode, wl_surface.commit on a sub-surface will
766 /// accumulate the committed state in a cache, but the state will
767 /// not be applied and hence will not change the compositor output.
768 /// The cached state is applied to the sub-surface immediately after
769 /// the parent surface's state is applied. This ensures atomic
770 /// updates of the parent and all its synchronized sub-surfaces.
771 /// Applying the cached state will invalidate the cache, so further
772 /// parent surface commits do not (re-)apply old state.
773 ///
774 /// See wl_subsurface for the recursive effect of this mode.
775 #[inline]
776 fn handle_set_sync(
777 &mut self,
778 slf: &Rc<WlSubsurface>,
779 ) {
780 if !slf.core.forward_to_server.get() {
781 return;
782 }
783 let res = slf.try_send_set_sync(
784 );
785 if let Err(e) = res {
786 log_forward("wl_subsurface.set_sync", &e);
787 }
788 }
789
790 /// set sub-surface to desynchronized mode
791 ///
792 /// Change the commit behaviour of the sub-surface to desynchronized
793 /// mode, also described as independent or freely running mode.
794 ///
795 /// In desynchronized mode, wl_surface.commit on a sub-surface will
796 /// apply the pending state directly, without caching, as happens
797 /// normally with a wl_surface. Calling wl_surface.commit on the
798 /// parent surface has no effect on the sub-surface's wl_surface
799 /// state. This mode allows a sub-surface to be updated on its own.
800 ///
801 /// If cached state exists when wl_surface.commit is called in
802 /// desynchronized mode, the pending state is added to the cached
803 /// state, and applied as a whole. This invalidates the cache.
804 ///
805 /// Note: even if a sub-surface is set to desynchronized, a parent
806 /// sub-surface may override it to behave as synchronized. For details,
807 /// see wl_subsurface.
808 ///
809 /// If a surface's parent surface behaves as desynchronized, then
810 /// the cached state is applied on set_desync.
811 #[inline]
812 fn handle_set_desync(
813 &mut self,
814 slf: &Rc<WlSubsurface>,
815 ) {
816 if !slf.core.forward_to_server.get() {
817 return;
818 }
819 let res = slf.try_send_set_desync(
820 );
821 if let Err(e) = res {
822 log_forward("wl_subsurface.set_desync", &e);
823 }
824 }
825}
826
827impl ObjectPrivate for WlSubsurface {
828 fn new(state: &Rc<State>, version: u32) -> Rc<Self> {
829 Rc::<Self>::new_cyclic(|slf| Self {
830 core: ObjectCore::new(state, slf.clone(), ObjectInterface::WlSubsurface, version),
831 handler: Default::default(),
832 })
833 }
834
835 fn delete_id(self: Rc<Self>) -> Result<(), (ObjectError, Rc<dyn Object>)> {
836 let Some(mut handler) = self.handler.try_borrow_mut() else {
837 return Err((ObjectError(ObjectErrorKind::HandlerBorrowed), self));
838 };
839 if let Some(handler) = &mut *handler {
840 handler.delete_id(&self);
841 } else {
842 self.core.delete_id();
843 }
844 Ok(())
845 }
846
847 fn handle_request(self: Rc<Self>, client: &Rc<Client>, msg: &[u32], fds: &mut VecDeque<Rc<OwnedFd>>) -> Result<(), ObjectError> {
848 let Some(mut handler) = self.handler.try_borrow_mut() else {
849 return Err(ObjectError(ObjectErrorKind::HandlerBorrowed));
850 };
851 let handler = &mut *handler;
852 match msg[1] & 0xffff {
853 0 => {
854 if msg.len() != 2 {
855 return Err(ObjectError(ObjectErrorKind::WrongMessageSize(msg.len() as u32 * 4, 8)));
856 }
857 #[cfg(feature = "logging")]
858 if self.core.state.log {
859 #[cold]
860 fn log(state: &State, client_id: u64, id: u32) {
861 let (millis, micros) = time_since_epoch();
862 let prefix = &state.log_prefix;
863 let args = format_args!("[{millis:7}.{micros:03}] {prefix}client#{:<4} -> wl_subsurface#{}.destroy()\n", client_id, id);
864 state.log(args);
865 }
866 log(&self.core.state, client.endpoint.id, msg[0]);
867 }
868 self.core.handle_client_destroy();
869 if let Some(handler) = handler {
870 (**handler).handle_destroy(&self);
871 } else {
872 DefaultHandler.handle_destroy(&self);
873 }
874 }
875 1 => {
876 let [
877 arg0,
878 arg1,
879 ] = msg[2..] else {
880 return Err(ObjectError(ObjectErrorKind::WrongMessageSize(msg.len() as u32 * 4, 16)));
881 };
882 let arg0 = arg0 as i32;
883 let arg1 = arg1 as i32;
884 #[cfg(feature = "logging")]
885 if self.core.state.log {
886 #[cold]
887 fn log(state: &State, client_id: u64, id: u32, arg0: i32, arg1: i32) {
888 let (millis, micros) = time_since_epoch();
889 let prefix = &state.log_prefix;
890 let args = format_args!("[{millis:7}.{micros:03}] {prefix}client#{:<4} -> wl_subsurface#{}.set_position(x: {}, y: {})\n", client_id, id, arg0, arg1);
891 state.log(args);
892 }
893 log(&self.core.state, client.endpoint.id, msg[0], arg0, arg1);
894 }
895 if let Some(handler) = handler {
896 (**handler).handle_set_position(&self, arg0, arg1);
897 } else {
898 DefaultHandler.handle_set_position(&self, arg0, arg1);
899 }
900 }
901 2 => {
902 let [
903 arg0,
904 ] = msg[2..] else {
905 return Err(ObjectError(ObjectErrorKind::WrongMessageSize(msg.len() as u32 * 4, 12)));
906 };
907 #[cfg(feature = "logging")]
908 if self.core.state.log {
909 #[cold]
910 fn log(state: &State, client_id: u64, id: u32, arg0: u32) {
911 let (millis, micros) = time_since_epoch();
912 let prefix = &state.log_prefix;
913 let args = format_args!("[{millis:7}.{micros:03}] {prefix}client#{:<4} -> wl_subsurface#{}.place_above(sibling: wl_surface#{})\n", client_id, id, arg0);
914 state.log(args);
915 }
916 log(&self.core.state, client.endpoint.id, msg[0], arg0);
917 }
918 let arg0_id = arg0;
919 let Some(arg0) = client.endpoint.lookup(arg0_id) else {
920 return Err(ObjectError(ObjectErrorKind::NoClientObject(client.endpoint.id, arg0_id)));
921 };
922 let Ok(arg0) = (arg0 as Rc<dyn Any>).downcast::<WlSurface>() else {
923 let o = client.endpoint.lookup(arg0_id).unwrap();
924 return Err(ObjectError(ObjectErrorKind::WrongObjectType("sibling", o.core().interface, ObjectInterface::WlSurface)));
925 };
926 let arg0 = &arg0;
927 if let Some(handler) = handler {
928 (**handler).handle_place_above(&self, arg0);
929 } else {
930 DefaultHandler.handle_place_above(&self, arg0);
931 }
932 }
933 3 => {
934 let [
935 arg0,
936 ] = msg[2..] else {
937 return Err(ObjectError(ObjectErrorKind::WrongMessageSize(msg.len() as u32 * 4, 12)));
938 };
939 #[cfg(feature = "logging")]
940 if self.core.state.log {
941 #[cold]
942 fn log(state: &State, client_id: u64, id: u32, arg0: u32) {
943 let (millis, micros) = time_since_epoch();
944 let prefix = &state.log_prefix;
945 let args = format_args!("[{millis:7}.{micros:03}] {prefix}client#{:<4} -> wl_subsurface#{}.place_below(sibling: wl_surface#{})\n", client_id, id, arg0);
946 state.log(args);
947 }
948 log(&self.core.state, client.endpoint.id, msg[0], arg0);
949 }
950 let arg0_id = arg0;
951 let Some(arg0) = client.endpoint.lookup(arg0_id) else {
952 return Err(ObjectError(ObjectErrorKind::NoClientObject(client.endpoint.id, arg0_id)));
953 };
954 let Ok(arg0) = (arg0 as Rc<dyn Any>).downcast::<WlSurface>() else {
955 let o = client.endpoint.lookup(arg0_id).unwrap();
956 return Err(ObjectError(ObjectErrorKind::WrongObjectType("sibling", o.core().interface, ObjectInterface::WlSurface)));
957 };
958 let arg0 = &arg0;
959 if let Some(handler) = handler {
960 (**handler).handle_place_below(&self, arg0);
961 } else {
962 DefaultHandler.handle_place_below(&self, arg0);
963 }
964 }
965 4 => {
966 if msg.len() != 2 {
967 return Err(ObjectError(ObjectErrorKind::WrongMessageSize(msg.len() as u32 * 4, 8)));
968 }
969 #[cfg(feature = "logging")]
970 if self.core.state.log {
971 #[cold]
972 fn log(state: &State, client_id: u64, id: u32) {
973 let (millis, micros) = time_since_epoch();
974 let prefix = &state.log_prefix;
975 let args = format_args!("[{millis:7}.{micros:03}] {prefix}client#{:<4} -> wl_subsurface#{}.set_sync()\n", client_id, id);
976 state.log(args);
977 }
978 log(&self.core.state, client.endpoint.id, msg[0]);
979 }
980 if let Some(handler) = handler {
981 (**handler).handle_set_sync(&self);
982 } else {
983 DefaultHandler.handle_set_sync(&self);
984 }
985 }
986 5 => {
987 if msg.len() != 2 {
988 return Err(ObjectError(ObjectErrorKind::WrongMessageSize(msg.len() as u32 * 4, 8)));
989 }
990 #[cfg(feature = "logging")]
991 if self.core.state.log {
992 #[cold]
993 fn log(state: &State, client_id: u64, id: u32) {
994 let (millis, micros) = time_since_epoch();
995 let prefix = &state.log_prefix;
996 let args = format_args!("[{millis:7}.{micros:03}] {prefix}client#{:<4} -> wl_subsurface#{}.set_desync()\n", client_id, id);
997 state.log(args);
998 }
999 log(&self.core.state, client.endpoint.id, msg[0]);
1000 }
1001 if let Some(handler) = handler {
1002 (**handler).handle_set_desync(&self);
1003 } else {
1004 DefaultHandler.handle_set_desync(&self);
1005 }
1006 }
1007 n => {
1008 let _ = client;
1009 let _ = msg;
1010 let _ = fds;
1011 let _ = handler;
1012 return Err(ObjectError(ObjectErrorKind::UnknownMessageId(n)));
1013 }
1014 }
1015 Ok(())
1016 }
1017
1018 fn handle_event(self: Rc<Self>, server: &Endpoint, msg: &[u32], fds: &mut VecDeque<Rc<OwnedFd>>) -> Result<(), ObjectError> {
1019 let Some(mut handler) = self.handler.try_borrow_mut() else {
1020 return Err(ObjectError(ObjectErrorKind::HandlerBorrowed));
1021 };
1022 let handler = &mut *handler;
1023 match msg[1] & 0xffff {
1024 n => {
1025 let _ = server;
1026 let _ = msg;
1027 let _ = fds;
1028 let _ = handler;
1029 return Err(ObjectError(ObjectErrorKind::UnknownMessageId(n)));
1030 }
1031 }
1032 }
1033
1034 fn get_request_name(&self, id: u32) -> Option<&'static str> {
1035 let name = match id {
1036 0 => "destroy",
1037 1 => "set_position",
1038 2 => "place_above",
1039 3 => "place_below",
1040 4 => "set_sync",
1041 5 => "set_desync",
1042 _ => return None,
1043 };
1044 Some(name)
1045 }
1046
1047 fn get_event_name(&self, id: u32) -> Option<&'static str> {
1048 let _ = id;
1049 None
1050 }
1051}
1052
1053impl Object for WlSubsurface {
1054 fn core(&self) -> &ObjectCore {
1055 &self.core
1056 }
1057
1058 fn unset_handler(&self) {
1059 self.handler.set(None);
1060 }
1061
1062 fn get_handler_any_ref(&self) -> Result<HandlerRef<'_, dyn Any>, HandlerAccessError> {
1063 let borrowed = self.handler.try_borrow().ok_or(HandlerAccessError::AlreadyBorrowed)?;
1064 if borrowed.is_none() {
1065 return Err(HandlerAccessError::NoHandler);
1066 }
1067 Ok(HandlerRef::map(borrowed, |handler| &**handler.as_ref().unwrap() as &dyn Any))
1068 }
1069
1070 fn get_handler_any_mut(&self) -> Result<HandlerMut<'_, dyn Any>, HandlerAccessError> {
1071 let borrowed = self.handler.try_borrow_mut().ok_or(HandlerAccessError::AlreadyBorrowed)?;
1072 if borrowed.is_none() {
1073 return Err(HandlerAccessError::NoHandler);
1074 }
1075 Ok(HandlerMut::map(borrowed, |handler| &mut **handler.as_mut().unwrap() as &mut dyn Any))
1076 }
1077}
1078
1079impl WlSubsurface {
1080 /// Since when the error.bad_surface enum variant is available.
1081 pub const ENM__ERROR_BAD_SURFACE__SINCE: u32 = 1;
1082}
1083
1084#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
1085pub struct WlSubsurfaceError(pub u32);
1086
1087impl WlSubsurfaceError {
1088 /// wl_surface is not a sibling or the parent
1089 pub const BAD_SURFACE: Self = Self(0);
1090}
1091
1092impl Debug for WlSubsurfaceError {
1093 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1094 let name = match *self {
1095 Self::BAD_SURFACE => "BAD_SURFACE",
1096 _ => return Debug::fmt(&self.0, f),
1097 };
1098 f.write_str(name)
1099 }
1100}