diff --git a/exp/examples/basic/main.go b/exp/examples/basic/main.go index ad1284142..bea07f89f 100644 --- a/exp/examples/basic/main.go +++ b/exp/examples/basic/main.go @@ -45,17 +45,22 @@ func main() { }, }) - myWindow2 := app.NewWindow(&options.Window{ - Title: "#2", - Width: 1024, - Height: 768, - AlwaysOnTop: false, - URL: "https://google.com", - DisableResize: true, - Mac: &options.MacWindow{ - Backdrop: options.MacBackdropTranslucent, - }, - }) + var myWindow2 *application.Window + go func() { + time.Sleep(2 * time.Second) + myWindow2 = app.NewWindow(&options.Window{ + Title: "#2", + Width: 1024, + Height: 768, + AlwaysOnTop: false, + URL: "https://google.com", + DisableResize: true, + Mac: &options.MacWindow{ + Backdrop: options.MacBackdropTranslucent, + }, + }) + + }() go func() { time.Sleep(5 * time.Second) diff --git a/exp/pkg/application/application.go b/exp/pkg/application/application.go index 55668f494..9dce249ee 100644 --- a/exp/pkg/application/application.go +++ b/exp/pkg/application/application.go @@ -40,10 +40,7 @@ func (a *App) NewWindow(options *options.Window) *Window { } a.windows[id] = newWindow if a.running { - err := newWindow.Run() - if err != nil { - panic(err) - } + newWindow.Run() } return newWindow @@ -67,10 +64,7 @@ func (a *App) Run() error { // run windows for _, window := range a.windows { - err := window.Run() - if err != nil { - return err - } + go window.Run() } return a.run() diff --git a/exp/pkg/application/mainthread.go b/exp/pkg/application/mainthread.go new file mode 100644 index 000000000..4e201c71e --- /dev/null +++ b/exp/pkg/application/mainthread.go @@ -0,0 +1,41 @@ +//go:build darwin + +package application + +/* +extern void dispatch(unsigned int id); +*/ +import "C" +import "strconv" + +var mainThreadFuntionStore = make(map[uint]func()) + +func generateFunctionStoreID() uint { + startID := 0 + for { + if _, ok := mainThreadFuntionStore[uint(startID)]; !ok { + return uint(startID) + } + startID++ + if startID == 0 { + panic("Too many functions stored") + } + } +} + +func Dispatch(fn func()) { + id := generateFunctionStoreID() + mainThreadFuntionStore[id] = fn + C.dispatch(C.uint(id)) +} + +//export dispatchCallback +func dispatchCallback(id C.uint) { + + fn := mainThreadFuntionStore[uint(id)] + if fn == nil { + panic("dispatchCallback called with invalid id " + strconv.Itoa(int(id))) + } + fn() + delete(mainThreadFuntionStore, uint(id)) +} diff --git a/exp/pkg/application/mainthread_darwin.go b/exp/pkg/application/mainthread_darwin.go new file mode 100644 index 000000000..4654bfa6c --- /dev/null +++ b/exp/pkg/application/mainthread_darwin.go @@ -0,0 +1,20 @@ +//go:build darwin + +package application + +/* +#cgo CFLAGS: -mmacosx-version-min=10.13 -x objective-c +#cgo LDFLAGS: -framework Cocoa + +#include "Cocoa/Cocoa.h" + +extern void dispatchCallback(unsigned int); + +void dispatch(unsigned int id) { + dispatch_async(dispatch_get_main_queue(), ^{ + dispatchCallback(id); + }); +} + +*/ +import "C" diff --git a/exp/pkg/application/window.go b/exp/pkg/application/window.go index ea785e6e0..33017a9ed 100644 --- a/exp/pkg/application/window.go +++ b/exp/pkg/application/window.go @@ -11,7 +11,6 @@ type windowImpl interface { setTitle(title string) setSize(width, height int) setAlwaysOnTop(alwaysOnTop bool) - run() error navigateToURL(url string) setResizable(resizable bool) setMinSize(width, height int) @@ -26,6 +25,7 @@ type windowImpl interface { isFullscreen() bool restore() setBackgroundColor(color *options.RGBA) + run() } type Window struct { @@ -68,9 +68,9 @@ func (w *Window) SetSize(width, height int) { w.impl.setSize(width, height) } -func (w *Window) Run() error { +func (w *Window) Run() { w.impl = newWindowImpl(w.id, w.options) - return w.impl.run() + w.impl.run() } func (w *Window) SetAlwaysOnTop(b bool) { diff --git a/exp/pkg/application/window_darwin.go b/exp/pkg/application/window_darwin.go index f2ff9bd83..06d28010a 100644 --- a/exp/pkg/application/window_darwin.go +++ b/exp/pkg/application/window_darwin.go @@ -489,59 +489,59 @@ func (w *macosWindow) enableDevTools() { C.windowEnableDevTools(w.nsWindow) } -func (w *macosWindow) run() error { - w.nsWindow = C.windowNew(C.uint(w.id), C.int(w.options.Width), C.int(w.options.Height)) - w.setTitle(w.options.Title) - w.setAlwaysOnTop(w.options.AlwaysOnTop) - w.setResizable(!w.options.DisableResize) - w.setMinSize(w.options.MinWidth, w.options.MinHeight) - w.setMaxSize(w.options.MaxWidth, w.options.MaxHeight) - if w.options.URL != "" { - w.navigateToURL(w.options.URL) - } - if w.options.EnableDevTools { - w.enableDevTools() - } - w.setBackgroundColor(w.options.BackgroundColour) - if w.options.Mac != nil { - macOptions := w.options.Mac - switch macOptions.Backdrop { - case options.MacBackdropTransparent: - C.windowSetTransparent(w.nsWindow) - C.webviewSetTransparent(w.nsWindow) - case options.MacBackdropTranslucent: - C.windowSetTranslucent(w.nsWindow) - C.webviewSetTransparent(w.nsWindow) +func (w *macosWindow) run() { + Dispatch(func() { + w.nsWindow = C.windowNew(C.uint(w.id), C.int(w.options.Width), C.int(w.options.Height)) + w.setTitle(w.options.Title) + w.setAlwaysOnTop(w.options.AlwaysOnTop) + w.setResizable(!w.options.DisableResize) + w.setMinSize(w.options.MinWidth, w.options.MinHeight) + w.setMaxSize(w.options.MaxWidth, w.options.MaxHeight) + if w.options.URL != "" { + w.navigateToURL(w.options.URL) } - - if macOptions.TitleBar != nil { - titleBarOptions := macOptions.TitleBar - C.windowSetTitleBarAppearsTransparent(w.nsWindow, C.bool(titleBarOptions.AppearsTransparent)) - C.windowSetHideTitleBar(w.nsWindow, C.bool(titleBarOptions.Hide)) - C.windowSetHideTitle(w.nsWindow, C.bool(titleBarOptions.HideTitle)) - C.windowSetFullSizeContent(w.nsWindow, C.bool(titleBarOptions.FullSizeContent)) - C.windowSetUseToolbar(w.nsWindow, C.bool(titleBarOptions.UseToolbar)) - C.windowSetHideToolbarSeparator(w.nsWindow, C.bool(titleBarOptions.HideToolbarSeparator)) + if w.options.EnableDevTools { + w.enableDevTools() } + w.setBackgroundColor(w.options.BackgroundColour) + if w.options.Mac != nil { + macOptions := w.options.Mac + switch macOptions.Backdrop { + case options.MacBackdropTransparent: + C.windowSetTransparent(w.nsWindow) + C.webviewSetTransparent(w.nsWindow) + case options.MacBackdropTranslucent: + C.windowSetTranslucent(w.nsWindow) + C.webviewSetTransparent(w.nsWindow) + } - if macOptions.Appearance != "" { - C.windowSetAppearanceTypeByName(w.nsWindow, C.CString(string(macOptions.Appearance))) - } + if macOptions.TitleBar != nil { + titleBarOptions := macOptions.TitleBar + C.windowSetTitleBarAppearsTransparent(w.nsWindow, C.bool(titleBarOptions.AppearsTransparent)) + C.windowSetHideTitleBar(w.nsWindow, C.bool(titleBarOptions.Hide)) + C.windowSetHideTitle(w.nsWindow, C.bool(titleBarOptions.HideTitle)) + C.windowSetFullSizeContent(w.nsWindow, C.bool(titleBarOptions.FullSizeContent)) + C.windowSetUseToolbar(w.nsWindow, C.bool(titleBarOptions.UseToolbar)) + C.windowSetHideToolbarSeparator(w.nsWindow, C.bool(titleBarOptions.HideToolbarSeparator)) + } - switch w.options.StartState { - case options.WindowStateMaximised: - w.setMaximised() - case options.WindowStateMinimised: - w.setMinimised() - case options.WindowStateFullscreen: - w.setFullscreen() + if macOptions.Appearance != "" { + C.windowSetAppearanceTypeByName(w.nsWindow, C.CString(string(macOptions.Appearance))) + } + + switch w.options.StartState { + case options.WindowStateMaximised: + w.setMaximised() + case options.WindowStateMinimised: + w.setMinimised() + case options.WindowStateFullscreen: + w.setFullscreen() + + } } - - } - C.windowShow(w.nsWindow) - - return nil + C.windowShow(w.nsWindow) + }) } func (w *macosWindow) setBackgroundColor(colour *options.RGBA) {