mirror of
https://github.com/wailsapp/wails.git
synced 2026-03-14 14:45:49 +01:00
refactor(theme): fix window run() for both macos and windows. refactor events for app.SetTheme() and win.SetTheme()
This commit is contained in:
parent
e8a1bf0886
commit
2c123b8530
11 changed files with 73 additions and 49 deletions
|
|
@ -1,6 +1,8 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/wailsapp/wails/v3/pkg/application"
|
||||
)
|
||||
|
||||
|
|
@ -16,13 +18,12 @@ func (s *WindowService) GetAppTheme() string {
|
|||
return s.app.GetTheme()
|
||||
}
|
||||
|
||||
func (s *WindowService) SetWinTheme(theme string) {
|
||||
func (s *WindowService) SetWinTheme(ctx context.Context, theme string) {
|
||||
win := s.app.Window.Current()
|
||||
win.SetTheme((application.WinTheme(theme)))
|
||||
}
|
||||
|
||||
func (s *WindowService) GetWinTheme() string {
|
||||
win := s.app.Window.Current()
|
||||
theme := win.GetTheme()
|
||||
return theme
|
||||
func (s *WindowService) GetWinTheme(ctx context.Context) string {
|
||||
win := ctx.Value(application.WindowKey).(application.Window)
|
||||
return win.GetTheme()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { Call, CancellablePromise, Create} from "/wails/runtime.js";
|
||||
import { Events } from "/wails/runtime.js";
|
||||
import { Events, Window} from "/wails/runtime.js";
|
||||
|
||||
const resultsApp = document.getElementById("app-theme");
|
||||
const resultsWin = document.getElementById("win-theme");
|
||||
|
|
@ -38,9 +38,9 @@ document.getElementById("win-theme-light").addEventListener("click", () => setWi
|
|||
document.getElementById("win-theme-dark").addEventListener("click", () => setWinTheme("dark"));
|
||||
|
||||
// Go Event Listeners
|
||||
Events.On("applicationThemeChanged", async (ev) => {
|
||||
console.log("[JS] theme changed event", ev.data.theme);
|
||||
resultsApp.innerText = ev.data.theme;
|
||||
Events.On("common:ApplicationThemeChanged", async (ev) => {
|
||||
const appTheme = await callBinding("main.WindowService.GetAppTheme");
|
||||
resultsApp.innerText = appTheme;
|
||||
});
|
||||
|
||||
Events.On("common:ThemeChanged", async (ev) => {
|
||||
|
|
|
|||
|
|
@ -16,6 +16,8 @@ func main() {
|
|||
app := application.New(application.Options{
|
||||
Name: "customEventProcessor Demo",
|
||||
Description: "A demo of the customEventProcessor API",
|
||||
// We Start With Dark Theme
|
||||
Theme: application.AppDark,
|
||||
Assets: application.AssetOptions{
|
||||
Handler: application.BundledAssetFileServer(assets),
|
||||
},
|
||||
|
|
@ -28,25 +30,35 @@ func main() {
|
|||
},
|
||||
})
|
||||
|
||||
// Listen for the theme‑change event and log the payload
|
||||
// app.Event.On("applicationThemeChanged", func(ev *application.CustomEvent) {
|
||||
// fmt.Printf("[Go] applicationThemeChanged received, data = %v\n", ev.Data)
|
||||
// })
|
||||
|
||||
windowService.app = app
|
||||
app.Window.NewWithOptions(application.WebviewWindowOptions{
|
||||
Title: "Window 1",
|
||||
Name: "Window 1",
|
||||
// Both Mac and Windows will follow light theme
|
||||
Mac: application.MacWindow{
|
||||
Appearance: "NSAppearanceNameAqua",
|
||||
},
|
||||
Windows: application.WindowsWindow{
|
||||
Theme: "light",
|
||||
},
|
||||
})
|
||||
|
||||
app.Window.NewWithOptions(application.WebviewWindowOptions{
|
||||
Title: "Window 2",
|
||||
Name: "Window 2",
|
||||
// Both Mac and Widnows will follow Application Theme
|
||||
})
|
||||
|
||||
app.Window.NewWithOptions(application.WebviewWindowOptions{
|
||||
Title: "Window 3",
|
||||
Name: "Window 3",
|
||||
// Both Mac and Widnows will follow Dark Theme
|
||||
Mac: application.MacWindow{
|
||||
Appearance: "NSAppearanceNameDarkAqua",
|
||||
},
|
||||
Windows: application.WindowsWindow{
|
||||
Theme: "dark",
|
||||
},
|
||||
})
|
||||
|
||||
err := app.Run()
|
||||
|
|
|
|||
|
|
@ -183,6 +183,12 @@ func New(appOptions Options) *App {
|
|||
}
|
||||
}
|
||||
|
||||
// Set the application Theme
|
||||
result.theme = AppSystemDefault
|
||||
if appOptions.Theme != "" {
|
||||
result.theme = appOptions.Theme
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
|
|
@ -647,12 +653,6 @@ func (a *App) Run() error {
|
|||
a.impl.setIcon(a.options.Icon)
|
||||
}
|
||||
|
||||
// Set the application Theme
|
||||
a.theme = AppSystemDefault
|
||||
if a.options.Theme != "" {
|
||||
a.theme = a.options.Theme
|
||||
}
|
||||
|
||||
return a.impl.run()
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -7,9 +7,9 @@ const (
|
|||
// AppSystemDefault follows the system theme (light or dark).
|
||||
AppSystemDefault AppTheme = "system"
|
||||
// AppDark forces the application to use a dark theme.
|
||||
AppDark AppTheme = "dark"
|
||||
AppDark AppTheme = "dark"
|
||||
// AppLight forces the application to use a light theme.
|
||||
AppLight AppTheme = "light"
|
||||
AppLight AppTheme = "light"
|
||||
)
|
||||
|
||||
// String returns the string representation of the application theme.
|
||||
|
|
@ -48,7 +48,5 @@ func (a *App) SetTheme(theme AppTheme) {
|
|||
}
|
||||
|
||||
// Notify listeners of the theme change
|
||||
a.Event.Emit("applicationThemeChanged", map[string]any{
|
||||
"theme": a.theme.String(),
|
||||
})
|
||||
a.Event.Emit("common:ApplicationThemeChanged")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -98,7 +98,7 @@ func (w *macosWebviewWindow) getTheme() WinTheme {
|
|||
|
||||
explicitAppearance := w.getExplicitAppearanceName()
|
||||
|
||||
if !explicitAppearance {
|
||||
if explicitAppearance == "" {
|
||||
return WinThemeSystem
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -5,26 +5,26 @@ package application
|
|||
import "github.com/wailsapp/wails/v3/pkg/w32"
|
||||
|
||||
// resolveWindowsEffectiveTheme determines the realized Theme for the window by resolving
|
||||
// application-level and window-level theme settings.
|
||||
func resolveWindowsEffectiveTheme(winTheme WinTheme, appTheme AppTheme) Theme {
|
||||
// application-level and window-level theme settings. It also returns whether the window follows the application theme.
|
||||
func resolveWindowsEffectiveTheme(winTheme WinTheme, appTheme AppTheme) (Theme, bool) {
|
||||
switch winTheme {
|
||||
case WinThemeDark:
|
||||
return Dark
|
||||
return Dark, false
|
||||
case WinThemeLight:
|
||||
return Light
|
||||
return Light, false
|
||||
case WinThemeSystem:
|
||||
return SystemDefault
|
||||
return SystemDefault, false
|
||||
default:
|
||||
// For WinThemeApplication and/or Unset values we default to following
|
||||
switch appTheme {
|
||||
case AppDark:
|
||||
return Dark
|
||||
return Dark, true
|
||||
case AppLight:
|
||||
return Light
|
||||
return Light, true
|
||||
case AppSystemDefault:
|
||||
return SystemDefault
|
||||
return SystemDefault, true
|
||||
default:
|
||||
return SystemDefault
|
||||
return SystemDefault, true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1426,13 +1426,20 @@ func (w *macosWebviewWindow) run() {
|
|||
C.windowSetHideToolbarSeparator(w.nsWindow, C.bool(titleBarOptions.HideToolbarSeparator))
|
||||
}
|
||||
|
||||
// if macOptions.Appearance != "" {
|
||||
// C.windowSetAppearanceTypeByName(w.nsWindow, C.CString(string(macOptions.Appearance)))
|
||||
// }
|
||||
// Does the Window follow Application Theme
|
||||
w.parent.followApplicationTheme = true
|
||||
if macOptions.Appearance != "" {
|
||||
// Explicit Appearance has been provided
|
||||
w.parent.followApplicationTheme = false
|
||||
w.setAppearanceByName(macOptions.Appearance)
|
||||
} else {
|
||||
// If we do follow Application Resolve the Window to follow Application Theme
|
||||
switch globalApplication.theme {
|
||||
case AppDark:
|
||||
w.setAppearanceByName(NSAppearanceNameDarkAqua)
|
||||
case AppLight:
|
||||
w.setAppearanceByName(NSAppearanceNameAqua)
|
||||
}
|
||||
}
|
||||
|
||||
// Only apply invisible title bar when the native drag area is hidden
|
||||
|
|
|
|||
|
|
@ -297,8 +297,8 @@ func TestWindowsWindow_Defaults(t *testing.T) {
|
|||
if opts.DisableIcon != false {
|
||||
t.Error("DisableIcon should default to false")
|
||||
}
|
||||
if opts.Theme != WinThemeApplication {
|
||||
t.Error("Theme should default to SystemDefault")
|
||||
if opts.Theme != "" {
|
||||
t.Error("Theme should default to empty string")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -508,21 +508,27 @@ func (w *windowsWebviewWindow) run() {
|
|||
}
|
||||
|
||||
// Process the theme
|
||||
// Resolve the Complicated App State to a simple theme
|
||||
w.parent.followApplicationTheme = false
|
||||
if options.Windows.Theme == WinThemeApplication || options.Windows.Theme == "" {
|
||||
w.parent.followApplicationTheme = true
|
||||
}
|
||||
|
||||
// System, Dark, Light - Resolved Theme to Apply
|
||||
w.theme = resolveWindowsEffectiveTheme(options.Windows.Theme, globalApplication.theme)
|
||||
w.syncTheme()
|
||||
theme, followAppTheme := resolveWindowsEffectiveTheme(options.Windows.Theme, globalApplication.theme)
|
||||
w.theme = theme
|
||||
w.parent.followApplicationTheme = followAppTheme
|
||||
|
||||
switch w.theme {
|
||||
case SystemDefault:
|
||||
w.updateTheme(w32.IsCurrentlyDarkMode())
|
||||
case Dark:
|
||||
w32.AllowDarkModeForWindow(w.hwnd, true)
|
||||
w.updateTheme(true)
|
||||
case Light:
|
||||
w.updateTheme(false)
|
||||
}
|
||||
|
||||
// Always listen to OS theme changes but only update the theme if we are following the application theme
|
||||
w.parent.onApplicationEvent(events.Windows.SystemThemeChanged, func(*ApplicationEvent) {
|
||||
if w.theme != SystemDefault {
|
||||
if !w.parent.followApplicationTheme || w.theme != SystemDefault {
|
||||
return
|
||||
}
|
||||
|
||||
InvokeAsync(func() {
|
||||
w.updateTheme(w32.IsCurrentlyDarkMode())
|
||||
})
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue