From 0d200a87b20bb1c13f8af34951ca6e53a56f8e92 Mon Sep 17 00:00:00 2001 From: Takashi Kokubun Date: Thu, 31 Mar 2022 23:47:26 -0700 Subject: [PATCH 1/4] Add timeout_millis for nested remap --- src/config/action.rs | 27 +++++++++++++++++---------- src/config/mod.rs | 1 + src/config/remap.rs | 10 ++++++++++ src/config/tests.rs | 1 + src/event_handler.rs | 15 ++++++++++++--- 5 files changed, 41 insertions(+), 13 deletions(-) create mode 100644 src/config/remap.rs diff --git a/src/config/action.rs b/src/config/action.rs index f8d8305..e6834e1 100644 --- a/src/config/action.rs +++ b/src/config/action.rs @@ -1,9 +1,11 @@ use crate::config::key_press::KeyPress; use std::collections::HashMap; +use crate::config::remap::Remap; use serde::de; use serde::{Deserialize, Deserializer}; use std::fmt::Debug; +use std::time::Duration; // Values in `keymap.remap` #[derive(Clone, Debug, Deserialize)] @@ -11,7 +13,7 @@ use std::fmt::Debug; pub enum Action { KeyPress(KeyPress), #[serde(deserialize_with = "deserialize_remap")] - Remap(HashMap>), + Remap(Remap), #[serde(deserialize_with = "deserialize_launch")] Launch(Vec), #[serde(deserialize_with = "deserialize_set_mark")] @@ -22,17 +24,15 @@ pub enum Action { EscapeNextKey(bool), } -fn deserialize_remap<'de, D>(deserializer: D) -> Result>, D::Error> +fn deserialize_remap<'de, D>(deserializer: D) -> Result where D: Deserializer<'de>, { - let mut action = HashMap::>::deserialize(deserializer)?; - if let Some(remap) = action.remove("remap") { - if action.is_empty() { - return Ok(remap.into_iter().map(|(k, v)| (k, v.into_vec())).collect()); - } - } - Err(de::Error::custom("not a map with a single \"remap\" key")) + let action = RemapActions::deserialize(deserializer)?; + return Ok(Remap { + remap: action.remap.into_iter().map(|(k, v)| (k, v.into_vec())).collect(), + timeout: action.timeout_millis.map(|ms| Duration::from_millis(ms)), + }); } fn deserialize_launch<'de, D>(deserializer: D) -> Result, D::Error> @@ -88,7 +88,7 @@ where } // Used only for deserializing Vec -#[derive(Clone, Deserialize)] +#[derive(Clone, Debug, Deserialize)] #[serde(untagged)] pub enum Actions { Action(Action), @@ -103,3 +103,10 @@ impl Actions { } } } + +// Used only for deserializing Remap with Vec +#[derive(Debug, Deserialize)] +pub struct RemapActions { + pub remap: HashMap, + pub timeout_millis: Option, +} diff --git a/src/config/mod.rs b/src/config/mod.rs index 28d1512..ac60526 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -6,6 +6,7 @@ pub mod key_press; mod keymap; mod modmap; +mod remap; #[cfg(test)] mod tests; diff --git a/src/config/remap.rs b/src/config/remap.rs new file mode 100644 index 0000000..7ddc9d8 --- /dev/null +++ b/src/config/remap.rs @@ -0,0 +1,10 @@ +use crate::config::action::Action; +use crate::config::key_press::KeyPress; +use std::collections::HashMap; +use std::time::Duration; + +#[derive(Clone, Debug)] +pub struct Remap { + pub remap: HashMap>, + pub timeout: Option, +} diff --git a/src/config/tests.rs b/src/config/tests.rs index d13289b..56f4ff0 100644 --- a/src/config/tests.rs +++ b/src/config/tests.rs @@ -110,6 +110,7 @@ fn test_keymap_remap() { C-s: remap: x: C-z + timeout_millis: 1000 "}) } diff --git a/src/event_handler.rs b/src/event_handler.rs index f640476..4448e17 100644 --- a/src/event_handler.rs +++ b/src/event_handler.rs @@ -25,6 +25,7 @@ pub struct EventHandler { application_cache: Option, multi_purpose_keys: HashMap, override_remap: Option>>, + override_timeout_at: Option, sigaction_set: bool, mark_set: bool, escape_next_key: bool, @@ -42,6 +43,7 @@ impl EventHandler { application_cache: None, multi_purpose_keys: HashMap::new(), override_remap: None, + override_timeout_at: None, sigaction_set: false, mark_set: false, escape_next_key: false, @@ -169,6 +171,12 @@ impl EventHandler { alt: self.alt.to_modifier_state(), windows: self.windows.to_modifier_state(), }; + if let Some(override_timeout_at) = self.override_timeout_at { + if override_timeout_at < Instant::now() { + self.override_remap = None; + self.override_timeout_at = None; + } + } if let Some(override_remap) = &self.override_remap { let override_remap = override_remap.clone(); self.override_remap = None; @@ -192,12 +200,13 @@ impl EventHandler { fn dispatch_action(&mut self, action: &Action) -> Result<(), Box> { match action { Action::KeyPress(key_press) => self.send_key_press(key_press)?, - Action::Remap(remap) => { + Action::Remap(action) => { let mut override_remap: HashMap> = HashMap::new(); - for (key_press, actions) in remap.iter() { + for (key_press, actions) in action.remap.iter() { override_remap.insert(key_press.clone(), actions.to_vec()); } - self.override_remap = Some(override_remap) + self.override_remap = Some(override_remap); + self.override_timeout_at = action.timeout.map(|t| Instant::now() + t) } Action::Launch(command) => self.run_command(command.clone()), Action::SetMark(set) => self.mark_set = *set, From 65f5f27d0214ec4cdf6fe4774b7a6e616d95c6c4 Mon Sep 17 00:00:00 2001 From: Takashi Kokubun Date: Fri, 1 Apr 2022 20:48:25 -0700 Subject: [PATCH 2/4] Flush buffered keys on timeout --- src/event_handler.rs | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/src/event_handler.rs b/src/event_handler.rs index 4448e17..5e3389e 100644 --- a/src/event_handler.rs +++ b/src/event_handler.rs @@ -26,6 +26,7 @@ pub struct EventHandler { multi_purpose_keys: HashMap, override_remap: Option>>, override_timeout_at: Option, + override_timeout_keys: Vec, sigaction_set: bool, mark_set: bool, escape_next_key: bool, @@ -44,6 +45,7 @@ impl EventHandler { multi_purpose_keys: HashMap::new(), override_remap: None, override_timeout_at: None, + override_timeout_keys: vec![], sigaction_set: false, mark_set: false, escape_next_key: false, @@ -52,7 +54,20 @@ impl EventHandler { // Handle EventType::KEY pub fn on_event(&mut self, event: InputEvent, config: &Config) -> Result<(), Box> { + // Pre-event updates self.application_cache = None; // expire cache + if let Some(override_timeout_at) = self.override_timeout_at { + if override_timeout_at < Instant::now() { + self.override_remap = None; + self.override_timeout_at = None; + for key in self.override_timeout_keys.clone() { + self.send_key(&key, PRESS)?; + self.send_key(&key, RELEASE)?; + } + self.override_timeout_keys = vec![]; + } + } + let key = Key::new(event.code()); debug!("=> {}: {:?}", event.value(), &key); @@ -75,7 +90,7 @@ impl EventHandler { self.escape_next_key = false } else if let Some(actions) = self.find_keymap(config, &key) { for action in &actions { - self.dispatch_action(action)?; + self.dispatch_action(action, &key)?; } continue; } @@ -171,15 +186,11 @@ impl EventHandler { alt: self.alt.to_modifier_state(), windows: self.windows.to_modifier_state(), }; - if let Some(override_timeout_at) = self.override_timeout_at { - if override_timeout_at < Instant::now() { - self.override_remap = None; - self.override_timeout_at = None; - } - } if let Some(override_remap) = &self.override_remap { let override_remap = override_remap.clone(); self.override_remap = None; + self.override_timeout_at = None; + self.override_timeout_keys = vec![]; if let Some(actions) = override_remap.get(&key_press) { return Some(actions.to_vec()); } @@ -197,7 +208,7 @@ impl EventHandler { None } - fn dispatch_action(&mut self, action: &Action) -> Result<(), Box> { + fn dispatch_action(&mut self, action: &Action, key: &Key) -> Result<(), Box> { match action { Action::KeyPress(key_press) => self.send_key_press(key_press)?, Action::Remap(action) => { @@ -206,7 +217,8 @@ impl EventHandler { override_remap.insert(key_press.clone(), actions.to_vec()); } self.override_remap = Some(override_remap); - self.override_timeout_at = action.timeout.map(|t| Instant::now() + t) + self.override_timeout_at = action.timeout.map(|t| Instant::now() + t); + self.override_timeout_keys.push(key.clone()); } Action::Launch(command) => self.run_command(command.clone()), Action::SetMark(set) => self.mark_set = *set, From 2adf8f070783803f28d47c8693415b5855cc0898 Mon Sep 17 00:00:00 2001 From: Takashi Kokubun Date: Fri, 1 Apr 2022 21:00:01 -0700 Subject: [PATCH 3/4] Flush a buffered key on unhandled events --- src/event_handler.rs | 49 ++++++++++++++++++++++++-------------------- 1 file changed, 27 insertions(+), 22 deletions(-) diff --git a/src/event_handler.rs b/src/event_handler.rs index 5e3389e..c4a522a 100644 --- a/src/event_handler.rs +++ b/src/event_handler.rs @@ -26,7 +26,7 @@ pub struct EventHandler { multi_purpose_keys: HashMap, override_remap: Option>>, override_timeout_at: Option, - override_timeout_keys: Vec, + override_timeout_key: Option, sigaction_set: bool, mark_set: bool, escape_next_key: bool, @@ -45,7 +45,7 @@ impl EventHandler { multi_purpose_keys: HashMap::new(), override_remap: None, override_timeout_at: None, - override_timeout_keys: vec![], + override_timeout_key: None, sigaction_set: false, mark_set: false, escape_next_key: false, @@ -54,20 +54,7 @@ impl EventHandler { // Handle EventType::KEY pub fn on_event(&mut self, event: InputEvent, config: &Config) -> Result<(), Box> { - // Pre-event updates self.application_cache = None; // expire cache - if let Some(override_timeout_at) = self.override_timeout_at { - if override_timeout_at < Instant::now() { - self.override_remap = None; - self.override_timeout_at = None; - for key in self.override_timeout_keys.clone() { - self.send_key(&key, PRESS)?; - self.send_key(&key, RELEASE)?; - } - self.override_timeout_keys = vec![]; - } - } - let key = Key::new(event.code()); debug!("=> {}: {:?}", event.value(), &key); @@ -88,7 +75,7 @@ impl EventHandler { } else if is_pressed(value) { if self.escape_next_key { self.escape_next_key = false - } else if let Some(actions) = self.find_keymap(config, &key) { + } else if let Some(actions) = self.find_keymap(config, &key)? { for action in &actions { self.dispatch_action(action, &key)?; } @@ -178,7 +165,7 @@ impl EventHandler { None } - fn find_keymap(&mut self, config: &Config, key: &Key) -> Option> { + fn find_keymap(&mut self, config: &Config, key: &Key) -> Result>, Box> { let key_press = KeyPress { key: *key, shift: self.shift.to_modifier_state(), @@ -186,13 +173,22 @@ impl EventHandler { alt: self.alt.to_modifier_state(), windows: self.windows.to_modifier_state(), }; + if let Some(override_timeout_at) = self.override_timeout_at { + if override_timeout_at < Instant::now() { + self.override_remap = None; + self.override_timeout_at = None; + self.flush_override_key()?; + } + } if let Some(override_remap) = &self.override_remap { let override_remap = override_remap.clone(); self.override_remap = None; self.override_timeout_at = None; - self.override_timeout_keys = vec![]; if let Some(actions) = override_remap.get(&key_press) { - return Some(actions.to_vec()); + self.override_timeout_key = None; + return Ok(Some(actions.to_vec())); + } else { + self.flush_override_key()?; } } for keymap in &config.keymap { @@ -202,10 +198,10 @@ impl EventHandler { continue; } } - return Some(actions.to_vec()); + return Ok(Some(actions.to_vec())); } } - None + Ok(None) } fn dispatch_action(&mut self, action: &Action, key: &Key) -> Result<(), Box> { @@ -218,7 +214,7 @@ impl EventHandler { } self.override_remap = Some(override_remap); self.override_timeout_at = action.timeout.map(|t| Instant::now() + t); - self.override_timeout_keys.push(key.clone()); + self.override_timeout_key = Some(key.clone()); } Action::Launch(command) => self.run_command(command.clone()), Action::SetMark(set) => self.mark_set = *set, @@ -411,6 +407,15 @@ impl EventHandler { panic!("unexpected key {:?} at update_modifier", Key::new(code)); } } + + fn flush_override_key(&mut self) -> Result<(), Box> { + if let Some(key) = self.override_timeout_key { + self.send_key(&key, PRESS)?; + self.send_key(&key, RELEASE)?; + } + self.override_timeout_key = None; + Ok(()) + } } lazy_static! { From 140a478e0dfa51f272c0a82329b673817f38943c Mon Sep 17 00:00:00 2001 From: Takashi Kokubun Date: Sat, 2 Apr 2022 13:59:19 -0700 Subject: [PATCH 4/4] Eagerly expire a timeout prefix --- src/event_handler.rs | 56 +++++++++++++++++++++++--------------------- src/main.rs | 22 +++++++++++++---- 2 files changed, 47 insertions(+), 31 deletions(-) diff --git a/src/event_handler.rs b/src/event_handler.rs index c4a522a..d3cb603 100644 --- a/src/event_handler.rs +++ b/src/event_handler.rs @@ -10,6 +10,8 @@ use lazy_static::lazy_static; use log::{debug, error}; use nix::sys::signal; use nix::sys::signal::{sigaction, SaFlags, SigAction, SigHandler, SigSet}; +use nix::sys::time::TimeSpec; +use nix::sys::timerfd::{Expiration, TimerFd, TimerSetTimeFlags}; use std::collections::HashMap; use std::error::Error; use std::process::{Command, Stdio}; @@ -17,6 +19,7 @@ use std::time::Instant; pub struct EventHandler { device: VirtualDevice, + timer: TimerFd, shift: PressState, control: PressState, alt: PressState, @@ -25,7 +28,6 @@ pub struct EventHandler { application_cache: Option, multi_purpose_keys: HashMap, override_remap: Option>>, - override_timeout_at: Option, override_timeout_key: Option, sigaction_set: bool, mark_set: bool, @@ -33,9 +35,10 @@ pub struct EventHandler { } impl EventHandler { - pub fn new(device: VirtualDevice) -> EventHandler { + pub fn new(device: VirtualDevice, timer: TimerFd) -> EventHandler { EventHandler { device, + timer, shift: PressState::new(), control: PressState::new(), alt: PressState::new(), @@ -44,7 +47,6 @@ impl EventHandler { application_cache: None, multi_purpose_keys: HashMap::new(), override_remap: None, - override_timeout_at: None, override_timeout_key: None, sigaction_set: false, mark_set: false, @@ -94,6 +96,21 @@ impl EventHandler { self.device.emit(&[event]) } + pub fn timeout_override(&mut self) -> Result<(), Box> { + if let Some(key) = self.override_timeout_key { + self.send_key(&key, PRESS)?; + self.send_key(&key, RELEASE)?; + } + self.remove_override() + } + + fn remove_override(&mut self) -> Result<(), Box> { + self.timer.unset()?; + self.override_remap = None; + self.override_timeout_key = None; + Ok(()) + } + fn send_key(&mut self, key: &Key, value: i32) -> std::io::Result<()> { let event = InputEvent::new(EventType::KEY, key.code(), value); self.send_event(event) @@ -173,22 +190,12 @@ impl EventHandler { alt: self.alt.to_modifier_state(), windows: self.windows.to_modifier_state(), }; - if let Some(override_timeout_at) = self.override_timeout_at { - if override_timeout_at < Instant::now() { - self.override_remap = None; - self.override_timeout_at = None; - self.flush_override_key()?; - } - } if let Some(override_remap) = &self.override_remap { - let override_remap = override_remap.clone(); - self.override_remap = None; - self.override_timeout_at = None; - if let Some(actions) = override_remap.get(&key_press) { - self.override_timeout_key = None; + if let Some(actions) = override_remap.clone().get(&key_press) { + self.remove_override()?; return Ok(Some(actions.to_vec())); } else { - self.flush_override_key()?; + self.timeout_override()?; } } for keymap in &config.keymap { @@ -213,8 +220,12 @@ impl EventHandler { override_remap.insert(key_press.clone(), actions.to_vec()); } self.override_remap = Some(override_remap); - self.override_timeout_at = action.timeout.map(|t| Instant::now() + t); - self.override_timeout_key = Some(key.clone()); + if let Some(timeout) = action.timeout { + let expiration = Expiration::OneShot(TimeSpec::from_duration(timeout)); + self.timer.unset()?; + self.timer.set(expiration, TimerSetTimeFlags::empty())?; + self.override_timeout_key = Some(key.clone()); + } } Action::Launch(command) => self.run_command(command.clone()), Action::SetMark(set) => self.mark_set = *set, @@ -407,15 +418,6 @@ impl EventHandler { panic!("unexpected key {:?} at update_modifier", Key::new(code)); } } - - fn flush_override_key(&mut self) -> Result<(), Box> { - if let Some(key) = self.override_timeout_key { - self.send_key(&key, PRESS)?; - self.send_key(&key, RELEASE)?; - } - self.override_timeout_key = None; - Ok(()) - } } lazy_static! { diff --git a/src/main.rs b/src/main.rs index c21fe5d..9497e8a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -11,8 +11,9 @@ use nix::libc::ENODEV; use nix::sys::inotify::{AddWatchFlags, Inotify}; use nix::sys::select::select; use nix::sys::select::FdSet; +use nix::sys::timerfd::{ClockId, TimerFd, TimerFlags}; use std::io::stdout; -use std::os::unix::io::AsRawFd; +use std::os::unix::io::{AsRawFd, RawFd}; use std::path::PathBuf; mod client; @@ -97,7 +98,9 @@ fn main() -> anyhow::Result<()> { Ok(output_device) => output_device, Err(e) => bail!("Failed to prepare an output device: {}", e), }; - let mut handler = EventHandler::new(output_device); + let timer = TimerFd::new(ClockId::CLOCK_MONOTONIC, TimerFlags::empty())?; + let timer_fd = timer.as_raw_fd(); + let mut handler = EventHandler::new(output_device, timer); let mut input_devices = match get_input_devices(&device_filter, &ignore_filter, watch_devices) { Ok(input_devices) => input_devices, Err(e) => bail!("Failed to prepare input devices: {}", e), @@ -108,7 +111,13 @@ fn main() -> anyhow::Result<()> { loop { match 'event_loop: loop { - let readable_fds = select_readable(input_devices.values(), &watchers)?; + let readable_fds = select_readable(input_devices.values(), &watchers, timer_fd)?; + if readable_fds.contains(timer_fd) { + if let Err(error) = handler.timeout_override() { + println!("Error on remap timeout: {error}") + } + } + for input_device in input_devices.values_mut() { if readable_fds.contains(input_device.as_raw_fd()) { match input_device.fetch_events().map_err(|e| (e.raw_os_error(), e)) { @@ -207,8 +216,13 @@ enum Event { ReloadDevices, } -fn select_readable<'a>(devices: impl Iterator, watchers: &[&Inotify]) -> anyhow::Result { +fn select_readable<'a>( + devices: impl Iterator, + watchers: &[&Inotify], + timer_fd: RawFd, +) -> anyhow::Result { let mut read_fds = FdSet::new(); + read_fds.insert(timer_fd); for device in devices { read_fds.insert(device.as_raw_fd()); }