diff --git a/komorebi-for-mac/Cargo.lock b/komorebi-for-mac/Cargo.lock index 8ffee69a..ecf125b5 100644 --- a/komorebi-for-mac/Cargo.lock +++ b/komorebi-for-mac/Cargo.lock @@ -3310,7 +3310,10 @@ dependencies = [ name = "komorebi-transport" version = "0.1.42" dependencies = [ + "color-eyre", "komorebi-protocol", + "tracing", + "uds_windows", ] [[package]] diff --git a/komorebi-for-mac/komorebi/src/process_command.rs b/komorebi-for-mac/komorebi/src/process_command.rs index e4499dca..cbb03fb3 100644 --- a/komorebi-for-mac/komorebi/src/process_command.rs +++ b/komorebi-for-mac/komorebi/src/process_command.rs @@ -59,17 +59,16 @@ use color_eyre::eyre; use color_eyre::eyre::Context; use color_eyre::eyre::OptionExt; use komorebi_themes::colour::Rgb; -use komorebi_transport::allowed_while_paused; +use komorebi_transport::CommandTarget; +use komorebi_transport::NoPolicy; use objc2_core_foundation::CFDictionary; use parking_lot::Mutex; use std::collections::HashMap; use std::fs::File; use std::fs::OpenOptions; -use std::io::BufRead; -use std::io::BufReader; use std::num::NonZeroUsize; +use std::os::unix::net::UnixListener; use std::os::unix::net::UnixStream; -use std::str::FromStr; use std::sync::Arc; use std::sync::atomic::Ordering; use std::time::Duration; @@ -77,43 +76,37 @@ use version::build; #[tracing::instrument] pub fn listen_for_commands(wm: Arc>) { - std::thread::spawn(move || { - loop { - let wm = wm.clone(); + komorebi_transport::listen_for_commands::(wm, NoPolicy); +} - let _ = std::thread::spawn(move || { - let listener = wm - .lock() - .command_listener - .try_clone() - .expect("could not clone unix listener"); +/// What the generic command listener needs of the window manager +impl CommandTarget for WindowManager { + type Listener = UnixListener; + type Shared = Arc>; - tracing::info!("listening on komorebi.sock"); - for client in listener.incoming() { - match client { - Ok(stream) => { - let wm_clone = wm.clone(); - std::thread::spawn(move || { - match read_commands_uds(&wm_clone, stream) { - Ok(()) => {} - Err(error) => { - tracing::error!("{error}") - } - } - }); - } - Err(error) => { - tracing::error!("failed to get unix stream {}", error); - break; - } - } - } - }) - .join(); + fn command_listener(shared: &Self::Shared) -> std::io::Result { + shared.lock().command_listener.try_clone() + } - tracing::error!("restarting failed thread"); - } - }); + fn try_lock_for( + shared: &Self::Shared, + timeout: Duration, + f: impl FnOnce(&mut Self) -> R, + ) -> Option { + shared.try_lock_for(timeout).map(|mut wm| f(&mut wm)) + } + + fn is_paused(&self) -> bool { + self.is_paused + } + + fn process_command( + &mut self, + message: SocketMessage, + reply: &mut UnixStream, + ) -> eyre::Result<()> { + WindowManager::process_command(self, message, reply) + } } impl WindowManager { @@ -1916,38 +1909,9 @@ impl WindowManager { pub fn read_commands_uds( wm: &Arc>, - mut stream: UnixStream, + stream: UnixStream, ) -> eyre::Result<()> { - let reader = BufReader::new(stream.try_clone()?); - // TODO(raggi): while this processes more than one command, if there are - // replies there is no clearly defined protocol for framing yet - it's - // perhaps whole-json objects for now, but termination is signalled by - // socket shutdown. - for line in reader.lines() { - let message = SocketMessage::from_str(&line?)?; - - match wm.try_lock_for(Duration::from_secs(1)) { - None => { - tracing::warn!( - "could not acquire window manager lock, not processing message: {message}" - ); - } - Some(mut wm) => { - if wm.is_paused { - return if allowed_while_paused(&message) { - Ok(wm.process_command(message, &mut stream)?) - } else { - tracing::trace!("ignoring while paused"); - Ok(()) - }; - } - - wm.process_command(message.clone(), &mut stream)?; - } - } - } - - Ok(()) + komorebi_transport::read_commands::(wm, stream, &NoPolicy) } #[cfg(test)]