Support the reMarkable Paper Pro Move by detecting geometry at runtime#23
Support the reMarkable Paper Pro Move by detecting geometry at runtime#23z3knayr0 wants to merge 3 commits into
Conversation
Riddle hardcoded the Paper Pro's ("ferrari") panel resolution and pen
digitizer range as compile-time constants throughout the codebase.
The Paper Pro Move ("chiappa") has a different panel (960x1696 aux
framebuffer vs. 1620x2160) and a different digitizer range, so the
app misrendered/mismapped pen input on that device.
Instead of adding a second hardcoded set of constants (which would
require detecting the device model and duplicate the problem for any
future panel size), this makes both values runtime-detected:
- fb.rs: SCREEN_W/SCREEN_H become screen_w()/screen_h() backed by a
OnceLock, set once via fb::init_screen() right after the display
backend reports its real surface dimensions (works for both the
takeover/quill and windowed/qtfb paths).
- pen.rs: DIGI_MAX_X/DIGI_MAX_Y are now read per-device via
EVIOCGABS on the marker input fd at PenDevice::open() time, with
the Paper Pro's known values kept only as a fallback if the ioctl
ever fails.
The qtfb (windowed AppLoad) path is left as Ferrari-only — its wire
format (FBFMT_RMPP_RGB565) is documented as Paper-Pro-native, and
riddle ships with "qtfb": false in its manifest, so that path isn't
exercised by the shipped app either way.
Tested on real hardware: built with the official chiappa SDK
(v3.27.0.97, matching device OS 3.27.1.0) against libqsgepaper.so
pulled from the device, deployed, and ran a live takeover session
that confirmed:
quill: aux framebuffer 960x1696 format=4 bpl=3840
riddle: display quill/takeover (960x1696 stride 3840)
riddle: pen digitizer range 6760x11960
and produced a working oracle reply end-to-end.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 4d83180331
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| pub fn screen_w() -> usize { | ||
| SCREEN_DIMS.get().expect("init_screen not called before screen_w").0 |
There was a problem hiding this comment.
Initialize geometry before using screen helpers in tests
When unit tests or other non-run() paths call these helpers, SCREEN_DIMS has never been set because fb::init_screen() is only called after Display::open() in run(). Existing tests such as help::modal_renders_and_restores/sleep_page_renders_and_restores call screen_w() directly, and the ink tests reach it through BBox::add, so the suite now panics before exercising those cases; add a test/default initialization path or avoid requiring global display initialization for these helpers.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Fixed — added fb::test_init_screen() (idempotent OnceLock::set, safe under parallel test execution) and called it at the top of the four affected tests: help::tests::modal_renders_and_restores, help::tests::sleep_page_renders_and_restores, and the two ink::tests that reach BBox::add via Ink::pen_point. cargo test now passes: 26 passed; 0 failed. See fc75f1f.
Two related problems, both found testing long replies on the Move's
shorter 1696px page:
1. A fresh reply started at ((screen_h - total_h) / 3), centered on
the *first streamed chunk's* height -- not the full reply's, which
isn't known yet. Short first chunks (the common case, since models
stream a few words at a time) pushed the start point a third of
the way down the page, wasting the space above and leaving less
room below for what turned out to be a long reply. Replies now
start at a small fixed top margin instead.
2. Once a reply reached the page-bottom margin, the rest of the
streamed text was silently dropped ("reply reached the page
bottom; trailing text dropped") -- still recorded in memory, but
never shown on screen and unrecoverable since there's no scrolling
on this hardware.
plan_reply now only lays out as many lines as fit before the page
bottom and hands back whatever didn't as leftover text. When a page
finishes inking with leftover pending, the diary parks (`PageFull`)
rather than auto-advancing -- fading and writing the rest before it's
been read would be pointless. Touching the pen to the page (the same
gesture that already early-dismisses `Lingering`) dissolves the page
and continues writing the rest from the top (`TurningPage`), while
still absorbing further streamed text in the background so it's
ready the moment the page turns. A freshly-turned page is itself
capped to what fits, so accumulated backlog re-paginates correctly
no matter how much piled up while parked.
screen_w()/screen_h() panic until fb::init_screen() runs, which only happens in run() after Display::open(). Tests that reach them directly (help::tests::modal_renders_and_restores, help::tests::sleep_page_renders_and_restores) or transitively via BBox::add (ink::tests::erase_forgets_covered_points_and_splits_strokes, ink::tests::erasing_everything_empties_the_ink) never go through run(), so the suite panicked before exercising those cases. Adds fb::test_init_screen() (any real dimensions work for a test; uses the Paper Pro's since that's what these tests were originally written against) and calls it at the top of each affected test. OnceLock::set is idempotent, so this is safe under parallel test execution. `cargo test` now passes: 26 passed; 0 failed.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: fc75f1ffba
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| let (plan, pending) = plan_reply(&font, &oracle_excuse("no oracle"), Some(y)); | ||
| State::Replying { plan, next: Instant::now(), rx: None, pending } |
There was a problem hiding this comment.
Include retained ink in no-oracle pagination
When the no-oracle message is paginated (for example, on the 960x1696 Move after the user writes near the bottom), this branch deliberately leaves the user's handwriting on the page but only carries the reply plan forward. The later page-turn path dissolves plan.region only, so tapping for the remaining error text leaves the original handwriting underneath the next page; include user_ink.bbox in the paginated region here or avoid paginating this "leave the writing" path.
Useful? React with 👍 / 👎.
Summary
Riddle hardcoded the Paper Pro's ("ferrari") panel resolution and pen digitizer range as compile-time constants throughout the codebase. The Paper Pro Move ("chiappa") has a different panel and digitizer range, so the app misrendered/mismapped pen input on that device.
Rather than adding a second hardcoded constant set (which just duplicates the problem for any future device), both values are now detected at runtime:
fb.rs:SCREEN_W/SCREEN_H→screen_w()/screen_h()backed by aOnceLock, set once viafb::init_screen()right after the display backend reports its real surface dimensions.pen.rs:DIGI_MAX_X/DIGI_MAX_Yare now read per-device viaEVIOCGABSon the marker input fd atPenDevice::open()time, with the Paper Pro's known values kept only as a fallback if the ioctl ever fails.display.rs: added a comment noting theqtfb(windowed AppLoad) path is Ferrari-only (its wire format is documented as Paper-Pro-native) and isn't exercised by the shipped app anyway ("qtfb": falsein the manifest).Also included: reply pagination
Testing long replies on the Move's shorter 1696px page surfaced a pre-existing bug unrelated to device support: replies started a third of the way down the page (centered on the first streamed chunk's height, not the full reply's) and anything past the page bottom was silently dropped ("reply reached the page bottom; trailing text dropped") — still recorded in memory, but never shown, with no way to scroll back to it.
Fixed with proper pagination:
plan_replyonly lays out as many lines as fit before the page bottom and hands back the rest as leftover text.PageFull) rather than auto-advancing — fading and writing the rest before it's been read would be pointless. Touching the pen to the page (the same gesture that already early-dismissesLingering) dissolves it and continues writing from the top (TurningPage), while still absorbing further streamed text in the background so it's ready the moment the page turns.Review feedback addressed
Codex flagged that
screen_w()/screen_h()panic untilfb::init_screen()runs (only called fromrun()), which broke 4 existing tests that reach screen geometry without going throughrun(). Fixed by addingfb::test_init_screen()and calling it at the top of each affected test.cargo testnow passes: 26 passed, 0 failed.Device info (Paper Pro Move / "chiappa")
chiappa, SoC: i.MX93, hostnameimx93-chiappaABS_Xmax 6760,ABS_Ymax 11960remarkable-production-image-5.7.119-chiappa-public-aarch64-toolchain.sh(v3.27.0.97)Testing
Built with the official chiappa SDK against
libqsgepaper.sopulled directly from the device, deployed, and ran a live takeover session on real hardware. Confirmed via device logs:Also confirmed end-to-end with real oracle round-trips (handwritten input -> OpenRouter -> handwritten reply) in normal use via AppLoad, including a long reply that exercised the new pagination (page filled, parked, touch-turned, continued writing).
Existing Paper Pro behavior is unchanged --
screen_w()/screen_h()and the digitizer read resolve to the same 1620x2160 / 11180x15340 values as before, just discovered at runtime instead of compiled in.