file manager
git clone https://git.lucas.co/cce-files.git
fix: carve the dropdown's ring from this frame's rect, not last frame's
`rebuild_layout` carved the view dropdown's flush inset plate off
`view_dropdown.rect()` — but the PAGES are what lay the dropdown out, and
they run further down the same method. So the carve read the rect the
previous frame assigned: the ring trailed the control by a frame through
a resize, and on the first frame it carved a 0x0 rect (confirmed by
instrumenting both reads: stale=(0,0,0,0) against fresh=(380,12,120,24)).
Moved the carve below the page dispatch, where the rect is this frame's,
and gave it a name — `pages::dropdown_relief`, beside the
`breadcrumb_relief` it visually pairs with.
It stays in `window_pc` rather than moving into the page's own
`PageContent` next to the layout call that would make the staleness
structurally impossible. That was the first attempt, and it changed how
the control looks: these are overlay carves shaded against what is
already beneath them, so emitting page-side put the ring after the
dropdown's background quad instead of before it and visibly thinned the
lit top rim. `CCE_PLATE_DEBUG=1` reports both orders as 0 grouped / all
overlay fallback, so it is compositing order, not plate grouping.
Verified live against the pre-change binary still running in the session:
the dropdown region is pixel-identical (diff bbox None), while the first
frame's carve moved from a 0x0 rect to (380,12 120x24).
src/main.rs | 23 +++++++++++++++--------
src/pages/mod.rs | 36 ++++++++++++++++++++++++++++++++++++
2 files changed, 51 insertions(+), 8 deletions(-)
diff --git a/src/main.rs b/src/main.rs
index 992964e..95f9003 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -535,14 +535,9 @@ impl FilesystemApp {
window_pc.rects.extend(rounded);
window_pc.absorb(plain_pc);
- // The view dropdown's flush inset plate (control_relief) lives
- // in its modern paint(); the flat view loses it — restore it as
- // the groove ring + edges-only lip pair.
- let (dx, dy, dw, dh) = (*self_ptr).view_dropdown.rect();
- let dr = cce_ui::layout::dropdown_corner_radius();
- let g = cce_ui::layout::bevel_width().min(dh * 0.2) * 0.5;
- window_pc.relief_recessed(dx - g, dy - g, dw + 2.0 * g, dh + 2.0 * g, dr + g);
- window_pc.relief_raised(dx, dy, dw, dh, dr);
+ // The view dropdown's flush inset plate is carved below, once
+ // the pages have laid the dropdown out — carving it here would
+ // read the previous frame's rect (`pages::dropdown_relief`).
}
}
@@ -569,6 +564,18 @@ impl FilesystemApp {
}
}
+ // The view dropdown's flush inset plate (control_relief) lives in its
+ // modern paint(); the flat view loses it, so carve it here — from the
+ // rect the page above just laid the dropdown out at, NOT the one it
+ // held when this method started.
+ {
+ let (dx, dy, dw, dh) = self.view_dropdown.rect();
+ pages::dropdown_relief(
+ &mut window_pc,
+ cce_ui::scene::layout::Rect { x: dx, y: dy, width: dw, height: dh },
+ );
+ }
+
// Draw bottom selection bar if select_mode is enabled. It lives below the
// content region, so it goes into window_pc: page content (pc) is clipped
// to the viewport and would swallow the bar entirely.
diff --git a/src/pages/mod.rs b/src/pages/mod.rs
index 9ceec00..30337fd 100644
--- a/src/pages/mod.rs
+++ b/src/pages/mod.rs
@@ -58,6 +58,42 @@ pub fn breadcrumb_relief(
}
}
+/// Mirror the view dropdown's flush inset plate into a flat-path
+/// [`PageContent`]: the groove ring sunk around the control, and the control's
+/// own edge rolling back up out of it — face level with the window plate, so
+/// the seam is the only thing saying it is a separate part.
+///
+/// `Dropdown::paint` emits this as one `ctx.inset_plate`; `render_widget` keeps
+/// only quads and text, so the carve is app-side — the same story as
+/// [`breadcrumb_relief`], which is the well-and-plate this pairs with.
+///
+/// **Carve it into `window_pc`, AFTER the page's `view()` has run.** Two
+/// constraints pin it there, and they pull in opposite directions:
+///
+/// - *After the pages* — because the pages are what lay the dropdown out. Read
+/// `view_dropdown.rect()` before they run and you get the rect they assigned
+/// on the PREVIOUS frame, so the ring trails the control by a frame through a
+/// resize (and on the very first frame it carves a 0×0 rect).
+/// - *Into `window_pc`, not the page's own `pc`* — because these are overlay
+/// carves, shaded against whatever is already beneath them. Emitting them
+/// page-side puts them after the dropdown's own background quad instead of
+/// before it, which visibly thins the lit top rim. Same rect, different
+/// material. (Verified by pixel-diffing the two orders; `CCE_PLATE_DEBUG=1`
+/// shows both as overlay fallback, so this is compositing order, not
+/// plate grouping.)
+pub fn dropdown_relief(pc: &mut PageContent, rect: cce_ui::scene::layout::Rect) {
+ let r = cce_ui::layout::dropdown_corner_radius();
+ let g = cce_ui::layout::bevel_width().min(rect.height * 0.2) * 0.5;
+ pc.relief_recessed(
+ rect.x - g,
+ rect.y - g,
+ rect.width + 2.0 * g,
+ rect.height + 2.0 * g,
+ r + g,
+ );
+ pc.relief_raised(rect.x, rect.y, rect.width, rect.height, r);
+}
+
pub const RELIEF_RECESSED: u8 = 0;
pub const RELIEF_RAISED: u8 = 1;
pub const RELIEF_INSET: u8 = 2;