Skip to content
This repository has been archived by the owner on Jul 15, 2024. It is now read-only.

Update to AccessKit 0.12 #173

Merged
merged 2 commits into from
Nov 23, 2023
Merged
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
6 changes: 3 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -56,13 +56,13 @@ memchr = "2.5"

# Optional dependencies
raw-window-handle = { version = "0.5.0", default_features = false }
accesskit = { version = "0.11.0", optional = true }
accesskit = { version = "0.12.0", optional = true }
once_cell = { version = "1", optional = true }

[target.'cfg(target_os="windows")'.dependencies]
scopeguard = "1.1.0"
wio = "0.2.2"
accesskit_windows = { version = "0.14.0", optional = true }
accesskit_windows = { version = "0.15.0", optional = true }
once_cell = "1"

[target.'cfg(target_os="windows")'.dependencies.winapi]
Expand Down Expand Up @@ -93,7 +93,7 @@ cocoa = "0.25.0"
objc = "0.2.7"
core-graphics = "0.23.0"
bitflags = "2.0.0"
accesskit_macos = { version = "0.9.0", optional = true }
accesskit_macos = { version = "0.10.0", optional = true }

[target.'cfg(any(target_os = "freebsd", target_os="linux", target_os="openbsd"))'.dependencies]
ashpd = { version = "0.5", optional = true }
Expand Down
43 changes: 12 additions & 31 deletions examples/accesskit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,11 @@
// See the License for the specific language governing permissions and
// limitations under the License.

use std::{any::Any, num::NonZeroU128};
use std::any::Any;

use accesskit::{
Action, ActionRequest, CheckedState, DefaultActionVerb, Node, NodeBuilder, NodeClassSet,
NodeId, Rect, Role, Tree, TreeUpdate,
Action, ActionRequest, Checked, DefaultActionVerb, Node, NodeBuilder, NodeClassSet, NodeId,
Rect, Role, Tree, TreeUpdate,
};

use glazier::kurbo::Size;
Expand All @@ -25,9 +25,9 @@ use glazier::{Application, KbKey, KeyEvent, Region, WinHandler, WindowBuilder, W

const WINDOW_TITLE: &str = "Hello world";

const WINDOW_ID: NodeId = NodeId(unsafe { NonZeroU128::new_unchecked(1) });
const CHECKBOX_1_ID: NodeId = NodeId(unsafe { NonZeroU128::new_unchecked(2) });
const CHECKBOX_2_ID: NodeId = NodeId(unsafe { NonZeroU128::new_unchecked(3) });
const WINDOW_ID: NodeId = NodeId(0);
const CHECKBOX_1_ID: NodeId = NodeId(1);
const CHECKBOX_2_ID: NodeId = NodeId(2);
const INITIAL_FOCUS: NodeId = CHECKBOX_1_ID;

const CHECKBOX_1_NAME: &str = "Checkbox 1";
Expand Down Expand Up @@ -59,18 +59,17 @@ fn build_checkbox(id: NodeId, checked: bool, classes: &mut NodeClassSet) -> Node
builder.set_name(name);
builder.add_action(Action::Focus);
builder.set_default_action_verb(DefaultActionVerb::Click);
builder.set_checked_state(if checked {
CheckedState::True
builder.set_checked(if checked {
Checked::True
} else {
CheckedState::False
Checked::False
});
builder.build(classes)
}

struct HelloState {
size: Size,
focus: NodeId,
is_window_focused: bool,
checkbox_1_checked: bool,
checkbox_2_checked: bool,
handle: WindowHandle,
Expand All @@ -82,23 +81,18 @@ impl HelloState {
Self {
size: Default::default(),
focus: INITIAL_FOCUS,
is_window_focused: false,
checkbox_1_checked: false,
checkbox_2_checked: false,
handle: Default::default(),
node_classes: NodeClassSet::new(),
}
}

fn accesskit_focus(&self) -> Option<NodeId> {
self.is_window_focused.then_some(self.focus)
}

fn update_accesskit_focus(&self) {
self.handle.update_accesskit_if_active(|| TreeUpdate {
nodes: vec![],
tree: None,
focus: self.accesskit_focus(),
focus: self.focus,
});
}

Expand All @@ -114,10 +108,7 @@ impl HelloState {
}
_ => unreachable!(),
};
// We have to be slightly less lazy here than we'd like because we can't
// borrow self immutably inside the closure while we have a mutable
// borrow of self.node_classes. TBD: Does this indicate a design flaw?
let focus = self.accesskit_focus();
let focus = self.focus;
let node_classes = &mut self.node_classes;
self.handle.update_accesskit_if_active(|| {
let node = build_checkbox(id, checked, node_classes);
Expand Down Expand Up @@ -163,7 +154,7 @@ impl WinHandler for HelloState {
(CHECKBOX_2_ID, checkbox_2),
],
tree: Some(Tree::new(WINDOW_ID)),
focus: self.accesskit_focus(),
focus: self.focus,
}
}

Expand All @@ -188,16 +179,6 @@ impl WinHandler for HelloState {
self.size = size;
}

fn got_focus(&mut self) {
self.is_window_focused = true;
self.update_accesskit_focus();
}

fn lost_focus(&mut self) {
self.is_window_focused = false;
self.update_accesskit_focus();
}

fn accesskit_action(&mut self, request: ActionRequest) {
if let ActionRequest {
action,
Expand Down
11 changes: 10 additions & 1 deletion examples/edit_text.rs
Original file line number Diff line number Diff line change
Expand Up @@ -327,7 +327,16 @@ impl WinHandler for WindowState {
#[cfg(feature = "accesskit")]
fn accesskit_tree(&mut self) -> TreeUpdate {
// TODO: Construct a real TreeUpdate
TreeUpdate::default()
use accesskit::{NodeBuilder, NodeClassSet, NodeId, Role, Tree};
let builder = NodeBuilder::new(Role::Window);
let mut node_classes = NodeClassSet::new();
let node = builder.build(&mut node_classes);
const WINDOW_ID: NodeId = NodeId(0);
TreeUpdate {
nodes: vec![(WINDOW_ID, node)],
tree: Some(Tree::new(WINDOW_ID)),
focus: WINDOW_ID,
}
}

fn size(&mut self, size: Size) {
Expand Down
11 changes: 10 additions & 1 deletion examples/pen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,16 @@ impl WinHandler for WindowState {
#[cfg(feature = "accesskit")]
fn accesskit_tree(&mut self) -> TreeUpdate {
// TODO: Construct a real TreeUpdate
TreeUpdate::default()
use accesskit::{NodeBuilder, NodeClassSet, NodeId, Role, Tree};
let builder = NodeBuilder::new(Role::Window);
let mut node_classes = NodeClassSet::new();
let node = builder.build(&mut node_classes);
const WINDOW_ID: NodeId = NodeId(0);
TreeUpdate {
nodes: vec![(WINDOW_ID, node)],
tree: Some(Tree::new(WINDOW_ID)),
focus: WINDOW_ID,
}
}

fn idle(&mut self, _: IdleToken) {
Expand Down
11 changes: 10 additions & 1 deletion examples/shello.rs
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,16 @@ impl WinHandler for WindowState {
#[cfg(feature = "accesskit")]
fn accesskit_tree(&mut self) -> TreeUpdate {
// TODO: Construct a real TreeUpdate
TreeUpdate::default()
use accesskit::{NodeBuilder, NodeClassSet, NodeId, Role, Tree};
let builder = NodeBuilder::new(Role::Window);
let mut node_classes = NodeClassSet::new();
let node = builder.build(&mut node_classes);
const WINDOW_ID: NodeId = NodeId(0);
TreeUpdate {
nodes: vec![(WINDOW_ID, node)],
tree: Some(Tree::new(WINDOW_ID)),
focus: WINDOW_ID,
}
}

fn idle(&mut self, _: IdleToken) {}
Expand Down
11 changes: 10 additions & 1 deletion examples/wgpu-triangle/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,16 @@ impl WinHandler for WindowState {
#[cfg(feature = "accesskit")]
fn accesskit_tree(&mut self) -> TreeUpdate {
// TODO: Construct a real TreeUpdate
TreeUpdate::default()
use accesskit::{NodeBuilder, NodeClassSet, NodeId, Role, Tree};
let builder = NodeBuilder::new(Role::Window);
let mut node_classes = NodeClassSet::new();
let node = builder.build(&mut node_classes);
const WINDOW_ID: NodeId = NodeId(0);
TreeUpdate {
nodes: vec![(WINDOW_ID, node)],
tree: Some(Tree::new(WINDOW_ID)),
focus: WINDOW_ID,
}
}

fn idle(&mut self, _: IdleToken) {}
Expand Down
26 changes: 24 additions & 2 deletions src/backend/mac/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,8 @@ struct ViewState {
parent: Option<crate::WindowHandle>,
#[cfg(feature = "accesskit")]
accesskit_adapter: OnceCell<AccessKitAdapter>,
#[cfg(feature = "accesskit")]
is_focused: bool,
}

#[derive(Clone, PartialEq, Eq)]
Expand Down Expand Up @@ -650,6 +652,8 @@ fn make_view(handler: Box<dyn WinHandler>) -> (id, Weak<Mutex<Vec<IdleKind>>>) {
parent: None,
#[cfg(feature = "accesskit")]
accesskit_adapter: OnceCell::new(),
#[cfg(feature = "accesskit")]
is_focused: false,
};
let state_ptr = Box::into_raw(Box::new(state));
(*view).set_ivar("viewState", state_ptr as *mut c_void);
Expand Down Expand Up @@ -1105,6 +1109,14 @@ extern "C" fn window_did_become_key(this: &mut Object, _: Sel, _notification: id
let view_state: *mut c_void = *this.get_ivar("viewState");
let view_state = &mut *(view_state as *mut ViewState);
view_state.handler.got_focus();
#[cfg(feature = "accesskit")]
{
view_state.is_focused = true;
if let Some(adapter) = view_state.accesskit_adapter.get() {
let events = adapter.update_view_focus_state(true);
events.raise();
}
}
}
}

Expand All @@ -1113,6 +1125,14 @@ extern "C" fn window_did_resign_key(this: &mut Object, _: Sel, _notification: id
let view_state: *mut c_void = *this.get_ivar("viewState");
let view_state = &mut *(view_state as *mut ViewState);
view_state.handler.lost_focus();
#[cfg(feature = "accesskit")]
{
view_state.is_focused = false;
if let Some(adapter) = view_state.accesskit_adapter.get() {
let events = adapter.update_view_focus_state(false);
events.raise();
}
}
}
}

Expand Down Expand Up @@ -1596,7 +1616,7 @@ impl IdleHandle {

#[cfg(feature = "accesskit")]
impl accesskit::ActionHandler for AccessKitActionHandler {
fn do_action(&self, request: accesskit::ActionRequest) {
fn do_action(&mut self, request: accesskit::ActionRequest) {
self.idle_handle.add_idle_callback(move |handler| {
handler.accesskit_action(request);
});
Expand All @@ -1616,14 +1636,16 @@ impl ViewState {
}
let view = view as *mut Object as *mut c_void;
let initial_state = self.handler.accesskit_tree();
let is_focused = self.is_focused;
let idle_handle = IdleHandle {
nsview: self.nsview.clone(),
idle_queue: Arc::downgrade(&self.idle_queue),
};
let action_handler = Box::new(AccessKitActionHandler { idle_handle });
// SAFETY: The view pointer is based on a valid borrowed reference
// to the view.
let adapter = unsafe { AccessKitAdapter::new(view, initial_state, action_handler) };
let adapter =
unsafe { AccessKitAdapter::new(view, initial_state, is_focused, action_handler) };
match self.accesskit_adapter.try_insert(adapter) {
Ok(adapter) => adapter,
Err((old_adapter, _)) => {
Expand Down
32 changes: 31 additions & 1 deletion src/backend/windows/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,8 @@ struct WindowState {
uia_init_marker: UiaInitMarker, // zero size
#[cfg(feature = "accesskit")]
accesskit_adapter: OnceCell<AccessKitAdapter>,
#[cfg(feature = "accesskit")]
is_focused: Cell<bool>,
}

impl std::fmt::Debug for WindowState {
Expand Down Expand Up @@ -737,10 +739,34 @@ impl WndProc for MyWndProc {
WM_ERASEBKGND => Some(0),
WM_SETFOCUS => {
self.with_wnd_state(|s| s.handler.got_focus());
#[cfg(feature = "accesskit")]
{
let handle = self.handle.borrow();
if let Some(state) = handle.state.upgrade() {
state.is_focused.set(true);
if let Some(adapter) = state.accesskit_adapter.get() {
let events = adapter.update_window_focus_state(true);
drop(handle);
events.raise();
}
}
}
Some(0)
}
WM_KILLFOCUS => {
self.with_wnd_state(|s| s.handler.lost_focus());
#[cfg(feature = "accesskit")]
{
let handle = self.handle.borrow();
if let Some(state) = handle.state.upgrade() {
state.is_focused.set(false);
if let Some(adapter) = state.accesskit_adapter.get() {
let events = adapter.update_window_focus_state(false);
drop(handle);
events.raise();
}
}
}
Some(0)
}
WM_PAINT => unsafe {
Expand Down Expand Up @@ -1187,6 +1213,7 @@ impl WndProc for MyWndProc {
let wparam = accesskit_windows::WPARAM(wparam);
let lparam = accesskit_windows::LPARAM(lparam);
let idle_queue = &state.idle_queue;
let is_focused = state.is_focused.get();
let uia_init_marker = state.uia_init_marker; // zero size and Copy
state
.accesskit_adapter
Expand All @@ -1202,6 +1229,7 @@ impl WndProc for MyWndProc {
AccessKitAdapter::new(
hwnd,
initial_tree_state,
is_focused,
action_handler,
uia_init_marker,
)
Expand Down Expand Up @@ -1391,6 +1419,8 @@ impl WindowBuilder {
uia_init_marker: UiaInitMarker::new(),
#[cfg(feature = "accesskit")]
accesskit_adapter: OnceCell::new(),
#[cfg(feature = "accesskit")]
is_focused: Cell::new(false),
};
let win = Rc::new(window);
let handle = WindowHandle {
Expand Down Expand Up @@ -2087,7 +2117,7 @@ impl IdleHandle {

#[cfg(feature = "accesskit")]
impl accesskit::ActionHandler for AccessKitActionHandler {
fn do_action(&self, request: accesskit::ActionRequest) {
fn do_action(&mut self, request: accesskit::ActionRequest) {
self.idle_handle.add_idle_callback(move |handler| {
handler.accesskit_action(request);
});
Expand Down