v0.2.1: Fix cancel key (Escape) being swallowed globally

The cancel key was consumed by rdev::grab at all times, not just during
recording/transcribing. This made the Escape key unusable system-wide
while Mouth was running. Now the cancel key only gets swallowed when
Mouth is actively recording or transcribing.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-12 16:37:50 +01:00
parent 9ad870d260
commit 3fa4d102df
5 changed files with 25 additions and 10 deletions
+6
View File
@@ -1,9 +1,13 @@
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::RwLock;
use std::time::Instant;
/// Thread-safe shared state accessible by the coordinator, IPC listener, and tray icon.
pub struct SharedState {
pub state: RwLock<String>,
/// True when recording or transcribing — the hotkey listener uses this to
/// decide whether to swallow the cancel key.
pub is_active: AtomicBool,
pub model: String,
pub accelerator: String,
pub started_at: Instant,
@@ -13,6 +17,7 @@ impl SharedState {
pub fn new(model: String, accelerator: String) -> Self {
Self {
state: RwLock::new("idle".to_string()),
is_active: AtomicBool::new(false),
model,
accelerator,
started_at: Instant::now(),
@@ -23,6 +28,7 @@ impl SharedState {
if let Ok(mut s) = self.state.write() {
*s = state.to_string();
}
self.is_active.store(state != "idle", Ordering::Release);
}
pub fn get_state(&self) -> String {