mirror of
https://github.com/italicsjenga/winit-sonoma-fix.git
synced 2024-12-23 22:01:31 +11:00
On Web, map bfcache load/unload to suspend/resume
This commit is contained in:
parent
b97df599c5
commit
924f3323b5
|
@ -76,7 +76,7 @@ And please only add new entries to the top of this list, right below the `# Unre
|
||||||
- On Web, use the correct canvas size when calculating the new size during scale factor change,
|
- On Web, use the correct canvas size when calculating the new size during scale factor change,
|
||||||
instead of using the output bitmap size.
|
instead of using the output bitmap size.
|
||||||
- On Web, scale factor and dark mode detection are now more robust.
|
- On Web, scale factor and dark mode detection are now more robust.
|
||||||
- On Web, fix the bfcache by not using the `beforeunload` event.
|
- On Web, fix the bfcache by not using the `beforeunload` event and map bfcache loading/unloading to `Suspended`/`Resumed` events.
|
||||||
- On Web, fix scale factor resize suggestion always overwriting the canvas size.
|
- On Web, fix scale factor resize suggestion always overwriting the canvas size.
|
||||||
- On macOS, fix crash when dropping `Window`.
|
- On macOS, fix crash when dropping `Window`.
|
||||||
- On Web, use `Window.requestIdleCallback()` for `ControlFlow::Poll` when available.
|
- On Web, use `Window.requestIdleCallback()` for `ControlFlow::Poll` when available.
|
||||||
|
|
|
@ -148,6 +148,7 @@ features = [
|
||||||
'KeyboardEvent',
|
'KeyboardEvent',
|
||||||
'MediaQueryList',
|
'MediaQueryList',
|
||||||
'Node',
|
'Node',
|
||||||
|
'PageTransitionEvent',
|
||||||
'PointerEvent',
|
'PointerEvent',
|
||||||
'ResizeObserver',
|
'ResizeObserver',
|
||||||
'ResizeObserverBoxOptions',
|
'ResizeObserverBoxOptions',
|
||||||
|
|
24
src/event.rs
24
src/event.rs
|
@ -125,6 +125,18 @@ pub enum Event<'a, T: 'static> {
|
||||||
/// [`applicationWillResignActive`]: https://developer.apple.com/documentation/uikit/uiapplicationdelegate/1622950-applicationwillresignactive
|
/// [`applicationWillResignActive`]: https://developer.apple.com/documentation/uikit/uiapplicationdelegate/1622950-applicationwillresignactive
|
||||||
/// [iOS application lifecycle]: https://developer.apple.com/documentation/uikit/app_and_environment/managing_your_app_s_life_cycle
|
/// [iOS application lifecycle]: https://developer.apple.com/documentation/uikit/app_and_environment/managing_your_app_s_life_cycle
|
||||||
///
|
///
|
||||||
|
/// ## Web
|
||||||
|
///
|
||||||
|
/// On Web, the `Suspended` event is emitted in response to a [`pagehide`] event
|
||||||
|
/// with the property [`persisted`] being true, which means that the page is being
|
||||||
|
/// put in the [´bfcache`] (back/forward cache) - an in-memory cache that stores a
|
||||||
|
/// complete snapshot of a page (including the JavaScript heap) as the user is
|
||||||
|
/// navigating away.
|
||||||
|
///
|
||||||
|
/// [`pagehide`]: https://developer.mozilla.org/en-US/docs/Web/API/Window/pagehide_event
|
||||||
|
/// [`persisted`]: https://developer.mozilla.org/en-US/docs/Web/API/PageTransitionEvent/persisted
|
||||||
|
/// [`bfcache`]: https://web.dev/bfcache/
|
||||||
|
///
|
||||||
/// [`Resumed`]: Self::Resumed
|
/// [`Resumed`]: Self::Resumed
|
||||||
Suspended,
|
Suspended,
|
||||||
|
|
||||||
|
@ -179,6 +191,18 @@ pub enum Event<'a, T: 'static> {
|
||||||
/// [`applicationDidBecomeActive`]: https://developer.apple.com/documentation/uikit/uiapplicationdelegate/1622956-applicationdidbecomeactive
|
/// [`applicationDidBecomeActive`]: https://developer.apple.com/documentation/uikit/uiapplicationdelegate/1622956-applicationdidbecomeactive
|
||||||
/// [iOS application lifecycle]: https://developer.apple.com/documentation/uikit/app_and_environment/managing_your_app_s_life_cycle
|
/// [iOS application lifecycle]: https://developer.apple.com/documentation/uikit/app_and_environment/managing_your_app_s_life_cycle
|
||||||
///
|
///
|
||||||
|
/// ## Web
|
||||||
|
///
|
||||||
|
/// On Web, the `Resumed` event is emitted in response to a [`pageshow`] event
|
||||||
|
/// with the property [`persisted`] being true, which means that the page is being
|
||||||
|
/// restored from the [´bfcache`] (back/forward cache) - an in-memory cache that
|
||||||
|
/// stores a complete snapshot of a page (including the JavaScript heap) as the
|
||||||
|
/// user is navigating away.
|
||||||
|
///
|
||||||
|
/// [`pageshow`]: https://developer.mozilla.org/en-US/docs/Web/API/Window/pageshow_event
|
||||||
|
/// [`persisted`]: https://developer.mozilla.org/en-US/docs/Web/API/PageTransitionEvent/persisted
|
||||||
|
/// [`bfcache`]: https://web.dev/bfcache/
|
||||||
|
///
|
||||||
/// [`Suspended`]: Self::Suspended
|
/// [`Suspended`]: Self::Suspended
|
||||||
Resumed,
|
Resumed,
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,7 @@ use std::{
|
||||||
rc::{Rc, Weak},
|
rc::{Rc, Weak},
|
||||||
};
|
};
|
||||||
use wasm_bindgen::prelude::Closure;
|
use wasm_bindgen::prelude::Closure;
|
||||||
use web_sys::{KeyboardEvent, PointerEvent, WheelEvent};
|
use web_sys::{KeyboardEvent, PageTransitionEvent, PointerEvent, WheelEvent};
|
||||||
use web_time::{Duration, Instant};
|
use web_time::{Duration, Instant};
|
||||||
|
|
||||||
pub struct Shared<T: 'static>(Rc<Execution<T>>);
|
pub struct Shared<T: 'static>(Rc<Execution<T>>);
|
||||||
|
@ -41,7 +41,7 @@ pub struct Execution<T: 'static> {
|
||||||
all_canvases: RefCell<Vec<(WindowId, Weak<RefCell<backend::Canvas>>)>>,
|
all_canvases: RefCell<Vec<(WindowId, Weak<RefCell<backend::Canvas>>)>>,
|
||||||
redraw_pending: RefCell<HashSet<WindowId>>,
|
redraw_pending: RefCell<HashSet<WindowId>>,
|
||||||
destroy_pending: RefCell<VecDeque<WindowId>>,
|
destroy_pending: RefCell<VecDeque<WindowId>>,
|
||||||
unload_event_handle: RefCell<Option<backend::UnloadEventHandle>>,
|
page_transition_event_handle: RefCell<Option<backend::PageTransitionEventHandle>>,
|
||||||
device_events: Cell<DeviceEvents>,
|
device_events: Cell<DeviceEvents>,
|
||||||
on_mouse_move: OnEventHandle<PointerEvent>,
|
on_mouse_move: OnEventHandle<PointerEvent>,
|
||||||
on_wheel: OnEventHandle<WheelEvent>,
|
on_wheel: OnEventHandle<WheelEvent>,
|
||||||
|
@ -146,7 +146,7 @@ impl<T: 'static> Shared<T> {
|
||||||
all_canvases: RefCell::new(Vec::new()),
|
all_canvases: RefCell::new(Vec::new()),
|
||||||
redraw_pending: RefCell::new(HashSet::new()),
|
redraw_pending: RefCell::new(HashSet::new()),
|
||||||
destroy_pending: RefCell::new(VecDeque::new()),
|
destroy_pending: RefCell::new(VecDeque::new()),
|
||||||
unload_event_handle: RefCell::new(None),
|
page_transition_event_handle: RefCell::new(None),
|
||||||
device_events: Cell::default(),
|
device_events: Cell::default(),
|
||||||
on_mouse_move: RefCell::new(None),
|
on_mouse_move: RefCell::new(None),
|
||||||
on_wheel: RefCell::new(None),
|
on_wheel: RefCell::new(None),
|
||||||
|
@ -183,11 +183,27 @@ impl<T: 'static> Shared<T> {
|
||||||
}
|
}
|
||||||
self.init();
|
self.init();
|
||||||
|
|
||||||
let close_instance = self.clone();
|
*self.0.page_transition_event_handle.borrow_mut() = Some(backend::on_page_transition(
|
||||||
*self.0.unload_event_handle.borrow_mut() =
|
self.window(),
|
||||||
Some(backend::on_unload(self.window(), move || {
|
{
|
||||||
close_instance.handle_unload()
|
let runner = self.clone();
|
||||||
}));
|
move |event: PageTransitionEvent| {
|
||||||
|
if event.persisted() {
|
||||||
|
runner.send_event(Event::Resumed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
let runner = self.clone();
|
||||||
|
move |event: PageTransitionEvent| {
|
||||||
|
if event.persisted() {
|
||||||
|
runner.send_event(Event::Suspended);
|
||||||
|
} else {
|
||||||
|
runner.handle_unload();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
));
|
||||||
|
|
||||||
let runner = self.clone();
|
let runner = self.clone();
|
||||||
let window = self.window().clone();
|
let window = self.window().clone();
|
||||||
|
@ -605,7 +621,7 @@ impl<T: 'static> Shared<T> {
|
||||||
fn handle_loop_destroyed(&self, control: &mut ControlFlow) {
|
fn handle_loop_destroyed(&self, control: &mut ControlFlow) {
|
||||||
self.handle_event(Event::LoopDestroyed, control);
|
self.handle_event(Event::LoopDestroyed, control);
|
||||||
let all_canvases = std::mem::take(&mut *self.0.all_canvases.borrow_mut());
|
let all_canvases = std::mem::take(&mut *self.0.all_canvases.borrow_mut());
|
||||||
*self.0.unload_event_handle.borrow_mut() = None;
|
*self.0.page_transition_event_handle.borrow_mut() = None;
|
||||||
*self.0.on_mouse_move.borrow_mut() = None;
|
*self.0.on_mouse_move.borrow_mut() = None;
|
||||||
*self.0.on_wheel.borrow_mut() = None;
|
*self.0.on_wheel.borrow_mut() = None;
|
||||||
*self.0.on_mouse_press.borrow_mut() = None;
|
*self.0.on_mouse_press.borrow_mut() = None;
|
||||||
|
|
|
@ -16,7 +16,7 @@ use crate::dpi::LogicalSize;
|
||||||
use crate::platform::web::WindowExtWebSys;
|
use crate::platform::web::WindowExtWebSys;
|
||||||
use crate::window::Window;
|
use crate::window::Window;
|
||||||
use wasm_bindgen::closure::Closure;
|
use wasm_bindgen::closure::Closure;
|
||||||
use web_sys::{CssStyleDeclaration, Element, HtmlCanvasElement};
|
use web_sys::{CssStyleDeclaration, Element, HtmlCanvasElement, PageTransitionEvent};
|
||||||
|
|
||||||
pub fn throw(msg: &str) {
|
pub fn throw(msg: &str) {
|
||||||
wasm_bindgen::throw_str(msg);
|
wasm_bindgen::throw_str(msg);
|
||||||
|
@ -28,16 +28,24 @@ pub fn exit_fullscreen(window: &web_sys::Window) {
|
||||||
document.exit_fullscreen();
|
document.exit_fullscreen();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct UnloadEventHandle {
|
pub struct PageTransitionEventHandle {
|
||||||
_listener: event_handle::EventListenerHandle<dyn FnMut()>,
|
_show_listener: event_handle::EventListenerHandle<dyn FnMut(PageTransitionEvent)>,
|
||||||
|
_hide_listener: event_handle::EventListenerHandle<dyn FnMut(PageTransitionEvent)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn on_unload(window: &web_sys::Window, handler: impl FnMut() + 'static) -> UnloadEventHandle {
|
pub fn on_page_transition(
|
||||||
let closure = Closure::new(handler);
|
window: &web_sys::Window,
|
||||||
|
show_handler: impl FnMut(PageTransitionEvent) + 'static,
|
||||||
|
hide_handler: impl FnMut(PageTransitionEvent) + 'static,
|
||||||
|
) -> PageTransitionEventHandle {
|
||||||
|
let show_closure = Closure::new(show_handler);
|
||||||
|
let hide_closure = Closure::new(hide_handler);
|
||||||
|
|
||||||
let listener = event_handle::EventListenerHandle::new(window, "pagehide", closure);
|
let show_listener = event_handle::EventListenerHandle::new(window, "pageshow", show_closure);
|
||||||
UnloadEventHandle {
|
let hide_listener = event_handle::EventListenerHandle::new(window, "pagehide", hide_closure);
|
||||||
_listener: listener,
|
PageTransitionEventHandle {
|
||||||
|
_show_listener: show_listener,
|
||||||
|
_hide_listener: hide_listener,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue