L'API Screen Capture consente all'utente di selezionare una scheda, una finestra o uno schermo da acquisire come flusso multimediale. Questo stream può essere registrato o condiviso con altri tramite la rete. Questa documentazione introduce Conditional Focus, un meccanismo che consente alle app web di controllare se la scheda o la finestra acquisita verrà messa a fuoco all'inizio dell'acquisizione o se la pagina di acquisizione rimarrà in primo piano.
Supporto browser
La messa a fuoco condizionale è disponibile a partire da Chrome 109.
Sfondo
Quando un'app web inizia ad acquisire una scheda o una finestra, il browser deve decidere se portare in primo piano la superficie acquisita o mantenere la pagina di acquisizione in primo piano. La risposta dipende dal motivo della chiamata a getDisplayMedia()
e dalla superficie che l'utente seleziona.
Prendi in considerazione un'app web di videoconferenza ipotetica. Leggendo track.getSettings().displaySurface
ed esaminando potenzialmente l'handle di acquisizione, l'app web di videoconferenza può capire cosa ha scelto di condividere l'utente. Quindi:
- Se la scheda o la finestra acquisita può essere controllata da remoto, mantieni la videoconferenza in primo piano.
- In caso contrario, metti a fuoco la scheda o la finestra acquisita.
Nell'esempio precedente, l'app web di videoconferenza manterrebbe lo stato attivo se si condivide un file di presentazioni, consentendo all'utente di sfogliare le slide da remoto. Tuttavia, se l'utente sceglie di condividere un editor di testo, l'app web di videoconferenza sposterebbe immediatamente lo stato attivo sulla scheda o sulla finestra acquisita.
Utilizzo dell'API Conditional Focus
Crea un'istanza di CaptureController
e passala a getDisplayMedia()
. Chiamando setFocusBehavior()
immediatamente dopo la risoluzione della promessa restituita da getDiplayMedia()
, puoi controllare se la scheda o la finestra acquisita verrà messa a fuoco o meno. Questa operazione può essere eseguita solo se l'utente ha condiviso una scheda o una finestra.
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");
}
Quando decidi se mettere a fuoco, puoi prendere in considerazione la maniglia di acquisizione.
// 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");
}
È anche possibile decidere se concentrarsi prima di chiamare 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 });
Puoi chiamare setFocusBehavior()
un numero arbitrario di volte prima che la promessa venga risolta oppure al massimo una volta subito dopo la risoluzione della promessa. L'ultima chiamata sostituisce tutte le precedenti.
Più precisamente:
- La promessa restituita getDisplayMedia()
viene risolta in un microtask. La chiamata di setFocusBehavior()
dopo il completamento di questa microattività genera un errore.
- La chiamata di setFocusBehavior()
più di un secondo dopo l'inizio dell'acquisizione non ha effetto.
ovvero entrambi i seguenti snippet non andranno a buon fine:
// 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");
La chiamata a setFocusBehavior()
viene interrotta anche nei seguenti casi:
- la traccia video dello stream restituita da
getDisplayMedia()
non è "live". - dopo la risoluzione della promessa restituita da
getDisplayMedia()
, se l'utente ha condiviso uno schermo (non una scheda o una finestra).
Esempio
Puoi provare la messa a fuoco condizionale eseguendo la demo.
Rilevamento delle funzionalità
Per verificare se CaptureController.setFocusBehavior()
è supportato, utilizza:
if (
"CaptureController" in window &&
"setFocusBehavior" in CaptureController.prototype
) {
// CaptureController.setFocusBehavior() is supported.
}
Feedback
Il team di Chrome e la community degli standard web vogliono conoscere le tue esperienze con la messa a fuoco condizionale.
Descrivi il design
C'è qualcosa in merito alla messa a fuoco condizionale che non funziona come previsto? Oppure mancano metodi o proprietà che ti servono per implementare la tua idea? Hai una domanda o un commento sul modello di sicurezza?
- Invia una segnalazione relativa alle specifiche nel repository GitHub o aggiungi i tuoi commenti a una segnalazione esistente.
Problemi con l'implementazione?
Hai trovato un bug nell'implementazione di Chrome? L'implementazione è diversa dalla specifica?
- Invia una segnalazione di bug all'indirizzo https://new.crbug.com. Assicurati di includere il maggior numero di dettagli possibile e istruzioni semplici per la riproduzione.
Mostrare il proprio sostegno
Hai intenzione di utilizzare la messa a fuoco condizionale? Il tuo supporto pubblico aiuta il team di Chrome a dare la priorità alle funzionalità e mostra ad altri fornitori di browser quanto sia fondamentale supportarle.
Invia un tweet a @ChromiumDev e facci sapere dove e come lo utilizzi.
Link utili
Ringraziamenti
Immagine promozionale di Elena Taranenko.
Grazie a Rachel Andrew per aver esaminato questo articolo.