git.lucas.co / cce-system-interface
system settings
git clone https://git.lucas.co/cce-system-interface.git

commit34d8baa78f1edbe3026104c59a8be4da245bb9ac
parented6d0a9373
authorLucas Galante <[email protected]>
date2026-06-24 12:46
perf: implement in-place scroll shifting to optimize layout rebuild during scrolling

 src/input_handler.rs | 18 +++++++++++++++++-
 src/main.rs          |  8 ++++++++
 src/renderer.rs      |  5 +++++
 3 files changed, 30 insertions(+), 1 deletion(-)

diff --git a/src/input_handler.rs b/src/input_handler.rs
index 4535de3..05c7ac0 100644
--- a/src/input_handler.rs
+++ b/src/input_handler.rs
@@ -680,7 +680,23 @@ impl SystemInterface {
             let old_scroll = self.scroll_y;
             self.scroll_y = (self.scroll_y + dy).max(0.0).min(self.max_scroll_y);
             if (self.scroll_y - old_scroll).abs() > 0.01 {
-                self.needs_rebuild = true;
+                let actual_dy = self.scroll_y - old_scroll;
+                for w in &mut self.widgets[self.scrollable_widgets_start_idx..] {
+                    w.y -= actual_dy;
+                }
+                for ti in &mut self.text_items[self.scrollable_text_items_start_idx..] {
+                    ti.y -= actual_dy;
+                    if let Some(ref mut b) = ti.bounds {
+                        b[1] -= actual_dy;
+                        b[3] -= actual_dy;
+                    }
+                }
+                for (btn, _) in &mut self.page_buttons[self.scrollable_buttons_start_idx..] {
+                    if let Some(base) = btn.base_mut() {
+                        base.y -= actual_dy;
+                    }
+                }
+                self.last_scroll_y = self.scroll_y;
                 return true;
             }
         } else {
diff --git a/src/main.rs b/src/main.rs
index d20e247..ebbbdad 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -160,6 +160,10 @@ struct SystemInterface {
     needs_rebuild: bool,
     scroll_y: f32,
     max_scroll_y: f32,
+    scrollable_widgets_start_idx: usize,
+    scrollable_text_items_start_idx: usize,
+    scrollable_buttons_start_idx: usize,
+    last_scroll_y: f32,
     audio_sink_dragging: Option<usize>,
     audio_source_dragging: Option<usize>,
     display_brightness_dragging: bool,
@@ -256,6 +260,10 @@ impl cce_ui::engine::Application for SystemInterface {
             needs_rebuild: true,
             scroll_y: 0.0,
             max_scroll_y: 0.0,
+            scrollable_widgets_start_idx: 0,
+            scrollable_text_items_start_idx: 0,
+            scrollable_buttons_start_idx: 0,
+            last_scroll_y: 0.0,
             audio_sink_dragging: None,
             audio_source_dragging: None,
             display_brightness_dragging: false,
diff --git a/src/renderer.rs b/src/renderer.rs
index fbc179e..5eef5cc 100644
--- a/src/renderer.rs
+++ b/src/renderer.rs
@@ -630,6 +630,10 @@ impl SystemInterface {
             }
         }
 
+        self.scrollable_widgets_start_idx = widgets.len();
+        self.scrollable_text_items_start_idx = text_items.len();
+        self.scrollable_buttons_start_idx = page_buttons.len();
+
         // Page content in LOGICAL coordinates, then scale to physical
         let pc = self.render_page_content(lcx, lcy, lcw, lch);
 
@@ -812,6 +816,7 @@ impl SystemInterface {
         self.text_items = text_items;
         self.page_buttons = page_buttons;
         self.needs_rebuild = false;
+        self.last_scroll_y = self.scroll_y;
         self.ui_context.clear_dirty();
     }