Zarządzanie kilkoma wyświetlaczami za pomocą interfejsu Window Management API

Uzyskuj informacje o połączonych wyświetlaczach i oknach położenia względem tych wyświetlaczy.

Interfejs API zarządzania oknami

Interfejs Window Management API umożliwia numerowanie wyświetlaczy podłączonych do Twojego komputera i umiejscowienie okien na konkretnych ekranach.

Sugerowane zastosowania

Przykłady witryn, które mogą korzystać z tego interfejsu API:

  • Edytory grafiki do wielu okien à la Gimp może umieszczać różne narzędzi do edycji w dokładnie rozmieszczonych oknach.
  • Wirtualne platformy zakupowe mogą pokazywać tendencje rynkowe w wielu okresach, z których można wyświetlać trybu pełnoekranowego.
  • Aplikacje do pokazu slajdów mogą wyświetlać notatki prelegenta na wewnętrznym ekranie głównym i w prezentacji na z zewnętrznego projektora.

Jak korzystać z interfejsu Window Management API

Problem

Działające od lat podejście do sterowania oknami Window.open() to niestety nie wiedząc o dodatkowych ekranach. Chociaż niektóre aspekty tego interfejsu API wydają się nieco przestarzałe, windowFeatures DOMString, sprawdza się on jednak na przestrzeni lat. Aby określić position, można przekazać współrzędne jak left i top (lub odpowiednio screenX i screenY) i przekazują wybrane rozmiar jako width i height (lub odpowiednio innerWidth i innerHeight). Aby na przykład otworzyć Okno 400 × 300 w odległości 50 pikseli od lewej i 50 pikseli od góry. może użyć:

const popup = window.open(
  'https://example.com/',
  'My Popup',
  'left=50,top=50,width=400,height=300',
);

Informacje o bieżącym ekranie znajdziesz w window.screen, która zwraca obiekt Screen. To jest 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łam dostosować się do nowej rzeczywistości w pracy i skonfigurować osobistego biura domowego. Moja wygląda tak jak na poniższym zdjęciu (jeśli chcesz, możesz zapoznać się z o mojej konfiguracji). iPad obok mojego MacBooka jest połączony z laptopem przez Sidecar, więc w razie potrzeby mogę szybko na iPadzie.

Ławka szkolna na dwóch krzesłach. U góry ławki szkolnej znajdują się pudełka na buty podtrzymujące laptopa oraz 2 iPady wokół niego.
Konfiguracja optymalizacji pod kątem wielu urządzeń

Na większym ekranie mogę umieścić wyskakujące okienko przykładowy kod powyżej na drugi ekran. Ja to robię podobny do tego:

popup.moveTo(2500, 50);

To przybliżone oszacowanie, ponieważ nie można poznać wymiarów drugiego ekranu. Informacje od window.screen obejmuje tylko ekran wbudowany, ale nie ekran iPada. Zgłoszone width wbudowanego ekranu miało 1680 piks., dlatego przejście na 2500 piks. może pomóc w przesunięciu na iPada, bo widzę, że znajduje się on po prawej stronie mojego MacBooka. Jak Czy mogę to zrobić w ogólnym przypadku? Okazuje się, że jest lepszy sposób niż zgadywanie. Dzięki temu Interfejs API zarządzania oknami.

Wykrywanie cech

Aby sprawdzić, czy interfejs Window Management API jest obsługiwany, użyj tego polecenia:

if ('getScreenDetails' in window) {
  // The Window Management API is supported.
}

Uprawnienia window-management

Aby móc używać interfejsu Window Management API, muszę poprosić użytkownika o zgodę. Zapytanie o uprawnienie window-management może działać przy użyciu Permissions API:

let granted = false;
try {
  const { state } = await navigator.permissions.query({ name: 'window-management' });
  granted = state === 'granted';
} catch {
  // Nothing.
}

Chociaż używane są przeglądarki ze starą i nową nazwą uprawnienia, przy prośbie o uprawnienia należy używać kodu obronnego, tak jak w poniższym 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żna chcę dynamicznie wyświetlać prośbę o uprawnienia przy pierwszej próbie użycia dowolnej z metod nowym API. Czytaj dalej, aby dowiedzieć się więcej.

Właściwość window.screen.isExtended

Aby sprawdzić, czy do mojego urządzenia jest podłączony więcej niż jeden ekran, otwieram window.screen.isExtended. Zwraca true lub false. W mojej konfiguracji zwraca wartość true.

window.screen.isExtended;
// Returns `true` or `false`.

Metoda getScreenDetails()

Teraz gdy już wiem, że obecne ustawienia są dostosowywane na wiele urządzeń, mogę dowiedzieć się więcej o drugi ekran za pomocą funkcji Window.getScreenDetails(). Wywołanie tej funkcji spowoduje wyświetlenie prośby o zgodę, która pyta mnie, czy strona może się otwierać i umieszczać okna na ekranie. Funkcja zwraca obietnicę , który kończy się za pomocą obiektu ScreenDetailed. Na moim MacBooku Pro 13 z podłączonym iPadem w tym 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ę, jak wartość left w przypadku iPada rozpoczyna się od 1680, czyli dokładnie width w przypadku wbudowanego wyświetlacza. Ten pozwala mi dokładnie określić logiczny układ ekranów (obok siebie, na górze do siebie nawzajem itp.). Dostępne są też teraz dane dla każdego ekranu, które pokazują, czy należy on do isInternal i określ, czy jest to isPrimary. Wbudowany ekran nie musi być ekranem głównym.

Pole currentScreen jest aktywnym obiektem odpowiadającym bieżącemu obiektowi window.screen. Obiekt są aktualizowane w przypadku miejsc docelowych okien na różnych urządzeniach lub zmian na urządzeniach.

Wydarzenie screenschange

Obecnie brakuje tylko sposobu wykrywania zmian w konfiguracji ekranu. Nowe zdarzenie, screenschange robi dokładnie to samo: uruchamia się po zmianie konstelacji ekranu. (Uwaga które „ekrany” jest liczbą mnogą w nazwie wydarzenia). Oznacza to, że zdarzenie jest uruchamiane po każdym pojawieniu się nowego ekranu lub obecny ekran jest (fizycznie lub wirtualnie w przypadku aplikacji Sidecar) podłączony lub odłączony.

Pamiętaj, że szczegóły nowego ekranu musisz wyświetlać asynchronicznie, czyli zdarzenie screenschange sama nie dostarcza tych danych. Aby wyszukać szczegóły ekranu, użyj aktywnego obiektu z pamięci podręcznej Interfejs 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;
  }
});

Wydarzenie currentscreenchange

Jeśli interesują mnie tylko zmiany na bieżącym ekranie (czyli wartość aktywnego obiektu 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);
});

Wydarzenie change

Na koniec, jeśli interesują mnie tylko zmiany na konkretnym ekranie, mogę odsłuchać change zdarzenie.

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świetlanie elementów w trybie pełnoekranowym za pomocą odpowiedniej nazwy requestFullScreen() . Metoda przyjmuje parametr options, w którym można przekazać FullscreenOptions Jak dotąd, jego jedyną właściwością jest navigationUI Interfejs Window Management API dodaje nową właściwość screen, która pozwala określić na którym ekranie chcesz włączyć widok pełnoekranowy. Na przykład: jeśli chcesz ustawić ekran główny pełny ekran:

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);
}

Watolina

Nie można zastosować kodu polyfill w interfejsie Window Management API, ale można podłożyć jego kształt, możesz 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 = async () => [window.screen];
  // Set to `false`, noting that this might be a lie.
  window.screen.isExtended = false;
}

inne aspekty interfejsu API, takie jak różne zdarzenia zmiany ekranu i właściwość screen. FullscreenOptions, nie zostanie po prostu nigdy wywołana lub zostanie zignorowana dyskretnie przez które nie obsługują tej przeglądarki.

Prezentacja

Jeśli tak jak ja, będziesz uważnie śledzić rozwój kryptowaluty. (Właściwie to przeważnie nie, ponieważ kocham tę planetę, ale... na potrzeby tego artykułu przyjmijmy, did.) Aby śledzić posiadane kryptowaluty, stworzyłem aplikację internetową, która pozwala Obserwujemy rynki we wszystkich sytuacjach, np. w łóżku, gdzie mam przyzwoity konfiguracji na jednym ekranie.

Ogromny ekran telewizora na końcu łóżka z częściowo widocznymi nogami autora. Na ekranie widać fałszywą platformę do obrotu kryptowalutami.
Relaks i obserwowanie rynku.

Jeśli chodzi o kryptowaluty, na rynku panuje gwałtowny ruch w każdej chwili. Jeśli tak się stanie, mogę szybko Przejdź do mojego biurka, gdzie mam sprzęt wieloekranowy. Mogę kliknąć okno dowolnej waluty by szybko zobaczyć pełne szczegóły w widoku pełnoekranowym na drugim ekranie. Oto najnowsze zdjęcie moje zdjęcie zostało zrobione podczas ostatniej baterii YCY. Przyciągnęła mnie zupełnie niemiarodajny z rękami na twarzy.

Autor z rękami na zapadającej twarz i wpatrujący się w platformę handlu kryptowalutami.
Panicky jako świadka kąpieliska YCY.

Możesz skorzystać z umieszczonej poniżej wersji demonstracyjnej lub zobaczyć jej kod źródłowy w wersji glitch.

Bezpieczeństwo i uprawnienia

Zespół Chrome zaprojektował i wdrożył interfejs Window Management API z użyciem zasad zdefiniowanych w artykule Kontrolowanie dostępu do zaawansowanych funkcji platform internetowych, takich jak kontrola użytkownika, przejrzystość i ergonomia. Interfejs Window Management API ujawnia nowych informacji o ekranach podłączonych do urządzenia, co zwiększyło możliwości zwłaszcza tych mających wiele urządzeń, z których jeden jest stale połączony. Jako jeden aby złagodzić tę ochronę prywatności, właściwości naświetlonego ekranu są ograniczone do minimum do typowych przypadków użycia miejsc docelowych. Witryny mogą działać pod kątem wielu urządzeń dopiero po otrzymaniu uprawnień użytkownika informacjami i umieszczać okna na innych ekranach. Chromium zwraca szczegółowe etykiety ekranu, Przeglądarki mogą zwracać mniej opisowe (lub nawet puste etykiety).

Kontrola użytkowników

Użytkownik ma pełną kontrolę nad dostępem do swojej konfiguracji. Może zaakceptować lub odrzucić i cofnąć otrzymane wcześniej uprawnienia, korzystając z funkcji informacji o witrynie z przeglądarki.

Kontrola firmy

Użytkownicy Chrome Enterprise mogą kontrolować kilka aspektów interfejsu Window Management API, omówione w odpowiedniej sekcji Atomic Policy Groups (Atomowe grupy zasad) ustawieniach.

Przejrzystość

Fakt przyznania uprawnień do korzystania z interfejsu Window Management API jest widoczne w informacjach o witrynie przeglądarki, a także dla zapytań wysyłanych przez interfejs Permissions API.

Trwałość uprawnień

Przeglądarka zachowuje przyznane uprawnienia. Uprawnienia można cofnąć w witrynie przeglądarki i informacjami o nich.

Prześlij opinię

Zespół Chrome chce poznać Twoją opinię na temat korzystania z interfejsu Window Management API.

Opowiedz nam o konstrukcji interfejsu API

Czy jest coś, co nie działa w interfejsie API zgodnie z oczekiwaniami? Czy może brakuje tu metod lub właściwości potrzebne do realizacji pomysłu? Masz pytanie lub komentarz na temat zabezpieczeń model?

  • Zgłoś problem ze specyfikacją w odpowiednim repozytorium GitHub lub dodaj uwagi do istniejącego Google Cloud.

Zgłoś problem z implementacją

Czy wystąpił błąd z implementacją Chrome? Czy implementacja różni się od specyfikacji?

  • Zgłoś błąd na new.crbug.com. Podaj jak najwięcej szczegółów można, wykonać proste instrukcje odtwarzania i wpisać Blink>Screen>MultiScreen w polu Okno Komponenty. Usługa Glitch świetnie nadaje się do szybkiego i łatwego udostępniania poprawek.

Pokaż wsparcie dla interfejsu API

Czy planujesz skorzystać z interfejsu Window Management API? Wasze publiczne wsparcie pomaga nam ulepszyć Chrome nadając priorytet funkcjom i pokazując innym dostawcom przeglądarek, jak ważne jest ich wsparcie.

Przydatne linki

Podziękowania

Specyfikacja interfejsu Window Management API została edytowana przez Victor Costan Joshua Bell oraz Mike Wasserman Interfejs API został wdrożony przez Mike Wasserman i Adrienne Walker Ten artykuł zrecenzował(a) Joe Medley, François Beaufort, i Kayce Basques. Dziękujemy Laurze Torrent Puig za zdjęcia.