mirror of
https://github.com/emilk/egui.git
synced 2026-08-30 05:10:03 -04:00
Remove last_accesskit_update and add on_accesskit_update hook
This commit is contained in:
@@ -89,7 +89,6 @@ pub struct Harness<'a, State: 'static = ()> {
|
|||||||
plugins: Vec<Box<dyn Plugin<State>>>,
|
plugins: Vec<Box<dyn Plugin<State>>>,
|
||||||
entry_location: Option<&'static std::panic::Location<'static>>,
|
entry_location: Option<&'static std::panic::Location<'static>>,
|
||||||
consumed_event_locations: Vec<&'static std::panic::Location<'static>>,
|
consumed_event_locations: Vec<&'static std::panic::Location<'static>>,
|
||||||
last_accesskit_update: Option<egui::accesskit::TreeUpdate>,
|
|
||||||
|
|
||||||
#[cfg(feature = "snapshot")]
|
#[cfg(feature = "snapshot")]
|
||||||
default_snapshot_options: SnapshotOptions,
|
default_snapshot_options: SnapshotOptions,
|
||||||
@@ -168,7 +167,7 @@ impl<'a, State: 'static> Harness<'a, State> {
|
|||||||
app,
|
app,
|
||||||
ctx,
|
ctx,
|
||||||
input,
|
input,
|
||||||
kittest: kittest::State::new(initial_accesskit.clone()),
|
kittest: kittest::State::new(initial_accesskit),
|
||||||
output,
|
output,
|
||||||
response,
|
response,
|
||||||
state,
|
state,
|
||||||
@@ -181,7 +180,6 @@ impl<'a, State: 'static> Harness<'a, State> {
|
|||||||
plugins,
|
plugins,
|
||||||
entry_location: None,
|
entry_location: None,
|
||||||
consumed_event_locations: Vec::new(),
|
consumed_event_locations: Vec::new(),
|
||||||
last_accesskit_update: Some(initial_accesskit),
|
|
||||||
|
|
||||||
#[cfg(feature = "snapshot")]
|
#[cfg(feature = "snapshot")]
|
||||||
default_snapshot_options,
|
default_snapshot_options,
|
||||||
@@ -247,12 +245,6 @@ impl<'a, State: 'static> Harness<'a, State> {
|
|||||||
self._step_inner(false);
|
self._step_inner(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The most recent AccessKit tree update, if any. Useful for plugins that mirror
|
|
||||||
/// the accessibility tree to an external debugger.
|
|
||||||
pub fn accesskit_tree_update(&self) -> Option<&egui::accesskit::TreeUpdate> {
|
|
||||||
self.last_accesskit_update.as_ref()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// [`std::panic::Location`] of the most recent public `#[track_caller]` entry point
|
/// [`std::panic::Location`] of the most recent public `#[track_caller]` entry point
|
||||||
/// (e.g. the caller of `step()` / `run()`), or `None` if no such call has been made yet.
|
/// (e.g. the caller of `step()` / `run()`), or `None` if no such call has been made yet.
|
||||||
pub fn entry_location(&self) -> Option<&'static std::panic::Location<'static>> {
|
pub fn entry_location(&self) -> Option<&'static std::panic::Location<'static>> {
|
||||||
@@ -378,7 +370,7 @@ impl<'a, State: 'static> Harness<'a, State> {
|
|||||||
.accesskit_update
|
.accesskit_update
|
||||||
.take()
|
.take()
|
||||||
.expect("AccessKit was disabled");
|
.expect("AccessKit was disabled");
|
||||||
self.last_accesskit_update = Some(accesskit_update.clone());
|
self.dispatch(|p, h| p.on_accesskit_update(h, &accesskit_update));
|
||||||
self.kittest.update(accesskit_update);
|
self.kittest.update(accesskit_update);
|
||||||
self.renderer.handle_delta(&output.textures_delta);
|
self.renderer.handle_delta(&output.textures_delta);
|
||||||
self.output = output;
|
self.output = output;
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ use crate::{ExceededMaxStepsError, Harness};
|
|||||||
/// Plugin hooks receive `&mut Harness`. Calling [`Harness::step`] / [`Harness::run`] /
|
/// Plugin hooks receive `&mut Harness`. Calling [`Harness::step`] / [`Harness::run`] /
|
||||||
/// etc. from inside a hook will recurse infinitely through your own `after_step`. If
|
/// etc. from inside a hook will recurse infinitely through your own `after_step`. If
|
||||||
/// a plugin needs to advance the harness from inside a hook — e.g. an inspector that
|
/// a plugin needs to advance the harness from inside a hook — e.g. an inspector that
|
||||||
/// blocks on user input — use [`Harness::advance_frame`] instead.
|
/// blocks on user input — use [`Harness::step_no_side_effects`] instead.
|
||||||
#[expect(unused_variables, reason = "default no-op impls")]
|
#[expect(unused_variables, reason = "default no-op impls")]
|
||||||
pub trait Plugin<State = ()>: Send + Any {
|
pub trait Plugin<State = ()>: Send + Any {
|
||||||
/// Called once at the start of every `run()` / `try_run()` / `try_run_realtime()` /
|
/// Called once at the start of every `run()` / `try_run()` / `try_run_realtime()` /
|
||||||
@@ -58,6 +58,18 @@ pub trait Plugin<State = ()>: Send + Any {
|
|||||||
/// Called immediately after each single-frame step.
|
/// Called immediately after each single-frame step.
|
||||||
fn after_step(&mut self, harness: &mut Harness<'_, State>) {}
|
fn after_step(&mut self, harness: &mut Harness<'_, State>) {}
|
||||||
|
|
||||||
|
/// Called after each single-frame step with the AccessKit tree update egui produced
|
||||||
|
/// for that frame, before it's applied to the internal kittest state.
|
||||||
|
///
|
||||||
|
/// Plugins that need the tree (e.g. to stream it to an external debugger) should
|
||||||
|
/// clone it here — the harness no longer retains it after this hook returns.
|
||||||
|
fn on_accesskit_update(
|
||||||
|
&mut self,
|
||||||
|
harness: &mut Harness<'_, State>,
|
||||||
|
tree: &egui::accesskit::TreeUpdate,
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
/// Called after a queued event has been pushed into the harness input, before the
|
/// Called after a queued event has been pushed into the harness input, before the
|
||||||
/// frame runs that consumes it.
|
/// frame runs that consumes it.
|
||||||
fn on_event(&mut self, harness: &mut Harness<'_, State>, event: &egui::Event) {}
|
fn on_event(&mut self, harness: &mut Harness<'_, State>, event: &egui::Event) {}
|
||||||
|
|||||||
@@ -119,20 +119,20 @@ fn on_event_fires_per_event() {
|
|||||||
assert_eq!(events, 2, "expected 2 on_event calls, got log: {log:?}");
|
assert_eq!(events, 2, "expected 2 on_event calls, got log: {log:?}");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// `advance_frame` does NOT fire `before_step`/`after_step`.
|
/// `step_no_side_effects` does NOT fire `before_step`/`after_step`.
|
||||||
#[test]
|
#[test]
|
||||||
fn advance_frame_skips_hooks() {
|
fn step_no_side_effects_skips_hooks() {
|
||||||
struct DrivingPlugin {
|
struct DrivingPlugin {
|
||||||
log: Log,
|
log: Log,
|
||||||
drove: bool,
|
drove: bool,
|
||||||
}
|
}
|
||||||
impl<S> Plugin<S> for DrivingPlugin {
|
impl<S: 'static> Plugin<S> for DrivingPlugin {
|
||||||
fn after_step(&mut self, h: &mut Harness<'_, S>) {
|
fn after_step(&mut self, h: &mut Harness<'_, S>) {
|
||||||
self.log.lock().unwrap().push("after_step".into());
|
self.log.lock().unwrap().push("after_step".into());
|
||||||
if !self.drove {
|
if !self.drove {
|
||||||
self.drove = true;
|
self.drove = true;
|
||||||
// Call advance_frame from inside a hook — must not recurse.
|
// Call step_no_side_effects from inside a hook — must not recurse.
|
||||||
h.advance_frame();
|
h.step_no_side_effects();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -152,7 +152,7 @@ fn advance_frame_skips_hooks() {
|
|||||||
|
|
||||||
let log = log.lock().unwrap();
|
let log = log.lock().unwrap();
|
||||||
// Exactly one after_step from the user's step(), plus any from construction-time run_ok
|
// Exactly one after_step from the user's step(), plus any from construction-time run_ok
|
||||||
// (cleared above). advance_frame must NOT have produced another after_step.
|
// (cleared above). step_no_side_effects must NOT have produced another after_step.
|
||||||
assert_eq!(log.iter().filter(|s| s == &"after_step").count(), 1);
|
assert_eq!(log.iter().filter(|s| s == &"after_step").count(), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user