Wayland compositor (wlroots)
git clone https://git.lucas.co/cce-compositor.git
Update clear-computing-environment-client to adapt to Element trait refactoring (modified: src/config.rs, src/decorations.rs, src/inspector_cli.rs and 4 others)
src/config.rs | 18 ++++++
src/decorations.rs | 157 +++++++++++++++++++++++++++++++++++++++++++++++++--
src/inspector_cli.rs | 4 +-
src/ipc.rs | 14 +++++
src/types.rs | 4 ++
src/wayland.rs | 102 ++++++++++++++++++++++++++++-----
src/wm.rs | 8 ++-
7 files changed, 281 insertions(+), 26 deletions(-)
diff --git a/src/config.rs b/src/config.rs
index b3abb45..dcd933b 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -84,6 +84,10 @@ 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,
}
impl Default for LayoutConfig {
@@ -108,6 +112,8 @@ 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(),
}
}
}
@@ -124,6 +130,14 @@ fn default_window_blur() -> bool {
false
}
+fn default_side_panel_behavior() -> String {
+ "inline".to_string()
+}
+
+fn default_side_panel_width() -> i64 {
+ 360
+}
+
fn default_gap() -> i64 {
48
}
@@ -325,6 +339,8 @@ pub fn parse_config(path: &str, cold_start: bool, state: &mut 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.clone();
+ state.layout.side_panel_width = config.layout.side_panel_width as i32;
if let Some((r, g, b, a)) = parse_hex_color(&config.layout.border_color) {
state.layout.border_r = r;
state.layout.border_g = g;
@@ -698,6 +714,8 @@ mod tests {
assert_eq!(lc.border_color, "#3e3e3e");
assert_eq!(lc.border_font_size, 11);
assert_eq!(lc.grid_gap, 18);
+ assert_eq!(lc.side_panel_width, 360);
+ assert_eq!(lc.side_panel_behavior, "inline");
}
#[test]
diff --git a/src/decorations.rs b/src/decorations.rs
index d77ac08..bcb08d8 100644
--- a/src/decorations.rs
+++ b/src/decorations.rs
@@ -283,6 +283,8 @@ fn update_border_decoration(
rect_h: i32,
border_width: i32,
round_bottom: bool,
+ side: &str,
+ hover_info: Option<(f64, f64)>,
) {
let dec_width = logical_width * scale;
let dec_height = logical_height * scale;
@@ -378,6 +380,50 @@ fn update_border_decoration(
*pixel = 0x00000000;
}
+ let mut highlight_region: Option<HighlightRegion> = None;
+ if let Some((hx, hy)) = hover_info {
+ const CORNER_THRESHOLD: f64 = 16.0;
+ match side {
+ "left" => {
+ let mid_x = (logical_width as f64) / 2.0;
+ if hx < mid_x {
+ if hy < CORNER_THRESHOLD {
+ highlight_region = Some(HighlightRegion::TopLeft);
+ } else if hy > (logical_height as f64 - CORNER_THRESHOLD) {
+ highlight_region = Some(HighlightRegion::BottomLeft);
+ } else {
+ highlight_region = Some(HighlightRegion::Left);
+ }
+ }
+ }
+ "right" => {
+ let mid_x = (logical_width as f64) / 2.0;
+ if hx >= mid_x {
+ if hy < CORNER_THRESHOLD {
+ highlight_region = Some(HighlightRegion::TopRight);
+ } else if hy > (logical_height as f64 - CORNER_THRESHOLD) {
+ highlight_region = Some(HighlightRegion::BottomRight);
+ } else {
+ highlight_region = Some(HighlightRegion::Right);
+ }
+ }
+ }
+ "bottom" => {
+ let mid_y = (logical_height as f64) / 2.0;
+ if hy >= mid_y {
+ if hx < CORNER_THRESHOLD {
+ highlight_region = Some(HighlightRegion::BottomLeft);
+ } else if hx > (logical_width as f64 - CORNER_THRESHOLD) {
+ highlight_region = Some(HighlightRegion::BottomRight);
+ } else {
+ highlight_region = Some(HighlightRegion::Bottom);
+ }
+ }
+ }
+ _ => {}
+ }
+ }
+
// Draw visual border color with 3D cylindrical shading and mitred joints
let rx_start = rect_x * scale;
let ry_start = rect_y * scale;
@@ -444,9 +490,17 @@ fn update_border_decoration(
};
let a = ((bg_color >> 24) & 0xFF) as f32;
- let r_val = (((bg_color >> 16) & 0xFF) as f32 * s).round().min(255.0) as u32;
- let g = (((bg_color >> 8) & 0xFF) as f32 * s).round().min(255.0) as u32;
- let b = ((bg_color & 0xFF) as f32 * s).round().min(255.0) as u32;
+ let mut r_val = (((bg_color >> 16) & 0xFF) as f32 * s).round().min(255.0) as u32;
+ let mut g = (((bg_color >> 8) & 0xFF) as f32 * s).round().min(255.0) as u32;
+ let mut b = ((bg_color & 0xFF) as f32 * s).round().min(255.0) as u32;
+
+ if let Some(region) = highlight_region {
+ if is_pixel_in_highlight_region(side, region, px, py, logical_width, logical_height, scale) {
+ r_val = (r_val as f32 * 0.6 + 255.0 * 0.4).round() as u32;
+ g = (g as f32 * 0.6 + 255.0 * 0.4).round() as u32;
+ b = (b as f32 * 0.6 + 255.0 * 0.4).round() as u32;
+ }
+ }
buffer_slice[row_offset + px as usize] = ((a as u32) << 24)
| (r_val << 16)
@@ -699,6 +753,10 @@ pub fn update_decorations(state: &mut AppState, qhandle: &QueueHandle<AppState>)
border_width.max(1)
};
+ let hover_left = state.pointer_hovered_surface.as_ref()
+ .filter(|surf| wp.dec_left.as_ref().map_or(false, |d| &d.surface == *surf))
+ .map(|_| (state.last_pointer_surface_x, state.last_pointer_surface_y));
+
update_border_decoration(
wid,
&mut wp.dec_left,
@@ -719,8 +777,14 @@ pub fn update_decorations(state: &mut AppState, qhandle: &QueueHandle<AppState>)
win_height,
border_width,
false,
+ "left",
+ hover_left,
);
+ let hover_right = state.pointer_hovered_surface.as_ref()
+ .filter(|surf| wp.dec_right.as_ref().map_or(false, |d| &d.surface == *surf))
+ .map(|_| (state.last_pointer_surface_x, state.last_pointer_surface_y));
+
update_border_decoration(
wid,
&mut wp.dec_right,
@@ -741,8 +805,14 @@ pub fn update_decorations(state: &mut AppState, qhandle: &QueueHandle<AppState>)
win_height,
border_width,
false,
+ "right",
+ hover_right,
);
+ let hover_bottom = state.pointer_hovered_surface.as_ref()
+ .filter(|surf| wp.dec_bottom.as_ref().map_or(false, |d| &d.surface == *surf))
+ .map(|_| (state.last_pointer_surface_x, state.last_pointer_surface_y));
+
update_border_decoration(
wid,
&mut wp.dec_bottom,
@@ -763,6 +833,8 @@ pub fn update_decorations(state: &mut AppState, qhandle: &QueueHandle<AppState>)
border_width,
border_width,
true,
+ "bottom",
+ hover_bottom,
);
}
@@ -799,6 +871,10 @@ pub fn update_decorations(state: &mut AppState, qhandle: &QueueHandle<AppState>)
});
}
+ let hover_top = state.pointer_hovered_surface.as_ref()
+ .filter(|surf| wp.decoration.as_ref().map_or(false, |d| &d.surface == *surf))
+ .map(|_| (state.last_pointer_surface_x, state.last_pointer_surface_y));
+
let dec = wp.decoration.as_mut().unwrap();
// Position decoration on top of the window top border
@@ -888,6 +964,21 @@ pub fn update_decorations(state: &mut AppState, qhandle: &QueueHandle<AppState>)
let titlebar_h_scaled = logical_height * scale;
let win_w_scaled = (if is_minimized { 160 - 2 * border_width } else { win_width }) * scale;
+ let mut highlight_region: Option<HighlightRegion> = None;
+ if let Some((hx, hy)) = hover_top {
+ let mid_y = (logical_height as f64) / 2.0;
+ if hy < mid_y {
+ const CORNER_THRESHOLD: f64 = 16.0;
+ if hx < CORNER_THRESHOLD {
+ highlight_region = Some(HighlightRegion::TopLeft);
+ } else if hx > (logical_width as f64 - CORNER_THRESHOLD) {
+ highlight_region = Some(HighlightRegion::TopRight);
+ } else {
+ highlight_region = Some(HighlightRegion::Top);
+ }
+ }
+ }
+
for py in 0..dec_height {
let row_offset = (py * dec_width) as usize;
for px in 0..dec_width {
@@ -924,9 +1015,17 @@ pub fn update_decorations(state: &mut AppState, qhandle: &QueueHandle<AppState>)
};
let a = ((bg_color >> 24) & 0xFF) as f32;
- let r_val = (((bg_color >> 16) & 0xFF) as f32 * s).round().min(255.0) as u32;
- let g = (((bg_color >> 8) & 0xFF) as f32 * s).round().min(255.0) as u32;
- let b = ((bg_color & 0xFF) as f32 * s).round().min(255.0) as u32;
+ let mut r_val = (((bg_color >> 16) & 0xFF) as f32 * s).round().min(255.0) as u32;
+ let mut g = (((bg_color >> 8) & 0xFF) as f32 * s).round().min(255.0) as u32;
+ let mut b = ((bg_color & 0xFF) as f32 * s).round().min(255.0) as u32;
+
+ if let Some(region) = highlight_region {
+ if is_pixel_in_highlight_region("top", region, px, py, logical_width, logical_height, scale) {
+ r_val = (r_val as f32 * 0.6 + 255.0 * 0.4).round() as u32;
+ g = (g as f32 * 0.6 + 255.0 * 0.4).round() as u32;
+ b = (b as f32 * 0.6 + 255.0 * 0.4).round() as u32;
+ }
+ }
buffer_slice[row_offset + px as usize] = ((a as u32) << 24) | (r_val << 16) | (g << 8) | b;
}
@@ -1035,3 +1134,49 @@ pub fn update_decorations(state: &mut AppState, qhandle: &QueueHandle<AppState>)
}
}
}
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+enum HighlightRegion {
+ TopLeft,
+ Top,
+ TopRight,
+ Left,
+ Right,
+ BottomLeft,
+ Bottom,
+ BottomRight,
+}
+
+fn is_pixel_in_highlight_region(
+ side: &str,
+ region: HighlightRegion,
+ px: i32,
+ py: i32,
+ logical_width: i32,
+ logical_height: i32,
+ scale: i32,
+) -> bool {
+ let px_logical = px as f32 / scale as f32;
+ let py_logical = py as f32 / scale as f32;
+ const CORNER_THRESHOLD: f32 = 16.0;
+
+ match (side, region) {
+ ("left", HighlightRegion::TopLeft) => py_logical < CORNER_THRESHOLD,
+ ("left", HighlightRegion::BottomLeft) => py_logical > (logical_height as f32 - CORNER_THRESHOLD),
+ ("left", HighlightRegion::Left) => py_logical >= CORNER_THRESHOLD && py_logical <= (logical_height as f32 - CORNER_THRESHOLD),
+
+ ("right", HighlightRegion::TopRight) => py_logical < CORNER_THRESHOLD,
+ ("right", HighlightRegion::BottomRight) => py_logical > (logical_height as f32 - CORNER_THRESHOLD),
+ ("right", HighlightRegion::Right) => py_logical >= CORNER_THRESHOLD && py_logical <= (logical_height as f32 - CORNER_THRESHOLD),
+
+ ("bottom", HighlightRegion::BottomLeft) => px_logical < CORNER_THRESHOLD,
+ ("bottom", HighlightRegion::BottomRight) => px_logical > (logical_width as f32 - CORNER_THRESHOLD),
+ ("bottom", HighlightRegion::Bottom) => px_logical >= CORNER_THRESHOLD && px_logical <= (logical_width as f32 - CORNER_THRESHOLD),
+
+ ("top", HighlightRegion::TopLeft) => px_logical < CORNER_THRESHOLD,
+ ("top", HighlightRegion::TopRight) => px_logical > (logical_width as f32 - CORNER_THRESHOLD),
+ ("top", HighlightRegion::Top) => px_logical >= CORNER_THRESHOLD && px_logical <= (logical_width as f32 - CORNER_THRESHOLD),
+
+ _ => false,
+ }
+}
diff --git a/src/inspector_cli.rs b/src/inspector_cli.rs
index 8c62ae6..da24454 100644
--- a/src/inspector_cli.rs
+++ b/src/inspector_cli.rs
@@ -321,7 +321,7 @@ fn main() {
}
}
} else {
- eprintln!("Error: Widget of type '{}'{} not found in surface '{}'",
+ eprintln!("Error: Element of type '{}'{} not found in surface '{}'",
target_type,
widget_label.as_ref().map(|l| format!(" with label '{}'", l)).unwrap_or_default(),
target_app_id
@@ -351,7 +351,7 @@ fn main() {
println!(" Dimensions: {}x{} px", surface.width, surface.height);
// Pretty print widget state if it's JSON
- print!(" Widget Tree: ");
+ print!(" Element Tree: ");
if let Ok(json_val) = serde_json::from_str::<Value>(&surface.state) {
if let Ok(pretty_json) = serde_json::to_string_pretty(&json_val) {
// Indent pretty JSON for clean display
diff --git a/src/ipc.rs b/src/ipc.rs
index 442dc51..274d695 100644
--- a/src/ipc.rs
+++ b/src/ipc.rs
@@ -706,6 +706,20 @@ fn handle_layout_command(rest: &str, state: &mut WindowManager) {
}
}
}
+ "side_panel_behavior" | "side-panel-behavior" => {
+ state.layout.side_panel_behavior = value_str.to_string();
+ if state.notifications_enable {
+ crate::config::show_notification("ccec", &format!("Side panel behavior set to {}", value_str));
+ }
+ }
+ "side_panel_width" | "side-panel-width" => {
+ if let Ok(value) = value_str.parse::<i32>() {
+ state.layout.side_panel_width = value;
+ if state.notifications_enable {
+ crate::config::show_notification("ccec", &format!("Side panel width set to {}px", value));
+ }
+ }
+ }
_ => {}
}
state.needs_render = true;
diff --git a/src/types.rs b/src/types.rs
index 3a70e00..4e1dcda 100644
--- a/src/types.rs
+++ b/src/types.rs
@@ -90,6 +90,8 @@ 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,
}
impl Default for Layout {
@@ -120,6 +122,8 @@ impl Default for Layout {
grid_gap: 18,
border_blur: false,
window_blur: false,
+ side_panel_behavior: "inline".to_string(),
+ side_panel_width: 360,
}
}
}
diff --git a/src/wayland.rs b/src/wayland.rs
index 360cb81..274a145 100644
--- a/src/wayland.rs
+++ b/src/wayland.rs
@@ -1076,6 +1076,20 @@ impl Dispatch<RiverWindowManagerV1, ()> for AppState {
0
} else if win.tiling_mode == crate::types::TilingMode::Popup {
5
+ } else if win.tiling_mode == crate::types::TilingMode::SidePanel {
+ if state.wm.layout.side_panel_behavior == "above" {
+ if Some(win.id) == focused_id {
+ 4
+ } else {
+ 3
+ }
+ } else {
+ if Some(win.id) == focused_id {
+ 2
+ } else {
+ 1
+ }
+ }
} else if win.tiling_mode != crate::types::TilingMode::Floating {
if Some(win.id) == focused_id {
2
@@ -1616,11 +1630,32 @@ impl Dispatch<RiverWindowV1, ()> for AppState {
river_window_v1::Event::PointerResizeRequested { seat, edges } => {
if let Some(_sid) = state.seat_id_for_proxy(&seat) {
+ let edges_u32: u32 = edges.into();
+ let op_type = match edges_u32 {
+ 1 => PointerOpType::ResizeTop,
+ 2 => PointerOpType::ResizeBottom,
+ 4 => PointerOpType::ResizeLeft,
+ 8 => PointerOpType::ResizeRight,
+ 5 => PointerOpType::ResizeTopLeft,
+ 9 => PointerOpType::ResizeTopRight,
+ 6 => PointerOpType::ResizeBottomLeft,
+ 10 => PointerOpType::ResizeBottomRight,
+ _ => PointerOpType::Resize,
+ };
+
let mut window_found = false;
let mut needs_render = false;
if let Some(win) = state.wm.get_window_mut(wid) {
if win.tiling_mode != TilingMode::Fullscreen && win.tiling_mode != TilingMode::Popup {
- if win.tiling_mode != TilingMode::Floating {
+ let is_right_resize_on_side_panel = win.tiling_mode == TilingMode::SidePanel
+ && matches!(
+ op_type,
+ PointerOpType::Resize
+ | PointerOpType::ResizeRight
+ | PointerOpType::ResizeTopRight
+ | PointerOpType::ResizeBottomRight
+ );
+ if !is_right_resize_on_side_panel && win.tiling_mode != TilingMode::Floating {
win.tiling_mode = TilingMode::Floating;
needs_render = true;
}
@@ -1642,18 +1677,6 @@ impl Dispatch<RiverWindowV1, ()> for AppState {
win.anim_h = None;
win.anim_opacity = None;
- let edges_u32: u32 = edges.into();
- let op_type = match edges_u32 {
- 1 => PointerOpType::ResizeTop,
- 2 => PointerOpType::ResizeBottom,
- 4 => PointerOpType::ResizeLeft,
- 8 => PointerOpType::ResizeRight,
- 5 => PointerOpType::ResizeTopLeft,
- 9 => PointerOpType::ResizeTopRight,
- 6 => PointerOpType::ResizeBottomLeft,
- 10 => PointerOpType::ResizeBottomRight,
- _ => PointerOpType::Resize,
- };
state.active_pointer_op = Some(PointerOp {
window_id: wid,
op_type,
@@ -1782,6 +1805,7 @@ impl Dispatch<RiverSeatV1, ()> for AppState {
river_seat_v1::Event::OpDelta { dx, dy } => {
if let Some(ref op) = state.active_pointer_op {
let wid = op.window_id;
+ let bw = state.wm.layout.cascade_border_width;
if let Some(win) = state.wm.get_window_mut(wid) {
match op.op_type {
PointerOpType::Move => {
@@ -1790,6 +1814,9 @@ impl Dispatch<RiverSeatV1, ()> for AppState {
}
PointerOpType::Resize | PointerOpType::ResizeRight => {
win.width = std::cmp::max(50, op.start_width + dx);
+ if win.tiling_mode == TilingMode::SidePanel {
+ win.hint_min_width = win.width + bw * 2;
+ }
}
PointerOpType::ResizeLeft => {
let target_width = std::cmp::max(50, op.start_width - dx);
@@ -1809,6 +1836,9 @@ impl Dispatch<RiverSeatV1, ()> for AppState {
PointerOpType::ResizeBottomRight => {
win.width = std::cmp::max(50, op.start_width + dx);
win.height = std::cmp::max(50, op.start_height + dy);
+ if win.tiling_mode == TilingMode::SidePanel {
+ win.hint_min_width = win.width + bw * 2;
+ }
}
PointerOpType::ResizeBottomLeft => {
let target_width = std::cmp::max(50, op.start_width - dx);
@@ -1835,6 +1865,9 @@ impl Dispatch<RiverSeatV1, ()> for AppState {
let actual_dy = op.start_height - target_height;
win.y = op.start_y + actual_dy;
win.height = target_height;
+ if win.tiling_mode == TilingMode::SidePanel {
+ win.hint_min_width = win.width + bw * 2;
+ }
}
}
}
@@ -2490,7 +2523,15 @@ fn execute_action(state: &mut AppState, seat_id: u64, action: &crate::types::Act
let mut needs_render = false;
if let Some(win) = state.wm.get_window_mut(wid) {
if win.tiling_mode != TilingMode::Fullscreen && win.tiling_mode != TilingMode::Popup {
- if win.tiling_mode != TilingMode::Floating {
+ let is_right_resize_on_side_panel = win.tiling_mode == TilingMode::SidePanel
+ && matches!(
+ op_type,
+ PointerOpType::Resize
+ | PointerOpType::ResizeRight
+ | PointerOpType::ResizeTopRight
+ | PointerOpType::ResizeBottomRight
+ );
+ if !is_right_resize_on_side_panel && win.tiling_mode != TilingMode::Floating {
win.tiling_mode = TilingMode::Floating;
needs_render = true;
}
@@ -3730,6 +3771,16 @@ impl Dispatch<wl_pointer::WlPointer, ()> for AppState {
Self::update_cursor_shape_for_surface(state, proxy);
+ let is_decoration = state.window_proxies.iter().any(|(_, wp)| {
+ wp.decoration.as_ref().map_or(false, |d| &d.surface == &surface)
+ || wp.dec_left.as_ref().map_or(false, |d| &d.surface == &surface)
+ || wp.dec_right.as_ref().map_or(false, |d| &d.surface == &surface)
+ || wp.dec_bottom.as_ref().map_or(false, |d| &d.surface == &surface)
+ });
+ if is_decoration {
+ state.wm.needs_render = true;
+ }
+
if state.wm.expose_active {
let current_surface = &surface;
let matched_window = state.window_proxies.iter().find_map(|(id, proxy)| {
@@ -3787,6 +3838,7 @@ impl Dispatch<wl_pointer::WlPointer, ()> for AppState {
eprintln!("[pointer] leave");
state.pointer_hovered_surface = None;
Self::update_cursor_shape_for_surface(state, proxy);
+ state.wm.needs_render = true;
}
wl_pointer::Event::Motion { surface_x, surface_y, .. } => {
state.last_pointer_surface_x = surface_x;
@@ -3794,6 +3846,18 @@ impl Dispatch<wl_pointer::WlPointer, ()> for AppState {
Self::update_cursor_shape_for_surface(state, proxy);
+ if let Some(ref current_surface) = state.pointer_hovered_surface {
+ let is_decoration = state.window_proxies.iter().any(|(_, wp)| {
+ wp.decoration.as_ref().map_or(false, |d| &d.surface == current_surface)
+ || wp.dec_left.as_ref().map_or(false, |d| &d.surface == current_surface)
+ || wp.dec_right.as_ref().map_or(false, |d| &d.surface == current_surface)
+ || wp.dec_bottom.as_ref().map_or(false, |d| &d.surface == current_surface)
+ });
+ if is_decoration {
+ state.wm.needs_render = true;
+ }
+ }
+
if let Some(pending) = state.pending_border_drag.clone() {
let dx = surface_x - pending.start_surface_x;
let dy = surface_y - pending.start_surface_y;
@@ -3806,7 +3870,15 @@ impl Dispatch<wl_pointer::WlPointer, ()> for AppState {
let mut needs_render = false;
if let Some(win) = state.wm.get_window_mut(pending.window_id) {
if win.tiling_mode != TilingMode::Fullscreen && win.tiling_mode != TilingMode::Popup {
- if win.tiling_mode != TilingMode::Floating {
+ let is_right_resize_on_side_panel = win.tiling_mode == TilingMode::SidePanel
+ && matches!(
+ pending.op_type,
+ PointerOpType::Resize
+ | PointerOpType::ResizeRight
+ | PointerOpType::ResizeTopRight
+ | PointerOpType::ResizeBottomRight
+ );
+ if !is_right_resize_on_side_panel && win.tiling_mode != TilingMode::Floating {
win.tiling_mode = TilingMode::Floating;
needs_render = true;
}
diff --git a/src/wm.rs b/src/wm.rs
index 1908264..3b1fa97 100644
--- a/src/wm.rs
+++ b/src/wm.rs
@@ -491,10 +491,12 @@ fn compute_tiling(
});
let shift_x = if let Some(panel_win) = side_panel_win {
- if panel_win.hint_min_width > 32 {
+ if wm.layout.side_panel_behavior == "above" {
+ 0
+ } else if panel_win.hint_min_width > 32 {
panel_win.hint_min_width
} else {
- 360
+ wm.layout.side_panel_width
}
} else {
0
@@ -517,7 +519,7 @@ fn compute_tiling(
let target_w = if win.hint_min_width > 32 {
win.hint_min_width
} else {
- 360
+ wm.layout.side_panel_width
};
let bw = wm.layout.cascade_border_width;
let dec_h = std::cmp::max(bw, 16);