Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 16 additions & 8 deletions crates/egui-winit/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ use winit::{
window::{CursorGrabMode, Window, WindowButtons, WindowLevel},
};

use std::sync::Arc;
use std::sync::RwLock;

pub fn screen_size_in_pixels(window: &Window) -> egui::Vec2 {
let size = if cfg!(target_os = "ios") {
// `outer_size` Includes the area behind the "dynamic island".
Expand Down Expand Up @@ -102,7 +105,7 @@ pub struct State {
has_sent_ime_enabled: bool,

#[cfg(feature = "accesskit")]
accesskit: Option<accesskit_winit::Adapter>,
accesskit: Option<Arc<RwLock<accesskit_winit::Adapter>>>,

allow_ime: bool,
ime_rect_px: Option<egui::Rect>,
Expand Down Expand Up @@ -172,11 +175,14 @@ impl State {
) {
profiling::function_scope!();

self.accesskit = Some(accesskit_winit::Adapter::with_event_loop_proxy(
event_loop,
window,
event_loop_proxy,
));
self.accesskit = Some(Arc::new(RwLock::new(
accesskit_winit::Adapter::with_event_loop_proxy(event_loop, window, event_loop_proxy),
)));
}

#[cfg(feature = "accesskit")]
pub fn init_accesskit_with_adapter(&mut self, adapter: Arc<RwLock<accesskit_winit::Adapter>>) {
self.accesskit = Some(adapter);
}

/// Call this once a graphics context has been created to update the maximum texture dimensions
Expand Down Expand Up @@ -270,7 +276,8 @@ impl State {
profiling::function_scope!(short_window_event_description(event));

#[cfg(feature = "accesskit")]
if let Some(accesskit) = self.accesskit.as_mut() {
if let Some(accesskit) = self.accesskit.as_ref() {
let mut accesskit = accesskit.write().unwrap();
accesskit.process_event(window, event);
}

Expand Down Expand Up @@ -941,9 +948,10 @@ impl State {
}

#[cfg(feature = "accesskit")]
if let Some(accesskit) = self.accesskit.as_mut()
if let Some(accesskit) = self.accesskit.as_ref()
&& let Some(update) = accesskit_update
{
let mut accesskit = accesskit.write().unwrap();
profiling::scope!("accesskit");
accesskit.update_if_active(|| update);
}
Expand Down
55 changes: 55 additions & 0 deletions crates/egui/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -622,6 +622,36 @@ impl ContextImpl {
builders.get_mut(&id).unwrap()
}

#[cfg(feature = "accesskit")]
fn add_accesskit_node(&mut self, id: Id, node: accesskit::Node) {
let state = self.viewport().this_pass.accesskit_state.as_mut().unwrap();
let nodes = &mut state.nodes;
assert_eq!(nodes.insert(id, node), None);

/// Find the first ancestor that already has an accesskit node.
fn find_accesskit_parent(
parent_map: &IdMap<Id>,
node_map: &IdMap<accesskit::Node>,
id: Id,
) -> Option<Id> {
if let Some(parent_id) = parent_map.get(&id) {
if node_map.contains_key(parent_id) {
Some(*parent_id)
} else {
find_accesskit_parent(parent_map, node_map, *parent_id)
}
} else {
None
}
}

let parent_id = find_accesskit_parent(&state.parent_map, nodes, id)
.unwrap_or(crate::accesskit_root_id());

let parent_builder = nodes.get_mut(&parent_id).unwrap();
parent_builder.push_child(id.accesskit_id());
}

fn pixels_per_point(&mut self) -> f32 {
self.viewport().input.pixels_per_point
}
Expand Down Expand Up @@ -3515,6 +3545,31 @@ impl Context {
})
}

/// If AccessKit support is active for the current frame, build a new node
/// with the given ID using `writer`. The writer receives the node and a struct
/// that allows it to insert nodes for other descendants as needed.
///
/// Returns `None` if acesskit is off.
// TODO(emilk): consider making both read-only and read-write versions
#[cfg(feature = "accesskit")]
pub fn accesskit_subtree_builder<R>(
&self,
id: Id,
writer: impl FnOnce(&mut accesskit::Node, &mut crate::pass_state::AccessKitPassState) -> R,
) -> Option<R> {
self.write(|ctx| {
let mut node = accesskit::Node::default();
let accesskit_state = &mut ctx.viewport().this_pass.accesskit_state;
let result = accesskit_state
.as_mut()
.map(|state| writer(&mut node, state));
if accesskit_state.is_some() {
ctx.add_accesskit_node(id, node);
}
result
})
}

#[cfg(feature = "accesskit")]
pub(crate) fn register_accesskit_parent(&self, id: Id, parent_id: Id) {
self.write(|ctx| {
Expand Down
Loading