Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve theme change at runtime #1473

Merged
merged 5 commits into from
Jun 21, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 3 additions & 16 deletions v2/internal/frontend/desktop/windows/frontend.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,28 +106,15 @@ func (f *Frontend) WindowReload() {
}

func (f *Frontend) WindowSetSystemDefaultTheme() {
f.mainWindow.frontendOptions.Windows.Theme = windows.SystemDefault
f.mainWindow.Invoke(func() {
f.mainWindow.updateTheme()
})
f.mainWindow.SetTheme(windows.SystemDefault)
}

func (f *Frontend) WindowSetLightTheme() {
if f.mainWindow.frontendOptions != nil && f.mainWindow.frontendOptions.Windows != nil {
f.mainWindow.frontendOptions.Windows.Theme = windows.Light
f.mainWindow.Invoke(func() {
f.mainWindow.updateTheme()
})
}
f.mainWindow.SetTheme(windows.Light)
}

func (f *Frontend) WindowSetDarkTheme() {
if f.mainWindow.frontendOptions != nil && f.mainWindow.frontendOptions.Windows != nil {
f.mainWindow.frontendOptions.Windows.Theme = windows.Dark
f.mainWindow.Invoke(func() {
f.mainWindow.updateTheme()
})
}
f.mainWindow.SetTheme(windows.Dark)
}

func (f *Frontend) Run(ctx context.Context) error {
Expand Down
31 changes: 18 additions & 13 deletions v2/internal/frontend/desktop/windows/theme.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,32 +7,37 @@ import (

func (w *Window) updateTheme() {

// Don't redraw theme if nothing has changed
if !w.themeChanged {
return
}
w.themeChanged = false

if win32.IsCurrentlyHighContrastMode() {
return
}

if !win32.SupportsThemes() {
return
}
// Only process if there's a theme change
isDarkMode := win32.IsCurrentlyDarkMode()
w.isDarkMode = isDarkMode

// Default use system theme
var isDarkMode bool
switch w.theme {
case windows.SystemDefault:
isDarkMode = win32.IsCurrentlyDarkMode()
leaanthony marked this conversation as resolved.
Show resolved Hide resolved
case windows.Dark:
isDarkMode = true
case windows.Light:
isDarkMode = false
}
win32.SetTheme(w.Handle(), isDarkMode)

// Custom theme processing
winOptions := w.frontendOptions.Windows
var customTheme *windows.ThemeSettings
if winOptions != nil {
customTheme = winOptions.CustomTheme
if winOptions.Theme == windows.Dark {
isDarkMode = true
}
if winOptions.Theme == windows.Light {
isDarkMode = false
}
}

win32.SetTheme(w.Handle(), isDarkMode)

// Custom theme
if win32.SupportsCustomThemes() && customTheme != nil {
if w.isActive {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't we need to also set w.themeChanged = true when w.isActive gets changed during w32.WM_ACTIVATE?
I think we might loose the adaption of the active/inactive color when customThemes are active.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

Expand Down
27 changes: 27 additions & 0 deletions v2/internal/frontend/desktop/windows/window.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/winc/w32"
"github.com/wailsapp/wails/v2/pkg/menu"
"github.com/wailsapp/wails/v2/pkg/options"
winoptions "github.com/wailsapp/wails/v2/pkg/options/windows"
)

type Window struct {
Expand All @@ -24,6 +25,11 @@ type Window struct {
isDarkMode bool
isActive bool
hasBeenShown bool

// Theme
theme winoptions.Theme
themeChanged bool

OnSuspend func()
OnResume func()
}
Expand All @@ -37,6 +43,7 @@ func NewWindow(parent winc.Controller, appoptions *options.App, versionInfo *ope
maxWidth: appoptions.MaxWidth,
versionInfo: versionInfo,
isActive: true,
themeChanged: true,
}
result.SetIsForm(true)

Expand Down Expand Up @@ -73,6 +80,16 @@ func NewWindow(parent winc.Controller, appoptions *options.App, versionInfo *ope
win32.SetBackgroundColour(result.Handle(), appoptions.BackgroundColour.R, appoptions.BackgroundColour.G, appoptions.BackgroundColour.B)
}

if appoptions.Windows != nil {
result.theme = appoptions.Windows.Theme
} else {
result.theme = winoptions.SystemDefault
}

if appoptions.BackgroundColour != nil {
win32.SetBackgroundColour(result.Handle(), appoptions.BackgroundColour.R, appoptions.BackgroundColour.G, appoptions.BackgroundColour.B)
}

result.SetSize(appoptions.Width, appoptions.Height)
result.SetText(appoptions.Title)
result.EnableSizable(!appoptions.DisableResize)
Expand Down Expand Up @@ -163,6 +180,7 @@ func (w *Window) WndProc(msg uint32, wparam, lparam uintptr) uintptr {
case w32.WM_SETTINGCHANGE:
settingChanged := w32.UTF16PtrToString((*uint16)(unsafe.Pointer(lparam)))
if settingChanged == "ImmersiveColorSet" {
w.themeChanged = true
w.updateTheme()
}
return 0
Expand All @@ -174,6 +192,7 @@ func (w *Window) WndProc(msg uint32, wparam, lparam uintptr) uintptr {
}
case w32.WM_ACTIVATE:
//if !w.frontendOptions.Frameless {
w.themeChanged = true
if int(wparam) == w32.WA_INACTIVE {
w.isActive = false
w.updateTheme()
Expand Down Expand Up @@ -262,3 +281,11 @@ func (w *Window) IsMaximised() bool {
func (w *Window) IsMinimised() bool {
return win32.IsWindowMinimised(w.Handle())
}

func (w *Window) SetTheme(theme winoptions.Theme) {
w.theme = theme
w.themeChanged = true
w.Invoke(func() {
w.updateTheme()
})
}