git.lucas.co / cce-browser
web browser (Servo)
git clone https://git.lucas.co/cce-browser.git

commit6ac7ef25fc7c821b857dba7814c7215c4e9a1cb1
parente9176ea2cb
authorLucas Galante <[email protected]>
date2026-09-05 20:20
fix: the corner dot sits in the window's corner, not the bar's

The circle menu is the window's corner control, so it goes where the
terminal puts its own: `plate_dock::corner_center` on the window rect —
top-right at the DE inset — regardless of which edge the bar is
anchored to. The bar unfolds from its own top-right corner (the one
nearest the dot), so a bottom-anchored bar grows from its corner rather
than flying down the window.

Co-Authored-By: Claude Fable 5.1 <[email protected]>

 CLAUDE.md   | 11 +++++++----
 src/main.rs | 30 ++++++++++++++++++++----------
 2 files changed, 27 insertions(+), 14 deletions(-)

diff --git a/CLAUDE.md b/CLAUDE.md
index 501abc6..541ff88 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -174,15 +174,18 @@ readings of one geometry** — change a rect helper, not one call site.
 The chrome's persistent element is the **DE's corner control** —
 `cce_ui::widget::plate_dock::draw_corner_dot`, the same 8px plate-border-colored
 dot a designer pane or the terminal window wears at its top-right — sitting at
-the bar plate's top-right inset (`dot_center()`). It is always drawn and always
-live: clicking it unfolds the two-row bar from under it, clicking it again
-folds the bar back. `chrome_open` names the state, `chrome_t` the unfold
+the **window's** top-right inset (`dot_center()`, via `plate_dock::corner_center`
+on the window rect, exactly as the terminal places its own). It is always drawn
+and always live: clicking it unfolds the two-row bar, clicking it again folds
+the bar back. `chrome_open` names the state, `chrome_t` the unfold
 progress (animated in `tick` over `CHROME_ANIM_S`), and `dot_hover` its hover
 emphasis, which is a repaint. **Do not decorate the dot** — no glyph, no
 lines, no ring; it is the DE's control, not a browser icon.
 
 `chrome_plate()` is the one shape draw and hit-test both read — the bar, or
-the lerp from a dot-sized seed disc under the control up to the bar — and
+the lerp from a dot-sized seed disc at the bar's own top-right corner
+(`seed_center()`, the corner nearest the control; a bottom-anchored bar grows
+from its own corner rather than flying down the window) up to the bar — and
 `chrome_hit()` is the chrome's pointer gate (the dot always, the plate while
 any of it shows). The bar's contents are laid out at their *final* rects and
 clipped to the growing plate, so the unfold is a reveal, not a re-layout. The
diff --git a/src/main.rs b/src/main.rs
index 13d2652..5ca16bd 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -59,9 +59,9 @@ const BAR_RADIUS: f32 = 10.0;
 const BAR_PAD: f32 = 7.0;
 /// Seconds for the bar to unfold from the corner control (and back).
 const CHROME_ANIM_S: f32 = 0.18;
-/// Width reserved at the right end of the tab row for the corner control,
-/// which rides the bar's top-right at the DE's inset and would otherwise
-/// sit on the "+" button.
+/// Width reserved at the right end of the tab row for the corner control:
+/// at the window's top-right it overlaps a top-anchored bar's "+" button
+/// otherwise. Reserved for a bottom bar too, so the two layouts agree.
 const DOT_COL: f32 = 2.0 * plate_dock::CORNER_INSET;
 const TAB_H: f32 = 24.0;
 const TAB_GAP: f32 = 4.0;
@@ -462,11 +462,22 @@ impl BrowserApp {
         bar_rect(self.win, self.settings.bar_position)
     }
 
-    /// Centre of the corner control: the bar plate's top-right at the DE's
-    /// inset, exactly where a designer pane or the terminal wears its own.
-    /// It is there whether the bar is open or not — the bar unfolds from
-    /// under it, and it is what folds the bar back.
+    /// Centre of the corner control: the WINDOW's top-right at the DE's
+    /// inset — the terminal's placement, the window being the plate the
+    /// control belongs to. It is there whether the bar is open or not, and
+    /// it is what folds the bar back.
     fn dot_center(&self) -> (f32, f32) {
+        plate_dock::corner_center((0.0, 0.0, self.win.0, self.win.1), false).unwrap_or((
+            self.win.0 - plate_dock::CORNER_INSET,
+            plate_dock::CORNER_INSET,
+        ))
+    }
+
+    /// Where the bar grows from: its own top-right corner, the one nearest
+    /// the control. For a top-anchored bar that is a few px from the dot,
+    /// so the unfold still reads as coming from it; a bottom-anchored bar
+    /// grows from its own corner rather than flying down the window.
+    fn seed_center(&self) -> (f32, f32) {
         let bar = self.bar();
         (bar.x + bar.width - plate_dock::CORNER_INSET, bar.y + plate_dock::CORNER_INSET)
     }
@@ -483,11 +494,10 @@ impl BrowserApp {
 
     /// The bar plate as currently drawn — the full bar, or the shape it is
     /// unfolding through — and its corner radius. It grows out of a
-    /// dot-sized disc under the corner control, so the unfold reads as the
-    /// bar coming from the control that was clicked.
+    /// dot-sized disc at its corner nearest the control.
     fn chrome_plate(&self) -> (Rect, f32) {
         let e = self.chrome_ease();
-        let (cx, cy) = self.dot_center();
+        let (cx, cy) = self.seed_center();
         let seed = plate_dock::CORNER_INSET;
         let bar = self.bar();
         let lerp = |a: f32, b: f32| a + (b - a) * e;