קבלת מידע על מסכים מחוברים ועל מיקום החלונות ביחס למסכים האלה.
ממשק API לניהול חלונות
ה-Window Management API מאפשר לך לספור את המסכים שמחוברים למכונה שלך ולהציב חלונות במסכים ספציפיים.
תרחישים לדוגמה
דוגמאות לאתרים שעשויים להשתמש בממשק API זה:
- כלי עריכה גרפיים עם ריבוי חלונות יכולים להיעזר ב-Gimp כדי למקם כלי עריכה שונים בחלונות במיקום מדויק.
- בשולחנות המסחר הווירטואליים אפשר להציג את המגמות בשוק בכמה חלונות, שבכל אחד מהם אפשר להציג במצב מסך מלא.
- אפליקציות מצגת יכולות להציג הערות דובר במסך הראשי הפנימי ובמצגת במקרן חיצוני.
איך משתמשים ב-Window Management API
הבעיה
לצערנו, הגישה שנבדקה בזמן לשליטה בחלונות, Window.open()
, לא מודעת למסכים נוספים. חלק מההיבטים של ה-API הזה נראים קצת מיושנים, למשל הפרמטר
windowFeatures
DOMString
שלו, אבל הוא שירת אותנו היטב לאורך השנים. כדי לציין את המיקום של החלון, אפשר להעביר את הקואורדינטות כ-left
ו-top
(או screenX
ו-screenY
בהתאמה) ולהעביר את הגודל הרצוי כ-width
ו-height
(או innerWidth
ו-innerHeight
בהתאמה). לדוגמה, כדי לפתוח חלון בגודל 400×300 פיקסלים משמאל ו-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;
});
הדפדפן יכול לבחור להציג את הבקשה להרשאה באופן דינמי בניסיון הראשון להשתמש באחת מהשיטות של ה-API החדש. מידע נוסף מפורט בהמשך.
הנכס 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, אבל אפשר להחליף את הצורה שלו כדי לקודד אך ורק מול ה-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. זה תפס אותי לגמרי והשאיר אותי עם הידיים על הפנים.
אפשר לשחק בהדגמה שמוטמעת בהמשך, או לראות את קוד המקור שלה עם תקלה.
אבטחה והרשאות
צוות Chrome תכנן והטמיע את window Management API באמצעות עקרונות הליבה שהוגדרו במאמר שליטה בגישה לתכונות מתקדמות של פלטפורמת אינטרנט, כולל בקרת משתמשים, שקיפות וארגונומיה. ה-Window Management API חושף מידע חדש על המסכים שמחוברים למכשיר, ומגדיל את השטח ליצירת טביעות אצבע של משתמשים, במיוחד משתמשים שיש להם מספר מסכים שמחוברים באופן עקבי למכשירים שלהם. כדי להפחית את הפגיעה בפרטיות, מאפייני המסך החשוף מוגבלים למינימום הדרוש בתרחישים נפוצים של מיקומי מודעות. נדרשת הרשאת משתמש כדי שאתרים יוכלו לקבל מידע על ריבוי מסכים ולהציב חלונות במסכים אחרים. למרות ש-Chromium מחזיר תוויות מסך מפורטות, דפדפנים יכולים להחזיר בצורה פחות תיאורית (או אפילו תוויות ריקות).
בקרת משתמשים
למשתמש יש שליטה מלאה על החשיפה של ההגדרות שלו. הם יכולים לקבל או לדחות את בקשת ההרשאה, ולבטל הרשאה שהוענקה בעבר דרך התכונה 'פרטי אתרים' בדפדפן.
בקרה ארגונית
משתמשי Chrome Enterprise יכולים לשלוט בכמה היבטים של window Management API, כפי שמתואר בקטע הרלוונטי בהגדרות של Atomic Policy Groups.
שקיפות
העובדה אם ההרשאה לשימוש ב-Window Management API הוענקה גלויה בפרטי האתר של הדפדפן וניתן להריץ שאילתות לגביה גם דרך Permissions API.
שמירת הרשאה
הדפדפן ממשיך להעניק הרשאות. ניתן לבטל את ההרשאה באמצעות פרטי האתר של הדפדפן.
משוב
צוות Chrome ישמח לשמוע על החוויה שלך בשימוש ב-Window Management API.
לספר לנו על עיצוב ה-API
האם יש משהו ב-API שלא פועל כצפוי? או האם חסרים שיטות או מאפיינים שאתם צריכים ליישם את הרעיון? יש לכם שאלה או הערה לגבי מודל האבטחה?
- שלחו בעיה במפרט במאגר GitHub המתאים, או הוסיפו את המחשבות שלכם לבעיה קיימת.
דיווח על בעיה בהטמעה
האם מצאת באג בהטמעה של Chrome? או שההטמעה שונה מהמפרט?
- אפשר לדווח על באג בכתובת new.crbug.com. חשוב לכלול כמה שיותר פרטים, הוראות פשוטות לשחזור, ולהזין
Blink>Screen>MultiScreen
בתיבה רכיבים. גליץ' הוא כלי מעולה לשיתוף גיבויים מהירים וקלים.
הבעת תמיכה ב-API
האם בכוונתך להשתמש ב-Window Management API? התמיכה הציבורית עוזרת לצוות Chrome לקבוע סדרי עדיפות לתכונות, ומראה לספקי דפדפנים אחרים עד כמה חשוב התמיכה בהן.
- נשמח לדעת איך בכוונתך להשתמש בה בשרשור של WiCG ב-Wi-Fi.
- שלח ציוץ אל @ChromiumDev באמצעות ה-hashtag
#WindowManagement
וספר לנו איפה ואיך אתם משתמשים בו. - בקשו מספקי דפדפנים אחרים להטמיע את ה-API.
קישורים שימושיים
- טיוטת המפרט
- הודעת הסבר ציבורית
- הדגמה של ממשק API לניהול חלונות | מקור הדגמה של ממשק ה-API לניהול
- באג במעקב ב-Chromium
- רשומת ChromeStatus.com
- רכיב הבהוב:
Blink>Screen>MultiScreen
- תיוג ביקורת
- כוונת ניסוי
אישורים
המפרט של window Management API נערך על ידי ויקטור קוסטן, ג'ושוע בל ומייק וואסרמן. ה-API הוטמע על ידי Mike Wasserman ו-Adrienne ווקר. המאמר הזה נכתב על ידי Joe Medley, François Beaufort ו-Kayce Basques. תודה ללורה טורנט פואיג על התמונות.