Compare commits

..

2 Commits

Author SHA1 Message Date
Lea Anthony
07c17c9e81 Merge branch 'develop' into 253-fix-runtime-import 2019-10-09 19:32:40 +11:00
Lea Anthony
79c258bbe0 fix: importing runtime 2019-10-09 14:44:53 +11:00
14 changed files with 32 additions and 157 deletions

View File

@@ -19,4 +19,3 @@ Wails is what it is because of the time and effort given by these great people.
* [Nikolai Zimmermann](https://github.com/Chronophylos) * [Nikolai Zimmermann](https://github.com/Chronophylos)
* [Toyam Cox](https://github.com/Vaelatern) * [Toyam Cox](https://github.com/Vaelatern)
* [Robin Eklind](https://github.com/mewmew) * [Robin Eklind](https://github.com/mewmew)
* [Kris Raney](https://github.com/kraney)

39
app.go
View File

@@ -1,10 +1,6 @@
package wails package wails
import ( import (
"os"
"syscall"
"github.com/syossan27/tebata"
"github.com/wailsapp/wails/cmd" "github.com/wailsapp/wails/cmd"
"github.com/wailsapp/wails/lib/binding" "github.com/wailsapp/wails/lib/binding"
"github.com/wailsapp/wails/lib/event" "github.com/wailsapp/wails/lib/event"
@@ -70,7 +66,6 @@ func CreateApp(optionalConfig ...*AppConfig) *App {
// Run the app // Run the app
func (a *App) Run() error { func (a *App) Run() error {
if BuildMode != cmd.BuildModeProd { if BuildMode != cmd.BuildModeProd {
return a.cli.Run() return a.cli.Run()
} }
@@ -102,13 +97,6 @@ func (a *App) start() error {
return err return err
} }
// Start signal handler
t := tebata.New(os.Interrupt, os.Kill, syscall.SIGTERM, syscall.SIGINT, syscall.SIGKILL)
t.Reserve(func() {
a.log.Debug("SIGNAL CAUGHT! Starting Shutdown")
a.renderer.Close()
})
// Start event manager and give it our renderer // Start event manager and give it our renderer
a.eventManager.Start(a.renderer) a.eventManager.Start(a.renderer)
@@ -124,33 +112,8 @@ func (a *App) start() error {
return err return err
} }
// Defer the shutdown
defer a.shutdown()
// Run the renderer // Run the renderer
err = a.renderer.Run() return a.renderer.Run()
if err != nil {
return err
}
return nil
}
// shutdown the app
func (a *App) shutdown() {
// Make sure this is only called once
a.log.Debug("Shutting down")
// Shutdown Binding Manager
a.bindingManager.Shutdown()
// Shutdown IPC Manager
a.ipc.Shutdown()
// Shutdown Event Manager
a.eventManager.Shutdown()
a.log.Debug("Cleanly Shutdown")
} }
// Bind allows the user to bind the given object // Bind allows the user to bind the given object

1
go.mod
View File

@@ -22,7 +22,6 @@ require (
github.com/pkg/errors v0.8.1 // indirect github.com/pkg/errors v0.8.1 // indirect
github.com/sirupsen/logrus v1.4.1 github.com/sirupsen/logrus v1.4.1
github.com/stretchr/testify v1.3.0 // indirect github.com/stretchr/testify v1.3.0 // indirect
github.com/syossan27/tebata v0.0.0-20180602121909-b283fe4bc5ba
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529 // indirect golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529 // indirect
golang.org/x/net v0.0.0-20190509222800-a4d6f7feada5 // indirect golang.org/x/net v0.0.0-20190509222800-a4d6f7feada5 // indirect
golang.org/x/sys v0.0.0-20190509141414-a5b02f93d862 golang.org/x/sys v0.0.0-20190509141414-a5b02f93d862

2
go.sum
View File

@@ -68,8 +68,6 @@ github.com/stretchr/testify v1.2.1/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/syossan27/tebata v0.0.0-20180602121909-b283fe4bc5ba h1:2DHfQOxcpWdGf5q5IzCUFPNvRX9Icf+09RvQK2VnJq0=
github.com/syossan27/tebata v0.0.0-20180602121909-b283fe4bc5ba/go.mod h1:iLnlXG2Pakcii2CU0cbY07DRCSvpWNa7nFxtevhOChk=
golang.org/x/crypto v0.0.0-20190123085648-057139ce5d2b/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190123085648-057139ce5d2b/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529 h1:iMGN4xG0cnqj3t+zOM8wUB0BiPKHEwSxEZCvzcbZuvk= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529 h1:iMGN4xG0cnqj3t+zOM8wUB0BiPKHEwSxEZCvzcbZuvk=

View File

@@ -16,7 +16,6 @@ type Manager struct {
functions map[string]*boundFunction functions map[string]*boundFunction
internalMethods *internalMethods internalMethods *internalMethods
initMethods []*boundMethod initMethods []*boundMethod
shutdownMethods []*boundMethod
log *logger.CustomLogger log *logger.CustomLogger
renderer interfaces.Renderer renderer interfaces.Renderer
runtime interfaces.Runtime // The runtime object to pass to bound structs runtime interfaces.Runtime // The runtime object to pass to bound structs
@@ -128,9 +127,6 @@ func (b *Manager) bindMethod(object interface{}) error {
if newMethod.isWailsInit { if newMethod.isWailsInit {
b.log.Debugf("Detected WailsInit function: %s", fullMethodName) b.log.Debugf("Detected WailsInit function: %s", fullMethodName)
b.initMethods = append(b.initMethods, newMethod) b.initMethods = append(b.initMethods, newMethod)
} else if newMethod.isWailsShutdown {
b.log.Debugf("Detected WailsShutdown function: %s", fullMethodName)
b.shutdownMethods = append(b.shutdownMethods, newMethod)
} else { } else {
// Save boundMethod // Save boundMethod
b.log.Infof("Bound Method: %s()", fullMethodName) b.log.Infof("Bound Method: %s()", fullMethodName)
@@ -296,13 +292,3 @@ func (b *Manager) callWailsInitMethods() error {
} }
return nil return nil
} }
// Shutdown the binding manager
func (b *Manager) Shutdown() {
b.log.Debug("Shutdown called")
for _, method := range b.shutdownMethods {
b.log.Debugf("Calling Shutdown for method: %s", method.fullName)
method.call("[]")
}
b.log.Debug("Shutdown complete")
}

View File

@@ -18,7 +18,6 @@ type boundMethod struct {
log *logger.CustomLogger log *logger.CustomLogger
hasErrorReturnType bool // Indicates if there is an error return type hasErrorReturnType bool // Indicates if there is an error return type
isWailsInit bool isWailsInit bool
isWailsShutdown bool
} }
// Creates a new bound method based on the given method + type // Creates a new bound method based on the given method + type
@@ -40,11 +39,6 @@ func newBoundMethod(name string, fullName string, method reflect.Value, objectTy
err = result.processWailsInit() err = result.processWailsInit()
} }
// Are we a WailsShutdown method?
if result.Name == "WailsShutdown" {
err = result.processWailsShutdown()
}
return result, err return result, err
} }
@@ -217,20 +211,3 @@ func (b *boundMethod) processWailsInit() error {
return nil return nil
} }
func (b *boundMethod) processWailsShutdown() error {
// We must have only 1 input, it must be *wails.Runtime
if len(b.inputs) != 0 {
return fmt.Errorf("Invalid WailsShutdown() definition. Expected 0 inputs, but got %d", len(b.inputs))
}
// We must have only 1 output, it must be error
if len(b.returnTypes) != 0 {
return fmt.Errorf("Invalid WailsShutdown() definition. Expected 0 return types, but got %d", len(b.returnTypes))
}
// We are indeed a wails Shutdown method
b.isWailsShutdown = true
return nil
}

View File

@@ -3,21 +3,18 @@ package event
import ( import (
"fmt" "fmt"
"sync" "sync"
"time"
"github.com/wailsapp/wails/lib/interfaces"
"github.com/wailsapp/wails/lib/logger" "github.com/wailsapp/wails/lib/logger"
"github.com/wailsapp/wails/lib/messages" "github.com/wailsapp/wails/lib/messages"
"github.com/wailsapp/wails/lib/interfaces"
) )
// Manager handles and processes events // Manager handles and processes events
type Manager struct { type Manager struct {
incomingEvents chan *messages.EventData incomingEvents chan *messages.EventData
listeners map[string][]*eventListener listeners map[string][]*eventListener
running bool exit bool
log *logger.CustomLogger log *logger.CustomLogger
renderer interfaces.Renderer // Messages will be dispatched to the frontend renderer interfaces.Renderer // Messages will be dispatched to the frontend
wg sync.WaitGroup
} }
// NewManager creates a new event manager with a 100 event buffer // NewManager creates a new event manager with a 100 event buffer
@@ -25,7 +22,7 @@ func NewManager() interfaces.EventManager {
return &Manager{ return &Manager{
incomingEvents: make(chan *messages.EventData, 100), incomingEvents: make(chan *messages.EventData, 100),
listeners: make(map[string][]*eventListener), listeners: make(map[string][]*eventListener),
running: false, exit: false,
log: logger.NewCustomLogger("Events"), log: logger.NewCustomLogger("Events"),
} }
} }
@@ -90,14 +87,15 @@ func (e *Manager) Start(renderer interfaces.Renderer) {
// Store renderer // Store renderer
e.renderer = renderer e.renderer = renderer
// Set up waitgroup so we can wait for goroutine to quit // Set up waitgroup so we can wait for goroutine to start
e.running = true var wg sync.WaitGroup
e.wg.Add(1) wg.Add(1)
// Run main loop in separate goroutine // Run main loop in separate goroutine
go func() { go func() {
wg.Done()
e.log.Info("Listening") e.log.Info("Listening")
for e.running { for e.exit == false {
// TODO: Listen for application exit // TODO: Listen for application exit
select { select {
case event := <-e.incomingEvents: case event := <-e.incomingEvents:
@@ -141,18 +139,14 @@ func (e *Manager) Start(renderer interfaces.Renderer) {
} }
} }
} }
default:
time.Sleep(1 * time.Millisecond)
} }
} }
e.wg.Done()
}() }()
// Wait for goroutine to start
wg.Wait()
} }
// Shutdown is called when exiting the Application func (e *Manager) stop() {
func (e *Manager) Shutdown() { e.exit = true
e.log.Debug("Shutting Down")
e.running = false
e.log.Debug("Waiting for main loop to exit")
e.wg.Wait()
} }

View File

@@ -7,5 +7,4 @@ type BindingManager interface {
Bind(object interface{}) Bind(object interface{})
Start(renderer Renderer, runtime Runtime) error Start(renderer Renderer, runtime Runtime) error
ProcessCall(callData *messages.CallData) (result interface{}, err error) ProcessCall(callData *messages.CallData) (result interface{}, err error)
Shutdown()
} }

View File

@@ -8,5 +8,4 @@ type EventManager interface {
Emit(eventName string, optionalData ...interface{}) Emit(eventName string, optionalData ...interface{})
On(eventName string, callback func(...interface{})) On(eventName string, callback func(...interface{}))
Start(Renderer) Start(Renderer)
Shutdown()
} }

View File

@@ -5,5 +5,4 @@ type IPCManager interface {
BindRenderer(Renderer) BindRenderer(Renderer)
Dispatch(message string) Dispatch(message string)
Start(eventManager EventManager, bindingManager BindingManager) Start(eventManager EventManager, bindingManager BindingManager)
Shutdown()
} }

View File

@@ -2,8 +2,6 @@ package ipc
import ( import (
"fmt" "fmt"
"sync"
"time"
"github.com/wailsapp/wails/lib/interfaces" "github.com/wailsapp/wails/lib/interfaces"
"github.com/wailsapp/wails/lib/logger" "github.com/wailsapp/wails/lib/logger"
@@ -14,20 +12,18 @@ import (
type Manager struct { type Manager struct {
renderer interfaces.Renderer // The renderer renderer interfaces.Renderer // The renderer
messageQueue chan *ipcMessage messageQueue chan *ipcMessage
quitChannel chan struct{} // quitChannel chan struct{}
// signals chan os.Signal // signals chan os.Signal
log *logger.CustomLogger log *logger.CustomLogger
eventManager interfaces.EventManager eventManager interfaces.EventManager
bindingManager interfaces.BindingManager bindingManager interfaces.BindingManager
running bool
wg sync.WaitGroup
} }
// NewManager creates a new IPC Manager // NewManager creates a new IPC Manager
func NewManager() interfaces.IPCManager { func NewManager() interfaces.IPCManager {
result := &Manager{ result := &Manager{
messageQueue: make(chan *ipcMessage, 100), messageQueue: make(chan *ipcMessage, 100),
quitChannel: make(chan struct{}), // quitChannel: make(chan struct{}),
// signals: make(chan os.Signal, 1), // signals: make(chan os.Signal, 1),
log: logger.NewCustomLogger("IPC"), log: logger.NewCustomLogger("IPC"),
} }
@@ -48,12 +44,9 @@ func (i *Manager) Start(eventManager interfaces.EventManager, bindingManager int
i.log.Info("Starting") i.log.Info("Starting")
// signal.Notify(manager.signals, os.Interrupt) // signal.Notify(manager.signals, os.Interrupt)
i.running = true
// Keep track of this goroutine
i.wg.Add(1)
go func() { go func() {
for i.running { running := true
for running {
select { select {
case incomingMessage := <-i.messageQueue: case incomingMessage := <-i.messageQueue:
i.log.DebugFields("Processing message", logger.Fields{ i.log.DebugFields("Processing message", logger.Fields{
@@ -124,12 +117,15 @@ func (i *Manager) Start(eventManager interfaces.EventManager, bindingManager int
i.log.DebugFields("Finished processing message", logger.Fields{ i.log.DebugFields("Finished processing message", logger.Fields{
"1D": &incomingMessage, "1D": &incomingMessage,
}) })
default: // case <-manager.quitChannel:
time.Sleep(1 * time.Millisecond) // Debug("[MessageQueue] Quit caught")
// running = false
// case <-manager.signals:
// Debug("[MessageQueue] Signal caught")
// running = false
} }
} }
i.log.Debug("Stopping") i.log.Debug("Stopping")
i.wg.Done()
}() }()
} }
@@ -171,11 +167,3 @@ func (i *Manager) SendResponse(response *ipcResponse) error {
// Call back to the front end // Call back to the front end
return i.renderer.Callback(data) return i.renderer.Callback(data)
} }
// Shutdown is called when exiting the Application
func (i *Manager) Shutdown() {
i.log.Debug("Shutdown called")
i.running = false
i.log.Debug("Waiting of main loop shutdown")
i.wg.Wait()
}

View File

@@ -156,7 +156,7 @@ func (h *Bridge) Run() error {
h.log.Info("The frontend will connect automatically.") h.log.Info("The frontend will connect automatically.")
err := h.server.ListenAndServe() err := h.server.ListenAndServe()
if err != nil && err != http.ErrServerClosed { if err != nil {
h.log.Fatal(err.Error()) h.log.Fatal(err.Error())
} }
return err return err
@@ -250,9 +250,5 @@ func (h *Bridge) SetTitle(title string) {
// Close is unsupported for Bridge but required // Close is unsupported for Bridge but required
// for the Renderer interface // for the Renderer interface
func (h *Bridge) Close() { func (h *Bridge) Close() {
h.log.Debug("Shutting down") h.log.Warn("Close() unsupported in bridge mode")
err := h.server.Close()
if err != nil {
h.log.Errorf(err.Error())
}
} }

View File

@@ -11,7 +11,7 @@
package webview package webview
/* /*
#cgo linux openbsd freebsd CFLAGS: -DWEBVIEW_GTK=1 -Wno-deprecated-declarations #cgo linux openbsd freebsd CFLAGS: -DWEBVIEW_GTK=1
#cgo linux openbsd freebsd pkg-config: gtk+-3.0 webkit2gtk-4.0 #cgo linux openbsd freebsd pkg-config: gtk+-3.0 webkit2gtk-4.0
#cgo windows CFLAGS: -DWEBVIEW_WINAPI=1 #cgo windows CFLAGS: -DWEBVIEW_WINAPI=1

View File

@@ -86,7 +86,7 @@ struct webview_priv
NSAutoreleasePool *pool; NSAutoreleasePool *pool;
NSWindow *window; NSWindow *window;
WebView *webview; WebView *webview;
id delegate; id windowDelegate;
int should_exit; int should_exit;
}; };
#else #else
@@ -1894,22 +1894,6 @@ struct webview_priv
[script setValue:self forKey:@"external"]; [script setValue:self forKey:@"external"];
} }
static void webview_run_input_open_panel(id self, SEL cmd, id webview,
id listener, BOOL allowMultiple) {
char filename[256] = "";
struct webview *w =
(struct webview *)objc_getAssociatedObject(self, "webview");
webview_dialog(w, WEBVIEW_DIALOG_TYPE_OPEN, WEBVIEW_DIALOG_FLAG_FILE, "", "",
filename, 255);
if (strlen(filename)) {
[listener chooseFilename:[NSString stringWithUTF8String:filename]];
} else {
[listener cancel];
}
}
static void webview_external_invoke(id self, SEL cmd, id arg) static void webview_external_invoke(id self, SEL cmd, id arg)
{ {
struct webview *w = struct webview *w =
@@ -1943,17 +1927,12 @@ static void webview_run_input_open_panel(id self, SEL cmd, id webview,
class_addMethod(webViewDelegateClass, class_addMethod(webViewDelegateClass,
sel_registerName("webView:didClearWindowObject:forFrame:"), sel_registerName("webView:didClearWindowObject:forFrame:"),
(IMP)webview_did_clear_window_object, "v@:@@@"); (IMP)webview_did_clear_window_object, "v@:@@@");
class_addMethod(
webViewDelegateClass,
sel_registerName("webView:runOpenPanelForFileButtonWithResultListener:"
"allowMultipleFiles:"),
(IMP)webview_run_input_open_panel, "v@:@@c");
class_addMethod(webViewDelegateClass, sel_registerName("invoke:"), class_addMethod(webViewDelegateClass, sel_registerName("invoke:"),
(IMP)webview_external_invoke, "v@:@"); (IMP)webview_external_invoke, "v@:@");
objc_registerClassPair(webViewDelegateClass); objc_registerClassPair(webViewDelegateClass);
w->priv.delegate = [[webViewDelegateClass alloc] init]; w->priv.windowDelegate = [[webViewDelegateClass alloc] init];
objc_setAssociatedObject(w->priv.delegate, "webview", (id)(w), objc_setAssociatedObject(w->priv.windowDelegate, "webview", (id)(w),
OBJC_ASSOCIATION_ASSIGN); OBJC_ASSOCIATION_ASSIGN);
NSRect r = NSMakeRect(0, 0, w->width, w->height); NSRect r = NSMakeRect(0, 0, w->width, w->height);
@@ -1981,7 +1960,7 @@ static void webview_run_input_open_panel(id self, SEL cmd, id webview,
NSString *nsTitle = [NSString stringWithUTF8String:w->title]; NSString *nsTitle = [NSString stringWithUTF8String:w->title];
[w->priv.window setTitle:nsTitle]; [w->priv.window setTitle:nsTitle];
[w->priv.window setDelegate:w->priv.delegate]; [w->priv.window setDelegate:w->priv.windowDelegate];
[w->priv.window center]; [w->priv.window center];
// NSToolbar *toolbar = [[NSToolbar alloc] initWithIdentifier:@"wat"]; // NSToolbar *toolbar = [[NSToolbar alloc] initWithIdentifier:@"wat"];
@@ -2010,8 +1989,7 @@ static void webview_run_input_open_panel(id self, SEL cmd, id webview,
[w->priv.webview setAutoresizesSubviews:YES]; [w->priv.webview setAutoresizesSubviews:YES];
[w->priv.webview [w->priv.webview
setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable]; setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
w->priv.webview.frameLoadDelegate = w->priv.delegate; w->priv.webview.frameLoadDelegate = w->priv.windowDelegate;
w->priv.webview.UIDelegate = w->priv.delegate;
[[w->priv.window contentView] addSubview:w->priv.webview]; [[w->priv.window contentView] addSubview:w->priv.webview];
[w->priv.window orderFrontRegardless]; [w->priv.window orderFrontRegardless];