Bessere Bildschirmfreigabe dank bedingtem Fokus

Beaufort
François Beaufort
Elad Alon
Elad Alon

Unterstützte Browser

  • 109
  • 109
  • x
  • x

Quelle

Mit der Screen Capture API kann der Nutzer einen Tab, ein Fenster oder einen Bildschirm auswählen, um ihn als Medienstream aufzunehmen. Dieser Stream kann dann aufgezeichnet oder mit anderen über das Netzwerk geteilt werden. In dieser Dokumentation wird der bedingte Fokus vorgestellt. Mit diesem Mechanismus können Web-Apps steuern, ob der erfasste Tab oder das erfasste Fenster beim Start der Aufnahme im Fokus ist oder ob die Erfassungsseite im Fokus bleiben soll.

Unterstützte Browser

Der bedingte Fokus ist ab Chrome 109 verfügbar.

Hintergrund

Wenn eine Web-App mit der Aufzeichnung eines Tabs oder eines Fensters beginnt, steht der Browser vor einer Entscheidung: Soll die erfasste Oberfläche in den Vordergrund gestellt werden oder soll die Erfassungsseite im Fokus bleiben? Die Antwort hängt vom Grund für den Aufruf von getDisplayMedia() und von der Oberfläche ab, die der Nutzer letztendlich auswählt.

Stellen Sie sich eine hypothetische Webanwendung für Videokonferenzen vor. Wenn Sie „track.getSettings().displaySurface“ lesen und sich möglicherweise den Alias „Aufnahme“ ansehen, kann die Web-App für Videokonferenzen verstehen, was der Nutzer geteilt hat. Dann:

  • Wenn der aufgenommene Tab oder das erfasste Fenster ferngesteuert werden kann, sollte die Videokonferenz im Fokus bleiben.
  • Andernfalls fokussieren Sie den aufgenommenen Tab oder das erfasste Fenster.

Im obigen Beispiel würde die Web-App für Videokonferenzen den Fokus beim Teilen einer Präsentation behalten, sodass der Nutzer aus der Ferne durch die Folien blättern kann. Würde der Nutzer jedoch einen Texteditor freigeben, würde die Videokonferenz-Web-App den Fokus sofort auf den erfassten Tab oder das erfasste Fenster verschieben.

Conditional Focus API verwenden

Instanziieren Sie ein CaptureController und übergeben Sie es an getDisplayMedia(). Wenn Sie setFocusBehavior() aufrufen, sobald das zurückgegebene Versprechen von getDiplayMedia() aufgelöst wurde, können Sie festlegen, ob der erfasste Tab oder das erfasste Fenster im Fokus ist oder nicht. Dies ist nur möglich, wenn der Nutzer einen Tab oder ein Fenster freigegeben hat.

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");
}

Bei der Entscheidung, ob du den Fokus festlegen möchtest, kann der Aufnahmegriff berücksichtigt werden.

// 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");
}

Sie können sogar entscheiden, ob Sie den Fokus legen möchten, bevor getDisplayMedia() aufgerufen wird.

// 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 });

Du kannst setFocusBehavior() beliebig oft aufrufen, bevor das Versprechen aufgelöst wird, oder höchstens einmal direkt nach der Auflösung. Der letzte Aufruf überschreibt alle vorherigen Aufrufe.

Genauer gesagt: – Das zurückgegebene Versprechen getDisplayMedia() wird für eine Mikroaufgabe aufgelöst. Wenn Sie setFocusBehavior() aufrufen, nachdem diese Mikroaufgabe abgeschlossen ist, wird ein Fehler ausgegeben. – Wenn setFocusBehavior() länger als eine Sekunde nach dem Start der Aufnahme aufgerufen wird, ist kein Vorgang mehr erforderlich.

Das heißt, die beiden folgenden Snippets schlagen fehl:

// 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");

Der Aufruf von setFocusBehavior() löst auch in den folgenden Fällen aus:

  • der von getDisplayMedia() zurückgegebene Videotrack des Streams ist nicht "live".
  • nachdem das getDisplayMedia() zurückgegebene Versprechen aufgelöst wurde, wenn der Nutzer einen Bildschirm (kein Tab oder Fenster) freigegeben hat.

Beispiel

Du kannst den bedingten Fokus ausprobieren, indem du die Demo auf Glitch ausführst. Prüfen Sie unbedingt den Quellcode.

Funktionserkennung

Mit dem folgenden Befehl kannst du prüfen, ob CaptureController.setFocusBehavior() unterstützt wird:

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

Feedback

Das Chrome-Team und die Webstandards-Community möchten mehr über Ihre Erfahrungen mit Conditional Focus erfahren.

Erzählen Sie uns mehr über das Design

Gibt es etwas in der bedingten Konzentration, das nicht wie erwartet funktioniert? Oder fehlen Methoden oder Eigenschaften, die du zur Umsetzung deiner Idee benötigst? Haben Sie eine Frage oder einen Kommentar zum Sicherheitsmodell?

  • Sie können ein Spezifikationsproblem im GitHub-Repository melden oder Ihre Meinung zu einem bereits bestehenden Problem hinzufügen.

Probleme bei der Implementierung?

Haben Sie bei der Implementierung von Chrome einen Fehler gefunden? Oder unterscheidet sich die Implementierung von der Spezifikation?

  • Melden Sie den Fehler unter https://new.crbug.com. Geben Sie dabei so viele Details wie möglich und eine einfache Anleitung zum Reproduzieren an. Glitch eignet sich gut zum Teilen von Code.

Unterstützung zeigen

Planen Sie den bedingten Fokus? Ihre öffentliche Unterstützung hilft dem Chrome-Team bei der Priorisierung von Funktionen und zeigt anderen Browseranbietern, wie wichtig es ist, diese Funktionen zu unterstützen.

Senden Sie einen Tweet an @ChromiumDev und teilen Sie uns mit, wo und wie Sie sie verwenden.

Danksagungen

Hero-Image von Elena Taranenko.

Vielen Dank an Rachel Andrew für die Rezension dieses Artikels.