diff --git a/src/wayland/shell/legacy/mod.rs b/src/wayland/shell/legacy/mod.rs index d7d098a..031280d 100644 --- a/src/wayland/shell/legacy/mod.rs +++ b/src/wayland/shell/legacy/mod.rs @@ -1,3 +1 @@ - - -mod wl_handlers; \ No newline at end of file +mod wl_handlers; diff --git a/src/wayland/shell/legacy/wl_handlers.rs b/src/wayland/shell/legacy/wl_handlers.rs index e69de29..8b13789 100644 --- a/src/wayland/shell/legacy/wl_handlers.rs +++ b/src/wayland/shell/legacy/wl_handlers.rs @@ -0,0 +1 @@ + diff --git a/src/wayland/shell/xdg/xdg_handlers.rs b/src/wayland/shell/xdg/xdg_handlers.rs index 4681d6f..7858dac 100644 --- a/src/wayland/shell/xdg/xdg_handlers.rs +++ b/src/wayland/shell/xdg/xdg_handlers.rs @@ -224,6 +224,12 @@ fn destroy_surface( surface.set_user_data(::std::ptr::null_mut()); // take back ownership of the userdata let data = unsafe { Box::from_raw(ptr as *mut XdgSurfaceUserData) }; + if !data.0.is_alive() { + // the wl_surface is destroyed, this means the client is not + // trying to change the role but it's a cleanup (possibly a + // disconnecting client), ignore the protocol check. + return; + } implem .compositor_token .with_role_data::(&data.0, |rdata| { @@ -582,25 +588,27 @@ fn destroy_toplevel( toplevel.set_user_data(::std::ptr::null_mut()); // take back ownership of the userdata let data = *unsafe { Box::from_raw(ptr as *mut ShellSurfaceUserData) }; - implem - .compositor_token - .with_role_data::(&data.0, |data| { - data.pending_state = ShellSurfacePendingState::None; - data.configured = false; - }) - .expect("xdg_toplevel exists but surface has not shell_surface role?!"); + if !data.0.is_alive() { + // the wl_surface is destroyed, this means the client is not + // trying to change the role but it's a cleanup (possibly a + // disconnecting client), ignore the protocol check. + return; + } else { + implem + .compositor_token + .with_role_data::(&data.0, |data| { + data.pending_state = ShellSurfacePendingState::None; + data.configured = false; + }) + .expect("xdg_toplevel exists but surface has not shell_surface role?!"); + } // remove this surface from the known ones (as well as any leftover dead surface) implem .shell_state .lock() .unwrap() .known_toplevels - .retain(|other| { - other - .get_surface() - .map(|s| !s.equals(&data.0)) - .unwrap_or(false) - }); + .retain(|other| other.alive()); } /* @@ -688,23 +696,25 @@ fn destroy_popup( popup.set_user_data(::std::ptr::null_mut()); // take back ownership of the userdata let data = *unsafe { Box::from_raw(ptr as *mut ShellSurfaceUserData) }; - implem - .compositor_token - .with_role_data::(&data.0, |data| { - data.pending_state = ShellSurfacePendingState::None; - data.configured = false; - }) - .expect("xdg_popup exists but surface has not shell_surface role?!"); + if !data.0.is_alive() { + // the wl_surface is destroyed, this means the client is not + // trying to change the role but it's a cleanup (possibly a + // disconnecting client), ignore the protocol check. + return; + } else { + implem + .compositor_token + .with_role_data::(&data.0, |data| { + data.pending_state = ShellSurfacePendingState::None; + data.configured = false; + }) + .expect("xdg_popup exists but surface has not shell_surface role?!"); + } // remove this surface from the known ones (as well as any leftover dead surface) implem .shell_state .lock() .unwrap() .known_popups - .retain(|other| { - other - .get_surface() - .map(|s| !s.equals(&data.0)) - .unwrap_or(false) - }); + .retain(|other| other.alive()); } diff --git a/src/wayland/shell/xdg/zxdgv6_handlers.rs b/src/wayland/shell/xdg/zxdgv6_handlers.rs index f77de21..4a0d9dc 100644 --- a/src/wayland/shell/xdg/zxdgv6_handlers.rs +++ b/src/wayland/shell/xdg/zxdgv6_handlers.rs @@ -240,6 +240,12 @@ fn destroy_surface( surface.set_user_data(::std::ptr::null_mut()); // take back ownership of the userdata let data = unsafe { Box::from_raw(ptr as *mut XdgSurfaceUserData) }; + if !data.0.is_alive() { + // the wl_surface is destroyed, this means the client is not + // trying to change the role but it's a cleanup (possibly a + // disconnecting client), ignore the protocol check. + return; + } implem .compositor_token .with_role_data::(&data.0, |rdata| { @@ -603,25 +609,27 @@ fn destroy_toplevel( toplevel.set_user_data(::std::ptr::null_mut()); // take back ownership of the userdata let data = *unsafe { Box::from_raw(ptr as *mut ShellSurfaceUserData) }; - implem - .compositor_token - .with_role_data::(&data.0, |data| { - data.pending_state = ShellSurfacePendingState::None; - data.configured = false; - }) - .expect("xdg_toplevel exists but surface has not shell_surface role?!"); + if !data.0.is_alive() { + // the wl_surface is destroyed, this means the client is not + // trying to change the role but it's a cleanup (possibly a + // disconnecting client), ignore the protocol check. + return; + } else { + implem + .compositor_token + .with_role_data::(&data.0, |data| { + data.pending_state = ShellSurfacePendingState::None; + data.configured = false; + }) + .expect("xdg_toplevel exists but surface has not shell_surface role?!"); + } // remove this surface from the known ones (as well as any leftover dead surface) implem .shell_state .lock() .unwrap() .known_toplevels - .retain(|other| { - other - .get_surface() - .map(|s| !s.equals(&data.0)) - .unwrap_or(false) - }); + .retain(|other| other.alive()); } /* @@ -709,25 +717,27 @@ fn destroy_popup( popup.set_user_data(::std::ptr::null_mut()); // take back ownership of the userdata let data = *unsafe { Box::from_raw(ptr as *mut ShellSurfaceUserData) }; - implem - .compositor_token - .with_role_data::(&data.0, |data| { - data.pending_state = ShellSurfacePendingState::None; - data.configured = false; - }) - .expect("xdg_popup exists but surface has not shell_surface role?!"); + if !data.0.is_alive() { + // the wl_surface is destroyed, this means the client is not + // trying to change the role but it's a cleanup (possibly a + // disconnecting client), ignore the protocol check. + return; + } else { + implem + .compositor_token + .with_role_data::(&data.0, |data| { + data.pending_state = ShellSurfacePendingState::None; + data.configured = false; + }) + .expect("xdg_popup exists but surface has not shell_surface role?!"); + } // remove this surface from the known ones (as well as any leftover dead surface) implem .shell_state .lock() .unwrap() .known_popups - .retain(|other| { - other - .get_surface() - .map(|s| !s.equals(&data.0)) - .unwrap_or(false) - }); + .retain(|other| other.alive()); } fn zxdg_edges_to_xdg(e: zxdg_toplevel_v6::ResizeEdge) -> xdg_toplevel::ResizeEdge {