mirror of
https://github.com/emilk/egui.git
synced 2026-08-29 04:40:03 -04:00
Add egui_inspection::Request::Settle (#8344)
This allows inspection clients to know if the app is in a settled state and/or run the app until it settles (similar to egui_kittests `run`/`run_ok`).
This commit is contained in:
@@ -56,6 +56,9 @@ enum Phase {
|
||||
/// A screenshot was dispatched with this `user_data` id; reply when the matching
|
||||
/// [`egui::Event::Screenshot`] arrives.
|
||||
AwaitScreenshot { id: u64 },
|
||||
|
||||
/// Watching for the app to go idle.
|
||||
Settle { steps_taken: u64, max_steps: u64 },
|
||||
}
|
||||
|
||||
struct InFlight {
|
||||
@@ -116,7 +119,12 @@ impl InspectionPlugin {
|
||||
/// While requests are still in flight, keep the UI loop spinning — reactive apps would
|
||||
/// otherwise go idle between hooks before a screenshot round-trips.
|
||||
fn maybe_repaint(&self, ctx: &Context) {
|
||||
if !self.in_flight.is_empty() {
|
||||
// Don't repaint if there's only a `Request::Settle`.
|
||||
if self
|
||||
.in_flight
|
||||
.iter()
|
||||
.any(|item| !matches!(item.req, Request::Settle { .. }))
|
||||
{
|
||||
ctx.request_repaint();
|
||||
}
|
||||
}
|
||||
@@ -236,6 +244,13 @@ impl egui::Plugin for InspectionPlugin {
|
||||
item.phase = Phase::AwaitScreenshot { id };
|
||||
true
|
||||
}
|
||||
Request::Settle { max_steps } => {
|
||||
item.phase = Phase::Settle {
|
||||
steps_taken: 0,
|
||||
max_steps: *max_steps,
|
||||
};
|
||||
true
|
||||
}
|
||||
}
|
||||
});
|
||||
self.next_screenshot_id = next_id;
|
||||
@@ -249,9 +264,14 @@ impl egui::Plugin for InspectionPlugin {
|
||||
return;
|
||||
}
|
||||
|
||||
let immediate_repaint = output
|
||||
.viewport_output
|
||||
.values()
|
||||
.any(|viewport| viewport.repaint_delay == Duration::ZERO);
|
||||
|
||||
let step = self.step;
|
||||
self.in_flight
|
||||
.retain_mut(|item| match (&item.phase, &item.req) {
|
||||
.retain_mut(|item| match (&mut item.phase, &item.req) {
|
||||
(Phase::AwaitOutput, Request::GetTree) => {
|
||||
if let Some(reply) = item.reply.take() {
|
||||
reply(Response::Tree {
|
||||
@@ -268,6 +288,27 @@ impl egui::Plugin for InspectionPlugin {
|
||||
}
|
||||
false
|
||||
}
|
||||
(
|
||||
Phase::Settle {
|
||||
steps_taken,
|
||||
max_steps,
|
||||
},
|
||||
Request::Settle { .. },
|
||||
) => {
|
||||
*steps_taken += 1;
|
||||
let steps_exceeded = *steps_taken >= *max_steps;
|
||||
if !immediate_repaint || steps_exceeded {
|
||||
if let Some(reply) = item.reply.take() {
|
||||
reply(Response::Settled {
|
||||
settled: !immediate_repaint,
|
||||
steps: *steps_taken,
|
||||
});
|
||||
}
|
||||
false
|
||||
} else {
|
||||
true
|
||||
}
|
||||
}
|
||||
_ => true,
|
||||
});
|
||||
|
||||
|
||||
@@ -63,6 +63,11 @@ pub enum Request {
|
||||
/// (via [`egui::ViewportCommand::InnerSize`]). Reply: [`Response::Done`]. This is the one
|
||||
/// action that isn't expressible as an [`egui::Event`].
|
||||
Resize { width: u32, height: u32 },
|
||||
|
||||
/// Wait until the app goes idle, then reply [`Response::Settled`].
|
||||
///
|
||||
/// Will wait for at most `max_steps`.
|
||||
Settle { max_steps: u64 },
|
||||
}
|
||||
|
||||
/// Sent peer → inspector, exactly one per [`Request`].
|
||||
@@ -99,6 +104,15 @@ pub enum Response {
|
||||
/// (not merely received): the events were processed by a frame, or the resize dispatched.
|
||||
Done,
|
||||
|
||||
/// Reply to [`Request::Settle`].
|
||||
Settled {
|
||||
/// Did we settle within `max_steps`?
|
||||
settled: bool,
|
||||
|
||||
/// How many frames did we run until we settled?
|
||||
steps: u64,
|
||||
},
|
||||
|
||||
/// The peer failed to service the request (recoverable; the connection stays open).
|
||||
Error { message: String },
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user