From 461d34c620c414273e4af11caac5022b9ecee8c9 Mon Sep 17 00:00:00 2001 From: 562589540 <73332665+562589540@users.noreply.github.com> Date: Thu, 26 Dec 2024 13:13:46 +0800 Subject: [PATCH] fix: prevent unnecessary redraws during window minimize/restore (#3955) * fix: prevent unnecessary redraws during window minimize/restore This fixes the window flickering issue when minimizing/restoring by: 1. Adding isMinimizing flag to track window state 2. Adding SetPadding filter to prevent redundant redraws 3. Properly handling minimize/restore window states Fixes #3951 * docs: improve comments and changelog for frameless window flickering fix - Add detailed comments about frameless window fix - Update changelog to clarify this is a frameless window issue - Add bilingual comments for better understanding Fixes #3951 --------- Co-authored-by: Lea Anthony --- .../frontend/desktop/windows/frontend.go | 11 +++++++ .../frontend/desktop/windows/window.go | 30 ++++++++++++++++--- website/src/pages/changelog.mdx | 1 + 3 files changed, 38 insertions(+), 4 deletions(-) diff --git a/v2/internal/frontend/desktop/windows/frontend.go b/v2/internal/frontend/desktop/windows/frontend.go index 806f4ffbab1..65490ef2376 100644 --- a/v2/internal/frontend/desktop/windows/frontend.go +++ b/v2/internal/frontend/desktop/windows/frontend.go @@ -170,10 +170,21 @@ func (f *Frontend) Run(ctx context.Context) error { // depends on the content in the WebView, see https://github.com/wailsapp/wails/issues/1319 event, _ := arg.Data.(*winc.SizeEventData) if event != nil && event.Type == w32.SIZE_MINIMIZED { + // Set minimizing flag to prevent unnecessary redraws during minimize/restore for frameless windows + // 设置最小化标志以防止无边框窗口在最小化/恢复过程中的不必要重绘 + // This fixes window flickering when minimizing/restoring frameless windows + // 这修复了无边框窗口在最小化/恢复时的闪烁问题 + // Reference: https://github.com/wailsapp/wails/issues/3951 + f.mainWindow.isMinimizing = true return } } + // Clear minimizing flag for all non-minimize size events + // 对于所有非最小化的尺寸变化事件,清除最小化标志 + // Reference: https://github.com/wailsapp/wails/issues/3951 + f.mainWindow.isMinimizing = false + if f.resizeDebouncer != nil { f.resizeDebouncer(func() { f.mainWindow.Invoke(func() { diff --git a/v2/internal/frontend/desktop/windows/window.go b/v2/internal/frontend/desktop/windows/window.go index 1e4289ee63d..19ea9db2668 100644 --- a/v2/internal/frontend/desktop/windows/window.go +++ b/v2/internal/frontend/desktop/windows/window.go @@ -3,10 +3,11 @@ package windows import ( - "github.com/wailsapp/go-webview2/pkg/edge" "sync" "unsafe" + "github.com/wailsapp/go-webview2/pkg/edge" + "github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/win32" "github.com/wailsapp/wails/v2/internal/system/operatingsystem" @@ -37,6 +38,13 @@ type Window struct { OnResume func() chromium *edge.Chromium + + // isMinimizing indicates whether the window is currently being minimized + // 标识窗口是否处于最小化状态,用于解决最小化/恢复时的闪屏问题 + // This flag is used to prevent unnecessary redraws during minimize/restore transitions for frameless windows + // 此标志用于防止无边框窗口在最小化/恢复过程中的不必要重绘 + // Reference: https://github.com/wailsapp/wails/issues/3951 + isMinimizing bool } func NewWindow(parent winc.Controller, appoptions *options.App, versionInfo *operatingsystem.WindowsVersionInfo, chromium *edge.Chromium) *Window { @@ -256,7 +264,7 @@ func (w *Window) WndProc(msg uint32, wparam, lparam uintptr) uintptr { rgrc := (*w32.RECT)(unsafe.Pointer(lparam)) if w.Form.IsFullScreen() { // In Full-Screen mode we don't need to adjust anything - w.chromium.SetPadding(edge.Rect{}) + w.SetPadding(edge.Rect{}) } else if w.IsMaximised() { // If the window is maximized we must adjust the client area to the work area of the monitor. Otherwise // some content goes beyond the visible part of the monitor. @@ -287,7 +295,7 @@ func (w *Window) WndProc(msg uint32, wparam, lparam uintptr) uintptr { } } } - w.chromium.SetPadding(edge.Rect{}) + w.SetPadding(edge.Rect{}) } else { // This is needed to workaround the resize flickering in frameless mode with WindowDecorations // See: https://stackoverflow.com/a/6558508 @@ -296,7 +304,7 @@ func (w *Window) WndProc(msg uint32, wparam, lparam uintptr) uintptr { // Increasing the bottom also worksaround the flickering but we would loose 1px of the WebView content // therefore let's pad the content with 1px at the bottom. rgrc.Bottom += 1 - w.chromium.SetPadding(edge.Rect{Bottom: 1}) + w.SetPadding(edge.Rect{Bottom: 1}) } return 0 } @@ -339,3 +347,17 @@ func invokeSync[T any](cba *Window, fn func() (T, error)) (res T, err error) { wg.Wait() return res, err } + +// SetPadding is a filter that wraps chromium.SetPadding to prevent unnecessary redraws during minimize/restore +// 包装了chromium.SetPadding的过滤器,用于防止窗口最小化/恢复过程中的不必要重绘 +// This fixes window flickering when minimizing/restoring frameless windows +// 这修复了无边框窗口在最小化/恢复时的闪烁问题 +// Reference: https://github.com/wailsapp/wails/issues/3951 +func (w *Window) SetPadding(padding edge.Rect) { + // Skip SetPadding if window is being minimized to prevent flickering + // 如果窗口正在最小化,跳过设置padding以防止闪烁 + if w.isMinimizing { + return + } + w.chromium.SetPadding(padding) +} diff --git a/website/src/pages/changelog.mdx b/website/src/pages/changelog.mdx index c852352ab5e..a0e491134cf 100644 --- a/website/src/pages/changelog.mdx +++ b/website/src/pages/changelog.mdx @@ -27,6 +27,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Fixed typo by @takuyahara in [PR](https://github.com/wailsapp/wails/pull/3846) - Fixed incorrect TS definition of `WindowSetSize` by @leaanthony - chore: fix some comments in [PR](https://github.com/wailsapp/wails/pull/3932) by @lvyaoting +- [windows] Fixed frameless window flickering when minimizing/restoring by preventing unnecessary redraws [#3951](https://github.com/wailsapp/wails/issues/3951) ### Changed