From 657b4fd59eb8d4f89eef8388e3346e7901ed1fa6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20R=C3=B8yset?= Date: Mon, 24 May 2021 19:06:21 +0200 Subject: [PATCH] Remove support for `stdweb` (#1941) * Remove support for `stdweb` * Expunge `stdweb`; make `web-sys` the default * Mark this change as a breaking change * Re-insert accidental removal of space * Use the correct cargo feature syntax * Re-add some `cfg` attributes * Remove `web-sys` feature from CI --- .github/workflows/ci.yml | 3 +- CHANGELOG.md | 1 + Cargo.toml | 14 +- FEATURES.md | 4 +- README.md | 5 +- examples/web.rs | 22 +- src/lib.rs | 2 - src/platform/web.rs | 36 +-- src/platform_impl/web/mod.rs | 13 +- src/platform_impl/web/stdweb/canvas.rs | 319 ------------------------ src/platform_impl/web/stdweb/event.rs | 239 ------------------ src/platform_impl/web/stdweb/mod.rs | 94 ------- src/platform_impl/web/stdweb/scaling.rs | 13 - src/platform_impl/web/stdweb/timeout.rs | 63 ----- 14 files changed, 13 insertions(+), 815 deletions(-) delete mode 100644 src/platform_impl/web/stdweb/canvas.rs delete mode 100644 src/platform_impl/web/stdweb/event.rs delete mode 100644 src/platform_impl/web/stdweb/mod.rs delete mode 100644 src/platform_impl/web/stdweb/scaling.rs delete mode 100644 src/platform_impl/web/stdweb/timeout.rs diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1c354514..84e32dca 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -45,8 +45,7 @@ jobs: - { target: aarch64-apple-ios, os: macos-latest, } # We're using Windows rather than Ubuntu to run the wasm tests because caching cargo-web # doesn't currently work on Linux. - - { target: wasm32-unknown-unknown, os: windows-latest, features: stdweb, cmd: web } - - { target: wasm32-unknown-unknown, os: windows-latest, features: web-sys, cmd: web } + - { target: wasm32-unknown-unknown, os: windows-latest, cmd: web } env: RUST_BACKTRACE: 1 diff --git a/CHANGELOG.md b/CHANGELOG.md index 49f6d595..48b46118 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,6 @@ # Unreleased +- **Breaking:** On Web, remove the `stdweb` backend. - Added `Window::focus_window`to bring the window to the front and set input focus. # 0.25.0 (2021-05-15) diff --git a/Cargo.toml b/Cargo.toml index bb0da1eb..ce4a2579 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,19 +12,17 @@ documentation = "https://docs.rs/winit" categories = ["gui"] [package.metadata.docs.rs] -features = ["serde", "web-sys"] +features = ["serde"] default-target = "x86_64-unknown-linux-gnu" targets = ["i686-pc-windows-msvc", "x86_64-pc-windows-msvc", "i686-unknown-linux-gnu", "x86_64-unknown-linux-gnu", "x86_64-apple-darwin", "wasm32-unknown-unknown"] [features] default = ["x11", "wayland"] -web-sys = ["web_sys", "wasm-bindgen", "instant/wasm-bindgen"] -stdweb = ["std_web", "instant/stdweb"] x11 = ["x11-dl", "mio", "mio-misc", "percent-encoding", "parking_lot"] wayland = ["wayland-client", "sctk"] [dependencies] -instant = "0.1" +instant = { version = "0.1", features = ["wasm-bindgen"] } lazy_static = "1" libc = "0.2.64" log = "0.4" @@ -97,7 +95,6 @@ parking_lot = { version = "0.11.0", optional = true } [target.'cfg(target_arch = "wasm32")'.dependencies.web_sys] package = "web-sys" version = "0.3.22" -optional = true features = [ 'console', "AddEventListenerOptions", @@ -123,13 +120,6 @@ features = [ [target.'cfg(target_arch = "wasm32")'.dependencies.wasm-bindgen] version = "0.2.45" -optional = true - -[target.'cfg(target_arch = "wasm32")'.dependencies.std_web] -package = "stdweb" -version = "=0.4.20" -optional = true -features = ["experimental_features_which_may_break_on_minor_version_bumps"] [target.'cfg(target_arch = "wasm32")'.dev-dependencies] console_log = "0.2" diff --git a/FEATURES.md b/FEATURES.md index 8bea2043..96052a76 100644 --- a/FEATURES.md +++ b/FEATURES.md @@ -183,11 +183,9 @@ Legend: |Fullscreen |✔️ |✔️ |✔️ |✔️ |**N/A**|✔️ |✔️ | |Fullscreen toggle |✔️ |✔️ |✔️ |✔️ |**N/A**|✔️ |✔️ | |Exclusive fullscreen |✔️ |✔️ |✔️ |**N/A** |❌ |✔️ |**N/A**| -|HiDPI support |✔️ |✔️ |✔️ |✔️ |▢[#721]|✔️ |✔️ \*1| +|HiDPI support |✔️ |✔️ |✔️ |✔️ |▢[#721]|✔️ |✔️ | |Popup windows |❌ |❌ |❌ |❌ |❌ |❌ |**N/A**| -\*1: `WindowEvent::ScaleFactorChanged` is not sent on `stdweb` backend. - ### System information |Feature |Windows|MacOS |Linux x11|Linux Wayland|Android|iOS |WASM | |---------------- | ----- | ---- | ------- | ----------- | ----- | ------- | -------- | diff --git a/README.md b/README.md index 51c2a106..717d52e0 100644 --- a/README.md +++ b/README.md @@ -72,10 +72,7 @@ Winit provides the following features, which can be enabled in your `Cargo.toml` #### WebAssembly -Winit supports compiling to the `wasm32-unknown-unknown` target with either a -`stdweb` or a `web-sys` backend for use on web browsers. However, please note -that **the `stdweb` backend is being deprecated and may be removed in a future -release of Winit**. The `web-sys` backend is also more feature complete. +Winit supports compiling to the `wasm32-unknown-unknown` target with `web-sys`. On the web platform, a Winit window is backed by a `` element. You can either [provide Winit with a `` element][web with_canvas], or [let Winit diff --git a/examples/web.rs b/examples/web.rs index 46b024cc..1936bc2b 100644 --- a/examples/web.rs +++ b/examples/web.rs @@ -12,7 +12,7 @@ pub fn main() { .build(&event_loop) .unwrap(); - #[cfg(feature = "web-sys")] + #[cfg(target_arch = "wasm32")] { use winit::platform::web::WindowExtWebSys; @@ -26,28 +26,12 @@ pub fn main() { .expect("Append canvas to HTML body"); } - #[cfg(feature = "stdweb")] - { - use std_web::web::INode; - use winit::platform::web::WindowExtStdweb; - - let canvas = window.canvas(); - - let document = std_web::web::document(); - let body: std_web::web::Node = document.body().expect("Get HTML body").into(); - - body.append_child(&canvas); - } - event_loop.run(move |event, _, control_flow| { *control_flow = ControlFlow::Wait; - #[cfg(feature = "web-sys")] + #[cfg(target_arch = "wasm32")] log::debug!("{:?}", event); - #[cfg(feature = "stdweb")] - std_web::console!(log, "%s", format!("{:?}", event)); - match event { Event::WindowEvent { event: WindowEvent::CloseRequested, @@ -61,7 +45,7 @@ pub fn main() { }); } -#[cfg(feature = "web-sys")] +#[cfg(target_arch = "wasm32")] mod wasm { use wasm_bindgen::prelude::*; diff --git a/src/lib.rs b/src/lib.rs index 51f4a863..c3101d8d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -146,8 +146,6 @@ extern crate bitflags; #[cfg(any(target_os = "macos", target_os = "ios"))] #[macro_use] extern crate objc; -#[cfg(all(target_arch = "wasm32", feature = "std_web"))] -extern crate std_web as stdweb; pub mod dpi; #[macro_use] diff --git a/src/platform/web.rs b/src/platform/web.rs index c5ceca90..210f87b9 100644 --- a/src/platform/web.rs +++ b/src/platform/web.rs @@ -1,28 +1,14 @@ #![cfg(target_arch = "wasm32")] //! The web target does not automatically insert the canvas element object into the web page, to -//! allow end users to determine how the page should be laid out. Use the `WindowExtStdweb` or -//! `WindowExtWebSys` traits (depending on your web backend) to retrieve the canvas from the -//! Window. Alternatively, use the `WindowBuilderExtStdweb` or `WindowBuilderExtWebSys` to provide -//! your own canvas. +//! allow end users to determine how the page should be laid out. Use the `WindowExtWebSys` trait +//! to retrieve the canvas from the Window. Alternatively, use the `WindowBuilderExtWebSys` trait +//! to provide your own canvas. use crate::window::WindowBuilder; -#[cfg(feature = "stdweb")] -use stdweb::web::html_element::CanvasElement; - -#[cfg(feature = "stdweb")] -pub trait WindowExtStdweb { - fn canvas(&self) -> CanvasElement; - - /// Whether the browser reports the preferred color scheme to be "dark". - fn is_dark_mode(&self) -> bool; -} - -#[cfg(feature = "web-sys")] use web_sys::HtmlCanvasElement; -#[cfg(feature = "web-sys")] pub trait WindowExtWebSys { fn canvas(&self) -> HtmlCanvasElement; @@ -30,26 +16,10 @@ pub trait WindowExtWebSys { fn is_dark_mode(&self) -> bool; } -#[cfg(feature = "stdweb")] -pub trait WindowBuilderExtStdweb { - fn with_canvas(self, canvas: Option) -> Self; -} - -#[cfg(feature = "stdweb")] -impl WindowBuilderExtStdweb for WindowBuilder { - fn with_canvas(mut self, canvas: Option) -> Self { - self.platform_specific.canvas = canvas; - - self - } -} - -#[cfg(feature = "web-sys")] pub trait WindowBuilderExtWebSys { fn with_canvas(self, canvas: Option) -> Self; } -#[cfg(feature = "web-sys")] impl WindowBuilderExtWebSys for WindowBuilder { fn with_canvas(mut self, canvas: Option) -> Self { self.platform_specific.canvas = canvas; diff --git a/src/platform_impl/web/mod.rs b/src/platform_impl/web/mod.rs index 1eb47917..8c7f993f 100644 --- a/src/platform_impl/web/mod.rs +++ b/src/platform_impl/web/mod.rs @@ -1,5 +1,5 @@ // Brief introduction to the internals of the web backend: -// Currently, the web backend supports both wasm-bindgen and stdweb as methods of binding to the +// The web backend used to support both wasm-bindgen and stdweb as methods of binding to the // environment. Because they are both supporting the same underlying APIs, the actual web bindings // are cordoned off into backend abstractions, which present the thinnest unifying layer possible. // @@ -17,26 +17,15 @@ // incoming events (from the registered handlers) and ensuring they are passed to the user in a // compliant way. -// Silence warnings from use of deprecated stdweb backend -#![allow(deprecated)] - mod device; mod error; mod event_loop; mod monitor; mod window; -#[cfg(feature = "web-sys")] #[path = "web_sys/mod.rs"] mod backend; -#[cfg(feature = "stdweb")] -#[path = "stdweb/mod.rs"] -mod backend; - -#[cfg(not(any(feature = "web-sys", feature = "stdweb")))] -compile_error!("Please select a feature to build for web: `web-sys`, `stdweb`"); - pub use self::device::Id as DeviceId; pub use self::error::OsError; pub use self::event_loop::{ diff --git a/src/platform_impl/web/stdweb/canvas.rs b/src/platform_impl/web/stdweb/canvas.rs deleted file mode 100644 index cea976e2..00000000 --- a/src/platform_impl/web/stdweb/canvas.rs +++ /dev/null @@ -1,319 +0,0 @@ -use super::event; -use crate::dpi::{LogicalPosition, PhysicalPosition, PhysicalSize}; -use crate::error::OsError as RootOE; -use crate::event::{ModifiersState, MouseButton, MouseScrollDelta, ScanCode, VirtualKeyCode}; -use crate::platform_impl::{OsError, PlatformSpecificWindowBuilderAttributes}; - -use std::cell::RefCell; -use std::rc::Rc; -use stdweb::js; -use stdweb::traits::IPointerEvent; -use stdweb::unstable::TryInto; -use stdweb::web::event::{ - BlurEvent, ConcreteEvent, FocusEvent, FullscreenChangeEvent, IEvent, IKeyboardEvent, - KeyDownEvent, KeyPressEvent, KeyUpEvent, ModifierKey, MouseWheelEvent, PointerDownEvent, - PointerMoveEvent, PointerOutEvent, PointerOverEvent, PointerUpEvent, -}; -use stdweb::web::html_element::CanvasElement; -use stdweb::web::{document, EventListenerHandle, IElement, IEventTarget, IHtmlElement}; - -#[allow(dead_code)] -pub struct Canvas { - /// Note: resizing the CanvasElement should go through `backend::set_canvas_size` to ensure the DPI factor is maintained. - raw: CanvasElement, - on_focus: Option, - on_blur: Option, - on_keyboard_release: Option, - on_keyboard_press: Option, - on_received_character: Option, - on_cursor_leave: Option, - on_cursor_enter: Option, - on_cursor_move: Option, - on_mouse_press: Option, - on_mouse_release: Option, - on_mouse_wheel: Option, - on_fullscreen_change: Option, - wants_fullscreen: Rc>, -} - -impl Canvas { - pub fn create(attr: PlatformSpecificWindowBuilderAttributes) -> Result { - let canvas = match attr.canvas { - Some(canvas) => canvas, - None => document() - .create_element("canvas") - .map_err(|_| os_error!(OsError("Failed to create canvas element".to_owned())))? - .try_into() - .map_err(|_| os_error!(OsError("Failed to create canvas element".to_owned())))?, - }; - - // A tabindex is needed in order to capture local keyboard events. - // A "0" value means that the element should be focusable in - // sequential keyboard navigation, but its order is defined by the - // document's source order. - // https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/tabindex - canvas - .set_attribute("tabindex", "0") - .map_err(|_| os_error!(OsError("Failed to set a tabindex".to_owned())))?; - - Ok(Canvas { - raw: canvas, - on_blur: None, - on_focus: None, - on_keyboard_release: None, - on_keyboard_press: None, - on_received_character: None, - on_cursor_leave: None, - on_cursor_enter: None, - on_cursor_move: None, - on_mouse_release: None, - on_mouse_press: None, - on_mouse_wheel: None, - on_fullscreen_change: None, - wants_fullscreen: Rc::new(RefCell::new(false)), - }) - } - - pub fn set_attribute(&self, attribute: &str, value: &str) { - self.raw - .set_attribute(attribute, value) - .expect(&format!("Set attribute: {}", attribute)); - } - - pub fn position(&self) -> LogicalPosition { - let bounds = self.raw.get_bounding_client_rect(); - - LogicalPosition { - x: bounds.get_x(), - y: bounds.get_y(), - } - } - - pub fn size(&self) -> PhysicalSize { - PhysicalSize { - width: self.raw.width() as u32, - height: self.raw.height() as u32, - } - } - - pub fn raw(&self) -> &CanvasElement { - &self.raw - } - - pub fn on_blur(&mut self, mut handler: F) - where - F: 'static + FnMut(), - { - self.on_blur = Some(self.add_event(move |_: BlurEvent| { - handler(); - })); - } - - pub fn on_focus(&mut self, mut handler: F) - where - F: 'static + FnMut(), - { - self.on_focus = Some(self.add_event(move |_: FocusEvent| { - handler(); - })); - } - - pub fn on_keyboard_release(&mut self, mut handler: F) - where - F: 'static + FnMut(ScanCode, Option, ModifiersState), - { - self.on_keyboard_release = Some(self.add_user_event(move |event: KeyUpEvent| { - event.prevent_default(); - handler( - event::scan_code(&event), - event::virtual_key_code(&event), - event::keyboard_modifiers(&event), - ); - })); - } - - pub fn on_keyboard_press(&mut self, mut handler: F) - where - F: 'static + FnMut(ScanCode, Option, ModifiersState), - { - self.on_keyboard_press = Some(self.add_user_event(move |event: KeyDownEvent| { - // event.prevent_default() would suppress subsequent on_received_character() calls. That - // supression is correct for key sequences like Tab/Shift-Tab, Ctrl+R, PgUp/Down to - // scroll, etc. We should not do it for key sequences that result in meaningful character - // input though. - let event_key = &event.key(); - let is_key_string = event_key.len() == 1 || !event_key.is_ascii(); - let is_shortcut_modifiers = (event.ctrl_key() || event.alt_key()) - && !event.get_modifier_state(ModifierKey::AltGr); - if !is_key_string || is_shortcut_modifiers { - event.prevent_default(); - } - handler( - event::scan_code(&event), - event::virtual_key_code(&event), - event::keyboard_modifiers(&event), - ); - })); - } - - pub fn on_received_character(&mut self, mut handler: F) - where - F: 'static + FnMut(char), - { - // TODO: Use `beforeinput`. - // - // The `keypress` event is deprecated, but there does not seem to be a - // viable/compatible alternative as of now. `beforeinput` is still widely - // unsupported. - self.on_received_character = Some(self.add_user_event(move |event: KeyPressEvent| { - // Supress further handling to stop keys like the space key from scrolling the page. - event.prevent_default(); - handler(event::codepoint(&event)); - })); - } - - pub fn on_cursor_leave(&mut self, mut handler: F) - where - F: 'static + FnMut(i32), - { - self.on_cursor_leave = Some(self.add_event(move |event: PointerOutEvent| { - handler(event.pointer_id()); - })); - } - - pub fn on_cursor_enter(&mut self, mut handler: F) - where - F: 'static + FnMut(i32), - { - self.on_cursor_enter = Some(self.add_event(move |event: PointerOverEvent| { - handler(event.pointer_id()); - })); - } - - pub fn on_mouse_release(&mut self, mut handler: F) - where - F: 'static + FnMut(i32, MouseButton, ModifiersState), - { - self.on_mouse_release = Some(self.add_user_event(move |event: PointerUpEvent| { - handler( - event.pointer_id(), - event::mouse_button(&event), - event::mouse_modifiers(&event), - ); - })); - } - - pub fn on_mouse_press(&mut self, mut handler: F) - where - F: 'static + FnMut(i32, PhysicalPosition, MouseButton, ModifiersState), - { - let canvas = self.raw.clone(); - self.on_mouse_press = Some(self.add_user_event(move |event: PointerDownEvent| { - handler( - event.pointer_id(), - event::mouse_position(&event).to_physical(super::scale_factor()), - event::mouse_button(&event), - event::mouse_modifiers(&event), - ); - canvas - .set_pointer_capture(event.pointer_id()) - .expect("Failed to set pointer capture"); - })); - } - - pub fn on_cursor_move(&mut self, mut handler: F) - where - F: 'static + FnMut(i32, PhysicalPosition, PhysicalPosition, ModifiersState), - { - // todo - self.on_cursor_move = Some(self.add_event(move |event: PointerMoveEvent| { - handler( - event.pointer_id(), - event::mouse_position(&event).to_physical(super::scale_factor()), - event::mouse_delta(&event).to_physical(super::scale_factor()), - event::mouse_modifiers(&event), - ); - })); - } - - pub fn on_mouse_wheel(&mut self, mut handler: F) - where - F: 'static + FnMut(i32, MouseScrollDelta, ModifiersState), - { - self.on_mouse_wheel = Some(self.add_event(move |event: MouseWheelEvent| { - event.prevent_default(); - if let Some(delta) = event::mouse_scroll_delta(&event) { - handler(0, delta, event::mouse_modifiers(&event)); - } - })); - } - - pub fn on_fullscreen_change(&mut self, mut handler: F) - where - F: 'static + FnMut(), - { - self.on_fullscreen_change = Some(self.add_event(move |_: FullscreenChangeEvent| handler())); - } - - pub fn on_dark_mode(&mut self, handler: F) - where - F: 'static + FnMut(bool), - { - // TODO: upstream to stdweb - js! { - var handler = @{handler}; - - if (window.matchMedia) { - window.matchMedia("(prefers-color-scheme: dark)").addListener(function(e) { - handler(event.matches) - }); - } - } - } - - fn add_event(&self, mut handler: F) -> EventListenerHandle - where - E: ConcreteEvent, - F: 'static + FnMut(E), - { - self.raw.add_event_listener(move |event: E| { - event.stop_propagation(); - event.cancel_bubble(); - - handler(event); - }) - } - - // The difference between add_event and add_user_event is that the latter has a special meaning - // for browser security. A user event is a deliberate action by the user (like a mouse or key - // press) and is the only time things like a fullscreen request may be successfully completed.) - fn add_user_event(&self, mut handler: F) -> EventListenerHandle - where - E: ConcreteEvent, - F: 'static + FnMut(E), - { - let wants_fullscreen = self.wants_fullscreen.clone(); - let canvas = self.raw.clone(); - - self.add_event(move |event: E| { - handler(event); - - if *wants_fullscreen.borrow() { - canvas.request_fullscreen(); - *wants_fullscreen.borrow_mut() = false; - } - }) - } - - pub fn request_fullscreen(&self) { - *self.wants_fullscreen.borrow_mut() = true; - } - - pub fn is_fullscreen(&self) -> bool { - super::is_fullscreen(&self.raw) - } - - pub fn remove_listeners(&mut self) { - // TODO: Stub, unimplemented (see web_sys for reference). - } -} diff --git a/src/platform_impl/web/stdweb/event.rs b/src/platform_impl/web/stdweb/event.rs deleted file mode 100644 index b4edcb72..00000000 --- a/src/platform_impl/web/stdweb/event.rs +++ /dev/null @@ -1,239 +0,0 @@ -use crate::dpi::LogicalPosition; -use crate::event::{ModifiersState, MouseButton, MouseScrollDelta, ScanCode, VirtualKeyCode}; - -use stdweb::web::event::{IKeyboardEvent, IMouseEvent, MouseWheelDeltaMode, MouseWheelEvent}; -use stdweb::{js, unstable::TryInto, JsSerialize}; - -pub fn mouse_button(event: &impl IMouseEvent) -> MouseButton { - match event.button() { - stdweb::web::event::MouseButton::Left => MouseButton::Left, - stdweb::web::event::MouseButton::Right => MouseButton::Right, - stdweb::web::event::MouseButton::Wheel => MouseButton::Middle, - stdweb::web::event::MouseButton::Button4 => MouseButton::Other(0), - stdweb::web::event::MouseButton::Button5 => MouseButton::Other(1), - } -} - -pub fn mouse_modifiers(event: &impl IMouseEvent) -> ModifiersState { - let mut m = ModifiersState::empty(); - m.set(ModifiersState::SHIFT, event.shift_key()); - m.set(ModifiersState::CTRL, event.ctrl_key()); - m.set(ModifiersState::ALT, event.alt_key()); - m.set(ModifiersState::LOGO, event.meta_key()); - m -} - -pub fn mouse_position(event: &impl IMouseEvent) -> LogicalPosition { - LogicalPosition { - x: event.offset_x() as f64, - y: event.offset_y() as f64, - } -} - -pub fn mouse_delta(event: &impl IMouseEvent) -> LogicalPosition { - LogicalPosition { - x: event.movement_x() as f64, - y: event.movement_y() as f64, - } -} - -pub fn mouse_scroll_delta(event: &MouseWheelEvent) -> Option { - let x = event.delta_x(); - let y = -event.delta_y(); - - match event.delta_mode() { - MouseWheelDeltaMode::Line => Some(MouseScrollDelta::LineDelta(x as f32, y as f32)), - MouseWheelDeltaMode::Pixel => { - let delta = LogicalPosition::new(x, y).to_physical(super::scale_factor()); - Some(MouseScrollDelta::PixelDelta(delta)) - } - MouseWheelDeltaMode::Page => None, - } -} - -pub fn scan_code(event: &T) -> ScanCode { - let key_code = js! ( return @{event}.keyCode; ); - - key_code - .try_into() - .expect("The which value should be a number") -} - -pub fn virtual_key_code(event: &impl IKeyboardEvent) -> Option { - Some(match &event.code()[..] { - "Digit1" => VirtualKeyCode::Key1, - "Digit2" => VirtualKeyCode::Key2, - "Digit3" => VirtualKeyCode::Key3, - "Digit4" => VirtualKeyCode::Key4, - "Digit5" => VirtualKeyCode::Key5, - "Digit6" => VirtualKeyCode::Key6, - "Digit7" => VirtualKeyCode::Key7, - "Digit8" => VirtualKeyCode::Key8, - "Digit9" => VirtualKeyCode::Key9, - "Digit0" => VirtualKeyCode::Key0, - "KeyA" => VirtualKeyCode::A, - "KeyB" => VirtualKeyCode::B, - "KeyC" => VirtualKeyCode::C, - "KeyD" => VirtualKeyCode::D, - "KeyE" => VirtualKeyCode::E, - "KeyF" => VirtualKeyCode::F, - "KeyG" => VirtualKeyCode::G, - "KeyH" => VirtualKeyCode::H, - "KeyI" => VirtualKeyCode::I, - "KeyJ" => VirtualKeyCode::J, - "KeyK" => VirtualKeyCode::K, - "KeyL" => VirtualKeyCode::L, - "KeyM" => VirtualKeyCode::M, - "KeyN" => VirtualKeyCode::N, - "KeyO" => VirtualKeyCode::O, - "KeyP" => VirtualKeyCode::P, - "KeyQ" => VirtualKeyCode::Q, - "KeyR" => VirtualKeyCode::R, - "KeyS" => VirtualKeyCode::S, - "KeyT" => VirtualKeyCode::T, - "KeyU" => VirtualKeyCode::U, - "KeyV" => VirtualKeyCode::V, - "KeyW" => VirtualKeyCode::W, - "KeyX" => VirtualKeyCode::X, - "KeyY" => VirtualKeyCode::Y, - "KeyZ" => VirtualKeyCode::Z, - "Escape" => VirtualKeyCode::Escape, - "F1" => VirtualKeyCode::F1, - "F2" => VirtualKeyCode::F2, - "F3" => VirtualKeyCode::F3, - "F4" => VirtualKeyCode::F4, - "F5" => VirtualKeyCode::F5, - "F6" => VirtualKeyCode::F6, - "F7" => VirtualKeyCode::F7, - "F8" => VirtualKeyCode::F8, - "F9" => VirtualKeyCode::F9, - "F10" => VirtualKeyCode::F10, - "F11" => VirtualKeyCode::F11, - "F12" => VirtualKeyCode::F12, - "F13" => VirtualKeyCode::F13, - "F14" => VirtualKeyCode::F14, - "F15" => VirtualKeyCode::F15, - "F16" => VirtualKeyCode::F16, - "F17" => VirtualKeyCode::F17, - "F18" => VirtualKeyCode::F18, - "F19" => VirtualKeyCode::F19, - "F20" => VirtualKeyCode::F20, - "F21" => VirtualKeyCode::F21, - "F22" => VirtualKeyCode::F22, - "F23" => VirtualKeyCode::F23, - "F24" => VirtualKeyCode::F24, - "PrintScreen" => VirtualKeyCode::Snapshot, - "ScrollLock" => VirtualKeyCode::Scroll, - "Pause" => VirtualKeyCode::Pause, - "Insert" => VirtualKeyCode::Insert, - "Home" => VirtualKeyCode::Home, - "Delete" => VirtualKeyCode::Delete, - "End" => VirtualKeyCode::End, - "PageDown" => VirtualKeyCode::PageDown, - "PageUp" => VirtualKeyCode::PageUp, - "ArrowLeft" => VirtualKeyCode::Left, - "ArrowUp" => VirtualKeyCode::Up, - "ArrowRight" => VirtualKeyCode::Right, - "ArrowDown" => VirtualKeyCode::Down, - "Backspace" => VirtualKeyCode::Back, - "Enter" => VirtualKeyCode::Return, - "Space" => VirtualKeyCode::Space, - "Compose" => VirtualKeyCode::Compose, - "Caret" => VirtualKeyCode::Caret, - "NumLock" => VirtualKeyCode::Numlock, - "Numpad0" => VirtualKeyCode::Numpad0, - "Numpad1" => VirtualKeyCode::Numpad1, - "Numpad2" => VirtualKeyCode::Numpad2, - "Numpad3" => VirtualKeyCode::Numpad3, - "Numpad4" => VirtualKeyCode::Numpad4, - "Numpad5" => VirtualKeyCode::Numpad5, - "Numpad6" => VirtualKeyCode::Numpad6, - "Numpad7" => VirtualKeyCode::Numpad7, - "Numpad8" => VirtualKeyCode::Numpad8, - "Numpad9" => VirtualKeyCode::Numpad9, - "AbntC1" => VirtualKeyCode::AbntC1, - "AbntC2" => VirtualKeyCode::AbntC2, - "NumpadAdd" => VirtualKeyCode::NumpadAdd, - "Quote" => VirtualKeyCode::Apostrophe, - "Apps" => VirtualKeyCode::Apps, - "At" => VirtualKeyCode::At, - "Ax" => VirtualKeyCode::Ax, - "Backslash" => VirtualKeyCode::Backslash, - "Calculator" => VirtualKeyCode::Calculator, - "Capital" => VirtualKeyCode::Capital, - "Semicolon" => VirtualKeyCode::Semicolon, - "Comma" => VirtualKeyCode::Comma, - "Convert" => VirtualKeyCode::Convert, - "NumpadDecimal" => VirtualKeyCode::NumpadDecimal, - "NumpadDivide" => VirtualKeyCode::NumpadDivide, - "Equal" => VirtualKeyCode::Equals, - "Backquote" => VirtualKeyCode::Grave, - "Kana" => VirtualKeyCode::Kana, - "Kanji" => VirtualKeyCode::Kanji, - "AltLeft" => VirtualKeyCode::LAlt, - "BracketLeft" => VirtualKeyCode::LBracket, - "ControlLeft" => VirtualKeyCode::LControl, - "ShiftLeft" => VirtualKeyCode::LShift, - "MetaLeft" => VirtualKeyCode::LWin, - "Mail" => VirtualKeyCode::Mail, - "MediaSelect" => VirtualKeyCode::MediaSelect, - "MediaStop" => VirtualKeyCode::MediaStop, - "Minus" => VirtualKeyCode::Minus, - "NumpadMultiply" => VirtualKeyCode::NumpadMultiply, - "Mute" => VirtualKeyCode::Mute, - "LaunchMyComputer" => VirtualKeyCode::MyComputer, - "NavigateForward" => VirtualKeyCode::NavigateForward, - "NavigateBackward" => VirtualKeyCode::NavigateBackward, - "NextTrack" => VirtualKeyCode::NextTrack, - "NoConvert" => VirtualKeyCode::NoConvert, - "NumpadComma" => VirtualKeyCode::NumpadComma, - "NumpadEnter" => VirtualKeyCode::NumpadEnter, - "NumpadEquals" => VirtualKeyCode::NumpadEquals, - "OEM102" => VirtualKeyCode::OEM102, - "Period" => VirtualKeyCode::Period, - "PlayPause" => VirtualKeyCode::PlayPause, - "Power" => VirtualKeyCode::Power, - "PrevTrack" => VirtualKeyCode::PrevTrack, - "AltRight" => VirtualKeyCode::RAlt, - "BracketRight" => VirtualKeyCode::RBracket, - "ControlRight" => VirtualKeyCode::RControl, - "ShiftRight" => VirtualKeyCode::RShift, - "MetaRight" => VirtualKeyCode::RWin, - "Slash" => VirtualKeyCode::Slash, - "Sleep" => VirtualKeyCode::Sleep, - "Stop" => VirtualKeyCode::Stop, - "NumpadSubtract" => VirtualKeyCode::NumpadSubtract, - "Sysrq" => VirtualKeyCode::Sysrq, - "Tab" => VirtualKeyCode::Tab, - "Underline" => VirtualKeyCode::Underline, - "Unlabeled" => VirtualKeyCode::Unlabeled, - "AudioVolumeDown" => VirtualKeyCode::VolumeDown, - "AudioVolumeUp" => VirtualKeyCode::VolumeUp, - "Wake" => VirtualKeyCode::Wake, - "WebBack" => VirtualKeyCode::WebBack, - "WebFavorites" => VirtualKeyCode::WebFavorites, - "WebForward" => VirtualKeyCode::WebForward, - "WebHome" => VirtualKeyCode::WebHome, - "WebRefresh" => VirtualKeyCode::WebRefresh, - "WebSearch" => VirtualKeyCode::WebSearch, - "WebStop" => VirtualKeyCode::WebStop, - "Yen" => VirtualKeyCode::Yen, - _ => return None, - }) -} - -pub fn keyboard_modifiers(event: &impl IKeyboardEvent) -> ModifiersState { - let mut m = ModifiersState::empty(); - m.set(ModifiersState::SHIFT, event.shift_key()); - m.set(ModifiersState::CTRL, event.ctrl_key()); - m.set(ModifiersState::ALT, event.alt_key()); - m.set(ModifiersState::LOGO, event.meta_key()); - m -} - -pub fn codepoint(event: &impl IKeyboardEvent) -> char { - // `event.key()` always returns a non-empty `String`. Therefore, this should - // never panic. - // https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key - event.key().chars().next().unwrap() -} diff --git a/src/platform_impl/web/stdweb/mod.rs b/src/platform_impl/web/stdweb/mod.rs deleted file mode 100644 index e7a61227..00000000 --- a/src/platform_impl/web/stdweb/mod.rs +++ /dev/null @@ -1,94 +0,0 @@ -#![deprecated(since = "0.23.0", note = "Please migrate to web-sys over stdweb")] - -mod canvas; -mod event; -mod scaling; -mod timeout; - -pub use self::canvas::Canvas; -pub use self::scaling::ScaleChangeDetector; -pub use self::timeout::{AnimationFrameRequest, Timeout}; - -use crate::dpi::{LogicalSize, Size}; -use crate::platform::web::WindowExtStdweb; -use crate::window::Window; - -use stdweb::js; -use stdweb::unstable::TryInto; -use stdweb::web::event::BeforeUnloadEvent; -use stdweb::web::window; -use stdweb::web::IEventTarget; -use stdweb::web::{document, html_element::CanvasElement, Element}; - -pub fn throw(msg: &str) { - js! { throw @{msg} } -} - -pub fn exit_fullscreen() { - document().exit_fullscreen(); -} - -pub type UnloadEventHandle = (); - -pub fn on_unload(mut handler: impl FnMut() + 'static) -> UnloadEventHandle { - window().add_event_listener(move |_: BeforeUnloadEvent| handler()); -} - -impl WindowExtStdweb for Window { - fn canvas(&self) -> CanvasElement { - self.window.canvas().raw().clone() - } - - fn is_dark_mode(&self) -> bool { - // TODO: upstream to stdweb - let is_dark_mode = js! { - return (window.matchMedia && window.matchMedia("(prefers-color-scheme: dark)").matches) - }; - - is_dark_mode.try_into().expect("should return a bool") - } -} - -pub fn window_size() -> LogicalSize { - let window = window(); - let width = window.inner_width() as f64; - let height = window.inner_height() as f64; - - LogicalSize { width, height } -} - -pub fn scale_factor() -> f64 { - let window = window(); - window.device_pixel_ratio() -} - -pub fn set_canvas_size(raw: &CanvasElement, size: Size) { - let scale_factor = scale_factor(); - - let physical_size = size.to_physical::(scale_factor); - let logical_size = size.to_logical::(scale_factor); - - raw.set_width(physical_size.width); - raw.set_height(physical_size.height); - - set_canvas_style_property(raw, "width", &format!("{}px", logical_size.width)); - set_canvas_style_property(raw, "height", &format!("{}px", logical_size.height)); -} - -pub fn set_canvas_style_property(raw: &CanvasElement, style_attribute: &str, value: &str) { - js! { - @{raw.as_ref()}.style[@{style_attribute}] = @{value}; - } -} - -pub fn is_fullscreen(canvas: &CanvasElement) -> bool { - match document().fullscreen_element() { - Some(elem) => { - let raw: Element = canvas.clone().into(); - raw == elem - } - None => false, - } -} - -pub type RawCanvasType = CanvasElement; diff --git a/src/platform_impl/web/stdweb/scaling.rs b/src/platform_impl/web/stdweb/scaling.rs deleted file mode 100644 index 28024735..00000000 --- a/src/platform_impl/web/stdweb/scaling.rs +++ /dev/null @@ -1,13 +0,0 @@ -use super::super::ScaleChangeArgs; - -pub struct ScaleChangeDetector(()); - -impl ScaleChangeDetector { - pub(crate) fn new(_handler: F) -> Self - where - F: 'static + FnMut(ScaleChangeArgs), - { - // TODO: Stub, unimplemented (see web_sys for reference). - Self(()) - } -} diff --git a/src/platform_impl/web/stdweb/timeout.rs b/src/platform_impl/web/stdweb/timeout.rs deleted file mode 100644 index 72bfb72b..00000000 --- a/src/platform_impl/web/stdweb/timeout.rs +++ /dev/null @@ -1,63 +0,0 @@ -use std::cell::Cell; -use std::rc::Rc; -use std::time::Duration; -use stdweb::web::{window, IWindowOrWorker, RequestAnimationFrameHandle, TimeoutHandle}; - -#[derive(Debug)] -pub struct Timeout { - handle: Option, -} - -impl Timeout { - pub fn new(f: F, duration: Duration) -> Timeout - where - F: 'static + FnMut(), - { - Timeout { - handle: Some(window().set_clearable_timeout(f, duration.as_millis() as u32)), - } - } -} - -impl Drop for Timeout { - fn drop(&mut self) { - let handle = self.handle.take().unwrap(); - handle.clear(); - } -} - -#[derive(Debug)] -pub struct AnimationFrameRequest { - handle: Option, - // track callback state, because `cancelAnimationFrame` is slow - fired: Rc>, -} - -impl AnimationFrameRequest { - pub fn new(mut f: F) -> AnimationFrameRequest - where - F: 'static + FnMut(), - { - let fired = Rc::new(Cell::new(false)); - let c_fired = fired.clone(); - let handle = window().request_animation_frame(move |_| { - (*c_fired).set(true); - f(); - }); - - AnimationFrameRequest { - handle: Some(handle), - fired, - } - } -} - -impl Drop for AnimationFrameRequest { - fn drop(&mut self) { - if !(*self.fired).get() { - if let Some(handle) = self.handle.take() { - handle.cancel(); - } - } - } -}