Skip to content

Scroll the launcher page so the footer stops covering the panel - #369

Merged
bryanthaboi merged 1 commit into
bryanthaboi:devfrom
pmarcus93:launcher-page-scroll
Jul 29, 2026
Merged

Scroll the launcher page so the footer stops covering the panel#369
bryanthaboi merged 1 commit into
bryanthaboi:devfrom
pmarcus93:launcher-page-scroll

Conversation

@pmarcus93

@pmarcus93 pmarcus93 commented Jul 29, 2026

Copy link
Copy Markdown

The problem

On a window too short for the stacked single-column layout (a phone, or a narrow desktop window), the ROM / SAVE FILES / Play / SAVE SLOT stack runs past the bottom of the window. The footer stays pinned there and draws over it: nothing clips the panel and nothing scrolls it, so everything below the fold is unreachable.

On a 420x820 window the panel wants ~647px and the content region offers ~441px, so roughly 200px of it is simply lost behind the footer.

The change

Everything under the tab bar (panel, updater banner, footer) becomes one scrolling column, used only when it is taller than the room below the tab bar. The strip, logo and tab bar stay pinned, so navigation is always on screen, and the footer is laid out downward from footerTop right after the content instead of upward from the window bottom.

  • RomImporter.pageScrollFor is the whole decision, pure and covered by tests/engine/launcher_page_scroll.lua. A window that grows back drags the offset down with it, so the page never stays parked past its own end.
  • The panels return their natural height as they draw, so the measurement is the previous frame's: the same one-frame settle the slot and mod lists already use.
  • One scroll axis at a time. While the page scrolls, the panels draw paged: the slot and mod lists take their natural height, keep no inner scroll region and report a max of 0, so wheel, right stick and drag all move the page and never fight a list for the same gesture. Two-column layouts do not overflow, paged stays false, and every one of these behaves exactly as before.
  • inside() and _ptIn() reject a rect that scrolled out of the viewport, so a control that slid under the tab bar cannot be clicked through it. Tab chips are pinned and exempt. pageScroll resets on a tab change.

Android needed an input path first

Android had no scroll gesture at all. The launcher is handed no move events (main.lua forwards neither touchmoved nor mousemoved while it is up) and its mouse emulation was never trusted, which is what "no reliable pointer polling" referred to. That was survivable while every scroll region was an inner list with a wheel alternative, and useless once the page itself is what scrolls, since a phone is exactly where it overflows.

love.touch is pollable, so _pointerHold reads the first active touch there and hands _updateSlotDrag the same (held, y) pair the mouse gives on desktop. Slot rows and mod toggles consequently arm on press and commit on release on Android too, matching desktop, so a swipe that starts on a card scrolls instead of selecting it. All of it is gated on touchPollable: without love.touch, every Android path is exactly what it was.

Window floor

conf.lua grows minwidth/minheight (480x360) for the desktop window, under which the cards stop being readable at all. Mobile is fullscreen and ignores it.

Verification

  • scripts/test.sh --quick passes, including the new engine-tier suite.
  • Headless draw pass over seven window sizes (420x820, 480x640, 1200x420, 1024x768, 1440x900, plus the mods tab): 1024x768 and 1440x900 do not scroll, so the desktop layout is untouched; the narrow ones do, and the footer lands inside the window at full scroll. Scrolled to the end, the ROM button (now above the viewport) fails the hit test while the on-screen controls still pass.
  • On the Android emulator at 1080x2400, against a build of the parent commit: before, the footer painted over the SAVE SLOT card with the content unreachable; after, the page pans by touch, the tab bar stays pinned and clips the content under it, and the footer is reachable and intact.

Screenshots

Android

Current build on a Galaxy S26 Ultra (unscrollable, logo on top of other elements):

image

Fixed build on the simulator (scrollable):

Captura de Tela 2026-07-28 às 23 57 36

MacOS

Current build on a narrow window, same problems as the Android version (unscrollable, logo on top of other elements):

Captura de Tela 2026-07-28 às 23 59 10

Dev build (fixed):

image

@pmarcus93
pmarcus93 force-pushed the launcher-page-scroll branch from 3107180 to 234a3be Compare July 29, 2026 03:14
@bryanthaboi

Copy link
Copy Markdown
Owner

can u update ur branch

On a window too short for the stacked single-column layout -- a phone, or a
narrow desktop window -- the ROM / SAVE FILES / Play / SAVE SLOT stack ran
past the bottom of the window while the footer stayed pinned there and drew
over it. Nothing clipped the panel and nothing scrolled it, so the overflow
was unreachable.

Everything under the tab bar (panel, updater banner, footer) is now one
scrolling column, used only when it is taller than the room below the tab
bar. The strip, logo and tab bar stay pinned, so navigation is always on
screen, and the footer is laid out downward from footerTop right after the
content instead of upward from the window bottom.

- RomImporter.pageScrollFor is the whole decision, pure and covered by
  tests/engine/launcher_page_scroll.lua. A window that grows back drags the
  offset down with it, so the page never stays parked past its own end.
- The panels return their natural height as they draw, so the measurement is
  the previous frame's: the same one-frame settle the slot and mod lists
  already rely on.
- One scroll axis at a time. While the page scrolls, the panels draw paged:
  the slot and mod lists take their natural height, keep no inner scroll
  region and report a max of 0, so wheel, right stick and drag all move the
  page. Two-column layouts do not overflow, paged stays false, and every one
  of these behaves exactly as before.
- inside() and _ptIn() reject a rect that scrolled out of the viewport, so a
  control that slid under the tab bar cannot be clicked through it. Tab chips
  are pinned and exempt. pageScroll resets on a tab change.

Android had no scroll gesture at all: the launcher is handed no move events
(main.lua forwards neither touchmoved nor mousemoved while it is up) and its
mouse emulation was never trusted, which is what "no reliable pointer
polling" referred to. That was survivable while every scroll region was an
inner list, and useless once the page itself scrolls, since a phone is
exactly where it overflows. love.touch is pollable, so _pointerHold reads the
first active touch there and hands _updateSlotDrag the same (held, y) pair
the mouse gives on desktop. Slot rows and mod toggles consequently arm on
press and commit on release on Android too, matching desktop, so a swipe that
starts on a card scrolls instead of selecting it. All of it is gated on
touchPollable: without love.touch every Android path is exactly what it was.

conf.lua also grows minwidth/minheight (480x360) for the desktop window,
under which the cards stop being readable. Mobile is fullscreen and ignores
it.

Verified on the Android emulator (1080x2400) against a build of the parent
commit: before, the footer painted over the SAVE SLOT card with no way to
reach it; after, the page pans by touch and the footer is reachable and
intact.
@pmarcus93
pmarcus93 force-pushed the launcher-page-scroll branch from 234a3be to cc67be3 Compare July 29, 2026 15:54
@bryanthaboi
bryanthaboi merged commit c52a352 into bryanthaboi:dev Jul 29, 2026
4 checks passed
@pmarcus93

Copy link
Copy Markdown
Author

Thanks, @bryanthaboi!

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