feat(windows): system-wide push-to-talk via Raw Input
PTT was focus-scoped (WinForms KeyDown/KeyUp) so it died the moment the window lost focus. Add an optional system-wide path using the Raw Input API (RegisterRawInputDevices + WM_INPUT with RIDEV_INPUTSINK) instead of a WH_KEYBOARD_LL low-level hook -- the latter is the keylogger pattern AV heuristics flag, which is worse for our unsigned MinGW binary. Raw Input involves no DLL injection or global hook and passes keys through. - New VoiceCat.App/Native/RawInput.cs: P/Invoke + structs; register the keyboard sink, decode WM_INPUT to vkey/up-down, GetAsyncKeyState helper. - MainForm overrides OnHandleCreated/OnHandleDestroyed/WndProc to manage the sink and route WM_INPUT to PTT; gates the focus-scoped KeyDown/KeyUp off when system-wide is on; makes the Deactivate force-release conditional; adds a GetAsyncKeyState watchdog on the pump timer so a missed key-up (RDP/lock-screen) cannot leave PTT stuck. - VoiceSettings.SystemWidePtt (default ON) + system-wide checkbox in the Audio settings PTT section. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -34,6 +34,13 @@ public sealed class VoiceSettings
|
||||
/// <summary>Push-to-talk key, stored as the integer value of System.Windows.Forms.Keys.</summary>
|
||||
public int PttKey { get; set; } = (int)Keys.F8;
|
||||
|
||||
/// <summary>Make push-to-talk work system-wide — i.e. while another app is focused. When on,
|
||||
/// MainForm registers a background Raw Input keyboard device (WM_INPUT + RIDEV_INPUTSINK) so the
|
||||
/// PTT key is observed even when VoiceCat is not in the foreground; when off, PTT is focus-scoped
|
||||
/// (only fires while the VoiceCat window has focus). Raw Input is used instead of a low-level
|
||||
/// keyboard hook to avoid antivirus keylogger heuristics.</summary>
|
||||
public bool SystemWidePtt { get; set; } = true;
|
||||
|
||||
/// <summary>Saved device ID from the last session; null means use the system default.</summary>
|
||||
public string? InputDeviceId { get; set; } = null;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user