Wayland compositor (wlroots)
git clone https://git.lucas.co/cce-compositor.git
feat: add style.surface.cloud.position_default config key
src/server/config.rs | 38 ++++++++++++++++++++++++++++++++++++++
src/server/window_manager.rs | 25 +++++++++++++++++++++++--
2 files changed, 61 insertions(+), 2 deletions(-)
diff --git a/src/server/config.rs b/src/server/config.rs
index 4c4675b..f349cc8 100644
--- a/src/server/config.rs
+++ b/src/server/config.rs
@@ -54,6 +54,7 @@ pub struct Layout {
pub status_backdrop_blur_ignore_transparent: bool,
pub window_backdrop_blur_ignore_transparent: bool,
pub status_module_hide_mode_preview: i64,
+ pub cloud_position_default: Option<[i32; 2]>,
}
impl Default for Layout {
@@ -106,6 +107,7 @@ impl Default for Layout {
status_backdrop_blur_ignore_transparent: true,
window_backdrop_blur_ignore_transparent: true,
status_module_hide_mode_preview: 4,
+ cloud_position_default: None,
}
}
}
@@ -300,6 +302,8 @@ pub struct SurfaceConfig {
pub backplate_blur: f64,
#[serde(default = "default_backplate_corner_radius")]
pub backplate_corner_radius: i64,
+ #[serde(default = "default_cloud_position_default")]
+ pub cloud_position_default: Option<[i32; 2]>,
}
impl Default for SurfaceConfig {
@@ -317,11 +321,17 @@ impl Default for SurfaceConfig {
backplate_color: default_backplate_color(),
backplate_blur: default_backplate_blur(),
backplate_corner_radius: default_backplate_corner_radius(),
+ cloud_position_default: default_cloud_position_default(),
}
}
}
+fn default_cloud_position_default() -> Option<[i32; 2]> {
+ None
+}
+
fn default_desktop_gap_color() -> String {
+
"#000000".to_string()
}
@@ -816,6 +826,26 @@ fn get_child_arg_f64_opt(node: &kdl::KdlNode, child_name: &str) -> Option<f64> {
None
}
+fn get_child_arg_vec2i_opt(node: &kdl::KdlNode, child_name: &str) -> Option<[i32; 2]> {
+ if let Some(children) = node.children() {
+ for child in children.nodes() {
+ if child.name().value() == child_name {
+ let entries = child.entries();
+ if entries.len() >= 2 {
+ let has_tag = entries.first().and_then(|e| e.ty()).map_or(false, |t| t.value() == "vec2i");
+ if has_tag {
+ let x = entries[0].value().as_i64()? as i32;
+ let y = entries[1].value().as_i64()? as i32;
+ return Some([x, y]);
+ }
+ }
+ }
+ }
+ }
+ None
+}
+
+
fn get_child_arg_string_opt(node: &kdl::KdlNode, child_name: &str) -> Option<String> {
if let Some(children) = node.children() {
for child in children.nodes() {
@@ -1411,6 +1441,12 @@ fn parse_kdl_config(content: &str) -> Result<Config, String> {
}
}
}
+ if let Some(cloud_node) = surface_children.nodes().iter().find(|n| n.name().value() == "cloud") {
+ found_nested = true;
+ if let Some(pos) = get_child_arg_vec2i_opt(cloud_node, "position_default") {
+ surface.cloud_position_default = Some(pos);
+ }
+ }
}
}
}
@@ -1429,6 +1465,7 @@ fn parse_kdl_config(content: &str) -> Result<Config, String> {
surface.backplate_color = get_child_arg_string(node, "backplate_color", &default_backplate_color());
surface.backplate_blur = get_child_arg_f64(node, "backplate_blur", default_backplate_blur());
surface.backplate_corner_radius = get_child_arg_i64(node, "backplate_corner_radius", default_backplate_corner_radius());
+ surface.cloud_position_default = get_child_arg_vec2i_opt(node, "cloud_position_default");
}
}
@@ -1543,6 +1580,7 @@ pub fn parse_config(path: &str, state: &mut crate::window_manager::WindowManager
state.layout.status_backdrop_blur_ignore_transparent = config.layout.status_backdrop_blur_ignore_transparent;
state.layout.window_backdrop_blur_ignore_transparent = config.layout.window_backdrop_blur_ignore_transparent;
state.layout.status_module_hide_mode_preview = config.layout.status_module_hide_mode_preview;
+ state.layout.cloud_position_default = config.surface.cloud_position_default;
for (key, val) in &config.env {
let expanded = expand_env_vars(val);
diff --git a/src/server/window_manager.rs b/src/server/window_manager.rs
index bebfc1b..f1d26e5 100644
--- a/src/server/window_manager.rs
+++ b/src/server/window_manager.rs
@@ -1307,11 +1307,15 @@ fn get_closest_tag(x: f64, y: f64) -> i32 {
let dec_h = std::cmp::max(bw, 16);
for (sp_idx, &win_ptr) in overlay_windows.iter().enumerate() {
if sp_idx == 0 {
+ let app_id = (*win_ptr).get_app_id_string();
+ let is_cce_cloud = app_id.as_deref().map_or(false, |id| id.starts_with("cce-cloud"));
+
let mut sp_x = (*win_ptr).box_geom.x;
let mut sp_y = (*win_ptr).box_geom.y;
let mut sp_w = (*win_ptr).box_geom.width as i32;
let mut sp_h = (*win_ptr).box_geom.height as i32;
+
if sp_w == 0 || sp_h == 0 {
sp_w = if (*win_ptr).wm_scheduled.dimensions_hint.min_width > 32 {
std::cmp::max(self.layout.overlay_width, (*win_ptr).wm_scheduled.dimensions_hint.min_width as i32)
@@ -1331,12 +1335,21 @@ fn get_closest_tag(x: f64, y: f64) -> i32 {
(*win_ptr).box_geom.y = sp_y;
(*win_ptr).box_geom.width = sp_w;
(*win_ptr).box_geom.height = sp_h;
+ } else if is_cce_cloud {
+ if let Some(pos) = self.layout.cloud_position_default {
+ sp_x = usable_x + pos[0];
+ sp_y = usable_y + pos[1];
+ (*win_ptr).box_geom.x = sp_x;
+ (*win_ptr).box_geom.y = sp_y;
+ }
}
(*win_ptr).rendering_requested.x = sp_x;
(*win_ptr).rendering_requested.y = sp_y;
(*win_ptr).scale = 1.0;
+
+
let vx = self.desk_pan_x + (sp_x - phys_x) as f64 / self.desk_zoom;
let vy = self.desk_pan_y + (sp_y - phys_y) as f64 / self.desk_zoom;
(*win_ptr).virtual_x = vx;
@@ -1461,12 +1474,20 @@ fn get_closest_tag(x: f64, y: f64) -> i32 {
} else {
100
};
- let fx = usable_x + usable_w - fw - self.layout.gap_right;
- let fy = usable_y + self.layout.gap_top;
+ let app_id = (*win_ptr).get_app_id_string();
+ let is_cce_cloud = app_id.as_deref().map_or(false, |id| id.starts_with("cce-cloud"));
+
+ let (fx, fy) = if is_cce_cloud && self.layout.cloud_position_default.is_some() {
+ let pos = self.layout.cloud_position_default.unwrap();
+ (usable_x + pos[0], usable_y + pos[1])
+ } else {
+ (usable_x + usable_w - fw - self.layout.gap_right, usable_y + self.layout.gap_top)
+ };
(*win_ptr).rendering_requested.x = fx;
(*win_ptr).rendering_requested.y = fy;
(*win_ptr).scale = 1.0;
+
(*win_ptr).wm_requested.dimensions = Some(crate::window::Dimensions {
width: fw as u32,
height: fh as u32,