Move Web backend to winit-web
This commit is contained in:
parent
2d4b9938f0
commit
e542a78deb
50 changed files with 259 additions and 273 deletions
3
.github/CODEOWNERS
vendored
3
.github/CODEOWNERS
vendored
|
|
@ -17,8 +17,7 @@
|
|||
/winit-x11 @kchibisov @notgull
|
||||
|
||||
# Web
|
||||
/src/platform/web.rs @daxpedda
|
||||
/src/platform_impl/web @daxpedda
|
||||
/winit-web @daxpedda
|
||||
|
||||
# Windows (Win32)
|
||||
/winit-win32 @notgull
|
||||
|
|
|
|||
14
.github/workflows/ci.yml
vendored
14
.github/workflows/ci.yml
vendored
|
|
@ -199,7 +199,7 @@ jobs:
|
|||
|
||||
- name: Test winit AppKit
|
||||
if: contains(matrix.platform.target, 'macos')
|
||||
run: cargo $CMD test -p winit-appkit --target=${{ matrix.platform.target }}
|
||||
run: cargo $CMD test -p winit-appkit $OPTIONS
|
||||
|
||||
- name: Test winit Orbital
|
||||
if: contains(matrix.platform.target, 'redox')
|
||||
|
|
@ -208,11 +208,15 @@ jobs:
|
|||
- name: Test winit UIKit
|
||||
if: contains(matrix.platform.target, 'ios')
|
||||
# TODO: Run on Simulator
|
||||
run: cargo $CMD test -p winit-uikit --target=${{ matrix.platform.target }} --no-run
|
||||
run: cargo $CMD test -p winit-uikit $OPTIONS --no-run
|
||||
|
||||
- name: Test winit Web
|
||||
if: contains(matrix.platform.target, 'wasm')
|
||||
run: cargo $CMD test -p winit-web $OPTIONS --no-run
|
||||
|
||||
- name: Test winit Win32
|
||||
if: contains(matrix.platform.target, 'windows')
|
||||
run: cargo $CMD test -p winit-win32 --target=${{ matrix.platform.target }}
|
||||
run: cargo $CMD test -p winit-win32 $OPTIONS
|
||||
|
||||
- name: Test winit X11
|
||||
if: contains(matrix.platform.target, 'linux-gnu')
|
||||
|
|
@ -317,7 +321,7 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
defaults:
|
||||
run:
|
||||
working-directory: ./src/platform_impl/web/script
|
||||
working-directory: ./winit-web/src/script
|
||||
|
||||
steps:
|
||||
- uses: taiki-e/checkout-action@v1
|
||||
|
|
@ -332,7 +336,7 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
defaults:
|
||||
run:
|
||||
working-directory: ./src/platform_impl/web/script
|
||||
working-directory: ./winit-web/src/script
|
||||
|
||||
steps:
|
||||
- uses: taiki-e/checkout-action@v1
|
||||
|
|
|
|||
78
Cargo.toml
78
Cargo.toml
|
|
@ -19,6 +19,7 @@ winit-core = { version = "0.0.0", path = "winit-core" }
|
|||
winit-orbital = { version = "0.0.0", path = "winit-orbital" }
|
||||
winit-uikit = { version = "0.0.0", path = "winit-uikit" }
|
||||
winit-wayland = { version = "0.0.0", path = "winit-wayland", default-features = false }
|
||||
winit-web = { version = "0.0.0", path = "winit-web" }
|
||||
winit-win32 = { version = "0.0.0", path = "winit-win32" }
|
||||
winit-x11 = { version = "0.0.0", path = "winit-x11" }
|
||||
|
||||
|
|
@ -108,17 +109,7 @@ categories = ["gui"]
|
|||
description = "Cross-platform window creation library."
|
||||
documentation = "https://docs.rs/winit"
|
||||
edition.workspace = true
|
||||
include = [
|
||||
"/build.rs",
|
||||
"/docs",
|
||||
"/examples",
|
||||
"/FEATURES.md",
|
||||
"/LICENSE",
|
||||
"/src",
|
||||
"!/src/platform_impl/web/script",
|
||||
"/src/platform_impl/web/script/**/*.min.js",
|
||||
"/tests",
|
||||
]
|
||||
include = ["/build.rs", "/docs", "/examples", "/FEATURES.md", "/LICENSE", "/src", "/tests"]
|
||||
keywords = ["windowing"]
|
||||
license.workspace = true
|
||||
name = "winit"
|
||||
|
|
@ -221,74 +212,15 @@ winit-x11 = { workspace = true, optional = true }
|
|||
[target.'cfg(target_os = "redox")'.dependencies]
|
||||
winit-orbital.workspace = true
|
||||
|
||||
# Web
|
||||
[target.'cfg(target_family = "wasm")'.dependencies]
|
||||
js-sys.workspace = true
|
||||
pin-project.workspace = true
|
||||
wasm-bindgen.workspace = true
|
||||
wasm-bindgen-futures.workspace = true
|
||||
web-time.workspace = true
|
||||
web_sys = { workspace = true, features = [
|
||||
"AbortController",
|
||||
"AbortSignal",
|
||||
"Blob",
|
||||
"BlobPropertyBag",
|
||||
"console",
|
||||
"CssStyleDeclaration",
|
||||
"Document",
|
||||
"DomException",
|
||||
"DomRect",
|
||||
"DomRectReadOnly",
|
||||
"Element",
|
||||
"Event",
|
||||
"EventTarget",
|
||||
"FocusEvent",
|
||||
"HtmlCanvasElement",
|
||||
"HtmlElement",
|
||||
"HtmlHtmlElement",
|
||||
"HtmlImageElement",
|
||||
"ImageBitmap",
|
||||
"ImageBitmapOptions",
|
||||
"ImageBitmapRenderingContext",
|
||||
"ImageData",
|
||||
"IntersectionObserver",
|
||||
"IntersectionObserverEntry",
|
||||
"KeyboardEvent",
|
||||
"MediaQueryList",
|
||||
"MessageChannel",
|
||||
"MessagePort",
|
||||
"Navigator",
|
||||
"Node",
|
||||
"OrientationLockType",
|
||||
"OrientationType",
|
||||
"PageTransitionEvent",
|
||||
"Permissions",
|
||||
"PermissionState",
|
||||
"PermissionStatus",
|
||||
"PointerEvent",
|
||||
"PremultiplyAlpha",
|
||||
"ResizeObserver",
|
||||
"ResizeObserverBoxOptions",
|
||||
"ResizeObserverEntry",
|
||||
"ResizeObserverOptions",
|
||||
"ResizeObserverSize",
|
||||
"Screen",
|
||||
"ScreenOrientation",
|
||||
"Url",
|
||||
"VisibilityState",
|
||||
"WheelEvent",
|
||||
"Window",
|
||||
"Worker",
|
||||
] }
|
||||
|
||||
[target.'cfg(all(target_family = "wasm", target_feature = "atomics"))'.dependencies]
|
||||
atomic-waker.workspace = true
|
||||
concurrent-queue.workspace = true
|
||||
winit-web.workspace = true
|
||||
|
||||
[target.'cfg(target_family = "wasm")'.dev-dependencies]
|
||||
console_error_panic_hook.workspace = true
|
||||
tracing-web.workspace = true
|
||||
wasm-bindgen-futures.workspace = true
|
||||
wasm-bindgen-test.workspace = true
|
||||
web-time.workspace = true
|
||||
|
||||
[[example]]
|
||||
doc-scrape-examples = true
|
||||
|
|
|
|||
|
|
@ -383,6 +383,41 @@ impl winit_wayland::EventLoopBuilderExtWayland for EventLoopBuilder {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(web_platform)]
|
||||
impl winit_web::EventLoopExtWeb for EventLoop {
|
||||
fn spawn_app<A: ApplicationHandler + 'static>(self, app: A) {
|
||||
self.event_loop.spawn_app(app);
|
||||
}
|
||||
|
||||
fn set_poll_strategy(&self, strategy: winit_web::PollStrategy) {
|
||||
self.event_loop.set_poll_strategy(strategy);
|
||||
}
|
||||
|
||||
fn poll_strategy(&self) -> winit_web::PollStrategy {
|
||||
self.event_loop.poll_strategy()
|
||||
}
|
||||
|
||||
fn set_wait_until_strategy(&self, strategy: winit_web::WaitUntilStrategy) {
|
||||
self.event_loop.set_wait_until_strategy(strategy);
|
||||
}
|
||||
|
||||
fn wait_until_strategy(&self) -> winit_web::WaitUntilStrategy {
|
||||
self.event_loop.wait_until_strategy()
|
||||
}
|
||||
|
||||
fn has_multiple_screens(&self) -> Result<bool, winit_core::error::NotSupportedError> {
|
||||
self.event_loop.has_multiple_screens()
|
||||
}
|
||||
|
||||
fn request_detailed_monitor_permission(&self) -> winit_web::MonitorPermissionFuture {
|
||||
self.event_loop.request_detailed_monitor_permission()
|
||||
}
|
||||
|
||||
fn has_detailed_monitor_permission(&self) -> winit_web::HasMonitorPermissionFuture {
|
||||
self.event_loop.has_detailed_monitor_permission()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(windows_platform)]
|
||||
impl winit_win32::EventLoopBuilderExtWindows for EventLoopBuilder {
|
||||
#[inline]
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ pub mod startup_notify;
|
|||
#[cfg(wayland_platform)]
|
||||
pub use winit_wayland as wayland;
|
||||
#[cfg(web_platform)]
|
||||
pub mod web;
|
||||
pub use winit_web as web;
|
||||
#[cfg(windows_platform)]
|
||||
pub use winit_win32 as windows;
|
||||
#[cfg(x11_platform)]
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ pub(crate) use winit_orbital as platform;
|
|||
#[cfg(ios_platform)]
|
||||
pub(crate) use winit_uikit as platform;
|
||||
#[cfg(web_platform)]
|
||||
mod web;
|
||||
pub(crate) use winit_web as platform;
|
||||
#[cfg(windows_platform)]
|
||||
pub(crate) use winit_win32 as platform;
|
||||
|
||||
|
|
@ -17,8 +17,6 @@ pub(crate) use winit_win32 as platform;
|
|||
use self::linux as platform;
|
||||
#[allow(unused_imports)]
|
||||
pub use self::platform::*;
|
||||
#[cfg(web_platform)]
|
||||
use self::web as platform;
|
||||
|
||||
#[cfg(all(
|
||||
not(ios_platform),
|
||||
|
|
|
|||
|
|
@ -1,44 +0,0 @@
|
|||
// Brief introduction to the internals of the Web backend:
|
||||
// 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.
|
||||
//
|
||||
// When adding support for new events or interactions with the browser, first consult trusted
|
||||
// documentation (such as MDN) to ensure it is well-standardised and supported across many browsers.
|
||||
// Once you have decided on the relevant Web APIs, add support to both backends.
|
||||
//
|
||||
// The backend is used by the rest of the module to implement Winit's business logic, which forms
|
||||
// the rest of the code. 'device', 'error', 'monitor', and 'window' define Web-specific structures
|
||||
// for winit's cross-platform structures. They are all relatively simple translations.
|
||||
//
|
||||
// The event_loop module handles listening for and processing events. 'Proxy' implements
|
||||
// EventLoopProxy and 'WindowTarget' implements ActiveEventLoop. WindowTarget also handles
|
||||
// registering the event handlers. The 'Execution' struct in the 'runner' module handles taking
|
||||
// incoming events (from the registered handlers) and ensuring they are passed to the user in a
|
||||
// compliant way.
|
||||
|
||||
// TODO: FP, remove when <https://github.com/rust-lang/rust-clippy/issues/12377> is fixed.
|
||||
#![allow(clippy::empty_docs)]
|
||||
|
||||
mod r#async;
|
||||
mod cursor;
|
||||
mod error;
|
||||
mod event;
|
||||
pub(crate) mod event_loop;
|
||||
mod keyboard;
|
||||
mod lock;
|
||||
pub(crate) mod main_thread;
|
||||
mod monitor;
|
||||
pub(crate) mod web_sys;
|
||||
pub(crate) mod window;
|
||||
|
||||
pub(crate) use cursor::CustomCursorFuture;
|
||||
|
||||
pub(crate) use self::event_loop::{
|
||||
ActiveEventLoop, EventLoop, PlatformSpecificEventLoopAttributes,
|
||||
};
|
||||
pub(crate) use self::monitor::{
|
||||
HasMonitorPermissionFuture, MonitorHandle, MonitorPermissionFuture, OrientationLockFuture,
|
||||
};
|
||||
use self::web_sys as backend;
|
||||
pub use self::window::Window;
|
||||
95
winit-web/Cargo.toml
Normal file
95
winit-web/Cargo.toml
Normal file
|
|
@ -0,0 +1,95 @@
|
|||
[package]
|
||||
description = "Winit's Web (WebAssembly) backend"
|
||||
documentation = "https://docs.rs/winit-web"
|
||||
edition.workspace = true
|
||||
include = [
|
||||
"/src",
|
||||
"!/src/platform_impl/web/script",
|
||||
"/src/platform_impl/web/script/**/*.min.js",
|
||||
"README.md",
|
||||
]
|
||||
license.workspace = true
|
||||
name = "winit-web"
|
||||
repository.workspace = true
|
||||
rust-version.workspace = true
|
||||
version = "0.0.0"
|
||||
|
||||
[features]
|
||||
serde = ["dep:serde", "bitflags/serde", "smol_str/serde", "dpi/serde"]
|
||||
|
||||
[dependencies]
|
||||
bitflags.workspace = true
|
||||
cursor-icon.workspace = true
|
||||
dpi.workspace = true
|
||||
rwh_06.workspace = true
|
||||
serde = { workspace = true, optional = true }
|
||||
smol_str.workspace = true
|
||||
tracing.workspace = true
|
||||
winit-core.workspace = true
|
||||
|
||||
# Platform-specific
|
||||
js-sys.workspace = true
|
||||
pin-project.workspace = true
|
||||
wasm-bindgen.workspace = true
|
||||
wasm-bindgen-futures.workspace = true
|
||||
web-time.workspace = true
|
||||
web_sys = { workspace = true, features = [
|
||||
"AbortController",
|
||||
"AbortSignal",
|
||||
"Blob",
|
||||
"BlobPropertyBag",
|
||||
"console",
|
||||
"CssStyleDeclaration",
|
||||
"Document",
|
||||
"DomException",
|
||||
"DomRect",
|
||||
"DomRectReadOnly",
|
||||
"Element",
|
||||
"Event",
|
||||
"EventTarget",
|
||||
"FocusEvent",
|
||||
"HtmlCanvasElement",
|
||||
"HtmlElement",
|
||||
"HtmlHtmlElement",
|
||||
"HtmlImageElement",
|
||||
"ImageBitmap",
|
||||
"ImageBitmapOptions",
|
||||
"ImageBitmapRenderingContext",
|
||||
"ImageData",
|
||||
"IntersectionObserver",
|
||||
"IntersectionObserverEntry",
|
||||
"KeyboardEvent",
|
||||
"MediaQueryList",
|
||||
"MessageChannel",
|
||||
"MessagePort",
|
||||
"Navigator",
|
||||
"Node",
|
||||
"OrientationLockType",
|
||||
"OrientationType",
|
||||
"PageTransitionEvent",
|
||||
"Permissions",
|
||||
"PermissionState",
|
||||
"PermissionStatus",
|
||||
"PointerEvent",
|
||||
"PremultiplyAlpha",
|
||||
"ResizeObserver",
|
||||
"ResizeObserverBoxOptions",
|
||||
"ResizeObserverEntry",
|
||||
"ResizeObserverOptions",
|
||||
"ResizeObserverSize",
|
||||
"Screen",
|
||||
"ScreenOrientation",
|
||||
"Url",
|
||||
"VisibilityState",
|
||||
"WheelEvent",
|
||||
"Window",
|
||||
"Worker",
|
||||
] }
|
||||
|
||||
[target.'cfg(target_feature = "atomics")'.dependencies]
|
||||
atomic-waker.workspace = true
|
||||
concurrent-queue.workspace = true
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
all-features = true
|
||||
targets = ["wasm32-unknown-unknown"]
|
||||
1
winit-web/README.md
Symbolic link
1
winit-web/README.md
Symbolic link
|
|
@ -0,0 +1 @@
|
|||
../README.md
|
||||
|
|
@ -21,11 +21,11 @@ use web_sys::{
|
|||
};
|
||||
use winit_core::cursor::{Cursor, CursorImage, CustomCursorProvider, CustomCursorSource};
|
||||
|
||||
use super::backend::Style;
|
||||
use super::main_thread::{MainThreadMarker, MainThreadSafe};
|
||||
use super::r#async::{AbortHandle, Abortable, DropAbortHandle, Notified, Notifier};
|
||||
use super::ActiveEventLoop;
|
||||
use crate::platform::web::CustomCursorError;
|
||||
use crate::backend::Style;
|
||||
use crate::event_loop::ActiveEventLoop;
|
||||
use crate::main_thread::{MainThreadMarker, MainThreadSafe};
|
||||
use crate::r#async::{AbortHandle, Abortable, DropAbortHandle, Notified, Notifier};
|
||||
use crate::CustomCursorError;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct CustomCursor {
|
||||
|
|
@ -4,8 +4,9 @@ use winit_core::application::ApplicationHandler;
|
|||
use winit_core::error::{EventLoopError, NotSupportedError};
|
||||
use winit_core::event_loop::ActiveEventLoop as RootActiveEventLoop;
|
||||
|
||||
use super::{backend, HasMonitorPermissionFuture, MonitorPermissionFuture};
|
||||
use crate::platform::web::{PollStrategy, WaitUntilStrategy};
|
||||
use crate::{
|
||||
backend, HasMonitorPermissionFuture, MonitorPermissionFuture, PollStrategy, WaitUntilStrategy,
|
||||
};
|
||||
|
||||
mod proxy;
|
||||
pub(crate) mod runner;
|
||||
|
|
@ -20,12 +21,12 @@ pub struct EventLoop {
|
|||
}
|
||||
|
||||
#[derive(Default, Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
||||
pub(crate) struct PlatformSpecificEventLoopAttributes {}
|
||||
pub struct PlatformSpecificEventLoopAttributes {}
|
||||
|
||||
static EVENT_LOOP_CREATED: AtomicBool = AtomicBool::new(false);
|
||||
|
||||
impl EventLoop {
|
||||
pub(crate) fn new(_: &PlatformSpecificEventLoopAttributes) -> Result<Self, EventLoopError> {
|
||||
pub fn new(_: &PlatformSpecificEventLoopAttributes) -> Result<Self, EventLoopError> {
|
||||
if EVENT_LOOP_CREATED.swap(true, Ordering::Relaxed) {
|
||||
// For better cross-platformness.
|
||||
return Err(EventLoopError::RecreationAttempt);
|
||||
|
|
@ -90,11 +91,13 @@ impl EventLoop {
|
|||
self.elw.has_multiple_screens()
|
||||
}
|
||||
|
||||
pub(crate) fn request_detailed_monitor_permission(&self) -> MonitorPermissionFuture {
|
||||
self.elw.request_detailed_monitor_permission()
|
||||
pub fn request_detailed_monitor_permission(&self) -> MonitorPermissionFuture {
|
||||
MonitorPermissionFuture(self.elw.request_detailed_monitor_permission())
|
||||
}
|
||||
|
||||
pub fn has_detailed_monitor_permission(&self) -> HasMonitorPermissionFuture {
|
||||
self.elw.runner.monitor().has_detailed_monitor_permission_async()
|
||||
HasMonitorPermissionFuture(
|
||||
self.elw.runner.monitor().has_detailed_monitor_permission_async(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -6,8 +6,8 @@ use std::task::Poll;
|
|||
use winit_core::event_loop::EventLoopProxyProvider;
|
||||
|
||||
use super::super::main_thread::MainThreadMarker;
|
||||
use crate::platform_impl::web::event_loop::runner::WeakShared;
|
||||
use crate::platform_impl::web::r#async::{AtomicWaker, Wrapper};
|
||||
use crate::event_loop::runner::WeakShared;
|
||||
use crate::r#async::{AtomicWaker, Wrapper};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct EventLoopProxy(Wrapper<WeakShared, Arc<State>, ()>);
|
||||
|
|
@ -17,17 +17,16 @@ use winit_core::event::{
|
|||
use winit_core::event_loop::{ControlFlow, DeviceEvents};
|
||||
use winit_core::window::WindowId;
|
||||
|
||||
use super::super::event;
|
||||
use super::super::main_thread::MainThreadMarker;
|
||||
use super::super::monitor::MonitorHandler;
|
||||
use super::proxy::EventLoopProxy;
|
||||
use super::state::State;
|
||||
use super::{backend, ActiveEventLoop, EventLoop};
|
||||
use crate::platform::web::{PollStrategy, WaitUntilStrategy};
|
||||
use crate::platform_impl::platform::backend::{EventListenerHandle, SafeAreaHandle};
|
||||
use crate::platform_impl::platform::r#async::DispatchRunner;
|
||||
use crate::platform_impl::platform::window::Inner;
|
||||
use crate::platform_impl::web::web_sys::event::mouse_button_to_id;
|
||||
use crate::backend::{EventListenerHandle, SafeAreaHandle};
|
||||
use crate::event_loop::ActiveEventLoop;
|
||||
use crate::main_thread::MainThreadMarker;
|
||||
use crate::monitor::MonitorHandler;
|
||||
use crate::r#async::DispatchRunner;
|
||||
use crate::web_sys::event::mouse_button_to_id;
|
||||
use crate::window::Inner;
|
||||
use crate::{backend, event, EventLoop, PollStrategy, WaitUntilStrategy};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Shared(Rc<Execution>);
|
||||
|
|
@ -21,10 +21,10 @@ use super::super::lock;
|
|||
use super::super::monitor::MonitorPermissionFuture;
|
||||
use super::runner::Event;
|
||||
use super::{backend, runner};
|
||||
use crate::platform::web::{CustomCursorFuture, PollStrategy, WaitUntilStrategy};
|
||||
use crate::platform_impl::platform::cursor::CustomCursor;
|
||||
use crate::platform_impl::web::event_loop::proxy::EventLoopProxy;
|
||||
use crate::platform_impl::Window;
|
||||
use crate::cursor::CustomCursor;
|
||||
use crate::event_loop::proxy::EventLoopProxy;
|
||||
use crate::window::Window;
|
||||
use crate::{CustomCursorFuture, PollStrategy, WaitUntilStrategy};
|
||||
|
||||
#[derive(Default, Debug)]
|
||||
struct ModifiersShared(Rc<Cell<ModifiersState>>);
|
||||
|
|
@ -16,7 +16,7 @@
|
|||
//! [with_canvas]: WindowAttributesWeb::with_canvas
|
||||
//! [get]: WindowExtWeb::canvas
|
||||
//! [insert]: WindowAttributesWeb::with_append
|
||||
#![cfg_attr(not(web_platform), doc = "[wasm_bindgen]: https://docs.rs/wasm-bindgen")]
|
||||
//! [wasm_bindgen]: https://docs.rs/wasm-bindgen
|
||||
//! [Rust and WebAssembly book]: https://rustwasm.github.io/book
|
||||
//!
|
||||
//! ## CSS properties
|
||||
|
|
@ -41,6 +41,43 @@
|
|||
//! [`WindowEvent::PointerLeft`]: crate::event::WindowEvent::PointerLeft
|
||||
//! [`Window::set_outer_position()`]: crate::window::Window::set_outer_position
|
||||
|
||||
// Brief introduction to the internals of the Web backend:
|
||||
// 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.
|
||||
//
|
||||
// When adding support for new events or interactions with the browser, first consult trusted
|
||||
// documentation (such as MDN) to ensure it is well-standardised and supported across many browsers.
|
||||
// Once you have decided on the relevant Web APIs, add support to both backends.
|
||||
//
|
||||
// The backend is used by the rest of the module to implement Winit's business logic, which forms
|
||||
// the rest of the code. 'device', 'error', 'monitor', and 'window' define Web-specific structures
|
||||
// for winit's cross-platform structures. They are all relatively simple translations.
|
||||
//
|
||||
// The event_loop module handles listening for and processing events. 'Proxy' implements
|
||||
// EventLoopProxy and 'WindowTarget' implements ActiveEventLoop. WindowTarget also handles
|
||||
// registering the event handlers. The 'Execution' struct in the 'runner' module handles taking
|
||||
// incoming events (from the registered handlers) and ensuring they are passed to the user in a
|
||||
// compliant way.
|
||||
|
||||
macro_rules! os_error {
|
||||
($error:expr) => {{
|
||||
winit_core::error::OsError::new(line!(), file!(), $error)
|
||||
}};
|
||||
}
|
||||
|
||||
mod r#async;
|
||||
mod cursor;
|
||||
mod error;
|
||||
mod event;
|
||||
pub(crate) mod event_loop;
|
||||
mod keyboard;
|
||||
mod lock;
|
||||
pub(crate) mod main_thread;
|
||||
mod monitor;
|
||||
pub(crate) mod web_sys;
|
||||
pub(crate) mod window;
|
||||
|
||||
use std::cell::Ref;
|
||||
use std::error::Error;
|
||||
use std::fmt::{self, Display, Formatter};
|
||||
|
|
@ -49,31 +86,27 @@ use std::pin::Pin;
|
|||
use std::sync::Arc;
|
||||
use std::task::{Context, Poll};
|
||||
|
||||
use ::web_sys::HtmlCanvasElement;
|
||||
#[cfg(feature = "serde")]
|
||||
use serde::{Deserialize, Serialize};
|
||||
#[cfg(web_platform)]
|
||||
use web_sys::HtmlCanvasElement;
|
||||
use winit_core::window::PlatformWindowAttributes;
|
||||
use winit_core::application::ApplicationHandler;
|
||||
use winit_core::cursor::{CustomCursor, CustomCursorSource};
|
||||
use winit_core::error::NotSupportedError;
|
||||
use winit_core::event_loop::ActiveEventLoop;
|
||||
use winit_core::monitor::MonitorHandleProvider;
|
||||
use winit_core::window::{PlatformWindowAttributes, Window};
|
||||
|
||||
use crate::application::ApplicationHandler;
|
||||
use crate::cursor::{CustomCursor, CustomCursorSource};
|
||||
use crate::error::NotSupportedError;
|
||||
use crate::event_loop::{ActiveEventLoop, EventLoop};
|
||||
use crate::monitor::MonitorHandleProvider;
|
||||
use crate::platform_impl::main_thread::{MainThreadMarker, MainThreadSafe};
|
||||
use crate::platform_impl::{web_sys as backend, MonitorHandle as WebMonitorHandle};
|
||||
#[cfg(web_platform)]
|
||||
use crate::platform_impl::{
|
||||
CustomCursorFuture as PlatformCustomCursorFuture,
|
||||
pub use self::event_loop::{EventLoop, PlatformSpecificEventLoopAttributes};
|
||||
use self::web_sys as backend;
|
||||
use self::window::Window as WebWindow;
|
||||
use crate::cursor::CustomCursorFuture as PlatformCustomCursorFuture;
|
||||
use crate::event_loop::ActiveEventLoop as WebActiveEventLoop;
|
||||
use crate::main_thread::{MainThreadMarker, MainThreadSafe};
|
||||
use crate::monitor::{
|
||||
HasMonitorPermissionFuture as PlatformHasMonitorPermissionFuture,
|
||||
MonitorPermissionFuture as PlatformMonitorPermissionFuture,
|
||||
MonitorHandle as WebMonitorHandle, MonitorPermissionFuture as PlatformMonitorPermissionFuture,
|
||||
OrientationLockFuture as PlatformOrientationLockFuture,
|
||||
};
|
||||
use crate::window::Window;
|
||||
|
||||
#[cfg(not(web_platform))]
|
||||
#[doc(hidden)]
|
||||
pub struct HtmlCanvasElement;
|
||||
|
||||
pub trait WindowExtWeb {
|
||||
/// Only returns the canvas if called from inside the window context (the
|
||||
|
|
@ -107,25 +140,21 @@ pub trait WindowExtWeb {
|
|||
impl WindowExtWeb for dyn Window + '_ {
|
||||
#[inline]
|
||||
fn canvas(&self) -> Option<Ref<'_, HtmlCanvasElement>> {
|
||||
self.cast_ref::<crate::platform_impl::Window>().expect("non Web window on Web").canvas()
|
||||
self.cast_ref::<WebWindow>().expect("non Web window on Web").canvas()
|
||||
}
|
||||
|
||||
fn prevent_default(&self) -> bool {
|
||||
self.cast_ref::<crate::platform_impl::Window>()
|
||||
.expect("non Web window on Web")
|
||||
.prevent_default()
|
||||
self.cast_ref::<WebWindow>().expect("non Web window on Web").prevent_default()
|
||||
}
|
||||
|
||||
fn set_prevent_default(&self, prevent_default: bool) {
|
||||
self.cast_ref::<crate::platform_impl::Window>()
|
||||
self.cast_ref::<WebWindow>()
|
||||
.expect("non Web window on Web")
|
||||
.set_prevent_default(prevent_default)
|
||||
}
|
||||
|
||||
fn is_cursor_lock_raw(&self) -> bool {
|
||||
self.cast_ref::<crate::platform_impl::Window>()
|
||||
.expect("non Web window on Web")
|
||||
.is_cursor_lock_raw()
|
||||
self.cast_ref::<WebWindow>().expect("non Web window on Web").is_cursor_lock_raw()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -144,7 +173,6 @@ impl WindowAttributesWeb {
|
|||
/// In any case, the canvas won't be automatically inserted into the Web page.
|
||||
///
|
||||
/// [`None`] by default.
|
||||
#[cfg_attr(not(web_platform), doc = "", doc = "[`HtmlCanvasElement`]: #only-available-on-wasm")]
|
||||
pub fn with_canvas(mut self, canvas: Option<HtmlCanvasElement>) -> Self {
|
||||
match canvas {
|
||||
Some(canvas) => {
|
||||
|
|
@ -216,9 +244,9 @@ pub trait EventLoopExtWeb {
|
|||
/// Initializes the winit event loop.
|
||||
///
|
||||
/// Unlike
|
||||
#[cfg_attr(all(web_platform, target_feature = "exception-handling"), doc = "`run_app()`")]
|
||||
#[cfg_attr(target_feature = "exception-handling", doc = "`run_app()`")]
|
||||
#[cfg_attr(
|
||||
not(all(web_platform, target_feature = "exception-handling")),
|
||||
not(target_feature = "exception-handling"),
|
||||
doc = "[`run_app()`]"
|
||||
)]
|
||||
/// [^1], this returns immediately, and doesn't throw an exception in order to
|
||||
|
|
@ -231,7 +259,7 @@ pub trait EventLoopExtWeb {
|
|||
#[rustfmt::skip]
|
||||
///
|
||||
#[cfg_attr(
|
||||
not(all(web_platform, target_feature = "exception-handling")),
|
||||
not(target_feature = "exception-handling"),
|
||||
doc = "[`run_app()`]: EventLoop::run_app()"
|
||||
)]
|
||||
/// [^1]: `run_app()` is _not_ available on Wasm when the target supports `exception-handling`.
|
||||
|
|
@ -294,40 +322,6 @@ pub trait EventLoopExtWeb {
|
|||
fn has_detailed_monitor_permission(&self) -> HasMonitorPermissionFuture;
|
||||
}
|
||||
|
||||
impl EventLoopExtWeb for EventLoop {
|
||||
fn spawn_app<A: ApplicationHandler + 'static>(self, app: A) {
|
||||
self.event_loop.spawn_app(app);
|
||||
}
|
||||
|
||||
fn set_poll_strategy(&self, strategy: PollStrategy) {
|
||||
self.event_loop.set_poll_strategy(strategy);
|
||||
}
|
||||
|
||||
fn poll_strategy(&self) -> PollStrategy {
|
||||
self.event_loop.poll_strategy()
|
||||
}
|
||||
|
||||
fn set_wait_until_strategy(&self, strategy: WaitUntilStrategy) {
|
||||
self.event_loop.set_wait_until_strategy(strategy);
|
||||
}
|
||||
|
||||
fn wait_until_strategy(&self) -> WaitUntilStrategy {
|
||||
self.event_loop.wait_until_strategy()
|
||||
}
|
||||
|
||||
fn has_multiple_screens(&self) -> Result<bool, NotSupportedError> {
|
||||
self.event_loop.has_multiple_screens()
|
||||
}
|
||||
|
||||
fn request_detailed_monitor_permission(&self) -> MonitorPermissionFuture {
|
||||
MonitorPermissionFuture(self.event_loop.request_detailed_monitor_permission())
|
||||
}
|
||||
|
||||
fn has_detailed_monitor_permission(&self) -> HasMonitorPermissionFuture {
|
||||
HasMonitorPermissionFuture(self.event_loop.has_detailed_monitor_permission())
|
||||
}
|
||||
}
|
||||
|
||||
pub trait ActiveEventLoopExtWeb {
|
||||
/// Sets the strategy for [`ControlFlow::Poll`].
|
||||
///
|
||||
|
|
@ -396,73 +390,55 @@ pub trait ActiveEventLoopExtWeb {
|
|||
impl ActiveEventLoopExtWeb for dyn ActiveEventLoop + '_ {
|
||||
#[inline]
|
||||
fn create_custom_cursor_async(&self, source: CustomCursorSource) -> CustomCursorFuture {
|
||||
let event_loop = self
|
||||
.cast_ref::<crate::platform_impl::ActiveEventLoop>()
|
||||
.expect("non Web event loop on Web");
|
||||
let event_loop = self.cast_ref::<WebActiveEventLoop>().expect("non Web event loop on Web");
|
||||
event_loop.create_custom_cursor_async(source)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn set_poll_strategy(&self, strategy: PollStrategy) {
|
||||
let event_loop = self
|
||||
.cast_ref::<crate::platform_impl::ActiveEventLoop>()
|
||||
.expect("non Web event loop on Web");
|
||||
let event_loop = self.cast_ref::<WebActiveEventLoop>().expect("non Web event loop on Web");
|
||||
event_loop.set_poll_strategy(strategy);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn poll_strategy(&self) -> PollStrategy {
|
||||
let event_loop = self
|
||||
.cast_ref::<crate::platform_impl::ActiveEventLoop>()
|
||||
.expect("non Web event loop on Web");
|
||||
let event_loop = self.cast_ref::<WebActiveEventLoop>().expect("non Web event loop on Web");
|
||||
event_loop.poll_strategy()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn set_wait_until_strategy(&self, strategy: WaitUntilStrategy) {
|
||||
let event_loop = self
|
||||
.cast_ref::<crate::platform_impl::ActiveEventLoop>()
|
||||
.expect("non Web event loop on Web");
|
||||
let event_loop = self.cast_ref::<WebActiveEventLoop>().expect("non Web event loop on Web");
|
||||
event_loop.set_wait_until_strategy(strategy);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn wait_until_strategy(&self) -> WaitUntilStrategy {
|
||||
let event_loop = self
|
||||
.cast_ref::<crate::platform_impl::ActiveEventLoop>()
|
||||
.expect("non Web event loop on Web");
|
||||
let event_loop = self.cast_ref::<WebActiveEventLoop>().expect("non Web event loop on Web");
|
||||
event_loop.wait_until_strategy()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn is_cursor_lock_raw(&self) -> bool {
|
||||
let event_loop = self
|
||||
.cast_ref::<crate::platform_impl::ActiveEventLoop>()
|
||||
.expect("non Web event loop on Web");
|
||||
let event_loop = self.cast_ref::<WebActiveEventLoop>().expect("non Web event loop on Web");
|
||||
event_loop.is_cursor_lock_raw()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn has_multiple_screens(&self) -> Result<bool, NotSupportedError> {
|
||||
let event_loop = self
|
||||
.cast_ref::<crate::platform_impl::ActiveEventLoop>()
|
||||
.expect("non Web event loop on Web");
|
||||
let event_loop = self.cast_ref::<WebActiveEventLoop>().expect("non Web event loop on Web");
|
||||
event_loop.has_multiple_screens()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn request_detailed_monitor_permission(&self) -> MonitorPermissionFuture {
|
||||
let event_loop = self
|
||||
.cast_ref::<crate::platform_impl::ActiveEventLoop>()
|
||||
.expect("non Web event loop on Web");
|
||||
let event_loop = self.cast_ref::<WebActiveEventLoop>().expect("non Web event loop on Web");
|
||||
MonitorPermissionFuture(event_loop.request_detailed_monitor_permission())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn has_detailed_monitor_permission(&self) -> bool {
|
||||
let event_loop = self
|
||||
.cast_ref::<crate::platform_impl::ActiveEventLoop>()
|
||||
.expect("non Web event loop on Web");
|
||||
let event_loop = self.cast_ref::<WebActiveEventLoop>().expect("non Web event loop on Web");
|
||||
event_loop.has_detailed_monitor_permission()
|
||||
}
|
||||
}
|
||||
|
|
@ -518,9 +494,6 @@ pub enum WaitUntilStrategy {
|
|||
Worker,
|
||||
}
|
||||
|
||||
#[cfg(not(web_platform))]
|
||||
struct PlatformCustomCursorFuture;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct CustomCursorFuture(pub(crate) PlatformCustomCursorFuture);
|
||||
|
||||
|
|
@ -550,9 +523,6 @@ impl Display for CustomCursorError {
|
|||
|
||||
impl Error for CustomCursorError {}
|
||||
|
||||
#[cfg(not(web_platform))]
|
||||
struct PlatformMonitorPermissionFuture;
|
||||
|
||||
/// Can be dropped without aborting the request for detailed monitor permissions.
|
||||
#[derive(Debug)]
|
||||
pub struct MonitorPermissionFuture(pub(crate) PlatformMonitorPermissionFuture);
|
||||
|
|
@ -595,9 +565,6 @@ impl Display for MonitorPermissionError {
|
|||
|
||||
impl Error for MonitorPermissionError {}
|
||||
|
||||
#[cfg(not(web_platform))]
|
||||
struct PlatformHasMonitorPermissionFuture;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct HasMonitorPermissionFuture(PlatformHasMonitorPermissionFuture);
|
||||
|
||||
|
|
@ -713,9 +680,6 @@ pub enum OrientationLock {
|
|||
},
|
||||
}
|
||||
|
||||
#[cfg(not(web_platform))]
|
||||
struct PlatformOrientationLockFuture;
|
||||
|
||||
/// Can be dropped without aborting the request to lock the screen.
|
||||
#[derive(Debug)]
|
||||
pub struct OrientationLockFuture(PlatformOrientationLockFuture);
|
||||
|
|
@ -28,7 +28,7 @@ use super::event_loop::runner::WeakShared;
|
|||
use super::main_thread::MainThreadMarker;
|
||||
use super::r#async::{Dispatcher, Notified, Notifier};
|
||||
use super::web_sys::{Engine, EventListenerHandle};
|
||||
use crate::platform::web::{
|
||||
use crate::{
|
||||
MonitorPermissionError, Orientation, OrientationData, OrientationLock, OrientationLockError,
|
||||
};
|
||||
|
||||
|
|
@ -29,7 +29,7 @@ use super::intersection_handle::IntersectionObserverHandle;
|
|||
use super::media_query_handle::MediaQueryListHandle;
|
||||
use super::pointer::PointerHandler;
|
||||
use super::{event, fullscreen, ResizeScaleHandle};
|
||||
use crate::platform::web::WindowAttributesWeb;
|
||||
use crate::WindowAttributesWeb;
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub struct Canvas {
|
||||
|
|
@ -9,7 +9,7 @@ use winit_core::event::{FingerId, MouseButton, MouseScrollDelta, PointerKind};
|
|||
use winit_core::keyboard::{Key, KeyLocation, ModifiersState, NamedKey, PhysicalKey};
|
||||
|
||||
use super::Engine;
|
||||
use crate::platform_impl::web::keyboard::FromAttributeValue;
|
||||
use crate::keyboard::FromAttributeValue;
|
||||
|
||||
bitflags::bitflags! {
|
||||
// https://www.w3.org/TR/pointerevents3/#the-buttons-property
|
||||
|
|
@ -8,9 +8,8 @@ use wasm_bindgen::{JsCast, JsValue};
|
|||
use web_sys::{console, Document, Element, HtmlCanvasElement, Window};
|
||||
use winit_core::monitor::Fullscreen;
|
||||
|
||||
use super::super::main_thread::MainThreadMarker;
|
||||
use super::super::monitor::{self, ScreenDetailed};
|
||||
use crate::platform_impl::MonitorHandle;
|
||||
use crate::main_thread::MainThreadMarker;
|
||||
use crate::monitor::{self, MonitorHandle, ScreenDetailed};
|
||||
|
||||
pub(crate) fn request_fullscreen(
|
||||
main_thread: MainThreadMarker,
|
||||
|
|
@ -9,8 +9,8 @@ use winit_core::keyboard::ModifiersState;
|
|||
use super::canvas::Common;
|
||||
use super::event;
|
||||
use super::event_handle::EventListenerHandle;
|
||||
use crate::platform_impl::web::event::mkdid;
|
||||
use crate::platform_impl::web::web_sys::event::mouse_button_to_id;
|
||||
use crate::event::mkdid;
|
||||
use crate::web_sys::event::mouse_button_to_id;
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub(super) struct PointerHandler {
|
||||
|
|
@ -9,7 +9,7 @@ use web_sys::{
|
|||
AbortController, AbortSignal, Blob, BlobPropertyBag, MessageChannel, MessagePort, Url, Worker,
|
||||
};
|
||||
|
||||
use crate::platform::web::{PollStrategy, WaitUntilStrategy};
|
||||
use crate::{PollStrategy, WaitUntilStrategy};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Schedule {
|
||||
|
|
@ -16,10 +16,11 @@ use winit_core::window::{
|
|||
WindowAttributes, WindowButtons, WindowId, WindowLevel,
|
||||
};
|
||||
|
||||
use super::main_thread::MainThreadMarker;
|
||||
use super::monitor::MonitorHandler;
|
||||
use super::r#async::Dispatcher;
|
||||
use super::{backend, lock, ActiveEventLoop};
|
||||
use crate::event_loop::ActiveEventLoop;
|
||||
use crate::main_thread::MainThreadMarker;
|
||||
use crate::monitor::MonitorHandler;
|
||||
use crate::r#async::Dispatcher;
|
||||
use crate::{backend, lock};
|
||||
|
||||
pub struct Window {
|
||||
inner: Dispatcher<Inner>,
|
||||
Loading…
Add table
Add a link
Reference in a new issue