Skip to content

Commit b56b4ea

Browse files
authored
feat: Add features for async runtimes on Unix (#248)
1 parent 9829d0d commit b56b4ea

File tree

6 files changed

+181
-74
lines changed

6 files changed

+181
-74
lines changed

Cargo.lock

Lines changed: 47 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

platforms/unix/Cargo.toml

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,18 @@ repository = "https://github.com/AccessKit/accesskit"
1010
readme = "README.md"
1111
edition = "2021"
1212

13+
[features]
14+
default = ["async-io"]
15+
async-io = ["zbus/async-io"]
16+
tokio = ["dep:once_cell", "dep:tokio", "zbus/tokio"]
17+
1318
[dependencies]
1419
accesskit = { version = "0.11.0", path = "../../common" }
1520
accesskit_consumer = { version = "0.15.0", path = "../../consumer" }
1621
async-channel = "1.8.0"
17-
atspi = "0.10.1"
22+
atspi = { version = "0.10.1", default-features = false }
1823
futures-lite = "1.12.0"
24+
once_cell = { version = "1.17.1", optional = true }
1925
serde = "1.0"
20-
zbus = "3.6"
21-
26+
tokio = { version = "1.10.0", optional = true, features = ["rt-multi-thread", "net", "time"] }
27+
zbus = { version = "3.6", default-features = false }

platforms/unix/src/adapter.rs

Lines changed: 65 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use crate::{
1313
},
1414
context::Context,
1515
node::{filter, filter_detached, NodeWrapper, PlatformNode},
16-
util::AppContext,
16+
util::{block_on, AppContext},
1717
};
1818
use accesskit::{ActionHandler, NodeId, Rect, Role, TreeUpdate};
1919
use accesskit_consumer::{DetachedNode, FilterResult, Node, Tree, TreeChangeHandler, TreeState};
@@ -39,10 +39,12 @@ impl Adapter {
3939
initial_state: impl 'static + FnOnce() -> TreeUpdate,
4040
action_handler: Box<dyn ActionHandler + Send + Sync>,
4141
) -> Option<Self> {
42-
let mut atspi_bus = Bus::a11y_bus()?;
42+
let mut atspi_bus = block_on(async { Bus::a11y_bus().await })?;
4343
let (event_sender, event_receiver) = async_channel::unbounded();
4444
let atspi_bus_copy = atspi_bus.clone();
45-
let event_task = atspi_bus.connection().inner().executor().spawn(
45+
#[cfg(feature = "tokio")]
46+
let _guard = crate::util::TOKIO_RT.enter();
47+
let event_task = atspi_bus.connection().executor().spawn(
4648
async move {
4749
handle_events(atspi_bus_copy, event_receiver).await;
4850
},
@@ -51,7 +53,7 @@ impl Adapter {
5153
let tree = Tree::new(initial_state());
5254
let app_context = AppContext::new(app_name, toolkit_name, toolkit_version);
5355
let context = Context::new(tree, action_handler, app_context);
54-
atspi_bus.register_root_node(&context).ok()?;
56+
block_on(async { atspi_bus.register_root_node(&context).await.ok() })?;
5557
let adapter = Adapter {
5658
atspi_bus,
5759
_event_task: event_task,
@@ -85,31 +87,47 @@ impl Adapter {
8587
fn register_interfaces(&self, id: NodeId, new_interfaces: InterfaceSet) -> zbus::Result<bool> {
8688
let path = format!("{}{}", ACCESSIBLE_PATH_PREFIX, ObjectId::from(id).as_str());
8789
if new_interfaces.contains(Interface::Accessible) {
88-
self.atspi_bus.register_interface(
89-
&path,
90-
AccessibleInterface::new(
91-
self.atspi_bus.unique_name().to_owned(),
92-
PlatformNode::new(&self.context, id),
93-
),
94-
)?;
90+
block_on(async {
91+
self.atspi_bus
92+
.register_interface(
93+
&path,
94+
AccessibleInterface::new(
95+
self.atspi_bus.unique_name().to_owned(),
96+
PlatformNode::new(&self.context, id),
97+
),
98+
)
99+
.await
100+
})?;
95101
}
96102
if new_interfaces.contains(Interface::Action) {
97-
self.atspi_bus.register_interface(
98-
&path,
99-
ActionInterface::new(PlatformNode::new(&self.context, id)),
100-
)?;
103+
block_on(async {
104+
self.atspi_bus
105+
.register_interface(
106+
&path,
107+
ActionInterface::new(PlatformNode::new(&self.context, id)),
108+
)
109+
.await
110+
})?;
101111
}
102112
if new_interfaces.contains(Interface::Component) {
103-
self.atspi_bus.register_interface(
104-
&path,
105-
ComponentInterface::new(PlatformNode::new(&self.context, id)),
106-
)?;
113+
block_on(async {
114+
self.atspi_bus
115+
.register_interface(
116+
&path,
117+
ComponentInterface::new(PlatformNode::new(&self.context, id)),
118+
)
119+
.await
120+
})?;
107121
}
108122
if new_interfaces.contains(Interface::Value) {
109-
self.atspi_bus.register_interface(
110-
&path,
111-
ValueInterface::new(PlatformNode::new(&self.context, id)),
112-
)?;
123+
block_on(async {
124+
self.atspi_bus
125+
.register_interface(
126+
&path,
127+
ValueInterface::new(PlatformNode::new(&self.context, id)),
128+
)
129+
.await
130+
})?;
113131
}
114132
Ok(true)
115133
}
@@ -119,24 +137,30 @@ impl Adapter {
119137
id: &ObjectId,
120138
old_interfaces: InterfaceSet,
121139
) -> zbus::Result<bool> {
122-
let path = format!("{}{}", ACCESSIBLE_PATH_PREFIX, id.as_str());
123-
if old_interfaces.contains(Interface::Accessible) {
124-
self.atspi_bus
125-
.unregister_interface::<AccessibleInterface<PlatformNode>>(&path)?;
126-
}
127-
if old_interfaces.contains(Interface::Action) {
128-
self.atspi_bus
129-
.unregister_interface::<ActionInterface>(&path)?;
130-
}
131-
if old_interfaces.contains(Interface::Component) {
132-
self.atspi_bus
133-
.unregister_interface::<ComponentInterface>(&path)?;
134-
}
135-
if old_interfaces.contains(Interface::Value) {
136-
self.atspi_bus
137-
.unregister_interface::<ValueInterface>(&path)?;
138-
}
139-
Ok(true)
140+
block_on(async {
141+
let path = format!("{}{}", ACCESSIBLE_PATH_PREFIX, id.as_str());
142+
if old_interfaces.contains(Interface::Accessible) {
143+
self.atspi_bus
144+
.unregister_interface::<AccessibleInterface<PlatformNode>>(&path)
145+
.await?;
146+
}
147+
if old_interfaces.contains(Interface::Action) {
148+
self.atspi_bus
149+
.unregister_interface::<ActionInterface>(&path)
150+
.await?;
151+
}
152+
if old_interfaces.contains(Interface::Component) {
153+
self.atspi_bus
154+
.unregister_interface::<ComponentInterface>(&path)
155+
.await?;
156+
}
157+
if old_interfaces.contains(Interface::Value) {
158+
self.atspi_bus
159+
.unregister_interface::<ValueInterface>(&path)
160+
.await?;
161+
}
162+
Ok(true)
163+
})
140164
}
141165

142166
pub fn set_root_window_bounds(&self, outer: Rect, inner: Rect) {

platforms/unix/src/atspi/bus.rs

Lines changed: 34 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -8,26 +8,25 @@ use crate::{
88
context::Context,
99
PlatformRootNode,
1010
};
11-
use atspi::{bus::BusProxyBlocking, socket::SocketProxyBlocking, EventBody};
11+
use atspi::{bus::BusProxy, socket::SocketProxy, EventBody};
1212
use serde::Serialize;
1313
use std::{collections::HashMap, env::var, sync::Arc};
1414
use zbus::{
15-
blocking::{Connection, ConnectionBuilder},
1615
names::{BusName, InterfaceName, MemberName, OwnedUniqueName},
1716
zvariant::{ObjectPath, Str, Value},
18-
Address, Result,
17+
Address, Connection, ConnectionBuilder, Result,
1918
};
2019

2120
#[derive(Clone)]
2221
pub(crate) struct Bus {
2322
conn: Connection,
24-
socket_proxy: SocketProxyBlocking<'static>,
23+
socket_proxy: SocketProxy<'static>,
2524
}
2625

2726
impl Bus {
28-
pub fn a11y_bus() -> Option<Self> {
29-
let conn = a11y_bus()?;
30-
let socket_proxy = SocketProxyBlocking::new(&conn).ok()?;
27+
pub async fn a11y_bus() -> Option<Self> {
28+
let conn = a11y_bus().await?;
29+
let socket_proxy = SocketProxy::new(&conn).await.ok()?;
3130
Some(Bus { conn, socket_proxy })
3231
}
3332

@@ -39,36 +38,44 @@ impl Bus {
3938
self.conn.unique_name().unwrap()
4039
}
4140

42-
pub fn register_interface<T>(&self, path: &str, interface: T) -> Result<bool>
41+
pub async fn register_interface<T>(&self, path: &str, interface: T) -> Result<bool>
4342
where
4443
T: zbus::Interface,
4544
{
46-
self.conn.object_server().at(path, interface)
45+
self.conn.object_server().at(path, interface).await
4746
}
4847

49-
pub fn unregister_interface<T>(&self, path: &str) -> Result<bool>
48+
pub async fn unregister_interface<T>(&self, path: &str) -> Result<bool>
5049
where
5150
T: zbus::Interface,
5251
{
53-
self.conn.object_server().remove::<T, _>(path)
52+
self.conn.object_server().remove::<T, _>(path).await
5453
}
5554

56-
pub fn register_root_node(&mut self, context: &Arc<Context>) -> Result<bool> {
55+
pub async fn register_root_node(&mut self, context: &Arc<Context>) -> Result<bool> {
5756
let node = PlatformRootNode::new(context);
5857
let path = format!("{}{}", ACCESSIBLE_PATH_PREFIX, ObjectId::root().as_str());
5958
let registered = self
6059
.conn
6160
.object_server()
62-
.at(path.clone(), ApplicationInterface(node.clone()))?
63-
&& self.conn.object_server().at(
64-
path,
65-
AccessibleInterface::new(self.unique_name().to_owned(), node),
66-
)?;
61+
.at(path.clone(), ApplicationInterface(node.clone()))
62+
.await?
63+
&& self
64+
.conn
65+
.object_server()
66+
.at(
67+
path,
68+
AccessibleInterface::new(self.unique_name().to_owned(), node),
69+
)
70+
.await?;
6771
if registered {
68-
let desktop = self.socket_proxy.embed(&(
69-
self.unique_name().as_str(),
70-
ObjectPath::from_str_unchecked(ROOT_PATH),
71-
))?;
72+
let desktop = self
73+
.socket_proxy
74+
.embed(&(
75+
self.unique_name().as_str(),
76+
ObjectPath::from_str_unchecked(ROOT_PATH),
77+
))
78+
.await?;
7279
context.app_context.write().unwrap().desktop_address = Some(desktop.into());
7380
Ok(true)
7481
} else {
@@ -219,7 +226,6 @@ impl Bus {
219226
) -> Result<()> {
220227
let path = format!("{}{}", ACCESSIBLE_PATH_PREFIX, id.as_str());
221228
self.conn
222-
.inner()
223229
.emit_signal(
224230
Option::<BusName>::None,
225231
path,
@@ -231,17 +237,19 @@ impl Bus {
231237
}
232238
}
233239

234-
fn a11y_bus() -> Option<Connection> {
240+
async fn a11y_bus() -> Option<Connection> {
235241
let address = match var("AT_SPI_BUS_ADDRESS") {
236242
Ok(address) if !address.is_empty() => address,
237243
_ => {
238-
let session_bus = Connection::session().ok()?;
239-
BusProxyBlocking::new(&session_bus)
244+
let session_bus = Connection::session().await.ok()?;
245+
BusProxy::new(&session_bus)
246+
.await
240247
.ok()?
241248
.get_address()
249+
.await
242250
.ok()?
243251
}
244252
};
245253
let address: Address = address.as_str().try_into().ok()?;
246-
ConnectionBuilder::address(address).ok()?.build().ok()
254+
ConnectionBuilder::address(address).ok()?.build().await.ok()
247255
}

0 commit comments

Comments
 (0)