Repository navigation
fix: v0.10.0 review follow-ups — window bounds under per-monitor DPI, git busy key, unmerged/quoted status (#181) - #185
Merged
Conversation
…ey, unmerged/quoted status (#181) - Window bounds: read the window fields of state.json synchronously in the constructor and apply them in OnSourceInitialized with SetWindowPlacement, before the window is shown, in physical pixels (new AppState.LastPlacement + DPI). Re-apply once if the move changed the window's DPI so the saved size is exact in mixed-DPI setups. Visibility/fallback decided against monitor work areas by the WPF-free WindowPlacementMath; legacy DIP bounds still honoured. - Git busy slot: claim it with a key resolved via EnsureRepoRootAsync (off the UI thread) instead of falling back to the working folder before RepoRoot lands; keys folded by GitWorktrees.BusyKey. - ParseStatusV2: unmerged entries keep their real XY code; C-quoted paths are unquoted (escapes, octal UTF-8 bytes), renames split before unquoting. Closes #181 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NsYm9iLc2aRnRDfV2uZRQX
…able repo-root keys - Window bounds: a Normal window saves GetWindowRect (a snapped window's rcNormalPosition is its pre-snap rect); maximized/minimized save rcNormalPosition. Offset and DPI now come from the monitor the rect is on (WindowPlacementMath.SaveFromScreen / SaveFromWorkspace), not MonitorFromWindow. A restored Normal window is verified with GetWindowRect and corrected with SetWindowPos. - Legacy LastNormalBounds: try every monitor's DPI as the scale and keep the one whose scaled rect lands on that monitor (v0.10.0 saved per-monitor DIPs); primary breaks ties. - EnsureRepoRootAsync no longer caches a root probed for a folder that changed during the await. - GetRepoRootAsync: map a Linux-absolute --git-common-dir from a WSL worktree to \wsl$\<distro>\..., and canonicalise the result so 8.3/junction spellings of one repo share a busy-slot key. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NsYm9iLc2aRnRDfV2uZRQX
Conflicts: CLAUDE.md (kept the window-bounds paragraph and the new Bundled ConPTY section) and MainWindow.OnLoaded (kept PreferBundledConPty; the old RestoreWindowState call stays removed — bounds are applied before show). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NsYm9iLc2aRnRDfV2uZRQX
Conflict in MainWindow.OnLoaded: kept EnsureOpenWithSeeded(); the old RestoreWindowState call stays removed (bounds are applied before show). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NsYm9iLc2aRnRDfV2uZRQX
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Follow-ups from the v0.10.0 pre-release review.
1. Window bounds restore under per-monitor DPI v2
state.jsonsynchronously (StateService.TryReadWindowState), andOnSourceInitializedapplies them withSetWindowPlacement, in physical pixels.SetWindowPos.AppState.LastPlacementstores physical pixels plus the DPI of the monitor the rect is on:GetWindowRect, so a snapped window comes back snapped, as before.rcNormalPosition.WindowPlacementMath.LastNormalBoundsis still written. When there is noLastPlacement, it is read by trying each monitor's DPI as the scale: v0.10.0 saved DIPs per the window's own monitor, older builds DIPs per the primary monitor.2. Git busy-slot key before RepoRoot resolves
SessionViewModel.EnsureRepoRootAsync. That runs off the UI thread and never caches a root for a folder that has since changed.GetRepoRootAsyncnow returns one spelling per repo: canonicalised, and with a WSL worktree's Linux path mapped to\wsl$.3.
ParseStatusV2core.quotePath=falseare unquoted, including octal escapes as UTF-8.Review
A read-only review of the first commit found two problems, both fixed in the second commit:
Tests
822 unit tests pass (57 new):
WindowPlacementMathTests: per-monitor offset and DPI round trips, saving a rect that sits on another monitor, legacy v0.10.0 and system-DPI bounds.StateServiceTests,BusyKeyandRepoRootFromCommonDir(local and WSL).Manual verification still needed (multi-monitor, not yet done)
state.jsonwith the window on the secondary puts it on the right monitor at the right size.Closes #181
🤖 Generated with Claude Code
https://claude.ai/code/session_01NsYm9iLc2aRnRDfV2uZRQX