mirror of
https://github.com/emilk/egui.git
synced 2026-08-31 22:00:03 -04:00
request_repaint_after also fires the request_repaint callback
This commit is contained in:
@@ -19,7 +19,12 @@ use super::epi_integration::{self, EpiIntegration};
|
|||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum UserEvent {
|
pub enum UserEvent {
|
||||||
RequestRepaint,
|
RequestRepaint {
|
||||||
|
when: Instant,
|
||||||
|
/// What the frame number was when the repaint was _requested_.
|
||||||
|
frame_nr: u64,
|
||||||
|
},
|
||||||
|
|
||||||
#[cfg(feature = "accesskit")]
|
#[cfg(feature = "accesskit")]
|
||||||
AccessKitActionRequest(accesskit_winit::ActionRequestEvent),
|
AccessKitActionRequest(accesskit_winit::ActionRequestEvent),
|
||||||
}
|
}
|
||||||
@@ -58,6 +63,9 @@ enum EventResult {
|
|||||||
}
|
}
|
||||||
|
|
||||||
trait WinitApp {
|
trait WinitApp {
|
||||||
|
/// The current frame number, as reported by egui.
|
||||||
|
fn frame_nr(&self) -> u64;
|
||||||
|
|
||||||
fn is_focused(&self) -> bool;
|
fn is_focused(&self) -> bool;
|
||||||
|
|
||||||
fn integration(&self) -> Option<&EpiIntegration>;
|
fn integration(&self) -> Option<&EpiIntegration>;
|
||||||
@@ -66,7 +74,7 @@ trait WinitApp {
|
|||||||
|
|
||||||
fn save_and_destroy(&mut self);
|
fn save_and_destroy(&mut self);
|
||||||
|
|
||||||
fn paint(&mut self) -> EventResult;
|
fn run_ui_and_paint(&mut self) -> EventResult;
|
||||||
|
|
||||||
fn on_event(
|
fn on_event(
|
||||||
&mut self,
|
&mut self,
|
||||||
@@ -137,17 +145,26 @@ fn run_and_return(
|
|||||||
// See: https://github.com/rust-windowing/winit/issues/1619
|
// See: https://github.com/rust-windowing/winit/issues/1619
|
||||||
winit::event::Event::RedrawEventsCleared if cfg!(windows) => {
|
winit::event::Event::RedrawEventsCleared if cfg!(windows) => {
|
||||||
next_repaint_time = Instant::now() + Duration::from_secs(1_000_000_000);
|
next_repaint_time = Instant::now() + Duration::from_secs(1_000_000_000);
|
||||||
winit_app.paint()
|
winit_app.run_ui_and_paint()
|
||||||
}
|
}
|
||||||
winit::event::Event::RedrawRequested(_) if !cfg!(windows) => {
|
winit::event::Event::RedrawRequested(_) if !cfg!(windows) => {
|
||||||
next_repaint_time = Instant::now() + Duration::from_secs(1_000_000_000);
|
next_repaint_time = Instant::now() + Duration::from_secs(1_000_000_000);
|
||||||
winit_app.paint()
|
winit_app.run_ui_and_paint()
|
||||||
}
|
}
|
||||||
|
|
||||||
winit::event::Event::UserEvent(UserEvent::RequestRepaint)
|
winit::event::Event::UserEvent(UserEvent::RequestRepaint { when, frame_nr }) => {
|
||||||
| winit::event::Event::NewEvents(winit::event::StartCause::ResumeTimeReached {
|
if winit_app.frame_nr() == *frame_nr {
|
||||||
|
log::trace!("UserEvent::RequestRepaint scheduling repaint at {when:?}");
|
||||||
|
EventResult::RepaintAt(*when)
|
||||||
|
} else {
|
||||||
|
log::trace!("Got outdated UserEvent::RequestRepaint");
|
||||||
|
EventResult::Wait // old request - we've already repainted
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
winit::event::Event::NewEvents(winit::event::StartCause::ResumeTimeReached {
|
||||||
..
|
..
|
||||||
}) => EventResult::RepaintNext,
|
}) => EventResult::Wait, // We just woke up to check next_repaint_time
|
||||||
|
|
||||||
winit::event::Event::WindowEvent { window_id, .. }
|
winit::event::Event::WindowEvent { window_id, .. }
|
||||||
if winit_app.window().is_none()
|
if winit_app.window().is_none()
|
||||||
@@ -175,7 +192,7 @@ fn run_and_return(
|
|||||||
if cfg!(windows) {
|
if cfg!(windows) {
|
||||||
// Fix flickering on Windows, see https://github.com/emilk/egui/pull/2280
|
// Fix flickering on Windows, see https://github.com/emilk/egui/pull/2280
|
||||||
next_repaint_time = Instant::now() + Duration::from_secs(1_000_000_000);
|
next_repaint_time = Instant::now() + Duration::from_secs(1_000_000_000);
|
||||||
winit_app.paint();
|
winit_app.run_ui_and_paint();
|
||||||
} else {
|
} else {
|
||||||
// Fix for https://github.com/emilk/egui/issues/2425
|
// Fix for https://github.com/emilk/egui/issues/2425
|
||||||
next_repaint_time = Instant::now();
|
next_repaint_time = Instant::now();
|
||||||
@@ -196,18 +213,16 @@ fn run_and_return(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
*control_flow = match next_repaint_time.checked_duration_since(Instant::now()) {
|
*control_flow = if next_repaint_time <= Instant::now() {
|
||||||
None => {
|
if let Some(window) = winit_app.window() {
|
||||||
if let Some(window) = winit_app.window() {
|
log::trace!("request_redraw");
|
||||||
window.request_redraw();
|
window.request_redraw();
|
||||||
}
|
|
||||||
next_repaint_time = Instant::now() + Duration::from_secs(1_000_000_000);
|
|
||||||
ControlFlow::Poll
|
|
||||||
}
|
}
|
||||||
Some(time_until_next_repaint) => {
|
next_repaint_time = Instant::now() + Duration::from_secs(1_000_000_000);
|
||||||
ControlFlow::WaitUntil(Instant::now() + time_until_next_repaint)
|
ControlFlow::Poll
|
||||||
}
|
} else {
|
||||||
}
|
ControlFlow::WaitUntil(next_repaint_time)
|
||||||
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
log::debug!("eframe window closed");
|
log::debug!("eframe window closed");
|
||||||
@@ -240,17 +255,24 @@ fn run_and_exit(event_loop: EventLoop<UserEvent>, mut winit_app: impl WinitApp +
|
|||||||
// See: https://github.com/rust-windowing/winit/issues/1619
|
// See: https://github.com/rust-windowing/winit/issues/1619
|
||||||
winit::event::Event::RedrawEventsCleared if cfg!(windows) => {
|
winit::event::Event::RedrawEventsCleared if cfg!(windows) => {
|
||||||
next_repaint_time = Instant::now() + Duration::from_secs(1_000_000_000);
|
next_repaint_time = Instant::now() + Duration::from_secs(1_000_000_000);
|
||||||
winit_app.paint()
|
winit_app.run_ui_and_paint()
|
||||||
}
|
}
|
||||||
winit::event::Event::RedrawRequested(_) if !cfg!(windows) => {
|
winit::event::Event::RedrawRequested(_) if !cfg!(windows) => {
|
||||||
next_repaint_time = Instant::now() + Duration::from_secs(1_000_000_000);
|
next_repaint_time = Instant::now() + Duration::from_secs(1_000_000_000);
|
||||||
winit_app.paint()
|
winit_app.run_ui_and_paint()
|
||||||
}
|
}
|
||||||
|
|
||||||
winit::event::Event::UserEvent(UserEvent::RequestRepaint)
|
winit::event::Event::UserEvent(UserEvent::RequestRepaint { when, frame_nr }) => {
|
||||||
| winit::event::Event::NewEvents(winit::event::StartCause::ResumeTimeReached {
|
if winit_app.frame_nr() == frame_nr {
|
||||||
|
EventResult::RepaintAt(when)
|
||||||
|
} else {
|
||||||
|
EventResult::Wait // old request - we've already repainted
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
winit::event::Event::NewEvents(winit::event::StartCause::ResumeTimeReached {
|
||||||
..
|
..
|
||||||
}) => EventResult::RepaintNext,
|
}) => EventResult::Wait, // We just woke up to check next_repaint_time
|
||||||
|
|
||||||
event => match winit_app.on_event(event_loop, &event) {
|
event => match winit_app.on_event(event_loop, &event) {
|
||||||
Ok(event_result) => event_result,
|
Ok(event_result) => event_result,
|
||||||
@@ -266,7 +288,7 @@ fn run_and_exit(event_loop: EventLoop<UserEvent>, mut winit_app: impl WinitApp +
|
|||||||
if cfg!(windows) {
|
if cfg!(windows) {
|
||||||
// Fix flickering on Windows, see https://github.com/emilk/egui/pull/2280
|
// Fix flickering on Windows, see https://github.com/emilk/egui/pull/2280
|
||||||
next_repaint_time = Instant::now() + Duration::from_secs(1_000_000_000);
|
next_repaint_time = Instant::now() + Duration::from_secs(1_000_000_000);
|
||||||
winit_app.paint();
|
winit_app.run_ui_and_paint();
|
||||||
} else {
|
} else {
|
||||||
// Fix for https://github.com/emilk/egui/issues/2425
|
// Fix for https://github.com/emilk/egui/issues/2425
|
||||||
next_repaint_time = Instant::now();
|
next_repaint_time = Instant::now();
|
||||||
@@ -286,17 +308,15 @@ fn run_and_exit(event_loop: EventLoop<UserEvent>, mut winit_app: impl WinitApp +
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
*control_flow = match next_repaint_time.checked_duration_since(Instant::now()) {
|
*control_flow = if next_repaint_time <= Instant::now() {
|
||||||
None => {
|
if let Some(window) = winit_app.window() {
|
||||||
if let Some(window) = winit_app.window() {
|
window.request_redraw();
|
||||||
window.request_redraw();
|
|
||||||
}
|
|
||||||
ControlFlow::Poll
|
|
||||||
}
|
}
|
||||||
Some(time_until_next_repaint) => {
|
next_repaint_time = Instant::now() + Duration::from_secs(1_000_000_000);
|
||||||
ControlFlow::WaitUntil(Instant::now() + time_until_next_repaint)
|
ControlFlow::Poll
|
||||||
}
|
} else {
|
||||||
}
|
ControlFlow::WaitUntil(next_repaint_time)
|
||||||
|
};
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -601,8 +621,6 @@ mod glow_integration {
|
|||||||
// suspends and resumes.
|
// suspends and resumes.
|
||||||
app_creator: Option<epi::AppCreator>,
|
app_creator: Option<epi::AppCreator>,
|
||||||
is_focused: bool,
|
is_focused: bool,
|
||||||
|
|
||||||
frame_nr: u64,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GlowWinitApp {
|
impl GlowWinitApp {
|
||||||
@@ -619,7 +637,6 @@ mod glow_integration {
|
|||||||
running: None,
|
running: None,
|
||||||
app_creator: Some(app_creator),
|
app_creator: Some(app_creator),
|
||||||
is_focused: true,
|
is_focused: true,
|
||||||
frame_nr: 0,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -698,12 +715,17 @@ mod glow_integration {
|
|||||||
|
|
||||||
{
|
{
|
||||||
let event_loop_proxy = self.repaint_proxy.clone();
|
let event_loop_proxy = self.repaint_proxy.clone();
|
||||||
integration.egui_ctx.set_request_repaint_callback(move || {
|
integration
|
||||||
event_loop_proxy
|
.egui_ctx
|
||||||
.lock()
|
.set_request_repaint_callback(move |info| {
|
||||||
.send_event(UserEvent::RequestRepaint)
|
log::trace!("request_repaint_callback: {info:?}");
|
||||||
.ok();
|
let when = Instant::now() + info.after;
|
||||||
});
|
let frame_nr = info.current_frame_nr;
|
||||||
|
event_loop_proxy
|
||||||
|
.lock()
|
||||||
|
.send_event(UserEvent::RequestRepaint { when, frame_nr })
|
||||||
|
.ok();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
let app_creator = std::mem::take(&mut self.app_creator)
|
let app_creator = std::mem::take(&mut self.app_creator)
|
||||||
@@ -734,6 +756,12 @@ mod glow_integration {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl WinitApp for GlowWinitApp {
|
impl WinitApp for GlowWinitApp {
|
||||||
|
fn frame_nr(&self) -> u64 {
|
||||||
|
self.running
|
||||||
|
.as_ref()
|
||||||
|
.map_or(0, |r| r.integration.egui_ctx.frame_nr())
|
||||||
|
}
|
||||||
|
|
||||||
fn is_focused(&self) -> bool {
|
fn is_focused(&self) -> bool {
|
||||||
self.is_focused
|
self.is_focused
|
||||||
}
|
}
|
||||||
@@ -756,7 +784,7 @@ mod glow_integration {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn paint(&mut self) -> EventResult {
|
fn run_ui_and_paint(&mut self) -> EventResult {
|
||||||
if let Some(running) = &mut self.running {
|
if let Some(running) = &mut self.running {
|
||||||
#[cfg(feature = "puffin")]
|
#[cfg(feature = "puffin")]
|
||||||
puffin::GlobalProfiler::lock().new_frame();
|
puffin::GlobalProfiler::lock().new_frame();
|
||||||
@@ -820,7 +848,7 @@ mod glow_integration {
|
|||||||
|
|
||||||
#[cfg(feature = "__screenshot")]
|
#[cfg(feature = "__screenshot")]
|
||||||
// give it time to settle:
|
// give it time to settle:
|
||||||
if self.frame_nr == 2 {
|
if integration.egui_ctx.frame_nr() == 2 {
|
||||||
if let Ok(path) = std::env::var("EFRAME_SCREENSHOT_TO") {
|
if let Ok(path) = std::env::var("EFRAME_SCREENSHOT_TO") {
|
||||||
assert!(
|
assert!(
|
||||||
path.ends_with(".png"),
|
path.ends_with(".png"),
|
||||||
@@ -871,8 +899,6 @@ mod glow_integration {
|
|||||||
std::thread::sleep(std::time::Duration::from_millis(10));
|
std::thread::sleep(std::time::Duration::from_millis(10));
|
||||||
}
|
}
|
||||||
|
|
||||||
self.frame_nr += 1;
|
|
||||||
|
|
||||||
control_flow
|
control_flow
|
||||||
} else {
|
} else {
|
||||||
EventResult::Wait
|
EventResult::Wait
|
||||||
@@ -1150,13 +1176,18 @@ mod wgpu_integration {
|
|||||||
|
|
||||||
{
|
{
|
||||||
let event_loop_proxy = self.repaint_proxy.clone();
|
let event_loop_proxy = self.repaint_proxy.clone();
|
||||||
integration.egui_ctx.set_request_repaint_callback(move || {
|
integration
|
||||||
event_loop_proxy
|
.egui_ctx
|
||||||
.lock()
|
.set_request_repaint_callback(move |info| {
|
||||||
.unwrap()
|
log::trace!("request_repaint_callback: {info:?}");
|
||||||
.send_event(UserEvent::RequestRepaint)
|
let when = Instant::now() + info.after;
|
||||||
.ok();
|
let frame_nr = info.current_frame_nr;
|
||||||
});
|
event_loop_proxy
|
||||||
|
.lock()
|
||||||
|
.unwrap()
|
||||||
|
.send_event(UserEvent::RequestRepaint { when, frame_nr })
|
||||||
|
.ok();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
let app_creator = std::mem::take(&mut self.app_creator)
|
let app_creator = std::mem::take(&mut self.app_creator)
|
||||||
@@ -1186,6 +1217,12 @@ mod wgpu_integration {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl WinitApp for WgpuWinitApp {
|
impl WinitApp for WgpuWinitApp {
|
||||||
|
fn frame_nr(&self) -> u64 {
|
||||||
|
self.running
|
||||||
|
.as_ref()
|
||||||
|
.map_or(0, |r| r.integration.egui_ctx.frame_nr())
|
||||||
|
}
|
||||||
|
|
||||||
fn is_focused(&self) -> bool {
|
fn is_focused(&self) -> bool {
|
||||||
self.is_focused
|
self.is_focused
|
||||||
}
|
}
|
||||||
@@ -1214,7 +1251,7 @@ mod wgpu_integration {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn paint(&mut self) -> EventResult {
|
fn run_ui_and_paint(&mut self) -> EventResult {
|
||||||
if let (Some(running), Some(window)) = (&mut self.running, &self.window) {
|
if let (Some(running), Some(window)) = (&mut self.running, &self.window) {
|
||||||
#[cfg(feature = "puffin")]
|
#[cfg(feature = "puffin")]
|
||||||
puffin::GlobalProfiler::lock().new_frame();
|
puffin::GlobalProfiler::lock().new_frame();
|
||||||
|
|||||||
@@ -8,6 +8,21 @@ use crate::{
|
|||||||
};
|
};
|
||||||
use epaint::{mutex::*, stats::*, text::Fonts, TessellationOptions, *};
|
use epaint::{mutex::*, stats::*, text::Fonts, TessellationOptions, *};
|
||||||
|
|
||||||
|
/// Information given to the backend about when it is time to repaint the ui.
|
||||||
|
///
|
||||||
|
/// This is given in the callback set by [`Context::set_request_repaint_callback`].
|
||||||
|
#[derive(Clone, Copy, Debug)]
|
||||||
|
pub struct RequestRepaintInfo {
|
||||||
|
/// Repaint after this duration. If zero, repaint as soon as possible.
|
||||||
|
pub after: std::time::Duration,
|
||||||
|
|
||||||
|
/// The curent frame number.
|
||||||
|
///
|
||||||
|
/// This can be compared to [`Context::frame_nr`] to see if we've already
|
||||||
|
/// triggered the painting of the next frame.
|
||||||
|
pub current_frame_nr: u64,
|
||||||
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
struct WrappedTextureManager(Arc<RwLock<epaint::TextureManager>>);
|
struct WrappedTextureManager(Arc<RwLock<epaint::TextureManager>>);
|
||||||
@@ -32,16 +47,20 @@ impl Default for WrappedTextureManager {
|
|||||||
|
|
||||||
/// Logic related to repainting the ui.
|
/// Logic related to repainting the ui.
|
||||||
struct Repaint {
|
struct Repaint {
|
||||||
/// the duration backend will poll for new events, before forcing another egui update
|
/// The current frame number.
|
||||||
|
///
|
||||||
|
/// Incremented at the end of each frame.
|
||||||
|
frame_nr: u64,
|
||||||
|
|
||||||
|
/// The duration backend will poll for new events, before forcing another egui update
|
||||||
/// even if there's no new events.
|
/// even if there's no new events.
|
||||||
|
///
|
||||||
|
/// Also used to suppress multiple calls to the repaint callback during the same frame.
|
||||||
repaint_after: std::time::Duration,
|
repaint_after: std::time::Duration,
|
||||||
|
|
||||||
/// While positive, keep requesting repaints. Decrement at the end of each frame.
|
/// While positive, keep requesting repaints. Decrement at the end of each frame.
|
||||||
repaint_requests: u32,
|
repaint_requests: u32,
|
||||||
request_repaint_callback: Option<Box<dyn Fn() + Send + Sync>>,
|
request_repaint_callback: Option<Box<dyn Fn(RequestRepaintInfo) + Send + Sync>>,
|
||||||
|
|
||||||
/// used to suppress multiple calls to [`Self::request_repaint_callback`] during the same frame.
|
|
||||||
has_requested_repaint_this_frame: bool,
|
|
||||||
|
|
||||||
requested_repaint_last_frame: bool,
|
requested_repaint_last_frame: bool,
|
||||||
}
|
}
|
||||||
@@ -49,12 +68,12 @@ struct Repaint {
|
|||||||
impl Default for Repaint {
|
impl Default for Repaint {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
frame_nr: 0,
|
||||||
repaint_after: std::time::Duration::from_millis(100),
|
repaint_after: std::time::Duration::from_millis(100),
|
||||||
// Start with painting an extra frame to compensate for some widgets
|
// Start with painting an extra frame to compensate for some widgets
|
||||||
// that take two frames before they "settle":
|
// that take two frames before they "settle":
|
||||||
repaint_requests: 1,
|
repaint_requests: 1,
|
||||||
request_repaint_callback: None,
|
request_repaint_callback: None,
|
||||||
has_requested_repaint_this_frame: false,
|
|
||||||
requested_repaint_last_frame: false,
|
requested_repaint_last_frame: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -62,18 +81,33 @@ impl Default for Repaint {
|
|||||||
|
|
||||||
impl Repaint {
|
impl Repaint {
|
||||||
fn request_repaint(&mut self) {
|
fn request_repaint(&mut self) {
|
||||||
self.repaint_requests = 2;
|
self.request_repaint_after(std::time::Duration::ZERO);
|
||||||
if let Some(callback) = &self.request_repaint_callback {
|
}
|
||||||
if !self.has_requested_repaint_this_frame {
|
|
||||||
(callback)();
|
fn request_repaint_after(&mut self, after: std::time::Duration) {
|
||||||
self.has_requested_repaint_this_frame = true;
|
if after == std::time::Duration::ZERO {
|
||||||
|
// Do a few extra frames to let things settle.
|
||||||
|
// This is a bit of a hack, and we don't support it for `repaint_after` callbacks yet.
|
||||||
|
self.repaint_requests = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We only re-call the callback if we get a lower duration,
|
||||||
|
// otherwise it's already been covered by the previous callback.
|
||||||
|
if after < self.repaint_after {
|
||||||
|
self.repaint_after = after;
|
||||||
|
|
||||||
|
if let Some(callback) = &self.request_repaint_callback {
|
||||||
|
let info = RequestRepaintInfo {
|
||||||
|
after,
|
||||||
|
current_frame_nr: self.frame_nr,
|
||||||
|
};
|
||||||
|
(callback)(info);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn request_repaint_after(&mut self, duration: std::time::Duration) {
|
#[allow(clippy::unused_self)]
|
||||||
self.repaint_after = self.repaint_after.min(duration);
|
fn start_frame(&mut self) {}
|
||||||
}
|
|
||||||
|
|
||||||
// returns how long to wait until repaint
|
// returns how long to wait until repaint
|
||||||
fn end_frame(&mut self) -> std::time::Duration {
|
fn end_frame(&mut self) -> std::time::Duration {
|
||||||
@@ -88,7 +122,6 @@ impl Repaint {
|
|||||||
self.repaint_after = std::time::Duration::MAX;
|
self.repaint_after = std::time::Duration::MAX;
|
||||||
|
|
||||||
self.requested_repaint_last_frame = repaint_after.is_zero();
|
self.requested_repaint_last_frame = repaint_after.is_zero();
|
||||||
self.has_requested_repaint_this_frame = false; // allow new calls between frames
|
|
||||||
|
|
||||||
repaint_after
|
repaint_after
|
||||||
}
|
}
|
||||||
@@ -133,7 +166,7 @@ struct ContextImpl {
|
|||||||
|
|
||||||
impl ContextImpl {
|
impl ContextImpl {
|
||||||
fn begin_frame_mut(&mut self, mut new_raw_input: RawInput) {
|
fn begin_frame_mut(&mut self, mut new_raw_input: RawInput) {
|
||||||
self.repaint.has_requested_repaint_this_frame = false; // allow new calls during the frame
|
self.repaint.start_frame();
|
||||||
|
|
||||||
if let Some(new_pixels_per_point) = self.memory.new_pixels_per_point.take() {
|
if let Some(new_pixels_per_point) = self.memory.new_pixels_per_point.take() {
|
||||||
new_raw_input.pixels_per_point = Some(new_pixels_per_point);
|
new_raw_input.pixels_per_point = Some(new_pixels_per_point);
|
||||||
@@ -901,6 +934,15 @@ impl Context {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 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(&self) -> u64 {
|
||||||
|
self.read(|ctx| ctx.repaint.frame_nr)
|
||||||
|
}
|
||||||
|
|
||||||
/// Call this if there is need to repaint the UI, i.e. if you are showing an animation.
|
/// Call this if there is need to repaint the UI, i.e. if you are showing an animation.
|
||||||
///
|
///
|
||||||
/// If this is called at least once in a frame, then there will be another frame right after this.
|
/// If this is called at least once in a frame, then there will be another frame right after this.
|
||||||
@@ -951,7 +993,10 @@ impl Context {
|
|||||||
/// This lets you wake up a sleeping UI thread.
|
/// This lets you wake up a sleeping UI thread.
|
||||||
///
|
///
|
||||||
/// Note that only one callback can be set. Any new call overrides the previous callback.
|
/// Note that only one callback can be set. Any new call overrides the previous callback.
|
||||||
pub fn set_request_repaint_callback(&self, callback: impl Fn() + Send + Sync + 'static) {
|
pub fn set_request_repaint_callback(
|
||||||
|
&self,
|
||||||
|
callback: impl Fn(RequestRepaintInfo) + Send + Sync + 'static,
|
||||||
|
) {
|
||||||
let callback = Box::new(callback);
|
let callback = Box::new(callback);
|
||||||
self.write(|ctx| ctx.repaint.request_repaint_callback = Some(callback));
|
self.write(|ctx| ctx.repaint.request_repaint_callback = Some(callback));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -354,7 +354,7 @@ pub mod text {
|
|||||||
|
|
||||||
pub use {
|
pub use {
|
||||||
containers::*,
|
containers::*,
|
||||||
context::Context,
|
context::{Context, RequestRepaintInfo},
|
||||||
data::{
|
data::{
|
||||||
input::*,
|
input::*,
|
||||||
output::{self, CursorIcon, FullOutput, PlatformOutput, UserAttentionType, WidgetInfo},
|
output::{self, CursorIcon, FullOutput, PlatformOutput, UserAttentionType, WidgetInfo},
|
||||||
|
|||||||
Reference in New Issue
Block a user