1
0
mirror of https://github.com/emilk/egui.git synced 2026-06-27 15:13:12 -04:00
* now every viewport has his own frame_nr

eframe:
* some refactoring
* now on Windows spinner will make the async viewport refresh, this problem was only for async viewport in Windows

* problem found there are two redraw systems, one was broken now is fixed, the one that was broken on Linux X11 was not needed, but for Windows both are needed!
1: The egui repaint_callback system
2: The egui repaint_after from FullOutput
This commit is contained in:
Konkitoman
2023-10-18 18:47:16 +03:00
parent 701d31a887
commit b1e7fafe70
2 changed files with 48 additions and 54 deletions

View File

@@ -42,7 +42,7 @@ pub enum UserEvent {
/// A repaint is requested.
RequestRepaint {
/// What to repaint.
id: ViewportId,
viewport_id: ViewportId,
/// When to repaint.
when: Instant,
@@ -91,7 +91,7 @@ enum EventResult {
trait WinitApp {
/// The current frame number, as reported by egui.
fn frame_nr(&self) -> u64;
fn frame_nr(&self, viewport_id: ViewportId) -> u64;
fn is_focused(&self, window_id: winit::window::WindowId) -> bool;
@@ -187,16 +187,6 @@ fn run_and_return(
return;
}
// Platform-dependent event handlers to workaround a winit bug
// See: https://github.com/rust-windowing/winit/issues/987
// See: https://github.com/rust-windowing/winit/issues/1619
// #[cfg(target_os = "windows")]
// winit::event::Event::RedrawEventsCleared => {
// windows_next_repaint_times.clear();
// winit_app.run_ui_and_paint(None)
// vec![EventResult::Wait]
// }
// #[cfg(not(target_os = "windows"))]
winit::event::Event::RedrawRequested(window_id) => {
windows_next_repaint_times.remove(window_id);
winit_app.run_ui_and_paint(*window_id)
@@ -205,11 +195,11 @@ fn run_and_return(
winit::event::Event::UserEvent(UserEvent::RequestRepaint {
when,
frame_nr,
id: window_id,
viewport_id,
}) => {
if winit_app.frame_nr() == *frame_nr {
if winit_app.frame_nr(*viewport_id) == *frame_nr + 1 {
log::trace!("UserEvent::RequestRepaint scheduling repaint at {when:?}");
if let Some(window_id) = winit_app.get_window_winit_id(*window_id) {
if let Some(window_id) = winit_app.get_window_winit_id(*viewport_id) {
vec![EventResult::RepaintAt(window_id, *when)]
} else {
vec![EventResult::Wait]
@@ -287,13 +277,11 @@ fn run_and_return(
for (window_id, repaint_time) in &windows_next_repaint_times.clone() {
if *repaint_time <= Instant::now() {
if let Some(window) = winit_app.window(*window_id) {
log::trace!("request_redraw");
window.read().request_redraw();
windows_next_repaint_times.remove(window_id);
control_flow.set_poll();
} else {
windows_next_repaint_times.remove(window_id);
control_flow.set_wait();
}
windows_next_repaint_times.remove(window_id);
control_flow.set_poll();
} else {
next_repaint_time =
Some(next_repaint_time.map_or(*repaint_time, |last| last.min(*repaint_time)));
@@ -344,15 +332,7 @@ fn run_and_exit(event_loop: EventLoop<UserEvent>, mut winit_app: impl WinitApp +
vec![EventResult::Exit]
}
// Platform-dependent event handlers to workaround a winit bug
// See: https://github.com/rust-windowing/winit/issues/987
// See: https://github.com/rust-windowing/winit/issues/1619
winit::event::Event::RedrawEventsCleared if cfg!(target_os = "windows") => {
// windows_next_repaint_times.clear();
// winit_app.run_ui_and_paint(None)
vec![]
}
winit::event::Event::RedrawRequested(window_id) if !cfg!(target_os = "windows") => {
winit::event::Event::RedrawRequested(window_id) => {
windows_next_repaint_times.remove(&window_id);
winit_app.run_ui_and_paint(window_id)
}
@@ -360,10 +340,10 @@ fn run_and_exit(event_loop: EventLoop<UserEvent>, mut winit_app: impl WinitApp +
winit::event::Event::UserEvent(UserEvent::RequestRepaint {
when,
frame_nr,
id: window_id,
viewport_id,
}) => {
if winit_app.frame_nr() == frame_nr {
if let Some(window_id) = winit_app.get_window_winit_id(window_id) {
if winit_app.frame_nr(viewport_id) == frame_nr + 1 {
if let Some(window_id) = winit_app.get_window_winit_id(viewport_id) {
vec![EventResult::RepaintAt(window_id, when)]
} else {
vec![EventResult::Wait]
@@ -425,8 +405,8 @@ fn run_and_exit(event_loop: EventLoop<UserEvent>, mut winit_app: impl WinitApp +
if let Some(window) = winit_app.window(*window_id) {
log::trace!("request_redraw");
window.read().request_redraw();
windows_next_repaint_times.remove(window_id);
}
windows_next_repaint_times.remove(window_id);
control_flow.set_poll();
} else {
next_repaint_time =
@@ -1030,7 +1010,7 @@ mod glow_integration {
event_loop_proxy
.lock()
.send_event(UserEvent::RequestRepaint {
id: info.viewport_id,
viewport_id: info.viewport_id,
when,
frame_nr,
})
@@ -1303,11 +1283,10 @@ mod glow_integration {
}
impl WinitApp for GlowWinitApp {
fn frame_nr(&self) -> u64 {
self.running
.read()
.as_ref()
.map_or(0, |r| r.integration.read().egui_ctx.frame_nr())
fn frame_nr(&self, viewport_id: ViewportId) -> u64 {
self.running.read().as_ref().map_or(0, |r| {
r.integration.read().egui_ctx.frame_nr_for(viewport_id)
})
}
fn is_focused(&self, window_id: winit::window::WindowId) -> bool {
@@ -2073,7 +2052,7 @@ mod wgpu_integration {
.send_event(UserEvent::RequestRepaint {
when,
frame_nr,
id: info.viewport_id,
viewport_id: info.viewport_id,
})
.ok();
});
@@ -2249,10 +2228,10 @@ mod wgpu_integration {
}
impl WinitApp for WgpuWinitApp {
fn frame_nr(&self) -> u64 {
self.running
.as_ref()
.map_or(0, |r| r.integration.read().egui_ctx.frame_nr())
fn frame_nr(&self, viewport_id: ViewportId) -> u64 {
self.running.as_ref().map_or(0, |r| {
r.integration.read().egui_ctx.frame_nr_for(viewport_id)
})
}
fn is_focused(&self, window_id: winit::window::WindowId) -> bool {

View File

@@ -58,7 +58,7 @@ struct Repaint {
/// The current frame number.
///
/// Incremented at the end of each frame.
frame_nr: u64,
viewports_frame_nr: HashMap<ViewportId, u64>,
/// The duration backend will poll for new events, before forcing another egui update
/// even if there's no new events.
@@ -83,7 +83,7 @@ impl Default for Repaint {
let mut repaint_requests = HashMap::default();
repaint_requests.insert(ViewportId::MAIN, 1);
Self {
frame_nr: 0,
viewports_frame_nr: HashMap::default(),
repaint_after,
repaint_requests,
request_repaint_callback: None,
@@ -118,7 +118,7 @@ impl Repaint {
if let Some(callback) = &self.request_repaint_callback {
let info = RequestRepaintInfo {
after,
current_frame_nr: self.frame_nr,
current_frame_nr: *self.viewports_frame_nr.entry(viewport_id).or_default(),
viewport_id,
};
(callback)(info);
@@ -160,9 +160,11 @@ impl Repaint {
self.repaint_after.insert(viewport_id, repaint_after);
self.requested_repaint_last_frame = repaint_after.is_zero();
self.frame_nr += 1;
*self.viewports_frame_nr.entry(viewport_id).or_default() += 1;
self.repaint_after.retain(|id, _| viewports.contains(id));
self.viewports_frame_nr
.retain(|id, _| viewports.contains(id));
self.repaint_requests
.retain(|id, repaints| viewports.contains(id) && *repaints != 0);
@@ -1150,13 +1152,28 @@ impl Context {
}
}
/// The current frame number.
/// The current frame number for the current viewport.
///
/// Starts at zero, and is incremented at the end of [`Self::run`] or by [`Self::end_frame`].
///
/// Between calls to [`Self::run`], this is the frame number of the coming frame.
pub fn frame_nr(&self) -> u64 {
self.read(|ctx| ctx.repaint.frame_nr)
self.frame_nr_for(self.viewport_id())
}
/// The current frame number.
///
/// Starts at zero, and is incremented at the end of [`Self::run`] or by [`Self::end_frame`].
///
/// Between calls to [`Self::run`], this is the frame number of the coming frame.
pub fn frame_nr_for(&self, id: ViewportId) -> u64 {
self.read(|ctx| {
ctx.repaint
.viewports_frame_nr
.get(&id)
.copied()
.unwrap_or_default()
})
}
/// Call this if there is need to repaint the UI, i.e. if you are showing an animation.
@@ -1648,10 +1665,8 @@ impl Context {
});
}
let repaint_after = self.write(|ctx| {
ctx.repaint
.end_frame(ctx.viewport_id(), &avalibile_viewports)
});
let repaint_after =
self.write(|ctx| ctx.repaint.end_frame(viewport_id, &avalibile_viewports));
FullOutput {
platform_output,