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

Implement theme variant auto-switching for Windows #3

Merged
merged 2 commits into from
Jul 28, 2024
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
3 changes: 2 additions & 1 deletion app/app_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"syscall"

"fyne.io/fyne/v2"
internalapp "fyne.io/fyne/v2/internal/app"
)

const notificationTemplate = `$title = "%s"
Expand Down Expand Up @@ -95,5 +96,5 @@ func runScript(name, script string) {
}
}
func watchTheme() {
// TODO monitor the Windows theme
go internalapp.WatchTheme(fyne.CurrentApp().Settings().(*settings).setupTheme)
}
30 changes: 29 additions & 1 deletion internal/app/theme_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,16 @@
package app

import (
"syscall"

"golang.org/x/sys/windows/registry"

"fyne.io/fyne/v2"
"fyne.io/fyne/v2/theme"
)

const themeRegKey = `SOFTWARE\Microsoft\Windows\CurrentVersion\Themes\Personalize`

// DefaultVariant returns the systems default fyne.ThemeVariant.
// Normally, you should not need this. It is extracted out of the root app package to give the
// settings app access to it.
Expand All @@ -20,7 +24,7 @@ func DefaultVariant() fyne.ThemeVariant {
}

func isDark() bool {
k, err := registry.OpenKey(registry.CURRENT_USER, `SOFTWARE\Microsoft\Windows\CurrentVersion\Themes\Personalize`, registry.QUERY_VALUE)
k, err := registry.OpenKey(registry.CURRENT_USER, themeRegKey, registry.QUERY_VALUE)
if err != nil { // older version of Windows will not have this key
return false
}
Expand All @@ -33,3 +37,27 @@ func isDark() bool {

return useLight == 0
}

// WatchTheme calls the supplied function when the Windows dark/light theme changes.
func WatchTheme(onChanged func()) {
// implementation based on an MIT-licensed Github Gist by Jeremy Black (c) 2022
// https://gist.github.com/jerblack/1d05bbcebb50ad55c312e4d7cf1bc909
var regNotifyChangeKeyValue *syscall.Proc
if advapi32, err := syscall.LoadDLL("Advapi32.dll"); err == nil {
if p, err := advapi32.FindProc("RegNotifyChangeKeyValue"); err == nil {
regNotifyChangeKeyValue = p
}
}
if regNotifyChangeKeyValue == nil {
return
}
k, err := registry.OpenKey(registry.CURRENT_USER, themeRegKey, syscall.KEY_NOTIFY|registry.QUERY_VALUE)
if err != nil {
return // on older versions of windows the key may not exist
}
for {
// blocks until the reigstry key has been changed
regNotifyChangeKeyValue.Call(uintptr(k), 0, 0x00000001|0x00000004, 0, 0)
onChanged()
}
}
Loading