/* * Mr. 4th Dimention - Allen Webster * * 28.06.2017 * * Mac Objective C layer for 4coder * */ // TOP #include "4ed_defines.h" #include "4coder_API/version.h" #define WINDOW_NAME "4coder" VERSION #undef internal #undef global #undef external #define external #include "osx_objective_c_to_cpp_links.h" #import #import #import #import #import void osx_post_to_clipboard(char *str){ NSPasteboard *board = [NSPasteboard generalPasteboard]; NSString *utf8_type = @"public.utf8-plain-text"; NSArray *typesArray = [NSArray arrayWithObjects: utf8_type, nil]; [board declareTypes:typesArray owner:nil]; NSString *paste_string = [NSString stringWithUTF8String:str]; [board setString:paste_string forType:utf8_type]; osx.just_posted_to_clipboard = true; } // // Entry point, OpenGL window setup. // @interface AppDelegate : NSObject @end @interface My4coderView : NSOpenGLView{ @public CVDisplayLinkRef displayLink; } - (CVReturn)getFrameForTime:(const CVTimeStamp*)time; @end #define DISPLINK_SIG(n) CVReturn n(CVDisplayLinkRef link, const CVTimeStamp *now, const CVTimeStamp *output, CVOptionFlags flags_in, CVOptionFlags *flags_out, void *context) static DISPLINK_SIG(osx_display_link); @implementation My4coderView - (void)keyDown:(NSEvent *)event{ NSString *real = [event charactersIgnoringModifiers]; NSString *with_mods = [event characters]; b32 is_dead_key = false; if (real && !with_mods){ is_dead_key = true; } OSX_Keyboard_Modifiers mods = {0}; NSEventModifierFlags flags = [NSEvent modifierFlags]; mods.shift = ((flags & NSEventModifierFlagShift) != 0); mods.command = ((flags & NSEventModifierFlagCommand) != 0); mods.control = ((flags & NSEventModifierFlagControl) != 0); mods.option = ((flags & NSEventModifierFlagOption) != 0); u32 length = real.length; for (u32 i = 0; i < length; ++i){ unichar c = [real characterAtIndex:i]; osx_character_input(c, mods); } } - (void)mouseDown:(NSEvent*)event{ NSPoint m = [event locationInWindow]; osx_mouse(m.x, m.y, MouseType_Press); } - (void)mouseDragged:(NSEvent*)event{ NSPoint m = [event locationInWindow]; osx_mouse(m.x, m.y, MouseType_Move); } - (void)mouseMoved:(NSEvent*)event{ NSPoint m = [event locationInWindow]; osx_mouse(m.x, m.y, MouseType_Move); } - (void)mouseUp:(NSEvent*)event{ NSPoint m = [event locationInWindow]; osx_mouse(m.x, m.y, MouseType_Release); } - (void)scrollWheel:(NSEvent*)event{ float dx = event.scrollingDeltaX; float dy = event.scrollingDeltaY; osx_mouse_wheel(dx, dy); } - (CVReturn)getFrameForTime:(const CVTimeStamp*)time{ @autoreleasepool { if (osx.running){ NSPasteboard *board = [NSPasteboard generalPasteboard]; if (board.changeCount != osx.prev_clipboard_change_count){ if (!osx.just_posted_to_clipboard){ NSString *utf8_type = @"public.utf8-plain-text"; NSArray *array = [NSArray arrayWithObjects: utf8_type, nil]; NSString *has_string = [board availableTypeFromArray:array]; if (has_string != nil){ NSData *data = [board dataForType: utf8_type]; if (data != nil){ u32 copy_length = data.length; if (copy_length > 0){ // TODO(allen): Grow clipboard memory if needed. if (copy_length+1 < osx.clipboard_max){ osx.clipboard_size = copy_length; [data getBytes: osx.clipboard_data length: copy_length]; ((char*)osx.clipboard_data)[copy_length] = 0; osx.has_clipboard_item = true; } } } } } else{ osx.just_posted_to_clipboard = false; } osx.prev_clipboard_change_count = board.changeCount; } CGLLockContext([[self openGLContext] CGLContextObj]); [[self openGLContext] makeCurrentContext]; osx_step(); [[self openGLContext] flushBuffer]; CGLUnlockContext([[self openGLContext] CGLContextObj]); } } return kCVReturnSuccess; } - (void)reshape { [super reshape]; NSRect rect = [self bounds]; osx_resize(rect.size.width, rect.size.height); } - (void)init_gl { if(osx.running) { return; } [self setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable]; NSOpenGLPixelFormatAttribute attrs[] = { NSOpenGLPFAOpenGLProfile, //NSOpenGLProfileVersion3_2Core, NSOpenGLProfileVersionLegacy, NSOpenGLPFAColorSize, 24, NSOpenGLPFAAlphaSize, 8, NSOpenGLPFAAccelerated, NSOpenGLPFADoubleBuffer, 0 }; NSOpenGLPixelFormat* format = [[NSOpenGLPixelFormat alloc] initWithAttributes:attrs]; if(format == nil) { fprintf(stderr, "Error creating OpenGLPixelFormat\n"); exit(1); } NSOpenGLContext* context = [[NSOpenGLContext alloc] initWithFormat:format shareContext:nil]; [self setPixelFormat:format]; [self setOpenGLContext:context]; [context makeCurrentContext]; osx.running = true; } - (id)init { self = [super init]; if(self == nil) { return nil; } [self init_gl]; return self; } - (void)awakeFromNib { [self init_gl]; } - (void)prepareOpenGL { [super prepareOpenGL]; [[self openGLContext] makeCurrentContext]; GLint swapInt = 1; [[self openGLContext] setValues:&swapInt forParameter:NSOpenGLCPSwapInterval]; CVReturn cvreturn = CVDisplayLinkCreateWithActiveCGDisplays(&displayLink); cvreturn = CVDisplayLinkSetOutputCallback(displayLink, &osx_display_link, (__bridge void*)(self)); CGLContextObj cglContext = [[self openGLContext] CGLContextObj]; CGLPixelFormatObj cglPixelFormat = [[self pixelFormat] CGLPixelFormatObj]; cvreturn = CVDisplayLinkSetCurrentCGDisplayFromOpenGLContext(displayLink, cglContext, cglPixelFormat); CVDisplayLinkStart(displayLink); } - (void)dealloc { [super dealloc]; CVDisplayLinkStop(displayLink); CVDisplayLinkRelease(displayLink); } - (BOOL)acceptsFirstResponder { return YES; } - (BOOL)becomeFirstResponder { return YES; } - (BOOL)resignFirstResponder { return YES; } @end static DISPLINK_SIG(osx_display_link){ My4coderView* view = (__bridge My4coderView*)context; CVReturn result = [view getFrameForTime:output]; return result; } @implementation AppDelegate - (void)applicationDidFinishLaunching:(id)sender { } - (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication*)sender { return YES; } - (void)applicationWillTerminate:(NSApplication*)sender { } @end int main(int argc, char **argv){ memset(&osx, 0, sizeof(osx)); umem clipboard_size = MB(4); osx.clipboard_data = osx_allocate(clipboard_size); osx.clipboard_max = clipboard_size; osx_init(); @autoreleasepool{ NSApplication *app = [NSApplication sharedApplication]; [NSApp setActivationPolicy:NSApplicationActivationPolicyRegular]; [app setDelegate:[[AppDelegate alloc] init]]; NSRect screenRect = [[NSScreen mainScreen] frame]; float w = 800.f; float h = 600.f; NSRect frame = NSMakeRect((screenRect.size.width - w) * 0.5, (screenRect.size.height - h) * 0.5, w, h); u32 flags = NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask | NSResizableWindowMask; NSWindow* window = [[NSWindow alloc] initWithContentRect:frame styleMask:flags backing:NSBackingStoreBuffered defer:NO]; [window setAcceptsMouseMovedEvents:YES]; My4coderView* view = [[My4coderView alloc] init]; [view setFrame:[[window contentView] bounds]]; [view setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable]; [[window contentView] addSubview:view]; [window setMinSize:NSMakeSize(100, 100)]; [window setTitle:@WINDOW_NAME]; [window makeKeyAndOrderFront:nil]; [NSApp run]; } return(0); } // BOTTOM