github.com/graybobo/golang.org-package-offline-cache@v0.0.0-20200626051047-6608995c132f/x/mobile/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  void runApp(void);
    21  void setContext(void* context);
    22  uint64_t threadID();
    23  */
    24  import "C"
    25  import (
    26  	"log"
    27  	"runtime"
    28  	"strings"
    29  	"sync"
    30  	"unsafe"
    31  
    32  	"golang.org/x/mobile/event/lifecycle"
    33  	"golang.org/x/mobile/event/paint"
    34  	"golang.org/x/mobile/event/size"
    35  	"golang.org/x/mobile/event/touch"
    36  	"golang.org/x/mobile/geom"
    37  )
    38  
    39  var initThreadID uint64
    40  
    41  func init() {
    42  	// Lock the goroutine responsible for initialization to an OS thread.
    43  	// This means the goroutine running main (and calling the run function
    44  	// below) is locked to the OS thread that started the program. This is
    45  	// necessary for the correct delivery of UIKit events to the process.
    46  	//
    47  	// A discussion on this topic:
    48  	// https://groups.google.com/forum/#!msg/golang-nuts/IiWZ2hUuLDA/SNKYYZBelsYJ
    49  	runtime.LockOSThread()
    50  	initThreadID = uint64(C.threadID())
    51  }
    52  
    53  func main(f func(App)) {
    54  	if tid := uint64(C.threadID()); tid != initThreadID {
    55  		log.Fatalf("app.Run called on thread %d, but app.init ran on %d", tid, initThreadID)
    56  	}
    57  
    58  	go func() {
    59  		f(theApp)
    60  		// TODO(crawshaw): trigger runApp to return
    61  	}()
    62  	C.runApp()
    63  	panic("unexpected return from app.runApp")
    64  }
    65  
    66  var pixelsPerPt float32
    67  var screenScale int // [UIScreen mainScreen].scale, either 1, 2, or 3.
    68  
    69  //export setScreen
    70  func setScreen(scale int) {
    71  	C.uname(&C.sysInfo)
    72  	name := C.GoString(&C.sysInfo.machine[0])
    73  
    74  	var v float32
    75  
    76  	switch {
    77  	case strings.HasPrefix(name, "iPhone"):
    78  		v = 163
    79  	case strings.HasPrefix(name, "iPad"):
    80  		// TODO: is there a better way to distinguish the iPad Mini?
    81  		switch name {
    82  		case "iPad2,5", "iPad2,6", "iPad2,7", "iPad4,4", "iPad4,5", "iPad4,6", "iPad4,7":
    83  			v = 163 // iPad Mini
    84  		default:
    85  			v = 132
    86  		}
    87  	default:
    88  		v = 163 // names like i386 and x86_64 are the simulator
    89  	}
    90  
    91  	if v == 0 {
    92  		log.Printf("unknown machine: %s", name)
    93  		v = 163 // emergency fallback
    94  	}
    95  
    96  	pixelsPerPt = v * float32(scale) / 72
    97  	screenScale = scale
    98  }
    99  
   100  //export updateConfig
   101  func updateConfig(width, height, orientation int32) {
   102  	o := size.OrientationUnknown
   103  	switch orientation {
   104  	case C.UIDeviceOrientationPortrait, C.UIDeviceOrientationPortraitUpsideDown:
   105  		o = size.OrientationPortrait
   106  	case C.UIDeviceOrientationLandscapeLeft, C.UIDeviceOrientationLandscapeRight:
   107  		o = size.OrientationLandscape
   108  	}
   109  	widthPx := screenScale * int(width)
   110  	heightPx := screenScale * int(height)
   111  	theApp.eventsIn <- size.Event{
   112  		WidthPx:     widthPx,
   113  		HeightPx:    heightPx,
   114  		WidthPt:     geom.Pt(float32(widthPx) / pixelsPerPt),
   115  		HeightPt:    geom.Pt(float32(heightPx) / pixelsPerPt),
   116  		PixelsPerPt: pixelsPerPt,
   117  		Orientation: o,
   118  	}
   119  }
   120  
   121  // touchIDs is the current active touches. The position in the array
   122  // is the ID, the value is the UITouch* pointer value.
   123  //
   124  // It is widely reported that the iPhone can handle up to 5 simultaneous
   125  // touch events, while the iPad can handle 11.
   126  var touchIDs [11]uintptr
   127  
   128  var touchEvents struct {
   129  	sync.Mutex
   130  	pending []touch.Event
   131  }
   132  
   133  //export sendTouch
   134  func sendTouch(cTouch, cTouchType uintptr, x, y float32) {
   135  	id := -1
   136  	for i, val := range touchIDs {
   137  		if val == cTouch {
   138  			id = i
   139  			break
   140  		}
   141  	}
   142  	if id == -1 {
   143  		for i, val := range touchIDs {
   144  			if val == 0 {
   145  				touchIDs[i] = cTouch
   146  				id = i
   147  				break
   148  			}
   149  		}
   150  		if id == -1 {
   151  			panic("out of touchIDs")
   152  		}
   153  	}
   154  
   155  	t := touch.Type(cTouchType)
   156  	if t == touch.TypeEnd {
   157  		touchIDs[id] = 0
   158  	}
   159  
   160  	theApp.eventsIn <- touch.Event{
   161  		X:        x,
   162  		Y:        y,
   163  		Sequence: touch.Sequence(id),
   164  		Type:     t,
   165  	}
   166  }
   167  
   168  var workAvailable <-chan struct{}
   169  
   170  //export drawgl
   171  func drawgl(ctx uintptr) {
   172  	if workAvailable == nil {
   173  		C.setContext(unsafe.Pointer(ctx))
   174  		workAvailable = theApp.worker.WorkAvailable()
   175  		// TODO(crawshaw): not just on process start.
   176  		theApp.sendLifecycle(lifecycle.StageFocused)
   177  	}
   178  
   179  	// TODO(crawshaw): don't send a paint.Event unconditionally. Only send one
   180  	// if the window actually needs redrawing.
   181  	theApp.eventsIn <- paint.Event{}
   182  
   183  	for {
   184  		select {
   185  		case <-workAvailable:
   186  			theApp.worker.DoWork()
   187  		case <-theApp.publish:
   188  			theApp.publishResult <- PublishResult{}
   189  			return
   190  		}
   191  	}
   192  }