Eagerly expire a timeout prefix

pull/82/head
Takashi Kokubun 3 years ago
parent 2adf8f0707
commit 140a478e0d
No known key found for this signature in database
GPG Key ID: 6FFC433B12EE23DD

@ -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<String>,
multi_purpose_keys: HashMap<Key, MultiPurposeKeyState>,
override_remap: Option<HashMap<KeyPress, Vec<Action>>>,
override_timeout_at: Option<Instant>,
override_timeout_key: Option<Key>,
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<dyn Error>> {
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<dyn Error>> {
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<dyn Error>> {
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! {

@ -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<Item = &'a InputDevice>, watchers: &[&Inotify]) -> anyhow::Result<FdSet> {
fn select_readable<'a>(
devices: impl Iterator<Item = &'a InputDevice>,
watchers: &[&Inotify],
timer_fd: RawFd,
) -> anyhow::Result<FdSet> {
let mut read_fds = FdSet::new();
read_fds.insert(timer_fd);
for device in devices {
read_fds.insert(device.as_raw_fd());
}

Loading…
Cancel
Save