Gestione di diversi schermi con l'API Window Management

Consente di ricevere informazioni sui display collegati e sulla posizione delle finestre rispetto a questi display.

API Window Management

L'API Window Management ti consente di enumerare i display connessi alla tua macchina e posizionare finestre su schermi specifici.

Casi d'uso suggeriti

Ecco alcuni esempi di siti che possono utilizzare questa API:

  • Editor di grafica multi-finestra con opzioni Gimp può posizionare diversi strumenti di modifica nelle finestre posizionate con precisione.
  • I virtual trading desk possono mostrare le tendenze del mercato in più finestre, ognuna delle quali può essere visualizzata modalità a schermo intero.
  • Le app di presentazione possono mostrare le note del relatore sulla schermata principale interna e la presentazione su un un proiettore esterno.

Come utilizzare l'API Window Management

Il problema

L'approccio collaudato al controllo delle finestre, Window.open(), purtroppo, non è a conoscenza di schermate aggiuntive. Alcuni aspetti di questa API sembrano un po' arcaici, come la sua windowFeatures DOMString, ci ha comunque servito bene nel corso degli anni. Per specificare la position, puoi passare il parametro coordinate rispettivamente come left e top (o screenX e screenY rispettivamente) e superi la taglia come width e height (o innerWidth e innerHeight rispettivamente). Ad esempio, per aprire una finestra 400x300 a 50 pixel da sinistra e 50 pixel dall'alto, questo è il codice che potresti usare:

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

Puoi ottenere informazioni sulla schermata corrente osservando il window.screen, che restituisce un oggetto Screen. Questo è il output sul mio 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
*/

Come gran parte delle persone che lavorano nel campo della tecnologia, ho dovuto adattarmi alla nuova realtà lavorativa e configurare il mio ufficio personale in casa. Il mio appare nella foto qui sotto (se ti interessa, puoi leggere dettagli completi sulla mia configurazione). L'iPad accanto al mio MacBook è collegato al laptop tramite Sidecar, così ogni volta che ne ho bisogno posso mettere rapidamente in iPad su un secondo schermo.

Panca di scuola su due sedie. Sopra la panca della scuola ci sono scatole da scarpe che supportano un laptop e due iPad circondati da due iPad.
Una configurazione multischermo.

Per sfruttare al meglio lo schermo più grande, posso inserire il popup esempio di codice riportato sopra sul secondo schermo. Ce l'ho fatta nel seguente modo:

popup.moveTo(2500, 50);

Si tratta di un'ipotesi approssimativa, in quanto non è possibile conoscere le dimensioni del secondo schermo. Le informazioni di window.screen copre solo lo schermo integrato, non lo schermo dell'iPad. Hai segnalato width dello schermo integrato era di 1680 pixel, quindi passare a 2500 pixel potrebbe funzionare sull'iPad, perché mi so che si trova sulla destra del mio MacBook. Come posso farlo in caso generale? A quanto pare, c'è un modo migliore di indovinare. In questo modo API Window Management.

Rilevamento delle caratteristiche

Per verificare se l'API Window Management è supportata, utilizza:

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

Autorizzazione window-management

Devo chiedere all'utente l'autorizzazione prima di poter utilizzare l'API Window Management. È possibile eseguire query sull'autorizzazione window-management con il API Permissions in questo modo:

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

Mentre sono in uso i browser con il nome di autorizzazione precedente e quello nuovo, assicurati di utilizzare il codice difensivo quando richiedi l'autorizzazione, come nell'esempio riportato di seguito.

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

Il browser può scegliere di mostrare la richiesta di autorizzazione in modo dinamico al primo tentativo di utilizzare uno dei metodi di la nuova API. Per saperne di più, continua a leggere quanto segue.

La proprietà window.screen.isExtended

Per scoprire se al mio dispositivo sono connessi più schermi, accedo allo window.screen.isExtended proprietà. Restituisce true o false. Per la mia configurazione, restituisce true.

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

Il metodo getScreenDetails()

Ora che so che l'impostazione corrente è multischermo, posso ottenere maggiori informazioni secondo schermo con Window.getScreenDetails(). La chiamata di questa funzione mostrerà un prompt di autorizzazione mi chiede se il sito può aprire e posizionare finestre sullo schermo. La funzione restituisce una promessa che si risolve con un oggetto ScreenDetailed. Sul mio MacBook Pro 13 con un iPad connesso, questo include un campo screens con due oggetti 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
  }]
}
*/

Le informazioni sugli schermi connessi sono disponibili nell'array screens. Nota come il valore left per iPad parte da 1680, che è esattamente il width del display integrato. Questo mi consente di stabilire esattamente come sono disposti in modo logico gli schermi (uno accanto all'altro, in cima tra loro e così via). Ora ci sono anche dati per ogni schermata che mostrano se si tratta di isInternal e se è isPrimary. Tieni presente che lo schermo integrato non è necessariamente la schermata principale.

Il campo currentScreen è un oggetto attivo corrispondente all'attuale window.screen. L'oggetto vengono aggiornati sui posizionamenti delle finestre su più schermi o sulle modifiche ai dispositivi.

L'evento screenschange

L'unica cosa che manca adesso è un modo per rilevare quando la configurazione dello schermo cambia. Un nuovo evento, screenschange fa esattamente questo: si attiva ogni volta che la costellazione dello schermo viene modificata. (Avviso che "schermate" è plurale nel nome dell'evento.) Ciò significa che l'evento viene attivato ogni volta che viene visualizzata una nuova schermata o lo schermo esistente è (fisicamente o virtualmente nel caso di Sidecar) collegato o scollegato.

Tieni presente che devi cercare i dettagli della nuova schermata in modo asincrono, l'evento screenschange non fornisce questi dati. Per cercare i dettagli della schermata, utilizza l'oggetto attivo memorizzato nella cache interfaccia di 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;
  }
});

L'evento currentscreenchange

Se mi interessano solo le modifiche alla schermata corrente (ovvero, il valore dell'oggetto attivo currentScreen), posso ascoltare l'evento currentscreenchange.

const screenDetails = await window.getScreenDetails();
screenDetails.addEventListener('currentscreenchange', async (event) => {
  const details = screenDetails.currentScreen;
  console.log('The current screen has changed.', event, details);
});

L'evento change

Infine, se mi interessano solo le modifiche a una schermata di cemento, posso ascoltare i contenuti change evento.

const firstScreen = (await window.getScreenDetails())[0];
firstScreen.addEventListener('change', async (event) => {
  console.log('The first screen has changed.', event, firstScreen);
});

Nuove opzioni a schermo intero

Finora, potevi richiedere che gli elementi vengano visualizzati in modalità a schermo intero utilizzando requestFullScreen() . Il metodo richiede un parametro options al quale puoi passare FullscreenOptions Finora, la sua unica proprietà è stata navigationUI L'API Window Management aggiunge una nuova proprietà screen che ti consente di determinare su quale schermata avviare la visualizzazione a schermo intero. Ad esempio, se vuoi rendere la schermata principale schermo intero:

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

Non è possibile eseguire il polyfill dell'API Window Management, ma puoi modificarne la forma in modo da puoi scrivere il codice esclusivamente sulla nuova 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;
}

Gli altri aspetti dell'API, ovvero i vari eventi di modifica dello schermo e la proprietà screen della il criterio FullscreenOptions, semplicemente non si attiverà mai o non verrebbe mai ignorato, rispettivamente browser che non li supportano.

Demo

Se anche tu come me, tieni d'occhio lo sviluppo dei vari le criptovalute. (In realtà non lo faccio perché amo questo pianeta, ma ai fini di questo articolo, supponiamo che did.) Per tenere traccia delle criptovalute che possiedo, ho sviluppato un'app web che mi consente di guardare i mercati in tutte le situazioni della vita, ad esempio stando comodamente a letto, dove posso trovare configurazione in una sola schermata.

Enorme schermo televisivo in fondo a un letto con le gambe dell'autore parzialmente visibili. Sullo schermo è mostrato un trading desk di criptovalute.
Rilassarti e osservare i mercati.

Parlando delle criptovalute, i mercati possono diventare frenetici in qualsiasi momento. In tal caso, posso rapidamente alla mia scrivania, dove ho una configurazione multischermo. posso fare clic sulla finestra di una valuta vedere rapidamente tutti i dettagli in una visualizzazione a schermo intero sullo schermo opposto. Di seguito è riportata una foto recente di che mi hanno scattato durante l'ultimo battaglia di sangue degli YCY. Mi ha beccato completamente alla sprovvista e mi ha lasciato con le mani sul viso.

L'autore si mette le mani sul viso in preda al panico e fissa il trading desk di criptovalute.
Panesimo, assistere al bagno di sangue di YCY.

Puoi giocare con la demo incorporata di seguito o vedere il codice sorgente per glitch.

Sicurezza e autorizzazioni

Il team di Chrome ha progettato e implementato l'API Window Management utilizzando le principi definiti in Controllo dell'accesso a potenti funzionalità della piattaforma web, tra cui controllo dell'utente, trasparenza ed ergonomia. L'API Window Management espone nuove informazioni sugli schermi collegati a un dispositivo, aumentando la superficie di fingerprinting agli utenti, in particolare quelli con più schermi costantemente connessi ai loro dispositivi. Come uno per ridurre il problema di privacy, le proprietà delle schermate esposte sono limitate al minimo necessario per casi d'uso comuni relativi ai posizionamenti. L'autorizzazione dell'utente è necessaria per consentire ai siti di usare la funzionalità multischermo informazioni e posizionare finestre su altri schermi. Chromium restituisce etichette dettagliate sullo schermo, i browser sono liberi di restituire etichette meno descrittive (o persino vuote).

Controllo utenti

L'utente ha il pieno controllo dell'esposizione della propria configurazione. Può accettare o rifiutare i richiesta di autorizzazione e revoca un'autorizzazione concessa in precedenza tramite la funzionalità delle informazioni sul sito in il browser.

Controllo aziendale

Gli utenti di Chrome Enterprise possono controllare diversi aspetti dell'API Window Management descritto nella sezione pertinente del Gruppi atomici di criteri impostazioni.

Trasparenza

Il fatto che sia stata concessa l'autorizzazione a utilizzare l'API Window Management sia esposto nelle informazioni del sito del browser e interrogabile anche tramite l'APIPermissions.

Persistenza dell'autorizzazione

Il browser mantiene le concessioni di autorizzazioni. L'autorizzazione può essere revocata tramite il sito del browser informazioni.

Feedback

Il team di Chrome vuole conoscere la tua esperienza con l'API Window Management.

Parlaci della progettazione dell'API

C'è qualcosa nell'API che non funziona come previsto? Oppure mancano metodi o le proprietà necessarie per implementare la tua idea? Hai una domanda o un commento sulla sicurezza modello?

  • Segnala un problema relativo alle specifiche sul repository GitHub corrispondente o aggiungi le tue opinioni a un problema.

Segnalare un problema con l'implementazione

Hai trovato un bug nell'implementazione di Chrome? Oppure l'implementazione è diversa dalle specifiche?

  • Segnala un bug all'indirizzo new.crbug.com. Assicurati di includere il maggior numero di dettagli possibile puoi, semplici istruzioni per la riproduzione e inserisci Blink>Screen>MultiScreen nel nella casella Componenti. Glitch è la soluzione perfetta per condividere riproduzioni in modo facile e veloce.

Mostra il supporto per l'API

Intendi utilizzare l'API Window Management? Il tuo supporto pubblico aiuta Chrome del team responsabile delle priorità delle funzionalità e mostra agli altri fornitori di browser quanto sia fondamentale supportarli.

Link utili

Ringraziamenti

La specifica dell'API Window Management è stata modificata da Vittorio Costan Joshua Bell e Mike Wasserman. L'API è stata implementata da Mike Wasserman e Adrienne Walker Questo articolo è stato esaminato da Joe Medley, François Beaufort, e Kayce Basques. Grazie a Laura Torrent Puig per le foto.