إدارة عدة شاشات باستخدام Window Management API

الحصول على معلومات حول الشاشات المرتبطة وتحديد موضع النوافذ بالنسبة إلى شاشات العرض هذه.

واجهة برمجة التطبيقات Window Management API

تتيح لك Window Management API تعداد شاشات العرض المتصلة بجهازك. ولوضع النوافذ على شاشات محددة.

حالات الاستخدام المقترَحة

تتضمّن أمثلة المواقع الإلكترونية التي قد تستخدم واجهة برمجة التطبيقات هذه ما يلي:

  • أدوات تحرير رسومات متعددة النوافذ بإمكان Gimp وضع العديد من أدوات التحرير في نوافذ ذات مواضع دقيقة.
  • يمكن أن تظهر مكاتب التداول الافتراضية اتجاهات السوق في نوافذ متعددة يمكن مشاهدة أي منها في وضع ملء الشاشة.
  • يمكن لتطبيقات عرض الشرائح إظهار ملاحظات المحاضر على الشاشة الأساسية الداخلية والعرض التقديمي على جهاز العرض الخارجي.

كيفية استخدام واجهة برمجة التطبيقات Window Management API

المشكلة

والنهج الذي تم اختباره زمنيًا للتحكم في النوافذ، Window.open()، للأسف غير مدركين للشاشات الإضافية. وعلى الرغم من أنّ بعض جوانب واجهة برمجة التطبيقات هذه تبدو قديمة بعض الشيء، مثل windowFeatures DOMString، إلا أنها استفدت من الخدمة كثيرًا على مر السنين. لتحديد نافذة position، يمكنك تمرير left وtop (أو screenX وscreenY على التوالي) وتمرير المقاس ضمن width وheight (أو innerWidth وinnerHeight على التوالي). على سبيل المثال، لفتح نافذة 400×300 على بُعد 50 بكسل من اليسار و50 بكسل من الأعلى، هذه هي الكود الذي المستخدم:

const popup = window.open(
  'https://example.com/',
  'My Popup',
  'left=50,top=50,width=400,height=300',
);

يمكنك الحصول على معلومات حول الشاشة الحالية من خلال الاطّلاع على window.screen، تعرض الكائن Screen. هذه هي الناتج على جهاز MacBook Pro 13":

window.screen;
/* Output from my MacBook Pro 13″:
  availHeight: 969
  availLeft: 0
  availTop: 25
  availWidth: 1680
  colorDepth: 30
  height: 1050
  isExtended: true
  onchange: null
  orientation: ScreenOrientation {angle: 0, type: "landscape-primary", onchange: null}
  pixelDepth: 30
  width: 1680
*/

ومثل معظم العاملين في مجال التكنولوجيا، اضطررت إلى تكييف نفسي مع واقع العمل الجديد وإعداد مكتب منزلي شخصي. يبدو لي في الصورة أدناه (إذا كنت مهتمًا، يمكنك قراءة التفاصيل الكاملة حول الإعداد). يتم توصيل جهاز iPad المجاور لجهاز MacBook بالكمبيوتر المحمول عبر Sidecar، فمتى أحتاج إلى ذلك، يمكنني تحويل نقل جهاز iPad إلى شاشة ثانية

مقعد مدرسي على كرسيين. وفي أعلى مقعد المدرسة توجد صناديق أحذية تدعم جهاز كمبيوتر محمول وتحيط به جهازي iPad.
إعداد شاشات متعددة:

إذا أردت الاستفادة من الشاشة الأكبر، يمكنني وضع النافذة المنبثقة من نموذج التعليمات البرمجية أعلاه في الشاشة الثانية. أنا أفعل ذلك النحو التالي:

popup.moveTo(2500, 50);

هذا تخمين تقريبي، حيث لا توجد طريقة لمعرفة أبعاد الشاشة الثانية. المعلومات من window.screen: يغطي الشاشة المدمَجة فقط، وليس شاشة iPad. width التي تم الإبلاغ عنها من الشاشة المضمنة 1680 بكسل، لذا فإن الانتقال إلى 2500 بكسل قد يعمل على تغيير إلى جهاز iPad، لأنّ أنا أعرف أنّه يقع على يمين جهاز MacBook. الطريقة هل يمكنني إجراء ذلك في الحالة العامة؟ تبين أن هناك طريقة أفضل من التخمين. بهذه الطريقة واجهة برمجة التطبيقات Window Management API

رصد الميزات

للتحقّق مما إذا كانت واجهة برمجة التطبيقات Window Management API متوافقة، استخدِم:

if ('getScreenDetails' in window) {
  // The Window Management API is supported.
}

الإذن window-management

يجب أن أطلب من المستخدم الإذن لتنفيذ هذا الإجراء كي أتمكّن من استخدام واجهة برمجة التطبيقات Window Management API. يمكن البحث عن إذن "window-management" باستخدام Permissions API على النحو التالي:

let granted = false;
try {
  const { state } = await navigator.permissions.query({ name: 'window-management' });
  granted = state === 'granted';
} catch {
  // Nothing.
}

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

async function getWindowManagementPermissionState() {
  let state;
  // The new permission name.
  try {
    ({ state } = await navigator.permissions.query({
      name: "window-management",
    }));
  } catch (err) {
    return `${err.name}: ${err.message}`;
  }
  return state;
}

document.querySelector("button").addEventListener("click", async () => {
  const state = await getWindowManagementPermissionState();
  document.querySelector("pre").textContent = state;
});

المتصفح يمكن عرض طلب الحصول على الإذن ديناميكيًا عند أول محاولة لاستخدام أي من طرق واجهة برمجة التطبيقات الجديدة. تابع القراءة لمعرفة المزيد.

السمة window.screen.isExtended

لمعرفة ما إذا كانت هناك أكثر من شاشة متصلة بجهازي، يمكن الوصول إلى الموقع: window.screen.isExtended. وهي تعرض true أو false. بالنسبة إلى الإعداد الخاص بي، تعرض الأداة true.

window.screen.isExtended;
// Returns `true` or `false`.

الطريقة getScreenDetails()

الآن بعد أن تعرفت على أن الإعداد الحالي متعدد الشاشات، يمكنني الحصول على مزيد من المعلومات حول شاشة ثانية باستخدام Window.getScreenDetails(). سيؤدي استدعاء هذه الدالة إلى ظهور طلب للحصول على إذن يسألني ما إذا كان بإمكان الموقع فتح النوافذ ووضعها على شاشتي. تُرجع الدالة وعدًا يتم حلها باستخدام كائن ScreenDetailed. على جهاز MacBook Pro 13 مع جهاز iPad متصل، ويتضمّن ذلك حقل screens مع كائنَين من النوع ScreenDetailed:

await window.getScreenDetails();
/* Output from my MacBook Pro 13″ with the iPad attached:
{
  currentScreen: ScreenDetailed {left: 0, top: 0, isPrimary: true, isInternal: true, devicePixelRatio: 2, …}
  oncurrentscreenchange: null
  onscreenschange: null
  screens: [{
    // The MacBook Pro
    availHeight: 969
    availLeft: 0
    availTop: 25
    availWidth: 1680
    colorDepth: 30
    devicePixelRatio: 2
    height: 1050
    isExtended: true
    isInternal: true
    isPrimary: true
    label: "Built-in Retina Display"
    left: 0
    onchange: null
    orientation: ScreenOrientation {angle: 0, type: "landscape-primary", onchange: null}
    pixelDepth: 30
    top: 0
    width: 1680
  },
  {
    // The iPad
    availHeight: 999
    availLeft: 1680
    availTop: 25
    availWidth: 1366
    colorDepth: 24
    devicePixelRatio: 2
    height: 1024
    isExtended: true
    isInternal: false
    isPrimary: false
    label: "Sidecar Display (AirPlay)"
    left: 1680
    onchange: null
    orientation: ScreenOrientation {angle: 0, type: "landscape-primary", onchange: null}
    pixelDepth: 24
    top: 0
    width: 1366
  }]
}
*/

تتوفّر معلومات حول الشاشات المرتبطة في مصفوفة "screens". لاحظ كيف أن قيمة يبدأ left لجهاز iPad من 1680، وهو بالضبط width للشاشة المدمجة. هذا النمط تسمح لي بتحديد كيفية ترتيب الشاشات بالضبط بشكل منطقي (بجوار بعضها البعض، أعلى بعضها البعض، وما إلى ذلك). تتوفّر أيضًا بيانات الآن لكل شاشة لتوضيح ما إذا كانت شاشة "isInternal". وما إذا كانت القيمة isPrimary. لاحظ أن الشاشة المدمجة ليس بالضرورة الشاشة الأساسية.

الحقل currentScreen هو كائن مباشر يوازي قيمة window.screen الحالية. الكائن يتم تعديل مواضع الإعلانات على النوافذ على الشاشات المختلفة أو تغييرات الأجهزة.

الحدث screenschange

الشيء الوحيد غير المتاح الآن هو طريقة لرصد تغييرات إعدادات الشاشة. حدث جديد، وتنفِّذ screenschange ذلك بالضبط: حيث يتم تنشيطها كلما تم تعديل مجموعة الصور البانورامية للشاشة. (إشعار أن "الشاشات" صيغة الجمع في اسم الحدث.) وهذا يعني أنه يتم تنشيط الحدث عندما يتم تنشيط شاشة جديدة أو توصيل الشاشة الحالية (فعليًا أو افتراضيًا في حالة استخدام Sidecar) بالكهرباء أو فصلها.

يُرجى العلم أنّه عليك البحث عن تفاصيل الشاشة الجديدة بشكل غير متزامن، وهو حدث screenschange. نفسه لا يقدم هذه البيانات. للبحث عن تفاصيل الشاشة، يمكنك استخدام الكائن المباشر من نسخة مخزَّنة مؤقتًا. واجهة Screens.

const screenDetails = await window.getScreenDetails();
let cachedScreensLength = screenDetails.screens.length;
screenDetails.addEventListener('screenschange', (event) => {
  if (screenDetails.screens.length !== cachedScreensLength) {
    console.log(
      `The screen count changed from ${cachedScreensLength} to ${screenDetails.screens.length}`,
    );
    cachedScreensLength = screenDetails.screens.length;
  }
});

الحدث currentscreenchange

إذا كنت مهتمًا فقط بالتغييرات التي يتم إجراؤها على الشاشة الحالية (أي قيمة العنصر المباشر) currentScreen)، يمكنني الاستماع إلى حدث "currentscreenchange".

const screenDetails = await window.getScreenDetails();
screenDetails.addEventListener('currentscreenchange', async (event) => {
  const details = screenDetails.currentScreen;
  console.log('The current screen has changed.', event, details);
});

الحدث change

أخيرًا، إذا كنت مهتمًا فقط بإجراء تغييرات على شاشة خرسانية، يمكنني الاستماع إلى حدث واحد (change).

const firstScreen = (await window.getScreenDetails())[0];
firstScreen.addEventListener('change', async (event) => {
  console.log('The first screen has changed.', event, firstScreen);
});

خيارات جديدة بملء الشاشة

حتى الآن، يمكنك طلب عرض العناصر في وضع ملء الشاشة عبر القنوات التي requestFullScreen() . تأخذ الطريقة مَعلمة options حيث يمكنك تمريرها. FullscreenOptions حتى الآن، موقعه الوحيد navigationUI تضيف واجهة برمجة التطبيقات Window Management API سمة screen جديدة تتيح لك تحديد. الشاشة التي تريد بدء العرض بملء الشاشة عليها. على سبيل المثال، إذا كنت تريد جعل الشاشة الأساسية ملء الشاشة:

try {
  const primaryScreen = (await getScreenDetails()).screens.filter((screen) => screen.isPrimary)[0];
  await document.body.requestFullscreen({ screen: primaryScreen });
} catch (err) {
  console.error(err.name, err.message);
}

الملء التلقائي

لا يمكن تعويض واجهة برمجة التطبيقات Window Management API، ولكن يمكنك تعديل شكلها بحيث يمكنك الترميز حصريًا باستخدام واجهة برمجة التطبيقات الجديدة:

if (!('getScreenDetails' in window)) {
  // Returning a one-element array with the current screen,
  // noting that there might be more.
  window.getScreenDetails = async () => [window.screen];
  // Set to `false`, noting that this might be a lie.
  window.screen.isExtended = false;
}

الجوانب الأخرى لواجهة برمجة التطبيقات، وهي الأحداث المختلفة لتغيير الشاشة والسمة screen فإن FullscreenOptions، ببساطة، لن تطلق أبدًا أو يتم تجاهلها تلقائيًا على التوالي من خلال المتصفحات التي لا تعمل.

عرض توضيحي

إذا كنت أي شيء مثلي، تراقب عن كثب تطور العملات المشفّرة. (في الواقع أنا لا أحب هذا الكوكب كثيرًا، ولكنني بالنسبة إلى هذه المقالة، افترض فقط أنني did.) لتتبّع العملات المشفّرة التي أملكها، ابتكرتُ تطبيق ويب يتيح لي أشاهد الأسواق في كل مواقف حياتي، مثل وأنت مرتاح في سريري، حيث أستيقظ من إعداد شاشة واحدة.

شاشة تلفزيون ضخمة في نهاية سرير مع ظهور ساقَي المؤلف جزئيًا يظهر على الشاشة مكتب مزيّف لتداول العملات المشفّرة.
الاسترخاء ومشاهدة الأسواق

إذا كان هذا الأمر يتعلّق بالعملات المشفّرة، قد تكون هناك صعوبات في الأسواق في أي وقت. وإذا حدث ذلك، فيمكنني بسرعة سأنتقل إلى مكتبي حيث يتوفر لدي إعداد للشاشات المتعددة. يمكنني النقر فوق نافذة أي عملة الاطّلاع سريعًا على التفاصيل الكاملة في عرض ملء الشاشة على الشاشة المعاكسة يوجد أدناه صورة حديثة لـ التي التقطتها خلال آخر موضة دماء YCY. اصطحبني فجأة تمامًا وتركتني مع وضع يدي على وجهي.

المؤلف يمسك بيديه وجهه المذعور ويحدّق في مكتب تداول العملات المشفَّرة المزيفة
ذعر، ويشاهدون دماء YCY

يمكنك استخدام العرض التوضيحي المضمّن أدناه أو الاطّلاع على الرمز المصدر الخاص به بسبب العطل.

الأمان والأذونات

صمم فريق Chrome ونفذ واجهة برمجة التطبيقات Window Management API باستخدام المحددة في التحكُّم في الوصول إلى ميزات النظام الأساسي للويب الفعّالة بما في ذلك تحكُّم المستخدم والشفافية وتسهيل الاستخدام. تعرض واجهة برمجة التطبيقات Window Management API معلومات جديدة حول الشاشات المتصلة بأحد الأجهزة، مما يزيد من سطح البصمات للمستخدمين، خاصة أولئك الذين لديهم شاشات متعددة مرتبطة باستمرار بأجهزتهم. كواحد وللتخفيف من حدة هذه المشكلة المتعلقة بالخصوصية، تقتصر خصائص الشاشة المكشوفة على الحد الأدنى للتعرّف على حالات استخدام المواضع الشائعة. يجب الحصول على إذن المستخدم لتتمكّن المواقع الإلكترونية من عرض شاشات متعددة المعلومات ووضع النوافذ على الشاشات الأخرى. يعرض Chromium تصنيفات الشاشة التفصيلية، المتصفحات لها حرية عرض تصنيفات أقل وصفية (أو حتى تسميات فارغة).

تحكم المستخدم

يمكن للمستخدم التحكّم بشكل كامل في عدد الأشخاص الظاهرين في الإعدادات. يمكنه قبول أو رفض طلب الحصول على إذن، وإبطال إذن تم منحه سابقًا عبر ميزة معلومات الموقع في المتصفح.

تحكُّم في المؤسسة

يمكن لمستخدمي Chrome Enterprise التحكّم في العديد من جوانب واجهة برمجة التطبيقات Window Management API مثل الموضحة في القسم ذي الصلة مجموعات السياسات الصغيرة الإعدادات.

الشفافية

تأكيد ما إذا كان قد تم منح الإذن لاستخدام واجهة برمجة التطبيقات Window Management API أم لا الكشف عنها في معلومات موقع المتصفح، كما يمكن طلبها من خلال واجهة برمجة التطبيقات Permissions API.

استمرار الإذن

يستمر المتصفّح في منح الأذونات. يمكن إبطال الإذن من خلال الموقع الإلكتروني للمتصفّح. المعلومات.

ملاحظات

يود فريق Chrome معرفة المزيد عن تجاربك في استخدام واجهة برمجة التطبيقات Window Management API.

أخبِرنا عن تصميم واجهة برمجة التطبيقات

هل هناك أي مشكلة في واجهة برمجة التطبيقات لا تعمل بالشكل الذي توقعته؟ أم أن هناك طرق مفقودة أو الخصائص التي تحتاج إليها لتنفيذ فكرتك؟ طرح سؤال أو تعليق بشأن الأمان النموذج؟

  • يُرجى الإبلاغ عن مشكلة في المواصفات حول مستودع GitHub ذي الصلة، أو إضافة أفكارك إلى المشكلة.

الإبلاغ عن مشكلة في التنفيذ

هل واجهت مشكلة في التنفيذ في Chrome؟ أم أن التنفيذ يختلف عن المواصفات؟

  • يُرجى الإبلاغ عن الخطأ على new.crbug.com. تأكد من تضمين أكبر قدر ممكن من التفاصيل يمكنك، والتعليمات البسيطة لإعادة الإنتاج، وإدخال Blink>Screen>MultiScreen في مربع المكونات. تعمل ميزة الخطأ بشكلٍ رائع لمشاركة النسخ المُعاد إنتاجها بسرعة وسهولة.

إظهار الدعم لواجهة برمجة التطبيقات

هل لديك خطة لاستخدام واجهة برمجة تطبيقات إدارة النوافذ؟ يساعد دعمك العام متصفّح Chrome لتحديد أولويات الميزات وإظهار لموردي المتصفحات الآخرين مدى أهمية دعمهم لها.

  • شارِك الطريقة التي تنوي استخدامها بها في سلسلة محادثات WICG Discourse.
  • إرسال تغريدة إلى @ChromiumDev باستخدام علامة التصنيف #WindowManagement و أخبرنا بمكان وكيفية استخدامك له.
  • طلب تنفيذ واجهة برمجة التطبيقات من مورِّدي المتصفّحات الآخرين

روابط مفيدة

شكر وتقدير

تم تعديل مواصفات واجهة برمجة التطبيقات Window Management API من قِبل فيكتور كوستان، وJoshua Bell، مايك واسرمان تم تنفيذ واجهة برمجة التطبيقات بواسطة مايك واسرمان أدريان ووكر. تمت مراجعة هذه المقالة بواسطة جو ميدلي وفرانسوا بوفورت وكايس باسك. شكرًا لـ "لورا تورنت بويغ" على الصور.