fix(voice): abort voice recording on Ctrl key chords; skip insert on empty transcription#12268
fix(voice): abort voice recording on Ctrl key chords; skip insert on empty transcription#12268kyledross wants to merge 1 commit into
Conversation
When a modifier key other than the configured voice toggle key is pressed while voice recording is active (e.g. Shift pressed while Ctrl is the voice toggle key), voice is now aborted immediately. This ensures the editor is back in Editable state before the subsequent non-modifier key press (e.g. V) triggers its keybinding. Root cause: the WarpUI event system matches keybindings *before* running element event handlers for KeyDown events. This meant that when the user held Ctrl (starting voice, locking the editor to Selectable) and pressed Ctrl+Shift+V to paste, the Paste keybinding fired while the editor was still Selectable, silently failing. The element-level key handler that was intended to abort voice was never reached because the keybinding was already matched and consumed the event. Two complementary fixes: 1. modifier_key_change (element.rs): When any modifier key other than the voice toggle key is pressed while voice is active, dispatch AbortVoiceInput immediately. Because modifier-key events bypass the keybinding system entirely, this handler always fires. For Ctrl+Shift+V this aborts voice on the Shift press, so by the time V is pressed the editor is already Editable and the Paste keybinding succeeds. 2. paste() (mod.rs): Abort voice at the start of the Paste action as a safety net for chords with no intermediate modifier press (e.g. Ctrl+V). Restores Editable state before the clipboard insert runs. Additionally, apply_transcribed_voice_input no longer inserts into the editor when transcription returns an empty string, preventing a silent buffer mutation when the user presses and releases the voice toggle key without speaking anything. New AbortVoiceInput EditorAction variant encapsulates the abort call so it can be dispatched from both the element-level modifier handler and any future action handlers without exposing stop_voice_input beyond its current pub(super) scope. Tests added: - test_empty_transcription_does_not_modify_buffer - test_non_empty_transcription_inserts_text - test_transcription_error_does_not_modify_buffer - test_unhandled_modifier_key_is_noop_when_voice_inactive Co-Authored-By: Oz <oz-agent@warp.dev>
|
Every PR must be linked to a same-repo issue before Oz can review it. This PR is linked to #11415, but no linked issue is marked See the contribution guidelines for the full readiness model. Powered by Oz |
There was a problem hiding this comment.
Every PR must be linked to a same-repo issue before Oz can review it.
This PR is linked to #11415, but no linked issue is marked ready-to-implement yet. Only repository maintainers apply that label, so please wait for a maintainer to mark the issue. Once it is marked, push a new commit or comment /oz-review to re-trigger review.
See the contribution guidelines for the full readiness model.
Powered by Oz
Fixes #11415
Description
Two bugs in the voice input code path when a modifier key is configured as the voice toggle.
Ctrl-chord conflict: Pressing a chord with the voice-toggle modifier while recording is active (e.g. Ctrl+Shift+V to paste) dispatched the keybinding while the editor was still locked in
Selectablestate, causing the action to silently fail.Root cause: WarpUI matches keybindings before running element event handlers for
KeyDownevents. So the Paste binding fired while the editor was non-editable, and the element-level handler that was meant to abort voice was never reached.Empty transcription clears selection: Starting and stopping voice without speaking returned an empty transcription string.
apply_transcribed_voice_inputcalleduser_insert("")unconditionally, replacing any active selection with nothing.Linked Issue
Fixes #11415
ready-to-specorready-to-implement.Changes
element.rs—modifier_key_change: When any modifier key other than the voice toggle key is pressed while voice is active, dispatchAbortVoiceInputimmediately. Modifier-key events bypass the keybinding system entirely, so this handler always fires. For Ctrl+Shift+V, voice is aborted on the Shift press, so the editor is alreadyEditableby the time V triggers Paste.mod.rs—paste(): Abort voice at the start of the Paste action as a safety net for chords with no intermediate modifier press (e.g. a direct Ctrl+V).apply_transcribed_voice_input: Skipuser_insertwhen transcription returns an empty string.New
AbortVoiceInputEditorActionvariant: Encapsulates the abort call so it can be dispatched from the element-level modifier handler and any future action handlers without exposingstop_voice_inputbeyond its currentpub(super)scope.Testing
./script/runTests added:
test_empty_transcription_does_not_modify_buffertest_non_empty_transcription_inserts_texttest_transcription_error_does_not_modify_buffertest_unhandled_modifier_key_is_noop_when_voice_inactiveAgent Mode
Co-Authored-By: Oz oz-agent@warp.dev