From d787cc7902954b59ffb913a9518ee61d0e475e35 Mon Sep 17 00:00:00 2001 From: Luo Zhiaho Date: Fri, 4 Sep 2026 22:47:03 +0800 Subject: [PATCH] Don't despawn render window entities when the raw handle is removed Removing `RawHandleWrapper` is not necessarily terminal: on Android the native window is destroyed (and its handle removed) when the app suspends, but the window entity survives and is given a new handle on resume. Despawning the synced render entity left the main world entity's `SubEntity` pointing at a dead entity, and the next round of extraction panicked with `Entity despawned` when reusing it. The render entity is only ever despawned by the entity sync system once the main world window entity is actually destroyed. Tear down the surface and drop the extracted window data instead; extraction and `create_surfaces` recreate them whenever the window has a new `RawHandleWrapper`. --- crates/bevy_render/src/view/window/mod.rs | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/crates/bevy_render/src/view/window/mod.rs b/crates/bevy_render/src/view/window/mod.rs index 653cea31bffae..279569fdf1348 100644 --- a/crates/bevy_render/src/view/window/mod.rs +++ b/crates/bevy_render/src/view/window/mod.rs @@ -190,14 +190,29 @@ fn extract_windows( } } + // Remove the components instead of despawn the synced render entity here: + // `RawHandleWrapper` removal is not necessarily + // terminal. On Android the native window is destroyed (and its handle removed) when the app + // suspends, but the window entity survives and is given a new handle on resume. Despawning + // would leave the `SubEntity` on the main world entity pointing at a dead entity, and the + // next round of extraction would panic when reusing it. + // + // The render entity is only ever despawned by the entity sync system once the main world + // window entity is actually destroyed. Here we only tear down the surface and drop the + // extracted window data; extraction and `create_surfaces` will recreate them whenever the + // window has a (new) `RawHandleWrapper` again. for closing_window in closing.read() { if let Ok(render_entity) = mapper.get(closing_window.window) { - commands.entity(render_entity.entity()).despawn(); + commands + .entity(render_entity.entity()) + .remove::<(ExtractedWindow, RawHandleWrapper, SurfaceData)>(); } } for removed_window in removed.read() { if let Ok(render_entity) = mapper.get(removed_window) { - commands.entity(render_entity.entity()).despawn(); + commands + .entity(render_entity.entity()) + .remove::<(ExtractedWindow, RawHandleWrapper, SurfaceData)>(); } } for removed_window in removed_primary.read() {