mirror of
https://github.com/italicsjenga/winit-sonoma-fix.git
synced 2025-01-10 21:21:29 +11:00
On Web, use requestAnimationFrame
for RedrawRequested
This commit is contained in:
parent
7a58fe58ce
commit
57fad2ce15
|
@ -8,6 +8,7 @@ And please only add new entries to the top of this list, right below the `# Unre
|
||||||
|
|
||||||
# Unreleased
|
# Unreleased
|
||||||
|
|
||||||
|
- On Web, use `Window.requestAnimationFrame()` to throttle `RedrawRequested` events.
|
||||||
- On Wayland, use frame callbacks to throttle `RedrawRequested` events so redraws will align with compositor.
|
- On Wayland, use frame callbacks to throttle `RedrawRequested` events so redraws will align with compositor.
|
||||||
- Add `Window::pre_present_notify` to notify winit before presenting to the windowing system.
|
- Add `Window::pre_present_notify` to notify winit before presenting to the windowing system.
|
||||||
- On Windows, added `WindowBuilderExtWindows::with_class_name` to customize the internal class name.
|
- On Windows, added `WindowBuilderExtWindows::with_class_name` to customize the internal class name.
|
||||||
|
|
|
@ -735,7 +735,10 @@ impl<T> EventLoopWindowTarget<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
canvas_clone.borrow_mut().is_intersecting = Some(is_intersecting);
|
canvas_clone.borrow_mut().is_intersecting = Some(is_intersecting);
|
||||||
})
|
});
|
||||||
|
|
||||||
|
let runner = self.runner.clone();
|
||||||
|
canvas.on_animation_frame(move || runner.request_redraw(RootWindowId(id)));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn available_monitors(&self) -> VecDequeIter<MonitorHandle> {
|
pub fn available_monitors(&self) -> VecDequeIter<MonitorHandle> {
|
||||||
|
|
62
src/platform_impl/web/web_sys/animation_frame.rs
Normal file
62
src/platform_impl/web/web_sys/animation_frame.rs
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
use std::cell::Cell;
|
||||||
|
use std::rc::Rc;
|
||||||
|
use wasm_bindgen::closure::Closure;
|
||||||
|
use wasm_bindgen::JsCast;
|
||||||
|
|
||||||
|
pub struct AnimationFrameHandler {
|
||||||
|
window: web_sys::Window,
|
||||||
|
closure: Closure<dyn FnMut()>,
|
||||||
|
handle: Rc<Cell<Option<i32>>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AnimationFrameHandler {
|
||||||
|
pub fn new(window: web_sys::Window) -> Self {
|
||||||
|
let handle = Rc::new(Cell::new(None));
|
||||||
|
let closure = Closure::new({
|
||||||
|
let handle = handle.clone();
|
||||||
|
move || handle.set(None)
|
||||||
|
});
|
||||||
|
|
||||||
|
Self {
|
||||||
|
window,
|
||||||
|
closure,
|
||||||
|
handle,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn on_animation_frame<F>(&mut self, mut f: F)
|
||||||
|
where
|
||||||
|
F: 'static + FnMut(),
|
||||||
|
{
|
||||||
|
let handle = self.handle.clone();
|
||||||
|
self.closure = Closure::new(move || {
|
||||||
|
handle.set(None);
|
||||||
|
f();
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn request(&self) {
|
||||||
|
if let Some(handle) = self.handle.take() {
|
||||||
|
self.window
|
||||||
|
.cancel_animation_frame(handle)
|
||||||
|
.expect("Failed to cancel animation frame");
|
||||||
|
}
|
||||||
|
|
||||||
|
let handle = self
|
||||||
|
.window
|
||||||
|
.request_animation_frame(self.closure.as_ref().unchecked_ref())
|
||||||
|
.expect("Failed to request animation frame");
|
||||||
|
|
||||||
|
self.handle.set(Some(handle));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Drop for AnimationFrameHandler {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
if let Some(handle) = self.handle.take() {
|
||||||
|
self.window
|
||||||
|
.cancel_animation_frame(handle)
|
||||||
|
.expect("Failed to cancel animation frame");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -19,6 +19,7 @@ use crate::platform_impl::{OsError, PlatformSpecificWindowBuilderAttributes};
|
||||||
use crate::window::{WindowAttributes, WindowId as RootWindowId};
|
use crate::window::{WindowAttributes, WindowId as RootWindowId};
|
||||||
|
|
||||||
use super::super::WindowId;
|
use super::super::WindowId;
|
||||||
|
use super::animation_frame::AnimationFrameHandler;
|
||||||
use super::event_handle::EventListenerHandle;
|
use super::event_handle::EventListenerHandle;
|
||||||
use super::intersection_handle::IntersectionObserverHandle;
|
use super::intersection_handle::IntersectionObserverHandle;
|
||||||
use super::media_query_handle::MediaQueryListHandle;
|
use super::media_query_handle::MediaQueryListHandle;
|
||||||
|
@ -42,6 +43,7 @@ pub struct Canvas {
|
||||||
pointer_handler: PointerHandler,
|
pointer_handler: PointerHandler,
|
||||||
on_resize_scale: Option<ResizeScaleHandle>,
|
on_resize_scale: Option<ResizeScaleHandle>,
|
||||||
on_intersect: Option<IntersectionObserverHandle>,
|
on_intersect: Option<IntersectionObserverHandle>,
|
||||||
|
animation_frame_handler: AnimationFrameHandler,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Common {
|
pub struct Common {
|
||||||
|
@ -98,7 +100,7 @@ impl Canvas {
|
||||||
.expect("Invalid pseudo-element");
|
.expect("Invalid pseudo-element");
|
||||||
|
|
||||||
let common = Common {
|
let common = Common {
|
||||||
window,
|
window: window.clone(),
|
||||||
document,
|
document,
|
||||||
raw: canvas,
|
raw: canvas,
|
||||||
style,
|
style,
|
||||||
|
@ -151,6 +153,7 @@ impl Canvas {
|
||||||
pointer_handler: PointerHandler::new(),
|
pointer_handler: PointerHandler::new(),
|
||||||
on_resize_scale: None,
|
on_resize_scale: None,
|
||||||
on_intersect: None,
|
on_intersect: None,
|
||||||
|
animation_frame_handler: AnimationFrameHandler::new(window),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -441,6 +444,13 @@ impl Canvas {
|
||||||
self.on_intersect = Some(IntersectionObserverHandle::new(self.raw(), handler));
|
self.on_intersect = Some(IntersectionObserverHandle::new(self.raw(), handler));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn on_animation_frame<F>(&mut self, f: F)
|
||||||
|
where
|
||||||
|
F: 'static + FnMut(),
|
||||||
|
{
|
||||||
|
self.animation_frame_handler.on_animation_frame(f)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn request_fullscreen(&self) {
|
pub fn request_fullscreen(&self) {
|
||||||
self.common.request_fullscreen()
|
self.common.request_fullscreen()
|
||||||
}
|
}
|
||||||
|
@ -449,6 +459,10 @@ impl Canvas {
|
||||||
self.common.is_fullscreen()
|
self.common.is_fullscreen()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn request_animation_frame(&self) {
|
||||||
|
self.animation_frame_handler.request();
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn handle_scale_change<T: 'static>(
|
pub(crate) fn handle_scale_change<T: 'static>(
|
||||||
&self,
|
&self,
|
||||||
runner: &super::super::event_loop::runner::Shared<T>,
|
runner: &super::super::event_loop::runner::Shared<T>,
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
mod animation_frame;
|
||||||
mod canvas;
|
mod canvas;
|
||||||
pub mod event;
|
pub mod event;
|
||||||
mod event_handle;
|
mod event_handle;
|
||||||
|
|
|
@ -30,7 +30,6 @@ pub struct Inner {
|
||||||
document: Document,
|
document: Document,
|
||||||
canvas: Rc<RefCell<backend::Canvas>>,
|
canvas: Rc<RefCell<backend::Canvas>>,
|
||||||
previous_pointer: RefCell<&'static str>,
|
previous_pointer: RefCell<&'static str>,
|
||||||
register_redraw_request: Box<dyn Fn()>,
|
|
||||||
destroy_fn: Option<Box<dyn FnOnce()>>,
|
destroy_fn: Option<Box<dyn FnOnce()>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,8 +39,6 @@ impl Window {
|
||||||
attr: WindowAttributes,
|
attr: WindowAttributes,
|
||||||
platform_attr: PlatformSpecificWindowBuilderAttributes,
|
platform_attr: PlatformSpecificWindowBuilderAttributes,
|
||||||
) -> Result<Self, RootOE> {
|
) -> Result<Self, RootOE> {
|
||||||
let runner = target.runner.clone();
|
|
||||||
|
|
||||||
let id = target.generate_id();
|
let id = target.generate_id();
|
||||||
|
|
||||||
let prevent_default = platform_attr.prevent_default;
|
let prevent_default = platform_attr.prevent_default;
|
||||||
|
@ -52,8 +49,6 @@ impl Window {
|
||||||
backend::Canvas::create(id, window.clone(), document.clone(), &attr, platform_attr)?;
|
backend::Canvas::create(id, window.clone(), document.clone(), &attr, platform_attr)?;
|
||||||
let canvas = Rc::new(RefCell::new(canvas));
|
let canvas = Rc::new(RefCell::new(canvas));
|
||||||
|
|
||||||
let register_redraw_request = Box::new(move || runner.request_redraw(RootWI(id)));
|
|
||||||
|
|
||||||
target.register(&canvas, id, prevent_default);
|
target.register(&canvas, id, prevent_default);
|
||||||
|
|
||||||
let runner = target.runner.clone();
|
let runner = target.runner.clone();
|
||||||
|
@ -68,7 +63,6 @@ impl Window {
|
||||||
document: document.clone(),
|
document: document.clone(),
|
||||||
canvas,
|
canvas,
|
||||||
previous_pointer: RefCell::new("auto"),
|
previous_pointer: RefCell::new("auto"),
|
||||||
register_redraw_request,
|
|
||||||
destroy_fn: Some(destroy_fn),
|
destroy_fn: Some(destroy_fn),
|
||||||
})
|
})
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
|
@ -110,8 +104,9 @@ impl Window {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn request_redraw(&self) {
|
pub fn request_redraw(&self) {
|
||||||
self.inner
|
self.inner.dispatch(move |inner| {
|
||||||
.dispatch(|inner| (inner.register_redraw_request)());
|
inner.canvas.borrow().request_animation_frame();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn pre_present_notify(&self) {}
|
pub fn pre_present_notify(&self) {}
|
||||||
|
|
|
@ -547,6 +547,7 @@ impl Window {
|
||||||
/// - **iOS:** Can only be called on the main thread.
|
/// - **iOS:** Can only be called on the main thread.
|
||||||
/// - **Wayland:** The events are aligned with the frame callbacks when [`Window::pre_present_notify`]
|
/// - **Wayland:** The events are aligned with the frame callbacks when [`Window::pre_present_notify`]
|
||||||
/// is used.
|
/// is used.
|
||||||
|
/// - **Web:** [`Event::RedrawRequested`] will be aligned with the `requestAnimationFrame`.
|
||||||
///
|
///
|
||||||
/// [`Event::RedrawRequested`]: crate::event::Event::RedrawRequested
|
/// [`Event::RedrawRequested`]: crate::event::Event::RedrawRequested
|
||||||
#[inline]
|
#[inline]
|
||||||
|
|
Loading…
Reference in a new issue