Set Window Background colour if provided + debounce redraw option (#1466)

* Set Window Background colour if provided. Added debounce option for Webview2 redraw on resize

* [windows] Workaround resize flickering in frameless mode

Co-authored-by: stffabi <stffabi@users.noreply.github.com>
This commit is contained in:
Lea Anthony
2022-06-20 17:47:13 +10:00
committed by GitHub
co-authored by stffabi
parent 4dd1be5252
commit cb169611b1
8 changed files with 84 additions and 15 deletions
+1
View File
@@ -42,6 +42,7 @@ require github.com/bitfield/script v0.19.0
require (
bitbucket.org/creachadair/shell v0.0.7 // indirect
github.com/Microsoft/go-winio v0.4.16 // indirect
github.com/bep/debounce v1.2.1 // indirect
github.com/emirpasic/gods v1.12.0 // indirect
github.com/go-git/gcfg v1.5.0 // indirect
github.com/go-ole/go-ole v1.2.6 // indirect
+2
View File
@@ -11,6 +11,8 @@ github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 h1:kFOfPq6dUM1hTo
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
github.com/bep/debounce v1.2.1 h1:v67fRdBA9UQu2NhLFXrSg0Brw7CexQekrBwDMM8bzeY=
github.com/bep/debounce v1.2.1/go.mod h1:H8yggRPQKLUhUoqrJC1bO2xNya7vanpDl7xR3ISbCJ0=
github.com/bitfield/script v0.19.0 h1:W24f+FQuPab9gXcW8bhcbo5qO8AtrXyu3XOnR4zhHN0=
github.com/bitfield/script v0.19.0/go.mod h1:ana6F8YOSZ3ImT8SauIzuYSqXgFVkSUJ6kgja+WMmIY=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
@@ -7,7 +7,18 @@ import (
"context"
"encoding/json"
"fmt"
"github.com/bep/debounce"
"github.com/wailsapp/wails/v2/internal/binding"
"github.com/wailsapp/wails/v2/internal/frontend"
"github.com/wailsapp/wails/v2/internal/frontend/assetserver"
"github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge"
"github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/win32"
"github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/winc"
"github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/winc/w32"
"github.com/wailsapp/wails/v2/internal/logger"
"github.com/wailsapp/wails/v2/internal/system/operatingsystem"
"github.com/wailsapp/wails/v2/pkg/options"
"github.com/wailsapp/wails/v2/pkg/options/windows"
"io"
"log"
"net/http"
@@ -17,17 +28,7 @@ import (
"strconv"
"strings"
"text/template"
"github.com/wailsapp/wails/v2/internal/binding"
"github.com/wailsapp/wails/v2/internal/frontend"
"github.com/wailsapp/wails/v2/internal/frontend/assetserver"
"github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge"
"github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/winc"
"github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/winc/w32"
"github.com/wailsapp/wails/v2/internal/logger"
"github.com/wailsapp/wails/v2/internal/system/operatingsystem"
"github.com/wailsapp/wails/v2/pkg/options"
"github.com/wailsapp/wails/v2/pkg/options/windows"
"time"
)
const startURL = "http://wails.localhost/"
@@ -54,7 +55,8 @@ type Frontend struct {
hasStarted bool
// Windows build number
versionInfo *operatingsystem.WindowsVersionInfo
versionInfo *operatingsystem.WindowsVersionInfo
resizeDebouncer func(f func())
}
func NewFrontend(ctx context.Context, appoptions *options.App, myLogger *logger.Logger, appBindings *binding.Bindings, dispatcher frontend.Dispatcher) *Frontend {
@@ -71,6 +73,12 @@ func NewFrontend(ctx context.Context, appoptions *options.App, myLogger *logger.
versionInfo: versionInfo,
}
if appoptions.Windows != nil {
if appoptions.Windows.ResizeDebounceMS > 0 {
result.resizeDebouncer = debounce.New(time.Duration(appoptions.Windows.ResizeDebounceMS) * time.Millisecond)
}
}
// We currently can't use wails://wails/ as other platforms do, therefore we map the assets sever onto the following url.
result.startURL, _ = url.Parse(startURL)
@@ -151,7 +159,15 @@ func (f *Frontend) Run(ctx context.Context) error {
}
}
f.chromium.Resize()
if f.resizeDebouncer != nil {
f.resizeDebouncer(func() {
f.mainWindow.Invoke(func() {
f.chromium.Resize()
})
})
} else {
f.chromium.Resize()
}
})
mainWindow.OnClose().Bind(func(arg *winc.Event) {
@@ -329,6 +345,7 @@ func (f *Frontend) WindowSetRGBA(col *options.RGBA) {
log.Fatal(err)
}
})
}
func (f *Frontend) Quit() {
@@ -15,6 +15,7 @@ var (
moduser32 = syscall.NewLazyDLL("user32.dll")
procSystemParametersInfo = moduser32.NewProc("SystemParametersInfoW")
procGetWindowLong = moduser32.NewProc("GetWindowLongW")
procSetClassLongPtr = moduser32.NewProc("SetClassLongPtrW")
procShowWindow = moduser32.NewProc("ShowWindow")
)
var (
@@ -22,6 +23,11 @@ var (
procDwmSetWindowAttribute = moddwmapi.NewProc("DwmSetWindowAttribute")
procDwmExtendFrameIntoClientArea = moddwmapi.NewProc("DwmExtendFrameIntoClientArea")
)
var (
modwingdi = syscall.NewLazyDLL("gdi32.dll")
procCreateSolidBrush = modwingdi.NewProc("CreateSolidBrush")
)
var windowsVersion, _ = operatingsystem.GetWindowsVersionInfo()
func IsWindowsVersionAtLeast(major, minor, buildNumber int) bool {
@@ -4,6 +4,7 @@ package win32
import (
"fmt"
"github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/winc"
"log"
"syscall"
"unsafe"
@@ -33,6 +34,10 @@ const (
SW_FORCEMINIMIZE = 11
)
const (
GCLP_HBRBACKGROUND int32 = -10
)
// http://msdn.microsoft.com/en-us/library/windows/desktop/bb773244.aspx
type MARGINS struct {
CxLeftWidth, CxRightWidth, CyTopHeight, CyBottomHeight int32
@@ -74,6 +79,12 @@ func ShowWindowMinimised(hwnd uintptr) {
showWindow(hwnd, SW_MINIMIZE)
}
func SetBackgroundColour(hwnd uintptr, r, g, b uint8) {
col := winc.RGB(r, g, b)
hbrush, _, _ := procCreateSolidBrush.Call(uintptr(col))
setClassLongPtr(hwnd, GCLP_HBRBACKGROUND, hbrush)
}
func dwmExtendFrameIntoClientArea(hwnd uintptr, margins *MARGINS) error {
ret, _, _ := procDwmExtendFrameIntoClientArea.Call(
hwnd,
@@ -86,6 +97,15 @@ func dwmExtendFrameIntoClientArea(hwnd uintptr, margins *MARGINS) error {
return nil
}
func setClassLongPtr(hwnd uintptr, param int32, val uintptr) bool {
ret, _, _ := procSetClassLongPtr.Call(
hwnd,
uintptr(param),
val,
)
return ret != 0
}
func getWindowLong(hwnd uintptr, index int) int32 {
ret, _, _ := procGetWindowLong.Call(
hwnd,
+12 -2
View File
@@ -3,9 +3,10 @@
package windows
import (
"unsafe"
"github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/win32"
"github.com/wailsapp/wails/v2/internal/system/operatingsystem"
"unsafe"
"github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/winc"
"github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/winc/w32"
@@ -66,6 +67,10 @@ func NewWindow(parent winc.Controller, appoptions *options.App, versionInfo *ope
}
}
if appoptions.RGBA != nil {
win32.SetBackgroundColour(result.Handle(), appoptions.RGBA.R, appoptions.RGBA.G, appoptions.RGBA.B)
}
result.SetSize(appoptions.Width, appoptions.Height)
result.SetText(appoptions.Title)
result.EnableSizable(!appoptions.DisableResize)
@@ -191,6 +196,8 @@ func (w *Window) WndProc(msg uint32, wparam, lparam uintptr) uintptr {
// This hides the titlebar and also disables the resizing from user interaction because the standard frame is not
// shown. We still need the WS_THICKFRAME style to enable resizing from the frontend.
if wparam != 0 {
rgrc := (*w32.RECT)(unsafe.Pointer(lparam))
style := uint32(w32.GetWindowLong(w.Handle(), w32.GWL_STYLE))
if style&w32.WS_MAXIMIZE != 0 {
// If the window is maximized we must adjust the client area to the work area of the monitor. Otherwise
@@ -200,7 +207,6 @@ func (w *Window) WndProc(msg uint32, wparam, lparam uintptr) uintptr {
var monitorInfo w32.MONITORINFO
monitorInfo.CbSize = uint32(unsafe.Sizeof(monitorInfo))
if w32.GetMonitorInfo(monitor, &monitorInfo) {
rgrc := (*w32.RECT)(unsafe.Pointer(lparam))
*rgrc = monitorInfo.RcWork
maxWidth := w.frontendOptions.MaxWidth
@@ -220,6 +226,10 @@ func (w *Window) WndProc(msg uint32, wparam, lparam uintptr) uintptr {
}
}
}
} else {
// This is needed to workaround the resize flickering in frameless mode with WindowDecorations
// See: https://stackoverflow.com/a/6558508
rgrc.Bottom -= 1
}
return 0
+4
View File
@@ -82,6 +82,10 @@ type Options struct {
// User messages that can be customised
Messages *Messages
// ResizeDebounceMS is the amount of time to debounce redraws of webview2
// when resizing the window
ResizeDebounceMS uint16
}
func DefaultMessages() *Messages {
+9
View File
@@ -511,6 +511,15 @@ Type: `*windows.Messages`
A struct of strings used by the webview2 installer if a valid webview2 runtime is not found.
Customise this for any language you choose to support.
### ResizeDebounceMS
Name: ResizeDebounceMS
Type: uint16
ResizeDebounceMS is the amount of time to debounce redraws of webview2 when resizing the window.
The default value (0) will perform redraws as fast as it can.
## Mac Specific Options
### TitleBar