mirror of
https://github.com/wailsapp/wails.git
synced 2025-05-07 02:30:45 +08:00
[v3] Update application.On
and window.On
to return functions that unregister the listener. WebviewWindow.onApplicationEvent
is a helper which will manage the unregistering for you on window destroy.
This commit is contained in:
parent
178ea9c8c5
commit
f08ae2fc62
@ -1,6 +1,7 @@
|
|||||||
package application
|
package application
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/samber/lo"
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
@ -23,6 +24,10 @@ func init() {
|
|||||||
runtime.LockOSThread()
|
runtime.LockOSThread()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type EventListener struct {
|
||||||
|
callback func()
|
||||||
|
}
|
||||||
|
|
||||||
func New(appOptions Options) *App {
|
func New(appOptions Options) *App {
|
||||||
if globalApplication != nil {
|
if globalApplication != nil {
|
||||||
return globalApplication
|
return globalApplication
|
||||||
@ -32,7 +37,7 @@ func New(appOptions Options) *App {
|
|||||||
|
|
||||||
result := &App{
|
result := &App{
|
||||||
options: appOptions,
|
options: appOptions,
|
||||||
applicationEventListeners: make(map[uint][]func()),
|
applicationEventListeners: make(map[uint][]*EventListener),
|
||||||
systemTrays: make(map[uint]*SystemTray),
|
systemTrays: make(map[uint]*SystemTray),
|
||||||
log: logger.New(appOptions.Logger.CustomLoggers...),
|
log: logger.New(appOptions.Logger.CustomLoggers...),
|
||||||
contextMenus: make(map[string]*Menu),
|
contextMenus: make(map[string]*Menu),
|
||||||
@ -155,7 +160,7 @@ var webviewRequests = make(chan *webViewAssetRequest)
|
|||||||
|
|
||||||
type App struct {
|
type App struct {
|
||||||
options Options
|
options Options
|
||||||
applicationEventListeners map[uint][]func()
|
applicationEventListeners map[uint][]*EventListener
|
||||||
applicationEventListenersLock sync.RWMutex
|
applicationEventListenersLock sync.RWMutex
|
||||||
|
|
||||||
// Windows
|
// Windows
|
||||||
@ -216,14 +221,25 @@ func (a *App) deleteWindowByID(id uint) {
|
|||||||
delete(a.windows, id)
|
delete(a.windows, id)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *App) On(eventType events.ApplicationEventType, callback func()) {
|
func (a *App) On(eventType events.ApplicationEventType, callback func()) func() {
|
||||||
eventID := uint(eventType)
|
eventID := uint(eventType)
|
||||||
a.applicationEventListenersLock.Lock()
|
a.applicationEventListenersLock.Lock()
|
||||||
defer a.applicationEventListenersLock.Unlock()
|
defer a.applicationEventListenersLock.Unlock()
|
||||||
a.applicationEventListeners[eventID] = append(a.applicationEventListeners[eventID], callback)
|
listener := &EventListener{
|
||||||
|
callback: callback,
|
||||||
|
}
|
||||||
|
a.applicationEventListeners[eventID] = append(a.applicationEventListeners[eventID], listener)
|
||||||
if a.impl != nil {
|
if a.impl != nil {
|
||||||
go a.impl.on(eventID)
|
go a.impl.on(eventID)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return func() {
|
||||||
|
// lock the map
|
||||||
|
a.applicationEventListenersLock.Lock()
|
||||||
|
defer a.applicationEventListenersLock.Unlock()
|
||||||
|
// Remove listener
|
||||||
|
a.applicationEventListeners[eventID] = lo.Without(a.applicationEventListeners[eventID], listener)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
func (a *App) NewWebviewWindow() *WebviewWindow {
|
func (a *App) NewWebviewWindow() *WebviewWindow {
|
||||||
return a.NewWebviewWindowWithOptions(&WebviewWindowOptions{})
|
return a.NewWebviewWindowWithOptions(&WebviewWindowOptions{})
|
||||||
@ -383,7 +399,7 @@ func (a *App) handleApplicationEvent(event uint) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
for _, listener := range listeners {
|
for _, listener := range listeners {
|
||||||
go listener()
|
go listener.callback()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@ package application
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/samber/lo"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@ -61,17 +62,25 @@ type (
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type WindowEventListener struct {
|
||||||
|
callback func(ctx *WindowEventContext)
|
||||||
|
}
|
||||||
|
|
||||||
type WebviewWindow struct {
|
type WebviewWindow struct {
|
||||||
options *WebviewWindowOptions
|
options *WebviewWindowOptions
|
||||||
impl webviewWindowImpl
|
impl webviewWindowImpl
|
||||||
implLock sync.RWMutex
|
implLock sync.RWMutex
|
||||||
id uint
|
id uint
|
||||||
|
|
||||||
eventListeners map[uint][]func(ctx *WindowEventContext)
|
eventListeners map[uint][]*WindowEventListener
|
||||||
eventListenersLock sync.RWMutex
|
eventListenersLock sync.RWMutex
|
||||||
|
|
||||||
contextMenus map[string]*Menu
|
contextMenus map[string]*Menu
|
||||||
contextMenusLock sync.RWMutex
|
contextMenusLock sync.RWMutex
|
||||||
|
|
||||||
|
// A map of listener cancellation functions
|
||||||
|
cancellersLock sync.RWMutex
|
||||||
|
cancellers []func()
|
||||||
}
|
}
|
||||||
|
|
||||||
var windowID uint
|
var windowID uint
|
||||||
@ -84,6 +93,13 @@ func getWindowID() uint {
|
|||||||
return windowID
|
return windowID
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Use onApplicationEvent to register a callback for an application event from a window.
|
||||||
|
// This will handle tidying up the callback when the window is destroyed
|
||||||
|
func (w *WebviewWindow) onApplicationEvent(eventType events.ApplicationEventType, callback func()) {
|
||||||
|
cancelFn := globalApplication.On(eventType, callback)
|
||||||
|
w.addCancellationFunction(cancelFn)
|
||||||
|
}
|
||||||
|
|
||||||
func NewWindow(options *WebviewWindowOptions) *WebviewWindow {
|
func NewWindow(options *WebviewWindowOptions) *WebviewWindow {
|
||||||
if options.Width == 0 {
|
if options.Width == 0 {
|
||||||
options.Width = 800
|
options.Width = 800
|
||||||
@ -98,13 +114,19 @@ func NewWindow(options *WebviewWindowOptions) *WebviewWindow {
|
|||||||
result := &WebviewWindow{
|
result := &WebviewWindow{
|
||||||
id: getWindowID(),
|
id: getWindowID(),
|
||||||
options: options,
|
options: options,
|
||||||
eventListeners: make(map[uint][]func(ctx *WindowEventContext)),
|
eventListeners: make(map[uint][]*WindowEventListener),
|
||||||
contextMenus: make(map[string]*Menu),
|
contextMenus: make(map[string]*Menu),
|
||||||
}
|
}
|
||||||
|
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (w *WebviewWindow) addCancellationFunction(canceller func()) {
|
||||||
|
w.cancellersLock.Lock()
|
||||||
|
defer w.cancellersLock.Unlock()
|
||||||
|
w.cancellers = append(w.cancellers, canceller)
|
||||||
|
}
|
||||||
|
|
||||||
func (w *WebviewWindow) SetTitle(title string) *WebviewWindow {
|
func (w *WebviewWindow) SetTitle(title string) *WebviewWindow {
|
||||||
w.implLock.RLock()
|
w.implLock.RLock()
|
||||||
defer w.implLock.RUnlock()
|
defer w.implLock.RUnlock()
|
||||||
@ -371,20 +393,30 @@ func (w *WebviewWindow) Center() {
|
|||||||
w.impl.center()
|
w.impl.center()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *WebviewWindow) On(eventType events.WindowEventType, callback func(ctx *WindowEventContext)) {
|
func (w *WebviewWindow) On(eventType events.WindowEventType, callback func(ctx *WindowEventContext)) func() {
|
||||||
eventID := uint(eventType)
|
eventID := uint(eventType)
|
||||||
w.eventListenersLock.Lock()
|
w.eventListenersLock.Lock()
|
||||||
defer w.eventListenersLock.Unlock()
|
defer w.eventListenersLock.Unlock()
|
||||||
w.eventListeners[eventID] = append(w.eventListeners[eventID], callback)
|
windowEventListener := &WindowEventListener{
|
||||||
|
callback: callback,
|
||||||
|
}
|
||||||
|
w.eventListeners[eventID] = append(w.eventListeners[eventID], windowEventListener)
|
||||||
if w.impl != nil {
|
if w.impl != nil {
|
||||||
w.impl.on(eventID)
|
w.impl.on(eventID)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return func() {
|
||||||
|
w.eventListenersLock.Lock()
|
||||||
|
defer w.eventListenersLock.Unlock()
|
||||||
|
w.eventListeners[eventID] = lo.Without(w.eventListeners[eventID], windowEventListener)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *WebviewWindow) handleWindowEvent(id uint) {
|
func (w *WebviewWindow) handleWindowEvent(id uint) {
|
||||||
w.eventListenersLock.RLock()
|
w.eventListenersLock.RLock()
|
||||||
for _, callback := range w.eventListeners[id] {
|
for _, listener := range w.eventListeners[id] {
|
||||||
go callback(blankWindowEventContext)
|
go listener.callback(blankWindowEventContext)
|
||||||
}
|
}
|
||||||
w.eventListenersLock.RUnlock()
|
w.eventListenersLock.RUnlock()
|
||||||
}
|
}
|
||||||
@ -416,6 +448,10 @@ func (w *WebviewWindow) Destroy() {
|
|||||||
if w.impl == nil {
|
if w.impl == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
// Cancel the callbacks
|
||||||
|
for _, cancelFunc := range w.cancellers {
|
||||||
|
cancelFunc()
|
||||||
|
}
|
||||||
w.impl.destroy()
|
w.impl.destroy()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -631,7 +667,7 @@ func (w *WebviewWindow) handleDragAndDropMessage(event *dragAndDropMessage) {
|
|||||||
ctx := newWindowEventContext()
|
ctx := newWindowEventContext()
|
||||||
ctx.setDroppedFiles(event.filenames)
|
ctx.setDroppedFiles(event.filenames)
|
||||||
for _, listener := range w.eventListeners[uint(events.FilesDropped)] {
|
for _, listener := range w.eventListeners[uint(events.FilesDropped)] {
|
||||||
listener(ctx)
|
listener.callback(ctx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -140,7 +140,8 @@ func (w *windowsWebviewWindow) _run() {
|
|||||||
switch options.Windows.Theme {
|
switch options.Windows.Theme {
|
||||||
case SystemDefault:
|
case SystemDefault:
|
||||||
w.updateTheme(w32.IsCurrentlyDarkMode())
|
w.updateTheme(w32.IsCurrentlyDarkMode())
|
||||||
globalApplication.On(events.Windows.SystemThemeChanged, func() {
|
// Setup a listener to respond to theme changes
|
||||||
|
w.parent.onApplicationEvent(events.Windows.SystemThemeChanged, func() {
|
||||||
w.updateTheme(w32.IsCurrentlyDarkMode())
|
w.updateTheme(w32.IsCurrentlyDarkMode())
|
||||||
})
|
})
|
||||||
case Light:
|
case Light:
|
||||||
|
Loading…
Reference in New Issue
Block a user