diff --git a/Cargo.lock b/Cargo.lock index 7c965b2..18a8a6d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -186,7 +186,7 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "lefthk" -version = "0.1.3" +version = "0.1.4" dependencies = [ "clap", "kdl", @@ -203,7 +203,7 @@ dependencies = [ [[package]] name = "lefthk-core" -version = "0.1.3" +version = "0.1.4" dependencies = [ "log", "mio", diff --git a/lefthk-core/Cargo.toml b/lefthk-core/Cargo.toml index 8e6d30c..831d806 100644 --- a/lefthk-core/Cargo.toml +++ b/lefthk-core/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "lefthk-core" version = "0.1.4" -edition = "2018" +edition = "2021" license = "BSD-3-Clause" readme = "README.md" repository = "https://github.com/leftwm/lefthk" @@ -17,8 +17,5 @@ tokio = { version = "1.14.0", features = ["fs", "io-util", "macros", "net", "rt- x11-dl = "2.19.1" xdg = "2.4.0" -[features] -watcher = [] - [dev-dependencies] tempfile = "3.2.0" diff --git a/lefthk-core/src/config.rs b/lefthk-core/src/config.rs index 6a106db..39f9e1e 100644 --- a/lefthk-core/src/config.rs +++ b/lefthk-core/src/config.rs @@ -46,78 +46,3 @@ pub struct Keybind { pub trait Config { fn mapped_bindings(&self) -> Vec; } - -#[cfg(feature = "watcher")] -pub mod watcher { - use crate::errors::{Error, Result}; - use nix::sys::inotify::{AddWatchFlags, InitFlags, Inotify}; - use std::os::unix::prelude::AsRawFd; - use std::path::Path; - use std::sync::Arc; - use tokio::sync::{oneshot, Notify}; - use tokio::time::Duration; - - pub struct Watcher { - fd: Inotify, - task_notify: Arc, - _task_guard: oneshot::Receiver<()>, - } - - impl Watcher { - pub fn new(config_file: &Path) -> Result { - const INOTIFY: mio::Token = mio::Token(0); - let fd = Inotify::init(InitFlags::all())?; - let mut flags = AddWatchFlags::empty(); - flags.insert(AddWatchFlags::IN_MODIFY); - let _wd = fd.add_watch(config_file, flags)?; - - let (guard, _task_guard) = oneshot::channel::<()>(); - let notify = Arc::new(Notify::new()); - let task_notify = notify.clone(); - let mut poll = mio::Poll::new()?; - let mut events = mio::Events::with_capacity(1); - poll.registry().register( - &mut mio::unix::SourceFd(&fd.as_raw_fd()), - INOTIFY, - mio::Interest::READABLE, - )?; - let timeout = Duration::from_millis(50); - tokio::task::spawn_blocking(move || loop { - if guard.is_closed() { - return; - } - - if let Err(err) = poll.poll(&mut events, Some(timeout)) { - log::warn!("Inotify socket poll failed with {:?}", err); - continue; - } - - events - .iter() - .filter(|event| INOTIFY == event.token()) - .for_each(|_| notify.notify_one()); - }); - Ok(Self { - fd, - task_notify, - _task_guard, - }) - } - - pub fn refresh_watch(&self, config_file: &Path) -> Error { - let mut flags = AddWatchFlags::empty(); - flags.insert(AddWatchFlags::IN_MODIFY); - let _wd = self.fd.add_watch(config_file, flags)?; - Ok(()) - } - - pub fn has_events(&self) -> bool { - self.fd.read_events().is_ok() - } - - /// Wait until readable. - pub async fn wait_readable(&mut self) { - self.task_notify.notified().await; - } - } -} diff --git a/lefthk-core/src/errors.rs b/lefthk-core/src/errors.rs index 95f5a22..888b3e1 100644 --- a/lefthk-core/src/errors.rs +++ b/lefthk-core/src/errors.rs @@ -48,8 +48,6 @@ pub enum LeftError { NoConfigFound, #[error("No value set for execution.")] ValueNotFound, - #[error("Config watcher dropped.")] - WatcherDropped, #[error("X failed status error.")] XFailedStatus, } diff --git a/lefthk-core/src/tests.rs b/lefthk-core/src/tests.rs index 5fc5430..1a93557 100644 --- a/lefthk-core/src/tests.rs +++ b/lefthk-core/src/tests.rs @@ -11,31 +11,6 @@ pub(crate) mod test { } } -/// Config Testing -#[cfg(test)] -#[cfg(feature = "watcher")] -mod config { - use super::test::temp_path; - use crate::config::watcher::Watcher; - use tokio::{fs, io::AsyncWriteExt}; - - #[tokio::test] - async fn check_watcher() { - let config_file = temp_path().await.unwrap(); - let watcher = Watcher::new(&config_file).unwrap(); - - let mut file = fs::OpenOptions::new() - .write(true) - .open(&config_file) - .await - .unwrap(); - file.write_all(b"\n").await.unwrap(); - file.flush().await.unwrap(); - - assert!(watcher.has_events()); - } -} - /// IPC Testing #[cfg(test)] mod ipc { diff --git a/lefthk-core/src/worker.rs b/lefthk-core/src/worker.rs index cbe3146..02a4f0a 100644 --- a/lefthk-core/src/worker.rs +++ b/lefthk-core/src/worker.rs @@ -3,17 +3,13 @@ use crate::config::{self, Keybind}; use crate::errors::{self, Error, LeftError}; use crate::ipc::Pipe; use crate::xkeysym_lookup; -use crate::xwrap::{self, XWrap}; -#[cfg(feature = "watcher")] -use std::path::PathBuf; +use crate::xwrap::XWrap; use std::process::{Command, Stdio}; use x11_dl::xlib; use xdg::BaseDirectories; pub struct Worker { pub keybinds: Vec, - #[cfg(feature = "watcher")] - pub config_file: PathBuf, pub base_directory: BaseDirectories, pub xwrap: XWrap, pub children: Children, @@ -30,81 +26,6 @@ impl Drop for Worker { } impl Worker { - #[cfg(feature = "watcher")] - pub fn new( - keybinds: Vec, - config_file: PathBuf, - base_directory: BaseDirectories, - ) -> Self { - Self { - keybinds, - config_file, - base_directory, - xwrap: XWrap::new(), - children: Children::new(), - reload_requested: false, - kill_requested: false, - chord_keybinds: None, - chord_elapsed: false, - } - } - - #[cfg(feature = "watcher")] - pub async fn event_loop(&mut self) { - use crate::config::watcher::Watcher; - - self.xwrap.grab_keys(&self.keybinds); - let mut watcher = errors::exit_on_error!(Watcher::new(&self.config_file)); - let pipe_name = Pipe::pipe_name(); - let pipe_file = errors::exit_on_error!(self.base_directory.place_runtime_file(pipe_name)); - let mut pipe = errors::exit_on_error!(Pipe::new(pipe_file).await); - loop { - if self.kill_requested || self.reload_requested { - break; - } - - if self.chord_elapsed { - self.xwrap.grab_keys(&self.keybinds); - self.chord_keybinds = None; - self.chord_elapsed = false; - } - - let task_notify = xwrap::wait_readable(self.xwrap.task_notify.clone()); - tokio::pin!(task_notify); - - tokio::select! { - _ = self.children.wait_readable() => { - self.children.reap(); - continue; - } - _ = &mut task_notify => { - let event_in_queue = self.xwrap.queue_len(); - for _ in 0..event_in_queue { - let xlib_event = self.xwrap.get_next_event(); - self.handle_event(&xlib_event); - } - continue; - } - _ = watcher.wait_readable(), if cfg!(watcher) => { - if watcher.has_events() { - errors::exit_on_error!(watcher.refresh_watch(&self.config_file)); - self.reload_requested = true; - } - continue; - } - Some(command) = pipe.read_command() => { - match command { - config::Command::Reload => self.reload_requested = true, - config::Command::Kill => self.kill_requested = true, - _ => (), - } - continue; - } - } - } - } - - #[cfg(not(feature = "watcher"))] pub fn new(keybinds: Vec, base_directory: BaseDirectories) -> Self { Self { keybinds, @@ -118,7 +39,6 @@ impl Worker { } } - #[cfg(not(feature = "watcher"))] pub async fn event_loop(&mut self) { self.xwrap.grab_keys(&self.keybinds); let pipe_name = Pipe::pipe_name(); @@ -134,18 +54,18 @@ impl Worker { self.chord_keybinds = None; self.chord_elapsed = false; } - - let task_notify = xwrap::wait_readable(self.xwrap.task_notify.clone()); - tokio::pin!(task_notify); + println!("1"); tokio::select! { _ = self.children.wait_readable() => { self.children.reap(); continue; } - _ = &mut task_notify => { + _ = self.xwrap.wait_readable() => { + println!("2"); let event_in_queue = self.xwrap.queue_len(); for _ in 0..event_in_queue { + println!("3"); let xlib_event = self.xwrap.get_next_event(); self.handle_event(&xlib_event); } @@ -169,7 +89,7 @@ impl Worker { xlib::MappingNotify => self.mapping_notify(&mut xlib::XMappingEvent::from(xlib_event)), _ => return, }; - let _ = errors::log_on_error!(error); + errors::log_on_error!(error); } fn key_press(&mut self, event: &xlib::XKeyEvent) -> Error { diff --git a/lefthk-core/src/xwrap.rs b/lefthk-core/src/xwrap.rs index 5433d50..fe13ebe 100644 --- a/lefthk-core/src/xwrap.rs +++ b/lefthk-core/src/xwrap.rs @@ -1,7 +1,9 @@ use crate::config::Keybind; use crate::errors::{self, Error, LeftError}; use crate::xkeysym_lookup; +use std::future::Future; use std::os::raw::{c_int, c_ulong}; +use std::pin::Pin; use std::ptr; use std::sync::Arc; use tokio::sync::{oneshot, Notify}; @@ -44,7 +46,7 @@ impl XWrap { SERVER, mio::Interest::READABLE, )); - let timeout = Duration::from_millis(50); + let timeout = Duration::from_millis(100); tokio::task::spawn_blocking(move || loop { if guard.is_closed() { return; @@ -187,9 +189,12 @@ impl XWrap { pub fn queue_len(&self) -> i32 { unsafe { (self.xlib.XPending)(self.display) } } -} -/// Wait until readable. -pub async fn wait_readable(task_notify: Arc) { - task_notify.notified().await; + /// Wait until readable. + pub fn wait_readable(&mut self) -> Pin>> { + let task_notify = self.task_notify.clone(); + Box::pin(async move { + task_notify.notified().await; + }) + } } diff --git a/lefthk/Cargo.toml b/lefthk/Cargo.toml index dd2ad9a..eee37cc 100644 --- a/lefthk/Cargo.toml +++ b/lefthk/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "lefthk" version = "0.1.4" -edition = "2018" +edition = "2021" license = "BSD-3-Clause" readme = "README.md" repository = "https://github.com/leftwm/lefthk" @@ -19,8 +19,5 @@ thiserror = "1.0.30" tokio = { version = "1.14.0", features = ["fs", "io-util", "macros", "net", "rt-multi-thread", "sync", "time"] } xdg = "2.4.0" -[features] -watcher = ["lefthk-core/watcher"] - [dev-dependencies] tempfile = "3.2.0" diff --git a/lefthk/src/config.rs b/lefthk/src/config.rs index e9ddffa..501925c 100644 --- a/lefthk/src/config.rs +++ b/lefthk/src/config.rs @@ -4,7 +4,7 @@ use serde::{Deserialize, Serialize}; use std::{convert::TryFrom, fs, path::Path}; use xdg::BaseDirectories; -#[derive(Debug, Serialize, Deserialize, PartialEq, Clone)] +#[derive(Debug, Serialize, Deserialize, Eq, PartialEq, Clone)] pub enum Command { Chord, Execute, diff --git a/lefthk/src/errors.rs b/lefthk/src/errors.rs index b57b7f6..22fa1b3 100644 --- a/lefthk/src/errors.rs +++ b/lefthk/src/errors.rs @@ -49,8 +49,6 @@ pub enum LeftError { NoConfigFound, #[error("No value set for execution.")] ValueNotFound, - #[error("Config watcher dropped.")] - WatcherDropped, #[error("X failed status error.")] XFailedStatus, } diff --git a/lefthk/src/main.rs b/lefthk/src/main.rs index 0c44ec2..79d77ff 100644 --- a/lefthk/src/main.rs +++ b/lefthk/src/main.rs @@ -37,8 +37,6 @@ fn main() { pretty_env_logger::init(); let mut old_config = None; let path = errors::exit_on_error!(BaseDirectories::with_prefix("lefthk")); - #[cfg(feature = "watcher")] - let config_file = errors::exit_on_error!(path.place_config_file("config.kdl")); loop { let config = match config::load() { Ok(config) => config, @@ -54,11 +52,7 @@ fn main() { let completed = std::panic::catch_unwind(|| { let rt = errors::return_on_error!(tokio::runtime::Runtime::new()); let _rt_guard = rt.enter(); - #[cfg(feature = "watcher")] - let mut worker = - Worker::new(config.mapped_bindings(), config_file.clone(), path.clone()); - #[cfg(not(feature = "watcher"))] let mut worker = Worker::new(config.mapped_bindings(), path.clone()); rt.block_on(worker.event_loop());