Skip to content

Commit 9a9a0d6

Browse files
authored
macos helper updates (#198)
* have RunApp handle LockOSThread * updated examples to use RunApp API * added doc examples in macos package * also added MenuItem_SeparatorItem() * used proper New methods in Menu helpers
1 parent 66531b8 commit 9a9a0d6

File tree

16 files changed

+284
-297
lines changed

16 files changed

+284
-297
lines changed

README.md

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,20 +19,13 @@ DarwinKit lets you work with [supported Apple frameworks](https://pkg.go.dev/git
1919
package main
2020

2121
import (
22-
"runtime"
23-
2422
"github.com/progrium/macdriver/objc"
2523
"github.com/progrium/macdriver/macos"
2624
"github.com/progrium/macdriver/macos/appkit"
2725
"github.com/progrium/macdriver/macos/foundation"
2826
"github.com/progrium/macdriver/macos/webkit"
2927
)
3028

31-
func init() {
32-
// ensure main is run on the startup thread
33-
runtime.LockOSThread()
34-
}
35-
3629
func main() {
3730
// runs macOS application event loop with a callback on success
3831
macos.RunApp(func(app appkit.Application, delegate *appkit.ApplicationDelegate) {

macos/_examples/form/main.go

Lines changed: 9 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,21 @@
11
package main
22

33
import (
4-
"runtime"
5-
64
"github.com/progrium/macdriver/helper/layout"
75
"github.com/progrium/macdriver/helper/widgets"
6+
"github.com/progrium/macdriver/macos"
87
"github.com/progrium/macdriver/macos/appkit"
98
"github.com/progrium/macdriver/macos/foundation"
9+
"github.com/progrium/macdriver/objc"
1010
)
1111

12-
// Arrange that main.main runs on main thread.
13-
func init() {
14-
runtime.LockOSThread()
12+
func main() {
13+
macos.RunApp(launched)
1514
}
1615

17-
func initAndRun() {
18-
app := appkit.Application_SharedApplication()
19-
app.SetActivationPolicy(appkit.ApplicationActivationPolicyRegular)
20-
app.ActivateIgnoringOtherApps(true)
16+
func launched(app appkit.Application, delegate *appkit.ApplicationDelegate) {
2117
w := appkit.NewWindowWithSize(600, 400)
18+
objc.Retain(&w)
2219
w.SetTitle("Form")
2320

2421
fv := widgets.NewFormView()
@@ -38,19 +35,9 @@ func initAndRun() {
3835
w.MakeKeyAndOrderFront(nil)
3936
w.Center()
4037

41-
ad := &appkit.ApplicationDelegate{}
42-
ad.SetApplicationDidFinishLaunching(func(foundation.Notification) {
43-
app.SetActivationPolicy(appkit.ApplicationActivationPolicyRegular)
44-
app.ActivateIgnoringOtherApps(true)
45-
})
46-
ad.SetApplicationShouldTerminateAfterLastWindowClosed(func(appkit.Application) bool {
38+
delegate.SetApplicationShouldTerminateAfterLastWindowClosed(func(appkit.Application) bool {
4739
return true
4840
})
49-
app.SetDelegate(ad)
50-
51-
app.Run()
52-
}
53-
54-
func main() {
55-
initAndRun()
41+
app.SetActivationPolicy(appkit.ApplicationActivationPolicyRegular)
42+
app.ActivateIgnoringOtherApps(true)
5643
}

macos/_examples/helloworld/main.go

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,13 @@
11
package main
22

33
import (
4-
"runtime"
5-
64
"github.com/progrium/macdriver/macos"
75
"github.com/progrium/macdriver/macos/appkit"
86
"github.com/progrium/macdriver/macos/foundation"
97
"github.com/progrium/macdriver/macos/webkit"
108
"github.com/progrium/macdriver/objc"
119
)
1210

13-
func init() {
14-
// ensure main is run on the startup thread
15-
runtime.LockOSThread()
16-
}
17-
1811
func main() {
1912
// runs macOS application event loop with a callback on success
2013
macos.RunApp(func(app appkit.Application, delegate *appkit.ApplicationDelegate) {

macos/_examples/largetype/main.go

Lines changed: 18 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3,31 +3,36 @@ package main
33
import (
44
"flag"
55
"fmt"
6-
"runtime"
76
"strings"
87

8+
"github.com/progrium/macdriver/macos"
99
"github.com/progrium/macdriver/macos/appkit"
1010
"github.com/progrium/macdriver/macos/foundation"
1111
"github.com/progrium/macdriver/objc"
1212
)
1313

14-
func init() {
15-
runtime.LockOSThread()
16-
}
14+
var (
15+
fontName *string
16+
text string
17+
)
1718

1819
func main() {
19-
fontName := flag.String("font", "Helvetica", "font to use")
20+
fontName = flag.String("font", "Helvetica", "font to use")
2021
flag.Parse()
21-
text := strings.Join(flag.Args(), " ")
22+
23+
text = strings.Join(flag.Args(), " ")
2224
if text == "" {
2325
text = "Hello world"
2426
}
25-
26-
app := appkit.Application_SharedApplication()
27-
screen := appkit.Screen_MainScreen().Frame().Size
2827
text = fmt.Sprintf(" %s ", text)
2928
fmt.Println(text)
3029

30+
macos.RunApp(launched)
31+
}
32+
33+
func launched(app appkit.Application, delegate *appkit.ApplicationDelegate) {
34+
screen := appkit.Screen_MainScreen().Frame().Size
35+
3136
tr, fontSize := func() (rect foundation.Rect, size float64) {
3237
t := appkit.NewTextViewWithFrame(rectOf(0, 0, 0, 0))
3338
t.SetString(text)
@@ -53,8 +58,8 @@ func main() {
5358
t.SetDrawsBackground(false)
5459

5560
c := appkit.NewViewWithFrame(rectOf(0, 0, 0, 0))
56-
// deprecated...
57-
// c.SetBackgroundColor(appkit.Color_ColorWithRedGreenBlueAlpha(0, 0, 0, 0.75))
61+
// deprecated call, no bindings
62+
objc.Call[objc.Void](c, objc.Sel("setBackgroundColor:"), appkit.Color_ColorWithRedGreenBlueAlpha(0, 0, 0, 0.75))
5863
c.SetWantsLayer(true)
5964
c.Layer().SetCornerRadius(32.0)
6065
c.AddSubviewPositionedRelativeTo(t, appkit.WindowAbove, nil)
@@ -79,14 +84,8 @@ func main() {
7984
appkit.Application_SharedApplication().Terminate(nil)
8085
})
8186

82-
ad := &appkit.ApplicationDelegate{}
83-
ad.SetApplicationDidFinishLaunching(func(foundation.Notification) {
84-
app.SetActivationPolicy(appkit.ApplicationActivationPolicyRegular)
85-
app.ActivateIgnoringOtherApps(true)
86-
})
87-
app.SetDelegate(ad)
88-
89-
app.Run()
87+
app.SetActivationPolicy(appkit.ApplicationActivationPolicyRegular)
88+
app.ActivateIgnoringOtherApps(true)
9089
}
9190

9291
func rectOf(x, y, width, height float64) foundation.Rect {

macos/_examples/layout/main.go

Lines changed: 7 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2,26 +2,26 @@ package main
22

33
import (
44
"fmt"
5-
"runtime"
65

76
"github.com/progrium/macdriver/helper/action"
87
"github.com/progrium/macdriver/helper/layout"
98
"github.com/progrium/macdriver/helper/widgets"
9+
"github.com/progrium/macdriver/macos"
1010
"github.com/progrium/macdriver/macos/appkit"
1111
"github.com/progrium/macdriver/macos/foundation"
1212
"github.com/progrium/macdriver/objc"
1313
)
1414

15-
// Arrange that main.main runs on main thread.
16-
func init() {
17-
runtime.LockOSThread()
15+
func main() {
16+
macos.RunApp(launched)
1817
}
1918

20-
func initAndRun() {
21-
app := appkit.Application_SharedApplication()
19+
func launched(app appkit.Application, delegate *appkit.ApplicationDelegate) {
2220
app.SetActivationPolicy(appkit.ApplicationActivationPolicyRegular)
2321
app.ActivateIgnoringOtherApps(true)
22+
2423
w := appkit.NewWindowWithSize(600, 400)
24+
objc.Retain(&w)
2525
w.SetTitle("Test Layout")
2626

2727
label := appkit.NewLabel("label")
@@ -71,19 +71,7 @@ func initAndRun() {
7171
w.MakeKeyAndOrderFront(nil)
7272
w.Center()
7373

74-
ad := &appkit.ApplicationDelegate{}
75-
ad.SetApplicationDidFinishLaunching(func(foundation.Notification) {
76-
app.SetActivationPolicy(appkit.ApplicationActivationPolicyRegular)
77-
app.ActivateIgnoringOtherApps(true)
78-
})
79-
ad.SetApplicationShouldTerminateAfterLastWindowClosed(func(appkit.Application) bool {
74+
delegate.SetApplicationShouldTerminateAfterLastWindowClosed(func(appkit.Application) bool {
8075
return true
8176
})
82-
app.SetDelegate(ad)
83-
84-
app.Run()
85-
}
86-
87-
func main() {
88-
initAndRun()
8977
}

macos/_examples/menu/main.go

Lines changed: 28 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -8,50 +8,43 @@ import (
88
"github.com/progrium/macdriver/objc"
99
)
1010

11-
// menus and tray
12-
13-
// Arrange that main.main runs on main thread.
14-
func init() {
11+
func main() {
1512
runtime.LockOSThread()
16-
}
1713

18-
func initAndRun() {
1914
app := appkit.Application_SharedApplication()
20-
w := appkit.NewWindowWithSize(600, 400)
21-
w.SetTitle("Test")
2215

23-
// text field
24-
textView := appkit.TextView_ScrollableTextView()
25-
textView.SetTranslatesAutoresizingMaskIntoConstraints(false)
26-
tv := appkit.TextViewFrom(textView.DocumentView().Ptr())
27-
tv.SetAllowsUndo(true)
28-
tv.SetRichText(false)
29-
w.ContentView().AddSubview(textView)
30-
w.ContentView().LeadingAnchor().ConstraintEqualToAnchorConstant(textView.LeadingAnchor(), -10).SetActive(true)
31-
w.ContentView().TopAnchor().ConstraintEqualToAnchorConstant(textView.TopAnchor(), -10).SetActive(true)
32-
w.ContentView().TrailingAnchor().ConstraintEqualToAnchorConstant(textView.TrailingAnchor(), 10).SetActive(true)
33-
w.ContentView().BottomAnchor().ConstraintEqualToAnchorConstant(textView.BottomAnchor(), 10).SetActive(true)
16+
delegate := &appkit.ApplicationDelegate{}
17+
delegate.SetApplicationDidFinishLaunching(func(foundation.Notification) {
18+
w := appkit.NewWindowWithSize(600, 400)
19+
objc.Retain(&w)
20+
w.SetTitle("Test")
21+
22+
textView := appkit.TextView_ScrollableTextView()
23+
textView.SetTranslatesAutoresizingMaskIntoConstraints(false)
24+
tv := appkit.TextViewFrom(textView.DocumentView().Ptr())
25+
tv.SetAllowsUndo(true)
26+
tv.SetRichText(false)
27+
w.ContentView().AddSubview(textView)
28+
w.ContentView().LeadingAnchor().ConstraintEqualToAnchorConstant(textView.LeadingAnchor(), -10).SetActive(true)
29+
w.ContentView().TopAnchor().ConstraintEqualToAnchorConstant(textView.TopAnchor(), -10).SetActive(true)
30+
w.ContentView().TrailingAnchor().ConstraintEqualToAnchorConstant(textView.TrailingAnchor(), 10).SetActive(true)
31+
w.ContentView().BottomAnchor().ConstraintEqualToAnchorConstant(textView.BottomAnchor(), 10).SetActive(true)
32+
33+
w.MakeKeyAndOrderFront(nil)
34+
w.Center()
3435

35-
w.MakeKeyAndOrderFront(nil)
36-
w.Center()
36+
setSystemBar(app)
3737

38-
ad := &appkit.ApplicationDelegate{}
39-
ad.SetApplicationDidFinishLaunching(func(foundation.Notification) {
4038
app.SetActivationPolicy(appkit.ApplicationActivationPolicyRegular)
4139
app.ActivateIgnoringOtherApps(true)
4240
})
43-
ad.SetApplicationWillFinishLaunching(func(foundation.Notification) {
44-
// should set menu bar at ApplicationWillFinishLaunching
41+
delegate.SetApplicationWillFinishLaunching(func(foundation.Notification) {
4542
setMainMenu(app)
4643
})
47-
ad.SetApplicationShouldTerminateAfterLastWindowClosed(func(appkit.Application) bool {
44+
delegate.SetApplicationShouldTerminateAfterLastWindowClosed(func(appkit.Application) bool {
4845
return true
4946
})
50-
app.SetDelegate(ad)
51-
52-
// should set system bar after window show
53-
setSystemBar(app)
54-
47+
app.SetDelegate(delegate)
5548
app.Run()
5649
}
5750

@@ -69,8 +62,7 @@ func setMainMenu(app appkit.Application) {
6962
testMenuItem := appkit.NewMenuItemWithSelector("", "", objc.Selector{})
7063
testMenu := appkit.NewMenuWithTitle("Edit")
7164
testMenu.AddItem(appkit.NewMenuItemWithSelector("Select All", "a", objc.Sel("selectAll:")))
72-
// missing symbol?
73-
//testMenu.AddItem(appkit.MenuItem_SeparatorItem())
65+
testMenu.AddItem(appkit.MenuItem_SeparatorItem())
7466
testMenu.AddItem(appkit.NewMenuItemWithSelector("Copy", "c", objc.Sel("copy:")))
7567
testMenu.AddItem(appkit.NewMenuItemWithSelector("Paste", "v", objc.Sel("paste:")))
7668
testMenu.AddItem(appkit.NewMenuItemWithSelector("Cut", "x", objc.Sel("cut:")))
@@ -81,17 +73,12 @@ func setMainMenu(app appkit.Application) {
8173
}
8274

8375
func setSystemBar(app appkit.Application) {
84-
bar := appkit.StatusBar_SystemStatusBar()
85-
item := bar.StatusItemWithLength(appkit.VariableStatusItemLength)
86-
button := item.Button()
87-
button.SetTitle("TestTray")
76+
item := appkit.StatusBar_SystemStatusBar().StatusItemWithLength(appkit.VariableStatusItemLength)
77+
objc.Retain(&item)
78+
item.Button().SetTitle("TestTray")
8879

8980
menu := appkit.NewMenuWithTitle("main")
9081
menu.AddItem(appkit.NewMenuItemWithAction("Hide", "h", func(sender objc.Object) { app.Hide(nil) }))
9182
menu.AddItem(appkit.NewMenuItemWithAction("Quit", "q", func(sender objc.Object) { app.Terminate(nil) }))
9283
item.SetMenu(menu)
9384
}
94-
95-
func main() {
96-
initAndRun()
97-
}

macos/_examples/notification/main.go

Lines changed: 9 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2,44 +2,34 @@ package main
22

33
import (
44
"runtime"
5+
"time"
56

6-
"github.com/progrium/macdriver/macos/appkit"
77
"github.com/progrium/macdriver/macos/foundation"
88
"github.com/progrium/macdriver/objc"
99
)
1010

11-
func init() {
12-
runtime.LockOSThread()
13-
}
14-
1511
func main() {
16-
app := appkit.Application_SharedApplication()
12+
runtime.LockOSThread()
1713

14+
// notifications need a unique bundleIdentifier which we can define by
15+
// replacing the bundleIdentifier method on the default main bundle
1816
nsbundle := foundation.Bundle_MainBundle().Class()
1917
objc.ReplaceMethod(nsbundle, objc.Sel("bundleIdentifier"), func(_ objc.IObject) string {
2018
return "com.example.fake2" // change this if you miss the allow notification
2119
})
2220

23-
ad := &appkit.ApplicationDelegate{}
24-
ad.SetApplicationDidFinishLaunching(func(foundation.Notification) {
25-
21+
objc.WithAutoreleasePool(func() {
22+
// this API is deprecated and we currently don't generate bindings for deprecated APIs,
23+
// so this is what using an API without bindings looks like.
2624
notif := objc.Call[objc.Object](objc.GetClass("NSUserNotification"), objc.Sel("new"))
2725
notif.Autorelease()
2826
objc.Call[objc.Void](notif, objc.Sel("setTitle:"), "Hello, world!")
2927
objc.Call[objc.Void](notif, objc.Sel("setInformativeText:"), "More text")
3028

3129
center := objc.Call[objc.Object](objc.GetClass("NSUserNotificationCenter"), objc.Sel("defaultUserNotificationCenter"))
3230
objc.Call[objc.Void](center, objc.Sel("deliverNotification:"), notif)
33-
34-
//app.Terminate(nil)
35-
36-
})
37-
ad.SetApplicationShouldTerminateAfterLastWindowClosed(func(appkit.Application) bool {
38-
return true
3931
})
40-
app.SetDelegate(ad)
4132

42-
app.SetActivationPolicy(appkit.ApplicationActivationPolicyRegular)
43-
app.ActivateIgnoringOtherApps(true)
44-
app.Run()
33+
// give notification center a moment
34+
<-time.After(1 * time.Second)
4535
}

0 commit comments

Comments
 (0)