跳转到内容

能力 · API

Window Management API

发布于

有限可用不支持的浏览器: Firefox (Desktop)、Firefox (Android)、Safari (macOS)、Safari (iOS)W3C 草案

Window Management API 让页面得知设备有几块屏幕、各在什么位置,然后把窗口放到指定屏幕上。window.screen.isExtended 无需提示即可回答第一个问题;window.getScreenDetails() 请求 window-management 权限,并以 ScreenDetails 对象兑现,其 screens 数组为每块显示器提供一个 ScreenDetailed,坐标相对于多屏原点,这样 window.open() 的 features 与 requestFullscreen({ screen }) 就能指向某块显示器。

Chrome 100 在桌面端发布了 getScreenDetails()、Screen.isExtended 和 ScreenDetailed;Edge 与 Opera 继承该实现,Android 版 Chrome 暴露相同接口。Firefox 和 Safari 任何版本都没有实现(BCD api.Window.getScreenDetails)。所有接口都带 [SecureContext]。

window.screen.isExtended
window.getScreenDetails()
screenDetails.screens
screenDetails.currentScreen
element.requestFullscreen({ screen: screenDetailed })

isExtended 是现有 Screen 接口上的同步 boolean。getScreenDetails() 返回 Promise<ScreenDetails>;对同一个 Window 每次调用返回同一个 ScreenDetails 对象,显示器增减时触发 screenschange,窗口移到另一块显示器或所在屏幕的属性变化时触发 currentscreenchange。ScreenDetailed 继承自 Screen,所以除下表成员外还有 width、height、availWidth、availHeight、colorDepth 和 orientation。

getScreenDetails() 不接受参数。它返回的对象携带以下成员;FullscreenOptions 的 screen 成员是该 API 新增的唯一输入。

成员 类型 必填 说明
ScreenDetails.screens FrozenArray<ScreenDetailed> 只读 全部屏幕,先按 left 再按 top 排序。集合变化时换成新数组。
ScreenDetails.currentScreen ScreenDetailed 只读 窗口所在的屏幕;与 screens 中的某一项 ===,所以 screens.find(s => s !== currentScreen) 可以选出副屏。
ScreenDetailed.left、ScreenDetailed.top long 只读 多屏原点到该屏幕左边缘、上边缘的距离,单位 CSS 像素。
ScreenDetailed.availLeft、ScreenDetailed.availTop long 只读 同上,但针对排除任务栏与 Dock 的可用区域。在 window.open() 的 features 里用作 left/top。
ScreenDetailed.isPrimary boolean 只读 操作系统指定的主显示器为 true。
ScreenDetailed.isInternal boolean 只读 笔记本屏幕之类的内置面板为 true,外接显示器为 false。
ScreenDetailed.devicePixelRatio float 只读 该屏幕的物理像素与 CSS 像素之比,可能不同于 window.devicePixelRatio。
ScreenDetailed.label DOMString 只读 操作系统提供的名称,例如 "Built-in Retina Display" 或 "DELL U2720Q";可能为空。
FullscreenOptions.screen ScreenDetailed 否 要求 requestFullscreen() 先把窗口移到该屏幕。浏览器可以转而尊重用户偏好。

规范为 getScreenDetails() 定义了一种拒绝名称,并在相关的 minimize()、maximize()、restore() 和 setResizable() 方法中复用(见 getScreenDetails() 方法(w3.org))。

异常 条件
NotAllowedError 文档不被允许使用 window-management Permissions Policy 特性(默认允许列表为 'self');或权限请求的结果为 "denied",原因是用户拒绝了提示,或者调用时没有瞬时激活而权限仍是 "prompt"。窗口显示状态方法在文档不是已安装 Web 应用、缺少瞬时激活或操作系统拒绝更改时也以它拒绝。

isExtended 不抛任何异常,Permissions Policy 拦截该特性时返回 false,所以 false 的含义是「单屏,或不被允许知道」。screen 选项若指向另一个窗口的 ScreenDetails 里的 ScreenDetailed,会被忽略而不是拒绝。

每个示例都退化为单屏行为:Firefox 和 Safari 永远走不到多屏分支,Chrome 上用户拒绝权限时该分支也会被跳过。

先检查 isExtended(无提示),在 click 处理函数内调用 getScreenDetails() 以便允许弹出权限提示,任何失败都回退到普通的 window.open()。

button.addEventListener("click", async () => {
const url = "/presenter-notes";
if (!("getScreenDetails" in window) || !window.screen.isExtended) {
window.open(url, "_blank", "popup");
return;
}
try {
const details = await window.getScreenDetails();
const target = details.screens.find((s) => s !== details.currentScreen) ?? details.currentScreen;
const features = `popup,left=${target.availLeft},top=${target.availTop},width=${target.availWidth},height=${target.availHeight}`;
window.open(url, "_blank", features);
} catch (err) {
console.warn(`${err.name}: ${err.message}`);
window.open(url, "_blank", "popup");
}
});

权限授予后,features 字符串里的 left 和 top 按多屏原点解释,所以位于主屏左侧或上方的显示器用负坐标是合法的。

在外接显示器上全屏演示,笔记留在笔记本屏幕

Section titled “在外接显示器上全屏演示,笔记留在笔记本屏幕”

把选中的 ScreenDetailed 作为 FullscreenOptions.screen 传入。规范允许一次成功的跨屏全屏请求为紧随其后的一次 window.open() 免去激活要求,这正是同一次点击还能打开笔记窗口的原因。

async function startPresentation(slides) {
if (!("getScreenDetails" in window)) {
return slides.requestFullscreen(); // 仅当前屏幕
}
const details = await window.getScreenDetails();
const external = details.screens.find((s) => !s.isInternal);
if (!external) return slides.requestFullscreen();
await slides.requestFullscreen({ screen: external });
const notes = details.screens.find((s) => s.isInternal) ?? details.currentScreen;
window.open("/notes", "_blank", `popup,left=${notes.availLeft},top=${notes.availTop},width=800,height=600`);
}

每块屏幕都报告 isInternal: false(接两台显示器的台式机)时,代码回退到当前屏幕而不是猜测。

screenschange 在 ScreenDetails 对象上触发,而不是在 window 上,并且 screens 数组是整体替换而非原地修改。在处理函数里重新读取它,并关闭所在屏幕已消失的伴随窗口。

async function watchScreens(onChange) {
if (!("getScreenDetails" in window)) {
window.screen.addEventListener("change", () => onChange([window.screen]));
return;
}
const details = await window.getScreenDetails();
onChange(details.screens);
details.addEventListener("screenschange", () => onChange(details.screens));
details.addEventListener("currentscreenchange", () => {
document.documentElement.style.setProperty("--dpr", details.currentScreen.devicePixelRatio);
});
}

单屏回退监听的是同一份规范为 Screen 新增的 change 事件,窗口当前屏幕的基本属性(尺寸、方向、像素比)变化时触发。

规范

规范状态
Window Management(窗口管理)W3C 草案
Window Management: getScreenDetails() methodW3C 草案
Window Management: ScreenDetailed interfaceW3C 草案
Window Management: extensions to FullscreenOptionsW3C 草案
  • 图例
  • 支持
  • 部分支持
  • 需开启标志
  • 不支持
  • 未知
浏览器 / 平台支持版本置信度来源备注
Chrome (Desktop)支持100高来源—
Chrome (Android)支持100高来源1
Edge (Desktop)支持100高来源2
Firefox (Desktop)不支持—高来源3
Firefox (Android)不支持—高来源45
Safari (macOS)不支持—高来源6
Safari (iOS)不支持—高来源78
Samsung Internet支持19.0高来源9
WebView (Android)支持100高来源10
  1. 由 browser-compat-data 镜像自 Chrome 的数据推导。
  2. 由 browser-compat-data 镜像自 Chrome 的数据推导。
  3. browser-compat-data 未记录 Firefox 的支持。
  4. browser-compat-data 未记录 Firefox for Android 的支持。
  5. 由 browser-compat-data 镜像自 Firefox 的数据推导。
  6. browser-compat-data 未记录 Safari 的支持。
  7. browser-compat-data 未记录 iOS 版 Safari 的支持。
  8. 由 browser-compat-data 镜像自 Safari 的数据推导。
  9. 由 browser-compat-data 镜像自 Chrome Android 的数据推导。
  10. 由 browser-compat-data 镜像自 Chrome Android 的数据推导。

源数据: /compatibility/window-management.json · 全球使用占比: 72 % (StatCounter 2026-05)

来源: 规范 · MDN · 最近核验 2026-10-03 · 置信度: 高 (由来源计算)