Files

256 lines
5.8 KiB
Go
Raw Permalink Normal View History

2023-06-15 13:53:22 -05:00
//go:build linux
package application
2024-03-19 20:36:52 +11:00
/*
#include "gtk/gtk.h"
#include "webkit2/webkit2.h"
static guint get_compiled_gtk_major_version() { return GTK_MAJOR_VERSION; }
static guint get_compiled_gtk_minor_version() { return GTK_MINOR_VERSION; }
static guint get_compiled_gtk_micro_version() { return GTK_MICRO_VERSION; }
static guint get_compiled_webkit_major_version() { return WEBKIT_MAJOR_VERSION; }
static guint get_compiled_webkit_minor_version() { return WEBKIT_MINOR_VERSION; }
static guint get_compiled_webkit_micro_version() { return WEBKIT_MICRO_VERSION; }
*/
import "C"
2023-06-15 13:53:22 -05:00
import (
2023-10-07 12:21:49 +11:00
"fmt"
2023-06-15 13:53:22 -05:00
"os"
"strings"
"sync"
2023-10-07 12:21:49 +11:00
"github.com/godbus/dbus/v5"
2023-11-01 10:53:31 -05:00
"github.com/wailsapp/wails/v3/internal/operatingsystem"
2023-10-07 12:21:49 +11:00
"github.com/wailsapp/wails/v3/pkg/events"
2023-06-15 13:53:22 -05:00
)
func init() {
// FIXME: This should be handled appropriately in the individual files most likely.
// Set GDK_BACKEND=x11 if currently unset and XDG_SESSION_TYPE is unset, unspecified or x11 to prevent warnings
_ = os.Setenv("GDK_BACKEND", "x11")
}
type linuxApp struct {
2024-02-06 21:14:51 +11:00
application pointer
parent *App
2023-06-15 13:53:22 -05:00
startupActions []func()
// Native -> uint
windowMap map[windowPointer]uint
windowMapLock sync.Mutex
theme string
icon pointer
2023-06-15 13:53:22 -05:00
}
2024-02-07 22:19:33 +11:00
func (a *linuxApp) GetFlags(options Options) map[string]any {
2023-06-15 13:53:22 -05:00
if options.Flags == nil {
options.Flags = make(map[string]any)
}
return options.Flags
}
func getNativeApplication() *linuxApp {
return globalApplication.impl.(*linuxApp)
}
2024-02-07 22:19:33 +11:00
func (a *linuxApp) hide() {
a.hideAllWindows()
2023-06-15 13:53:22 -05:00
}
2024-02-07 22:19:33 +11:00
func (a *linuxApp) show() {
a.showAllWindows()
2023-06-15 13:53:22 -05:00
}
2024-02-07 22:19:33 +11:00
func (a *linuxApp) on(eventID uint) {
2024-02-06 21:14:51 +11:00
// TODO: Test register/unregister events
//C.registerApplicationEvent(l.application, C.uint(eventID))
2023-06-15 13:53:22 -05:00
}
2024-02-07 22:19:33 +11:00
func (a *linuxApp) name() string {
2023-06-15 13:53:22 -05:00
return appName()
}
2023-09-11 17:08:19 -05:00
type rnr struct {
f func()
}
func (r rnr) run() {
r.f()
}
2024-02-07 22:19:33 +11:00
func (a *linuxApp) setApplicationMenu(menu *Menu) {
2023-09-11 17:08:19 -05:00
// FIXME: How do we avoid putting a menu?
2023-06-15 13:53:22 -05:00
if menu == nil {
// Create a default menu
menu = defaultApplicationMenu()
2023-09-11 17:08:19 -05:00
globalApplication.ApplicationMenu = menu
2023-06-15 13:53:22 -05:00
}
}
2024-02-07 22:19:33 +11:00
func (a *linuxApp) run() error {
2023-06-15 13:53:22 -05:00
2024-02-07 22:19:33 +11:00
a.parent.On(events.Linux.ApplicationStartup, func(evt *Event) {
fmt.Println("events.Linux.ApplicationStartup received!")
2023-10-07 12:21:49 +11:00
})
2024-02-07 22:19:33 +11:00
a.setupCommonEvents()
a.monitorThemeChanges()
return appRun(a.application)
2023-06-15 13:53:22 -05:00
}
2024-02-07 22:19:33 +11:00
func (a *linuxApp) unregisterWindow(w windowPointer) {
a.windowMapLock.Lock()
delete(a.windowMap, w)
a.windowMapLock.Unlock()
// If this was the last window...
2024-02-07 22:19:33 +11:00
if len(a.windowMap) == 0 && !a.parent.options.Linux.DisableQuitOnLastWindowClosed {
a.destroy()
}
}
2024-02-07 22:19:33 +11:00
func (a *linuxApp) destroy() {
2024-01-17 20:45:30 +11:00
if !globalApplication.shouldQuit() {
return
}
globalApplication.cleanup()
2024-02-07 22:19:33 +11:00
appDestroy(a.application)
2023-06-15 13:53:22 -05:00
}
2024-02-07 22:19:33 +11:00
func (a *linuxApp) isOnMainThread() bool {
2023-09-11 17:08:19 -05:00
return isOnMainThread()
2023-06-21 12:36:10 -05:00
}
2023-06-15 13:53:22 -05:00
// register our window to our parent mapping
2024-02-07 22:19:33 +11:00
func (a *linuxApp) registerWindow(window pointer, id uint) {
a.windowMapLock.Lock()
a.windowMap[windowPointer(window)] = id
a.windowMapLock.Unlock()
2023-06-15 13:53:22 -05:00
}
2024-02-07 22:19:33 +11:00
func (a *linuxApp) isDarkMode() bool {
return strings.Contains(a.theme, "dark")
}
2024-02-07 22:19:33 +11:00
func (a *linuxApp) monitorThemeChanges() {
go func() {
conn, err := dbus.ConnectSessionBus()
if err != nil {
2024-02-07 22:19:33 +11:00
a.parent.info("[WARNING] Failed to connect to session bus; monitoring for theme changes will not function:", err)
return
}
defer conn.Close()
if err = conn.AddMatchSignal(
dbus.WithMatchObjectPath("/org/freedesktop/portal/desktop"),
); err != nil {
panic(err)
}
c := make(chan *dbus.Signal, 10)
conn.Signal(c)
getTheme := func(body []interface{}) (string, bool) {
2023-11-08 22:38:04 -06:00
if len(body) < 2 {
return "", false
}
if body[0].(string) != "org.gnome.desktop.interface" {
return "", false
}
if body[1].(string) == "color-scheme" {
return body[2].(dbus.Variant).Value().(string), true
}
return "", false
}
for v := range c {
theme, ok := getTheme(v.Body)
if !ok {
continue
}
2024-02-07 22:19:33 +11:00
if theme != a.theme {
a.theme = theme
event := newApplicationEvent(events.Common.ThemeChanged)
2024-02-07 22:19:33 +11:00
event.Context().setIsDarkMode(a.isDarkMode())
applicationEvents <- event
}
}
}()
2023-08-18 15:12:34 -05:00
}
2023-06-15 13:53:22 -05:00
func newPlatformApp(parent *App) *linuxApp {
2024-02-26 21:39:01 +11:00
2023-06-15 13:53:22 -05:00
name := strings.ToLower(strings.Replace(parent.options.Name, " ", "", -1))
if name == "" {
name = "undefined"
}
app := &linuxApp{
parent: parent,
application: appNew(name),
windowMap: map[windowPointer]uint{},
2023-06-15 13:53:22 -05:00
}
2024-03-17 21:09:20 +11:00
if parent.options.Linux.ProgramName != "" {
setProgramName(parent.options.Linux.ProgramName)
}
2023-06-15 13:53:22 -05:00
return app
}
2023-11-01 10:53:31 -05:00
// logPlatformInfo logs the platform information to the console
func (a *App) logPlatformInfo() {
info, err := operatingsystem.Info()
if err != nil {
a.error("Error getting OS info", "error", err.Error())
return
}
wkVersion := operatingsystem.GetWebkitVersion()
platformInfo := info.AsLogSlice()
platformInfo = append(platformInfo, "Webkit2Gtk", wkVersion)
a.info("Platform Info:", platformInfo...)
2023-11-01 10:53:31 -05:00
}
//export processWindowEvent
func processWindowEvent(windowID C.uint, eventID C.uint) {
windowEvents <- &windowEvent{
WindowID: uint(windowID),
EventID: uint(eventID),
}
}
2024-03-19 20:36:52 +11:00
func buildVersionString(major, minor, micro C.uint) string {
return fmt.Sprintf("%d.%d.%d", uint(major), uint(minor), uint(micro))
}
func (a *App) platformEnvironment() map[string]any {
result := map[string]any{}
result["gtk3-compiled"] = buildVersionString(
C.get_compiled_gtk_major_version(),
C.get_compiled_gtk_minor_version(),
C.get_compiled_gtk_micro_version(),
)
result["gtk3-runtime"] = buildVersionString(
C.gtk_get_major_version(),
C.gtk_get_minor_version(),
C.gtk_get_micro_version(),
)
result["webkit2gtk-compiled"] = buildVersionString(
C.get_compiled_webkit_major_version(),
C.get_compiled_webkit_minor_version(),
C.get_compiled_webkit_micro_version(),
)
result["webkit2gtk-runtime"] = buildVersionString(
C.webkit_get_major_version(),
C.webkit_get_minor_version(),
C.webkit_get_micro_version(),
)
return result
}