ferroui_browser/rendering/
browser_surface.rs1use crate::interop::canvas_helper::CanvasSurface;
2use ferroui_base::rendering::composition::Compositor;
3use ferroui_base::utilities::HandlerList;
4use ferroui_base::{PixelSize, Size};
5use std::cell::{Cell, RefCell};
6use std::rc::Rc;
7
8pub struct BrowserSurface {
11 compositor: Rc<Compositor>,
12 js_surface: RefCell<Option<CanvasSurface>>,
13 scaling: Cell<f64>,
14 client_size: Cell<Size>,
15 render_size: Cell<PixelSize>,
16 size_changed: HandlerList<dyn Fn()>,
17 scaling_changed: HandlerList<dyn Fn()>,
18}
19
20impl BrowserSurface {
21 pub fn new(js_surface: CanvasSurface, compositor: Rc<Compositor>) -> Self {
23 Self {
24 compositor,
25 js_surface: RefCell::new(Some(js_surface)),
26 scaling: Cell::new(1.0),
27 client_size: Cell::new(Size::new(1.0, 1.0)),
28 render_size: Cell::new(PixelSize::new(1, 1)),
29 size_changed: HandlerList::new(),
30 scaling_changed: HandlerList::new(),
31 }
32 }
33
34 pub fn compositor(&self) -> Rc<Compositor> {
36 self.compositor.clone()
37 }
38
39 pub fn scaling(&self) -> f64 {
41 self.scaling.get()
42 }
43
44 pub fn client_size(&self) -> Size {
46 self.client_size.get()
47 }
48
49 pub fn render_size(&self) -> PixelSize {
51 self.render_size.get()
52 }
53
54 pub fn is_valid(&self) -> bool {
56 let render_size = self.render_size.get();
57 render_size.width > 0 && render_size.height > 0 && self.scaling.get() > 0.0
58 }
59
60 pub fn size_changed(&self, handler: Rc<dyn Fn()>) -> u64 {
62 self.size_changed.add(handler)
63 }
64
65 pub fn scaling_changed(&self, handler: Rc<dyn Fn()>) -> u64 {
67 self.scaling_changed.add(handler)
68 }
69
70 pub fn initial_size(&self) -> Option<(f64, f64, f64)> {
73 let js_surface = self.js_surface.borrow();
74 let js_surface = js_surface.as_ref()?;
75 Some((js_surface.width(), js_surface.height(), js_surface.scaling()))
76 }
77
78 pub fn dispose(&self) {
80 let js_surface = self.js_surface.borrow_mut().take();
81 if let Some(js_surface) = js_surface {
82 CanvasSurface::destroy(&js_surface);
83 }
84 self.render_size.set(PixelSize::default());
85 self.client_size.set(Size::default());
86 }
87
88 pub fn on_size_changed(&self, pixel_width: f64, pixel_height: f64, dpr: f64) {
93 let old_scaling = self.scaling.get();
94 let old_client_size = self.client_size.get();
95 self.render_size.set(PixelSize::new(pixel_width as i32, pixel_height as i32));
96 self.client_size.set(self.render_size.get().to_size(dpr));
97 self.scaling.set(dpr);
98 if old_client_size != self.client_size.get() {
99 for (_, handler) in self.size_changed.snapshot().iter() {
100 handler();
101 }
102 }
103 if (old_scaling - dpr).abs() > 0.0001 {
104 for (_, handler) in self.scaling_changed.snapshot().iter() {
105 handler();
106 }
107 }
108 }
109}