diff --git a/README.md b/README.md index e746fad..b0405cf 100644 --- a/README.md +++ b/README.md @@ -118,10 +118,18 @@ Without these tools, Handy falls back to enigo which may have limited compatibil - The recording overlay is disabled by default on Linux (`Overlay Position: None`) because certain compositors treat it as the active window. When the overlay is visible it can steal focus, which prevents Handy from pasting back into the application that triggered transcription. If you enable the overlay anyway, be aware that clipboard-based pasting might fail or end up in the wrong window. - If you are having trouble with the app, running with the environment variable `WEBKIT_DISABLE_DMABUF_RENDERER=1` may help -- You can manage global shortcuts outside of Handy and still control the app via signals. Sending `SIGUSR2` to the Handy process toggles recording on/off, which lets Wayland window managers or other hotkey daemons keep ownership of keybindings. Example (Sway): +- You can manage global shortcuts outside of Handy and still control the app via signals, which lets Wayland window managers or other hotkey daemons keep ownership of keybindings: + + | Signal | Action | Example | + | --------- | ----------------------------------------- | ---------------------- | + | `SIGUSR2` | Toggle transcription | `pkill -USR2 -n handy` | + | `SIGUSR1` | Toggle transcription with post-processing | `pkill -USR1 -n handy` | + + Example Sway config: ```ini bindsym $mod+o exec pkill -USR2 -n handy + bindsym $mod+p exec pkill -USR1 -n handy ``` `pkill` here simply delivers the signal—it does not terminate the process. diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index 36f28e5..7b280c1 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -26,7 +26,7 @@ use managers::history::HistoryManager; use managers::model::ModelManager; use managers::transcription::TranscriptionManager; #[cfg(unix)] -use signal_hook::consts::SIGUSR2; +use signal_hook::consts::{SIGUSR1, SIGUSR2}; #[cfg(unix)] use signal_hook::iterator::Signals; use std::sync::atomic::{AtomicU8, Ordering}; @@ -132,8 +132,8 @@ fn initialize_core_logic(app_handle: &AppHandle) { // This matches the pattern used for Enigo initialization. #[cfg(unix)] - let signals = Signals::new(&[SIGUSR2]).unwrap(); - // Set up SIGUSR2 signal handler for toggling transcription + let signals = Signals::new(&[SIGUSR1, SIGUSR2]).unwrap(); + // Set up signal handlers for toggling transcription #[cfg(unix)] signal_handle::setup_signal_handler(app_handle.clone(), signals); diff --git a/src-tauri/src/signal_handle.rs b/src-tauri/src/signal_handle.rs index 35ff261..1113eb5 100644 --- a/src-tauri/src/signal_handle.rs +++ b/src-tauri/src/signal_handle.rs @@ -4,22 +4,25 @@ use std::thread; use tauri::{AppHandle, Manager}; #[cfg(unix)] -use signal_hook::consts::SIGUSR2; +use signal_hook::consts::{SIGUSR1, SIGUSR2}; #[cfg(unix)] use signal_hook::iterator::Signals; #[cfg(unix)] pub fn setup_signal_handler(app_handle: AppHandle, mut signals: Signals) { - debug!("SIGUSR2 signal handler registered"); + debug!("Signal handlers registered (SIGUSR1, SIGUSR2)"); thread::spawn(move || { for sig in signals.forever() { - if sig == SIGUSR2 { - debug!("Received SIGUSR2"); - if let Some(c) = app_handle.try_state::() { - c.send_input("transcribe", "SIGUSR2", true, false); - } else { - warn!("TranscriptionCoordinator not initialized"); - } + let (binding_id, signal_name) = match sig { + SIGUSR1 => ("transcribe_with_post_process", "SIGUSR1"), + SIGUSR2 => ("transcribe", "SIGUSR2"), + _ => continue, + }; + debug!("Received {signal_name}"); + if let Some(c) = app_handle.try_state::() { + c.send_input(binding_id, signal_name, true, false); + } else { + warn!("TranscriptionCoordinator not initialized"); } } });