X4 Pro: measured viewable insets, safeArea plumbed to DeviceContext - #59
X4 Pro: measured viewable insets, safeArea plumbed to DeviceContext#59ma-r-s wants to merge 4 commits into
Conversation
Measured 2026-08-26 on the physical unit with CrossPlay's BEZEL ruler app:
the glass hides 10 rows at the top, 1 column each side, 0 at the bottom.
Replaces {9, 7, 3, 7}: the 9/3s were the X4's eyeballed values carried over
'pending measurement', and the 7 was a scrollbar-aesthetics constant, not a
measurement. Community data (crosspoint-reader #618) puts per-unit top
overlap at 5-11 rows, so units that still clip should be re-measured, not
padded.
The GfxRenderer adapter now reports the bezel-covered edge pixels (BoardConfig viewableInsets, rotated into the current orientation) through DeviceContext.safeArea, so Screen's content rect -- seeded from safeRect() -- keeps every fui-laid-out screen clear of the glass. Adds Screen::setContentMarginAbsolute() for hosts whose chrome is drawn at absolute renderer coordinates and whose margins already fold the safe area in (they derive from an insets-aware rect): insetting those from safeRect() would apply the safe area twice.
Themed header at an explicit rect, sharing the anchor overload's theme substitution: for chrome that positions the band itself, e.g. a band whose visible top tracks the device safe area while the layout below keeps its own geometry. Does not consume body space.
The bezel-overlap work: the BEZEL ruler app, measured X4 Pro viewable insets (T10 R1 B0 L1, replacing inherited guesses), safe-area enforcement for content that reaches the glass (xkcd, readers, system screens), and the game-chrome visible-band design (band bottom fixed, hidden rows cut off the top, titles recentred in the visible part). Bumps freeink-sdk to 2b717e95 on the ma-r-s fork (.gitmodules repointed; upstream PR Free-Ink/freeink-sdk#59 carries the commits to Free-Ink).
|
Just a note: x4 pro screen placement varies. On mine, a thin progress bar is invisible unless the device is tilted, and for another user it's fully visible with extra space on the bottom too. |
|
@ma-r-s can you check this against latest code in crosspoint for viewable insets and solve conflicts? |
Resolves the two conflicts Justin flagged on Free-Ink#59. BoardConfig.h: keep the measured X4 Pro viewable insets {10,1,0,1} AND upstream's new batteryChargeStatusActiveHigh field, which was appended to the same profile after this branch forked. FreeInkApp.h: upstream landed setContentMarginFromScreen, which overlaps with this branch's setContentMarginAbsolute but is not the same operation. Upstream takes max(margin, safeArea) per side; the absolute variant insets the full frame exactly. A caller passing a zero margin (ToyboxScreen's absoluteChrome) wants the whole frame and must not be inset by the safe area again, so both are kept and the comment now says how they differ. No firmware caller changes.
|
Merged latest main in, both conflicts resolved. The insets conflict was just the new batteryChargeStatusActiveHigh field landing after I forked. Kept the measured values, added the field. The margins one actually overlaps. setContentMarginFromScreen takes max(margin, safeArea) per side, setContentMarginAbsolute insets the full frame exactly, so passing zero gives you the whole frame instead of the safe area. CrossPlay uses that in about twenty places so I kept both. Say if you want mine gone. |
… X4 Pro units) The submodule was pinned to this fork's x4pro-measured-insets branch, 69 commits behind Free-Ink/freeink-sdk main. Four users report a vertically mirrored display and an unresponsive device after flashing (#6, plus two on the launch thread); the maintainer's diagnosis is that the pin is stale. It does not reproduce here, and the X4 Pro selects one of SSD1677, UC8179 or UC8279 at boot, so this cannot be witnessed on the desk unit. Missing upstream work now included: an X4 Pro display driver update, e-ink init and ghosting improvements, and the touch/RTL mirroring fixes. Conflicts resolved in the submodule (0a631e2), both by keeping work rather than dropping it: - BoardConfig.h: the measured X4 Pro insets {10,1,0,1} plus upstream's new batteryChargeStatusActiveHigh field, appended to the same profile after the branch forked. - FreeInkApp.h: upstream's setContentMarginFromScreen takes max(margin, safeArea) per side; this fork's setContentMarginAbsolute insets the full frame exactly. A zero margin means "whole frame, do not inset again", which ToyboxScreen::absoluteChrome and ~20 call sites rely on, so both are kept. No firmware caller changed. check.sh green: host suites, gcc cross-compile, x4pro and sticky builds. Free-Ink/freeink-sdk#59 is MERGEABLE/CLEAN again. Docs: none affected. Triage: closes nothing; #6 stays open until a reporter confirms on their hardware, since it cannot be verified here.

Three related changes from running CrossPlay on a physical Xteink X4 Pro:
Measured viewable insets for the X4 Pro profile. The bezel overlap was inherited from the X4 ('pending measurement' in the comment): top/bottom were eyeballed values and the 7px side inset was a scrollbar aesthetic, not a measurement. Measured on hardware with an on-screen 1px ruler: the glass hides 10 rows at the top, 1 column per side, 0 at the bottom (the panel sits shifted toward its bottom flex cable). Per-unit variance is real (crosspoint-reader#618 measured 5-11 hidden top rows across eleven X4 units), so units that still clip should be re-measured rather than padded; the comment now says so.
GfxRendererTarget::deviceContext() fills DeviceContext.safeArea from GfxRenderer::getOrientedViewableTRBL(), so Screen's content rect (seeded from safeRect()) keeps fui-laid-out screens clear of the covered pixels. Contexts built without the adapter are unchanged (safeArea stays zero).
Screen::header(props, rect) overload plus Screen::setContentMarginAbsolute(): the first lets chrome position the band itself (e.g. a band whose visible top tracks the safe area while the layout below keeps its own geometry) while sharing the anchor overload's theme substitution; the second is for hosts whose margins are already absolute-frame and insets-aware, where insetting from safeRect() would apply the safe area twice.
All three are shipping in CrossPlay (built for the X4 Pro) and were verified on the device; the firmware side that consumes them is in ma-r-s/crossplay.