mirror of
https://github.com/Syngnat/GoNavi.git
synced 2026-08-11 01:03:51 +08:00
- 在主程序 Dock 菜单动态列出并聚焦已就绪的独立窗口 - 在 Wails 启动前固定子进程为 Accessory,消除临时 Dock 图标闪现 - 按多显示器可见区域修正越界窗口并回写实际坐标 - 将自定义 AI 面板快捷键同步到独立窗口并转交主窗口处理 - 补齐 Go、Objective-C、前端及 Wails 绑定回归测试
129 lines
2.9 KiB
Go
129 lines
2.9 KiB
Go
package nativewindow
|
|
|
|
import (
|
|
"encoding/json"
|
|
"sort"
|
|
"strings"
|
|
"sync"
|
|
)
|
|
|
|
type dockMenuWindow struct {
|
|
ID string `json:"id"`
|
|
Title string `json:"title"`
|
|
PID int `json:"pid,omitempty"`
|
|
}
|
|
|
|
var detachedDockMenuManager struct {
|
|
sync.RWMutex
|
|
manager *Manager
|
|
}
|
|
|
|
var detachedDockMenuPublisher struct {
|
|
sync.Mutex
|
|
revision uint64
|
|
}
|
|
|
|
func registerDetachedDockMenuManager(manager *Manager) {
|
|
if manager == nil || !supportsDetachedDockMenu() {
|
|
return
|
|
}
|
|
detachedDockMenuManager.Lock()
|
|
detachedDockMenuManager.manager = manager
|
|
detachedDockMenuManager.Unlock()
|
|
installDetachedDockMenu()
|
|
publishDetachedDockMenuSnapshot(manager)
|
|
}
|
|
|
|
func unregisterDetachedDockMenuManager(manager *Manager) {
|
|
if !supportsDetachedDockMenu() {
|
|
return
|
|
}
|
|
detachedDockMenuManager.Lock()
|
|
if detachedDockMenuManager.manager == manager {
|
|
detachedDockMenuManager.manager = nil
|
|
detachedDockMenuManager.Unlock()
|
|
publishDetachedDockMenuSnapshot(nil)
|
|
return
|
|
}
|
|
detachedDockMenuManager.Unlock()
|
|
}
|
|
|
|
func currentDetachedDockMenuManager() *Manager {
|
|
detachedDockMenuManager.RLock()
|
|
manager := detachedDockMenuManager.manager
|
|
detachedDockMenuManager.RUnlock()
|
|
return manager
|
|
}
|
|
|
|
func publishDetachedDockMenuSnapshot(manager *Manager) {
|
|
if !supportsDetachedDockMenu() {
|
|
return
|
|
}
|
|
detachedDockMenuPublisher.Lock()
|
|
defer detachedDockMenuPublisher.Unlock()
|
|
|
|
var windows []WindowInfo
|
|
if manager == nil {
|
|
if currentDetachedDockMenuManager() != nil {
|
|
return
|
|
}
|
|
} else {
|
|
if currentDetachedDockMenuManager() != manager {
|
|
return
|
|
}
|
|
manager.mu.RLock()
|
|
if manager.started && !manager.closing {
|
|
windows = make([]WindowInfo, 0, len(manager.windows))
|
|
for _, entry := range manager.windows {
|
|
windows = append(windows, entry.info)
|
|
}
|
|
}
|
|
manager.mu.RUnlock()
|
|
}
|
|
payload, err := json.Marshal(buildDockMenuSnapshot(windows))
|
|
if err != nil {
|
|
return
|
|
}
|
|
detachedDockMenuPublisher.revision++
|
|
publishDetachedDockMenuSnapshotToPlatform(payload, detachedDockMenuPublisher.revision)
|
|
}
|
|
|
|
func buildDockMenuSnapshot(windows []WindowInfo) []dockMenuWindow {
|
|
current := make([]WindowInfo, 0, len(windows))
|
|
for _, window := range windows {
|
|
window.ID = strings.TrimSpace(window.ID)
|
|
if window.ID == "" || !window.Ready || window.CloseSent {
|
|
continue
|
|
}
|
|
current = append(current, window)
|
|
}
|
|
sort.Slice(current, func(i int, j int) bool {
|
|
if current[i].OpenedAt != current[j].OpenedAt {
|
|
return current[i].OpenedAt < current[j].OpenedAt
|
|
}
|
|
return current[i].ID < current[j].ID
|
|
})
|
|
|
|
result := make([]dockMenuWindow, 0, len(current))
|
|
for _, window := range current {
|
|
title := strings.TrimSpace(window.Title)
|
|
if title == "" {
|
|
title = "GoNavi"
|
|
}
|
|
result = append(result, dockMenuWindow{
|
|
ID: window.ID,
|
|
Title: title,
|
|
PID: window.PID,
|
|
})
|
|
}
|
|
return result
|
|
}
|
|
|
|
func focusDetachedDockMenuWindow(id string) {
|
|
manager := currentDetachedDockMenuManager()
|
|
if manager == nil {
|
|
return
|
|
}
|
|
manager.Focus(strings.TrimSpace(id))
|
|
}
|