Skip to main content

ferroui_base/rendering/composition/generated/
composition_visual_surface.rs

1// @generated by scripts/generate_composition.py — do not edit
2
3//! `CompositionVisualSurface`.
4//!
5//! Defined by the FerroUI overlay (scripts/composition-schema-winui.xml).
6
7use bitflags::bitflags;
8use crate::Vector;
9use crate::rendering::composition::ICompositionObject;
10use crate::rendering::composition::ICompositionObjectHost;
11use crate::rendering::composition::animations::AnimationInstanceFactory;
12use crate::rendering::composition::animations::ICompositionAnimation;
13use crate::rendering::composition::expressions::ExpressionVariant;
14use crate::rendering::composition::server::AsServerRenderResource;
15use crate::rendering::composition::server::CompositionProperty;
16use crate::rendering::composition::server::CompositionPropertyOf;
17use crate::rendering::composition::server::IServerAnimatedPropertyHost;
18use crate::rendering::composition::server::IServerObject;
19use crate::rendering::composition::server::ServerPropertyValue;
20use crate::rendering::composition::server::ServerValueChange;
21use crate::rendering::composition::server::props_of;
22use crate::rendering::composition::server::read_server_object;
23use crate::rendering::composition::transport::BatchStreamReader;
24use crate::rendering::composition::transport::BatchStreamWriter;
25use crate::rendering::composition::transport::BatchValue;
26use crate::rendering::composition::transport::BatchValueReader;
27use std::any::Any;
28use std::any::TypeId;
29use std::cell::Cell;
30use std::cell::RefCell;
31use std::rc::Rc;
32use std::sync::OnceLock;
33use std::time::Duration;
34
35bitflags! {
36    /// The fields of `CompositionVisualSurface` that changed since its last serialization.
37    #[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
38    pub struct CompositionVisualSurfaceChangedFields: u8 {
39        const SOURCE_VISUAL = 1;
40        const SOURCE_OFFSET = 2;
41        const SOURCE_OFFSET_ANIMATED = 4;
42        const SOURCE_SIZE = 8;
43        const SOURCE_SIZE_ANIMATED = 16;
44    }
45}
46
47impl BatchValue for CompositionVisualSurfaceChangedFields {
48    #[inline]
49    fn write_to(&self, out: &mut Vec<u8>) {
50        self.bits().write_to(out);
51    }
52
53    #[inline]
54    fn read_from(input: &mut BatchValueReader<'_>) -> Self {
55        CompositionVisualSurfaceChangedFields::from_bits_retain(u8::read_from(input))
56    }
57}
58
59/// The partial methods of `CompositionVisualSurface`: implemented by the class that embeds
60/// [`CompositionVisualSurfaceProps`]. Every hook defaults to doing nothing.
61pub trait CompositionVisualSurfaceHooks: ICompositionObjectHost {
62    fn initialize_defaults_extra(&self) {}
63
64    fn validate_source_visual_change(&self, _old_value: &Option<Rc<dyn ICompositionObject>>, _new_value: &Option<Rc<dyn ICompositionObject>>) {}
65    fn on_source_visual_changed(&self) {}
66    fn on_source_visual_changing(&self) {}
67
68    fn validate_source_offset_change(&self, _old_value: Vector, _new_value: Vector) {}
69    fn on_source_offset_changed(&self) {}
70    fn on_source_offset_changing(&self) {}
71
72    fn validate_source_size_change(&self, _old_value: Vector, _new_value: Vector) {}
73    fn on_source_size_changed(&self) {}
74    fn on_source_size_changing(&self) {}
75}
76
77/// The UI-thread properties of `CompositionVisualSurface`.
78pub struct CompositionVisualSurfaceProps {
79    changed_fields_of_composition_visual_surface: Cell<CompositionVisualSurfaceChangedFields>,
80    source_visual: RefCell<Option<Rc<dyn ICompositionObject>>>,
81    source_offset: Cell<Vector>,
82    source_size: Cell<Vector>,
83}
84
85impl Default for CompositionVisualSurfaceProps {
86    fn default() -> Self {
87        Self::new()
88    }
89}
90
91impl CompositionVisualSurfaceProps {
92    /// Creates the properties with every field at the default of its type.
93    /// The defaults of the schema are applied by
94    /// [`initialize_defaults`](Self::initialize_defaults).
95    pub fn new() -> Self {
96        Self {
97            changed_fields_of_composition_visual_surface: Cell::new(CompositionVisualSurfaceChangedFields::empty()),
98            source_visual: RefCell::new(None),
99            source_offset: Cell::new(Default::default()),
100            source_size: Cell::new(Default::default()),
101        }
102    }
103
104    /// The `InitializeDefaults` calls of the constructor chain: the base
105    /// classes first, then this class.
106    pub fn initialize_defaults(&self, host: &dyn CompositionVisualSurfaceHooks) {
107        self.initialize_own_defaults(host);
108    }
109
110    /// `InitializeDefaults` of this class alone.
111    pub fn initialize_own_defaults(&self, host: &dyn CompositionVisualSurfaceHooks) {
112        CompositionVisualSurfaceHooks::initialize_defaults_extra(host);
113    }
114
115    /// `SourceVisual` (FerroUI overlay).
116    pub fn source_visual(&self) -> Option<Rc<dyn ICompositionObject>> {
117        self.source_visual.borrow().clone()
118    }
119
120    /// Sets `SourceVisual` (FerroUI overlay).
121    pub fn set_source_visual(&self, host: &dyn CompositionVisualSurfaceHooks, value: Option<Rc<dyn ICompositionObject>>) {
122        let mut changed = false;
123        let old_value = self.source_visual.borrow().clone();
124        if old_value.differs(&value) {
125            CompositionVisualSurfaceHooks::validate_source_visual_change(host, &old_value, &value);
126            CompositionVisualSurfaceHooks::on_source_visual_changing(host);
127            changed = true;
128            // Update the backing value
129            *self.source_visual.borrow_mut() = value.clone();
130            // Register object for serialization in the next batch
131            self.changed_fields_of_composition_visual_surface.set(self.changed_fields_of_composition_visual_surface.get() | CompositionVisualSurfaceChangedFields::SOURCE_VISUAL);
132            host.register_for_serialization();
133        }
134        *self.source_visual.borrow_mut() = value;
135        if changed {
136            CompositionVisualSurfaceHooks::on_source_visual_changed(host);
137        }
138    }
139
140    /// `SourceOffset` (animated, FerroUI overlay).
141    pub fn source_offset(&self) -> Vector {
142        self.source_offset.get()
143    }
144
145    /// Sets `SourceOffset` (animated, FerroUI overlay).
146    pub fn set_source_offset(&self, host: &dyn CompositionVisualSurfaceHooks, value: Vector) {
147        let mut changed = false;
148        let old_value = self.source_offset.get();
149        if old_value.differs(&value) {
150            CompositionVisualSurfaceHooks::validate_source_offset_change(host, old_value, value);
151            CompositionVisualSurfaceHooks::on_source_offset_changing(host);
152            changed = true;
153            // Update the backing value
154            self.source_offset.set(value);
155            // Register object for serialization in the next batch
156            self.changed_fields_of_composition_visual_surface.set(self.changed_fields_of_composition_visual_surface.get() | CompositionVisualSurfaceChangedFields::SOURCE_OFFSET);
157            host.register_for_serialization();
158            // Reset previous animation if any
159            host.pending_animations().remove(ServerCompositionVisualSurfaceProps::id_of_source_offset_property().base());
160            self.changed_fields_of_composition_visual_surface.set(self.changed_fields_of_composition_visual_surface.get() & !CompositionVisualSurfaceChangedFields::SOURCE_OFFSET_ANIMATED);
161            // Check for implicit animations
162            if let Some(animation) = host.implicit_animation("SourceOffset") {
163                // Animation affects only current property
164                if let Some(a) = animation.as_composition_animation() {
165                    self.changed_fields_of_composition_visual_surface.set(self.changed_fields_of_composition_visual_surface.get() | CompositionVisualSurfaceChangedFields::SOURCE_OFFSET_ANIMATED);
166                    host.pending_animations().set(
167                        ServerCompositionVisualSurfaceProps::id_of_source_offset_property().base(),
168                        a.create_instance(host.server(), Some(ExpressionVariant::create(value))),
169                    );
170                }
171                // Animation is triggered by the current field, but does not necessary affects it
172                host.start_animation_group(&animation, "SourceOffset", ExpressionVariant::create(value));
173            }
174        }
175        self.source_offset.set(value);
176        if changed {
177            CompositionVisualSurfaceHooks::on_source_offset_changed(host);
178        }
179    }
180
181    /// `SourceSize` (animated, FerroUI overlay).
182    pub fn source_size(&self) -> Vector {
183        self.source_size.get()
184    }
185
186    /// Sets `SourceSize` (animated, FerroUI overlay).
187    pub fn set_source_size(&self, host: &dyn CompositionVisualSurfaceHooks, value: Vector) {
188        let mut changed = false;
189        let old_value = self.source_size.get();
190        if old_value.differs(&value) {
191            CompositionVisualSurfaceHooks::validate_source_size_change(host, old_value, value);
192            CompositionVisualSurfaceHooks::on_source_size_changing(host);
193            changed = true;
194            // Update the backing value
195            self.source_size.set(value);
196            // Register object for serialization in the next batch
197            self.changed_fields_of_composition_visual_surface.set(self.changed_fields_of_composition_visual_surface.get() | CompositionVisualSurfaceChangedFields::SOURCE_SIZE);
198            host.register_for_serialization();
199            // Reset previous animation if any
200            host.pending_animations().remove(ServerCompositionVisualSurfaceProps::id_of_source_size_property().base());
201            self.changed_fields_of_composition_visual_surface.set(self.changed_fields_of_composition_visual_surface.get() & !CompositionVisualSurfaceChangedFields::SOURCE_SIZE_ANIMATED);
202            // Check for implicit animations
203            if let Some(animation) = host.implicit_animation("SourceSize") {
204                // Animation affects only current property
205                if let Some(a) = animation.as_composition_animation() {
206                    self.changed_fields_of_composition_visual_surface.set(self.changed_fields_of_composition_visual_surface.get() | CompositionVisualSurfaceChangedFields::SOURCE_SIZE_ANIMATED);
207                    host.pending_animations().set(
208                        ServerCompositionVisualSurfaceProps::id_of_source_size_property().base(),
209                        a.create_instance(host.server(), Some(ExpressionVariant::create(value))),
210                    );
211                }
212                // Animation is triggered by the current field, but does not necessary affects it
213                host.start_animation_group(&animation, "SourceSize", ExpressionVariant::create(value));
214            }
215        }
216        self.source_size.set(value);
217        if changed {
218            CompositionVisualSurfaceHooks::on_source_size_changed(host);
219        }
220    }
221
222    /// Connects an animation with the named property. Returns `false` when
223    /// neither this class nor its generated bases have an animated property
224    /// of that name: the caller continues with its hand-written base.
225    pub fn start_animation(
226        &self,
227        host: &dyn CompositionVisualSurfaceHooks,
228        property_name: &str,
229        animation: &dyn ICompositionAnimation,
230        final_value: Option<ExpressionVariant>,
231    ) -> bool {
232        if property_name == "SourceOffset" {
233            let server = animation.create_instance(host.server(), final_value);
234            host.pending_animations().set(ServerCompositionVisualSurfaceProps::id_of_source_offset_property().base(), server);
235            self.changed_fields_of_composition_visual_surface.set(self.changed_fields_of_composition_visual_surface.get() | CompositionVisualSurfaceChangedFields::SOURCE_OFFSET_ANIMATED);
236            host.register_for_serialization();
237            return true;
238        }
239        if property_name == "SourceSize" {
240            let server = animation.create_instance(host.server(), final_value);
241            host.pending_animations().set(ServerCompositionVisualSurfaceProps::id_of_source_size_property().base(), server);
242            self.changed_fields_of_composition_visual_surface.set(self.changed_fields_of_composition_visual_surface.get() | CompositionVisualSurfaceChangedFields::SOURCE_SIZE_ANIMATED);
243            host.register_for_serialization();
244            return true;
245        }
246        false
247    }
248
249    /// Writes the changes of the object: the base class first, then the
250    /// changed-fields mask and the changed members of this class.
251    pub fn serialize_changes_core(&self, host: &dyn CompositionVisualSurfaceHooks, writer: &mut BatchStreamWriter<'_>) {
252        let changed = self.changed_fields_of_composition_visual_surface.get();
253        writer.write(changed);
254        if changed.contains(CompositionVisualSurfaceChangedFields::SOURCE_VISUAL) {
255            writer.write_server_object(self.source_visual.borrow().clone().map(|o| o.server()));
256        }
257        if changed.contains(CompositionVisualSurfaceChangedFields::SOURCE_OFFSET_ANIMATED) {
258            writer.write_value(host.pending_animations().get_and_remove(ServerCompositionVisualSurfaceProps::id_of_source_offset_property().base()));
259        } else if changed.contains(CompositionVisualSurfaceChangedFields::SOURCE_OFFSET) {
260            writer.write(self.source_offset.get());
261        }
262        if changed.contains(CompositionVisualSurfaceChangedFields::SOURCE_SIZE_ANIMATED) {
263            writer.write_value(host.pending_animations().get_and_remove(ServerCompositionVisualSurfaceProps::id_of_source_size_property().base()));
264        } else if changed.contains(CompositionVisualSurfaceChangedFields::SOURCE_SIZE) {
265            writer.write(self.source_size.get());
266        }
267        self.changed_fields_of_composition_visual_surface.set(CompositionVisualSurfaceChangedFields::empty());
268    }
269}
270
271/// The partial methods of `ServerCompositionVisualSurface`: implemented by the class that embeds
272/// [`ServerCompositionVisualSurfaceProps`]. Every hook defaults to doing nothing.
273pub trait ServerCompositionVisualSurfaceHooks: IServerAnimatedPropertyHost {
274    fn deserialize_changes_extra(&self, _reader: &mut BatchStreamReader<'_>) {}
275    fn on_fields_deserialized(&self, _changed: CompositionVisualSurfaceChangedFields) {}
276
277    fn on_source_visual_changed(&self) {}
278    fn on_source_visual_changing(&self) {}
279}
280
281/// The server-side properties of `ServerCompositionVisualSurface`.
282pub struct ServerCompositionVisualSurfaceProps {
283    source_visual: RefCell<Option<Rc<dyn IServerObject>>>,
284    source_offset: Cell<Vector>,
285    source_size: Cell<Vector>,
286}
287
288impl Default for ServerCompositionVisualSurfaceProps {
289    fn default() -> Self {
290        Self::new()
291    }
292}
293
294impl ServerCompositionVisualSurfaceProps {
295    /// Creates the properties with every field at the default of its type; the
296    /// values of the UI thread arrive with the first batch.
297    pub fn new() -> Self {
298        Self {
299            source_visual: RefCell::new(None),
300            source_offset: Cell::new(Default::default()),
301            source_size: Cell::new(Default::default()),
302        }
303    }
304
305    /// This block or the block of a base class, by type: what
306    /// `IServerObject::get_props` of the embedding class returns.
307    pub fn find_props(&self, type_id: TypeId) -> Option<&dyn Any> {
308        if type_id == TypeId::of::<Self>() {
309            return Some(self);
310        }
311        None
312    }
313
314    /// The composition property of `SourceVisual`.
315    pub fn id_of_source_visual_property() -> &'static CompositionPropertyOf<Option<Rc<dyn IServerObject>>> {
316        static PROPERTY: OnceLock<CompositionPropertyOf<Option<Rc<dyn IServerObject>>>> = OnceLock::new();
317        PROPERTY.get_or_init(|| {
318            CompositionProperty::register::<ServerCompositionVisualSurfaceProps, Option<Rc<dyn IServerObject>>>(
319                "SourceVisual",
320                "ServerCompositionVisualSurface",
321                |obj| props_of::<ServerCompositionVisualSurfaceProps>(obj).source_visual.borrow().clone(),
322                |obj, v| *props_of::<ServerCompositionVisualSurfaceProps>(obj).source_visual.borrow_mut() = v,
323                None,
324                None,
325            )
326        })
327    }
328
329    /// `SourceVisual`.
330    pub fn source_visual(&self) -> Option<Rc<dyn IServerObject>> {
331        self.source_visual.borrow().clone()
332    }
333
334    pub fn set_source_visual(&self, host: &dyn ServerCompositionVisualSurfaceHooks, value: Option<Rc<dyn IServerObject>>) {
335        let old_value = self.source_visual.borrow().clone();
336        let mut changed = false;
337        if old_value.differs(&value) {
338            ServerCompositionVisualSurfaceHooks::on_source_visual_changing(host);
339            changed = true;
340        }
341        host.set_value(
342            Self::id_of_source_visual_property().base(),
343            ServerValueChange {
344                equal: old_value.default_equals(&value),
345                old_resource: old_value.as_server_render_resource(),
346                new_resource: value.as_server_render_resource(),
347                assign: &mut || *self.source_visual.borrow_mut() = value.clone(),
348            },
349        );
350        if changed {
351            ServerCompositionVisualSurfaceHooks::on_source_visual_changed(host);
352        }
353    }
354
355    /// The composition property of `SourceOffset`.
356    pub fn id_of_source_offset_property() -> &'static CompositionPropertyOf<Vector> {
357        static PROPERTY: OnceLock<CompositionPropertyOf<Vector>> = OnceLock::new();
358        PROPERTY.get_or_init(|| {
359            CompositionProperty::register::<ServerCompositionVisualSurfaceProps, Vector>(
360                "SourceOffset",
361                "ServerCompositionVisualSurface",
362                |obj| props_of::<ServerCompositionVisualSurfaceProps>(obj).source_offset.get(),
363                |obj, v| props_of::<ServerCompositionVisualSurfaceProps>(obj).source_offset.set(v),
364                Some(|obj| ExpressionVariant::create(props_of::<ServerCompositionVisualSurfaceProps>(obj).source_offset.get())),
365                Some(|obj, v: ExpressionVariant| props_of::<ServerCompositionVisualSurfaceProps>(obj).source_offset.set(v.cast_or_default::<Vector>())),
366            )
367        })
368    }
369
370    /// `SourceOffset` (animated).
371    pub fn source_offset(&self) -> Vector {
372        self.source_offset.get()
373    }
374
375    pub fn set_source_offset(&self, host: &dyn ServerCompositionVisualSurfaceHooks, value: Vector) {
376        self.source_offset.set(value);
377        host.remove_animation_for_property(Self::id_of_source_offset_property().base());
378    }
379
380    /// The composition property of `SourceSize`.
381    pub fn id_of_source_size_property() -> &'static CompositionPropertyOf<Vector> {
382        static PROPERTY: OnceLock<CompositionPropertyOf<Vector>> = OnceLock::new();
383        PROPERTY.get_or_init(|| {
384            CompositionProperty::register::<ServerCompositionVisualSurfaceProps, Vector>(
385                "SourceSize",
386                "ServerCompositionVisualSurface",
387                |obj| props_of::<ServerCompositionVisualSurfaceProps>(obj).source_size.get(),
388                |obj, v| props_of::<ServerCompositionVisualSurfaceProps>(obj).source_size.set(v),
389                Some(|obj| ExpressionVariant::create(props_of::<ServerCompositionVisualSurfaceProps>(obj).source_size.get())),
390                Some(|obj, v: ExpressionVariant| props_of::<ServerCompositionVisualSurfaceProps>(obj).source_size.set(v.cast_or_default::<Vector>())),
391            )
392        })
393    }
394
395    /// `SourceSize` (animated).
396    pub fn source_size(&self) -> Vector {
397        self.source_size.get()
398    }
399
400    pub fn set_source_size(&self, host: &dyn ServerCompositionVisualSurfaceHooks, value: Vector) {
401        self.source_size.set(value);
402        host.remove_animation_for_property(Self::id_of_source_size_property().base());
403    }
404
405    /// Reads the changes of the object: the base class first, then the
406    /// changed-fields mask and the changed members of this class.
407    pub fn deserialize_changes_core(
408        &self,
409        host: &dyn ServerCompositionVisualSurfaceHooks,
410        reader: &mut BatchStreamReader<'_>,
411        committed_at: Duration,
412    ) {
413        let compositor = host.server_compositor();
414        ServerCompositionVisualSurfaceHooks::deserialize_changes_extra(host, reader);
415        let changed = reader.read::<CompositionVisualSurfaceChangedFields>();
416        if changed.contains(CompositionVisualSurfaceChangedFields::SOURCE_VISUAL) {
417            let value = read_server_object(reader, compositor.as_ref());
418            self.set_source_visual(host, value);
419        }
420        if changed.contains(CompositionVisualSurfaceChangedFields::SOURCE_OFFSET_ANIMATED) {
421            let Some(animation) = reader.read_value::<AnimationInstanceFactory>().map(AnimationInstanceFactory::create) else {
422                panic!("a batch starts an animation of `SourceOffset` without an animation instance");
423            };
424            host.set_animated_value(
425                Self::id_of_source_offset_property().base(),
426                ExpressionVariant::create(self.source_offset.get()),
427                committed_at,
428                animation,
429            );
430        } else if changed.contains(CompositionVisualSurfaceChangedFields::SOURCE_OFFSET) {
431            let value = reader.read::<Vector>();
432            self.set_source_offset(host, value);
433        }
434        if changed.contains(CompositionVisualSurfaceChangedFields::SOURCE_SIZE_ANIMATED) {
435            let Some(animation) = reader.read_value::<AnimationInstanceFactory>().map(AnimationInstanceFactory::create) else {
436                panic!("a batch starts an animation of `SourceSize` without an animation instance");
437            };
438            host.set_animated_value(
439                Self::id_of_source_size_property().base(),
440                ExpressionVariant::create(self.source_size.get()),
441                committed_at,
442                animation,
443            );
444        } else if changed.contains(CompositionVisualSurfaceChangedFields::SOURCE_SIZE) {
445            let value = reader.read::<Vector>();
446            self.set_source_size(host, value);
447        }
448        ServerCompositionVisualSurfaceHooks::on_fields_deserialized(host, changed);
449    }
450
451    /// The composition property with the given name, among the properties
452    /// of this class and of its generated bases that have a variant form.
453    pub fn get_composition_property(name: &str) -> Option<&'static CompositionProperty> {
454        if name == "SourceOffset" {
455            return Some(Self::id_of_source_offset_property().base());
456        }
457        if name == "SourceSize" {
458            return Some(Self::id_of_source_size_property().base());
459        }
460        None
461    }
462}