Fix the desktop window chrome and remember its geometry - #81
Merged
Conversation
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.
Both bugs reported at the end of #69.
Fixes #69
macOS: traffic lights sit across the edge of a collapsed sidebar
The cluster is positioned by the system against the window, not by the app's layout,
and it runs to x=69pt. The collapsed rail was
3.5rem(56px), so its right borderlanded on the green button's left edge and left that button over the content pane.
--rail-wnow carries the collapsed width:3.5remby default,5remunder:root[data-os='macos']— the only platform that draws its title bar over the app.Measured against the compiled stylesheet in headless Chromium at 1100x720 @2x: the
rail is 56px unchanged off macOS and 80px on it, holding the whole 9..69pt cluster
with the border at 79..80 and no interactive element intersecting it.
Widening the rail exposed a latent centring bug in the session rows, so it is fixed
here too: the collapsed row's inner button carried
flex-1and absorbed the row, sothe wrapper's
justify-centerhad nothing to distribute and the icon sat at the startedge. At 56px that was 1.5px off centre and invisible; at 80px it would have been
10.5px, a visibly left-shifted column against every other icon in the rail. The button
now only takes
flex-1when the sidebar is expanded, where the label needs it.Measured after the fix: header, nav and session icons all centre at 39.5.
Considered and rejected:
trafficLightPositionintauri.conf.json. The cluster is60pt wide, so no offset fits it inside a 56px rail, and Tauri 2.11.5 exposes the
setting at window-creation only — there is no runtime setter to follow the collapse.
Window size and position are not remembered
Every launch reset the window to the configured 1100x720 wherever the system put it.
Adds
tauri-plugin-window-state, registered Rust-side only — no JS permission isgranted for its commands.
The flag set is the load-bearing part. The plugin's default is
StateFlags::all(),and it applies every flag from
on_window_ready, which runs before the page exists.Only sizing and moving leave a hidden window hidden (
set_outer_positionandset_inner_size_physicalreachSetWindowPoswithoutSWP_SHOWWINDOW); the rest donot:
VISIBLEcallsshow()+set_focus()there, defeatingvisible: falseand thepage-load reveal on every launch — reintroducing the blank frame 1.1.1 removed —
while
tests/startup_contract.rsstayed green, since it only reads JSON.MAXIMIZEDreachesShowWindow(SW_MAXIMIZE)on Windows (taowindow_state.rsapply_diff), which has no visibility guard. The window is re-hidden a few lineslater, so the exposure is a frame rather than a session, but it is a show-then-hide
on the one window this code keeps off screen until it has painted.
FULLSCREENtouches the same hidden window;DECORATIONSre-derives the macOSstyle mask the overlay title bar depends on.
So the plugin gets
SIZE | POSITIONand nothing else. That is not free, and thecomment on the constant says so: the plugin records a move without checking whether
the window is maximised, so a window quit while maximised reopens at its pre-maximise
size but in the display's corner. Restoring the maximised state instead would mean
touching the window before it has painted, which is the trade this slice refuses.
Two guards, because the failure mode is silent and the app has no tray icon to
recover through:
VISIBLE,MAXIMIZED,FULLSCREEN,DECORATIONS, matching the existingRENDER_HEAL_DEADLINEidiom.Verified non-vacuous: adding
VISIBLEfails the build withevaluation panicked.startup_contract.rstest for the other half — a call site that stops taking itsflags from the constant.
Upstream limits worth knowing, not introduced here and not papered over in the
changelog: the plugin's monitor-intersection fallback covers position only, so a size
saved on a larger display is restored as-is; geometry is stored in physical pixels, so
moving between a 1x and 2x display rescales the window; and a window quit from macOS
fullscreen saves the fullscreen frame as its windowed size. All three are recoverable
by resizing.
Verification
cargo clippy --workspace --all-targets -- -D warnings,cargo fmt --all --check,cargo test -p omnyssh-gui --locked,npm run check(417 files, 0/0),npm test(215/215),
npm run build— all clean.committed_bindings_are_in_syncpasses: thisslice adds no DTO, command or event, so the IPC contract is untouched.
Reviewed per CLAUDE.md:
/code-reviewat high, then an adversarial pass against theacceptance criteria. Both found real defects — the Windows
MAXIMIZEDbreach and thesession-icon regression above — and both are fixed here rather than waived.
Unrelated, found while running the suite
e2e/terminal.spec.ts:119fails onmaintoo. It looks for the accessible nameClose web-1 · terminal, whileSidebar.svelterendersClose web-1— the twodrifted when
sessionLabelwas shortened to the host name. CI does not run the e2esuite, so it went unnoticed. Left alone here; worth its own fix.