مشاركة الشاشة بشكلٍ أفضل باستخدام ميزة "التركيز المشروط"

François Beaufort
François Beaufort

دعم المتصفح

  • Chrome: 109
  • الحافة: 109.
  • Firefox: غير متوافق
  • Safari: غير متوافق

المصدر

تتيح واجهة برمجة التطبيقات Screen Capture API للمستخدم اختيار علامة تبويب أو نافذة أو شاشة لتسجيلها كبث وسائط. ويمكن بعد ذلك تسجيل هذا البث أو مشاركته مع الآخرين عبر الشبكة. يقدّم هذا المستند ميزة "التركيز الشرطي"، وهي آلية لتطبيقات الويب للتحكّم في التركيز على علامة التبويب أو النافذة التي تم التقاطها عند بدء الالتقاط، أو في ما إذا كانت صفحة التسجيل ستبقى مركّزة.

دعم المتصفح

تتوفّر ميزة "التركيز المشروط" في الإصدار 109 من Chrome.

الخلفية

عندما يبدأ تطبيق الويب في تسجيل علامة تبويب أو نافذة، يواجه المتصفّح قرارًا: هل يجب عرض المساحة التي تم تسجيلها في المقدّمة، أم يجب أن تظل الصفحة التي يتم التسجيل منها هي محل التركيز؟ تعتمد الإجابة على سبب طلب الرقم getDisplayMedia()، وتظهر نتائج البحث للمستخدمِين أمامهم.

لنفترض أنّ هناك تطبيقًا افتراضيًا على الويب لعقد اجتماعات الفيديو. من خلال قراءة track.getSettings().displaySurface وربما فحص اسم معرِّف الالتقاط، يمكن لتطبيق الويب لعقد اجتماعات الفيديو فهم ما اختار المستخدم مشاركته. بعد ذلك:

  • إذا كان من الممكن التحكم عن بُعد في علامة التبويب أو النافذة التي تم التقاطها، أبقِ مكالمة الفيديو محل التركيز.
  • وبخلاف ذلك، ركِّز على علامة التبويب أو النافذة التي تم تسجيلها.

في المثال أعلاه، سيحتفظ تطبيق الويب لمؤتمرات الفيديو بالتركيز في حال مشاركة مجموعة شرائح، ما يسمح للمستخدم بالانتقال من شريحة إلى أخرى عن بُعد، ولكن إذا اختار المستخدم مشاركة محرِّر نص، سينقل تطبيق الويب لمؤتمرات الفيديو التركيز على الفور إلى علامة التبويب أو النافذة التي تم التقاطها.

استخدام Conditional Focus 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() الذي تم إرجاعه، إذا شارك المستخدم شاشة (وليس علامة تبويب أو نافذة).

عيّنة

يمكنك اللعب باستخدام ميزة "التركيز الشرطي" من خلال تنفيذ العرض التوضيحي على أداة 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 وإعلامنا بمكان استخدامها وكيفية استخدامها.

الشكر والتقدير

صورة رئيسية من إعداد إيلينا تارانينكو

نشكر راشيل أندرو على مراجعة هذه المقالة.