Skip to content

web: fullscreen keeps the display's aspect ratio on any page shell#260

Merged
LinuxJedi merged 2 commits into
mainfrom
fix/web-fullscreen-letterbox
Jul 23, 2026
Merged

web: fullscreen keeps the display's aspect ratio on any page shell#260
LinuxJedi merged 2 commits into
mainfrom
fix/web-fullscreen-letterbox

Conversation

@LinuxJedi

@LinuxJedi LinuxJedi commented Jul 23, 2026

Copy link
Copy Markdown
Owner

Fullscreen in the browser build stretched the picture to the monitor's aspect ratio on any page shell without its own :fullscreen CSS - very visibly on ultrawide monitors.

Root cause. In real element fullscreen try.js relied entirely on the host page's stylesheet to letterbox the canvas, and only the hosted /try shell carries a :fullscreen rule; any other embedding (the retro32 page, self-hosted shells) keeps its normal width: 100% canvas rule, which fills the monitor. The hosted rule was also subtly off: object-fit: contain letterboxes at the presentation buffer's own ratio (the PAL capture is 668x540, about 1.24:1), not the 4:3 TV shape every shell gives the canvas in the page layout.

Fix, all in the page glue so it holds on every embedding:

  • CSS_FS_CANVAS now makes the canvas the largest 4:3 box that fits the screen, centred by auto margins, with object-fit pinned to fill so a shell's own :fullscreen rule cannot re-letterbox the bitmap inside the box. Dynamic viewport units (dvw/dvh) measure the monitor exactly in real fullscreen and track the visible area in the pinned iPhone fallback, where plain vh reaches under Safari's chrome.
  • The styles are applied on fullscreenchange for real fullscreen (previously only the CSS fallback got them) and removed on any exit, Esc included.
  • cssToEmu() loses its fullscreen special case: the bitmap fills the canvas element in every mode now, so the width ratio is the displayed scale.
  • docs/guide/browser.md documents the fullscreen behaviour, which had no doc coverage.

Verified by serving the real page shell with the modified glue and driving Chrome: in fullscreen the canvas measures exactly 4:3 (ratio 1.3333), centred with equal pillarbox bars on a 1.75:1 viewport, and exiting restores the page layout with all inline styles cleared. Chrome denies requestFullscreen to automation input, so the scripted run exercised the pinned-shell fallback path; it applies the identical style object through the same fullscreenchange listener, but the real-fullscreen entry itself still wants a one-click manual check on a wide monitor.

Follow-up for the website repository (not part of this PR): the .try-shell:fullscreen #screen rule in try/index.html is now redundant - the inline styles override it - and can be dropped.

In real element fullscreen the page glue relied on the host page's CSS
to letterbox the canvas, and only the hosted /try shell had a
:fullscreen rule: any other embedding kept its normal width:100% canvas
rule, stretching the picture to the monitor's shape (grotesquely so on
ultrawide monitors). Even the hosted rule letterboxed via object-fit at
the presentation buffer's own ratio (the PAL capture is 668x540), not
the 4:3 TV shape the page layout gives the canvas.

The glue now letterboxes with inline styles in both fullscreen paths:
the canvas becomes the largest 4:3 box that fits the screen, centred,
with object-fit pinned to fill so a shell's own :fullscreen rule cannot
re-letterbox the bitmap inside the box. Dynamic viewport units measure
the monitor exactly in real fullscreen and track the visible area in
the pinned iPhone fallback, where plain vh reaches under Safari's
chrome. cssToEmu() loses its fullscreen special case since the bitmap
now fills the element in every mode, and docs/guide/browser.md gains
the previously undocumented fullscreen behaviour.
Copilot AI review requested due to automatic review settings July 23, 2026 07:00

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes browser fullscreen rendering for Copperline’s web build so the emulator display preserves a consistent 4:3 aspect ratio across any embedding shell (not just the hosted /try page), avoiding visible stretching on wide/ultrawide monitors.

Changes:

  • Apply a 4:3 “largest box that fits” fullscreen letterbox via inline canvas styles (CSS_FS_CANVAS) so it works in all embedding shells.
  • Apply/remove the fullscreen canvas styling on fullscreenchange (real element fullscreen), not only in the CSS-pinned fallback path.
  • Document the fullscreen behavior (including the iPhone pinned fallback) in docs/guide/browser.md.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
docs/guide/browser.md Documents expected fullscreen + iPhone fallback behavior for the browser build.
crates/copperline-web/www/try.js Enforces consistent 4:3 fullscreen sizing via inline styles and updates fullscreen event handling and CSS→emulated scaling logic.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread crates/copperline-web/www/try.js Outdated
The presentation buffer is not the canvas element's shape (the PAL
capture is 668x540 shown as 4:3), so emulated pixels per CSS pixel
differ between the axes; sharing the width ratio skewed vertical
pointer speed by ~8% and made the unlocked cursor-follow pointer drift
vertically from the host cursor. Long-standing in the page layout, and
the fullscreen letterbox now shows the same geometry, so scale each
axis by its own ratio in the pointer-lock, cursor-follow and touch
trackpad delta paths.
@LinuxJedi
LinuxJedi merged commit 8f9c111 into main Jul 23, 2026
11 checks passed
@LinuxJedi
LinuxJedi deleted the fix/web-fullscreen-letterbox branch July 23, 2026 07:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants