- GUI 单实例锁: 新增 internal/instance 包,首实例监听专用端点, 第二实例发送 focus 信号后静默退出 (Unix: gui.sock, Win: 18924) - 守护进程弱锁修复: NewServer() 在 os.Remove 前先 net.Dial 探测, 有活进程时拒绝启动,避免静默抢占 socket 导致孤儿进程 - macOS .app 重开恢复: 通过 class_addMethod 给 GLFWApplicationDelegate 注册 applicationShouldHandleReopen:hasVisibleWindows: 回调, 绕过 GLFW 直接用 Cocoa makeKeyAndOrderFront: 显示窗口 - 三平台覆盖: macOS/Linux 用 unix socket, Windows 用 TCP 端口
56 lines
1.7 KiB
Go
56 lines
1.7 KiB
Go
//go:build windows
|
|
|
|
package paths
|
|
|
|
import (
|
|
"os"
|
|
"path/filepath"
|
|
)
|
|
|
|
// IPCNetwork returns the transport network for GUI <-> daemon IPC.
|
|
// Windows uses TCP because AF_UNIX sockets enforce mandatory
|
|
// integrity-level checks: a socket created by the elevated daemon
|
|
// (High Integrity) cannot be connected to by the non-elevated GUI
|
|
// (Medium Integrity). TCP on 127.0.0.1 has no such restriction.
|
|
func IPCNetwork() string { return "tcp" }
|
|
|
|
// IPCAddress returns the listen/dial address for GUI <-> daemon IPC.
|
|
// On Windows this is a TCP address on localhost.
|
|
const ipcPort = "18923"
|
|
|
|
func IPCAddress() string { return "127.0.0.1:" + ipcPort }
|
|
|
|
// GUILockNetwork returns the transport for the GUI single-instance lock.
|
|
// Windows uses TCP (same reason as IPC: AF_UNIX integrity-level checks).
|
|
func GUILockNetwork() string { return "tcp" }
|
|
|
|
// GUILockAddress returns the address for the GUI single-instance lock.
|
|
func GUILockAddress() string { return "127.0.0.1:18924" }
|
|
|
|
func init() {
|
|
home, _ := os.UserHomeDir()
|
|
recomputePaths(home)
|
|
}
|
|
|
|
// recomputePaths sets Paths based on the given home directory.
|
|
// On Windows the layout follows platform conventions:
|
|
//
|
|
// %APPDATA%\<BundleID>\ data (db, config)
|
|
// %LOCALAPPDATA%\<BundleID>\ cache
|
|
// %LOCALAPPDATA%\<BundleID>\Logs\ logs
|
|
func recomputePaths(home string) {
|
|
appData := os.Getenv("APPDATA")
|
|
if appData == "" {
|
|
appData = filepath.Join(home, "AppData", "Roaming")
|
|
}
|
|
localAppData := os.Getenv("LOCALAPPDATA")
|
|
if localAppData == "" {
|
|
localAppData = filepath.Join(home, "AppData", "Local")
|
|
}
|
|
Paths = Dirs{
|
|
Data: filepath.Join(appData, BundleID),
|
|
Cache: filepath.Join(localAppData, BundleID),
|
|
Log: filepath.Join(localAppData, BundleID, "Logs"),
|
|
}
|
|
}
|