You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用Go语言获取X11环境下的窗口列表及窗口名称

在X11环境下用Go获取所有窗口列表及名称(基于xgb包)

首先安装依赖的xgb包:

go get github.com/BurntSushi/xgb
go get github.com/BurntSushi/xgb/xproto

下面是可直接运行的完整实现代码:

package main

import (
	"fmt"
	"log"

	"github.com/BurntSushi/xgb"
	"github.com/BurntSushi/xgb/xproto"
)

func main() {
	// 连接默认X服务器
	X, err := xgb.NewConn()
	if err != nil {
		log.Fatalf("无法连接X服务器: %v", err)
	}
	defer X.Close()

	// 获取X11顶层根窗口
	root := xproto.Setup(X).DefaultScreen(X).Root

	// 查询根窗口下的所有子窗口
	queryReply, err := xproto.QueryTree(X, root).Reply()
	if err != nil {
		log.Fatalf("查询窗口树失败: %v", err)
	}

	// 遍历所有子窗口,提取窗口名称
	for _, window := range queryReply.Children {
		// 获取_NET_WM_NAME原子(EWMH标准窗口名称属性)
		netWmNameAtom, err := xproto.InternAtom(X, true, uint16(len("_NET_WM_NAME")), "_NET_WM_NAME").Reply()
		if err != nil {
			log.Printf("获取_NET_WM_NAME原子失败: %v", err)
			continue
		}

		// 获取UTF8_STRING原子(_NET_WM_NAME的标准编码)
		utf8Atom, err := xproto.InternAtom(X, true, uint16(len("UTF8_STRING")), "UTF8_STRING").Reply()
		if err != nil {
			log.Printf("获取UTF8_STRING原子失败: %v", err)
			continue
		}

		// 读取窗口的_NET_WM_NAME属性值
		propReply, err := xproto.GetProperty(X, false, window, netWmNameAtom.Atom, utf8Atom.Atom, 0, 1024).Reply()
		if err != nil {
			log.Printf("读取窗口属性失败: %v", err)
			continue
		}

		// 解析并输出窗口名称
		if propReply.Type == utf8Atom.Atom && propReply.ValueLen > 0 {
			windowName := string(propReply.Value)
			fmt.Printf("窗口ID: %d, 名称: %s\n", window, windowName)
		} else {
			// 兼容旧标准:尝试读取WM_NAME属性
			wmNameAtom, err := xproto.InternAtom(X, true, uint16(len("WM_NAME")), "WM_NAME").Reply()
			if err != nil {
				continue
			}
			oldPropReply, err := xproto.GetProperty(X, false, window, wmNameAtom.Atom, xproto.GetPropertyTypeAny, 0, 1024).Reply()
			if err != nil || oldPropReply.ValueLen == 0 {
				continue
			}
			windowName := string(oldPropReply.Value)
			fmt.Printf("窗口ID: %d, 名称: %s(旧标准WM_NAME)\n", window, windowName)
		}
	}
}

核心逻辑说明

  • X服务器连接:xgb.NewConn()自动读取DISPLAY环境变量,连接当前桌面的X服务器。
  • 窗口树遍历:通过QueryTree获取根窗口的直接子窗口,这些就是桌面上的顶级应用窗口。
  • 名称属性优先级:优先使用_NET_WM_NAME(现代窗口管理器标准,UTF8编码),失败则 fallback到旧标准WM_NAME。
  • 容错处理:每个步骤单独捕获错误,避免单个窗口的异常导致整个程序终止。

在X11环境下直接运行go run main.go,就能输出所有已打开窗口的ID和对应名称。

内容的提问来源于stack exchange,提问作者1nf

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 02:50:40