fix: smooth move/resize on Chromium/Electron apps by disabling AXEnhancedUserInterface during the gesture#177
Conversation
…ncedUserInterface during the gesture Chromium/Electron apps enable AXEnhancedUserInterface while an AX client is active, which makes programmatic kAXPosition/kAXSize updates slow and non-live (laggy drag/ resize) even though native title-bar drag / corner-resize of the same window stays smooth. Disable it on the tracked app for the duration of the gesture and restore on mouse-up. Public AX API, no SIP. Addresses the Electron-app lag from pablopunk#157 / pablopunk#106 / pablopunk#167. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Review or Edit in CodeSandboxOpen the branch in Web Editor • VS Code • Insiders |
|
@Wex9 is attempting to deploy a commit to the Pablo Varela's projects Team on Vercel. A member of the Team first needs to authorize it. |
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
Walkthrough
Suggested Reviewers
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@Swift` Shift/src/Manager/MouseTracker.swift:
- Around line 51-52: The restoreEnhancedUIForTrackedApp() call in stopTracking
is being executed before the pending mouse updates are flushed, which causes the
final move/resize operations to still run on the slow Chromium/Electron AX path.
Move the restoreEnhancedUIForTrackedApp() call to after both
flushQueuedExternalMouseUpdate() and flushPendingMouseUpdate() have completed,
then followed by the remaining cleanup operations (invalidateTrackingTimer,
removeMouseEventMonitor, resetTrackingVariables, clearQueuedExternalMouseUpdate,
and isTracking = false).
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 5515b16f-1424-4bd6-9918-f9a38f41179b
📒 Files selected for processing (1)
Swift Shift/src/Manager/MouseTracker.swift
CodeRabbit: in stopTracking, restore AXEnhancedUserInterface AFTER the final flushQueuedExternalMouseUpdate()/flushPendingMouseUpdate() so the last applied move/resize still runs on the fast path. Also add docstrings to the helpers. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
@fpwex9 thanks for the PR and the explanation! Would you mind adding a before/after video? I can't test this because resizing is always smooth for me. Look: ChromeCleanShot.2026-06-22.at.10.39.34.mp4And electron apps behave the same for me |
|
Thanks @pablopunk! Before/after below — macOS 26.5.1, Apple Silicon, resizing the same Chrome window with the same gesture: Before (stock): before.movAfter (this PR): after.movAccording to Claude Code – the lag only appears while the app actually has (Also addressed CodeRabbit's note in 7cac176 — the attribute is now restored after the final flush.) |
|
Funny enough, I just tried your code and it does fix a similar issue I only have with the Zen browser. So it seems it's not only chromium-based apps lol. Will merge! ty |
Problem
On macOS Tahoe (26.x), moving/resizing Chromium/Electron windows (Chrome, VS Code, Obsidian, …) with Swift Shift is laggy and "smeared", while it stays perfectly smooth on native AppKit apps (Finder, Terminal, Sublime, Notes). Crucially, dragging the same Electron window by its native title bar, or resizing it by its native corner, is smooth — so the renderer can relayout in real time; the lag is specific to the AX-driven path. Related: #157, #106, #167.
Root cause
Chromium/Electron apps enable
AXEnhancedUserInterfaceon their application element while an AX client is active. With it on, programmaticAXUIElementSetAttributeValueupdates ofkAXPosition/kAXSizebecome slow and non-live — which is exactly what Swift Shift does on every mouse move. (Lowering the 120 HzminimumUpdateIntervalinMouseTrackeronly helps marginally, confirming it's the per-call cost, not the update rate.)Fix
Temporarily disable
AXEnhancedUserInterfaceon the tracked window's application for the duration of the gesture, and restore the previous value on mouse-up:prepareTracking→ read & remember the app's currentAXEnhancedUserInterface, set it tofalseif it was on.stopTracking→ restore the previous value.Public AX API only, no SIP, no private frameworks. Native apps are unaffected (they don't have the attribute set). Tested on macOS 26.5.1 (Apple Silicon): Chrome / VS Code / Obsidian now move and resize as smoothly as native windows.
Design note
I restore the attribute on mouse-up to avoid permanently changing the app's accessibility state. The alternative (what yabai does) is to leave it off while the WM is active — simpler, but it alters the app's a11y behaviour globally. Happy to switch, or gate it behind a setting.
Test plan
🤖 Generated with Claude Code
Summary by CodeRabbit