mirror of
https://github.com/emilk/egui.git
synced 2026-06-26 22:53:14 -04:00
Add egui_inspection protocol and plugin (#8234)
Introduces live inspection for running egui apps over a small TCP request/response protocol, plus the `egui::Plugin` that serves it. This is the minimal surface to get the egui mcp in, we may want to extend this in the future to add support for the inspection gui. --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -116,6 +116,12 @@ x11 = [
|
||||
## This is used to generate images for examples.
|
||||
__screenshot = []
|
||||
|
||||
## Enable the [`egui_inspection`] plugin. When the `EGUI_INSPECTION` (or
|
||||
## `EGUI_INSPECTION_ADDR`) env var is set, eframe opens a TCP inspection port on startup that
|
||||
## lets an external tool (e.g. the `egui_mcp` server) read the AccessKit tree, inject input,
|
||||
## and capture screenshots. Off unless the env var is set; no-op on wasm.
|
||||
inspection = ["dep:egui_inspection", "accesskit"]
|
||||
|
||||
[dependencies]
|
||||
egui = { workspace = true, default-features = false, features = ["bytemuck"] }
|
||||
|
||||
@@ -131,6 +137,7 @@ web-time.workspace = true
|
||||
# Optional dependencies
|
||||
|
||||
egui_glow = { workspace = true, optional = true, default-features = false }
|
||||
egui_inspection = { workspace = true, optional = true, features = ["plugin"] }
|
||||
glow = { workspace = true, optional = true }
|
||||
ron = { workspace = true, optional = true, features = ["integer128"] }
|
||||
serde = { workspace = true, optional = true }
|
||||
|
||||
@@ -209,6 +209,35 @@ pub use native::file_storage::storage_dir;
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
pub mod icon_data;
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
/// Attach an [`egui_inspection::InspectionPlugin`] to `ctx` when enabled via the environment.
|
||||
#[cfg(all(feature = "inspection", not(target_arch = "wasm32")))]
|
||||
pub(crate) fn maybe_attach_inspection_plugin(ctx: &egui::Context, label: Option<String>) {
|
||||
match egui_inspection::attach_from_env(ctx, label) {
|
||||
Ok(true) => log::info!("egui_inspection plugin attached"),
|
||||
Ok(false) => {}
|
||||
Err(err) => log::warn!("egui_inspection attach failed: {err}"),
|
||||
}
|
||||
}
|
||||
|
||||
/// Fallback for native builds without the `inspection` feature. Logs warning if inspection env
|
||||
/// var was set.
|
||||
#[cfg(all(
|
||||
not(feature = "inspection"),
|
||||
not(target_arch = "wasm32"),
|
||||
any(feature = "glow", feature = "wgpu_no_default_features")
|
||||
))]
|
||||
pub(crate) fn maybe_attach_inspection_plugin(_ctx: &egui::Context, _label: Option<String>) {
|
||||
if let Ok(value) = std::env::var("EGUI_INSPECTION")
|
||||
&& value != "0"
|
||||
&& value != "false"
|
||||
&& !value.is_empty()
|
||||
{
|
||||
log::warn!("Inspection env var set but app was compiled without eframe/inspection feature");
|
||||
}
|
||||
}
|
||||
|
||||
/// This is how you start a native (desktop) app.
|
||||
///
|
||||
/// The first argument is name of your app, which is an identifier
|
||||
|
||||
@@ -299,6 +299,9 @@ impl<'app> GlowWinitApp<'app> {
|
||||
let app_creator = std::mem::take(&mut self.app_creator)
|
||||
.expect("Single-use AppCreator has unexpectedly already been taken");
|
||||
|
||||
#[cfg(all(not(feature = "inspection"), not(target_arch = "wasm32")))]
|
||||
crate::maybe_attach_inspection_plugin(&integration.egui_ctx, Some(self.app_name.clone()));
|
||||
|
||||
let app: Box<dyn 'app + App> = {
|
||||
// Use latest raw_window_handle for eframe compatibility
|
||||
use raw_window_handle::{HasDisplayHandle as _, HasWindowHandle as _};
|
||||
|
||||
@@ -291,6 +291,9 @@ impl<'app> WgpuWinitApp<'app> {
|
||||
|
||||
let app_creator = std::mem::take(&mut self.app_creator)
|
||||
.expect("Single-use AppCreator has unexpectedly already been taken");
|
||||
|
||||
crate::maybe_attach_inspection_plugin(&egui_ctx, Some(self.app_name.clone()));
|
||||
|
||||
let cc = CreationContext {
|
||||
egui_ctx: egui_ctx.clone(),
|
||||
integration_info: integration.frame.info().clone(),
|
||||
|
||||
Reference in New Issue
Block a user