الحصول على معلومات حول الشاشات المتصلة وتحديد موضع النوافذ بالنسبة إلى تلك الشاشات
Window Management API
تتيح لك واجهة برمجة التطبيقات Window Management API إدراج شاشات العرض المتصلة بجهازك ووضع النوافذ على شاشات محدّدة.
حالات الاستخدام المقترَحة
في ما يلي أمثلة على المواقع الإلكترونية التي قد تستخدم واجهة برمجة التطبيقات هذه:
- يمكن لمحرّرات الرسومات المتعددة النوافذ، مثل Gimp، وضع أدوات التعديل المختلفة في نوافذ موضوعة بدقة.
- يمكن أن تعرض منصات التداول الافتراضية مؤشرات السوق في نوافذ متعددة، ويمكن عرض أي منها في وضع ملء الشاشة.
- يمكن لتطبيقات العروض التقديمية عرض ملاحظات المحاضر على الشاشة الأساسية الداخلية والعرض التقديمي على جهاز عرض خارجي.
كيفية استخدام Window Management API
المشكلة
إنّ الطريقة المجربة والمختبرة للتحكّم في النوافذ،
Window.open()
، لا تتيح للأسف
التعرّف على الشاشات الإضافية. على الرغم من أنّ بعض جوانب واجهة برمجة التطبيقات هذه تبدو قديمة بعض الشيء، مثل المَعلمة
windowFeatures
DOMString
، إلا أنّها كانت مفيدة لنا على مر السنين. لتحديد موضع نافذة، يمكنك تمرير الإحداثيات كـ 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 إلى شاشة ثانية بسرعة عند الحاجة.

إذا أردت الاستفادة من الشاشة الأكبر، يمكنني وضع النافذة المنبثقة من نموذج الرمز أعلاه على الشاشة الثانية. أقوم بذلك على النحو التالي:
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);
}
Polyfill
لا يمكن تنفيذ Window Management API باستخدام polyfill، ولكن يمكنك محاكاة شكله حتى تتمكّن من كتابة الرمز البرمجي حصريًا باستخدام واجهة برمجة التطبيقات الجديدة:
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
، فلن يتم تشغيلها أو سيتم تجاهلها بدون تنبيه من قِبل المتصفحات غير المتوافقة.
عرض توضيحي
إذا كنت مثلي، فستراقب عن كثب تطوّر العملات المشفرة المختلفة. (في الواقع، أنا لا أوافق على ذلك لأنني أحب هذا الكوكب، ولكن لأغراض هذه المقالة، افترض أنّني أوافق على ذلك). لتتبُّع العملات المشفّرة التي أملكها، طوّرتُ تطبيق ويب يتيح لي متابعة الأسواق في جميع مواقف الحياة، مثلاً وأنا مستلقٍ على سريري حيث أستخدم شاشة واحدة.

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

يمكنك تجربة العرض التوضيحي المضمّن أدناه، أو الاطّلاع على الرمز المصدر على GitHub.
الأمان والأذونات
صمَّم فريق 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
في المربّع المكوّنات.
إظهار الدعم لواجهة برمجة التطبيقات
هل تخطّط لاستخدام Window Management API؟ يساعد دعمك العلني فريق Chrome في تحديد أولويات الميزات، ويوضّح لمورّدي المتصفّحات الآخرين مدى أهمية توفيرها.
- شارِك كيف تخطّط لاستخدامه في سلسلة محادثات WICG Discourse.
- يمكنك إرسال تغريدة إلى @ChromiumDev باستخدام الهاشتاغ
#WindowManagement
وإخبارنا بمكان استخدامك لهذه الميزة وكيفية استخدامها. - اطلب من مورّدي المتصفحات الآخرين تنفيذ واجهة برمجة التطبيقات.
روابط مفيدة
- مسودة المواصفات
- شرح علني
- عرض توضيحي لواجهة Window Management API | عرض توضيحي لواجهة Window Management API source
- خطأ تتبُّع Chromium
- إدخال ChromeStatus.com
- مكوّن Blink:
Blink>Screen>MultiScreen
- مراجعة TAG
- النية في إجراء تجربة
الإقرارات
تم تعديل مواصفات Window Management API بواسطة فيكتور كوستان و جوشوا بيل و مايك واسرمان. تم تنفيذ واجهة برمجة التطبيقات من قِبل مايك واسرمان و أدريان ووكر. راجع هذه المقالة جو ميدلي وفرانسوا بوفورت وكايسي باسكس. نشكر "لورا تورنت بويغ" على الصور.