fix: panics on output removal

Despawning the output when its global was removed proved to be
overzealous, as the Dispatch of `zxdg_output_v1` still needed it for
cleanup. Instead, only the `OutputScaleFactor` element is removed, and
every surface entity with an `OnOutput` referencing the removed output,
so scaling events sent to surfaces on non-existent outputs did not panic
or use the provided scale as if an output still existed for it.
This commit is contained in:
En-En 2026-02-05 13:22:57 +00:00 committed by Supreeeme
parent 0947c4685f
commit e6dd3c05c0
3 changed files with 36 additions and 13 deletions

View file

@ -795,26 +795,38 @@ impl<S: X11Selection + 'static> InnerServerState<S> {
handle_new_globals::<S>(&mut self.globals_map, &self.dh, &globals);
let globals = std::mem::take(&mut self.world.removed_globals);
if globals.is_empty() {
return;
for global in globals {
let (global_struct, global_id) = self.globals_map.remove(&global).unwrap();
self.dh.disable_global::<InnerServerState<S>>(global_id);
if global_struct.interface == <WlOutput>::interface().name {
self.remove_output(global);
}
}
}
fn remove_output(&mut self, global: GlobalName) {
let query = self
.world
.query_mut::<(&WlOutput, &GlobalName)>()
.into_iter()
.map(|(e, (_, name))| (e, *name))
.collect::<Vec<_>>();
for global in globals {
let (global_struct, global_id) = self.globals_map.remove(&global).unwrap();
self.dh.disable_global::<InnerServerState<S>>(global_id);
if global_struct.interface == <WlOutput>::interface().name {
for (entity, name) in query.iter() {
if *name == global {
self.updated_outputs.push(*entity);
self.world.despawn(*entity).unwrap();
break;
for (entity, name) in query.iter() {
if *name == global {
self.updated_outputs.push(*entity);
self.world.remove_one::<OutputScaleFactor>(*entity).unwrap();
let query = self
.world
.query_mut::<&OnOutput>()
.into_iter()
.map(|(e, on_out)| (e, *on_out))
.collect::<Vec<_>>();
for (e, on_out) in query.iter() {
if *on_out == OnOutput(*entity) {
self.world.remove_one::<OnOutput>(*e).unwrap();
}
}
break;
}
}
}