Tooling · Inspection: inspector, FPS meter, render counter and event logger

install_inspector draws gpui's debug inspector in Ely's look: a panel
with the picked box's source, ids and box model, and its margin,
border, padding and size drawn over the page through raise, since the
panel scrolls. FpsMeter counts frames on the executor's clock and
colors each by the frames it missed. RenderCounter counts the renders
of the view that draws it. EventLogger lists the input that reaches
what it holds, its canvas laid first so a child's stop hides nothing.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
ZacharyZhang-NYandClaude Opus 5.5 committed 2026-09-28 07:13:12 -04:00
1 parent a0d93eb35f
commit 5f951ea581
14 files changed
+1378 -7

No files matched your search

+135
View File
@@ -0,0 +1,135 @@
use gpui::{
AnyElement, Context, FocusHandle, InteractiveElement, IntoElement, KeyUpEvent, Keystroke,
ParentElement, Render, Styled, TestAppContext, VisualTestContext, Window, div, px,
};
use std::cell::Cell;
use crate::{
forms,
primitives::{FocusNext, FocusPrev, FocusScope},
theme::Theme,
tooling::{Knob, Playground},
};
mod inspection;
struct Stage {
root: FocusHandle,
}
impl Render for Stage {
fn render(&mut self, _: &mut Window, _: &mut Context<Self>) -> impl IntoElement {
FocusScope::new(&self.root)
.root()
.size_full()
.child(div().w(px(600.0)).child(playground()))
}
}
thread_local! {
static LARGE: Cell<bool> = const { Cell::new(true) };
}
fn playground() -> AnyElement {
Playground::new(
"playground",
[
Knob::Toggle("disabled".into(), false),
Knob::Choice(
"size".into(),
["Sm", "Md", "Lg"][..2 + usize::from(LARGE.get())]
.iter()
.map(|size| (*size).into())
.collect(),
1,
),
Knob::Number("share".into(), 0.5, (0.0, 1.0), 0.25),
],
|settings, _, _| {
let shown = format!(
"preview-{}-{}-{:.2}",
settings.on("disabled"),
settings.picked("size"),
settings.number("share")
);
div().debug_selector(|| shown).into_any_element()
},
)
.into_any_element()
}
fn settle(cx: &mut VisualTestContext) {
for _ in 0..3 {
cx.run_until_parked();
cx.update(|window, _| window.refresh());
}
cx.run_until_parked();
}
/// Presses a key with no refresh of its own, so only what notifies redraws.
fn press(key: &str, cx: &mut VisualTestContext) {
cx.simulate_keystrokes(key);
cx.run_until_parked();
cx.simulate_event(KeyUpEvent {
keystroke: Keystroke::parse(key).expect("a key"),
});
cx.run_until_parked();
}
/// Each knob's edit redraws the preview with the new settings.
#[gpui::test]
fn knobs_redraw_the_preview(cx: &mut TestAppContext) {
cx.update(|cx| {
Theme::init(cx);
forms::bind_keys(cx);
cx.bind_keys([
gpui::KeyBinding::new("tab", FocusNext, None),
gpui::KeyBinding::new("shift-tab", FocusPrev, None),
]);
});
let (view, cx) = cx.add_window_view(|_, cx| Stage {
root: cx.focus_handle(),
});
let root = view.read_with(cx, |stage, _| stage.root.clone());
cx.update(|window, _| window.focus(&root));
settle(cx);
let shown =
|selector: &'static str, cx: &mut VisualTestContext| cx.debug_bounds(selector).is_some();
assert!(shown("preview-false-Md-0.50", cx));
press("tab", cx);
press("space", cx);
assert!(shown("preview-true-Md-0.50", cx), "the switch turned");
press("tab", cx);
for key in ["down", "down", "enter"] {
press(key, cx);
}
assert!(shown("preview-true-Lg-0.50", cx), "the choice moved");
press("tab", cx);
press("right", cx);
press("right", cx);
assert!(
shown("preview-true-Lg-1.00", cx),
"the number stepped twice"
);
assert!(
shown("knob-readout-share-1.00", cx),
"its readout in the step's places"
);
press("shift-tab", cx);
press("shift-tab", cx);
press("space", cx);
assert!(
shown("preview-false-Lg-1.00", cx),
"the switch showed its own setting, so a second press turned it back"
);
LARGE.set(false);
settle(cx);
press("tab", cx);
press("tab", cx);
press("right", cx);
assert!(
shown("preview-false-Md-0.75", cx),
"the owner took away the picked size, so every setting started over"
);
}