diff --git a/docs/config.adoc b/docs/config.adoc index d59440802..025c3a4c1 100644 --- a/docs/config.adoc +++ b/docs/config.adoc @@ -1747,8 +1747,8 @@ physical key presses and can only be activated via these actions: * `+(on-release-fakekey )+`: Activate a fake key action when releasing the key mapped to this action. * `+(on-idle-fakekey )+`: - Activate a fake key action - when the keyboard is idle for `idle time` milliseconds + Activate a fake key action when kanata has been idle + for at least `idle time` milliseconds. A fake key can be defined in a `+deffakekeys+` configuration entry. Configuring this entry is similar to `+defalias+`, but you cannot make use of aliases @@ -1762,6 +1762,14 @@ The aforementioned `++` can be one of three values: * `+release+`: Release the fake key. If it's not already pressed, this does nothing. * `+tap+`: Press and release the fake key. If it's already pressed, this only releases it. +Expanding on the `on-idle-fakekey` action some more, +the wording that "kanata" has been idle is important. +Even if the keyboard is idle, kanata may not yet be idle. +For example, if a long-running macro is playing, +or kanata is waiting for the timeout of actions such as `caps-word` or `tap-dance`, +kanata is not yet idle, and the tick count for the `` parameter +will not yet be counting even if you no longer have any keyboard keys pressed. + .Example: [source] ---- @@ -2042,14 +2050,14 @@ One case is a triple of: - keys check - action: to activate if keys check succeeds -- fallthrough|break: stop evaluating cases +- `fallthrough|break`: choose to continue vs. stop evaluating cases The default use of keys check behaves similarly to fork. For example, the keys check `(a b c)` will activate the corresponding action if any of a, b, or c are currently pressed. -The keys check also accepts the boolean operators and|or to allow more +The keys check also accepts the boolean operators `and|or` to allow more complex use cases. The order of cases matters. diff --git a/src/kanata/mod.rs b/src/kanata/mod.rs index 8acd95ad0..6e32a21b1 100644 --- a/src/kanata/mod.rs +++ b/src/kanata/mod.rs @@ -419,7 +419,8 @@ impl Kanata { } /// Advance keyberon layout state and send events based on changes to its state. - fn handle_time_ticks(&mut self, tx: &Option>) -> Result<()> { + /// Returns the number of ticks that elapsed. + fn handle_time_ticks(&mut self, tx: &Option>) -> Result { const NS_IN_MS: u128 = 1_000_000; let now = time::Instant::now(); let ns_elapsed = now.duration_since(self.last_tick).as_nanos(); @@ -464,7 +465,12 @@ impl Kanata { self.check_handle_layer_change(tx); } - Ok(()) + #[cfg(feature = "perf_logging")] + log::info!("ms elapsed: {ms_elapsed}"); + // Note regarding `as` casting. It doesn't really matter if the result would truncate and + // end up being wrong. Prefer to do the cheaper operation, as compared to doing the min of + // u16::MAX and ms_elapsed. + Ok(ms_elapsed as u16) } fn handle_scrolling(&mut self) -> Result<()> { @@ -1143,6 +1149,7 @@ impl Kanata { | CustomAction::DelayOnRelease(_) | CustomAction::CancelMacroOnRelease => {} CustomAction::FakeKeyOnIdle(fkd) => { + self.ticks_since_idle = 0; self.waiting_for_idle.insert(*fkd); } } @@ -1446,6 +1453,7 @@ impl Kanata { std::thread::sleep(time::Duration::from_millis(1)); } } + let mut ms_elapsed = 0; info!("Starting kanata proper"); let err = loop { @@ -1459,7 +1467,9 @@ impl Kanata { if !is_idle { k.ticks_since_idle = 0; } else if is_idle && counting_idle_ticks { - k.ticks_since_idle = k.ticks_since_idle.saturating_add(1); + k.ticks_since_idle = k.ticks_since_idle.saturating_add(ms_elapsed); + #[cfg(feature = "perf_logging")] + log::info!("ticks since idle: {}", k.ticks_since_idle); } is_idle && !counting_idle_ticks }; @@ -1487,9 +1497,10 @@ impl Kanata { #[cfg(feature = "perf_logging")] let start = std::time::Instant::now(); - if let Err(e) = k.handle_time_ticks(&tx) { - break e; - } + match k.handle_time_ticks(&tx) { + Ok(ms) => ms_elapsed = ms, + Err(e) => break e, + }; #[cfg(feature = "perf_logging")] log::info!( @@ -1521,9 +1532,10 @@ impl Kanata { #[cfg(feature = "perf_logging")] let start = std::time::Instant::now(); - if let Err(e) = k.handle_time_ticks(&tx) { - break e; - } + match k.handle_time_ticks(&tx) { + Ok(ms) => ms_elapsed = ms, + Err(e) => break e, + }; #[cfg(feature = "perf_logging")] log::info!( @@ -1535,9 +1547,10 @@ impl Kanata { #[cfg(feature = "perf_logging")] let start = std::time::Instant::now(); - if let Err(e) = k.handle_time_ticks(&tx) { - break e; - } + match k.handle_time_ticks(&tx) { + Ok(ms) => ms_elapsed = ms, + Err(e) => break e, + }; #[cfg(feature = "perf_logging")] log::info!(