Skip to content

Commit

Permalink
feat!: Allow providing app_name, toolkit_name and toolkit_version in …
Browse files Browse the repository at this point in the history
…Tree, remove parameters from unix adapter constructor (#291)
  • Loading branch information
LeonarddeR authored Sep 27, 2023
1 parent 8d52a5f commit 5313860
Show file tree
Hide file tree
Showing 13 changed files with 195 additions and 56 deletions.
1 change: 1 addition & 0 deletions AUTHORS
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@
Matt Campbell
Arnold Loubriat
Google LLC
Leonard de Ruijter
14 changes: 8 additions & 6 deletions bindings/c/examples/sdl/hello_world.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ const accesskit_node_id WINDOW_ID = 0;
const accesskit_node_id BUTTON_1_ID = 1;
const accesskit_node_id BUTTON_2_ID = 2;
const accesskit_node_id ANNOUNCEMENT_ID = 3;
const accesskit_node_id INITIAL_FOCUS = BUTTON_1_ID;
#define INITIAL_FOCUS BUTTON_1_ID

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

Expand Down Expand Up @@ -64,7 +64,7 @@ struct accesskit_sdl_adapter {
};

void accesskit_sdl_adapter_init(struct accesskit_sdl_adapter *adapter,
SDL_Window *window, const char *app_name,
SDL_Window *window,
accesskit_tree_update_factory source,
void *source_userdata,
accesskit_action_handler *handler) {
Expand All @@ -76,8 +76,8 @@ void accesskit_sdl_adapter_init(struct accesskit_sdl_adapter *adapter,
adapter->adapter = accesskit_macos_subclassing_adapter_for_window(
(void *)wmInfo.info.cocoa.window, source, source_userdata, handler);
#elif defined(UNIX)
adapter->adapter = accesskit_unix_adapter_new(
app_name, "SDL", "2.0", source, source_userdata, false, handler);
adapter->adapter =
accesskit_unix_adapter_new(source, source_userdata, false, handler);
#elif defined(_WIN32)
SDL_SysWMinfo wmInfo;
SDL_VERSION(&wmInfo.version);
Expand Down Expand Up @@ -229,7 +229,9 @@ accesskit_tree_update *window_state_build_initial_tree(
build_button(BUTTON_2_ID, "Button 2", state->node_classes);
accesskit_tree_update *result = accesskit_tree_update_with_capacity_and_focus(
(state->announcement != NULL) ? 4 : 3, state->focus);
accesskit_tree_update_set_tree(result, accesskit_tree_new(WINDOW_ID));
accesskit_tree *tree = accesskit_tree_new(WINDOW_ID);
accesskit_tree_set_app_name(tree, "Hello World");
accesskit_tree_update_set_tree(result, tree);
accesskit_tree_update_push_node(result, WINDOW_ID, root);
accesskit_tree_update_push_node(result, BUTTON_1_ID, button_1);
accesskit_tree_update_push_node(result, BUTTON_2_ID, button_2);
Expand Down Expand Up @@ -343,7 +345,7 @@ int main(int argc, char *argv[]) {
struct action_handler_state action_handler = {user_event, window_id};
struct accesskit_sdl_adapter adapter;
accesskit_sdl_adapter_init(
&adapter, window, "hello_world", build_initial_tree, &state,
&adapter, window, build_initial_tree, &state,
accesskit_action_handler_new(do_action, &action_handler));
SDL_ShowWindow(window);

Expand Down
6 changes: 4 additions & 2 deletions bindings/c/examples/windows/hello_world.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ const accesskit_node_id WINDOW_ID = 0;
const accesskit_node_id BUTTON_1_ID = 1;
const accesskit_node_id BUTTON_2_ID = 2;
const accesskit_node_id ANNOUNCEMENT_ID = 3;
const accesskit_node_id INITIAL_FOCUS = BUTTON_1_ID;
#define INITIAL_FOCUS BUTTON_1_ID

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

Expand Down Expand Up @@ -88,7 +88,9 @@ accesskit_tree_update *window_state_build_initial_tree(
build_button(BUTTON_2_ID, "Button 2", state->node_classes);
accesskit_tree_update *result = accesskit_tree_update_with_capacity_and_focus(
(state->announcement != NULL) ? 4 : 3, state->focus);
accesskit_tree_update_set_tree(result, accesskit_tree_new(WINDOW_ID));
accesskit_tree *tree = accesskit_tree_new(WINDOW_ID);
accesskit_tree_set_app_name(tree, "Hello World");
accesskit_tree_update_set_tree(result, tree);
accesskit_tree_update_push_node(result, WINDOW_ID, root);
accesskit_tree_update_push_node(result, BUTTON_1_ID, button_1);
accesskit_tree_update_push_node(result, BUTTON_2_ID, button_2);
Expand Down
103 changes: 92 additions & 11 deletions bindings/c/src/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -851,24 +851,105 @@ impl node_builder {
}
}

#[repr(C)]
pub struct tree {
pub root: node_id,
_private: [u8; 0],
}

impl CastPtr for tree {
type RustType = Tree;
}

impl BoxCastPtr for tree {}

impl tree {
#[no_mangle]
pub extern "C" fn accesskit_tree_new(root: node_id) -> tree {
tree { root }
pub extern "C" fn accesskit_tree_new(root: node_id) -> *mut tree {
let tree = Tree::new(root.into());
BoxCastPtr::to_mut_ptr(tree)
}
}

impl From<tree> for Tree {
fn from(tree: tree) -> Self {
Self {
root: tree.root.into(),
#[no_mangle]
pub extern "C" fn accesskit_tree_free(tree: *mut tree) {
drop(box_from_ptr(tree));
}

/// Caller must call `accesskit_string_free` with the return value.
#[no_mangle]
pub extern "C" fn accesskit_tree_get_app_name(tree: *const tree) -> *mut c_char {
let tree = ref_from_ptr(tree);
match tree.app_name.as_ref() {
Some(value) => CString::new(value.clone()).unwrap().into_raw(),
None => ptr::null_mut(),
}
}

#[no_mangle]
pub extern "C" fn accesskit_tree_set_app_name(tree: *mut tree, app_name: *const c_char) {
let tree = mut_from_ptr(tree);
tree.app_name = Some(String::from(
unsafe { CStr::from_ptr(app_name) }.to_string_lossy(),
));
}

#[no_mangle]
pub extern "C" fn accesskit_tree_clear_app_name(tree: *mut tree) {
let tree = mut_from_ptr(tree);
tree.app_name = None;
}

/// Caller must call `accesskit_string_free` with the return value.
#[no_mangle]
pub extern "C" fn accesskit_tree_get_toolkit_name(tree: *const tree) -> *mut c_char {
let tree = ref_from_ptr(tree);
match tree.toolkit_name.as_ref() {
Some(value) => CString::new(value.clone()).unwrap().into_raw(),
None => ptr::null_mut(),
}
}

#[no_mangle]
pub extern "C" fn accesskit_tree_set_toolkit_name(
tree: *mut tree,
toolkit_name: *const c_char,
) {
let tree = mut_from_ptr(tree);
tree.toolkit_name = Some(String::from(
unsafe { CStr::from_ptr(toolkit_name) }.to_string_lossy(),
));
}

#[no_mangle]
pub extern "C" fn accesskit_tree_clear_toolkit_name(tree: *mut tree) {
let tree = mut_from_ptr(tree);
tree.toolkit_name = None;
}

/// Caller must call `accesskit_string_free` with the return value.
#[no_mangle]
pub extern "C" fn accesskit_tree_get_toolkit_version(tree: *const tree) -> *mut c_char {
let tree = ref_from_ptr(tree);
match tree.toolkit_version.as_ref() {
Some(value) => CString::new(value.clone()).unwrap().into_raw(),
None => ptr::null_mut(),
}
}

#[no_mangle]
pub extern "C" fn accesskit_tree_set_toolkit_version(
tree: *mut tree,
toolkit_version: *const c_char,
) {
let tree = mut_from_ptr(tree);
tree.toolkit_version = Some(String::from(
unsafe { CStr::from_ptr(toolkit_version) }.to_string_lossy(),
));
}

#[no_mangle]
pub extern "C" fn accesskit_tree_clear_toolkit_version(tree: *mut tree) {
let tree = mut_from_ptr(tree);
tree.toolkit_version = None;
}
}

pub struct tree_update {
Expand Down Expand Up @@ -924,9 +1005,9 @@ impl tree_update {
}

#[no_mangle]
pub extern "C" fn accesskit_tree_update_set_tree(update: *mut tree_update, tree: tree) {
pub extern "C" fn accesskit_tree_update_set_tree(update: *mut tree_update, tree: *mut tree) {
let update = mut_from_ptr(update);
update.tree = Some(tree.into());
update.tree = Some(*box_from_ptr(tree));
}

#[no_mangle]
Expand Down
16 changes: 1 addition & 15 deletions bindings/c/src/unix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,7 @@ use crate::{
};
use accesskit::Rect;
use accesskit_unix::Adapter;
use std::{
ffi::CStr,
os::raw::{c_char, c_void},
ptr,
};
use std::{os::raw::c_void, ptr};

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

impl unix_adapter {
/// Caller is responsible for freeing `app_name`, `toolkit_name` and `toolkit_version`.
/// This function will take ownership of the pointer returned by `initial_state`, which can't be null.
#[no_mangle]
pub extern "C" fn accesskit_unix_adapter_new(
app_name: *const c_char,
toolkit_name: *const c_char,
toolkit_version: *const c_char,
initial_state: tree_update_factory,
initial_state_userdata: *mut c_void,
is_window_focused: bool,
handler: *mut action_handler,
) -> *mut unix_adapter {
let app_name = unsafe { CStr::from_ptr(app_name).to_string_lossy().into() };
let toolkit_name = unsafe { CStr::from_ptr(toolkit_name).to_string_lossy().into() };
let toolkit_version = unsafe { CStr::from_ptr(toolkit_version).to_string_lossy().into() };
let initial_state = initial_state.unwrap();
let handler = box_from_ptr(handler);
let adapter = Adapter::new(
app_name,
toolkit_name,
toolkit_version,
move || *box_from_ptr(initial_state(initial_state_userdata)),
is_window_focused,
handler,
Expand Down
14 changes: 13 additions & 1 deletion common/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2236,13 +2236,25 @@ impl JsonSchema for Node {
#[cfg_attr(feature = "serde", serde(deny_unknown_fields))]
#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
pub struct Tree {
/// The identifier of the tree's root node.
pub root: NodeId,
/// The name of the application this tree belongs to.
pub app_name: Option<String>,
/// The name of the UI toolkit in use.
pub toolkit_name: Option<String>,
/// The version of the UI toolkit.
pub toolkit_version: Option<String>,
}

impl Tree {
#[inline]
pub fn new(root: NodeId) -> Tree {
Tree { root }
Tree {
root,
app_name: None,
toolkit_name: None,
toolkit_version: None,
}
}
}

Expand Down
12 changes: 12 additions & 0 deletions consumer/src/tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,18 @@ impl State {
pub fn focus(&self) -> Option<Node<'_>> {
self.focus_id().map(|id| self.node_by_id(id).unwrap())
}

pub fn app_name(&self) -> Option<String> {
self.data.app_name.clone()
}

pub fn toolkit_name(&self) -> Option<String> {
self.data.toolkit_name.clone()
}

pub fn toolkit_version(&self) -> Option<String> {
self.data.toolkit_version.clone()
}
}

pub trait ChangeHandler {
Expand Down
9 changes: 5 additions & 4 deletions platforms/unix/src/adapter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -209,9 +209,6 @@ pub struct Adapter {
impl Adapter {
/// Create a new Unix adapter.
pub fn new(
app_name: String,
toolkit_name: String,
toolkit_version: String,
initial_state: impl 'static + FnOnce() -> TreeUpdate,
is_window_focused: bool,
action_handler: Box<dyn ActionHandler + Send>,
Expand All @@ -230,7 +227,11 @@ impl Adapter {
let tree = Tree::new(initial_state(), is_window_focused);
let id = NEXT_ADAPTER_ID.fetch_add(1, Ordering::SeqCst);
let root_id = tree.state().root_id();
let app_context = AppContext::get_or_init(app_name, toolkit_name, toolkit_version);
let app_context = AppContext::get_or_init(
tree.state().app_name().unwrap_or_default(),
tree.state().toolkit_name().unwrap_or_default(),
tree.state().toolkit_version().unwrap_or_default(),
);
let context = Context::new(tree, action_handler, &app_context);
let adapter_index = app_context.write().unwrap().push_adapter(id, &context);
block_on(async {
Expand Down
5 changes: 4 additions & 1 deletion platforms/windows/examples/hello_world.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,13 +105,16 @@ impl InnerWindowState {
let root = self.build_root();
let button_1 = build_button(BUTTON_1_ID, "Button 1", &mut self.node_classes);
let button_2 = build_button(BUTTON_2_ID, "Button 2", &mut self.node_classes);
let mut tree = Tree::new(WINDOW_ID);
tree.app_name = Some(env!("CARGO_BIN_NAME").to_string());

let mut result = TreeUpdate {
nodes: vec![
(WINDOW_ID, root),
(BUTTON_1_ID, button_1),
(BUTTON_2_ID, button_2),
],
tree: Some(Tree::new(WINDOW_ID)),
tree: Some(tree),
focus: self.focus,
};
if let Some(announcement) = &self.announcement {
Expand Down
36 changes: 29 additions & 7 deletions platforms/windows/src/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -524,6 +524,19 @@ impl PlatformNode {
})
}

fn resolve_with_tree_state_and_context<F, T>(&self, f: F) -> Result<T>
where
for<'a> F: FnOnce(Node<'a>, &TreeState, &Context) -> Result<T>,
{
self.with_tree_state_and_context(|state, context| {
if let Some(node) = state.node_by_id(self.node_id) {
f(node, state, context)
} else {
Err(element_not_available())
}
})
}

fn resolve<F, T>(&self, f: F) -> Result<T>
where
for<'a> F: FnOnce(Node<'a>) -> Result<T>,
Expand Down Expand Up @@ -597,16 +610,25 @@ impl IRawElementProviderSimple_Impl for PlatformNode {
}

fn GetPropertyValue(&self, property_id: UIA_PROPERTY_ID) -> Result<VARIANT> {
self.resolve_with_context(|node, context| {
self.resolve_with_tree_state_and_context(|node, state, context| {
let wrapper = NodeWrapper::Node(&node);
let mut result = wrapper.get_property_value(property_id);
if result.is_empty() && node.is_root() {
match property_id {
UIA_NamePropertyId => {
result = window_title(context.hwnd).into();
if result.is_empty() {
if node.is_root() {
match property_id {
UIA_NamePropertyId => {
result = window_title(context.hwnd).into();
}
UIA_NativeWindowHandlePropertyId => {
result = (context.hwnd.0 as i32).into();
}
_ => (),
}
UIA_NativeWindowHandlePropertyId => {
result = (context.hwnd.0 as i32).into();
}
match property_id {
UIA_FrameworkIdPropertyId => result = state.toolkit_name().into(),
UIA_ProviderDescriptionPropertyId => {
result = app_and_toolkit_description(state).into()
}
_ => (),
}
Expand Down
Loading

0 comments on commit 5313860

Please sign in to comment.