Feat : detection de fullscreen
All checks were successful
release / build (push) Successful in 30s
release / verify-windows (push) Successful in 2m57s

This commit is contained in:
jeanotx32
2026-08-13 14:05:49 -04:00
parent a1295003fd
commit 00535d5e19
4 changed files with 366 additions and 25 deletions

View File

@@ -180,7 +180,7 @@ Le rappel du plein écran dépend entièrement de ce choix, qui se règle par ag
| --- | --- | --- |
| Ouverture d'une page | commande dans l'instance pilotée | un processus lancé par page |
| Plein écran | commande WebDriver adressée à Firefox | touche envoyée au serveur d'affichage |
| Effet vérifié ? | oui — `document.fullscreenElement` est relu | non |
| Effet vérifié ? | oui — la place occupée par le lecteur est mesurée | non |
| Session Wayland | **fonctionne** | impossible (voir plus bas) |
| Dépendances | Firefox | xdotool + session X11 |
@@ -199,16 +199,59 @@ Séquence du rappel de plein écran :
1. `browsingContext.activate` — sans quoi la touche partirait vers un onglet d'arrière-plan ;
2. `input.performActions` — la touche configurée (`f` par défaut), délivrée à la page comme
un vrai évènement (`isTrusted: true`), donc traitée par le lecteur du site ;
3. relecture de `document.fullscreenElement`, et verdict rapporté dans l'historique de la VM.
3. **mesure** de la place réellement occupée par le lecteur, et verdict rapporté dans
l'historique de la VM.
Une seule voie, volontairement, sans repli. Une version antérieure appelait
`requestFullscreen()` sur l'élément `<video>` brut quand `document.fullscreenElement` restait
vide après la touche — mais ce champ ne dit rien du mode « théâtre » de Stripchat, qui garde
la barre du haut visible et n'a le plus souvent rien à voir avec l'API plein écran native du
navigateur. Le repli déclenchait alors un vrai plein écran natif — vidéo seule, tout le reste
disparu — l'exact inverse de ce que la touche du lecteur, elle, obtient. `confirmed` reste
donc indéterminé (`undefined`, pas `false`) quand l'API native ne signale rien : ce n'est pas
un échec, juste un mode que ce champ ne peut pas observer.
disparu — l'exact inverse de ce que la touche du lecteur, elle, obtient.
##### Mesurer plutôt que demander
`document.fullscreenElement` ne connaît que l'API native : il ignore le mode théâtre, donc il
ne renseignait presque jamais rien. L'agent **mesure** désormais ce qui compte vraiment — la
part de la fenêtre que le lecteur occupe, relevée par `getBoundingClientRect()` sur l'élément
`<video>` et ramenée au cadre visible (ce qui déborde n'est pas capturé par OBS).
**C'est la hauteur qui tranche, pas la surface.** Un lecteur passé en théâtre remplit toujours
la fenêtre verticalement, alors que sa largeur dépend de la forme du flux. Un flux vertical —
courant sur cette plateforme — reste cerné de bandes noires même en plein écran : mesuré en
surface, il passerait pour un échec permanent. Vérifié en conditions réelles contre un Firefox
piloté : un lecteur vertical en théâtre ne couvre que **27 %** de la fenêtre (contre 12 %
fenêtré), mais en occupe bien toute la hauteur.
**Un repère plutôt qu'un seuil absolu.** La hauteur du lecteur *fenêtré* est relevée une fois
par page, juste avant le premier envoi de touche ; le plein écran est reconnu quand la hauteur
dépasse ce repère d'un quart. Rien ne garantit qu'un site laisse au lecteur la même part
d'écran d'une mise en page à l'autre, et un seuil fixe se serait trompé sur la première
refonte venue. Le repère n'est jamais réécrit ensuite — un second relevé, pris alors que le
plein écran est déjà en place, en ferait la nouvelle référence et rendrait toute mesure
ultérieure aveugle. Il est en revanche oublié à chaque changement de page.
Il en découle **trois verdicts et non deux**. `false` n'est rendu que là où l'échec est
réellement établi ; sans repère fenêtré auquel se comparer (agent redémarré au milieu d'une
capture), on retombe sur un substitut — hauteur ≥ 80 % — dont le négatif reste *indéterminé*
plutôt qu'annoncé comme un échec. L'état apparaît sur la fiche de la VM (⛶ plein écran / hors
plein écran), et rien n'est affiché tant qu'il est indéterminé : faire passer un doute pour un
constat serait pire que se taire.
**Une seconde tentative, jamais plus, et seulement sur un échec établi.** La touche *bascule*
l'affichage : réappuyer sur une simple présomption ferait *sortir* du plein écran une page qui
y était déjà. C'est précisément la mesure fiable qui rend ce second essai possible.
**Le plein écran est relu toutes les 30 s pendant une capture.** Il peut se perdre sans que le
statut du stream bouge — un clic malheureux, un ré-affichage du lecteur, une publicité qui
reprend la main — et rien ne le signalait jusqu'ici : la capture en sortait sans qu'on sache
ni quand ni pourquoi. La relecture est espacée à dessein (c'est une évaluation dans la page,
pas au rythme du statut), et n'a lieu que pendant un enregistrement **actif et non suspendu** :
hors capture il n'y a rien à cadrer, et pendant une pause de show privé l'overlay du site
occupe le lecteur. Le constat part au journal **avec les mesures qui l'ont motivé**
(« hauteur 55 %, surface 27 %, repère fenêtré 55 % »), pour que la perte soit diagnosticable
après coup. Après trois rappels sans effet, la surveillance se suspend jusqu'au prochain
enregistrement plutôt que d'insister toutes les 30 s.
**Un seul envoi à la fois, et pas plus d'un toutes les 10 s.** Deux mécanismes indépendants
peuvent réclamer ce rappel : la séquence d'ouverture (une fois, à l'arrivée sur la page) et