fix: screen fit-to-window actually scales the canvas (#133)
The fit toggle relied on canvas.fit { max-width/max-height: 100% }.
The canvas is a flex item, and a flex item's automatic minimum size
(min-width/min-height: auto → the replaced element's intrinsic size)
overrides max-*, so an oversized desktop never shrank — it just got
centred and clipped, looking like the toggle did nothing.
Replace the CSS approach with explicit JS sizing: relayoutCanvas()
computes a scale factor (min of width/height ratios, capped at 1 so
it never upscales) and sets canvas.style.width/height in px,
preserving aspect ratio. Recomputed on fit toggle, window resize,
and framebuffer-size (ServerInit). Pointer mapping is unaffected —
sendPointer already derives scale from getBoundingClientRect().
This commit is contained in:
parent
00281730bb
commit
dfee0574a5
1 changed files with 31 additions and 10 deletions
|
|
@ -57,12 +57,10 @@ html, body { height: 100%; background: var(--base); color: var(--text);
|
|||
width: 100%; height: calc(100% - 36px); overflow: auto;
|
||||
background: var(--crust);
|
||||
}
|
||||
/* Fit mode: centre the canvas and let CSS scale it down to the
|
||||
viewport (intrinsic resolution unchanged — see canvas.fit). */
|
||||
/* Fit mode: centre the canvas (relayoutCanvas() scales it in JS to
|
||||
fit the wrap) and clip any sub-pixel rounding overflow. */
|
||||
#canvas-wrap.fit { align-items: center; overflow: hidden; }
|
||||
canvas { display: block; cursor: default; }
|
||||
/* max-* on a replaced element shrinks it preserving aspect ratio. */
|
||||
canvas.fit { max-width: 100%; max-height: 100%; }
|
||||
#msg {
|
||||
position: fixed; bottom: 1rem; left: 50%; transform: translateX(-50%);
|
||||
background: var(--surface0); color: var(--yellow); border-radius: 6px;
|
||||
|
|
@ -114,22 +112,44 @@ canvas.fit { max-width: 100%; max-height: 100%; }
|
|||
});
|
||||
|
||||
// --- Fit-to-window toggle ---
|
||||
// Scales the canvas down via CSS so the whole desktop is visible
|
||||
// without scrolling. The canvas's intrinsic resolution is untouched;
|
||||
// only its displayed size changes (see canvas.fit / #canvas-wrap.fit).
|
||||
// Pointer coordinates are rescaled in sendPointer to stay accurate.
|
||||
// The choice is persisted in localStorage; default is fit-on.
|
||||
// Scales the canvas down so the whole desktop is visible without
|
||||
// scrolling. The canvas's intrinsic resolution (width/height attrs)
|
||||
// is untouched — only its CSS display size changes, set explicitly
|
||||
// by relayoutCanvas(). Pointer coordinates are rescaled in
|
||||
// sendPointer to stay accurate. Persisted in localStorage; default
|
||||
// is fit-on.
|
||||
let fitMode = localStorage.getItem('screen-fit') !== 'off';
|
||||
// Size the canvas. In fit mode, scale down (never up) to the wrap,
|
||||
// preserving aspect ratio. Explicit px sizing rather than CSS
|
||||
// max-width/max-height: on a flex item those are overridden by the
|
||||
// automatic minimum size, so fit mode was a silent no-op — the
|
||||
// oversized canvas just got centred and clipped (issue #133).
|
||||
function relayoutCanvas() {
|
||||
if (fitMode && canvas.width && canvas.height
|
||||
&& canvasWrap.clientWidth && canvasWrap.clientHeight) {
|
||||
const scale = Math.min(
|
||||
canvasWrap.clientWidth / canvas.width,
|
||||
canvasWrap.clientHeight / canvas.height,
|
||||
1,
|
||||
);
|
||||
canvas.style.width = (canvas.width * scale) + 'px';
|
||||
canvas.style.height = (canvas.height * scale) + 'px';
|
||||
} else if (!fitMode) {
|
||||
canvas.style.width = '';
|
||||
canvas.style.height = '';
|
||||
}
|
||||
}
|
||||
function applyFitMode() {
|
||||
canvas.classList.toggle('fit', fitMode);
|
||||
canvasWrap.classList.toggle('fit', fitMode);
|
||||
fitBtn.classList.toggle('active', fitMode);
|
||||
relayoutCanvas();
|
||||
}
|
||||
fitBtn.addEventListener('click', () => {
|
||||
fitMode = !fitMode;
|
||||
localStorage.setItem('screen-fit', fitMode ? 'on' : 'off');
|
||||
applyFitMode();
|
||||
});
|
||||
window.addEventListener('resize', relayoutCanvas);
|
||||
applyFitMode();
|
||||
|
||||
function hex(bytes) {
|
||||
|
|
@ -514,6 +534,7 @@ canvas.fit { max-width: 100%; max-height: 100%; }
|
|||
dbg('← server-init: ' + fbW + 'x' + fbH + ' bpp=' + pixelFormat.bpp, 'ok');
|
||||
canvas.width = fbW;
|
||||
canvas.height = fbH;
|
||||
relayoutCanvas();
|
||||
setStatus('connected', 'connected');
|
||||
// Request full framebuffer update
|
||||
requestUpdate(0, 0, 0, fbW, fbH);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue