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}