窗口管理

W3C 工作草案,

关于本文档的更多信息
该版本:
https://www.w3.org/TR/2024/WD-window-management-20240607/
最新发布版本:
https://www.w3.org/TR/window-management/
编辑草案:
https://w3c.github.io/window-management/
以往版本:
历史记录:
https://www.w3.org/standards/history/window-management/
反馈:
GitHub
规范内讨论
编辑者:
(Google Inc.)
(Google Inc.)
测试套件:
https://github.com/web-platform-tests/wpt/tree/master/window-management
https://github.com/web-platform-tests/wpt/tree/master/screen-details

摘要

本文档定义了一个 Web 平台 API,允许脚本查询设备的屏幕信息,并在特定屏幕上展示内容。

本文档状态

本节描述了本文档在发布时的状态。当前 W3C 出版物列表及本技术报告的最新修订版,可在 W3C 技术报告索引(https://www.w3.org/TR/)找到。

本文档由 Second Screen 工作组 作为工作草案,并采用了 推荐轨道。本文档计划成为 W3C 推荐标准。

Second Screen 工作组维护着 尚未处理的所有问题列表。本草案标出了一些仍待小组讨论的问题。对于这些问题的结果,包括其是否有效,目前尚未作出决定。欢迎提交针对未解决问题的规范文本合并请求。

工作草案的发布并不代表 W3C 及其成员的认可。此文档为草案,随时可能更新、替换或废止。除作进行中工作外,不应引用此文档。

本文档由遵循 W3C 专利政策 的小组编写。W3C 保持一份 与小组交付物相关的专利披露公开列表;该页面亦包括披露专利的说明。了解到某项专利且认为其包含必要权利要求的个人,必须依照W3C 专利政策第6节进行披露。

本文档受 2023年11月3日 W3C 流程文档 管辖。

1. 引言

本节为非规范性内容。

操作系统通常允许用户将多个屏幕连接到单一设备上,并以虚拟方式排列这些屏幕,从而扩展整体的视觉工作区域。

多种应用程序会利用平台工具在这种多屏环境中放置其内容,但 Web 应用开发者受限于现有 API,这些 API 通常是围绕单一屏幕的使用设计的。

随着多屏设备和应用成为用户体验中越来越常见且重要的一部分,提供信息和工具让 Web 开发者能够充分利用扩展的视觉环境变得更加重要。

本规范按步骤扩展了 WindowScreenFullscreenOptions 等 API,并引入了新的 ScreenDetailsScreenDetailed 接口。这些改变允许 Web 应用通过在特定屏幕上放置内容,提供引人入胜的多屏体验。

1.1. 动机与用例

本规范旨在为拥有多屏设备的 Web 应用用户带来更好的体验。以下用例为设计提供了参考:

1.2. 用法概览

为支持多屏体验,该 API 允许 Web 应用:

  1. 检测设备是否存在多个屏幕

  2. 请求在特定屏幕上放置内容所需的信息

  3. 检测屏幕的添加或移除

  4. 检测当前屏幕或其属性的变化

  5. 将某个元素以全屏方式显示在特定屏幕上

  6. 将窗口放置在特定屏幕上

  7. 通过单次用户操作启动多屏体验

API 用法的一个基本示例如下:

// Detect if the device has more than one screen.
if (window.screen.isExtended) {
  // Request information required to place content on specific screens.
  const screenDetails = await window.getScreenDetails();

  // Detect when a screen is added or removed.
  screenDetails.addEventListener('screenschange', onScreensChange);

  // Detect when the current \`ScreenDetailed\` or an attribute thereof changes.
  screenDetails.addEventListener('currentscreenchange', onCurrentScreenChange);

  // Find the primary screen, show some content fullscreen there.
  const primaryScreen = screenDetails.screens.find(s => s.isPrimary);
  document.documentElement.requestFullscreen({screen : primaryScreen});

  // Find a different screen, fill its available area with a new window.
  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 {
  // Detect when an attribute of the legacy \`Screen\` interface changes.
  window.screen.addEventListener('change', onScreenChange);

  // Arrange content within the traditional single-screen environment...
}

1.2.1. 检测多屏存在

支持多屏体验的核心问题之一,是设备是否有多个屏幕可用于放置内容。这些屏幕可以是设备的内置显示(如笔记本的显示屏)、通过有线连接(如电脑通过 HDMI 连上显示器)、通过其他方式连接(如 Mac 和 iPad 的 Sidecar 功能),或者通过显示虚拟化实现。isExtended 布尔值用于此判断,对安全上下文开放且无需权限提示。

if (screen.isExtended) {
  // Offer multi-screen controls for the user.
}

1.2.2. 检测 Screen 属性变化

监听传统 Screen 属性变化对内容适配很有用,即使是在单屏设备上。此外,监听 isExtended 有助于检测单屏与多屏配置之间的切换。为避免轮询,change 事件会在 Screen 对象上触发:

screen.addEventListener('change', e => {
  // An attribute of the legacy \`Screen\` interface has changed.
});

1.2.3. 请求详细屏幕信息

可通过 getScreenDetails() 方法请求设备使用的屏幕详细信息。该方法可能会弹出权限请求。得到的 ScreenDetails 对象允许开发者枚举所有屏幕、检查其属性并监听变化。

try {
  // Request screen details and process the information immediately.
  const screenDetails = await window.getScreenDetails();
  processScreenDetails(screenDetails);

  // Process updated screen details when the set of screens change.
  screenDetails.onscreenschange = () => {
    processScreenDetails(screenDetails);
  };
} catch (err) {

  console.error(err);
  // Handle denied permission and other errors.
}

function processScreenDetails(screenDetails) {
  // Build a UI listing screens, using assumed helpers.
  clearScreenList();
  screenDetails.screens.forEach(screen => {
    addToScreenList({name: screen.label, screen: screen});
    // Process updated screen details when a particular screen's details change.
    screen.onchange = () => {
      processScreenDetails(screenDetails);
    };
  });
  selectCurrentInScreenList(screenDetails.currentScreen);
}

1.2.4. 在特定屏幕上放置全屏内容

一个常见的多屏用例是在特定屏幕上以全屏形式展示部分内容。屏幕可以通过交互选择,也可以基于屏幕属性或先前选择自动选出。一旦选定屏幕,可作为参数传递给 requestFullscreen() 方法。

// Call an assumed helper that returns a selected \`ScreenDetailed\` instance.
const screenDetailed = getScreenForSlideshow();

// Request that a particular element be shown fullscreen on the selected screen.
slideshowElement.requestFullscreen({ screen: screenDetailed });

1.2.5. 在特定屏幕上放置窗口

另一个常见的多屏用例是在特定屏幕上放置窗口。这可以结合 ScreenDetailed 接口提供的坐标,与现有 open()moveTo() 方法完成。

function openCenteredWindow(url, screenDetailed, w, h) {
  // Compute coordinates centering the window on the target screen.
  const l = screenDetailed.left + Math.round(screenDetailed.width - w) / 2;
  const t = screenDetailed.top + Math.round(screenDetailed.height - h) / 2;

  // Open the window with the requested dimensions.
  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 () => {
  // Find the primary screen, show some content fullscreen there.
  const primaryScreen = screenDetails.screens.find(s => s.isPrimary);
  await document.documentElement.requestFullscreen({screen : primaryScreen});

  // Find a different screen, fill its available area with a new window.
  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. 屏幕

承载用户代理的设备拥有单个 screen 或多个 screens,用于显示视觉内容。screens 的集合可能随用户代理运行期间设备硬件或软件配置的变更而变化。

注: 屏幕配置变化的一些基本例子包括:通过 HDMI 线把电视或投影仪接到笔记本电脑,合上笔记本盖从而关闭内置 LCD 屏,更改接入 LCD 显示器的分辨率等。

一个 screen 拥有 色深,即屏幕像素的 色深

一个 screen 拥有 设备像素比,类似 WindowdevicePixelRatio ,其值计算方式如下:

  1. CSS pixel sizeCSS 像素 的大小。

  2. device pixel size像素 的垂直尺寸。

  3. 返回 CSS pixel size 除以 device pixel size 的结果。

一个 screen 拥有 方向,定义见 [screen-orientation]

一个 screen 拥有 标签,即用于帮助用户区分识别屏幕的有意义描述字符串。

注: 标签 可以是用户代理选择的任意字符串。它可能描述屏幕与设备的关系,如 "internal""external";也可能包含分辨率信息,如 "640×480";还可能包含硬件型号,如 "Acme Telletube 1000x"(取自 VESA E-EDID 数据)、区分编号如 "screen 1""screen 2",甚至全部兼有。如果底层显示详情未知,或用户代理选择隐藏这些信息,也可为空串。应用不能假定标签一定包含设备类型、型号、尺寸、密度等特定信息。

虽然许多屏幕属性都可能被用于 主动指纹识别,但 标签 所用字符串尤其应谨慎,尽量降低唯一性。例如,不应将设备序列号包含其中。

设备像素比 是否应计入 页面缩放

2.2. 屏幕像素

一个屏幕具有像素,像素是屏幕中可以直接编程的最小组件。每个像素显示一种颜色。

注:在液晶显示屏(LCD)上,每个像素由三个分量组成,每个分量为(红、绿、蓝)可变强度的光。关于像素分量(亚像素渲染)的讨论不在本规范范围内。

注:有些屏幕可以被配置为以与物理硬件固有排列不同的分辨率进行内容显示;例如,硬件分辨率为2560×1440的显示器可被设备设置为1920×1080的显示分辨率。

一个像素具有色深,即用于表示它能显示颜色的位数。

注:一些流行的渲染系统将像素建模为具有24位色深。这3组8位分别表示LCD像素的红、绿、蓝亚像素的强度。

2.3. 屏幕区域

一个屏幕具有屏幕区域,这是一个二维矩形格网,由像素组成,用于向用户显示来自操作系统和客户端应用程序的视觉内容。这对应于特定屏幕Web公开屏幕区域

一个屏幕区域具有宽度,即矩形格网水平方向上的像素数量。

一个屏幕区域具有高度,即矩形格网竖直方向上的像素数量。

注:格网大小通常表示为<宽度>×<高度>。例如,1920×1080的屏幕区域即宽度为1920像素、高度为1080像素的格网。

注:CSSOM View § 2.3 Web公开屏幕信息 所述,UA 可选择隐藏显示设备屏幕的信息,以保护用户隐私。在此情况下,屏幕区域可等同于视口

2.4. 可用屏幕区域

一个屏幕具有可用屏幕区域,是屏幕区域的矩形子集,操作系统允许Web应用窗口放置在其中。该矩形的边缘与屏幕区域边平行。此区域不包括任何被操作系统保留用于自身 UI 元素(如任务栏、菜单栏)的屏幕区域部分。等价于特定屏幕Web公开可用屏幕区域

一个屏幕可用宽度,即可用屏幕区域矩形格网水平方向上的像素数量。

一个屏幕可用高度,即可用屏幕区域矩形格网竖直方向上的像素数量。

2.5. 虚拟屏幕排列

设备有一个虚拟屏幕排列,用于定义组成设备整体视觉环境的屏幕的相对位置。排列通常在一个二维平面上组成,向右和向下 (x, y) 坐标分别递增,原点为多屏原点多屏原点是实现自定义的点,定义了虚拟屏幕排列的(0, 0)坐标。

常见做法是将多屏原点设置在屏幕的左上角,但它也可以是虚拟屏幕排列内的任意点。每个屏幕屏幕区域都是对虚拟屏幕排列矩形子集的可视。

下图展示了多屏幕虚拟屏幕排列中的一些排列示例,以及一些可能的多屏原点

Diagram showing various examples of screens and multi-screen origins

注:Second Screen Community GroupForm Factors Explained 草案报告探讨了相关术语和概念模型。

2.6. 屏幕位置

一个屏幕具有屏幕位置,即其屏幕区域虚拟屏幕排列中相对于多屏原点的(x, y)坐标。坐标可为负数,通常写作(x, y)。

2.7. 可用屏幕位置

一个屏幕具有可用屏幕位置,即其可用屏幕区域虚拟屏幕排列中相对于多屏原点的(x, y)坐标。坐标可为负数,通常写作(x, y)。

2.8. 主屏幕

承载用户代理的设备恰好有一个屏幕。其它所有屏幕皆为

注:主屏幕通常承载操作系统的任务管理界面,如 Windows 任务栏或 macOS Dock。

一个屏幕被指定为的身份可能会在用户代理运行时发生变化。

注:大多数操作系统允许用户通过管理界面(如 Windows 控制面板和 macOS 偏好设置)选择主屏幕。

2.9. 内置屏幕

每个屏幕可以被指定为内置外接

外接屏幕是由提供其视觉输出的设备单独制造的。一块外接屏幕可以从一个设备上断开连接再连接到另一设备上,这很常见。

注:例如,一台台式机可能通过HDMI线将其视觉输出显示在外接屏上。HDMI线可随时插拔,计算机会随硬件变更调整视觉环境。

内置屏幕通常在设备生产时就被装配上。内置屏不是给用户拆卸用的。但内置屏幕 依然可以在用户代理运行时被启用或禁用。

注:例如,笔记本合盖时会禁用内置屏幕及输入设备,用户可以通过外接屏幕和输入设备继续使用。关闭时禁用的内置屏幕在合盖期间不会作为设备使用的屏幕上报。

2.10. 当前屏幕

Window上下文中运行的脚本可以访问screen属性。此Screen对象反映了当前屏幕的属性,即当前在该屏幕上展示窗口的屏幕

注:在许多操作系统下,窗口可能横跨不同属性的多个屏幕,也可能处于“隐藏”状态不显示在任何屏幕上。操作系统和UA通常为给定Window确定一个标准屏幕,比如与窗口交集面积最大者。

2.11. 可观察屏幕属性

屏幕基础可观察属性包括:

屏幕进阶可观察属性包括:

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

Screen 继承自 EventTarget ,详见 CSSOM View § 4.3 The Screen Interface

3.1.1. isExtended 属性

isExtended getter 步骤如下:

  1. 如果this相关全局对象相关文档权限使用名为"window-management"的策略受控特性,返回 false 并终止步骤。

  2. 如设备有一个以上屏幕,返回 true,否则返回 false。

3.1.2. onchange 属性

onchange 属性是事件处理IDL属性,其事件处理类型change

Window window当前屏幕的任何基础可观察属性发生变化时,在window相关全局对象上使用window placement task source排队一个全局任务触发一个事件,事件名为change,目标是由windowScreen属性引用的对象。

3.2. Window 接口的扩展

[HTML] 标准定义了 Window 接口,本规范对此进行扩展:

window . getScreenDetails()

返回一个 promise,当其完成时会获得一个关于设备屏幕信息的 ScreenDetails 对象。如果权限被拒,promise 将被拒绝。

partial interface Window {
  [SecureContext]
  Promise<ScreenDetails> getScreenDetails();
};

3.2.1. getScreenDetails() 方法

getScreenDetails() 方法是异步完成的,其工作会被排入 window placement task source

Window 的实例创建时包含名为 [[screenDetails]]内部槽位,初始值为 undefined

getScreenDetails() 方法步骤如下:

  1. promise新建的 promise

  2. 如果this相关全局对象相关文档权限使用名为"window-management"的策略受控特性,则用 "NotAllowedError" DOMException 拒绝 promise,并终止步骤。

  3. 如下步骤并行执行:

    1. permissionState请求使用权限 "window-management" 的结果。

    2. 排队全局任务this 的相关全局对象,用 window placement task source 执行以下步骤:

      1. 如果 permissionState 为 "denied", 则用 "NotAllowedError" DOMException 拒绝 promise,并终止步骤。

      2. 如果this.[[screenDetails]]undefined,则设置 this.[[screenDetails]] 为新的 ScreenDetails 对象。

      3. 解决 promise,值为 this.[[screenDetails]]

  4. 返回 promise

3.2.2. Window 属性和方法定义变更

如下 Window 属性和方法定义被更新为返回和解释相对于多屏原点的值:

3.2.3. Window.open() 方法定义变更

Window 实例创建时有个名为 [[targetScreenFullscreen]]内部槽,该槽在数据模型上等价于上次激活时间戳。其对应于 DOMHighResTimeStamp 类型值,除了两种特殊情况:正无穷表示该窗口从未被激活,负无穷表示用户激活门控 API(见 HTML § 6.4.3 用户激活门控 API消耗了该窗口的上次激活。初始值为正无穷。

Window.open() 方法及其中调用方法的步骤被更新,可选择性地:

  1. 瞬时激活状态要求被放宽(即 当前高精度时间 大于等于 相关全局对象this.[[targetScreenFullscreen]] 且小于 this.[[targetScreenFullscreen]]瞬时激活时间时。

  2. 消耗用户激活步骤后,立即将 this.[[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 getter 步骤如下:

  1. screens 为新的 列表

  2. 对于设备的每个 screen屏幕):

    1. a 为描述 screenScreenDetailed 对象。

    2. a 添加到 screens

  3. 返回 升序排序 screens(依据 屏幕排序算法)的结果。

屏幕排序 算法定义:如果以下判断为真,则认为某 屏幕 a 小于另一个 屏幕 b

  1. 如果 a屏幕位置 x 坐标小于 b屏幕位置 x 坐标,则返回 true。

  2. 如果 b屏幕位置 x 坐标小于 a屏幕位置 x 坐标,则返回 false。

  3. 如果 a屏幕位置 y 坐标小于 b屏幕位置 y 坐标,则返回 true。

  4. 否则返回 false。

3.3.2. currentScreen 属性

currentScreen getter 步骤为返回 ScreenDetailed 对象,该对象在 screens 中,代表与 当前屏幕 相关联的 Window 对象。

注: 哪个 ScreenDetailed 对象在 screens 中代表某个 Window当前屏幕,通常由操作系统和用户代理定义。这与 Window.screen 一致,即窗口的规范屏幕,例如与窗口交集区域最大者。

注: currentScreen 保证可以通过 ===screens 中的某项比较相等,便于如 screenDetails.screens.find(s => s !== screenDetails.currentScreen); 这类比较。因此 currentScreen 不会被标记为 [SameObject]。类似地,添加在 change 上的事件监听器仅会通知对应 screen 的变化,而监听 currentscreenchange 的监听器会收到当前 screen (即窗口切换到不同屏幕后) 的变化事件。

3.3.3. onscreenschange 属性

onscreenschange 属性是事件处理 IDL 属性,其事件类型screenschange

当某 ScreenDetails 对象 screenDetailsscreens 集合发生变化时,需在 screenDetails相关全局对象上用 window placement task source 触发 screenschange 事件

3.3.4. oncurrentscreenchange 属性

oncurrentscreenchange 属性是事件处理 IDL 属性,其事件类型currentscreenchange

当某 Window window当前屏幕由一个 screen 变为另一个(例如窗口被移动到不同的显示屏),或 window当前屏幕 的任何 基础可观察属性高级可观察属性发生变化时,要在 window相关全局对象上用 window placement task source 触发 currentscreenchange 事件,目标为 ScreenDetails 对象(存储在 window 的内部槽 [[screenDetails]] 中)。

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 getter 步骤为返回 可用屏幕位置 的 x 坐标。

availTop getter 步骤为返回 可用屏幕位置 的 y 坐标。

left getter 步骤为返回 屏幕位置 的 x 坐标。

top getter 步骤为返回 屏幕位置 的 y 坐标。

isPrimary getter 步骤为:如 this screen 屏幕,返回 true,否则为 false。

isInternal getter 步骤为:如 this screen内置,返回 true,否则为 false。

devicePixelRatio getter 步骤为返回 设备像素比

label getter 步骤为返回 标签

3.4.1. onchange 属性

onchange 属性是继承自 onchange 的属性,来自 Screen

ScreenDetailed 对象 screenDetailed 所代表的 屏幕 的任一 基础可观察属性高级可观察属性变更时,要在 screenDetailed相关全局对象上用 window placement task source 触发 change 事件

3.5. FullscreenOptions 的扩展

fullscreenOptions . screen

为元素全屏请求指定一个 屏幕

partial dictionary FullscreenOptions {
  ScreenDetailed screen;
};

可选成员 FullscreenOptionsscreen,表示应用希望将元素全屏显示在特定 屏幕 上。用户代理总是可优先考虑用户偏好而非应用优先级。默认值 undefined 表示无应用偏好。

3.5.1. Element.requestFullscreen() 方法定义变更

Element.requestFullscreen() 方法的步骤可选地:

  1. 当调整 pendingDoc顶级浏览上下文活动文档视口时,如 options["screen"] 有指定,可将视口移动到指定 屏幕

  2. options["screen"] 指定的 ScreenDetailed 对象且其 isExtended 为 true,则将本对象的 [[targetScreenFullscreen]] 内部槽设置为当前高精度时间

3.6. 权限 API 集成

本规范定义了一个默认强大特性,其名称为 name "window-management"。

[permissions] API 提供了统一方式供网站查询其权限状态。

注: 本文档之前公开的版本使用了权限名 "window-placement"。用户代理应谨慎迁移到新的权限字符串 "window-management"。参见 #114

window-management 添加到 [permissions] 注册表。

定义当权限被撤销时缓存对象和方法步骤的行为。(见 #80

3.7. 权限策略集成

本规范定义了一个策略受控特性,字符串为 "window-management",用于控制是否允许 isExtendedgetScreenDetails 及相关功能的使用。该特性的默认允许列表'self'。参见 [permissions-policy] 及其 Experimental Features 列表。

注: 一个 document 的权限策略决定了该文档内的任何内容是否能从 isExtended 获取有效值、访问 ScreenDetails 或在特定屏幕上放置内容。如被禁用,isExtended 返回 false,getScreenDetails 返回的 promise 会被拒绝,试图将内容放到特定屏幕会被限定在 当前屏幕

适当时将 window-management 移至 ProposedStandardized 列表。

4. 安全性考量

本规范使站点可以将内容放置在特定屏幕上,这可能带来有限的新安全风险:

  1. 站点可能试图在意外的屏幕上突出显示敏感内容

  2. 站点可能试图秘密地在不显眼的屏幕上显示不良内容,例如:

  3. 站点可能通过将用户的注意力吸引到特定屏幕上,并利用那里的交互信号,在其他较少被注意的屏幕上显示带有欺骗性的内容,从而试图伪造操作系统、浏览器或其他站点进行钓鱼攻击

  4. 站点可能试图以其他欺骗性、滥用性或令人烦恼的方式,将内容放置在特定屏幕上

为帮助缓解这些风险,跨屏幕放置能力要求在安全上下文中获得明确许可,并受 [permissions-policy] 约束,默认防止第三方访问。

用户代理可以检测跨屏幕放置请求,并采取措施保护用户免受潜在的滥用。例如,当站点将内容放置在另一个屏幕上,或者窗口在跨屏幕放置后获得用户关注时,用户代理可以显示明显的安全界面。此外,跨屏幕放置请求可以被拒绝或限制在 当前屏幕,以符合一些用户代理的现有行为。

其他补充说明:

请参阅以下关于安全性考量的深入探讨:

5. 隐私性考量

本规范向站点暴露了关于设备连接屏幕的新信息,这可能带来有限的新隐私风险。此额外信息增加了设备的 指纹识别 面,尤其是在屏幕配置非典型的设备上。

为缓解这些风险,新信息被压缩到常见放置场景所需的最小值,大部分访问需要在安全上下文中明确授权,并受到 [permissions-policy] 约束,默认防止第三方访问。暴露出来的屏幕列表有明确顺序,以减少互操作性问题并缓解指纹化。用户代理通常可以检测并干预站点请求新信息的行为。

Screen.isExtended 布尔值无需明确权限检查即可暴露,因为这一最小的单比特信息支持一些关键特性(例如显示/隐藏“在另一屏幕显示”等多屏 UI 入口),提示授权会打扰用户,并有助于避免对单屏用户无意义的提示。这通常符合 TAG 设备枚举设计原则(参见 Web Platform Design Principles § device-enumeration)。

很多用户代理已经通过 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(本规范编写所用工具),以及他在规范撰写方面的指导。

一致性

文档约定

一致性要求通过描述性断言和 RFC 2119 术语的组合表达。 规范性文本中的关键字 “MUST”、 “MUST NOT”、 “REQUIRED”、 “SHALL”、 “SHALL NOT”、 “SHOULD”、 “SHOULD NOT”、 “RECOMMENDED”、 “MAY” 和 “OPTIONAL” 应根据 RFC 2119 的描述加以理解。 不过,为了可读性,本规范中这些词并非都用全大写字母表示。

除明确标记为非规范性、示例和注释的部分外,本规范所有文本均为规范性内容。[RFC2119]

本规范中的示例会用 “for example” 引出,或用 class="example" 与规范性文本区分开,如下所示:

这是一个知识性示例。

说明性注释以 “Note” 开头,或用 class="note" 与规范性文本区分开,如下所示:

注:这是一个说明性注释。

一致性算法

以命令式措辞写在算法(如 "strip any leading space characters" 或 "return false and abort these steps")中的要求,应根据该算法引言处用到的关键字(如 "must"、"should"、"may" 等)加以理解。

以算法或具体步骤表达的一致性要求可通过任何方式实现,只要最终结果等效即可。特别地,本规范定义的算法意在易于理解,而非追求性能,鼓励实现者优化。

索引

本规范定义的术语

引用定义的术语

参考文献

规范性引用

[CSS-VALUES-4]
Tab Atkins Jr.; Elika Etemad. CSS Values and Units Module Level 4. 12 March 2024. WD. URL: https://www.w3.org/TR/css-values-4/
[CSSOM-VIEW-1]
Simon Pieters. CSSOM View Module. 17 March 2016. WD. URL: https://www.w3.org/TR/cssom-view-1/
[DESIGN-PRINCIPLES]
Sangwhan Moon; Lea Verou. Web Platform Design Principles. 30 January 2024. NOTE. URL: https://www.w3.org/TR/design-principles/
[DOM]
Anne van Kesteren. DOM Standard. Living Standard. URL: https://dom.spec.whatwg.org/
[ECMASCRIPT]
ECMAScript Language Specification. URL: https://tc39.es/ecma262/multipage/
[FINGERPRINTING-GUIDANCE]
Nick Doty. Mitigating Browser Fingerprinting in Web Specifications. 28 March 2019. NOTE. URL: https://www.w3.org/TR/fingerprinting-guidance/
[Fullscreen]
Philip Jägenstedt. Fullscreen API Standard. Living Standard. URL: https://fullscreen.spec.whatwg.org/
[HR-TIME-3]
Yoav Weiss. High Resolution Time. 19 July 2023. WD. URL: https://www.w3.org/TR/hr-time-3/
[HTML]
Anne van Kesteren; et al. HTML Standard. Living Standard. URL: https://html.spec.whatwg.org/multipage/
[INFRA]
Anne van Kesteren; Domenic Denicola. Infra Standard. Living Standard. URL: https://infra.spec.whatwg.org/
[PERMISSIONS]
Marcos Caceres; Mike Taylor. Permissions. 19 March 2024. WD. URL: https://www.w3.org/TR/permissions/
[PERMISSIONS-POLICY]
Ian Clelland. Permissions Policy. 18 December 2023. WD. URL: https://www.w3.org/TR/permissions-policy-1/
[RFC2119]
S. Bradner. Key words for use in RFCs to Indicate Requirement Levels. March 1997. Best Current Practice. URL: https://datatracker.ietf.org/doc/html/rfc2119
[WEBIDL]
Edgar Chen; Timothy Gu. Web IDL Standard. Living Standard. URL: https://webidl.spec.whatwg.org/

参考性引用

[SCREEN-ORIENTATION]
Marcos Caceres. Screen Orientation. 9 August 2023. WD. URL: https://www.w3.org/TR/screen-orientation/

IDL 索引

partial interface Screen /* : EventTarget */ {
  [SecureContext]
  readonly attribute boolean isExtended;

  [SecureContext]
  attribute EventHandler onchange;
};

partial interface Window {
  [SecureContext]
  Promise<ScreenDetails> getScreenDetails();
};

[Exposed=Window, SecureContext]
interface ScreenDetails : EventTarget {
  readonly attribute FrozenArray<ScreenDetailed> screens;
  readonly attribute ScreenDetailed currentScreen;

  attribute EventHandler onscreenschange;
  attribute EventHandler oncurrentscreenchange;
};

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

partial dictionary FullscreenOptions {
  ScreenDetailed screen;
};

问题索引

设备像素比是否应包含页面缩放?
CSSOM View § 4.3 The Screen Interface 中让 Screen 继承自 EventTarget
window-management 添加到 [permissions] 注册表。
定义当权限被撤销时缓存对象和方法步骤的行为。(参见 #80
window-management 在适当时移动到 ProposedStandardized feature 列表。
请确认我们没有漏掉任何人!