From 6bac3d702fa3cdb60264db93345bb2cb20cf01df Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Thu, 20 Apr 2023 10:14:17 +0200 Subject: [PATCH] Fix the web backend too --- Cargo.lock | 2 ++ crates/eframe/src/web/backend.rs | 4 ++-- crates/eframe/src/web/events.rs | 7 ++++-- crates/egui_demo_app/Cargo.toml | 2 ++ crates/egui_demo_app/src/backend_panel.rs | 28 +++++++++++++++++++++-- 5 files changed, 37 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b0fd14715..f3dc1a9c3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1272,7 +1272,9 @@ dependencies = [ "log", "poll-promise", "serde", + "wasm-bindgen", "wasm-bindgen-futures", + "web-sys", ] [[package]] diff --git a/crates/eframe/src/web/backend.rs b/crates/eframe/src/web/backend.rs index 2f1fc3f78..e07df652b 100644 --- a/crates/eframe/src/web/backend.rs +++ b/crates/eframe/src/web/backend.rs @@ -259,8 +259,8 @@ impl AppRunner { let needs_repaint: std::sync::Arc = Default::default(); { let needs_repaint = needs_repaint.clone(); - egui_ctx.set_request_repaint_callback(move || { - needs_repaint.repaint_asap(); + egui_ctx.set_request_repaint_callback(move |info| { + needs_repaint.repaint_after(info.after.as_secs_f64()); }); } diff --git a/crates/eframe/src/web/events.rs b/crates/eframe/src/web/events.rs index 44881cb5d..b8a7f0cd6 100644 --- a/crates/eframe/src/web/events.rs +++ b/crates/eframe/src/web/events.rs @@ -4,12 +4,15 @@ use egui::Key; use super::*; -struct IsDestroyed(pub bool); - +/// Calls `request_animation_frame` to schedule repaint. +/// +/// It will only paint if needed, but will always call `request_animation_frame` immediately. pub fn paint_and_schedule( runner_ref: &AppRunnerRef, panicked: Arc, ) -> Result<(), JsValue> { + struct IsDestroyed(pub bool); + fn paint_if_needed(runner_ref: &AppRunnerRef) -> Result { let mut runner_lock = runner_ref.lock(); let is_destroyed = runner_lock.is_destroyed.fetch(); diff --git a/crates/egui_demo_app/Cargo.toml b/crates/egui_demo_app/Cargo.toml index 49676fe21..0c011e7b5 100644 --- a/crates/egui_demo_app/Cargo.toml +++ b/crates/egui_demo_app/Cargo.toml @@ -63,4 +63,6 @@ env_logger = "0.10" # web: [target.'cfg(target_arch = "wasm32")'.dependencies] console_error_panic_hook = "0.1.6" +wasm-bindgen = "=0.2.84" wasm-bindgen-futures = "0.4" +web-sys = "0.3" diff --git a/crates/egui_demo_app/src/backend_panel.rs b/crates/egui_demo_app/src/backend_panel.rs index c478231ff..ea11c13f0 100644 --- a/crates/egui_demo_app/src/backend_panel.rs +++ b/crates/egui_demo_app/src/backend_panel.rs @@ -265,8 +265,7 @@ impl BackendPanel { { log::info!("Waiting 2s before requesting repaint..."); let ctx = ui.ctx().clone(); - std::thread::spawn(move || { - std::thread::sleep(std::time::Duration::from_secs(2)); + call_after_delay(std::time::Duration::from_secs(2), move || { log::info!("Request a repaint in 3s..."); ctx.request_repaint_after(std::time::Duration::from_secs(3)); }); @@ -385,3 +384,28 @@ impl EguiWindows { }); } } + +// ---------------------------------------------------------------------------- + +#[cfg(not(target_arch = "wasm32"))] +fn call_after_delay(delay: std::time::Duration, f: impl FnOnce() + Send + 'static) { + std::thread::spawn(move || { + std::thread::sleep(delay); + f(); + }); +} + +#[cfg(target_arch = "wasm32")] +fn call_after_delay(delay: std::time::Duration, f: impl FnOnce() + Send + 'static) { + use wasm_bindgen::prelude::*; + let window = web_sys::window().unwrap(); + let closure = Closure::once(f); + let delay_ms = delay.as_millis() as _; + window + .set_timeout_with_callback_and_timeout_and_arguments_0( + closure.as_ref().unchecked_ref(), + delay_ms, + ) + .unwrap(); + closure.forget(); // We must forget it, or else the callback is canceled on drop +}