feat(linux): add SIGUSR1 signal for transcribe_with_post_process (#759)
* feat(linux): add SIGUSR1 signal for transcribe_with_post_process Register SIGUSR1 alongside SIGUSR2 in the signal handler so Linux users can trigger transcription with post-processing via system signals (e.g. `pkill -SIGUSR1 -x handy`). This mirrors the existing SIGUSR2 toggle pattern and maps to the `transcribe_with_post_process` action already present in ACTION_MAP. Closes #758 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * readme * format --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> Co-authored-by: CJ Pais <cj@cjpais.com>
This commit is contained in:
parent
7fdde63460
commit
203ba1dbc2
3 changed files with 24 additions and 13 deletions
10
README.md
10
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.
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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::<TranscriptionCoordinator>() {
|
||||
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::<TranscriptionCoordinator>() {
|
||||
c.send_input(binding_id, signal_name, true, false);
|
||||
} else {
|
||||
warn!("TranscriptionCoordinator not initialized");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
|||
Loading…
Reference in a new issue