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

commit6a84de8addced2a3389832defd234f01260de327
parentedd0d2b510
authorLucas Galante <[email protected]>
date2026-06-22 12:44
feat: implement CPU bounds clipping for Window descendants

 src/widget/container/paginator.rs | 19 +++++++++++++-
 src/widget/container/window.rs    | 55 ++++++++++++++++++++++++++++++++++-----
 2 files changed, 67 insertions(+), 7 deletions(-)

diff --git a/src/widget/container/paginator.rs b/src/widget/container/paginator.rs
index 23c1435..f377771 100644
--- a/src/widget/container/paginator.rs
+++ b/src/widget/container/paginator.rs
@@ -21,9 +21,26 @@ pub struct Paginator {
 }
 
 impl Paginator {
-    pub fn new(sidebar_w: f32, pages: Vec<String>) -> Self {
+    pub fn new(pages: Vec<String>) -> Self {
         let num_pages = pages.len();
 
+        let temp_paginator = Self {
+            x: 0.0,
+            y: 0.0,
+            w: 0.0,
+            h: 0.0,
+            sidebar_menu: ButtonStrip::new(0.0, 0.0, 0.0, 0.0),
+            plates: Vec::new(),
+            selected_page: 0,
+            page_hidden: false,
+            sidebar_w: 0.0,
+            pages: pages.clone(),
+            parent: None,
+            on_page_changed_cb: None,
+            just_clicked: None,
+        };
+        let sidebar_w = temp_paginator.sidebar_w();
+
         let mut sidebar_menu = ButtonStrip::new(0.0, 0.0, sidebar_w, 0.0)
             .with_vertical(true)
             .with_buttons(pages.clone());
diff --git a/src/widget/container/window.rs b/src/widget/container/window.rs
index 1183f3d..0d66fc7 100644
--- a/src/widget/container/window.rs
+++ b/src/widget/container/window.rs
@@ -154,18 +154,29 @@ impl Element for Window {
         }
         let mut quads = Vec::new();
         let bg_color = self.color();
+        let (wx, wy, ww, wh) = self.rect();
         if bg_color[3] != 0.0 {
-            let (wx, wy, ww, wh) = self.rect();
             quads.push((wx, wy, ww, wh, bg_color));
         }
         for &child_ptr in &self.children {
             let widget = unsafe { &*child_ptr };
+            let mut child_quads = Vec::new();
             let cc = widget.color();
             if cc[3] > 0.0 {
-                let (wx, wy, ww, wh) = widget.rect();
-                quads.push((wx, wy, ww, wh, cc));
+                let (cx, cy, cw, ch) = widget.rect();
+                child_quads.push((cx, cy, cw, ch, cc));
+            }
+            child_quads.extend(widget.all_quads(ctx));
+
+            for (qx, qy, qw, qh, qc) in child_quads {
+                let x0 = qx.max(wx);
+                let y0 = qy.max(wy);
+                let x1 = (qx + qw).min(wx + ww);
+                let y1 = (qy + qh).min(wy + wh);
+                if x1 > x0 && y1 > y0 {
+                    quads.push((x0, y0, x1 - x0, y1 - y0, qc));
+                }
             }
-            quads.extend(widget.all_quads(ctx));
         }
         quads
     }
@@ -187,9 +198,25 @@ impl Element for Window {
             return Vec::new();
         }
         let mut result = Vec::new();
+        let (wx, wy, ww, wh) = self.rect();
         for &child_ptr in &self.children {
             let widget = unsafe { &*child_ptr };
-            result.extend(widget.text_labels_with_bounds(ctx));
+            for (label, bounds) in widget.text_labels_with_bounds(ctx) {
+                let cb = if let Some(b) = bounds {
+                    let cx0 = b[0].max(wx);
+                    let cy0 = b[1].max(wy);
+                    let cx1 = b[2].min(wx + ww);
+                    let cy1 = b[3].min(wy + wh);
+                    if cx1 > cx0 && cy1 > cy0 {
+                        Some([cx0, cy0, cx1, cy1])
+                    } else {
+                        continue;
+                    }
+                } else {
+                    Some([wx, wy, wx + ww, wy + wh])
+                };
+                result.push((label, cb));
+            }
         }
         result
     }
@@ -199,9 +226,25 @@ impl Element for Window {
             return Vec::new();
         }
         let mut result = Vec::new();
+        let (wx, wy, ww, wh) = self.rect();
         for &child_ptr in &self.children {
             let widget = unsafe { &*child_ptr };
-            result.extend(widget.text_labels_with_font_and_bounds(ctx));
+            for (label, font, bounds) in widget.text_labels_with_font_and_bounds(ctx) {
+                let cb = if let Some(b) = bounds {
+                    let cx0 = b[0].max(wx);
+                    let cy0 = b[1].max(wy);
+                    let cx1 = b[2].min(wx + ww);
+                    let cy1 = b[3].min(wy + wh);
+                    if cx1 > cx0 && cy1 > cy0 {
+                        Some([cx0, cy0, cx1, cy1])
+                    } else {
+                        continue;
+                    }
+                } else {
+                    Some([wx, wy, wx + ww, wy + wh])
+                };
+                result.push((label, font, cb));
+            }
         }
         result
     }