Amélioration du partage d'écran avec la mise au point conditionnelle

François Beaufort
François Beaufort

Navigateurs pris en charge

  • Chrome: 109.
  • Edge: 109.
  • Firefox: non compatible.
  • Safari: non compatible.

Source

L'API Screen Capture permet à l'utilisateur de sélectionner un onglet, une fenêtre ou un écran à capturer en tant que flux multimédia. Ce flux peut ensuite être enregistré ou partagé avec d'autres utilisateurs sur le réseau. Cette documentation présente la mise au point conditionnelle, un mécanisme permettant aux applications Web de contrôler si l'onglet ou la fenêtre capturés seront mis au point au début de la capture ou si la page de capture restera mise au point.

Prise en charge des navigateurs

La mise au point conditionnelle est disponible à partir de Chrome 109.

Contexte

Lorsqu'une application Web commence à capturer un onglet ou une fenêtre, le navigateur doit prendre une décision : la surface capturée doit-elle être mise au premier plan ou la page de capture doit-elle rester active ? La réponse dépend de la raison pour laquelle getDisplayMedia() est appelé et de la surface que l'utilisateur finit par sélectionner.

Prenons l'exemple d'une application Web de visioconférence hypothétique. En lisant track.getSettings().displaySurface et en examinant éventuellement le handle de capture, l'application Web de visioconférence peut comprendre ce que l'utilisateur a choisi de partager. Ensuite :

  • Si l'onglet ou la fenêtre capturés peuvent être contrôlés à distance, maintenez la conférence vidéo au premier plan.
  • Sinon, mettez en surbrillance l'onglet ou la fenêtre capturés.

Dans l'exemple ci-dessus, l'application Web de visioconférence conserve la sélection si vous partagez une présentation, ce qui permet à l'utilisateur de faire défiler les diapositives à distance. Toutefois, si l'utilisateur choisit de partager un éditeur de texte, l'application Web de visioconférence passe immédiatement en mode sélection sur l'onglet ou la fenêtre capturés.

Utiliser l'API Conditional Focus

Instanciez une CaptureController et transmettez-la à getDisplayMedia(). En appelant setFocusBehavior() immédiatement après la résolution de la promesse renvoyée par getDiplayMedia(), vous pouvez contrôler si l'onglet ou la fenêtre capturés seront mis en surbrillance ou non. Cela n'est possible que si l'utilisateur a partagé un onglet ou une fenêtre.

const controller = new CaptureController();

// Prompt the user to share a tab, a window or a screen.
const stream =
    await navigator.mediaDevices.getDisplayMedia({ controller });

const [track] = stream.getVideoTracks();
const displaySurface = track.getSettings().displaySurface;
if (displaySurface == "browser") {
  // Focus the captured tab.
  controller.setFocusBehavior("focus-captured-surface");
} else if (displaySurface == "window") {
  // Do not move focus to the captured window.
  // Keep the capturing page focused.
  controller.setFocusBehavior("focus-capturing-application");
}

Pour décider de mettre au point, vous pouvez prendre en compte le poignée de capture.

// Retain focus if capturing a tab dialed to example.com.
// Focus anything else.
const origin = track.getCaptureHandle().origin;
if (displaySurface == "browser" && origin == "https://example.com") {
  controller.setFocusBehavior("focus-capturing-application");
} else if (displaySurface != "monitor") {
  controller.setFocusBehavior("focus-captured-surface");
}

Vous pouvez même décider de mettre au point avant d'appeler getDisplayMedia().

// Focus the captured tab or window when capture starts.
const controller = new CaptureController();
controller.setFocusBehavior("focus-captured-surface");

// Prompt the user to share their screen.
const stream =
    await navigator.mediaDevices.getDisplayMedia({ controller });

Vous pouvez appeler setFocusBehavior() un nombre arbitraire de fois avant la résolution de la promesse, ou au plus une fois immédiatement après la résolution de la promesse. La dernière invocation remplace toutes les invocations précédentes.

Plus précisément : - La promesse renvoyée par getDisplayMedia() se résout sur une micro-tâche. Appeler setFocusBehavior() une fois la microtâche terminée génère une erreur. - Appeler setFocusBehavior() plus d'une seconde après le début de la capture n'a aucun effet.

Autrement dit, les deux extraits suivants échoueront:

// Prompt the user to share their screen.
const stream =
    await navigator.mediaDevices.getDisplayMedia({ controller });

// Too late, because it follows the completion of the task
// on which the getDisplayMedia() promise resolved.
// This will throw.
setTimeout(() => {
  controller.setFocusBehavior("focus-captured-surface");
});
// Prompt the user to share their screen.
const stream =
    await navigator.mediaDevices.getDisplayMedia({ controller });

const start = new Date();
while (new Date() - start <= 1000) {
  // Idle for ≈1s.
}

// Because too much time has elapsed, the browser will have
// already decided whether to focus.
// This fails silently.
controller.setFocusBehavior("focus-captured-surface");

L'appel de setFocusBehavior() génère également une exception dans les cas suivants:

  • la piste vidéo du flux renvoyée par getDisplayMedia() n'est pas "en direct".
  • une fois la promesse renvoyée par getDisplayMedia() résolue, si l'utilisateur a partagé un écran (et non un onglet ou une fenêtre).

Échantillon

Vous pouvez tester la mise au point conditionnelle en exécutant la démo sur Glitch. N'oubliez pas de consulter le code source.

Détection de fonctionnalités

Pour vérifier si CaptureController.setFocusBehavior() est compatible, utilisez:

if (
  "CaptureController" in window &&
  "setFocusBehavior" in CaptureController.prototype
) {
  // CaptureController.setFocusBehavior() is supported.
}

Commentaires

L'équipe Chrome et la communauté des normes Web souhaitent connaître votre expérience avec la mise au point conditionnelle.

Parlez-nous de la conception

Le focus conditionnel ne fonctionne-t-il pas comme prévu ? Ou manque-t-il des méthodes ou des propriétés dont vous avez besoin pour implémenter votre idée ? Vous avez une question ou un commentaire sur le modèle de sécurité ?

  • Signalez un problème de spécification dans le dépôt GitHub ou ajoutez vos commentaires à un problème existant.

Problème d'implémentation ?

Avez-vous trouvé un bug dans l'implémentation de Chrome ? Ou l'implémentation est-elle différente de la spécification ?

  • Signalez un bug sur https://new.crbug.com. Veillez à inclure autant de détails que possible et des instructions simples pour reproduire le problème. Glitch est un bon outil pour partager du code.

Montrer votre soutien

Prévoyez-vous d'utiliser la mise au point conditionnelle ? Votre soutien public aide l'équipe Chrome à hiérarchiser les fonctionnalités et montre aux autres fournisseurs de navigateurs à quel point il est essentiel de les prendre en charge.

Envoyez un tweet à @ChromiumDev et dites-nous où et comment vous l'utilisez.

Remerciements

Image principale par Elena Taranenko.

Merci à Rachel Andrew d'avoir relu cet article.