🐛 fix(window): 修复 Windows 后台可见时输入卡顿

- Windows 默认关闭透明 WebView、窗口透明与 Acrylic 背景
- 保留 macOS 透明效果并补充跨平台窗口视觉配置回归测试
- 同步更新多语言性能模式提示与开发文档
This commit is contained in:
Syngnat
2026-07-10 11:16:34 +08:00
parent 8d186fc066
commit 06bfbc4a84
10 changed files with 99 additions and 39 deletions

View File

@@ -168,8 +168,7 @@ node tools/wails-fast-dev.mjs
# Refresh Wails JS bindings after changing exported Go method signatures
node tools/wails-fast-dev.mjs --refresh-bindings
# Windows PowerShell low-memory visual mode: disables transparent WebView/Acrylic backdrop
$env:GONAVI_LOW_MEMORY_MODE="1"; node tools/wails-fast-dev.mjs
# Windows desktop builds use an opaque WebView without an Acrylic backdrop by default.
```
### Build

View File

@@ -162,8 +162,7 @@ node tools/wails-fast-dev.mjs
# 修改 Go 导出方法签名后刷新 Wails JS 绑定
node tools/wails-fast-dev.mjs --refresh-bindings
# Windows PowerShell 低内存视觉模式:关闭透明 WebView Acrylic 背景
$env:GONAVI_LOW_MEMORY_MODE="1"; node tools/wails-fast-dev.mjs
# Windows 桌面端默认使用不透明 WebView,并关闭 Acrylic 背景
```
### 编译构建

40
main.go
View File

@@ -41,13 +41,9 @@ func main() {
application := app.NewApp()
aiService := aiservice.NewService()
lowMemoryMode := isLowMemoryMode()
backgroundColour, windowsOptions := resolveWindowVisualOptions(runtime.GOOS, lowMemoryMode)
windowsOptions.WebviewUserDataPath = resolveWindowsWebviewUserDataPath()
var runtimeCtx context.Context
backgroundColour := &options.RGBA{R: 0, G: 0, B: 0, A: 0}
windowsBackdrop := windows.Acrylic
if lowMemoryMode {
backgroundColour = &options.RGBA{R: 255, G: 255, B: 255, A: 255}
windowsBackdrop = windows.None
}
var appMenu *menu.Menu
if strings.EqualFold(strings.TrimSpace(runtime.GOOS), "darwin") {
appMenu = buildMacApplicationMenu(func() {
@@ -97,14 +93,7 @@ func main() {
application,
aiService,
},
Windows: &windows.Options{
WebviewIsTransparent: !lowMemoryMode,
WindowIsTranslucent: !lowMemoryMode,
BackdropType: windowsBackdrop,
DisableWindowIcon: false,
DisableFramelessWindowDecorations: false,
WebviewUserDataPath: resolveWindowsWebviewUserDataPath(),
},
Windows: windowsOptions,
Mac: &mac.Options{
WebviewIsTransparent: true,
WindowIsTranslucent: true,
@@ -186,3 +175,26 @@ func isLowMemoryMode() bool {
return false
}
}
func resolveWindowVisualOptions(goos string, lowMemoryMode bool) (*options.RGBA, *windows.Options) {
// A visible Acrylic surface keeps DWM composing after GoNavi loses focus.
// Windows therefore uses an opaque surface by default; macOS keeps its separate native effect path.
disableTransparency := lowMemoryMode || strings.EqualFold(strings.TrimSpace(goos), "windows")
if disableTransparency {
return &options.RGBA{R: 255, G: 255, B: 255, A: 255}, &windows.Options{
WebviewIsTransparent: false,
WindowIsTranslucent: false,
BackdropType: windows.None,
DisableWindowIcon: false,
DisableFramelessWindowDecorations: false,
}
}
return &options.RGBA{R: 0, G: 0, B: 0, A: 0}, &windows.Options{
WebviewIsTransparent: true,
WindowIsTranslucent: true,
BackdropType: windows.Acrylic,
DisableWindowIcon: false,
DisableFramelessWindowDecorations: false,
}
}

View File

@@ -5,6 +5,8 @@ import (
"github.com/wailsapp/wails/v2/pkg/menu"
"github.com/wailsapp/wails/v2/pkg/menu/keys"
"github.com/wailsapp/wails/v2/pkg/options"
"github.com/wailsapp/wails/v2/pkg/options/windows"
)
func TestIsLowMemoryMode(t *testing.T) {
@@ -30,24 +32,72 @@ func TestIsLowMemoryMode(t *testing.T) {
}
}
func TestShouldRunMCPServerMode(t *testing.T) {
cases := []struct {
name string
args []string
want bool
func TestResolveWindowVisualOptions(t *testing.T) {
tests := []struct {
name string
goos string
lowMemoryMode bool
wantBackground options.RGBA
wantWebviewOpaque bool
wantWindowOpaque bool
wantWindowsBackdrop windows.BackdropType
}{
{name: "empty", args: nil, want: false},
{name: "mcp-server", args: []string{"mcp-server"}, want: true},
{name: "flag style", args: []string{"--mcp-server"}, want: true},
{name: "mcp-server http mode", args: []string{"mcp-server", "http"}, want: true},
{name: "mcp-server remote config", args: []string{"mcp-server", "remote-config"}, want: true},
{name: "unknown", args: []string{"serve"}, want: false},
{
name: "windows defaults to opaque without acrylic",
goos: "windows",
wantBackground: options.RGBA{R: 255, G: 255, B: 255, A: 255},
wantWebviewOpaque: true,
wantWindowOpaque: true,
wantWindowsBackdrop: windows.None,
},
{
name: "windows low memory remains opaque",
goos: " Windows ",
lowMemoryMode: true,
wantBackground: options.RGBA{R: 255, G: 255, B: 255, A: 255},
wantWebviewOpaque: true,
wantWindowOpaque: true,
wantWindowsBackdrop: windows.None,
},
{
name: "mac default remains transparent",
goos: "darwin",
wantBackground: options.RGBA{R: 0, G: 0, B: 0, A: 0},
wantWebviewOpaque: false,
wantWindowOpaque: false,
wantWindowsBackdrop: windows.Acrylic,
},
{
name: "low memory remains opaque on other platforms",
goos: "darwin",
lowMemoryMode: true,
wantBackground: options.RGBA{R: 255, G: 255, B: 255, A: 255},
wantWebviewOpaque: true,
wantWindowOpaque: true,
wantWindowsBackdrop: windows.None,
},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
if got := shouldRunMCPServerMode(tc.args); got != tc.want {
t.Fatalf("shouldRunMCPServerMode(%v) = %v, want %v", tc.args, got, tc.want)
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
background, windowsOptions := resolveWindowVisualOptions(tt.goos, tt.lowMemoryMode)
if background == nil {
t.Fatal("resolveWindowVisualOptions() background is nil")
}
if got := *background; got != tt.wantBackground {
t.Fatalf("background = %+v, want %+v", got, tt.wantBackground)
}
if windowsOptions == nil {
t.Fatal("resolveWindowVisualOptions() windows options are nil")
}
if got := !windowsOptions.WebviewIsTransparent; got != tt.wantWebviewOpaque {
t.Fatalf("webview opaque = %v, want %v", got, tt.wantWebviewOpaque)
}
if got := !windowsOptions.WindowIsTranslucent; got != tt.wantWindowOpaque {
t.Fatalf("window opaque = %v, want %v", got, tt.wantWindowOpaque)
}
if got := windowsOptions.BackdropType; got != tt.wantWindowsBackdrop {
t.Fatalf("Windows backdrop = %v, want %v", got, tt.wantWindowsBackdrop)
}
})
}

View File

@@ -2797,7 +2797,7 @@
"app.theme.appearance.transparency_blur_title": "Transparenz- und Weichzeichnungseffekte",
"app.theme.appearance.ui_scale_hint": "* Für kleine Bildschirme werden 85%-95% empfohlen",
"app.theme.appearance.ui_scale_title": "UI-Skalierung (UI Scale)",
"app.theme.appearance.windows_acrylic_hint": "Windows verwendet den systemeigenen Acrylic-Effekt. Die Unschärfestärke wird vom System gesteuert.",
"app.theme.appearance.windows_acrylic_hint": "Windows-Leistungsmodus: Systemhintergrundunschärfe ist deaktiviert.",
"app.theme.appearance_settings_description": "Skalierung, Schriftgröße, Transparenz und Weichzeichnung zentral anpassen.",
"app.theme.appearance_settings_title": "Darstellungseinstellungen",
"app.theme.data_table.column_width_hint": "Der Standardmodus nutzt 200px, der kompakte Modus 140px als Standardspaltenbreite. Manuell angepasste Spaltenbreiten bleiben vorrangig erhalten.",

View File

@@ -2797,7 +2797,7 @@
"app.theme.appearance.transparency_blur_title": "Transparency and Blur Effects",
"app.theme.appearance.ui_scale_hint": "* Recommended for small screens: 85%-95%",
"app.theme.appearance.ui_scale_title": "UI Scale (UI Scale)",
"app.theme.appearance.windows_acrylic_hint": "Windows uses the system Acrylic effect. Blur intensity is controlled by the system.",
"app.theme.appearance.windows_acrylic_hint": "Windows performance mode: system background blur is off.",
"app.theme.appearance_settings_description": "Adjust scale, font size, transparency, and blur effects in one place.",
"app.theme.appearance_settings_title": "Appearance Settings",
"app.theme.data_table.column_width_hint": "Standard mode defaults to 200px; compact mode defaults to 140px. Manually adjusted column widths are preserved first.",

View File

@@ -2797,7 +2797,7 @@
"app.theme.appearance.transparency_blur_title": "透明度とぼかし効果",
"app.theme.appearance.ui_scale_hint": "* 小さい画面では 85%-95% を推奨します",
"app.theme.appearance.ui_scale_title": "UI スケール (UI Scale)",
"app.theme.appearance.windows_acrylic_hint": "Windows ではシステムの Acrylic 効果を使用します。ぼかしの強さはシステムにより制御されます。",
"app.theme.appearance.windows_acrylic_hint": "Windows パフォーマンスモード:システム背景のぼかしは無効です。",
"app.theme.appearance_settings_description": "スケール、フォントサイズ、透明度、ぼかし効果をまとめて調整します。",
"app.theme.appearance_settings_title": "外観設定",
"app.theme.data_table.column_width_hint": "標準モードの既定列幅は 200px、コンパクトモードの既定列幅は 140px です。手動で調整した列幅は優先して保持されます。",

View File

@@ -2797,7 +2797,7 @@
"app.theme.appearance.transparency_blur_title": "Эффекты прозрачности и размытия",
"app.theme.appearance.ui_scale_hint": "* Для небольших экранов рекомендуется 85%-95%",
"app.theme.appearance.ui_scale_title": "Масштаб UI (UI Scale)",
"app.theme.appearance.windows_acrylic_hint": "Windows использует системный эффект Acrylic. Сила размытия управляется системой.",
"app.theme.appearance.windows_acrylic_hint": "Режим производительности Windows: системное размытие фона отключено.",
"app.theme.appearance_settings_description": "Единая настройка масштаба, размера шрифта, прозрачности и размытия.",
"app.theme.appearance_settings_title": "Настройки внешнего вида",
"app.theme.data_table.column_width_hint": "В стандартном режиме ширина столбца по умолчанию 200px; в компактном режиме 140px. Вручную измененные ширины столбцов сохраняются в приоритете.",

View File

@@ -2797,7 +2797,7 @@
"app.theme.appearance.transparency_blur_title": "透明与模糊效果",
"app.theme.appearance.ui_scale_hint": "* 建议小屏设备设置为 85%-95%",
"app.theme.appearance.ui_scale_title": "界面缩放 (UI Scale)",
"app.theme.appearance.windows_acrylic_hint": "Windows 使用系统 Acrylic 效果,模糊程度由系统控制",
"app.theme.appearance.windows_acrylic_hint": "Windows 性能模式:已关闭系统背景模糊",
"app.theme.appearance_settings_description": "统一调整缩放、字体、透明度与模糊效果。",
"app.theme.appearance_settings_title": "外观设置",
"app.theme.data_table.column_width_hint": "标准模式默认列宽 200px紧凑模式默认列宽 140px。已手动拖拽调整的列宽优先保留。",

View File

@@ -2797,7 +2797,7 @@
"app.theme.appearance.transparency_blur_title": "透明与模糊效果",
"app.theme.appearance.ui_scale_hint": "* 建议小屏设备設定为 85%-95%",
"app.theme.appearance.ui_scale_title": "界面缩放 (UI Scale)",
"app.theme.appearance.windows_acrylic_hint": "Windows 使用系统 Acrylic 效果,模糊程度由系统控制",
"app.theme.appearance.windows_acrylic_hint": "Windows 效能模式:已停用系統背景模糊",
"app.theme.appearance_settings_description": "集中調整縮放、字型、透明度與模糊效果。",
"app.theme.appearance_settings_title": "外觀設定",
"app.theme.data_table.column_width_hint": "标准模式預設列宽 200px紧凑模式預設列宽 140px。已手动拖拽调整的列宽优先保留。",