https://github.com/progrium/macdriver Skip to content Sign up * Why GitHub? Features - + Mobile - + Actions - + Codespaces - + Packages - + Security - + Code review - + Project management - + Integrations - + GitHub Sponsors - + Customer stories - + Security - * Team * Enterprise * Explore + Explore GitHub - Learn & contribute + Topics - + Collections - + Trending - + Learning Lab - + Open source guides - Connect with others + The ReadME Project - + Events - + Community forum - + GitHub Education - + GitHub Stars program - * Marketplace * Pricing Plans - + Compare plans - + Contact Sales - + Nonprofit - + Education - [ ] [search-key] * # In this repository All GitHub | Jump to | * No suggested jump to results * # In this repository All GitHub | Jump to | * # In this user All GitHub | Jump to | * # In this repository All GitHub | Jump to | Sign in Sign up {{ message }} progrium / macdriver * Watch 23 * Star 1.1k * Fork 20 Native Mac APIs for Go MIT License 1.1k stars 20 forks Star Watch * Code * Issues 3 * Pull requests 0 * Discussions * Actions * Security * Insights More * Code * Issues * Pull requests * Discussions * Actions * Security * Insights main 2 branches 1 tag Go to file Code Clone HTTPS GitHub CLI [https://github.com/p] Use Git or checkout with SVN using the web URL. [gh repo clone progri] Work fast with our official CLI. Learn more. * Open with GitHub Desktop * Download ZIP Launching GitHub Desktop If nothing happens, download GitHub Desktop and try again. Go back Launching GitHub Desktop If nothing happens, download GitHub Desktop and try again. Go back Launching Xcode If nothing happens, download Xcode and try again. Go back Launching Visual Studio If nothing happens, download the GitHub extension for Visual Studio and try again. Go back Latest commit @progrium progrium Update README.md ... 8d2ca95 Feb 4, 2021 Update README.md 8d2ca95 Git stats * 62 commits Files Permalink Failed to load latest commit information. Type Name Latest commit message Commit time .github/workflows github: only test on mac Jan 11, 2021 bridge clarify readme bit more. handle possible case of nil resource handle Jan 22, 2021 cmd/macbridge dropped pkg dir, more readme bits Dec 31, 2020 cocoa feat: add collection behavior to NSWindow Jan 6, 2021 core dropped pkg dir, more readme bits Dec 31, 2020 examples bridge: cleanup and redesigned resources Jan 21, 2021 misc add test workflow Jan 11, 2021 objc dropped pkg dir, more readme bits Dec 31, 2020 webkit dropped pkg dir, more readme bits Dec 31, 2020 .gitignore ignore dist folder Jan 11, 2021 .goreleaser.yml simplify goreleaser config Jan 11, 2021 LICENSE dropped pkg dir, more readme bits Dec 31, 2020 Makefile bridge: cleanup and redesigned resources Jan 21, 2021 README.md Update README.md Feb 4, 2021 go.mod fix: invalid qtalk version Jan 5, 2021 go.sum fix: invalid qtalk version Jan 5, 2021 macdriver.gif logo Dec 29, 2020 View code README.md MacDriver Logo Native Mac APIs for Golang! GoDoc Test workflow Go Report Card @progriumHQ on Twitter Project Forum Sponsor Project --------------------------------------------------------------------- MacDriver is a toolkit for working with Apple/Mac APIs and frameworks in Go. It currently has 3 "layers": 1. Bindings for Objective-C The objc package wraps the Objective-C runtime to dynamically interact with Objective-C objects and classes: cls := objc.NewClass("AppDelegate", "NSObject") cls.AddMethod("applicationDidFinishLaunching:", func(app objc.Object) { fmt.Println("Launched!") }) objc.RegisterClass(cls) delegate := objc.Get("AppDelegate").Alloc().Init() app := objc.Get("NSApplication").Get("sharedApplication") app.Set("delegate:", delegate) app.Send("run") * Access any class or method you can access in Objective-C * Common object convenience methods: Get, Set, Alloc, Init, ... * Create and extend classes at runtime that can be used by Objective-C code * Retain and Release methods for working with Objective-C memory management 2. Framework Packages The cocoa, webkit, and core packages wrap objc with wrapper types for parts of the Apple/Mac APIs. They're being added to as needed by hand until we can automate this process with schema data. These packages effectively let you use Apple APIs as if they were native Go libraries, letting you write Mac applications (potentially also iOS, watchOS, etc) as Go applications: func main() { app := cocoa.NSApp_WithDidLaunch(func(notification objc.Object) { config := webkit.WKWebViewConfiguration_New() wv := webkit.WKWebView_Init(core.Rect(0, 0, 1440, 900), config) url := core.URL("http://progrium.com") req := core.NSURLRequest_Init(url) wv.LoadRequest(req) w := cocoa.NSWindow_Init(core.Rect(0, 0, 1440, 900), cocoa.NSClosableWindowMask| cocoa.NSTitledWindowMask, cocoa.NSBackingStoreBuffered, false) w.SetContentView(wv) w.MakeKeyAndOrderFront(w) w.Center() }) app.SetActivationPolicy(cocoa.NSApplicationActivationPolicyRegular) app.ActivateIgnoringOtherApps(true) app.Run() } * 1:1 mapping of API names with Objective-C APIs * Cocoa types: NSApplication, NSImage, NSMenu, NSWindow, more ... * Webkit types: WKWebView and configuration classes * Core types: NSData, NSDictionary, NSNumber, NSPoint, NSRect, NSSize, NSString, NSURL, more ... * Core also allows dispatching Go functions in the Cocoa run loop * Many constants/enums are defined Examples examples/largetype - A Contacts/Quicksilver-style Large Type utility in under 80 lines: largetype screenshot examples/pomodoro - A menu bar pomodoro timer in under 80 lines: pomodoro gif examples/topframe - A non-interactive, always-on-top webview with transparent background in 120 lines so you can draw on your screen with HTML/JS: topframe screenshot Note: topframe currently relies on embed which you can use with go 1.16beta 3. Bridge System Lastly, a common case for this toolkit is not just building full native apps, but integrating Go applications with Mac systems, like windows, native menus, status icons (systray), etc. One-off libraries for some of these exist, but besides often limiting what you can do, they're also just not composable. They all want to own the main thread! For this and other reasons, we often run the above kind of code in a separate process altogether from our Go application. This might seem like a step backwards, but it is safer and more robust in a way. The bridge package takes advantage of this situation to create a higher-level abstraction more aligned with a potential cross-platform toolkit. You can declaratively describe and modify structs that can be copied to the bridge process and applied to the Objective-C objects in a manner similar to configuration management: package main import ( "os" "github.com/progrium/macdriver/bridge" ) func main() { // start a bridge subprocess host := bridge.NewHost(os.Stderr) go host.Run() // create a window window := bridge.Window{ Title: "My Title", Size: bridge.Size{W: 480, H: 240}, Position: bridge.Point{X: 200, Y: 200}, Closable: true, Minimizable: false, Resizable: false, Borderless: false, AlwaysOnTop: true, Background: &bridge.Color{R: 1, G: 1, B: 1, A: 0.5}, } host.Sync(&window) // change its title window.Title = "My New Title" host.Sync(&window) // destroy the window host.Release(&window) } This is the most WIP part of the project, but once developed further we can take this API and build a bridge system with the same resources for Windows and Linux, making a cross-platform OS "driver". We'll see. * Current bridge types available: + Window + StatusItem (systray) + Menu Development Notes As far as we know, due to limitations of Go modules, we often need to add replace directives to our go.mod during development to work against a local checkout of some dependency (like qtalk). However, these should not be versioned, so for now we encourage you to use git update-index --skip-worktree go.mod on your checkout if you need to add replace directives. When updates need to be checked in, git update-index --no-skip-worktree go.mod can be used to reverse this on your local repo to commit changes and then re-enable. Generating wrappers Eventually we can generate most of the wrapper APIs using bridgesupport and/or doc schemas. However, the number of APIs is pretty ridiculous so there are lots of edge cases I wouldn't know how to automate yet. We can just continue to create them by hand as needed until we have enough coverage/confidence to know how we'd generate wrappers. Thanks The original objc and variadic packages were written by Mikkel Krautz . The variadic package is some assembly magic to make everything possible since libobjc relies heavily on variadic function calls, which aren't possible out of the box in Cgo. License MIT About Native Mac APIs for Go Topics go macos golang mac ios apple objective-c bindings native-apps cgo bridge cocoa webkit objc-runtime macos-application apple-apis libobjc Resources Readme License MIT License Releases 1 tags Contributors 2 * @progrium progrium Jeff Lindsay * @flexzuu flexzuu Jonas Faber Languages * Go 96.2% * Assembly 2.3% * Other 1.5% * (c) 2021 GitHub, Inc. * Terms * Privacy * Security * Status * Docs * Contact GitHub * Pricing * API * Training * Blog * About You can't perform that action at this time. You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.