Улучшенное совместное использование экрана с помощью условного фокуса

Франсуа Бофор
François Beaufort

Browser Support

  • Хром: 109.
  • Край: 109.
  • Firefox: не поддерживается.
  • Safari: не поддерживается.

Source

API захвата экрана позволяет пользователю выбрать вкладку, окно или экран для захвата в виде медиапотока. Этот поток затем можно записать или поделиться им с другими пользователями по сети. В этой документации рассматривается условный фокус — механизм, позволяющий веб-приложениям управлять тем, будет ли фокусироваться захваченная вкладка или окно при начале захвата, или же фокус останется на странице захвата.

Поддержка браузеров

Условный фокус доступен в Chrome 109.

Фон

Когда веб-приложение начинает захват вкладки или окна, браузеру приходится решать: вывести захваченную поверхность на передний план или оставить в фокусе страницу, на которой был сделан захват? Ответ зависит от причины вызова getDisplayMedia() и от того, какую поверхность в итоге выберет пользователь.

Рассмотрим гипотетическое веб-приложение для видеоконференций. Считывая track.getSettings().displaySurface и потенциально проверяя Capture Handle , веб-приложение для видеоконференций может понять, что именно решил показать пользователь. Затем:

  • Если захваченной вкладкой или окном можно управлять удаленно, держите видеоконференцию в фокусе.
  • В противном случае сфокусируйтесь на захваченной вкладке или окне.

В приведенном выше примере веб-приложение для видеоконференций сохранит фокус при совместном использовании набора слайдов, позволяя пользователю удаленно пролистывать слайды; но если пользователь решит предоставить общий доступ к текстовому редактору, веб-приложение для видеоконференций немедленно переключит фокус на захваченную вкладку или окно.

Использование API условного фокуса

Создайте экземпляр CaptureController и передайте его в getDisplayMedia() . Вызывая setFocusBehavior() сразу после завершения возвращаемого промиса getDiplayMedia() , вы можете управлять фокусировкой захваченной вкладки или окна. Это возможно только в том случае, если пользователь предоставил общий доступ к вкладке или окну.

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() произвольное количество раз до завершения обещания или не более одного раза сразу после его завершения. Последний вызов переопределяет все предыдущие.

Точнее: - Промис, возвращаемый getDisplayMedia() разрешается на микрозадаче. Вызов setFocusBehavior() после завершения этой микрозадачи приводит к ошибке. - Вызов 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() не является «живой» .
  • после того, как getDisplayMedia() вернет обещание, если пользователь открыл общий экран (а не вкладку или окно).

Образец

Вы можете поэкспериментировать с условным фокусом, запустив демо-версию .

Обнаружение особенностей

Чтобы проверить, поддерживается ли CaptureController.setFocusBehavior() , используйте:

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

Обратная связь

Команда Chrome и сообщество веб-стандартов хотят узнать о вашем опыте использования Conditional Focus.

Расскажите нам о дизайне

Есть ли что-то в условном фокусе, что работает не так, как вы ожидали? Или не хватает методов или свойств, необходимых для реализации вашей идеи? Есть вопросы или комментарии по модели безопасности?

  • Отправьте сообщение о проблеме со спецификацией в репозиторий GitHub или добавьте свои мысли к существующей проблеме.

Проблема с реализацией?

Вы обнаружили ошибку в реализации Chrome? Или реализация отличается от спецификации?

  • Сообщите об ошибке по адресу https://new.crbug.com . Опишите её как можно подробнее и предоставьте простые инструкции по её воспроизведению.

Выразить поддержку

Планируете ли вы использовать условный фокус? Ваша публичная поддержка помогает команде Chrome расставлять приоритеты в отношении функций и показывает другим разработчикам браузеров, насколько важна их поддержка.

Отправьте твит @ChromiumDev и расскажите, где и как вы его используете.

Благодарности

Автор изображения — Елена Тараненко .

Спасибо Рэйчел Эндрю за рецензирование этой статьи.