# Window Management API：跨多屏放置窗口

> window.screen.isExtended 和 Window.getScreenDetails() 如何暴露多屏布局细节、window-management 权限提示、安全上下文要求，以及根据 MDN 当前仅 Chromium 支持的现状。

**一句话：** Window Management API 让页面发现用户设备上连接的屏幕，并在指定屏幕上打开或
移动窗口——`window.screen.isExtended` 报告是否存在多于一个屏幕，而受权限门控的
`Window.getScreenDetails()` 返回每个屏幕的位置、尺寸、方向等细节，以便精确放置窗口。

## `isExtended` 与 `getScreenDetails()` 的区别

- **`window.screen.isExtended`** 是现有 `Screen` 接口上的一个布尔属性。根据 MDN，设备拥有
  多个屏幕时返回 `true`，否则返回 `false`。根据 MDN，仅 `getScreenDetails()` 被记录为会
  触发权限提示——因此可以在决定是否提供多窗口布局之前先安全地检查 `isExtended`。
- **`Window.getScreenDetails()`** 才是真正提供逐屏数据的 API。它返回一个解析为
  `ScreenDetails` 对象的 `Promise`，列出设备可用的每个屏幕。根据 MDN，调用它会向用户
  请求跨显示器管理窗口的权限；返回的 `ScreenDetails.screens` 数组携带每个屏幕的位置和
  尺寸，供调用方计算新窗口应打开在何处。

## 权限模型

- 根据 MDN，调用 `getScreenDetails()` 会请求权限；可以通过
  `navigator.permissions.query({ name: 'window-management' })` 在不触发提示的情况下读取
  其状态。
- 根据 MDN，`getScreenDetails()` 和 `isExtended` 都需要**安全上下文**（HTTPS 或
  `localhost`）。
- 根据 MDN，若设置了阻止该 API 的 `window-management` Permissions-Policy，
  `getScreenDetails()` 会以 `NotAllowedError` 拒绝，`isExtended` 则始终报告 `false`。

## 在指定屏幕上放置窗口

```js
async function openOnSecondaryScreen(url) {
  if (!('getScreenDetails' in window)) {
    // 回退：没有多屏 API——在默认屏幕上打开单个窗口。
    window.open(url, '_blank');
    return;
  }
  try {
    const screenDetails = await window.getScreenDetails();
    const target = screenDetails.screens.find((s) => s !== screenDetails.currentScreen)
      ?? screenDetails.screens[0];
    window.open(
      url,
      '_blank',
      `left=${target.availLeft},top=${target.availTop},width=${target.availWidth},height=${target.availHeight}`,
    );
  } catch (err) {
    // 用户拒绝了权限提示，或被 Permissions-Policy 阻止。
    window.open(url, '_blank');
  }
}
```

## 特性检测与回退

在提供多窗口布局之前先检查 `window.screen.isExtended`——它不需要权限提示——然后在调用
`getScreenDetails` 前对其本身做特性检测，并在任一检查失败时始终回退到普通的单屏
`window.open()`：

```js
if (window.screen.isExtended && 'getScreenDetails' in window) {
  // 提供"跨所有屏幕打开"的能力。
} else {
  // 单屏，或该 API 不可用：表现为普通的单窗口应用。
}
```

## 浏览器与生态支持

根据 MDN，Window Management API 是**实验性**技术，尚未进入 Baseline，因为并非所有主流
浏览器都支持它。`getScreenDetails()` 和 `isExtended` 已在 Chrome 和 Edge 中实现；Firefox
和 Safari（包括 iOS Safari）均未实现。

## 实践清单

- [ ] 先检查 `window.screen.isExtended`——它不需要权限提示，可以据此判断多窗口布局是否
      可行。
- [ ] 调用 `getScreenDetails()` 前先做 `'getScreenDetails' in window` 特性检测——它在
      Chromium 之外的浏览器中不存在。
- [ ] 用 `try`/`catch` 包裹 `getScreenDetails()`——被拒绝或被 `window-management`
      Permissions-Policy 阻止时会以 `NotAllowedError` 拒绝。
- [ ] 在不支持的浏览器或权限被拒绝时始终回退到普通的 `window.open()`——不要让多窗口路径
      成为唯一选项。
- [ ] 通过 HTTPS（或 `localhost`）提供页面；该 API 在安全上下文之外不可用。

## 相关参考

- [display_override](/zh/reference/manifest/display-override/)
- [标签页应用模式](/zh/reference/manifest/tabbed-display/)