Skip to content

X4 Pro: measured viewable insets, safeArea plumbed to DeviceContext - #59

Open
ma-r-s wants to merge 4 commits into
Free-Ink:mainfrom
ma-r-s:x4pro-measured-insets
Open

X4 Pro: measured viewable insets, safeArea plumbed to DeviceContext#59
ma-r-s wants to merge 4 commits into
Free-Ink:mainfrom
ma-r-s:x4pro-measured-insets

Conversation

@ma-r-s

@ma-r-s ma-r-s commented Aug 27, 2026

Copy link
Copy Markdown

Three related changes from running CrossPlay on a physical Xteink X4 Pro:

  1. 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.

  2. 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).

  3. 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.

ma-r-s added 3 commits August 26, 2026 11:56
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.
ma-r-s added a commit to ma-r-s/crossplay that referenced this pull request Aug 27, 2026
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).
@prokrypt

prokrypt commented Aug 27, 2026

Copy link
Copy Markdown

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.

@prokrypt

Copy link
Copy Markdown
sticker_1787851608680 2 rectangles--one is 5 pixels from the edges, second is 10 pixels from the edges

@itsthisjustin

itsthisjustin commented Aug 29, 2026

Copy link
Copy Markdown
Contributor

@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.
@ma-r-s

ma-r-s commented Aug 31, 2026

Copy link
Copy Markdown
Author

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.

ma-r-s added a commit to ma-r-s/crossplay that referenced this pull request Aug 31, 2026
… 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.
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.

3 participants