Fix microphone, hotkey, and Dock reliability - #934
Conversation
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
Greptile SummaryThis PR preserves suppressed microphones across reconnects, reapplies the saved Dock policy when reopening the app, blocks new recording actions while macOS is locked, and narrows/rebuilds the global event tap based on configured mouse shortcuts.
|
| if mouseButtons.contains(0) { | ||
| mask |= (CGEventMask(1) << CGEventType.leftMouseDown.rawValue) | ||
| | (CGEventMask(1) << CGEventType.leftMouseUp.rawValue) | ||
| } | ||
| if mouseButtons.contains(1) { | ||
| mask |= (CGEventMask(1) << CGEventType.rightMouseDown.rawValue) | ||
| | (CGEventMask(1) << CGEventType.rightMouseUp.rawValue) | ||
| } | ||
| if mouseButtons.contains(where: { $0 >= 2 }) { | ||
| mask |= (CGEventMask(1) << CGEventType.otherMouseDown.rawValue) | ||
| | (CGEventMask(1) << CGEventType.otherMouseUp.rawValue) | ||
| } |
There was a problem hiding this comment.
Mouse clicks no longer interrupt
When a user presses a modifier-only recording shortcut and then clicks an unconfigured mouse button, the narrowed event mask drops that click before markOtherInputDuringModifierOnly() can mark the press as interrupted. Releasing the modifier is consequently treated as a clean shortcut and can incorrectly start recording.
Knowledge Base Used:
Prompt To Fix With AI
This is a comment left during a code review.
Path: Sources/Fluid/Services/GlobalHotkeyManager.swift
Line: 719-730
Comment:
**Mouse clicks no longer interrupt**
When a user presses a modifier-only recording shortcut and then clicks an unconfigured mouse button, the narrowed event mask drops that click before `markOtherInputDuringModifierOnly()` can mark the press as interrupted. Releasing the modifier is consequently treated as a clean shortcut and can incorrectly start recording.
**Knowledge Base Used:**
- [Voice dictation pipeline](https://app.greptile.com/altic/-/custom-context/knowledge-base/altic-dev/fluidvoice/-/docs/voice-dictation.md)
- [Settings and onboarding](https://app.greptile.com/altic/-/custom-context/knowledge-base/altic-dev/fluidvoice/-/docs/settings-and-onboarding.md)
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.| if !self.setupGlobalHotkey() { | ||
| self.isInitialized = false | ||
| DebugLogger.shared.error( | ||
| "Failed to rebuild event tap after mouse shortcut change", | ||
| source: "GlobalHotkeyManager" | ||
| ) | ||
| } |
There was a problem hiding this comment.
When event-tap recreation transiently fails after a mouse-shortcut setting changes, setupGlobalHotkey() has already invalidated the working tap and this branch does not invoke the immediate retry path. All global shortcuts remain unavailable until the periodic health check runs, which can take approximately 30 seconds.
Knowledge Base Used: Settings and onboarding
Prompt To Fix With AI
This is a comment left during a code review.
Path: Sources/Fluid/Services/GlobalHotkeyManager.swift
Line: 553-559
Comment:
**Tap rebuild loses shortcuts**
When event-tap recreation transiently fails after a mouse-shortcut setting changes, `setupGlobalHotkey()` has already invalidated the working tap and this branch does not invoke the immediate retry path. All global shortcuts remain unavailable until the periodic health check runs, which can take approximately 30 seconds.
**Knowledge Base Used:** [Settings and onboarding](https://app.greptile.com/altic/-/custom-context/knowledge-base/altic-dev/fluidvoice/-/docs/settings-and-onboarding.md)
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: a94865365f
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| "Mouse shortcut configuration changed; rebuilding event tap", | ||
| source: "GlobalHotkeyManager" | ||
| ) | ||
| if !self.setupGlobalHotkey() { |
There was a problem hiding this comment.
Retry event-tap rebuilds after configuration changes
If CGEvent.tapCreate or enabling the replacement tap fails transiently while a user changes mouse shortcuts, setupGlobalHotkey() has already destroyed the working tap, but this path only sets isInitialized to false. Subsequent shortcut changes then skip rebuilding because of the guard above, leaving all global hotkeys unavailable until the 30-second health check runs. Route this failure through the existing retry/reinitialization mechanism so a configuration edit does not cause an extended hotkey outage.
Useful? React with 👍 / 👎.
FluidVoice PR build readyDownload FluidVoice-PR-934-a94865365fcc The artifact contains the ad-hoc-signed app ZIP, Xcode archive, build manifest, and installation instructions. It expires 5 days after the build. Install the app
This build has its own app identity, so its permissions are separate from the release version of FluidVoice. |
|
Superseded by #937, which merged the independent microphone, Dock, and locked-session fixes. The mouse event-tap changes are intentionally excluded and will be handled separately. |
Description
Type of Change
Related Issue or Discussion
Closes #933
Closes #921
Closes #753
Addresses #884
Related to #657 and #789.
#891 is the separate configured mouse-shortcut ownership case and is not fixed by this PR.
Testing
swiftlint --strict --config .swiftlint.yml Sourcesswiftformat --config .swiftformat Sourcessh build_with_FI_incremental.shScreenshots / Video
Notes
The event tap remains filter-mode because configured shortcuts must be suppressible. This PR narrows its event mask to the configured mouse-button families and recreates it only when that configuration changes. #657 still needs affected-machine soak testing; this PR adds clearer immediate recovery diagnostics and safer tap lifecycle cleanup without claiming full resolution.