Seelen UI 窗口管理器平铺布局完全指南:用声明式插件树定义 Tiling Window Manager 布局

发布时间:2026/9/14 0:22:15
Seelen UI 窗口管理器平铺布局完全指南:用声明式插件树定义 Tiling Window Manager 布局 Seelen UI 窗口管理器平铺布局完全指南用声明式插件树定义 Tiling Window Manager 布局【免费下载链接】Seelen-UIThe Fully Customizable Desktop Environment for Windows 10/11.项目地址: https://gitcode.com/GitHub_Trending/se/Seelen-UISeelen UIWindows 10/11 的桌面环境内置了一个平铺窗口管理器Tiling Window Managerseelen/window-manager而它的布局完全由用户自定义你不需要写任何脚本只需编写一段声明式的 YAML 插件资源描述一棵布局树Rust 核心就会把它解析为实时运行的平铺规则。本文基于仓库文档 wm-layouts.md 完整讲解该布局 SchemaTwmPlugin/TwmPluginNode/TwmCondition、节点字段、条件表达式、运行时解析原理并给出仓库内置的 wm-columns、wm-bspwm、wm-grid 三个完整可用的布局配置让你能够从零写出属于自己的平铺布局。说明本文引用的源码相对路径以仓库根目录为起点可对照阅读wm-layouts.md、plugin-guidelines.md、twm.rs、wm_layout.rs、state_v2.rs。1. 布局即插件窗口管理器的声明式扩展机制在 Seelen UI 中不存在独立的 Layout 资源种类。一个平铺布局本质上就是一个Plugin资源只是它的target固定为seelen/window-manager。要理解这一点需要先了解 Seelen UI 的插件机制详见 plugin-guidelines.md插件是一个纯声明文件只有id、target和一个自由格式的plugin载荷本身不定义运行时、沙箱或任何执行模型Seelen UI 核心不做通用的plugin解析/校验/执行只负责把资源路由给target指向的 widget每个 widget 自己定义它期望的plugin结构工具栏插件可能定义带 JS 回调的按钮见 toolbar-plugins.mdDock 插件可能定义图标项见 dock-plugins.md而窗口管理器插件则定义一棵无任何代码的静态布局树。因此窗口管理器布局完全由seelen/window-manager这个 widget 自己拥有Schema、解析、执行都在这一个 widget 内Seelen UI 核心没有任何针对它的特判。与工具栏、Dock 插件不同WM 布局完全没有脚本scripts——它是一棵被 Rust 代码遍历的声明式树而不是被当作 JS 求值的程序。2.plugin载荷TwmPlugin布局资源的最小骨架如下对应 Rust 结构体 TwmPluginstructure字段被serde以camelCase反序列化id: yourname/my-layout target: seelen/window-manager plugin: structure: # 一棵 TwmPluginNode 树省略或为 null 则退化为纯浮动布局 type: Horizontal children: - type: Leaf - type: Leaf关键规则structure省略或为null时该布局下没有任何窗口被平铺所有窗口浮动源码注释null means no tiling, only float layout。structure的根节点就是布局树根类型必须是容器Vertical/Horizontal或单槽节点Leaf/Stack。其余字段如metadata、icon与通用插件一致可参考 plugin-guidelines.md 中的metadata.yml模板plugin块内同样支持!include引入外部文件。3.TwmPluginNode节点字段与四种节点类型布局树由节点Node组成每个节点包括根节点都支持以下字段对应 TwmPluginNode字段类型默认值含义type/kindLeaf|Stack|Vertical|Horizontal—节点类型。YAML 中type与kind可互换#[serde(alias type)]lifetimePermanent|TemporalPermanent节点清空后是否保留还是被清理回收prioritynumber1兄弟节点间的遍历顺序——越小越先被尝试growFactornumber1.0该节点占父容器剩余空间的相对份额conditionTwmCondition或省略无门控该节点当前是否接收新窗口见 §5childrenTwmPluginNode[][]仅对Vertical/Horizontal有意义Leaf/Stack忽略maxStackSizenumber 或省略3仅对Stack有意义省略/null表示不限大小stackPolicyManual|AutoWhenOverflow|AutoAuto仅对Stack有意义见 §4源码中 Default 实现 确认了上述默认值kind Leaf、lifetime Permanent、priority 1、grow_factor 1.0、max_stack_size Some(3)、stack_policy Auto。3.1 节点类型Node Kinds对应枚举 TwmNodeKind类型角色Leaf单窗口槽位仅在空时接收一个窗口Stack多个窗口在同一个槽位中标签式堆叠受stackPolicy/maxStackSize约束Vertical容器——把children上下top/bottom切分自身不直接持有窗口Horizontal容器——把children左右left/right切分自身不直接持有窗口从源码注释看四者的几何语义分别是node will not grow, this is the final nodeLeaf不生长、是末端节点、node will grow on z-axisStack沿 Z 轴生长、node will grow on y-axisVertical沿 Y 轴生长、node will grow on x-axisHorizontal沿 X 轴生长。4. Stack 节点的stackPolicy只有Stack节点关心stackPolicy对应枚举 TwmStackPolicy默认Auto值行为Auto默认自由接收窗口直到达到maxStackSizeAutoWhenOverflow只有当其他节点都无法再接收窗口时才接收Manual从不自动接收窗口只能通过用户显式操作放入配合maxStackSize默认3设为null表示不限即可控制堆叠行为。从运行时看Manual堆叠一般由用户显式命令如把窗口入栈触发而 normalize 会把只剩 ≤1 个窗口的Manual堆叠自动折叠回Leaf避免残留无意义节点。5.conditionTwmCondition布尔表达式condition是一个针对当前平铺状态求值的布尔表达式用于门控节点当前是否接收窗口。它对应枚举 TwmCondition支持四种形式compare、and、or、not。5.1 基础比较condition: compare: left: tiling-windows # 或 is-reindexing op: ge # eq | ne | lt | le | gt | ge right: 45.2 复合条件condition: or: - compare: { left: tiling-windows, op: eq, right: 3 } - compare: { left: tiling-windows, op: ge, right: 5 }condition: and: - compare: { left: tiling-windows, op: ge, right: 2 } - compare: { left: tiling-windows, op: lt, right: 8 }condition: not: compare: { left: is-reindexing, op: eq, right: true }注意and/or/not在 Rust 中分别由TwmCondition::And(Box, Box)、Or(Box, Box)、Not(Box)表示evaluate采用短路求值见 twm.rs。YAML 里or/and下列表语义上等价于逐项二元组合。5.3 操作数Operandsleft可用的操作数对应枚举 Operand经#[serde(rename_all kebab-case)]序列化为操作数值tiling-windows当前工作区中已平铺窗口的数量ctx.tiling_windows: usizeis-reindexingWM 当前是否正在重索引批量重新分配窗口中ctx.is_reindexing: bool5.4 比较符Comparatorsop可选eq、ne、lt、le、gt、ge对应 Comparator与right一个普通 YAML/JSON 值number / string / boolean取决于操作数做标准数值或相等比较。源码的 compare 实现 有一个值得注意的细节当左右两侧都是 number 时按浮点数做完整的大小比较否则只支持eq/ne其余比较符一律返回false——所以对布尔操作数如is-reindexing只能用eq/ne。6. 从声明树到运行时树TwmRuntimeTree的解析与窗口分配运行时Seelen UI 会解析当前激活布局的Plugin资源把structure解析为TwmPluginNode再转换成运行时树TwmRuntimeTree。转换入口是 TwmRuntimeTree::from_plugin配合 insert_plugin_node 递归展开kind、lifetime、priority、growFactor、condition、maxStackSize、stackPolicy原样拷贝growFactor同时用作初始值和运行时用户可调整的实时 grow factor切换布局或执行 reset_sizes 时会从initial_grow_factor重置运行时专有状态已分配窗口、活动窗口、屏幕矩形等初始化为空。此后每当有窗口需要槽位WM 就按priority顺序遍历整棵树依次询问每个节点accepts_windows?见 try_add_window。判定过程分两层条件门控若节点带condition先基于当前上下文{ tiling-windows, is-reindexing }求值上下文构造见 get_context类型规则Leaf仅在空时接收Stack按其stackPolicy/maxStackSize接收容器节点从不直接接收只有它们的子节点接收。若正常路径找不到可接收节点还会走一次溢出通道accepts_windows_on_overflow即AutoWhenOverflow堆叠的兜底。6.1 重索引Reindex与is-reindexing为了支持tiling-windows 4时换一种排布这类逻辑每当树结构或窗口数量发生显著变化WM 会执行 reindex_windows把符合条件的窗口跳过 ≥2 窗口的Manual堆叠全部抽出、清空节点然后按窗口进入时间先后排序最早的先放在is-reindexing: true的上下文里重新依次放入各节点。放不下的窗口作为残余residual返回交给浮动层。add_to_tiled/remove_window都会触发重索引见 add_to_tiled这就是is-reindexing操作数存在的意义——避免条件表达式在重索引中途读到中间态而抖动。6.2 布局切换与 Monocle工作区与布局 ID 的对应关系缓存在TwmState的layout_cache中当用户在设置里切换布局时on_settings_changed 会比较新旧 IDchange_layout 会把旧树中所有平铺窗口抽出来、把浮动窗口保留再按新布局的from_plugin树重新分配——放不下的继续浮动。Monocle 模式单窗口放大并不是独立的机制它只是同一套 Schema 的另一种实例——{ kind: Stack, maxStackSize: null }不限大小的堆叠、单一槽位。源码 TwmPlugin::monocle() 正是这样构造的运行时 toggle_monocle 在 monocle 布局与用户配置布局之间切换快捷键Win M。这也解释了为什么 monocle 下所有窗口都以标签页形式叠在一起、只显示一个。7. 完整示例仓库内置的三个布局以下三个布局直接取自仓库真实配置文件src/static/plugins/下的wm_columns、wm_bsp、wm_grid是验证本文 Schema 的最佳范本。7.1default/wm-columns最扁平的三列布局配置见 wm_columns/metadata.yml三棵固定列无任何条件id: default/wm-columns target: seelen/window-manager plugin: structure: type: Horizontal children: - type: Leaf - type: Leaf - type: Leaf7.2default/wm-bspwm递归二叉空间分割配置见 wm_bsp/metadata.yml前 6 个窗口按 bspwm 风格递归二分并用priority控制填充顺序注意注释标注的窗口序号id: default/wm-bspwm target: seelen/window-manager plugin: structure: type: Horizontal children: - type: Leaf # 第 1 个窗口 - type: Vertical children: - type: Leaf # 第 2 个窗口 - type: Horizontal children: - type: Vertical priority: 2 children: - type: Horizontal priority: 2 children: - type: Leaf # 第 5 个窗口 - type: Leaf # 第 6 个窗口 - type: Leaf # 第 4 个窗口 priority: 1 - type: Leaf # 第 3 个窗口 priority: 1布局逻辑Horizontal根先左右一分为二左侧叶子装第 1 个窗口右侧Vertical再上下切上方装第 2 个窗口下方Horizontal再切……每一层都靠priority决定同层子节点的填充先后最终得到递归平衡的 bsp 树。7.3default/wm-grid基于condition的动态网格配置见 wm_grid/metadata.yml是最能体现condition威力的示例——同一个布局随平铺窗口数量自动重塑形态id: default/wm-grid target: seelen/window-manager plugin: structure: type: Horizontal children: - type: Vertical priority: 3 condition: compare: { left: tiling-windows, op: ge, right: 4 } children: - type: Leaf priority: 3 condition: compare: { left: tiling-windows, op: ge, right: 7 } - type: Leaf - type: Leaf - type: Vertical priority: 1 children: - type: Leaf priority: 3 condition: compare: { left: tiling-windows, op: eq, right: 8 } - type: Leaf priority: 1 - type: Leaf priority: 2 condition: or: - compare: { left: tiling-windows, op: eq, right: 3 } - compare: { left: tiling-windows, op: ge, right: 5 } - type: Vertical priority: 2 children: - type: Leaf priority: 3 condition: compare: { left: tiling-windows, op: ge, right: 6 } - type: Leaf - type: Leaf读法示范中间的Verticalpriority: 1总是最优先填充它容纳第 1、2 个窗口且仅当tiling-windows 3或 5时其第 3 个叶子才开放形成 3 窗口/5 窗口以上的列右侧列priority: 2第 3 个叶子要求 6左侧列要求 4——窗口多了才逐步启用这些列顶部的额外叶子进一步细分左列第 1 个叶子要 7中列第 1 个叶子要求恰好 8。由于窗口分配时按priority遍历并实时求值condition配合重索引这个布局就能做到窗口少时是简单的单列/双列窗口增多后逐步长出第三列和细分槽位窗口数变化后自动重排。8. 将布局放入仓库并启用布局即插件资源把上述 YAML含id、target、plugin.structure作为独立的插件包放入src/static/plugins/下参考wm_columns/wm_bsp/wm_grid的目录结构含metadata.yml与i18n/下的display_name.yml/description.yml安装后在 Seelen UI 设置中为该工作区选择布局 ID运行时由 state_v2.rs 中的TwmState负责按工作区缓存布局、监听设置变更并热切换change_layout会无损迁移已有窗口放不下的进入浮动层想进一步控制窗口行为可结合设置项如auto_stacking_by_category见 state_v2.rs 中按窗口类别自动堆叠的逻辑与TwmReservation左/右/上/下/入栈/浮动的手动安置见 twm.rs。结语Seelen UI 的平铺布局把布局彻底数据化TwmPlugin定义载荷、TwmPluginNode定义树、TwmCondition定义动态门控而 wm_layout.rs 与 state_v2.rs 中的 Rust 实现负责把声明变成实时树、按priority遍历分配窗口并在条件变化时重索引。掌握这套 Schema 后你可以仅凭 YAML 写出列布局、bsp 布局、随窗口数量自适应的网格布局乃至自定义 Monocle——整个过程零脚本、纯声明这正是插件即纯声明、行为归 widget这一设计哲学在窗口管理器上的完整落地。【免费下载链接】Seelen-UIThe Fully Customizable Desktop Environment for Windows 10/11.项目地址: https://gitcode.com/GitHub_Trending/se/Seelen-UI创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询