获取已连接显示屏的信息,以及相对于这些显示屏放置窗口。
窗口管理 API
借助 Window Management API,您可以枚举连接到计算机的显示屏 以及将窗口放置在特定屏幕上
建议的用例
可以使用此 API 的网站示例包括:
- 多窗口图形编辑器 Gimp 可以在 Google Cloud 上 编辑工具。
- 虚拟交易公司可通过多个窗口显示市场趋势,其中任一窗口均可查看 全屏模式。
- 幻灯片应用可以在内部主屏幕中显示演讲者备注,并在 外部投影仪
如何使用 Window Management API
问题
久经考验的窗户控制方法
Window.open()
,很遗憾
而不知道额外屏幕虽然该 API 的某些方面有点陈旧,
windowFeatures
DOMString
参数,但这些年来它仍为我们提供了很大的帮助。要指定窗口的
position 之后,您可以传递
坐标为 left
和 top
(或分别为 screenX
和 screenY
),并传递所需的
size 为
width
和 height
(或分别为 innerWidth
和 innerHeight
)。例如,要打开
400×300 窗口,距左侧 50 像素,距顶部 50 像素,这就是
可以使用:
const popup = window.open(
'https://example.com/',
'My Popup',
'left=50,top=50,width=400,height=300',
);
您可以查看
window.screen
属性:
会返回一个 Screen
对象。这是
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
*/
与大多数技术行业员工一样,我必须适应新的工作现实, 个人家庭办公室。我的矿物在下面的照片上看起来很像(如果您感兴趣,可以阅读 有关我的设置的完整详细信息)。 我的 MacBook 旁边的 iPad 通过 Sidecar,这样每当需要时,我都可以快速 iPad 切换到第二屏幕。
<ph type="x-smartling-placeholder">如果我想利用更大的屏幕,可以将弹出式窗口从 代码示例。我处理 如下所示:
popup.moveTo(2500, 50);
这是粗略的猜测,因为我们无法知道第二个屏幕的尺寸。信息
(来自 window.screen
)仅覆盖内置屏幕,不会覆盖 iPad 屏幕。报告的width
1680
像素,因此2500
像素可能
因为我恰好知道它位于 MacBook 的右侧。方法
在一般情况下,我可以这样做吗?但事实证明,还有比猜测更好的方法。这样,
Window Management API。
功能检测
如需检查 Window Management API 是否受支持,请使用以下命令:
if ('getScreenDetails' in window) {
// The Window Management API is supported.
}
window-management
权限
我必须先向用户请求权限,然后才能使用 Window Management API。
您可以使用window-management
Permissions API,如下所示:
let granted = false;
try {
const { state } = await navigator.permissions.query({ name: 'window-management' });
granted = state === 'granted';
} catch {
// Nothing.
}
当浏览器处于使用旧权限和新权限时,请确保在请求权限时使用防御性代码,如下例所示。
async function getWindowManagementPermissionState() {
let state;
// The new permission name.
try {
({ state } = await navigator.permissions.query({
name: "window-management",
}));
} catch (err) {
return `${err.name}: ${err.message}`;
}
return state;
}
document.querySelector("button").addEventListener("click", async () => {
const state = await getWindowManagementPermissionState();
document.querySelector("pre").textContent = state;
});
浏览器 可以 选择在首次尝试使用 新 API。请阅读下文,了解详情。
window.screen.isExtended
属性
如果想了解我的设备是否连接了多个屏幕,我会访问
window.screen.isExtended
属性。它会返回 true
或 false
。对于我的设置,它返回了 true
。
window.screen.isExtended;
// Returns `true` or `false`.
getScreenDetails()
方法
在确定当前设置是跨屏设置后,我可以获取更多有关
显示第二个屏幕(使用 Window.getScreenDetails()
)。调用此函数将显示权限提示,
询问该网站是否可以打开并在我的屏幕上放置窗口。该函数返回一个 promise
使用 ScreenDetailed
对象解析。在连接了 iPad 的 MacBook Pro 13 上,
这包含一个带有两个 ScreenDetailed
对象的 screens
字段:
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: "Built-in Retina Display"
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: "Sidecar Display (AirPlay)"
left: 1680
onchange: null
orientation: ScreenOrientation {angle: 0, type: "landscape-primary", onchange: null}
pixelDepth: 24
top: 0
width: 1366
}]
}
*/
screens
数组中提供了已连接屏幕的相关信息。请注意
对于 iPad,left
以 1680
开头,这正是内置显示屏的 width
。本次
我可以准确确定屏幕的逻辑排列方式(相邻,
相互通信等等)。系统现在还会提供每个屏幕的数据,以显示相应屏幕是否是 isInternal
屏幕
以及是否为 isPrimary
。请注意,内置屏幕
不一定是主屏幕
currentScreen
字段是与当前 window.screen
对应的有效对象。对象
会随着跨屏窗口展示位置或设备变化而更新。
screenschange
事件
现在唯一缺少的就是检测屏幕设置何时发生变化。一个新活动
screenschange
就是这样做的:每当修改屏幕全景荟萃时,它都会触发。(通知
“屏幕”在事件名称中是复数形式。)这意味着每当有新的屏幕或
现有屏幕(如果是 Sidecar,则是实际或虚拟方式)插入或拔出。
请注意,您需要异步查询新的屏幕详情,即 screenschange
事件。
本身不提供此类数据。如需查询屏幕详情,请使用缓存中的活动对象
Screens
接口。
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
事件
如果我只对当前屏幕的更改(即当前对象的值)感兴趣
currentScreen
),则可以监听 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
事件
最后,如果我只对某个具体屏幕的更改感兴趣,就可以监听该屏幕的
change
事件。
const firstScreen = (await window.getScreenDetails())[0];
firstScreen.addEventListener('change', async (event) => {
console.log('The first screen has changed.', event, firstScreen);
});
新的全屏选项
在此之前,您可以通过适当命名的
requestFullScreen()
方法。该方法带有一个 options
参数,您可以将该参数传递到
FullscreenOptions
。到目前为止,
它的唯一属性
navigationUI
。
Window Management API 添加了一个新的 screen
属性,可让您确定
从哪个屏幕启动全屏视图。例如,如果您希望将主屏幕设为
全屏:
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);
}
聚酯纤维
无法对 Window Management API 执行 polyfill 操作,但可以对其形状进行转换, 您可以专门针对新 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;
}
API 的其他方面,即各种屏幕更改事件和 screen
属性
FullscreenOptions
只会被触发,或被静默忽略,
浏览器不受支持。
演示
如果您像我一样,就要密切关注各种工具的发展 以及加密货币。(实际上,我其实并不爱这颗星球,但是, 在本文中,假设 did.)为了跟踪我拥有的加密货币,我开发了一款 Web 应用, 留意生活中各种情形的市场,比如在舒适的床上, 单屏设置
<ph type="x-smartling-placeholder">这与加密货币有关,市场可能随时都很忙。如果发生这种情况 移到我的办公桌上,那里有一个跨屏设备。我可以点击任意币种对应的窗口 在另一屏幕的全屏视图中快速查看全部细节。以下是最近拍摄的照片 这是我上次 YCY 血浴期间拍摄的。它抓住了我 我完全不知所措,留下了我 双手放在脸上。
<ph type="x-smartling-placeholder">您可以播放下方嵌入的演示,也可以查看其源代码,查看是否存在故障。
安全与权限
Chrome 团队设计并实施了 Window Management API,该 API 的核心是 控制对强大的网络平台功能的访问权限中定义的原则, 包括用户控制、透明度和人体工程学。Window Management API 提供 与连接到设备的屏幕有关的新信息,扩大了指纹的指纹识别面 用户,尤其是那些有多个屏幕一直连接到其设备的用户。合并为一个 为缓解这一隐私问题,公开的屏幕属性被限制在 了解常见的展示位置用例。网站需要用户权限才能使用跨屏功能 并将窗口放置在其他屏幕上。Chromium 会返回详细的屏幕标签, 浏览器可以随意返回较少的描述性内容(甚至是空标签)。
用户控制
用户可完全控制其设置的公开范围。他们可以接受或拒绝 权限提示,以及通过 。
企业控制
Chrome 企业版用户可以从多个方面控制 Window Management API,例如 请参阅 原子政策组 设置。
透明度
“是否有权使用 Window Management API”这一事实为 还会显示在浏览器的网站信息中,并且可通过 Permissions API 查询。
权限保留
浏览器会保持权限授予状态。可通过浏览器的网站撤消权限 信息。
反馈
Chrome 团队希望了解您使用 Window Management API 的体验。
向我们介绍 API 设计
API 是否有什么无法按预期运行?或者是否缺少方法 需要哪些资源或属性来实现您的想法?对安全性有疑问或意见 模型?
- 在相应的 GitHub 代码库中提交规范问题,或将您的想法添加到现有 问题。
报告实现存在的问题
您在 Chrome 的实现过程中是否发现了错误?或者,实现是否与规范不同?
- 在 new.crbug.com 上提交 bug。请务必提供尽可能多的细节信息
以及简单的重现说明,然后在
Blink>Screen>MultiScreen
组件框中。Glitch 非常适用于分享轻松快速的重现问题。
表示对 API 的支持
您打算使用 Window Management API 吗?您的公开支持对 Chrome 很有帮助 确定各项功能的优先级,并向其他浏览器供应商展示支持这些功能的重要性。
- 请在 WICG Discourse 会话中说明您打算如何使用它。
- 使用 # 标签向 @ChromiumDev 发送推文
#WindowManagement
和 请告诉我们您使用它的地点和方式。 - 请求其他浏览器供应商实现 API。
实用链接
- 规范草稿
- 公开铺垫消息
- Window Management API 演示 |Window Management API 演示 来源
- Chromium 跟踪错误
- ChromeStatus.com 条目
- Blink 组件:
Blink>Screen>MultiScreen
- 代码审核
- 愿意进行实验
致谢
Window Management API 规范的修改者 Victor Costan, Joshua Bell 和 Mike Wasserman。 此 API 由 Mike Wasserman 和 Adrienne Walker。本文由以下人员审核: Joe Medley、François Beaufort、 以及凯斯·巴斯克语感谢 Laura Torrent Puig 提供照片。