display.rs

 1use anyhow::Result;
 2use gpui::{Bounds, DisplayId, Pixels, PlatformDisplay, Point, Size, px};
 3
 4#[derive(Debug)]
 5pub struct WebDisplay {
 6    id: DisplayId,
 7    uuid: uuid::Uuid,
 8    browser_window: web_sys::Window,
 9}
10
11// Safety: WASM is single-threaded — there is no concurrent access to `web_sys::Window`.
12unsafe impl Send for WebDisplay {}
13unsafe impl Sync for WebDisplay {}
14
15impl WebDisplay {
16    pub fn new(browser_window: web_sys::Window) -> Self {
17        WebDisplay {
18            id: DisplayId::new(1),
19            uuid: uuid::Uuid::new_v4(),
20            browser_window,
21        }
22    }
23
24    fn screen_size(&self) -> Size<Pixels> {
25        let Some(screen) = self.browser_window.screen().ok() else {
26            return Size {
27                width: px(1920.),
28                height: px(1080.),
29            };
30        };
31
32        let width = screen.width().unwrap_or(1920) as f32;
33        let height = screen.height().unwrap_or(1080) as f32;
34
35        Size {
36            width: px(width),
37            height: px(height),
38        }
39    }
40
41    fn viewport_size(&self) -> Size<Pixels> {
42        let width = self
43            .browser_window
44            .inner_width()
45            .ok()
46            .and_then(|v| v.as_f64())
47            .unwrap_or(1920.0) as f32;
48        let height = self
49            .browser_window
50            .inner_height()
51            .ok()
52            .and_then(|v| v.as_f64())
53            .unwrap_or(1080.0) as f32;
54
55        Size {
56            width: px(width),
57            height: px(height),
58        }
59    }
60}
61
62impl PlatformDisplay for WebDisplay {
63    fn id(&self) -> DisplayId {
64        self.id
65    }
66
67    fn uuid(&self) -> Result<uuid::Uuid> {
68        Ok(self.uuid)
69    }
70
71    fn bounds(&self) -> Bounds<Pixels> {
72        let size = self.screen_size();
73        Bounds {
74            origin: Point::default(),
75            size,
76        }
77    }
78
79    fn visible_bounds(&self) -> Bounds<Pixels> {
80        let size = self.viewport_size();
81        Bounds {
82            origin: Point::default(),
83            size,
84        }
85    }
86
87    fn default_bounds(&self) -> Bounds<Pixels> {
88        let visible = self.visible_bounds();
89        let width = visible.size.width * 0.75;
90        let height = visible.size.height * 0.75;
91        let origin_x = (visible.size.width - width) / 2.0;
92        let origin_y = (visible.size.height - height) / 2.0;
93        Bounds {
94            origin: Point::new(origin_x, origin_y),
95            size: Size { width, height },
96        }
97    }
98}