Bessere Bildschirmfreigabe dank bedingtem Fokus

François Beaufort
François Beaufort

Browser Support

  • Chrome: 109.
  • Edge: 109.
  • Firefox: not supported.
  • Safari: not supported.

Source

Mit der Screen Capture API kann der Nutzer einen Tab, ein Fenster oder einen Bildschirm auswählen, der als Media-Stream aufgenommen werden soll. Dieser Stream kann dann aufgezeichnet oder über das Netzwerk mit anderen geteilt werden. In dieser Dokumentation wird „Conditional Focus“ vorgestellt, ein Mechanismus für Web-Apps, mit dem gesteuert werden kann, ob der Fokus auf dem erfassten Tab oder Fenster liegt, wenn die Erfassung beginnt, oder ob der Fokus auf der erfassenden Seite bleibt.

Unterstützte Browser

Conditional Focus ist ab Chrome 109 verfügbar.

Hintergrund

Wenn eine Web-App beginnt, einen Tab oder ein Fenster zu erfassen, muss der Browser entscheiden, ob die erfasste Oberfläche in den Vordergrund gerückt oder die erfassende Seite im Fokus bleiben soll. Die Antwort hängt vom Grund für den Anruf bei getDisplayMedia() und von der Oberfläche ab, die der Nutzer auswählt.

Nehmen wir an, es handelt sich um eine hypothetische Videokonferenz-Web-App. Durch Lesen von track.getSettings().displaySurface und möglicherweise durch Untersuchen des Capture Handle kann die Videokonferenz-Web-App erkennen, was der Nutzer freigegeben hat. Dann:

  • Wenn der erfasste Tab oder das erfasste Fenster per Fernzugriff gesteuert werden kann, sollte der Fokus auf der Videokonferenz liegen.
  • Andernfalls wird der Fokus auf den erfassten Tab oder das erfasste Fenster gelegt.

Im obigen Beispiel würde die Videokonferenz-Web-App den Fokus behalten, wenn eine Präsentation geteilt wird. So kann der Nutzer die Folien per Fernzugriff durchblättern. Wenn der Nutzer jedoch einen Texteditor teilt, würde die Videokonferenz-Web-App den Fokus sofort auf den aufgenommenen Tab oder das aufgenommene Fenster verlagern.

Conditional Focus API verwenden

Instanziieren Sie ein CaptureController-Objekt und übergeben Sie es an getDisplayMedia(). Wenn Sie setFocusBehavior() unmittelbar nach dem Auflösen des von getDiplayMedia() zurückgegebenen Versprechens aufrufen, können Sie steuern, ob der erfasste Tab oder das erfasste Fenster fokussiert wird. Das 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 Sie sich auf ein bestimmtes Thema konzentrieren, können Sie die Capture Handle berücksichtigen.

// 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 der Fokus vor dem Aufrufen von getDisplayMedia() festgelegt werden soll.

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

Sie können setFocusBehavior() beliebig oft aufrufen, bevor das Promise aufgelöst wird, oder höchstens einmal unmittelbar danach. Der letzte Aufruf überschreibt alle vorherigen Aufrufe.

Genauer gesagt: - Das von getDisplayMedia() zurückgegebene Promise wird in einem Microtask aufgelöst. Wenn Sie setFocusBehavior() nach Abschluss dieser Mikroaufgabe aufrufen, wird ein Fehler ausgegeben. – Wenn setFocusBehavior() mehr als eine Sekunde nach Beginn der Erfassung aufgerufen wird, hat das keine Auswirkungen.

Das bedeutet, dass beide folgenden Snippets fehlschlagen:

// 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 eine Ausnahme aus:

  • Der von getDisplayMedia() zurückgegebene Videotrack des Streams ist nicht „live“.
  • nachdem das zurückgegebene Promise getDisplayMedia() aufgelöst wurde, wenn der Nutzer einen Bildschirm (nicht einen Tab oder ein Fenster) geteilt hat.

Beispiel

Sie können mit Conditional Focus experimentieren, indem Sie die Demo ausführen.

Funktionserkennung

So prüfen Sie, 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.

Informationen zum Design

Funktioniert etwas an der Funktion „Bedingter Fokus“ nicht wie erwartet? Oder fehlen Methoden oder Eigenschaften, die Sie für die Umsetzung Ihrer Idee benötigen? Haben Sie eine Frage oder einen Kommentar zum Sicherheitsmodell?

  • Melden Sie ein Spezifikationsproblem im GitHub-Repository oder fügen Sie einem bestehenden Problem Ihre Gedanken hinzu.

Probleme bei der Implementierung?

Haben Sie einen Fehler in der Chrome-Implementierung gefunden? Oder weicht die Implementierung von der Spezifikation ab?

Unterstützung zeigen

Planen Sie, Conditional Focus zu verwenden? Ihre öffentliche Unterstützung hilft dem Chrome-Team, Funktionen zu priorisieren, und zeigt anderen Browseranbietern, wie wichtig es ist, sie zu unterstützen.

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

Danksagungen

Hero-Image von Elena Taranenko.

Vielen Dank an Rachel Andrew für die Überprüfung dieses Artikels.