All notable changes to this fork of ModMove.
- Fixed windows being pinned at the edge shared between vertically/horizontally adjacent
screens. A window at the top edge of a bottom screen could not be resized taller or
slow-dragged into the screen above, because move/resize were constrained to the single
screen the window sat on (turning the shared edge into a hard wall).
- Move constraints now apply against the whole desktop (
WindowCalculations.desktopBoundingFrame, the union of all screens' visible frames), so internal shared edges are never walls; only the desktop's outer perimeter constrains. - Resize constraints use the desktop frame when all displays share one Space, but the
single containing screen when "Displays have separate Spaces" is enabled — macOS
refuses display-spanning windows in that mode (
WindowCalculations.resizeConstraintFrame).
- Move constraints now apply against the whole desktop (
- Fixed windows collapsing to near-zero height when growing across a shared screen edge:
the old position-first resize order moved the origin across the edge before growing, and
macOS clamped the size to the sliver of the destination screen. Growing now sets size
first (away from the anchor), falls back to position-first only when clamped at an outer
edge (the 2025-12-06 case), and rolls back the frame on a catastrophic clamp instead of
anchoring around a sliver. Clamp events are logged (see
./logs.sh). - Fixed windows snapping to their minimum ("half") height when resized at the edge shared
by two screens — the root cause of the original shared-edge report:
- Screen lookup matched the window's top-left POINT with inclusive bounds; an origin
exactly on the shared edge is contained by BOTH screens, and the first-listed screen
won. With the wrong screen selected, the sticky-edge cap forced the resize delta to
-height, driving the desired height to 0 (macOS then clamps to the app minimum). - Screen selection is now by largest window-rect overlap
(
WindowCalculations.screenContaining), which is unambiguous and order-independent. - Resize constraints now require the window to be inside the constraint frame (same semantics as move constraints): they can prevent leaving, but never yank a window that is already outside — so any future wrong-frame bug degrades to "unconstrained" instead of a violent snap.
- Suite now 98 tests.
- Screen lookup matched the window's top-left POINT with inclusive bounds; an origin
exactly on the shared edge is contained by BOTH screens, and the first-listed screen
won. With the wrong screen selected, the sticky-edge cap forced the resize delta to
- Fixed windows being TELEPORTED ("snaps to half height") when resized at the edge shared
by two screens — root cause found by empirically probing the WindowServer
(
scripts/ax-probe.swift) on macOS 26.5:- AX position sets whose rect would straddle two displays are not applied; the WindowServer teleports the window elsewhere (still returning success). Per-frame anchor-fix position sets during upward growth at the shared edge hit this constantly.
- Resize constraints now always use the single screen containing the window: shared edges are honest walls for resizes (moves still cross screens fine).
- The per-frame resize orchestration was extracted into
ResizeFrameApplier(over aWindowControllingprotocol) with a verify-and-repair guard: any teleport is detected and the pre-frame rect restored. - Orchestration is now unit-tested against a simulated WindowServer implementing the
probed teleport laws (
ResizeOrchestrationTests); tests were confirmed failing against the old logic before the fix. Suite now 102 tests.
- Added
ResizePropertyTests: seeded (reproducible) fuzzing of ~550 random screen layouts / windows / corners / speeds / multi-frame gestures per run, checking frame-by-frame invariants (no teleports, no sub-minimum sizes, anchor corner never drifts, constrained gestures stay on screen). Plus deterministic edge cases (ResizeEdgeCaseTests): screen-corner pinning, full-height windows, reversal gestures, shrink-past-minimum, mixed-axis drags. - Bugs found by the fuzzer and fixed:
- Mixed-axis resizes (grow one axis, shrink the other) misfired the catastrophic-clamp rollback and emitted an off-screen transient position; the check now compares against min(current, desired) per axis and the rollback restores size before position.
- Float drift (1e-14) at an exact screen edge disabled the constraint gates via exact containment; gates now use 0.5px tolerance.
- Straddling windows (spanning two screens) now resize size-only: every position set — including rollbacks — is unreliable for them (verified failing before the guard).
- Suite now 110 tests.
- Optimized
windowInsideFrame()to use cached values instead of Accessibility API queries- Eliminates 120-240 expensive API calls per second during window moves
- Commit: e1b663a
- Replaced
Date()withCACurrentMediaTime()for mouse speed tracking- Eliminates 60-120 object allocations per second
- More accurate timing with monotonic clock
- Commit: f3b3d85
- Improved state cleanup between move/resize operations
- Properly resets tracking variables (prevMousePosition, mouseSpeed, prevTime)
- Ensures clean transitions between operations
- Added
build.shscript for Release builds - Added
deploy.shscript for easy installation to /Applications - Fixed build issues with missing ApplicationServices import
- Windows now resize from the corner closest to the mouse cursor
- Makes resize behavior more intuitive and natural
- Commit: 168b8a0
- Changed from frame-to-frame delta to absolute position tracking
- Tracks initial mouse position, window position, and window size
- Eliminates cumulative drift and jitter during moves/resizes
- Commits: 107c349, 37e0874
- Windows stay within visible screen bounds during slow movements
- Respects macOS menu bar and dock (uses NSScreen.visibleFrame)
- Added to both move and resize operations
- Commits: 88ea9ab, 8c20c56
- Mouse speed tracking using exponential moving average
- Fast movements (>1000 px/sec) bypass boundary constraints
- Allows "throwing" windows outside screen bounds when needed
- Slow movements remain constrained for precision
- Commit: d5e95ee
Based on @keith's ModMove - a lightweight macOS utility implementing the window manipulation feature from HyperDock.