Wayland compositor (wlroots)
git clone https://git.lucas.co/cce-compositor.git
Fix Trackmania flickering by improving wine window detection and enforcing tiling bounds for non-floating/non-popup windows
src/server/window.rs | 39 +++++++++++++++++++++++++++------------
src/server/xwayland_window.rs | 25 ++++++++-----------------
2 files changed, 35 insertions(+), 29 deletions(-)
diff --git a/src/server/window.rs b/src/server/window.rs
index d29b545..8281847 100644
--- a/src/server/window.rs
+++ b/src/server/window.rs
@@ -241,6 +241,31 @@ pub struct Window {
}
impl Window {
+ pub unsafe fn is_wine(&self) -> bool {
+ match self.impl_type {
+ WindowImpl::Xwayland(xwindow) => {
+ if xwindow.is_null() {
+ return false;
+ }
+ let class_ptr = (*(*xwindow).xsurface).class;
+ let class = if class_ptr.is_null() { "" } else { std::ffi::CStr::from_ptr(class_ptr).to_str().unwrap_or("") };
+ let title_ptr = (*(*xwindow).xsurface).title;
+ let title = if title_ptr.is_null() { "" } else { std::ffi::CStr::from_ptr(title_ptr).to_str().unwrap_or("") };
+
+ let class_lower = class.to_lowercase();
+ let title_lower = title.to_lowercase();
+ class_lower.contains("steam_proton")
+ || class_lower.contains("steam_app")
+ || class_lower.contains("wine")
+ || class_lower.contains("upc.exe")
+ || class_lower.contains("trackmania")
+ || title_lower.contains("ubisoft")
+ || title_lower.contains("trackmania")
+ }
+ _ => false,
+ }
+ }
+
pub unsafe fn create(impl_type: WindowImpl, server: *mut Server) -> Result<*mut Self, &'static str> {
let hidden_tree = (*server).scene.hidden_tree;
let tree = ffi::wlr_scene_tree_create(hidden_tree);
@@ -1230,13 +1255,8 @@ impl Window {
if !xwindow.is_null() {
let mut w = (*(*xwindow).xsurface).width as u32;
let mut h = (*(*xwindow).xsurface).height as u32;
- let class_ptr = (*(*xwindow).xsurface).class;
- let class = if class_ptr.is_null() { "" } else { std::ffi::CStr::from_ptr(class_ptr).to_str().unwrap_or("") };
- let title_ptr = (*(*xwindow).xsurface).title;
- let title = if title_ptr.is_null() { "" } else { std::ffi::CStr::from_ptr(title_ptr).to_str().unwrap_or("") };
- let is_wine = class.contains("steam_proton") || class.contains("wine") || class.contains("upc.exe") || title.contains("Ubisoft");
let has_parent = !(*(*xwindow).xsurface).parent.is_null();
- if is_wine && !has_parent {
+ if self.is_wine() && !has_parent {
w = w.saturating_sub(32);
h = h.saturating_sub(32);
}
@@ -1515,13 +1535,8 @@ impl Window {
WindowImpl::Xwayland(xwindow) => {
if !xwindow.is_null() {
if !(*xwindow).surface_tree.is_null() {
- let class_ptr = (*(*xwindow).xsurface).class;
- let class = if class_ptr.is_null() { "" } else { std::ffi::CStr::from_ptr(class_ptr).to_str().unwrap_or("") };
- let title_ptr = (*(*xwindow).xsurface).title;
- let title = if title_ptr.is_null() { "" } else { std::ffi::CStr::from_ptr(title_ptr).to_str().unwrap_or("") };
- let is_wine = class.contains("steam_proton") || class.contains("wine") || class.contains("upc.exe") || title.contains("Ubisoft");
let has_parent = !(*(*xwindow).xsurface).parent.is_null();
- if is_wine && !has_parent {
+ if self.is_wine() && !has_parent {
ffi::wlr_scene_node_set_position((*xwindow).surface_tree as *mut ffi::wlr_scene_node, -16, -16);
} else {
ffi::wlr_scene_node_set_position((*xwindow).surface_tree as *mut ffi::wlr_scene_node, 0, 0);
diff --git a/src/server/xwayland_window.rs b/src/server/xwayland_window.rs
index b95bc09..87d6174 100644
--- a/src/server/xwayland_window.rs
+++ b/src/server/xwayland_window.rs
@@ -169,14 +169,9 @@ impl XwaylandWindow {
let mut phys_x = ((*window).box_geom.x as f32 * scale).round() as i16;
let mut phys_y = ((*window).box_geom.y as f32 * scale).round() as i16;
- let class_ptr = (*self.xsurface).class;
- let class = if class_ptr.is_null() { "" } else { std::ffi::CStr::from_ptr(class_ptr).to_str().unwrap_or("") };
- let title_ptr = (*self.xsurface).title;
- let title = if title_ptr.is_null() { "" } else { std::ffi::CStr::from_ptr(title_ptr).to_str().unwrap_or("") };
- let is_wine = class.contains("steam_proton") || class.contains("wine") || class.contains("upc.exe") || title.contains("Ubisoft");
let has_parent = !(*self.xsurface).parent.is_null();
- if is_wine && !has_parent {
+ if (*window).is_wine() && !has_parent {
if scheduled.width.is_some() {
phys_width += 32;
}
@@ -214,7 +209,7 @@ impl XwaylandWindow {
let mut width = scheduled.width.unwrap_or((*self.xsurface).width as u32);
let mut height = scheduled.height.unwrap_or((*self.xsurface).height as u32);
- if is_wine && !has_parent {
+ if (*window).is_wine() && !has_parent {
if scheduled.width.is_none() {
width = width.saturating_sub(32);
}
@@ -317,14 +312,9 @@ unsafe fn handle_map_impl(xwindow: *mut XwaylandWindow) {
}
(*xwindow).surface_tree = surface_tree;
- let class_ptr = (*(*xwindow).xsurface).class;
- let class = if class_ptr.is_null() { "" } else { std::ffi::CStr::from_ptr(class_ptr).to_str().unwrap_or("") };
- let title_ptr = (*(*xwindow).xsurface).title;
- let title = if title_ptr.is_null() { "" } else { std::ffi::CStr::from_ptr(title_ptr).to_str().unwrap_or("") };
- let is_wine = class.contains("steam_proton") || class.contains("wine") || class.contains("upc.exe") || title.contains("Ubisoft");
let has_parent = !(*(*xwindow).xsurface).parent.is_null();
- if is_wine && !has_parent {
+ if (*(*xwindow).window).is_wine() && !has_parent {
ffi::wlr_scene_node_set_position(surface_tree as *mut ffi::wlr_scene_node, -16, -16);
}
@@ -387,7 +377,8 @@ unsafe extern "C" fn handle_request_configure(listener: *mut ffi::wl_listener, d
let class = if class_ptr.is_null() { "" } else { std::ffi::CStr::from_ptr(class_ptr).to_str().unwrap_or("") };
let title_ptr = (*(*xwindow).xsurface).title;
let title = if title_ptr.is_null() { "" } else { std::ffi::CStr::from_ptr(title_ptr).to_str().unwrap_or("") };
- let is_wine = class.contains("steam_proton") || class.contains("wine") || class.contains("upc.exe") || title.contains("Ubisoft");
+ let window = (*xwindow).window;
+ let is_wine = (*window).is_wine();
let has_parent = !(*(*xwindow).xsurface).parent.is_null();
log::info!(
@@ -414,7 +405,6 @@ unsafe extern "C" fn handle_request_configure(listener: *mut ffi::wl_listener, d
let log_width = (*event).width as u32;
let log_height = (*event).height as u32;
- let window = (*xwindow).window;
(*window).box_geom.x = log_x;
(*window).box_geom.y = log_y;
(*window).box_geom.width = log_width as i32;
@@ -427,8 +417,9 @@ unsafe extern "C" fn handle_request_configure(listener: *mut ffi::wl_listener, d
return;
}
- let window = (*xwindow).window;
- let is_tiled = unsafe { (*window).wm_requested.tiled != 0 };
+ let is_tiled = unsafe {
+ (*window).wm_requested.tiled != 0 || !matches!((*window).tiling_mode, crate::tiling::TilingMode::Floating | crate::tiling::TilingMode::Popup)
+ };
let (phys_width, phys_height) = if is_tiled {
let log_w = (*window).configure_sent.width.unwrap_or((*window).box_geom.width as u32);