git.lucas.co / cce-compositor
Wayland compositor (wlroots)
git clone https://git.lucas.co/cce-compositor.git

commitf5f50c68d478433660274a2b972d64cf854251c6
parented9a3f21e4
authorLucas Galante <[email protected]>
date2026-06-23 14:38
feat: replace SidePanel window mode with Pinned

 src/server/config.rs         | 88 ++++++++++++++++++++++----------------------
 src/server/tiling.rs         |  4 +-
 src/server/window_manager.rs | 54 +++++++++++++--------------
 3 files changed, 73 insertions(+), 73 deletions(-)

diff --git a/src/server/config.rs b/src/server/config.rs
index 058d22f..4212857 100644
--- a/src/server/config.rs
+++ b/src/server/config.rs
@@ -32,11 +32,11 @@ pub struct Layout {
     pub grid_gap: i32,
     pub border_blur: bool,
     pub window_blur: bool,
-    pub side_panel_behavior: String,
-    pub side_panel_width: i32,
-    pub side_panel_position: String,
-    pub side_panel_border_gap: i32,
-    pub side_panel_border_opacity: i32,
+    pub pinned_behavior: String,
+    pub pinned_width: i32,
+    pub pinned_position: String,
+    pub pinned_border_gap: i32,
+    pub pinned_border_opacity: i32,
     pub status_normal_color: String,
     pub desktop_background: String,
     pub transparency_opacity: f32,
@@ -71,11 +71,11 @@ impl Default for Layout {
             grid_gap: 18,
             border_blur: false,
             window_blur: false,
-            side_panel_behavior: "inline".to_string(),
-            side_panel_width: 360,
-            side_panel_position: "left".to_string(),
-            side_panel_border_gap: 0,
-            side_panel_border_opacity: 100,
+            pinned_behavior: "inline".to_string(),
+            pinned_width: 360,
+            pinned_position: "left".to_string(),
+            pinned_border_gap: 0,
+            pinned_border_opacity: 100,
             status_normal_color: "#ccccd8".to_string(),
             desktop_background: "#000000".to_string(),
             transparency_opacity: 0.9,
@@ -125,8 +125,8 @@ pub enum Action {
     SetTag4,
     Expose,
     Minimize,
-    SidePanelLeft,
-    SidePanelRight,
+    PinnedLeft,
+    PinnedRight,
     ZoomIn,
     ZoomOut,
     ZoomReset,
@@ -319,16 +319,16 @@ pub struct LayoutConfig {
     pub border_blur: bool,
     #[serde(default = "default_window_blur")]
     pub window_blur: bool,
-    #[serde(default = "default_side_panel_behavior")]
-    pub side_panel_behavior: String,
-    #[serde(default = "default_side_panel_width")]
-    pub side_panel_width: i64,
-    #[serde(default = "default_side_panel_position")]
-    pub side_panel_position: String,
-    #[serde(default = "default_side_panel_border_gap")]
-    pub side_panel_border_gap: i64,
-    #[serde(default = "default_side_panel_border_opacity")]
-    pub side_panel_border_opacity: i64,
+    #[serde(default = "default_pinned_behavior", alias = "side_panel_behavior")]
+    pub pinned_behavior: String,
+    #[serde(default = "default_pinned_width", alias = "side_panel_width")]
+    pub pinned_width: i64,
+    #[serde(default = "default_pinned_position", alias = "side_panel_position")]
+    pub pinned_position: String,
+    #[serde(default = "default_pinned_border_gap", alias = "side_panel_border_gap")]
+    pub pinned_border_gap: i64,
+    #[serde(default = "default_pinned_border_opacity", alias = "side_panel_border_opacity")]
+    pub pinned_border_opacity: i64,
     #[serde(default = "default_status_normal_color")]
     pub status_normal_color: String,
     #[serde(default = "default_window_opacity")]
@@ -357,11 +357,11 @@ impl Default for LayoutConfig {
             grid_gap: default_grid_gap(),
             border_blur: default_border_blur(),
             window_blur: default_window_blur(),
-            side_panel_behavior: default_side_panel_behavior(),
-            side_panel_width: default_side_panel_width(),
-            side_panel_position: default_side_panel_position(),
-            side_panel_border_gap: default_side_panel_border_gap(),
-            side_panel_border_opacity: default_side_panel_border_opacity(),
+            pinned_behavior: default_pinned_behavior(),
+            pinned_width: default_pinned_width(),
+            pinned_position: default_pinned_position(),
+            pinned_border_gap: default_pinned_border_gap(),
+            pinned_border_opacity: default_pinned_border_opacity(),
             status_normal_color: default_status_normal_color(),
             window_opacity: default_window_opacity(),
         }
@@ -387,11 +387,11 @@ fn default_transition_duration() -> i64 { 300 }
 fn default_grid_gap() -> i64 { 18 }
 fn default_border_blur() -> bool { false }
 fn default_window_blur() -> bool { false }
-fn default_side_panel_behavior() -> String { "inline".to_string() }
-fn default_side_panel_width() -> i64 { 360 }
-fn default_side_panel_position() -> String { "left".to_string() }
-fn default_side_panel_border_gap() -> i64 { 0 }
-fn default_side_panel_border_opacity() -> i64 { 100 }
+fn default_pinned_behavior() -> String { "inline".to_string() }
+fn default_pinned_width() -> i64 { 360 }
+fn default_pinned_position() -> String { "left".to_string() }
+fn default_pinned_border_gap() -> i64 { 0 }
+fn default_pinned_border_opacity() -> i64 { 100 }
 fn default_status_normal_color() -> String { "#ccccd8".to_string() }
 fn default_window_opacity() -> bool { true }
 
@@ -432,7 +432,7 @@ pub fn parse_tiling_mode(s: &str) -> TilingMode {
         "grid" => TilingMode::Grid,
         "fullscreen" => TilingMode::Fullscreen,
         "popup" => TilingMode::Popup,
-        "sidepanel" | "side_panel" | "side-panel" => TilingMode::SidePanel,
+        "sidepanel" | "side_panel" | "side-panel" | "pinned" => TilingMode::Pinned,
         "expose" => TilingMode::Expose,
         "status" => TilingMode::Status,
         _ => TilingMode::Cascade,
@@ -552,10 +552,10 @@ pub fn parse_action(s: &str) -> Action {
         Action::None
     } else if s == "expose" {
         Action::Expose
-    } else if s == "side-panel-left" {
-        Action::SidePanelLeft
-    } else if s == "side-panel-right" {
-        Action::SidePanelRight
+    } else if s == "side-panel-left" || s == "pinned-left" {
+        Action::PinnedLeft
+    } else if s == "side-panel-right" || s == "pinned-right" {
+        Action::PinnedRight
     } else if s == "zoom-in" {
         Action::ZoomIn
     } else if s == "zoom-out" {
@@ -700,11 +700,11 @@ pub fn parse_config(path: &str, state: &mut crate::window_manager::WindowManager
     state.layout.grid_gap = config.layout.grid_gap as i32;
     state.layout.border_blur = config.layout.border_blur;
     state.layout.window_blur = config.layout.window_blur;
-    state.layout.side_panel_behavior = config.layout.side_panel_behavior;
-    state.layout.side_panel_width = config.layout.side_panel_width as i32;
-    state.layout.side_panel_position = config.layout.side_panel_position;
-    state.layout.side_panel_border_gap = config.layout.side_panel_border_gap as i32;
-    state.layout.side_panel_border_opacity = config.layout.side_panel_border_opacity as i32;
+    state.layout.pinned_behavior = config.layout.pinned_behavior;
+    state.layout.pinned_width = config.layout.pinned_width as i32;
+    state.layout.pinned_position = config.layout.pinned_position;
+    state.layout.pinned_border_gap = config.layout.pinned_border_gap as i32;
+    state.layout.pinned_border_opacity = config.layout.pinned_border_opacity as i32;
     state.layout.status_normal_color = config.layout.status_normal_color.clone();
     state.layout.transparency_opacity = config.transparency.as_ref().and_then(|t| t.opacity).unwrap_or(0.9) as f32;
     state.layout.window_opacity = config.layout.window_opacity;
@@ -746,7 +746,7 @@ pub fn parse_config(path: &str, state: &mut crate::window_manager::WindowManager
         state.keybinds.push(Keybind {
             mods: super_mod,
             keysym: left_sym,
-            action: Action::SidePanelLeft,
+            action: Action::PinnedLeft,
             command: None,
         });
     }
@@ -754,7 +754,7 @@ pub fn parse_config(path: &str, state: &mut crate::window_manager::WindowManager
         state.keybinds.push(Keybind {
             mods: super_mod,
             keysym: right_sym,
-            action: Action::SidePanelRight,
+            action: Action::PinnedRight,
             command: None,
         });
     }
diff --git a/src/server/tiling.rs b/src/server/tiling.rs
index be49df9..828b24a 100644
--- a/src/server/tiling.rs
+++ b/src/server/tiling.rs
@@ -7,7 +7,7 @@ pub enum TilingMode {
     Grid,
     Fullscreen,
     Popup,
-    SidePanel,
+    Pinned,
     Expose,
     Status,
 }
@@ -20,7 +20,7 @@ impl TilingMode {
             TilingMode::Grid => "Grid",
             TilingMode::Fullscreen => "Fullscreen",
             TilingMode::Popup => "Popup",
-            TilingMode::SidePanel => "Side Panel",
+            TilingMode::Pinned => "Pinned",
             TilingMode::Expose => "Expose",
             TilingMode::Status => "Status",
         }
diff --git a/src/server/window_manager.rs b/src/server/window_manager.rs
index 03c81c3..a5d242a 100644
--- a/src/server/window_manager.rs
+++ b/src/server/window_manager.rs
@@ -456,7 +456,7 @@ impl WindowManager {
         self.keep_status_bar_on_top();
 
         let mut hasher = std::collections::hash_map::DefaultHasher::new();
-        self.layout.side_panel_behavior.hash(&mut hasher);
+        self.layout.pinned_behavior.hash(&mut hasher);
         let render_list = &mut self.rendering_requested.list as *mut ffi::wl_list as *mut WlList;
         let mut curr = (*render_list).next;
         while curr != render_list {
@@ -501,7 +501,7 @@ impl WindowManager {
                             } else if (*window).rendering_requested.circular {
                                 ffi::wlr_scene_node_reparent((*window).tree as *mut _, (*self.server).scene.layers.top);
                                 ffi::wlr_scene_node_raise_to_top((*window).tree as *mut _);
-                            } else if (*window).tiling_mode == crate::tiling::TilingMode::SidePanel && self.layout.side_panel_behavior == "above" {
+                            } else if (*window).tiling_mode == crate::tiling::TilingMode::Pinned && self.layout.pinned_behavior == "above" {
                                 ffi::wlr_scene_node_reparent((*window).tree as *mut _, (*self.server).scene.layers.top);
                                 ffi::wlr_scene_node_raise_to_top((*window).tree as *mut _);
                             } else {
@@ -720,7 +720,7 @@ fn get_closest_tag(x: f64, y: f64) -> i32 {
             let camera_center_y = self.desk_pan_y + (viewport_h / 2.0) / self.desk_zoom;
             let active_tag = Self::get_closest_tag(camera_center_x, camera_center_y);
 
-            let mut side_panel_windows: Vec<*mut Window> = Vec::new();
+            let mut pinned_windows: Vec<*mut Window> = Vec::new();
             let mut normal_windows: Vec<*mut Window> = Vec::new();
 
             for &win_ptr in self.windows.iter() {
@@ -774,38 +774,38 @@ fn get_closest_tag(x: f64, y: f64) -> i32 {
                 }
 
                 let window_tag = Self::get_closest_tag((*win_ptr).virtual_x, (*win_ptr).virtual_y);
-                if mode == crate::tiling::TilingMode::SidePanel && window_tag == active_tag {
-                    side_panel_windows.push(win_ptr);
+                if mode == crate::tiling::TilingMode::Pinned && window_tag == active_tag {
+                    pinned_windows.push(win_ptr);
                 } else {
                     normal_windows.push(win_ptr);
                 }
             }
 
-            // Arrange side panel windows (fixed on screen, scale = 1.0)
-            let side_panel_win = side_panel_windows.first().copied();
-            let mut side_panel_w = 0;
+            // Arrange pinned windows (fixed on screen, scale = 1.0)
+            let pinned_win = pinned_windows.first().copied();
+            let mut pinned_w = 0;
             let bw = self.layout.border_width;
-            if let Some(sp_win) = side_panel_win {
+            if let Some(sp_win) = pinned_win {
                 let hint_min_w = (*sp_win).wm_scheduled.dimensions_hint.min_width as i32;
-                side_panel_w = if hint_min_w > 32 {
-                    std::cmp::max(self.layout.side_panel_width, hint_min_w)
+                pinned_w = if hint_min_w > 32 {
+                    std::cmp::max(self.layout.pinned_width, hint_min_w)
                 } else {
-                    self.layout.side_panel_width
+                    self.layout.pinned_width
                 };
             }
 
-            let g = self.layout.side_panel_border_gap;
+            let g = self.layout.pinned_border_gap;
             let dec_h = std::cmp::max(bw, 16);
-            for (sp_idx, &win_ptr) in side_panel_windows.iter().enumerate() {
+            for (sp_idx, &win_ptr) in pinned_windows.iter().enumerate() {
                 if sp_idx == 0 {
-                    let sp_x = if self.layout.side_panel_position == "right" {
-                        usable_x + usable_w - side_panel_w - g + bw
+                    let sp_x = if self.layout.pinned_position == "right" {
+                        usable_x + usable_w - pinned_w - g + bw
                     } else {
                         usable_x + g + bw
                     };
                     let sp_y = usable_y + dec_h + g;
                     let sp_h = (usable_h - (dec_h + bw) - 2 * g).max(1);
-                    let sp_w = (side_panel_w - bw * 2).max(1);
+                    let sp_w = (pinned_w - bw * 2).max(1);
 
                     (*win_ptr).rendering_requested.x = sp_x;
                     (*win_ptr).rendering_requested.y = sp_y;
@@ -828,7 +828,7 @@ fn get_closest_tag(x: f64, y: f64) -> i32 {
                     };
                     (*win_ptr).wm_requested.tiled = 1 | 2 | 4 | 8;
 
-                    let opacity_factor = if !self.layout.window_opacity { 1.0f32 } else { self.layout.side_panel_border_opacity as f32 / 100.0 };
+                    let opacity_factor = if !self.layout.window_opacity { 1.0f32 } else { self.layout.pinned_border_opacity as f32 / 100.0 };
                     let is_focused = win_ptr == focused_window;
                     let r = self.layout.border_r;
                     let g_color = self.layout.border_g;
@@ -1420,12 +1420,12 @@ fn get_closest_tag(x: f64, y: f64) -> i32 {
                 }
                 self.dirty_windowing();
             }
-            Action::SidePanelLeft => {
-                self.layout.side_panel_position = "left".to_string();
+            Action::PinnedLeft => {
+                self.layout.pinned_position = "left".to_string();
                 self.dirty_windowing();
             }
-            Action::SidePanelRight => {
-                self.layout.side_panel_position = "right".to_string();
+            Action::PinnedRight => {
+                self.layout.pinned_position = "right".to_string();
                 self.dirty_windowing();
             }
             Action::Expose => {
@@ -1752,11 +1752,11 @@ fn get_closest_tag(x: f64, y: f64) -> i32 {
                         self.layout.border_g = ((border_color_val >> 8) & 0xFF) * 0x01010101;
                         self.layout.border_b = (border_color_val & 0xFF) * 0x01010101;
                     }
-                    "side_panel_width" => { if let Ok(v) = val.parse::<i32>() { self.layout.side_panel_width = v; } }
-                    "side_panel_behavior" => { self.layout.side_panel_behavior = val.to_string(); }
-                    "side_panel_position" => { self.layout.side_panel_position = val.to_string(); }
-                    "side_panel_border_gap" => { if let Ok(v) = val.parse::<i32>() { self.layout.side_panel_border_gap = v; } }
-                    "side_panel_border_opacity" => { if let Ok(v) = val.parse::<i32>() { self.layout.side_panel_border_opacity = v; } }
+                    "side_panel_width" | "pinned_width" => { if let Ok(v) = val.parse::<i32>() { self.layout.pinned_width = v; } }
+                    "side_panel_behavior" | "pinned_behavior" => { self.layout.pinned_behavior = val.to_string(); }
+                    "side_panel_position" | "pinned_position" => { self.layout.pinned_position = val.to_string(); }
+                    "side_panel_border_gap" | "pinned_border_gap" => { if let Ok(v) = val.parse::<i32>() { self.layout.pinned_border_gap = v; } }
+                    "side_panel_border_opacity" | "pinned_border_opacity" => { if let Ok(v) = val.parse::<i32>() { self.layout.pinned_border_opacity = v; } }
                     _ => return format!("error: unknown layout key: {}\n", key),
                 }
                 self.dirty_windowing();