Last active
December 19, 2023 08:47
-
-
Save nathankerr/38d8b0d45590741b57f5f79be336f07c to your computer and use it in GitHub Desktop.
Registering a Go app as a protocol handler under Mac OS X
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#import <Foundation/Foundation.h> | |
extern void HandleURL(char*); | |
@interface GoPasser : NSObject | |
+ (void)handleGetURLEvent:(NSAppleEventDescriptor *)event; | |
@end | |
void StartURLHandler(void); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "handler.h" | |
@implementation GoPasser | |
+ (void)handleGetURLEvent:(NSAppleEventDescriptor *)event | |
{ | |
HandleURL([[[event paramDescriptorForKeyword:keyDirectObject] stringValue] UTF8String]); | |
} | |
@end | |
void StartURLHandler(void) { | |
NSAppleEventManager *appleEventManager = [NSAppleEventManager sharedAppleEventManager]; | |
[appleEventManager setEventHandler:[GoPasser class] | |
andSelector:@selector(handleGetURLEvent:) | |
forEventClass:kInternetEventClass andEventID:kAEGetURL]; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?xml version="1.0" encoding="UTF-8"?> | |
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | |
<plist version="1.0"> | |
<dict> | |
<key>CFBundleExecutable</key> | |
<string>myapp</string> | |
<key>CFBundleIdentifier</key> | |
<string>com.pocketgophers.myapp</string> | |
<key>CFBundleURLTypes</key> | |
<array> | |
<dict> | |
<key>CFBundleURLName</key> | |
<string>com.pocketgophers.myapp</string> | |
<key>CFBundleURLSchemes</key> | |
<array> | |
<string>myapp</string> | |
</array> | |
</dict> | |
</array> | |
<key>CFBundleInfoDictionaryVersion</key> | |
<string>6.0</string> | |
<key>CFBundleName</key> | |
<string>MyApp</string> | |
<key>CFBundlePackageType</key> | |
<string>APPL</string> | |
<key>CFBundleShortVersionString</key> | |
<string>1.0.0</string> | |
<key>CFBundleVersion</key> | |
<string>20</string> | |
</dict> | |
</plist> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
/* | |
#cgo CFLAGS: -x objective-c | |
#cgo LDFLAGS: -framework Foundation | |
#include "handler.h" | |
*/ | |
import "C" | |
import ( | |
"log" | |
"github.com/andlabs/ui" | |
) | |
// Sources used to figure this out: | |
// Info.plist: https://gist.github.com/chrissnell/db95a3c5ad6ceca4c673e96cca0f7548 | |
// custom url handler example: http://fredandrandall.com/blog/2011/07/30/how-to-launch-your-macios-app-with-a-custom-url/ | |
// obj-c example: https://gist.github.com/leepro/016d7d6b61021dfc67daf61771c92b3c | |
// note: import .h, not .m | |
var labelText chan string | |
func main() { | |
log.SetFlags(log.Lshortfile) | |
labelText = make(chan string, 1) // the event handler blocks!, so buffer the channel at least once to get the first message | |
C.StartURLHandler() | |
err := ui.Main(func() { | |
greeting := ui.NewLabel("greeting\nline 2") | |
window := ui.NewWindow("Hello", 200, 100, true) | |
window.SetChild(greeting) | |
window.OnClosing(func(*ui.Window) bool { | |
ui.Quit() | |
return true | |
}) | |
window.Show() | |
go func() { | |
for text := range labelText { | |
ui.QueueMain(func() { | |
greeting.SetText(text) | |
}) | |
} | |
}() | |
}) | |
if err != nil { | |
log.Fatal(err) | |
} | |
} | |
//export HandleURL | |
func HandleURL(u *C.char) { | |
labelText <- C.GoString(u) | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
myapp.app: *.go *.h *.m Makefile Info.plist | |
mkdir -p myapp.app/Contents/MacOS | |
go build -i -o myapp.app/Contents/MacOS/myapp | |
cp Info.plist myapp.app/Contents/Info.plist | |
.PHONY: open | |
open: myapp.app | |
open myapp.app | |
.PHONY: scheme | |
scheme: myapp.app | |
open myapp://hello/world | |
.PHONY: clean | |
clean: | |
rm -rf myapp.app | |
@ManuelEberhardinger @monmohan (and more likely, anyone who stumbles across this later)
I used mainthread to workaround the issue by separating out the handler code into its own package, and calling its init function in a go routine.
import (
"github.com/golang-design/mainthread"
"example.com/module/ui"
"example.com/module/handler"
)
func main() { mainthread.Init(fn) }
// fn is the actual main function
func fn() {
// macos requires UI to be run on the main thread so schedule that here (in my case, a tray icon)
mainthread.Go(ui.Init)
// moved protocol handler out of main() and into its own package with an init function
go handler.Init()
// execute the rest of your main here
restOfMain()
}
fails on mac for me.
on 11.7.4 ( Big Sur )
make
mkdir -p myapp.app/Contents/MacOS
go build -o myapp.app/Contents/MacOS/myapp .
# myapp
handler.m:7:12: warning: passing 'NS_RETURNS_INNER_POINTER const char *' to parameter of type 'char *' discards qualifiers [-Wincompatible-pointer-types-discards-qualifiers]
./handler.h:3:28: note: passing argument to parameter here
handler.m:15:40: error: use of undeclared identifier 'kInternetEventClass'; did you mean 'kCoreEventClass'?
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/CoreServices.framework/Frameworks/AE.framework/Headers/AppleEvents.h:65:3: note: 'kCoreEventClass' declared here
handler.m:15:71: error: use of undeclared identifier 'kAEGetURL'; did you mean 'kAEISGetURL'?
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/CoreServices.framework/Frameworks/AE.framework/Headers/AERegistry.h:829:3: note: 'kAEISGetURL' declared here
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I have the same problem. Do you found any solution for this?