-
Notifications
You must be signed in to change notification settings - Fork 52
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
AccessKit integration #78
Changes from 23 commits
d611f85
e710cdc
860e80d
46a48b4
21e11b6
b09b2f9
9228169
b270203
e108b15
a6c643c
f4d03f7
dde3fcb
dcbfb91
5b4e544
f2be9f3
a419383
d407e0b
05b04a2
3d3e67d
6a009f5
7f7e91b
0ce74dd
709d505
f657a96
c2f984b
9ae0fb7
a882185
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
use dioxus::prelude::*; | ||
|
||
fn main() { | ||
dioxus_blitz::launch(app); | ||
} | ||
|
||
fn app() -> Element { | ||
rsx! { | ||
body { | ||
App {} | ||
} | ||
} | ||
} | ||
|
||
#[component] | ||
fn App() -> Element { | ||
rsx! { | ||
div { "Dioxus for all" } | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
use crate::waker::UserEvent; | ||
use accesskit::Role; | ||
use blitz_dom::{local_name, Document, Node}; | ||
use winit::{event_loop::EventLoopProxy, window::Window}; | ||
|
||
/// State of the accessibility node tree and platform adapter. | ||
pub struct AccessibilityState { | ||
/// Adapter to connect to the [`EventLoop`](`winit::event_loop::EventLoop`). | ||
adapter: accesskit_winit::Adapter, | ||
|
||
/// Next ID to assign an an [`accesskit::Node`]. | ||
next_id: u64, | ||
} | ||
|
||
impl AccessibilityState { | ||
pub fn new(window: &Window, proxy: EventLoopProxy<UserEvent>) -> Self { | ||
Self { | ||
adapter: accesskit_winit::Adapter::with_event_loop_proxy(window, proxy.clone()), | ||
next_id: 1, | ||
} | ||
} | ||
pub fn build_tree(&mut self, doc: &Document) { | ||
let mut nodes = std::collections::HashMap::new(); | ||
let mut window = accesskit::NodeBuilder::new(accesskit::Role::Window); | ||
|
||
doc.visit(|node_id, node| { | ||
let (id, node_builder) = self.build_node(node); | ||
|
||
if let Some(parent_id) = node.parent { | ||
let (_, parent_node): &mut (_, accesskit::NodeBuilder) = | ||
nodes.get_mut(&parent_id).unwrap(); | ||
parent_node.push_child(id) | ||
} else { | ||
window.push_child(id) | ||
} | ||
|
||
nodes.insert(node_id, (id, node_builder)); | ||
}); | ||
|
||
let mut nodes: Vec<_> = nodes | ||
.into_iter() | ||
.map(|(_, (id, node))| (id, node.build())) | ||
.collect(); | ||
nodes.push((accesskit::NodeId(0), window.build())); | ||
|
||
let tree = accesskit::Tree::new(accesskit::NodeId(0)); | ||
let tree_update = accesskit::TreeUpdate { | ||
nodes, | ||
tree: Some(tree), | ||
focus: accesskit::NodeId(0), | ||
}; | ||
|
||
self.adapter.update_if_active(|| tree_update) | ||
} | ||
|
||
#[cfg(feature = "accessibility")] | ||
fn build_node(&mut self, node: &Node) -> (accesskit::NodeId, accesskit::NodeBuilder) { | ||
let mut node_builder = accesskit::NodeBuilder::default(); | ||
if let Some(element_data) = node.element_data() { | ||
let name = element_data.name.local.to_string(); | ||
|
||
// TODO match more roles | ||
let role = match &*name { | ||
"button" => Role::Button, | ||
"div" => Role::GenericContainer, | ||
"header" => Role::Header, | ||
"h1" | "h2" | "h3" | "h4" | "h5" | "h6" => Role::Heading, | ||
"p" => Role::Paragraph, | ||
"section" => Role::Section, | ||
"input" => { | ||
let ty = element_data.attr(local_name!("type")).unwrap_or("text"); | ||
match ty { | ||
"number" => Role::NumberInput, | ||
_ => Role::TextInput, | ||
} | ||
} | ||
_ => Role::Unknown, | ||
}; | ||
|
||
node_builder.set_role(role); | ||
node_builder.set_name(name); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In this scope, the variable |
||
} else if node.is_text_node() { | ||
node_builder.set_role(accesskit::Role::StaticText); | ||
node_builder.set_name(node.text_content()); | ||
} | ||
|
||
let id = accesskit::NodeId(self.next_id); | ||
self.next_id += 1; | ||
|
||
(id, node_builder) | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's the reason for moving all of these deps from "dev-dependencies" to "dependencies"?