file manager
git clone https://git.lucas.co/cce-files.git
fix: carve the dropdown's ring at the lip's depth, not the ring's
`dropdown_relief` hand-rolled the pair `PaintCtx::inset_plate` expands to —
`recess` over a rect expanded by depth/2, then `boss` — instead of calling
it. That is the same treatment `Dropdown::paint_background` applies, so the
flat mirror was structurally right, but one number was not.
`relief_recessed` derives its depth from the height it is HANDED, and what
it was handed was the ALREADY-expanded height: min(9.3, 28.8*0.2) = 5.76,
against the lip's min(9.3, 24*0.2) = 4.8. A 5.76 wall with only a 2.4
expansion over-runs the lip by ~1px instead of meeting it, which is exactly
what inset_plate's contract rules out — "the ring is expanded by depth/2, so
the descending wall meets the rising lip in a tight V-groove with no flat
floor between them". The over-run dug that flat floor.
Routing through `relief_inset` -> `WidgetFx::Inset` -> `pc.inset_plate`
reaches the widget's own call, so the two cannot drift again. That path was
already wired end to end and had zero callers.
Pixel-diffed against the previous binary, same directory and window size
(the render is deterministic across restarts — three separate launches of
the old binary gave byte-identical captures, which is what makes the diff
attributable). The diff bounding box is (750,13)-(1011,83): the dropdown and
nothing else in the 2064x1008 window. The lit lip is byte-identical, since
its 4.8 was already correct; the ring's outer edge pulls in ~1px and the
false floor at the groove bottom lifts ~5/255. Live-verified after: the menu
opens, selecting Space switches the page, and the ring tracks the control to
the different coordinates that page lays it out at.
src/pages/mod.rs | 24 +++++++++++++++---------
1 file changed, 15 insertions(+), 9 deletions(-)
diff --git a/src/pages/mod.rs b/src/pages/mod.rs
index 30337fd..098bab7 100644
--- a/src/pages/mod.rs
+++ b/src/pages/mod.rs
@@ -67,6 +67,15 @@ pub fn breadcrumb_relief(
/// 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.
///
+/// It reaches the SAME `inset_plate` call the widget makes, via
+/// [`PageContent::relief_inset`] → `WidgetFx::Inset`. It used to hand-roll the
+/// pair `inset_plate` expands to (`relief_recessed` over an expanded rect, then
+/// `relief_raised`) — which got the ring's depth wrong, because
+/// `relief_recessed` derives depth from the height it is HANDED, and that was
+/// the already-expanded one: a 5.76px wall against a 4.8px lip, so the
+/// descending wall over-ran the lip instead of meeting it in the tight V-groove
+/// with no flat floor that `inset_plate` documents.
+///
/// **Carve it into `window_pc`, AFTER the page's `view()` has run.** Two
/// constraints pin it there, and they pull in opposite directions:
///
@@ -82,16 +91,13 @@ pub fn breadcrumb_relief(
/// 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_inset(
+ rect.x,
+ rect.y,
+ rect.width,
+ rect.height,
+ cce_ui::layout::dropdown_corner_radius(),
);
- pc.relief_raised(rect.x, rect.y, rect.width, rect.height, r);
}
pub const RELIEF_RECESSED: u8 = 0;