github.com/c-darwin/mobile@v0.0.0-20160313183840-ff625c46f7c9/app/darwin_armx.go (about) 1 // Copyright 2015 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // +build darwin 6 // +build arm arm64 7 8 package app 9 10 /* 11 #cgo CFLAGS: -x objective-c 12 #cgo LDFLAGS: -framework Foundation -framework UIKit -framework GLKit -framework OpenGLES -framework QuartzCore 13 #include <sys/utsname.h> 14 #include <stdint.h> 15 #include <pthread.h> 16 #include <UIKit/UIDevice.h> 17 18 extern struct utsname sysInfo; 19 20 char* GetFilesDir(void); 21 void runApp(void); 22 void setContext(void* context); 23 uint64_t threadID(); 24 */ 25 import "C" 26 import ( 27 "log" 28 "runtime" 29 "strings" 30 "sync" 31 "unsafe" 32 "github.com/democratic-coin/dcoin-go/packages/dcoin" 33 "github.com/c-darwin/mobile/event/lifecycle" 34 "github.com/c-darwin/mobile/event/paint" 35 "github.com/c-darwin/mobile/event/size" 36 "github.com/c-darwin/mobile/event/touch" 37 "github.com/c-darwin/mobile/geom" 38 "github.com/c-darwin/mobile/gl" 39 ) 40 41 var initThreadID uint64 42 43 //export dcoinStart 44 func dcoinStart(){ 45 go dcoin.Start(C.GoString(C.GetFilesDir()), nil); 46 } 47 48 //export dcoinStop 49 func dcoinStop(){ 50 go dcoin.Stop(); 51 } 52 53 //export dcoinStopHTTPServer 54 func dcoinStopHTTPServer(){ 55 go dcoin.StopHTTPServer(); 56 } 57 58 func init() { 59 // Lock the goroutine responsible for initialization to an OS thread. 60 // This means the goroutine running main (and calling the run function 61 // below) is locked to the OS thread that started the program. This is 62 // necessary for the correct delivery of UIKit events to the process. 63 // 64 // A discussion on this topic: 65 // https://groups.google.com/forum/#!msg/golang-nuts/IiWZ2hUuLDA/SNKYYZBelsYJ 66 runtime.LockOSThread() 67 initThreadID = uint64(C.threadID()) 68 } 69 70 func main(f func(App)) { 71 if tid := uint64(C.threadID()); tid != initThreadID { 72 log.Fatalf("app.Run called on thread %d, but app.init ran on %d", tid, initThreadID) 73 } 74 75 go func() { 76 f(app{}) 77 // TODO(crawshaw): trigger runApp to return 78 }() 79 C.runApp() 80 panic("unexpected return from app.runApp") 81 } 82 83 var pixelsPerPt float32 84 var screenScale int // [UIScreen mainScreen].scale, either 1, 2, or 3. 85 86 //export setScreen 87 func setScreen(scale int) { 88 C.uname(&C.sysInfo) 89 name := C.GoString(&C.sysInfo.machine[0]) 90 91 var v float32 92 93 switch { 94 case strings.HasPrefix(name, "iPhone"): 95 v = 163 96 case strings.HasPrefix(name, "iPad"): 97 // TODO: is there a better way to distinguish the iPad Mini? 98 switch name { 99 case "iPad2,5", "iPad2,6", "iPad2,7", "iPad4,4", "iPad4,5", "iPad4,6", "iPad4,7": 100 v = 163 // iPad Mini 101 default: 102 v = 132 103 } 104 default: 105 v = 163 // names like i386 and x86_64 are the simulator 106 } 107 108 if v == 0 { 109 log.Printf("unknown machine: %s", name) 110 v = 163 // emergency fallback 111 } 112 113 pixelsPerPt = v * float32(scale) / 72 114 screenScale = scale 115 } 116 117 //export updateConfig 118 func updateConfig(width, height, orientation int32) { 119 o := size.OrientationUnknown 120 switch orientation { 121 case C.UIDeviceOrientationPortrait, C.UIDeviceOrientationPortraitUpsideDown: 122 o = size.OrientationPortrait 123 case C.UIDeviceOrientationLandscapeLeft, C.UIDeviceOrientationLandscapeRight: 124 o = size.OrientationLandscape 125 } 126 widthPx := screenScale * int(width) 127 heightPx := screenScale * int(height) 128 eventsIn <- size.Event{ 129 WidthPx: widthPx, 130 HeightPx: heightPx, 131 WidthPt: geom.Pt(float32(widthPx) / pixelsPerPt), 132 HeightPt: geom.Pt(float32(heightPx) / pixelsPerPt), 133 PixelsPerPt: pixelsPerPt, 134 Orientation: o, 135 } 136 } 137 138 var startedgl = false 139 140 // touchIDs is the current active touches. The position in the array 141 // is the ID, the value is the UITouch* pointer value. 142 // 143 // It is widely reported that the iPhone can handle up to 5 simultaneous 144 // touch events, while the iPad can handle 11. 145 var touchIDs [11]uintptr 146 147 var touchEvents struct { 148 sync.Mutex 149 pending []touch.Event 150 } 151 152 //export sendTouch 153 func sendTouch(cTouch, cTouchType uintptr, x, y float32) { 154 id := -1 155 for i, val := range touchIDs { 156 if val == cTouch { 157 id = i 158 break 159 } 160 } 161 if id == -1 { 162 for i, val := range touchIDs { 163 if val == 0 { 164 touchIDs[i] = cTouch 165 id = i 166 break 167 } 168 } 169 if id == -1 { 170 panic("out of touchIDs") 171 } 172 } 173 174 t := touch.Type(cTouchType) 175 if t == touch.TypeEnd { 176 touchIDs[id] = 0 177 } 178 179 eventsIn <- touch.Event{ 180 X: x, 181 Y: y, 182 Sequence: touch.Sequence(id), 183 Type: t, 184 } 185 } 186 187 //export drawgl 188 func drawgl(ctx uintptr) { 189 if !startedgl { 190 startedgl = true 191 C.setContext(unsafe.Pointer(ctx)) 192 // TODO(crawshaw): not just on process start. 193 sendLifecycle(lifecycle.StageFocused) 194 } 195 196 eventsIn <- paint.Event{} 197 198 for { 199 select { 200 case <-gl.WorkAvailable: 201 gl.DoWork() 202 case <-endPaint: 203 return 204 } 205 } 206 }