uttrflow / uttrflow/uttrflow-swift
The dictation keyboard tap gives up for good after two disables within a minute, and nothing restarts it or says so
- Dominant language
- Swift
- Stars
- 4
- Forks
- 17
- Avg merge
- 3h 32m
- Merged PRs (30d)
- 277
Description
## What happens
#141 added re-enabling to the dictation shortcut's event tap. The re-enable is rationed by `TapDisableWindow`: a second disable within 60 seconds of the previous one returns `reEnable == false` (`Sources/UttrflowInput/TapDisableWindow.swift:4-14`, `limit = 2`). In `SystemKeyboard` that answer simply leaves the tap off (`Sources/UttrflowInput/SystemKeyboard.swift:178-183`):
```swift
if type == .tapDisabledByTimeout || type == .tapDisabledByUserInput {
if delivery.shouldReEnable(), let port = delivery.port() {
CGEvent.tapEnable(tap: port, enable: true)
}
return Unmanaged.passUnretained(event)
}
```
After that:
- no event reaches `ActivationMonitor`, so `DictationController` never hears about it;
- `AppDelegate.shortcutFailure` stays `nil`, so `applicationDidBecomeActive` (`Sources/Uttrflow/AppDelegate.swift:507-512`), the one place a shortcut is re-armed, does nothing;
- nothing is drawn or logged.
The tab-to-complete tap handles the same answer: `KeyInterceptor` emits `.stopped(.disabledTwice)` (`Sources/UttrflowInput/KeyInterceptor.swift:304`) and `SuggestionCoordinator.handle` rests and restarts it (`Sources/Uttrflow/Suggestion/SuggestionCoordinator.swift:669-671`). The dictation tap has no equivalent, which #141 raised ("consider surfacing it") and is still the case.
## Why it matters
Timeout disables cluster: a busy machine, an 8 GB Mac swapping while a model loads, or a long main-thread stall can disable a tap twice in quick succession. The result is the exact symptom #141 was filed for — the shortcut stops responding with no error, until relaunch — only rarer.
## How to reproduce / measure
- Unit: `Delivery.shouldReEnable()` answers `true` then `false` when called twice in a row (the existing `TapDisableWindowTests` pin the rule); no code path acts on the `false`.
- Real machine (help wanted): starving the process so the tap is disabled twice in a minute, then pressing the shortcut. Without a way to force `tapDisabledByTimeout` headlessly, confirming the symptom needs someone willing to reproduce it on their Mac.
## Acceptance criteria
- When the dictation tap is left off, the app knows: the monitor reports it, and the tap is rebuilt after a rest (as the suggestion tap does) or the shortcut is shown as unarmed with a way to re-arm it.
- The recovery rule is testable without a window server (for example a fake `KeyboardEventSource` that reports a give-up).
- A hold in progress when the tap is given up on is released, so the microphone does not stay open (see #609).
Contributor guide
Research direction
Start with Sources/UttrflowInput/TapDisableWindow.swift and SystemKeyboard.swift, then compare the give-up handling in KeyInterceptor.swift and SuggestionCoordinator.swift. Run the existing TapDisableWindowTests and trace ActivationMonitor, DictationController, and AppDelegate.shortcutFailure. Done means the dictation tap reports and recovers from a give-up, the recovery is testable without a window server, and an in-progress hold is released.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- macos, swift
- Domain
- accessibility, desktop
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 67/100