wmctrl命令详解

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> 修改窗口状态:添加、移除或切换窗口的特定状态。 支持 addremovetoggle 及状态属性。
-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 的真正威力在于与其他工具结合,编写自动化脚本。

场景一:根据进程名激活窗口

结合 grepawk 命令,可以创建一个更智能的窗口切换脚本。

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

常见问题与提示

  1. 标题匹配失败 :使用 wmctrl -l 精确查看窗口标题。如果标题很长或动态变化,可以改用 -x 匹配窗口类(如 wmctrl -x -a "Firefox"),或使用 -F 进行大小写敏感的精确匹配 。

  2. 操作无效 :确认你的窗口管理器(如 i3、awesome 等平铺窗口管理器)是否完整支持 EWMH 规范。可以运行 wmctrl -m 查看兼容性信息。

  3. 在脚本中使用 :如果窗口启动较慢,操作命令可能会失败。在执行 wmctrl 操作前,使用 sleep 命令添加适当的延迟(例如 sleep 2)是一个常用的技巧。

相关推荐
utf8mb4安全女神3 小时前
shell脚本实现服务器免密登录
linux·运维·服务器
JD技术委员会3 小时前
TypeScript 在 MCP Server 开发中为什么受关注
linux·服务器·typescript
zhexiao273 小时前
ohmyzsh 安装与使用
linux
JAVA面经实录9173 小时前
Spring Cloud Alibaba 微服务企业实战完整文档(架构+规范+调优+故障+源码)
java·运维·spring cloud·微服务
CHANG_THE_WORLD3 小时前
在 VS Code 中让终端显示简洁路径(告别冗长全路径)
linux
va学弟3 小时前
Java 网络通信编程(9):从 BIO 到 NIO
java·运维·服务器·网络
凡人叶枫3 小时前
Effective C++ 条款05:了解 C++ 默默编写并调用哪些函数
java·linux·开发语言·c++·effective c++·编程范式
HackTwoHub3 小时前
关于文件上传漏洞深度绕过利用教程,突破命令执行限制
运维·安全·web安全·网络安全·系统安全·安全架构
ftf拿破仑3 小时前
嵌入式面试高频问题
linux·面试