Electron BaseWindow 构造选项详解:BaseWindowConstructorOptions 全参数指南与源码实现解析
本文基于 Electron 官方文档中的 BaseWindowConstructorOptions 结构说明,完整覆盖创建 BaseWindow(及其子类 BrowserWindow)时支持的全部构造参数——包括尺寸与位置约束、窗口样式与标题栏、全屏/置顶/Kiosk 行为、跨平台专属选项(macOS 毛玻璃、Windows Mica 材质、窗口类型等),并结合 shell/browser 目录下的 C++ 源码,解释 name 唯一性校验、窗口状态持久化、offscreen 强制无框架窗等参数在底层是如何被解析和生效的。读完本文,你既能逐条查阅每个选项的类型、默认值与平台限制,也能理解这些选项从 JS 选项对象到原生窗口的实际落地路径。
BaseWindowConstructorOptions 是什么
BaseWindowConstructorOptions 是 Electron 中 BaseWindow 构造函数接收的选项对象。它是 Electron 窗口体系的基础:BaseWindow 是一个不直接渲染网页内容的窗口容器,BrowserWindow 在其基础上附加 WebContents 渲染能力。因此 BrowserWindowConstructorOptions 直接继承 BaseWindowConstructorOptions,仅额外增加 webPreferences 与 paintWhenInitiallyHidden 两个参数:
webPreferencesWebPreferences(可选)—— 网页功能配置;paintWhenInitiallyHiddenboolean(可选)—— 当show为false时渲染器是否保持活跃。为使document.visibilityState在show: false首次加载时正确工作应设为false;设为false会导致ready-to-show事件不触发。默认true。
也就是说,本文列出的每一个选项对 BaseWindow 和 BrowserWindow 两个构造函数都生效。
从源码结构看,选项对象的最终消费点在 electron_api_base_window.cc:BaseWindow 构造函数先处理 title、parent 等特殊字段,随后调用 NativeWindow::Create(GetID(), options, parent_native) 创建原生窗口,最后通过 window()->InitFromOptions(options) 把选项批量应用到窗口上。
尺寸、位置与大小约束
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
width |
Integer(可选) | 800 |
窗口宽度(像素) |
height |
Integer(可选) | 600 |
窗口高度(像素) |
x |
Integer(可选) | 居中 | 窗口左边缘距屏幕的偏移(若使用了 y 则必填) |
y |
Integer(可选) | 居中 | 窗口上边缘距屏幕的偏移(若使用了 x 则必填) |
useContentSize |
boolean(可选) | false |
为 true 时 width/height 被解释为网页内容区尺寸,实际窗口尺寸会加上窗口框架而略大 |
center |
boolean(可选) | false |
将窗口显示在屏幕中央 |
minWidth |
Integer(可选) | 0 |
窗口最小宽度 |
minHeight |
Integer(可选) | 0 |
窗口最小高度 |
maxWidth |
Integer(可选) | 无限制 | 窗口最大宽度 |
maxHeight |
Integer(可选) | 无限制 | 窗口最大高度 |
resizable |
boolean(可选) | true |
窗口是否可调整大小 |
x 与 y 是成对约束的:单独设置其中一个会报错,两者都不设置时窗口默认居中。useContentSize 对应 SetContentSize/GetContentSize 这条 API 线,在 electron_api_base_window.cc 中可以看到 SetContentBounds/SetContentSize 与 SetBounds/SetSize 是两套独立的实现,前者始终换算到内容区矩形。
一个容易误解的约束语义:文档明确指出,通过 minWidth/maxWidth/minHeight/maxHeight 设置的约束只约束用户(拖拽窗口边缘等 UI 操作),并不会阻止你向 setBounds/setSize 或构造函数传入一个不满足约束的尺寸。不过从源码实现看存在一条边界:SetSize 内部会以最小尺寸做钳制——
void BaseWindow::SetSize(int width, int height, gin::Arguments* args) {
bool animate = false;
gfx::Size size = window_->GetMinimumSize();
size.SetToMax(gfx::Size(width, height)); // 传入值不会低于最小尺寸
args->GetNext(&animate);
window_->SetSize(size, animate);
}
见 electron_api_base_window.cc#L494-L500。
窗口行为控制
| 参数 | 类型 | 平台 | 默认值 | 说明 |
|---|---|---|---|---|
movable |
boolean(可选) | macOS / Windows | true |
窗口是否可移动(Linux 未实现) |
minimizable |
boolean(可选) | macOS / Windows | true |
窗口是否可最小化(Linux 未实现) |
maximizable |
boolean(可选) | macOS / Windows | true |
窗口是否可最大化(Linux 未实现) |
closable |
boolean(可选) | macOS / Windows | true |
窗口是否可关闭(Linux 未实现) |
focusable |
boolean(可选) | 全部 | true |
窗口能否获得焦点。Windows 上设为 false 同时隐含 skipTaskbar: true;Linux 上设为 false 会让窗口停止与窗口管理器交互,从而始终停留在所有工作区的最前 |
alwaysOnTop |
boolean(可选) | 全部(Wayland 除外) | false |
窗口是否始终位于其他窗口之上;Linux 的 Wayland 下不支持 |
kiosk |
boolean(可选) | 全部 | false |
窗口是否处于 Kiosk(展示)模式 |
skipTaskbar |
boolean(可选) | macOS / Windows | false |
是否从任务栏中隐藏窗口 |
hiddenInMissionControl |
boolean(可选) | macOS | — | 用户切换 Mission Control 时窗口是否被隐藏 |
show |
boolean(可选) | 全部 | true |
窗口创建时是否立即显示 |
parent |
BaseWindow(可选) | 全部 | null |
指定父窗口 |
modal |
boolean(可选) | 全部 | false |
是否为模态窗口,仅在作为子窗口(设置了 parent)时生效 |
acceptFirstMouse |
boolean(可选) | macOS | false |
点击非活动窗口时点击是否直接穿透到网页内容;其他平台不可配置 |
disableAutoHideCursor |
boolean(可选) | 全部 | false |
是否禁止输入时自动隐藏光标 |
autoHideMenuBar |
boolean(可选) | Linux / Windows | false |
除非按下 Alt 键否则自动隐藏菜单栏 |
enableLargerThanScreen |
boolean(可选) | macOS | false |
允许窗口被调整得比屏幕更大(其他系统默认允许) |
其中 parent + modal 组合构成 Electron 的子窗口体系:源码中 SetParentWindow 明确禁止对模态窗口调用(抛出 "Can not be called for modal window"),见 electron_api_base_window.cc#L796-L813。
全屏相关选项
| 参数 | 类型 | 平台 | 默认值 | 说明 |
|---|---|---|---|---|
fullscreen |
boolean(可选) | 全部 | false |
窗口是否以全屏方式显示。若显式设为 false,macOS 上的全屏按钮会被隐藏或禁用 |
fullscreenable |
boolean(可选) | 全部 | true |
窗口能否进入全屏模式。在 macOS 上还决定"最大化/缩放"按钮是切换全屏还是最大化 |
simpleFullscreen |
boolean(可选) | macOS | false |
使用 Lion 之前的旧式全屏(simple full screen) |
zoomToPageWidth |
boolean(可选) | macOS | false |
控制 macOS 上 Option 点击绿色按钮或 Window > Zoom 菜单的行为:true 时缩放至网页首选宽度,false 时缩放至屏幕宽度;调用 maximize() 时的行为同样受影响 |
窗口外观:框架、标题栏与背景
| 参数 | 类型 | 平台 | 默认值 | 说明 |
|---|---|---|---|---|
frame |
boolean(可选) | 全部 | true |
设为 false 创建无框架窗口 |
title |
string(可选) | 全部 | "Electron" |
默认窗口标题。若 loadURL() 加载的 HTML 定义了 <title> 标签,该属性会被忽略 |
icon |
NativeImage | string(可选) | 全部 | — | 窗口图标。Windows 上建议使用 ICO 格式以获得最佳视觉效果;也可以不设置,此时使用可执行文件自身的图标 |
backgroundColor |
string(可选) | 全部 | #FFF(白色) |
窗口背景色,支持 Hex、RGB、RGBA、HSL、HSLA 或 CSS 命名色;当 transparent 为 true 时支持 #AARRGGBB 的 Alpha 通道 |
hasShadow |
boolean(可选) | 全部 | true |
窗口是否带阴影 |
opacity |
number(可选) | macOS / Windows | — | 窗口初始不透明度,0.0(全透明)到 1.0(不透明),仅 Windows 与 macOS 实现 |
darkTheme |
boolean(可选) | Linux | false |
强制窗口使用深色主题,仅对部分 GTK+3 桌面环境生效 |
transparent |
boolean(可选) | 全部 | false |
使窗口透明。Windows 上仅无框架窗口可用。向 BaseWindow 添加 View 时,还需对相应 View 调用 view.setBackgroundColor 设置透明背景色,该视图背景才会透明 |
thickFrame |
boolean(可选) | Windows | true |
为 Windows 无框架窗口使用 WS_THICKFRAME 样式以添加标准窗口框架;设为 false 会移除窗口阴影与窗口动画,并禁用拖拽窗口边缘缩放 |
roundedCorners |
boolean(可选) | 全部 | true |
无框架窗口是否使用圆角。早于 Windows 11 Build 22000 的版本无效果;Linux 上仅当桌面环境支持客户端装饰(CSD)时才绘制圆角 |
关于 title 有一个源码层面的细节值得注意:构造时只要显式传入了 title,就会置位 title_set_from_api_ 标志:
// make sure we don't override title on back/forward navigation
// if the title is provided
if (std::string title; options.Get(options::kTitle, &title))
title_set_from_api_ = true;
见 electron_api_base_window.cc#L101-L106。配套逻辑在 SetTitleFromPageIfNotSetFromApi(electron_api_base_window.cc#L639-L646):只有当标题不是由 API 设置时,网页 <title> 才会覆盖窗口标题——这正是文档所说"若定义了 <title> 则此属性被忽略"的实现依据。
标题栏样式与 Window Controls Overlay
| 参数 | 类型 | 平台 | 默认值 | 说明 |
|---|---|---|---|---|
titleBarStyle |
string(可选) | 全部 | default |
标题栏样式,取值见下表 |
titleBarOverlay |
Object | boolean(可选) | 全部 | false |
启用 Window Controls Overlay(WCO)API。传入 true 得到使用系统默认颜色的覆盖层 |
titleBarOverlay.color |
string(可选) | Windows / Linux | 系统色 | 覆盖层启用时的 CSS 背景色 |
titleBarOverlay.symbolColor |
string(可选) | Windows / Linux | 系统色 | 覆盖层上按钮符号的 CSS 颜色 |
titleBarOverlay.height |
Integer(可选) | 全部 | 系统高度 | 标题栏与 Window Controls Overlay 的高度(像素) |
trafficLightPosition |
Point(可选) | macOS | — | 在无框架窗口中自定义"红绿灯"按钮位置 |
visualEffectState |
string(可选) | macOS | followWindow |
指定毛玻璃材质外观如何反映窗口活动状态,必须与 vibrancy 属性配合使用。取值:followWindow(随窗口活动状态自动切换,默认)、active(始终呈活动态)、inactive(始终呈非活动态) |
vibrancy |
string(可选) | macOS | — | 为窗口添加毛玻璃(vibrancy)效果,可取 appearance-based、titlebar、selection、menu、popover、sidebar、header、sheet、window、hud、fullscreen-ui、tooltip、content、under-window、under-page |
backgroundMaterial |
string(可选) | Windows | — | 设置窗口由系统绘制的背景材质(含非客户区之后),可取 auto、none、mica、acrylic 或 tabbed,详见 win.setBackgroundMaterial |
accentColor |
boolean | string(可选) | Windows | 跟随系统 | 窗口强调色。默认跟随系统设置中的用户偏好;设为 false 显式禁用;或传入 Hex/RGB/RGBA/HSL/HSLA/CSS 命名色,Alpha 值会被忽略 |
titleBarStyle 的完整取值:
default—— macOS 或 Windows 各自的标准标题栏;hidden—— 隐藏标题栏并让内容窗口全屏。macOS 上左上角仍保留标准窗口控制按钮("红绿灯");Windows 与 Linux 上,配合titleBarOverlay: true会激活 Window Controls Overlay,否则不显示任何窗口控制按钮;hiddenInset(macOS)—— 隐藏标题栏,红绿灯按钮相对窗口边缘有更大的内缩,呈现另一种观感;customButtonsOnHover(macOS,实验性)—— 隐藏标题栏且内容全屏,红绿灯按钮在鼠标悬停于窗口左上角时才显示。
无框架/透明窗口的视觉效果可以参考仓库中的示意图:
titleBarOverlay 的运行时实现入口在 electron_api_base_window.cc#L1182-L1188,仅在 Windows 与 Linux 编译路径下暴露 setTitleBarOverlay,并转发给 NativeWindowViews 处理;accentColor 同理仅存在于 BUILDFLAG(IS_WIN) 编译块内(SetAccentColor,electron_api_base_window.cc#L1141-L1170),与文档标注的平台限制一致。
name 与窗口状态持久化(windowStatePersistence)
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
name |
string(可选) | — | 窗口的唯一标识符,供 Electron 内部用于状态持久化等特性。每个窗口必须拥有不同的 name,在对应窗口被销毁之前不能复用;若 name 已被占用,构造会抛出错误。注意:它不是标题栏上显示给用户的可见标题 |
windowStatePersistence |
WindowStatePersistence | boolean(可选) | — | 配置或启用窗口状态(位置、大小、最大化状态等)在应用重启间的持久化。未提供窗口 name 时无效果;当没有可用显示器时自动禁用。Experimental |
name 的唯一性校验发生在构造函数入口处。BaseWindow::New 在真正创建窗口前调用 IsWindowNameValid,遍历 WindowList::GetWindows() 中所有现存窗口比对 GetName(),发现重名则抛出 TypeError:
// Window names must be unique for state persistence to work correctly
if (name_in_use) {
*error_message = "Window name '" + window_name +
"' is already in use. Window names must be unique.";
return false;
}
这正是文档所说 "An error is thrown if the name is already in use" 的实现。状态持久化的存储与清除逻辑也在同一文件中:静态方法 ClearPersistedState 通过 PrefService 从 app.getPath('userData') 下的 Local State JSON 文件(kWindowStates 偏好项)中移除指定窗口名的状态(electron_api_base_window.cc#L1190-L1209),并对外暴露为 BaseWindow.clearPersistedState(electron_api_base_window.cc#L1439-L1440)。
从源码结构看,持久化的写入时机非常具体:maximize、unmaximize、resize、move、enter-full-screen、leave-full-screen 这些原生回调里都会调用 window_->DebouncedSaveWindowState() 做防抖保存;窗口关闭时 OnWindowClosed 会再调用 window_->FlushWindowState() 做最终落盘(electron_api_base_window.cc#L169-L189);而状态从存储恢复后则触发 persisted-state-restored 事件(OnWindowStateRestored,electron_api_base_window.cc#L363-L365)。因此使用 windowStatePersistence 时,监听 persisted-state-restored 是确认状态恢复完成的可靠信号。
type 选项:平台相关的窗口类型
type 字符串决定窗口的原生类型(默认为普通窗口),其可选值随平台不同:
Linux 上可取 desktop、dock、toolbar、splash、notification:
desktop—— 将窗口置于桌面背景窗口层级(kCGDesktopWindowLevel - 1)。注意桌面窗口不会接收焦点、键盘或鼠标事件,但仍可谨慎地用globalShortcut接收输入;dock—— 创建具有 Dock 类行为的窗口;toolbar—— 创建具有工具栏外观的窗口;splash—— 行为特殊:即使 CSS 中设置了-webkit-app-region: drag也不可拖拽。常用于启动画面(splash screen);notification—— 创建行为类似系统通知的窗口。
macOS 上可取 desktop、textured、panel:
textured—— 添加金属渐变外观,该选项已弃用;desktop—— 同 Linux,置于桌面背景窗口层级,不接收焦点/键盘/鼠标事件,可用globalShortcut接收输入;panel—— 在运行时添加NSWindowStyleMaskNonactivatingPanel样式掩码(通常专属于 NSPanel),使窗口能够悬浮在全屏应用之上;同时窗口会出现在所有 Space(桌面)上。
Windows 上仅支持 toolbar 类型。
其他 macOS 专属选项
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
tabbingIdentifier |
string(可选) | — | Tab 分组名,允许将窗口作为原生标签页打开。具有相同 tabbingIdentifier 的窗口会被归为一组;同时会在窗口标签栏上添加原生"新建标签页"按钮,并使 app 与窗口能够接收 new-window-for-tab 事件 |
tabbingIdentifier 的运行时读写路径在 electron_api_base_window.cc:与 macOS 标签页相关的 selectPreviousTab/selectNextTab/showAllTabs/mergeAllWindows/moveTabToNewWindow/toggleTabBar/addTabbedWindow 等原型方法均在 BUILDFLAG(IS_MAC) 编译块中注册,GetTabbingIdentifier 在未设置时返回 undefined。new-window-for-tab 事件由 OnNewWindowForTab 回调发出(electron_api_base_window.cc#L353-L355),与文档描述一一对应。
构造流程速览:选项如何变成原生窗口
把上面的源码证据串起来,一个 new BaseWindow(options) 的完整链路是:
- JS 层传入选项对象;
BaseWindow::New(electron_api_base_window.cc#L1212-L1224)解析选项字典并做name唯一性校验,重名直接抛错;BaseWindow构造函数(electron_api_base_window.cc#L101-L134):- 读取
title并置位 API 标题标志; - 读取
parent并保存父窗口引用; - 若
webPreferences.offscreen为true,强制把frame改写为false(offscreen 窗口一律无框架)——这是文档未明说、但源码明确的一条隐含规则; - 调用
NativeWindow::Create创建原生窗口,随后应用icon;
- 读取
- 独立 BaseWindow 的构造路径最后调用
window()->InitFromOptions(options),在此集中应用尺寸、位置、alwaysOnTop、transparent、titleBarStyle、vibrancy等其余选项。
相关行为可由 spec/api-base-window-spec.ts 中的测试用例验证,其中覆盖了父/子窗口、modal、focusable 等构造选项的行为断言。
常见组合示例
一个典型的自定义外观主窗口(无框架 + WCO + 状态持久化):
const { BrowserWindow } = require('electron')
const win = new BrowserWindow({
width: 1024,
height: 700,
useContentSize: true, // 宽高按网页内容区计算
name: 'main-window', // 持久化的唯一标识,进程内不可重复
windowStatePersistence: true,
title: 'My App', // 若页面有 <title> 则被忽略
frame: false, // 无框架窗口
titleBarStyle: 'hidden', // 内容占满整个窗口
titleBarOverlay: {
color: '#2b2b2b', // Windows/Linux 覆盖层背景色
symbolColor: '#e6e6e6', // Windows/Linux 覆盖层符号色
height: 40
},
minWidth: 640,
minHeight: 400,
resizable: true,
show: false // 配合 ready-to-show 事件显示以避免白闪
})
macOS 毛玻璃窗口:
const win = new BrowserWindow({
width: 480,
height: 320,
vibrancy: 'sidebar', // 毛玻璃材质
visualEffectState: 'followWindow',
backgroundColor: '#00000000' // 配合 transparent 使用 AARRGGBB
})
Windows Mica/Acrylic 背景:
const win = new BrowserWindow({
backgroundMaterial: 'mica', // 或 'acrylic' | 'tabbed' | 'auto' | 'none'
accentColor: '#4f46e5' // 可传 false 禁用,或省略跟随系统
})
以上示例中每个参数均出自本文引用的 docs/api/structures/base-window-options.md 文档条目;ready-to-show、transparent 等窗口显示与透明行为的进一步说明见 custom-window-styles 教程。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0624
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
