mirror of
https://github.com/italicsjenga/winit-sonoma-fix.git
synced 2024-12-23 22:01:31 +11:00
Add Fullscreen API compatibility for Safari (#2948)
This commit is contained in:
parent
af26f01b95
commit
50b17a3907
|
@ -14,6 +14,7 @@ And please only add new entries to the top of this list, right below the `# Unre
|
|||
- On Web, implement `WindowEvent::Occluded`.
|
||||
- On Web, fix touch location to be as accurate as mouse position.
|
||||
- On Web, account for CSS `padding`, `border`, and `margin` when getting or setting the canvas position.
|
||||
- On Web, add Fullscreen API compatibility for Safari.
|
||||
|
||||
# 0.29.0-beta.0
|
||||
|
||||
|
|
|
@ -6,4 +6,7 @@ disallowed-methods = [
|
|||
{ path = "web_sys::HtmlCanvasElement::set_height", reason = "Winit shouldn't touch the internal canvas size" },
|
||||
{ path = "web_sys::Window::document", reason = "cache this to reduce calls to JS" },
|
||||
{ path = "web_sys::Window::get_computed_style", reason = "cache this to reduce calls to JS" },
|
||||
{ path = "web_sys::Element::request_fullscreen", reason = "Doesn't account for compatibility with Safari" },
|
||||
{ path = "web_sys::Document::exit_fullscreen", reason = "Doesn't account for compatibility with Safari" },
|
||||
{ path = "web_sys::Document::fullscreen_element", reason = "Doesn't account for compatibility with Safari" },
|
||||
]
|
||||
|
|
|
@ -3,7 +3,7 @@ use super::event_handle::EventListenerHandle;
|
|||
use super::intersection_handle::IntersectionObserverHandle;
|
||||
use super::media_query_handle::MediaQueryListHandle;
|
||||
use super::pointer::PointerHandler;
|
||||
use super::{event, ButtonsState, ResizeScaleHandle};
|
||||
use super::{event, fullscreen, ButtonsState, ResizeScaleHandle};
|
||||
use crate::dpi::{LogicalPosition, PhysicalPosition, PhysicalSize};
|
||||
use crate::error::OsError as RootOE;
|
||||
use crate::event::{Force, MouseButton, MouseScrollDelta};
|
||||
|
@ -18,8 +18,7 @@ use std::sync::Arc;
|
|||
|
||||
use js_sys::Promise;
|
||||
use smol_str::SmolStr;
|
||||
use wasm_bindgen::prelude::wasm_bindgen;
|
||||
use wasm_bindgen::{closure::Closure, JsCast, JsValue};
|
||||
use wasm_bindgen::{closure::Closure, JsCast};
|
||||
use wasm_bindgen_futures::JsFuture;
|
||||
use web_sys::{
|
||||
CssStyleDeclaration, Document, Event, FocusEvent, HtmlCanvasElement, KeyboardEvent, WheelEvent,
|
||||
|
@ -504,27 +503,15 @@ impl Common {
|
|||
handler(event);
|
||||
|
||||
if *wants_fullscreen.borrow() {
|
||||
canvas
|
||||
.request_fullscreen()
|
||||
.expect("Failed to enter fullscreen");
|
||||
fullscreen::request_fullscreen(&canvas).expect("Failed to enter fullscreen");
|
||||
*wants_fullscreen.borrow_mut() = false;
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
pub fn request_fullscreen(&self) {
|
||||
#[wasm_bindgen]
|
||||
extern "C" {
|
||||
type ElementExt;
|
||||
|
||||
#[wasm_bindgen(catch, method, js_name = requestFullscreen)]
|
||||
fn request_fullscreen(this: &ElementExt) -> Result<JsValue, JsValue>;
|
||||
}
|
||||
|
||||
let raw: &ElementExt = self.raw.unchecked_ref();
|
||||
|
||||
// This should return a `Promise`, but Safari v<16.4 is not up-to-date with the spec.
|
||||
match raw.request_fullscreen() {
|
||||
match fullscreen::request_fullscreen(&self.raw) {
|
||||
Ok(value) if !value.is_undefined() => {
|
||||
let promise: Promise = value.unchecked_into();
|
||||
let wants_fullscreen = self.wants_fullscreen.clone();
|
||||
|
|
99
src/platform_impl/web/web_sys/fullscreen.rs
Normal file
99
src/platform_impl/web/web_sys/fullscreen.rs
Normal file
|
@ -0,0 +1,99 @@
|
|||
use once_cell::unsync::OnceCell;
|
||||
use wasm_bindgen::prelude::wasm_bindgen;
|
||||
use wasm_bindgen::{JsCast, JsValue};
|
||||
use web_sys::{Document, Element, HtmlCanvasElement};
|
||||
|
||||
thread_local! {
|
||||
static FULLSCREEN_API_SUPPORT: OnceCell<bool> = OnceCell::new();
|
||||
}
|
||||
|
||||
fn canvas_has_fullscreen_api_support(canvas: &HtmlCanvasElement) -> bool {
|
||||
FULLSCREEN_API_SUPPORT.with(|support| {
|
||||
*support.get_or_init(|| {
|
||||
#[wasm_bindgen]
|
||||
extern "C" {
|
||||
type CanvasFullScreenApiSupport;
|
||||
|
||||
#[wasm_bindgen(method, getter, js_name = requestFullscreen)]
|
||||
fn has_request_fullscreen(this: &CanvasFullScreenApiSupport) -> JsValue;
|
||||
}
|
||||
|
||||
let support: &CanvasFullScreenApiSupport = canvas.unchecked_ref();
|
||||
!support.has_request_fullscreen().is_undefined()
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
fn document_has_fullscreen_api_support(document: &Document) -> bool {
|
||||
FULLSCREEN_API_SUPPORT.with(|support| {
|
||||
*support.get_or_init(|| {
|
||||
#[wasm_bindgen]
|
||||
extern "C" {
|
||||
type DocumentFullScreenApiSupport;
|
||||
|
||||
#[wasm_bindgen(method, getter, js_name = exitFullscreen)]
|
||||
fn has_exit_fullscreen(this: &DocumentFullScreenApiSupport) -> JsValue;
|
||||
}
|
||||
|
||||
let support: &DocumentFullScreenApiSupport = document.unchecked_ref();
|
||||
!support.has_exit_fullscreen().is_undefined()
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
pub fn request_fullscreen(canvas: &HtmlCanvasElement) -> Result<JsValue, JsValue> {
|
||||
#[wasm_bindgen]
|
||||
extern "C" {
|
||||
type RequestFullscreen;
|
||||
|
||||
#[wasm_bindgen(catch, method, js_name = requestFullscreen)]
|
||||
fn request_fullscreen(this: &RequestFullscreen) -> Result<JsValue, JsValue>;
|
||||
|
||||
#[wasm_bindgen(catch, method, js_name = webkitRequestFullscreen)]
|
||||
fn webkit_request_fullscreen(this: &RequestFullscreen) -> Result<JsValue, JsValue>;
|
||||
}
|
||||
|
||||
let element: &RequestFullscreen = canvas.unchecked_ref();
|
||||
|
||||
if canvas_has_fullscreen_api_support(canvas) {
|
||||
element.request_fullscreen()
|
||||
} else {
|
||||
element.webkit_request_fullscreen()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn exit_fullscreen(document: &Document) {
|
||||
#[wasm_bindgen]
|
||||
extern "C" {
|
||||
type ExitFullscreen;
|
||||
|
||||
#[wasm_bindgen(method, js_name = webkitExitFullscreen)]
|
||||
fn webkit_exit_fullscreen(this: &ExitFullscreen);
|
||||
}
|
||||
|
||||
if document_has_fullscreen_api_support(document) {
|
||||
#[allow(clippy::disallowed_methods)]
|
||||
document.exit_fullscreen()
|
||||
} else {
|
||||
let document: &ExitFullscreen = document.unchecked_ref();
|
||||
document.webkit_exit_fullscreen()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn fullscreen_element(document: &Document) -> Option<Element> {
|
||||
#[wasm_bindgen]
|
||||
extern "C" {
|
||||
type FullscreenElement;
|
||||
|
||||
#[wasm_bindgen(method, getter, js_name = webkitFullscreenElement)]
|
||||
fn webkit_fullscreen_element(this: &FullscreenElement) -> Option<Element>;
|
||||
}
|
||||
|
||||
if document_has_fullscreen_api_support(document) {
|
||||
#[allow(clippy::disallowed_methods)]
|
||||
document.fullscreen_element()
|
||||
} else {
|
||||
let document: &FullscreenElement = document.unchecked_ref();
|
||||
document.webkit_fullscreen_element()
|
||||
}
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
mod canvas;
|
||||
pub mod event;
|
||||
mod event_handle;
|
||||
mod fullscreen;
|
||||
mod intersection_handle;
|
||||
mod media_query_handle;
|
||||
mod pointer;
|
||||
|
@ -26,7 +27,7 @@ pub fn throw(msg: &str) {
|
|||
}
|
||||
|
||||
pub fn exit_fullscreen(document: &Document) {
|
||||
document.exit_fullscreen();
|
||||
fullscreen::exit_fullscreen(document);
|
||||
}
|
||||
|
||||
pub struct PageTransitionEventHandle {
|
||||
|
@ -115,7 +116,7 @@ pub fn set_canvas_style_property(raw: &HtmlCanvasElement, property: &str, value:
|
|||
}
|
||||
|
||||
pub fn is_fullscreen(document: &Document, canvas: &HtmlCanvasElement) -> bool {
|
||||
match document.fullscreen_element() {
|
||||
match fullscreen::fullscreen_element(document) {
|
||||
Some(elem) => {
|
||||
let canvas: &Element = canvas;
|
||||
canvas == &elem
|
||||
|
|
Loading…
Reference in a new issue