Encodes gui_surface_layout (0xA4): the authoritative per-frame surface
placement carrier (#2219 child E / #2268).
This is the single emitter of gui_surface_layout. It takes wire-shaped
placement maps (already numbered by MingaEditor.Layout.SurfaceRegistry, the
one source of surface rects and z-order that also feeds BEAM mouse
hit-testing) and lays them out as a sectioned command using the
schema-generated pure encoder
Minga.Protocol.Encode.encode_gui_surface_layout_placements/1. Because both
the placement bytes and the BEAM hit-test read the same registry placements,
the emitted rect for every surface equals its hit-test rect by construction
(#2268 AC-1).
Identity unification (#2268)
The schema carries surface_id as a raw u16 and hit_kind as a raw u8
with no enum (a new schema vocabulary was explicitly avoided). The numeric
identity is authoritative in SurfaceRegistry, which projects each placement
to its wire shape (SurfaceRegistry.wire_placements/1). This encoder consumes
those plain maps and never depends on MingaEditor.*: one writer (the
registry owns the numbering), one reader (this encoder lays out bytes).
Framing
Sectioned framing (opcode + section_count + section{id, len16, body}) reuses
the gui_window_content/picker counted-array carrier so the generator emits a
placement decoder both frontends already know how to size (the reviewer-
adjudicated carrier choice from child A). There is a single section,
placements (id 0x01), holding a counted array of surface_placement.
Summary
Types
A placement already projected to its wire shape (see SurfaceRegistry.wire_placement/0).
Functions
Encodes the frame's wire-shaped surface placements into a gui_surface_layout
command.
Types
@type wire_placement() :: %{ surface_id: non_neg_integer(), rect: %{ row: non_neg_integer(), col: non_neg_integer(), width: non_neg_integer(), height: non_neg_integer() }, z: non_neg_integer(), hit_kind: non_neg_integer() }
A placement already projected to its wire shape (see SurfaceRegistry.wire_placement/0).
Functions
@spec encode_command([wire_placement()]) :: binary()
Encodes the frame's wire-shaped surface placements into a gui_surface_layout
command.
Always emits (one section, possibly with an empty placement array). The command is part of the frame transaction, so it ships every frame between begin_frame and commit_frame; there is no skip-if-unchanged cache because the placement list IS the per-frame layout authority. Cell fields are clamped to u16/u8 so a degenerate rect can never produce a malformed packet (mirrors the window encoder's clamp policy).