Phase 13.2.b.2 fix — raise des subsurfaces avec leur parent

Bug observé sur le client de test 13.2.b.3 : le carré rouge subsurface
est rendu correctement au commit du child (à parent_pos + offset), mais
le `parent_surface.commit()` final côté client appelle raise(parent) et
place le parent au-dessus du child dans le z_order. Résultat visuel :
parent overdraw child, subsurface invisible.

Fix : après raise(parent_id), scanner surfaces_by_id pour trouver toutes
les subsurfaces dont le subsurface_link.parent pointe vers cette
SurfaceId, et les raise() juste après. Coût O(N) par raise, mais N est
petit (1-10 toplevels typique).

Note design : c'est une solution naïve. Une vraie implémentation
maintient un index parent_id → Vec<child_id> mis à jour à GetSubsurface
et à Destroy. À durcir en phase 13.2.b.5 si le scan O(N) devient
limitant (genre 50+ surfaces visibles).

Les 2 tests natifs continuent de passer en non-régression.

Leyoda 2026 – GPLv3
This commit is contained in:
Votre Nom 2026-05-16 14:33:11 +02:00
parent 1dab6ff51b
commit dfb5c66453

View file

@ -1603,6 +1603,36 @@ impl wayland_server::Dispatch<wl_surface::WlSurface, Arc<SurfaceData>> for Wayla
// indépendamment de leur parent ; elles vivent à
// parent.z + 1 par convention de leur création.
state.registry.raise(id);
// Phase 13.2.b.2 fix bug visuel : si on vient de raise un
// parent toplevel, raise aussi toutes ses subsurfaces
// pour qu'elles restent au-dessus dans le z_order. Sinon
// un re-commit du parent (sans buffer) après création
// des subsurfaces les masquerait. Cas observé sur le
// client de test 13.2.b.3 où le parent.commit() final
// de rafraîchissement faisait disparaître le carré rouge.
let parent_id_to_match = id;
let children_to_raise: Vec<SurfaceId> = state
.surfaces_by_id
.iter()
.filter_map(|(sid, surf)| {
let sd = surf.data::<Arc<SurfaceData>>()?;
let link = sd.subsurface_link.lock().unwrap();
let ld = link.as_ref()?;
let parent_sid = ld
.parent
.data::<Arc<SurfaceData>>()
.and_then(|psd| *psd.id.lock().unwrap())?;
if parent_sid == parent_id_to_match {
Some(*sid)
} else {
None
}
})
.collect();
for cid in children_to_raise {
state.registry.raise(cid);
}
}
// Frame callbacks en attente → bump dans la queue globale