From df518bf3c6dad5c2ca0c4bb04830900ebcff4988 Mon Sep 17 00:00:00 2001 From: Red Artist Date: Sun, 29 May 2022 01:33:28 +0530 Subject: [PATCH 01/18] start working on idle timeout repaint interval --- eframe/src/native/run.rs | 14 +++++++++++--- egui-winit/src/lib.rs | 3 ++- egui/src/context.rs | 8 ++++++++ egui/src/data/output.rs | 24 ++++++++++++++++++++++-- 4 files changed, 43 insertions(+), 6 deletions(-) diff --git a/eframe/src/native/run.rs b/eframe/src/native/run.rs index 606d85d1bf9..f3370293cd9 100644 --- a/eframe/src/native/run.rs +++ b/eframe/src/native/run.rs @@ -111,7 +111,7 @@ pub fn run_glow( textures_delta, shapes, } = integration.update(app.as_mut(), window); - + let idle_duration = platform_output.idle_timeout_interval; integration.handle_platform_output(window, platform_output); let clipped_primitives = { @@ -136,6 +136,10 @@ pub fn run_glow( } else if needs_repaint { window.request_redraw(); winit::event_loop::ControlFlow::Poll + } else if let Some(idle_duration) = idle_duration { + let idle_duration = std::time::Instant::now() + + idle_duration; + winit::event_loop::ControlFlow::WaitUntil(idle_duration) } else { winit::event_loop::ControlFlow::Wait }; @@ -152,7 +156,6 @@ pub fn run_glow( std::thread::sleep(std::time::Duration::from_millis(10)); } }; - match event { // Platform-dependent event handlers to workaround a winit bug // See: https://github.com/rust-windowing/winit/issues/987 @@ -194,7 +197,12 @@ pub fn run_glow( painter.destroy(); } winit::event::Event::UserEvent(RequestRepaintEvent) => window.request_redraw(), - _ => (), + winit::event::Event::NewEvents(winit::event::StartCause::ResumeTimeReached { + .. + }) => { + window.request_redraw(); + } + _ => {} } }); } diff --git a/egui-winit/src/lib.rs b/egui-winit/src/lib.rs index 6ce5120437d..f28e27dc493 100644 --- a/egui-winit/src/lib.rs +++ b/egui-winit/src/lib.rs @@ -469,13 +469,14 @@ impl State { let egui::PlatformOutput { cursor_icon, + idle_timeout_interval, open_url, copied_text, events: _, // handled above mutable_text_under_cursor: _, // only used in eframe web text_cursor_pos, } = platform_output; - + let _ = idle_timeout_interval; self.current_pixels_per_point = egui_ctx.pixels_per_point(); // someone can have changed it to scale the UI self.set_cursor_icon(window, cursor_icon); diff --git a/egui/src/context.rs b/egui/src/context.rs index 17c86327f4b..dbb417906b0 100644 --- a/egui/src/context.rs +++ b/egui/src/context.rs @@ -582,6 +582,14 @@ impl Context { self.write().request_repaint_callbacks = Some(callback); } + /// in reactive mode, egui is only repainted upon new input events + /// but, your gui might become too stale due to long periods of inactivity in cases where app is + /// idling in the background. + /// this function can set a idle repaint interval, and when egui has been idling without any + /// new input for the duration of the interval, the app will be forced to update. + pub fn set_idle_repaint_interval(&mut self, interval: Option) { + self.write().output.idle_timeout_interval = interval; + } /// Tell `egui` which fonts to use. /// /// The default `egui` fonts only support latin and cyrillic alphabets, diff --git a/egui/src/data/output.rs b/egui/src/data/output.rs index 741112848ef..1b52cac197e 100644 --- a/egui/src/data/output.rs +++ b/egui/src/data/output.rs @@ -49,12 +49,15 @@ impl FullOutput { /// You can access (and modify) this with [`crate::Context::output`]. /// /// The backend should use this. -#[derive(Clone, Default, PartialEq)] +#[derive(Clone, PartialEq)] #[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] pub struct PlatformOutput { /// Set the cursor to this icon. pub cursor_icon: CursorIcon, + /// Interval duration to wait for events before forcing update + pub idle_timeout_interval: Option, + /// If set, open this url. pub open_url: Option, @@ -73,7 +76,19 @@ pub struct PlatformOutput { /// Screen-space position of text edit cursor (used for IME). pub text_cursor_pos: Option, } - +impl Default for PlatformOutput { + fn default() -> Self { + Self { + cursor_icon: Default::default(), + idle_timeout_interval: Some(std::time::Duration::from_secs(1)), + open_url: None, + copied_text: "".to_string(), + events: vec![], + mutable_text_under_cursor: false, + text_cursor_pos: None, + } + } +} impl PlatformOutput { /// Open the given url in a web browser. /// If egui is running in a browser, the same tab will be reused. @@ -103,6 +118,7 @@ impl PlatformOutput { pub fn append(&mut self, newer: Self) { let Self { cursor_icon, + idle_timeout_interval, open_url, copied_text, mut events, @@ -111,6 +127,9 @@ impl PlatformOutput { } = newer; self.cursor_icon = cursor_icon; + if idle_timeout_interval.is_some() { + self.idle_timeout_interval = idle_timeout_interval; + } if open_url.is_some() { self.open_url = open_url; } @@ -126,6 +145,7 @@ impl PlatformOutput { pub fn take(&mut self) -> Self { let taken = std::mem::take(self); self.cursor_icon = taken.cursor_icon; // eveything else is ephemeral + self.idle_timeout_interval = taken.idle_timeout_interval; taken } } From 9e780b69b2aa15c5290893841f8736c63d9a5f36 Mon Sep 17 00:00:00 2001 From: Red Artist Date: Mon, 30 May 2022 21:02:45 +0530 Subject: [PATCH 02/18] replace needs_repaint with repaint_after --- eframe/src/native/run.rs | 32 ++++++++++----- eframe/src/web/backend.rs | 6 +-- eframe/src/web/events.rs | 4 +- egui-winit/src/lib.rs | 2 - egui/src/context.rs | 63 +++++++++++++++++++++--------- egui/src/data/output.rs | 37 ++++++------------ egui_demo_app/src/backend_panel.rs | 41 +++++++++++++++++-- egui_glium/src/lib.rs | 10 +++-- 8 files changed, 127 insertions(+), 68 deletions(-) diff --git a/eframe/src/native/run.rs b/eframe/src/native/run.rs index f3370293cd9..ce057971ba6 100644 --- a/eframe/src/native/run.rs +++ b/eframe/src/native/run.rs @@ -107,11 +107,11 @@ pub fn run_glow( let egui::FullOutput { platform_output, - needs_repaint, + repaint_after, textures_delta, shapes, } = integration.update(app.as_mut(), window); - let idle_duration = platform_output.idle_timeout_interval; + integration.handle_platform_output(window, platform_output); let clipped_primitives = { @@ -133,13 +133,18 @@ pub fn run_glow( *control_flow = if integration.should_quit() { winit::event_loop::ControlFlow::Exit - } else if needs_repaint { + } else if repaint_after.is_zero() { window.request_redraw(); winit::event_loop::ControlFlow::Poll - } else if let Some(idle_duration) = idle_duration { - let idle_duration = std::time::Instant::now() - + idle_duration; - winit::event_loop::ControlFlow::WaitUntil(idle_duration) + } else if let Some(repaint_after_instant) = + std::time::Instant::now().checked_add(repaint_after) + { + // if repaint_after is something huge and can't be added to Instant, + // we will use `ControlFlow::Wait` instead. + // technically, this might lead to some weird corner cases where the user *WANTS* + // winit to use `WaitUntil(MAX_INSTANT)` explicitly. they can roll their own + // egui backend impl i guess. + winit::event_loop::ControlFlow::WaitUntil(repaint_after_instant) } else { winit::event_loop::ControlFlow::Wait }; @@ -287,7 +292,7 @@ pub fn run_wgpu( let egui::FullOutput { platform_output, - needs_repaint, + repaint_after, textures_delta, shapes, } = integration.update(app.as_mut(), window); @@ -308,9 +313,18 @@ pub fn run_wgpu( *control_flow = if integration.should_quit() { winit::event_loop::ControlFlow::Exit - } else if needs_repaint { + } else if repaint_after.is_zero() { window.request_redraw(); winit::event_loop::ControlFlow::Poll + } else if let Some(repaint_after_instant) = + std::time::Instant::now().checked_add(repaint_after) + { + // if repaint_after is something huge and can't be added to Instant, + // we will use `ControlFlow::Wait` instead. + // technically, this might lead to some weird corner cases where the user *WANTS* + // winit to use `WaitUntil(MAX_INSTANT)` explicitly. they can roll their own + // egui backend impl i guess. + winit::event_loop::ControlFlow::WaitUntil(repaint_after_instant) } else { winit::event_loop::ControlFlow::Wait }; diff --git a/eframe/src/web/backend.rs b/eframe/src/web/backend.rs index a636f40550a..dbb4e54587f 100644 --- a/eframe/src/web/backend.rs +++ b/eframe/src/web/backend.rs @@ -248,7 +248,7 @@ impl AppRunner { /// Returns `true` if egui requests a repaint. /// /// Call [`Self::paint`] later to paint - pub fn logic(&mut self) -> Result<(bool, Vec), JsValue> { + pub fn logic(&mut self) -> Result<(std::time::Duration, Vec), JsValue> { let frame_start = now_sec(); resize_canvas_to_screen_size(self.canvas_id(), self.app.max_size_points()); @@ -260,7 +260,7 @@ impl AppRunner { }); let egui::FullOutput { platform_output, - needs_repaint, + repaint_after, textures_delta, shapes, } = full_output; @@ -282,7 +282,7 @@ impl AppRunner { } self.frame.info.cpu_usage = Some((now_sec() - frame_start) as f32); - Ok((needs_repaint, clipped_primitives)) + Ok((repaint_after, clipped_primitives)) } pub fn clear_color_buffer(&self) { diff --git a/eframe/src/web/events.rs b/eframe/src/web/events.rs index 26e7fc34db8..bc260b181da 100644 --- a/eframe/src/web/events.rs +++ b/eframe/src/web/events.rs @@ -9,9 +9,9 @@ pub fn paint_and_schedule( let mut runner_lock = runner_ref.lock(); if runner_lock.needs_repaint.fetch_and_clear() { runner_lock.clear_color_buffer(); - let (needs_repaint, clipped_primitives) = runner_lock.logic()?; + let (repaint_after, clipped_primitives) = runner_lock.logic()?; runner_lock.paint(&clipped_primitives)?; - if needs_repaint { + if repaint_after.is_zero() { runner_lock.needs_repaint.set_true(); } runner_lock.auto_save(); diff --git a/egui-winit/src/lib.rs b/egui-winit/src/lib.rs index f28e27dc493..b869aed96c7 100644 --- a/egui-winit/src/lib.rs +++ b/egui-winit/src/lib.rs @@ -469,14 +469,12 @@ impl State { let egui::PlatformOutput { cursor_icon, - idle_timeout_interval, open_url, copied_text, events: _, // handled above mutable_text_under_cursor: _, // only used in eframe web text_cursor_pos, } = platform_output; - let _ = idle_timeout_interval; self.current_pixels_per_point = egui_ctx.pixels_per_point(); // someone can have changed it to scale the UI self.set_cursor_icon(window, cursor_icon); diff --git a/egui/src/context.rs b/egui/src/context.rs index dbb417906b0..49d5e1c6850 100644 --- a/egui/src/context.rs +++ b/egui/src/context.rs @@ -28,7 +28,6 @@ impl Default for WrappedTextureManager { } // ---------------------------------------------------------------------------- - #[derive(Default)] struct ContextImpl { /// `None` until the start of the first frame. @@ -47,7 +46,9 @@ struct ContextImpl { output: PlatformOutput, paint_stats: PaintStats, - + /// the duration backend will poll for new events, before forcing another egui update + /// even if there's no new events. + repaint_after: std::time::Duration, /// While positive, keep requesting repaints. Decrement at the end of each frame. repaint_requests: u32, request_repaint_callbacks: Option>, @@ -574,6 +575,39 @@ impl Context { } } + /// request repaint after the specified duration elapses in the case of no new input + /// events being received. + /// + /// function can be multiple times, but only the *smallest* duration will be considered. + /// so, if the function is called two times with `1 second` and `2 seconds`, egui will repaint + /// after `1 second` + /// + /// this is primarily useful for applications who would like to save battery by avoiding wasted + /// redraws when the app is not in focus. but sometimes the GUI of the app might become stale + /// and outdated if it is not updated for too long. + /// + /// lets say, something like a stop watch widget that displays the time in seconds. you would waste + /// resources repainting multiple times within the same second (when you have no input), + /// just calculate the difference of duration between current time and next second change, + /// and call this function, to make sure that you are displaying the latest updated time, but + /// not wasting resources on needless repaints within the same second. + /// + /// NOTE: only works if called before `Context::end_frame()`. to force egui to update, + /// use `Context::request_repaint()` instead. + /// + /// Quirk: + /// + /// duration begins at the next frame. lets say for example that its a very inefficient app + /// and takes 500 milliseconds per frame at 2 fps. the widget / user might want a repaint in + /// next 500 milliseconds. now, app takes 1000 ms per frame (1 fps) because the backend event + /// timeout takes 500 milli seconds AFTER the vsync swap buffer. + /// so, its not that we are requesting repaint within X duration. we are rather timing out + /// during app idle time where we are not receiving any new input events. + pub fn request_repaint_after(&self, duration: std::time::Duration) { + // maybe we can check if duration is ZERO, and call self.request_repaint()? + let mut ctx = self.write(); + ctx.repaint_after = ctx.repaint_after.min(duration); + } /// For integrations: this callback will be called when an egui user calls [`Self::request_repaint`]. /// /// This lets you wake up a sleeping UI thread. @@ -582,14 +616,6 @@ impl Context { self.write().request_repaint_callbacks = Some(callback); } - /// in reactive mode, egui is only repainted upon new input events - /// but, your gui might become too stale due to long periods of inactivity in cases where app is - /// idling in the background. - /// this function can set a idle repaint interval, and when egui has been idling without any - /// new input for the duration of the interval, the app will be forced to update. - pub fn set_idle_repaint_interval(&mut self, interval: Option) { - self.write().output.idle_timeout_interval = interval; - } /// Tell `egui` which fonts to use. /// /// The default `egui` fonts only support latin and cyrillic alphabets, @@ -813,19 +839,18 @@ impl Context { let platform_output: PlatformOutput = std::mem::take(&mut self.output()); - let needs_repaint = if self.read().repaint_requests > 0 { - self.write().repaint_requests -= 1; - true - } else { - false - }; - self.write().requested_repaint_last_frame = needs_repaint; - + let repaint_after = self.read().repaint_after; + self.write().requested_repaint_last_frame = repaint_after.is_zero(); + // make sure we reset the repaint_after duration. + // otherwise, if repaint_after is low, then any widget setting repaint_after next frame, + // will fail to overwrite the previous lower value. and thus, repaints will never + // go back to higher values. + self.write().repaint_after = std::time::Duration::MAX; let shapes = self.drain_paint_lists(); FullOutput { platform_output, - needs_repaint, + repaint_after, textures_delta, shapes, } diff --git a/egui/src/data/output.rs b/egui/src/data/output.rs index 1b52cac197e..385cd6731d7 100644 --- a/egui/src/data/output.rs +++ b/egui/src/data/output.rs @@ -10,10 +10,15 @@ pub struct FullOutput { /// Non-rendering related output. pub platform_output: PlatformOutput, - /// If `true`, egui is requesting immediate repaint (i.e. on the next frame). + /// If `Duration::is_zero()`, egui is requesting immediate repaint (i.e. on the next frame). /// /// This happens for instance when there is an animation, or if a user has called `Context::request_repaint()`. - pub needs_repaint: bool, + /// + /// If `Duration` is greater than zero, egui wants to be repainted at or before the specified + /// duration elapses. when in reactive mode, egui spends forever waiting for input and only then, + /// will it repaint itself. this can be used to make sure that backend will only wait for a + /// specified amount of time, and repaint egui without any new input. + pub repaint_after: std::time::Duration, /// Texture changes since last frame (including the font texture). /// @@ -32,13 +37,13 @@ impl FullOutput { pub fn append(&mut self, newer: Self) { let Self { platform_output, - needs_repaint, + repaint_after, textures_delta, shapes, } = newer; self.platform_output.append(platform_output); - self.needs_repaint = needs_repaint; // if the last frame doesn't need a repaint, then we don't need to repaint + self.repaint_after = repaint_after; // if the last frame doesn't need a repaint, then we don't need to repaint self.textures_delta.append(textures_delta); self.shapes = shapes; // Only paint the latest } @@ -49,15 +54,12 @@ impl FullOutput { /// You can access (and modify) this with [`crate::Context::output`]. /// /// The backend should use this. -#[derive(Clone, PartialEq)] +#[derive(Default, Clone, PartialEq)] #[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] pub struct PlatformOutput { /// Set the cursor to this icon. pub cursor_icon: CursorIcon, - /// Interval duration to wait for events before forcing update - pub idle_timeout_interval: Option, - /// If set, open this url. pub open_url: Option, @@ -76,19 +78,7 @@ pub struct PlatformOutput { /// Screen-space position of text edit cursor (used for IME). pub text_cursor_pos: Option, } -impl Default for PlatformOutput { - fn default() -> Self { - Self { - cursor_icon: Default::default(), - idle_timeout_interval: Some(std::time::Duration::from_secs(1)), - open_url: None, - copied_text: "".to_string(), - events: vec![], - mutable_text_under_cursor: false, - text_cursor_pos: None, - } - } -} + impl PlatformOutput { /// Open the given url in a web browser. /// If egui is running in a browser, the same tab will be reused. @@ -118,7 +108,6 @@ impl PlatformOutput { pub fn append(&mut self, newer: Self) { let Self { cursor_icon, - idle_timeout_interval, open_url, copied_text, mut events, @@ -127,9 +116,6 @@ impl PlatformOutput { } = newer; self.cursor_icon = cursor_icon; - if idle_timeout_interval.is_some() { - self.idle_timeout_interval = idle_timeout_interval; - } if open_url.is_some() { self.open_url = open_url; } @@ -145,7 +131,6 @@ impl PlatformOutput { pub fn take(&mut self) -> Self { let taken = std::mem::take(self); self.cursor_icon = taken.cursor_icon; // eveything else is ephemeral - self.idle_timeout_interval = taken.idle_timeout_interval; taken } } diff --git a/egui_demo_app/src/backend_panel.rs b/egui_demo_app/src/backend_panel.rs index 28810075197..49b4f210be2 100644 --- a/egui_demo_app/src/backend_panel.rs +++ b/egui_demo_app/src/backend_panel.rs @@ -1,3 +1,5 @@ +use egui::Widget; + /// How often we repaint the demo app by default #[derive(Clone, Copy, Debug, Eq, PartialEq)] enum RunMode { @@ -41,7 +43,6 @@ impl Default for RunMode { // ---------------------------------------------------------------------------- -#[derive(Default)] #[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] #[cfg_attr(feature = "serde", serde(default))] pub struct BackendPanel { @@ -51,6 +52,10 @@ pub struct BackendPanel { // go back to [`Reactive`] mode each time we start run_mode: RunMode, + #[cfg_attr(feature = "serde", serde(skip))] + // reset to 1 second as default repaint_after idle timeout. + repaint_after_timeout: std::time::Duration, + /// current slider value for current gui scale #[cfg_attr(feature = "serde", serde(skip))] pixels_per_point: Option, @@ -61,14 +66,32 @@ pub struct BackendPanel { egui_windows: EguiWindows, } +impl Default for BackendPanel { + fn default() -> Self { + Self { + open: false, + run_mode: Default::default(), + repaint_after_timeout: std::time::Duration::from_secs(1), + pixels_per_point: None, + frame_history: Default::default(), + egui_windows: Default::default(), + } + } +} + impl BackendPanel { pub fn update(&mut self, ctx: &egui::Context, frame: &mut eframe::Frame) { self.frame_history .on_new_frame(ctx.input().time, frame.info().cpu_usage); - if self.run_mode == RunMode::Continuous { - // Tell the backend to repaint as soon as possible - ctx.request_repaint(); + match self.run_mode { + RunMode::Reactive => { + ctx.request_repaint_after(self.repaint_after_timeout); + } + RunMode::Continuous => { + // Tell the backend to repaint as soon as possible + ctx.request_repaint(); + } } } @@ -220,6 +243,16 @@ impl BackendPanel { )); } else { ui.label("Only running UI code when there are animations or input."); + ui.label("but if there's no input for the repaint_after duration, we force an update"); + ui.label("repaint_after (in seconds)"); + let mut milli_seconds = self.repaint_after_timeout.as_secs_f32(); + if egui::DragValue::new(&mut milli_seconds) + .clamp_range(0.1..=10.0) + .ui(ui) + .changed() + { + self.repaint_after_timeout = std::time::Duration::from_secs_f32(milli_seconds); + } } } } diff --git a/egui_glium/src/lib.rs b/egui_glium/src/lib.rs index 84a2459fb0b..fa7437f9d94 100644 --- a/egui_glium/src/lib.rs +++ b/egui_glium/src/lib.rs @@ -56,13 +56,17 @@ impl EguiGlium { /// Returns `true` if egui requests a repaint. /// /// Call [`Self::paint`] later to paint. - pub fn run(&mut self, display: &glium::Display, run_ui: impl FnMut(&egui::Context)) -> bool { + pub fn run( + &mut self, + display: &glium::Display, + run_ui: impl FnMut(&egui::Context), + ) -> std::time::Duration { let raw_input = self .egui_winit .take_egui_input(display.gl_window().window()); let egui::FullOutput { platform_output, - needs_repaint, + repaint_after, textures_delta, shapes, } = self.egui_ctx.run(raw_input, run_ui); @@ -76,7 +80,7 @@ impl EguiGlium { self.shapes = shapes; self.textures_delta.append(textures_delta); - needs_repaint + repaint_after } /// Paint the results of the last call to [`Self::run`]. From 80d47e19e8edd38734682474c5e60270940ab9ae Mon Sep 17 00:00:00 2001 From: Red Artist Date: Mon, 30 May 2022 21:10:00 +0530 Subject: [PATCH 03/18] forgot to reduce repaint_requests count at the end of frame. --- egui/src/context.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/egui/src/context.rs b/egui/src/context.rs index 49d5e1c6850..5d48d749bc9 100644 --- a/egui/src/context.rs +++ b/egui/src/context.rs @@ -839,6 +839,9 @@ impl Context { let platform_output: PlatformOutput = std::mem::take(&mut self.output()); + if self.read().repaint_requests > 0 { + self.write().repaint_requests -= 1; + } let repaint_after = self.read().repaint_after; self.write().requested_repaint_last_frame = repaint_after.is_zero(); // make sure we reset the repaint_after duration. From f51a3e013f28e552f05bbe510cc871796fc13054 Mon Sep 17 00:00:00 2001 From: Red Artist Date: Mon, 30 May 2022 22:27:12 +0530 Subject: [PATCH 04/18] set repaint_after to Duration::ZERO when repaint_requests is positive --- egui/src/context.rs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/egui/src/context.rs b/egui/src/context.rs index 5d48d749bc9..392ff2f93c6 100644 --- a/egui/src/context.rs +++ b/egui/src/context.rs @@ -839,10 +839,15 @@ impl Context { let platform_output: PlatformOutput = std::mem::take(&mut self.output()); - if self.read().repaint_requests > 0 { + // if repaint_requests is greater than zero. just set the duration to zero for immediate + // repaint. if there's no repaint requests, then we can use the actual repaint_after instead. + let repaint_after = if self.read().repaint_requests > 0 { self.write().repaint_requests -= 1; - } - let repaint_after = self.read().repaint_after; + std::time::Duration::ZERO + } else { + self.read().repaint_after; + }; + self.write().requested_repaint_last_frame = repaint_after.is_zero(); // make sure we reset the repaint_after duration. // otherwise, if repaint_after is low, then any widget setting repaint_after next frame, From 07e6e23024ad4ea8394e64b033e3e19cbf94ef8f Mon Sep 17 00:00:00 2001 From: Red Artist Date: Mon, 30 May 2022 22:28:53 +0530 Subject: [PATCH 05/18] fix return type docs in web logic() function --- eframe/src/web/backend.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eframe/src/web/backend.rs b/eframe/src/web/backend.rs index dbb4e54587f..71a6aa1a68f 100644 --- a/eframe/src/web/backend.rs +++ b/eframe/src/web/backend.rs @@ -245,7 +245,7 @@ impl AppRunner { Ok(()) } - /// Returns `true` if egui requests a repaint. + /// Returns how long to wait until the next repaint. /// /// Call [`Self::paint`] later to paint pub fn logic(&mut self) -> Result<(std::time::Duration, Vec), JsValue> { From 5fb30b0c3cadfcd6095e4028e552b6f304918bf5 Mon Sep 17 00:00:00 2001 From: Red Artist Date: Tue, 31 May 2022 16:32:52 +0530 Subject: [PATCH 06/18] fix accidental semi colon --- egui/src/context.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/egui/src/context.rs b/egui/src/context.rs index 392ff2f93c6..1600d7b072d 100644 --- a/egui/src/context.rs +++ b/egui/src/context.rs @@ -845,7 +845,7 @@ impl Context { self.write().repaint_requests -= 1; std::time::Duration::ZERO } else { - self.read().repaint_after; + self.read().repaint_after }; self.write().requested_repaint_last_frame = repaint_after.is_zero(); From 72a7d102804bd7872ec4fec4ed931cbb4e324e03 Mon Sep 17 00:00:00 2001 From: Red Artist Date: Tue, 31 May 2022 16:43:53 +0530 Subject: [PATCH 07/18] add to changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ca1fc513679..7d2a9222f9b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,7 @@ NOTE: [`epaint`](epaint/CHANGELOG.md), [`eframe`](eframe/CHANGELOG.md), [`egui-w ### Changed * `PaintCallback` shapes now require the whole callback to be put in an `Arc` with the value being a backend-specific callback type. ([#1684](https://github.com/emilk/egui/pull/1684)) +* Replaced `needs_repaint` in `FullOutput` with `repaint_after`. used to force repaint after the set duration in reactive mode.([#1694](https://github.com/emilk/egui/pull/1694)) ### Fixed 🐛 * Fixed `ImageButton`'s changing background padding on hover ([#1595](https://github.com/emilk/egui/pull/1595)). From 1e5ac46700a46af79d27fd543fdc95b8f32e8cc5 Mon Sep 17 00:00:00 2001 From: Red Artist Date: Tue, 31 May 2022 21:04:07 +0530 Subject: [PATCH 08/18] change egui glow to use repaint_after instead of needs_repaint --- egui_glow/examples/pure_glow.rs | 8 ++++++-- egui_glow/src/winit.rs | 6 +++--- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/egui_glow/examples/pure_glow.rs b/egui_glow/examples/pure_glow.rs index 3af2f8bc5f1..2b421fd936a 100644 --- a/egui_glow/examples/pure_glow.rs +++ b/egui_glow/examples/pure_glow.rs @@ -16,7 +16,7 @@ fn main() { let mut redraw = || { let mut quit = false; - let needs_repaint = egui_glow.run(gl_window.window(), |egui_ctx| { + let repaint_after = egui_glow.run(gl_window.window(), |egui_ctx| { egui::SidePanel::left("my_side_panel").show(egui_ctx, |ui| { ui.heading("Hello World!"); if ui.button("Quit").clicked() { @@ -28,9 +28,13 @@ fn main() { *control_flow = if quit { glutin::event_loop::ControlFlow::Exit - } else if needs_repaint { + } else if repaint_after.is_zero() { gl_window.window().request_redraw(); glutin::event_loop::ControlFlow::Poll + } else if let Some(repaint_after_instant) = + std::time::Instant::now().checked_add(repaint_after) + { + glutin::event_loop::ControlFlow::WaitUntil(repaint_after_instant) } else { glutin::event_loop::ControlFlow::Wait }; diff --git a/egui_glow/src/winit.rs b/egui_glow/src/winit.rs index 52a0301f3d6..b75e1431b60 100644 --- a/egui_glow/src/winit.rs +++ b/egui_glow/src/winit.rs @@ -48,11 +48,11 @@ impl EguiGlow { &mut self, window: &winit::window::Window, run_ui: impl FnMut(&egui::Context), - ) -> bool { + ) -> std::time::Duration { let raw_input = self.egui_winit.take_egui_input(window); let egui::FullOutput { platform_output, - needs_repaint, + repaint_after, textures_delta, shapes, } = self.egui_ctx.run(raw_input, run_ui); @@ -62,7 +62,7 @@ impl EguiGlow { self.shapes = shapes; self.textures_delta.append(textures_delta); - needs_repaint + repaint_after } /// Paint the results of the last call to [`Self::run`]. From 9444edefaf15e2742a4d27df9d6fc0c29e3f569a Mon Sep 17 00:00:00 2001 From: Red Artist Date: Tue, 31 May 2022 21:13:17 +0530 Subject: [PATCH 09/18] change egui glium examples to use repaint_after instead of needs_repaint --- egui_glium/examples/native_texture.rs | 8 ++++++-- egui_glium/examples/pure_glium.rs | 8 ++++++-- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/egui_glium/examples/native_texture.rs b/egui_glium/examples/native_texture.rs index de7ec818cdf..d0ffa4876ac 100644 --- a/egui_glium/examples/native_texture.rs +++ b/egui_glium/examples/native_texture.rs @@ -24,7 +24,7 @@ fn main() { let mut redraw = || { let mut quit = false; - let needs_repaint = egui_glium.run(&display, |egui_ctx| { + let repaint_after = egui_glium.run(&display, |egui_ctx| { egui::SidePanel::left("my_side_panel").show(egui_ctx, |ui| { if ui .add(egui::Button::image_and_text( @@ -44,9 +44,13 @@ fn main() { *control_flow = if quit { glutin::event_loop::ControlFlow::Exit - } else if needs_repaint { + } else if repaint_after.is_zero() { display.gl_window().window().request_redraw(); glutin::event_loop::ControlFlow::Poll + } else if let Some(repaint_after_instant) = + std::time::Instant::now().checked_add(repaint_after) + { + glutin::event_loop::ControlFlow::WaitUntil(repaint_after_instant) } else { glutin::event_loop::ControlFlow::Wait }; diff --git a/egui_glium/examples/pure_glium.rs b/egui_glium/examples/pure_glium.rs index d1d81a91828..5d6a7b7fa54 100644 --- a/egui_glium/examples/pure_glium.rs +++ b/egui_glium/examples/pure_glium.rs @@ -14,7 +14,7 @@ fn main() { let mut redraw = || { let mut quit = false; - let needs_repaint = egui_glium.run(&display, |egui_ctx| { + let repaint_after = egui_glium.run(&display, |egui_ctx| { egui::SidePanel::left("my_side_panel").show(egui_ctx, |ui| { ui.heading("Hello World!"); if ui.button("Quit").clicked() { @@ -25,9 +25,13 @@ fn main() { *control_flow = if quit { glutin::event_loop::ControlFlow::Exit - } else if needs_repaint { + } else if repaint_after.is_zero() { display.gl_window().window().request_redraw(); glutin::event_loop::ControlFlow::Poll + } else if let Some(repaint_after_instant) = + std::time::Instant::now().checked_add(repaint_after) + { + glutin::event_loop::ControlFlow::WaitUntil(repaint_after_instant) } else { glutin::event_loop::ControlFlow::Wait }; From 2870d9ee8a1606c720c52fc19bd6e32938583d86 Mon Sep 17 00:00:00 2001 From: Red Artist Date: Tue, 31 May 2022 21:29:34 +0530 Subject: [PATCH 10/18] fix docs --- egui/src/context.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/egui/src/context.rs b/egui/src/context.rs index 1600d7b072d..b727bc03c1d 100644 --- a/egui/src/context.rs +++ b/egui/src/context.rs @@ -596,7 +596,6 @@ impl Context { /// use `Context::request_repaint()` instead. /// /// Quirk: - /// /// duration begins at the next frame. lets say for example that its a very inefficient app /// and takes 500 milliseconds per frame at 2 fps. the widget / user might want a repaint in /// next 500 milliseconds. now, app takes 1000 ms per frame (1 fps) because the backend event @@ -608,6 +607,7 @@ impl Context { let mut ctx = self.write(); ctx.repaint_after = ctx.repaint_after.min(duration); } + /// For integrations: this callback will be called when an egui user calls [`Self::request_repaint`]. /// /// This lets you wake up a sleeping UI thread. From 9976e47835901e883a56caae0b9254b22c25ad5e Mon Sep 17 00:00:00 2001 From: Red Artist Date: Tue, 21 Jun 2022 01:34:54 +0530 Subject: [PATCH 11/18] fix some docs and other review suggestions --- CHANGELOG.md | 2 +- eframe/src/native/run.rs | 5 +++++ egui/src/context.rs | 28 +++++++++++++-------------- egui_demo_app/src/backend_panel.rs | 6 +++--- egui_glium/examples/native_texture.rs | 6 ++++++ egui_glium/examples/pure_glium.rs | 6 +++++- egui_glow/examples/pure_glow.rs | 7 +++++++ egui_glow/src/winit.rs | 2 +- 8 files changed, 42 insertions(+), 20 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7d2a9222f9b..374d1f7d581 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,7 +17,7 @@ NOTE: [`epaint`](epaint/CHANGELOG.md), [`eframe`](eframe/CHANGELOG.md), [`egui-w ### Changed * `PaintCallback` shapes now require the whole callback to be put in an `Arc` with the value being a backend-specific callback type. ([#1684](https://github.com/emilk/egui/pull/1684)) -* Replaced `needs_repaint` in `FullOutput` with `repaint_after`. used to force repaint after the set duration in reactive mode.([#1694](https://github.com/emilk/egui/pull/1694)) +* Replaced `needs_repaint` in `FullOutput` with `repaint_after`. Used to force repaint after the set duration in reactive mode.([#1694](https://github.com/emilk/egui/pull/1694)). ### Fixed 🐛 * Fixed `ImageButton`'s changing background padding on hover ([#1595](https://github.com/emilk/egui/pull/1595)). diff --git a/eframe/src/native/run.rs b/eframe/src/native/run.rs index ce057971ba6..579489e3c62 100644 --- a/eframe/src/native/run.rs +++ b/eframe/src/native/run.rs @@ -398,6 +398,11 @@ pub fn run_wgpu( painter.destroy(); } winit::event::Event::UserEvent(RequestRepaintEvent) => window.request_redraw(), + winit::event::Event::NewEvents(winit::event::StartCause::ResumeTimeReached { + .. + }) => { + window.request_redraw(); + } _ => (), } }); diff --git a/egui/src/context.rs b/egui/src/context.rs index b727bc03c1d..dc58bb61eea 100644 --- a/egui/src/context.rs +++ b/egui/src/context.rs @@ -575,18 +575,18 @@ impl Context { } } - /// request repaint after the specified duration elapses in the case of no new input + /// Request repaint after the specified duration elapses in the case of no new input /// events being received. /// - /// function can be multiple times, but only the *smallest* duration will be considered. - /// so, if the function is called two times with `1 second` and `2 seconds`, egui will repaint + /// The function can be multiple times, but only the *smallest* duration will be considered. + /// So, if the function is called two times with `1 second` and `2 seconds`, egui will repaint /// after `1 second` /// - /// this is primarily useful for applications who would like to save battery by avoiding wasted - /// redraws when the app is not in focus. but sometimes the GUI of the app might become stale + /// This is primarily useful for applications who would like to save battery by avoiding wasted + /// redraws when the app is not in focus. But sometimes the GUI of the app might become stale /// and outdated if it is not updated for too long. /// - /// lets say, something like a stop watch widget that displays the time in seconds. you would waste + /// Lets say, something like a stop watch widget that displays the time in seconds. You would waste /// resources repainting multiple times within the same second (when you have no input), /// just calculate the difference of duration between current time and next second change, /// and call this function, to make sure that you are displaying the latest updated time, but @@ -595,15 +595,15 @@ impl Context { /// NOTE: only works if called before `Context::end_frame()`. to force egui to update, /// use `Context::request_repaint()` instead. /// - /// Quirk: - /// duration begins at the next frame. lets say for example that its a very inefficient app - /// and takes 500 milliseconds per frame at 2 fps. the widget / user might want a repaint in - /// next 500 milliseconds. now, app takes 1000 ms per frame (1 fps) because the backend event - /// timeout takes 500 milli seconds AFTER the vsync swap buffer. - /// so, its not that we are requesting repaint within X duration. we are rather timing out - /// during app idle time where we are not receiving any new input events. + /// ### Quirk: + /// Duration begins at the next frame. lets say for example that its a very inefficient app + /// and takes 500 milliseconds per frame at 2 fps. The widget / user might want a repaint in + /// next 500 milliseconds. Now, app takes 1000 ms per frame (1 fps) because the backend event + /// timeout takes 500 milli seconds AFTER the vsync swap buffer. + /// So, its not that we are requesting repaint within X duration. We are rather timing out + /// during app idle time where we are not receiving any new input events. pub fn request_repaint_after(&self, duration: std::time::Duration) { - // maybe we can check if duration is ZERO, and call self.request_repaint()? + // Maybe we can check if duration is ZERO, and call self.request_repaint()? let mut ctx = self.write(); ctx.repaint_after = ctx.repaint_after.min(duration); } diff --git a/egui_demo_app/src/backend_panel.rs b/egui_demo_app/src/backend_panel.rs index 49b4f210be2..854f24ad01b 100644 --- a/egui_demo_app/src/backend_panel.rs +++ b/egui_demo_app/src/backend_panel.rs @@ -245,13 +245,13 @@ impl BackendPanel { ui.label("Only running UI code when there are animations or input."); ui.label("but if there's no input for the repaint_after duration, we force an update"); ui.label("repaint_after (in seconds)"); - let mut milli_seconds = self.repaint_after_timeout.as_secs_f32(); - if egui::DragValue::new(&mut milli_seconds) + let mut seconds = self.repaint_after_timeout.as_secs_f32(); + if egui::DragValue::new(&mut seconds) .clamp_range(0.1..=10.0) .ui(ui) .changed() { - self.repaint_after_timeout = std::time::Duration::from_secs_f32(milli_seconds); + self.repaint_after_timeout = std::time::Duration::from_secs_f32(seconds); } } } diff --git a/egui_glium/examples/native_texture.rs b/egui_glium/examples/native_texture.rs index d0ffa4876ac..5784975f7af 100644 --- a/egui_glium/examples/native_texture.rs +++ b/egui_glium/examples/native_texture.rs @@ -1,6 +1,7 @@ #![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] // hide console window on Windows in release use glium::glutin; +use egui_winit::winit; fn main() { let event_loop = glutin::event_loop::EventLoop::with_user_event(); @@ -89,6 +90,11 @@ fn main() { display.gl_window().window().request_redraw(); // TODO(emilk): ask egui if the events warrants a repaint instead } + glutin::event::Event::NewEvents(glutin::event::StartCause::ResumeTimeReached { + .. + }) => { + window.request_redraw(); + } _ => (), } diff --git a/egui_glium/examples/pure_glium.rs b/egui_glium/examples/pure_glium.rs index 5d6a7b7fa54..d910eb4e78b 100644 --- a/egui_glium/examples/pure_glium.rs +++ b/egui_glium/examples/pure_glium.rs @@ -70,7 +70,11 @@ fn main() { display.gl_window().window().request_redraw(); // TODO(emilk): ask egui if the events warrants a repaint instead } - + glutin::event::Event::NewEvents(glutin::event::StartCause::ResumeTimeReached { + .. + }) => { + window.request_redraw(); + } _ => (), } }); diff --git a/egui_glow/examples/pure_glow.rs b/egui_glow/examples/pure_glow.rs index 2b421fd936a..9fa6c3814ec 100644 --- a/egui_glow/examples/pure_glow.rs +++ b/egui_glow/examples/pure_glow.rs @@ -3,6 +3,8 @@ #![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] // hide console window on Windows in release #![allow(unsafe_code)] +use web_sys::window; + fn main() { let mut clear_color = [0.1, 0.1, 0.1]; @@ -86,6 +88,11 @@ fn main() { glutin::event::Event::LoopDestroyed => { egui_glow.destroy(); } + glutin::event::Event::NewEvents(glutin::event::StartCause::ResumeTimeReached { + .. + }) => { + gl_window..window().request_redraw(); + } _ => (), } diff --git a/egui_glow/src/winit.rs b/egui_glow/src/winit.rs index b75e1431b60..786cb18a43c 100644 --- a/egui_glow/src/winit.rs +++ b/egui_glow/src/winit.rs @@ -41,7 +41,7 @@ impl EguiGlow { self.egui_winit.on_event(&self.egui_ctx, event) } - /// Returns `true` if egui requests a repaint. + /// Returns the `Duration` of the timeout after which egui should be repainted even if there's no new events. /// /// Call [`Self::paint`] later to paint. pub fn run( From 1229a707d88a1be254da15c04c9c135be25fed4e Mon Sep 17 00:00:00 2001 From: Red Artist Date: Tue, 21 Jun 2022 01:37:21 +0530 Subject: [PATCH 12/18] fmt --- eframe/src/native/run.rs | 2 +- egui_glium/examples/native_texture.rs | 4 ++-- egui_glium/examples/pure_glium.rs | 4 ++-- egui_glow/examples/pure_glow.rs | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/eframe/src/native/run.rs b/eframe/src/native/run.rs index 579489e3c62..fbfceb0afe5 100644 --- a/eframe/src/native/run.rs +++ b/eframe/src/native/run.rs @@ -399,7 +399,7 @@ pub fn run_wgpu( } winit::event::Event::UserEvent(RequestRepaintEvent) => window.request_redraw(), winit::event::Event::NewEvents(winit::event::StartCause::ResumeTimeReached { - .. + .. }) => { window.request_redraw(); } diff --git a/egui_glium/examples/native_texture.rs b/egui_glium/examples/native_texture.rs index 5784975f7af..0b5f6855fbb 100644 --- a/egui_glium/examples/native_texture.rs +++ b/egui_glium/examples/native_texture.rs @@ -1,7 +1,7 @@ #![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] // hide console window on Windows in release -use glium::glutin; use egui_winit::winit; +use glium::glutin; fn main() { let event_loop = glutin::event_loop::EventLoop::with_user_event(); @@ -91,7 +91,7 @@ fn main() { display.gl_window().window().request_redraw(); // TODO(emilk): ask egui if the events warrants a repaint instead } glutin::event::Event::NewEvents(glutin::event::StartCause::ResumeTimeReached { - .. + .. }) => { window.request_redraw(); } diff --git a/egui_glium/examples/pure_glium.rs b/egui_glium/examples/pure_glium.rs index d910eb4e78b..3e608248ed8 100644 --- a/egui_glium/examples/pure_glium.rs +++ b/egui_glium/examples/pure_glium.rs @@ -71,8 +71,8 @@ fn main() { display.gl_window().window().request_redraw(); // TODO(emilk): ask egui if the events warrants a repaint instead } glutin::event::Event::NewEvents(glutin::event::StartCause::ResumeTimeReached { - .. - }) => { + .. + }) => { window.request_redraw(); } _ => (), diff --git a/egui_glow/examples/pure_glow.rs b/egui_glow/examples/pure_glow.rs index 9fa6c3814ec..9051300556f 100644 --- a/egui_glow/examples/pure_glow.rs +++ b/egui_glow/examples/pure_glow.rs @@ -89,8 +89,8 @@ fn main() { egui_glow.destroy(); } glutin::event::Event::NewEvents(glutin::event::StartCause::ResumeTimeReached { - .. - }) => { + .. + }) => { gl_window..window().request_redraw(); } From c4e3190a809ebba47a1b2f437c0406cfaa29cdf7 Mon Sep 17 00:00:00 2001 From: Red Artist Date: Tue, 21 Jun 2022 01:48:00 +0530 Subject: [PATCH 13/18] fix clippy fail --- egui_glium/examples/pure_glium.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/egui_glium/examples/pure_glium.rs b/egui_glium/examples/pure_glium.rs index 3e608248ed8..778f4aabb0f 100644 --- a/egui_glium/examples/pure_glium.rs +++ b/egui_glium/examples/pure_glium.rs @@ -73,7 +73,7 @@ fn main() { glutin::event::Event::NewEvents(glutin::event::StartCause::ResumeTimeReached { .. }) => { - window.request_redraw(); + display.gl_window().window().request_redraw(); } _ => (), } From c1b3486e14d66765080f157c144836118a5dc83d Mon Sep 17 00:00:00 2001 From: Red Artist Date: Tue, 21 Jun 2022 01:50:35 +0530 Subject: [PATCH 14/18] fix clippy glow --- egui_glow/examples/pure_glow.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/egui_glow/examples/pure_glow.rs b/egui_glow/examples/pure_glow.rs index 9051300556f..287db57a9c0 100644 --- a/egui_glow/examples/pure_glow.rs +++ b/egui_glow/examples/pure_glow.rs @@ -3,8 +3,6 @@ #![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] // hide console window on Windows in release #![allow(unsafe_code)] -use web_sys::window; - fn main() { let mut clear_color = [0.1, 0.1, 0.1]; @@ -54,7 +52,7 @@ fn main() { // draw things on top of egui here - gl_window.swap_buffers().unwrap(); + gl_window.window().swap_buffers().unwrap(); } }; From 4e8c0314297aba5fe21aded3e50f7184211ebb7e Mon Sep 17 00:00:00 2001 From: Red Artist Date: Tue, 21 Jun 2022 11:01:44 +0530 Subject: [PATCH 15/18] fix more clippy glow --- egui_glium/examples/native_texture.rs | 2 +- egui_glow/examples/pure_glow.rs | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/egui_glium/examples/native_texture.rs b/egui_glium/examples/native_texture.rs index 0b5f6855fbb..217c608d5e4 100644 --- a/egui_glium/examples/native_texture.rs +++ b/egui_glium/examples/native_texture.rs @@ -93,7 +93,7 @@ fn main() { glutin::event::Event::NewEvents(glutin::event::StartCause::ResumeTimeReached { .. }) => { - window.request_redraw(); + display.gl_window().window().request_redraw(); } _ => (), diff --git a/egui_glow/examples/pure_glow.rs b/egui_glow/examples/pure_glow.rs index 287db57a9c0..93b33e2461d 100644 --- a/egui_glow/examples/pure_glow.rs +++ b/egui_glow/examples/pure_glow.rs @@ -3,6 +3,8 @@ #![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] // hide console window on Windows in release #![allow(unsafe_code)] +use web_sys::window; + fn main() { let mut clear_color = [0.1, 0.1, 0.1]; @@ -52,7 +54,7 @@ fn main() { // draw things on top of egui here - gl_window.window().swap_buffers().unwrap(); + gl_window.swap_buffers().unwrap(); } }; @@ -89,7 +91,7 @@ fn main() { glutin::event::Event::NewEvents(glutin::event::StartCause::ResumeTimeReached { .. }) => { - gl_window..window().request_redraw(); + gl_window.window().request_redraw(); } _ => (), From a4e0029400be5b4bfc376adefa2088386fabe15e Mon Sep 17 00:00:00 2001 From: Red Artist Date: Tue, 21 Jun 2022 11:01:44 +0530 Subject: [PATCH 16/18] fix more clippy glow --- egui_glium/examples/native_texture.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/egui_glium/examples/native_texture.rs b/egui_glium/examples/native_texture.rs index 217c608d5e4..ae09ae9d14d 100644 --- a/egui_glium/examples/native_texture.rs +++ b/egui_glium/examples/native_texture.rs @@ -1,6 +1,5 @@ #![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] // hide console window on Windows in release -use egui_winit::winit; use glium::glutin; fn main() { From b31e11b20b594cb16a314b4d87e0d4d401baf7a9 Mon Sep 17 00:00:00 2001 From: Red Artist Date: Tue, 21 Jun 2022 11:01:44 +0530 Subject: [PATCH 17/18] fix more clippy glow --- egui_glow/examples/pure_glow.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/egui_glow/examples/pure_glow.rs b/egui_glow/examples/pure_glow.rs index 93b33e2461d..1e10cb1dbe4 100644 --- a/egui_glow/examples/pure_glow.rs +++ b/egui_glow/examples/pure_glow.rs @@ -3,8 +3,6 @@ #![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] // hide console window on Windows in release #![allow(unsafe_code)] -use web_sys::window; - fn main() { let mut clear_color = [0.1, 0.1, 0.1]; From 698cab03285aa36bf405a3327a501bcccb81aaee Mon Sep 17 00:00:00 2001 From: Red Artist Date: Tue, 21 Jun 2022 11:44:08 +0530 Subject: [PATCH 18/18] add TODO to impl this in web --- eframe/src/web/events.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/eframe/src/web/events.rs b/eframe/src/web/events.rs index bc260b181da..be679588cc7 100644 --- a/eframe/src/web/events.rs +++ b/eframe/src/web/events.rs @@ -14,6 +14,7 @@ pub fn paint_and_schedule( if repaint_after.is_zero() { runner_lock.needs_repaint.set_true(); } + // TODO: schedule a repaint after `repaint_after` when it is not zero runner_lock.auto_save(); }