לקבל מידע על מסכים מחוברים ולמקם חלונות ביחס למסכים האלה.
פורסם: 14 בספטמבר 2020
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
*/
כמו רוב האנשים שעובדים בתחום הטכנולוגיה, גם אני נאלצתי להסתגל למציאות של העבודה בשנת 2020, ולהקים משרד ביתי אישי. ההגדרה שלי נראית כמו בתמונה (אם זה מעניין אותך, אפשר לקרוא את הפרטים המלאים על ההגדרה שלי). ה-iPad שלי מחובר ל-MacBook באמצעות Sidecar, כך שאני יכול להפוך את ה-iPad למסך שני במהירות כשצריך.
אם רוצים לנצל את המסך הגדול יותר, אפשר להעביר את ההודעה הקופצת מהקוד לדוגמה למסך השני. ככה אני עושה את זה:
popup.moveTo(2500, 50);
זוהי הערכה גסה, כי אין דרך לדעת את המידות של המסך השני. המידע מ-window.screen מתייחס רק למסך המובנה, ולא למסך של האייפד. הרוחב המדווח של המסך המובנה היה width פיקסלים, ולכן מעבר ל-2500 פיקסלים עשוי להזיז את החלון לאייפד, כי ידוע לי שהוא ממוקם בצד ימין של המקבוק שלי.1680 איך אפשר לעשות את זה באופן כללי? מסתבר שיש דרך טובה יותר מניחוש. הדרך הזו היא 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 = as>ync () = [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.
התמדה של הרשאות
הדפדפן שומר את ההרשאות שניתנו. אפשר לבטל את ההרשאה דרך פרטי האתר בדפדפן.
משוב
האם יש משהו ב-API שלא פועל כמו שציפית? או שיש שיטות או מאפיינים חסרים שצריך להטמיע כדי לממש את הרעיון? יש לך שאלה או הערה לגבי מודל האבטחה?
- אפשר לפתוח בעיה במפרט במאגר GitHub המתאים, או להוסיף את המחשבות שלכם לבעיה קיימת.
- דיווח על באג בהטמעה של Chrome חשוב לכלול כמה שיותר פרטים, הוראות לשחזור הבעיה ולהזין
Blink>Screen>MultiScreenבתיבה רכיבים.
תמיכה ב-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. המאמר הזה נבדק על ידי ג'ו מדלי, פרנסואה בופור וקייסי באסקס. תודה ללורה טורנט פויג על התמונות.