Administrar varias pantallas con la API de colocación de ventanas multipantalla
Obtenga información sobre las pantallas conectadas y la posición de las ventanas en relación con esas pantallas.
La API de colocación de ventanas multipantalla es parte del proyecto de capacidades y está actualmente en desarrollo. Esta publicación se actualizará a medida que avance la implementación.
La API de colocación de ventanas multipantalla le permite enumerar las pantallas conectadas a su máquina y colocar ventanas en pantallas específicas.
Casos de uso sugeridos
Ejemplos de sitios que pueden usar esta API incluyen:
- Los editores gráficos de ventanas múltiples tipo Gimp pueden colocar varias herramientas de edición en ventanas colocadas con precisión.
- Las mesas de trading virtual pueden mostrar las tendencias del mercado en múltiples ventanas, cualquiera de las cuales se puede ver en modo de pantalla completa.
- Las aplicaciones de presentación de diapositivas pueden mostrar notas del orador en la pantalla principal interna y la presentación en un proyector externo.
Estado actual
Paso | Estado |
---|---|
1. Crea un explicador | Completado |
2. Crear borrador inicial de especificación | Completado |
3. Recopile comentarios y repita el diseño | En curso |
4. Prueba de origen | |
5. Lanzamiento | No empezado |
Cómo utilizar la API de colocación de ventanas multipantalla
El problema
El enfoque probado con el tiempo para controlar las ventanas, Window.open()
, desafortunadamente no toma en cuenta las pantallas adicionales. Si bien algunos aspectos de esta API parecen un poco arcaicos, como su parámetro windowFeatures
DOMString
, nos ha servido bien a lo largo de los años. Para especificar la posición de una ventana, puede pasar las coordenadas como left
y top
(o screenX
y screenY
respectivamente) y pasar el tamaño deseado como width
y height
(o innerwidth
e innerHeight
respectivamente). Por ejemplo, para abrir una ventana de 400 × 300 a 50 píxeles de la izquierda y 50 píxeles de la parte superior, podría usar este código:
const popup = window.open(
'https://example.com/',
'My Popup',
'left=50,top=50,width=400,height=300',
);
Puede obtener información sobre la pantalla actual mirando la window.screen
, que devuelve un objeto Screen
. Esta es la salida en mi 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
*/
Como la mayoría de las personas que trabajan en campos de tecnología, he tenido que adaptarme a la nueva realidad laboral y montar mi propia oficina en casa. La mía se ve como en la foto de abajo (si está interesado, puede leer los detalles completos sobre mi configuración). El iPad al lado de mi MacBook está conectado a la computadora portátil a través de Sidecar , por lo que siempre que lo necesito, puedo convertir rápidamente el iPad en una segunda pantalla.
Si quiero aprovechar la pantalla más grande, puedo colocar la ventana emergente del ejemplo de código anterior en la segunda pantalla. Lo hago así:
popup.moveTo(2500, 50);
Esta es una suposición aproximada, ya que no hay forma de conocer las dimensiones de la segunda pantalla. La información de window.screen
solo cubre la pantalla incorporada, pero no la pantalla del iPad. El width
informado de la pantalla incorporada fue de 1680
píxeles, por lo que pasar a 2500
píxeles podría funcionar para cambiar la ventana al iPad, ya que sé que está ubicada a la derecha de mi MacBook. ¿Cómo puedo hacer esto en un caso general? Resulta que hay una forma mejor que tratar de adivinar. Esa forma es la API de colocación de ventanas multipantalla.
Detección de características
Para comprobar si la API de colocación de ventanas multipantalla es compatible, utilice:
if ('getScreenDetails' in window) {
// The Multi-Screen Window Placement API is supported.
}
window-placement
El permiso Antes de poder utilizar la API de colocación de ventanas multipantalla, debo pedirle permiso al usuario para hacerlo. El nuevo window-placement
se puede consultar con la API de permisos de la siguiente manera:
let granted = false;
try {
const { state } = await navigator.permissions.query({ name: 'window-placement' });
granted = state === 'granted';
} catch {
// Nothing.
}
El navegador puede optar por mostrar la solicitud de permiso de forma dinámica en el primer intento de utilizar cualquiera de los métodos de la nueva API. Siga leyendo para obtener más información.
window.screen.isExtended
La propiedad Para saber si hay más de una pantalla conectada a mi dispositivo, yo accedo a la propiedad window.screen.isExtended
. Devuelve true
o false
. Para mi configuración, devuelve true
.
window.screen.isExtended;
// Returns `true` or `false`.
getScreenDetails()
El método Ahora que sé que la configuración actual es multipantalla, puedo obtener más información sobre la segunda pantalla usando Window.getScreenDetails()
. Llamar a esta función mostrará un mensaje de permiso que me pregunta si el sitio puede abrir y colocar ventanas en mi pantalla. La función devuelve una promesa que se resuelve con un objeto ScreenDetailed
. En mi MacBook Pro 13 con un iPad conectado, esto incluye un campo de screens
con dos objetos 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: ""
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: ""
left: 1680
onchange: null
orientation: ScreenOrientation {angle: 0, type: "landscape-primary", onchange: null}
pixelDepth: 24
top: 0
width: 1366
}]
}
*/
La información sobre las pantallas conectadas está disponible en la matriz de screens
. Observe cómo el valor de left
para el iPad comienza en 1680
, que es exactamente el width
de la pantalla incorporada. Esto me permite determinar exactamente cómo están dispuestas lógicamente las pantallas (una al lado de la otra, una encima de la otra, etc.). También hay datos ahora de cada pantalla para mostrar si es interna (isInternal
) y si es una Principal isPrimary
. Tenga en cuenta que la pantalla incorporada no es necesariamente la pantalla principal .
El campo currentScreen
es un objeto vivo correspondiente a la pantalla window.screen
actual. El objeto se actualiza en ubicaciones cruzadas de ventanas o cambios de dispositivo.
screenschange
El evento Lo único que falta ahora es una forma de detectar cuándo cambia la configuración de mi pantalla. Un nuevo evento, screenschange
, hace exactamente eso: se activa cada vez que se modifica la constelación de pantallas. (Observe que "screens" es plural en el nombre del evento). Esto significa que el evento se activa cada vez que se conecta o desconecta una nueva pantalla o una pantalla existente (física o virtualmente en el caso de Sidecar).
Tenga en cuenta que debe buscar los detalles de la nueva pantalla de forma asincrónica, el evento screenschange
por sí no proporciona estos datos. Para buscar los detalles de la pantalla, use el objeto vivo desde una interfaz de Screens
en caché.
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
El evento Si sólo estoy interesado en los cambios en la pantalla actual (es decir, el valor del objeto directo currentScreen
), puedo escuchar el 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);
});
change
El evento Finalmente, si solo estoy interesado en cambios en una pantalla concreta, puedo escuchar el evento change
.
const firstScreen = (await window.getScreenDetails())[0];
firstScreen.addEventListener('change', async (event) => {
console.log('The first screen has changed.', event, firstScreen);
});
Nuevas opciones de pantalla completa
Hasta ahora, podía solicitar que los elementos se mostraran en modo de pantalla completa a través del método requestFullScreen()
. El método toma un parámetro options
donde puede pasar FullscreenOptions
. Hasta ahora, su única propiedad ha sido navigationUI
. La API de colocación de ventanas multipantalla agrega una nueva propiedad screen
que le permite determinar en qué pantalla iniciar la vista de pantalla completa. Por ejemplo, si desea que la pantalla principal esté en pantalla completa:
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
No es posible aplicar polyfill a la API de colocación de ventanas multipantalla, pero puede ajustar su forma para poder codificar exclusivamente hacia la nueva 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;
}
Los otros aspectos de la API, es decir, los diversos eventos de cambio de pantalla y la propiedad screen
del FullscreenOptions
, simplemente nunca se activarían o serían ignorados en silencio, respectivamente, por los navegadores no compatibles.
Demostración
Si usted es como yo, vigila de cerca el desarrollo de las distintas criptomonedas. (En realidad, no lo hago mucho porque amo este planeta, pero, por el bien de este artículo, asuma que lo hago). Para realizar un seguimiento de las criptomonedas que poseo, he desarrollado una aplicación web que me permite ver los mercados en todas las situaciones de la vida, como desde la comodidad de mi cama, donde tengo una configuración decente de pantalla única.
Al tratarse de criptomonedas, los mercados pueden agitarse en cualquier momento. Si esto sucediera, puedo moverme rápidamente a mi escritorio donde tengo una configuración de múltiples pantallas. Puedo hacer clic en la ventana de cualquier moneda y ver rápidamente los detalles completos en una vista de pantalla completa en la pantalla opuesta. A continuación se muestra una foto reciente mía tomada durante el último baño de sangre de YCY. Me tomó completamente desprevenido y me dejó con las manos en la cara.
Puede jugar con la demostración incrustada a continuación, o ver su código fuente en glitch.
Seguridad y permisos
El equipo de Chrome ha diseñado e implementado la API de colocación de ventanas multipantalla utilizando los principios básicos definidos en Control del acceso a las potentes funciones de la plataforma web, incluyendo el control del usuario, la transparencia y la ergonomía. La API de colocación de ventanas multipantalla expone nueva información sobre las pantallas conectadas a un dispositivo, lo que aumenta la superficie de huellas dactilares de los usuarios, especialmente aquellos con varias pantallas conectadas constantemente a sus dispositivos. Como mitigación de este problema de privacidad, las propiedades de la pantalla expuesta se limitan al mínimo necesario para los casos de uso común de la ubicación. Se requiere permisos de usuario para que los sitios obtengan información multipantalla y coloquen ventanas en otras pantallas.
Control de usuario
El usuario tiene el control total de la exposición de su configuración. Pueden aceptar o rechazar la solicitud de permiso y revocar un permiso otorgado previamente a través de la función de información del sitio en el navegador.
Transparencia
El hecho de que se haya otorgado el permiso para usar la API de colocación de ventanas multipantalla se muestra en la información del sitio del navegador y también se puede consultar a través de la API de permisos.
Persistencia del permiso
El navegador conserva las concesiones de permisos. El permiso se puede revocar a través de la información del sitio del navegador.
Retroalimentación
El equipo de Chrome desea conocer sus experiencias con la API de colocación de ventanas multipantalla.
Cuéntenos sobre el diseño de la API
¿Hay algo en la API que no funciona como esperaba? ¿O faltan métodos o propiedades que necesita para implementar su idea? ¿Tiene alguna pregunta o comentario sobre el modelo de seguridad?
- Reporte un problema de especificaciones en el repositorio de GitHub correspondiente o agregue sus comentarios a un reporte existente.
Reporte problemas con la implementación
¿Encontró un error con la implementación en Chrome? ¿O la implementación es diferente de la especificación?
- Reporte los errores en new.crbug.com. Asegúrese de incluir todos los detalles que pueda, instrucciones simples para reproducir el error e ingrese
Blink>WindowDialog
en el cuadro Components. Glitch funciona muy bien para compartir repros rápidos y fáciles.
Muestre su apoyo a la API
¿Está pensando en utilizar la API de colocación de ventanas multipantalla? Su apoyo público ayuda al equipo de Chrome a priorizar las funciones y muestra a otros proveedores de navegadores lo importante que es brindarles soporte.
- Comparta cómo planea usarlo en el hilo WICG Discourse .
- Envíe un tweet a @ChromiumDev utilizando el hashtag
#WindowPlacement
y díganos dónde y cómo lo está utilizando. - Solicite a otros proveedores de navegadores que implementen la API.
Enlaces útiles
- Borrador de especificaciones
- Explicador público
- Demostración de la API de colocación de ventanas multipantalla | Fuente de demostración de la API de colocación de ventanas multipantalla
- Error de seguimiento de Chromium
- Entrada de ChromeStatus.com
- Componente Blink:
Blink>WindowDialog
- Revisión de TAG
- Intent to Experiment
Agradecimientos
Victor Costan y Joshua Bell editaron la especificación de la API de colocación de ventanas multipantalla. La API fue implementada por Mike Wasserman y Adrienne Walker. Este artículo fue revisado por Joe Medley, François Beaufort y Kayce Basques. Gracias a Laura Torrent Puig por las fotos.