Repository navigation
Stop drawing every border blurred, and give the app back its motion - #1
Conversation
The hairline helper every outlined surface goes through inset its path by a whole pixel before stroking. Under PixelOffsetMode.HighQuality that lands the centreline on a pixel boundary, so GDI+ split each border across two rows at roughly two-thirds strength -- measured, a #3F424D edge on #161826 came back as two rows of #2B2D3A. The stroke now sits on a half-pixel centreline. Invisible under libgdiplus, which is why it survived a redesign reviewed on Linux. Restores the window style bits FormBorderStyle.None strips, so Aero Snap, Snap Layouts, the Alt+Space menu and the minimise animation work again. Adds NAnim, a reusable eased value generalised from the toggle knob -- the one thing in the app that had ever animated. NControl and NPanel drive one for hover and one for press; buttons, select cards and text inputs now fade rather than switch. Honours SPI_GETCLIENTAREAANIMATION. Scrolling eases toward a target instead of jumping 54px per notch. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: f4ad09f868
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| _dragging = true; | ||
| _dragOffset = e.Y - t.Y; | ||
| Capture = true; | ||
| _glide.Stop(); |
There was a problem hiding this comment.
Synchronize the target when cancelling a glide
If the user presses the scrollbar thumb while a wheel glide is still in progress and releases it without moving, this stops the timer but leaves _target at the old destination. The next wheel event is therefore accumulated from that stale destination rather than the visible ScrollY, causing the panel to resume the cancelled glide and potentially jump hundreds of pixels. Set _target to the current scroll position when the thumb cancels the glide.
Useful? React with 👍 / 👎.
Three rendering and interaction defects, all of which came from the interface having only ever been reviewed under libgdiplus on Linux.
Every outlined surface was drawn blurred
Cards, buttons, inputs, tags, toggles, checkboxes, table rows, the sidebar rule and the window's own edge all reach the screen through one hairline helper, which inset its path by a whole pixel before stroking. The app paints under
PixelOffsetMode.HighQuality, which puts sample points on pixel corners, so a 1px pen on an integer coordinate straddles two rows.Measured on Windows — a
#3F424Dedge on#161826:#2B2D3A#3F424DThe stroke now sits on a half-pixel centreline, with the corner radius pulled in so its outer edge still follows the fill beneath it. Verified in the built binary at 150% scale: column 359 background, column 360 exactly
63,66,77, column 361 card surface.libgdiplus does not reproduce the split, so on Linux the borders had always looked correct.
Snap, the window menu and the minimise animation did nothing
FormBorderStyle.NonestripsWS_THICKFRAME,WS_MINIMIZEBOX,WS_MAXIMIZEBOXandWS_SYSMENU. The window was reporting0x16010000— no thick frame, no system menu — so Windows treated it as a fixed panel. Restored inCreateParams. The window still draws all its own chrome, and maximise stays inside the work area becauseWM_GETMINMAXINFOwas already answered correctly.Rounded corners, shadow and the DWM border were never affected; Windows 11 gives those to any top-level window regardless. That was checked before changing anything.
Nothing responded to the pointer
Only the toggle knob had ever animated. That curve is now
NAnim, a reusable eased value;NControlandNPaneleach drive one for hover and one for press, so painters read a float instead of a bool. Buttons, select cards and text inputs use it.SPI_GETCLIENTAREAANIMATIONis honoured, so anyone who has turned animation off in Windows gets none of it.Scrolling also eases toward a target rather than jumping 54px per notch, and the wheel router no longer keeps a second copy of the scroll distance.
Checks
TreatWarningsAsErrorson.0.323 → 0.503 → 0.663 → 0.787 → 0.885 → 0.954 → 0.991 → 1.000, settled and stopped at 133ms.ConfigurO.log.Not verified by execution: the reduced-motion path (would need the Windows setting toggled), and snap/menu behaviour end to end — the style bits are confirmed set, the interactions are not.
version.txtis deliberately untouched; cutting 3.2 is a separate step.