gioui.org/ui@v0.0.0-20190926171558-ce74bc0cbaea/app/gl_macos.m (about)

     1  // SPDX-License-Identifier: Unlicense OR MIT
     2  
     3  // +build darwin,!ios
     4  
     5  @import AppKit;
     6  
     7  #include <CoreFoundation/CoreFoundation.h>
     8  #include <OpenGL/OpenGL.h>
     9  #include <OpenGL/gl3.h>
    10  #include "os_macos.h"
    11  #include "gl_macos.h"
    12  #include "_cgo_export.h"
    13  
    14  static void handleMouse(NSView *view, NSEvent *event, int typ, CGFloat dx, CGFloat dy) {
    15  	NSPoint p = [view convertPoint:[event locationInWindow] fromView:nil];
    16  	if (!event.hasPreciseScrollingDeltas) {
    17  		// dx and dy are in rows and columns.
    18  		dx *= 10;
    19  		dy *= 10;
    20  	}
    21  	gio_onMouse((__bridge CFTypeRef)view, typ, p.x, p.y, dx, dy, [event timestamp]);
    22  }
    23  
    24  static CVReturn displayLinkCallback(CVDisplayLinkRef displayLink, const CVTimeStamp *inNow, const CVTimeStamp *inOutputTime, CVOptionFlags flagsIn, CVOptionFlags *flagsOut, void *displayLinkContext) {
    25  	CFTypeRef view = (CFTypeRef *)displayLinkContext;
    26  	gio_onFrameCallback(view);
    27  	return kCVReturnSuccess;
    28  }
    29  
    30  @interface GioView : NSOpenGLView 
    31  @end
    32  
    33  @implementation GioView {
    34  CVDisplayLinkRef displayLink;
    35  }
    36  - (instancetype)initWithFrame:(NSRect)frameRect
    37  				  pixelFormat:(NSOpenGLPixelFormat *)format {
    38  	self = [super initWithFrame:frameRect pixelFormat:format];
    39  	if (self) {
    40  		CVDisplayLinkCreateWithActiveCGDisplays(&displayLink);
    41  		CVDisplayLinkSetOutputCallback(displayLink, displayLinkCallback, (__bridge void*)self);
    42  	}
    43  	return self;
    44  }
    45  - (void)dealloc {
    46  	CVDisplayLinkRelease(displayLink);
    47  }
    48  - (void)setAnimating:(BOOL)anim {
    49  	if (anim) {
    50  		CVDisplayLinkStart(displayLink);
    51  	} else {
    52  		CVDisplayLinkStop(displayLink);
    53  	}
    54  }
    55  - (void)updateDisplay:(CGDirectDisplayID)dispID {
    56  	CVDisplayLinkSetCurrentCGDisplay(displayLink, dispID);
    57  }
    58  - (void)prepareOpenGL {
    59  	[super prepareOpenGL];
    60  	// Bind a default VBA to emulate OpenGL ES 2.
    61  	GLuint defVBA;
    62  	glGenVertexArrays(1, &defVBA);
    63  	glBindVertexArray(defVBA);
    64  	glEnable(GL_FRAMEBUFFER_SRGB);
    65  }
    66  - (BOOL)isFlipped {
    67  	return YES;
    68  }
    69  - (void)update {
    70  	[super update];
    71  	[self setNeedsDisplay:YES];
    72  }
    73  - (void)drawRect:(NSRect)r {
    74  	gio_onDraw((__bridge CFTypeRef)self);
    75  }
    76  - (void)mouseDown:(NSEvent *)event {
    77  	handleMouse(self, event, GIO_MOUSE_DOWN, 0, 0);
    78  }
    79  - (void)mouseUp:(NSEvent *)event {
    80  	handleMouse(self, event, GIO_MOUSE_UP, 0, 0);
    81  }
    82  - (void)mouseMoved:(NSEvent *)event {
    83  	handleMouse(self, event, GIO_MOUSE_MOVE, 0, 0);
    84  }
    85  - (void)mouseDragged:(NSEvent *)event {
    86  	handleMouse(self, event, GIO_MOUSE_MOVE, 0, 0);
    87  }
    88  - (void)scrollWheel:(NSEvent *)event {
    89  	CGFloat dx = -event.scrollingDeltaX;
    90  	CGFloat dy = -event.scrollingDeltaY;
    91  	handleMouse(self, event, GIO_MOUSE_MOVE, dx, dy);
    92  }
    93  - (void)keyDown:(NSEvent *)event {
    94  	NSString *keys = [event charactersIgnoringModifiers];
    95  	gio_onKeys((__bridge CFTypeRef)self, (char *)[keys UTF8String], [event timestamp], [event modifierFlags]);
    96  	[self interpretKeyEvents:[NSArray arrayWithObject:event]];
    97  }
    98  - (void)insertText:(id)string {
    99  	const char *utf8 = [string UTF8String];
   100  	gio_onText((__bridge CFTypeRef)self, (char *)utf8);
   101  }
   102  - (void)doCommandBySelector:(SEL)sel {
   103  	// Don't pass commands up the responder chain.
   104  	// They will end up in a beep.
   105  }
   106  @end
   107  
   108  CFTypeRef gio_createGLView(void) {
   109  	@autoreleasepool {
   110  		NSOpenGLPixelFormatAttribute attr[] = {
   111  			NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core,
   112  			NSOpenGLPFAColorSize,     24,
   113  			NSOpenGLPFADepthSize,     16,
   114  			NSOpenGLPFAAccelerated,
   115  			// Opt-in to automatic GPU switching. CGL-only property.
   116  			kCGLPFASupportsAutomaticGraphicsSwitching,
   117  			NSOpenGLPFAAllowOfflineRenderers,
   118  			0
   119  		};
   120  		id pixFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:attr];
   121  
   122  		NSRect frame = NSMakeRect(0, 0, 0, 0);
   123  		GioView* view = [[GioView alloc] initWithFrame:frame pixelFormat:pixFormat];
   124  
   125  		[view setWantsBestResolutionOpenGLSurface:YES];
   126  		[view setWantsLayer:YES]; // The default in Mojave.
   127  
   128  		return CFBridgingRetain(view);
   129  	}
   130  }
   131  
   132  void gio_updateDisplayLink(CFTypeRef viewRef, CGDirectDisplayID dispID) {
   133  	GioView *view = (__bridge GioView *)viewRef;
   134  	[view updateDisplay:dispID];
   135  }
   136  
   137  void gio_setAnimating(CFTypeRef viewRef, BOOL anim) {
   138  	GioView *view = (__bridge GioView *)viewRef;
   139  	dispatch_async(dispatch_get_main_queue(), ^{
   140  		[view setAnimating:anim];
   141  	});
   142  }
   143  
   144  CFTypeRef gio_contextForView(CFTypeRef viewRef) {
   145  	NSOpenGLView *view = (__bridge NSOpenGLView *)viewRef;
   146  	return (__bridge CFTypeRef)view.openGLContext;
   147  }
   148  
   149  void gio_clearCurrentContext(void) {
   150  	[NSOpenGLContext clearCurrentContext];
   151  }
   152  
   153  void gio_makeCurrentContext(CFTypeRef ctxRef) {
   154  	NSOpenGLContext *ctx = (__bridge NSOpenGLContext *)ctxRef;
   155  	return [ctx makeCurrentContext];
   156  }
   157  
   158  void gio_lockContext(CFTypeRef ctxRef) {
   159  	NSOpenGLContext *ctx = (__bridge NSOpenGLContext *)ctxRef;
   160  	CGLLockContext([ctx CGLContextObj]);
   161  }
   162  
   163  void gio_unlockContext(CFTypeRef ctxRef) {
   164  	NSOpenGLContext *ctx = (__bridge NSOpenGLContext *)ctxRef;
   165  	CGLUnlockContext([ctx CGLContextObj]);
   166  }