bevy_web_resizer/
lib.rs

1#[cfg(target_arch = "wasm32")]
2mod wasm32 {
3    use bevy::log;
4    use bevy::prelude::*;
5    use bevy::window::WindowId;
6    use bevy::winit::WinitWindows;
7    use crossbeam_channel::Receiver;
8    use wasm_bindgen::JsCast;
9    use winit::dpi::{Size, LogicalSize};
10
11    pub struct Plugin;
12
13    impl bevy::app::Plugin for Plugin {
14        fn build(&self, app: &mut App) {
15            app.add_system(web_resize_system);
16        }
17    }
18
19    fn web_resize_system(
20        winit_windows: NonSend<WinitWindows>,
21        web_resizing: Local<WinitWebResizing>,
22    ) {
23        let winit_window = winit_windows.get_window(WindowId::primary()).unwrap();
24        if let Some(size) = web_resizing.rx.clone().try_iter().last() {
25            winit_window.set_inner_size(size);
26        }
27    }
28
29    impl Default for WinitWebResizing {
30        fn default() -> Self {
31            WinitWebResizing::new()
32        }
33    }
34
35    pub struct WinitWebResizing {
36        pub rx: Receiver<LogicalSize<f32>>,
37    }
38
39    impl WinitWebResizing {
40        pub fn new() -> Self {
41            let (tx, rx) = crossbeam_channel::unbounded();
42
43            let get_full_size = || {
44                let win = web_sys::window().unwrap();
45                // `inner_width` corresponds to the browser's `self.innerWidth` function, which are in
46                // Logical, not Physical, pixels
47                winit::dpi::LogicalSize::new(
48                    win.inner_width().unwrap().as_f64().unwrap() as f32,
49                    win.inner_height().unwrap().as_f64().unwrap() as f32,
50                )
51            };
52
53            tx.send(get_full_size()).unwrap();
54
55            let closure = wasm_bindgen::closure::Closure::wrap(Box::new(move |e: web_sys::Event| {
56                log::debug!("handling resize event: {:?}", e);
57                tx.send(get_full_size()).unwrap();
58            }) as Box<dyn FnMut(_)>);
59            let window = web_sys::window().unwrap();
60            window
61                .add_event_listener_with_callback("resize", closure.as_ref().unchecked_ref())
62                .unwrap();
63            closure.forget();
64
65            return Self { rx };
66        }
67    }
68}
69
70#[cfg(target_arch = "wasm32")]
71pub use wasm32::Plugin;