diff --git a/v2/internal/ffenestri/ffenestri_darwin.c b/v2/internal/ffenestri/ffenestri_darwin.c index daa7f6797..480e2a1b7 100644 --- a/v2/internal/ffenestri/ffenestri_darwin.c +++ b/v2/internal/ffenestri/ffenestri_darwin.c @@ -128,6 +128,7 @@ struct Application { int hideToolbarSeparator; int windowBackgroundIsTranslucent; int hasURLHandlers; + const char *startupURL; // Menu Menu *applicationMenu; @@ -144,6 +145,9 @@ struct Application { // shutting down flag bool shuttingDown; + // Running flag + bool running; + }; // Debug works like sprintf but mutes if the global debug flag is true @@ -304,8 +308,19 @@ void messageHandler(id self, SEL cmd, id contentController, id message) { // TODO: Check this actually does reduce flicker msg(app->config, s("setValue:forKey:"), msg(c("NSNumber"), s("numberWithBool:"), 0), str("suppressesIncrementalRendering")); + // We are now running! + app->running = true; + + // Notify backend we are ready (system startup) - app->sendMessageToBackend("SS"); + const char *readyMessage = "SS"; + if( app->startupURL == NULL ) { + app->sendMessageToBackend("SS"); + return; + } + readyMessage = concat("SS", app->startupURL); + app->sendMessageToBackend(readyMessage); + MEMFREE(readyMessage); } else if( strcmp(name, "windowDrag") == 0 ) { // Guard against null events @@ -403,6 +418,11 @@ void ExecJS(struct Application *app, const char *js) { void willFinishLaunching(id self, SEL cmd, id sender) { struct Application *app = (struct Application *) objc_getAssociatedObject(self, "application"); + // If there are URL Handlers, register a listener for them + if( app->hasURLHandlers ) { + id eventManager = msg(c("NSAppleEventManager"), s("sharedAppleEventManager")); + msg(eventManager, s("setEventHandler:andSelector:forEventClass:andEventID:"), self, s("getUrl:withReplyEvent:"), kInternetEventClass, kAEGetURL); + } messageFromWindowCallback("Ej{\"name\":\"wails:launched\",\"data\":[]}"); } @@ -427,12 +447,6 @@ void themeChanged(id self, SEL cmd, id sender) { } } -// void willFinishLaunching(id self) { -// struct Application *app = (struct Application *) objc_getAssociatedObject(self, "application"); -// Debug(app, "willFinishLaunching called!"); -// } - - int releaseNSObject(void *const context, struct hashmap_element_s *const e) { msg(e->data, s("release")); return -1; @@ -465,6 +479,10 @@ void DestroyApplication(struct Application *app) { Debug(app, "Almost a double free for app->bindings"); } + if( app->startupURL != NULL ) { + MEMFREE(app->startupURL); + } + // Remove mouse monitors if( app->mouseDownMonitor != NULL ) { msg( c("NSEvent"), s("removeMonitor:"), app->mouseDownMonitor); @@ -1156,12 +1174,28 @@ void DarkModeEnabled(struct Application *app, const char *callbackID) { } void getURL(id self, SEL selector, id event, id replyEvent) { - id desc = msg(event, s("paramDescriptorForKeyword:"), keyDirectObject); - id url = msg(desc, s("stringValue")); - const char* curl = cstr(url); - const char* message = concat("UC", curl); - messageFromWindowCallback(message); - MEMFREE(message); + struct Application *app = (struct Application *)objc_getAssociatedObject(self, "application"); + id desc = msg(event, s("paramDescriptorForKeyword:"), keyDirectObject); + id url = msg(desc, s("stringValue")); + const char* curl = cstr(url); + if( curl == NULL ) { + return; + } + + // If this was an incoming URL, but we aren't running yet + // save it to return when we complete + if( app->running != true ) { + app->startupURL = STRCOPY(curl); + return; + } + + const char* message = concat("UC", curl); + messageFromWindowCallback(message); + MEMFREE(message); +} + +void openURLs(id self, SEL selector, id event) { + filelog("\n\nI AM HERE!!!!!\n\n"); } @@ -1190,12 +1224,6 @@ void createDelegate(struct Application *app) { id delegate = msg((id)appDelegate, s("new")); objc_setAssociatedObject(delegate, "application", (id)app, OBJC_ASSOCIATION_ASSIGN); - // If there are URL Handlers, register a listener for them - if( app->hasURLHandlers ) { - id eventManager = msg(c("NSAppleEventManager"), s("sharedAppleEventManager")); - msg(eventManager, s("setEventHandler:andSelector:forEventClass:andEventID:"), delegate, s("getUrl:withReplyEvent:"), kInternetEventClass, kAEGetURL); - } - // Theme change listener class_addMethod(appDelegate, s("themeChanged:"), (IMP) themeChanged, "v@:@@"); @@ -1976,6 +2004,10 @@ void* NewApplication(const char *title, int width, int height, int resizable, in result->hasURLHandlers = 0; + result->startupURL = NULL; + + result->running = false; + return (void*) result; } diff --git a/v2/internal/messagedispatcher/message/system.go b/v2/internal/messagedispatcher/message/system.go index 1e69ec62e..1bda75140 100644 --- a/v2/internal/messagedispatcher/message/system.go +++ b/v2/internal/messagedispatcher/message/system.go @@ -40,7 +40,8 @@ func systemMessageParser(message string) (*parsedMessage, error) { // This is our startup hook - the frontend is now ready case 'S': topic := "hooks:startup" - responseMessage = &parsedMessage{Topic: topic, Data: nil} + startupURL := message[1:] + responseMessage = &parsedMessage{Topic: topic, Data: startupURL} default: return nil, fmt.Errorf("Invalid message to systemMessageParser()") } diff --git a/v2/internal/subsystem/runtime.go b/v2/internal/subsystem/runtime.go index 7b44ddb7c..3f890ed96 100644 --- a/v2/internal/subsystem/runtime.go +++ b/v2/internal/subsystem/runtime.go @@ -34,6 +34,9 @@ type Runtime struct { // Startup Hook startupOnce sync.Once + + // Service bus + bus *servicebus.ServiceBus } // NewRuntime creates a new runtime subsystem @@ -58,6 +61,7 @@ func NewRuntime(ctx context.Context, bus *servicebus.ServiceBus, logger *logger. runtime: runtime.New(bus), startupCallback: startupCallback, ctx: ctx, + bus: bus, } return result, nil @@ -79,7 +83,15 @@ func (r *Runtime) Start() error { case "startup": if r.startupCallback != nil { r.startupOnce.Do(func() { - go r.startupCallback(r.runtime) + go func() { + r.startupCallback(r.runtime) + + // If we got a url, publish it now startup completed + url, ok := hooksMessage.Data().(string) + if ok && len(url) > 0 { + r.bus.Publish("url:handler", url) + } + }() }) } else { r.logger.Warning("no startup callback registered!")