Share the GridMsg-to-renderer sync from felis-client via felis-client-core #442
Labels
No labels
priority/P0
priority/P1
priority/P2
release/v0.1.0
status/blocked
status/planned
type/bug
type/design
type/test-gap
type/tracker
No milestone
No project
No assignees
1 participant
Due date
No due date set.
Dependencies
No dependencies set
Reference
natsukium/felis#442
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Motivation
felis-client keeps two things in sync after each
ShadowScreen::apply: the shadow screen, and renderer-side state that the shadow does not carry.ShadowScreentreatsThemeColor,PaletteColorandPaletteResetAllas no-ops (crates/felis-client-core/src/shadow.rs:355-359). felis-client then maps messages to renderer calls itself (crates/felis-client/src/event_handler.rs:405-445):ThemeColor→apply_theme_overridePaletteColor→apply_palette_overridePaletteResetAll→reset_palette_overridesRehydrateBegin→reset_session_colorsModeFlags.reverse_video→set_reverse_videoEvery other renderer consumer has to copy this mapping. The planned felis-reel (headless
.fcast→ video, which depends on the offscreen renderer issue) is the first such consumer. A copy silently goes stale when felis adds a message that affects the renderer but not the shadow. When that happens, a recording that changes colors through OSC 4/10/11 renders in the base theme, and nothing reports an error.Proposal
Move the mapping into felis-client-core as a shared function, for example
fn sync_renderer(msg: &GridMsg, sink: &mut impl RendererSink), whereRendererSinkis a small trait covering the override setters above. felis-client and felis-reel would both call it, so a new message would need handling in only one place.Open question
felis-client-core has no renderer dependency, so the trait would decouple it from felis-render-wgpu. An alternative is to implement the trait in felis-render-wgpu behind a feature.
This does not block the felis-reel PoC: the PoC copies the five arms from
felis-client/src/event_handler.rsand this lands afterwards.The drift has already happened
felis-web-component (
src/lib.rs, pinned to an older felis) carries its own copy that handles onlyThemeColor, in the older{channel, rgb}shape.PaletteColor,PaletteResetAll,RehydrateBeginand reverse video are dropped there without an error. felis-reel would be the third copy.Design: return data instead of a trait
A
RendererSinktrait in felis-client-core cannot be implemented forfelis_render_wgpu::Rendererfrom felis-client (orphan rule). The workarounds are a newtype in every consumer, or a new felis-render-wgpu → felis-client-core dependency edge. A pure function needs neither and also works from wasm:What it guarantees, and what it does not
If
renderer_effectmatchesGridMsgwithout a_arm and consumers matchRendererEffectexhaustively, a new message variant or a new effect breaks the build instead of rendering silently wrong. It does not catch a new renderer-affecting field inside an arm matched with..(for exampleModeFlags). The PR therefore adds:renderer_effectrather than its own mapping.