3 livrables qui polissent le compositor pour des toolkits Wayland
réels.
Frontend additions :
1. set_min_size / set_max_size
- XdgToplevelData : min_size/max_size: Mutex<(i32, i32)>
- Handlers SetMinSize/SetMaxSize stockent
- apply_interactive_drag(Resize) clamp new_w/new_h aux contraintes
après compute_resize_geom
2. Activated state au focus change
- WaylandFrontend.toplevels_by_id: HashMap<SurfaceId, XdgToplevel>
peuplé à xdg_surface.GetToplevel, nettoyé à wl_surface.Destroy
et garbage_collect_dead_clients
- Méthode send_focus_configure(toplevel, sid, states) : envoie
configure(w, h, states) avec taille du buffer courant +
xdg_surface.configure(serial) + update last_serial
- set_focus envoie configure([Activated]) à la nouvelle focused
surface et configure([]) à l'ancienne
3. Throttling configure pendant resize
- InteractiveDrag : last_configure_size + last_configure_at
- apply_interactive_drag(Resize) skip l'envoi si taille inchangée
OU elapsed < 16ms (max ~60fps), mais applique quand même le
delta de position pour que la fenêtre suive le curseur
Test client : set_min_size(150, 80) + set_max_size(600, 400)
Validation runtime :
- [frontend] xdg_toplevel.set_min_size(150, 80) + set_max_size logs
- focus change → configure(320x200) reçu côté client = Activated OK
- Configure pendant resize : un seul w=150 h=80 envoyé pour les 4
phases de cursor (clamp + throttling = même résultat → skip)
Capture phase7-9-2-clamp-min.png montre la fenêtre clampée à 150x80
malgré des cursor moves qui auraient produit des tailles négatives.
Bilan phase 7 (1-9) close. Compositor 7.x suffisamment poli pour
toolkits Wayland réels : xdg-shell complet, focus avec Activated,
input filtré, cursor, move/resize avec contraintes, robustesse,
multi-clients avec cleanup.
Prochain jalon : port COSMIC (phase 13 plan-directeur, réordonnée
avant GPU).
Doc complète : docs/phase7-9-polish.md
Leyoda 2026 – GPLv3
Resize complet implémenté (compute selon edges + configure cycle)
+ durcissements sécu Move/Resize.
Frontend additions :
- Helper compute_resize_geom(edges, start_x/y/w/h, dx, dy) qui
interprète le bitmask xdg_toplevel::ResizeEdge :
Top(1)/Bottom(2)/Left(4)/Right(8). Coins = combinaisons.
Clamp w/h à MIN_RESIZE_DIM=32.
- Handler xdg_toplevel.Resize complet : valide serial!=0,
validation soft du serial vs last_button_serial (log warning,
accept), refuse si drag déjà actif, check client_id (caller ==
owner de la surface — sécu défense en profondeur). Capture
start_geom (x,y,w,h) + start_cursor, stocke InteractiveDrag::
Resize(edges).
- apply_interactive_drag(Resize) : compute new geom, modifie
registry x/y, envoie xdg_toplevel.configure(w, h, [Resizing]) +
xdg_surface.configure(serial). Met à jour
XdgSurfaceData.last_serial = serial pour que l'ack du client
soit accepté (sinon refusé par garde 7.5).
- Move handler : check client_id ajouté en mode défense en
profondeur (un client ne peut pas drag une surface d'un autre).
Nouveau crate : redox-wl-test-client-resize (~285 lignes)
- Bind wl_seat
- 1 fenêtre 320x200 cyan + bordure noire
- À T+8s : toplevel.resize(seat, 1, BottomRight)
- Écoute xdg_toplevel.Configure : à chaque new size, ack +
nouveau shm pool + nouveau buffer + attach + commit
- Vec<WlShmPool>/Vec<WlBuffer> pour ne pas drop les anciens
pendant que le serveur peut encore les utiliser
Pièges trouvés :
- last_serial doit être mis à jour à chaque configure envoyé
pendant le resize, sinon l'ack du client est refusé par le
garde 7.5 (serial > last_sent → ignoring).
- Le client peut ignorer la taille initiale suggérée par le
configure du compositor (legal selon spec). Le compositor
compose à la taille du buffer attaché.
- À chaque resize, garder les anciens pool+buffer en mémoire
pour ne pas crasher le serveur qui mmap dessus.
Validation runtime : 3 captures à 3 tailles distinctes (320x200
initial, ~520x300 agrandi, ~70x25 rétréci) confirment le pipeline
end-to-end. Logs symétriques côté client et compositor.
Bilan phase 7 (1-8) :
- 7.1 xdg-shell, 7.2 wl_seat, 7.3 cursor, 7.4 focus/raise,
7.5 robustesse, 7.6 multi-clients, 7.7 move, 7.8 resize
- Compositor 7.x désormais utilisable pour un toolkit Wayland
basique. Prochain jalon : port COSMIC (phase 13 plan-directeur,
réordonnée avant GPU).
Doc complète : docs/phase7-8-resize.md
Leyoda 2026 – GPLv3