1
0
mirror of https://github.com/emilk/egui.git synced 2026-08-29 04:40:03 -04:00

Add RepaintCauses and TreeUpdate to egui_inspection::Settle response

This commit is contained in:
Lucas Meurer
2026-08-17 17:09:35 +02:00
parent d802a982ce
commit 9512224eb4
2 changed files with 47 additions and 18 deletions

View File

@@ -38,7 +38,7 @@ use std::sync::mpsc;
use egui::{Context, FullOutput, RawInput};
use crate::protocol::{EncodedPng, Request, Response};
use crate::protocol::{EncodedPng, Request, Response, Tree, TreeResponse};
/// How long [`serve`]'s connection threads wait for the UI thread before giving up. Generous:
/// a backgrounded window may not paint (and thus not service requests) for a while.
@@ -274,11 +274,11 @@ impl egui::Plugin for InspectionPlugin {
.retain_mut(|item| match (&mut item.phase, &item.req) {
(Phase::AwaitOutput, Request::GetTree) => {
if let Some(reply) = item.reply.take() {
reply(Response::Tree {
reply(Response::Tree(TreeResponse {
step,
pixels_per_point: output.pixels_per_point,
accesskit: output.platform_output.accesskit_update.clone(),
});
}));
}
false
}
@@ -299,9 +299,25 @@ impl egui::Plugin for InspectionPlugin {
let steps_exceeded = *steps_taken >= *max_steps;
if !immediate_repaint || steps_exceeded {
if let Some(reply) = item.reply.take() {
// Report what keeps the app busy, so the inspector can say *why* it
// never settled instead of only that it didn't.
let repaint_causes = if immediate_repaint {
ctx.repaint_causes()
.iter()
.map(ToString::to_string)
.collect()
} else {
Vec::new()
};
reply(Response::Settled {
settled: !immediate_repaint,
steps: *steps_taken,
repaint_causes,
tree: TreeResponse {
step,
pixels_per_point: output.pixels_per_point,
accesskit: output.platform_output.accesskit_update.clone(),
},
});
}
false

View File

@@ -23,7 +23,7 @@ use egui::accesskit;
/// Wire-protocol version, sent in the connection handshake (see [`write_handshake`]).
///
/// Bump on any non-additive change to [`Request`] / [`Response`].
pub const PROTOCOL_VERSION: u32 = 1;
pub const PROTOCOL_VERSION: u32 = 2;
/// Magic bytes that open every connection, identifying the egui inspection protocol.
pub const PROTOCOL_MAGIC: [u8; 4] = *b"eins";
@@ -66,10 +66,26 @@ pub enum Request {
/// Wait until the app goes idle, then reply [`Response::Settled`].
///
/// Will wait for at most `max_steps`.
/// Will wait for at most `max_steps`. If the app never goes idle, the reply lists the
/// repaint causes that kept it busy.
Settle { max_steps: u64 },
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct TreeResponse {
/// Monotonically increasing frame counter.
pub step: u64,
/// `physical_pixel = logical_point * pixels_per_point`. AccessKit bounds are in
/// logical coords; a screenshot is in physical pixels — multiply to align them.
pub pixels_per_point: f32,
/// The current full AccessKit tree. egui rebuilds the complete node set every pass,
/// so this is a full snapshot, not an incremental update. `None` if AccessKit hasn't
/// produced a tree yet.
pub accesskit: Option<accesskit::TreeUpdate>,
}
/// Sent peer → inspector, exactly one per [`Request`].
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub enum Response {
@@ -83,19 +99,7 @@ pub enum Response {
},
/// Reply to [`Request::GetTree`].
Tree {
/// Monotonically increasing frame counter.
step: u64,
/// `physical_pixel = logical_point * pixels_per_point`. AccessKit bounds are in
/// logical coords; a screenshot is in physical pixels — multiply to align them.
pixels_per_point: f32,
/// The current full AccessKit tree. egui rebuilds the complete node set every pass,
/// so this is a full snapshot, not an incremental update. `None` if AccessKit hasn't
/// produced a tree yet.
accesskit: Option<accesskit::TreeUpdate>,
},
Tree(TreeResponse),
/// Reply to [`Request::GetScreenshot`].
Screenshot(EncodedPng),
@@ -111,6 +115,15 @@ pub enum Response {
/// How many frames did we run until we settled?
steps: u64,
/// Why did the app keep repainting? One formatted `egui::RepaintCause`
/// (`file:line reason`) per entry.
///
/// Empty when `settled` is true.
repaint_causes: Vec<String>,
/// The last frames tree.
tree: TreeResponse,
},
/// The peer failed to service the request (recoverable; the connection stays open).