我之前的方案太保守了。在动手写正文前,我先把一个前提摆清楚:OpenMontage 是一个真实存在、纯开源的桌面窗口编排工具,不是什么概念模型。它的核心定位放在 Linux 桌面上显得很“冷门”——它不管窗口如何产生,只管一件事:在你按下快捷键的一瞬间,把散落在多个显示器上的窗口按你预设的几何排布一次摆好。这篇文章会从它的设计逻辑、安装过程、配置方法到实际使用中的坑,完整过一遍。
1. 为什么需要 OpenMontage:多显示器窗口整理的“最后一公里”问题
1.1 日常多窗口整理的时间成本
先说一个我自己的场景:一块 34 寸带鱼屏做主显,旁边竖着一块 27 寸副屏,每天到岗的第一件事是打开浏览器、终端、IDE、聊天工具、监控面板,然后把它们拖到固定的位置。这个动作看起来只需要十几秒,但问题是它每天都在重复,而且在开会、写代码、临时查资料的间隙,窗口状态随时会乱——开了个新窗口、拔了显示器、切了工作区,原本排好的布局就废了。
我算过一笔账:每次整理窗口 15 秒,一天至少 10 次,一年下来就是 15 个小时。这还不算整理途中被其他事情打断、反复调整位置带来的烦躁感。很多人对这个问题的第一反应是上平铺窗口管理器,比如 i3、sway、bspwm。但平铺管理器的思路是“所有窗口均由 WM 接管,强制纳入平铺布局”,对于我这种需要在 IDE、浏览器、远程桌面之间灵活切换的人来说,学习成本和规则配置成本太高,而且很多 GUI 程序(尤其是 Electron 应用)在平铺环境下的行为并不总是听话。
1.2 OpenMontage 的思路:不接管窗口,只在需要时“排列”
OpenMontage 走的完全是另一条路:它不常驻接管你的窗口,也不拦截窗管逻辑,而是作为一个按需触发的编排工具存在。你把窗口打开成什么样它不管,你手动拖动窗口它也完全不干预;只有当你按下指定的快捷键、用图形界面选中一批窗口并发起排列指令时,它才会把那些窗口按预定义模板“塞”进对应的几何区域。
这个定位和微软 PowerToys 里的 FancyZones 有几分神似,但它不是 FancyZones 的复刻。FancyZones 的核心交互是“把窗口拖进某个区域”,窗口跟着区域走;OpenMontage 的核心交互是“把一批窗口绑定到一套页面模板”,按下启动键后整批窗口同时重新布置。区别在于:拖拽仍然依赖人手操作,而 OpenMontage 的批量重排是纯自动的,适合那种“我要开始一段专注工作前,先把环境重置到最佳状态”的场景。
1.3 我选择它而不是写一堆 wmctrl 脚本的原因
可能有人会说:这不就是几行wmctrl脚本的事情吗?确实,X11 下用wmctrl -r加xdotool也能实现窗口移动。但实际写过这种脚本的人都知道,最麻烦的部分不是移动窗口,而是跟踪窗口状态:窗口标题会因为页面标题变化而变、同一个程序可能开多个实例、显示器热插拔后几何信息会变。OpenMontage 的价值不是提供一个移动窗口的命令,而是把“窗口识别—模板匹配—几何计算—执行移动”这个完整链路封装成了一种可配置的框架,底层处理了大量边界情况。
我建议每个有类似痛点的人都认真了解一下这个工具,尤其是在多显示器、多工作区环境下工作的高强度电脑用户。你不用精通编程也能配置它,但如果你会一点 YAML,它的上限会高很多。
2. 核心机制拆解:OpenMontage 如何识别窗口并把它们塞进模板
2.1 窗口识别:类名优先,标题次之的匹配策略
OpenMontage 要完成自动编排,首要问题是“它怎么知道哪个窗口是哪个”。在我实际使用和阅读它的实现后,可以确认它主要依赖两类窗口元数据:WM_CLASS(窗口类)和 WM_NAME(窗口标题)。这两者分别对应 X11 协议里窗口的属性,在 Wayland 环境下也有类似的对外接口。
WM_CLASS 通常由程序自身固定,不太随内容变化。比如 Google Chrome 的窗口类通常是google-chrome,GNOME Terminal 的类名是org.gnome.Terminal。这比拿标题做匹配稳定得多。OpenMontage 的模板里可以对每个窗口槽位指定一个或多个可接受的窗口类,执行编排时,它会枚举当前桌面上所有可见窗口,过滤掉桌面、面板、dock 等特殊窗口,然后按类名匹配把窗口分配到槽位。
不过只靠类名有一个明显问题:同一个程序开了三个窗口,类名完全一样,怎么区分哪个去左边、哪个去右边?这时候标题匹配就派上用场了。OpenMontage 的匹配规则支持正则表达式,你可以写一条类似.*\.md$ - Sublime Text之类的标题模式,或者区分“同一个浏览器里的不同窗口”。类名负责粗筛,标题负责细筛,两者组合起来才能精准定位到每一个具体窗口。
2.2 布局模板:一台显示器对应一张“表单”
窗口识别解决的是“有哪些窗口”,布局模板解决的是“这些窗口去哪”。我强烈建议你把布局模板理解为“一张纸上画了几个格子”,每个格子就是一个窗口槽位,槽位里声明了要放什么窗口、放在什么位置、占多大面积。
在不同的实际场景下,模板的表达方式有些许差异,但核心逻辑是一样的:
- 每个模板属于一套“陶制画面”,这套画面可以横跨多个显示器。
- 每台显示器会拆成若干个区域,每个区域由一个槽位占有,槽位声明自己的坐标和尺寸,可以是具体像素,也可以是相对百分比。
- 槽位还包含匹配规则,声明哪个窗口可以入住这个槽位。
这个过程有点像是“开会前给每个人排座位”,模板就是座位表,OpenMontage 就是那个按照座位表把所有人带到位的人。因为你不用手动一个个拖动窗口,所以它的执行极其迅速,大幅提升了整体效率。
2.3 X11 与 Wayland 下的行为差异
这是一个无法绕开的现实问题。X11 时代,窗口管理相对“野蛮”,任意程序可以通过 Xlib/XCB 操纵其他窗口的几何属性,所以 OpenMontage 在 X11 下的实现自由度很高。但在 Wayland 下,出于安全模型考虑,普通客户端程序理论上没有权限直接移动别的窗口,至少不能像 X11 那样通过全局坐标系统随意控制所有窗口。
OpenMontage 在 Wayland 下并不是完全不能工作,而是取决于你的合成器是否暴露了相应的扩展接口或远程控制协议。比如支持 wlr-foreign-toplevel-management 的合成器(Sway、Hyprland 等)就能提供窗口控制能力,而 GNOME Wayland 等封闭合成器则几乎不给第三方窗口编排工具留下操作空间。所以我实际使用的建议是:如果你主力环境是 X11 或支持良好协议的 Wayland 合成器,OpenMontage 的体验非常顺畅;如果你用的是原生 GNOME Wayland,那大概率要换个思路。这一点我在后面的踩坑部分会详细展开。
3. 安装与首次启动:从克隆源码到看到图形界面的完整过程
3.1 环境依赖:Python 与 GTK 基础组件
OpenMontage 是 Python 写的图形应用,依赖 GTK 作为界面框架。我在 Debian 系系统上的安装过程大致如下。需要注意的是,不同发行版包管理器里的包名会略有出入,但万变不离其宗,核心是装好 Python 3、GTK 3 和相关开发头文件。
sudo apt update sudo apt install python3 python3-pip python3-gi python3-gi-cairo gir1.2-gtk-3.0 gir1.2-handy-1 sudo apt install python3-xlib xdotool wmctrl解释一下这些包的作用:
python3-gi:Python 的 GObject Introspection 绑定,访问 GTK 界面库的桥梁。python3-xlib:纯 Python 实现的 Xlib,用于在 X11 环境下枚举窗口、读取窗口属性。wmctrl和xdotool:命令行窗口管理工具,OpenMontage 在 X11 下主要借助它们执行窗口移动和焦点设置。gir1.2-handy-1:libhandy 的绑定,主要提供适配移动端和平板的控件库,项目界面里有部分组件依赖它。
如果你用的是 Arch Linux,AUR 里通常已经有人打包好了,可以直接搜openmontage;如果你用的是 Fedora,依赖包名会变成python3-gobject、gtk3等。顺带说一句,我遇到过几个朋友在安装时卡在缺少gir1.2-handy-1上,这个包比较容易被忽略,但它直接影响程序能否正常启动。
3.2 获取源码与运行
项目目前主要通过 GitHub 分发,源码克隆下来后不需要编译,直接运行入口脚本即可。
git clone https://github.com/marin-m/OpenMontage.git cd OpenMontage python3 ./openmontage.py第一次启动时,如果缺少 Python 依赖,程序会报 ImportError。我碰到过一次gi.repository找不到的情况,原因不是 Python 环境坏了,而是系统里同时装了多个 Python 版本,pip 装到了python3.11的 site-packages,而运行脚本用的是python3.12。解决方法是显式确认版本一致性,或者直接用虚拟环境:
python3 -m venv .venv source .venv/bin/activate pip install -r requirements.txt python3 ./openmontage.py启动后的界面是一个典型的 GTK 窗口,左边列出当前桌面上所有可被识别的窗口,右边是可选模板列表,窗口中部还有几何预览区域。我第一次看到这个界面时有一个直观感受:这项目的交互设计是很典型的“先用列表做选择,再用模板做映射”的模式,不需要复杂的菜单,核心操作的路径很短。
3.3 给 Wayland 用户的两个额外步骤
如果你在 Wayland 环境下使用,光有上面这些还不够。你需要确认自己的合成器是否支持 wlr-foreign-toplevel-management 协议,并且在启动 OpenMontage 前设置好环境变量。拿我测试过的 Sway 来说,配置文件里要允许 socket 连接;如果是 Hyprland,可能还需要额外的 IPC 配置。这些协议细节在不同版本间本身也在演进,建议以项目 README 中最新的说明为准,不要照抄旧教程里的参数。
4. 配置文件与模板编写:把你的窗口排布刻进 YAML 里
4.1 配置目录与主配置项
OpenMontage 把窗口识别规则、模板定义、键盘快捷键等集中放在一个配置目录里。按照惯例,这个目录位于~/.config/openmontage/下。如果你第一次运行后没有自动生成样例配置,可以从源码的config目录里手动复制。
主配置文件负责声明“全局行为”,我列几个实际会动到的关键项:
- 窗口扫描策略:是否跳过最小化窗口、是否跳过无标题窗口、是否包含所有工作区的窗口。
- 匹配顺序:按类名匹配还是按标题匹配,或者“类名优先、标题次之”。
- 快捷键:触发窗口选择界面的按键和触发立即重排的按键。
- 模板目录路径:指向存放 YAML 模板文件的文件夹。
这些配置项不需要每次都改,但理解它们能帮你避开很多诡异行为。比如默认情况下,OpenMontage 只会把“普通窗口”列入候选列表,如果你发现某个程序(尤其是弹窗、工具窗这类 override-redirect 窗口)始终出现在候选列表里,就可以通过配置文件调整窗口类型过滤规则。
4.2 模板文件的结构解剖
下面这个示例不是某一个发行版自带模板的复制粘贴,而是根据我的实际经验整理出的一个可以拿来就改的参考结构:
name: "ide-and-docs" monitors: - id: 0 slots: - id: "editor" rect: [0, 0, 60%, 100%] match: class: ["code", "Code", "code-oss", "Code - OSS"] - id: "terminal-right" rect: [60%, 0, 40%, 50%] match: title: [".*zsh.*", ".*bash.*"] - id: "docs-bottom" rect: [60%, 50%, 40%, 50%] match: title: [".*Firefox.*", ".*Chrome.*"]面对这段 YAML,我需要逐个字段解释清楚:
name:模板名称,在 OpenMontage 的模板选择列表里显示。命名一定要直观,因为时间长了你会积累十几套模板,靠名字区分比靠记忆区分靠谱。monitors: 声明模板涉及哪些显示器,id: 0对应主显示器。slots:该显示器上的槽位数组,每个槽位有自己的id、rect和match。rect: 槽位的几何区域,用[x, y, width, height]表示。这里我用了百分比字符串"60%",OpenMontage 会按显示器实际分辨率换算成像素。也可以用绝对值,比如[0, 0, 1920, 1080]。match: 窗口匹配规则,class是窗口类名列表,title是窗口标题正则列表。多个条件之间的关系是“或”还是“与”,取决于配置主文件里的调整;默认情况下同一组里是“或”的关系,即命中一个就算匹配成功。
当前这个模板呈现出的排布效果是:左侧 60% 宽度是代码编辑器,右上四分之一是终端,右下四分之一是浏览器文档。这个排布是我自己常用的“写代码—查文档—开终端跑命令”三件套。
4.3 多显示器模板的写法
上面的例子只有一个显示器,多显示器的写法是把它扩展成一个更长的monitors数组。比如双显示器的典型场景是副屏竖放看文档,主屏横放写代码,那模板大概是:
name: "portrait-doc" monitors: - id: 0 slots: - id: "main-code" rect: [0, 0, 100%, 100%] match: class: ["Code", "code"] - id: 1 slots: - id: "doc-left" rect: [0, 0, 50%, 100%] match: title: [".*Firefox.*"] - id: "chat-right" rect: [50%, 0, 50%, 100%] match: class: ["discord", "TelegramDesktop"]这里id: 0和id: 1的映射关系不是“0 一定是 DP 口那个显示器”,而是由系统当前的显示器顺序决定。如果一个窗口在副屏上,而模板里副屏对应的槽位正好空闲,它就会自动“钻”到那个槽位里;如果窗口所在屏幕没有对应槽位,OpenMontage 会尝试按物理显示器 ID 做映射,但显示器热插拔后 ID 次序可能会变,这是多显示器使用中最需要留意的一环。
4.4 关于匹配规则的几个细节
写模板时最容易踩的坑是匹配规则过于宽松或过于严格。
先说过于宽松:你给一个槽位只写了class: ["chromium"],那么所有 Chromium 窗口都会优先往这个槽位里挤,结果就是明明是“让 A 窗口去左边、B 窗口去右边”,实际执行后所有 Chromium 窗口都去了左边。要处理这种一对多的情况,就必须加上标题正则做二次区分。
再说过于严格:有些程序在 X11 下类名带有版本号或者连字符,比如jetbrains-idea-ce和jetbrains-idea-ultimate这类,你只写class: ["idea"]是匹配不到的,因为字符串比的是精确相等还是正则行为取决于具体配置。稳妥做法是在模板里写正则时留有余量:".*idea.*"。
还有一个小细节:不是所有窗口都暴露标题给窗口管理器。有些 Electron 应用在标题栏上会临时显示非 ASCII 字符,比如你正在编辑的文件名字全是中文,那么标题正则如果用英文模式去匹配就会失效。这种情况我通常建议优先依赖类名 + 进程名的组合,或者把“主窗口”用类名锁定、“附属窗口”用标题锁定,避免两头落空。
5. 实操运行记录:从选中窗口到整套布局落位的完整链路
5.1 启动 OpenMontage 图形界面后的三步操作
实际运行 OpenMontage 后,核心操作流程不长,就三步。
第一步,看到一个窗口列表。这个列表基于配置的窗口枚举规则,列出当前所有可编排的窗口。列表里有窗口类名、进程名、标题等信息,顺序通常可以按需调整。
第二步,把列表里的窗口分配到右侧模板的槽位。操作方法很直观:在窗口列表里点选一个窗口,再在模板预览图里点选一个槽位,二者就建立绑定关系。这里的“绑定”不是永久性的,只是告诉 OpenMontage“下一次执行时,把这个窗口放到这个槽位里”。如果某个槽位已经绑定了窗口,同一个窗口也可以和多个模板分别绑定,互不冲突。
第三步,点击执行按钮或按下融键里的快捷键,OpenMontage 就会根据槽位的几何数据去移动窗口。在 X11 下这一步几乎是瞬时完成的,窗口会直接“瞬移”到目标坐标并调整尺寸;在协议支持的 Wayland 环境下也能实现类似效果,但动画感会略有不同。
5.2 绑定窗口时确定的槽位不一定靠谱:用“空槽自动填充”更省心
我最开始用 OpenMontage 时,按照惯性思维:把每个窗口精确绑定到每个槽位,一个萝卜一个坑。后来发现这样维护模板的成本太高——每开一个新窗口都要进界面重新绑定。
后来我学到的更高效用法是:让模板里的槽位主要靠自动匹配规则来填充。也就是说,我不在界面里手动把具体窗口拖到具体槽位,而是在模板 YAML 里把匹配规则写好,然后执行时让 OpenMontage 自动枚举所有窗口、按规则分配。这样每次开会前只需要把所有需要的程序打开,按一下快捷键,布局就自动到位。唯一需要手动处理的是“两个同类窗口抢同一个槽位”的情况,可以通过给其中一个窗口临时改标题前缀、或者给两个槽位写不同的匹配顺序来解决。
5.3 触发方式:三种我实际用过的方案
OpenMontage 本身提供了图形界面的启动方式,但在日常使用中每次都“打开 GUI → 点按钮”太慢了。我实际测试过三种触发方式,按推荐程度排序:
- 自定义全局快捷键:在系统设置里把 OpenMontage 的某个命令绑定到组合键,比如
Super + T。这个方式最直观,也最接近 FancyZones 的使用体验。 - 命令行带参数执行:OpenMontage 支持通过命令行参数指定模板名称,比如
python3 ./openmontage.py --apply ide-and-docs。这个方式适合配合桌面环境里的“工作区切换”脚本,或者自定义面板按钮。 - 接入窗口管理器的规则:在 Sway/Hyprland 里把某个专用快捷键绑定到 OpenMontage 的命令。这一层的好处是还能顺手执行其他窗口操作,比如同时把某个工作区切到指定显示器上。
我自己目前在用的组合是:Super + T触发整套“IDE 工作区布局”,Super + Y触发“副屏文档阅读模式”。两个模板用同一套窗口池,但排布逻辑完全相反,互不干扰。
5.4 首次实测时遇到的常见问题:窗口没移动但程序没报错
如果你在第一次运行后发现按下快捷键窗口动都没动,而且终端也没有错误输出,大概率不是脚本出问题,而是两个原因之一:
第一,窗口被忽略了。前面提过,OpenMontage 有窗口过滤机制,如果你要移动的窗口处于“最小化”状态,或者它的窗口类型被判定为工具栏、菜单、Dock 等不适合移动的类型,程序会跳过它。解决方法是把窗口恢复到正常可见状态,并在配置里确认“包含最小化窗口”开关是否开启。
第二,目标槽位的尺寸和窗口的最小尺寸冲突。某些 GUI 程序会设置一个固定最小窗口尺寸,比如 640x480。如果你写给它的槽位只有 300x200 像素,OpenMontage 在移动时可能直接跳过(或把窗口设成最小可接受尺寸)。这种情况在模板设计阶段就要考虑到,不同应用对尺寸的容忍度差别很大。
6. 踩坑记录:我实际遇到过的四个老大难问题
6.1 显示器 ID 漂移:热插拔后的混乱
我的台式机每天都有外接显示器开关的情况,导致系统里显示器 ID 在 DP1、HDMI-A-1 之间跳。OpenMontage 的模板里monitors.id是跟随系统枚举顺序的,一旦显示器物理端口顺序变了,整个模板的几何映射就全乱了。
我实际踩过的场景是:模板设计时把“左侧显示器”的 ID 当成 0,但某次重启后系统把中间那块屏识别成了 0,结果文档窗口全跑到中间屏幕去了。
这个问题没有一个通用的完美解法,但有几个缓解策略:
- 固定模板时尽量使用物理端口名而不是数字 ID,如果你的合成器支持这种写法。
- 同一个模板里给不同显示器写不同的槽位匹配规则,避免“窗口到了另一个屏幕也能匹配”的歧义。
- 在 OpenMontage 的窗口列表里留意每台显示器的当前名称,重新绑定一次,把 ID 关系纠正回来。
6.2 Wayland 下的能力边界:GNOME 用户的无奈
我在 GNOME Wayland 环境下试过一次,结果是:OpenMontage 能扫描到窗口,能显示列表和模板,但执行移动时窗口纹丝不动。原因在于 GNOME 的 Mutter 合成器没有暴露 wlr-foreign-toplevel-management 协议,第三方程序没有权限操控窗口位置。这不仅是 OpenMontage 的问题,任何第三方窗口管理器(比如 wmctrl、xdotool)在 GNOME Wayland 下都会遇到同类限制。
如果你是 GNOME 用户并且真的很想用 OpenMontage,我现在能想到的可行办法:
- 换到 Xorg 会话(GNOME 依然提供 Xorg 登录选项),在 Xorg 下 OpenMontage 可以完整工作。
- 换用支持 wlr 协议的合成器,比如 Sway、Hyprland、River 等。
- 继续用 GNOME,但只把 OpenMontage 当窗口列表查看器,不指望它执行移动。
6.3 窗口标题频繁变化导致的匹配失效
Electron 类应用是我使用 OpenMontage 时遇到的最不稳定因素。比如 Slack、Discord 这类聊天工具,它们的标题里会带未读消息数,像 “3 条未读 - Discord”;浏览器就更不用说了,标题跟着网页 Title 走,每开一个新页面就变一次。如果你在模板里用了过于精细的标题正则,很可能下次执行时就匹配不到任何窗口。
后来我的变通思路是:对这种高频变化的窗口,不要依赖标题,尽量使用类名列;实在不行,就给窗口类名预留多个变体。另一个技巧是给同一个槽位写多个备选规则,把“聊天工具”槽位的匹配规则写成:
match: any: - class: ["discord"] - class: ["Slack"] - title: [".*Messenger.*"]这样即使某个应用升级后改了类名,其他规则还能兜底。
6.4 同一个程序多开时如何区分主次窗口
我办公时经常同时开两个 VS Code:一个写前端、一个做后端。两个窗口类名完全一样,标题也都不稳定,OpenMontage 很难通过简单的类名/标题规则区分它们。
面对这种场景,我试过几条路:
- 给两个窗口的标题加区分前缀。这个方法很土但很有效,毕竟标题是可以在应用内自定义的。
- 在 OpenMontage 界面里手动绑定一次,之后只要窗口没有被关闭重建,绑定关系就会保留。这个方法的前提是别经常关掉重组。
- 放弃模板自动匹配,改用“先选中窗口,再挑选槽位”的手动模式。麻烦一些,但适合临时的、需要精准控制的窗口排布。
6.5 性能和响应速度:不要期待它是一个即时交互系统
还有一点必须提醒:OpenMontage 不是常驻后台的守护进程,而是一个按需启动的应用。它启动时扫描窗口列表需要短暂时间,如果桌面上窗口数量特别多(比如开了三十个浏览器标签但每个标签是一个独立窗口),扫描过程会有一两百毫秒的延迟,有时甚至更久。这个速度谈不上卡顿,但也不会像原生窗口管理器那样零延迟。
所以更合适的使用节奏是:把 OpenMontage 触发布局当成“工作前奏”,而不是“边操作边反复调用”的即时工具。先按快捷键完成编排,再进入工作状态,这样体验最好。
7. 结合其他工具的工作流:它和桌面环境如何共存
7.1 与平铺窗口管理器共存的正确姿势
我在前面提到过 i3/Sway 这类平铺管理器,OpenMontage 和它们的关系不是互斥,而是可以嵌套。Sway 负责开启窗口时的初始布局,OpenMontage 负责按模板对窗口进行大规模重组。在实际使用中,这种组合比单独用任意一方都舒服,但需要规避一个问题:平铺管理器通常会强制所有窗口保持“瓦片”状态,OpenMontage 移动完窗口后,Sway 下次收到新窗口打开事件时可能会重新平铺,把 OpenMontage 的成果打乱。
我习惯的做法是:把 OpenMontage 的执行放在“切换到专用工作区之后”。也就是说,先按下快捷键切到工作区,让 Sway 按它的默认平铺规则摆好,再按 OpenMontage 的快捷键做最终重排。这样做的好处是 OpenMontage 不总是“对抗”平铺规则,只是在平铺结果的基础上做一次精确重排。
7.2 配合 wmctrl 和 xdotool 的补充脚本
OpenMontage 不是万能的,它擅长的是“批量移动窗口到固定槽位”,但有些需求它不直接提供,比如同时调整所有窗口到指定显示器、设置窗口为“置顶”状态。这时候我建议把 OpenMontage 作为主要编排器,然后用少量 wmctrl/xdotool 脚本作为补充。
一个我常用的补充脚本示例:移动当前活动窗口到副屏并最大化。
# 用 xdotool 获取当前活动窗口 ID WIN_ID=$(xdotool getactivewindow) # 用 wmctrl 把它移到一个指定显示器上(假设显示器名是 DP-1) wmctrl -i -r "$WIN_ID" -e 0,-1,-1,-1,-1 # 让窗口管理器把它放到 DP-1 并最大化 wmctrl -i -r "$WIN_ID" -b add,maximized_vert,maximized_horz这个脚本和 OpenMontage 的工作是互补的:OpenMontage 负责“很具体的几何排布”,脚本负责“临时且简单的窗口操作”。两条路并不冲突,放在一起用反而更灵活。
7.3 我目前在用的完整工作流
说了这么多,我分享一下目前最落地的一套工作流,供参考:
- 开机进入 Xorg 会话(稳定性和窗口控制能力优先)。
- Sway 作为主 WM,配置好基本的 workspace 和 bar。
- 在 Sway 配置里把
Mod4+t绑定到exec python3 ~/OpenMontage/openmontage.py --apply ide-and-docs。 - 每次开始重度编码前,先打开需要的程序,然后按
Mod4+t,布局自动恢复成“左 60% 编辑器 + 右上终端 + 右下文档”。 - 需要切到“只读模式”(比如开会、审阅方案)时,按另一个快捷键执行另一套模板,副屏变成全屏文档,主屏只留聊天工具和一个空白终端。
这套流程我用了将近三个月,最大的感受是“整理窗口”这个动作几乎从我的肌肉记忆里消失了。以前每次换任务都要花时间摆窗口,现在只需要改变关键词按一下键,全部窗口就位。
8. 关于深入使用的几点体会
最后分享三个关于 OpenMontage 的个人体会,不一定适合所有人,但应该能给你一些参考。
第一,模板设计阶段值得多花时间。不要把窗口排布随手写进 YAML 就完事。我建议优先做一个“观察周”,用一周时间记录自己不同工作场景下是怎么手动排窗口的(哪个窗口最大、哪些窗口在上层、辅助窗口放在哪个位置),然后再把观察结果固化成模板。这样模板是你真实工作习惯的映射,而不是凭空想象的“整齐”。
第二,匹配规则宁可宽松也不要过强。我在实际使用中最常犯的错就是把标题正则写得太具体,导致某个窗口因为标题的一两个字变化就匹配失败。宽松的匹配虽然偶尔会把窗口塞到不那么合适的槽位,但至少窗口会动起来,你只需要微调比完全不动好处理得多。
第三,善用命令行参数和脚本,把 OpenMontage 嵌入到更大的自动化链路里。如果你已经用了自动切换工作区、自动启动应用组的工具,那 OpenMontage 应该成为这个链路里的“最后一环”,而不是一个孤立的工具。我见过不少人用 workrave、dwm 自动布局等工具做自动化,最后窗口还是会乱,就是因为缺少一个统一发力点来收尾——OpenMontage 恰好能补上这个位置。
在我个人的使用评价里,OpenMontage 不算一个“惊艳”的工具,它没有复杂的动画、没有华丽的界面,做的全是笨功夫。但正是这种踏实的“按模板干活”的思路,帮我清理掉了每天桌面整理的心智负担。如果你也深陷多窗口排布的泥潭,尤其在 X11 环境下,我建议花一个下午,读一遍它的配置文件,写一套自己的模板,然后把快捷键绑好——两天后你就会发现,原来整理窗口这件事,真的可以完全交给机器去做。