diff options
author | David Robillard <d@drobilla.net> | 2019-07-27 21:24:36 +0200 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2019-07-29 01:59:19 +0200 |
commit | 37fe29ab9c4a5ea22bc5996b020fa39c854965fa (patch) | |
tree | 5ac433830c4113d07c51b662ca6d4707d4be12e8 /pugl/pugl_osx.m | |
parent | 41dea932f866c10eb9c303298545d6b7151cfcd0 (diff) | |
download | pugl-37fe29ab9c4a5ea22bc5996b020fa39c854965fa.tar.gz pugl-37fe29ab9c4a5ea22bc5996b020fa39c854965fa.tar.bz2 pugl-37fe29ab9c4a5ea22bc5996b020fa39c854965fa.zip |
Reorganize source to separate private implementation details
Taking a page from C++ convention, where "detail" is for things that should not
be included in user code.
Diffstat (limited to 'pugl/pugl_osx.m')
-rw-r--r-- | pugl/pugl_osx.m | 1069 |
1 files changed, 0 insertions, 1069 deletions
diff --git a/pugl/pugl_osx.m b/pugl/pugl_osx.m deleted file mode 100644 index a5ec994..0000000 --- a/pugl/pugl_osx.m +++ /dev/null @@ -1,1069 +0,0 @@ -/* - Copyright 2012-2019 David Robillard <http://drobilla.net> - Copyright 2017 Hanspeter Portner <dev@open-music-kontrollers.ch> - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ - -/** - @file pugl_osx.m MacOS implementation. -*/ - -#define GL_SILENCE_DEPRECATION 1 - -#include "pugl/gl.h" -#include "pugl/pugl_gl_backend.h" -#include "pugl/pugl_internal.h" - -#ifdef PUGL_HAVE_CAIRO -#include "pugl/pugl_cairo_backend.h" -#include "pugl/cairo_gl.h" -#endif - -#import <Cocoa/Cocoa.h> - -#include <mach/mach_time.h> - -#include <stdlib.h> - -#ifndef __MAC_10_10 -#define NSOpenGLProfileVersion4_1Core NSOpenGLProfileVersion3_2Core -typedef NSUInteger NSEventModifierFlags; -typedef NSUInteger NSWindowStyleMask; -#endif - -@class PuglOpenGLView; - -struct PuglInternalsImpl { - NSApplication* app; - PuglOpenGLView* glview; - id window; - NSEvent* nextEvent; - uint32_t mods; -#ifdef PUGL_HAVE_CAIRO - cairo_surface_t* surface; - cairo_t* cr; - PuglCairoGL cairo_gl; -#endif -}; - -@interface PuglWindow : NSWindow -{ -@public - PuglView* puglview; -} - -- (void) setPuglview:(PuglView*)view; - -@end - -@implementation PuglWindow - -- (id) initWithContentRect:(NSRect)contentRect - styleMask:(NSWindowStyleMask)aStyle - backing:(NSBackingStoreType)bufferingType - defer:(BOOL)flag -{ - (void)flag; - - NSWindow* result = [super initWithContentRect:contentRect - styleMask:aStyle - backing:bufferingType - defer:NO]; - - [result setAcceptsMouseMovedEvents:YES]; - return (PuglWindow*)result; -} - -- (void)setPuglview:(PuglView*)view -{ - puglview = view; - [self setContentSize:NSMakeSize(view->width, view->height)]; -} - -- (BOOL) canBecomeKeyWindow -{ - return YES; -} - -- (BOOL) canBecomeMainWindow -{ - return YES; -} - -@end - -@interface PuglOpenGLView : NSOpenGLView<NSTextInputClient> -{ -@public - PuglView* puglview; - NSTrackingArea* trackingArea; - NSMutableAttributedString* markedText; - NSTimer* timer; - NSTimer* urgentTimer; -} - -@end - -@implementation PuglOpenGLView - -- (id) initWithFrame:(NSRect)frame -{ - const int major = puglview->hints.context_version_major; - const int profile = ((puglview->hints.use_compat_profile || major < 3) - ? NSOpenGLProfileVersionLegacy - : puglview->hints.context_version_major >= 4 - ? NSOpenGLProfileVersion4_1Core - : NSOpenGLProfileVersion3_2Core); - - NSOpenGLPixelFormatAttribute pixelAttribs[16] = { - NSOpenGLPFADoubleBuffer, - NSOpenGLPFAAccelerated, - NSOpenGLPFAOpenGLProfile, profile, - NSOpenGLPFAColorSize, 32, - NSOpenGLPFADepthSize, 32, - NSOpenGLPFAMultisample, puglview->hints.samples ? 1 : 0, - NSOpenGLPFASampleBuffers, puglview->hints.samples ? 1 : 0, - NSOpenGLPFASamples, puglview->hints.samples, - 0}; - - NSOpenGLPixelFormat *pixelFormat = [ - [NSOpenGLPixelFormat alloc] initWithAttributes:pixelAttribs]; - - if (pixelFormat) { - self = [super initWithFrame:frame pixelFormat:pixelFormat]; - [pixelFormat release]; - } else { - self = [super initWithFrame:frame]; - } - - if (self) { - [[self openGLContext] makeCurrentContext]; - [self reshape]; - } - return self; -} - -- (void) reshape -{ - [super reshape]; - [[self openGLContext] update]; - - if (!puglview) { - return; - } - - const NSRect bounds = [self bounds]; - const PuglEventConfigure ev = { - PUGL_CONFIGURE, - 0, - bounds.origin.x, - bounds.origin.y, - bounds.size.width, - bounds.size.height, - }; - - puglview->backend->resize(puglview, ev.width, ev.height); - - puglDispatchEvent(puglview, (const PuglEvent*)&ev); -} - -- (void) drawRect:(NSRect)rect -{ - const PuglEventExpose ev = { - PUGL_EXPOSE, - 0, - rect.origin.x, - rect.origin.y, - rect.size.width, - rect.size.height, - 0 - }; - - puglDispatchEvent(puglview, (const PuglEvent*)&ev); -} - -- (BOOL) isFlipped -{ - return YES; -} - -- (BOOL) acceptsFirstResponder -{ - return YES; -} - -static uint32_t -getModifiers(const NSEvent* const ev) -{ - const NSEventModifierFlags modifierFlags = [ev modifierFlags]; - - return (((modifierFlags & NSShiftKeyMask) ? PUGL_MOD_SHIFT : 0) | - ((modifierFlags & NSControlKeyMask) ? PUGL_MOD_CTRL : 0) | - ((modifierFlags & NSAlternateKeyMask) ? PUGL_MOD_ALT : 0) | - ((modifierFlags & NSCommandKeyMask) ? PUGL_MOD_SUPER : 0)); -} - -static PuglKey -keySymToSpecial(const NSEvent* const ev) -{ - NSString* chars = [ev charactersIgnoringModifiers]; - if ([chars length] == 1) { - switch ([chars characterAtIndex:0]) { - case NSF1FunctionKey: return PUGL_KEY_F1; - case NSF2FunctionKey: return PUGL_KEY_F2; - case NSF3FunctionKey: return PUGL_KEY_F3; - case NSF4FunctionKey: return PUGL_KEY_F4; - case NSF5FunctionKey: return PUGL_KEY_F5; - case NSF6FunctionKey: return PUGL_KEY_F6; - case NSF7FunctionKey: return PUGL_KEY_F7; - case NSF8FunctionKey: return PUGL_KEY_F8; - case NSF9FunctionKey: return PUGL_KEY_F9; - case NSF10FunctionKey: return PUGL_KEY_F10; - case NSF11FunctionKey: return PUGL_KEY_F11; - case NSF12FunctionKey: return PUGL_KEY_F12; - case NSDeleteCharacter: return PUGL_KEY_BACKSPACE; - case NSDeleteFunctionKey: return PUGL_KEY_DELETE; - case NSLeftArrowFunctionKey: return PUGL_KEY_LEFT; - case NSUpArrowFunctionKey: return PUGL_KEY_UP; - case NSRightArrowFunctionKey: return PUGL_KEY_RIGHT; - case NSDownArrowFunctionKey: return PUGL_KEY_DOWN; - case NSPageUpFunctionKey: return PUGL_KEY_PAGE_UP; - case NSPageDownFunctionKey: return PUGL_KEY_PAGE_DOWN; - case NSHomeFunctionKey: return PUGL_KEY_HOME; - case NSEndFunctionKey: return PUGL_KEY_END; - case NSInsertFunctionKey: return PUGL_KEY_INSERT; - case NSMenuFunctionKey: return PUGL_KEY_MENU; - case NSScrollLockFunctionKey: return PUGL_KEY_SCROLL_LOCK; - case NSClearLineFunctionKey: return PUGL_KEY_NUM_LOCK; - case NSPrintScreenFunctionKey: return PUGL_KEY_PRINT_SCREEN; - case NSPauseFunctionKey: return PUGL_KEY_PAUSE; - } - // SHIFT, CTRL, ALT, and SUPER are handled in [flagsChanged] - } - return (PuglKey)0; -} - -- (void) updateTrackingAreas -{ - if (trackingArea != nil) { - [self removeTrackingArea:trackingArea]; - [trackingArea release]; - } - - const int opts = (NSTrackingMouseEnteredAndExited | - NSTrackingMouseMoved | - NSTrackingActiveAlways); - trackingArea = [[NSTrackingArea alloc] initWithRect:[self bounds] - options:opts - owner:self - userInfo:nil]; - [self addTrackingArea:trackingArea]; - [super updateTrackingAreas]; -} - -- (NSPoint) eventLocation:(NSEvent*)event -{ - return [self convertPoint:[event locationInWindow] fromView:nil]; -} - -static void -handleCrossing(PuglOpenGLView* view, NSEvent* event, const PuglEventType type) -{ - const NSPoint wloc = [view eventLocation:event]; - const NSPoint rloc = [NSEvent mouseLocation]; - const PuglEventCrossing ev = { - type, - 0, - [event timestamp], - wloc.x, - wloc.y, - rloc.x, - [[NSScreen mainScreen] frame].size.height - rloc.y, - getModifiers(event), - PUGL_CROSSING_NORMAL - }; - puglDispatchEvent(view->puglview, (const PuglEvent*)&ev); -} - -- (void) mouseEntered:(NSEvent*)event -{ - handleCrossing(self, event, PUGL_ENTER_NOTIFY); -} - -- (void) mouseExited:(NSEvent*)event -{ - handleCrossing(self, event, PUGL_LEAVE_NOTIFY); -} - -- (void) mouseMoved:(NSEvent*)event -{ - const NSPoint wloc = [self eventLocation:event]; - const NSPoint rloc = [NSEvent mouseLocation]; - const PuglEventMotion ev = { - PUGL_MOTION_NOTIFY, - 0, - [event timestamp], - wloc.x, - wloc.y, - rloc.x, - [[NSScreen mainScreen] frame].size.height - rloc.y, - getModifiers(event), - 0, - 1 - }; - puglDispatchEvent(puglview, (const PuglEvent*)&ev); -} - -- (void) mouseDragged:(NSEvent*)event -{ - [self mouseMoved: event]; -} - -- (void) rightMouseDragged:(NSEvent*)event -{ - [self mouseMoved: event]; -} - -- (void) otherMouseDragged:(NSEvent*)event -{ - [self mouseMoved: event]; -} - -- (void) mouseDown:(NSEvent*)event -{ - const NSPoint wloc = [self eventLocation:event]; - const NSPoint rloc = [NSEvent mouseLocation]; - const PuglEventButton ev = { - PUGL_BUTTON_PRESS, - 0, - [event timestamp], - wloc.x, - wloc.y, - rloc.x, - [[NSScreen mainScreen] frame].size.height - rloc.y, - getModifiers(event), - (uint32_t)[event buttonNumber] + 1 - }; - puglDispatchEvent(puglview, (const PuglEvent*)&ev); -} - -- (void) mouseUp:(NSEvent*)event -{ - const NSPoint wloc = [self eventLocation:event]; - const NSPoint rloc = [NSEvent mouseLocation]; - const PuglEventButton ev = { - PUGL_BUTTON_RELEASE, - 0, - [event timestamp], - wloc.x, - wloc.y, - rloc.x, - [[NSScreen mainScreen] frame].size.height - rloc.y, - getModifiers(event), - (uint32_t)[event buttonNumber] + 1 - }; - puglDispatchEvent(puglview, (const PuglEvent*)&ev); -} - -- (void) rightMouseDown:(NSEvent*)event -{ - [self mouseDown: event]; -} - -- (void) rightMouseUp:(NSEvent*)event -{ - [self mouseUp: event]; -} - -- (void) otherMouseDown:(NSEvent*)event -{ - [self mouseDown: event]; -} - -- (void) otherMouseUp:(NSEvent*)event -{ - [self mouseUp: event]; -} - -- (void) scrollWheel:(NSEvent*)event -{ - const NSPoint wloc = [self eventLocation:event]; - const NSPoint rloc = [NSEvent mouseLocation]; - const PuglEventScroll ev = { - PUGL_SCROLL, - 0, - [event timestamp], - wloc.x, - wloc.y, - rloc.x, - [[NSScreen mainScreen] frame].size.height - rloc.y, - getModifiers(event), - [event deltaX], - [event deltaY] - }; - puglDispatchEvent(puglview, (const PuglEvent*)&ev); -} - -- (void) keyDown:(NSEvent*)event -{ - if (puglview->ignoreKeyRepeat && [event isARepeat]) { - return; - } - - const NSPoint wloc = [self eventLocation:event]; - const NSPoint rloc = [NSEvent mouseLocation]; - const PuglKey spec = keySymToSpecial(event); - const NSString* chars = [event charactersIgnoringModifiers]; - const char* str = [[chars lowercaseString] UTF8String]; - const uint32_t code = ( - spec ? spec : puglDecodeUTF8((const uint8_t*)str)); - - const PuglEventKey ev = { - PUGL_KEY_PRESS, - 0, - [event timestamp], - wloc.x, - wloc.y, - rloc.x, - [[NSScreen mainScreen] frame].size.height - rloc.y, - getModifiers(event), - [event keyCode], - (code != 0xFFFD) ? code : 0 - }; - - puglDispatchEvent(puglview, (const PuglEvent*)&ev); - - if (!spec) { - [self interpretKeyEvents:@[event]]; - } -} - -- (void) keyUp:(NSEvent*)event -{ - const NSPoint wloc = [self eventLocation:event]; - const NSPoint rloc = [NSEvent mouseLocation]; - const PuglKey spec = keySymToSpecial(event); - const NSString* chars = [event charactersIgnoringModifiers]; - const char* str = [[chars lowercaseString] UTF8String]; - const uint32_t code = - (spec ? spec : puglDecodeUTF8((const uint8_t*)str)); - - const PuglEventKey ev = { - PUGL_KEY_RELEASE, - 0, - [event timestamp], - wloc.x, - wloc.y, - rloc.x, - [[NSScreen mainScreen] frame].size.height - rloc.y, - getModifiers(event), - [event keyCode], - (code != 0xFFFD) ? code : 0 - }; - puglDispatchEvent(puglview, (const PuglEvent*)&ev); -} - -- (BOOL) hasMarkedText -{ - return [markedText length] > 0; -} - -- (NSRange) markedRange -{ - return (([markedText length] > 0) - ? NSMakeRange(0, [markedText length] - 1) - : NSMakeRange(NSNotFound, 0)); -} - -- (NSRange) selectedRange -{ - return NSMakeRange(NSNotFound, 0); -} - -- (void)setMarkedText:(id)string - selectedRange:(NSRange)selected - replacementRange:(NSRange)replacement -{ - (void)selected; - (void)replacement; - [markedText release]; - markedText = ( - [string isKindOfClass:[NSAttributedString class]] - ? [[NSMutableAttributedString alloc] initWithAttributedString:string] - : [[NSMutableAttributedString alloc] initWithString:string]); -} - -- (void) unmarkText -{ - [[markedText mutableString] setString:@""]; -} - -- (NSArray*) validAttributesForMarkedText -{ - return @[]; -} - -- (NSAttributedString*) - attributedSubstringForProposedRange:(NSRange)range - actualRange:(NSRangePointer)actual -{ - (void)range; - (void)actual; - return nil; -} - -- (NSUInteger) characterIndexForPoint:(NSPoint)point -{ - (void)point; - return 0; -} - -- (NSRect) firstRectForCharacterRange:(NSRange)range - actualRange:(NSRangePointer)actual -{ - (void)range; - (void)actual; - - const NSRect frame = [(id)puglview bounds]; - return NSMakeRect(frame.origin.x, frame.origin.y, 0.0, 0.0); -} - -- (void) insertText:(id)string - replacementRange:(NSRange)replacement -{ - (void)replacement; - - NSEvent* const event = [NSApp currentEvent]; - NSString* const characters = - ([string isKindOfClass:[NSAttributedString class]] - ? [string string] - : (NSString*)string); - - const NSPoint wloc = [self eventLocation:event]; - const NSPoint rloc = [NSEvent mouseLocation]; - for (size_t i = 0; i < [characters length]; ++i) { - const uint32_t code = [characters characterAtIndex:i]; - char utf8[8] = {0}; - NSUInteger len = 0; - - [characters getBytes:utf8 - maxLength:sizeof(utf8) - usedLength:&len - encoding:NSUTF8StringEncoding - options:0 - range:NSMakeRange(i, i + 1) - remainingRange:nil]; - - PuglEventText ev = { PUGL_TEXT, - 0, - [event timestamp], - wloc.x, - wloc.y, - rloc.x, - [[NSScreen mainScreen] frame].size.height - rloc.y, - getModifiers(event), - [event keyCode], - code, - { 0, 0, 0, 0, 0, 0, 0, 0 } }; - - memcpy(ev.string, utf8, len); - puglDispatchEvent(puglview, (const PuglEvent*)&ev); - } -} - -- (void) flagsChanged:(NSEvent*)event -{ - const uint32_t mods = getModifiers(event); - PuglEventType type = PUGL_NOTHING; - PuglKey special = 0; - - if ((mods & PUGL_MOD_SHIFT) != (puglview->impl->mods & PUGL_MOD_SHIFT)) { - type = mods & PUGL_MOD_SHIFT ? PUGL_KEY_PRESS : PUGL_KEY_RELEASE; - special = PUGL_KEY_SHIFT; - } else if ((mods & PUGL_MOD_CTRL) != (puglview->impl->mods & PUGL_MOD_CTRL)) { - type = mods & PUGL_MOD_CTRL ? PUGL_KEY_PRESS : PUGL_KEY_RELEASE; - special = PUGL_KEY_CTRL; - } else if ((mods & PUGL_MOD_ALT) != (puglview->impl->mods & PUGL_MOD_ALT)) { - type = mods & PUGL_MOD_ALT ? PUGL_KEY_PRESS : PUGL_KEY_RELEASE; - special = PUGL_KEY_ALT; - } else if ((mods & PUGL_MOD_SUPER) != (puglview->impl->mods & PUGL_MOD_SUPER)) { - type = mods & PUGL_MOD_SUPER ? PUGL_KEY_PRESS : PUGL_KEY_RELEASE; - special = PUGL_KEY_SUPER; - } - - if (special != 0) { - const NSPoint wloc = [self eventLocation:event]; - const NSPoint rloc = [NSEvent mouseLocation]; - PuglEventKey ev = { - type, - 0, - [event timestamp], - wloc.x, - wloc.y, - rloc.x, - [[NSScreen mainScreen] frame].size.height - rloc.y, - mods, - [event keyCode], - special - }; - puglDispatchEvent(puglview, (const PuglEvent*)&ev); - } - - puglview->impl->mods = mods; -} - -- (BOOL) preservesContentInLiveResize -{ - return NO; -} - -- (void) viewWillStartLiveResize -{ - timer = [NSTimer timerWithTimeInterval:(1 / 60.0) - target:self - selector:@selector(resizeTick) - userInfo:nil - repeats:YES]; - [[NSRunLoop currentRunLoop] addTimer:timer - forMode:NSRunLoopCommonModes]; - - [super viewWillStartLiveResize]; -} - -- (void) resizeTick -{ - puglPostRedisplay(puglview); -} - -- (void) urgentTick -{ - [NSApp requestUserAttention:NSInformationalRequest]; -} - -- (void) viewDidEndLiveResize -{ - [super viewDidEndLiveResize]; - [timer invalidate]; - timer = NULL; -} - -@end - -@interface PuglWindowDelegate : NSObject<NSWindowDelegate> -{ - PuglWindow* window; -} - -- (instancetype) initWithPuglWindow:(PuglWindow*)window; - -@end - -@implementation PuglWindowDelegate - -- (instancetype) initWithPuglWindow:(PuglWindow*)puglWindow -{ - if ((self = [super init])) { - window = puglWindow; - } - - return self; -} - -- (BOOL) windowShouldClose:(id)sender -{ - (void)sender; - - PuglEvent ev = { 0 }; - ev.type = PUGL_CLOSE; - puglDispatchEvent(window->puglview, &ev); - return YES; -} - -- (void) windowDidBecomeKey:(NSNotification*)notification -{ - (void)notification; - - PuglOpenGLView* glview = window->puglview->impl->glview; - if (window->puglview->impl->glview->urgentTimer) { - [glview->urgentTimer invalidate]; - glview->urgentTimer = NULL; - } - - PuglEvent ev = { 0 }; - ev.type = PUGL_FOCUS_IN; - ev.focus.grab = false; - puglDispatchEvent(window->puglview, &ev); -} - -- (void) windowDidResignKey:(NSNotification*)notification -{ - (void)notification; - - PuglEvent ev = { 0 }; - ev.type = PUGL_FOCUS_OUT; - ev.focus.grab = false; - puglDispatchEvent(window->puglview, &ev); -} - -@end - -PuglInternals* -puglInitInternals(void) -{ - return (PuglInternals*)calloc(1, sizeof(PuglInternals)); -} - -static NSLayoutConstraint* -puglConstraint(id item, NSLayoutAttribute attribute, float constant) -{ - return [NSLayoutConstraint - constraintWithItem: item - attribute: attribute - relatedBy: NSLayoutRelationGreaterThanOrEqual - toItem: nil - attribute: NSLayoutAttributeNotAnAttribute - multiplier: 1.0 - constant: constant]; -} - -int -puglCreateWindow(PuglView* view, const char* title) -{ - PuglInternals* impl = view->impl; - - [NSAutoreleasePool new]; - impl->app = [NSApplication sharedApplication]; - - impl->glview = [PuglOpenGLView alloc]; - impl->glview->trackingArea = nil; - impl->glview->markedText = [[NSMutableAttributedString alloc] init]; - impl->glview->puglview = view; - - [impl->glview initWithFrame:NSMakeRect(0, 0, view->width, view->height)]; - [impl->glview addConstraint: - puglConstraint(impl->glview, NSLayoutAttributeWidth, view->min_width)]; - [impl->glview addConstraint: - puglConstraint(impl->glview, NSLayoutAttributeHeight, view->min_height)]; - if (!view->hints.resizable) { - [impl->glview setAutoresizingMask:NSViewNotSizable]; - } - - if (view->parent) { - NSView* pview = (NSView*)view->parent; - [pview addSubview:impl->glview]; - [impl->glview setHidden:NO]; - [[impl->glview window] makeFirstResponder:impl->glview]; - } else { - NSString* titleString = [[NSString alloc] - initWithBytes:title - length:strlen(title) - encoding:NSUTF8StringEncoding]; - NSRect frame = NSMakeRect(0, 0, view->min_width, view->min_height); - unsigned style = (NSClosableWindowMask | - NSTitledWindowMask | - NSMiniaturizableWindowMask ); - if (view->hints.resizable) { - style |= NSResizableWindowMask; - } - - id window = [[[PuglWindow alloc] - initWithContentRect:frame - styleMask:style - backing:NSBackingStoreBuffered - defer:NO - ] retain]; - [window setPuglview:view]; - [window setTitle:titleString]; - if (view->min_width || view->min_height) { - [window setContentMinSize:NSMakeSize(view->min_width, - view->min_height)]; - } - impl->window = window; - - ((NSWindow*)window).delegate = [[PuglWindowDelegate alloc] - initWithPuglWindow:window]; - - if (view->min_aspect_x && view->min_aspect_y) { - [window setContentAspectRatio:NSMakeSize(view->min_aspect_x, - view->min_aspect_y)]; - } - - [window setContentView:impl->glview]; - [impl->app activateIgnoringOtherApps:YES]; - [window makeFirstResponder:impl->glview]; - [window makeKeyAndOrderFront:window]; - } - - [impl->glview updateTrackingAreas]; - - return 0; -} - -void -puglShowWindow(PuglView* view) -{ - [view->impl->window setIsVisible:YES]; - view->visible = true; -} - -void -puglHideWindow(PuglView* view) -{ - [view->impl->window setIsVisible:NO]; - view->visible = false; -} - -void -puglDestroy(PuglView* view) -{ - view->backend->destroy(view); - view->impl->glview->puglview = NULL; - [view->impl->glview removeFromSuperview]; - if (view->impl->window) { - [view->impl->window close]; - } - [view->impl->glview release]; - if (view->impl->window) { - [view->impl->window release]; - } - free(view->windowClass); - free(view->impl); - free(view); -} - -void -puglGrabFocus(PuglView* view) -{ - [view->impl->window makeKeyWindow]; -} - -void -puglRequestAttention(PuglView* view) -{ - if (![view->impl->window isKeyWindow]) { - [NSApp requestUserAttention:NSInformationalRequest]; - view->impl->glview->urgentTimer = - [NSTimer scheduledTimerWithTimeInterval:2.0 - target:view->impl->glview - selector:@selector(urgentTick) - userInfo:nil - repeats:YES]; - } -} - -PuglStatus -puglWaitForEvent(PuglView* view) -{ - /* Note that dequeue:NO is broken (it blocks forever even when events are - pending), so we work around this by dequeueing the event here and - storing it in view->impl->nextEvent for later processing. */ - if (!view->impl->nextEvent) { - view->impl->nextEvent = - [view->impl->window nextEventMatchingMask:NSAnyEventMask]; - } - - return PUGL_SUCCESS; -} - -PuglStatus -puglProcessEvents(PuglView* view) -{ - if (view->impl->nextEvent) { - // Process event that was dequeued earier by puglWaitForEvent - [view->impl->app sendEvent: view->impl->nextEvent]; - view->impl->nextEvent = NULL; - } - - // Process all pending events - for (NSEvent* ev = NULL; - (ev = [view->impl->window nextEventMatchingMask:NSAnyEventMask - untilDate:nil - inMode:NSDefaultRunLoopMode - dequeue:YES]);) { - [view->impl->app sendEvent: ev]; - } - - return PUGL_SUCCESS; -} - -PuglGlFunc -puglGetProcAddress(const char *name) -{ - CFBundleRef framework = - CFBundleGetBundleWithIdentifier(CFSTR("com.apple.opengl")); - - CFStringRef symbol = CFStringCreateWithCString( - kCFAllocatorDefault, name, kCFStringEncodingASCII); - - PuglGlFunc func = (PuglGlFunc)CFBundleGetFunctionPointerForName( - framework, symbol); - - CFRelease(symbol); - - return func; -} - -double -puglGetTime(PuglView* view) -{ - return (mach_absolute_time() / 1e9) - view->start_time; -} - -void -puglPostRedisplay(PuglView* view) -{ - [view->impl->glview setNeedsDisplay: YES]; -} - -PuglNativeWindow -puglGetNativeWindow(PuglView* view) -{ - return (PuglNativeWindow)view->impl->glview; -} - -// Backend - -static int -puglMacConfigure(PuglView* PUGL_UNUSED(view)) -{ - return 0; -} - -static int -puglMacCreate(PuglView* PUGL_UNUSED(view)) -{ - return 0; -} - -static int -puglMacGlDestroy(PuglView* PUGL_UNUSED(view)) -{ - return 0; -} - -static int -puglMacGlEnter(PuglView* view, bool PUGL_UNUSED(drawing)) -{ - [[view->impl->glview openGLContext] makeCurrentContext]; - return 0; -} - -static int -puglMacGlLeave(PuglView* view, bool drawing) -{ - if (drawing) { - [[view->impl->glview openGLContext] flushBuffer]; - } - - [NSOpenGLContext clearCurrentContext]; - - return 0; -} - -static int -puglMacGlResize(PuglView* PUGL_UNUSED(view), - int PUGL_UNUSED(width), - int PUGL_UNUSED(height)) -{ - return 0; -} - -static void* -puglMacGlGetContext(PuglView* PUGL_UNUSED(view)) -{ - return NULL; -} - -const PuglBackend* puglGlBackend(void) -{ - static const PuglBackend backend = { - puglMacConfigure, - puglMacCreate, - puglMacGlDestroy, - puglMacGlEnter, - puglMacGlLeave, - puglMacGlResize, - puglMacGlGetContext - }; - - return &backend; -} - -#ifdef PUGL_HAVE_CAIRO - -static int -puglMacCairoDestroy(PuglView* view) -{ - pugl_cairo_gl_free(&view->impl->cairo_gl); - return 0; -} - -static int -puglMacCairoEnter(PuglView* view, bool PUGL_UNUSED(drawing)) -{ - [[view->impl->glview openGLContext] makeCurrentContext]; - - return 0; -} - -static int -puglMacCairoLeave(PuglView* view, bool drawing) -{ - if (drawing) { - pugl_cairo_gl_draw(&view->impl->cairo_gl, view->width, view->height); - [[view->impl->glview openGLContext] flushBuffer]; - } - - [NSOpenGLContext clearCurrentContext]; - - return 0; -} - - -static int -puglMacCairoResize(PuglView* view, int width, int height) -{ - PuglInternals* impl = view->impl; - - cairo_surface_destroy(impl->surface); - cairo_destroy(impl->cr); - impl->surface = pugl_cairo_gl_create(&impl->cairo_gl, width, height, 4); - impl->cr = cairo_create(impl->surface); - pugl_cairo_gl_configure(&impl->cairo_gl, width, height); - - return 0; -} - -static void* -puglMacCairoGetContext(PuglView* view) -{ - return view->impl->cr; -} - -const PuglBackend* puglCairoBackend(void) -{ - static const PuglBackend backend = { - puglMacConfigure, - puglMacCreate, - puglMacCairoDestroy, - puglMacCairoEnter, - puglMacCairoLeave, - puglMacCairoResize, - puglMacCairoGetContext - }; - - return &backend; -} - -#endif |