wmctrl 是一个强大的 Linux 命令行工具,用于与支持 EWMH/NetWM 标准的 X 窗口管理器(如 GNOME、KDE、Xfce、i3 等)进行交互 。简单来说,就是用命令来控制窗口,例如切换工作区、移动或调整窗口大小、最大化/最小化等,非常适合编写脚本以实现窗口管理的自动化。
安装方法
在绝大多数 Linux 发行版中,都可以通过包管理器轻松安装:
-
Debian/Ubuntu :
sudo apt install wmctrl -
Fedora :
sudo dnf install wmctrl -
Arch Linux :
sudo pacman -S wmctrl
安装后,运行 wmctrl --version 即可验证是否成功。
核心概念:如何指定一个窗口
大部分操作都需要通过 -r 参数或其他 action 来指定目标窗口 <WIN>。wmctrl 提供了非常灵活的指定方式:
| 指定方式 | 语法 | 说明 |
|---|---|---|
| 窗口标题 | wmctrl -a "Firefox" |
默认行为,匹配包含该字符串的窗口(不区分大小写),适合快速操作。 |
| 窗口ID | wmctrl -i -r 0x03a00004 |
配合 -i 选项使用,通过唯一的十六进制窗口ID来精确定位。 |
| 窗口类 | wmctrl -x -r "Firefox" |
配合 -x 选项使用,通过窗口的类名(如 'Firefox'、'Gnome-terminal')来匹配。 |
| 交互选择 | wmctrl -r :SELECT: |
使用特殊字符串 :SELECT:,执行命令后鼠标指针会变化,点击目标窗口即选中。 |
| 当前活动窗口 | wmctrl -r :ACTIVE: |
使用特殊字符串 :ACTIVE:,直接对当前获得焦点的窗口进行操作。 |
常用命令与操作
wmctrl 的功能可以分为"信息查询"和"执行操作"两大类。
1. 信息查询
| 命令 | 功能说明 | 常用选项 |
|---|---|---|
wmctrl -l |
列出所有窗口:显示窗口ID、桌面号、机器名和标题。 | -p(显示PID), -G(显示几何位置和大小), -x(显示窗口类) |
wmctrl -d |
列出所有工作区:显示工作区编号、当前活动工作区(*标记)、几何尺寸等。 | 无 |
wmctrl -m |
显示窗口管理器信息:展示当前窗口管理器的名称、版本以及是否支持 EWMH 标准。 | 无 |
使用示例:
bash
# 列出所有窗口,并显示它们的PID和几何信息
wmctrl -lpG
# 输出结果示例
# 0x03a00004 0 3345 100 100 800 600 my-machine Mozilla Firefox
如上所示,可以通过 PID 关联进程 -3,通过几何信息进行后续操作。
2. 执行操作
| 命令 | 功能说明 | 常用选项/参数 |
|---|---|---|
-a <WIN> |
激活窗口:切换到窗口所在桌面并将其置于前台并获得焦点。 | 无 |
-s <DESK> |
切换工作区:切换到指定的桌面编号(从 0 开始)。 | 无 |
-r <WIN> -t <DESK> |
移动窗口到指定工作区:将窗口移动到目标桌面。 | <DESK> 是工作区编号。 |
-r <WIN> -e <MVARG> |
移动和调整窗口大小:修改窗口的位置和尺寸。 | <MVARG> 格式为 g,x,y,w,h,其中 -1 表示保持不变 -1。 |
-r <WIN> -b <STATE> |
修改窗口状态:添加、移除或切换窗口的特定状态。 | 支持 add、remove、toggle 及状态属性。 |
-c <WIN> |
关闭窗口:优雅地关闭一个窗口(模拟点击关闭按钮)。 | 无 |
-k (on/off) |
切换"显示桌面"模式:最小化所有窗口或恢复。 | 许多窗口管理器支持此功能。 |
使用示例:
bash
# 将当前活动窗口移动到第 3 个工作区(桌面编号为 2)
wmctrl -r :ACTIVE: -t 2
# 将标题包含 "VSCode" 的窗口移动到坐标 (100, 100),并调整为 800x600 大小
# 格式:-e 重力,X,Y,宽,高 。重力通常用 0,-1 表示保持原值不变。
wmctrl -r "VSCode" -e 0,100,100,800,600
# 将当前窗口最大化(同时添加垂直和水平最大化属性)
wmctrl -r :ACTIVE: -b add,maximized_vert,maximized_horz
# 切换火狐浏览器的全屏模式
wmctrl -r "Firefox" -b toggle,fullscreen
# 交互式地选择一个窗口并关闭它
wmctrl -c :SELECT:
# 最大化指定窗口(添加垂直和水平最大化)
wmctrl -r "窗口标题" -b add,maximized_vert,maximized_horz
# 1. 最大化 Firefox 窗口
wmctrl -r "Firefox" -b add,maximized_vert,maximized_horz
# 2. 最大化当前活动窗口
wmctrl -r :ACTIVE: -b add,maximized_vert,maximized_horz
# 3. 通过窗口ID最大化
wmctrl -i -r 0x03a00004 -b add,maximized_vert,maximized_horz
# 4. 通过窗口类名最大化
wmctrl -x -r "Firefox" -b add,maximized_vert,maximized_horz
# 5. 交互式选择窗口并最大化
wmctrl -r :SELECT: -b add,maximized_vert,maximized_horz
# 取消最大化(恢复原始大小)
wmctrl -r "Firefox" -b remove,maximized_vert,maximized_horz
# 切换最大化状态(如果已最大化则取消,否则最大化)
wmctrl -r "Firefox" -b toggle,maximized_vert,maximized_horz
# 仅水平方向最大化
wmctrl -r "Firefox" -b add,maximized_horz
# 仅垂直方向最大化
wmctrl -r "Firefox" -b add,maximized_vert
bash
#!/bin/bash
# 功能:最大化所有匹配某个模式的应用窗口
APP_NAME="Firefox"
# 获取所有匹配的窗口ID
WIN_IDS=$(wmctrl -l | grep "$APP_NAME" | awk '{print $1}')
if [ -z "$WIN_IDS" ]; then
echo "未找到包含 '$APP_NAME' 的窗口"
exit 1
fi
# 逐个最大化
for WIN_ID in $WIN_IDS; do
echo "最大化窗口: $WIN_ID"
wmctrl -i -r "$WIN_ID" -b add,maximized_vert,maximized_horz
done
echo "完成"
高级用法与脚本示例
wmctrl 的真正威力在于与其他工具结合,编写自动化脚本。
场景一:根据进程名激活窗口
结合 grep 和 awk 命令,可以创建一个更智能的窗口切换脚本。
bash
#!/bin/bash
# 功能:激活名为 "Firefox" 的窗口,如果不存在则启动它。
WIN_ID=$(wmctrl -l | grep "Firefox" | awk '{print $1}')
if [ -n "$WIN_ID" ]; then
# 如果窗口存在,则激活它
wmctrl -i -a "$WIN_ID"
else
# 如果窗口不存在,则启动程序
firefox &
fi
场景二:创建桌面布局
编写一个脚本,在开发环境启动时,自动将各个窗口排列整齐。
bash
#!/bin/bash
# 启动终端,并等待它出现
gnome-terminal &
sleep 1
# 移动终端窗口到左上角,大小为 800x600
wmctrl -r "Terminal" -e 0,0,0,800,600
# 启动浏览器
google-chrome &
sleep 2
# 移动浏览器窗口到右上角,大小为 800x600
wmctrl -r "Google Chrome" -e 0,800,0,800,600
**场景三:**移除最大化标志,手动设置指定尺寸
先让窗口取消最大化,再手动设置到你要的尺寸:
bash
#!/bin/bash
# 功能:将指定窗口设置为特定尺寸(模拟"最大化"效果)
TARGET_WIDTH=1200
TARGET_HEIGHT=800
# 取消最大化并设置为指定大小
wmctrl -r "Firefox" -b remove,maximized_vert,maximized_horz
wmctrl -r "Firefox" -e 0,-1,-1,$TARGET_WIDTH,$TARGET_HEIGHT
缺点:当用户点击窗口的"最大化"按钮时,窗口还是会恢复到真正的全屏最大化。
**场景四:**基于事件的自动调整脚本
使用 wmctrl 配合循环监听,持续检测窗口状态变化:
bash
#!/bin/bash
# 监控指定窗口,一旦检测到最大化状态,立即调整为指定尺寸
TARGET_W=1200
TARGET_H=800
APP_CLASS="Firefox"
while true; do
# 获取窗口ID
WIN_ID=$(wmctrl -lx | grep "$APP_CLASS" | awk '{print $1}' | head -1)
if [ -n "$WIN_ID" ]; then
# 获取当前窗口状态(需要xprop命令)
if xprop -id "$WIN_ID" _NET_WM_STATE | grep -q "_NET_WM_STATE_MAXIMIZED"; then
# 检测到最大化,立即移除最大化标志并设置尺寸
wmctrl -i -r "$WIN_ID" -b remove,maximized_vert,maximized_horz
sleep 0.1 # 短暂延迟确保移除生效
wmctrl -i -r "$WIN_ID" -e 0,-1,-1,$TARGET_W,$TARGET_H
echo "$(date): Reset window size from maximized to ${TARGET_W}x${TARGET_H}"
fi
fi
sleep 0.5 # 降低CPU使用率
done
运行方式 :保存为 window_watcher.sh 并后台运行
bash
chmod +x window_watcher.sh
./window_watcher.sh &
**场景五:**完全禁用最大化功能
如果你完全不需要最大化按钮,可以强制移除它:
bash
# 使用 xprop 移除窗口的"最大化"功能
xprop -name "Firefox" -f _NET_WM_ALLOWED_ACTIONS 32a -set _NET_WM_ALLOWED_ACTIONS _NET_WM_ACTION_MOVE,_NET_WM_ACTION_RESIZE,_NET_WM_ACTION_CLOSE,_NET_WM_ACTION_MINIMIZE
这样用户只能手动调整窗口大小,无法最大化。
**场景六:**实用脚本:完全控制的窗口管理器
这里提供一个完整的脚本,可以对特定应用实现完全自定义的窗口行为:
bash
#!/bin/bash
# 完整的窗口控制脚本
CONFIG_FILE="$HOME/.wmctrl_custom.conf"
# 配置文件格式示例:
# Firefox|1200|800
# Gnome-terminal|800|600
setup_windows() {
while IFS='|' read -r app_class width height; do
if [ -z "$app_class" ]; then continue; fi
# 获取该应用的所有窗口
wmctrl -lx | grep -i "$app_class" | while read -r id rest; do
echo "处理: $app_class (ID: $id)"
# 移除最大化
wmctrl -i -r "$id" -b remove,maximized_vert,maximized_horz 2>/dev/null
# 设置大小
wmctrl -i -r "$id" -e 0,-1,-1,$width,$height 2>/dev/null
# 可选:居中显示
SCREEN_W=$(xrandr --current | grep '*' | uniq | awk '{print $1}' | cut -d 'x' -f1)
SCREEN_H=$(xrandr --current | grep '*' | uniq | awk '{print $1}' | cut -d 'x' -f2)
if [ -n "$SCREEN_W" ] && [ -n "$SCREEN_H" ]; then
POS_X=$((($SCREEN_W - $width) / 2))
POS_Y=$((($SCREEN_H - $height) / 2))
wmctrl -i -r "$id" -e 0,$POS_X,$POS_Y,-1,-1
fi
done
done < "$CONFIG_FILE"
}
# 创建示例配置文件
if [ ! -f "$CONFIG_FILE" ]; then
cat > "$CONFIG_FILE" << EOF
# 格式: 应用类名|宽度|高度
Firefox|1200|800
Gnome-terminal|900|600
EOF
echo "已创建示例配置文件: $CONFIG_FILE"
echo "请编辑此文件后重新运行"
exit 0
fi
setup_windows
常见问题与提示
-
标题匹配失败 :使用
wmctrl -l精确查看窗口标题。如果标题很长或动态变化,可以改用-x匹配窗口类(如wmctrl -x -a "Firefox"),或使用-F进行大小写敏感的精确匹配 。 -
操作无效 :确认你的窗口管理器(如 i3、awesome 等平铺窗口管理器)是否完整支持 EWMH 规范。可以运行
wmctrl -m查看兼容性信息。 -
在脚本中使用 :如果窗口启动较慢,操作命令可能会失败。在执行
wmctrl操作前,使用sleep命令添加适当的延迟(例如sleep 2)是一个常用的技巧。