git.lucas.co / cce-ui
GPU-accelerated UI toolkit (Vulkan)
git clone https://git.lucas.co/cce-ui.git

commiteea3c3db96e0034dd13aab6a325571a788280522
parent4de2aff0bb
authorLucas Galante <[email protected]>
date2026-06-18 02:15
Fix remaining missing as_ptr/as_ptr_mut widget overrides and apply strict anchor rect bounds clamping

 src/backend/window_runner.rs     | 20 ++++++++++++++------
 src/widget/display/graph.rs      |  3 +++
 src/widget/display/node.rs       |  6 ++++++
 src/widget/display/separator.rs  |  6 ++++++
 src/widget/display/sidebar.rs    |  6 ++++++
 src/widget/display/splitter.rs   |  6 ++++++
 src/widget/display/status_bar.rs |  6 ++++++
 src/widget/display/svg.rs        |  6 ++++++
 src/widget/input/canvas.rs       |  6 ++++++
 9 files changed, 59 insertions(+), 6 deletions(-)

diff --git a/src/backend/window_runner.rs b/src/backend/window_runner.rs
index 38da5ec..6299ec6 100644
--- a/src/backend/window_runner.rs
+++ b/src/backend/window_runner.rs
@@ -2038,15 +2038,23 @@ pub fn run<A: Application>() {
                     let (rx, ry, rw, rh) = popover_widget.rect();
                     let scroll_y = crate::widget::hover_animation::get_scroll_offset();
                     let screen_ry = ry - scroll_y;
-                    let ax = (rx as i32).clamp(0, (engine_state.logical_width as i32 - 1).max(0));
-                    let ay = (screen_ry as i32).clamp(0, (engine_state.logical_height as i32 - 1).max(0));
-                    positioner.set_anchor_rect(ax, ay, rw as i32, rh as i32);
+                    let lw = engine_state.logical_width as i32;
+                    let lh = engine_state.logical_height as i32;
+                    let ax = (rx as i32).clamp(0, (lw - 1).max(0));
+                    let ay = (screen_ry as i32).clamp(0, (lh - 1).max(0));
+                    let aw = (rw as i32).clamp(1, (lw - ax).max(1));
+                    let ah = (rh as i32).clamp(1, (lh - ay).max(1));
+                    positioner.set_anchor_rect(ax, ay, aw, ah);
                     positioner.set_anchor(Anchor::BottomLeft);
                     positioner.set_gravity(Gravity::BottomRight);
                 } else {
-                    let ax = (px as i32).clamp(0, (engine_state.logical_width as i32 - 1).max(0));
-                    let ay = (py as i32).clamp(0, (engine_state.logical_height as i32 - 1).max(0));
-                    positioner.set_anchor_rect(ax, ay, 1, 1);
+                    let lw = engine_state.logical_width as i32;
+                    let lh = engine_state.logical_height as i32;
+                    let ax = (px as i32).clamp(0, (lw - 1).max(0));
+                    let ay = (py as i32).clamp(0, (lh - 1).max(0));
+                    let aw = 1.clamp(1, (lw - ax).max(1));
+                    let ah = 1.clamp(1, (lh - ay).max(1));
+                    positioner.set_anchor_rect(ax, ay, aw, ah);
                     positioner.set_anchor(Anchor::TopLeft);
                     positioner.set_gravity(Gravity::BottomRight);
                 }
diff --git a/src/widget/display/graph.rs b/src/widget/display/graph.rs
index ad58b85..d254a1e 100644
--- a/src/widget/display/graph.rs
+++ b/src/widget/display/graph.rs
@@ -245,6 +245,9 @@ impl Element for Graph {
     fn as_ptr(&self) -> *mut (dyn Element + 'static) {
         self as *const Self as *mut Self as *mut (dyn Element + 'static)
     }
+    fn as_ptr_mut(&mut self) -> *mut (dyn Element + 'static) {
+        self as *mut Self as *mut (dyn Element + 'static)
+    }
 
     fn rounded_corners(&self) -> (bool, bool, bool, bool) { (false, false, true, true) }
 
diff --git a/src/widget/display/node.rs b/src/widget/display/node.rs
index 6ba2e09..59fcdb9 100644
--- a/src/widget/display/node.rs
+++ b/src/widget/display/node.rs
@@ -59,6 +59,12 @@ impl Element for Node {
         else if self.selected { colors::node_selected_color() }
         else { colors::node_color() }
     }
+    fn as_ptr(&self) -> *mut (dyn Element + 'static) {
+        self as *const Self as *mut Self as *mut (dyn Element + 'static)
+    }
+    fn as_ptr_mut(&mut self) -> *mut (dyn Element + 'static) {
+        self as *mut Self as *mut (dyn Element + 'static)
+    }
     fn set_hovered(&mut self, v: bool) { self.hovered = v; }
     fn hovered(&self) -> bool { self.hovered }
 
diff --git a/src/widget/display/separator.rs b/src/widget/display/separator.rs
index e223f5c..54ba050 100644
--- a/src/widget/display/separator.rs
+++ b/src/widget/display/separator.rs
@@ -19,6 +19,12 @@ impl Element for Separator {
     fn rect(&self) -> (f32, f32, f32, f32) {
         (self.x, self.y, self.w, self.h)
     }
+    fn as_ptr(&self) -> *mut (dyn Element + 'static) {
+        self as *const Self as *mut Self as *mut (dyn Element + 'static)
+    }
+    fn as_ptr_mut(&mut self) -> *mut (dyn Element + 'static) {
+        self as *mut Self as *mut (dyn Element + 'static)
+    }
 
     fn set_rect(&mut self, x: f32, y: f32, w: f32, h: f32) {
         self.x = x;
diff --git a/src/widget/display/sidebar.rs b/src/widget/display/sidebar.rs
index 6877198..8a3651e 100644
--- a/src/widget/display/sidebar.rs
+++ b/src/widget/display/sidebar.rs
@@ -14,6 +14,12 @@ impl Element for Sidebar {
     fn rect(&self) -> (f32, f32, f32, f32) { (self.x, self.y, self.w, self.h) }
     fn set_rect(&mut self, x: f32, y: f32, w: f32, h: f32) { self.x = x; self.y = y; self.w = w; self.h = h; }
     fn color(&self) -> [f32; 4] { colors::sidebar_bg_color() }
+    fn as_ptr(&self) -> *mut (dyn Element + 'static) {
+        self as *const Self as *mut Self as *mut (dyn Element + 'static)
+    }
+    fn as_ptr_mut(&mut self) -> *mut (dyn Element + 'static) {
+        self as *mut Self as *mut (dyn Element + 'static)
+    }
     fn set_hovered(&mut self, v: bool) { self.hovered = v; }
     fn hovered(&self) -> bool { self.hovered }
 }
diff --git a/src/widget/display/splitter.rs b/src/widget/display/splitter.rs
index c773573..22a165b 100644
--- a/src/widget/display/splitter.rs
+++ b/src/widget/display/splitter.rs
@@ -17,6 +17,12 @@ impl Splitter {
 impl Element for Splitter {
     fn rect(&self) -> (f32, f32, f32, f32) { (self.x, self.y, self.w, self.h) }
     fn set_rect(&mut self, x: f32, y: f32, w: f32, h: f32) { self.x = x; self.y = y; self.w = w; self.h = h; }
+    fn as_ptr(&self) -> *mut (dyn Element + 'static) {
+        self as *const Self as *mut Self as *mut (dyn Element + 'static)
+    }
+    fn as_ptr_mut(&mut self) -> *mut (dyn Element + 'static) {
+        self as *mut Self as *mut (dyn Element + 'static)
+    }
     fn color(&self) -> [f32; 4] {
         if self.dragging { colors::SPLITTER_DRAG }
         else if self.hovered { colors::SPLITTER_HOVER }
diff --git a/src/widget/display/status_bar.rs b/src/widget/display/status_bar.rs
index 191b008..4f1ad19 100644
--- a/src/widget/display/status_bar.rs
+++ b/src/widget/display/status_bar.rs
@@ -57,6 +57,12 @@ impl StatusBar {
 impl Element for StatusBar {
     fn rect(&self) -> (f32, f32, f32, f32) { (self.x, self.y, self.w, self.h) }
     fn set_rect(&mut self, x: f32, y: f32, w: f32, h: f32) { self.x = x; self.y = y; self.w = w; self.h = h; }
+    fn as_ptr(&self) -> *mut (dyn Element + 'static) {
+        self as *const Self as *mut Self as *mut (dyn Element + 'static)
+    }
+    fn as_ptr_mut(&mut self) -> *mut (dyn Element + 'static) {
+        self as *mut Self as *mut (dyn Element + 'static)
+    }
     fn color(&self) -> [f32; 4] { self.bg_color.unwrap_or(colors::STATUS_BG) }
     fn set_hovered(&mut self, v: bool) { self.hovered = v; }
     fn hovered(&self) -> bool { self.hovered }
diff --git a/src/widget/display/svg.rs b/src/widget/display/svg.rs
index 7ef46d6..e8c26b6 100644
--- a/src/widget/display/svg.rs
+++ b/src/widget/display/svg.rs
@@ -68,6 +68,12 @@ impl Svg {
 
 impl Element for Svg {
     fn rect(&self) -> (f32, f32, f32, f32) { (self.x, self.y, self.w, self.h) }
+    fn as_ptr(&self) -> *mut (dyn Element + 'static) {
+        self as *const Self as *mut Self as *mut (dyn Element + 'static)
+    }
+    fn as_ptr_mut(&mut self) -> *mut (dyn Element + 'static) {
+        self as *mut Self as *mut (dyn Element + 'static)
+    }
     
     fn set_rect(&mut self, x: f32, y: f32, w: f32, h: f32) {
         let dx = x - self.x;
diff --git a/src/widget/input/canvas.rs b/src/widget/input/canvas.rs
index 1867305..f88b092 100644
--- a/src/widget/input/canvas.rs
+++ b/src/widget/input/canvas.rs
@@ -13,6 +13,12 @@ impl Element for Canvas {
     fn rect(&self) -> (f32, f32, f32, f32) { (self.x, self.y, self.w, self.h) }
     fn set_rect(&mut self, x: f32, y: f32, w: f32, h: f32) { self.x = x; self.y = y; self.w = w; self.h = h; }
     fn color(&self) -> [f32; 4] { [0.0, 0.0, 0.0, 0.0] }
+    fn as_ptr(&self) -> *mut (dyn Element + 'static) {
+        self as *const Self as *mut Self as *mut (dyn Element + 'static)
+    }
+    fn as_ptr_mut(&mut self) -> *mut (dyn Element + 'static) {
+        self as *mut Self as *mut (dyn Element + 'static)
+    }
     fn set_hovered(&mut self, v: bool) { self.hovered = v; }
     fn hovered(&self) -> bool { self.hovered }
     fn hit_test(&self, _px: f32, _py: f32, _ctx: &UiContext) -> bool { false }