mirror of
https://github.com/emilk/egui.git
synced 2026-09-02 06:40:06 -04:00
Add support for scrolling via accesskit / kittest (#7286)
I need to scroll in a snapshot test in my app, and kittest had no utilities for this. Event::MouseWheel is error prone. This adds support for some accesskit scroll actions, and uses this in kittest to add helpers to scroll to a node / scroll the scroll area surrounding a node. The accesskit code says down/up/left/right `Scrolls by approximately one screen in a specific direction.`. Unfortunately it's difficult to get the size of a "screen" (I guess that would be the size of the containing scroll area)where I implemented the scrolling, so for now I've hardcoded it to 100px. I think scrolling a fixed amount is still better than not scrolling at all. --------- Co-authored-by: Emil Ernerfeldt <emil.ernerfeldt@gmail.com>
This commit is contained in:
@@ -1149,7 +1149,7 @@ impl Context {
|
||||
ID clashes happens when things like Windows or CollapsingHeaders share names,\n\
|
||||
or when things like Plot and Grid:s aren't given unique id_salt:s.\n\n\
|
||||
Sometimes the solution is to use ui.push_id.",
|
||||
if below { "above" } else { "below" })
|
||||
if below { "above" } else { "below" }),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1216,6 +1216,51 @@ impl Context {
|
||||
self.accesskit_node_builder(w.id, |builder| res.fill_accesskit_node_common(builder));
|
||||
}
|
||||
|
||||
#[cfg(feature = "accesskit")]
|
||||
self.write(|ctx| {
|
||||
use crate::{Align, pass_state::ScrollTarget, style::ScrollAnimation};
|
||||
let viewport = ctx.viewport_for(ctx.viewport_id());
|
||||
|
||||
viewport
|
||||
.input
|
||||
.consume_accesskit_action_requests(res.id, |request| {
|
||||
// TODO(lucasmerlin): Correctly handle the scroll unit:
|
||||
// https://github.com/AccessKit/accesskit/blob/e639c0e0d8ccbfd9dff302d972fa06f9766d608e/common/src/lib.rs#L2621
|
||||
const DISTANCE: f32 = 100.0;
|
||||
|
||||
match &request.action {
|
||||
accesskit::Action::ScrollIntoView => {
|
||||
viewport.this_pass.scroll_target = [
|
||||
Some(ScrollTarget::new(
|
||||
res.rect.x_range(),
|
||||
Some(Align::Center),
|
||||
ScrollAnimation::none(),
|
||||
)),
|
||||
Some(ScrollTarget::new(
|
||||
res.rect.y_range(),
|
||||
Some(Align::Center),
|
||||
ScrollAnimation::none(),
|
||||
)),
|
||||
];
|
||||
}
|
||||
accesskit::Action::ScrollDown => {
|
||||
viewport.this_pass.scroll_delta.0 += DISTANCE * Vec2::UP;
|
||||
}
|
||||
accesskit::Action::ScrollUp => {
|
||||
viewport.this_pass.scroll_delta.0 += DISTANCE * Vec2::DOWN;
|
||||
}
|
||||
accesskit::Action::ScrollLeft => {
|
||||
viewport.this_pass.scroll_delta.0 += DISTANCE * Vec2::LEFT;
|
||||
}
|
||||
accesskit::Action::ScrollRight => {
|
||||
viewport.this_pass.scroll_delta.0 += DISTANCE * Vec2::RIGHT;
|
||||
}
|
||||
_ => return false,
|
||||
};
|
||||
true
|
||||
});
|
||||
});
|
||||
|
||||
res
|
||||
}
|
||||
|
||||
|
||||
@@ -824,6 +824,23 @@ impl InputState {
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(feature = "accesskit")]
|
||||
pub fn consume_accesskit_action_requests(
|
||||
&mut self,
|
||||
id: crate::Id,
|
||||
mut consume: impl FnMut(&accesskit::ActionRequest) -> bool,
|
||||
) {
|
||||
let accesskit_id = id.accesskit_id();
|
||||
self.events.retain(|event| {
|
||||
if let Event::AccessKitActionRequest(request) = event {
|
||||
if request.target == accesskit_id {
|
||||
return !consume(request);
|
||||
}
|
||||
}
|
||||
true
|
||||
});
|
||||
}
|
||||
|
||||
#[cfg(feature = "accesskit")]
|
||||
pub fn has_accesskit_action_request(&self, id: crate::Id, action: accesskit::Action) -> bool {
|
||||
self.accesskit_action_requests(id, action).next().is_some()
|
||||
|
||||
Reference in New Issue
Block a user