Skip to content

Commit

Permalink
fix: prevent unnecessary redraws during window minimize/restore (#3955)
Browse files Browse the repository at this point in the history
* 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 <lea.anthony@gmail.com>
  • Loading branch information
562589540 and leaanthony authored Dec 26, 2024
1 parent ee2156e commit 461d34c
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 4 deletions.
11 changes: 11 additions & 0 deletions v2/internal/frontend/desktop/windows/frontend.go
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down
30 changes: 26 additions & 4 deletions v2/internal/frontend/desktop/windows/window.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"

Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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
Expand All @@ -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
}
Expand Down Expand Up @@ -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)
}
1 change: 1 addition & 0 deletions website/src/pages/changelog.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit 461d34c

Please sign in to comment.