Wayland compositor (wlroots)
git clone https://git.lucas.co/cce-compositor.git
Rename desktop_background to desktop_background_color
src/server/config.rs | 22 ++---
src/server/output.rs | 2 +-
src/server/window.rs | 182 +++++++++++++++++++++++++++++++++++----
src/server/window_manager.rs | 4 +-
src/server/wlroots_log_wrapper.c | 27 +++++-
wrapper.h | 2 +
6 files changed, 202 insertions(+), 37 deletions(-)
diff --git a/src/server/config.rs b/src/server/config.rs
index be37f70..a3f7d2e 100644
--- a/src/server/config.rs
+++ b/src/server/config.rs
@@ -37,7 +37,7 @@ pub struct Layout {
pub overlay_position: String,
pub overlay_border_gap: i32,
pub status_normal_color: String,
- pub desktop_background: String,
+ pub desktop_background_color: String,
pub transparency_opacity: f32,
pub window_opacity: bool,
pub desktop_grid_color: [f32; 4],
@@ -78,7 +78,7 @@ impl Default for Layout {
overlay_position: "left".to_string(),
overlay_border_gap: 0,
status_normal_color: "#ccccd8".to_string(),
- desktop_background: "#000000".to_string(),
+ desktop_background_color: "#000000".to_string(),
transparency_opacity: 0.9,
window_opacity: true,
desktop_grid_color: [1.0, 1.0, 1.0, 0.05],
@@ -239,8 +239,8 @@ pub struct TransparencyConfig {
#[derive(Debug, Deserialize, Clone)]
pub struct SurfacesConfig {
- #[serde(default = "default_desktop_background")]
- pub desktop_background: String,
+ #[serde(default = "default_desktop_background_color")]
+ pub desktop_background_color: String,
#[serde(default = "default_desktop_grid_color")]
pub desktop_grid_color: String,
#[serde(default = "default_desktop_grid_scale")]
@@ -252,7 +252,7 @@ pub struct SurfacesConfig {
impl Default for SurfacesConfig {
fn default() -> Self {
Self {
- desktop_background: default_desktop_background(),
+ desktop_background_color: default_desktop_background_color(),
desktop_grid_color: default_desktop_grid_color(),
desktop_grid_scale: default_desktop_grid_scale(),
desktop_line_width: default_desktop_line_width(),
@@ -260,7 +260,7 @@ impl Default for SurfacesConfig {
}
}
-fn default_desktop_background() -> String {
+fn default_desktop_background_color() -> String {
"#000000".to_string()
}
@@ -1077,9 +1077,9 @@ fn parse_kdl_config(content: &str) -> Result<Config, String> {
for entry in desktop_node.entries() {
if let Some(id) = entry.name() {
match id.value() {
- "background" => {
+ "background_color" => {
if let Some(val) = entry.value().as_string() {
- surfaces.desktop_background = val.to_string();
+ surfaces.desktop_background_color = val.to_string();
}
}
"grid_color" => {
@@ -1103,7 +1103,7 @@ fn parse_kdl_config(content: &str) -> Result<Config, String> {
}
if !found_nested {
if let Some(node) = doc.nodes().iter().find(|n| n.name().value() == "surfaces") {
- surfaces.desktop_background = get_child_arg_string(node, "desktop_background", &default_desktop_background());
+ surfaces.desktop_background_color = get_child_arg_string(node, "desktop_background_color", &default_desktop_background_color());
surfaces.desktop_grid_color = get_child_arg_string(node, "desktop_grid_color", &default_desktop_grid_color());
surfaces.desktop_grid_scale = get_child_arg_i64(node, "desktop_grid_scale", default_desktop_grid_scale());
surfaces.desktop_line_width = get_child_arg_i64(node, "desktop_line_width", default_desktop_line_width());
@@ -1157,8 +1157,8 @@ pub fn parse_config(path: &str, state: &mut crate::window_manager::WindowManager
state.layout.border_b = 0x3E3E3E3E;
state.layout.border_a = 0xFFFFFFFF;
- let desktop_background_str = config.surfaces.desktop_background.clone();
- state.layout.desktop_background = desktop_background_str.clone();
+ let desktop_background_str = config.surfaces.desktop_background_color.clone();
+ state.layout.desktop_background_color = desktop_background_str.clone();
let background_color_val = parse_hex_color(&desktop_background_str);
state.layout.background_r = ((background_color_val >> 16) & 0xFF) * 0x01010101;
diff --git a/src/server/output.rs b/src/server/output.rs
index a08ae7f..ec1960f 100644
--- a/src/server/output.rs
+++ b/src/server/output.rs
@@ -460,7 +460,7 @@ impl Output {
let wm = &(*self.server).wm;
for &window in wm.windows.iter() {
if !window.is_null() && (*window).scale != 1.0 {
- (*window).render_finish();
+ (*window).scale_only_render_finish();
}
}
diff --git a/src/server/window.rs b/src/server/window.rs
index 3772eba..2c01ef5 100644
--- a/src/server/window.rs
+++ b/src/server/window.rs
@@ -843,9 +843,8 @@ impl Window {
if self.wm_sent.dimensions_hint != hint {
if matches!(self.tiling_mode, crate::tiling::TilingMode::Floating | crate::tiling::TilingMode::Popup | crate::tiling::TilingMode::Status) {
(*self.server).wm.dirty_windowing();
- } else {
- self.wm_sent.dimensions_hint = hint;
}
+ self.wm_sent.dimensions_hint = hint;
}
}
@@ -864,6 +863,7 @@ impl Window {
self.wm_scheduled.decoration_hint = hint;
if hint != self.wm_sent.decoration_hint {
(*self.server).wm.dirty_windowing();
+ self.wm_sent.decoration_hint = hint;
}
}
@@ -1549,24 +1549,9 @@ impl Window {
0
};
- unsafe extern "C" fn set_corner_radius_iterator(
- buffer: *mut ffi::wlr_scene_buffer,
- _sx: i32,
- _sy: i32,
- user_data: *mut std::ffi::c_void,
- ) {
- let radius = *(user_data as *const i32);
- ffi::wlr_scene_buffer_set_corner_radius(
- buffer,
- radius,
- ffi::corner_location_CORNER_LOCATION_ALL,
- );
- }
-
- ffi::wlr_scene_node_for_each_buffer(
+ ffi::river_scene_node_set_corner_radius(
self.surfaces.tree as *mut ffi::wlr_scene_node,
- Some(set_corner_radius_iterator),
- &radius as *const i32 as *mut std::ffi::c_void,
+ radius,
);
struct ScaleData {
@@ -1749,6 +1734,94 @@ impl Window {
}
}
+ pub unsafe fn scale_only_render_finish(&mut self) {
+ if self.scale == 1.0 {
+ return;
+ }
+
+ struct ScaleData {
+ scale: f64,
+ ancestor: *mut ffi::wlr_scene_node,
+ }
+
+ unsafe extern "C" fn set_expose_scale_iterator(
+ buffer: *mut ffi::wlr_scene_buffer,
+ sx: i32,
+ sy: i32,
+ user_data: *mut std::ffi::c_void,
+ ) {
+ let data = &*(user_data as *const ScaleData);
+ let node = buffer as *mut ffi::wlr_scene_node;
+
+ let surface = ffi::river_scene_node_get_surface(node);
+ if !surface.is_null() {
+ let w = ffi::river_wlr_surface_get_width(surface);
+ let h = ffi::river_wlr_surface_get_height(surface);
+ if data.scale == 1.0 {
+ ffi::river_scene_buffer_set_dest_size_if_changed(buffer, w, h);
+ ffi::river_scene_node_set_position_if_changed(node, 0, 0);
+ } else {
+ let dest_w = (w as f64 * data.scale) as i32;
+ let dest_h = (h as f64 * data.scale) as i32;
+ ffi::river_scene_buffer_set_dest_size_if_changed(buffer, dest_w, dest_h);
+
+ let (px, py) = get_parent_position_relative_to(node, data.ancestor);
+ let dest_x = (px as f64 * (data.scale - 1.0)) as i32;
+ let dest_y = (py as f64 * (data.scale - 1.0)) as i32;
+ ffi::river_scene_node_set_position_if_changed(node, dest_x, dest_y);
+ }
+ } else if data.scale == 1.0 {
+ ffi::river_scene_buffer_set_dest_size_if_changed(buffer, 0, 0);
+ ffi::river_scene_node_set_position_if_changed(node, sx, sy);
+ } else {
+ let w = ffi::river_scene_buffer_get_width(buffer);
+ let h = ffi::river_scene_buffer_get_height(buffer);
+ let dest_w = (w as f64 * data.scale) as i32;
+ let dest_h = (h as f64 * data.scale) as i32;
+ ffi::river_scene_buffer_set_dest_size_if_changed(buffer, dest_w, dest_h);
+
+ let (px, py) = get_parent_position_relative_to(node, data.ancestor);
+ let dest_x = (px as f64 * (data.scale - 1.0)) as i32;
+ let dest_y = (py as f64 * (data.scale - 1.0)) as i32;
+ ffi::river_scene_node_set_position_if_changed(node, dest_x, dest_y);
+ }
+ }
+
+ let scale_data_surfaces = ScaleData { scale: self.scale, ancestor: self.surfaces.tree as *mut ffi::wlr_scene_node };
+ ffi::wlr_scene_node_for_each_buffer(
+ self.surfaces.tree as *mut ffi::wlr_scene_node,
+ Some(set_expose_scale_iterator),
+ &scale_data_surfaces as *const ScaleData as *mut std::ffi::c_void,
+ );
+
+ if self.surfaces.saved {
+ let scale_data_saved = ScaleData { scale: self.scale, ancestor: self.surfaces.saved_tree as *mut ffi::wlr_scene_node };
+ ffi::wlr_scene_node_for_each_buffer(
+ self.surfaces.saved_tree as *mut ffi::wlr_scene_node,
+ Some(set_expose_scale_iterator),
+ &scale_data_saved as *const ScaleData as *mut std::ffi::c_void,
+ );
+ }
+
+ let scale_data_popup = ScaleData { scale: self.scale, ancestor: self.popup_tree as *mut ffi::wlr_scene_node };
+ ffi::wlr_scene_node_for_each_buffer(
+ self.popup_tree as *mut ffi::wlr_scene_node,
+ Some(set_expose_scale_iterator),
+ &scale_data_popup as *const ScaleData as *mut std::ffi::c_void,
+ );
+
+ for decorations in [&mut self.decorations_above as *mut ffi::wl_list, &mut self.decorations_below as *mut ffi::wl_list] {
+ let list_head = decorations as *mut WlList;
+ let mut curr = (*list_head).next;
+ while curr != list_head {
+ let next = (*curr).next;
+ let dec = crate::container_of!(curr, Decoration, link);
+ (*dec).scale_only_render_finish();
+ curr = next;
+ }
+ }
+ }
+
pub unsafe fn draw_borders(&mut self) {
let requested = &self.rendering_requested;
@@ -2746,6 +2819,77 @@ impl Decoration {
ffi::wlr_scene_subsurface_tree_set_clip(self.surfaces.tree as *mut ffi::wlr_scene_node, std::ptr::null());
}
}
+
+ pub unsafe fn scale_only_render_finish(&mut self) {
+ let scale = (*self.window).scale;
+ if scale == 1.0 {
+ return;
+ }
+
+ struct ScaleData {
+ scale: f64,
+ ancestor: *mut ffi::wlr_scene_node,
+ }
+
+ unsafe extern "C" fn set_expose_scale_iterator(
+ buffer: *mut ffi::wlr_scene_buffer,
+ sx: i32,
+ sy: i32,
+ user_data: *mut std::ffi::c_void,
+ ) {
+ let data = &*(user_data as *const ScaleData);
+ let node = buffer as *mut ffi::wlr_scene_node;
+
+ let surface = ffi::river_scene_node_get_surface(node);
+ if !surface.is_null() {
+ let w = ffi::river_wlr_surface_get_width(surface);
+ let h = ffi::river_wlr_surface_get_height(surface);
+ if data.scale == 1.0 {
+ ffi::river_scene_buffer_set_dest_size_if_changed(buffer, w, h);
+ ffi::river_scene_node_set_position_if_changed(node, 0, 0);
+ } else {
+ let dest_w = (w as f64 * data.scale) as i32;
+ let dest_h = (h as f64 * data.scale) as i32;
+ ffi::river_scene_buffer_set_dest_size_if_changed(buffer, dest_w, dest_h);
+
+ let (px, py) = get_parent_position_relative_to(node, data.ancestor);
+ let dest_x = (px as f64 * (data.scale - 1.0)) as i32;
+ let dest_y = (py as f64 * (data.scale - 1.0)) as i32;
+ ffi::river_scene_node_set_position_if_changed(node, dest_x, dest_y);
+ }
+ } else if data.scale == 1.0 {
+ ffi::river_scene_buffer_set_dest_size_if_changed(buffer, 0, 0);
+ ffi::river_scene_node_set_position_if_changed(node, sx, sy);
+ } else {
+ let w = ffi::river_scene_buffer_get_width(buffer);
+ let h = ffi::river_scene_buffer_get_height(buffer);
+ let dest_w = (w as f64 * data.scale) as i32;
+ let dest_h = (h as f64 * data.scale) as i32;
+ ffi::river_scene_buffer_set_dest_size_if_changed(buffer, dest_w, dest_h);
+
+ let (px, py) = get_parent_position_relative_to(node, data.ancestor);
+ let dest_x = (px as f64 * (data.scale - 1.0)) as i32;
+ let dest_y = (py as f64 * (data.scale - 1.0)) as i32;
+ ffi::river_scene_node_set_position_if_changed(node, dest_x, dest_y);
+ }
+ }
+
+ let scale_data = ScaleData { scale, ancestor: self.surfaces.tree as *mut ffi::wlr_scene_node };
+ ffi::wlr_scene_node_for_each_buffer(
+ self.surfaces.tree as *mut ffi::wlr_scene_node,
+ Some(set_expose_scale_iterator),
+ &scale_data as *const ScaleData as *mut std::ffi::c_void,
+ );
+
+ if self.surfaces.saved {
+ let scale_data_saved = ScaleData { scale, ancestor: self.surfaces.saved_tree as *mut ffi::wlr_scene_node };
+ ffi::wlr_scene_node_for_each_buffer(
+ self.surfaces.saved_tree as *mut ffi::wlr_scene_node,
+ Some(set_expose_scale_iterator),
+ &scale_data_saved as *const ScaleData as *mut std::ffi::c_void,
+ );
+ }
+ }
}
pub unsafe fn decoration_from_wlr_surface(surface: *mut ffi::wlr_surface) -> *mut Decoration {
diff --git a/src/server/window_manager.rs b/src/server/window_manager.rs
index 4fd2a72..0651c18 100644
--- a/src/server/window_manager.rs
+++ b/src/server/window_manager.rs
@@ -2268,8 +2268,8 @@ fn get_closest_tag(x: f64, y: f64) -> i32 {
let key = parts[1];
let val = parts[2];
match key {
- "desktop_background" => {
- self.layout.desktop_background = val.to_string();
+ "desktop_background_color" => {
+ self.layout.desktop_background_color = val.to_string();
let parsed_color = crate::config::parse_hex_color(val);
self.layout.background_r = ((parsed_color >> 16) & 0xFF) * 0x01010101;
self.layout.background_g = ((parsed_color >> 8) & 0xFF) * 0x01010101;
diff --git a/src/server/wlroots_log_wrapper.c b/src/server/wlroots_log_wrapper.c
index 6d7a13b..1cd1362 100644
--- a/src/server/wlroots_log_wrapper.c
+++ b/src/server/wlroots_log_wrapper.c
@@ -660,9 +660,13 @@ static void enable_blur_iterator(struct wlr_scene_buffer *buffer, int sx, int sy
return;
}
bool enabled = *(bool *)user_data;
- wlr_scene_buffer_set_backdrop_blur(buffer, enabled);
- wlr_scene_buffer_set_backdrop_blur_optimized(buffer, enabled);
- wlr_scene_buffer_set_backdrop_blur_ignore_transparent(buffer, enabled);
+ if (buffer->backdrop_blur != enabled ||
+ buffer->backdrop_blur_optimized != enabled ||
+ buffer->backdrop_blur_ignore_transparent != enabled) {
+ wlr_scene_buffer_set_backdrop_blur(buffer, enabled);
+ wlr_scene_buffer_set_backdrop_blur_optimized(buffer, enabled);
+ wlr_scene_buffer_set_backdrop_blur_ignore_transparent(buffer, enabled);
+ }
}
void river_scene_node_enable_blur(struct wlr_scene_node *node, bool enabled) {
@@ -673,13 +677,28 @@ static void set_opacity_iterator(struct wlr_scene_buffer *buffer, int sx, int sy
(void)sx;
(void)sy;
float opacity = *(float *)user_data;
- wlr_scene_buffer_set_opacity(buffer, opacity);
+ if (buffer->opacity != opacity) {
+ wlr_scene_buffer_set_opacity(buffer, opacity);
+ }
}
void river_scene_node_set_opacity(struct wlr_scene_node *node, float opacity) {
wlr_scene_node_for_each_buffer(node, set_opacity_iterator, &opacity);
}
+static void set_corner_radius_iterator(struct wlr_scene_buffer *buffer, int sx, int sy, void *user_data) {
+ (void)sx;
+ (void)sy;
+ int radius = *(int *)user_data;
+ if (buffer->corner_radius != radius || buffer->corners != CORNER_LOCATION_ALL) {
+ wlr_scene_buffer_set_corner_radius(buffer, radius, CORNER_LOCATION_ALL);
+ }
+}
+
+void river_scene_node_set_corner_radius(struct wlr_scene_node *node, int radius) {
+ wlr_scene_node_for_each_buffer(node, set_corner_radius_iterator, &radius);
+}
+
void river_scene_buffer_set_dest_size_if_changed(struct wlr_scene_buffer *scene_buffer, int width, int height) {
if (scene_buffer->dst_width != width || scene_buffer->dst_height != height) {
wlr_scene_buffer_set_dest_size(scene_buffer, width, height);
diff --git a/wrapper.h b/wrapper.h
index 715b85f..eb573c3 100644
--- a/wrapper.h
+++ b/wrapper.h
@@ -261,6 +261,8 @@ void river_scene_node_enable_blur(struct wlr_scene_node *node, bool enabled);
void river_scene_node_set_opacity(struct wlr_scene_node *node, float opacity);
+void river_scene_node_set_corner_radius(struct wlr_scene_node *node, int radius);
+
void river_scene_buffer_set_dest_size_if_changed(struct wlr_scene_buffer *scene_buffer, int width, int height);
int river_scene_buffer_get_width(struct wlr_scene_buffer *scene_buffer);
int river_scene_buffer_get_height(struct wlr_scene_buffer *scene_buffer);