Skip to content
Draft
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
9 changes: 8 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ members = ["cosmic-comp-config"]
[dependencies]
anyhow = { version = "1.0.102", features = ["backtrace"] }
bitflags = "2.11.0"
calloop = { version = "0.14.4", features = ["executor"] }
calloop = { version = "0.14.4", features = ["executor", "stream"] }
cosmic-comp-config = { path = "cosmic-comp-config", features = [
"libdisplay-info",
"output",
Expand Down Expand Up @@ -86,9 +86,9 @@ rand = "0.10"
clap_lex = "1.0"
parking_lot = "0.12.5"
logind-zbus = { version = "5.3.2", optional = true }
futures-executor = { version = "0.3.32", features = ["thread-pool"] }
futures-util = "0.3.32"
cgmath = "0.18.0"
async-once-cell = "0.5.4"

[dependencies.id_tree]
branch = "feature/copy_clone"
Expand Down
88 changes: 31 additions & 57 deletions src/dbus/a11y_keyboard_monitor.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
// https://gitlab.gnome.org/GNOME/mutter/-/blob/main/data/dbus-interfaces/org.freedesktop.a11y.xml

use futures_executor::ThreadPool;
use smithay::{
backend::input::KeyState,
input::keyboard::{KeysymHandle, ModifiersState},
};
use std::{
collections::{HashMap, HashSet},
sync::{Arc, Mutex, OnceLock},
sync::{Arc, Mutex},
};
use tracing::debug;
use xkbcommon::xkb::Keysym;
Expand Down Expand Up @@ -72,40 +71,38 @@ impl Clients {

#[derive(Debug)]
pub struct A11yKeyboardMonitorState {
executor: ThreadPool,
executor: calloop::futures::Scheduler<()>,
clients: Arc<Mutex<Clients>>,
active_virtual_mods: HashSet<Keysym>,
conn: Arc<OnceLock<zbus::Connection>>,
name_owners: Arc<OnceLock<NameOwners>>,
conn: zbus::Connection,
name_owners: NameOwners,
}

impl A11yKeyboardMonitorState {
pub fn new(executor: &ThreadPool) -> Self {
pub async fn new(
conn: &zbus::Connection,
name_owners: &NameOwners,
executor: &calloop::futures::Scheduler<()>,
) -> zbus::Result<Self> {
let clients = Arc::new(Mutex::new(Clients::default()));
let clients_clone = clients.clone();
let conn_cell = Arc::new(OnceLock::new());
let conn_cell_clone = conn_cell.clone();
let name_owners_cell = Arc::new(OnceLock::new());
let name_owners_cell_clone = name_owners_cell.clone();
let executor_clone = executor.clone();
executor.spawn_ok(async move {
match serve(clients_clone, &executor_clone).await {
Ok((conn, name_owners)) => {
conn_cell_clone.set(conn).unwrap();
name_owners_cell_clone.set(name_owners).unwrap();
}
Err(err) => {
tracing::error!("Failed to serve `org.freedesktop.a11y.Manager`: {err}");
}
}
});
Self {

let keyboard_monitor = KeyboardMonitor {
clients: clients.clone(),
name_owners: name_owners.clone(),
};
conn.object_server()
.at("/org/freedesktop/a11y/Manager", keyboard_monitor)
.await?;
conn.request_name("org.freedesktop.a11y.Manager").await?;

//tracing::error!("Failed to serve `org.freedesktop.a11y.Manager`: {err}");
Ok(Self {
executor: executor.clone(),
clients,
active_virtual_mods: HashSet::new(),
conn: conn_cell,
name_owners: name_owners_cell,
}
conn: conn.clone(),
name_owners: name_owners.clone(),
})
}

pub fn has_virtual_mod(&self, keysym: Keysym) -> bool {
Expand Down Expand Up @@ -154,18 +151,14 @@ impl A11yKeyboardMonitorState {
}

pub fn key_event(&self, modifiers: &ModifiersState, keysym: &KeysymHandle, state: KeyState) {
let Some(conn) = self.conn.get() else {
return;
};

let clients = self.clients.lock().unwrap();
for (unique_name, client) in clients.0.iter() {
if !client.watched && !self.has_key_grab(modifiers, keysym.modified_sym()) {
continue;
}

let mut signal_context =
SignalEmitter::new(conn, "/org/freedesktop/a11y/Manager").unwrap();
SignalEmitter::new(&self.conn, "/org/freedesktop/a11y/Manager").unwrap();
// Instead of sending signal to all clients, send only to authorized
// clients with registed watches.
signal_context = signal_context.set_destination(unique_name.clone().into());
Expand All @@ -186,7 +179,7 @@ impl A11yKeyboardMonitorState {
unichar,
keysym.raw_code().raw() as u16,
);
self.executor.spawn_ok(async {
let _ = self.executor.schedule(async {
let _ = future.await;
});
}
Expand All @@ -195,13 +188,11 @@ impl A11yKeyboardMonitorState {
pub fn refresh(&mut self) {
// Remove clients and associated grabs when unique names are no longer
// present on bus, or no longer hold approved name on bus.
if let Some(name_owners) = self.name_owners.get() {
self.clients
.lock()
.unwrap()
.0
.retain(|k, _| name_owners.check_owner_no_poll(k, ALLOWED_NAMES))
}
self.clients
.lock()
.unwrap()
.0
.retain(|k, _| self.name_owners.check_owner_no_poll(k, ALLOWED_NAMES))
}
}

Expand Down Expand Up @@ -311,20 +302,3 @@ impl KeyboardMonitor {
keycode: u16,
) -> zbus::Result<()>;
}

async fn serve(
clients: Arc<Mutex<Clients>>,
executor: &ThreadPool,
) -> zbus::Result<(zbus::Connection, NameOwners)> {
let conn = zbus::Connection::session().await?;
let name_owners = NameOwners::new(&conn, executor).await?;
let keyboard_monitor = KeyboardMonitor {
clients,
name_owners: name_owners.clone(),
};
conn.object_server()
.at("/org/freedesktop/a11y/Manager", keyboard_monitor)
.await?;
conn.request_name("org.freedesktop.a11y.Manager").await?;
Ok((conn, name_owners))
}
Loading