github.com/champo/mobile@v0.0.0-20190107162257-dc0771356504/app/darwin_ios.m (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 ios
     7  
     8  #include "_cgo_export.h"
     9  #include <pthread.h>
    10  #include <stdio.h>
    11  #include <sys/utsname.h>
    12  
    13  #import <UIKit/UIKit.h>
    14  #import <GLKit/GLKit.h>
    15  
    16  struct utsname sysInfo;
    17  
    18  @interface GoAppAppController : GLKViewController<UIContentContainer, GLKViewDelegate>
    19  @end
    20  
    21  @interface GoAppAppDelegate : UIResponder<UIApplicationDelegate>
    22  @property (strong, nonatomic) UIWindow *window;
    23  @property (strong, nonatomic) GoAppAppController *controller;
    24  @end
    25  
    26  @implementation GoAppAppDelegate
    27  - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    28  	lifecycleAlive();
    29  	self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    30  	self.controller = [[GoAppAppController alloc] initWithNibName:nil bundle:nil];
    31  	self.window.rootViewController = self.controller;
    32  	[self.window makeKeyAndVisible];
    33  	return YES;
    34  }
    35  
    36  - (void)applicationDidBecomeActive:(UIApplication * )application {
    37  	lifecycleFocused();
    38  }
    39  
    40  - (void)applicationWillResignActive:(UIApplication *)application {
    41  	lifecycleVisible();
    42  }
    43  
    44  - (void)applicationDidEnterBackground:(UIApplication *)application {
    45  	lifecycleAlive();
    46  }
    47  
    48  - (void)applicationWillTerminate:(UIApplication *)application {
    49  	lifecycleDead();
    50  }
    51  @end
    52  
    53  @interface GoAppAppController ()
    54  @property (strong, nonatomic) EAGLContext *context;
    55  @property (strong, nonatomic) GLKView *glview;
    56  @end
    57  
    58  @implementation GoAppAppController
    59  - (void)viewWillAppear:(BOOL)animated
    60  {
    61  	// TODO: replace by swapping out GLKViewController for a UIVIewController.
    62  	[super viewWillAppear:animated];
    63  	self.paused = YES;
    64  }
    65  
    66  - (void)viewDidLoad {
    67  	[super viewDidLoad];
    68  	self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
    69  	self.glview = (GLKView*)self.view;
    70  	self.glview.drawableDepthFormat = GLKViewDrawableDepthFormat24;
    71  	self.glview.multipleTouchEnabled = true; // TODO expose setting to user.
    72  	self.glview.context = self.context;
    73  	self.glview.userInteractionEnabled = YES;
    74  	self.glview.enableSetNeedsDisplay = YES; // only invoked once
    75  
    76  	// Do not use the GLKViewController draw loop.
    77  	self.paused = YES;
    78  	self.resumeOnDidBecomeActive = NO;
    79  	self.preferredFramesPerSecond = 0;
    80  
    81  	int scale = 1;
    82  	if ([[UIScreen mainScreen] respondsToSelector:@selector(displayLinkWithTarget:selector:)]) {
    83  		scale = (int)[UIScreen mainScreen].scale; // either 1.0, 2.0, or 3.0.
    84  	}
    85  	setScreen(scale);
    86  
    87  	CGSize size = [UIScreen mainScreen].bounds.size;
    88  	UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
    89  	updateConfig((int)size.width, (int)size.height, orientation);
    90  }
    91  
    92  - (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator {
    93  	[coordinator animateAlongsideTransition:^(id<UIViewControllerTransitionCoordinatorContext> context) {
    94  		// TODO(crawshaw): come up with a plan to handle animations.
    95  	} completion:^(id<UIViewControllerTransitionCoordinatorContext> context) {
    96  		UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
    97  		updateConfig((int)size.width, (int)size.height, orientation);
    98  	}];
    99  }
   100  
   101  - (void)glkView:(GLKView *)view drawInRect:(CGRect)rect {
   102  	// Now that we have been asked to do the first draw, disable any
   103  	// future draw and hand control over to the Go paint.Event cycle.
   104  	self.glview.enableSetNeedsDisplay = NO;
   105  	startloop((GLintptr)self.context);
   106  }
   107  
   108  #define TOUCH_TYPE_BEGIN 0 // touch.TypeBegin
   109  #define TOUCH_TYPE_MOVE  1 // touch.TypeMove
   110  #define TOUCH_TYPE_END   2 // touch.TypeEnd
   111  
   112  static void sendTouches(int change, NSSet* touches) {
   113  	CGFloat scale = [UIScreen mainScreen].scale;
   114  	for (UITouch* touch in touches) {
   115  		CGPoint p = [touch locationInView:touch.view];
   116  		sendTouch((GoUintptr)touch, (GoUintptr)change, p.x*scale, p.y*scale);
   117  	}
   118  }
   119  
   120  - (void)touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event {
   121  	sendTouches(TOUCH_TYPE_BEGIN, touches);
   122  }
   123  
   124  - (void)touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event {
   125  	sendTouches(TOUCH_TYPE_MOVE, touches);
   126  }
   127  
   128  - (void)touchesEnded:(NSSet*)touches withEvent:(UIEvent*)event {
   129  	sendTouches(TOUCH_TYPE_END, touches);
   130  }
   131  
   132  - (void)touchesCanceled:(NSSet*)touches withEvent:(UIEvent*)event {
   133      sendTouches(TOUCH_TYPE_END, touches);
   134  }
   135  @end
   136  
   137  void runApp(void) {
   138  	@autoreleasepool {
   139  		UIApplicationMain(0, nil, nil, NSStringFromClass([GoAppAppDelegate class]));
   140  	}
   141  }
   142  
   143  void makeCurrentContext(GLintptr context) {
   144  	EAGLContext* ctx = (EAGLContext*)context;
   145  	if (![EAGLContext setCurrentContext:ctx]) {
   146  		// TODO(crawshaw): determine how terrible this is. Exit?
   147  		NSLog(@"failed to set current context");
   148  	}
   149  }
   150  
   151  void swapBuffers(GLintptr context) {
   152  	__block EAGLContext* ctx = (EAGLContext*)context;
   153  	dispatch_sync(dispatch_get_main_queue(), ^{
   154  		[EAGLContext setCurrentContext:ctx];
   155  		[ctx presentRenderbuffer:GL_RENDERBUFFER];
   156  	});
   157  }
   158  
   159  uint64_t threadID() {
   160  	uint64_t id;
   161  	if (pthread_threadid_np(pthread_self(), &id)) {
   162  		abort();
   163  	}
   164  	return id;
   165  }