diff --git a/src/main.cpp b/src/main.cpp index d5dfa55..7cee294 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -7,6 +7,7 @@ #include "logical_size.h" #include "logger/logger.h" #include "provisioning.h" +#include "scroller_page.h" namespace { // How long audio fades out before the app tears down on quit. Only applied @@ -201,11 +202,15 @@ SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event) { std::to_string(event->window.data1) + "x" + std::to_string(event->window.data2)); // Logical presentation persists across resizes; re-apply defensively - // in case backend state was reset underneath us. - SDL_SetRenderLogicalPresentation(state.renderer, - radiantwave::kDesignWidth, - radiantwave::kDesignHeight, - SDL_LOGICAL_PRESENTATION_LETTERBOX); + // in case backend state was reset underneath us. Skip while the + // scroller is active — it owns its own presentation (NONE, full + // window) and restores LETTERBOX in onPop. + if (!dynamic_cast(state.pages.current())) { + SDL_SetRenderLogicalPresentation(state.renderer, + radiantwave::kDesignWidth, + radiantwave::kDesignHeight, + SDL_LOGICAL_PRESENTATION_LETTERBOX); + } } if (!state.keybinds.handleEvent(*event)) { diff --git a/src/scroller_page.cpp b/src/scroller_page.cpp index 3903e8e..6c6dc79 100644 --- a/src/scroller_page.cpp +++ b/src/scroller_page.cpp @@ -34,13 +34,37 @@ void ScrollerPage::onPush(AppState &state) { state_ = &state; - int winW = 0; - int winH = 0; - radiantwave::getLayoutSize(state.renderer, &winW, &winH); - screenW_ = static_cast(winW); - screenH_ = static_cast(winH); - // Lines are capped at the full screen width; the widest Fibonacci lines are - // sized to fill it with whole words (peak word count derived from the + // Save the current logical presentation (LETTERBOX at design resolution) + // and switch to NONE so we render into the full physical window. This + // lets the scroller scroll the entire vertical extent of tall/rotated + // displays while keeping text at the same pixel scale. onPop restores + // the original presentation for other pages. + SDL_GetRenderLogicalPresentation(state.renderer, &savedLogicalW_, + &savedLogicalH_, &savedMode_); + + SDL_Window *window = SDL_GetRenderWindow(state.renderer); + int windowW = 0; + int windowH = 0; + if (window) + { + SDL_GetWindowSize(window, &windowW, &windowH); + } + if (windowW <= 0) + { + windowW = radiantwave::kDesignWidth; + } + if (windowH <= 0) + { + windowH = radiantwave::kDesignHeight; + } + + SDL_SetRenderLogicalPresentation(state.renderer, windowW, windowH, + SDL_LOGICAL_PRESENTATION_DISABLED); + + screenW_ = static_cast(windowW); + screenH_ = static_cast(windowH); + // Lines are capped at the full screen width; the widest Fibonacci lines + // are sized to fill it with whole words (peak word count derived from the // screen), independent of resolution. maxLineWidth_ = screenW_; @@ -101,6 +125,11 @@ void ScrollerPage::onPause(AppState &state) void ScrollerPage::onPop(AppState &state) { + // Restore the original logical presentation so other pages (Home, + // Settings, etc.) render in the design-resolution LETTERBOX space. + SDL_SetRenderLogicalPresentation(state.renderer, savedLogicalW_, + savedLogicalH_, savedMode_); + state.audio.stopTrackFadeOut(kFadeSeconds); state.keybinds.unbindAll(); destroyResources(); diff --git a/src/scroller_page.h b/src/scroller_page.h index 4160cae..0ccd429 100644 --- a/src/scroller_page.h +++ b/src/scroller_page.h @@ -115,4 +115,8 @@ private: float velocityDelay_ = 2.5f; int velocityState_ = 0; float velocityTimer_ = 0.0f; + + int savedLogicalW_ = 0; + int savedLogicalH_ = 0; + SDL_RendererLogicalPresentation savedMode_ = SDL_LOGICAL_PRESENTATION_DISABLED; };