Files
u-desktop/systray.go

182 lines
3.8 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package main
import (
"log"
"os"
"os/exec"
"runtime"
"strconv"
"sync/atomic"
"time"
"unsafe"
"github.com/getlantern/systray"
"github.com/jchv/go-webview2"
)
func onSystrayReady() {
systray.SetIcon(trayIcon)
systray.SetTooltip("动态壁纸引擎")
mSettings := systray.AddMenuItem("桌面设置", "打开设置窗口")
mRestart := systray.AddMenuItem("重启", "重启程序")
mQuit := systray.AddMenuItem("退出", "退出程序")
// 设置窗口
go func() {
for {
<-mSettings.ClickedCh
openSettingsWindow()
}
}()
// 退出
go func() {
<-mQuit.ClickedCh
os.Exit(0)
}()
// 重启
go func() {
for {
<-mRestart.ClickedCh
exe, _ := os.Executable()
exec.Command(exe).Start()
os.Exit(0)
}
}()
go startWebView()
go weatherLoop()
go horoscopeLoop()
go aiNewsLoop()
go bingWallpaperLoop()
go knowledgeLoop()
go startPhotoLoop()
}
func startWebView() {
runtime.LockOSThread()
log.Println("startWebView: 开始")
workerw := findWorkerW()
if workerw == 0 {
log.Println("ERROR: WorkerW not found")
showError("无法找到桌面窗口WorkerW程序无法启动。")
os.Exit(1)
}
log.Printf("WorkerW: 0x%x", workerw)
screenW, screenH := getScreenSize()
log.Printf("Screen: %dx%d", screenW, screenH)
log.Println("创建 WebView2...")
wv = webview2.NewWithOptions(webview2.WebViewOptions{
AutoFocus: false,
WindowOptions: webview2.WindowOptions{
Title: "动态壁纸",
Width: uint(screenW),
Height: uint(screenH),
},
})
if wv == nil {
showError("WebView2 创建失败,请确保已安装 WebView2 Runtime。")
os.Exit(1)
}
log.Println("WebView2 创建成功")
// 立即获取 HWND 并隐藏窗口,避免闪烁
wvHwnd = uintptr(wv.Window())
procShowWindow.Call(wvHwnd, 0) // SW_HIDE
procSetWindowLongPtrW.Call(wvHwnd, gwlStyle, wsPopup|wsVisible|wsChild)
// 立即嵌入 WorkerW
procSetParent.Call(wvHwnd, workerw)
procMoveWindow.Call(wvHwnd, uintptr(^uint(0)), uintptr(^uint(0)), uintptr(screenW+2), uintptr(screenH+2), 1)
log.Printf("已嵌入 WorkerW: HWND=0x%x, %dx%d", wvHwnd, screenW, screenH)
wv.Bind("setZodiacFromGo", func(zodiac string) error {
cfg := loadConfig()
cfg.Zodiac = zodiac
return saveConfig(cfg)
})
log.Println("设置 HTML...")
cfg := loadConfig()
wv.SetHtml(buildWallpaperHTML(cfg))
time.Sleep(500 * time.Millisecond)
// 嵌入完成后再显示
procShowWindow.Call(wvHwnd, 5)
log.Println("壁纸窗口已显示")
go func() {
time.Sleep(500 * time.Millisecond)
reloadAllCards()
}()
go fullscreenMonitor()
type msg struct {
hwnd uintptr
message uint32
wParam uintptr
lParam uintptr
time uint32
pt struct{ x, y int32 }
}
var m msg
for {
ret, _, _ := procGetMessageW.Call(
uintptr(unsafe.Pointer(&m)),
0, 0, 0,
)
if ret == 0 {
break
}
if m.message == wmEvalJS {
for {
select {
case js := <-jsQueue:
wv.Eval(js)
default:
goto nextMsg
}
}
}
if m.message == wmSetHtml {
select {
case html := <-htmlQueue:
wv.SetHtml(html)
default:
}
goto nextMsg
}
nextMsg:
procTranslateMessage.Call(uintptr(unsafe.Pointer(&m)))
procDispatchMessageW.Call(uintptr(unsafe.Pointer(&m)))
}
}
func fullscreenMonitor() {
type rect struct{ Left, Top, Right, Bottom int32 }
var lastState string
for {
if atomic.LoadInt32(&paused) == 0 && wv != nil {
fg, _, _ := procGetForegroundWindow.Call()
if fg != 0 {
var r rect
procGetWindowRect.Call(fg, uintptr(unsafe.Pointer(&r)))
screenW, screenH := getScreenSize()
isFull := (r.Right-r.Left >= screenW) && (r.Bottom-r.Top >= screenH)
state := strconv.FormatBool(isFull)
if state != lastState {
lastState = state
evalJS("if(window.setFullscreen) setFullscreen(" + state + ")")
}
}
}
time.Sleep(2 * time.Second)
}
}