Interfejs Screen Capture API umożliwia użytkownikowi wybranie karty, okna lub ekranu do przechwycenia jako strumienia multimediów. Ten strumień można następnie nagrać lub udostępnić innym osobom w sieci. W tej dokumentacji przedstawiamy Conditional Focus, czyli mechanizm umożliwiający aplikacjom internetowym kontrolowanie, czy przechwycona karta lub okno będą aktywne po rozpoczęciu przechwytywania, czy też aktywna pozostanie strona przechwytująca.
Obsługa przeglądarek
Conditional Focus jest dostępny w Chrome 109.
Tło
Gdy aplikacja internetowa zaczyna przechwytywać kartę lub okno, przeglądarka musi podjąć decyzję – czy przechwycona powierzchnia ma zostać przeniesiona na pierwszy plan, czy też aktywna ma pozostać strona przechwytująca? Odpowiedź zależy od powodu wywołania getDisplayMedia() i od powierzchni, którą użytkownik wybierze do udostępnienia.
Rozważmy hipotetyczną aplikację internetową do prowadzenia rozmów wideo. Odczytując track.getSettings().displaySurface i ewentualnie sprawdzając Capture Handle, aplikacja internetowa do prowadzenia rozmów wideo może dowiedzieć się, co użytkownik wybrał do udostępnienia. Następnie:
- Jeśli przechwyconą kartę lub okno można zdalnie kontrolować, zachowaj rozmowę wideo na pierwszym planie.
- W przeciwnym razie ustaw aktywność na przechwyconą kartę lub okno.
W powyższym przykładzie aplikacja internetowa do prowadzenia rozmów wideo zachowa aktywność, jeśli udostępniana jest prezentacja slajdów, co umożliwi użytkownikowi zdalne przełączanie slajdów. Jeśli jednak użytkownik zdecyduje się udostępnić edytor tekstu, aplikacja internetowa do prowadzenia rozmów wideo natychmiast przełączy aktywność na przechwyconą kartę lub okno.
Korzystanie z interfejsu Conditional Focus API
Utwórz instancję CaptureController i przekaż ją do getDisplayMedia(). Wywołując setFocusBehavior() natychmiast po rozwiązaniu obietnicy zwróconej przez getDiplayMedia(), możesz określić, czy przechwycona karta lub okno będą aktywne. Można to zrobić tylko wtedy, gdy użytkownik udostępnił kartę lub okno.
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");
}
Decydując, czy ustawić aktywność, możesz wziąć pod uwagę Capture Handle.
// 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");
}
Możesz nawet zdecydować, czy ustawić aktywność przed wywołaniem 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 });
Możesz wywołać setFocusBehavior() dowolną liczbę razy przed rozwiązaniem obietnicy lub co najwyżej raz natychmiast po rozwiązaniu obietnicy. Ostatnie wywołanie zastępuje wszystkie poprzednie.
Więcej szczegółów:
- Obietnica zwrócona przez
getDisplayMedia()jest rozwiązywana w mikrozadaniu. WywołaniesetFocusBehavior()po zakończeniu tego mikrozadania powoduje błąd. - Wywołanie
setFocusBehavior()po upływie ponad sekundy od rozpoczęcia przechwytywania nie powoduje żadnego działania.
Oznacza to, że oba te fragmenty kodu nie będą działać:
// 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");
Wywołanie setFocusBehavior() powoduje też błąd w tych przypadkach:
- Ścieżka wideo strumienia zwróconego przez
getDisplayMedia()nie jest "na żywo". - Po rozwiązaniu obietnicy zwróconej przez
getDisplayMedia()użytkownik udostępnił ekran (nie kartę ani okno).
Przykład
Możesz wypróbować Conditional Focus, uruchamiając wersję demonstracyjną.
Wykrywanie funkcji
Aby sprawdzić, czy funkcja CaptureController.setFocusBehavior() jest obsługiwana, użyj tego kodu:
if (
"CaptureController" in window &&
"setFocusBehavior" in CaptureController.prototype
) {
// CaptureController.setFocusBehavior() is supported.
}
Prześlij opinię
Zespół Chrome i społeczność zajmująca się standardami internetowymi chcą poznać Twoje wrażenia związane z Conditional Focus.
Opowiedz nam o projekcie
Czy jest coś w Conditional Focus, co nie działa zgodnie z Twoimi oczekiwaniami? A może brakuje metod lub właściwości, których potrzebujesz do zrealizowania swojego pomysłu? Masz pytania lub uwagi dotyczące modelu zabezpieczeń?
- Zgłoś problem ze specyfikacją w repozytorium GitHub lub dodaj swoje uwagi do istniejącego problemu.
Problem z implementacją?
Czy udało Ci się znaleźć błąd w implementacji Chrome? A może implementacja różni się od specyfikacji?
- Zgłoś błąd na stronie https://new.crbug.com. Podaj jak najwięcej szczegółów i instrukcje dotyczące odtworzenia problemu.
Okaż wsparcie
Czy planujesz użycie Conditional Focus? Twoje publiczne wsparcie pomaga zespołowi Chrome ustalać priorytety funkcji i pokazuje innym dostawcom przeglądarek, jak ważne jest ich wsparcie.
Wyślij tweeta do @ChromiumDev i poinformuj nas, gdzie i jak korzystasz z tej funkcji.
Przydatne linki
Podziękowania
Dziękujemy Rachel Andrew za sprawdzenie tego dokumentu.