לקבל מידע על מסכים מחוברים ולמקם חלונות ביחס למסכים האלה.
Window Management API
Window Management API מאפשר לכם למנות את המסכים שמחוברים למחשב ולמקם חלונות במסכים ספציפיים.
תרחישים לדוגמה
דוגמאות לאתרים שעשויים להשתמש בממשק ה-API הזה:
- עורכי גרפיקה עם חלונות מרובים כמו Gimp יכולים למקם כלי עריכה שונים בחלונות במיקום מדויק.
- בחדרי מסחר וירטואליים אפשר לראות מגמות שוק בכמה חלונות, וכל אחד מהם יכול להיות מוצג במסך מלא.
- באפליקציות להצגת שקפים אפשר להציג את הערות הדובר במסך הראשי הפנימי ואת המצגת במקרן חיצוני.
איך משתמשים ב-Window Management API
הבעיה
הגישה המוכחת לשליטה בחלונות, Window.open()
, לא מודעת למסכים נוספים. אומנם יש היבטים ב-API הזה שנראים קצת מיושנים, כמו הפרמטר windowFeatures
DOMString
, אבל הוא שימש אותנו היטב לאורך השנים. כדי לציין את המיקום של חלון, אפשר להעביר את הקואורדינטות כ-left
ו-top
(או כ-screenX
ו-screenY
בהתאמה) ולהעביר את הגודל הרצוי כ-width
ו-height
(או כ-innerWidth
ו-innerHeight
בהתאמה). לדוגמה, כדי לפתוח חלון בגודל 400x300 פיקסלים במרחק של 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 שלי מחובר למחשב הנייד שלי באמצעות Sidecar, כך שבכל פעם שאני צריך, אני יכול להפוך את ה-iPad למסך שני.

אם רוצים לנצל את המסך הגדול יותר, אפשר להעביר את החלון הקופץ מהקוד לדוגמה שמופיע למעלה למסך השני. ככה אני עושה את זה:
popup.moveTo(2500, 50);
זוהי הערכה גסה, כי אין דרך לדעת את המידות של המסך השני. המידע מ-window.screen
מתייחס רק למסך המובנה, ולא למסך של האייפד. הדיווח על 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;
});
הדפדפן יכול לבחור להציג את בקשת ההרשאה באופן דינמי בניסיון הראשון להשתמש באחת מהשיטות של ה-API החדש. מידע נוסף מופיע בהמשך.
הנכס window.screen.isExtended
כדי לדעת אם יותר ממסך אחד מחובר למכשיר שלי, אני ניגש למאפיין window.screen.isExtended
. הפונקציה מחזירה true
או false
. במקרה שלי, הפונקציה מחזירה true
.
window.screen.isExtended;
// Returns `true` or `false`.
השיטה getScreenDetails()
עכשיו כשאני יודע שההגדרה הנוכחית היא של מסך מפוצל, אני יכול לקבל מידע נוסף על המסך השני באמצעות Window.getScreenDetails()
. הפעלת הפונקציה הזו תציג בקשת הרשאה שבה תישאלו אם האתר יכול לפתוח חלונות ולהציב אותם במסך. הפונקציה מחזירה הבטחה (promise) שמושלמת עם אובייקט 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
באייפד מתחיל ב-1680
, שהוא בדיוק width
של המסך המובנה. כך אוכל לקבוע בדיוק איך המסכים מסודרים מבחינה לוגית (זה לצד זה, זה מעל זה וכו'). בנוסף, יש עכשיו נתונים לגבי כל מסך שמראים אם הוא isInternal
אחד
ואם הוא isPrimary
אחד. שימו לב שהמסך המובנה לא בהכרח המסך הראשי.
השדה currentScreen
הוא אובייקט פעיל שמתאים ל-window.screen
הנוכחי. האובייקט
מתעדכן במיקומי חלונות חוצי מסך או בשינויים במכשיר.
האירוע screenschange
הדבר היחיד שחסר עכשיו הוא דרך לזהות מתי ההגדרה של המסך שלי משתנה. אירוע חדש, screenschange
, עושה בדיוק את זה: הוא מופעל בכל פעם שמשנים את מערך המסכים. (שימו לב שהמילה screens היא ברבים בשם האירוע). המשמעות היא שהאירוע מופעל בכל פעם שמחברים או מנתקים מסך חדש או מסך קיים (פיזית או וירטואלית במקרה של 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, אבל אפשר להשתמש ב-shim כדי לשנות את הצורה שלו, כך שתוכלו לכתוב קוד רק ל-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;
}
היבטים אחרים של ה-API, כלומר אירועים שונים של שינוי מסך והמאפיין screen
של FullscreenOptions
, פשוט לא יופעלו או שיתעלמו מהם בדפדפנים שלא תומכים בהם.
הדגמה (דמו)
אם אתם כמוני, אתם עוקבים מקרוב אחרי ההתפתחות של המטבעות הקריפטוגרפיים השונים. (במציאות, אני ממש לא רוצה כי אני אוהב את כדור הארץ, אבל לצורך המאמר הזה, נניח שכן). כדי לעקוב אחרי מטבעות קריפטו שבבעלותי, פיתחתי אפליקציית אינטרנט שמאפשרת לי לצפות בשווקים בכל מצב בחיים, למשל מנוחות המיטה שלי, שבה יש לי הגדרה הגונה של מסך יחיד.

מכיוון שמדובר במטבעות קריפטו, השווקים יכולים להיות עמוסים בכל רגע. אם זה יקרה, אוכל לעבור במהירות לשולחן שלי, שבו יש לי הגדרה של כמה מסכים. אני יכול ללחוץ על חלון של מטבע כלשהו ולראות במהירות את כל הפרטים בתצוגת מסך מלא במסך השני. למטה מצורפת תמונה שלי שצולמה לאחרונה במהלך YCY bloodbath האחרון. זה תפס אותי בהפתעה מוחלטת והשאיר אותי עם הידיים על הפנים.

אפשר להתנסות בהדגמה שמוטמעת בהמשך, או לעיין בקוד המקור שלה ב-GitHub.
אבטחה והרשאות
צוות Chrome תכנן והטמיע את Window Management API על סמך העקרונות המרכזיים שמוגדרים במאמר שליטה בגישה לתכונות עוצמתיות של פלטפורמת האינטרנט, כולל שליטה של המשתמש, שקיפות וארגונומיה. ממשק ה-API לניהול חלונות חושף מידע חדש על המסכים שמחוברים למכשיר, וכך מגדיל את שטח הפנים של טביעת האצבע של המשתמשים, במיוחד אלה שמחוברים למכשירים שלהם באופן עקבי עם כמה מסכים. כדי לצמצם את הסיכון לבעיות פרטיות, מאפייני המסך שחשופים מוגבלים למינימום הנדרש לתרחישי שימוש נפוצים של מיקום. נדרשת הרשאת משתמש כדי שאתרים יוכלו לקבל מידע על כמה מסכים ולמקם חלונות במסכים אחרים. Chromium מחזיר תוויות מפורטות למסך, אבל דפדפנים אחרים יכולים להחזיר תוויות פחות תיאוריות (או אפילו תוויות ריקות).
שליטת משתמשים
המשתמש שולט באופן מלא בחשיפה של ההגדרה שלו. הם יכולים לאשר או לדחות את בקשת ההרשאה, ולבטל הרשאה שניתנה בעבר באמצעות התכונה 'פרטי האתר' בדפדפן.
שליטה בארגון
משתמשי Chrome Enterprise יכולים לשלוט בכמה היבטים של Window Management API, כמו שמתואר בקטע הרלוונטי בהגדרות של קבוצות מדיניות אטומיות.
שקיפות
העובדה שההרשאה להשתמש ב-Window Management API ניתנה מוצגת בפרטי האתר בדפדפן, ואפשר גם לשלוח שאילתה לגביה דרך Permissions API.
התמדה של הרשאות
הדפדפן שומר את ההרשאות שניתנו. אפשר לבטל את ההרשאה דרך פרטי האתר בדפדפן.
משוב
צוות Chrome רוצה לשמוע על החוויות שלכם עם Window Management API.
נשמח לקבל מידע על עיצוב ה-API
האם יש משהו ב-API שלא פועל כמו שציפית? או שיש שיטות או מאפיינים חסרים שצריך להטמיע כדי לממש את הרעיון? יש לך שאלה או הערה לגבי מודל האבטחה?
- אפשר לפתוח בקשה בנושא מפרט במאגר GitHub המתאים, או להוסיף את המחשבות שלכם לבקשה קיימת.
דיווח על בעיה בהטמעה
מצאתם באג בהטמעה של Chrome? או שההטמעה שונה מהמפרט?
- מדווחים על הבאג בכתובת new.crbug.com. חשוב לכלול כמה שיותר פרטים, הוראות פשוטות לשחזור הבאג ולהזין
Blink>Screen>MultiScreen
בתיבה Components.
תמיכה ב-API
האם בכוונתך להשתמש ב-Window Management API? התמיכה הציבורית שלכם עוזרת לצוות Chrome לתעדף תכונות ומראה לספקי דפדפנים אחרים עד כמה חשוב לתמוך בהן.
- אפשר לשתף את התוכניות שלכם לשימוש ב-שרשור ב-WICG Discourse.
- אפשר לשלוח ציוץ אל @ChromiumDev באמצעות ההאשטאג
#WindowManagement
ולספר לנו איפה ואיך אתם משתמשים בו. - לבקש מספקי דפדפנים אחרים להטמיע את ה-API.
קישורים שימושיים
- Spec draft
- הסבר לציבור
- הדגמה של Window Management API | הדגמה של Window Management API מקור
- באג במעקב ב-Chromium
- ערך ב-ChromeStatus.com
- רכיב Blink:
Blink>Screen>MultiScreen
- TAG Review
- הבעת כוונות לניסוי
תודות
מפרט Window Management API נערך על ידי Victor Costan, Joshua Bell ו-Mike Wasserman. ה-API הוטמע על ידי Mike Wasserman ועל ידי Adrienne Walker. המאמר הזה נבדק על ידי ג'ו מדלי, פרנסואה בופור וקייסי בסקס. תודה ללורה טורנט פויג על התמונות.