条件付きフォーカスによる画面共有の改善

François Beaufort
François Beaufort

対応ブラウザ

  • 109
  • 109
  • x
  • x

ソース

Screen Capture API を使用すると、ユーザーはタブ、ウィンドウ、画面を選択して、メディア ストリームとしてキャプチャできます。このストリームは録画したり、ネットワークを介して他のユーザーと共有したりできます。このドキュメントでは、条件付きフォーカスについて説明します。条件付きフォーカスは、キャプチャの開始時にキャプチャしたタブやウィンドウにフォーカスするか、キャプチャ ページにフォーカスしたままにするかをウェブアプリが制御するためのメカニズムです。

ブラウザ サポート

条件付きフォーカスは Chrome 109 からご利用いただけます。

背景情報

ウェブアプリがタブやウィンドウのキャプチャを開始すると、ブラウザは、キャプチャしたサーフェスを前面に出すべきか、それともキャプチャするページにフォーカスしたままにするべきかという判断を下します。その答えは、getDisplayMedia() を呼び出す理由によって異なり、ユーザーは最終的にサーフェスで選択します。

架空のビデオ会議ウェブアプリについて考えてみましょう。track.getSettings().displaySurface を読み取ってキャプチャ ハンドルを調べることで、ビデオ会議ウェブアプリはユーザーが選択した共有対象を理解できます。この場合、次のようになります。

  • キャプチャしたタブやウィンドウをリモート操作できる場合は、ビデオ会議にフォーカスを合わせたままにします。
  • それ以外の場合は、キャプチャしたタブまたはウィンドウにフォーカスします。

上記の例では、スライド資料を共有しても、ビデオ会議ウェブアプリのフォーカスは保持されるため、ユーザーはリモートでスライドを次々と切り替えることができます。ただし、テキスト エディタの共有を選択すると、ビデオ会議ウェブアプリはキャプチャしたタブまたはウィンドウにフォーカスを直ちに切り替えます。

Conditional Focus API を使用する

CaptureController をインスタンス化し、getDisplayMedia() に渡します。返された getDiplayMedia() の Promise が解決された直後に setFocusBehavior() を呼び出すことで、キャプチャしたタブまたはウィンドウにフォーカスするかどうかを制御できます。この操作は、ユーザーがタブまたはウィンドウを共有した場合のみ行えます。

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

フォーカスするかどうかを決定する際は、キャプチャ ハンドルを考慮できます。

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

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

setFocusBehavior() は、Promise が解決される前に何度でも、Promise が解決された直後に 1 回だけ呼び出すことができます。最後の呼び出しで、以前のすべての呼び出しがオーバーライドされます。

より正確には、以下のとおりです。 - 返された getDisplayMedia() は、マイクロタスクで Promise を解決します。マイクロタスクの完了後に setFocusBehavior() を呼び出すと、エラーがスローされます。- キャプチャ開始から 1 秒以上後に setFocusBehavior() を呼び出しても何も起こらない。

つまり、次のスニペットはどちらも失敗します。

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

setFocusBehavior() を呼び出すと、次のケースでもスローされます。

  • getDisplayMedia() から返されたストリームの動画トラックが「live」ではない。
  • getDisplayMedia() が返す Promise が解決された後、ユーザーが(タブまたはウィンドウではなく)画面を共有した場合。

サンプル

条件付きフォーカスを試すには、Glitch でデモを実行します。必ずソースコードを確認してください。

機能検出

CaptureController.setFocusBehavior() がサポートされているかどうかを確認するには、次のコマンドを使用します。

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

フィードバック

Chrome チームとウェブ標準コミュニティは、条件付きフォーカスの使用体験についてご意見をお聞かせください。

デザインについて教えてください

条件付きフォーカスで想定どおりに機能していないものはありますか?または、アイデアを実装するために必要なメソッドやプロパティが不足しているか。セキュリティ モデルについて質問や意見がある場合は、

  • GitHub リポジトリで仕様に関する問題を報告するか、既存の問題にご意見をお寄せください。

実装に問題がある場合

Chrome の実装にバグは見つかりましたか?または、実装が仕様と異なっていますか?

  • https://new.crbug.com でバグを報告します。できるだけ詳しい情報と、再現するための簡単な手順を記載してください。Glitch はコードの共有に適しています。

サポートの気持ちを伝える

条件付きフォーカスを使用する予定はありますか?皆様の公開サポートは、Chrome チームが機能の優先度を判断したり、他のブラウザ ベンダーにそれらのサポートの重要性を把握したりするうえで役立ちます。

@ChromiumDev にツイートを送信して、どこでどのように使用しているかをお知らせください。

謝辞

ヒーロー画像作成者: Elena Taranenko

この記事をレビューしてくれた Rachel Andrew に感謝します。