diff --git a/crates/redox-wl-wayland-frontend/src/lib.rs b/crates/redox-wl-wayland-frontend/src/lib.rs
index 0e87f82..4f85505 100644
--- a/crates/redox-wl-wayland-frontend/src/lib.rs
+++ b/crates/redox-wl-wayland-frontend/src/lib.rs
@@ -186,6 +186,11 @@ struct SurfaceData {
/// surfaces d'un client déconnecté (à ce moment-là `surf.client()`
/// retourne déjà None, donc on ne pourrait pas re-déduire le ClientId).
client_id: Mutex>,
+ /// Phase 13.2.b.2 : si cette surface est une subsurface, lien vers les
+ /// données du wl_subsurface qui la pilote (parent ref, offset, sync).
+ /// Setté par `wl_subcompositor.GetSubsurface`. Lu au commit de cette
+ /// surface pour calculer sa position absolue = parent.pos + offset.
+ subsurface_link: Mutex >>,
}
/// Données par-xdg_surface : référence à la wl_surface sous-jacente +
@@ -1313,6 +1318,7 @@ impl wayland_server::Dispatch for WaylandFronte
// est encore vivant. À la déconnexion, `surf.client()`
// retournera None et on ne pourrait plus déduire ce mapping.
client_id: Mutex::new(Some(_client.id())),
+ subsurface_link: Mutex::new(None),
};
let surf = data_init.init(id, Arc::new(data));
// Phase 7.4 : enregistrer le mapping SurfaceId → WlSurface
@@ -1521,6 +1527,35 @@ impl wayland_server::Dispatch> for Wayla
}
let is_cursor = data.is_cursor.load(Ordering::Relaxed);
+ // Phase 13.2.b.2 : si cette surface est une subsurface,
+ // recalculer sa position absolue à partir de parent.pos +
+ // offset, avant que le commit applique pending→current.
+ // Détection via subsurface_link, peuplé par GetSubsurface.
+ let subsurface_link = data.subsurface_link.lock().unwrap().clone();
+ let is_subsurface = subsurface_link.is_some();
+ if let Some(sub_data) = &subsurface_link {
+ let parent_id_opt = sub_data
+ .parent
+ .data::>()
+ .and_then(|sd| *sd.id.lock().unwrap());
+ if let Some(parent_id) = parent_id_opt {
+ let parent_pos = state.registry.get(parent_id).map(|s| {
+ let cs = s.current();
+ (cs.x, cs.y)
+ });
+ if let Some((px, py)) = parent_pos {
+ let (ox, oy) = *sub_data.position.lock().unwrap();
+ state.registry.modify_pending(id, |s| {
+ s.x = px + ox;
+ s.y = py + oy;
+ });
+ tracing::debug!(
+ "subsurface commit: pos absolue = parent({},{}) + offset({},{}) = ({},{})",
+ px, py, ox, oy, px + ox, py + oy
+ );
+ }
+ }
+ }
// Lire le buffer attaché (s'il y en a un). On `take()` pour
// que le pending_buffer soit vidé après chaque commit
@@ -1560,10 +1595,13 @@ impl wayland_server::Dispatch> for Wayla
buf.release();
}
state.registry.commit(id);
- if !is_cursor {
+ if !is_cursor && !is_subsurface {
// Promouvoir au top du Z-order au commit (politique simple :
// dernière surface qui commit = au-dessus). À raffiner en
// phase 7 (focus, raise on click, etc.).
+ // Phase 13.2.b.2 : les subsurfaces ne raisent pas
+ // indépendamment de leur parent ; elles vivent à
+ // parent.z + 1 par convention de leur création.
state.registry.raise(id);
}
@@ -1572,11 +1610,13 @@ impl wayland_server::Dispatch> for Wayla
state.frame_callbacks.append(&mut *cbs);
drop(cbs);
- if !is_cursor {
+ if !is_cursor && !is_subsurface {
// Phase 7.2 : la surface qui vient de commiter et raise
// devient automatiquement la surface focalisée. Envoie les
// events keyboard/pointer enter/leave en conséquence.
// Une surface curseur n'a évidemment pas le focus — on skip.
+ // Phase 13.2.b.2 : pareil pour les subsurfaces — le
+ // focus reste sur le parent toplevel.
state.set_focus(Some(_resource.clone()));
}
}
@@ -2329,15 +2369,11 @@ impl wayland_server::Dispatch for Wayland
} => {
// Vérif soft : rôle déjà attribué ? (xdg_toplevel notamment).
// Pour 13.2.b.1 on se contente de logger ; le protocole exige
- // un bad_surface error mais on attendra 13.2.b.2 pour
- // l'enforcer car ça touche au design role-tracking.
+ // un bad_surface error mais on attendra une phase ultérieure
+ // pour l'enforcer (role-tracking).
if let Some(child_data) = surface.data::>() {
let id_lock = child_data.id.lock().unwrap();
if id_lock.is_some() {
- // La surface a déjà été registered comme toplevel ?
- // Hmm, en fait avoir un SurfaceId ne signifie pas un
- // rôle xdg — c'est juste qu'elle vit dans le registry.
- // On ne fait rien de plus que log debug.
tracing::debug!(
"GetSubsurface: surface child déjà dans registry (id={:?})",
*id_lock
@@ -2345,11 +2381,17 @@ impl wayland_server::Dispatch for Wayland
}
}
let data = Arc::new(SubsurfaceData {
- parent,
- child: surface,
+ parent: parent.clone(),
+ child: surface.clone(),
position: Mutex::new((0, 0)),
sync: AtomicBool::new(true), // default = sync per spec
});
+ // Phase 13.2.b.2 : lier la SurfaceData de la child au
+ // SubsurfaceData pour que le commit puisse calculer la
+ // position absolue parent.pos + offset.
+ if let Some(child_sd) = surface.data::>() {
+ *child_sd.subsurface_link.lock().unwrap() = Some(data.clone());
+ }
data_init.init(id, data);
tracing::debug!("wl_subcompositor.get_subsurface: subsurface créée");
}