Repository navigation
feat(runtime): preserve native column resizing - #145
Conversation
There was a problem hiding this comment.
1 issue found across 10 files
Confidence score: 4/5
- In
Sources/DefiRuntime/ScrollReconciliation.swift, learning width on each resize sample clones runtime state, including monitor and window collections, adding avoidable work during a drag. Compute the unbounded learning inputs without cloning the full state.
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="Sources/DefiRuntime/ScrollReconciliation.swift">
<violation number="1" location="Sources/DefiRuntime/ScrollReconciliation.swift:66">
P3: Width learning now clones and mutates the runtime state on every resize sample, forcing copy-on-write of the monitor and window collections during a drag. Compute the unbounded learning inputs without cloning the entire `RuntimeState` to avoid avoidable per-frame allocation and latency.</violation>
</file>
Reply with feedback, questions, or to request a fix.
View guided diff | Turn on auto-fix | Re-trigger cubic
ApprovabilityVerdict: Needs Human Approval Macroscope's review found this PR requires human approval — This PR adds native column resizing as a coordinated feature across the runtime, daemon synchronization, macOS event handling, WindowServer reconciliation, and overlay renderer, while also changing parking behavior. Its cross-layer state machine and production-path behavior changes are substantial enough to require human review. You can add or adjust custom eligibility rules. Learn more. |
Match a late post-release frame only against in-flight write targets, and document the helper build step in the column-resizing journey.
There was a problem hiding this comment.
All reported issues were addressed across 4 files (changes from recent commits).
Reply with feedback, questions, or to request a fix.
View guided diff | Turn on auto-fix | Re-trigger cubic
Size-only in-flight writes keep the window at its completed origin, so match late frames against that origin rather than the requested point.
Match a late post-release frame only against in-flight write targets, and document the helper build step in the column-resizing journey.
ad55b38 to
7d0d973
Compare
Size-only in-flight writes keep the window at its completed origin, so match late frames against that origin rather than the requested point.
Match a late post-release frame only against in-flight write targets, and document the helper build step in the column-resizing journey.
Size-only in-flight writes keep the window at its completed origin, so match late frames against that origin rather than the requested point.
7d0d973 to
05bea31
Compare
Restart the width-mismatch stability clock for the gesture window so a user-held width cannot age into an app constraint after release, and ignore post-release frames that match a recent Defi write.
A completed write equals the pre-gesture frame, so dragging a window back to its start width must still count as the user's width.
Match a late post-release frame only against in-flight write targets, and document the helper build step in the column-resizing journey.
Size-only in-flight writes keep the window at its completed origin, so match late frames against that origin rather than the requested point.
05bea31 to
7788a73
Compare
Apply an overlay drop on release only when the window moved, so a preview left by an interrupted drag can never turn an edge resize into a drop.
#152 made minimumTiledWidth and maximumTiledWidth the window's own width, with the layout adding the column's gaps. Native resize learning still compared them with column widths, so it dropped a minimum the window honored and ignored sibling bounds by one gap.
Dismissing prior approval to re-evaluate b3d056c
There was a problem hiding this comment.
1 issue found across 3 files (changes from recent commits).
Confidence score: 3/5
- In
ScrollReconciliation.swift, bypassingeffectiveMinimumTiledWidthcan make a near-request native minimum look like the slot width after gaps, causing a frame at the normal layout target to be mislearned as a user resize. Use the effective minimum during reconciliation.
You’re at about 96% of the monthly reviewed-line limit. You may want to disable incremental reviews to conserve quota. Reviews will continue until that limit is exceeded. If you need help avoiding interruptions, please contact contact@cubic.dev.
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="Sources/DefiRuntime/ScrollReconciliation.swift">
<violation number="1" location="Sources/DefiRuntime/ScrollReconciliation.swift:187">
P2: This bypasses `effectiveMinimumTiledWidth`, so a near-request native minimum is treated as a binding slot width after adding gaps. A frame already at the normal layout target can be falsely learned as a resize and have its minimum cleared; apply the same rounding rule when deriving `currentSlotWidth`.
(Based on your team's feedback about preserving near-request tiled widths as rounding.) [614eb153-c380-4bea-a404-2db8b3e7a129]</violation>
</file>
Reply with feedback, questions, or to request a fix.
View guided diff | Turn on auto-fix | Re-trigger cubic
Learning the width on every sync tick laid the workspace out mid-drag. Each layout restarted the overlay motion: neighbors sprang to the latest layout instead of following the edge, and a window entering the view slid in from its parked corner. While the overlay holds the gesture, the width is now learned once, from the released frame. Cycle width also steps from a width off the presets, such as a native resize, to the next wider or narrower preset instead of restarting.
The overlay scrolls the ribbon with a dragged left edge, but the learned width grew the window to the right on release, so the columns before it sprang back. The ribbon now scrolls by the edge's travel.
Desktop reads wait while the overlay draws, so the snapshot taken at release could hold a frame from before the drag and the width was lost.
The button state can read up one snapshot before the gesture's release event lands. That snapshot finished the gesture as inactive, so the release lost its start frame and the overlay-held width was never learned.
There was a problem hiding this comment.
All reported issues were addressed across 12 files (changes from recent commits).
You’re at about 96% of the monthly reviewed-line limit. You may want to disable incremental reviews to conserve quota. Reviews will continue until that limit is exceeded. If you need help avoiding interruptions, please contact contact@cubic.dev.
Reply with feedback, questions, or to request a fix.
View guided diff | Turn on auto-fix | Re-trigger cubic
…idths A parked window joined the stretch at its corner's height, so it slid in along the bottom. The stretch now clamps to the window's own width bounds and masks the start picture, which spilled into the gap once narrowed. A request just under a window's minimum is no longer learned as rounding, and a user resize clears stale rounding: both centred the window and widened its gaps.
There was a problem hiding this comment.
All reported issues were addressed across 5 files (changes from recent commits).
You’re at about 96% of the monthly reviewed-line limit. You may want to disable incremental reviews to conserve quota. Reviews will continue until that limit is exceeded. If you need help avoiding interruptions, please contact contact@cubic.dev.
Reply with feedback, questions, or to request a fix.
View guided diff | Turn on auto-fix | Re-trigger cubic
The stretch waited for a snapshot to see the resize, so on a fast drag the native edge moved while its neighbours stood still. A drag event now starts it as soon as the WindowServer shows the pressed tiled window resizing. The stretch measures shifts from the window's ribbon place instead of a native frame already resized, takes the held edge from the pointer, and keeps a window still travelling to or from its parking corner at its ribbon place.
There was a problem hiding this comment.
All reported issues were addressed across 4 files (changes from recent commits).
You’re at about 97% of the monthly reviewed-line limit. You may want to disable incremental reviews to conserve quota. Reviews will continue until that limit is exceeded. If you need help avoiding interruptions, please contact contact@cubic.dev.
Reply with feedback, questions, or to request a fix.
View guided diff | Turn on auto-fix | Re-trigger cubic
A terminal resizes in whole cells, so waiting for its native edge to move held the neighbours still for over 100 ms. A press on a tiled window's side edge now starts the stretch at the first horizontal move of 2 points.
There was a problem hiding this comment.
All reported issues were addressed across 1 file (changes from recent commits).
You’re at about 97% of the monthly reviewed-line limit. You may want to disable incremental reviews to conserve quota. Reviews will continue until that limit is exceeded. If you need help avoiding interruptions, please contact contact@cubic.dev.
Reply with feedback, questions, or to request a fix.
View guided diff | Turn on auto-fix | Re-trigger cubic
…lease During a stretch the daemon kept snapshotting the desktop. Its window list waited on the WindowServer, busy with the live resize, while holding the connection the overlay commits through, so the stretch froze for half a second. The daemon now skips snapshots until release, which learns the width. A release re-parks other workspaces' windows. Without ribbon history they started shifted by the ribbon's motion and crossed the screen into their corner; they now stay where they are.
Hidden windows waited in the bottom-right corner since #152, chosen to leave other displays clear without the staircase. The staircase came back, and any native motion the overlay misses now crossed the screen diagonally. Park at the side edge nearest the window, at its own height, as before #152 and as Rift, OmniWM and paneru do, so a missed motion is a short horizontal slide. Corners and the bottom edge remain the fallback when both side edges touch another display.
- Drop a contradicted width bound even when the column already has the released width, so a stacked window resized past its maximum keeps it. - Advance a settling release instead of restarting it on every button-up snapshot, so the settlement times out with animations off. - Release the gesture scroll anchor once a released resize is learned, so it no longer undoes the left-edge scroll shift. - Read the side-edge press at the event's location, not when the queue runs. - Keep the stretch width range under a native maximum below 240 pt.
Summary
Dragging a tiled window's side edge sets its column width, and the width stays. The overlay stretches the window and its neighbours with the pointer. Hidden windows wait at the side edge again. Closes #94.
Evidence
After: 0 freezes over 12 slow drags. Neighbours follow from the first event. Other workspaces stay parked on release (
anotherWorkspacesParkedWindowStaysPutWhenTheRibbonMoves). Installed build: hidden windows at x=1511 and x=-375, y=37, withparkingRepairs=0.python3 script/verify.py localpasses on b7c582c (build, Swift tests, workflow tests).Stacked window resized past its maximum to the column width drops the maximum: fails before b7c582c, passes after.Mouse resize forgets the learned width rounding,A request just under the window's minimum is a clamp, not rounding.ParkingTests: side-edge table, right-half window, displays on both sides fall back to the bottom edge.Merge Danger
Door: two-way
Revertible commits, with no stored data or config changes. The parking change also reverses #152's corner parking. AGENTS.md is updated to match.
Blast Radius: wide
Every hidden window moves to a new parking spot once, after the upgrade. A regression would show as a resize that snaps back, a stretch that lags or starts during a reorder drag, or a parked window showing on a side edge or on another display.
Note
Preserve native column resizing through gesture release, width learning, and parking changes
Daemon.mouseGestureChangedWindowFrameand settling against the latest WindowServer frame.learnTiledWindowWidthto keep valid min/max bounds, drop only bounds the observed frame violates, clear stale width rounding, and adjust workspace scroll offset from the released window's left edge.mouseGestureWidthLearningFramenow prefers a release frame and ignores frames matching recent internal Defi writes.AXFrameCoordinator.frameMatchesPendingInternalWriteto identify frames that match an in-flight internal write, and changesacceptTiledWindowFrameto not count minimum-width clamps as width-rounding overshoot.cycleWidthstep from off-preset pixel widths when a viewport width is supplied.parkedFramein Parking.swift returns side-edge positions instead of bottom/corner fallbacks;nearestPresetIndexin WorkspaceScrolling.swift is removed. Adds a manual verification guide at column-resizing.md.Macroscope summarized b7c582c.