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"); }