mirror of
https://github.com/wavetermdev/wails.git
synced 2026-08-05 13:53:43 -07:00
Improve Linux application events and refactor app method receivers
This commit includes the addition of common events for the Linux platform. Refactored and standardized the method receivers for the application from 'm' to 'l'. Also, the application startup events in the window example have been updated according to the new naming scheme.
This commit is contained in:
committed by
Travis McLane
parent
bfa53dfd6c
commit
05b16f1d63
@@ -3,6 +3,7 @@
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Title</title>
|
||||
<script src="runtime.js"></script>
|
||||
<style>body{ text-align: center; color: white; background-color: #191919; user-select: none; -ms-user-select: none; -webkit-user-select: none; }</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
@@ -24,7 +24,7 @@ func main() {
|
||||
ApplicationShouldTerminateAfterLastWindowClosed: false,
|
||||
},
|
||||
})
|
||||
app.On(events.Mac.ApplicationDidFinishLaunching, func(event *application.Event) {
|
||||
app.On(events.Common.ApplicationStarted, func(event *application.Event) {
|
||||
log.Println("ApplicationDidFinishLaunching")
|
||||
})
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ type linuxApp struct {
|
||||
theme string
|
||||
}
|
||||
|
||||
func (m *linuxApp) GetFlags(options Options) map[string]any {
|
||||
func (l *linuxApp) GetFlags(options Options) map[string]any {
|
||||
if options.Flags == nil {
|
||||
options.Flags = make(map[string]any)
|
||||
}
|
||||
@@ -46,30 +46,30 @@ func getNativeApplication() *linuxApp {
|
||||
return globalApplication.impl.(*linuxApp)
|
||||
}
|
||||
|
||||
func (m *linuxApp) hide() {
|
||||
hideAllWindows(m.application)
|
||||
func (l *linuxApp) hide() {
|
||||
hideAllWindows(l.application)
|
||||
}
|
||||
|
||||
func (m *linuxApp) show() {
|
||||
showAllWindows(m.application)
|
||||
func (l *linuxApp) show() {
|
||||
showAllWindows(l.application)
|
||||
}
|
||||
|
||||
func (m *linuxApp) on(eventID uint) {
|
||||
func (l *linuxApp) on(eventID uint) {
|
||||
// TODO: What do we need to do here?
|
||||
log.Println("linuxApp.on()", eventID)
|
||||
}
|
||||
|
||||
func (m *linuxApp) setIcon(icon []byte) {
|
||||
func (l *linuxApp) setIcon(icon []byte) {
|
||||
|
||||
log.Println("linuxApp.setIcon", "not implemented")
|
||||
}
|
||||
|
||||
func (m *linuxApp) name() string {
|
||||
func (l *linuxApp) name() string {
|
||||
return appName()
|
||||
}
|
||||
|
||||
func (m *linuxApp) getCurrentWindowID() uint {
|
||||
return getCurrentWindowID(m.application, m.windows)
|
||||
func (l *linuxApp) getCurrentWindowID() uint {
|
||||
return getCurrentWindowID(l.application, l.windows)
|
||||
}
|
||||
|
||||
type rnr struct {
|
||||
@@ -80,9 +80,9 @@ func (r rnr) run() {
|
||||
r.f()
|
||||
}
|
||||
|
||||
func (m *linuxApp) getApplicationMenu() pointer {
|
||||
if m.applicationMenu != nilPointer {
|
||||
return m.applicationMenu
|
||||
func (l *linuxApp) getApplicationMenu() pointer {
|
||||
if l.applicationMenu != nilPointer {
|
||||
return l.applicationMenu
|
||||
}
|
||||
|
||||
menu := globalApplication.ApplicationMenu
|
||||
@@ -90,12 +90,12 @@ func (m *linuxApp) getApplicationMenu() pointer {
|
||||
InvokeSync(func() {
|
||||
menu.Update()
|
||||
})
|
||||
m.applicationMenu = (menu.impl).(*linuxMenu).native
|
||||
l.applicationMenu = (menu.impl).(*linuxMenu).native
|
||||
}
|
||||
return m.applicationMenu
|
||||
return l.applicationMenu
|
||||
}
|
||||
|
||||
func (m *linuxApp) setApplicationMenu(menu *Menu) {
|
||||
func (l *linuxApp) setApplicationMenu(menu *Menu) {
|
||||
// FIXME: How do we avoid putting a menu?
|
||||
if menu == nil {
|
||||
// Create a default menu
|
||||
@@ -104,46 +104,44 @@ func (m *linuxApp) setApplicationMenu(menu *Menu) {
|
||||
}
|
||||
}
|
||||
|
||||
func (m *linuxApp) run() error {
|
||||
func (l *linuxApp) run() error {
|
||||
|
||||
// Add a hook to the ApplicationDidFinishLaunching event
|
||||
// FIXME: add Wails specific events - i.e. Shouldn't platform specific ones be translated to Wails events?
|
||||
m.parent.On(events.Mac.ApplicationDidFinishLaunching, func(evt *Event) {
|
||||
// Do we need to do anything now?
|
||||
fmt.Println("events.Mac.ApplicationDidFinishLaunching received!")
|
||||
l.parent.On(events.Linux.ApplicationStartup, func(evt *Event) {
|
||||
fmt.Println("events.Linux.ApplicationStartup received!")
|
||||
})
|
||||
m.monitorThemeChanges()
|
||||
return appRun(m.application)
|
||||
l.setupCommonEvents()
|
||||
l.monitorThemeChanges()
|
||||
return appRun(l.application)
|
||||
}
|
||||
|
||||
func (m *linuxApp) destroy() {
|
||||
func (l *linuxApp) destroy() {
|
||||
if !globalApplication.shouldQuit() {
|
||||
return
|
||||
}
|
||||
globalApplication.cleanup()
|
||||
appDestroy(m.application)
|
||||
appDestroy(l.application)
|
||||
}
|
||||
|
||||
func (m *linuxApp) isOnMainThread() bool {
|
||||
func (l *linuxApp) isOnMainThread() bool {
|
||||
return isOnMainThread()
|
||||
}
|
||||
|
||||
// register our window to our parent mapping
|
||||
func (m *linuxApp) registerWindow(window pointer, id uint) {
|
||||
m.windowsLock.Lock()
|
||||
m.windows[windowPointer(window)] = id
|
||||
m.windowsLock.Unlock()
|
||||
func (l *linuxApp) registerWindow(window pointer, id uint) {
|
||||
l.windowsLock.Lock()
|
||||
l.windows[windowPointer(window)] = id
|
||||
l.windowsLock.Unlock()
|
||||
}
|
||||
|
||||
func (m *linuxApp) isDarkMode() bool {
|
||||
return strings.Contains(m.theme, "dark")
|
||||
func (l *linuxApp) isDarkMode() bool {
|
||||
return strings.Contains(l.theme, "dark")
|
||||
}
|
||||
|
||||
func (m *linuxApp) monitorThemeChanges() {
|
||||
func (l *linuxApp) monitorThemeChanges() {
|
||||
go func() {
|
||||
conn, err := dbus.ConnectSessionBus()
|
||||
if err != nil {
|
||||
m.parent.info("[WARNING] Failed to connect to session bus; monitoring for theme changes will not function:", err)
|
||||
l.parent.info("[WARNING] Failed to connect to session bus; monitoring for theme changes will not function:", err)
|
||||
return
|
||||
}
|
||||
defer conn.Close()
|
||||
@@ -176,10 +174,10 @@ func (m *linuxApp) monitorThemeChanges() {
|
||||
continue
|
||||
}
|
||||
|
||||
if theme != m.theme {
|
||||
m.theme = theme
|
||||
if theme != l.theme {
|
||||
l.theme = theme
|
||||
event := newApplicationEvent(events.Common.ThemeChanged)
|
||||
event.Context().setIsDarkMode(m.isDarkMode())
|
||||
event.Context().setIsDarkMode(l.isDarkMode())
|
||||
applicationEvents <- event
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package application
|
||||
|
||||
func (m *linuxApp) showAboutDialog(title string, message string, icon []byte) {
|
||||
window := globalApplication.getWindowForID(m.getCurrentWindowID())
|
||||
func (l *linuxApp) showAboutDialog(title string, message string, icon []byte) {
|
||||
window := globalApplication.getWindowForID(l.getCurrentWindowID())
|
||||
var parent uintptr
|
||||
if window != nil {
|
||||
parent, _ = window.(*WebviewWindow).NativeWindowHandle()
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
//go:build linux
|
||||
|
||||
package application
|
||||
|
||||
import "github.com/wailsapp/wails/v3/pkg/events"
|
||||
|
||||
var commonApplicationEventMap = map[events.ApplicationEventType]events.ApplicationEventType{
|
||||
events.Linux.ApplicationStartup: events.Common.ApplicationStarted,
|
||||
events.Linux.SystemThemeChanged: events.Common.ThemeChanged,
|
||||
}
|
||||
|
||||
func (l *linuxApp) setupCommonEvents() {
|
||||
for sourceEvent, targetEvent := range commonApplicationEventMap {
|
||||
sourceEvent := sourceEvent
|
||||
targetEvent := targetEvent
|
||||
l.parent.On(sourceEvent, func(event *Event) {
|
||||
event.Id = uint(targetEvent)
|
||||
applicationEvents <- event
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -206,7 +206,36 @@ func dispatchOnMainThreadCallback(callbackID C.uint) {
|
||||
|
||||
//export activateLinux
|
||||
func activateLinux(data pointer) {
|
||||
// NOOP: Callback for now
|
||||
processApplicationEvent(C.uint(events.Linux.ApplicationStartup), data)
|
||||
}
|
||||
|
||||
//export processApplicationEvent
|
||||
func processApplicationEvent(eventID C.uint, data pointer) {
|
||||
event := newApplicationEvent(events.ApplicationEventType(eventID))
|
||||
|
||||
//if data != nil {
|
||||
// dataCStrJSON := C.serializationNSDictionary(data)
|
||||
// if dataCStrJSON != nil {
|
||||
// defer C.free(unsafe.Pointer(dataCStrJSON))
|
||||
//
|
||||
// dataJSON := C.GoString(dataCStrJSON)
|
||||
// var result map[string]any
|
||||
// err := json.Unmarshal([]byte(dataJSON), &result)
|
||||
//
|
||||
// if err != nil {
|
||||
// panic(err)
|
||||
// }
|
||||
//
|
||||
// event.Context().setData(result)
|
||||
// }
|
||||
//}
|
||||
|
||||
switch event.Id {
|
||||
case uint(events.Linux.SystemThemeChanged):
|
||||
isDark := globalApplication.IsDarkMode()
|
||||
event.Context().setIsDarkMode(isDark)
|
||||
}
|
||||
applicationEvents <- event
|
||||
}
|
||||
|
||||
func isOnMainThread() bool {
|
||||
@@ -236,17 +265,12 @@ func appNew(name string) pointer {
|
||||
|
||||
func appRun(app pointer) error {
|
||||
application := (*C.GApplication)(app)
|
||||
//TODO: Only set this if we configure it to do so
|
||||
C.g_application_hold(application) // allows it to run without a window
|
||||
|
||||
signal := C.CString("activate")
|
||||
defer C.free(unsafe.Pointer(signal))
|
||||
C.g_signal_connect_data(
|
||||
C.gpointer(application),
|
||||
signal,
|
||||
C.GCallback(C.activateLinux),
|
||||
nil,
|
||||
nil,
|
||||
0)
|
||||
C.signal_connect(unsafe.Pointer(application), signal, C.activateLinux, nil)
|
||||
status := C.g_application_run(application, 0, nil)
|
||||
C.g_application_release(application)
|
||||
C.g_object_unref(C.gpointer(app))
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
package application
|
||||
|
||||
func (m *linuxApp) dispatchOnMainThread(id uint) {
|
||||
func (l *linuxApp) dispatchOnMainThread(id uint) {
|
||||
dispatchOnMainThread(id)
|
||||
}
|
||||
|
||||
|
||||
@@ -7,17 +7,17 @@ import (
|
||||
"sync"
|
||||
)
|
||||
|
||||
func (m *linuxApp) getPrimaryScreen() (*Screen, error) {
|
||||
func (l *linuxApp) getPrimaryScreen() (*Screen, error) {
|
||||
return nil, fmt.Errorf("not implemented")
|
||||
}
|
||||
|
||||
func (m *linuxApp) getScreens() ([]*Screen, error) {
|
||||
func (l *linuxApp) getScreens() ([]*Screen, error) {
|
||||
var wg sync.WaitGroup
|
||||
var screens []*Screen
|
||||
var err error
|
||||
wg.Add(1)
|
||||
InvokeSync(func() {
|
||||
screens, err = getScreens(m.application)
|
||||
screens, err = getScreens(l.application)
|
||||
wg.Done()
|
||||
})
|
||||
wg.Wait()
|
||||
|
||||
@@ -259,11 +259,12 @@ func (w *linuxWebviewWindow) setAlwaysOnTop(alwaysOnTop bool) {
|
||||
func newWindowImpl(parent *WebviewWindow) *linuxWebviewWindow {
|
||||
// (*C.struct__GtkWidget)(m.native)
|
||||
//var menubar *C.struct__GtkWidget
|
||||
return &linuxWebviewWindow{
|
||||
result := &linuxWebviewWindow{
|
||||
application: getNativeApplication().application,
|
||||
parent: parent,
|
||||
// menubar: menubar,
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func (w *linuxWebviewWindow) setTitle(title string) {
|
||||
@@ -405,9 +406,7 @@ func (w *linuxWebviewWindow) run() {
|
||||
}
|
||||
|
||||
w.setURL(startURL)
|
||||
// We need to wait for the HTML to load before we can execute the javascript
|
||||
// FIXME: What event is this? DomReady?
|
||||
w.parent.On(events.Mac.WebViewDidFinishNavigation, func(_ *WindowEvent) {
|
||||
w.parent.On(events.Linux.WindowLoadChanged, func(_ *WindowEvent) {
|
||||
if w.parent.options.JS != "" {
|
||||
w.execJS(w.parent.options.JS)
|
||||
}
|
||||
@@ -416,6 +415,9 @@ func (w *linuxWebviewWindow) run() {
|
||||
w.execJS(js)
|
||||
}
|
||||
})
|
||||
w.parent.On(events.Linux.WindowDeleteEvent, func(e *WindowEvent) {
|
||||
w.parent.emit(events.Common.WindowClosing)
|
||||
})
|
||||
w.parent.RegisterHook(events.Linux.WindowLoadChanged, func(e *WindowEvent) {
|
||||
w.execJS(runtime.Core())
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user