Git Product home page Git Product logo

macdriver's Introduction

MacDriver Logo

Native Apple APIs for Golang!

GoDoc Go Report Card @progrium on Twitter Project Forum Sponsor Project

Important

Aug 23, 2023: MacDriver is becoming DarwinKit with the 0.5.0-preview release now available! The legacy branch and previous releases are still available for existing code to work against. Help me reach the 0.5.0 release milestone or request examples you'd like to see by posting in Discussions.


DarwinKit lets you work with supported Apple frameworks and build native applications using Go. With XCode and Go 1.18+ installed, you can write this program in a main.go file:

package main

import (
	"github.com/progrium/macdriver/objc"
	"github.com/progrium/macdriver/macos"
	"github.com/progrium/macdriver/macos/appkit"
	"github.com/progrium/macdriver/macos/foundation"
	"github.com/progrium/macdriver/macos/webkit"
)

func main() {
	// runs macOS application event loop with a callback on success
	macos.RunApp(func(app appkit.Application, delegate *appkit.ApplicationDelegate) {
		app.SetActivationPolicy(appkit.ApplicationActivationPolicyRegular)
		app.ActivateIgnoringOtherApps(true)

		url := foundation.URL_URLWithString("http://progrium.com")
		req := foundation.NewURLRequestWithURL(url)
		frame := foundation.Rect{Size: foundation.Size{1440, 900}}

		config := webkit.NewWebViewConfiguration()
		wv := webkit.NewWebViewWithFrameConfiguration(frame, config)
		wv.LoadRequest(req)

		w := appkit.NewWindowWithContentRectStyleMaskBackingDefer(frame,
			appkit.ClosableWindowMask|appkit.TitledWindowMask,
			appkit.BackingStoreBuffered, false)
		objc.Retain(&w)
		w.SetContentView(wv)
		w.MakeKeyAndOrderFront(w)
		w.Center()

		delegate.SetApplicationShouldTerminateAfterLastWindowClosed(func(appkit.Application) bool {
			return true
		})
	})
}

Then in this directory run:

go mod init helloworld
go get github.com/progrium/macdriver@main
go run main.go

This may take a moment the first time, but once the window pops up you just made a macOS program without using XCode or Objective-C. Run go build to get an executable.

Although currently outside the scope of this project, if you wanted you could put this executable into an Application bundle. You could even add entitlements, then sign and notarize this bundle or executable to let others run it. It could theoretically even be put on the App Store. It could theoretically be put on an iOS, tvOS, or watchOS device, though you would have to use different platform specific frameworks.

Caveats

  • You still need to know or learn how Apple frameworks work, so you'll have to use Apple documentation and understand how to translate Objective-C example code to the equivalent Go with DarwinKit.
  • Your programs link against the actual Apple frameworks using cgo, so XCode needs to be installed for the framework headers.
  • You will be using two memory management systems. Framework objects are managed by Objective-C memory management, so be sure to read our docs on memory management with DarwinKit.
  • Exceptions in frameworks will segfault, giving you both an Objective-C stacktrace and a Go panic stacktrace. You will be debugging a hybrid Go and Objective-C program.
  • Goroutines that interact with GUI objects need to dispatch operations on the main thread otherwise it will segfault.

This is all tenable for simple programs, but these are the reasons we don't recommend large/complex programs using DarwinKit.

Examples

A Contacts/Quicksilver-style Large Type utility in under 80 lines:

largetype screenshot

A menu bar pomodoro timer in under 80 lines:

pomodoro gif

A webview PNG capture example in under 100 lines:

webshot screenshot

How it works

Brief background on Objective-C

Ever since acquiring NeXT Computer in the 90s, Apple has used NeXTSTEP as the basis of their software stack, which is written in Objective-C. Unlike most systems languages with object orientation, Objective-C implements OOP as a runtime library. In fact, Objective-C is just C with the weird OOP specific syntax rewritten into C calls to libobjc, which is a normal C library implementing an object runtime. This runtime could be used to bring OOP to any language that can make calls to C code. It also lets you interact with objects and classes registered by other libraries, such as the Apple frameworks.

At the heart of DarwinKit is a package wrapping the Objective-C runtime using cgo and libffi. This is actually all you need to interact with Objective-C objects and classes, it'll just look like this:

app := objc.Call[objc.Object](objc.GetClass("NSApplication"), objc.Sel("sharedApplication"))
objc.Call[objc.Void](app, objc.Sel("run"))

So we wrap these calls in a Go API that lets us write code like this:

app := appkit.Application_SharedApplication()
app.Run()

These bindings are great, but we need to define them for every API we want to use. Presently, Apple has around 200 frameworks of nearly 5000 classes with 77k combined methods and properties. Not to mention all the constants, functions, structs, unions, and enums we need to work with those objects.

So DarwinKit generates its bindings. This is the hard part. Making sure the generation pipeline accurately produces usable bindings for all possible symbols is quite an arduous, iterative, manual process. Then since we're moving symbols that lived in a single namespace into Go packages, we have to manually decouple dependencies between them enough to avoid circular imports. If you want to help add frameworks, read our documentation on generation.

Objects are passed around as typed pointer values in Objective-C. When we receive an object from a method call in Go, the objc package receives it as a raw pointer, which it first puts into an unsafe.Pointer. The bindings for a class define a struct type that embeds an objc.Object struct, which contains a single field to hold the unsafe.Pointer. So unless working with a primitive type, you're working with an unsafe.Pointer wrapped in an objc.Object wrapped in a struct type that has the methods for the class of the object of the pointer. Be sure to read our documentation on memory management.

If you have questions, feel free to ask in the discussion forums.

Thanks

This project was inspired by and originally based on packages written by Mikkel Krautz. The latest version is based on packages written by Dong Liu.

Notice

This project is not affiliated or supported by Apple.

License

MIT

macdriver's People

Contributors

aidansteele avatar alessiodionisi avatar bob620 avatar bradfitz avatar catilac avatar charliego3 avatar corruptmemory avatar firelizzard18 avatar flexzuu avatar fserb avatar mgood avatar mkrautz avatar mvrilo avatar programmingkidx avatar progrium avatar revilon1991 avatar tmc avatar totallygamerjet avatar yummyweb avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

macdriver's Issues

free CString and CBytes

(Making note so I don't forget, but I'll try to come back and fix this)

Based on the cgo docs CString and CBytes use malloc to allocate memory and must be released with C.free.

There are a number of uses throughout objc and core where it's used inline, e.g.:

C.GoObjc_RegisterSelector(C.CString(name))

We should go through and add C.free as needed for each of these.

Adding CoreWLAN

@progrium Hope you are fine. Is there any plan to add corewlan module? If not anyone here can guide me to add things. Thanks.

Question: list all applications and application windows

Hi!

First, thanks for your awesome work on macdriver!

Question: is it possible to list active applications and their windows, or just all the active windows? I looked through macdriver and didn't find anything like "list applications" or "list windows". I checked StackOverflow, the only suggestion I found is "accessibility API" but I didn't find such binding in macdriver.

Thanks!

Todo for the project

It would be great if a contributing guide or a todo for the project is created to support individuals interested in the project.

NSImage with drawingHandler

Hi.

Is there a way to support NSImage init with drawingHandler to create dynamically drawn images.

If this init is not supported, is there another way around it? I.e. create the image first and then set it.

Support for NSWorkspace

๐Ÿ‘‹ are there any plans to support NSWorkspace.

I have a trivial application I'd like to migrate to test this library which opens links from a menu item. Natively, I use:

NSWorkspace.shared.open(url)

integrate objc `release` with Go garbage collector

as mentioned in #12, not using a pointer for type object means its passed as a value. i believe the suggestion was to use it as a pointer type so we could use SetFinalizer effectively. however, this brings up some questions.

since sendMsg creates (maybe all) object values, would we want to track those pointer values so there is only one object in go holding reference to an objc pointer?

would this negate the need for using autoreleasepool at all?

NSNib issues

I have some issues with the NSNib interface. My preferred solution would be API-breaking, which may be OK because the project is still pre-v1:

  • NSNib_Init - This uses a specific init method, so IMO it should be named something like NSNib_InitWithName
  • I'd like to add a wrapper for init from NSData, e.g. NSNib_InitWithData
  • InstantiateWithOwner discards the return value. instantiateNibWithOwner:topLevelObjects: can return false - that should be passed to the caller as a boolean.
  • instantiateNibWithOwner:topLevelObjects: is deprecated in favor of instantiateWithOwner:topLevelObjects:. The difference is that the latter requires the caller to retain any objects they are interested in. If I understand correctly, retaining a reference to the nib, the array, or a given object is sufficient to keep the object from being deallocated.

I'm happy to open a PR with these changes.

The readme says "1:1 mapping of API names with Objective-C APIs", and it sounds like the eventual goal is to use a generator. In that case, shouldn't the Go function names match the Objective-C method names?

How to install or incorporate into a project

Thanks a lot for the hard work on this. Looks perfect.

As the title suggests though I'd appreciate some guidance in the README on how to use this package within another project. Probably related to #1 but at the moment I believe the examples only work within the package itself?

Running a go get -u github.com/progrium/macdriver gives the following.

โžœ go get -u github.com/progrium/macdriver        
go: github.com/progrium/macdriver upgrade => v0.0.0-20201231002616-feae31acadf8
go get: github.com/progrium/[email protected] requires
        github.com/manifold/[email protected]: reading github.com/manifold/qtalk/go.mod at revision v0.0.0: unknown revision v0.0.0

I have an existing project where I'm looking to see if I can replace direct calls to Objective C (and then import "C" within Go) with this package instead.

(Also. It's highly likely this is my unfamiliarity with Go versus anything with the package so apologies in advance...)

generate enum & type alias definitions

Objective-C uses enums & type aliases quite often. The manually written macdriver code often only includes a subset that was needed at the time, but it would help to more easily import these into the generated code to ensure we have all the necessary values.

For enums we generally should have a Value listed that we could include directly in the Go code like:

const NSWindowStyleMaskBorderless = 0

However there are some things like the NSWindowLevel type alias where the docs don't include the actual values, and just the declaration const NSWindowLevel NSDockWindowLevel;. So an approach that would handle both is to use CGo, including the necessary headers and then:

const NSDockWindowLevel = C.NSDockWindowLevel

We should also generate the corresponding Go type names like:

type NSWindowStyleMask NSUInteger

Provide and document @autoreleasepool block equivalent

From this thread: https://news.ycombinator.com/item?id=26028441

If you call into Cocoa APIs from foreign threads without an @autoreleasepool block active, the APIs will leak memory.

https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmAutoreleasePools.html

Cocoa always expects code to be executed within an autorelease pool block, otherwise autoreleased objects do not get released and your application leaks memory

This StackOverflow answer suggests the @autoreleasepool block is implemented by generating calls to these objc runtime functions:

void *_objc_autoreleasePoolPush(void);
_objc_autoreleasePoolPop(void *ctxt); // ctxt is Apple's label for the param

Here's an example of how you might provide the API: https://play.golang.org/p/dljXN3BdEGr

I also suggest prominently documenting this once it is implemented, as any long running app calling into Cocoa APIs will leak without it.

Request: add nib file example

Hi, I am wishing for a nib file example using Go. I think most people out there will be making their interface using Xcode rather than thru code, so this example could help a lot of people out.

return NSWorkspace runningApplications array

Im trying to return an array of NSApplication from NSWorkspace.runningApplications. im having trouble working out how i can turn the returned value from "Get("runningApplications")" into an array of "NSRunningApplication" any help is appreciated.

Also im loving the work you've done, it's coming in real handy :)

`type NSWorkspace struct {
objc.Object
}

type NSRunningApplication struct {
objc.Object
}

var NSWorkspace_ = NSWorkspace{objc.Get("NSWorkspace")}

func NSWorkspace_New() NSWorkspace {
return NSWorkspace{NSWorkspace_.Alloc().Init()}
}

func (ws NSWorkspace) RunningApplications() {
i := ws.Get("runningApplications")

}`

menuitem .SetTitle() open/closes systray every time its called

Im in the process of moving over some code that's using https://github.com/getlantern/systray to macdriver. I have hit a weird issue where every call to menuitem .SetTitle() open/closes systray. When using https://github.com/getlantern/systray im able to set the item title as many time as i want without hitting this issue.

A simple bit of code that reproduces the issue. Run the code and then click on the systray icon, you will see the systray open and close every second.

go 1.16rc1

`package main

import (
"runtime"
"strconv"
"time"

"github.com/progrium/macdriver/cocoa"
"github.com/progrium/macdriver/objc"

)

func Run() {
runtime.LockOSThread()

app := cocoa.NSApp_WithDidLaunch(func(n objc.Object) {
	obj := cocoa.NSStatusBar_System().StatusItemWithLength(cocoa.NSVariableStatusItemLength)
	obj.Retain()
	obj.Button().SetTitle("counting")

	itemNext := cocoa.NSMenuItem_New()

	go func() {
		timer := 1
		for {
			select {
			case <-time.After(1 * time.Second):
				itemNext.SetTitle(strconv.Itoa(timer))
				timer++
			}
		}
	}()
	menu := cocoa.NSMenu_New()
	menu.AddItem(itemNext)
	obj.SetMenu(menu)

})
app.Run()

}`

retain or not

Hi thanks for the awesome package.
I have some questions about the example: pomodoro.
the source snippets

obj := cocoa.NSStatusBar_System().StatusItemWithLength(cocoa.NSVariableStatusItemLength)
obj.Retain()

and

itemNext := cocoa.NSMenuItem_New()

they all about create instance, why the first one need retain, but the second one is NOT, if the first ONE is about MRC and the second is about ARC, why there is no release for the first one, thanks

Compilation warnings with v0.2.0

Hi, I've started getting these errors since the v0.2.0 release:

$ make install
go install github.com/progrium/shelldriver/cmd/[email protected]
# github.com/progrium/macdriver/core
../../../go/pkg/mod/github.com/progrium/[email protected]/core/core_objc.gen.go:172:3: warning: class method '+localizedUserNotificationStringForKey:arguments:' not found (return type defaults to 'id') [-Wobjc-method-access]
../../../go/pkg/mod/github.com/progrium/[email protected]/core/core_objc.gen.go:887:3: warning: instance method '-shuffledArray' not found (return type defaults to 'id') [-Wobjc-method-access]

I'm on an M1 mac with Big Sur (11.4). I get the same thing when I try to compile with emulation:

$ arch -x86_64 make install
go install github.com/progrium/shelldriver/cmd/[email protected]
# github.com/progrium/macdriver/core
../../../go/pkg/mod/github.com/progrium/[email protected]/core/core_objc.gen.go:172:3: warning: class method '+localizedUserNotificationStringForKey:arguments:' not found (return type defaults to 'id') [-Wobjc-method-access]
../../../go/pkg/mod/github.com/progrium/[email protected]/core/core_objc.gen.go:887:3: warning: instance method '-shuffledArray' not found (return type defaults to 'id') [-Wobjc-method-access]

Is there something I can update to get this working?

Tutorial on how to add new Objective-C classes to MacDriver

Currently there is no step by step directions on how to add Objective-c classes to MacDriver. I ask that this tutorial be made.

My current idea is to make a program that scans an Objective-C class header file and records all the methods and their arguments into an API database. Then a second program can take the data in the API database and translate it into Go code making an automatic wrapper.

How to use printOperationWithPrintInfo with webkit framework ?

I want to use webkit framework to load a URL, and using printOperationWithPrintInfo, on button click, I want to show dialog box to print the webpage.

I am new to macOS development and am building a macOS app in golang using macdriver.

I have followed examples/topframe to launch WKWebView to show my URL. printOperationWithPrintInfo is mentioned in macdriver/api/webkit/wkwebview.objc.json but I am not getting how to proceed further to connect printOperationWithPrintInfo with it.

There is limited documentation online and would appreciate some direction on how to proceed.

error: returning 'id' from a function with incompatible result type 'double'

I tried to run all the examples in the example folder, but saw these errors every time:

cocoa/cocoa_objc.gen.go:3043:9: error: returning 'id' from a function with incompatible result type 'double'
        return [(NSScreen*)id
               ^~~~~~~~~~~~~~
cocoa/cocoa_objc.gen.go:3053:9: error: returning 'id' from a function with incompatible result type 'double'
        return [(NSScreen*)id

How to reproduce:
cd to root level of the macdriver folder.
Build the OpenGL example like this: go build ./examples/opengl/main.go

My info:
Mac OS 10.14
Go 1.18

Notes:
I used the June 11th version of MacDriver.
I downloaded a zip file from GitHub.com.

unavailable features in WKWebView

Thanks for this great project! I'm really excited about it. I have tested wetransfer.com and filebin.net in a WKWebView but was unable to open a file chooser. Is it supported yet? If not, any clues how can one implement or fix this? I'm interested in helping.

Original title:
<input type="file"> doesn't work when using webkit WKWebView

Request: official tutorial

I ask that a tutorial on how to use MacDriver be made please. I'm hoping for a YouTube video and a web page ๐Ÿ˜.

NSApp_WithDidLaunch callback passes wrong object

The function NSApp_WithDidLaunch takes a callback that is supposed to pass the notification object. But since the first thing sent to any objective-c function is the pointer to the "self" object, the wrong object is passed to the callback. Therefore calling any of the notification methods on it causes an unrecognizable selector exception.
Reproducible code:

  package main

  import (
      "fmt"
      "github.com/progrium/macdriver/cocoa"
      "github.com/progrium/macdriver/core"
      "github.com/progrium/macdriver/objc"
      "runtime"
  )
  
  func main() {
      runtime.LockOSThread()
      pool := core.NSAutoreleasePool_New()
      defer pool.Release()
      var window cocoa.NSWindow
      app := cocoa.NSApp_WithDidLaunch(func(notification objc.Object) {
	      fmt.Println(notification.Get("name").String())
	      // create a reference rect
	      contentSize := core.NSMakeRect(0, 0, 800, 600)
  
	      // allocate window
	      window = cocoa.NSWindow_Init(contentSize, cocoa.NSTitledWindowMask, cocoa.NSBackingStoreBuffered, true)
  
	      // allocate view
	      window.MakeKeyAndOrderFront(window)
      })
      app.SetActivationPolicy(cocoa.NSApplicationActivationPolicyRegular)
      app.ActivateIgnoringOtherApps(true)
      app.Run()
 }

This is the error:
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[DefaultDelegate name]: unrecognized selector sent to instance 0x450a3c0'

The solution is to either change the callback function signature to accommodate the "self" object or wrap the callback in another function so it works properly. I prefer the second option which would look something like this.
cocoa/NSApplication.go

func NSApp_WithDidLaunch(cb func(notification objc.Object)) NSApplication {
	DefaultDelegateClass.AddMethod("applicationDidFinishLaunching:", func(_, notification objc.Object) {
              cb(notification)
        })
	app := NSApp()
	app.SetDelegate(DefaultDelegate)
	return app
}

fatal error: 'objc/runtime.h' file not found

Hey @progrium ๐Ÿ‘‹

Thank you so much for macdriver, you have no idea how excited I am about this ๐Ÿ™Œ

I feel a bit silly not even being able to get going on the largetype example, but I get:

# github.com/progrium/macdriver/objc
../../../../go/pkg/mod/github.com/progrium/[email protected]/objc/class.go:10:10: fatal error: 'objc/runtime.h' file not found
#include <objc/runtime.h>
         ^~~~~~~~~~~~~~~~
1 error generated.

When I try to go run *.go with main.go containing the example's contents.
I've set up with the usual go mod init ... and go mod download.
Tried go get -u and CGO_ENABLED=1 go run *.go just in case, but it's the same results.

I'm sure it's just something dead simple that I'm missing ๐Ÿ˜…

Is example code running outside main goroutine unsafe?

My (very rusty) knowledge of Cocoa is that actions in the UI need to happen on the "main thread" / run loop. I assume think is why runtime.LockOSThread() is used in all of the examples. But it looks like the Pomodoro example has a menu item's title being changed from a different goroutine:


...
obj.Button().SetTitle(fmt.Sprintf(labels[state], timer/60, timer%60))

It appears to be working ok. My memory (again, faulty) is that these sorts of things can appear to work ok for a while, but fail in mysterious ways as the program becomes more complex. Is there some kind of wizardry going on that makes this code ok? Or should it be happening inside the Cocoa app's run loop?

unable to implement keyDown of NSView subclass

It seems you can subclass alright, both NSObject and NSView, however when actually using it there seems to be some missing information. The examples/subclass program demonstrates a program with a Window that uses a custom NSView to capture keydown events. It implements and seems to call acceptsFirstResponder since a keypress will trigger the crash (without acceptsFirstResponder it will do nothing as expected, see this), but keyDown is not called because of this error (press a key after the window appears):

$ CGO_CFLAGS="-w" go run main.go
2023/03/10 16:57:52 Program started.
2023/03/10 16:57:52 App started.
panic: interface conversion: reflect.Type is nil, not *reflect.rtype

goroutine 1 [running]:
reflect.NewAt(...)
        /usr/local/Cellar/go/1.19/libexec/src/reflect/value.go:3103
github.com/progrium/macdriver/objc.goMethodCallEntryPoint(0x4006b86?)
        /Users/progrium/Source/github.com/progrium/macdriver/objc/call_amd64.go:173 +0x2d85
...

OpenGL app crashes

I have a GTK app. I want to use macdriver to implement a native UI. The project is https://gitlab.com/eukano/runway. I'm executing go run ./cmd/runway view. It works for a few minutes or a few seconds, but it always crashes.

It occasionally fails in GC (in Go): gc1.log, gc2.log (GC error dumps are pretty long). Most of the time my app fails during an Objective-C call:

$ go run ./cmd/runway view
fatal error: unexpected signal during runtime execution
[signal SIGSEGV: segmentation violation code=0x1 addr=0x143545348 pc=0x7fff201aee89]

runtime stack:
runtime.throw(0x4c901c3, 0x2a)
        /GOROOTS/1.16.2/go/src/runtime/panic.go:1117 +0x72
runtime.sigpanic()
        /GOROOTS/1.16.2/go/src/runtime/signal_unix.go:718 +0x2ef

goroutine 1 [syscall, locked to thread]:
runtime.cgocall(0x4a50e10, 0xc0002fece8, 0x8)
        /GOROOTS/1.16.2/go/src/runtime/cgocall.go:154 +0x5b fp=0xc0002fecb8 sp=0xc0002fec80 pc=0x4006f7b
github.com/progrium/macdriver/objc._Cfunc_GoObjc_TypeInfoForMethod(0x143545348, 0x7fff7c628991, 0x0)
        _cgo_gotypes.go:263 +0x49 fp=0xc0002fece8 sp=0xc0002fecb8 pc=0x4a1bfe9
github.com/progrium/macdriver/objc.typeInfoForMethod.func1(0x5107518, 0xc00063e378, 0x7fff7c628991, 0xc00063e378)
        /PROJ/macdriver/objc/selector.go:85 +0x96 fp=0xc0002fed20 sp=0xc0002fece8 pc=0x4a25e56
github.com/progrium/macdriver/objc.typeInfoForMethod(0x5106da8, 0xc00063e370, 0x4c3da0c, 0xd, 0xc0002feda8, 0x4a1bd25)
        /PROJ/macdriver/objc/selector.go:85 +0x7d fp=0xc0002fed58 sp=0xc0002fed20 pc=0x4a24cdd
github.com/progrium/macdriver/objc.simpleTypeInfoForMethod(0x5106da8, 0xc00063e370, 0x4c3da0c, 0xd, 0xbff0000000000000, 0x0)
        /PROJ/macdriver/objc/selector.go:113 +0x59 fp=0xc0002fede0 sp=0xc0002fed58 pc=0x4a24d79
github.com/progrium/macdriver/objc.sendMsg(0x5106da8, 0xc00063e370, 0x4c3b11f, 0xc, 0x4c3da0c, 0xd, 0x0, 0x0, 0x0, 0x0, ...)
        /PROJ/macdriver/objc/msg_amd64.go:85 +0xe9 fp=0xc0002fefb8 sp=0xc0002fede0 pc=0x4a214a9
github.com/progrium/macdriver/objc.object.Send(...)
        /PROJ/macdriver/objc/msg_amd64.go:234
github.com/progrium/macdriver/objc.(*object).Send(0xc00063e338, 0x4c3da0c, 0xd, 0x0, 0x0, 0x0, 0x5106da8, 0x561ff00)
        <autogenerated>:1 +0xa8 fp=0xc0002ff020 sp=0xc0002fefb8 pc=0x4a28088
main.(*GLView).drawRect(0xc000caa018, 0x100000000000000)
        /PROJ/runway/cmd/runway/view_cocoa.go:172 +0x139 fp=0xc0002ff080 sp=0xc0002ff020 pc=0x4a47079
runtime.call16(0xc000ca6120, 0x4f8c5f0, 0xc000122930, 0x1000000010)
        /GOROOTS/1.16.2/go/src/runtime/asm_amd64.s:550 +0x3e fp=0xc0002ff0a0 sp=0xc0002ff080 pc=0x4078a1e
reflect.Value.call(0x4adf7a0, 0x4f8c5f0, 0x13, 0x4c2a426, 0x4, 0xc000ca6510, 0x2, 0x2, 0x2, 0x18, ...)
        /GOROOTS/1.16.2/go/src/reflect/value.go:476 +0x8e7 fp=0xc0002ff2a8 sp=0xc0002ff0a0 pc=0x40b9c67
reflect.Value.Call(0x4adf7a0, 0x4f8c5f0, 0x13, 0xc000ca6510, 0x2, 0x2, 0x1, 0x2, 0x0)
        /GOROOTS/1.16.2/go/src/reflect/value.go:337 +0xb9 fp=0xc0002ff328 sp=0xc0002ff2a8 pc=0x40b9139
github.com/progrium/macdriver/objc.goMethodCallEntryPoint(0x7ffeefbfc040, 0x40074fb)
        /PROJ/macdriver/objc/call_amd64.go:273 +0x27f0 fp=0xc0002ff7a8 sp=0xc0002ff328 pc=0x4a1edd0
_cgoexp_6ee9b331048c_goMethodCallEntryPoint(0x7ffeefbfc010)
        _cgo_gotypes.go:297 +0x2e fp=0xc0002ff7c8 sp=0xc0002ff7a8 pc=0x4a2604e
runtime.cgocallbackg1(0x4a26020, 0x7ffeefbfc010, 0x0)
        /GOROOTS/1.16.2/go/src/runtime/cgocall.go:292 +0x18c fp=0xc0002ff868 sp=0xc0002ff7c8 pc=0x400732c
runtime.cgocallbackg(0x4a26020, 0x7ffeefbfc010, 0x0)
        /GOROOTS/1.16.2/go/src/runtime/cgocall.go:228 +0xda fp=0xc0002ff8d8 sp=0xc0002ff868 pc=0x40070fa
runtime.cgocallback(0x4006f9f, 0x4a5f0b0, 0xc0002ff970)
        /GOROOTS/1.16.2/go/src/runtime/asm_amd64.s:788 +0xa9 fp=0xc0002ff900 sp=0xc0002ff8d8 pc=0x407a1e9
runtime.asmcgocall(0x4a5f0b0, 0xc0002ff970)
        /GOROOTS/1.16.2/go/src/runtime/asm_amd64.s:652 +0x42 fp=0xc0002ff908 sp=0xc0002ff900 pc=0x407a0c2
runtime.cgocall(0x4a5f0b0, 0xc0002ff970, 0xc0002ff980)
        /GOROOTS/1.16.2/go/src/runtime/cgocall.go:164 +0x7f fp=0xc0002ff940 sp=0xc0002ff908 pc=0x4006f9f
github.com/progrium/macdriver/misc/variadic._Cfunc_VariadicCall(0xc000150090, 0x0)
        _cgo_gotypes.go:73 +0x45 fp=0xc0002ff970 sp=0xc0002ff940 pc=0x4a1a565
github.com/progrium/macdriver/misc/variadic.(*FunctionCall).Call.func1(0xc000150090, 0xc0002ffa0c)
        /PROJ/macdriver/misc/variadic/variadic_amd64.go:68 +0x4d fp=0xc0002ff9a0 sp=0xc0002ff970 pc=0x4a1a9ad
github.com/progrium/macdriver/misc/variadic.(*FunctionCall).Call(0xc000150090, 0x76)
        /PROJ/macdriver/misc/variadic/variadic_amd64.go:68 +0x2b fp=0xc0002ff9c0 sp=0xc0002ff9a0 pc=0x4a1a86b
github.com/progrium/macdriver/objc.sendMsg(0x5106da8, 0xc00063e120, 0x4c3b11f, 0xc, 0x4c2a10e, 0x3, 0x0, 0x0, 0x0, 0x0, ...)
        /PROJ/macdriver/objc/msg_amd64.go:230 +0x705 fp=0xc0002ffb98 sp=0xc0002ff9c0 pc=0x4a21ac5
github.com/progrium/macdriver/objc.object.Send(...)
        /PROJ/macdriver/objc/msg_amd64.go:234
github.com/progrium/macdriver/objc.(*object).Send(0xc000389200, 0x4c2a10e, 0x3, 0x0, 0x0, 0x0, 0x5106da8, 0x561ff08)
        <autogenerated>:1 +0xa8 fp=0xc0002ffc00 sp=0xc0002ffb98 pc=0x4a28088
github.com/progrium/macdriver/cocoa.NSApplication.Run(...)
        /PROJ/macdriver/cocoa/NSApplication.go:51
main.viewRun(0x56a5340, 0x570c4e0, 0x0, 0x0)
        /PROJ/runway/cmd/runway/view_cocoa.go:128 +0x376 fp=0xc0002ffcc0 sp=0xc0002ffc00 pc=0x4a46936
github.com/spf13/cobra.(*Command).execute(0x56a5340, 0x570c4e0, 0x0, 0x0, 0x56a5340, 0x570c4e0)
        /GOROOTS/1.16.2/packages/pkg/mod/github.com/spf13/[email protected]/command.go:856 +0x2c2 fp=0xc0002ffd80 sp=0xc0002ffcc0 pc=0x42094e2
github.com/spf13/cobra.(*Command).ExecuteC(0x56a4940, 0x4c2d747, 0x6, 0x4c64d38)
        /GOROOTS/1.16.2/packages/pkg/mod/github.com/spf13/[email protected]/command.go:960 +0x375 fp=0xc0002ffe60 sp=0xc0002ffd80 pc=0x420a215
main.main()
        /PROJ/runway/cmd/runway/main.go:37 +0x21c fp=0xc0002fff88 sp=0xc0002ffe60 pc=0x4a4563c
runtime.main()
        /GOROOTS/1.16.2/go/src/runtime/proc.go:225 +0x256 fp=0xc0002fffe0 sp=0xc0002fff88 pc=0x4041536
runtime.goexit()
        /GOROOTS/1.16.2/go/src/runtime/asm_amd64.s:1371 +0x1 fp=0xc0002fffe8 sp=0xc0002fffe0 pc=0x407a461
exit status 2

v0.1.0 release

I try to roughly follow semantic versioning where you'll notice the first release is typically v0.1.0, but we're on v0.0.2. This 0.0.x phase is what I might call development pre-release, where the project has even less guarantees for stability and consistency across versions. I have to do this because not only do I work in the open as much as I can, but there are some issues I won't catch that are important and the shape of the problem of the project is still loose. I'd also like to figure out who might be around to help maintain the project to shepherd to a 1.0 release, since I'm unfortunately too busy to focus on any single project reliably.

The way I think of a v0.1.0 release in this case is to make sure initially discovered fundamental problems (such as #12) are solved and/or documented, that there is the start of documentation (the wiki and godocs), and a better idea of conventions and idioms for the project. I think we are very close. I'd like to use this issue to track progress, though keep in mind this is much looser than a definition of 1.0, which is an open discussion conversation.

  • Identify and document conventions for adding new wrapper types/code [#31]
  • Outline start for wiki documentation

Hopefully not much more. Many of these are just making sure things are started not finished, as that's more the role of 1.0.

Drop support for 386

  • Apple has not produced a 32-bit mac since 2007
  • iDevices are not relevant to this, because they all run on ARM
  • Go 1.15 dropped all support for 32-bit darwin (darwin/386 and darwin/arm)

@progrium @flexzuu Is there any reason to continue supporting 386?

How to monitor shortcut behavior

environment

  • macos verison: 11.2.3
  • github.com/progrium/macdriver v0.0.3-0.20210330171321-295658df6845

describe

I want to develop a shortcut function. But I couldn't capture the user's keyboard press event.

	events := make(chan cocoa.NSEvent)
	go func() {
		for e := range events {
			fmt.Println(e)
		}
	}()

	cocoa.NSEvent_GlobalMonitorMatchingMask(cocoa.NSEventMaskAny, events)

image

Only mouse/ctrl/option/command press events can be captured.

expect

Is there any other good way? or any example? thx.

NSDictionary and golang strings issue

package main

import "github.com/progrium/macdriver/core"
import "fmt"

func main() {
	dict := core.NSDictionary_Init("one", "two")
	fmt.Println("dictionary:", dict)
}

This program adds golang strings to an NSDictionary. When the program is ran it panics with this message:

2023/07/02 00:20:26 unhandled kind: string
panic: unhandled kind: string

goroutine 1 [running]:
log.Panicf({0x1004c14a8?, 0x1004ed2c0?}, {0x140000abe30?, 0x140000b4010?, 0x100918d28?})
/usr/local/go/src/log/log.go:391 +0x64
github.com/progrium/macdriver/objc.sendMsg({0x1005044e8, 0x140000b4020}, 0x0, {0x1004c2495, 0x17}, {0x140000c0000, 0x2, 0x1004b3f38?})
/Users/user/go/pkg/mod/github.com/progrium/[email protected]/objc/msg_arm64.go:159 +0xf28
github.com/progrium/macdriver/objc.object.Send(...)
/Users/user/go/pkg/mod/github.com/progrium/[email protected]/objc/msg_arm64.go:206
github.com/progrium/macdriver/core.NSDictionary_Init({0x140000c0000, 0x2, 0x2})
/Users/user/go/pkg/mod/github.com/progrium/[email protected]/core/NSDictionary.go:17 +0x50
main.main()
/Users/user/desktop/my go app/main.go:7 +0x58
exit status 2

Could a feature be added that makes golang strings usable in an NSDictionary?

NSArray_withObjects() causing segmentation violation

I was doing a test of NSArray. Using this program below causes a segmentation violation at the NSArray_WithObjects() function:

package main

import "github.com/progrium/macdriver/core"
import "fmt"

func main() {
	oneString := core.NSString_FromString("One")
	myArray := core.NSArray_WithObjects(oneString, nil)
	fmt.Println("array:", myArray)
}

I made a very similar program in objective-c and it worked correctly. This is it:

#import <Foundation/Foundation.h>

void main()
{
    NSString *oneString = @"One";
    NSArray *myArray = [NSArray arrayWithObjects: oneString, nil];
    NSLog(@"array: %@", myArray);
}

I am using Mac OS 12.3.1 on an M1 chip.

Here is the error:

fatal error: unexpected signal during runtime execution
[signal SIGSEGV: segmentation violation code=0x2 addr=0x20 pc=0x183d004b0]

runtime stack:
runtime.throw({0x102be9fe1?, 0x16d2c7390?})
/usr/local/go/src/runtime/panic.go:1047 +0x40 fp=0x16d2c7350 sp=0x16d2c7320 pc=0x102b6bac0
runtime.sigpanic()
/usr/local/go/src/runtime/signal_unix.go:821 +0x240 fp=0x16d2c7390 sp=0x16d2c7350 pc=0x102b80550

goroutine 1 [syscall]:
runtime.cgocall(0x102be2920, 0x14000115c18)
/usr/local/go/src/runtime/cgocall.go:157 +0x50 fp=0x14000115be0 sp=0x14000115ba0 pc=0x102b3e040
github.com/progrium/macdriver/misc/variadic._Cfunc_VariadicCall(0x1400010e750)
_cgo_gotypes.go:105 +0x34 fp=0x14000115c10 sp=0x14000115be0 pc=0x102bd0664
github.com/progrium/macdriver/misc/variadic.(*FunctionCall).Call.func1(0x14000115c68?)
/Users/user/go/pkg/mod/github.com/progrium/[email protected]/misc/variadic/variadic_arm64.go:77 +0x40 fp=0x14000115c50 sp=0x14000115c10 pc=0x102bd0810
github.com/progrium/macdriver/misc/variadic.(*FunctionCall).Call(0x1400010e750)
/Users/user/go/pkg/mod/github.com/progrium/[email protected]/misc/variadic/variadic_arm64.go:77 +0x20 fp=0x14000115c70 sp=0x14000115c50 pc=0x102bd07a0
github.com/progrium/macdriver/objc.sendMsg({0x102c2a160, 0x1400001c0d0}, 0x0, {0x102be4f82, 0x11}, {0x1400006c020, 0x2, 0x102c2a2e0?})
/Users/user/go/pkg/mod/github.com/progrium/[email protected]/objc/msg_arm64.go:202 +0x13a4 fp=0x14000115e10 sp=0x14000115c70 pc=0x102bd5604
github.com/progrium/macdriver/objc.object.Send(...)
/Users/user/go/pkg/mod/github.com/progrium/[email protected]/objc/msg_arm64.go:206
github.com/progrium/macdriver/objc.(*object).Send(0x102be355d?, {0x102be4f82?, 0x11?}, {0x1400006c020?, 0x2?, 0x2?})
:1 +0x78 fp=0x14000115e70 sp=0x14000115e10 pc=0x102bd6d48
github.com/progrium/macdriver/core.NSArray_WithObjects({0x14000115f28, 0x2, 0x14000115f28?})
/Users/user/go/pkg/mod/github.com/progrium/[email protected]/core/NSArray.go:22 +0xd4 fp=0x14000115ed0 sp=0x14000115e70 pc=0x102bd72f4
main.main()
/Users/user/desktop/my go app/main.go:8 +0x70 fp=0x14000115f70 sp=0x14000115ed0 pc=0x102bd98a0
runtime.main()
/usr/local/go/src/runtime/proc.go:250 +0x200 fp=0x14000115fd0 sp=0x14000115f70 pc=0x102b6e080
runtime.goexit()
/usr/local/go/src/runtime/asm_arm64.s:1172 +0x4 fp=0x14000115fd0 sp=0x14000115fd0 pc=0x102b98834

Add go bindings for `NSWorkspace`

It would be nice to have access to the NSWorkspace APIs in go, especially around launching applications and determining what apps are running.

Addig CoreBluetooth

It would be nice to have the CoreBluetooth module in the repository. I wanted to add it, but I faced with several issues. If you can help me with these I can handle the rest and creating the PR. (Assume I'm not a Mac programmer)

  1. The core bluetooth delegate implementations are Protocols, I don't know what does it mean, but the macschema can't handle it. (I cloned the repo and I built my own version, so I'm running on latest.) How can I add implementation to the macschema to handle this?
  2. If you check this, I added the generated api descriptors and it's generating the corebluetooth just fine. (Obviously I left out the delegate ones, because those were empty descriptors). But I needed to leave out the Enum descriptors as well, because I got a nil dereference error, from this section. (I just skipped this if it's Enum just for curiosity, and I got an other one from somewhere else). So it seems it's only handling Classes.

Let me know your thoughts, if you can help me, I can invest sometime to add these features.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.