Skip to content

🐞 Avoid cursor stutter when suppressing Mission Control - #1133

Open
jvanderen1 wants to merge 8 commits into
mrkai77:developfrom
jvanderen1:fix/609-suppress-mission-control-stutter
Open

jvanderen1 wants to merge 8 commits into
mrkai77:developfrom
jvanderen1:fix/609-suppress-mission-control-stutter

Conversation

@jvanderen1

@jvanderen1 jvanderen1 commented Aug 9, 2026 •

Copy link
Copy Markdown
Contributor

Description

With Suppress Mission Control enabled, dragging a window to the top of the screen stutters. #609 reported this and was closed by turning the toggle off. The stutter is still in current develop when the toggle stays on. Tracked again in #1159.

Why: Loop keeps Mission Control closed by warping the cursor 1px down on every drag event (CGWarpMouseCursorPosition). That fights the upward drag, so the cursor thrashes.

Fix: Rewrite the drag event’s location instead of warping the cursor. Snap detection stays on a listen-only tap. The active tap is created only after a window has been resolved and has moved, and it is removed on mouse-up. Drags that are not a window never hit it. A held top-edge drag is rewritten only once the previous event was already on that edge, so a single crossing between stacked displays is left alone.

Fixes #1159

How has this been tested?

Local Debug build on macOS 27.0 (also checked earlier on macOS Tahoe):

  • Suppress on + drag to top and hold — cursor stays smooth, Mission Control does not open
  • Top snap preview still appears and applies on mouse up
  • Suppress off — Mission Control can still open from a top-edge window drag
  • Unit tests for which display edge is rewritten, including a stacked-display seam and a shared corner

The checked drag tests are from the earlier build. This update changes when the tap exists: it starts only after the window moves, and it is gone on mouse-up.

Screencast

output.mp4

Checklist:

  • I have performed a self-review of my own code
  • I have made corresponding changes to the documentation if applicable
  • I have no unrelated changes in this PR.

Please describe to which degree, if any, an LLM was used in creating this pull request.

Cursor (Grok) helped investigate the stutter and draft the change in WindowDragManager, including the later event-tap hardening. I reviewed the code, confirmed it builds, and manually tested top-edge dragging before opening this PR.

jvanderen1 and others added 3 commits August 9, 2026 00:10
Rewrite top-edge drag events in an active tap instead of warping the cursor each frame, which caused the stutter reported in mrkai77#609.

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
@jvanderen1

Copy link
Copy Markdown
Contributor Author

@mrkai77 I was wondering if you had q chance to see this PR? I have noticed the "Supress Misson Control" option in Loop was quite laggy on the top edge. This resolves that issue.

Rewrite top-edge drags before window lookup finishes, and resolve the display with CoreGraphics so the tap thread does not touch AppKit.

Co-authored-by: Cursor <cursoragent@cursor.com>

@mrkai77 mrkai77 left a comment •

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for digging into this!

The thing stopping me from merging is the always-on active event tap (and I apologize for taking this long to respond). Right now every leftMouseDragged event on the system goes through our callback before macOS delivers it. That's true for all drags, for as long as Loop is running, even for users who have snapping or suppressMissionControlOnTopDrag turned off. A listen-only tap failing just means Loop misses events. If an active tap stalls or gets disabled by a timeout, drag input breaks for the whole system, and it's a failure point I'd rather avoid adding for this feature.

I think Rectangle handles this ideally, and it's worth a look. It rewrites the event location the same way this PR does, but it only keeps the active tap while the setting is on (startEventMonitor / reloadFromDefaults). Rectangle only blocks fast drags into Mission Control, and it may make sense to adopt this feature in Loop too.

Could we narrow the tap's lifetime along those lines? Some ideas from me:

  • Only while a window is being dragged. Keep the passive monitor as the default, create the active tap once we've resolved a window and seen it move, and remove it on mouse-up. Non-window drags would then never reach the active tap, so they'd stop getting rewritten.
  • At minimum, only while the setting is on. Use the passive monitor when suppressMissionControlOnTopDrag or snapping is off, and swap monitors when the setting changes, like Rectangle does.

If the lifetime is tied to a window drag, the generation/pause state probably goes away too. That would also remove a race I found while reviewing: the lookup Task reads generation only when it starts running, which can be after mouse-up has already bumped it, so a leftover pause can carry into the next drag.

One smaller thing: topEdgeY also matches the border between stacked displays, where Mission Control can't trigger. Rectangle's dragPrevY check avoids that by only rewriting when the cursor was already at the edge on the previous event.

An always-on active tap can stall every drag on the system. Snap detection stays listen-only, and the active tap is installed only after a resolved window moves.

Co-authored-by: Cursor <cursoragent@cursor.com>
@jvanderen1

Copy link
Copy Markdown
Contributor Author

The active tap is no longer always on.

Snap detection stays on the listen-only monitor. The active tap is created only after a window has been resolved and has moved, and it is removed on mouse-up, so a non-window drag never reaches it. The generation/pause state is gone with that. Rewriting also waits until the previous event was already on the same top edge, so crossing the seam between stacked displays once is left alone.

@jvanderen1
jvanderen1 requested a review from mrkai77 October 2, 2026 23:56

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

🐞 Cursor stutters at the top edge when Suppress Mission Control is on

2 participants