Files
gio/ui/app/gl_macos.m
T
Elias Naur 21ad48b7de ui/app: (macOS) use consistent scale for pointer events
Instead of querying the backing store scale for every pointer event,
use the scale from the last window draw. It might not make any visible
difference because we redraw on scale changes, but it is more correct.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2019-07-21 17:34:12 +02:00

167 lines
4.7 KiB
Objective-C

// SPDX-License-Identifier: Unlicense OR MIT
//+build darwin,!ios
@import AppKit;
#include <CoreFoundation/CoreFoundation.h>
#include <OpenGL/OpenGL.h>
#include <OpenGL/gl3.h>
#include "os_macos.h"
#include "gl_macos.h"
#include "_cgo_export.h"
static void handleMouse(NSView *view, NSEvent *event, int typ, CGFloat dx, CGFloat dy) {
NSPoint p = [view convertPoint:[event locationInWindow] fromView:nil];
if (!event.hasPreciseScrollingDeltas) {
// dx and dy are in rows and columns.
dx *= 10;
dy *= 10;
}
gio_onMouse((__bridge CFTypeRef)view, typ, p.x, p.y, dx, dy, [event timestamp]);
}
static CVReturn displayLinkCallback(CVDisplayLinkRef displayLink, const CVTimeStamp *inNow, const CVTimeStamp *inOutputTime, CVOptionFlags flagsIn, CVOptionFlags *flagsOut, void *displayLinkContext) {
CFTypeRef view = (CFTypeRef *)displayLinkContext;
gio_onFrameCallback(view);
return kCVReturnSuccess;
}
@interface GioView : NSOpenGLView
@end
@implementation GioView {
CVDisplayLinkRef displayLink;
}
- (instancetype)initWithFrame:(NSRect)frameRect
pixelFormat:(NSOpenGLPixelFormat *)format {
self = [super initWithFrame:frameRect pixelFormat:format];
if (self) {
CVDisplayLinkCreateWithActiveCGDisplays(&displayLink);
CVDisplayLinkSetOutputCallback(displayLink, displayLinkCallback, (__bridge void*)self);
}
return self;
}
- (void)dealloc {
CVDisplayLinkRelease(displayLink);
}
- (void)setAnimating:(BOOL)anim {
if (anim) {
CVDisplayLinkStart(displayLink);
} else {
CVDisplayLinkStop(displayLink);
}
}
- (void)updateDisplay:(CGDirectDisplayID)dispID {
CVDisplayLinkSetCurrentCGDisplay(displayLink, dispID);
}
- (void)prepareOpenGL {
[super prepareOpenGL];
// Bind a default VBA to emulate OpenGL ES 2.
GLuint defVBA;
glGenVertexArrays(1, &defVBA);
glBindVertexArray(defVBA);
glEnable(GL_FRAMEBUFFER_SRGB);
}
- (BOOL)isFlipped {
return YES;
}
- (void)update {
[super update];
gio_onDraw((__bridge CFTypeRef)self);
}
- (void)drawRect:(NSRect)r {
gio_onDraw((__bridge CFTypeRef)self);
}
- (void)mouseDown:(NSEvent *)event {
handleMouse(self, event, GIO_MOUSE_DOWN, 0, 0);
}
- (void)mouseUp:(NSEvent *)event {
handleMouse(self, event, GIO_MOUSE_UP, 0, 0);
}
- (void)mouseMoved:(NSEvent *)event {
handleMouse(self, event, GIO_MOUSE_MOVE, 0, 0);
}
- (void)mouseDragged:(NSEvent *)event {
handleMouse(self, event, GIO_MOUSE_MOVE, 0, 0);
}
- (void)scrollWheel:(NSEvent *)event {
CGFloat dx = -event.scrollingDeltaX;
CGFloat dy = -event.scrollingDeltaY;
handleMouse(self, event, GIO_MOUSE_MOVE, dx, dy);
}
- (void)keyDown:(NSEvent *)event {
NSString *keys = [event charactersIgnoringModifiers];
gio_onKeys((__bridge CFTypeRef)self, (char *)[keys UTF8String], [event timestamp], [event modifierFlags]);
[self interpretKeyEvents:[NSArray arrayWithObject:event]];
}
- (void)insertText:(id)string {
const char *utf8 = [string UTF8String];
gio_onText((__bridge CFTypeRef)self, (char *)utf8);
}
- (void)doCommandBySelector:(SEL)sel {
// Don't pass commands up the responder chain.
// They will end up in a beep.
}
@end
CFTypeRef gio_createGLView(void) {
@autoreleasepool {
NSOpenGLPixelFormatAttribute attr[] = {
NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core,
NSOpenGLPFAColorSize, 24,
NSOpenGLPFADepthSize, 16,
NSOpenGLPFAAccelerated,
// Opt-in to automatic GPU switching. CGL-only property.
kCGLPFASupportsAutomaticGraphicsSwitching,
NSOpenGLPFAAllowOfflineRenderers,
0
};
id pixFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:attr];
NSRect frame = NSMakeRect(0, 0, 0, 0);
GioView* view = [[GioView alloc] initWithFrame:frame pixelFormat:pixFormat];
[view setWantsBestResolutionOpenGLSurface:YES];
[view setWantsLayer:YES]; // The default in Mojave.
return CFBridgingRetain(view);
}
}
void gio_updateDisplayLink(CFTypeRef viewRef, CGDirectDisplayID dispID) {
GioView *view = (__bridge GioView *)viewRef;
[view updateDisplay:dispID];
}
void gio_setAnimating(CFTypeRef viewRef, BOOL anim) {
GioView *view = (__bridge GioView *)viewRef;
dispatch_async(dispatch_get_main_queue(), ^{
[view setAnimating:anim];
});
}
CFTypeRef gio_contextForView(CFTypeRef viewRef) {
NSOpenGLView *view = (__bridge NSOpenGLView *)viewRef;
return (__bridge CFTypeRef)view.openGLContext;
}
void gio_clearCurrentContext(void) {
[NSOpenGLContext clearCurrentContext];
}
void gio_makeCurrentContext(CFTypeRef ctxRef) {
NSOpenGLContext *ctx = (__bridge NSOpenGLContext *)ctxRef;
return [ctx makeCurrentContext];
}
void gio_lockContext(CFTypeRef ctxRef) {
NSOpenGLContext *ctx = (__bridge NSOpenGLContext *)ctxRef;
CGLLockContext([ctx CGLContextObj]);
}
void gio_unlockContext(CFTypeRef ctxRef) {
NSOpenGLContext *ctx = (__bridge NSOpenGLContext *)ctxRef;
CGLUnlockContext([ctx CGLContextObj]);
}