mirror of
https://github.com/LGUG2Z/komorebi.git
synced 2026-05-28 06:29:13 +02:00
feat(subscriptions): add uds subscription support
This commit adds support for subscriptions via Unix Domain Sockets which are better suited for IPC between Rust processes compared to Named Pipes which have issues that I don't want to spend time resolving. The main motivation for this change is to provide an easy way for the new zebar project to consume information about komorebi's state in the Rust backend so that a bar module can be created for komorebi users. The next step in this process will be to finally refactor the komorebi crate into a mixed bin/lib crate, and expose all notification-related structs and maybe some connection helper methods in a new komorebi-client crate. The previous "subscribe" and "unsubscribe" komorebic commands have had the "-pipe" suffix added to them, with aliases in place for the previous names in order to ensure backwards compat.
This commit is contained in:
+30
-8
@@ -38,6 +38,7 @@ use sysinfo::Process;
|
||||
use tracing_appender::non_blocking::WorkerGuard;
|
||||
use tracing_subscriber::layer::SubscriberExt;
|
||||
use tracing_subscriber::EnvFilter;
|
||||
use uds_windows::UnixStream;
|
||||
use which::which;
|
||||
use winreg::enums::HKEY_CURRENT_USER;
|
||||
use winreg::RegKey;
|
||||
@@ -172,6 +173,8 @@ lazy_static! {
|
||||
]));
|
||||
static ref SUBSCRIPTION_PIPES: Arc<Mutex<HashMap<String, File>>> =
|
||||
Arc::new(Mutex::new(HashMap::new()));
|
||||
static ref SUBSCRIPTION_SOCKETS: Arc<Mutex<HashMap<String, PathBuf>>> =
|
||||
Arc::new(Mutex::new(HashMap::new()));
|
||||
static ref TCP_CONNECTIONS: Arc<Mutex<HashMap<String, TcpStream>>> =
|
||||
Arc::new(Mutex::new(HashMap::new()));
|
||||
static ref HIDING_BEHAVIOUR: Arc<Mutex<HidingBehaviour>> =
|
||||
@@ -388,12 +391,32 @@ pub struct Notification {
|
||||
}
|
||||
|
||||
pub fn notify_subscribers(notification: &str) -> Result<()> {
|
||||
let mut stale_subscriptions = vec![];
|
||||
let mut subscriptions = SUBSCRIPTION_PIPES.lock();
|
||||
for (subscriber, pipe) in &mut *subscriptions {
|
||||
let mut stale_sockets = vec![];
|
||||
let mut sockets = SUBSCRIPTION_SOCKETS.lock();
|
||||
|
||||
for (socket, path) in &mut *sockets {
|
||||
match UnixStream::connect(path) {
|
||||
Ok(mut stream) => {
|
||||
tracing::debug!("pushed notification to subscriber: {socket}");
|
||||
stream.write_all(notification.as_bytes())?;
|
||||
}
|
||||
Err(_) => {
|
||||
stale_sockets.push(socket.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for socket in stale_sockets {
|
||||
tracing::warn!("removing stale subscription: {socket}");
|
||||
sockets.remove(&socket);
|
||||
}
|
||||
|
||||
let mut stale_pipes = vec![];
|
||||
let mut pipes = SUBSCRIPTION_PIPES.lock();
|
||||
for (subscriber, pipe) in &mut *pipes {
|
||||
match writeln!(pipe, "{notification}") {
|
||||
Ok(()) => {
|
||||
tracing::debug!("pushed notification to subscriber: {}", subscriber);
|
||||
tracing::debug!("pushed notification to subscriber: {subscriber}");
|
||||
}
|
||||
Err(error) => {
|
||||
// ERROR_FILE_NOT_FOUND
|
||||
@@ -406,16 +429,15 @@ pub fn notify_subscribers(notification: &str) -> Result<()> {
|
||||
|
||||
// Remove the subscription; the process will have to subscribe again
|
||||
if let Some(2 | 232) = error.raw_os_error() {
|
||||
let subscriber_cl = subscriber.clone();
|
||||
stale_subscriptions.push(subscriber_cl);
|
||||
stale_pipes.push(subscriber.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for subscriber in stale_subscriptions {
|
||||
for subscriber in stale_pipes {
|
||||
tracing::warn!("removing stale subscription: {}", subscriber);
|
||||
subscriptions.remove(&subscriber);
|
||||
pipes.remove(&subscriber);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
||||
@@ -59,6 +59,7 @@ use crate::BORDER_OFFSET;
|
||||
use crate::BORDER_OVERFLOW_IDENTIFIERS;
|
||||
use crate::BORDER_WIDTH;
|
||||
use crate::CUSTOM_FFM;
|
||||
use crate::DATA_DIR;
|
||||
use crate::DISPLAY_INDEX_PREFERENCES;
|
||||
use crate::FLOAT_IDENTIFIERS;
|
||||
use crate::HIDING_BEHAVIOUR;
|
||||
@@ -70,6 +71,7 @@ use crate::NO_TITLEBAR;
|
||||
use crate::OBJECT_NAME_CHANGE_ON_LAUNCH;
|
||||
use crate::REMOVE_TITLEBARS;
|
||||
use crate::SUBSCRIPTION_PIPES;
|
||||
use crate::SUBSCRIPTION_SOCKETS;
|
||||
use crate::TCP_CONNECTIONS;
|
||||
use crate::TRAY_AND_MULTI_WINDOW_IDENTIFIERS;
|
||||
use crate::WORKSPACE_RULES;
|
||||
@@ -1155,7 +1157,16 @@ impl WindowManager {
|
||||
workspace.set_resize_dimensions(resize);
|
||||
self.update_focused_workspace(false)?;
|
||||
}
|
||||
SocketMessage::AddSubscriber(ref subscriber) => {
|
||||
SocketMessage::AddSubscriberSocket(ref socket) => {
|
||||
let mut sockets = SUBSCRIPTION_SOCKETS.lock();
|
||||
let socket_path = DATA_DIR.join(socket);
|
||||
sockets.insert(socket.clone(), socket_path);
|
||||
}
|
||||
SocketMessage::RemoveSubscriberSocket(ref socket) => {
|
||||
let mut sockets = SUBSCRIPTION_SOCKETS.lock();
|
||||
sockets.remove(socket);
|
||||
}
|
||||
SocketMessage::AddSubscriberPipe(ref subscriber) => {
|
||||
let mut pipes = SUBSCRIPTION_PIPES.lock();
|
||||
let pipe_path = format!(r"\\.\pipe\{subscriber}");
|
||||
let pipe = connect(&pipe_path).map_err(|_| {
|
||||
@@ -1164,7 +1175,7 @@ impl WindowManager {
|
||||
|
||||
pipes.insert(subscriber.clone(), pipe);
|
||||
}
|
||||
SocketMessage::RemoveSubscriber(ref subscriber) => {
|
||||
SocketMessage::RemoveSubscriberPipe(ref subscriber) => {
|
||||
let mut pipes = SUBSCRIPTION_PIPES.lock();
|
||||
pipes.remove(subscriber);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user