
NW.js Screen API 完全指南屏幕信息查询、显示事件监听与桌面捕获【免费下载链接】nw.jsCall all Node.js modules directly from DOM/WebWorker and enable a new way of writing applications with all Web technologies.项目地址: https://gitcode.com/gh_mirrors/nw/nw.jsnw.Screen是 NW.js 暴露给 Node.js/浏览器混合环境的屏幕管理单例对象用于读取物理屏幕与工作区信息、监听屏幕增删与分辨率变化事件并通过chooseDesktopMedia与DesktopCaptureMonitor两条路径实现桌面/窗口捕获屏幕共享。读完本文你将掌握从初始化、事件订阅到getUserMedia采集桌面的完整实战链路并理解其底层与 Chromiumgfx::Display及 WebRTC Desktop Capture 的对接原理。概述Screen 是一个单例 EventEmitter在 NW.js 中nw.Screen是EventEmitter的实例因此可以使用nw.Screen.on(...)响应系统原生屏幕事件显示器拔插、分辨率/排列变化等。与大多数 NW.js API 不同Screen是一个单例对象必须在调用任何nw.Screen方法之前先通过nw.Screen.Init()初始化一次。从 screen.js 的实现可以看到Init()内部用screenInstance缓存实例只有第一次调用才会真正new Screen()之后exports.Screen被替换为实例对象重复调用是幂等的exports.Screen { Init: function() { if (screenInstance null) { screenInstance new Screen(); } exports.Screen screenInstance; return screenInstance; } };Screen对象通过nw.allocateObject分配原生对象句柄并继承exports.Base其on/addListener被重写只允许监听四个事件displayBoundsChanged、displayAdded、displayRemoved以及内部使用的chooseDesktopMedia监听其他事件名会直接抛出TypeErrorScreen.prototype.on Screen.prototype.addListener function(ev, callback) { if ( ev ! displayBoundsChanged ev ! displayAdded ev ! displayRemoved ev ! chooseDesktopMedia) throw new TypeError(only following event can be listened: displayBoundsChanged, displayAdded, displayRemoved); ... };同时该重写实现了懒注册第一个监听器挂上时才调用nw.callStaticMethodSync(Screen, AddScreenChangeCallback, [this.id])向原生侧注册屏幕变化回调最后一个监听器移除时自动调用RemoveScreenChangeCallback注销避免空转的系统监听开销。基本用法Synopsis文档给出的标准启动与监听示例// init must be called once during startup, before any function to nw.Screen can be called nw.Screen.Init(); var screenCB { onDisplayBoundsChanged: function(screen) { console.log(displayBoundsChanged, screen); }, onDisplayAdded: function(screen) { console.log(displayAdded, screen); }, onDisplayRemoved: function(screen) { console.log(displayRemoved, screen) } }; // listen to screen events nw.Screen.on(displayBoundsChanged, screenCB.onDisplayBoundsChanged); nw.Screen.on(displayAdded, screenCB.onDisplayAdded); nw.Screen.on(displayRemoved, screenCB.onDisplayRemoved);提示nw.Screen.Init()建议放在应用启动阶段如package.json的main脚本或dom-ready事件中执行一次即可无需也不应重复初始化。仓库的冒烟测试 screen-events/index.html 演示了先Init()再绑定三个显示事件的标准流程。Screen.Init()初始化Screen单例对象整个应用生命周期只需调用一次。任何nw.Screen的方法或属性访问尤其是screens与事件监听都应在Init()之后进行。Screen.screensnw.Screen.screens返回连接到计算机的显示器数组数组长度即屏幕数量。在 JS 侧这是一个 getter内部通过nw.callStaticMethodSync(Screen, GetScreens, [])同步获取并JSON.parse得到对象数组见 screen.js。每个screen对象具有如下结构screen { // unique id for a screen id: int, // physical screen resolution, can be negative, not necessarily start from 0,depending on screen arrangement bounds: { x: int, y: int, width: int, height: int }, // useable area within the screen bound work_area: { x: int, y: int, width: int, height: int }, scaleFactor: float, isBuiltIn: bool, rotation: int, touchSupport: int }字段说明id屏幕的唯一标识。bounds物理屏幕分辨率逻辑像素。注意坐标可以为负、不一定从 0 开始——取决于多显示器的排列方式例如副屏位于主屏左侧时x为负值。work_area屏幕边界内的可用区域扣除任务栏/ Dock 等系统 UI 后的区域。scaleFactor设备缩放因子如 Retina 屏为 2.0对应高分屏缩放。isBuiltIn是否为内置屏幕如笔记本自带面板。rotation屏幕旋转角度度。touchSupport触摸支持级别。这些字段在原生侧由 screen.cc 的DisplayToJSON()从 Chromiumgfx::Display直接序列化而来bounds()/work_area()取自gfx::RectscaleFactor对应device_scale_factor()isBuiltIn对应IsInternal()rotation对应RotationAsDegree()。GetScreens则遍历gfx::Screen::GetNativeScreen()-GetAllDisplays()拼接 JSON 数组见 screen.cc。Display的完整字段定义也可在 nw_screen.idl 中查看。Screen.chooseDesktopMedia (sources, callback)通过系统原生选择器让用户选择要共享的屏幕或窗口然后回调返回可用于getUserMedia的streamId。sources{String[]}源类型数组本 API 支持两种取值screen与window。callback{Function}携带所选streamId的回调函数若执行失败或已存在活动的选择会话则streamId为false。注意该功能依赖系统级选择器 GUI目前仅在 Windows、OS X 以及部分 Linux 发行版上可用。示例nw.Screen.Init(); // you only need to call this once nw.Screen.chooseDesktopMedia([window,screen], function(streamId) { var vid_constraint { mandatory: { chromeMediaSource: desktop, chromeMediaSourceId: streamId, maxWidth: 1920, maxHeight: 1080 }, optional: [] }; navigator.webkitGetUserMedia({audio: false, video: vid_constraint}, success_func, fallback_func); } );在拿到streamId后将其填入getUserMedia视频约束的chromeMediaSource: desktop与chromeMediaSourceId: streamId即可把屏幕/窗口画面作为媒体流交给success_func使用如渲染到video标签、录制或推流。底层实现要点见 desktop_capture_api.cc原生侧遍历sources数组识别window与screen分别置位show_windows/show_screens若两者都不满足直接返回错误At least one source type must be specified.。通过 WebRTC 的webrtc::ScreenCapturer与webrtc::WindowCapturer构建NativeDesktopMediaList再创建DesktopMediaPicker弹出选择器。DesktopMediaPicker只在TOOLKIT_VIEWSAura Linux/Windows或OS_MAC下实现其他平台返回Desktop Capture API is not yet implemented for this platform.——这正是文档注明平台限制的原因。回调结果经ChooseDesktopMediaCallback以chooseDesktopMedia事件形式派发给 JS 侧见 screen.ccscreen.js中chooseDesktopMedia返回true并注册一次性this.once(chooseDesktopMedia, callback)监听见 screen.js。若上一次选择会话gpDCCDMF尚未结束再次调用会直接返回falseJS 侧chooseDesktopMedia也随之返回false而不触发回调见 screen.cc。显示事件以下三个事件均通过 Chromium 的gfx::DisplayObserver驱动原生侧JavaScriptDisplayObserver在屏幕指标变化、新增、移除时把DisplayToJSON序列化后的屏幕对象以事件形式派发到 JS见 screen.cc。Event: displayBoundsChanged(screen)屏幕分辨率或排列布局发生变化时触发。回调携带 1 个参数screen格式同 Screen.screens。Event: displayAdded (screen)检测到新的屏幕接入时触发。回调携带 1 个参数screen格式同上。Event: displayRemoved (screen)已有屏幕被移除时触发。回调携带 1 个参数screen被移除屏幕的信息格式同上。Screen.DesktopCaptureMonitorScreen.DesktopCaptureMonitor提供了与chooseDesktopMedia类似的能力但不带系统 GUI——适合希望自行实现选择 UI 的场景如自定义缩略图选择面板。它同样是EventEmitter实例可用Screen.DesktopCaptureMonitor.on()监听事件。Synopsisvar dcm nw.Screen.DesktopCaptureMonitor; nw.Screen.Init(); dcm.on(added, function (id, name, order, type) { //select first stream and shutdown var constraints { audio: { mandatory: { chromeMediaSource: system, chromeMediaSourceId: dcm.registerStream(id) } }, video: { mandatory: { chromeMediaSource: desktop, chromeMediaSourceId: dcm.registerStream(id) } } }; // TODO: call getUserMedia with contraints dcm.stop(); }); dcm.on(removed, function (id) { }); dcm.on(orderchanged, function (id, new_order, old_order) { }); dcm.on(namechanged, function (id, name) { }); dcm.on(thumbnailchanged, function (id, thumbnail) { }); dcm.start(true, true);事件与原生侧的对应关系可在 nw_screen_api.cc 中找到added对应OnSourceAdded、removed对应OnSourceRemoved、orderchanged对应OnSourceMoved、namechanged对应OnSourceNameChanged、thumbnailchanged对应OnSourceThumbnailChanged事件名与参数定义见 nw_screen.idl。Screen.DesktopCaptureMonitor.started布尔值表示DesktopCaptureMonitor是否已处于启动监控状态。Screen.DesktopCaptureMonitor.start(should_include_screens, should_include_windows)should_include_screens{Boolean}是否监控屏幕源。should_include_windows{Boolean}是否监控窗口源。启动系统监控并开始触发事件。注意监控运行期间屏幕画面可能出现闪烁因此应尽量缩短监控窗口期。Screen.DesktopCaptureMonitor.stop()停止监控。选定一个流之后应立即调用stop()避免持续占用捕获资源与引起画面闪烁。Screen.DesktopCaptureMonitor.registerStream(id)将事件回调中拿到的源id注册为有效的流 ID并返回可直接填入getUserMedia约束chromeMediaSourceId的字符串。用法见上文 Synopsis。Event: added (id, name, order, type, primary)警告行为变更该特性在 0.13.0 中发生了变化详见 Migration Notes from 0.12 to 0.13。当新增一个可捕获源时触发。参数id{String}媒体 ID。需调用registerStream(id)得到可用于getUserMedia()的合法流 ID。name{String}窗口标题或屏幕名称。order{Integer}窗口的 Z 轴顺序若选择了屏幕屏幕源会排在最前。type{String}流类型取值为screen、window、other或unknown。primary{Boolean}仅 Windows 有效源为主显示器时该值为true。Event: removed (order)当某个源不再可捕获被移除时触发。参数order{Integer}被移除媒体源在列表中的顺序。Event: orderchanged (id, new_order, old_order)警告行为变更该特性在 0.13.0 中发生了变化详见 Migration Notes from 0.12 to 0.13。当某个源的 Z 轴顺序改变例如窗口被聚焦/失焦导致层级变化时触发。参数id{String}Z 轴顺序发生变化的屏幕或窗口的媒体 ID。new_order{Integer}新的 Z 轴顺序。old_order{Integer}旧的 Z 轴顺序。Event: namechanged (id, name)警告行为变更该特性在 0.13.0 中发生了变化详见 Migration Notes from 0.12 to 0.13。当源名称改变如窗口标题变化时触发。参数id{String}名称发生变化的屏幕或窗口的媒体 ID。name{String}该屏幕或窗口的新名称。Event: thumbnailchanged (id, thumbnail)警告行为变更该特性在 0.13.0 中发生了变化详见 Migration Notes from 0.12 to 0.13。当源的缩略图更新时触发。参数id{String}缩略图发生更新的屏幕或窗口的媒体 ID。thumbnail{String}Base64 编码的 PNG 缩略图数据可直接赋给img srcdata:image/png;base64,...渲染。最佳实践与注意事项先Init()再使用所有nw.Screen操作都依赖单例初始化Init()幂等可放心在启动阶段调用一次。事件监听白名单nw.Screen.on只接受displayBoundsChanged、displayAdded、displayRemoved三个显示事件传入其他事件名会抛TypeError桌面捕获相关事件请挂在nw.Screen.DesktopCaptureMonitor上。多屏坐标bounds与work_area的坐标原点不一定是(0, 0)拼接多屏布局时应以实际返回的x/y为准可为负。chooseDesktopMedia的一次性约束选择会话期间再次调用会返回false回调不会触发应避免重复发起选择。监控后及时stop()DesktopCaptureMonitor运行期间屏幕可能闪烁选定流后应立即停止同时可先通过thumbnailchanged拿到缩略图渲染自定义选择 UI。平台限制chooseDesktopMedia的桌面选择器仅在 Windows、macOS 与部分 LinuxAura发行版上可用跨平台应用需做好降级或平台分支。延伸阅读本文主题的官方参考文档Screen.mdJS 绑定实现src/api/screen/screen.js原生GetScreens/事件派发实现src/api/screen/screen.cc桌面捕获chooseDesktopMedia实现src/api/screen/desktop_capture_api.ccAPI 类型定义IDLsrc/api/nw_screen.idl屏幕事件绑定的冒烟测试test/sanity/screen-events/index.html0.12 到 0.13 的迁移说明涉及桌面捕获行为变更From 0.12 to 0.13【免费下载链接】nw.jsCall all Node.js modules directly from DOM/WebWorker and enable a new way of writing applications with all Web technologies.项目地址: https://gitcode.com/gh_mirrors/nw/nw.js创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考