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

commitf19d43bd77f6020ec9e5e984ac3565e80bceab61
parent8b7c6137e4
authorLucas Galante <[email protected]>
date2026-05-28 20:06
Fix compositor crash on TTY switch by implementing inert resource stubs

 src/layer_shell.rs  | 13 +++++++++++--
 src/seat.rs         | 14 +++++++++++++-
 src/xkb_bindings.rs |  9 ++++++++-
 3 files changed, 32 insertions(+), 4 deletions(-)

diff --git a/src/layer_shell.rs b/src/layer_shell.rs
index f652fd8..3ee16de 100644
--- a/src/layer_shell.rs
+++ b/src/layer_shell.rs
@@ -556,7 +556,7 @@ impl LayerShellOutput {
         if !self.object.is_null() {
             ffi::wl_resource_set_implementation(
                 self.object,
-                std::ptr::null(),
+                &INERT_LAYER_SHELL_OUTPUT_INTERFACE as *const _ as *const _,
                 std::ptr::null_mut(),
                 None,
             );
@@ -773,6 +773,11 @@ static LAYER_SHELL_OUTPUT_INTERFACE: ffi::river_layer_shell_output_v1_interface
     set_default: Some(layer_shell_output_set_default),
 };
 
+static INERT_LAYER_SHELL_OUTPUT_INTERFACE: ffi::river_layer_shell_output_v1_interface = ffi::river_layer_shell_output_v1_interface {
+    destroy: Some(layer_shell_output_destroy),
+    set_default: None,
+};
+
 unsafe fn container_of_output(layer_shell_output: *mut LayerShellOutput) -> *mut Output {
     crate::container_of!(layer_shell_output, Output, layer_shell)
 }
@@ -817,7 +822,7 @@ impl LayerShellSeat {
         if !self.object.is_null() {
             ffi::wl_resource_set_implementation(
                 self.object,
-                std::ptr::null(),
+                &INERT_LAYER_SHELL_SEAT_INTERFACE as *const _ as *const _,
                 std::ptr::null_mut(),
                 None,
             );
@@ -860,3 +865,7 @@ unsafe extern "C" fn layer_shell_seat_destroy(client: *mut ffi::wl_client, resou
 static LAYER_SHELL_SEAT_INTERFACE: ffi::river_layer_shell_seat_v1_interface = ffi::river_layer_shell_seat_v1_interface {
     destroy: Some(layer_shell_seat_destroy),
 };
+
+static INERT_LAYER_SHELL_SEAT_INTERFACE: ffi::river_layer_shell_seat_v1_interface = ffi::river_layer_shell_seat_v1_interface {
+    destroy: Some(layer_shell_seat_destroy),
+};
diff --git a/src/seat.rs b/src/seat.rs
index 7f07f71..f0bec50 100644
--- a/src/seat.rs
+++ b/src/seat.rs
@@ -657,7 +657,7 @@ impl Seat {
             ffi::wl_resource_post_event(self.object, 0); // river_seat_v1.removed
             ffi::wl_resource_set_implementation(
                 self.object,
-                std::ptr::null(),
+                &INERT_SEAT_INTERFACE as *const _ as *const _,
                 std::ptr::null_mut(),
                 None,
             );
@@ -1061,6 +1061,18 @@ static SEAT_INTERFACE: ffi::river_seat_v1_interface = ffi::river_seat_v1_interfa
     pointer_warp: Some(seat_pointer_warp),
 };
 
+static INERT_SEAT_INTERFACE: ffi::river_seat_v1_interface = ffi::river_seat_v1_interface {
+    destroy: Some(seat_destroy),
+    focus_window: None,
+    focus_shell_surface: None,
+    clear_focus: None,
+    op_start_pointer: None,
+    op_end: None,
+    get_pointer_binding: None,
+    set_xcursor_theme: None,
+    pointer_warp: None,
+};
+
 unsafe extern "C" fn handle_destroy_resource(resource: *mut ffi::wl_resource) {
     let seat = ffi::wl_resource_get_user_data(resource) as *mut Seat;
     if !seat.is_null() {
diff --git a/src/xkb_bindings.rs b/src/xkb_bindings.rs
index a39689d..f15d81e 100644
--- a/src/xkb_bindings.rs
+++ b/src/xkb_bindings.rs
@@ -70,7 +70,7 @@ impl XkbBindingsSeat {
         if !self.object.is_null() {
             ffi::wl_resource_set_implementation(
                 self.object,
-                std::ptr::null(),
+                &INERT_XKB_BINDINGS_SEAT_INTERFACE as *const _ as *const _,
                 std::ptr::null_mut(),
                 None,
             );
@@ -130,6 +130,13 @@ static XKB_BINDINGS_SEAT_INTERFACE: ffi::river_xkb_bindings_seat_v1_interface =
     modifiers_watch: Some(bindings_seat_modifiers_watch),
 };
 
+static INERT_XKB_BINDINGS_SEAT_INTERFACE: ffi::river_xkb_bindings_seat_v1_interface = ffi::river_xkb_bindings_seat_v1_interface {
+    destroy: Some(bindings_seat_destroy),
+    ensure_next_key_eaten: None,
+    cancel_ensure_next_key_eaten: None,
+    modifiers_watch: None,
+};
+
 unsafe extern "C" fn bindings_seat_destroy(
     _client: *mut ffi::wl_client,
     resource: *mut ffi::wl_resource,