ferroui_base/rendering/composition/server/
server_composition_surface_visual.rs1use super::{IServerCompositionSurface, IServerVisualContent, ServerCompositionTarget, ServerCompositionVisual, ServerSizeDependantVisual, ServerVisualRenderContext};
2use crate::platform::LtrbRect;
3use crate::rendering::composition::generated::{
4 ServerCompositionSurfaceVisualHooks, ServerCompositionSurfaceVisualProps,
5};
6use crate::rendering::composition::transport::BatchStreamReader;
7use crate::{Rect, Size};
8use std::any::{Any, TypeId};
9use std::rc::Rc;
10use std::time::Duration;
11
12#[derive(Default)]
14pub struct ServerCompositionSurfaceVisual {
15 props: ServerCompositionSurfaceVisualProps,
16}
17
18impl ServerCompositionSurfaceVisual {
19 pub fn new() -> Self {
20 Self::default()
21 }
22
23 pub fn surface(&self) -> Option<Rc<dyn IServerCompositionSurface>> {
24 self.props.surface().and_then(|surface| surface.as_surface())
25 }
26
27 fn subscribe(&self, visual: &ServerCompositionVisual) {
28 if let Some(surface) = self.surface() {
29 let weak = visual.weak();
30 surface.changed().add(
31 weak.as_ptr() as usize,
32 Rc::new(move || {
33 if let Some(visual) = weak.upgrade() {
35 visual.invalidate_content();
36 }
37 }),
38 );
39 }
40 }
41
42 fn unsubscribe(&self, visual: &ServerCompositionVisual) {
43 if let Some(surface) = self.surface() {
44 surface.changed().remove(visual.weak().as_ptr() as usize);
45 }
46 }
47}
48
49impl ServerCompositionSurfaceVisualHooks for ServerCompositionVisual {
50 fn base_deserialize_changes_core(&self, reader: &mut BatchStreamReader<'_>, committed_at: Duration) {
51 ServerCompositionVisual::base_deserialize_changes_core(self, reader, committed_at);
52 }
53
54 fn on_surface_changed(&self) {
55 if let Some(content) = self.content_as::<ServerCompositionSurfaceVisual>() {
56 content.subscribe(self);
57 }
58 }
59
60 fn on_surface_changing(&self) {
61 if let Some(content) = self.content_as::<ServerCompositionSurfaceVisual>() {
62 content.unsubscribe(self);
63 }
64 }
65}
66
67impl IServerVisualContent for ServerCompositionSurfaceVisual {
68 fn deserialize_changes_core(
69 &self,
70 visual: &ServerCompositionVisual,
71 reader: &mut BatchStreamReader<'_>,
72 committed_at: Duration,
73 ) {
74 self.props.deserialize_changes_core(visual, reader, committed_at);
75 }
76
77 fn compute_own_content_bounds(&self, visual: &ServerCompositionVisual) -> Option<LtrbRect> {
78 ServerSizeDependantVisual::compute_own_content_bounds(visual)
79 }
80
81 fn size_changed(&self, visual: &ServerCompositionVisual) {
82 ServerSizeDependantVisual::size_changed(visual);
83 }
84
85 fn render_core(
86 &self,
87 visual: &ServerCompositionVisual,
88 context: &mut ServerVisualRenderContext<'_>,
89 _current_transformed_clip: LtrbRect,
90 ) {
91 let Some(surface) = self.surface() else { return };
92
93 let size = visual.size();
98 surface.draw(context.canvas(), Rect::from_size(Size::new(size.x, size.y)), 1.0);
99 }
100
101 fn on_attached_to_root(&self, visual: &ServerCompositionVisual, _target: &Rc<ServerCompositionTarget>) {
102 self.subscribe(visual);
103 }
104
105 fn on_detached_from_root(&self, visual: &ServerCompositionVisual, _target: &Rc<ServerCompositionTarget>) {
106 self.unsubscribe(visual);
107 }
108
109 fn dispose(&self, visual: &ServerCompositionVisual) {
110 self.unsubscribe(visual);
111 }
112
113 fn find_props(&self, type_id: TypeId) -> Option<&dyn Any> {
114 self.props.find_props(type_id)
115 }
116
117 fn as_any(&self) -> &dyn Any {
118 self
119 }
120}