Skip to content

Commit f1caa03

Browse files
committed
compat.accesskit 0.23.1: AccessKit's C bindings, prebuilt — one accessibility tree served to UIA, NSAccessibility and AT-SPI
The library is Rust, so upstream's release archive is the artifact: its header and the static library of the host's platform (Linux x86_64, macOS arm64, Windows x86_64 MSVC), linked with the system libraries upstream's own accesskit-config.cmake names. tests/examples/accesskit builds a window and its button, reads the update back through the library, and on Linux makes an AT-SPI adapter and gives it the tree. Signed-off-by: Sunrisepeak <speakshen@163.com>
1 parent 66393d0 commit f1caa03

4 files changed

Lines changed: 146 additions & 0 deletions

File tree

‎mcpp.toml‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ members = [
4141
"tests/examples/abseil",
4242
"tests/examples/archive",
4343
"tests/examples/argparse",
44+
"tests/examples/accesskit",
4445
"tests/examples/asio-module",
4546
"tests/examples/asio-ssl",
4647
"tests/examples/boost-asio",

‎pkgs/c/compat.accesskit.lua‎

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
-- compat.accesskit — AccessKit's C bindings (accesskit-c), prebuilt: a UI
2+
-- describes its tree once and AccessKit serves it to each platform's
3+
-- assistive technology — UI Automation on Windows, NSAccessibility on macOS,
4+
-- AT-SPI on Linux (a screen reader, a magnifier, voice control).
5+
--
6+
-- THE LIBRARY IS RUST, SO ITS RELEASE IS THE ARTIFACT. Building it here would
7+
-- need a Rust toolchain in the recipe; upstream's release archive carries the
8+
-- header and a static library for every platform it supports, built from the
9+
-- tagged source by its own CI. This descriptor exposes the header and links the
10+
-- static library of the host's platform, with the system libraries upstream's
11+
-- own `accesskit-config.cmake` names for each.
12+
--
13+
-- WHAT IS NOT COVERED: upstream ships no Linux arm64 build, and this version
14+
-- links macOS arm64 and Windows x86_64 (the x86_64 Mac and arm64 Windows
15+
-- libraries are in the archive too, but the index states one library path per
16+
-- platform). A consumer that wants AccessKit there gates its use by platform.
17+
--
18+
-- One archive for all three platforms (about 64 MB): the paths below reach into
19+
-- its `accesskit-c-0.23.1/` wrap layer; mcpp rewrites a relative `-L` to the
20+
-- package's own directory.
21+
package = {
22+
spec = "1",
23+
namespace = "compat",
24+
name = "accesskit",
25+
description = "AccessKit C bindings (prebuilt static library): one accessibility tree served to UIA, NSAccessibility and AT-SPI",
26+
licenses = {"MIT", "Apache-2.0"},
27+
repo = "https://github.com/AccessKit/accesskit-c",
28+
type = "package",
29+
30+
xpm = {
31+
linux = {
32+
["0.23.1"] = {
33+
url = "https://github.com/AccessKit/accesskit-c/releases/download/0.23.1/accesskit-c-0.23.1.zip",
34+
sha256 = "35b7ca8a6f1e038b5da35e1e9e5a0adaed9bfcf21e1496d29598fbbadcc7043f",
35+
},
36+
["latest"] = { ref = "0.23.1" },
37+
},
38+
macosx = {
39+
["0.23.1"] = {
40+
url = "https://github.com/AccessKit/accesskit-c/releases/download/0.23.1/accesskit-c-0.23.1.zip",
41+
sha256 = "35b7ca8a6f1e038b5da35e1e9e5a0adaed9bfcf21e1496d29598fbbadcc7043f",
42+
},
43+
["latest"] = { ref = "0.23.1" },
44+
},
45+
windows = {
46+
["0.23.1"] = {
47+
url = "https://github.com/AccessKit/accesskit-c/releases/download/0.23.1/accesskit-c-0.23.1.zip",
48+
sha256 = "35b7ca8a6f1e038b5da35e1e9e5a0adaed9bfcf21e1496d29598fbbadcc7043f",
49+
},
50+
["latest"] = { ref = "0.23.1" },
51+
},
52+
},
53+
54+
mcpp = {
55+
language = "c++23",
56+
import_std = false,
57+
c_standard = "c11",
58+
include_dirs = { "*/include" },
59+
generated_files = {
60+
["mcpp_generated/accesskit_anchor.c"] = "int mcpp_compat_accesskit_anchor(void) { return 0; }\n",
61+
},
62+
sources = { "mcpp_generated/accesskit_anchor.c" },
63+
targets = { ["accesskit"] = { kind = "lib" } },
64+
deps = {},
65+
-- The static library and what upstream's accesskit-config.cmake links beside it.
66+
linux = {
67+
ldflags = { "-Laccesskit-c-0.23.1/lib/linux/x86_64/static", "-l:libaccesskit.a", "-static-libgcc", "-lm" },
68+
},
69+
macosx = {
70+
ldflags = { "-Laccesskit-c-0.23.1/lib/macos/arm64/static", "-laccesskit",
71+
"-framework", "AppKit", "-framework", "Foundation", "-framework", "CoreFoundation", "-lobjc", "-lc++" },
72+
},
73+
windows = {
74+
ldflags = { "-Laccesskit-c-0.23.1/lib/windows/x86_64/msvc/static", "-laccesskit",
75+
"-lbcrypt", "-lntdll", "-lpropsys", "-lruntimeobject", "-luiautomationcore", "-luserenv", "-lws2_32" },
76+
},
77+
},
78+
}

‎tests/examples/accesskit/mcpp.toml‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# compat.accesskit test project: a tree built and handed to AccessKit, and on
2+
# Linux an AT-SPI adapter made and given the tree. `compat` redirect inherited
3+
# from the workspace root.
4+
[package]
5+
name = "accesskit-tests"
6+
version = "0.1.0"
7+
8+
[dependencies.compat]
9+
accesskit = "0.23.1"
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
// Behavioral test: compat.accesskit builds a tree (a window holding a button
2+
// with a label, focusable, clickable), reads it back through the library's own
3+
// debug view, and on Linux makes an AT-SPI adapter and gives it the tree. Not
4+
// merely an include: these calls reach the prebuilt Rust library.
5+
#include <accesskit.h>
6+
#include <cstdio>
7+
#include <cstring>
8+
9+
static accesskit_tree_update *tree(void *userdata) {
10+
(void)userdata;
11+
accesskit_node *window = accesskit_node_new(ACCESSKIT_ROLE_WINDOW);
12+
accesskit_node_set_label(window, "Settings");
13+
accesskit_node_push_child(window, 2);
14+
accesskit_node *button = accesskit_node_new(ACCESSKIT_ROLE_BUTTON);
15+
accesskit_node_set_label(button, "Save");
16+
accesskit_node_add_action(button, ACCESSKIT_ACTION_CLICK);
17+
accesskit_node_add_action(button, ACCESSKIT_ACTION_FOCUS);
18+
accesskit_tree_update *update = accesskit_tree_update_with_capacity_and_focus(2, 2);
19+
accesskit_tree_update_set_tree_info(update, accesskit_tree_info_new(1));
20+
accesskit_tree_update_push_node(update, 1, window);
21+
accesskit_tree_update_push_node(update, 2, button);
22+
return update;
23+
}
24+
25+
#if defined(__linux__)
26+
static void act(accesskit_action_request *request, void *userdata) {
27+
(void)userdata;
28+
accesskit_action_request_free(request);
29+
}
30+
static void deactivated(void *userdata) { (void)userdata; }
31+
#endif
32+
33+
int main(void) {
34+
accesskit_tree_update *update = tree(nullptr);
35+
if (!update) {
36+
fprintf(stderr, "no tree update\n");
37+
return 1;
38+
}
39+
char *debug = accesskit_tree_update_debug(update);
40+
const int named = debug && strstr(debug, "Save") != NULL;
41+
if (debug) accesskit_string_free(debug);
42+
accesskit_tree_update_free(update);
43+
if (!named) {
44+
fprintf(stderr, "the tree update does not hold the button's label\n");
45+
return 1;
46+
}
47+
#if defined(__linux__)
48+
accesskit_unix_adapter *adapter = accesskit_unix_adapter_new(reinterpret_cast<accesskit_activation_handler_callback>(tree), nullptr, act, nullptr, deactivated, nullptr);
49+
if (!adapter) {
50+
fprintf(stderr, "no AT-SPI adapter\n");
51+
return 1;
52+
}
53+
accesskit_unix_adapter_update_window_focus_state(adapter, true);
54+
accesskit_unix_adapter_free(adapter);
55+
#endif
56+
printf("accesskit: a window and its button, served\n");
57+
return 0;
58+
}

0 commit comments

Comments
 (0)