Skip to content

Commit

Permalink
Merge branch 'main' of https://github.com/marc2332/freya into chore/m…
Browse files Browse the repository at this point in the history
…ove-accessibility-node-state
  • Loading branch information
marc2332 committed Jan 28, 2024
2 parents 59cadc7 + a03f1b3 commit 8796eab
Show file tree
Hide file tree
Showing 29 changed files with 492 additions and 600 deletions.
12 changes: 6 additions & 6 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,13 @@ dioxus-router = { version = "0.4", default-features = false }
skia-safe = { version = "0.67.0", features = ["gl", "textlayout", "svg"] }

gl = "0.14.0"
glutin = "0.30.10"
glutin-winit = "0.3.0"
raw-window-handle = "0.5.1"
winit = "0.28.7"
glutin = "0.31.2"
glutin-winit = "0.4.2"
raw-window-handle = "0.5.2"
winit = "0.29.9"
tokio = { version = "1.33.0", features = ["sync", "rt-multi-thread", "time", "macros"] }
accesskit = { version = "0.11.0", features = ["serde"]}
accesskit_winit = "0.14.1"
accesskit = { version = "0.12.2", features = ["serde"]}
accesskit_winit = "0.18.0"
zbus = "3.14.1"

euclid = "0.22.9"
Expand Down
2 changes: 1 addition & 1 deletion book/src/guides/style.md
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ Compatible elements: [`rect`](/guides/elements.html#rect)
The attributes that have colors as values can use the following syntax:

#### Static colors
- `rect`
- `red`
- `blue`
- `green`
- `yellow`
Expand Down
2 changes: 1 addition & 1 deletion book/src/guides/testing.md
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ async fn test() {
let mut utils = launch_test_with_config(
our_component,
TestingConfig::default().with_size((500.0, 800.0).into()),
*TestingConfig::default().with_size((500.0, 800.0).into()),
);
let root = utils.root();
Expand Down
2 changes: 1 addition & 1 deletion crates/components/src/accordion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ pub fn Accordion<'a>(cx: Scope<'a, AccordionProps<'a>>) -> Element<'a> {
let onmouseenter = {
to_owned![status, platform];
move |_| {
platform.set_cursor(CursorIcon::Hand);
platform.set_cursor(CursorIcon::Pointer);
status.set(AccordionStatus::Hovering);
}
};
Expand Down
2 changes: 1 addition & 1 deletion crates/components/src/button.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ pub fn Button<'a>(cx: Scope<'a, ButtonProps<'a>>) -> Element {
let onmouseenter = {
to_owned![status, platform];
move |_| {
platform.set_cursor(CursorIcon::Hand);
platform.set_cursor(CursorIcon::Pointer);
status.set(ButtonStatus::Hovering);
}
};
Expand Down
4 changes: 2 additions & 2 deletions crates/components/src/dropdown.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ where
let onmouseenter = {
to_owned![platform];
move |_| {
platform.set_cursor(CursorIcon::Hand);
platform.set_cursor(CursorIcon::Pointer);
status.set(DropdownItemStatus::Hovering);
}
};
Expand Down Expand Up @@ -231,7 +231,7 @@ where
let onmouseenter = {
to_owned![status, platform];
move |_| {
platform.set_cursor(CursorIcon::Hand);
platform.set_cursor(CursorIcon::Pointer);
status.set(DropdownStatus::Hovering);
}
};
Expand Down
1 change: 0 additions & 1 deletion crates/components/src/input.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,6 @@ pub struct InputProps<'a> {
/// ```rust,no_run
/// # use freya::prelude::*;
/// fn app(cx: Scope) -> Element {
/// use_init_focus(cx);
/// let value = use_state(cx, String::new);
///
/// render!(
Expand Down
2 changes: 1 addition & 1 deletion crates/components/src/slider.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ pub fn Slider<'a>(cx: Scope<'a, SliderProps>) -> Element<'a> {

let onmouseenter = move |_: MouseEvent| {
*status.write_silent() = SliderStatus::Hovering;
platform.set_cursor(CursorIcon::Hand);
platform.set_cursor(CursorIcon::Pointer);
};

let onmouseover = move |e: MouseEvent| {
Expand Down
2 changes: 1 addition & 1 deletion crates/components/src/switch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ pub fn Switch<'a>(cx: Scope<'a, SwitchProps<'a>>) -> Element<'a> {

let onmouseenter = move |_: MouseEvent| {
*status.write_silent() = SwitchStatus::Hovering;
platform.set_cursor(CursorIcon::Hand);
platform.set_cursor(CursorIcon::Pointer);
};

let onclick = |_: MouseEvent| {
Expand Down
125 changes: 55 additions & 70 deletions crates/core/src/accessibility/accessibility_provider.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,14 @@ use dioxus_native_core::{
NodeId,
};
use freya_dom::prelude::{DioxusDOM, DioxusNode};
use freya_node_state::AccessibilityState;
use freya_node_state::AccessibilityNodeState;
use std::slice::Iter;
use tokio::sync::watch;
use torin::{prelude::NodeAreas, torin::Torin};

use crate::layout::*;

use super::accessibility_state::ACCESSIBILITY_ROOT_ID;

/// Direction for the next Accessibility Node to be focused.
#[derive(PartialEq)]
pub enum AccessibilityFocusDirection {
Expand All @@ -29,7 +30,7 @@ pub trait AccessibilityProvider {
dioxus_node: &DioxusNode,
node_areas: &NodeAreas,
accessibility_id: AccessibilityId,
node_accessibility: &AccessibilityState,
node_accessibility: &AccessibilityNodeState,
) {
let mut builder = NodeBuilder::new(Role::Unknown);

Expand Down Expand Up @@ -88,20 +89,17 @@ pub trait AccessibilityProvider {
fn nodes(&self) -> Iter<(AccessibilityId, Node)>;

/// Get the currently focused Node's ID.
fn focus_id(&self) -> Option<AccessibilityId>;
fn focus_id(&self) -> AccessibilityId;

/// Update the focused Node ID.
fn set_focus(&mut self, new_focus_id: Option<AccessibilityId>);
fn set_focus(&mut self, new_focus_id: AccessibilityId);

/// Update the focused Node ID and generate a TreeUpdate if necessary.
fn set_focus_with_update(
&mut self,
new_focus_id: Option<AccessibilityId>,
) -> Option<TreeUpdate> {
fn set_focus_with_update(&mut self, new_focus_id: AccessibilityId) -> Option<TreeUpdate> {
self.set_focus(new_focus_id);

// Only focus the element if it exists
let node_focused_exists = self.nodes().any(|node| Some(node.0) == new_focus_id);
let node_focused_exists = self.nodes().any(|node| node.0 == new_focus_id);
if node_focused_exists {
Some(TreeUpdate {
nodes: Vec::new(),
Expand Down Expand Up @@ -133,13 +131,16 @@ pub trait AccessibilityProvider {
nodes.extend(self.nodes().cloned());
nodes.reverse();

let focus = self.nodes().find_map(|node| {
if Some(node.0) == self.focus_id() {
Some(node.0)
} else {
None
}
});
let focus = self
.nodes()
.find_map(|node| {
if node.0 == self.focus_id() {
Some(node.0)
} else {
None
}
})
.unwrap_or(ACCESSIBILITY_ROOT_ID);

TreeUpdate {
nodes,
Expand All @@ -149,58 +150,42 @@ pub trait AccessibilityProvider {
}

/// Focus the next/previous Node starting from the currently focused Node.
fn set_focus_on_next_node(
&mut self,
direction: AccessibilityFocusDirection,
focus_sender: &watch::Sender<Option<AccessibilityId>>,
) -> Option<TreeUpdate> {
// Start from the focused node or from the first registered node
let focused_node_id = self.focus_id().or(self.nodes().nth(0).map(|node| node.0));
if let Some(focused_node_id) = focused_node_id {
let current_node = self
.nodes()
.enumerate()
.find(|(_, node)| node.0 == focused_node_id)
.map(|(i, _)| i);

if let Some(node_index) = current_node {
let target_node_index = if direction == AccessibilityFocusDirection::Forward {
// Find the next Node
if node_index == self.nodes().len() - 1 {
0
} else {
node_index + 1
}
} else {
// Find the previous Node
if node_index == 0 {
self.nodes().len() - 1
} else {
node_index - 1
}
};

let target_node = self
.nodes()
.enumerate()
.find(|(i, _)| *i == target_node_index)
.map(|(_, node)| node.0);

self.set_focus(target_node);
fn set_focus_on_next_node(&mut self, direction: AccessibilityFocusDirection) -> TreeUpdate {
let node_index = self
.nodes()
.enumerate()
.find(|(_, node)| node.0 == self.focus_id())
.map(|(i, _)| i)
.unwrap();

let target_node_index = if direction == AccessibilityFocusDirection::Forward {
// Find the next Node
if node_index == self.nodes().len() - 1 {
0
} else {
// Select the first Node
self.set_focus(self.nodes().next().map(|(id, _)| *id))
node_index + 1
}
} else {
// Find the previous Node
if node_index == 0 {
self.nodes().len() - 1
} else {
node_index - 1
}
};

focus_sender.send(self.focus_id()).ok();
let target_node = self
.nodes()
.nth(target_node_index)
.map(|(id, _)| *id)
.unwrap_or(ACCESSIBILITY_ROOT_ID);

Some(TreeUpdate {
nodes: Vec::new(),
tree: None,
focus: self.focus_id(),
})
} else {
None
self.set_focus(target_node);

TreeUpdate {
nodes: Vec::new(),
tree: None,
focus: self.focus_id(),
}
}
}
Expand All @@ -227,13 +212,13 @@ impl NodeAccessibility for DioxusNode<'_> {
}
}

/// Collect all the AccessibilityIDs from a Node's children
/// Collect all the AccessibilityIDs from a Node's AccessibilityNodeState
fn get_accessibility_children(&self) -> Vec<AccessibilityId> {
self.children()
.iter()
.filter_map(|child| {
let node_accessibility = &*child.get::<AccessibilityState>().unwrap();
node_accessibility.focus_id
let node_accessibility = &*child.get::<AccessibilityNodeState>().unwrap();
node_accessibility.accessibility_id
})
.collect::<Vec<AccessibilityId>>()
}
Expand All @@ -250,8 +235,8 @@ pub fn process_accessibility(
let node_areas = layout.get(*node_id).unwrap();
let dioxus_node = rdom.get(*node_id);
if let Some(dioxus_node) = dioxus_node {
let node_accessibility = &*dioxus_node.get::<AccessibilityState>().unwrap();
if let Some(accessibility_id) = node_accessibility.focus_id {
let node_accessibility = &*dioxus_node.get::<AccessibilityNodeState>().unwrap();
if let Some(accessibility_id) = node_accessibility.accessibility_id {
access_provider.add_node(
&dioxus_node,
node_areas,
Expand Down
26 changes: 13 additions & 13 deletions crates/core/src/accessibility/accessibility_state.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,12 @@
use crate::accessibility::*;
use accesskit::{Node, NodeClassSet, NodeId as AccessibilityId};
use std::{
num::NonZeroU128,
sync::{Arc, Mutex},
};
use std::sync::{Arc, Mutex};

pub type SharedAccessibilityState = Arc<Mutex<AccessibilityState>>;

pub const ROOT_ID: AccessibilityId = AccessibilityId(unsafe { NonZeroU128::new_unchecked(1) });
pub const ACCESSIBILITY_ROOT_ID: AccessibilityId = AccessibilityId(0);

/// Manages the Accessibility integration.
#[derive(Default)]
pub struct AccessibilityState {
/// Accessibility Nodes
pub nodes: Vec<(AccessibilityId, Node)>,
Expand All @@ -19,12 +15,16 @@ pub struct AccessibilityState {
pub node_classes: NodeClassSet,

/// Current focused Accessibility Node.
pub focus: Option<AccessibilityId>,
pub focused_id: AccessibilityId,
}

impl AccessibilityState {
pub fn new() -> Self {
Self::default()
pub fn new(focused_id: AccessibilityId) -> Self {
Self {
focused_id,
node_classes: NodeClassSet::default(),
nodes: Vec::default(),
}
}

/// Wrap it in a `Arc<Mutex<T>>`.
Expand All @@ -47,12 +47,12 @@ impl AccessibilityProvider for AccessibilityState {
self.nodes.iter()
}

fn focus_id(&self) -> Option<AccessibilityId> {
self.focus
fn focus_id(&self) -> AccessibilityId {
self.focused_id
}

fn set_focus(&mut self, new_focus_id: Option<AccessibilityId>) {
self.focus = new_focus_id;
fn set_focus(&mut self, new_focus_id: AccessibilityId) {
self.focused_id = new_focus_id;
}

fn push_node(&mut self, id: AccessibilityId, node: Node) {
Expand Down
6 changes: 3 additions & 3 deletions crates/core/src/types.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
use crate::events::{DomEvent, FreyaEvent};
use dioxus_native_core::NodeId;

use accesskit::NodeId as AccessibilityId;
pub use accesskit::NodeId as AccessibilityId;
use rustc_hash::FxHashMap;
use smallvec::SmallVec;
use tokio::sync::mpsc::{UnboundedReceiver, UnboundedSender};
use tokio::sync::watch;

pub type FocusSender = watch::Sender<Option<AccessibilityId>>;
pub type FocusReceiver = watch::Receiver<Option<AccessibilityId>>;
pub type FocusSender = watch::Sender<AccessibilityId>;
pub type FocusReceiver = watch::Receiver<AccessibilityId>;
pub type EventEmitter = UnboundedSender<DomEvent>;
pub type EventReceiver = UnboundedReceiver<DomEvent>;
pub type EventsQueue = SmallVec<[FreyaEvent; 2]>;
Expand Down
3 changes: 1 addition & 2 deletions crates/devtools/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use freya_components::*;
use freya_core::node::{get_node_state, NodeState};
use freya_dom::prelude::SafeDOM;
use freya_elements::elements as dioxus_elements;
use freya_hooks::{use_init_accessibility, use_init_focus, use_init_theme, use_theme, DARK_THEME};
use freya_hooks::{use_init_accessibility, use_init_theme, use_theme, DARK_THEME};

use freya_renderer::HoveredNode;
use std::sync::Arc;
Expand Down Expand Up @@ -52,7 +52,6 @@ struct AppWithDevtoolsProps {

#[allow(non_snake_case)]
fn AppWithDevtools(cx: Scope<AppWithDevtoolsProps>) -> Element {
use_init_focus(cx);
use_init_accessibility(cx);

#[allow(non_snake_case)]
Expand Down
Loading

0 comments on commit 8796eab

Please sign in to comment.