uzyskiwać informacje o podłączonych wyświetlaczach i ustawiać okna względem nich;
Opublikowano: 14 września 2020 r.
Window Management API
Interfejs Window Management API umożliwia wyliczanie wyświetlaczy podłączonych do komputera i umieszczanie okien na określonych ekranach.
Sugerowane przypadki użycia
Przykłady witryn, które mogą korzystać z tego interfejsu API:
- Edytory graficzne z wieloma oknami, takie jak Gimp, mogą umieszczać różne narzędzia do edycji w dokładnie określonych oknach.
- Wirtualne platformy handlowe mogą wyświetlać trendy rynkowe w wielu oknach, z których każde można wyświetlić w trybie pełnoekranowym.
- Aplikacje do prezentacji mogą wyświetlać notatki prelegenta na wewnętrznym ekranie głównym, a prezentację na zewnętrznym projektorze.
Jak korzystać z interfejsu Window Management API
Sprawdzony sposób sterowania oknami,Window.open() niestety nie uwzględnia dodatkowych ekranów. Chociaż niektóre aspekty tego interfejsu API wydają się nieco przestarzałe, np. parametr windowFeatures
DOMString, to jednak przez lata dobrze nam służył. Aby określić położenie okna, możesz przekazać współrzędne jako left i top (lub odpowiednio screenX i screenY), a rozmiar jako width i height (lub odpowiednio innerWidth i innerHeight). Jeśli na przykład chcesz otworzyć okno o wymiarach 400 × 300 pikseli w odległości 50 pikseli od lewej krawędzi i 50 pikseli od górnej krawędzi, możesz użyć tego kodu:
const popup = window.open(
'https://example.com/',
'My Popup',
'left=50,top=50,width=400,height=300',
);
Informacje o bieżącym ekranie możesz uzyskać, sprawdzając właściwość window.screen, która zwraca obiekt Screen. Oto dane wyjściowe na moim MacBooku 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
*/
Jak większość osób pracujących w branży technologicznej musiałem dostosować się do realiów pracy w 2020 roku i skonfigurować osobiste biuro domowe. Mój wygląda tak jak na zdjęciu (jeśli chcesz, możesz przeczytać szczegółowe informacje o mojej konfiguracji). iPad obok MacBooka jest połączony z laptopem za pomocą funkcji Sidecar, więc w razie potrzeby mogę szybko przekształcić iPada w drugi ekran.
Jeśli chcę wykorzystać większy ekran, mogę przenieść wyskakujące okienko z przykładowego kodu na drugi ekran. Robię to tak:
popup.moveTo(2500, 50);
To tylko przybliżone oszacowanie, ponieważ nie ma możliwości poznania wymiarów drugiego ekranu. Informacje z window.screen obejmują tylko wbudowany ekran, a nie ekran iPada. Zgłoszona width
wartość wbudowanego ekranu wynosiła 1680 pikseli, więc przejście na 2500 pikseli może przesunąć okno na iPada, ponieważ wiem, że znajduje się on po prawej stronie mojego MacBooka. Jak mogę to zrobić w przypadku ogólnym? Okazuje się, że istnieje lepszy sposób niż zgadywanie. Jest to interfejs Window Management API.
Wykrywanie cech
Aby sprawdzić, czy interfejs Window Management API jest obsługiwany, użyj tego kodu:
if ('getScreenDetails' in window) {
// The Window Management API is supported.
}
Uprawnienie window-management
Zanim będę mógł używać interfejsu Window Management API, muszę poprosić użytkownika o zgodę na to. Uprawnienie window-management można sprawdzić za pomocą interfejsu Permissions API w ten sposób:
let granted = false;
try {
const { state } = await navigator.permissions.query({ name: 'window-management' });
granted = state === 'granted';
} catch {
// Nothing.
}
Dopóki przeglądarki z nową i starą nazwą uprawnień są w użyciu, podczas wysyłania prośby o uprawnienia używaj kodu defensywnego, jak w przykładzie.
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;
});
Przeglądarka może wyświetlać prośbę o przyznanie uprawnień dynamicznie przy pierwszej próbie użycia dowolnej metody nowego interfejsu API. Czytaj dalej, aby dowiedzieć się więcej.
Usługa window.screen.isExtended
Aby sprawdzić, czy do mojego urządzenia jest podłączony więcej niż 1 ekran, otwieram właściwość window.screen.isExtended. Zwraca wartość true lub false. W moim przypadku zwraca wartość true.
window.screen.isExtended;
// Returns `true` or `false`.
Metoda getScreenDetails()
Teraz, gdy wiem, że bieżąca konfiguracja obejmuje wiele ekranów, mogę uzyskać więcej informacji o drugim ekranie za pomocą Window.getScreenDetails(). Wywołanie tej funkcji spowoduje wyświetlenie prośby o uprawnienia, w której użytkownik zostanie zapytany, czy witryna może otwierać i umieszczać okna na jego ekranie. Funkcja zwraca obietnicę, która jest realizowana za pomocą obiektu ScreenDetailed. Na MacBooku Pro 13 z podłączonym iPadem obejmuje to pole screens z 2 obiektami 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
}]
}
*/
Informacje o połączonych ekranach są dostępne w tablicy screens. Zwróć uwagę, że wartość left na iPadzie zaczyna się od 1680, czyli dokładnie od width wbudowanego wyświetlacza. Dzięki temu mogę dokładnie określić, jak ekrany są rozmieszczone logicznie (obok siebie, jeden nad drugim itp.). Dostępne są też dane dotyczące każdego ekranu, które pokazują, czy jest on isInternal, czy isPrimary. Pamiętaj, że wbudowany ekran nie musi być ekranem głównym.
Pole currentScreen to aktywny obiekt odpowiadający bieżącemu window.screen. Obiekt
jest aktualizowany w przypadku umieszczeń w oknach na różnych ekranach lub zmian urządzeń.
Zdarzenie screenschange
Brakuje tylko sposobu wykrywania zmian w konfiguracji ekranu. Nowe zdarzenie,
screenschange, robi dokładnie to: uruchamia się za każdym razem, gdy zmienia się konfiguracja ekranu. (Zwróć uwagę, że w nazwie zdarzenia „screens” jest w liczbie mnogiej). Oznacza to, że zdarzenie jest wywoływane za każdym razem, gdy nowy ekran lub istniejący ekran jest podłączany lub odłączany (fizycznie lub wirtualnie w przypadku Sidecar).
Musisz asynchronicznie wyszukać szczegóły nowego ekranu, ponieważ samo zdarzenie screenschange nie zawiera tych danych. Aby sprawdzić szczegóły ekranu, użyj obiektu na żywo z interfejsu Screensw pamięci podręcznej.
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;
}
});
Zdarzenie currentscreenchange
Jeśli interesują mnie tylko zmiany na bieżącym ekranie (czyli wartość obiektu na żywo
currentScreen), mogę nasłuchiwać zdarzenia currentscreenchange.
const screenDetails = await window.getScreenDetails();
screenDetails.addEventListener('currentscreenchange', async (>event) = {
const details = screenDetails.currentScreen;
console.log('The current screen has changed.', event, details);
});
Zdarzenie change
Jeśli interesują mnie tylko zmiany na konkretnym ekranie, mogę nasłuchiwać zdarzenia change tego ekranu.
const firstScreen = (await window.getScreenDetails())[0];
firstScreen.addEventListener('change', async (>event) = {
console.log('The first screen has changed.', event, firstScreen);
});
Nowe opcje pełnego ekranu
Do tej pory można było poprosić o wyświetlenie elementów w trybie pełnoekranowym za pomocą metody o odpowiedniej nazwie
requestFullScreen(). Metoda przyjmuje parametr options, w którym możesz przekazać wartość FullscreenOptions. Do tej pory jedyną właściwością tej usługi była navigationUI.
Interfejs Window Management API dodaje nową właściwość screen, która pozwala określić, na którym ekranie ma się rozpocząć widok pełnoekranowy. Jeśli na przykład chcesz wyświetlić ekran główny na pełnym ekranie:
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);
}
Wypełnienie
Nie można zastosować polyfillu do interfejsu Window Management API, ale można zastosować shim do jego kształtu, aby można było pisać kod wyłącznie pod kątem nowego interfejsu 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;
}
Pozostałe aspekty interfejsu API, czyli różne zdarzenia zmiany ekranu i właściwość screen obiektu FullscreenOptions, nigdy nie byłyby wywoływane lub byłyby ignorowane przez przeglądarki, które ich nie obsługują.
Prezentacja
Jeśli uważnie śledzisz rozwój różnych kryptowalut, możesz monitorować rynki z wygody łóżka dzięki konfiguracji z jednym ekranem w mojej aplikacji. (Wcale tak nie jest, bo kocham tę planetę, ale na potrzeby tego artykułu załóżmy, że tak jest).
Ponieważ chodzi o kryptowaluty, rynki mogą w każdej chwili stać się niestabilne. W takiej sytuacji mogę szybko przejść do biurka, gdzie mam konfigurację z wieloma ekranami. Mogę kliknąć okno dowolnej waluty i szybko wyświetlić pełne szczegóły w widoku pełnoekranowym na przeciwnym ekranie. Oto moje ostatnie zdjęcie zrobione podczas ostatniej rzezi YCY. Zaskoczyło mnie to całkowicie i zostałem z rękami na twarzy.
Wypróbuj wersję demonstracyjną lub zobacz jej kod źródłowy na GitHubie.
Zabezpieczenia i uprawnienia
Zespół Chrome zaprojektował i wdrożył interfejs Window Management API zgodnie z głównymi zasadami określonymi w dokumencie Controlling Access to Powerful Web Platform Features, w tym z zasadami dotyczącymi kontroli użytkownika, przejrzystości i ergonomii. Interfejs Window Management API udostępnia nowe informacje o ekranach podłączonych do urządzenia, co zwiększa obszar odcisków cyfrowych użytkowników, zwłaszcza tych, którzy mają wiele ekranów stale podłączonych do swoich urządzeń. Aby ograniczyć to zagrożenie dla prywatności, udostępniane właściwości ekranu są ograniczone do minimum potrzebnego w przypadku typowych miejsc docelowych.
Aby witryny mogły uzyskiwać informacje o wielu ekranach i umieszczać okna na innych ekranach, wymagane jest zezwolenie użytkownika. Chromium zwraca szczegółowe etykiety ekranu, ale inne przeglądarki mogą zwracać mniej opisowe etykiety (lub nawet puste).
Kontrola sprawowana przez użytkowników
Użytkownik ma pełną kontrolę nad widocznością swojej konfiguracji. Mogą zaakceptować lub odrzucić prośbę o zezwolenie oraz cofnąć wcześniej przyznane uprawnienia za pomocą funkcji informacji o witrynie w przeglądarce.
Kontrola na poziomie firmy
Użytkownicy Chrome Enterprise mogą kontrolować różne aspekty interfejsu Window Management API, jak opisano w odpowiedniej sekcji ustawień atomowych grup zasad.
Przejrzystość
Informacja o tym, czy przyznano uprawnienia do korzystania z interfejsu Window Management API, jest widoczna w informacjach o witrynie w przeglądarce i można ją też uzyskać za pomocą interfejsu Permissions API.
Trwałość uprawnień
Przeglądarka zachowuje przyznane uprawnienia. Uprawnienia można cofnąć w informacjach o witrynie w przeglądarce.
Prześlij opinię
Czy coś w API nie działa tak, jak oczekujesz? Czy brakuje metod lub właściwości, które są potrzebne do realizacji Twojego pomysłu? Masz pytania lub uwagi dotyczące modelu zabezpieczeń?
- Zgłoś problem ze specyfikacją w odpowiednim repozytorium GitHub lub dodaj swoje uwagi do istniejącego problemu.
- Zgłoś błąd dotyczący implementacji w Chrome Podaj jak najwięcej szczegółów, instrukcje odtwarzania i wpisz
Blink>Screen>MultiScreenw polu Komponenty.
Wyrażanie poparcia dla interfejsu API
Czy planujesz używać interfejsu Window Management API? Twoje publiczne wsparcie pomaga zespołowi Chrome ustalać priorytety funkcji i pokazuje innym dostawcom przeglądarek, jak ważne jest ich obsługiwanie.
- Opisz, jak zamierzasz z niej korzystać, w wątku na forum WICG Discourse.
- Wyślij tweeta do @ChromiumDev z hasztagiem
#WindowManagementi napisz, gdzie i jak korzystasz z tej funkcji. - Poproś innych dostawców przeglądarek o wdrożenie interfejsu API.
Zasoby
- Wersja robocza specyfikacji
- Wyjaśnienie publiczne
- Demo interfejsu Window Management API | Demo interfejsu Window Management API source
- Błąd śledzenia w Chromium
- Wpis na ChromeStatus.com
- Komponent Blink:
Blink>Screen>MultiScreen - Sprawdzenie przez TAG
- Zamiar przeprowadzenia eksperymentu
Podziękowania
Specyfikację interfejsu Window Management API edytowali Victor Costan, Joshua Bell i Mike Wasserman. Interfejs API został wdrożony przez Mike’a Wassermana i Adrienne Walker. Ten artykuł został sprawdzony przez Joego Medleya, François Beauforta i Kayce Basques. Dziękujemy Laurze Torrent Puig za zdjęcia.