2020-08-29 00:08:51 +00:00
|
|
|
use bevy_utils::HashMap;
|
2020-08-13 08:47:40 +00:00
|
|
|
use bevy_window::{Window, WindowId, WindowMode};
|
2020-03-30 21:53:32 +00:00
|
|
|
|
2020-10-08 18:43:01 +00:00
|
|
|
#[derive(Debug, Default)]
|
2020-03-30 21:53:32 +00:00
|
|
|
pub struct WinitWindows {
|
|
|
|
pub windows: HashMap<winit::window::WindowId, winit::window::Window>,
|
|
|
|
pub window_id_to_winit: HashMap<WindowId, winit::window::WindowId>,
|
|
|
|
pub winit_to_window_id: HashMap<winit::window::WindowId, WindowId>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl WinitWindows {
|
|
|
|
pub fn create_window(
|
|
|
|
&mut self,
|
|
|
|
event_loop: &winit::event_loop::EventLoopWindowTarget<()>,
|
|
|
|
window: &Window,
|
|
|
|
) {
|
2020-07-26 19:36:01 +00:00
|
|
|
#[cfg(target_os = "windows")]
|
2020-08-13 09:27:51 +00:00
|
|
|
let mut winit_window_builder = {
|
2020-07-26 19:36:01 +00:00
|
|
|
use winit::platform::windows::WindowBuilderExtWindows;
|
2020-08-13 08:47:40 +00:00
|
|
|
winit::window::WindowBuilder::new().with_drag_and_drop(false)
|
2020-07-26 19:36:01 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
#[cfg(not(target_os = "windows"))]
|
2020-08-13 08:47:40 +00:00
|
|
|
let mut winit_window_builder = winit::window::WindowBuilder::new();
|
2020-08-13 06:18:10 +00:00
|
|
|
|
2020-08-13 09:27:51 +00:00
|
|
|
winit_window_builder = match window.mode {
|
|
|
|
WindowMode::BorderlessFullscreen => winit_window_builder.with_fullscreen(Some(
|
|
|
|
winit::window::Fullscreen::Borderless(event_loop.primary_monitor()),
|
|
|
|
)),
|
|
|
|
WindowMode::Fullscreen { use_size } => winit_window_builder.with_fullscreen(Some(
|
|
|
|
winit::window::Fullscreen::Exclusive(match use_size {
|
2020-10-02 19:24:30 +00:00
|
|
|
true => get_fitting_videomode(&event_loop.primary_monitor().unwrap(), &window),
|
|
|
|
false => get_best_videomode(&event_loop.primary_monitor().unwrap()),
|
2020-08-13 09:27:51 +00:00
|
|
|
}),
|
|
|
|
)),
|
2020-08-13 08:47:40 +00:00
|
|
|
_ => winit_window_builder
|
|
|
|
.with_inner_size(winit::dpi::PhysicalSize::new(window.width, window.height))
|
2020-10-05 17:51:36 +00:00
|
|
|
.with_resizable(window.resizable)
|
|
|
|
.with_decorations(window.decorations),
|
2020-08-13 08:47:40 +00:00
|
|
|
};
|
2020-07-26 19:36:01 +00:00
|
|
|
|
2020-09-21 23:12:34 +00:00
|
|
|
#[allow(unused_mut)]
|
|
|
|
let mut winit_window_builder = winit_window_builder.with_title(&window.title);
|
|
|
|
|
|
|
|
#[cfg(target_arch = "wasm32")]
|
|
|
|
{
|
|
|
|
use wasm_bindgen::JsCast;
|
|
|
|
use winit::platform::web::WindowBuilderExtWebSys;
|
|
|
|
|
|
|
|
if let Some(selector) = &window.canvas {
|
|
|
|
let window = web_sys::window().unwrap();
|
|
|
|
let document = window.document().unwrap();
|
|
|
|
let canvas = document
|
|
|
|
.query_selector(&selector)
|
|
|
|
.expect("Cannot query for canvas element");
|
|
|
|
if let Some(canvas) = canvas {
|
|
|
|
let canvas = canvas.dyn_into::<web_sys::HtmlCanvasElement>().ok();
|
|
|
|
winit_window_builder = winit_window_builder.with_canvas(canvas);
|
|
|
|
} else {
|
|
|
|
panic!("Cannot find element: {}", selector);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
let winit_window = winit_window_builder.build(&event_loop).unwrap();
|
2020-08-13 09:27:51 +00:00
|
|
|
|
2020-03-30 21:53:32 +00:00
|
|
|
self.window_id_to_winit.insert(window.id, winit_window.id());
|
|
|
|
self.winit_to_window_id.insert(winit_window.id(), window.id);
|
|
|
|
|
2020-09-19 03:11:26 +00:00
|
|
|
#[cfg(target_arch = "wasm32")]
|
|
|
|
{
|
|
|
|
use winit::platform::web::WindowExtWebSys;
|
|
|
|
|
2020-09-21 23:12:34 +00:00
|
|
|
if window.canvas.is_none() {
|
|
|
|
let canvas = winit_window.canvas();
|
2020-09-19 03:11:26 +00:00
|
|
|
|
2020-09-21 23:12:34 +00:00
|
|
|
let window = web_sys::window().unwrap();
|
|
|
|
let document = window.document().unwrap();
|
|
|
|
let body = document.body().unwrap();
|
2020-09-19 03:11:26 +00:00
|
|
|
|
2020-09-21 23:12:34 +00:00
|
|
|
body.append_child(&canvas)
|
|
|
|
.expect("Append canvas to HTML body");
|
|
|
|
}
|
2020-09-19 03:11:26 +00:00
|
|
|
}
|
|
|
|
|
2020-03-30 21:53:32 +00:00
|
|
|
self.windows.insert(winit_window.id(), winit_window);
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn get_window(&self, id: WindowId) -> Option<&winit::window::Window> {
|
|
|
|
self.window_id_to_winit
|
|
|
|
.get(&id)
|
|
|
|
.and_then(|id| self.windows.get(id))
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn get_window_id(&self, id: winit::window::WindowId) -> Option<WindowId> {
|
|
|
|
self.winit_to_window_id.get(&id).cloned()
|
|
|
|
}
|
|
|
|
}
|
2020-08-13 08:47:40 +00:00
|
|
|
fn get_fitting_videomode(
|
|
|
|
monitor: &winit::monitor::MonitorHandle,
|
|
|
|
window: &Window,
|
|
|
|
) -> winit::monitor::VideoMode {
|
|
|
|
let mut modes = monitor.video_modes().collect::<Vec<_>>();
|
|
|
|
|
|
|
|
fn abs_diff(a: u32, b: u32) -> u32 {
|
|
|
|
if a > b {
|
|
|
|
return a - b;
|
|
|
|
}
|
|
|
|
b - a
|
|
|
|
}
|
|
|
|
|
|
|
|
modes.sort_by(|a, b| {
|
|
|
|
use std::cmp::Ordering::*;
|
|
|
|
match abs_diff(a.size().width, window.width).cmp(&abs_diff(b.size().width, window.width)) {
|
|
|
|
Equal => {
|
|
|
|
match abs_diff(a.size().height, window.height)
|
|
|
|
.cmp(&abs_diff(b.size().height, window.height))
|
|
|
|
{
|
|
|
|
Equal => b.refresh_rate().cmp(&a.refresh_rate()),
|
|
|
|
default => default,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
default => default,
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
modes.first().unwrap().clone()
|
|
|
|
}
|
|
|
|
|
|
|
|
fn get_best_videomode(monitor: &winit::monitor::MonitorHandle) -> winit::monitor::VideoMode {
|
|
|
|
let mut modes = monitor.video_modes().collect::<Vec<_>>();
|
|
|
|
modes.sort_by(|a, b| {
|
|
|
|
use std::cmp::Ordering::*;
|
|
|
|
match b.size().width.cmp(&a.size().width) {
|
|
|
|
Equal => match b.size().height.cmp(&a.size().height) {
|
|
|
|
Equal => b.refresh_rate().cmp(&a.refresh_rate()),
|
|
|
|
default => default,
|
|
|
|
},
|
|
|
|
default => default,
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
modes.first().unwrap().clone()
|
|
|
|
}
|
2020-09-16 20:40:32 +00:00
|
|
|
|
|
|
|
// WARNING: this only works under the assumption that wasm runtime is single threaded
|
|
|
|
#[cfg(target_arch = "wasm32")]
|
|
|
|
unsafe impl Send for WinitWindows {}
|
|
|
|
#[cfg(target_arch = "wasm32")]
|
|
|
|
unsafe impl Sync for WinitWindows {}
|