1. 简介
本节为非规范性内容。
操作系统通常允许用户将多个屏幕连接到单个设备,并以虚拟方式排列这些屏幕,以扩展整体视觉工作区。
各种应用程序使用平台工具在此类多屏环境中放置其内容,但 Web 应用程序开发者受限于现有 API,这些 API 通常围绕使用单个屏幕而设计。
随着多屏设备和应用程序日益成为用户体验中更常见且更关键的一部分,为 Web 开发者提供利用这一扩展视觉 环境所需的信息和工具也变得更加重要。
本规范以增量方式扩展 Window、
Screen
和 FullscreenOptions
API,并引入新的 ScreenDetails
和 ScreenDetailed
接口。这些更改允许 Web 应用程序通过将内容放置在特定屏幕上,提供极具吸引力的多屏体验。
1.1. 典型使用场景
本规范旨在为使用多个屏幕的 Web 应用程序用户提供更好的体验。以下是为设计提供依据的一些使用场景:
-
幻灯片应用程序在投影仪上进行演示,并在笔记本电脑屏幕上显示演讲者备注。
-
金融应用程序在多个显示器上打开由多个窗口组成的仪表板。
-
医疗应用程序在高分辨率灰度显示器上打开图像(例如 X 光片)。
-
创意应用程序在单独的屏幕上显示辅助窗口(例如调色板)。
-
会议室应用程序在触摸屏设备上显示控件,并在电视上显示视频。
-
游戏、数字标牌、艺术创作及其他类型应用程序中的多屏布局。
-
当窗口跨越多个屏幕时,网站会优化内容和布局。
1.2. 使用概述
为支持多屏体验,该 API 允许 Web 应用程序:
-
检测设备是否具有多个屏幕
-
请求在特定屏幕上放置内容所需的信息
-
检测屏幕何时被添加或移除
-
检测当前屏幕或其属性何时发生变化
-
在特定屏幕上以全屏方式显示元素
-
在特定屏幕上放置窗口
-
通过单次瞬时用户激活启动多屏体验
该 API 的基本使用示例如下:
// 检测设备是否具有多个屏幕。 if ( window. screen. isExtended) { // 请求在特定屏幕上放置内容所需的信息。 const screenDetails= await window. getScreenDetails(); // 检测屏幕何时被添加或移除。 screenDetails. addEventListener( 'screenschange' , onScreensChange); // 检测当前 \`ScreenDetailed\` 或其属性何时发生变化。 screenDetails. addEventListener( 'currentscreenchange' , onCurrentScreenChange); // 找到主屏幕,并在其中以全屏方式显示一些内容。 const primaryScreen= screenDetails. screens. find( s=> s. isPrimary); document. documentElement. requestFullscreen({ screen: primaryScreen}); // 找到另一个屏幕,并使用新窗口填满其可用区域。 const otherScreen= screenDetails. screens. find( s=> s!== primaryScreen); window. open( url, '_blank' , \`left= ${ otherScreen. availLeft} ,\` + \`top= ${ otherScreen. availTop} ,\` + \`width= ${ otherScreen. availWidth} ,\` + \`height= ${ otherScreen. availHeight} \`); } else { // 检测旧版 \`Screen\` 接口的属性何时发生变化。 window.screen.addEventListener('change', onScreenChange); // 在传统的单屏环境中排列内容…… }
1.2.1. 检测是否存在多个屏幕
支持多屏体验的一个首要问题是,设备是否具有可在放置内容时使用的多个屏幕。这些屏幕可以内置于设备
中(例如笔记本电脑显示面板),可以通过线缆连接到设备(例如使用 HDMI 线缆连接的计算机和显示器),
可以通过其他方式连接到设备(例如 Mac 和 iPad 的“随航”功能),也可以通过显示设备虚拟化提供。
此信息由 isExtended
布尔值提供,该值会在安全上下文中公开,而无需显示权限提示。
if ( screen. isExtended) { // 向用户提供多屏控件。 }
1.2.2.
检测 Screen
属性变化
即使在单屏设备上,观察旧版 Screen
属性的变化对于调整内容也很有用。此外,观察
isExtended
对于检测单屏配置与多屏配置之间的转换也很有用。为避免轮询,会在 Screen
对象上触发 change
事件:
screen. addEventListener( 'change' , e=> { // 旧版 \`Screen\` 接口的某个属性已发生变化。 });
1.2.3. 请求详细的屏幕信息
可以通过 getScreenDetails()
方法请求有关设备所用屏幕的详细信息。此方法可能会提示用户授予权限。生成的 ScreenDetails
对象允许开发者枚举屏幕、检查其属性并监听变化。
try { // 请求屏幕详细信息并立即处理这些信息。 const screenDetails= await window. getScreenDetails(); processScreenDetails( screenDetails); // 当屏幕集合发生变化时,处理更新后的屏幕详细信息。 screenDetails. onscreenschange= () => { processScreenDetails( screenDetails); }; } catch ( err) { console. error( err); // 处理权限被拒绝及其他错误。 } function processScreenDetails( screenDetails) { // 使用假定存在的辅助函数,构建列出各屏幕的 UI。 clearScreenList(); screenDetails. screens. forEach( screen=> { addToScreenList({ name: screen. label, screen: screen}); // 当特定屏幕的详细信息发生变化时,处理更新后的屏幕详细信息。 screen. onchange= () => { processScreenDetails( screenDetails); }; }); selectCurrentInScreenList( screenDetails. currentScreen); }
1.2.4. 在特定屏幕上放置全屏内容
一种常见的多屏使用场景是在特定屏幕上以全屏方式呈现一些内容。屏幕可以通过交互方式选择,也可以根据
屏幕属性或用户先前的选择自动选定。选定屏幕后,可以将其传递给 requestFullscreen()
方法。
// 调用一个假定存在的辅助函数,该函数返回选定的 \`ScreenDetailed\` 实例。 const screenDetailed= getScreenForSlideshow(); // 请求在选定屏幕上以全屏方式显示特定元素。 slideshowElement. requestFullscreen({ screen: screenDetailed});
1.2.5. 在特定屏幕上放置窗口
另一种常见的多屏使用场景是在特定屏幕上放置窗口。可以将 ScreenDetailed
接口提供的坐标与现有的 open()
和 moveTo()
方法结合使用来实现此目的。
function openCenteredWindow( url, screenDetailed, w, h) { // 计算使窗口在目标屏幕上居中的坐标。 const l= screenDetailed. left+ Math. round( screenDetailed. width- w) / 2 ; const t= screenDetailed. top+ Math. round( screenDetailed. height- h) / 2 ; // 使用请求的尺寸打开窗口。 return window. open( url, '_blank' , \`left= ${ l} ,top= ${ t} ,width= ${ w} ,height= ${ h} \`); }
1.2.6. 启动多屏体验
一种经常被提出的多屏使用场景,是通过一次用户激活启动极具吸引力的多屏体验。一种具体的提议形式是, 允许网站通过单次用户手势§ 1.2.4 在特定屏幕上放置全屏内容 并§ 1.2.5 在特定屏幕上放置窗口。 可以通过在单个事件监听器中,首先请求在多屏设备的特定屏幕上进入全屏模式,然后在设备的另一个屏幕上 打开弹出窗口来实现此目的。
initiateMultiScreenExperienceButton. addEventListener( 'click' , async () => { // 找到主屏幕,并在其中以全屏方式显示一些内容。 const primaryScreen= screenDetails. screens. find( s=> s. isPrimary); await document. documentElement. requestFullscreen({ screen: primaryScreen}); // 找到另一个屏幕,并使用新窗口填满其可用区域。 const otherScreen= screenDetails. screens. find( s=> s!== primaryScreen); window. open( url, '_blank' , \`left= ${ otherScreen. availLeft} ,\` + \`top= ${ otherScreen. availTop} ,\` + \`width= ${ otherScreen. availWidth} ,\` + \`height= ${ otherScreen. availHeight} \`); });
2. 概念
本规范中的概念建立在 CSSOM-View-1 工作草案、CSSOM-View-1 编辑草案、[HTML] 和 [Fullscreen] 中的概念之上。
2.1. 屏幕
托管用户代理的设备具有一个 屏幕或多个屏幕,用于显示视觉内容。设备所使用的屏幕集合可能会在用户代理运行期间发生变化, 以反映设备硬件或软件配置的变化。
注: 屏幕配置变化的一些基本示例包括:使用 HDMI 线缆将电视或投影仪连接到笔记本电脑;合上笔记本电脑盖子以禁用其内置 LCD 面板;以及更改已连接 LCD 计算机显示器的显示分辨率。
屏幕具有一个设备像素比,类似于 Window
的
devicePixelRatio,
它是以下算法的结果:
屏幕具有一个方向, 其说明见 [screen-orientation]。
屏幕具有一个标签,它是一个 能够向用户有意义地描述屏幕的字符串,以帮助用户识别和区分各个屏幕。
注: 标签可以是用户代理选定的任意字符串。它可以描述屏幕
相对于设备的位置,例如 "internal" 与 "external";可以包括尺寸,例如
"640×480";可以包括来自 VESA E-EDID
数据的硬件型号信息,例如 "Acme Telletube 1000x";可以包括用于区分的编号,例如
"screen 1" 与 "screen 2";也可以包括以上所有内容。如果底层显示器
详细信息未知,或用户代理选择隐藏该信息,标签可以是空字符串。应用程序不能假定标签包含任何特定信息,
例如设备类型、型号、尺寸、密度等。
虽然许多屏幕属性都可用于主动指纹识别,但尤其应仔细考虑用作标签的字符串,以最大限度 降低其唯一性。例如,将设备序列号包含在内会是一个糟糕的选择。
2.2. 屏幕像素
屏幕具有像素,它们是 可以直接编程的最小屏幕组件。每个像素显示一种颜色。
注: 在液晶显示器(LCD)上,每个像素由三个组件 组成。每个组件都是强度可变的(红色、绿色、蓝色)光。对像素组件进行推理(子像素渲染)不在本规范的 范围内。
注: 某些屏幕可以配置为以不同于物理硬件固有 组成的分辨率显示内容;例如,硬件分辨率为 2560×1440 的显示器可以由设备配置为以 1920×1080 的 显示分辨率运行。
像素具有一个颜色深度,即用于表示其能够显示的颜色的位数。
注: 一些常用渲染系统将像素建模为具有 24 位颜色深度。 这 3 组各 8 位的数据表示 LCD 像素中(红色、绿色、 蓝色)子像素的强度。
2.3. 屏幕区域
屏幕具有一个屏幕区域, 它是由像素构成的矩形二维网格,用于向用户呈现来自操作系统和客户端 应用程序的视觉内容。这对应于特定屏幕的向 Web 公开的屏幕区域。
注: 网格大小通常表示为 <宽度>×<高度>。例如,1920×1080 的屏幕区域具有一个宽度为 1920 像素、高度为 1080 像素的网格,其中宽度为 1920 像素,高度为 1080 像素。
注: 如 CSSOM View § 2.3 向 Web 公开的屏幕信息中所规定,用户代理可以选择隐藏输出设备屏幕的信息,以保护用户隐私。 在这种情况下,屏幕区域可以等同于视口。
2.4. 可用屏幕区域
屏幕具有一个可用 屏幕区域,它是屏幕区域的一个矩形子集,操作系统 允许将 Web 应用程序窗口放置在其中。该矩形的边缘与屏幕区域 的边缘平行。该区域不包括屏幕区域中由操作系统保留用于其自身 用户界面元素的任何部分,例如任务栏和菜单栏。这等同于特定屏幕的向 Web 公开的可用屏幕区域。
2.5. 虚拟屏幕排列
设备具有一个虚拟屏幕排列,它定义组成设备整体视觉环境的各个屏幕的相对位置。该排列通常构成于一个向所有 方向延伸的二维平面上,其中(x, y)坐标分别从多屏 原点向右和向下增大。多屏原点是一个由实现定义的点,用于定义虚拟屏幕排列的(0, 0)坐标。
一种常见约定是将多屏原点设置为主屏幕的左上角,但它也可以是虚拟屏幕 排列中的任意点。每个屏幕的屏幕区域,都是虚拟屏幕排列的一个矩形子集的视图。
下图展示了多个屏幕在虚拟屏幕 排列中可能的若干排列方式,以及一些可能的多屏原点:
注: 第二屏社区组的外形规格说明报告草案探讨了相关术语和概念模型。
2.6. 屏幕位置
屏幕具有一个屏幕 位置,即屏幕区域在虚拟屏幕 排列中相对于多屏原点的(x, y)坐标。坐标可以为负数,通常表示为 (x, y)。
2.7. 可用屏幕位置
屏幕具有一个可用 屏幕位置,即可用屏幕区域在虚拟 屏幕排列中相对于多屏原点的(x, y)坐标。坐标可以为负数,通常表示为 (x, y)。
2.8. 主屏幕
托管用户代理的设备恰好具有一个主屏幕。 所有其他屏幕均视为辅助屏幕。
注: 主屏幕通常承载操作系统用于任务管理的用户界面, 例如 Windows 任务栏和 macOS 程序坞。
屏幕被指定为主屏幕或辅助屏幕的状态,可能会在用户代理运行期间发生变化。
注: 大多数操作系统允许用户通过管理用户界面选择主屏幕, 例如 Windows 控制面板和 macOS 系统设置应用程序。
2.9. 内置屏幕
每个屏幕都可以被指定为内置或外部屏幕。
外部屏幕与提供视觉输出的设备分开 制造。将一个外部屏幕从一台设备断开并连接到另一台设备并不少见。
注: 例如,台式计算机可以将其视觉输出显示在通过 HDMI 线缆连接的外部屏幕上。计算机 使用期间可以连接或断开 HDMI 线缆,计算机会调整其视觉环境,以适应该硬件配置变化。
内置屏幕通常在设备制造时安装到 设备上。内置屏幕并非设计为由用户 拆卸。然而,即使在用户代理运行期间,内置屏幕仍然可以被启用或禁用。
注: 例如,笔记本电脑在合上盖子时可以禁用其内置屏幕和输入设备。在此配置下, 仍可以通过外部屏幕和输入设备使用笔记本电脑。盖子合上时,被禁用的内置屏幕不能被报告为设备所使用的 屏幕。
2.10. 当前屏幕
在 Window
上下文中执行的脚本可以访问 screen
属性。该 Screen
对象反映当前屏幕的属性,即当前正在呈现窗口的屏幕。
注: 在许多操作系统上,一个窗口可以跨越具有不同属性的
多个屏幕呈现,也可以处于“隐藏”状态而不在任何屏幕上呈现。假定操作系统和用户代理会为给定的 Window
定义一个规范屏幕,例如与窗口相交面积最大的屏幕。
2.11. 可观察的屏幕属性
屏幕的基本可观察属性包括:
屏幕的高级可观察属性包括:
2.12. 窗口显示状态
顶级浏览上下文具有关联的显示状态,其值可以是 以下之一:
- 正常
-
窗口处于正常状态(既未最小化、最大化,也未进入全屏模式)。
- 最小化
-
窗口已最小化。
- 最大化
-
窗口已最大化。
- 全屏
-
窗口处于全屏模式。
3. API
3.1. Screen
接口的扩展
CSSOM View 模块
规范定义了 Screen
接口,本规范对其进行扩展:
- window . screen .
isExtended -
如果设备的视觉输出扩展到多个屏幕,则返回
true。 - window . screen .
onchange -
当窗口所在的屏幕或该屏幕的属性发生变化时触发。
partial interface Screen /* : EventTarget */ { [SecureContext ]readonly attribute boolean isExtended ; [SecureContext ]attribute EventHandler onchange ; };
在 CSSOM View § 4.3
Screen 接口中,使 Screen
派生自 EventTarget。
3.1.1.
isExtended
属性
isExtended 获取器步骤如下:
-
如果此对象的相关全局对象的关联 Document不被允许使用名为“
window-management”的策略控制特性,则返回 false 并中止这些步骤。 -
如果设备具有多个屏幕,则返回 true;否则返回 false。
3.1.2.
onchange
属性
onchange 属性是一个事件处理程序 IDL 属性,其事件处理程序事件类型为 change。
当 Window
window 的当前
屏幕的任何基本可观察属性发生变化时,使用窗口放置任务源,在
window 的相关全局对象上排入一个全局任务,以在 window 的 screen
属性所引用的 Screen
对象上触发一个事件,
其名称为 change。
3.2. Window
接口的扩展
[HTML] 标准定义了
Window
接口,本规范对其进行扩展:
- window .
getScreenDetails() -
返回一个 promise,该 promise 会兑现为一个
ScreenDetails对象,其中包含有关设备屏幕的信息。如果权限被拒绝,该 promise 将被拒绝。
partial interface Window { [SecureContext ]Promise <ScreenDetails >getScreenDetails (); [SecureContext ]Promise <undefined >minimize (); [SecureContext ]Promise <undefined >maximize (); [SecureContext ]Promise <undefined >restore (); [SecureContext ]Promise <undefined >setResizable (boolean ); };resizable
3.2.1. getScreenDetails()
方法
getScreenDetails()
方法异步完成,并将工作排入窗口放置任务源。
Window
实例在创建时会获得一个名为 [[screenDetails]] 的内部槽,其初始值为
undefined。
getScreenDetails() 方法步骤如下:
-
令 promise 为一个新的 promise。
-
如果此对象的相关全局对象的关联 Document不被允许使用名为“
window-management”的策略控制特性,则使用一个"NotAllowedError"DOMException拒绝 promise,并中止这些步骤。 -
并行运行以下步骤:
-
令 permissionState 为请求使用“
window-management”的权限所得的结果。 -
使用窗口放置任务源,在此对象的相关全局对象上排入一个全局任务,以运行以下步骤:
-
如果 permissionState 为“
denied”, 则使用一个"NotAllowedError"DOMException拒绝 promise,并中止这些步骤。 -
如果此对象.
[[screenDetails]]为undefined,则将此对象.[[screenDetails]]设置为一个新的ScreenDetails对象。 -
使用此对象.
[[screenDetails]]兑现 promise。
-
-
-
返回 promise。
3.2.2. 算法:请求更改窗口显示状态
要将目标显示状态 targetState 请求更改窗口显示状态:
-
令 promise 为一个新的 promise。
-
如果此对象的相关全局对象的关联 Document不被允许使用名为“
window-management”的策略控制特性,则使用一个"NotAllowedError"DOMException拒绝 promise,并中止这些步骤。 -
如果此对象的相关全局对象的关联 Document不是一个已安装的 Web 应用程序,则使用一个
"NotAllowedError"DOMException拒绝 promise,并中止这些步骤。 -
如果此对象的相关全局对象没有瞬时激活,则使用一个
"NotAllowedError"DOMException拒绝 promise,并中止这些步骤。 -
并行运行以下步骤:
-
令 permissionState 为请求使用“
window-management”的权限所得的结果。 -
使用窗口放置任务源,在此对象的相关全局对象上排入一个全局任务,以运行以下步骤:
-
如果 permissionState 为“
denied”, 则使用一个"NotAllowedError"DOMException拒绝 promise,并中止这些步骤。 -
令 state 为窗口的显示状态。
-
如果以下任一条件为真,则使用 undefined 兑现 promise,并中止这些步骤:
-
如果 targetState 为 "minimized" 或 "maximized":
-
请求用户代理将窗口的显示状态更改为 targetState。
-
-
否则,如果 targetState 为 "restored":
-
如果操作成功,则使用 undefined 兑现 promise。
-
如果操作失败,则使用一个
"NotAllowedError"DOMException拒绝 promise,并中止这些步骤。
-
-
-
返回 promise。
3.2.3.
minimize()
方法
minimize()
方法异步完成,并将工作排入窗口放置任务
源。
minimize() 方法步骤如下:
-
返回使用 "minimized" 运行请求更改窗口显示状态算法所得的结果。
3.2.4.
maximize()
方法
maximize()
方法异步完成,并将工作排入窗口放置任务
源。
maximize() 方法步骤如下:
-
返回使用 "maximized" 运行请求更改窗口显示 状态算法所得的结果。
3.2.5.
restore()
方法
restore()
方法异步完成,并将工作排入窗口放置任务
源。
restore() 方法步骤如下:
-
返回使用 "restored" 运行请求更改窗口显示 状态算法所得的结果。
3.2.6.
setResizable()
方法
setResizable()
方法异步完成,并将工作排入窗口放置任务
源。
setResizable(resizable) 方法步骤如下:
-
令 promise 为一个新的 promise。
-
如果此对象的相关全局对象的关联 Document不被允许使用名为“
window-management”的策略控制特性,则使用一个"NotAllowedError"DOMException拒绝 promise,并中止这些步骤。 -
如果此对象的相关全局对象的关联 Document不是一个已安装的 Web 应用程序,则使用一个
"NotAllowedError"DOMException拒绝 promise,并中止这些步骤。 -
并行运行以下步骤:
-
令 permissionState 为请求使用“
window-management”的权限所得的结果。 -
使用窗口放置任务源,在此对象的相关全局对象上排入一个全局任务,以运行以下步骤:
-
如果 permissionState 为“
denied”, 则使用一个"NotAllowedError"DOMException拒绝 promise,并中止这些步骤。 -
请求用户代理将窗口的可调整大小状态设置为 resizable。
-
如果操作成功,则使用 undefined 兑现 promise。
-
如果操作失败,则使用一个
"NotAllowedError"DOMException拒绝 promise,并中止这些步骤。
-
-
-
返回 promise。
3.2.7. Window
属性和方法定义的更改
以下 Window
属性和方法定义已更新,以返回和解释相对于多屏
原点的值:
-
screenX和screenLeft属性必须返回客户端窗口左边缘相对于多屏原点的 x 坐标, 以CSS 像素数表示; 如果不存在这样的值,则返回零。 -
screenY和screenTop属性必须返回客户端窗口上边缘相对于多屏原点的 y 坐标, 以CSS 像素数表示; 如果不存在这样的值,则返回零。
3.2.8. Window.open()
方法定义的更改
Window
实例在创建时会获得一个名为 [[targetScreenFullscreen]] 的内部槽,其数据模型等同于上次激活时间戳。除两种情况外,它对应一个 DOMHighResTimeStamp
值:正无穷表示该 Window
从未被激活;负无穷表示受用户激活限制的 API(参见 HTML
§ 6.4.3 受用户激活限制的 API)已消耗该 Window
的上一次用户激活。初始值为正无穷。
Window.open()
方法的步骤以及其中所调用方法的步骤已更新,以选择性地执行以下操作:
-
当相关全局对象的当前高分辨率时间大于或等于此对象.
[[targetScreenFullscreen]], 且小于此对象.[[targetScreenFullscreen]]加上瞬时激活持续时间时,免除瞬时激活状态要求。 -
在执行消耗用户激活的步骤之后,立即将此对象.
[[targetScreenFullscreen]]设置为负无穷。
3.3.
ScreenDetails
接口
- screenDetails .
screens -
返回一个由
ScreenDetailed对象组成的数组,其中每个对象描述一个屏幕。 - screenDetails .
currentScreen -
返回一个描述当前屏幕的
ScreenDetailed对象。该对象描述的屏幕与Window.screen所描述的屏幕相同,但提供了后者信息的超集。 - screenDetails .
onscreenschange - screenDetails .
oncurrentscreenchange
[Exposed =Window ,SecureContext ]interface :ScreenDetails EventTarget {readonly attribute FrozenArray <ScreenDetailed >screens ;readonly attribute ScreenDetailed currentScreen ;attribute EventHandler onscreenschange ;attribute EventHandler oncurrentscreenchange ; };
3.3.1. screens
属性
screens 获取器步骤如下:
3.3.2. currentScreen
属性
currentScreen 获取器步骤是返回 screens
中表示与此对象关联的 Window
对象的当前
屏幕的 ScreenDetailed
对象。
注: 假定操作系统和用户代理会定义 screens
中究竟哪个 ScreenDetailed
对象表示 Window
的当前
屏幕。这对应于 Window.screen,
即给定窗口的规范屏幕,例如与窗口相交面积最大的屏幕。
注: 保证 currentScreen
可以使用 === 与 screens
中的某个条目进行比较,以便进行此类比较,例如
screenDetails.screens.find(s => s !== screenDetails.currentScreen);。因此,不能将 currentScreen
标记为 [SameObject]。与此相关,添加到 currentScreen
的 change
事件监听器只会收到该特定屏幕变化的通知,而 currentscreenchange
事件监听器则会收到窗口碰巧所在的任何屏幕发生变化的通知,即窗口从一个屏幕移动到另一个屏幕后,窗口的当前屏幕所发生的变化。
3.3.3. onscreenschange
属性
onscreenschange 属性是一个事件处理程序 IDL 属性,其事件处理程序事件类型为 screenschange。
当 ScreenDetails
对象 screenDetails 的 screens
集合发生变化时,使用窗口放置任务源,在 screenDetails 的相关全局对象上排入一个全局任务,以在 screenDetails 上触发一个
事件,其名称为 screenschange。
3.3.4. oncurrentscreenchange
属性
oncurrentscreenchange 属性是一个事件处理程序 IDL 属性,其事件处理程序事件类型为 currentscreenchange。
当 Window
window 的当前屏幕
从一个屏幕变为另一个屏幕时(例如 Window
已移动到另一个显示器),或者当 window 的当前屏幕的任何基本
可观察属性或高级可观察属性发生变化时,使用窗口放置任务源,在
window 的相关全局对象上排入一个全局任务,以在 window 的内部槽 [[screenDetails]]
中存储的 ScreenDetails
对象上触发一个
事件,其名称为 currentscreenchange。
3.4.
ScreenDetailed
接口
ScreenDetailed
对象表示一个屏幕。
- screenDetailed .
availLeft -
返回从多屏原点到可用屏幕区域左边缘的距离。
- screenDetailed .
availTop -
返回从多屏原点到可用屏幕区域上边缘的距离。
- screenDetailed .
left -
返回从多屏原点到屏幕区域左边缘的距离。
- screenDetailed .
top -
返回从多屏原点到屏幕区域上边缘的距离。
- screenDetailed .
isPrimary -
返回操作系统是否将此屏幕指定为“主”屏幕(否则为“辅助”屏幕)。
- screenDetailed .
isInternal -
返回此屏幕是否为内置于设备中的“内置”面板,例如笔记本电脑显示器(否则为“外部”屏幕, 例如有线连接的显示器)。
- screenDetailed .
devicePixelRatio -
返回物理像素与逻辑像素之间的比率。
- screenDetailed .
label -
由用户代理和操作系统确定的、便于用户理解的屏幕标签。
[Exposed =Window ,SecureContext ]interface :ScreenDetailed Screen {readonly attribute long availLeft ;readonly attribute long availTop ;readonly attribute long left ;readonly attribute long top ;readonly attribute boolean isPrimary ;readonly attribute boolean isInternal ;readonly attribute float devicePixelRatio ;readonly attribute DOMString label ; };
availLeft 获取器步骤是返回此屏幕的可用屏幕位置的 x
坐标。
availTop 获取器步骤是返回此屏幕的可用屏幕位置的 y
坐标。
isPrimary 获取器步骤是:如果此屏幕是主屏幕,则返回
true;否则返回 false。
isInternal 获取器步骤是:如果此屏幕是内置屏幕,则返回 true;否则返回 false。
devicePixelRatio 获取器步骤是返回此屏幕的设备像素比。
3.4.1. onchange
属性
onchange 属性是从 Screen
继承的 onchange
属性。
当 ScreenDetailed
对象 screenDetailed 所表示的屏幕的任何基本可观察属性或高级可观察属性发生变化时,使用窗口放置任务源,在
screenDetailed 的相关全局对象上排入一个全局任务,以在 screenDetailed 上触发一个
事件,其名称为 change。
3.5.
FullscreenOptions
的扩展
partial dictionary FullscreenOptions {ScreenDetailed screen ; };
可选的 FullscreenOptions
screen 成员表示应用程序倾向于在特定屏幕上以全屏方式显示元素。用户代理始终可以优先遵循用户的偏好,而不是应用程序的偏好。
默认值 undefined 表示应用程序没有偏好。
3.5.1. Element.requestFullscreen()
方法定义的更改
Element.requestFullscreen()
方法的步骤已更新,以选择性地执行以下操作:
-
在移动和调整
pendingDoc的顶级浏览上下文的活动文档的视口大小时,考虑options["screen"]。 作为此修改后方法步骤的一部分,可以将视口移动到指定的屏幕。 -
如果
options["screen"] 指定了一个可识别的ScreenDetailed对象,且该对象的isExtended值为 true,则将此对象.[[targetScreenFullscreen]]内部槽设置为当前高分辨率时间。
3.6. CSS 扩展
本规范定义了新的 CSS 媒体特性,以允许样式表根据窗口状态进行调整。
3.6.1. 'display-state' 媒体特性
| 名称: | display-state |
|---|---|
| 适用于: | @media |
| 值: | normal | minimized | maximized | fullscreen |
| 类型: | 离散 |
'@media/display-state' 媒体特性描述当前浏览上下文向最终用户呈现时所处的窗口状态。在子浏览上下文中,显示状态必须与顶级浏览上下文的显示状态相匹配。
此特性主要用于确定主机操作系统向运行应用程序上下文的用户代理应用了哪个显示状态。
- normal
- 浏览上下文以正常显示状态显示。
- minimized
- 浏览上下文以最小化显示状态显示。
- maximized
- 浏览上下文以最大化显示状态显示。
- fullscreen
- 浏览上下文以全屏显示状态显示。
3.6.2. 'resizable' 媒体特性
| 名称: | resizable |
|---|---|
| 适用于: | @media |
| 值: | true | false |
| 类型: | 离散 |
'@media/resizable' 媒体特性描述用户是否可以调整窗口大小。
- true
- 用户可以通过拖动窗口边缘来调整窗口大小。
- false
- 用户不能通过拖动窗口边缘来调整窗口大小。
3.7. 权限 API 集成
本规范定义了一个默认强大特性,其名称
为“window-management”。
[permissions] API 为网站提供了 一种统一的方式来查询其权限状态。
注: 本文档先前发布的版本使用权限名称
"window-placement"。用户代理应谨慎迁移到更新后的权限字符串:“window-management”。
参见 #114。
将 window-management
添加到 [permissions]
注册表中。
定义权限被撤销时缓存 对象和方法步骤的行为。(参见 #80)
3.8. 权限策略集成
本规范定义了一个由字符串 "window-management" 标识的策略控制特性,用于控制是否可以使用 isExtended、
getScreenDetails
及其依赖功能。此特性的默认允许列表为
'self'。参见 [permissions-policy] 及其实验性
特性列表。
注: 文档的
权限策略决定该文档中的任何内容是否被允许从 isExtended
获取有意义的值、访问 ScreenDetails
或将内容放置在特定屏幕上。如果此特性被禁用,isExtended
将返回 false,getScreenDetails
返回的 promise 将被拒绝,并且将内容放置在特定屏幕上的请求将被限制到当前屏幕。
在适当时,将 window-management
移至提议的
或已标准化的
特性列表。
4. 安全注意事项
本规范允许网站将内容放置在特定屏幕上,这可能会带来有限的新安全风险:
-
网站可能会尝试在用户意料之外的屏幕上醒目地显示敏感内容
-
网站可能会尝试在不太显眼的屏幕上秘密显示不良内容,例如:
-
网站可能会尝试冒充操作系统、浏览器或其他网站来实施网络钓鱼攻击,方法是将用户的注意力吸引到特定 屏幕,并利用该屏幕上的交互信号,在另一个不太受关注的屏幕上显示欺骗性内容
-
网站可能会尝试以其他方式将内容放置在特定屏幕上,从而实施欺骗、滥用或令人烦扰的行为
为帮助缓解此类风险,跨屏放置功能要求在安全上下文中获得明确权限,并受 [permissions-policy] 约束,后者默认阻止第三方访问。
用户代理可以检测跨屏放置请求,并进行干预以保护用户免受潜在滥用。例如,当网站将内容放置在另一个屏幕上, 或窗口在跨屏放置后获得用户关注时,用户代理可以显示醒目的安全界面。此外,跨屏放置请求可以被拒绝或限制到 当前屏幕,这与某些用户代理已有的行为一致。
还需注意以下几点:
-
某些用户代理已不会将窗口放置请求限制在当前屏幕内;它们将
open()和moveTo()的坐标解释为相对于多屏原点的坐标,并接受将窗口放置在当前屏幕以外屏幕上的请求。 -
requestFullscreen()和open()通常已经要求瞬时用户激活,但moveTo()、moveBy()、resizeTo()和resizeBy()则不要求。 -
将内容放置在当前屏幕以外的屏幕上,不太可能给用户带来额外的点击劫持风险, 因为用户的光标或手指很可能与当前屏幕位于 同一位置,而不是位于单独的屏幕上。
-
根据指定权限限制旧有放置功能可能是可行的。
有关安全注意事项的其他探讨,请参见以下内容:
5. 隐私注意事项
本规范向网站公开有关连接到设备的屏幕的新信息,这可能会带来有限的新隐私风险。这些附加信息会增加设备的 指纹识别表面,尤其是具有非典型屏幕配置的 设备。
为帮助缓解此类风险,新信息被缩减到常见放置使用场景所需的最低限度;大多数访问要求在安全上下文中获得明确 权限,并受 [permissions-policy] 约束,后者默认阻止第三方访问。公开的屏幕列表 具有规定的顺序,以减少互操作性问题并缓解指纹识别。通常,用户代理可以在网站请求任何新信息时进行衡量和其他 形式的干预。
Screen.isExtended 布尔值在没有明确权限检查的情况下公开,因为这一个最小的信息位支持某些关键
功能,而为这些功能显示权限提示会造成干扰(例如显示或隐藏“在另一个屏幕上显示”等多屏 UI 入口),并有助于
避免不必要地向单屏用户请求不适用的信息和功能。这通常遵循 TAG 关于设备枚举的设计原则(参见 Web 平台设计
原则 § 9.2 公开用于选择或枚举设备的 API 时应谨慎)。
许多用户代理实际上已经向位于辅助屏幕上的窗口公开多个屏幕的存在,因为在这种情况下,
window.screen.availLeft|Top >> 0。脚本访问此信息位是一种可检测的主动指纹识别信号,用户代理可以观察并阻止它。此外,
不将未经许可的窗口放置请求限制在当前屏幕上的用户代理,允许攻击者尝试以编程方式将窗口放置在
其他屏幕上,此时有关该 window.screen 的信息便会被公开。
新的 Screen.onchange 事件会使临时指纹识别更加容易,因此会带来
轻微风险,但脚本已经可以通过轮询 window.screen 的变化实现相同结果。可以通过延迟隐藏文档的
事件分派,直到这些文档不再隐藏,来部分缓解此风险。
本规范考虑了向网站赋予较少能力的替代 API 形式,但这些形式会给用户和开发者带来较差的体验(例如提示用户 选择屏幕、要求开发者以声明方式为屏幕排序)。对于将应用程序窗口以非全屏方式放置在任何已连接屏幕上,几乎 没有其他替代方案。指定的 API 形式似乎是现有 API 最自然的扩展,可支持更加完整的多屏环境。未来的工作可能 包括查询限制更多的多屏信息的方法,使网站可以主动将其信息暴露降至最低。
指定的 API 设计允许用户代理使用新的访问模型选择性地公开屏幕,例如限制与用户所指示屏幕相关的屏幕信息和 放置功能。
还需注意以下几点:
-
根据指定权限限制旧有屏幕和窗口信息可能是可行的。
有关隐私注意事项的其他探讨,请参见以下内容:
6. 无障碍注意事项
本规范允许网站将内容放置在特定屏幕上,这可能会带来有限的无障碍新风险。视觉呈现、非视觉渲染以及辅助技术 对内容本身的影响,通常不会因内容被放置在某个屏幕还是另一个屏幕上而受到显著影响。不过,由于内容可放置的 区域得到扩展,以编程方式放置内容带来的现有无障碍风险仍可能加剧。与默认强大特性权限模型、提示方法和权限相关 UI 有关的现有 无障碍注意事项,也同样适用于本规范的特定权限。
目前尚无关于此 API 所公开的结构化屏幕信息及其无障碍特性的已记录无障碍注意事项。
7. 国际化注意事项
目前尚无已记录的国际化注意事项。
8. 致谢
衷心感谢 Adrienne Walker、 Anssi Kostiainen、 Chris Terefinko、 Domenic Denicola、 Jonathan Garbee、 Kenneth Rohde Christiansen、 L. David Baron、 Lukasz Olejnik、 Marijn Kruisselbrink、 Matt Giuca、 Michael Ketting、 Nadav Sinai、 Peter Linss、 Reilly Grant、 Staphany Park、 Theresa O’Connor、 Thomas Nattestad、 Thomas Steiner 和 Victor Costan 对本规范制定工作的帮助。
特别感谢 Tab Atkins, Jr. 创建并维护用于编制本文档的规范创作工具 Bikeshed,以及他提供的一般性创作建议。