Skip to content

Commit 5313860

Browse files
authored
feat!: Allow providing app_name, toolkit_name and toolkit_version in Tree, remove parameters from unix adapter constructor (#291)
1 parent 8d52a5f commit 5313860

File tree

13 files changed

+195
-56
lines changed

13 files changed

+195
-56
lines changed

AUTHORS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,4 @@
66
Matt Campbell
77
Arnold Loubriat
88
Google LLC
9+
Leonard de Ruijter

bindings/c/examples/sdl/hello_world.c

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ const accesskit_node_id WINDOW_ID = 0;
1616
const accesskit_node_id BUTTON_1_ID = 1;
1717
const accesskit_node_id BUTTON_2_ID = 2;
1818
const accesskit_node_id ANNOUNCEMENT_ID = 3;
19-
const accesskit_node_id INITIAL_FOCUS = BUTTON_1_ID;
19+
#define INITIAL_FOCUS BUTTON_1_ID
2020

2121
const accesskit_rect BUTTON_1_RECT = {20.0, 20.0, 100.0, 60.0};
2222

@@ -64,7 +64,7 @@ struct accesskit_sdl_adapter {
6464
};
6565

6666
void accesskit_sdl_adapter_init(struct accesskit_sdl_adapter *adapter,
67-
SDL_Window *window, const char *app_name,
67+
SDL_Window *window,
6868
accesskit_tree_update_factory source,
6969
void *source_userdata,
7070
accesskit_action_handler *handler) {
@@ -76,8 +76,8 @@ void accesskit_sdl_adapter_init(struct accesskit_sdl_adapter *adapter,
7676
adapter->adapter = accesskit_macos_subclassing_adapter_for_window(
7777
(void *)wmInfo.info.cocoa.window, source, source_userdata, handler);
7878
#elif defined(UNIX)
79-
adapter->adapter = accesskit_unix_adapter_new(
80-
app_name, "SDL", "2.0", source, source_userdata, false, handler);
79+
adapter->adapter =
80+
accesskit_unix_adapter_new(source, source_userdata, false, handler);
8181
#elif defined(_WIN32)
8282
SDL_SysWMinfo wmInfo;
8383
SDL_VERSION(&wmInfo.version);
@@ -229,7 +229,9 @@ accesskit_tree_update *window_state_build_initial_tree(
229229
build_button(BUTTON_2_ID, "Button 2", state->node_classes);
230230
accesskit_tree_update *result = accesskit_tree_update_with_capacity_and_focus(
231231
(state->announcement != NULL) ? 4 : 3, state->focus);
232-
accesskit_tree_update_set_tree(result, accesskit_tree_new(WINDOW_ID));
232+
accesskit_tree *tree = accesskit_tree_new(WINDOW_ID);
233+
accesskit_tree_set_app_name(tree, "Hello World");
234+
accesskit_tree_update_set_tree(result, tree);
233235
accesskit_tree_update_push_node(result, WINDOW_ID, root);
234236
accesskit_tree_update_push_node(result, BUTTON_1_ID, button_1);
235237
accesskit_tree_update_push_node(result, BUTTON_2_ID, button_2);
@@ -343,7 +345,7 @@ int main(int argc, char *argv[]) {
343345
struct action_handler_state action_handler = {user_event, window_id};
344346
struct accesskit_sdl_adapter adapter;
345347
accesskit_sdl_adapter_init(
346-
&adapter, window, "hello_world", build_initial_tree, &state,
348+
&adapter, window, build_initial_tree, &state,
347349
accesskit_action_handler_new(do_action, &action_handler));
348350
SDL_ShowWindow(window);
349351

bindings/c/examples/windows/hello_world.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ const accesskit_node_id WINDOW_ID = 0;
1111
const accesskit_node_id BUTTON_1_ID = 1;
1212
const accesskit_node_id BUTTON_2_ID = 2;
1313
const accesskit_node_id ANNOUNCEMENT_ID = 3;
14-
const accesskit_node_id INITIAL_FOCUS = BUTTON_1_ID;
14+
#define INITIAL_FOCUS BUTTON_1_ID
1515

1616
const accesskit_rect BUTTON_1_RECT = {20.0, 20.0, 100.0, 60.0};
1717

@@ -88,7 +88,9 @@ accesskit_tree_update *window_state_build_initial_tree(
8888
build_button(BUTTON_2_ID, "Button 2", state->node_classes);
8989
accesskit_tree_update *result = accesskit_tree_update_with_capacity_and_focus(
9090
(state->announcement != NULL) ? 4 : 3, state->focus);
91-
accesskit_tree_update_set_tree(result, accesskit_tree_new(WINDOW_ID));
91+
accesskit_tree *tree = accesskit_tree_new(WINDOW_ID);
92+
accesskit_tree_set_app_name(tree, "Hello World");
93+
accesskit_tree_update_set_tree(result, tree);
9294
accesskit_tree_update_push_node(result, WINDOW_ID, root);
9395
accesskit_tree_update_push_node(result, BUTTON_1_ID, button_1);
9496
accesskit_tree_update_push_node(result, BUTTON_2_ID, button_2);

bindings/c/src/common.rs

Lines changed: 92 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -851,24 +851,105 @@ impl node_builder {
851851
}
852852
}
853853

854-
#[repr(C)]
855854
pub struct tree {
856-
pub root: node_id,
855+
_private: [u8; 0],
857856
}
858857

858+
impl CastPtr for tree {
859+
type RustType = Tree;
860+
}
861+
862+
impl BoxCastPtr for tree {}
863+
859864
impl tree {
860865
#[no_mangle]
861-
pub extern "C" fn accesskit_tree_new(root: node_id) -> tree {
862-
tree { root }
866+
pub extern "C" fn accesskit_tree_new(root: node_id) -> *mut tree {
867+
let tree = Tree::new(root.into());
868+
BoxCastPtr::to_mut_ptr(tree)
863869
}
864-
}
865870

866-
impl From<tree> for Tree {
867-
fn from(tree: tree) -> Self {
868-
Self {
869-
root: tree.root.into(),
871+
#[no_mangle]
872+
pub extern "C" fn accesskit_tree_free(tree: *mut tree) {
873+
drop(box_from_ptr(tree));
874+
}
875+
876+
/// Caller must call `accesskit_string_free` with the return value.
877+
#[no_mangle]
878+
pub extern "C" fn accesskit_tree_get_app_name(tree: *const tree) -> *mut c_char {
879+
let tree = ref_from_ptr(tree);
880+
match tree.app_name.as_ref() {
881+
Some(value) => CString::new(value.clone()).unwrap().into_raw(),
882+
None => ptr::null_mut(),
870883
}
871884
}
885+
886+
#[no_mangle]
887+
pub extern "C" fn accesskit_tree_set_app_name(tree: *mut tree, app_name: *const c_char) {
888+
let tree = mut_from_ptr(tree);
889+
tree.app_name = Some(String::from(
890+
unsafe { CStr::from_ptr(app_name) }.to_string_lossy(),
891+
));
892+
}
893+
894+
#[no_mangle]
895+
pub extern "C" fn accesskit_tree_clear_app_name(tree: *mut tree) {
896+
let tree = mut_from_ptr(tree);
897+
tree.app_name = None;
898+
}
899+
900+
/// Caller must call `accesskit_string_free` with the return value.
901+
#[no_mangle]
902+
pub extern "C" fn accesskit_tree_get_toolkit_name(tree: *const tree) -> *mut c_char {
903+
let tree = ref_from_ptr(tree);
904+
match tree.toolkit_name.as_ref() {
905+
Some(value) => CString::new(value.clone()).unwrap().into_raw(),
906+
None => ptr::null_mut(),
907+
}
908+
}
909+
910+
#[no_mangle]
911+
pub extern "C" fn accesskit_tree_set_toolkit_name(
912+
tree: *mut tree,
913+
toolkit_name: *const c_char,
914+
) {
915+
let tree = mut_from_ptr(tree);
916+
tree.toolkit_name = Some(String::from(
917+
unsafe { CStr::from_ptr(toolkit_name) }.to_string_lossy(),
918+
));
919+
}
920+
921+
#[no_mangle]
922+
pub extern "C" fn accesskit_tree_clear_toolkit_name(tree: *mut tree) {
923+
let tree = mut_from_ptr(tree);
924+
tree.toolkit_name = None;
925+
}
926+
927+
/// Caller must call `accesskit_string_free` with the return value.
928+
#[no_mangle]
929+
pub extern "C" fn accesskit_tree_get_toolkit_version(tree: *const tree) -> *mut c_char {
930+
let tree = ref_from_ptr(tree);
931+
match tree.toolkit_version.as_ref() {
932+
Some(value) => CString::new(value.clone()).unwrap().into_raw(),
933+
None => ptr::null_mut(),
934+
}
935+
}
936+
937+
#[no_mangle]
938+
pub extern "C" fn accesskit_tree_set_toolkit_version(
939+
tree: *mut tree,
940+
toolkit_version: *const c_char,
941+
) {
942+
let tree = mut_from_ptr(tree);
943+
tree.toolkit_version = Some(String::from(
944+
unsafe { CStr::from_ptr(toolkit_version) }.to_string_lossy(),
945+
));
946+
}
947+
948+
#[no_mangle]
949+
pub extern "C" fn accesskit_tree_clear_toolkit_version(tree: *mut tree) {
950+
let tree = mut_from_ptr(tree);
951+
tree.toolkit_version = None;
952+
}
872953
}
873954

874955
pub struct tree_update {
@@ -924,9 +1005,9 @@ impl tree_update {
9241005
}
9251006

9261007
#[no_mangle]
927-
pub extern "C" fn accesskit_tree_update_set_tree(update: *mut tree_update, tree: tree) {
1008+
pub extern "C" fn accesskit_tree_update_set_tree(update: *mut tree_update, tree: *mut tree) {
9281009
let update = mut_from_ptr(update);
929-
update.tree = Some(tree.into());
1010+
update.tree = Some(*box_from_ptr(tree));
9301011
}
9311012

9321013
#[no_mangle]

bindings/c/src/unix.rs

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,7 @@ use crate::{
99
};
1010
use accesskit::Rect;
1111
use accesskit_unix::Adapter;
12-
use std::{
13-
ffi::CStr,
14-
os::raw::{c_char, c_void},
15-
ptr,
16-
};
12+
use std::{os::raw::c_void, ptr};
1713

1814
pub struct unix_adapter {
1915
_private: [u8; 0],
@@ -26,27 +22,17 @@ impl CastPtr for unix_adapter {
2622
impl BoxCastPtr for unix_adapter {}
2723

2824
impl unix_adapter {
29-
/// Caller is responsible for freeing `app_name`, `toolkit_name` and `toolkit_version`.
3025
/// This function will take ownership of the pointer returned by `initial_state`, which can't be null.
3126
#[no_mangle]
3227
pub extern "C" fn accesskit_unix_adapter_new(
33-
app_name: *const c_char,
34-
toolkit_name: *const c_char,
35-
toolkit_version: *const c_char,
3628
initial_state: tree_update_factory,
3729
initial_state_userdata: *mut c_void,
3830
is_window_focused: bool,
3931
handler: *mut action_handler,
4032
) -> *mut unix_adapter {
41-
let app_name = unsafe { CStr::from_ptr(app_name).to_string_lossy().into() };
42-
let toolkit_name = unsafe { CStr::from_ptr(toolkit_name).to_string_lossy().into() };
43-
let toolkit_version = unsafe { CStr::from_ptr(toolkit_version).to_string_lossy().into() };
4433
let initial_state = initial_state.unwrap();
4534
let handler = box_from_ptr(handler);
4635
let adapter = Adapter::new(
47-
app_name,
48-
toolkit_name,
49-
toolkit_version,
5036
move || *box_from_ptr(initial_state(initial_state_userdata)),
5137
is_window_focused,
5238
handler,

common/src/lib.rs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2236,13 +2236,25 @@ impl JsonSchema for Node {
22362236
#[cfg_attr(feature = "serde", serde(deny_unknown_fields))]
22372237
#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
22382238
pub struct Tree {
2239+
/// The identifier of the tree's root node.
22392240
pub root: NodeId,
2241+
/// The name of the application this tree belongs to.
2242+
pub app_name: Option<String>,
2243+
/// The name of the UI toolkit in use.
2244+
pub toolkit_name: Option<String>,
2245+
/// The version of the UI toolkit.
2246+
pub toolkit_version: Option<String>,
22402247
}
22412248

22422249
impl Tree {
22432250
#[inline]
22442251
pub fn new(root: NodeId) -> Tree {
2245-
Tree { root }
2252+
Tree {
2253+
root,
2254+
app_name: None,
2255+
toolkit_name: None,
2256+
toolkit_version: None,
2257+
}
22462258
}
22472259
}
22482260

consumer/src/tree.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,18 @@ impl State {
258258
pub fn focus(&self) -> Option<Node<'_>> {
259259
self.focus_id().map(|id| self.node_by_id(id).unwrap())
260260
}
261+
262+
pub fn app_name(&self) -> Option<String> {
263+
self.data.app_name.clone()
264+
}
265+
266+
pub fn toolkit_name(&self) -> Option<String> {
267+
self.data.toolkit_name.clone()
268+
}
269+
270+
pub fn toolkit_version(&self) -> Option<String> {
271+
self.data.toolkit_version.clone()
272+
}
261273
}
262274

263275
pub trait ChangeHandler {

platforms/unix/src/adapter.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -209,9 +209,6 @@ pub struct Adapter {
209209
impl Adapter {
210210
/// Create a new Unix adapter.
211211
pub fn new(
212-
app_name: String,
213-
toolkit_name: String,
214-
toolkit_version: String,
215212
initial_state: impl 'static + FnOnce() -> TreeUpdate,
216213
is_window_focused: bool,
217214
action_handler: Box<dyn ActionHandler + Send>,
@@ -230,7 +227,11 @@ impl Adapter {
230227
let tree = Tree::new(initial_state(), is_window_focused);
231228
let id = NEXT_ADAPTER_ID.fetch_add(1, Ordering::SeqCst);
232229
let root_id = tree.state().root_id();
233-
let app_context = AppContext::get_or_init(app_name, toolkit_name, toolkit_version);
230+
let app_context = AppContext::get_or_init(
231+
tree.state().app_name().unwrap_or_default(),
232+
tree.state().toolkit_name().unwrap_or_default(),
233+
tree.state().toolkit_version().unwrap_or_default(),
234+
);
234235
let context = Context::new(tree, action_handler, &app_context);
235236
let adapter_index = app_context.write().unwrap().push_adapter(id, &context);
236237
block_on(async {

platforms/windows/examples/hello_world.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,13 +105,16 @@ impl InnerWindowState {
105105
let root = self.build_root();
106106
let button_1 = build_button(BUTTON_1_ID, "Button 1", &mut self.node_classes);
107107
let button_2 = build_button(BUTTON_2_ID, "Button 2", &mut self.node_classes);
108+
let mut tree = Tree::new(WINDOW_ID);
109+
tree.app_name = Some(env!("CARGO_BIN_NAME").to_string());
110+
108111
let mut result = TreeUpdate {
109112
nodes: vec![
110113
(WINDOW_ID, root),
111114
(BUTTON_1_ID, button_1),
112115
(BUTTON_2_ID, button_2),
113116
],
114-
tree: Some(Tree::new(WINDOW_ID)),
117+
tree: Some(tree),
115118
focus: self.focus,
116119
};
117120
if let Some(announcement) = &self.announcement {

platforms/windows/src/node.rs

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -524,6 +524,19 @@ impl PlatformNode {
524524
})
525525
}
526526

527+
fn resolve_with_tree_state_and_context<F, T>(&self, f: F) -> Result<T>
528+
where
529+
for<'a> F: FnOnce(Node<'a>, &TreeState, &Context) -> Result<T>,
530+
{
531+
self.with_tree_state_and_context(|state, context| {
532+
if let Some(node) = state.node_by_id(self.node_id) {
533+
f(node, state, context)
534+
} else {
535+
Err(element_not_available())
536+
}
537+
})
538+
}
539+
527540
fn resolve<F, T>(&self, f: F) -> Result<T>
528541
where
529542
for<'a> F: FnOnce(Node<'a>) -> Result<T>,
@@ -597,16 +610,25 @@ impl IRawElementProviderSimple_Impl for PlatformNode {
597610
}
598611

599612
fn GetPropertyValue(&self, property_id: UIA_PROPERTY_ID) -> Result<VARIANT> {
600-
self.resolve_with_context(|node, context| {
613+
self.resolve_with_tree_state_and_context(|node, state, context| {
601614
let wrapper = NodeWrapper::Node(&node);
602615
let mut result = wrapper.get_property_value(property_id);
603-
if result.is_empty() && node.is_root() {
604-
match property_id {
605-
UIA_NamePropertyId => {
606-
result = window_title(context.hwnd).into();
616+
if result.is_empty() {
617+
if node.is_root() {
618+
match property_id {
619+
UIA_NamePropertyId => {
620+
result = window_title(context.hwnd).into();
621+
}
622+
UIA_NativeWindowHandlePropertyId => {
623+
result = (context.hwnd.0 as i32).into();
624+
}
625+
_ => (),
607626
}
608-
UIA_NativeWindowHandlePropertyId => {
609-
result = (context.hwnd.0 as i32).into();
627+
}
628+
match property_id {
629+
UIA_FrameworkIdPropertyId => result = state.toolkit_name().into(),
630+
UIA_ProviderDescriptionPropertyId => {
631+
result = app_and_toolkit_description(state).into()
610632
}
611633
_ => (),
612634
}

0 commit comments

Comments
 (0)