Skip to content

Commit ad421a2

Browse files
committed
fix(layout): make retained faces frame-wide
1 parent b80119c commit ad421a2

5 files changed

Lines changed: 377 additions & 155 deletions

File tree

‎neomacs-layout-engine/src/display_buffer_source_render_plan.rs‎

Lines changed: 6 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@ use neomacs_display_protocol::frame_glyphs::{
3838
CursorStyle, DisplaySlotId, GlyphRowRole, PhysCursor,
3939
};
4040
use neomacs_display_protocol::glyph_matrix::{FaceFillItem, GlyphArea};
41-
use neomacs_display_protocol::types::FaceId;
4241
use neomacs_display_protocol::types::{Color, DisplayWindowId, Rect};
4342
use neovm_core::buffer::BufferId;
4443
use neovm_core::window::{FrameId, WindowId};
@@ -563,26 +562,10 @@ impl BufferSourceOutputSetup {
563562
.collect();
564563

565564
let (mut output, evaluator) = output.into_parts();
566-
// Re-register the reused rows' faces under their prior-frame face_ids:
567-
// this frame's faces table was rebuilt from scratch and lacks them, so
568-
// without this the reused glyphs resolve to the wrong/missing face at
569-
// render. Reserve their id range so the chrome re-walk (which shares
570-
// `face_ids`, reset to SENTINEL) allocates NON-colliding ids. Must run
571-
// before `face_ids` is borrowed by the chrome render services below.
572-
// (Face-id collision audit fix.)
573-
let mut max_reused_face_id: Option<FaceId> = None;
574-
for (id, face) in &replay.faces {
575-
output.builder().install_output_frame_state(
576-
crate::display_output_install_request::OutputFrameStateInstallRequest::face(
577-
*id,
578-
face.clone(),
579-
),
580-
);
581-
max_reused_face_id = Some(max_reused_face_id.map_or(*id, |m| m.max(*id)));
582-
}
583-
if let Some(max) = max_reused_face_id {
584-
face_ids.reserve_after(max);
585-
}
565+
// Phase A admitted every replaying window's retained faces and
566+
// reserved their complete frame-wide ID range before any fresh face
567+
// allocation. This window can now install rows without mutating the
568+
// namespace behind glyphs emitted by an earlier sibling.
586569
let mut render_services =
587570
ChromeRowRenderServices::new(font_metrics, face_resolver, &mut face_ids);
588571

@@ -718,15 +701,8 @@ impl BufferSourceOutputSetup {
718701
// (shifted) above them, splice the snapshots, re-decorate the cursor, and
719702
// re-walk chrome. Byte-identical to a full rebuild of the scrolled window.
720703
if let Some(scroll) = scroll {
721-
// Reserve the reused rows' prior-frame face_id range BEFORE the partial
722-
// walk + chrome allocate from `face_ids` (reset to SENTINEL), so their
723-
// fresh ids do not collide with the reused glyphs' ids. The faces
724-
// themselves are re-registered after into_parts below. (Face-id
725-
// collision audit fix; the reused rows carry prior-frame face_ids that
726-
// this frame's freshly-built faces table otherwise lacks.)
727-
if let Some(max) = scroll.faces.keys().copied().max() {
728-
face_ids.reserve_after(max);
729-
}
704+
// Phase A already admitted the frame-wide retained face namespace
705+
// before this partial walk can mint IDs.
730706
let (mut output_emitter, _post_loop) = walk_setup.begin_render_body_and_tail(
731707
self.begin_request,
732708
&mut output,
@@ -747,17 +723,6 @@ impl BufferSourceOutputSetup {
747723
buf_access,
748724
);
749725
let (mut output, evaluator) = output.into_parts();
750-
// Re-register the reused rows' faces under their prior-frame face_ids
751-
// (the id range was reserved above, so these do not collide with the
752-
// walk/chrome allocations). (Face-id collision audit fix.)
753-
for (id, face) in &scroll.faces {
754-
output.builder().install_output_frame_state(
755-
crate::display_output_install_request::OutputFrameStateInstallRequest::face(
756-
*id,
757-
face.clone(),
758-
),
759-
);
760-
}
761726
let mut render_services =
762727
ChromeRowRenderServices::new(font_metrics, face_resolver, &mut face_ids);
763728

‎neomacs-layout-engine/src/display_frame_output.rs‎

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,24 @@ impl FrameOutputOwner {
138138
);
139139
}
140140

141+
pub(crate) fn install_retained_faces(
142+
&mut self,
143+
faces: impl IntoIterator<
144+
Item = (
145+
neomacs_display_protocol::types::FaceId,
146+
neomacs_display_protocol::face::Face,
147+
),
148+
>,
149+
) {
150+
for (face_id, face) in faces {
151+
self.builder.install_output_frame_state(
152+
crate::display_output_install_request::OutputFrameStateInstallRequest::face(
153+
face_id, face,
154+
),
155+
);
156+
}
157+
}
158+
141159
pub(crate) fn render_frame_tab_bar_row(
142160
&mut self,
143161
request: FrameTabBarDisplayRowRequest<'_>,

0 commit comments

Comments
 (0)