From 311dde474c0595a4badc7f0cb3d6d194d5b16e18 Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Sun, 25 Sep 2022 21:17:15 +1000 Subject: [PATCH] [windows] refactor out main loop. Create new application struct. Refactor assethandler/assetserver signatures. --- v2/internal/app/app.go | 8 ++ v2/internal/app/app_dev.go | 2 + v2/internal/app/app_production.go | 2 + .../frontend/assetserver/assethandler.go | 6 +- .../frontend/assetserver/assetserver.go | 6 +- .../frontend/desktop/windows/frontend.go | 15 +++- v2/internal/frontend/desktop/windows/theme.go | 2 +- .../frontend/desktop/windows/window.go | 15 ++-- v2/internal/frontend/frontend.go | 4 +- v2/pkg/application/application.go | 75 +++++++++++++++++++ v2/{ => pkg/application}/init.go | 4 +- v2/{ => pkg/application}/init_windows.go | 7 +- v2/pkg/options/options.go | 4 +- v2/wails.go | 36 +-------- 14 files changed, 123 insertions(+), 63 deletions(-) create mode 100644 v2/pkg/application/application.go rename v2/{ => pkg/application}/init.go (51%) rename v2/{ => pkg/application}/init_windows.go (72%) diff --git a/v2/internal/app/app.go b/v2/internal/app/app.go index 7853f3e3a..f2821aaba 100644 --- a/v2/internal/app/app.go +++ b/v2/internal/app/app.go @@ -5,6 +5,7 @@ import ( "github.com/wailsapp/wails/v2/internal/frontend" "github.com/wailsapp/wails/v2/internal/logger" "github.com/wailsapp/wails/v2/internal/menumanager" + "github.com/wailsapp/wails/v2/pkg/menu" "github.com/wailsapp/wails/v2/pkg/options" ) @@ -31,3 +32,10 @@ func (a *App) Shutdown() { a.frontend.Quit() } } + +// SetApplicationMenu sets the application menu +func (a *App) SetApplicationMenu(menu *menu.Menu) { + if a.frontend != nil { + a.frontend.MenuSetApplicationMenu(menu) + } +} diff --git a/v2/internal/app/app_dev.go b/v2/internal/app/app_dev.go index b61876213..52bc11011 100644 --- a/v2/internal/app/app_dev.go +++ b/v2/internal/app/app_dev.go @@ -27,6 +27,8 @@ import ( func (a *App) Run() error { err := a.frontend.Run(a.ctx) + a.frontend.RunMainLoop() + a.frontend.WindowClose() if a.shutdownCallback != nil { a.shutdownCallback(a.ctx) } diff --git a/v2/internal/app/app_production.go b/v2/internal/app/app_production.go index f33149e26..245d375ce 100644 --- a/v2/internal/app/app_production.go +++ b/v2/internal/app/app_production.go @@ -16,6 +16,8 @@ import ( func (a *App) Run() error { err := a.frontend.Run(a.ctx) + a.frontend.RunMainLoop() + a.frontend.WindowClose() if a.shutdownCallback != nil { a.shutdownCallback(a.ctx) } diff --git a/v2/internal/frontend/assetserver/assethandler.go b/v2/internal/frontend/assetserver/assethandler.go index 254f88e2c..eef09779e 100644 --- a/v2/internal/frontend/assetserver/assethandler.go +++ b/v2/internal/frontend/assetserver/assethandler.go @@ -14,7 +14,6 @@ import ( "github.com/wailsapp/wails/v2/internal/fs" "github.com/wailsapp/wails/v2/internal/logger" - "github.com/wailsapp/wails/v2/pkg/options" ) //go:embed defaultindex.html @@ -33,8 +32,7 @@ type assetHandler struct { retryMissingFiles bool } -func NewAssetHandler(ctx context.Context, options *options.App) (http.Handler, error) { - vfs := options.Assets +func NewAssetHandler(ctx context.Context, vfs iofs.FS, AssetsHandler http.Handler) (http.Handler, error) { if vfs != nil { if _, err := vfs.Open("."); err != nil { return nil, err @@ -53,7 +51,7 @@ func NewAssetHandler(ctx context.Context, options *options.App) (http.Handler, e result := &assetHandler{ fs: vfs, - handler: options.AssetsHandler, + handler: AssetsHandler, } if _logger := ctx.Value("logger"); _logger != nil { diff --git a/v2/internal/frontend/assetserver/assetserver.go b/v2/internal/frontend/assetserver/assetserver.go index fb47f881d..d35c5a8f6 100644 --- a/v2/internal/frontend/assetserver/assetserver.go +++ b/v2/internal/frontend/assetserver/assetserver.go @@ -4,13 +4,13 @@ import ( "bytes" "context" "fmt" + iofs "io/fs" "net/http" "net/http/httptest" "strconv" "github.com/wailsapp/wails/v2/internal/frontend/runtime" "github.com/wailsapp/wails/v2/internal/logger" - "github.com/wailsapp/wails/v2/pkg/options" "golang.org/x/net/html" ) @@ -31,8 +31,8 @@ type AssetServer struct { appendSpinnerToBody bool } -func NewAssetServer(ctx context.Context, options *options.App, bindingsJSON string) (*AssetServer, error) { - handler, err := NewAssetHandler(ctx, options) +func NewAssetServer(ctx context.Context, vfs iofs.FS, AssetsHandler http.Handler, bindingsJSON string) (*AssetServer, error) { + handler, err := NewAssetHandler(ctx, vfs, AssetsHandler) if err != nil { return nil, err } diff --git a/v2/internal/frontend/desktop/windows/frontend.go b/v2/internal/frontend/desktop/windows/frontend.go index a5d13f4c5..59c3dcbdb 100644 --- a/v2/internal/frontend/desktop/windows/frontend.go +++ b/v2/internal/frontend/desktop/windows/frontend.go @@ -102,7 +102,7 @@ func NewFrontend(ctx context.Context, appoptions *options.App, myLogger *logger. appBindings.DB().UpdateObfuscatedCallMap() } - assets, err := assetserver.NewAssetServer(ctx, appoptions, bindings) + assets, err := assetserver.NewAssetServer(ctx, appoptions.Assets, appoptions.AssetsHandler, bindings) if err != nil { log.Fatal(err) } @@ -180,11 +180,20 @@ func (f *Frontend) Run(ctx context.Context) error { f.frontendOptions.OnStartup(f.ctx) } }() - mainWindow.Run() - mainWindow.Close() + mainWindow.UpdateTheme() return nil } +func (f *Frontend) WindowClose() { + if f.mainWindow != nil { + f.mainWindow.Close() + } +} + +func (f *Frontend) RunMainLoop() { + _ = winc.RunMainLoop() +} + func (f *Frontend) WindowCenter() { runtime.LockOSThread() defer runtime.UnlockOSThread() diff --git a/v2/internal/frontend/desktop/windows/theme.go b/v2/internal/frontend/desktop/windows/theme.go index 897133026..e22f0c6cd 100644 --- a/v2/internal/frontend/desktop/windows/theme.go +++ b/v2/internal/frontend/desktop/windows/theme.go @@ -5,7 +5,7 @@ import ( "github.com/wailsapp/wails/v2/pkg/options/windows" ) -func (w *Window) updateTheme() { +func (w *Window) UpdateTheme() { // Don't redraw theme if nothing has changed if !w.themeChanged { diff --git a/v2/internal/frontend/desktop/windows/window.go b/v2/internal/frontend/desktop/windows/window.go index 1b511d34f..03c8807ce 100644 --- a/v2/internal/frontend/desktop/windows/window.go +++ b/v2/internal/frontend/desktop/windows/window.go @@ -99,7 +99,7 @@ func NewWindow(parent winc.Controller, appoptions *options.App, versionInfo *ope result.SetMaxSize(appoptions.MaxWidth, appoptions.MaxHeight) } - result.updateTheme() + result.UpdateTheme() if appoptions.Windows != nil { result.OnSuspend = appoptions.Windows.OnSuspend @@ -129,11 +129,6 @@ func NewWindow(parent winc.Controller, appoptions *options.App, versionInfo *ope return result } -func (w *Window) Run() int { - w.updateTheme() - return winc.RunMainLoop() -} - func (w *Window) Fullscreen() { w.Form.SetMaxSize(0, 0) w.Form.SetMinSize(0, 0) @@ -190,7 +185,7 @@ func (w *Window) WndProc(msg uint32, wparam, lparam uintptr) uintptr { settingChanged := w32.UTF16PtrToString((*uint16)(unsafe.Pointer(lparam))) if settingChanged == "ImmersiveColorSet" { w.themeChanged = true - w.updateTheme() + w.UpdateTheme() } return 0 case w32.WM_NCLBUTTONDOWN: @@ -204,10 +199,10 @@ func (w *Window) WndProc(msg uint32, wparam, lparam uintptr) uintptr { w.themeChanged = true if int(wparam) == w32.WA_INACTIVE { w.isActive = false - w.updateTheme() + w.UpdateTheme() } else { w.isActive = true - w.updateTheme() + w.UpdateTheme() //} } @@ -303,6 +298,6 @@ func (w *Window) SetTheme(theme winoptions.Theme) { w.theme = theme w.themeChanged = true w.Invoke(func() { - w.updateTheme() + w.UpdateTheme() }) } diff --git a/v2/internal/frontend/frontend.go b/v2/internal/frontend/frontend.go index 1d178c4ce..74ff93153 100644 --- a/v2/internal/frontend/frontend.go +++ b/v2/internal/frontend/frontend.go @@ -10,7 +10,7 @@ import ( // FileFilter defines a filter for dialog boxes type FileFilter struct { DisplayName string // Filter information EG: "Image Files (*.jpg, *.png)" - Pattern string // semi-colon separated list of extensions, EG: "*.jpg;*.png" + Pattern string // semicolon separated list of extensions, EG: "*.jpg;*.png" } // OpenDialogOptions contains the options for the OpenDialogOptions runtime method @@ -65,6 +65,7 @@ type MessageDialogOptions struct { type Frontend interface { Run(context.Context) error + RunMainLoop() Hide() Show() Quit() @@ -105,6 +106,7 @@ type Frontend interface { WindowIsMinimised() bool WindowIsNormal() bool WindowIsFullscreen() bool + WindowClose() //Screen ScreenGetAll() ([]Screen, error) diff --git a/v2/pkg/application/application.go b/v2/pkg/application/application.go new file mode 100644 index 000000000..205ef6bfb --- /dev/null +++ b/v2/pkg/application/application.go @@ -0,0 +1,75 @@ +package application + +import ( + "github.com/wailsapp/wails/v2/internal/app" + "github.com/wailsapp/wails/v2/internal/signal" + "github.com/wailsapp/wails/v2/pkg/menu" + "github.com/wailsapp/wails/v2/pkg/options" +) + +// Application is the main Wails application +type Application struct { + application *app.App + options *options.App + + // running flag + running bool +} + +// NewWithOptions creates a new Application with the given options +func NewWithOptions(options *options.App) *Application { + if options == nil { + return New() + } + return &Application{ + options: options, + } +} + +// New creates a new Application with the default options +func New() *Application { + return &Application{ + options: &options.App{}, + } +} + +// SetApplicationMenu sets the application menu +func (a *Application) SetApplicationMenu(appMenu *menu.Menu) { + if a.running { + a.application.SetApplicationMenu(appMenu) + return + } + + a.options.Menu = appMenu +} + +// Run starts the application +func (a *Application) Run() error { + + err := applicationInit() + if err != nil { + return err + } + + application, err := app.CreateApp(a.options) + if err != nil { + return err + } + + a.application = application + + // Control-C handlers + signal.OnShutdown(func() { + a.application.Shutdown() + }) + signal.Start() + + a.running = true + + return a.application.Run() +} + +// Quit will shut down the application +func (a *Application) Quit() { + a.application.Shutdown() +} diff --git a/v2/init.go b/v2/pkg/application/init.go similarity index 51% rename from v2/init.go rename to v2/pkg/application/init.go index d6652f014..0fc48cb05 100644 --- a/v2/init.go +++ b/v2/pkg/application/init.go @@ -1,8 +1,8 @@ //go:build !windows // +build !windows -package wails +package application -func Init() error { +func applicationInit() error { return nil } diff --git a/v2/init_windows.go b/v2/pkg/application/init_windows.go similarity index 72% rename from v2/init_windows.go rename to v2/pkg/application/init_windows.go index 173da0a89..7d2900d3d 100644 --- a/v2/init_windows.go +++ b/v2/pkg/application/init_windows.go @@ -1,12 +1,13 @@ -package wails +//go:build windows + +package application import ( "fmt" "syscall" ) -// Init is called at the start of the application -func Init() error { +func applicationInit() error { status, r, err := syscall.NewLazyDLL("user32.dll").NewProc("SetProcessDPIAware").Call() if status == 0 { return fmt.Errorf("exit status %d: %v %v", status, r, err) diff --git a/v2/pkg/options/options.go b/v2/pkg/options/options.go index 1f0a3532b..25f619b6b 100644 --- a/v2/pkg/options/options.go +++ b/v2/pkg/options/options.go @@ -47,9 +47,7 @@ type App struct { AlwaysOnTop bool // BackgroundColour is the background colour of the window // You can use the options.NewRGB and options.NewRGBA functions to create a new colour - BackgroundColour *RGBA - // RGBA is deprecated. Please use BackgroundColour - RGBA *RGBA + BackgroundColour *RGBA Assets fs.FS AssetsHandler http.Handler Menu *menu.Menu diff --git a/v2/wails.go b/v2/wails.go index 45334552a..54be64ca2 100644 --- a/v2/wails.go +++ b/v2/wails.go @@ -3,43 +3,13 @@ package wails import ( - "github.com/wailsapp/wails/v2/internal/app" _ "github.com/wailsapp/wails/v2/internal/goversion" // Add Compile-Time version check for minimum go version - "github.com/wailsapp/wails/v2/internal/signal" + "github.com/wailsapp/wails/v2/pkg/application" "github.com/wailsapp/wails/v2/pkg/options" ) -// This is the global application instance -var application *app.App - // Run creates an application based on the given config and executes it func Run(options *options.App) error { - - if options.RGBA != nil { - println("---- WARNING ----") - println("The `RGBA` option has been deprecated. Please use `BackgroundColour`.") - - if options.BackgroundColour == nil { - options.BackgroundColour = options.RGBA - } - } - - // Call an Init method manually - err := Init() - if err != nil { - return err - } - - application, err = app.CreateApp(options) - if err != nil { - return err - } - - signal.OnShutdown(func() { - application.Shutdown() - }) - - signal.Start() - - return application.Run() + mainApp := application.NewWithOptions(options) + return mainApp.Run() }