GPU-accelerated UI toolkit (Vulkan)
git clone https://git.lucas.co/cce-ui.git
feat(dropdown): app-owned corner_frame — concentric cut without a Backplate ancestor
Dropdown's backplate-concentric corner adjustment walked the tracked-parent
chain for a Backplate; once an app dissolves its root Backplate (Phase 6
per-app migration) the walk finds nothing and the cut silently degrades to a
plain rounded box. set_corner_frame hands the widget the plate frame
(rect, radius, corners) explicitly and takes precedence over the walk.
First consumer: cce-system-settings' page dropdown, flush against the
window's rounded bottom-right corner (Phase 6s).
Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_016MjP3pGQEDLkJbV5WEmYBe
src/widget/input/dropdown.rs | 22 +++++++++++++++++-----
1 file changed, 17 insertions(+), 5 deletions(-)
diff --git a/src/widget/input/dropdown.rs b/src/widget/input/dropdown.rs
index 59ea0e2..fa77401 100644
--- a/src/widget/input/dropdown.rs
+++ b/src/widget/input/dropdown.rs
@@ -60,6 +60,11 @@ pub struct Dropdown {
/// bookkeeping hit-tests through [`Input::hit`], which includes the open popover — matching
/// the legacy `on_cursor_moved` + popover-aware `hit_test` pair).
hovered: bool,
+ /// App-owned concentric frame (Phase 6s): `(rect, radius, corners)` of the rounded plate
+ /// the dropdown sits in. When set, the corner adjustment uses it INSTEAD of walking for a
+ /// `Backplate` ancestor — the hook that keeps the adjustment after an app dissolves its
+ /// root Backplate (the walk finds nothing once the widget is parentless).
+ corner_frame: Option<((f32, f32, f32, f32), f32, (bool, bool, bool, bool))>,
}
impl Dropdown {
@@ -78,9 +83,15 @@ impl Dropdown {
auto_width: false,
label: None,
hovered: false,
+ corner_frame: None,
})
}
+ /// Set (or clear) the app-owned concentric frame — see the `corner_frame` field docs.
+ pub fn set_corner_frame(&mut self, frame: Option<((f32, f32, f32, f32), f32, (bool, bool, bool, bool))>) {
+ self.corner_frame = frame;
+ }
+
pub fn take_change(&mut self) -> bool {
let changed = self.just_changed;
self.just_changed = false;
@@ -234,11 +245,12 @@ impl Dropdown {
let mut outer_radii = [radius; 4];
let mut inner_radii = [inner_radius; 4];
- if let Some(bp) = self.backplate_ancestor() {
- let (px, py, pw, ph) = unsafe { (*bp).rect() };
- let pr = unsafe { (*bp).corner_radius() };
- let (pr1, pr2, pr3, pr4) = unsafe { (*bp).rounded_corners() };
-
+ let frame = self.corner_frame.or_else(|| {
+ self.backplate_ancestor().map(|bp| unsafe {
+ ((*bp).rect(), (*bp).corner_radius(), (*bp).rounded_corners())
+ })
+ });
+ if let Some(((px, py, pw, ph), pr, (pr1, pr2, pr3, pr4))) = frame {
let g_left = x - px;
let g_top = y - py;
let g_right = (px + pw) - (x + w);