Suppress Calendar AX capture to prevent event popover dismissal#628
Suppress Calendar AX capture to prevent event popover dismissal#628akramj13 wants to merge 1 commit into
Conversation
| private static let unsafeBundleIdentifiers: Set<String> = [ | ||
| "com.apple.iCal" | ||
| ] |
There was a problem hiding this comment.
Hard-coded suppression has no user opt-out
unsafeBundleIdentifiers is a private constant, so there is no way for a user to re-enable AX capture for Calendar (e.g., when they are typing in a plain text area outside the event-editor popover). The policy fires before all user-preference checks in isCaptureSuppressedForBundle, meaning even an explicit per-app user preference cannot override it. The doc comment acknowledges this is "conservative," but unlike the isApplicationDisabled path, no corresponding UI toggle exists. Consider surfacing this as a per-app override in the accessibility settings pane, or at minimum document the intentional no-override behaviour in a follow-up issue so the decision is tracked.
Summary
Testing
AccessibilityCaptureSuppressionPolicy.Solves #544
Greptile Summary
Introduces
AccessibilityCaptureSuppressionPolicy, a hard-coded allowlist of apps whose AX trees Cotabby must not enumerate, and wires it intoFocusTrackingModel's capture gate ahead of the normal user-preference pipeline. The immediate motivation is Apple Calendar's event-editor popover, which dismisses itself when Cotabby polls its transient AX hierarchy.AccessibilityCaptureSuppressionPolicy) statically suppressescom.apple.iCal; the check fires beforeisGloballyEnabledor per-app toggle checks, so it cannot be overridden by user settings.CotabbyAppEnvironmentinserts the policy call at the top ofisCaptureSuppressedForBundle; however, the companionshouldProcessEventsProviderclosure oninputMonitordoes not consult the policy, leaving Cotabby's keyboard event tap active when Calendar is frontmost.nilbundle; project file correctly adds both new sources to their respective build phases.Confidence Score: 4/5
The Calendar-specific fix is narrow and well-targeted; the two observations are about design trade-offs rather than broken behaviour on the changed path.
The AX suppression path itself is correct, and the existing test coverage confirms the policy's basic contract. The gap between
isCaptureSuppressedForBundleandshouldProcessEventsProvidermeans Cotabby's event tap stays alive in Calendar — harmless if the tap is always passthrough-safe with no live suggestion, but that assumption is implicit rather than enforced. The lack of a user override for the hard-coded suppression is a deliberate design choice that's documented in the source, but it silently takes away Calendar support for users who might want it.CotabbyAppEnvironment.swift— the relationship betweenisCaptureSuppressedForBundleandshouldProcessEventsProviderdeserves a closer look to confirm the event tap is passthrough-safe in Calendar.Important Files Changed
com.apple.iCalas a permanently suppressed bundle; no user override path exists.isCaptureSuppressedForBundleahead of user-preference checks, butshouldProcessEventsProvideron the sameinputMonitordoes not consult the policy, leaving the event tap active in suppressed apps.Flowchart
%%{init: {'theme': 'neutral'}}%% flowchart TD A[AX poll fires] --> B{isCaptureSuppressedForBundle?} B --> C[AccessibilityCaptureSuppressionPolicy\n.shouldSuppressCapture] C --> D{bundle in\nunsafeBundleIdentifiers?} D -->|yes — e.g. com.apple.iCal| E[return true\nSkip AX walk] D -->|no| F{isGloballyEnabled?} F -->|false| E F -->|true| G{isApplicationDisabled\nfor bundle?} G -->|true| E G -->|false| H[return false\nProceed with AX walk] I[Keystroke event] --> J{shouldProcessEventsProvider} J --> K{isGloballyEnabled?} K -->|false| L[drop event] K -->|true| M{isTerminal or\napp-disabled?} M -->|yes| L M -->|no| N[process event\n⚠️ policy NOT consulted] N --> O[suggestion pipeline\nno AX snapshot available]Comments Outside Diff (1)
Cotabby/App/Core/CotabbyAppEnvironment.swift, line 95-104 (link)shouldProcessEventsProviderisCaptureSuppressedForBundlenow returnstruefor Calendar, stopping the AX walk, butshouldProcessEventsProvideroninputMonitornever consultsAccessibilityCaptureSuppressionPolicy. When Calendar is the frontmost app, Cotabby's event tap remains fully active: acceptance-key, word-acceptance, and global-toggle key presses are still evaluated. If any of those taps swallow the event before passing it through (even with no active suggestion), Calendar's own keyboard shortcuts could silently lose keystrokes. The fix intent—"leaving keyboard monitoring … untouched"—may be fine if the event tap is always passthrough-safe with no live suggestion, but that assumption isn't enforced here.Reviews (1): Last reviewed commit: "fix calendar popover dismissal by suppre..." | Re-trigger Greptile