git.lucas.co / cce-status-interface
status bar
git clone https://git.lucas.co/cce-status-interface.git

commit732bd2fd5d610d78a293bdeb50c86ca80bbb40dd
parentfefcd6a71e
authorLucas Galante <[email protected]>
date2026-08-10 10:27
refactor: remove the viewport tabs

The unfocused window module shows only the no-focus chip; clicking the
module always opens the window picker. Gone with the tabs: the
ViewportBounds plumbing through every StatusModule signature, the
viewport param of width/render, the tab click fallback, and
parse_viewport_text (+ its tests). The viewport subscription stays —
its {"active": N} payload feeds the layout menu's target, read at
menu-open time, so a viewport push never redraws.

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

 CLAUDE.md      |   9 ++--
 src/main.rs    | 164 +++------------------------------------------------------
 src/modules.rs | 111 ++++++++------------------------------
 3 files changed, 33 insertions(+), 251 deletions(-)

diff --git a/CLAUDE.md b/CLAUDE.md
index 9036989..8621654 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -57,7 +57,7 @@ The app implements `cce_ui::engine::Application` on the **`display_list()` paint
    `StatusApp`: `rects`, `rounded_boxes`, `text_prims`
    (the `TextPrim` tuple type; build them with `draw_label()` from a
    `cce_ui::widget::StyledLabel`), plus `input_regions`, `module_bounds`,
-   `tray_item_bounds`, `viewport_bounds`.
+   `tray_item_bounds`.
 2. `display_list()` replays those buffers into a `PaintCtx` each frame (and triggers
    `rebuild_layout()` when size/scale changed or `needs_rebuild` is set).
    `overlay_quads()` remains a separate on-top pass (used for drag feedback).
@@ -75,7 +75,9 @@ listen to tray D-Bus, etc.:
 - **Compositor status feed** (`spawn_status_listener`): connects to
   `/tmp/cce-status[-interface]-{WAYLAND_DISPLAY}.sock`, subscribes to `viewport`,
   `layout`, `title`, `modifiers` (line-oriented, auto-reconnects every 1s). The
-  `viewport` payload is Pango-ish markup parsed by `parse_viewport_text()`.
+  `viewport` payload is JSON carrying only the active viewport number
+  (`{"active": N}`), read at menu-open time for the layout menu's target —
+  nothing renders it (the old viewport tabs are gone).
 - **System stats** (`spawn_system_stats`): `/proc/stat`, `/proc/meminfo`,
   `/sys/class/power_supply/BAT*`, `/sys/class/backlight`, and `pactl` for volume/mute.
 - **Tray** (`spawn_status_tray`): a full StatusNotifierItem/Watcher host over `zbus`,
@@ -157,8 +159,7 @@ mtime in `tick()`, so there is no reload event to wire up.
   starts the same segment drag as adjust-position mode (snap to an edge on release,
   persisted to `layout.status_bar.<module>` in config.kdl). This app never sees those
   clicks and no longer tracks the super key.
-- Viewport tabs in the window module are clickable (`viewport_bounds` → `ccectl view`);
-  the layout indicator opens the layout-mode menu; tray icons left-click activate /
+- The layout indicator opens the layout-mode menu; tray icons left-click activate /
   right-click open their DBusMenu.
 - `ToggleHideModules` / `ToggleAdjustPositionMode` mirror their state to the compositor
   via `ccectl status-hide-mode|adjust-position-mode true|false`; the adjust-mode state
diff --git a/src/main.rs b/src/main.rs
index b663165..f642c07 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -54,15 +54,6 @@ pub struct TrayIconBounds {
     pub dbus_id: Option<String>,
 }
 
-#[derive(Debug, Clone)]
-pub struct ViewportBounds {
-    pub name: String,
-    pub x: f32,
-    pub y: f32,
-    pub w: f32,
-    pub h: f32,
-}
-
 #[derive(Debug, Clone)]
 pub struct LayoutBounds {
     pub x: f32,
@@ -228,41 +219,6 @@ pub(crate) fn make_text_buffer(fs: &mut FontSystem, text: &str, size: f32, font_
     buf
 }
 
-pub(crate) fn parse_hex_to_rgba(hex: &str) -> Option<[f32; 4]> {
-    cce_ui::color::parse_hex_rgba(hex)
-}
-
-pub(crate) fn parse_viewport_text(input: &str) -> Vec<([f32; 4], String)> {
-    let mut pango = input.to_string();
-    if let Ok(val) = serde_json::from_str::<serde_json::Value>(input) {
-        if let Some(t) = val.get("text").and_then(|v| v.as_str()) {
-            pango = t.to_string();
-        }
-    }
-    let mut result = Vec::new();
-    let mut remaining = pango.as_str();
-    while let Some(start_span) = remaining.find("<span color='") {
-        let color_start = start_span + "<span color='".len();
-        if let Some(color_end) = remaining[color_start..].find("'") {
-            let hex_color = &remaining[color_start..color_start + color_end];
-            let tag_start = color_start + color_end + "'>".len();
-            if let Some(tag_end) = remaining[tag_start..].find("</span>") {
-                let tag_text = &remaining[tag_start..tag_start + tag_end];
-                let color = parse_hex_to_rgba(hex_color).unwrap_or([0.8, 0.8, 0.8, 1.0]);
-                result.push((color, tag_text.to_string()));
-                remaining = &remaining[tag_start + tag_end + "</span>".len()..];
-            } else {
-                break;
-            }
-        } else {
-            break;
-        }
-    }
-    if result.is_empty() && !pango.is_empty() {
-        result.push(([0.8, 0.8, 0.8, 1.0], pango.to_string()));
-    }
-    result
-}
 
 
 pub struct RectWidget {
@@ -306,7 +262,6 @@ struct StatusApp {
     cursor_pos: (f64, f64),
     hovered_tray_item: Option<String>,
     tray_item_bounds: Vec<TrayIconBounds>,
-    viewport_bounds: Vec<ViewportBounds>,
     layout_bounds: Option<LayoutBounds>,
 
     font_system: FontSystem,
@@ -434,7 +389,6 @@ impl StatusApp {
             self.status_bar.set_bg_color(self.current_bg_color);
         }
 
-        self.viewport_bounds.clear();
         self.layout_bounds = None;
 
         let is_single = self.selected_module_name.is_some();
@@ -445,7 +399,6 @@ impl StatusApp {
         for module in &left_modules {
             let w = module.width(
                 &self.stats,
-                &self.viewport,
                 &self.layout,
                 &self.title,
                 &mut self.font_system,
@@ -482,7 +435,6 @@ impl StatusApp {
                     left_x,
                     w,
                     &self.stats,
-                    &self.viewport,
                     &self.layout,
                     &self.title,
                     &mut self.font_system,
@@ -494,7 +446,6 @@ impl StatusApp {
                     &mut self.text_prims,
                     &mut self.rects,
                     &mut self.overlay_rects,
-                    &mut self.viewport_bounds,
                     &mut self.layout_bounds,
                     &self.tray_items,
                     &mut self.tray_item_bounds,
@@ -521,7 +472,6 @@ impl StatusApp {
         for module in right_modules.iter().rev() {
             let w = module.width(
                 &self.stats,
-                &self.viewport,
                 &self.layout,
                 &self.title,
                 &mut self.font_system,
@@ -566,7 +516,6 @@ impl StatusApp {
                     right_x,
                     w,
                     &self.stats,
-                    &self.viewport,
                     &self.layout,
                     &self.title,
                     &mut self.font_system,
@@ -578,7 +527,6 @@ impl StatusApp {
                     &mut self.text_prims,
                     &mut self.rects,
                     &mut self.overlay_rects,
-                    &mut self.viewport_bounds,
                     &mut self.layout_bounds,
                     &self.tray_items,
                     &mut self.tray_item_bounds,
@@ -1219,7 +1167,6 @@ impl cce_ui::engine::Application for StatusApp {
             cursor_pos: (0.0, 0.0),
             hovered_tray_item: None,
             tray_item_bounds: Vec::new(),
-            viewport_bounds: Vec::new(),
             layout_bounds: None,
             font_system,
             status_bar: cce_ui::widget::StatusBar::new(),
@@ -1283,15 +1230,10 @@ impl cce_ui::engine::Application for StatusApp {
         let mut changed = true;
         match msg {
             CustomEvent::ViewportUpdated(t) => {
-                // Dedup on the PARSED tabs, not the raw payload: the raw
-                // text embeds live camera pan/zoom numbers, so a camera
-                // animation re-delivers a string that differs every frame
-                // while the rendered viewport content is identical — raw
-                // comparison made the whole segment rebuild (and the
-                // compositor re-bake its blur) per animation frame, which
-                // reads as the module flickering until the camera settles.
-                changed = self.viewport != t
-                    && parse_viewport_text(&t) != parse_viewport_text(&self.viewport);
+                // Nothing renders the viewport payload (the tabs are gone);
+                // it is only read at menu-open time for the layout menu's
+                // active viewport, so a push never redraws.
+                changed = false;
                 self.viewport = t;
             }
             CustomEvent::LayoutUpdated(l) => {
@@ -1895,31 +1837,8 @@ impl cce_ui::engine::Application for StatusApp {
                     }
 
                     if clicked_window {
-                        let has_focus = !self.title.is_empty() && self.title != "(none)";
-                        if !has_focus {
-                            let mut clicked_viewport = false;
-                            for bound in &self.viewport_bounds {
-                                if cx >= bound.x as f64 && cx <= (bound.x + bound.w) as f64
-                                    && cy >= bound.y as f64 && cy <= (bound.y + bound.h) as f64 {
-                                    log::debug!("[viewport-click-via-window] Viewport matched: {}", bound.name);
-                                    let name = bound.name.clone();
-                                    std::thread::spawn(move || {
-                                        let _ = std::process::Command::new(get_ccectl_cmd())
-                                            .args(["view", &name])
-                                            .spawn();
-                                    });
-                                    clicked_viewport = true;
-                                    break;
-                                }
-                            }
-                            if !clicked_viewport {
-                                log::debug!("[window-click] Window module clicked (no window focused, fallback to switcher)!");
-                                self.trigger_switcher(false);
-                            }
-                        } else {
-                            log::debug!("[window-click] Window module clicked (window focused)!");
-                            self.trigger_switcher(false);
-                        }
+                        log::debug!("[window-click] Window module clicked, opening window picker");
+                        self.trigger_switcher(false);
                     }
                 }
             }
@@ -2109,78 +2028,7 @@ mod tests {
     // tests moved to config.rs with the phase-2 rewrite.
     // ------------------------------------------------------------------
 
-    fn assert_rgba_close(actual: [f32; 4], expected: [f32; 4]) {
-        for i in 0..4 {
-            assert!(
-                (actual[i] - expected[i]).abs() < 1e-3,
-                "channel {} differs: actual {:?} vs expected {:?}",
-                i,
-                actual,
-                expected
-            );
-        }
-    }
 
-    // --- parse_viewport_text ---
-
-    #[test]
-    fn viewport_text_single_span() {
-        let out = parse_viewport_text("<span color='#ff0000'>1</span>");
-        assert_eq!(out.len(), 1);
-        assert_eq!(out[0].1, "1");
-        assert_rgba_close(out[0].0, [1.0, 0.0, 0.0, 1.0]);
-    }
-
-    #[test]
-    fn viewport_text_multiple_spans() {
-        let out = parse_viewport_text(
-            "<span color='#ff0000'>1</span><span color='#00ff00'>2</span>",
-        );
-        assert_eq!(out.len(), 2);
-        assert_eq!(out[0].1, "1");
-        assert_eq!(out[1].1, "2");
-        assert_rgba_close(out[1].0, [0.0, 1.0, 0.0, 1.0]);
-    }
-
-    #[test]
-    fn viewport_text_json_wrapped() {
-        let out = parse_viewport_text(r##"{"text": "<span color='#0000ff'>3</span>"}"##);
-        assert_eq!(out.len(), 1);
-        assert_eq!(out[0].1, "3");
-        assert_rgba_close(out[0].0, [0.0, 0.0, 1.0, 1.0]);
-    }
-
-    #[test]
-    fn viewport_text_plain_text_falls_back_to_default_color() {
-        let out = parse_viewport_text("hello");
-        assert_eq!(out.len(), 1);
-        assert_eq!(out[0].1, "hello");
-        assert_rgba_close(out[0].0, [0.8, 0.8, 0.8, 1.0]);
-    }
-
-    #[test]
-    fn viewport_text_unterminated_span_falls_back_to_raw_input() {
-        // A span with no closing tag aborts markup parsing; the whole raw
-        // input (markup included) is emitted with the default color.
-        let input = "<span color='#ff0000'>abc";
-        let out = parse_viewport_text(input);
-        assert_eq!(out.len(), 1);
-        assert_eq!(out[0].1, input);
-        assert_rgba_close(out[0].0, [0.8, 0.8, 0.8, 1.0]);
-    }
-
-    #[test]
-    fn viewport_text_bad_hex_gets_default_color() {
-        let out = parse_viewport_text("<span color='zzz'>x</span>");
-        assert_eq!(out.len(), 1);
-        assert_eq!(out[0].1, "x");
-        assert_rgba_close(out[0].0, [0.8, 0.8, 0.8, 1.0]);
-    }
-
-    #[test]
-    fn viewport_text_empty_input_is_empty() {
-        assert!(parse_viewport_text("").is_empty());
-    }
 
     // --- module_side_from_json ---
 
diff --git a/src/modules.rs b/src/modules.rs
index 5341b60..874490b 100644
--- a/src/modules.rs
+++ b/src/modules.rs
@@ -4,8 +4,8 @@ use cce_ui::color;
 use cce_ui::widget::StyledLabel as Label;
 
 use crate::{
-    RectWidget, RoundedBox, ViewportBounds, LayoutBounds, SystemStats, TrayItem,
-    TrayIconBounds, make_text_buffer, parse_viewport_text,
+    RectWidget, RoundedBox, LayoutBounds, SystemStats, TrayItem,
+    TrayIconBounds, make_text_buffer,
 };
 
 /// Vertical offset that centers a text run in a box `box_h` tall. The engine
@@ -24,7 +24,6 @@ pub trait StatusModule {
     fn width(
         &self,
         stats: &Option<SystemStats>,
-        viewport: &str,
         layout: &str,
         title: &str,
         font_system: &mut FontSystem,
@@ -39,7 +38,6 @@ pub trait StatusModule {
         x: f32,
         w: f32,
         stats: &Option<SystemStats>,
-        viewport: &str,
         layout: &str,
         title: &str,
         font_system: &mut FontSystem,
@@ -51,7 +49,6 @@ pub trait StatusModule {
         text_prims: &mut Vec<crate::TextPrim>,
         rects: &mut Vec<RectWidget>,
         overlay_rects: &mut Vec<RectWidget>,
-        viewport_bounds: &mut Vec<ViewportBounds>,
         layout_bounds: &mut Option<LayoutBounds>,
         tray_items: &HashMap<String, TrayItem>,
         tray_item_bounds: &mut Vec<TrayIconBounds>,
@@ -96,7 +93,6 @@ impl StatusModule for WindowModule {
     fn width(
         &self,
         _stats: &Option<SystemStats>,
-        viewport: &str,
         layout: &str,
         title: &str,
         font_system: &mut FontSystem,
@@ -141,18 +137,12 @@ impl StatusModule for WindowModule {
             // "(none)" is the compositor explicitly reporting Focus::None
             // (keystrokes go nowhere); an empty title is just the feed not
             // having connected yet, which must not flash the indicator.
-            let no_focus = title == "(none)";
-            let viewport_parsed = parse_viewport_text(viewport);
-            let mut total_w = 0.0;
-            if no_focus {
+            if title == "(none)" {
                 let label = Label::new_with_family(font_system, NO_FOCUS_TEXT, font_size, [0.0, 0.0, 0.0, 1.0], font_family);
-                total_w += label.w + 2.0 * padding + 4.0;
-            }
-            for (col, text) in &viewport_parsed {
-                let label = Label::new_with_family(font_system, text, font_size, *col, font_family);
-                total_w += label.w + 2.0 * padding + 4.0;
+                label.w + 2.0 * padding
+            } else {
+                0.0
             }
-            if total_w > 0.0 { total_w - 4.0 } else { 0.0 }
         }
     }
 
@@ -161,7 +151,6 @@ impl StatusModule for WindowModule {
         x: f32,
         _w: f32,
         _stats: &Option<SystemStats>,
-        viewport: &str,
         layout: &str,
         title: &str,
         font_system: &mut FontSystem,
@@ -173,7 +162,6 @@ impl StatusModule for WindowModule {
         text_prims: &mut Vec<crate::TextPrim>,
         _rects: &mut Vec<RectWidget>,
         _overlay_rects: &mut Vec<RectWidget>,
-        viewport_bounds: &mut Vec<ViewportBounds>,
         layout_bounds: &mut Option<LayoutBounds>,
         _tray_items: &HashMap<String, TrayItem>,
         _tray_item_bounds: &mut Vec<TrayIconBounds>,
@@ -217,58 +205,27 @@ impl StatusModule for WindowModule {
                     h: bar_h,
                 });
             }
-        } else {
-            let no_focus = title == "(none)";
-            let viewport_parsed = parse_viewport_text(viewport);
-            let mut cur_x = x;
-            if no_focus {
-                // Dim chip signalling that no window has keyboard focus —
-                // the state where typing goes nowhere. Same box as the
-                // viewport tabs, half-alpha text, not clickable.
-                let mut dim = normal_color;
-                dim[3] *= 0.5;
-                let label = Label::new_with_family(font_system, NO_FOCUS_TEXT, font_size, dim, font_family);
-                let box_w = label.w + 2.0 * padding;
-                if let Some(color) = box_bg_color {
-                    rounded_boxes.push(RoundedBox {
-                        x: cur_x,
-                        y: 0.0,
-                        w: box_w,
-                        h: bar_h,
-                        radius: status_box_radius,
-                        color,
-                        corners: (false, false, true, true),
-                        border: None,
-                    });
-                }
-                crate::draw_label(text_prims, label, cur_x + padding, centered_text_y(bar_h, font_size));
-                cur_x += box_w + 4.0;
-            }
-            for (col, text) in viewport_parsed {
-                let label = Label::new_with_family(font_system, &text, font_size, col, font_family);
-                let box_w = label.w + 2.0 * padding;
-                if let Some(color) = box_bg_color {
-                    rounded_boxes.push(RoundedBox {
-                        x: cur_x,
-                        y: 0.0,
-                        w: box_w,
-                        h: bar_h,
-                        radius: status_box_radius,
-                        color,
-                        corners: (false, false, true, true),
-                        border: None,
-                    });
-                }
-                crate::draw_label(text_prims, label, cur_x + padding, centered_text_y(bar_h, font_size));
-                viewport_bounds.push(ViewportBounds {
-                    name: text.clone(),
-                    x: cur_x,
+        } else if title == "(none)" {
+            // Dim chip signalling that no window has keyboard focus — the
+            // state where typing goes nowhere. Half-alpha text, not
+            // clickable.
+            let mut dim = normal_color;
+            dim[3] *= 0.5;
+            let label = Label::new_with_family(font_system, NO_FOCUS_TEXT, font_size, dim, font_family);
+            let box_w = label.w + 2.0 * padding;
+            if let Some(color) = box_bg_color {
+                rounded_boxes.push(RoundedBox {
+                    x,
                     y: 0.0,
                     w: box_w,
                     h: bar_h,
+                    radius: status_box_radius,
+                    color,
+                    corners: (false, false, true, true),
+                    border: None,
                 });
-                cur_x += box_w + 4.0;
             }
+            crate::draw_label(text_prims, label, x + padding, centered_text_y(bar_h, font_size));
         }
     }
 }
@@ -281,7 +238,6 @@ impl StatusModule for ClockModule {
     fn width(
         &self,
         stats: &Option<SystemStats>,
-        _viewport: &str,
         _layout: &str,
         _title: &str,
         font_system: &mut FontSystem,
@@ -304,7 +260,6 @@ impl StatusModule for ClockModule {
         x: f32,
         _w: f32,
         stats: &Option<SystemStats>,
-        _viewport: &str,
         _layout: &str,
         _title: &str,
         font_system: &mut FontSystem,
@@ -316,7 +271,6 @@ impl StatusModule for ClockModule {
         text_prims: &mut Vec<crate::TextPrim>,
         _rects: &mut Vec<RectWidget>,
         _overlay_rects: &mut Vec<RectWidget>,
-        _viewport_bounds: &mut Vec<ViewportBounds>,
         _layout_bounds: &mut Option<LayoutBounds>,
         _tray_items: &HashMap<String, TrayItem>,
         _tray_item_bounds: &mut Vec<TrayIconBounds>,
@@ -340,7 +294,6 @@ impl StatusModule for BatteryModule {
     fn width(
         &self,
         stats: &Option<SystemStats>,
-        _viewport: &str,
         _layout: &str,
         _title: &str,
         font_system: &mut FontSystem,
@@ -362,7 +315,6 @@ impl StatusModule for BatteryModule {
         x: f32,
         _w: f32,
         stats: &Option<SystemStats>,
-        _viewport: &str,
         _layout: &str,
         _title: &str,
         font_system: &mut FontSystem,
@@ -374,7 +326,6 @@ impl StatusModule for BatteryModule {
         text_prims: &mut Vec<crate::TextPrim>,
         _rects: &mut Vec<RectWidget>,
         _overlay_rects: &mut Vec<RectWidget>,
-        _viewport_bounds: &mut Vec<ViewportBounds>,
         _layout_bounds: &mut Option<LayoutBounds>,
         _tray_items: &HashMap<String, TrayItem>,
         _tray_item_bounds: &mut Vec<TrayIconBounds>,
@@ -405,7 +356,6 @@ impl StatusModule for VolumeModule {
     fn width(
         &self,
         stats: &Option<SystemStats>,
-        _viewport: &str,
         _layout: &str,
         _title: &str,
         font_system: &mut FontSystem,
@@ -427,7 +377,6 @@ impl StatusModule for VolumeModule {
         x: f32,
         _w: f32,
         stats: &Option<SystemStats>,
-        _viewport: &str,
         _layout: &str,
         _title: &str,
         font_system: &mut FontSystem,
@@ -439,7 +388,6 @@ impl StatusModule for VolumeModule {
         text_prims: &mut Vec<crate::TextPrim>,
         _rects: &mut Vec<RectWidget>,
         overlay_rects: &mut Vec<RectWidget>,
-        _viewport_bounds: &mut Vec<ViewportBounds>,
         _layout_bounds: &mut Option<LayoutBounds>,
         _tray_items: &HashMap<String, TrayItem>,
         _tray_item_bounds: &mut Vec<TrayIconBounds>,
@@ -483,7 +431,6 @@ impl StatusModule for BrightnessModule {
     fn width(
         &self,
         stats: &Option<SystemStats>,
-        _viewport: &str,
         _layout: &str,
         _title: &str,
         font_system: &mut FontSystem,
@@ -505,7 +452,6 @@ impl StatusModule for BrightnessModule {
         x: f32,
         _w: f32,
         stats: &Option<SystemStats>,
-        _viewport: &str,
         _layout: &str,
         _title: &str,
         font_system: &mut FontSystem,
@@ -517,7 +463,6 @@ impl StatusModule for BrightnessModule {
         text_prims: &mut Vec<crate::TextPrim>,
         _rects: &mut Vec<RectWidget>,
         _overlay_rects: &mut Vec<RectWidget>,
-        _viewport_bounds: &mut Vec<ViewportBounds>,
         _layout_bounds: &mut Option<LayoutBounds>,
         _tray_items: &HashMap<String, TrayItem>,
         _tray_item_bounds: &mut Vec<TrayIconBounds>,
@@ -543,7 +488,6 @@ impl StatusModule for MemoryModule {
     fn width(
         &self,
         stats: &Option<SystemStats>,
-        _viewport: &str,
         _layout: &str,
         _title: &str,
         font_system: &mut FontSystem,
@@ -573,7 +517,6 @@ impl StatusModule for MemoryModule {
         x: f32,
         _w: f32,
         stats: &Option<SystemStats>,
-        _viewport: &str,
         _layout: &str,
         _title: &str,
         font_system: &mut FontSystem,
@@ -585,7 +528,6 @@ impl StatusModule for MemoryModule {
         text_prims: &mut Vec<crate::TextPrim>,
         _rects: &mut Vec<RectWidget>,
         _overlay_rects: &mut Vec<RectWidget>,
-        _viewport_bounds: &mut Vec<ViewportBounds>,
         _layout_bounds: &mut Option<LayoutBounds>,
         _tray_items: &HashMap<String, TrayItem>,
         _tray_item_bounds: &mut Vec<TrayIconBounds>,
@@ -609,7 +551,6 @@ impl StatusModule for CpuModule {
     fn width(
         &self,
         stats: &Option<SystemStats>,
-        _viewport: &str,
         _layout: &str,
         _title: &str,
         font_system: &mut FontSystem,
@@ -631,7 +572,6 @@ impl StatusModule for CpuModule {
         x: f32,
         _w: f32,
         stats: &Option<SystemStats>,
-        _viewport: &str,
         _layout: &str,
         _title: &str,
         font_system: &mut FontSystem,
@@ -643,7 +583,6 @@ impl StatusModule for CpuModule {
         text_prims: &mut Vec<crate::TextPrim>,
         _rects: &mut Vec<RectWidget>,
         _overlay_rects: &mut Vec<RectWidget>,
-        _viewport_bounds: &mut Vec<ViewportBounds>,
         _layout_bounds: &mut Option<LayoutBounds>,
         _tray_items: &HashMap<String, TrayItem>,
         _tray_item_bounds: &mut Vec<TrayIconBounds>,
@@ -667,7 +606,6 @@ impl StatusModule for TrayModule {
     fn width(
         &self,
         _stats: &Option<SystemStats>,
-        _viewport: &str,
         _layout: &str,
         _title: &str,
         _font_system: &mut FontSystem,
@@ -689,7 +627,6 @@ impl StatusModule for TrayModule {
         x: f32,
         _w: f32,
         _stats: &Option<SystemStats>,
-        _viewport: &str,
         _layout: &str,
         _title: &str,
         font_system: &mut FontSystem,
@@ -701,7 +638,6 @@ impl StatusModule for TrayModule {
         text_prims: &mut Vec<crate::TextPrim>,
         _rects: &mut Vec<RectWidget>,
         overlay_rects: &mut Vec<RectWidget>,
-        _viewport_bounds: &mut Vec<ViewportBounds>,
         _layout_bounds: &mut Option<LayoutBounds>,
         tray_items: &HashMap<String, TrayItem>,
         tray_item_bounds: &mut Vec<TrayIconBounds>,
@@ -884,7 +820,6 @@ impl StatusModule for LightSourceModule {
     fn width(
         &self,
         _stats: &Option<SystemStats>,
-        _viewport: &str,
         _layout: &str,
         _title: &str,
         _font_system: &mut FontSystem,
@@ -903,7 +838,6 @@ impl StatusModule for LightSourceModule {
         x: f32,
         w: f32,
         _stats: &Option<SystemStats>,
-        _viewport: &str,
         _layout: &str,
         _title: &str,
         _font_system: &mut FontSystem,
@@ -915,7 +849,6 @@ impl StatusModule for LightSourceModule {
         _text_prims: &mut Vec<crate::TextPrim>,
         _rects: &mut Vec<RectWidget>,
         _overlay_rects: &mut Vec<RectWidget>,
-        _viewport_bounds: &mut Vec<ViewportBounds>,
         _layout_bounds: &mut Option<LayoutBounds>,
         _tray_items: &HashMap<String, TrayItem>,
         _tray_item_bounds: &mut Vec<TrayIconBounds>,