1use bitflags::bitflags;
8use crate::Size;
9use crate::rendering::LayoutPassTiming;
10use crate::rendering::RendererDebugOverlays;
11use crate::rendering::composition::CompositionTransparencyLevel;
12use crate::rendering::composition::ICompositionObject;
13use crate::rendering::composition::ICompositionObjectHost;
14use crate::rendering::composition::expressions::ExpressionVariant;
15use crate::rendering::composition::server::AsServerRenderResource;
16use crate::rendering::composition::server::CompositionProperty;
17use crate::rendering::composition::server::CompositionPropertyOf;
18use crate::rendering::composition::server::IServerAnimatedPropertyHost;
19use crate::rendering::composition::server::IServerObject;
20use crate::rendering::composition::server::ServerPropertyValue;
21use crate::rendering::composition::server::ServerValueChange;
22use crate::rendering::composition::server::props_of;
23use crate::rendering::composition::server::read_server_object;
24use crate::rendering::composition::transport::BatchStreamReader;
25use crate::rendering::composition::transport::BatchStreamWriter;
26use crate::rendering::composition::transport::BatchValue;
27use crate::rendering::composition::transport::BatchValueReader;
28use std::any::Any;
29use std::any::TypeId;
30use std::cell::Cell;
31use std::cell::RefCell;
32use std::rc::Rc;
33use std::sync::Arc;
34use std::sync::OnceLock;
35use std::time::Duration;
36
37bitflags! {
38 #[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
40 pub struct CompositionTargetChangedFields: u8 {
41 const ROOT = 1;
42 const IS_ENABLED = 2;
43 const DEBUG_OVERLAYS = 4;
44 const LAST_LAYOUT_PASS_TIMING = 8;
45 const SCALING = 16;
46 const SIZE = 32;
47 const TRANSPARENCY_LEVEL = 64;
48 const PLATFORM_SPECIFIC_SCENE_INFO = 128;
49 }
50}
51
52impl BatchValue for CompositionTargetChangedFields {
53 #[inline]
54 fn write_to(&self, out: &mut Vec<u8>) {
55 self.bits().write_to(out);
56 }
57
58 #[inline]
59 fn read_from(input: &mut BatchValueReader<'_>) -> Self {
60 CompositionTargetChangedFields::from_bits_retain(u8::read_from(input))
61 }
62}
63
64pub trait CompositionTargetHooks: ICompositionObjectHost {
67 fn initialize_defaults_extra(&self) {}
68
69 fn validate_root_change(&self, _old_value: &Option<Rc<dyn ICompositionObject>>, _new_value: &Option<Rc<dyn ICompositionObject>>) {}
70 fn on_root_changed(&self) {}
71 fn on_root_changing(&self) {}
72
73 fn validate_is_enabled_change(&self, _old_value: bool, _new_value: bool) {}
74 fn on_is_enabled_changed(&self) {}
75 fn on_is_enabled_changing(&self) {}
76
77 fn validate_debug_overlays_change(&self, _old_value: RendererDebugOverlays, _new_value: RendererDebugOverlays) {}
78 fn on_debug_overlays_changed(&self) {}
79 fn on_debug_overlays_changing(&self) {}
80
81 fn validate_last_layout_pass_timing_change(&self, _old_value: LayoutPassTiming, _new_value: LayoutPassTiming) {}
82 fn on_last_layout_pass_timing_changed(&self) {}
83 fn on_last_layout_pass_timing_changing(&self) {}
84
85 fn validate_scaling_change(&self, _old_value: f64, _new_value: f64) {}
86 fn on_scaling_changed(&self) {}
87 fn on_scaling_changing(&self) {}
88
89 fn validate_size_change(&self, _old_value: Size, _new_value: Size) {}
90 fn on_size_changed(&self) {}
91 fn on_size_changing(&self) {}
92
93 fn validate_transparency_level_change(&self, _old_value: CompositionTransparencyLevel, _new_value: CompositionTransparencyLevel) {}
94 fn on_transparency_level_changed(&self) {}
95 fn on_transparency_level_changing(&self) {}
96
97 fn validate_platform_specific_scene_info_change(&self, _old_value: &Option<Arc<dyn Any + Send + Sync>>, _new_value: &Option<Arc<dyn Any + Send + Sync>>) {}
98 fn on_platform_specific_scene_info_changed(&self) {}
99 fn on_platform_specific_scene_info_changing(&self) {}
100}
101
102pub struct CompositionTargetProps {
104 changed_fields_of_composition_target: Cell<CompositionTargetChangedFields>,
105 root: RefCell<Option<Rc<dyn ICompositionObject>>>,
106 is_enabled: Cell<bool>,
107 debug_overlays: Cell<RendererDebugOverlays>,
108 last_layout_pass_timing: Cell<LayoutPassTiming>,
109 scaling: Cell<f64>,
110 size: Cell<Size>,
111 transparency_level: Cell<CompositionTransparencyLevel>,
112 platform_specific_scene_info: RefCell<Option<Arc<dyn Any + Send + Sync>>>,
113}
114
115impl Default for CompositionTargetProps {
116 fn default() -> Self {
117 Self::new()
118 }
119}
120
121impl CompositionTargetProps {
122 pub fn new() -> Self {
126 Self {
127 changed_fields_of_composition_target: Cell::new(CompositionTargetChangedFields::empty()),
128 root: RefCell::new(None),
129 is_enabled: Cell::new(Default::default()),
130 debug_overlays: Cell::new(Default::default()),
131 last_layout_pass_timing: Cell::new(Default::default()),
132 scaling: Cell::new(Default::default()),
133 size: Cell::new(Default::default()),
134 transparency_level: Cell::new(Default::default()),
135 platform_specific_scene_info: RefCell::new(None),
136 }
137 }
138
139 pub fn initialize_defaults(&self, host: &dyn CompositionTargetHooks) {
142 self.initialize_own_defaults(host);
143 }
144
145 pub fn initialize_own_defaults(&self, host: &dyn CompositionTargetHooks) {
147 CompositionTargetHooks::initialize_defaults_extra(host);
148 }
149
150 pub fn root(&self) -> Option<Rc<dyn ICompositionObject>> {
152 self.root.borrow().clone()
153 }
154
155 pub fn set_root(&self, host: &dyn CompositionTargetHooks, value: Option<Rc<dyn ICompositionObject>>) {
157 let mut changed = false;
158 let old_value = self.root.borrow().clone();
159 if old_value.differs(&value) {
160 CompositionTargetHooks::validate_root_change(host, &old_value, &value);
161 CompositionTargetHooks::on_root_changing(host);
162 changed = true;
163 *self.root.borrow_mut() = value.clone();
165 self.changed_fields_of_composition_target.set(self.changed_fields_of_composition_target.get() | CompositionTargetChangedFields::ROOT);
167 host.register_for_serialization();
168 }
169 *self.root.borrow_mut() = value;
170 if changed {
171 CompositionTargetHooks::on_root_changed(host);
172 }
173 }
174
175 pub fn is_enabled(&self) -> bool {
177 self.is_enabled.get()
178 }
179
180 pub fn set_is_enabled(&self, host: &dyn CompositionTargetHooks, value: bool) {
182 let mut changed = false;
183 let old_value = self.is_enabled.get();
184 if old_value.differs(&value) {
185 CompositionTargetHooks::validate_is_enabled_change(host, old_value, value);
186 CompositionTargetHooks::on_is_enabled_changing(host);
187 changed = true;
188 self.is_enabled.set(value);
190 self.changed_fields_of_composition_target.set(self.changed_fields_of_composition_target.get() | CompositionTargetChangedFields::IS_ENABLED);
192 host.register_for_serialization();
193 }
194 self.is_enabled.set(value);
195 if changed {
196 CompositionTargetHooks::on_is_enabled_changed(host);
197 }
198 }
199
200 pub fn debug_overlays(&self) -> RendererDebugOverlays {
202 self.debug_overlays.get()
203 }
204
205 pub fn set_debug_overlays(&self, host: &dyn CompositionTargetHooks, value: RendererDebugOverlays) {
207 let mut changed = false;
208 let old_value = self.debug_overlays.get();
209 if old_value.differs(&value) {
210 CompositionTargetHooks::validate_debug_overlays_change(host, old_value, value);
211 CompositionTargetHooks::on_debug_overlays_changing(host);
212 changed = true;
213 self.debug_overlays.set(value);
215 self.changed_fields_of_composition_target.set(self.changed_fields_of_composition_target.get() | CompositionTargetChangedFields::DEBUG_OVERLAYS);
217 host.register_for_serialization();
218 }
219 self.debug_overlays.set(value);
220 if changed {
221 CompositionTargetHooks::on_debug_overlays_changed(host);
222 }
223 }
224
225 pub fn last_layout_pass_timing(&self) -> LayoutPassTiming {
227 self.last_layout_pass_timing.get()
228 }
229
230 pub fn set_last_layout_pass_timing(&self, host: &dyn CompositionTargetHooks, value: LayoutPassTiming) {
232 let mut changed = false;
233 let old_value = self.last_layout_pass_timing.get();
234 if old_value.differs(&value) {
235 CompositionTargetHooks::validate_last_layout_pass_timing_change(host, old_value, value);
236 CompositionTargetHooks::on_last_layout_pass_timing_changing(host);
237 changed = true;
238 self.last_layout_pass_timing.set(value);
240 self.changed_fields_of_composition_target.set(self.changed_fields_of_composition_target.get() | CompositionTargetChangedFields::LAST_LAYOUT_PASS_TIMING);
242 host.register_for_serialization();
243 }
244 self.last_layout_pass_timing.set(value);
245 if changed {
246 CompositionTargetHooks::on_last_layout_pass_timing_changed(host);
247 }
248 }
249
250 pub fn scaling(&self) -> f64 {
252 self.scaling.get()
253 }
254
255 pub fn set_scaling(&self, host: &dyn CompositionTargetHooks, value: f64) {
257 let mut changed = false;
258 let old_value = self.scaling.get();
259 if old_value.differs(&value) {
260 CompositionTargetHooks::validate_scaling_change(host, old_value, value);
261 CompositionTargetHooks::on_scaling_changing(host);
262 changed = true;
263 self.scaling.set(value);
265 self.changed_fields_of_composition_target.set(self.changed_fields_of_composition_target.get() | CompositionTargetChangedFields::SCALING);
267 host.register_for_serialization();
268 }
269 self.scaling.set(value);
270 if changed {
271 CompositionTargetHooks::on_scaling_changed(host);
272 }
273 }
274
275 pub fn size(&self) -> Size {
277 self.size.get()
278 }
279
280 pub fn set_size(&self, host: &dyn CompositionTargetHooks, value: Size) {
282 let mut changed = false;
283 let old_value = self.size.get();
284 if old_value.differs(&value) {
285 CompositionTargetHooks::validate_size_change(host, old_value, value);
286 CompositionTargetHooks::on_size_changing(host);
287 changed = true;
288 self.size.set(value);
290 self.changed_fields_of_composition_target.set(self.changed_fields_of_composition_target.get() | CompositionTargetChangedFields::SIZE);
292 host.register_for_serialization();
293 }
294 self.size.set(value);
295 if changed {
296 CompositionTargetHooks::on_size_changed(host);
297 }
298 }
299
300 pub fn transparency_level(&self) -> CompositionTransparencyLevel {
302 self.transparency_level.get()
303 }
304
305 pub fn set_transparency_level(&self, host: &dyn CompositionTargetHooks, value: CompositionTransparencyLevel) {
307 let mut changed = false;
308 let old_value = self.transparency_level.get();
309 if old_value.differs(&value) {
310 CompositionTargetHooks::validate_transparency_level_change(host, old_value, value);
311 CompositionTargetHooks::on_transparency_level_changing(host);
312 changed = true;
313 self.transparency_level.set(value);
315 self.changed_fields_of_composition_target.set(self.changed_fields_of_composition_target.get() | CompositionTargetChangedFields::TRANSPARENCY_LEVEL);
317 host.register_for_serialization();
318 }
319 self.transparency_level.set(value);
320 if changed {
321 CompositionTargetHooks::on_transparency_level_changed(host);
322 }
323 }
324
325 pub fn platform_specific_scene_info(&self) -> Option<Arc<dyn Any + Send + Sync>> {
327 self.platform_specific_scene_info.borrow().clone()
328 }
329
330 pub fn set_platform_specific_scene_info(&self, host: &dyn CompositionTargetHooks, value: Option<Arc<dyn Any + Send + Sync>>) {
332 let mut changed = false;
333 let old_value = self.platform_specific_scene_info.borrow().clone();
334 if old_value.differs(&value) {
335 CompositionTargetHooks::validate_platform_specific_scene_info_change(host, &old_value, &value);
336 CompositionTargetHooks::on_platform_specific_scene_info_changing(host);
337 changed = true;
338 *self.platform_specific_scene_info.borrow_mut() = value.clone();
340 self.changed_fields_of_composition_target.set(self.changed_fields_of_composition_target.get() | CompositionTargetChangedFields::PLATFORM_SPECIFIC_SCENE_INFO);
342 host.register_for_serialization();
343 }
344 *self.platform_specific_scene_info.borrow_mut() = value;
345 if changed {
346 CompositionTargetHooks::on_platform_specific_scene_info_changed(host);
347 }
348 }
349
350 pub fn serialize_changes_core(&self, _host: &dyn CompositionTargetHooks, writer: &mut BatchStreamWriter<'_>) {
353 let changed = self.changed_fields_of_composition_target.get();
354 writer.write(changed);
355 if changed.contains(CompositionTargetChangedFields::ROOT) {
356 writer.write_server_object(self.root.borrow().clone().map(|o| o.server()));
357 }
358 if changed.contains(CompositionTargetChangedFields::IS_ENABLED) {
359 writer.write(self.is_enabled.get());
360 }
361 if changed.contains(CompositionTargetChangedFields::DEBUG_OVERLAYS) {
362 writer.write(self.debug_overlays.get());
363 }
364 if changed.contains(CompositionTargetChangedFields::LAST_LAYOUT_PASS_TIMING) {
365 writer.write(self.last_layout_pass_timing.get());
366 }
367 if changed.contains(CompositionTargetChangedFields::SCALING) {
368 writer.write(self.scaling.get());
369 }
370 if changed.contains(CompositionTargetChangedFields::SIZE) {
371 writer.write(self.size.get());
372 }
373 if changed.contains(CompositionTargetChangedFields::TRANSPARENCY_LEVEL) {
374 writer.write(self.transparency_level.get());
375 }
376 if changed.contains(CompositionTargetChangedFields::PLATFORM_SPECIFIC_SCENE_INFO) {
377 writer.write_value(self.platform_specific_scene_info.borrow().clone());
378 }
379 self.changed_fields_of_composition_target.set(CompositionTargetChangedFields::empty());
380 }
381}
382
383pub trait ServerCompositionTargetHooks: IServerAnimatedPropertyHost {
386 fn deserialize_changes_extra(&self, _reader: &mut BatchStreamReader<'_>) {}
387 fn on_fields_deserialized(&self, _changed: CompositionTargetChangedFields) {}
388
389 fn on_root_changed(&self) {}
390 fn on_root_changing(&self) {}
391
392 fn on_is_enabled_changed(&self) {}
393 fn on_is_enabled_changing(&self) {}
394
395 fn on_debug_overlays_changed(&self) {}
396 fn on_debug_overlays_changing(&self) {}
397
398 fn on_last_layout_pass_timing_changed(&self) {}
399 fn on_last_layout_pass_timing_changing(&self) {}
400
401 fn on_scaling_changed(&self) {}
402 fn on_scaling_changing(&self) {}
403
404 fn on_size_changed(&self) {}
405 fn on_size_changing(&self) {}
406
407 fn on_transparency_level_changed(&self) {}
408 fn on_transparency_level_changing(&self) {}
409
410 fn on_platform_specific_scene_info_changed(&self) {}
411 fn on_platform_specific_scene_info_changing(&self) {}
412}
413
414pub struct ServerCompositionTargetProps {
416 root: RefCell<Option<Rc<dyn IServerObject>>>,
417 is_enabled: Cell<bool>,
418 debug_overlays: Cell<RendererDebugOverlays>,
419 last_layout_pass_timing: Cell<LayoutPassTiming>,
420 scaling: Cell<f64>,
421 size: Cell<Size>,
422 transparency_level: Cell<CompositionTransparencyLevel>,
423 platform_specific_scene_info: RefCell<Option<Arc<dyn Any + Send + Sync>>>,
424}
425
426impl Default for ServerCompositionTargetProps {
427 fn default() -> Self {
428 Self::new()
429 }
430}
431
432impl ServerCompositionTargetProps {
433 pub fn new() -> Self {
436 Self {
437 root: RefCell::new(None),
438 is_enabled: Cell::new(Default::default()),
439 debug_overlays: Cell::new(Default::default()),
440 last_layout_pass_timing: Cell::new(Default::default()),
441 scaling: Cell::new(Default::default()),
442 size: Cell::new(Default::default()),
443 transparency_level: Cell::new(Default::default()),
444 platform_specific_scene_info: RefCell::new(None),
445 }
446 }
447
448 pub fn find_props(&self, type_id: TypeId) -> Option<&dyn Any> {
451 if type_id == TypeId::of::<Self>() {
452 return Some(self);
453 }
454 None
455 }
456
457 pub fn id_of_root_property() -> &'static CompositionPropertyOf<Option<Rc<dyn IServerObject>>> {
459 static PROPERTY: OnceLock<CompositionPropertyOf<Option<Rc<dyn IServerObject>>>> = OnceLock::new();
460 PROPERTY.get_or_init(|| {
461 CompositionProperty::register::<ServerCompositionTargetProps, Option<Rc<dyn IServerObject>>>(
462 "Root",
463 "ServerCompositionTarget",
464 |obj| props_of::<ServerCompositionTargetProps>(obj).root.borrow().clone(),
465 |obj, v| *props_of::<ServerCompositionTargetProps>(obj).root.borrow_mut() = v,
466 None,
467 None,
468 )
469 })
470 }
471
472 pub fn root(&self) -> Option<Rc<dyn IServerObject>> {
474 self.root.borrow().clone()
475 }
476
477 pub fn set_root(&self, host: &dyn ServerCompositionTargetHooks, value: Option<Rc<dyn IServerObject>>) {
478 let old_value = self.root.borrow().clone();
479 let mut changed = false;
480 if old_value.differs(&value) {
481 ServerCompositionTargetHooks::on_root_changing(host);
482 changed = true;
483 }
484 host.set_value(
485 Self::id_of_root_property().base(),
486 ServerValueChange {
487 equal: old_value.default_equals(&value),
488 old_resource: old_value.as_server_render_resource(),
489 new_resource: value.as_server_render_resource(),
490 assign: &mut || *self.root.borrow_mut() = value.clone(),
491 },
492 );
493 if changed {
494 ServerCompositionTargetHooks::on_root_changed(host);
495 }
496 }
497
498 pub fn id_of_is_enabled_property() -> &'static CompositionPropertyOf<bool> {
500 static PROPERTY: OnceLock<CompositionPropertyOf<bool>> = OnceLock::new();
501 PROPERTY.get_or_init(|| {
502 CompositionProperty::register::<ServerCompositionTargetProps, bool>(
503 "IsEnabled",
504 "ServerCompositionTarget",
505 |obj| props_of::<ServerCompositionTargetProps>(obj).is_enabled.get(),
506 |obj, v| props_of::<ServerCompositionTargetProps>(obj).is_enabled.set(v),
507 Some(|obj| ExpressionVariant::create(props_of::<ServerCompositionTargetProps>(obj).is_enabled.get())),
508 None,
509 )
510 })
511 }
512
513 pub fn is_enabled(&self) -> bool {
515 self.is_enabled.get()
516 }
517
518 pub fn set_is_enabled(&self, host: &dyn ServerCompositionTargetHooks, value: bool) {
519 let old_value = self.is_enabled.get();
520 let mut changed = false;
521 if old_value.differs(&value) {
522 ServerCompositionTargetHooks::on_is_enabled_changing(host);
523 changed = true;
524 }
525 host.set_value(
526 Self::id_of_is_enabled_property().base(),
527 ServerValueChange {
528 equal: old_value.default_equals(&value),
529 old_resource: None,
530 new_resource: None,
531 assign: &mut || self.is_enabled.set(value),
532 },
533 );
534 if changed {
535 ServerCompositionTargetHooks::on_is_enabled_changed(host);
536 }
537 }
538
539 pub fn id_of_debug_overlays_property() -> &'static CompositionPropertyOf<RendererDebugOverlays> {
541 static PROPERTY: OnceLock<CompositionPropertyOf<RendererDebugOverlays>> = OnceLock::new();
542 PROPERTY.get_or_init(|| {
543 CompositionProperty::register::<ServerCompositionTargetProps, RendererDebugOverlays>(
544 "DebugOverlays",
545 "ServerCompositionTarget",
546 |obj| props_of::<ServerCompositionTargetProps>(obj).debug_overlays.get(),
547 |obj, v| props_of::<ServerCompositionTargetProps>(obj).debug_overlays.set(v),
548 None,
549 None,
550 )
551 })
552 }
553
554 pub fn debug_overlays(&self) -> RendererDebugOverlays {
556 self.debug_overlays.get()
557 }
558
559 pub fn set_debug_overlays(&self, host: &dyn ServerCompositionTargetHooks, value: RendererDebugOverlays) {
560 let old_value = self.debug_overlays.get();
561 let mut changed = false;
562 if old_value.differs(&value) {
563 ServerCompositionTargetHooks::on_debug_overlays_changing(host);
564 changed = true;
565 }
566 host.set_value(
567 Self::id_of_debug_overlays_property().base(),
568 ServerValueChange {
569 equal: old_value.default_equals(&value),
570 old_resource: None,
571 new_resource: None,
572 assign: &mut || self.debug_overlays.set(value),
573 },
574 );
575 if changed {
576 ServerCompositionTargetHooks::on_debug_overlays_changed(host);
577 }
578 }
579
580 pub fn id_of_last_layout_pass_timing_property() -> &'static CompositionPropertyOf<LayoutPassTiming> {
582 static PROPERTY: OnceLock<CompositionPropertyOf<LayoutPassTiming>> = OnceLock::new();
583 PROPERTY.get_or_init(|| {
584 CompositionProperty::register::<ServerCompositionTargetProps, LayoutPassTiming>(
585 "LastLayoutPassTiming",
586 "ServerCompositionTarget",
587 |obj| props_of::<ServerCompositionTargetProps>(obj).last_layout_pass_timing.get(),
588 |obj, v| props_of::<ServerCompositionTargetProps>(obj).last_layout_pass_timing.set(v),
589 None,
590 None,
591 )
592 })
593 }
594
595 pub fn last_layout_pass_timing(&self) -> LayoutPassTiming {
597 self.last_layout_pass_timing.get()
598 }
599
600 pub fn set_last_layout_pass_timing(&self, host: &dyn ServerCompositionTargetHooks, value: LayoutPassTiming) {
601 let old_value = self.last_layout_pass_timing.get();
602 let mut changed = false;
603 if old_value.differs(&value) {
604 ServerCompositionTargetHooks::on_last_layout_pass_timing_changing(host);
605 changed = true;
606 }
607 host.set_value(
608 Self::id_of_last_layout_pass_timing_property().base(),
609 ServerValueChange {
610 equal: old_value.default_equals(&value),
611 old_resource: None,
612 new_resource: None,
613 assign: &mut || self.last_layout_pass_timing.set(value),
614 },
615 );
616 if changed {
617 ServerCompositionTargetHooks::on_last_layout_pass_timing_changed(host);
618 }
619 }
620
621 pub fn id_of_scaling_property() -> &'static CompositionPropertyOf<f64> {
623 static PROPERTY: OnceLock<CompositionPropertyOf<f64>> = OnceLock::new();
624 PROPERTY.get_or_init(|| {
625 CompositionProperty::register::<ServerCompositionTargetProps, f64>(
626 "Scaling",
627 "ServerCompositionTarget",
628 |obj| props_of::<ServerCompositionTargetProps>(obj).scaling.get(),
629 |obj, v| props_of::<ServerCompositionTargetProps>(obj).scaling.set(v),
630 Some(|obj| ExpressionVariant::create(props_of::<ServerCompositionTargetProps>(obj).scaling.get())),
631 None,
632 )
633 })
634 }
635
636 pub fn scaling(&self) -> f64 {
638 self.scaling.get()
639 }
640
641 pub fn set_scaling(&self, host: &dyn ServerCompositionTargetHooks, value: f64) {
642 let old_value = self.scaling.get();
643 let mut changed = false;
644 if old_value.differs(&value) {
645 ServerCompositionTargetHooks::on_scaling_changing(host);
646 changed = true;
647 }
648 host.set_value(
649 Self::id_of_scaling_property().base(),
650 ServerValueChange {
651 equal: old_value.default_equals(&value),
652 old_resource: None,
653 new_resource: None,
654 assign: &mut || self.scaling.set(value),
655 },
656 );
657 if changed {
658 ServerCompositionTargetHooks::on_scaling_changed(host);
659 }
660 }
661
662 pub fn id_of_size_property() -> &'static CompositionPropertyOf<Size> {
664 static PROPERTY: OnceLock<CompositionPropertyOf<Size>> = OnceLock::new();
665 PROPERTY.get_or_init(|| {
666 CompositionProperty::register::<ServerCompositionTargetProps, Size>(
667 "Size",
668 "ServerCompositionTarget",
669 |obj| props_of::<ServerCompositionTargetProps>(obj).size.get(),
670 |obj, v| props_of::<ServerCompositionTargetProps>(obj).size.set(v),
671 None,
672 None,
673 )
674 })
675 }
676
677 pub fn size(&self) -> Size {
679 self.size.get()
680 }
681
682 pub fn set_size(&self, host: &dyn ServerCompositionTargetHooks, value: Size) {
683 let old_value = self.size.get();
684 let mut changed = false;
685 if old_value.differs(&value) {
686 ServerCompositionTargetHooks::on_size_changing(host);
687 changed = true;
688 }
689 host.set_value(
690 Self::id_of_size_property().base(),
691 ServerValueChange {
692 equal: old_value.default_equals(&value),
693 old_resource: None,
694 new_resource: None,
695 assign: &mut || self.size.set(value),
696 },
697 );
698 if changed {
699 ServerCompositionTargetHooks::on_size_changed(host);
700 }
701 }
702
703 pub fn id_of_transparency_level_property() -> &'static CompositionPropertyOf<CompositionTransparencyLevel> {
705 static PROPERTY: OnceLock<CompositionPropertyOf<CompositionTransparencyLevel>> = OnceLock::new();
706 PROPERTY.get_or_init(|| {
707 CompositionProperty::register::<ServerCompositionTargetProps, CompositionTransparencyLevel>(
708 "TransparencyLevel",
709 "ServerCompositionTarget",
710 |obj| props_of::<ServerCompositionTargetProps>(obj).transparency_level.get(),
711 |obj, v| props_of::<ServerCompositionTargetProps>(obj).transparency_level.set(v),
712 None,
713 None,
714 )
715 })
716 }
717
718 pub fn transparency_level(&self) -> CompositionTransparencyLevel {
720 self.transparency_level.get()
721 }
722
723 pub fn set_transparency_level(&self, host: &dyn ServerCompositionTargetHooks, value: CompositionTransparencyLevel) {
724 let old_value = self.transparency_level.get();
725 let mut changed = false;
726 if old_value.differs(&value) {
727 ServerCompositionTargetHooks::on_transparency_level_changing(host);
728 changed = true;
729 }
730 host.set_value(
731 Self::id_of_transparency_level_property().base(),
732 ServerValueChange {
733 equal: old_value.default_equals(&value),
734 old_resource: None,
735 new_resource: None,
736 assign: &mut || self.transparency_level.set(value),
737 },
738 );
739 if changed {
740 ServerCompositionTargetHooks::on_transparency_level_changed(host);
741 }
742 }
743
744 pub fn id_of_platform_specific_scene_info_property() -> &'static CompositionPropertyOf<Option<Arc<dyn Any + Send + Sync>>> {
746 static PROPERTY: OnceLock<CompositionPropertyOf<Option<Arc<dyn Any + Send + Sync>>>> = OnceLock::new();
747 PROPERTY.get_or_init(|| {
748 CompositionProperty::register::<ServerCompositionTargetProps, Option<Arc<dyn Any + Send + Sync>>>(
749 "PlatformSpecificSceneInfo",
750 "ServerCompositionTarget",
751 |obj| props_of::<ServerCompositionTargetProps>(obj).platform_specific_scene_info.borrow().clone(),
752 |obj, v| *props_of::<ServerCompositionTargetProps>(obj).platform_specific_scene_info.borrow_mut() = v,
753 None,
754 None,
755 )
756 })
757 }
758
759 pub fn platform_specific_scene_info(&self) -> Option<Arc<dyn Any + Send + Sync>> {
761 self.platform_specific_scene_info.borrow().clone()
762 }
763
764 pub fn set_platform_specific_scene_info(&self, host: &dyn ServerCompositionTargetHooks, value: Option<Arc<dyn Any + Send + Sync>>) {
765 let old_value = self.platform_specific_scene_info.borrow().clone();
766 let mut changed = false;
767 if old_value.differs(&value) {
768 ServerCompositionTargetHooks::on_platform_specific_scene_info_changing(host);
769 changed = true;
770 }
771 host.set_value(
772 Self::id_of_platform_specific_scene_info_property().base(),
773 ServerValueChange {
774 equal: old_value.default_equals(&value),
775 old_resource: None,
776 new_resource: None,
777 assign: &mut || *self.platform_specific_scene_info.borrow_mut() = value.clone(),
778 },
779 );
780 if changed {
781 ServerCompositionTargetHooks::on_platform_specific_scene_info_changed(host);
782 }
783 }
784
785 pub fn deserialize_changes_core(
788 &self,
789 host: &dyn ServerCompositionTargetHooks,
790 reader: &mut BatchStreamReader<'_>,
791 _committed_at: Duration,
792 ) {
793 let compositor = host.server_compositor();
794 ServerCompositionTargetHooks::deserialize_changes_extra(host, reader);
795 let changed = reader.read::<CompositionTargetChangedFields>();
796 if changed.contains(CompositionTargetChangedFields::ROOT) {
797 let value = read_server_object(reader, compositor.as_ref());
798 self.set_root(host, value);
799 }
800 if changed.contains(CompositionTargetChangedFields::IS_ENABLED) {
801 let value = reader.read::<bool>();
802 self.set_is_enabled(host, value);
803 }
804 if changed.contains(CompositionTargetChangedFields::DEBUG_OVERLAYS) {
805 let value = reader.read::<RendererDebugOverlays>();
806 self.set_debug_overlays(host, value);
807 }
808 if changed.contains(CompositionTargetChangedFields::LAST_LAYOUT_PASS_TIMING) {
809 let value = reader.read::<LayoutPassTiming>();
810 self.set_last_layout_pass_timing(host, value);
811 }
812 if changed.contains(CompositionTargetChangedFields::SCALING) {
813 let value = reader.read::<f64>();
814 self.set_scaling(host, value);
815 }
816 if changed.contains(CompositionTargetChangedFields::SIZE) {
817 let value = reader.read::<Size>();
818 self.set_size(host, value);
819 }
820 if changed.contains(CompositionTargetChangedFields::TRANSPARENCY_LEVEL) {
821 let value = reader.read::<CompositionTransparencyLevel>();
822 self.set_transparency_level(host, value);
823 }
824 if changed.contains(CompositionTargetChangedFields::PLATFORM_SPECIFIC_SCENE_INFO) {
825 let value = reader.read_value::<Arc<dyn Any + Send + Sync>>();
826 self.set_platform_specific_scene_info(host, value);
827 }
828 ServerCompositionTargetHooks::on_fields_deserialized(host, changed);
829 }
830
831 pub fn get_composition_property(name: &str) -> Option<&'static CompositionProperty> {
834 if name == "IsEnabled" {
835 return Some(Self::id_of_is_enabled_property().base());
836 }
837 if name == "Scaling" {
838 return Some(Self::id_of_scaling_property().base());
839 }
840 None
841 }
842}