mirror of
https://github.com/wailsapp/wails.git
synced 2025-05-04 15:32:12 +08:00
254 lines
5.7 KiB
Go
254 lines
5.7 KiB
Go
//go:build linux && purego
|
|
|
|
package application
|
|
|
|
import (
|
|
"fmt"
|
|
"log"
|
|
"os"
|
|
"strings"
|
|
"sync"
|
|
|
|
"github.com/ebitengine/purego"
|
|
"github.com/wailsapp/wails/v2/pkg/assetserver/webview"
|
|
)
|
|
|
|
const (
|
|
gtk3 = "libgtk-3.so"
|
|
gtk4 = "libgtk-4.so"
|
|
)
|
|
|
|
var (
|
|
gtk uintptr
|
|
version int
|
|
webkit uintptr
|
|
)
|
|
|
|
func init() {
|
|
// needed for GTK4 to function
|
|
_ = os.Setenv("GDK_BACKEND", "x11")
|
|
var err error
|
|
/*
|
|
gtk, err = purego.Dlopen(gtk4, purego.RTLD_NOW|purego.RTLD_GLOBAL)
|
|
if err == nil {
|
|
version = 4
|
|
return
|
|
}
|
|
|
|
log.Println("Failed to open GTK4: Falling back to GTK3")
|
|
*/
|
|
gtk, err = purego.Dlopen(gtk3, purego.RTLD_NOW|purego.RTLD_GLOBAL)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
version = 3
|
|
|
|
var webkit4 string = "libwebkit2gtk-4.1.so"
|
|
webkit, err = purego.Dlopen(webkit4, purego.RTLD_NOW|purego.RTLD_GLOBAL)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
}
|
|
|
|
type linuxApp struct {
|
|
appName string
|
|
application uintptr
|
|
applicationMenu uintptr
|
|
parent *App
|
|
|
|
// Native -> uint
|
|
windows map[uintptr]uint
|
|
windowsLock sync.Mutex
|
|
}
|
|
|
|
func getNativeApplication() *linuxApp {
|
|
return globalApplication.impl.(*linuxApp)
|
|
}
|
|
|
|
func (m *linuxApp) hide() {
|
|
// C.hide()
|
|
}
|
|
|
|
func (m *linuxApp) show() {
|
|
// C.show()
|
|
}
|
|
|
|
func (m *linuxApp) on(eventID uint) {
|
|
log.Println("linuxApp.on()", eventID)
|
|
|
|
// TODO: Setup signal handling as appropriate
|
|
// Note: GTK signals seem to be strings!
|
|
}
|
|
|
|
func (m *linuxApp) setIcon(icon []byte) {
|
|
// C.setApplicationIcon(unsafe.Pointer(&icon[0]), C.int(len(icon)))
|
|
}
|
|
|
|
func (m *linuxApp) name() string {
|
|
return m.appName
|
|
}
|
|
|
|
func (m *linuxApp) getCurrentWindowID() uint {
|
|
var getCurrentWindow func(uintptr) uintptr
|
|
purego.RegisterLibFunc(&getCurrentWindow, gtk, "gtk_application_get_active_window")
|
|
window := getCurrentWindow(m.application)
|
|
if window == 0 {
|
|
return 1
|
|
}
|
|
m.windowsLock.Lock()
|
|
defer m.windowsLock.Unlock()
|
|
if identifier, ok := m.windows[window]; ok {
|
|
return identifier
|
|
}
|
|
|
|
return 1
|
|
}
|
|
|
|
func (m *linuxApp) setApplicationMenu(menu *Menu) {
|
|
if menu == nil {
|
|
// Create a default menu
|
|
menu = defaultApplicationMenu()
|
|
}
|
|
globalApplication.dispatchOnMainThread(func() {
|
|
menu.Update()
|
|
m.applicationMenu = (menu.impl).(*linuxMenu).native
|
|
})
|
|
}
|
|
|
|
func (m *linuxApp) activate() {
|
|
fmt.Println("linuxApp.activated!", m.application)
|
|
var hold func(uintptr)
|
|
purego.RegisterLibFunc(&hold, gtk, "g_application_hold")
|
|
|
|
hold(m.application)
|
|
|
|
// time.Sleep(50 * time.Millisecond)
|
|
// m.parent.activate()
|
|
}
|
|
|
|
func (m *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() {
|
|
// Do we need to do anything now?
|
|
fmt.Println("ApplicationDidFinishLaunching!")
|
|
})
|
|
*/
|
|
m.parent.OnWindowCreation(func(window *WebviewWindow) {
|
|
fmt.Println("OnWindowCreation: ", window)
|
|
|
|
})
|
|
|
|
var g_signal_connect func(uintptr, string, uintptr, uintptr, bool, int) int
|
|
purego.RegisterLibFunc(&g_signal_connect, gtk, "g_signal_connect_data")
|
|
g_signal_connect(m.application, "activate", purego.NewCallback(m.activate), m.application, false, 0)
|
|
|
|
var run func(uintptr, int, []string) int
|
|
purego.RegisterLibFunc(&run, gtk, "g_application_run")
|
|
|
|
// FIXME: Convert status to 'error' if needed
|
|
status := run(m.application, 0, []string{})
|
|
fmt.Println("status", status)
|
|
|
|
var release func(uintptr)
|
|
purego.RegisterLibFunc(&release, gtk, "g_application_release")
|
|
release(m.application)
|
|
|
|
purego.RegisterLibFunc(&release, gtk, "g_object_unref")
|
|
release(m.application)
|
|
|
|
return nil
|
|
}
|
|
|
|
func (m *linuxApp) destroy() {
|
|
var quit func(uintptr)
|
|
purego.RegisterLibFunc(&quit, gtk, "g_application_quit")
|
|
quit(m.application)
|
|
}
|
|
|
|
func (m *linuxApp) registerWindow(address uintptr, window uint) {
|
|
m.windowsLock.Lock()
|
|
m.windows[address] = window
|
|
m.windowsLock.Unlock()
|
|
}
|
|
|
|
func newPlatformApp(parent *App) *linuxApp {
|
|
name := strings.ToLower(parent.options.Name)
|
|
if name == "" {
|
|
name = "undefined"
|
|
}
|
|
identifier := fmt.Sprintf("org.wails.%s", strings.Replace(name, " ", "-", -1))
|
|
|
|
var gtkNew func(string, uint) uintptr
|
|
purego.RegisterLibFunc(>kNew, gtk, "gtk_application_new")
|
|
app := &linuxApp{
|
|
appName: identifier,
|
|
parent: parent,
|
|
application: gtkNew(identifier, 0),
|
|
windows: map[uintptr]uint{},
|
|
}
|
|
return app
|
|
}
|
|
|
|
func processApplicationEvent(eventID uint) {
|
|
// TODO: add translation to Wails events
|
|
// currently reusing Mac specific values
|
|
applicationEvents <- eventID
|
|
}
|
|
|
|
func processWindowEvent(windowID uint, eventID uint) {
|
|
windowEvents <- &WindowEvent{
|
|
WindowID: windowID,
|
|
EventID: eventID,
|
|
}
|
|
}
|
|
|
|
func processMessage(windowID uint, message string) {
|
|
windowMessageBuffer <- &windowMessage{
|
|
windowId: windowID,
|
|
message: message,
|
|
}
|
|
}
|
|
|
|
func processURLRequest(windowID uint, wkUrlSchemeTask uintptr) {
|
|
fmt.Println("processURLRequest", windowID, wkUrlSchemeTask)
|
|
webviewRequests <- &webViewAssetRequest{
|
|
Request: webview.NewRequest(wkUrlSchemeTask),
|
|
windowId: windowID,
|
|
windowName: globalApplication.getWindowForID(windowID).Name(),
|
|
}
|
|
}
|
|
|
|
func processDragItems(windowID uint, arr []string, length int) {
|
|
windowDragAndDropBuffer <- &dragAndDropMessage{
|
|
windowId: windowID,
|
|
filenames: arr,
|
|
}
|
|
}
|
|
|
|
func processMenuItemClick(menuID uint) {
|
|
menuItemClicked <- menuID
|
|
}
|
|
|
|
func setIcon(icon []byte) {
|
|
if icon == nil {
|
|
return
|
|
}
|
|
fmt.Println("setIcon")
|
|
/*
|
|
GdkPixbufLoader *loader = gdk_pixbuf_loader_new();
|
|
if (!loader)
|
|
{
|
|
return;
|
|
}
|
|
if (gdk_pixbuf_loader_write(loader, buf, len, NULL) && gdk_pixbuf_loader_close(loader, NULL))
|
|
{
|
|
GdkPixbuf *pixbuf = gdk_pixbuf_loader_get_pixbuf(loader);
|
|
if (pixbuf)
|
|
{
|
|
gtk_window_set_icon(window, pixbuf);
|
|
}
|
|
}
|
|
g_object_unref(loader);*/
|
|
}
|