# switcher-go **Repository Path**: ssuiwp/switcher-go ## Basic Information - **Project Name**: switcher-go - **Description**: windows 窗口切换器 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-08-20 - **Last Updated**: 2026-08-25 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # switcher-go 一个用 Go + [Gio](https://gioui.org) 实现的 Windows 窗口切换器(灵感来自 [Switcheroo](https://github.com/switcheroo/switcheroo))。常驻系统托盘,通过增量搜索快速切换已打开的窗口。 ## 功能 - **增量搜索**:弹出窗口后输入关键字,按标题/进程名实时过滤窗口列表。 - **悬浮窗**:屏幕右下角常驻一个小悬浮按钮,鼠标悬停即弹出窗口列表(列表项可直接点击切换)。 - **系统托盘**:右键菜单可切换「显示悬浮窗」「悬停显示」「开机自启」「设置」「退出」。 - **设置窗口**:通过托盘菜单「设置」打开,可勾选上述开关。 - **编辑器快捷键**:搜索框支持一套 emacs 式快捷键(见下)。 ## 快捷键 ### 唤出切换器 - 默认热键:`Ctrl + \``(反引号)打开居中切换窗口。 - 悬浮窗:鼠标悬停自动弹出(可在托盘/设置关闭「悬停显示」)。 - 悬浮窗 / 托盘右键菜单:点击列表项切换窗口。 ### 搜索框编辑快捷键 | 快捷键 | 作用 | | --- | --- | | `Ctrl + N` / `Ctrl + P` | 在候选窗口间下移 / 上移 | | `Ctrl + F` / `Ctrl + B` | 光标右移 / 左移 | | `Ctrl + A` / `Ctrl + E` | 光标到行首 / 行尾(Home / End) | | `Alt + F` / `Alt + B` | 按词右移 / 左移 | | `Ctrl + U` | 清空搜索框 | | `Ctrl + D` | 删除光标后一个字符 | | `Alt + D` | 删除光标后一个单词 | | `Ctrl + Y` | 从系统剪贴板粘贴 | | `Ctrl + K` | 剪切光标后内容到系统剪贴板 | 搜索框右侧的 `?` 按钮可展开/收起以上快捷键提示。 ## 构建 需要 Go 1.21+(开发使用 Go 1.26.5)以及 Windows 环境(依赖 Win32 API)。 ```powershell # 默认构建会带一个控制台窗口 go build -o switcher-go.exe . # 推荐:以 GUI 子系统构建,启动时不显示控制台窗口 go build -ldflags "-H windowsgui" -o switcher-go.exe . ``` ## 运行 直接运行生成的 `switcher-go.exe` 即可。程序启动后常驻托盘,无主窗口界面。 ## 验证 ```powershell go vet ./... go build ./... go test ./... ``` ## 依赖 - `gioui.org v0.10.2` —— UI 框架(唯一直接依赖)。 - 其余 `gioui.org/shader`、`github.com/go-text/typesetting`、`golang.org/x/*` 等均为 gioui 的间接依赖,由 `go mod tidy` 维护。 - Windows 系统调用使用标准库 `syscall`,不依赖 `golang.org/x/sys`。 ## 说明 - 悬浮窗与切换窗口复用同一 Win32 窗口句柄,通过 `user32` / `kernel32` 进行无边框、置顶、剪贴板等底层操作。 - 悬停检测使用 Win32 `GetCursorPos` + 矩形命中测试轮询,以规避 Gio 合成指针事件在悬停场景下的不可靠性。 - 剪贴板读写通过 `GlobalAlloc` / `GlobalLock` / `RtlMoveMemory` 实现,避免 `unsafe.Pointer` 转换以通过 `go vet`。