2024-05-14 22:34:41 +02:00
|
|
|
// Copyright 2024, Command Line Inc.
|
|
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
|
|
|
|
package eventbus
|
|
|
|
|
|
|
|
import (
|
|
|
|
"errors"
|
2024-05-28 00:44:57 +02:00
|
|
|
"fmt"
|
2024-05-14 22:34:41 +02:00
|
|
|
"log"
|
|
|
|
"runtime/debug"
|
|
|
|
"sync"
|
|
|
|
|
|
|
|
"github.com/wailsapp/wails/v3/pkg/application"
|
2024-05-28 00:44:57 +02:00
|
|
|
"github.com/wavetermdev/thenextwave/pkg/waveobj"
|
2024-05-14 22:34:41 +02:00
|
|
|
)
|
|
|
|
|
|
|
|
const EventBufferSize = 50
|
|
|
|
|
|
|
|
var EventCh chan application.WailsEvent = make(chan application.WailsEvent, EventBufferSize)
|
|
|
|
var WindowEventCh chan WindowEvent = make(chan WindowEvent, EventBufferSize)
|
|
|
|
var shutdownCh chan struct{} = make(chan struct{})
|
|
|
|
var ErrQueueFull = errors.New("event queue full")
|
|
|
|
|
|
|
|
type WindowEvent struct {
|
|
|
|
WindowId uint
|
|
|
|
Event application.WailsEvent
|
|
|
|
}
|
|
|
|
|
2024-05-28 00:44:57 +02:00
|
|
|
type WindowWatchData struct {
|
|
|
|
Window *application.WebviewWindow
|
|
|
|
WaveWindowId string
|
|
|
|
WailsWindowId uint
|
|
|
|
WatchedORefs map[waveobj.ORef]bool
|
|
|
|
}
|
|
|
|
|
2024-05-14 22:34:41 +02:00
|
|
|
var globalLock = &sync.Mutex{}
|
|
|
|
var wailsApp *application.App
|
2024-05-28 00:44:57 +02:00
|
|
|
var wailsWindowMap = make(map[uint]*WindowWatchData)
|
2024-05-14 22:34:41 +02:00
|
|
|
|
|
|
|
func Start() {
|
|
|
|
go processEvents()
|
|
|
|
}
|
|
|
|
|
|
|
|
func Shutdown() {
|
|
|
|
close(shutdownCh)
|
|
|
|
}
|
|
|
|
|
|
|
|
func RegisterWailsApp(app *application.App) {
|
|
|
|
globalLock.Lock()
|
|
|
|
defer globalLock.Unlock()
|
|
|
|
wailsApp = app
|
|
|
|
}
|
|
|
|
|
2024-05-28 00:44:57 +02:00
|
|
|
func RegisterWailsWindow(window *application.WebviewWindow, windowId string) {
|
2024-05-14 22:34:41 +02:00
|
|
|
globalLock.Lock()
|
|
|
|
defer globalLock.Unlock()
|
2024-05-28 00:44:57 +02:00
|
|
|
if _, found := wailsWindowMap[window.ID()]; found {
|
|
|
|
panic(fmt.Errorf("wails window already registered with eventbus: %d", window.ID()))
|
|
|
|
}
|
|
|
|
wailsWindowMap[window.ID()] = &WindowWatchData{
|
|
|
|
Window: window,
|
|
|
|
WailsWindowId: window.ID(),
|
|
|
|
WaveWindowId: "",
|
|
|
|
WatchedORefs: make(map[waveobj.ORef]bool),
|
|
|
|
}
|
2024-05-14 22:34:41 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
func UnregisterWailsWindow(windowId uint) {
|
|
|
|
globalLock.Lock()
|
|
|
|
defer globalLock.Unlock()
|
|
|
|
delete(wailsWindowMap, windowId)
|
|
|
|
}
|
|
|
|
|
|
|
|
func emitEventToWindow(event WindowEvent) {
|
|
|
|
globalLock.Lock()
|
2024-05-28 00:44:57 +02:00
|
|
|
wdata := wailsWindowMap[event.WindowId]
|
2024-05-14 22:34:41 +02:00
|
|
|
globalLock.Unlock()
|
2024-05-28 00:44:57 +02:00
|
|
|
if wdata != nil {
|
|
|
|
wdata.Window.DispatchWailsEvent(&event.Event)
|
2024-05-14 22:34:41 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-05-16 21:39:14 +02:00
|
|
|
func emitEventToAllWindows(event *application.WailsEvent) {
|
|
|
|
globalLock.Lock()
|
|
|
|
wins := make([]*application.WebviewWindow, 0, len(wailsWindowMap))
|
2024-05-28 00:44:57 +02:00
|
|
|
for _, wdata := range wailsWindowMap {
|
|
|
|
wins = append(wins, wdata.Window)
|
2024-05-16 21:39:14 +02:00
|
|
|
}
|
|
|
|
globalLock.Unlock()
|
|
|
|
for _, window := range wins {
|
|
|
|
window.DispatchWailsEvent(event)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-05-14 22:34:41 +02:00
|
|
|
func SendEvent(event application.WailsEvent) {
|
|
|
|
EventCh <- event
|
|
|
|
}
|
|
|
|
|
2024-05-28 00:44:57 +02:00
|
|
|
func findWindowIdsByORef(oref waveobj.ORef) []uint {
|
|
|
|
globalLock.Lock()
|
|
|
|
defer globalLock.Unlock()
|
|
|
|
var ids []uint
|
|
|
|
for _, wdata := range wailsWindowMap {
|
|
|
|
if wdata.WatchedORefs[oref] {
|
|
|
|
ids = append(ids, wdata.WailsWindowId)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return ids
|
|
|
|
}
|
|
|
|
|
|
|
|
func SendORefEvent(oref waveobj.ORef, event application.WailsEvent) {
|
|
|
|
wins := findWindowIdsByORef(oref)
|
|
|
|
for _, windowId := range wins {
|
|
|
|
SendWindowEvent(windowId, event)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-05-14 22:34:41 +02:00
|
|
|
func SendEventNonBlocking(event application.WailsEvent) error {
|
|
|
|
select {
|
|
|
|
case EventCh <- event:
|
|
|
|
return nil
|
|
|
|
default:
|
|
|
|
return ErrQueueFull
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func SendWindowEvent(windowId uint, event application.WailsEvent) {
|
|
|
|
WindowEventCh <- WindowEvent{
|
|
|
|
WindowId: windowId,
|
|
|
|
Event: event,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func SendWindowEventNonBlocking(windowId uint, event application.WailsEvent) error {
|
|
|
|
select {
|
|
|
|
case WindowEventCh <- WindowEvent{
|
|
|
|
WindowId: windowId,
|
|
|
|
Event: event,
|
|
|
|
}:
|
|
|
|
return nil
|
|
|
|
default:
|
|
|
|
return ErrQueueFull
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func processEvents() {
|
|
|
|
defer func() {
|
|
|
|
if r := recover(); r != nil {
|
|
|
|
log.Printf("eventbus panic: %v\n", r)
|
|
|
|
debug.PrintStack()
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
|
|
|
|
log.Printf("eventbus starting\n")
|
|
|
|
for {
|
|
|
|
select {
|
|
|
|
case event := <-EventCh:
|
2024-05-16 21:39:14 +02:00
|
|
|
emitEventToAllWindows(&event)
|
2024-05-14 22:34:41 +02:00
|
|
|
case windowEvent := <-WindowEventCh:
|
|
|
|
emitEventToWindow(windowEvent)
|
|
|
|
|
|
|
|
case <-shutdownCh:
|
|
|
|
log.Printf("eventbus shutting down\n")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|