如何使用Python获取当前系统活跃的窗口管理器
从wmctrl输出中提取窗口管理器名称
你当前拿到的wmctrl -m输出是标准的逐行键值对格式,不需要复杂正则处理,逐行匹配name:开头的行,拆分提取值即可。修改后的实现代码如下,补全了异常捕获逻辑,避免裸except吞掉未知错误:
import subprocess def getWM(): try: output = subprocess.run( ['wmctrl', '-m'], text=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, check=True ) for line in output.stdout.splitlines(): stripped_line = line.strip() if stripped_line.startswith('name:'): # 按第一个冒号分割,兼容WM名称中带冒号的极端情况 return stripped_line.split(':', 1)[1].strip() return None except (subprocess.CalledProcessError, FileNotFoundError): # 覆盖wmctrl未安装、命令执行无权限、执行报错的场景 return None
其他获取窗口管理器信息的方案
除了调用subprocess执行wmctrl之外,还有几个更轻量、兼容性更好的方案:
- 基于
python-xlib直接读取X11根窗口属性
X11规范要求运行中的窗口管理器必须在根窗口写入_NET_SUPPORTING_WM_CHECK属性存储自身信息,用python-xlib可以直接读取该属性,不需要拉起外部子进程,性能更好,仅适用于X11会话。简单实现参考:from Xlib.display import Display def get_wm_via_xlib(): try: display = Display() root = display.screen().root wm_check_atom = display.intern_atom('_NET_SUPPORTING_WM_CHECK') wm_name_atom = display.intern_atom('_NET_WM_NAME') utf8_atom = display.intern_atom('UTF8_STRING') wm_win_id = root.get_full_property(wm_check_atom, wm_check_atom).value[0] wm_win = display.create_resource_object('window', wm_win_id) wm_name_prop = wm_win.get_full_property(wm_name_atom, utf8_atom) return wm_name_prop.value.decode('utf-8').strip() if wm_name_prop else None except Exception: return None - 适配Wayland环境的环境变量+进程检测方案
wmctrl本身不支持Wayland会话,这类场景下可以先读取XDG_SESSION_TYPE环境变量判断会话类型:如果是Wayland会话,可通过XDG_CURRENT_DESKTOP环境变量映射对应窗口管理器(比如值为GNOME对应Mutter、KDE对应KWin、sway对应Sway窗口管理器),也可以遍历/proc目录下的进程信息,匹配运行中的WM进程名。 - 基于PyGObject的GDK原生接口
如果你的程序运行在GTK桌面环境、本身已经依赖PyGObject,可以直接调用GDK封装的原生接口获取WM名称,不需要额外依赖命令行工具或其他库,直接调用Gdk.Display.get_default().get_window_manager_name()即可拿到结果。
内容的提问来源于stack exchange,提问作者Rafi
相关产品推荐
相关产品推荐

