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

commit7c3cb6c9a8bc7d776238786069b9d0576cdd1a22
parent72670d464e
authorLucas Galante <[email protected]>
date2026-06-13 21:29
Improve XWayland window and window manager node handling in server

 src/window.rs          | 125 +++++++++++++++++++++++++++++++++++++-----
 src/window_manager.rs  |  25 +++++----
 src/wm_node.rs         |   6 ++-
 src/xdg_toplevel.rs    |   5 +-
 src/xwayland_window.rs | 144 +++++++++++++++++++++++++++++++++++++++++++------
 start-rust.sh          |  15 +++---
 6 files changed, 270 insertions(+), 50 deletions(-)

diff --git a/src/window.rs b/src/window.rs
index 35d28f0..ed34b0f 100644
--- a/src/window.rs
+++ b/src/window.rs
@@ -152,7 +152,7 @@ impl Configure {
             height: None,
             bounds: Dimensions { width: 0, height: 0 },
             activated: false,
-            ssd: false,
+            ssd: true,
             tiled: 0,
             capabilities: 0,
             maximized: false,
@@ -314,7 +314,7 @@ impl Window {
             wm_requested: WmRequestedState {
                 dimensions: None,
                 bounds: Dimensions { width: 0, height: 0 },
-                ssd: false,
+                ssd: true,
                 tiled: 0,
                 capabilities: 1 | 2 | 4 | 8,
                 resizing: false,
@@ -667,7 +667,7 @@ impl Window {
                 self.wm_requested = WmRequestedState {
                     dimensions: None,
                     bounds: Dimensions { width: 0, height: 0 },
-                    ssd: false,
+                    ssd: true,
                     tiled: 0,
                     capabilities: 1 | 2 | 4 | 8,
                     resizing: false,
@@ -713,6 +713,7 @@ impl Window {
                         return;
                     }
                     self.object = res;
+                    self.rendering_scheduled.resend_dimensions = true;
                     ffi::wl_resource_set_implementation(
                         res,
                         &WINDOW_INTERFACE as *const _ as *const _,
@@ -1041,9 +1042,20 @@ impl Window {
             }
             WindowImpl::Xwayland(xwindow) => {
                 if !xwindow.is_null() {
-                    let scale = crate::xwayland_window::XwaylandWindow::get_scale(xwindow);
-                    self.rendering_scheduled.width = ((*(*xwindow).xsurface).width as f32 / scale).round() as u32;
-                    self.rendering_scheduled.height = ((*(*xwindow).xsurface).height as f32 / scale).round() as u32;
+                    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 {
+                        w = w.saturating_sub(32);
+                        h = h.saturating_sub(32);
+                    }
+                    self.rendering_scheduled.width = w;
+                    self.rendering_scheduled.height = h;
                 }
             }
             WindowImpl::Destroying => {}
@@ -1137,6 +1149,17 @@ impl Window {
         let requested = &self.rendering_requested;
         let enabled = !requested.hidden && (matches!(self.state, WindowState::Mapped) || matches!(self.state, WindowState::Closing));
 
+        let title_ptr = match self.impl_type {
+            WindowImpl::Xwayland(xwindow) => {
+                if xwindow.is_null() { std::ptr::null() } else { (*(*xwindow).xsurface).title }
+            }
+            _ => std::ptr::null(),
+        };
+        let title = if title_ptr.is_null() { "" } else { std::ffi::CStr::from_ptr(title_ptr).to_str().unwrap_or("") };
+        if title.contains("Ubisoft") {
+            log::info!("render_finish for '{}' (addr={:p}): enabled={} hidden={} state={:?}", title, self as *const Window, enabled, requested.hidden, self.state);
+        }
+
         ffi::wlr_scene_node_set_enabled(self.tree as *mut ffi::wlr_scene_node, enabled);
         ffi::wlr_scene_node_set_enabled(self.popup_tree as *mut ffi::wlr_scene_node, enabled);
 
@@ -1203,6 +1226,18 @@ impl Window {
         ffi::wlr_scene_node_set_position(self.tree as *mut ffi::wlr_scene_node, self.box_geom.x, self.box_geom.y);
         ffi::wlr_scene_node_set_position(self.popup_tree as *mut ffi::wlr_scene_node, self.box_geom.x, self.box_geom.y);
 
+        let (geom_x, geom_y) = match self.impl_type {
+            WindowImpl::Toplevel(toplevel) => {
+                if toplevel.is_null() {
+                    (0, 0)
+                } else {
+                    ((*toplevel).geometry.x, (*toplevel).geometry.y)
+                }
+            }
+            _ => (0, 0),
+        };
+        ffi::wlr_scene_node_set_position(self.surfaces.tree as *mut ffi::wlr_scene_node, -geom_x, -geom_y);
+
         self.apply_surface_clip(&clip, &content_clip);
 
         for decorations in [&mut self.decorations_above as *mut ffi::wl_list, &mut self.decorations_below as *mut ffi::wl_list] {
@@ -1219,6 +1254,19 @@ impl Window {
         match self.impl_type {
             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 {
+                            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);
+                        }
+                    }
                     (*xwindow).configure();
                 }
             }
@@ -1315,18 +1363,45 @@ impl Window {
         let a_empty = (*a).width == 0 && (*a).height == 0;
         let b_empty = (*b).width == 0 && (*b).height == 0;
 
+        let layout_box = ffi::wlr_box {
+            x: 0,
+            y: 0,
+            width: self.box_geom.width,
+            height: self.box_geom.height,
+        };
+
         if !a_empty && !b_empty {
-            if !ffi::wlr_box_intersection(&mut surface_clip, a, b) {
+            let mut temp_clip = std::mem::zeroed::<ffi::wlr_box>();
+            if !ffi::wlr_box_intersection(&mut temp_clip, a, b) {
+                self.surfaces.set_enabled(false);
+                return;
+            }
+            if !ffi::wlr_box_intersection(&mut surface_clip, &temp_clip, &layout_box) {
                 self.surfaces.set_enabled(false);
                 return;
             }
         } else if !a_empty {
-            surface_clip = *a;
+            if !ffi::wlr_box_intersection(&mut surface_clip, a, &layout_box) {
+                self.surfaces.set_enabled(false);
+                return;
+            }
+        } else if !b_empty {
+            if !ffi::wlr_box_intersection(&mut surface_clip, b, &layout_box) {
+                self.surfaces.set_enabled(false);
+                return;
+            }
         } else {
-            surface_clip = *b;
+            surface_clip = layout_box;
         }
 
         self.surfaces.set_enabled(true);
+
+        let margin = 4;
+        surface_clip.x -= margin;
+        surface_clip.y -= margin;
+        surface_clip.width += 2 * margin;
+        surface_clip.height += 2 * margin;
+
         match self.impl_type {
             WindowImpl::Toplevel(toplevel) => {
                 if !toplevel.is_null() {
@@ -1334,6 +1409,26 @@ impl Window {
                     surface_clip.y += (*toplevel).geometry.y;
                 }
             }
+            WindowImpl::Xwayland(xwindow) => {
+                if !xwindow.is_null() {
+                    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("") };
+                    if title.contains("Ubisoft") {
+                        log::info!(
+                            "XWayland window clip check: title='{}' box_geom=({}, {}, {}, {}) xsurface=({}, {}, {}, {})",
+                            title,
+                            self.box_geom.x,
+                            self.box_geom.y,
+                            self.box_geom.width,
+                            self.box_geom.height,
+                            (*(*xwindow).xsurface).x,
+                            (*(*xwindow).xsurface).y,
+                            (*(*xwindow).xsurface).width,
+                            (*(*xwindow).xsurface).height,
+                        );
+                    }
+                }
+            }
             _ => {}
         }
 
@@ -1406,10 +1501,12 @@ unsafe extern "C" fn window_propose_dimensions(
         );
         return;
     }
-    (*window).wm_requested.dimensions = Some(Dimensions {
-        width: width as u32,
-        height: height as u32,
-    });
+    if (*window).get_parent().is_null() {
+        (*window).wm_requested.dimensions = Some(Dimensions {
+            width: width as u32,
+            height: height as u32,
+        });
+    }
 }
 
 unsafe extern "C" fn window_hide(client: *mut ffi::wl_client, resource: *mut ffi::wl_resource) {
@@ -1446,6 +1543,7 @@ unsafe extern "C" fn window_use_csd(client: *mut ffi::wl_client, resource: *mut
         return;
     }
     (*window).wm_requested.ssd = false;
+    (*server).wm.dirty_windowing();
 }
 
 unsafe extern "C" fn window_use_ssd(client: *mut ffi::wl_client, resource: *mut ffi::wl_resource) {
@@ -1458,6 +1556,7 @@ unsafe extern "C" fn window_use_ssd(client: *mut ffi::wl_client, resource: *mut
         return;
     }
     (*window).wm_requested.ssd = true;
+    (*server).wm.dirty_windowing();
 }
 
 unsafe extern "C" fn window_set_borders(
diff --git a/src/window_manager.rs b/src/window_manager.rs
index 3202913..e407465 100644
--- a/src/window_manager.rs
+++ b/src/window_manager.rs
@@ -420,17 +420,22 @@ impl WindowManager {
                 crate::wm_node::WmNodeType::Window(window) => {
                     (*window).render_finish();
                     if reorder {
-                        ffi::wlr_scene_node_reparent((*window).popup_tree as *mut _, (*self.server).scene.layers.popups);
-                        if rendered_fullscreen(window) {
-                            ffi::wlr_scene_node_reparent((*window).tree as *mut _, (*self.server).scene.layers.fullscreen);
-                            ffi::wlr_scene_node_raise_to_top((*window).tree as *mut _);
-                            found_fullscreen = true;
-                        } 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 _);
+                        if (*window).rendering_requested.hidden {
+                            ffi::wlr_scene_node_reparent((*window).tree as *mut _, (*self.server).scene.hidden_tree);
+                            ffi::wlr_scene_node_reparent((*window).popup_tree as *mut _, (*self.server).scene.hidden_tree);
                         } else {
-                            ffi::wlr_scene_node_reparent((*window).tree as *mut _, (*self.server).scene.layers.wm);
-                            ffi::wlr_scene_node_raise_to_top((*window).tree as *mut _);
+                            ffi::wlr_scene_node_reparent((*window).popup_tree as *mut _, (*self.server).scene.layers.popups);
+                            if rendered_fullscreen(window) {
+                                ffi::wlr_scene_node_reparent((*window).tree as *mut _, (*self.server).scene.layers.fullscreen);
+                                ffi::wlr_scene_node_raise_to_top((*window).tree as *mut _);
+                                found_fullscreen = true;
+                            } 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 {
+                                ffi::wlr_scene_node_reparent((*window).tree as *mut _, (*self.server).scene.layers.wm);
+                                ffi::wlr_scene_node_raise_to_top((*window).tree as *mut _);
+                            }
                         }
                     }
                 }
diff --git a/src/wm_node.rs b/src/wm_node.rs
index 4faa91e..d7af93d 100644
--- a/src/wm_node.rs
+++ b/src/wm_node.rs
@@ -115,8 +115,10 @@ unsafe extern "C" fn node_set_position(
     
     match (*node).get() {
         WmNodeType::Window(w) => {
-            (*w).rendering_requested.x = x;
-            (*w).rendering_requested.y = y;
+            if (*w).get_parent().is_null() {
+                (*w).rendering_requested.x = x;
+                (*w).rendering_requested.y = y;
+            }
         }
         WmNodeType::ShellSurface(s) => {
             (*s).rendering_requested.x = x;
diff --git a/src/xdg_toplevel.rs b/src/xdg_toplevel.rs
index de98fa6..222e6c3 100644
--- a/src/xdg_toplevel.rs
+++ b/src/xdg_toplevel.rs
@@ -403,7 +403,10 @@ unsafe extern "C" fn handle_commit(listener: *mut ffi::wl_listener, _data: *mut
     let window = (*toplevel).window;
     let base = ffi::river_wlr_xdg_toplevel_get_base((*toplevel).wlr_toplevel);
 
-    ffi::river_scene_node_enable_blur((*window).surfaces.tree as *mut ffi::wlr_scene_node, true);
+    ffi::river_scene_node_enable_blur(
+        (*window).surfaces.tree as *mut ffi::wlr_scene_node,
+        (*window).rendering_requested.blur,
+    );
 
     let capture_node = &mut (*(*window).capture_scene).tree as *mut ffi::wlr_scene_tree as *mut ffi::wlr_scene_node;
     let mut geom = std::mem::zeroed();
diff --git a/src/xwayland_window.rs b/src/xwayland_window.rs
index 8833ae9..7df3d6e 100644
--- a/src/xwayland_window.rs
+++ b/src/xwayland_window.rs
@@ -154,20 +154,38 @@ impl XwaylandWindow {
             scheduled.height = Some((*self.xsurface).height as u32);
         }
 
-        let phys_width = if let Some(w) = scheduled.width {
-            (w as f32 * scale).round() as u16
+        let mut phys_width = if let Some(w) = scheduled.width {
+            w as u16
         } else {
             (*self.xsurface).width
         };
 
-        let phys_height = if let Some(h) = scheduled.height {
-            (h as f32 * scale).round() as u16
+        let mut phys_height = if let Some(h) = scheduled.height {
+            h as u16
         } else {
             (*self.xsurface).height
         };
 
-        let phys_x = ((*window).box_geom.x as f32 * scale).round() as i16;
-        let phys_y = ((*window).box_geom.y as f32 * scale).round() as i16;
+        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 scheduled.width.is_some() {
+                phys_width += 32;
+            }
+            if scheduled.height.is_some() {
+                phys_height += 32;
+            }
+            phys_x -= (16.0 * scale).round() as i16;
+            phys_y -= (16.0 * scale).round() as i16;
+        }
 
         if phys_x != (*self.xsurface).x
             || phys_y != (*self.xsurface).y
@@ -193,8 +211,17 @@ impl XwaylandWindow {
             ffi::wlr_xwayland_surface_set_fullscreen(self.xsurface, scheduled.inform_fullscreen);
         }
 
-        let width = scheduled.width.unwrap_or(((*self.xsurface).width as f32 / scale).round() as u32);
-        let height = scheduled.height.unwrap_or(((*self.xsurface).height as f32 / scale).round() as u32);
+        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 scheduled.width.is_none() {
+                width = width.saturating_sub(32);
+            }
+            if scheduled.height.is_none() {
+                height = height.saturating_sub(32);
+            }
+        }
 
         (*window).configure_sent = (*window).configure_scheduled.clone();
         (*window).configure_sent.width = Some(width);
@@ -289,6 +316,18 @@ unsafe fn handle_map_impl(xwindow: *mut XwaylandWindow) {
         return;
     }
     (*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 {
+        ffi::wlr_scene_node_set_position(surface_tree as *mut ffi::wlr_scene_node, -16, -16);
+    }
+
     ffi::river_wlr_surface_set_data(surface, &mut (*(*xwindow).window).node as *mut crate::wm_node::WmNode as *mut _);
 
     let capture_tree = &mut (*(*(*xwindow).window).capture_scene).tree as *mut ffi::wlr_scene_tree;
@@ -343,19 +382,94 @@ unsafe extern "C" fn handle_request_configure(listener: *mut ffi::wl_listener, d
     }
 
     let scale = XwaylandWindow::get_scale(xwindow);
-    let phys_x = ((*(*xwindow).window).box_geom.x as f32 * scale).round() as i16;
-    let phys_y = ((*(*xwindow).window).box_geom.y as f32 * scale).round() as i16;
+
+    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();
+    log::info!(
+        "XWayland configure request: title='{}' class='{}' has_parent={} is_wine={} event=({}, {}, {}, {}) xsurface=({}, {}, {}, {}) scale={}",
+        title,
+        class,
+        has_parent,
+        is_wine,
+        (*event).x, (*event).y, (*event).width, (*event).height,
+        (*(*xwindow).xsurface).x, (*(*xwindow).xsurface).y, (*(*xwindow).xsurface).width, (*(*xwindow).xsurface).height,
+        scale
+    );
+
+    if has_parent {
+        ffi::wlr_xwayland_surface_configure(
+            (*xwindow).xsurface,
+            (*event).x,
+            (*event).y,
+            (*event).width,
+            (*event).height,
+        );
+        let log_x = ((*event).x as f32 / scale).round() as i32;
+        let log_y = ((*event).y as f32 / scale).round() as i32;
+        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;
+        (*window).box_geom.height = log_height as i32;
+        (*window).rendering_requested.x = log_x;
+        (*window).rendering_requested.y = log_y;
+        (*window).rendering_sent.width = log_width;
+        (*window).rendering_sent.height = log_height;
+        (*window).set_dimensions(log_width, log_height);
+        return;
+    }
+
+    let window = (*xwindow).window;
+    let is_tiled = unsafe { (*window).wm_requested.tiled != 0 };
+
+    let (phys_width, phys_height) = if is_tiled {
+        let log_w = (*window).configure_sent.width.unwrap_or((*window).box_geom.width as u32);
+        let log_h = (*window).configure_sent.height.unwrap_or((*window).box_geom.height as u32);
+        if log_w > 0 && log_h > 0 {
+            let mut w = log_w;
+            let mut h = log_h;
+            if is_wine && !has_parent {
+                w += 32;
+                h += 32;
+            }
+            (w as u16, h as u16)
+        } else {
+            ((*event).width, (*event).height)
+        }
+    } else {
+        ((*event).width, (*event).height)
+    };
+
+    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;
+
+    if is_wine && !has_parent {
+        phys_x -= (16.0 * scale).round() as i16;
+        phys_y -= (16.0 * scale).round() as i16;
+    }
 
     ffi::wlr_xwayland_surface_configure(
         (*xwindow).xsurface,
         phys_x,
         phys_y,
-        (*event).width,
-        (*event).height,
+        phys_width,
+        phys_height,
     );
-    let log_width = ((*event).width as f32 / scale).round() as u32;
-    let log_height = ((*event).height as f32 / scale).round() as u32;
-    (*(*xwindow).window).set_dimensions(log_width, log_height);
+    let mut log_width = phys_width as u32;
+    let mut log_height = phys_height as u32;
+    if is_wine && !has_parent {
+        log_width = log_width.saturating_sub(32);
+        log_height = log_height.saturating_sub(32);
+    }
+    (*window).set_dimensions(log_width, log_height);
 }
 
 unsafe extern "C" fn handle_set_override_redirect(listener: *mut ffi::wl_listener, _data: *mut std::ffi::c_void) {
diff --git a/start-rust.sh b/start-rust.sh
index 398ee3a..84bff38 100755
--- a/start-rust.sh
+++ b/start-rust.sh
@@ -29,17 +29,14 @@ ${DEBUG_FLAG}exec /home/lsgalante/.local/bin/cce-client 2>/tmp/cce-client-\${WAY
 LAUNCH_EOF
 chmod +x /tmp/cce-client-launch-rust.sh
  
-if [ "$LOGGING" = true ] || [ "$DEBUG" = true ]; then
-    echo "Starting cce-server with cce-client..."
-    echo "  Logs: /tmp/river-cce-client.log + /tmp/cce-client-\${WAYLAND_DISPLAY}.log"
-    if [ "$DEBUG" = true ]; then
-        echo "  Wayland debug logging enabled (WAYLAND_DEBUG=1)"
-    fi
-fi
- 
 # Resolve script directory to reference target/release/cce-server reliably
 SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
 if [ "$DEBUG" = true ]; then
     export WAYLAND_DEBUG=1
 fi
-exec "$SCRIPT_DIR/target/release/cce-server" -c /tmp/cce-client-launch-rust.sh 2>/tmp/river-cce-client.log
+
+if [ "$LOGGING" = true ] || [ "$DEBUG" = true ]; then
+    exec "$SCRIPT_DIR/target/release/cce-server" -c /tmp/cce-client-launch-rust.sh 2>/tmp/river-cce-client.log
+else
+    exec "$SCRIPT_DIR/target/release/cce-server" --log-level error -c /tmp/cce-client-launch-rust.sh 2>/dev/null
+fi