Skip to content

Mouse-button push-to-talk (opt-in) - #13

Merged
Kuberwastaken merged 5 commits into
mainfrom
feat/mouse-ptt
Jul 21, 2026
Merged

Mouse-button push-to-talk (opt-in)#13
Kuberwastaken merged 5 commits into
mainfrom
feat/mouse-ptt

Conversation

@Kuberwastaken

Copy link
Copy Markdown
Owner

Bind a non-primary mouse button as a hold-to-talk trigger (off by default).

  • Extends the existing CGEvent tap (mask includes .otherMouseDown/Up only when enabled — zero overhead when off), so the bound click is actually consumed and never reaches the app under the cursor; down/up consumption stays paired.
  • Session wiring injects .holdActivated/.holdDeactivated into the existing keyboard funnel — no parallel dictation path; ignored while a keyboard session or transcription is active; consume decision is cheap/synchronous inside the tap, session work deferred to the main queue (watchdog-safe).
  • Bindable buttons: middle and above; left/right rejected at capture. Capture row suspends the global tap while recording, matching keyboard capture.
  • Settings: "Mouse Dictation" card (toggle + capture row), keys mouse_dictation_enabled / mouse_dictation_button.

Verified on macOS 26.5 (arm64): make test passes, full build clean. Manual QA checklist in comments below is worth running — event taps can't be unit-tested.

Conflicts: touches GlobalShortcutBackend/HotkeyManager alongside #rebindable-cancel.

All eight feature PRs register tests in Tests/AppContextServiceTests.swift and some extend the Makefile test list, so each merge after the first needs a trivial conflict resolution there. Suggested merge order: dictionary-ranking → formality-dial → caret-context → transforms → scratch-that → raw-undo → rebindable-cancel → mouse-ptt.

…button

Adds an optional mouse button to GlobalShortcutBackend's CGEvent tap
(otherMouseDown/otherMouseUp in the tap mask only when configured) with a
consume decision callback, plumbs it through HotkeyManager.start, and adds
MouseDictationButton with the bindability rules (middle button and above;
left/right never) plus 1-based display labels.
New settings mouse_dictation_enabled (default off) and
mouse_dictation_button (default 3, the 4th button) following the standard
storage-key/@Published-didSet/init-load pattern; both restart hotkey
monitoring, which reinstalls the event tap idempotently. Button-down starts
a hold session through handleShortcutEvent exactly like the keyboard path,
button-up stops it, and the tap consumes both events so the click never
reaches the target app. Downs are ignored while a keyboard-triggered
session or transcription is active, and every session-ending path clears
mouse ownership so a stale flag can never stop a later keyboard session.
New settings card with the enable toggle and a MouseDictationButtonRow
that shows the bound button ("Middle Button" / "Button N") and rebinds
via a local otherMouseDown monitor while capture is armed. The row is
disabled and dimmed while the feature is off, capture suspends the global
tap so the bound button cannot trigger dictation mid-rebind, and left or
right presses are rejected.
Bindability (left/right never, middle and side buttons yes), 1-based
display labels, stored-value normalization, and the button-4 default.
Registered in the hand-rolled runner and in both Makefile TEST_RUNNER
file lists.
@Kuberwastaken
Kuberwastaken merged commit dba97eb into main Jul 21, 2026
1 check passed
@Kuberwastaken
Kuberwastaken deleted the feat/mouse-ptt branch July 21, 2026 09:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant