يمكنك الحصول على معلومات عن الشاشات المتصلة وتحديد موضع النوافذ بالنسبة إلى تلك الشاشات.
واجهة برمجة التطبيقات Window Management
تُتيح لك واجهة برمجة التطبيقات 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 بسرعة إلى شاشة ثانية كلما احتجت إلى ذلك.
![مقعد مدرسي على كرسيين. فوق مقعد المدرسة توجد صناديق أحذية تدعم جهاز كمبيوتر محمول وجهازَي iPad يحيطان به.](https://developer.chrome.google.cn/static/docs/capabilities/web-apis/window-management/image/school-bench-two-chairs-8465336393f71.jpg?authuser=8&hl=ar)
إذا أردت الاستفادة من الشاشة الأكبر، يمكنني وضع النافذة المنبثقة من نموذج الرمز البرمجي أعلاه على الشاشة الثانية. أنا أفعل ذلك هكذا:
popup.moveTo(2500, 50);
هذا تخمين تقريبي، لأنه لا توجد طريقة لمعرفة أبعاد الشاشة الثانية. تشمل المعلومات الواردة من "window.screen
" الشاشة المدمجة فقط، ولا تشمل شاشة iPad. كانت نسبة width
من الشاشة المدمجة التي تم الإبلاغ عنها 1680
بكسل، لذلك قد يساعد الانتقال إلى 2500
بكسل على نقل النافذة إلى جهاز iPad، لأنّني أعرف أنّ هذه الشاشة على يمين جهاز MacBook. كيف يمكنني القيام بذلك في الحالة العامة؟ اتضح أن هناك طريقة أفضل من التخمين. بهذه الطريقة هي
واجهة برمجة التطبيقات لإدارة النوافذ.
رصد الميزات
للتحقّق من توفُّر واجهة برمجة التطبيقات 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
"، هذا الإجراء تمامًا، إذ يتم تنشيطه كلما تم تعديل مجموعة الصور البانورامية للشاشة. (لاحظ أن "الشاشات" هي صيغة جمع في اسم الحدث). هذا يعني أنّ الحدث يبدأ كلّما تم توصيل شاشة جديدة أو شاشة حالية (فعليًا أو افتراضيًا في حال استخدام Si Decar) أو فصله عن مصدر الطاقة.
ملاحظة: تحتاج إلى البحث عن تفاصيل الشاشة الجديدة بشكل غير متزامن، ولا يوفّر حدث 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
، فلن يتم تنشيطها مطلقًا أو يتم تجاهلها بدون تجاهل على التوالي من خلال المتصفّحات غير المتوافقة.
عرض توضيحي
إذا كنت مثلي، تراقب عن كثب تطوّر العملات المشفّرة المختلفة. (في الواقع، لا أحب هذا الكوكب كثيرًا، ولكن أفترض أنني أحببت هذه الكوكب في هذه المقالة.) لتتبع العملات المشفّرة التي أملكها، طوّرت تطبيق ويب يتيح لي مشاهدة الأسواق في جميع مواقف الحياة، مثل الاسترخاء في سريري، حيث أعمل على إعداد شاشة واحدة مناسبة.
![شاشة تلفزيون ضخمة في نهاية السرير تظهر جزئيًا ساقي المؤلف تظهر على الشاشة مكتب مزيّف لتداول العملات المشفّرة.](https://developer.chrome.google.cn/static/docs/capabilities/web-apis/window-management/image/massive-tv-screen-the-en-c57bfb0e325ff.jpg?authuser=8&hl=ar)
بالنسبة إلى العملات المشفّرة، يمكن أن تكون الأسواق مشغولة في أي وقت. إذا حدث ذلك، يمكنني الانتقال بسرعة إلى مكتبي حيث لدي إعداد متعدد الشاشات. يمكنني النقر فوق نافذة أي عملة ومشاهدة التفاصيل الكاملة بسرعة في عرض ملء الشاشة على الشاشة المقابلة. في ما يلي صورة حديثة لي تم التقاطها خلال آخر مضخ دماء YCY. لقد فاجأتني تمامًا وأصبحت واضعًا يدي على وجهي.
![المؤلف يديه على وجهه المذعور وينظران إلى مكتب تداول العملات المشفّرة الزائفة.](https://developer.chrome.google.cn/static/docs/capabilities/web-apis/window-management/image/the-author-his-hands-hi-0d430520b074a.jpg?authuser=8&hl=ar)
يمكنك تشغيل العرض التوضيحي المضمّن أدناه، أو الاطّلاع على رمز المصدر الخاص به بسبب حدوث خلل.
الأمان والأذونات
لقد صمّم فريق 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
في مربّع المكونات. تعمل ميزة Glitch بشكل رائع لمشاركة عمليات إعادة الإنشاء بسرعة وسهولة.
إظهار الدعم لواجهة برمجة التطبيقات
هل تخطّط لاستخدام واجهة برمجة التطبيقات Window Management API؟ يساعد الدعم المتاح للجميع فريق Chrome في تحديد أولويات الميزات ويُظهر لمورّدي المتصفِّح الآخرين مدى أهمية دعمهم لها.
- شارِك كيف تنوي استخدامها في سلسلة محادثات WICG Discourse.
- يمكنك إرسال تغريدة إلى @ChromiumDev باستخدام الهاشتاغ
#WindowManagement
وإعلامنا بمكان استخدامك لها وطريقة استخدامك لها. - طلب تنفيذ واجهة برمجة التطبيقات من مورِّدي المتصفِّح الآخرين
روابط مفيدة
- مسودة المواصفات
- شرح علني
- عرض توضيحي لواجهة برمجة تطبيقات إدارة النوافذ | مصدر العرض التوضيحي لواجهة برمجة تطبيقات إدارة النوافذ
- خطأ في تتبُّع Chromium
- إدخال ChromeStatus.com
- مكوّن Blink:
Blink>Screen>MultiScreen
- مراجعة TAG
- تنوي إجراء التجربة
شكر وتقدير
تم تعديل مواصفات واجهة برمجة التطبيقات Window Management API من قِبل Victor Costan وJoshua Bell وMike Wasserman. تم تنفيذ واجهة برمجة التطبيقات من قِبل Mike Wasserman وAdrienne Walker. راجعت هذه المقالة جو ميدلي وفرانسوا بوفورت وكايس باسك. شكرًا لورا تورنت بويغ على الصور.